From: Rui Ueyama Date: Sun, 24 Sep 2017 21:45:35 +0000 (+0000) Subject: Refactor GdbIndexSection. NFC. X-Git-Tag: llvmorg-6.0.0-rc1~7296 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9f4f490c31b6320efaccffa978e345376ab68539;p=platform%2Fupstream%2Fllvm.git Refactor GdbIndexSection. NFC. This patch rewrites a part of GdbIndexSection to address the following issues in the previous implementation: - Previously, some struct declarations were in GdbIndex.h while they were not used in GdbIndex.cpp. Such structs are moved to SyntheticSection.h. - The actual implementation were split into GdbIndexSection and GdbHash section, but that separation didn't make much sense. They are now unified as GdbIndexSection. In addition to the above changes, this patch splits functions, rename variables and remove redundant functions/variables to generally improve code quality. llvm-svn: 314084 --- diff --git a/lld/ELF/GdbIndex.cpp b/lld/ELF/GdbIndex.cpp index 1258bda..7db036d 100644 --- a/lld/ELF/GdbIndex.cpp +++ b/lld/ELF/GdbIndex.cpp @@ -24,30 +24,6 @@ using namespace llvm::object; using namespace lld; using namespace lld::elf; -std::pair GdbHashTab::add(uint32_t Hash, size_t Offset) { - GdbSymbol *&Sym = Map[Offset]; - if (Sym) - return {false, Sym}; - Sym = make(Hash, Offset); - return {true, Sym}; -} - -void GdbHashTab::finalizeContents() { - uint32_t Size = std::max(1024, NextPowerOf2(Map.size() * 4 / 3)); - uint32_t Mask = Size - 1; - Table.resize(Size); - - for (auto &P : Map) { - GdbSymbol *Sym = P.second; - uint32_t I = Sym->NameHash & Mask; - uint32_t Step = ((Sym->NameHash * 17) & Mask) | 1; - - while (Table[I]) - I = (I + Step) & Mask; - Table[I] = Sym; - } -} - template LLDDwarfObj::LLDDwarfObj(ObjFile *Obj) : Obj(Obj) { for (InputSectionBase *Sec : Obj->getSections()) { diff --git a/lld/ELF/GdbIndex.h b/lld/ELF/GdbIndex.h index cf2cafd..218ca99 100644 --- a/lld/ELF/GdbIndex.h +++ b/lld/ELF/GdbIndex.h @@ -64,63 +64,6 @@ public: uint64_t Pos) const override; }; -// Struct represents single entry of address area of gdb index. -struct AddressEntry { - InputSection *Section; - uint64_t LowAddress; - uint64_t HighAddress; - uint32_t CuIndex; -}; - -// Struct represents single entry of compilation units list area of gdb index. -// It consist of CU offset in .debug_info section and it's size. -struct CompilationUnitEntry { - uint64_t CuOffset; - uint64_t CuLength; -}; - -// Represents data about symbol and type names which are used -// to build symbol table and constant pool area of gdb index. -struct NameTypeEntry { - StringRef Name; - uint8_t Type; -}; - -// We fill one GdbIndexDataChunk for each object where scan of -// debug information performed. That information futher used -// for filling gdb index section areas. -struct GdbIndexChunk { - InputSection *DebugInfoSec; - std::vector AddressArea; - std::vector CompilationUnits; - std::vector NamesAndTypes; -}; - -// Element of GdbHashTab hash table. -struct GdbSymbol { - GdbSymbol(uint32_t Hash, size_t Offset) - : NameHash(Hash), NameOffset(Offset) {} - uint32_t NameHash; - size_t NameOffset; - size_t CuVectorIndex; -}; - -// This class manages the hashed symbol table for the .gdb_index section. -// The hash value for a table entry is computed by applying an iterative hash -// function to the symbol's name. -class GdbHashTab final { -public: - std::pair add(uint32_t Hash, size_t Offset); - - void finalizeContents(); - size_t getCapacity() { return Table.size(); } - GdbSymbol *getSymbol(size_t I) { return Table[I]; } - -private: - llvm::DenseMap Map; - std::vector Table; -}; - } // namespace elf } // namespace lld diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 9f33ab3..7858e56 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1707,29 +1707,29 @@ unsigned PltSection::getPltRelocOff() const { return (HeaderSize == 0) ? InX::Plt->getSize() : 0; } -// The hash function used for .gdb_index version 5 or above. -static uint32_t gdbHash(StringRef Str) { - uint32_t R = 0; - for (uint8_t C : Str) - R = R * 67 + tolower(C) - 113; - return R; -} - -static std::vector readCuList(DWARFContext &Dwarf) { - std::vector Ret; - for (std::unique_ptr &CU : Dwarf.compile_units()) - Ret.push_back({CU->getOffset(), CU->getLength() + 4}); +// The string hash function for .gdb_index. +static uint32_t computeGdbHash(StringRef S) { + uint32_t H = 0; + for (uint8_t C : S) + H = H * 67 + tolower(C) - 113; + return H; +} + +static std::vector readCuList(DWARFContext &Dwarf) { + std::vector Ret; + for (std::unique_ptr &Cu : Dwarf.compile_units()) + Ret.push_back({Cu->getOffset(), Cu->getLength() + 4}); return Ret; } -static std::vector readAddressArea(DWARFContext &Dwarf, - InputSection *Sec) { - std::vector Ret; +static std::vector +readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) { + std::vector Ret; - uint32_t CurrentCu = 0; - for (std::unique_ptr &CU : Dwarf.compile_units()) { + uint32_t CuIdx = 0; + for (std::unique_ptr &Cu : Dwarf.compile_units()) { DWARFAddressRangesVector Ranges; - CU->collectAddressRanges(Ranges); + Cu->collectAddressRanges(Ranges); ArrayRef Sections = Sec->File->getSections(); for (DWARFAddressRange &R : Ranges) { @@ -1741,22 +1741,22 @@ static std::vector readAddressArea(DWARFContext &Dwarf, continue; auto *IS = cast(S); uint64_t Offset = IS->getOffsetInFile(); - Ret.push_back({IS, R.LowPC - Offset, R.HighPC - Offset, CurrentCu}); + Ret.push_back({IS, R.LowPC - Offset, R.HighPC - Offset, CuIdx}); } - ++CurrentCu; + ++CuIdx; } return Ret; } -static std::vector readPubNamesAndTypes(DWARFContext &Dwarf, - bool IsLE) { - StringRef Data[] = {Dwarf.getDWARFObj().getGnuPubNamesSection(), - Dwarf.getDWARFObj().getGnuPubTypesSection()}; +static std::vector +readPubNamesAndTypes(DWARFContext &Dwarf) { + StringRef Sec1 = Dwarf.getDWARFObj().getGnuPubNamesSection(); + StringRef Sec2 = Dwarf.getDWARFObj().getGnuPubTypesSection(); - std::vector Ret; - for (StringRef D : Data) { - DWARFDebugPubTable PubTable(D, IsLE, true); - for (const DWARFDebugPubTable::Set &Set : PubTable.getData()) + std::vector Ret; + for (StringRef Sec : {Sec1, Sec2}) { + DWARFDebugPubTable Table(Sec, Config->IsLE, true); + for (const DWARFDebugPubTable::Set &Set : Table.getData()) for (const DWARFDebugPubTable::Entry &Ent : Set.Entries) Ret.push_back({Ent.Name, Ent.Descriptor.toBits()}); } @@ -1772,52 +1772,50 @@ static std::vector getDebugInfoSections() { return Ret; } -void GdbIndexSection::buildIndex() { - if (Chunks.empty()) - return; +void GdbIndexSection::fixCuIndex() { + uint32_t Idx = 0; + for (GdbIndexChunk &Chunk : Chunks) { + for (GdbIndexChunk::AddressEntry &Ent : Chunk.AddressAreas) + Ent.CuIndex += Idx; + Idx += Chunk.CompilationUnits.size(); + } +} - uint32_t CuId = 0; - for (GdbIndexChunk &D : Chunks) { - for (AddressEntry &E : D.AddressArea) - E.CuIndex += CuId; - - // Populate constant pool area. - for (NameTypeEntry &NameType : D.NamesAndTypes) { - uint32_t Hash = gdbHash(NameType.Name); - size_t Offset = StringPool.add(NameType.Name); - - bool IsNew; - GdbSymbol *Sym; - std::tie(IsNew, Sym) = HashTab.add(Hash, Offset); - if (IsNew) { - Sym->CuVectorIndex = CuVectors.size(); - CuVectors.resize(CuVectors.size() + 1); - } +std::vector> GdbIndexSection::createCuVectors() { + std::vector> Ret; + uint32_t Idx = 0; - CuVectors[Sym->CuVectorIndex].insert(CuId | (NameType.Type << 24)); - } + for (GdbIndexChunk &Chunk : Chunks) { + for (GdbIndexChunk::NameTypeEntry &Ent : Chunk.NamesAndTypes) { + uint32_t Hash = computeGdbHash(Ent.Name); + size_t Offset = StringPool.add(Ent.Name); - CuId += D.CompilationUnits.size(); + GdbSymbol *&Sym = SymbolMap[Offset]; + if (!Sym) { + Sym = make(GdbSymbol{Hash, Offset, Ret.size()}); + Ret.resize(Ret.size() + 1); + } + Ret[Sym->CuVectorIndex].insert((Ent.Type << 24) | Idx); + } + Idx += Chunk.CompilationUnits.size(); } -} - -static GdbIndexChunk readDwarf(DWARFContext &Dwarf, InputSection *Sec) { - GdbIndexChunk Ret; - Ret.DebugInfoSec = Sec; - Ret.CompilationUnits = readCuList(Dwarf); - Ret.AddressArea = readAddressArea(Dwarf, Sec); - Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE); return Ret; } template GdbIndexSection *elf::createGdbIndex() { std::vector Sections = getDebugInfoSections(); std::vector Chunks(Sections.size()); + parallelForEachN(0, Chunks.size(), [&](size_t I) { - ObjFile *F = Sections[I]->getFile(); - DWARFContext Dwarf(make_unique>(F)); - Chunks[I] = readDwarf(Dwarf, Sections[I]); + ObjFile *File = Sections[I]->getFile(); + DWARFContext Dwarf(make_unique>(File)); + + Chunks[I].DebugInfoSec = Sections[I]; + Chunks[I].CompilationUnits = readCuList(Dwarf); + Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]); + Chunks[I].NamesAndTypes = readPubNamesAndTypes(Dwarf); }); + return make(std::move(Chunks)); } @@ -1831,27 +1829,47 @@ static size_t getCuSize(ArrayRef Arr) { static size_t getAddressAreaSize(ArrayRef Arr) { size_t Ret = 0; for (const GdbIndexChunk &D : Arr) - Ret += D.AddressArea.size(); + Ret += D.AddressAreas.size(); + return Ret; +} + +std::vector GdbIndexSection::createGdbSymtab() { + uint32_t Size = + std::max(1024, NextPowerOf2(SymbolMap.size() * 4 / 3)); + uint32_t Mask = Size - 1; + std::vector Ret(Size); + + for (auto &KV : SymbolMap) { + GdbSymbol *Sym = KV.second; + uint32_t I = Sym->NameHash & Mask; + uint32_t Step = ((Sym->NameHash * 17) & Mask) | 1; + + while (Ret[I]) + I = (I + Step) & Mask; + Ret[I] = Sym; + } return Ret; } GdbIndexSection::GdbIndexSection(std::vector &&C) : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index"), StringPool(llvm::StringTableBuilder::ELF), Chunks(std::move(C)) { - buildIndex(); - HashTab.finalizeContents(); + fixCuIndex(); + CuVectors = createCuVectors(); + GdbSymtab = createGdbSymtab(); - // GdbIndex header consist from version fields - // and 5 more fields with different kinds of offsets. - CuTypesOffset = CuListOffset + getCuSize(Chunks) * CompilationUnitSize; - SymTabOffset = CuTypesOffset + getAddressAreaSize(Chunks) * AddressEntrySize; - ConstantPoolOffset = SymTabOffset + HashTab.getCapacity() * SymTabEntrySize; + // Compute offsets early to know the section size. + // Each chunk size needs to be in sync with what we write in writeTo. + CuTypesOffset = CuListOffset + getCuSize(Chunks) * 16; + SymtabOffset = CuTypesOffset + getAddressAreaSize(Chunks) * 20; + ConstantPoolOffset = SymtabOffset + GdbSymtab.size() * 8; + size_t Off = 0; for (std::set &CuVec : CuVectors) { - CuVectorsOffset.push_back(CuVectorsSize); - CuVectorsSize += OffsetTypeSize * (CuVec.size() + 1); + CuVectorOffsets.push_back(Off); + Off += (CuVec.size() + 1) * 4; } - StringPoolOffset = ConstantPoolOffset + CuVectorsSize; + StringPoolOffset = ConstantPoolOffset + Off; StringPool.finalizeInOrder(); } @@ -1860,17 +1878,18 @@ size_t GdbIndexSection::getSize() const { } void GdbIndexSection::writeTo(uint8_t *Buf) { - write32le(Buf, 7); // Write version - write32le(Buf + 4, CuListOffset); // CU list offset - write32le(Buf + 8, CuTypesOffset); // Types CU list offset - write32le(Buf + 12, CuTypesOffset); // Address area offset - write32le(Buf + 16, SymTabOffset); // Symbol table offset - write32le(Buf + 20, ConstantPoolOffset); // Constant pool offset + // Write the section header. + write32le(Buf, 7); + write32le(Buf + 4, CuListOffset); + write32le(Buf + 8, CuTypesOffset); + write32le(Buf + 12, CuTypesOffset); + write32le(Buf + 16, SymtabOffset); + write32le(Buf + 20, ConstantPoolOffset); Buf += 24; // Write the CU list. for (GdbIndexChunk &D : Chunks) { - for (CompilationUnitEntry &Cu : D.CompilationUnits) { + for (GdbIndexChunk::CuEntry &Cu : D.CompilationUnits) { write64le(Buf, D.DebugInfoSec->OutSecOff + Cu.CuOffset); write64le(Buf + 8, Cu.CuLength); Buf += 16; @@ -1879,7 +1898,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { // Write the address area. for (GdbIndexChunk &D : Chunks) { - for (AddressEntry &E : D.AddressArea) { + for (GdbIndexChunk::AddressEntry &E : D.AddressAreas) { uint64_t BaseAddr = E.Section->getParent()->Addr + E.Section->getOffset(0); write64le(Buf, BaseAddr + E.LowAddress); @@ -1890,19 +1909,15 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { } // Write the symbol table. - for (size_t I = 0; I < HashTab.getCapacity(); ++I) { - GdbSymbol *Sym = HashTab.getSymbol(I); + for (GdbSymbol *Sym : GdbSymtab) { if (Sym) { - size_t NameOffset = - Sym->NameOffset + StringPoolOffset - ConstantPoolOffset; - size_t CuVectorOffset = CuVectorsOffset[Sym->CuVectorIndex]; - write32le(Buf, NameOffset); - write32le(Buf + 4, CuVectorOffset); + write32le(Buf, Sym->NameOffset + StringPoolOffset - ConstantPoolOffset); + write32le(Buf + 4, CuVectorOffsets[Sym->CuVectorIndex]); } Buf += 8; } - // Write the CU vectors into the constant pool. + // Write the CU vectors. for (std::set &CuVec : CuVectors) { write32le(Buf, CuVec.size()); Buf += 4; @@ -1912,6 +1927,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { } } + // Write the string pool. StringPool.write(Buf); } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 3f19afb..1d4f2e9 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -494,13 +494,40 @@ private: size_t HeaderSize; }; -class GdbIndexSection final : public SyntheticSection { - const unsigned OffsetTypeSize = 4; - const unsigned CuListOffset = 6 * OffsetTypeSize; - const unsigned CompilationUnitSize = 16; - const unsigned AddressEntrySize = 16 + OffsetTypeSize; - const unsigned SymTabEntrySize = 2 * OffsetTypeSize; +// GdbIndexChunk is created for each .debug_info section and contains +// information to create a part of .gdb_index for a given input section. +struct GdbIndexChunk { + struct AddressEntry { + InputSection *Section; + uint64_t LowAddress; + uint64_t HighAddress; + uint32_t CuIndex; + }; + + struct CuEntry { + uint64_t CuOffset; + uint64_t CuLength; + }; + + struct NameTypeEntry { + StringRef Name; + uint8_t Type; + }; + + InputSection *DebugInfoSec; + std::vector AddressAreas; + std::vector CompilationUnits; + std::vector NamesAndTypes; +}; + +// The symbol type for the .gdb_index section. +struct GdbSymbol { + uint32_t NameHash; + size_t NameOffset; + size_t CuVectorIndex; +}; +class GdbIndexSection final : public SyntheticSection { public: GdbIndexSection(std::vector &&Chunks); void writeTo(uint8_t *Buf) override; @@ -508,9 +535,16 @@ public: bool empty() const override; private: - // Symbol table is a hash table for types and names. - // It is the area of gdb index. - GdbHashTab HashTab; + void fixCuIndex(); + std::vector> createCuVectors(); + std::vector createGdbSymtab(); + + // A symbol table for this .gdb_index section. + std::vector GdbSymtab; + + // Symbol table entries are uniquified by their offsets, so + // we need a map from offsets to symbols. + llvm::DenseMap SymbolMap; // CU vector is a part of constant pool area of section. std::vector> CuVectors; @@ -522,15 +556,13 @@ private: // object and used to build different areas of gdb index. std::vector Chunks; - void buildIndex(); - + static constexpr uint32_t CuListOffset = 24; uint32_t CuTypesOffset; - uint32_t SymTabOffset; + uint32_t SymtabOffset; uint32_t ConstantPoolOffset; uint32_t StringPoolOffset; - size_t CuVectorsSize = 0; - std::vector CuVectorsOffset; + std::vector CuVectorOffsets; }; template GdbIndexSection *createGdbIndex();