diff options
Diffstat (limited to 'lld/ELF/DWARF.cpp')
| -rw-r--r-- | lld/ELF/DWARF.cpp | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/lld/ELF/DWARF.cpp b/lld/ELF/DWARF.cpp index 24c44730bf64..707a6ebd1695 100644 --- a/lld/ELF/DWARF.cpp +++ b/lld/ELF/DWARF.cpp @@ -26,7 +26,12 @@ using namespace lld; using namespace lld::elf; template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *obj) { - for (InputSectionBase *sec : obj->getSections()) { + // Get the ELF sections to retrieve sh_flags. See the SHF_GROUP comment below. + ArrayRef<typename ELFT::Shdr> objSections = + CHECK(obj->getObj().sections(), obj); + assert(objSections.size() == obj->getSections().size()); + for (auto it : llvm::enumerate(obj->getSections())) { + InputSectionBase *sec = it.value(); if (!sec) continue; @@ -35,7 +40,6 @@ template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *obj) { .Case(".debug_addr", &addrSection) .Case(".debug_gnu_pubnames", &gnuPubnamesSection) .Case(".debug_gnu_pubtypes", &gnuPubtypesSection) - .Case(".debug_info", &infoSection) .Case(".debug_loclists", &loclistsSection) .Case(".debug_ranges", &rangesSection) .Case(".debug_rnglists", &rnglistsSection) @@ -53,24 +57,43 @@ template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *obj) { strSection = toStringRef(sec->data()); else if (sec->name == ".debug_line_str") lineStrSection = toStringRef(sec->data()); + else if (sec->name == ".debug_info" && + !(objSections[it.index()].sh_flags & ELF::SHF_GROUP)) { + // In DWARF v5, -fdebug-types-section places type units in .debug_info + // sections in COMDAT groups. They are not compile units and thus should + // be ignored for .gdb_index/diagnostics purposes. + // + // We use a simple heuristic: the compile unit does not have the SHF_GROUP + // flag. If we place compile units in COMDAT groups in the future, we may + // need to perform a lightweight parsing. We drop the SHF_GROUP flag when + // the InputSection was created, so we need to retrieve sh_flags from the + // associated ELF section header. + infoSection.Data = toStringRef(sec->data()); + infoSection.sec = sec; + } } } namespace { template <class RelTy> struct LLDRelocationResolver { // In the ELF ABIs, S sepresents the value of the symbol in the relocation - // entry. For Rela, the addend is stored as part of the relocation entry. - static uint64_t resolve(object::RelocationRef ref, uint64_t s, - uint64_t /* A */) { - return s + ref.getRawDataRefImpl().p; + // entry. For Rela, the addend is stored as part of the relocation entry and + // is provided by the `findAux` method. + // In resolve() methods, the `type` and `offset` arguments would always be 0, + // because we don't set an owning object for the `RelocationRef` instance that + // we create in `findAux()`. + static uint64_t resolve(uint64_t /*type*/, uint64_t /*offset*/, uint64_t s, + uint64_t /*locData*/, int64_t addend) { + return s + addend; } }; template <class ELFT> struct LLDRelocationResolver<Elf_Rel_Impl<ELFT, false>> { - // For Rel, the addend A is supplied by the caller. - static uint64_t resolve(object::RelocationRef /*Ref*/, uint64_t s, - uint64_t a) { - return s + a; + // For Rel, the addend is extracted from the relocated location and is + // supplied by the caller. + static uint64_t resolve(uint64_t /*type*/, uint64_t /*offset*/, uint64_t s, + uint64_t locData, int64_t /*addend*/) { + return s + locData; } }; } // namespace |
