Index: include/llvm/DebugInfo/DIContext.h =================================================================== --- include/llvm/DebugInfo/DIContext.h +++ include/llvm/DebugInfo/DIContext.h @@ -132,7 +132,8 @@ virtual ~DIContext(); /// getDWARFContext - get a context for binary DWARF data. - static DIContext *getDWARFContext(const object::ObjectFile &Obj); + static DIContext *getDWARFContext(const object::ObjectFile &Obj, + const object::LoadedObjectInfo *L = nullptr); virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; Index: include/llvm/DebugInfo/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARFContext.h +++ include/llvm/DebugInfo/DWARFContext.h @@ -21,6 +21,7 @@ #include "llvm/DebugInfo/DWARFSection.h" #include "llvm/DebugInfo/DWARFTypeUnit.h" #include "llvm/DebugInfo/DIContext.h" + #include namespace llvm { @@ -248,7 +249,8 @@ SmallVector, 4> UncompressedSections; public: - DWARFContextInMemory(const object::ObjectFile &Obj); + DWARFContextInMemory(const object::ObjectFile &Obj, + const object::LoadedObjectInfo *L = nullptr); bool isLittleEndian() const override { return IsLittleEndian; } uint8_t getAddressSize() const override { return AddressSize; } const DWARFSection &getInfoSection() override { return InfoSection; } Index: include/llvm/DebugInfo/DWARFDebugLine.h =================================================================== --- include/llvm/DebugInfo/DWARFDebugLine.h +++ include/llvm/DebugInfo/DWARFDebugLine.h @@ -94,6 +94,10 @@ return LHS.Address < RHS.Address; } + static bool orderByAddressLeq(const Row& LHS, const Row& RHS) { + return LHS.Address <= RHS.Address; + } + // The program-counter value corresponding to a machine instruction // generated by the compiler. uint64_t Address; Index: include/llvm/ExecutionEngine/RuntimeDyld.h =================================================================== --- include/llvm/ExecutionEngine/RuntimeDyld.h +++ include/llvm/ExecutionEngine/RuntimeDyld.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Memory.h" #include @@ -48,12 +49,14 @@ public: /// \brief Information about the loaded object. - class LoadedObjectInfo { + class LoadedObjectInfo : public object::LoadedObjectInfo { friend class RuntimeDyldImpl; public: LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, unsigned EndIdx) - : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } + : object::LoadedObjectInfo(), + RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) + { } virtual ~LoadedObjectInfo() {} @@ -62,6 +65,8 @@ uint64_t getSectionLoadAddress(StringRef Name) const; + virtual LoadedObjectInfo *clone() const = 0; + protected: virtual void anchor(); Index: include/llvm/Object/COFF.h =================================================================== --- include/llvm/Object/COFF.h +++ include/llvm/Object/COFF.h @@ -612,6 +612,7 @@ std::error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + section_iterator getRelocationSection(DataRefImpl Rel) const override; std::error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; std::error_code Index: include/llvm/Object/ELFObjectFile.h =================================================================== --- include/llvm/Object/ELFObjectFile.h +++ include/llvm/Object/ELFObjectFile.h @@ -112,6 +112,7 @@ std::error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + section_iterator getRelocationSection(DataRefImpl Rel) const override; std::error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; std::error_code @@ -565,6 +566,13 @@ return symbol_iterator(SymbolRef(SymbolData, this)); } +// ELF relocations can not target sections +template +section_iterator +ELFObjectFile::getRelocationSection(DataRefImpl Rel) const { + return section_end(); +} + template std::error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, Index: include/llvm/Object/MachO.h =================================================================== --- include/llvm/Object/MachO.h +++ include/llvm/Object/MachO.h @@ -235,6 +235,7 @@ std::error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + section_iterator getRelocationSection(DataRefImpl Rel) const override; std::error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; std::error_code @@ -245,6 +246,7 @@ SmallVectorImpl &Result) const override; std::error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const override; + std::error_code getRelocationLength(DataRefImpl Rel, uint8_t &Res) const; // MachO specific. std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; @@ -326,7 +328,7 @@ unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; - SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const; + SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const; // Walk load commands. LoadCommandInfo getFirstLoadCommandInfo() const; Index: include/llvm/Object/ObjectFile.h =================================================================== --- include/llvm/Object/ObjectFile.h +++ include/llvm/Object/ObjectFile.h @@ -32,6 +32,8 @@ class SymbolRef; class symbol_iterator; +class SectionRef; +typedef content_iterator section_iterator; /// RelocationRef - This is a value type class that represents a single /// relocation in the list of relocations in the object file. @@ -51,6 +53,7 @@ std::error_code getAddress(uint64_t &Result) const; std::error_code getOffset(uint64_t &Result) const; symbol_iterator getSymbol() const; + section_iterator getSection() const; std::error_code getType(uint64_t &Result) const; /// @brief Indicates whether this relocation should hidden when listing @@ -76,8 +79,6 @@ /// SectionRef - This is a value type class that represents a single section in /// the list of sections in the object file. -class SectionRef; -typedef content_iterator section_iterator; class SectionRef { friend class SymbolRef; DataRefImpl SectionPimpl; @@ -247,6 +248,7 @@ virtual std::error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const = 0; virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; + virtual section_iterator getRelocationSection(DataRefImpl Rel) const = 0; virtual std::error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const = 0; virtual std::error_code @@ -467,6 +469,10 @@ return OwningObject->getRelocationSymbol(RelocationPimpl); } +inline section_iterator RelocationRef::getSection() const { + return OwningObject->getRelocationSection(RelocationPimpl); +} + inline std::error_code RelocationRef::getType(uint64_t &Result) const { return OwningObject->getRelocationType(RelocationPimpl, Result); } @@ -493,6 +499,16 @@ return OwningObject; } +/// \brief An inferface for inquiring the load address of a loaded object file +class LoadedObjectInfo { +public: + LoadedObjectInfo() {} + virtual ~LoadedObjectInfo(); + + virtual uint64_t getSectionLoadAddress(StringRef Name) const = 0; + + virtual LoadedObjectInfo *clone() const = 0; +}; } // end namespace object } // end namespace llvm Index: include/llvm/Object/RelocVisitor.h =================================================================== --- include/llvm/Object/RelocVisitor.h +++ include/llvm/Object/RelocVisitor.h @@ -18,10 +18,12 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/MachO.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -52,6 +54,8 @@ return visitELF(RelocType, R, Value); if (isa(ObjToVisit)) return visitCOFF(RelocType, R, Value); + if (isa(ObjToVisit)) + return visitMachO(RelocType, R, Value); HasError = true; return RelocToApply(); @@ -221,6 +225,20 @@ return RelocToApply(); } + RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) { + switch (ObjToVisit.getArch()) { + default: break; + case Triple::x86_64: + switch (RelocType) { + default: break; + case MachO::X86_64_RELOC_UNSIGNED: + return visitMACHO_X86_64_UNSIGNED(R, Value); + } + } + HasError = true; + return RelocToApply(); + } + int64_t getELFAddend32LE(RelocationRef R) { const ELF32LEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); @@ -252,6 +270,15 @@ Obj->getRelocationAddend(DRI, Addend); return Addend; } + + uint8_t getLengthMachO64(RelocationRef R) { + const MachOObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + uint8_t Length; + Obj->getRelocationLength(DRI, Length); + return Length; + } + /// Operations /// 386-ELF @@ -413,6 +440,13 @@ RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) { return RelocToApply(Value, /*Width=*/8); } + + // X86_64 MachO + RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) { + uint8_t Length = getLengthMachO64(R); + Length = 1<getSectionLoadAddress(name) : 0; + if (LoadAddress != 0) + { + uint64_t Size = Section.getSize(); + data = StringRef(reinterpret_cast(LoadAddress),Size); + } else { + Section.getContents(data); + } name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. @@ -621,6 +630,13 @@ StringRef RelSecName; RelocatedSection->getName(RelSecName); + + // Check if the JIT already did the relocations for us + // If so, we just use the relocated section + bool AlreadyRelocated = L && L->getSectionLoadAddress(RelSecName) != 0; + if (AlreadyRelocated) + continue; + RelSecName = RelSecName.substr( RelSecName.find_first_not_of("._")); // Skip . and _ prefixes. @@ -656,9 +672,33 @@ uint64_t Type; Reloc.getType(Type); uint64_t SymAddr = 0; + uint64_t SectionLoadAddress = 0; object::symbol_iterator Sym = Reloc.getSymbol(); - if (Sym != Obj.symbol_end()) + object::section_iterator RSec(Obj.section_end()); + if (Sym != Obj.symbol_end()) { Sym->getAddress(SymAddr); + Sym->getSection(RSec); + if (RSec != Obj.section_end()) { + StringRef SecName; + RSec->getName(SecName); + SectionLoadAddress = L ? L->getSectionLoadAddress(SecName) : 0; + if (SectionLoadAddress != 0) { + uint64_t SecAddr = RSec->getAddress(); + SymAddr += SectionLoadAddress - SecAddr; + } + } + } else { + RSec = Reloc.getSection(); + if (RSec != Obj.section_end()) { + SymAddr = RSec->getAddress(); + StringRef SecName; + RSec->getName(SecName); + SectionLoadAddress = L ? L->getSectionLoadAddress(SecName) : 0; + if (SectionLoadAddress != 0) { + SymAddr = SectionLoadAddress; + } + } + } object::RelocVisitor V(Obj); object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); Index: lib/DebugInfo/DWARFDebugLine.cpp =================================================================== --- lib/DebugInfo/DWARFDebugLine.cpp +++ lib/DebugInfo/DWARFDebugLine.cpp @@ -605,13 +605,10 @@ RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex; RowIter last_row = Rows.begin() + cur_seq.LastRowIndex; RowIter row_pos = std::upper_bound(first_row, last_row, row, - DWARFDebugLine::Row::orderByAddress); + DWARFDebugLine::Row::orderByAddressLeq); // The 'row_pos' iterator references the first row that is greater than - // our start address. Unless that's the first row, we want to start at - // the row before that. + // or equal to our start address. first_row_index = cur_seq.FirstRowIndex + (row_pos - first_row); - if (row_pos != first_row) - --first_row_index; } else first_row_index = cur_seq.FirstRowIndex; @@ -623,9 +620,11 @@ RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex; RowIter last_row = Rows.begin() + cur_seq.LastRowIndex; RowIter row_pos = std::upper_bound(first_row, last_row, row, - DWARFDebugLine::Row::orderByAddress); + DWARFDebugLine::Row::orderByAddressLeq); // The 'row_pos' iterator references the first row that is greater than - // our end address. The row before that is the last row we want. + // or equal our end address. The row before that is the last row we want, + // since end_address is the first address past the end of the range we're + // looking up. last_row_index = cur_seq.FirstRowIndex + (row_pos - first_row) - 1; } else // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -111,6 +111,8 @@ OwningBinary getObjectForDebug(const ObjectFile &Obj) const override; + + RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedELFObjectInfo(*this); } }; template Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -37,6 +37,8 @@ getObjectForDebug(const ObjectFile &Obj) const override { return OwningBinary(); } + + RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedMachOObjectInfo(*this); } }; } @@ -75,7 +77,7 @@ Value.Offset = RE.Addend; } } else { - SectionRef Sec = Obj.getRelocationSection(RelInfo); + SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); bool IsCode = Sec.isText(); Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr = Sec.getAddress(); Index: lib/Object/COFFObjectFile.cpp =================================================================== --- lib/Object/COFFObjectFile.cpp +++ lib/Object/COFFObjectFile.cpp @@ -1037,6 +1037,10 @@ return symbol_iterator(SymbolRef(Ref, this)); } +section_iterator COFFObjectFile::getRelocationSection(DataRefImpl Rel) const { + return section_end(); +} + std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const coff_relocation* R = toRel(Rel); Index: lib/Object/MachOObjectFile.cpp =================================================================== --- lib/Object/MachOObjectFile.cpp +++ lib/Object/MachOObjectFile.cpp @@ -675,6 +675,11 @@ return symbol_iterator(SymbolRef(Sym, this)); } +section_iterator +MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { + return section_iterator(getAnyRelocationSection(getRelocation(Rel))); +} + std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { MachO::any_relocation_info RE = getRelocation(Rel); @@ -998,6 +1003,13 @@ return object_error::success; } +std::error_code MachOObjectFile::getRelocationLength(DataRefImpl Rel, + uint8_t &Res) const { + MachO::any_relocation_info RE = getRelocation(Rel); + Res = getAnyRelocationLength(RE); + return object_error::success; +} + // // guessLibraryShortName() is passed a name of a dynamic library and returns a // guess on what the short name is. Then name is returned as a substring of the @@ -2184,7 +2196,7 @@ } SectionRef -MachOObjectFile::getRelocationSection( +MachOObjectFile::getAnyRelocationSection( const MachO::any_relocation_info &RE) const { if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) return *section_end(); Index: lib/Object/ObjectFile.cpp =================================================================== --- lib/Object/ObjectFile.cpp +++ lib/Object/ObjectFile.cpp @@ -101,3 +101,5 @@ return OwningBinary(std::move(Obj), std::move(Buffer)); } + +LoadedObjectInfo::~LoadedObjectInfo() {} Index: test/DebugInfo/debuglineinfo.test =================================================================== --- test/DebugInfo/debuglineinfo.test +++ test/DebugInfo/debuglineinfo.test @@ -1,7 +1,11 @@ RUN: llvm-rtdyld -printline %p/Inputs/test-inline.o \ RUN: | FileCheck %s -check-prefix TEST_INLINE +RUN: llvm-rtdyld -printdebugline %p/Inputs/test-inline.o \ +RUN: | FileCheck %s -check-prefix TEST_INLINE RUN: llvm-rtdyld -printline %p/Inputs/test-parameters.o \ RUN: | FileCheck %s -check-prefix TEST_PARAMETERS +RUN: llvm-rtdyld -printdebugline %p/Inputs/test-parameters.o \ +RUN: | FileCheck %s -check-prefix TEST_PARAMETERS ; This test verifies that relocations are correctly applied to the ; .debug_line section and exercises DIContext::getLineInfoForAddressRange(). Index: tools/llvm-objdump/MachODump.cpp =================================================================== --- tools/llvm-objdump/MachODump.cpp +++ tools/llvm-objdump/MachODump.cpp @@ -2544,7 +2544,7 @@ } auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); - SectionRef RelocSection = Obj->getRelocationSection(RE); + SectionRef RelocSection = Obj->getAnyRelocationSection(RE); uint64_t SectionAddr = RelocSection.getAddress(); Index: tools/llvm-rtdyld/llvm-rtdyld.cpp =================================================================== --- tools/llvm-rtdyld/llvm-rtdyld.cpp +++ tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -45,6 +45,7 @@ enum ActionType { AC_Execute, AC_PrintLineInfo, + AC_PrintDebugLineInfo, AC_Verify }; @@ -55,6 +56,8 @@ "Load, link, and execute the inputs."), clEnumValN(AC_PrintLineInfo, "printline", "Load, link, and print line information for each function."), + clEnumValN(AC_PrintDebugLineInfo, "printdebugline", + "Load, link, and print line information for each function using the debug object"), clEnumValN(AC_Verify, "verify", "Load, link and verify the resulting memory image."), clEnumValEnd)); @@ -186,7 +189,7 @@ /* *** */ -static int printLineInfoForInput() { +static int printLineInfoForInput(bool UseDebugObj) { // Load any dylibs requested on the command line. loadDylibs(); @@ -223,14 +226,22 @@ // Resolve all the relocations we can. Dyld.resolveRelocations(); - OwningBinary DebugObj = LoadedObjInfo->getObjectForDebug(Obj); - - std::unique_ptr Context( - DIContext::getDWARFContext(*DebugObj.getBinary())); + OwningBinary DebugObj; + std::unique_ptr Context; + ObjectFile *SymbolObj = &Obj; + if (UseDebugObj) { + DebugObj = LoadedObjInfo->getObjectForDebug(Obj); + SymbolObj = DebugObj.getBinary(); + Context.reset( + DIContext::getDWARFContext(*SymbolObj)); + } else { + Context.reset( + DIContext::getDWARFContext(Obj,LoadedObjInfo.get())); + } // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(), - E = DebugObj.getBinary()->symbol_end(); + for (object::symbol_iterator I = SymbolObj->symbol_begin(), + E = SymbolObj->symbol_end(); I != E; ++I) { object::SymbolRef::Type SymType; if (I->getType(SymType)) continue; @@ -242,6 +253,16 @@ if (I->getAddress(Addr)) continue; if (I->getSize(Size)) continue; + if (!UseDebugObj) { + object::section_iterator Sec(SymbolObj->section_end()); + I->getSection(Sec); + StringRef SecName; + Sec->getName(SecName); + uint64_t SectionLoadAddress = LoadedObjInfo->getSectionLoadAddress(SecName); + if (SectionLoadAddress != 0) + Addr += SectionLoadAddress - Sec->getAddress(); + } + outs() << "Function: " << Name << ", Size = " << Size << "\n"; DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); @@ -580,7 +601,9 @@ case AC_Execute: return executeInput(); case AC_PrintLineInfo: - return printLineInfoForInput(); + return printLineInfoForInput(false); + case AC_PrintDebugLineInfo: + return printLineInfoForInput(true); case AC_Verify: return linkAndVerify(); }