Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -258,6 +258,7 @@ /// DWARFContext. It assumes all content is available in memory and stores /// pointers to it. class DWARFContextInMemory : public DWARFContext { +protected: virtual void anchor(); bool IsLittleEndian; @@ -357,6 +358,15 @@ StringRef getTUIndexSection() override { return TUIndexSection; } }; +/// GdbIndexBuilderDWARFContent is a version of DWARFContext used +/// for building .gdb_index sections. +class GdbIndexBuilderDWARFContent final : public DWARFContextInMemory { +public: + GdbIndexBuilderDWARFContent(const object::ObjectFile &Obj, + const LoadedObjectInfo *L); + +}; + } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -616,6 +616,95 @@ return InliningInfo; } +static Error createError(const Twine &Reason, llvm::Error E) { + return make_error(Reason + toString(std::move(E)), + inconvertibleErrorCode()); +} + +// Returns the address of symbol relocation used against. Used for futher +// relocations computation. Symbol's section load address is taken in account if +// LoadedObjectInfo interface is provided. +static Expected getSymbolAddress(const object::ObjectFile &Obj, + const RelocationRef &Reloc, + const LoadedObjectInfo *L) { + uint64_t Ret = 0; + object::section_iterator RSec = Obj.section_end(); + object::symbol_iterator Sym = Reloc.getSymbol(); + + // First calculate the address of the symbol or section as it appears + // in the object file + if (Sym != Obj.symbol_end()) { + Expected SymAddrOrErr = Sym->getAddress(); + if (!SymAddrOrErr) + return createError("error: failed to compute symbol address: ", + SymAddrOrErr.takeError()); + + // Also remember what section this symbol is in for later + auto SectOrErr = Sym->getSection(); + if (!SectOrErr) + return createError("error: failed to get symbol section: ", + SectOrErr.takeError()); + + RSec = *SectOrErr; + Ret = *SymAddrOrErr; + } else if (auto *MObj = dyn_cast(&Obj)) { + RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl()); + Ret = RSec->getAddress(); + } + + // If we are given load addresses for the sections, we need to adjust: + // SymAddr = (Address of Symbol Or Section in File) - + // (Address of Section in File) + + // (Load Address of Section) + if (L != nullptr && RSec != Obj.section_end()) { + // RSec is now either the section being targeted or the section + // containing the symbol being targeted. In either case, + // we need to perform the same computation. + uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec); + if (SectionLoadAddress != 0) + Ret += SectionLoadAddress - RSec->getAddress(); + } + + return Ret; +} + +// Resolves single relocation and andds result to Map. +static void applyRelocation(RelocAddrMap &Map, const SectionRef &Section, + const RelocationRef &Reloc, uint64_t Addr) { + uint64_t Address = Reloc.getOffset(); + uint64_t Type = Reloc.getType(); + + object::RelocVisitor V(*Section.getObject()); + object::RelocToApply R(V.visit(Type, Reloc, Addr)); + if (V.error()) { + SmallString<32> Name; + Reloc.getTypeName(Name); + errs() << "error: failed to compute relocation: " << Name << "\n"; + return; + } + + section_iterator RelocatedSection = Section.getRelocatedSection(); + uint64_t SectionSize = RelocatedSection->getSize(); + if (Address + R.Width > SectionSize) { + StringRef Name; + Section.getName(Name); + errs() << "error: " << R.Width << "-byte relocation starting " << Address + << " bytes into section " << Name << " which is " << SectionSize + << " bytes long.\n"; + return; + } + if (R.Width > 8) { + errs() << "error: can't handle a relocation of more than 8 bytes at " + "a time.\n"; + return; + } + DEBUG(dbgs() << "Writing " << format("%p", R.Value) << " at " + << format("%p", Address) << " with width " + << format("%d", R.Width) << "\n"); + Map.insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); + return; +} + DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L) : IsLittleEndian(Obj.isLittleEndian()), @@ -719,99 +808,13 @@ } if (Section.relocation_begin() != Section.relocation_end()) { - uint64_t SectionSize = RelocatedSection->getSize(); for (const RelocationRef &Reloc : Section.relocations()) { - uint64_t Address = Reloc.getOffset(); - uint64_t Type = Reloc.getType(); - uint64_t SymAddr = 0; - uint64_t SectionLoadAddress = 0; - object::symbol_iterator Sym = Reloc.getSymbol(); - object::section_iterator RSec = Obj.section_end(); - - // First calculate the address of the symbol or section as it appears - // in the objct file - if (Sym != Obj.symbol_end()) { - Expected SymAddrOrErr = Sym->getAddress(); - if (!SymAddrOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymAddrOrErr.takeError(), OS, ""); - OS.flush(); - errs() << "error: failed to compute symbol address: " - << Buf << '\n'; - continue; - } - SymAddr = *SymAddrOrErr; - // Also remember what section this symbol is in for later - auto SectOrErr = Sym->getSection(); - if (!SectOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SectOrErr.takeError(), OS, ""); - OS.flush(); - errs() << "error: failed to get symbol section: " - << Buf << '\n'; - continue; - } - RSec = *SectOrErr; - } else if (auto *MObj = dyn_cast(&Obj)) { - // MachO also has relocations that point to sections and - // scattered relocations. - auto RelocInfo = MObj->getRelocation(Reloc.getRawDataRefImpl()); - if (MObj->isRelocationScattered(RelocInfo)) { - // FIXME: it's not clear how to correctly handle scattered - // relocations. - continue; - } else { - RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl()); - SymAddr = RSec->getAddress(); - } - } - - // If we are given load addresses for the sections, we need to adjust: - // SymAddr = (Address of Symbol Or Section in File) - - // (Address of Section in File) + - // (Load Address of Section) - if (L != nullptr && RSec != Obj.section_end()) { - // RSec is now either the section being targeted or the section - // containing the symbol being targeted. In either case, - // we need to perform the same computation. - StringRef SecName; - RSec->getName(SecName); -// dbgs() << "Name: '" << SecName -// << "', RSec: " << RSec->getRawDataRefImpl() -// << ", Section: " << Section.getRawDataRefImpl() << "\n"; - SectionLoadAddress = L->getSectionLoadAddress(*RSec); - if (SectionLoadAddress != 0) - SymAddr += SectionLoadAddress - RSec->getAddress(); - } - - object::RelocVisitor V(Obj); - object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); - if (V.error()) { - SmallString<32> Name; - Reloc.getTypeName(Name); - errs() << "error: failed to compute relocation: " - << Name << "\n"; + Expected SymAddrOrErr = getSymbolAddress(Obj, Reloc, L); + if (!SymAddrOrErr) { + errs() << toString(std::move(SymAddrOrErr.takeError())) << '\n'; continue; - } - - if (Address + R.Width > SectionSize) { - errs() << "error: " << R.Width << "-byte relocation starting " - << Address << " bytes into section " << name << " which is " - << SectionSize << " bytes long.\n"; - continue; - } - if (R.Width > 8) { - errs() << "error: can't handle a relocation of more than 8 bytes at " - "a time.\n"; - continue; - } - DEBUG(dbgs() << "Writing " << format("%p", R.Value) - << " at " << format("%p", Address) - << " with width " << format("%d", R.Width) - << "\n"); - Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); + } + applyRelocation(*Map, Section, Reloc, *SymAddrOrErr); } } } @@ -863,3 +866,61 @@ } void DWARFContextInMemory::anchor() {} + +GdbIndexBuilderDWARFContent::GdbIndexBuilderDWARFContent( + const object::ObjectFile &Obj, const LoadedObjectInfo *L) + : DWARFContextInMemory({}, Obj.getBytesInAddress(), Obj.isLittleEndian()) { + + for (const SectionRef &Section : Obj.sections()) { + StringRef Name; + Section.getName(Name); + + // Compressed sections names in GNU style starts from ".z". + // Skip ".", "z" and "_" prefixes. + Name = Name.substr(Name.find_first_not_of("._z")); + StringRef *SectionData = StringSwitch(Name) + .Case("debug_info", &InfoSection.Data) + .Case("debug_abbrev", &AbbrevSection) + .Case("debug_gnu_pubnames", &GnuPubNamesSection) + .Case("debug_gnu_pubtypes", &GnuPubTypesSection) + .Default(nullptr); + + if (SectionData) + Section.getContents(*SectionData); + + section_iterator RelocatedSection = Section.getRelocatedSection(); + if (RelocatedSection == Obj.section_end()) + continue; + + StringRef RelSecName; + RelocatedSection->getName(RelSecName); + // Skip . and _ prefixes. + RelSecName = RelSecName.substr(RelSecName.find_first_not_of("._")); + if (RelSecName != "debug_info") + continue; + + if (Section.relocation_begin() != Section.relocation_end()) { + uint64_t SymAddr = 0; + object::symbol_iterator Sym = Obj.symbol_end(); + + for (const RelocationRef &Reloc : Section.relocations()) { + auto &Sec = static_cast( + **Reloc.getSymbol()->getSection()); + if ((Sec.getFlags() & ELF::SHF_ALLOC) == 0) + continue; + + object::symbol_iterator RelSym = Reloc.getSymbol(); + if (Sym == Obj.symbol_end() || Sym != RelSym) { + Expected SymAddrOrErr = getSymbolAddress(Obj, Reloc, L); + if (!SymAddrOrErr) { + errs() << toString(std::move(SymAddrOrErr.takeError())) << '\n'; + continue; + } + SymAddr = *SymAddrOrErr; + Sym = RelSym; + } + applyRelocation(InfoSection.Relocs, Section, Reloc, SymAddr); + } + } + } +}