Index: ELF/GdbIndex.h =================================================================== --- ELF/GdbIndex.h +++ ELF/GdbIndex.h @@ -45,6 +45,7 @@ // debug information performed. That information futher used // for filling gdb index section areas. struct GdbIndexChunk { + InputSection *Sec; std::vector AddressArea; std::vector CompilationUnits; std::vector NamesAndTypes; Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -501,15 +501,6 @@ if (Config->Strip != StripPolicy::None && Name.startswith(".debug")) return &InputSection::Discarded; - // If -gdb-index is given, LLD creates .gdb_index section, and that - // section serves the same purpose as .debug_gnu_pub{names,types} sections. - // If that's the case, we want to eliminate .debug_gnu_pub{names,types} - // because they are redundant and can waste large amount of disk space - // (for example, they are about 400 MiB in total for a clang debug build.) - if (Config->GdbIndex && - (Name == ".debug_gnu_pubnames" || Name == ".debug_gnu_pubtypes")) - return &InputSection::Discarded; - // The linkonce feature is a sort of proto-comdat. Some glibc i386 object // files contain definitions of symbol "__x86.get_pc_thunk.bx" in linkonce // sections. Drop those sections to avoid duplicate symbol errors. Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -503,7 +503,7 @@ const unsigned SymTabEntrySize = 2 * OffsetTypeSize; public: - GdbIndexSection(); + GdbIndexSection(std::vector Chunks); void finalizeContents() override; void writeTo(uint8_t *Buf) override; size_t getSize() const override; @@ -524,7 +524,6 @@ std::vector Chunks; private: - GdbIndexChunk readDwarf(InputSection *Sec); void buildIndex(); uint32_t CuTypesOffset; @@ -537,6 +536,7 @@ bool Finalized = false; }; +template GdbIndexSection *createGdbIndex(); // --eh-frame-hdr option tells linker to construct a header for all the // .eh_frame sections. This header is placed to a section named .eh_frame_hdr Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1700,9 +1700,9 @@ return (HeaderSize == 0) ? InX::Plt->getSize() : 0; } -GdbIndexSection::GdbIndexSection() +GdbIndexSection::GdbIndexSection(std::vector Chunks) : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index"), - StringPool(llvm::StringTableBuilder::ELF) {} + StringPool(llvm::StringTableBuilder::ELF), Chunks(std::move(Chunks)) {} // Iterative hash function for symbol's name is described in .gdb_index format // specification. Note that we use one for version 5 to 7 here, it is different @@ -1714,11 +1714,10 @@ return R; } -static std::vector readCuList(DWARFContext &Dwarf, - InputSection *Sec) { +static std::vector readCuList(DWARFContext &Dwarf) { std::vector Ret; for (std::unique_ptr &CU : Dwarf.compile_units()) - Ret.push_back({Sec->OutSecOff + CU->getOffset(), CU->getLength() + 4}); + Ret.push_back({CU->getOffset(), CU->getLength() + 4}); return Ret; } @@ -1763,21 +1762,31 @@ static std::vector getDebugInfoSections() { std::vector Ret; - for (InputSectionBase *S : InputSections) - if (InputSection *IS = dyn_cast(S)) - if (IS->getParent() && IS->Name == ".debug_info") - Ret.push_back(IS); + for (InputSectionBase *&S : InputSections) { + InputSection *IS = dyn_cast(S); + if (!IS) + continue; + StringRef Name = IS->Name; + if (Name == ".debug_info") + Ret.push_back(IS); + + // If -gdb-index is given, LLD creates .gdb_index section, and that + // section serves the same purpose as .debug_gnu_pub{names,types} sections. + // If that's the case, we want to eliminate .debug_gnu_pub{names,types} + // because they are redundant and can waste large amount of disk space + // (for example, they are about 400 MiB in total for a clang debug build.) + if (Name == ".debug_gnu_pubnames" || Name == ".debug_gnu_pubtypes") + S = nullptr; + } + std::vector &V = InputSections; + V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); return Ret; } void GdbIndexSection::buildIndex() { - std::vector V = getDebugInfoSections(); - if (V.empty()) + if (Chunks.empty()) return; - for (InputSection *Sec : V) - Chunks.push_back(readDwarf(Sec)); - uint32_t CuId = 0; for (GdbIndexChunk &D : Chunks) { for (AddressEntry &E : D.AddressArea) @@ -1803,27 +1812,34 @@ } } -GdbIndexChunk GdbIndexSection::readDwarf(InputSection *Sec) { - Expected> Obj = - object::ObjectFile::createObjectFile(Sec->File->MB); - if (!Obj) { - error(toString(Sec->File) + ": error creating DWARF context"); - return {}; - } - - DWARFContextInMemory Dwarf(*Obj.get(), nullptr, [&](Error E) { - error(toString(Sec->File) + ": error parsing DWARF data:\n>>> " + - toString(std::move(E))); - return ErrorPolicy::Continue; - }); - +static GdbIndexChunk readDwarf(DWARFContextInMemory &Dwarf, InputSection *Sec) { GdbIndexChunk Ret; - Ret.CompilationUnits = readCuList(Dwarf, Sec); + Ret.Sec = Sec; + Ret.CompilationUnits = readCuList(Dwarf); Ret.AddressArea = readAddressArea(Dwarf, Sec); Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE); return Ret; } +template GdbIndexSection *elf::createGdbIndex() { + std::vector V = getDebugInfoSections(); + std::vector Chunks; + for (InputSection *Sec : V) { + InputFile *F = Sec->File; + std::error_code EC; + ELFObjectFile Obj(F->MB, EC); + if (EC) + fatal(EC.message()); + DWARFContextInMemory Dwarf(Obj, nullptr, [&](Error E) { + error(toString(F) + ": error parsing DWARF data:\n>>> " + + toString(std::move(E))); + return ErrorPolicy::Continue; + }); + Chunks.push_back(readDwarf(Dwarf, Sec)); + } + return make(std::move(Chunks)); +} + static size_t getCuSize(std::vector &C) { size_t Ret = 0; for (GdbIndexChunk &D : C) @@ -1881,7 +1897,7 @@ // Write the CU list. for (GdbIndexChunk &D : Chunks) { for (CompilationUnitEntry &Cu : D.CompilationUnits) { - write64le(Buf, Cu.CuOffset); + write64le(Buf, D.Sec->OutSecOff + Cu.CuOffset); write64le(Buf + 8, Cu.CuLength); Buf += 16; } @@ -2265,7 +2281,6 @@ } for (auto *MS : MergeSections) MS->finalizeContents(); - std::vector &V = InputSections; V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); } @@ -2350,6 +2365,11 @@ StringTableSection *InX::StrTab; SymbolTableBaseSection *InX::SymTab; +template GdbIndexSection *elf::createGdbIndex(); +template GdbIndexSection *elf::createGdbIndex(); +template GdbIndexSection *elf::createGdbIndex(); +template GdbIndexSection *elf::createGdbIndex(); + template void PltSection::addEntry(SymbolBody &Sym); template void PltSection::addEntry(SymbolBody &Sym); template void PltSection::addEntry(SymbolBody &Sym); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -380,7 +380,7 @@ Add(InX::IgotPlt); if (Config->GdbIndex) { - InX::GdbIndex = make(); + InX::GdbIndex = createGdbIndex(); Add(InX::GdbIndex); }