diff --git a/lld/MachO/Dwarf.h b/lld/MachO/Dwarf.h --- a/lld/MachO/Dwarf.h +++ b/lld/MachO/Dwarf.h @@ -9,14 +9,23 @@ #ifndef LLD_MACHO_DWARF_H #define LLD_MACHO_DWARF_H +#include "Relocations.h" + #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DWARF/DWARFObject.h" +#include + namespace lld { namespace macho { 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 +33,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 +57,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 @@ -10,6 +10,7 @@ #include "InputFiles.h" #include "InputSection.h" #include "OutputSegment.h" +#include "Symbols.h" #include @@ -27,12 +28,24 @@ // ourselves. for (const InputSection *isec : obj->debugSections) { if (StringRef *s = StringSwitch(isec->name) - .Case("__debug_info", &dObj->infoSection.Data) .Case("__debug_abbrev", &dObj->abbrevSection) + .Case("__debug_line_str", &dObj->lineStrSection) .Case("__debug_str", &dObj->strSection) .Default(nullptr)) { *s = toStringRef(isec->data); hasDwarfInfo = true; + continue; + } + + if (MachODWARFSection *m = StringSwitch(isec->name) + .Case("__debug_addr", &dObj->addrSection) + .Case("__debug_info", &dObj->infoSection) + .Case("__debug_line", &dObj->lineSection) + .Default(nullptr)) { + m->Data = toStringRef(isec->data); + m->isec = isec; + hasDwarfInfo = true; + continue; } } @@ -40,3 +53,43 @@ 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 == nullptr) + return llvm::None; + + const Reloc *found = nullptr; + // FIXME: relocs might be sorted already? (in which case, better to bisct?) + 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}; +}