[lld] r304927 - [ELF] - Make implementation of .gdb index to be more natural for futher paralleling.
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 7 09:59:11 PDT 2017
Author: grimar
Date: Wed Jun 7 11:59:11 2017
New Revision: 304927
URL: http://llvm.org/viewvc/llvm-project?rev=304927&view=rev
Log:
[ELF] - Make implementation of .gdb index to be more natural for futher paralleling.
This patch reimplements .gdb_index in more natural way,
that makes proccess of switching to multithreaded index building to
be trivial.
Differential revision: https://reviews.llvm.org/D33552
Modified:
lld/trunk/ELF/GdbIndex.h
lld/trunk/ELF/SyntheticSections.cpp
lld/trunk/ELF/SyntheticSections.h
Modified: lld/trunk/ELF/GdbIndex.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/GdbIndex.h?rev=304927&r1=304926&r2=304927&view=diff
==============================================================================
--- lld/trunk/ELF/GdbIndex.h (original)
+++ lld/trunk/ELF/GdbIndex.h Wed Jun 7 11:59:11 2017
@@ -24,7 +24,30 @@ struct AddressEntry {
InputSection *Section;
uint64_t LowAddress;
uint64_t HighAddress;
- size_t CuIndex;
+ 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 {
+ std::vector<AddressEntry> AddressArea;
+ std::vector<CompilationUnitEntry> CompilationUnits;
+ std::vector<NameTypeEntry> NamesAndTypes;
};
// Element of GdbHashTab hash table.
Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=304927&r1=304926&r2=304927&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Jun 7 11:59:11 2017
@@ -1691,18 +1691,19 @@ static uint32_t hash(StringRef Str) {
return R;
}
-static std::vector<std::pair<uint64_t, uint64_t>>
-readCuList(DWARFContext &Dwarf, InputSection *Sec) {
- std::vector<std::pair<uint64_t, uint64_t>> Ret;
+static std::vector<CompilationUnitEntry> readCuList(DWARFContext &Dwarf,
+ InputSection *Sec) {
+ std::vector<CompilationUnitEntry> Ret;
for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units())
Ret.push_back({Sec->OutSecOff + CU->getOffset(), CU->getLength() + 4});
return Ret;
}
-static std::vector<AddressEntry>
-readAddressArea(DWARFContext &Dwarf, InputSection *Sec, size_t CurrentCU) {
+static std::vector<AddressEntry> readAddressArea(DWARFContext &Dwarf,
+ InputSection *Sec) {
std::vector<AddressEntry> Ret;
+ uint32_t CurrentCu = 0;
for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units()) {
DWARFAddressRangesVector Ranges;
CU->collectAddressRanges(Ranges);
@@ -1715,19 +1716,19 @@ readAddressArea(DWARFContext &Dwarf, Inp
// Range list with zero size has no effect.
if (R.LowPC == R.HighPC)
continue;
- Ret.push_back({cast<InputSection>(S), R.LowPC, R.HighPC, CurrentCU});
+ Ret.push_back({cast<InputSection>(S), R.LowPC, R.HighPC, CurrentCu});
}
- ++CurrentCU;
+ ++CurrentCu;
}
return Ret;
}
-static std::vector<std::pair<StringRef, uint8_t>>
-readPubNamesAndTypes(DWARFContext &Dwarf, bool IsLE) {
+static std::vector<NameTypeEntry> readPubNamesAndTypes(DWARFContext &Dwarf,
+ bool IsLE) {
StringRef Data[] = {Dwarf.getGnuPubNamesSection(),
Dwarf.getGnuPubTypesSection()};
- std::vector<std::pair<StringRef, uint8_t>> Ret;
+ std::vector<NameTypeEntry> Ret;
for (StringRef D : Data) {
DWARFDebugPubTable PubTable(D, IsLE, true);
for (const DWARFDebugPubTable::Set &Set : PubTable.getData())
@@ -1737,40 +1738,77 @@ readPubNamesAndTypes(DWARFContext &Dwarf
return Ret;
}
-void GdbIndexSection::readDwarf(InputSection *Sec) {
+static std::vector<InputSection *> getDebugInfoSections() {
+ std::vector<InputSection *> Ret;
+ for (InputSectionBase *S : InputSections)
+ if (InputSection *IS = dyn_cast<InputSection>(S))
+ if (IS->getParent() && IS->Name == ".debug_info")
+ Ret.push_back(IS);
+ return Ret;
+}
+
+void GdbIndexSection::buildIndex() {
+ std::vector<InputSection *> V = getDebugInfoSections();
+ if (V.empty())
+ return;
+
+ for (InputSection *Sec : V)
+ Chunks.push_back(readDwarf(Sec));
+
+ 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 = 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].insert(CuId | (NameType.Type << 24));
+ }
+
+ CuId += D.CompilationUnits.size();
+ }
+}
+
+GdbIndexChunk GdbIndexSection::readDwarf(InputSection *Sec) {
Expected<std::unique_ptr<object::ObjectFile>> Obj =
object::ObjectFile::createObjectFile(Sec->File->MB);
if (!Obj) {
error(toString(Sec->File) + ": error creating DWARF context");
- return;
+ return {};
}
DWARFContextInMemory Dwarf(*Obj.get());
- size_t CuId = CompilationUnits.size();
- for (std::pair<uint64_t, uint64_t> &P : readCuList(Dwarf, Sec))
- CompilationUnits.push_back(P);
-
- for (AddressEntry &Ent : readAddressArea(Dwarf, Sec, CuId))
- AddressArea.push_back(Ent);
-
- std::vector<std::pair<StringRef, uint8_t>> NamesAndTypes =
- readPubNamesAndTypes(Dwarf, Config->IsLE);
-
- for (std::pair<StringRef, uint8_t> &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.resize(CuVectors.size() + 1);
- }
+ GdbIndexChunk Ret;
+ Ret.CompilationUnits = readCuList(Dwarf, Sec);
+ Ret.AddressArea = readAddressArea(Dwarf, Sec);
+ Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE);
+ return Ret;
+}
- CuVectors[Sym->CuVectorIndex].insert((Pair.second << 24) | (uint32_t)CuId);
- }
+static size_t getCuSize(std::vector<GdbIndexChunk> &C) {
+ size_t Ret = 0;
+ for (GdbIndexChunk &D : C)
+ Ret += D.CompilationUnits.size();
+ return Ret;
+}
+
+static size_t getAddressAreaSize(std::vector<GdbIndexChunk> &C) {
+ size_t Ret = 0;
+ for (GdbIndexChunk &D : C)
+ Ret += D.AddressArea.size();
+ return Ret;
}
void GdbIndexSection::finalizeContents() {
@@ -1778,17 +1816,14 @@ void GdbIndexSection::finalizeContents()
return;
Finalized = true;
- for (InputSectionBase *S : InputSections)
- if (InputSection *IS = dyn_cast<InputSection>(S))
- if (IS->getParent() && 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 + getCuSize(Chunks) * CompilationUnitSize;
+ SymTabOffset = CuTypesOffset + getAddressAreaSize(Chunks) * AddressEntrySize;
ConstantPoolOffset =
SymTabOffset + SymbolTable.getCapacity() * SymTabEntrySize;
@@ -1817,19 +1852,24 @@ void GdbIndexSection::writeTo(uint8_t *B
Buf += 24;
// Write the CU list.
- for (std::pair<uint64_t, uint64_t> CU : CompilationUnits) {
- write64le(Buf, CU.first);
- write64le(Buf + 8, CU.second);
- Buf += 16;
+ for (GdbIndexChunk &D : Chunks) {
+ 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->getParent()->Addr + E.Section->getOffset(0);
- write64le(Buf, BaseAddr + E.LowAddress);
- write64le(Buf + 8, BaseAddr + E.HighAddress);
- write32le(Buf + 16, E.CuIndex);
- Buf += 20;
+ for (GdbIndexChunk &D : Chunks) {
+ for (AddressEntry &E : D.AddressArea) {
+ uint64_t BaseAddr =
+ E.Section->getParent()->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.
Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=304927&r1=304926&r2=304927&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Wed Jun 7 11:59:11 2017
@@ -509,20 +509,23 @@ public:
size_t getSize() const override;
bool empty() const override;
- // Pairs of [CU Offset, CU length].
- std::vector<std::pair<uint64_t, uint64_t>> CompilationUnits;
-
- llvm::StringTableBuilder StringPool;
-
+ // Symbol table is a hash table for types and names.
+ // It is the area of gdb index.
GdbHashTab SymbolTable;
- // The CU vector portion of the constant pool.
+ // CU vector is a part of constant pool area of section.
std::vector<std::set<uint32_t>> CuVectors;
- std::vector<AddressEntry> AddressArea;
+ // String pool is also a part of constant pool, it follows CU vectors.
+ llvm::StringTableBuilder StringPool;
+
+ // Each chunk contains information gathered from a debug sections of single
+ // object and used to build different areas of gdb index.
+ std::vector<GdbIndexChunk> Chunks;
private:
- void readDwarf(InputSection *Sec);
+ GdbIndexChunk readDwarf(InputSection *Sec);
+ void buildIndex();
uint32_t CuTypesOffset;
uint32_t SymTabOffset;
More information about the llvm-commits
mailing list