Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lld/ELF/SyntheticSections.cpp
Show First 20 Lines • Show All 2,693 Lines • ▼ Show 20 Lines | void GdbIndexSection::initOutputSize() { | ||||
// Add the constant pool size if exists. | // Add the constant pool size if exists. | ||||
if (!symbols.empty()) { | if (!symbols.empty()) { | ||||
GdbSymbol &sym = symbols.back(); | GdbSymbol &sym = symbols.back(); | ||||
size += sym.nameOff + sym.name.size() + 1; | size += sym.nameOff + sym.name.size() + 1; | ||||
} | } | ||||
} | } | ||||
static std::vector<InputSection *> getDebugInfoSections() { | static std::vector<InputSection *> getDebugInfoSections() { | ||||
// Add at most one .debug_info for an InputFile, Also see the comment in | |||||
// LLDDwarfObj<ELFT>::LLDDwarfObj. If we do lightweight parsing in the future, | |||||
// note that isec->data() may uncompress the full content, which should be | |||||
// parallelized. | |||||
std::vector<InputSection *> ret; | std::vector<InputSection *> ret; | ||||
DenseSet<InputFile *> seen; | |||||
for (InputSectionBase *s : inputSections) | for (InputSectionBase *s : inputSections) | ||||
if (InputSection *isec = dyn_cast<InputSection>(s)) | if (InputSection *isec = dyn_cast<InputSection>(s)) | ||||
if (isec->name == ".debug_info") | if (isec->name == ".debug_info" && seen.insert(isec->file).second) | ||||
ret.push_back(isec); | ret.push_back(isec); | ||||
return ret; | return ret; | ||||
} | } | ||||
static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &dwarf) { | static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &dwarf) { | ||||
std::vector<GdbIndexSection::CuEntry> ret; | std::vector<GdbIndexSection::CuEntry> ret; | ||||
for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units()) | for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units()) | ||||
ret.push_back({cu->getOffset(), cu->getLength() + 4}); | ret.push_back({cu->getOffset(), cu->getLength() + 4}); | ||||
▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | for (GdbSymbol &sym : ret) { | ||||
off += sym.name.size() + 1; | off += sym.name.size() + 1; | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
// Returns a newly-created .gdb_index section. | // Returns a newly-created .gdb_index section. | ||||
template <class ELFT> GdbIndexSection *GdbIndexSection::create() { | template <class ELFT> GdbIndexSection *GdbIndexSection::create() { | ||||
std::vector<InputSection *> sections = getDebugInfoSections(); | std::vector<InputSection *> sections = getDebugInfoSections(); | ||||
grimar: It doesn't seem the `getDebugInfoSections` helper and its name makes much sence now with this… | |||||
// .debug_gnu_pub{names,types} are useless in executables. | // .debug_gnu_pub{names,types} are useless in executables. | ||||
// They are present in input object files solely for creating | // They are present in input object files solely for creating | ||||
// a .gdb_index. So we can remove them from the output. | // a .gdb_index. So we can remove them from the output. | ||||
for (InputSectionBase *s : inputSections) | for (InputSectionBase *s : inputSections) | ||||
if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes") | if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes") | ||||
s->markDead(); | s->markDead(); | ||||
std::vector<GdbChunk> chunks(sections.size()); | std::vector<GdbChunk> chunks(sections.size()); | ||||
std::vector<std::vector<NameAttrEntry>> nameAttrs(sections.size()); | std::vector<std::vector<NameAttrEntry>> nameAttrs(sections.size()); | ||||
parallelForEachN(0, sections.size(), [&](size_t i) { | parallelForEachN(0, sections.size(), [&](size_t i) { | ||||
// To keep memory usage low, we don't want to keep cached DWARFContext, so | // To keep memory usage low, we don't want to keep cached DWARFContext, so | ||||
// avoid getDwarf() here. | // avoid getDwarf() here. | ||||
ObjFile<ELFT> *file = sections[i]->getFile<ELFT>(); | ObjFile<ELFT> *file = sections[i]->getFile<ELFT>(); | ||||
DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(file)); | DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(file)); | ||||
auto &dobj = static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()); | |||||
chunks[i].sec = sections[i]; | // sections[i] may not be the compile unit. Use dobj.getInfoSection(). | ||||
chunks[i].sec = dobj.getInfoSection(); | |||||
chunks[i].compilationUnits = readCuList(dwarf); | chunks[i].compilationUnits = readCuList(dwarf); | ||||
chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]); | chunks[i].addressAreas = readAddressAreas(dwarf, chunks[i].sec); | ||||
nameAttrs[i] = readPubNamesAndTypes<ELFT>( | nameAttrs[i] = readPubNamesAndTypes<ELFT>(dobj, chunks[i].compilationUnits); | ||||
static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()), | |||||
chunks[i].compilationUnits); | |||||
}); | }); | ||||
Previously, parallelForEachN loop assumed that there is a one .debug_info section in an object. Also, you do not need to build a list sections, because you are not using them (you call dobj.getInfoSection(); anyways), so With that we can have a simpler code: SetVector<ObjFile<ELFT> *> files; for (InputSectionBase *s : inputSections) { InputSection *isec = dyn_cast<InputSection>(s); if (!isec) continue; // .debug_gnu_pub{names,types} are useless in executables. // They are present in input object files solely for creating // a .gdb_index. So we can remove them from the output. if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes") s->markDead(); else if (isec->name == ".debug_info") files.insert(isec->getFile<ELFT>()); } std::vector<GdbChunk> chunks(files.size()); std::vector<std::vector<NameAttrEntry>> nameAttrs(files.size()); parallelForEachN(0, files.size(), [&](size_t i) { // To keep memory usage low, we don't want to keep cached DWARFContext, so // avoid getDwarf() here. DWARFContext dwarf(std::make_unique<LLDDwarfObj<ELFT>>(files[i])); auto &dobj = static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()); ... grimar: Previously, `parallelForEachN` loop assumed that there is a one `.debug_info` section in an… | |||||
Forgot to push this comment: Thanks! I'll make a small change: SetVector<InputFile *>, just so that we don't need to instantiate nearly identical code for 4 instantiations of ELFT. MaskRay: Forgot to push this comment:
Thanks! I'll make a small change: `SetVector<InputFile *>`, just… | |||||
auto *ret = make<GdbIndexSection>(); | auto *ret = make<GdbIndexSection>(); | ||||
ret->chunks = std::move(chunks); | ret->chunks = std::move(chunks); | ||||
ret->symbols = createSymbols(nameAttrs, ret->chunks); | ret->symbols = createSymbols(nameAttrs, ret->chunks); | ||||
ret->initOutputSize(); | ret->initOutputSize(); | ||||
return ret; | return ret; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 974 Lines • Show Last 20 Lines |
It doesn't seem the getDebugInfoSections helper and its name makes much sence now with this change?
So I think it should probably just be inlined and/or rewritten to collect a file set mentioned probably?