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:
Rafael Espindola 2017-07-12 23:56:53 +00:00
parent 6f7c9ad7d4
commit 300b38678c
4 changed files with 38 additions and 30 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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.

View File

@ -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);
} }