Index: include/llvm/DebugInfo/DWARF/DIContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DIContext.h +++ include/llvm/DebugInfo/DWARF/DIContext.h @@ -131,7 +131,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/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -248,7 +248,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/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() {} @@ -61,8 +64,13 @@ getObjectForDebug(const object::ObjectFile &Obj) const = 0; uint64_t getSectionLoadAddress(StringRef Name) const; + bool getLoadedSectionContents(StringRef Name, StringRef &Data) const; + + virtual LoadedObjectInfo *clone() const = 0; protected: + unsigned getSectionIdByName(StringRef Name) const; + virtual void anchor(); RuntimeDyldImpl &RTDyld; Index: include/llvm/Object/COFF.h =================================================================== --- include/llvm/Object/COFF.h +++ include/llvm/Object/COFF.h @@ -350,6 +350,10 @@ return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; } + bool isSection() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; + } + bool isSectionDefinition() const { // C++/CLI creates external ABS symbols for non-const appdomain globals. // These are also followed by an auxiliary section definition. @@ -612,6 +616,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 @@ -86,6 +86,7 @@ std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override; std::error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const override; + section_iterator getSymbolSection(const Elf_Sym *Symb) const; std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; @@ -112,6 +113,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 @@ -413,18 +415,23 @@ } template -std::error_code -ELFObjectFile::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const Elf_Sym *ESym = getSymbol(Symb); +section_iterator +ELFObjectFile::getSymbolSection(const Elf_Sym *ESym) const { const Elf_Shdr *ESec = EF.getSection(ESym); if (!ESec) - Res = section_end(); + return section_end(); else { DataRefImpl Sec; Sec.p = reinterpret_cast(ESec); - Res = section_iterator(SectionRef(Sec, this)); + return section_iterator(SectionRef(Sec, this)); } +} + +template +std::error_code +ELFObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + Res = getSymbolSection(getSymbol(Symb)); return object_error::success; } @@ -585,6 +592,20 @@ return symbol_iterator(SymbolRef(SymbolData, this)); } +// ELF relocations can target sections, by targetting a symbol of type +// STT_SECTION +template +section_iterator +ELFObjectFile::getRelocationSection(DataRefImpl Rel) const { + symbol_iterator Sym = getRelocationSymbol(Rel); + if (Sym == symbol_end()) + return section_end(); + const Elf_Sym *ESym = getSymbol(Sym->getRawDataRefImpl()); + if (ESym->getType() != ELF::STT_SECTION) + return section_end(); + return getSymbolSection(ESym); +} + 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 @@ -327,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,23 @@ 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; + + // If available in a convenient form the LoadedObjectInfo can provide + // the contents of the section. This is especially useful for cases + // where the loaded object resides in memory (as opposed to being remote) + virtual bool getLoadedSectionContents(StringRef Name, StringRef &Data) const { + return false; + } + + virtual LoadedObjectInfo *clone() const = 0; +}; } // end namespace object } // end namespace llvm Index: lib/DebugInfo/DWARF/DIContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DIContext.cpp +++ lib/DebugInfo/DWARF/DIContext.cpp @@ -13,6 +13,7 @@ DIContext::~DIContext() {} -DIContext *DIContext::getDWARFContext(const object::ObjectFile &Obj) { - return new DWARFContextInMemory(Obj); +DIContext *DIContext::getDWARFContext(const object::ObjectFile &Obj, + const object::LoadedObjectInfo *L) { + return new DWARFContextInMemory(Obj,L); } Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -537,7 +537,8 @@ return true; } -DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj) +DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj, + const object::LoadedObjectInfo *L) : IsLittleEndian(Obj.isLittleEndian()), AddressSize(Obj.getBytesInAddress()) { for (const SectionRef &Section : Obj.sections()) { @@ -551,7 +552,14 @@ if (IsVirtual) continue; StringRef data; - Section.getContents(data); + bool AlreadyRelocated = false; + + if (L && L->getLoadedSectionContents(name,data)) + { + AlreadyRelocated = true; + } else { + Section.getContents(data); + } name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. @@ -620,6 +628,12 @@ StringRef RelSecName; RelocatedSection->getName(RelSecName); + + // Check if the JIT already did the relocations for us + // If so, we just use the relocated section + if (L && L->getSectionLoadAddress(RelSecName)) + continue; + RelSecName = RelSecName.substr( RelSecName.find_first_not_of("._")); // Skip . and _ prefixes. @@ -655,9 +669,39 @@ 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()) - Sym->getAddress(SymAddr); + object::section_iterator RSec(Obj.section_end()); + + if (L == nullptr) { + if (Sym != Obj.symbol_end()) + Sym->getAddress(SymAddr); + } else { + if (Sym != Obj.symbol_end()) { + Sym->getAddress(SymAddr); + Sym->getSection(RSec); + if (RSec != Obj.section_end()) { + StringRef SecName; + RSec->getName(SecName); + SectionLoadAddress = L->getSectionLoadAddress(SecName); + 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->getSectionLoadAddress(SecName); + if (SectionLoadAddress != 0) { + SymAddr = SectionLoadAddress; + } + } + } + } object::RelocVisitor V(Obj); object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -820,13 +820,31 @@ //===----------------------------------------------------------------------===// // RuntimeDyld class implementation -uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( +RuntimeDyldImpl::SID RuntimeDyld::LoadedObjectInfo::getSectionIdByName( StringRef SectionName) const { for (unsigned I = BeginIdx; I != EndIdx; ++I) if (RTDyld.Sections[I].Name == SectionName) - return RTDyld.Sections[I].LoadAddress; + return I; + return RTDYLD_INVALID_SECTION_ID; +} - return 0; +uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( + StringRef SectionName) const { + RuntimeDyldImpl::SID I = getSectionIdByName(SectionName); + return I != RTDYLD_INVALID_SECTION_ID ? RTDyld.Sections[I].LoadAddress : 0; +} + +bool RuntimeDyld::LoadedObjectInfo::getLoadedSectionContents( + StringRef SectionName, + StringRef &Data) const { + RuntimeDyldImpl::SID I = getSectionIdByName(SectionName); + if (I == RTDYLD_INVALID_SECTION_ID) + return false; + if (!RTDyld.Sections[I].Address) + return false; + Data = StringRef(reinterpret_cast(RTDyld.Sections[I].LoadAddress), + RTDyld.Sections[I].Size); + return true; } RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -34,6 +34,8 @@ getObjectForDebug(const ObjectFile &Obj) const override { return OwningBinary(); } + + RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedCOFFObjectInfo(*this); } }; } 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/RuntimeDyldImpl.h =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -202,7 +202,7 @@ SectionList Sections; typedef unsigned SID; // Type for SectionIDs -#define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) +#define RTDYLD_INVALID_SECTION_ID ((RuntimeDyldImpl::SID)(-1)) // Keep a map of sections from object file to the SectionID which // references it. Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -36,6 +36,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 @@ -1044,6 +1044,19 @@ return symbol_iterator(SymbolRef(Ref, this)); } +section_iterator COFFObjectFile::getRelocationSection(DataRefImpl Rel) const { + symbol_iterator Sym = getRelocationSymbol(Rel); + if (Sym == symbol_end()) + return section_end(); + COFFSymbolRef Symb = getCOFFSymbol(*Sym); + if (!Symb.isSection()) + return section_end(); + section_iterator Res(section_end()); + if (getSymbolSection(Sym->getRawDataRefImpl(),Res)) + return section_end(); + return Res; +} + 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 @@ -710,6 +710,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); @@ -2229,7 +2234,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 @@ -102,3 +102,5 @@ return OwningBinary(std::move(Obj), std::move(Buffer)); } + +LoadedObjectInfo::~LoadedObjectInfo() {} Index: test/DebugInfo/debuglineinfo-macho.test =================================================================== --- test/DebugInfo/debuglineinfo-macho.test +++ test/DebugInfo/debuglineinfo-macho.test @@ -1,3 +1,7 @@ +RUN: llvm-rtdyld -printline %p/Inputs/test-simple-macho.o \ +RUN: | FileCheck %s -check-prefix TEST_SIMPLE +RUN: llvm-rtdyld -printline %p/Inputs/test-multiple-macho.o \ +RUN: | FileCheck %s -check-prefix TEST_MULTIPLE RUN: llvm-rtdyld -printobjline %p/Inputs/test-simple-macho.o \ RUN: | FileCheck %s -check-prefix TEST_SIMPLE RUN: llvm-rtdyld -printobjline %p/Inputs/test-multiple-macho.o \ 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 @@ -3385,7 +3385,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 @@ -46,6 +46,7 @@ AC_Execute, AC_PrintObjectLineInfo, AC_PrintLineInfo, + AC_PrintDebugLineInfo, AC_Verify }; @@ -58,6 +59,8 @@ "Print the line info directly from the input file"), 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)); @@ -233,14 +236,15 @@ // Resolve all the relocations we can. Dyld.resolveRelocations(); - assert(UseDebugObj); - DebugObj = LoadedObjInfo->getObjectForDebug(Obj); - SymbolObj = DebugObj.getBinary(); - Context.reset( + if (UseDebugObj) { + DebugObj = LoadedObjInfo->getObjectForDebug(Obj); + SymbolObj = DebugObj.getBinary(); + Context.reset( DIContext::getDWARFContext(*SymbolObj)); - } else { - Context.reset( - DIContext::getDWARFContext(Obj)); + } else { + Context.reset( + DIContext::getDWARFContext(Obj,LoadedObjInfo.get())); + } } // Use symbol info to iterate functions in the object. @@ -607,6 +611,8 @@ case AC_PrintObjectLineInfo: return printLineInfoForInput(false,false); case AC_PrintLineInfo: + return printLineInfoForInput(true,false); + case AC_PrintDebugLineInfo: return printLineInfoForInput(true,true); case AC_Verify: return linkAndVerify();