aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/DWARF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/DWARF.cpp')
-rw-r--r--lld/ELF/DWARF.cpp43
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