diff --git a/lld/MachO/Dwarf.h b/lld/MachO/Dwarf.h --- a/lld/MachO/Dwarf.h +++ b/lld/MachO/Dwarf.h @@ -9,6 +9,8 @@ #ifndef LLD_MACHO_DWARF_H #define LLD_MACHO_DWARF_H +#include "Relocations.h" + #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DWARF/DWARFObject.h" @@ -17,6 +19,11 @@ class ObjFile; +class MachODWARFSection final : public llvm::DWARFSection { +public: + const InputSection *isec = nullptr; +}; + // Implements the interface between LLVM's DWARF-parsing utilities and LLD's // InputSection structures. class DwarfObject final : public llvm::DWARFObject { @@ -24,17 +31,23 @@ bool isLittleEndian() const override { return true; } llvm::Optional find(const llvm::DWARFSection &sec, - uint64_t pos) const override { - // TODO: implement this - return llvm::None; - } + uint64_t pos) const override; void forEachInfoSections( llvm::function_ref f) const override { f(infoSection); } + const llvm::DWARFSection &getLineSection() const override { + return lineSection; + } + + const llvm::DWARFSection &getAddrSection() const override { + return addrSection; + } + llvm::StringRef getAbbrevSection() const override { return abbrevSection; } + llvm::StringRef getLineStrSection() const override { return lineStrSection; } llvm::StringRef getStrSection() const override { return strSection; } // Returns an instance of DwarfObject if the given object file has the @@ -42,8 +55,12 @@ static std::unique_ptr create(ObjFile *); private: - llvm::DWARFSection infoSection; + MachODWARFSection addrSection; + MachODWARFSection infoSection; + MachODWARFSection lineSection; + llvm::StringRef abbrevSection; + llvm::StringRef lineStrSection; llvm::StringRef strSection; }; diff --git a/lld/MachO/Dwarf.cpp b/lld/MachO/Dwarf.cpp --- a/lld/MachO/Dwarf.cpp +++ b/lld/MachO/Dwarf.cpp @@ -28,12 +28,23 @@ for (const InputSection *isec : obj->debugSections) { if (StringRef *s = StringSwitch(isec->name) - .Case(section_names::debugInfo, &dObj->infoSection.Data) + .Case(section_names::debugLineStr, &dObj->lineStrSection) .Case(section_names::debugAbbrev, &dObj->abbrevSection) .Case(section_names::debugStr, &dObj->strSection) .Default(nullptr)) { *s = toStringRef(isec->data); hasDwarfInfo = true; + + } else if (MachODWARFSection *m = + StringSwitch(isec->name) + .Case(section_names::debugAddr, &dObj->addrSection) + .Case(section_names::debugInfo, &dObj->infoSection) + .Case(section_names::debugLine, &dObj->lineSection) + .Default(nullptr)) { + m->Data = toStringRef(isec->data); + m->isec = isec; + hasDwarfInfo = true; + continue; } } @@ -41,3 +52,42 @@ return dObj; return nullptr; } + +static uint64_t resolver(uint64_t type, uint64_t offset, uint64_t s, + uint64_t locData, int64_t addend) { + return s + addend; +} + +llvm::Optional DwarfObject::find(const llvm::DWARFSection &sec, + uint64_t pos) const { + auto &msec = static_cast(sec); + if (!msec.isec) + return llvm::None; + + const Reloc *found = nullptr; + for (const auto &reloc : msec.isec->relocs) { + if (reloc.offset == pos) { + found = &reloc; + break; + } + } + if (!found) + return llvm::None; + + const Symbol *sym = found->referent.dyn_cast(); + if (!sym) + return llvm::None; + + uint32_t secIndex = sym->symtabIndex; + uint64_t val = 0; + if (const auto *def = dyn_cast(sym)) { + val = def->value; + } + + object::DataRefImpl d; + d.p = found->addend; + + return RelocAddrEntry{secIndex, object::RelocationRef(d, nullptr), + val, llvm::Optional(), + 0, resolver}; +} diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -261,17 +261,9 @@ isec->align = 1 << sec.align; isec->flags = sec.flags; - if (!(isDebugSection(isec->flags) && - isec->segname == segment_names::dwarf)) { - subsections.push_back({{0, isec}}); - } else { - // Instead of emitting DWARF sections, we emit STABS symbols to the - // object files that contain them. We filter them out early to avoid - // parsing their relocations unnecessarily. But we must still push an - // empty map to ensure the indices line up for the remaining sections. - subsections.push_back({}); + subsections.push_back({{0, isec}}); + if (isDebugSection(isec->flags) && isec->segname == segment_names::dwarf) debugSections.push_back(isec); - } } } diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -102,7 +102,10 @@ constexpr const char compactUnwind[] = "__compact_unwind"; constexpr const char data[] = "__data"; constexpr const char debugAbbrev[] = "__debug_abbrev"; +constexpr const char debugAddr[] = "__debug_addr"; constexpr const char debugInfo[] = "__debug_info"; +constexpr const char debugLine[] = "__debug_line"; +constexpr const char debugLineStr[] = "__debug_line_str"; constexpr const char debugStr[] = "__debug_str"; constexpr const char ehFrame[] = "__eh_frame"; constexpr const char export_[] = "__export";