Index: ELF/GdbIndex.h =================================================================== --- ELF/GdbIndex.h +++ ELF/GdbIndex.h @@ -27,6 +27,22 @@ size_t CuIndex; }; +struct CompilationUnitEntry { + size_t CuOffset; + size_t CuLength; +}; + +struct NameTypeEntry { + StringRef Name; + uint8_t Type; +}; + +struct FileGdbIndexData { + std::vector AddressArea; + std::vector CompilationUnits; + std::vector NamesAndTypes; +}; + // Element of GdbHashTab hash table. struct GdbSymbol { GdbSymbol(uint32_t Hash, size_t Offset) Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -507,20 +507,15 @@ size_t getSize() const override; bool empty() const override; - // Pairs of [CU Offset, CU length]. - std::vector> CompilationUnits; + std::vector> CuVectors; llvm::StringTableBuilder StringPool; - GdbHashTab SymbolTable; - - // The CU vector portion of the constant pool. - std::vector>> CuVectors; - - std::vector AddressArea; + std::vector IndexData; private: - void readDwarf(InputSection *Sec); + void readDwarf(InputSection *Sec, FileGdbIndexData &Data); + void buildIndex(); uint32_t CuTypesOffset; uint32_t SymTabOffset; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1685,9 +1685,9 @@ return R; } -static std::vector> -readCuList(DWARFContext &Dwarf, InputSection *Sec) { - std::vector> Ret; +static std::vector readCuList(DWARFContext &Dwarf, + InputSection *Sec) { + std::vector Ret; for (std::unique_ptr &CU : Dwarf.compile_units()) Ret.push_back({Sec->OutSecOff + CU->getOffset(), CU->getLength() + 4}); return Ret; @@ -1704,10 +1704,11 @@ return nullptr; } -static std::vector -readAddressArea(DWARFContext &Dwarf, InputSection *Sec, size_t CurrentCU) { +static std::vector readAddressArea(DWARFContext &Dwarf, + InputSection *Sec) { std::vector Ret; + size_t CurrentCU = 0; for (std::unique_ptr &CU : Dwarf.compile_units()) { DWARFAddressRangesVector Ranges; CU->collectAddressRanges(Ranges); @@ -1722,12 +1723,12 @@ return Ret; } -static std::vector> -readPubNamesAndTypes(DWARFContext &Dwarf, bool IsLE) { +static std::vector readPubNamesAndTypes(DWARFContext &Dwarf, + bool IsLE) { StringRef Data[] = {Dwarf.getGnuPubNamesSection(), Dwarf.getGnuPubTypesSection()}; - std::vector> Ret; + std::vector Ret; for (StringRef D : Data) { DWARFDebugPubTable PubTable(D, IsLE, true); for (const DWARFDebugPubTable::Set &Set : PubTable.getData()) @@ -1748,7 +1749,51 @@ std::unique_ptr clone() const override { return {}; } }; -void GdbIndexSection::readDwarf(InputSection *Sec) { +static std::vector getInfoSections() { + std::vector Ret; + for (InputSectionBase *S : InputSections) + if (InputSection *IS = dyn_cast(S)) + if (IS->OutSec && IS->Name == ".debug_info") + Ret.push_back(IS); + return Ret; +} + +void GdbIndexSection::buildIndex() { + std::vector V = getInfoSections(); + if (V.empty()) + return; + + IndexData.resize(V.size()); + for (size_t I = 0; I < V.size(); ++I) + readDwarf(V[I], IndexData[I]); + + size_t CuId = 0; + for (FileGdbIndexData &D : IndexData) { + for (AddressEntry &E : D.AddressArea) + E.CuIndex += CuId; + + // Populate constant pool area. + for (NameTypeEntry &NameType : D.NamesAndTypes) { + uint32_t Hash = hash(NameType.Name); + size_t Offset = StringPool.add(NameType.Name); + + bool IsNew; + GdbSymbol *Sym; + std::tie(IsNew, Sym) = SymbolTable.add(Hash, Offset); + if (IsNew) { + Sym->CuVectorIndex = CuVectors.size(); + CuVectors.push_back({}); + } + + CuVectors[Sym->CuVectorIndex].push_back((uint32_t)CuId | + (NameType.Type << 24)); + } + + CuId += D.CompilationUnits.size(); + } +} + +void GdbIndexSection::readDwarf(InputSection *Sec, FileGdbIndexData& Data) { Expected> Obj = object::ObjectFile::createObjectFile(Sec->File->MB); if (!Obj) { @@ -1759,31 +1804,23 @@ ObjInfoTy ObjInfo; DWARFContextInMemory Dwarf(*Obj.get(), &ObjInfo); - size_t CuId = CompilationUnits.size(); - for (std::pair &P : readCuList(Dwarf, Sec)) - CompilationUnits.push_back(P); - - for (AddressEntry &Ent : readAddressArea(Dwarf, Sec, CuId)) - AddressArea.push_back(Ent); - - std::vector> NamesAndTypes = - readPubNamesAndTypes(Dwarf, Config->IsLE); - - for (std::pair &Pair : NamesAndTypes) { - uint32_t Hash = hash(Pair.first); - size_t Offset = StringPool.add(Pair.first); - - bool IsNew; - GdbSymbol *Sym; - std::tie(IsNew, Sym) = SymbolTable.add(Hash, Offset); - if (IsNew) { - Sym->CuVectorIndex = CuVectors.size(); - CuVectors.push_back({{CuId, Pair.second}}); - continue; - } + Data.CompilationUnits = readCuList(Dwarf, Sec); + Data.AddressArea = readAddressArea(Dwarf, Sec); + Data.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE); +} - CuVectors[Sym->CuVectorIndex].push_back({CuId, Pair.second}); - } +static size_t findCUSize(std::vector &C) { + size_t Ret = 0; + for (FileGdbIndexData &D : C) + Ret += D.CompilationUnits.size(); + return Ret; +} + +static size_t findAddrAreaSize(std::vector &C) { + size_t Ret = 0; + for (FileGdbIndexData &D : C) + Ret += D.AddressArea.size(); + return Ret; } void GdbIndexSection::finalizeContents() { @@ -1791,22 +1828,19 @@ return; Finalized = true; - for (InputSectionBase *S : InputSections) - if (InputSection *IS = dyn_cast(S)) - if (IS->OutSec && IS->Name == ".debug_info") - readDwarf(IS); + buildIndex(); SymbolTable.finalizeContents(); // GdbIndex header consist from version fields // and 5 more fields with different kinds of offsets. - CuTypesOffset = CuListOffset + CompilationUnits.size() * CompilationUnitSize; - SymTabOffset = CuTypesOffset + AddressArea.size() * AddressEntrySize; + CuTypesOffset = CuListOffset + findCUSize(IndexData) * CompilationUnitSize; + SymTabOffset = CuTypesOffset + findAddrAreaSize(IndexData) * AddressEntrySize; ConstantPoolOffset = SymTabOffset + SymbolTable.getCapacity() * SymTabEntrySize; - for (std::vector> &CuVec : CuVectors) { + for (std::vector &CuVec : CuVectors) { CuVectorsOffset.push_back(CuVectorsSize); CuVectorsSize += OffsetTypeSize * (CuVec.size() + 1); } @@ -1830,19 +1864,23 @@ Buf += 24; // Write the CU list. - for (std::pair CU : CompilationUnits) { - write64le(Buf, CU.first); - write64le(Buf + 8, CU.second); - Buf += 16; + for (FileGdbIndexData &D : IndexData) { + for (CompilationUnitEntry &CU : D.CompilationUnits) { + write64le(Buf, CU.CuOffset); + write64le(Buf + 8, CU.CuLength); + Buf += 16; + } } // Write the address area. - for (AddressEntry &E : AddressArea) { - uint64_t BaseAddr = E.Section->OutSec->Addr + E.Section->getOffset(0); - write64le(Buf, BaseAddr + E.LowAddress); - write64le(Buf + 8, BaseAddr + E.HighAddress); - write32le(Buf + 16, E.CuIndex); - Buf += 20; + for (FileGdbIndexData &D : IndexData) { + for (AddressEntry &E : D.AddressArea) { + uint64_t BaseAddr = E.Section->OutSec->Addr + E.Section->getOffset(0); + write64le(Buf, BaseAddr + E.LowAddress); + write64le(Buf + 8, BaseAddr + E.HighAddress); + write32le(Buf + 16, E.CuIndex); + Buf += 20; + } } // Write the symbol table. @@ -1859,14 +1897,11 @@ } // Write the CU vectors into the constant pool. - for (std::vector> &CuVec : CuVectors) { + for (std::vector &CuVec : CuVectors) { write32le(Buf, CuVec.size()); Buf += 4; - for (std::pair &P : CuVec) { - uint32_t Index = P.first; - uint8_t Flags = P.second; - Index |= Flags << 24; - write32le(Buf, Index); + for (uint32_t Val : CuVec) { + write32le(Buf, Val); Buf += 4; } }