mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-16 20:41:44 +00:00
[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 llvm-svn: 304927
This commit is contained in:
parent
33e5872367
commit
8666562e89
@ -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.
|
||||
|
@ -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, InputSection *Sec, size_t CurrentCU) {
|
||||
// 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, bool IsLE) {
|
||||
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);
|
||||
GdbIndexChunk Ret;
|
||||
Ret.CompilationUnits = readCuList(Dwarf, Sec);
|
||||
Ret.AddressArea = readAddressArea(Dwarf, Sec);
|
||||
Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
for (AddressEntry &Ent : readAddressArea(Dwarf, Sec, CuId))
|
||||
AddressArea.push_back(Ent);
|
||||
static size_t getCuSize(std::vector<GdbIndexChunk> &C) {
|
||||
size_t Ret = 0;
|
||||
for (GdbIndexChunk &D : C)
|
||||
Ret += D.CompilationUnits.size();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
CuVectors[Sym->CuVectorIndex].insert((Pair.second << 24) | (uint32_t)CuId);
|
||||
}
|
||||
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 *Buf) {
|
||||
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.
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user