mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-17 04:50:15 +00:00
Refactor gdb index creation.
I have a patch to let DwarfContext defer to lld for getting section contents and relocations. That is a pretty big performance improvement. This is just a refactoring to make that easier to do. This change makes the *creation* of gdb index a dedicated step and makes that templated. That is so that we can uses Elf_Rel in the code. llvm-svn: 307867
This commit is contained in:
parent
6f7c9ad7d4
commit
300b38678c
@ -45,6 +45,7 @@ struct NameTypeEntry {
|
|||||||
// debug information performed. That information futher used
|
// debug information performed. That information futher used
|
||||||
// for filling gdb index section areas.
|
// for filling gdb index section areas.
|
||||||
struct GdbIndexChunk {
|
struct GdbIndexChunk {
|
||||||
|
InputSection *DebugInfoSec;
|
||||||
std::vector<AddressEntry> AddressArea;
|
std::vector<AddressEntry> AddressArea;
|
||||||
std::vector<CompilationUnitEntry> CompilationUnits;
|
std::vector<CompilationUnitEntry> CompilationUnits;
|
||||||
std::vector<NameTypeEntry> NamesAndTypes;
|
std::vector<NameTypeEntry> NamesAndTypes;
|
||||||
|
@ -1700,9 +1700,9 @@ unsigned PltSection::getPltRelocOff() const {
|
|||||||
return (HeaderSize == 0) ? InX::Plt->getSize() : 0;
|
return (HeaderSize == 0) ? InX::Plt->getSize() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GdbIndexSection::GdbIndexSection()
|
GdbIndexSection::GdbIndexSection(std::vector<GdbIndexChunk> &&Chunks)
|
||||||
: SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index"),
|
: 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
|
// 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
|
// specification. Note that we use one for version 5 to 7 here, it is different
|
||||||
@ -1714,11 +1714,10 @@ static uint32_t hash(StringRef Str) {
|
|||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<CompilationUnitEntry> readCuList(DWARFContext &Dwarf,
|
static std::vector<CompilationUnitEntry> readCuList(DWARFContext &Dwarf) {
|
||||||
InputSection *Sec) {
|
|
||||||
std::vector<CompilationUnitEntry> Ret;
|
std::vector<CompilationUnitEntry> Ret;
|
||||||
for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units())
|
for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units())
|
||||||
Ret.push_back({Sec->OutSecOff + CU->getOffset(), CU->getLength() + 4});
|
Ret.push_back({CU->getOffset(), CU->getLength() + 4});
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1765,19 +1764,15 @@ static std::vector<InputSection *> getDebugInfoSections() {
|
|||||||
std::vector<InputSection *> Ret;
|
std::vector<InputSection *> Ret;
|
||||||
for (InputSectionBase *S : InputSections)
|
for (InputSectionBase *S : InputSections)
|
||||||
if (InputSection *IS = dyn_cast<InputSection>(S))
|
if (InputSection *IS = dyn_cast<InputSection>(S))
|
||||||
if (IS->getParent() && IS->Name == ".debug_info")
|
if (IS->Name == ".debug_info")
|
||||||
Ret.push_back(IS);
|
Ret.push_back(IS);
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbIndexSection::buildIndex() {
|
void GdbIndexSection::buildIndex() {
|
||||||
std::vector<InputSection *> V = getDebugInfoSections();
|
if (Chunks.empty())
|
||||||
if (V.empty())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (InputSection *Sec : V)
|
|
||||||
Chunks.push_back(readDwarf(Sec));
|
|
||||||
|
|
||||||
uint32_t CuId = 0;
|
uint32_t CuId = 0;
|
||||||
for (GdbIndexChunk &D : Chunks) {
|
for (GdbIndexChunk &D : Chunks) {
|
||||||
for (AddressEntry &E : D.AddressArea)
|
for (AddressEntry &E : D.AddressArea)
|
||||||
@ -1803,27 +1798,33 @@ void GdbIndexSection::buildIndex() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GdbIndexChunk GdbIndexSection::readDwarf(InputSection *Sec) {
|
static GdbIndexChunk readDwarf(DWARFContextInMemory &Dwarf, 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 {};
|
|
||||||
}
|
|
||||||
|
|
||||||
DWARFContextInMemory Dwarf(*Obj.get(), nullptr, [&](Error E) {
|
|
||||||
error(toString(Sec->File) + ": error parsing DWARF data:\n>>> " +
|
|
||||||
toString(std::move(E)));
|
|
||||||
return ErrorPolicy::Continue;
|
|
||||||
});
|
|
||||||
|
|
||||||
GdbIndexChunk Ret;
|
GdbIndexChunk Ret;
|
||||||
Ret.CompilationUnits = readCuList(Dwarf, Sec);
|
Ret.DebugInfoSec = Sec;
|
||||||
|
Ret.CompilationUnits = readCuList(Dwarf);
|
||||||
Ret.AddressArea = readAddressArea(Dwarf, Sec);
|
Ret.AddressArea = readAddressArea(Dwarf, Sec);
|
||||||
Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE);
|
Ret.NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE);
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ELFT> GdbIndexSection *elf::createGdbIndex() {
|
||||||
|
std::vector<GdbIndexChunk> Chunks;
|
||||||
|
for (InputSection *Sec : getDebugInfoSections()) {
|
||||||
|
InputFile *F = Sec->File;
|
||||||
|
std::error_code EC;
|
||||||
|
ELFObjectFile<ELFT> 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<GdbIndexSection>(std::move(Chunks));
|
||||||
|
}
|
||||||
|
|
||||||
static size_t getCuSize(std::vector<GdbIndexChunk> &C) {
|
static size_t getCuSize(std::vector<GdbIndexChunk> &C) {
|
||||||
size_t Ret = 0;
|
size_t Ret = 0;
|
||||||
for (GdbIndexChunk &D : C)
|
for (GdbIndexChunk &D : C)
|
||||||
@ -1881,7 +1882,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {
|
|||||||
// Write the CU list.
|
// Write the CU list.
|
||||||
for (GdbIndexChunk &D : Chunks) {
|
for (GdbIndexChunk &D : Chunks) {
|
||||||
for (CompilationUnitEntry &Cu : D.CompilationUnits) {
|
for (CompilationUnitEntry &Cu : D.CompilationUnits) {
|
||||||
write64le(Buf, Cu.CuOffset);
|
write64le(Buf, D.DebugInfoSec->OutSecOff + Cu.CuOffset);
|
||||||
write64le(Buf + 8, Cu.CuLength);
|
write64le(Buf + 8, Cu.CuLength);
|
||||||
Buf += 16;
|
Buf += 16;
|
||||||
}
|
}
|
||||||
@ -2350,6 +2351,11 @@ StringTableSection *InX::ShStrTab;
|
|||||||
StringTableSection *InX::StrTab;
|
StringTableSection *InX::StrTab;
|
||||||
SymbolTableBaseSection *InX::SymTab;
|
SymbolTableBaseSection *InX::SymTab;
|
||||||
|
|
||||||
|
template GdbIndexSection *elf::createGdbIndex<ELF32LE>();
|
||||||
|
template GdbIndexSection *elf::createGdbIndex<ELF32BE>();
|
||||||
|
template GdbIndexSection *elf::createGdbIndex<ELF64LE>();
|
||||||
|
template GdbIndexSection *elf::createGdbIndex<ELF64BE>();
|
||||||
|
|
||||||
template void PltSection::addEntry<ELF32LE>(SymbolBody &Sym);
|
template void PltSection::addEntry<ELF32LE>(SymbolBody &Sym);
|
||||||
template void PltSection::addEntry<ELF32BE>(SymbolBody &Sym);
|
template void PltSection::addEntry<ELF32BE>(SymbolBody &Sym);
|
||||||
template void PltSection::addEntry<ELF64LE>(SymbolBody &Sym);
|
template void PltSection::addEntry<ELF64LE>(SymbolBody &Sym);
|
||||||
|
@ -503,7 +503,7 @@ class GdbIndexSection final : public SyntheticSection {
|
|||||||
const unsigned SymTabEntrySize = 2 * OffsetTypeSize;
|
const unsigned SymTabEntrySize = 2 * OffsetTypeSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GdbIndexSection();
|
GdbIndexSection(std::vector<GdbIndexChunk> &&Chunks);
|
||||||
void finalizeContents() override;
|
void finalizeContents() override;
|
||||||
void writeTo(uint8_t *Buf) override;
|
void writeTo(uint8_t *Buf) override;
|
||||||
size_t getSize() const override;
|
size_t getSize() const override;
|
||||||
@ -524,7 +524,6 @@ public:
|
|||||||
std::vector<GdbIndexChunk> Chunks;
|
std::vector<GdbIndexChunk> Chunks;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GdbIndexChunk readDwarf(InputSection *Sec);
|
|
||||||
void buildIndex();
|
void buildIndex();
|
||||||
|
|
||||||
uint32_t CuTypesOffset;
|
uint32_t CuTypesOffset;
|
||||||
@ -538,6 +537,8 @@ private:
|
|||||||
bool Finalized = false;
|
bool Finalized = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class ELFT> GdbIndexSection *createGdbIndex();
|
||||||
|
|
||||||
// --eh-frame-hdr option tells linker to construct a header for all the
|
// --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
|
// .eh_frame sections. This header is placed to a section named .eh_frame_hdr
|
||||||
// and also to a PT_GNU_EH_FRAME segment.
|
// and also to a PT_GNU_EH_FRAME segment.
|
||||||
|
@ -380,7 +380,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
|
|||||||
Add(InX::IgotPlt);
|
Add(InX::IgotPlt);
|
||||||
|
|
||||||
if (Config->GdbIndex) {
|
if (Config->GdbIndex) {
|
||||||
InX::GdbIndex = make<GdbIndexSection>();
|
InX::GdbIndex = createGdbIndex<ELFT>();
|
||||||
Add(InX::GdbIndex);
|
Add(InX::GdbIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user