Index: include/llvm/DebugInfo/DIContext.h =================================================================== --- include/llvm/DebugInfo/DIContext.h +++ include/llvm/DebugInfo/DIContext.h @@ -136,6 +136,26 @@ const DIContextKind Kind; }; +/// An inferface for inquiring the load address of a loaded object file +/// to be used by the DIContext implementations when applying relocations +/// on the fly. +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; +}; + } #endif Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -255,7 +255,8 @@ SmallVector, 4> UncompressedSections; public: - DWARFContextInMemory(const object::ObjectFile &Obj); + DWARFContextInMemory(const object::ObjectFile &Obj, + const 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 @@ -17,6 +17,7 @@ #include "JITSymbolFlags.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Memory.h" +#include "llvm/DebugInfo/DIContext.h" #include namespace llvm { @@ -54,7 +55,7 @@ }; /// \brief Information about the loaded object. - class LoadedObjectInfo { + class LoadedObjectInfo : public llvm::LoadedObjectInfo { friend class RuntimeDyldImpl; public: LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, 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 @@ -416,18 +418,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; } @@ -588,6 +595,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 @@ -326,7 +327,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); } 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 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/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 @@ -112,6 +112,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 @@ -203,7 +203,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); @@ -2224,7 +2229,7 @@ } SectionRef -MachOObjectFile::getRelocationSection( +MachOObjectFile::getAnyRelocationSection( const MachO::any_relocation_info &RE) const { if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) return *section_end(); 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 @@ -6484,7 +6484,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 @@ -47,6 +47,7 @@ enum ActionType { AC_Execute, AC_PrintLineInfo, + AC_PrintDebugLineInfo, AC_Verify }; @@ -57,6 +58,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)); @@ -188,7 +191,9 @@ /* *** */ -static int printLineInfoForInput() { +static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) { + assert(LoadObjects || !UseDebugObj); + // Load any dylibs requested on the command line. loadDylibs(); @@ -215,24 +220,32 @@ ObjectFile &Obj = **MaybeObj; - // Load the object file - std::unique_ptr LoadedObjInfo = - Dyld.loadObject(Obj); + OwningBinary DebugObj; + std::unique_ptr LoadedObjInfo = nullptr; + ObjectFile *SymbolObj = &Obj; + if (LoadObjects) { + // Load the object file + LoadedObjInfo = + Dyld.loadObject(Obj); - if (Dyld.hasError()) - return Error(Dyld.getErrorString()); + if (Dyld.hasError()) + return Error(Dyld.getErrorString()); - // Resolve all the relocations we can. - Dyld.resolveRelocations(); + // Resolve all the relocations we can. + Dyld.resolveRelocations(); - OwningBinary DebugObj = LoadedObjInfo->getObjectForDebug(Obj); + if (UseDebugObj) { + DebugObj = LoadedObjInfo->getObjectForDebug(Obj); + SymbolObj = DebugObj.getBinary(); + } + } std::unique_ptr Context( - new DWARFContextInMemory(*DebugObj.getBinary())); + new DWARFContextInMemory(*SymbolObj,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; @@ -244,7 +257,17 @@ if (I->getAddress(Addr)) continue; if (I->getSize(Size)) continue; - outs() << "Function: " << Name << ", Size = " << Size << "\n"; + if (!UseDebugObj) { + object::section_iterator Sec(SymbolObj->section_end()); + I->getSection(Sec); + StringRef SecName; + Sec->getName(SecName); + uint64_t SectionLoadAddress = LoadObjects ? LoadedObjInfo->getSectionLoadAddress(SecName) : 0; + if (SectionLoadAddress != 0) + Addr += SectionLoadAddress - Sec->getAddress(); + } + + outs() << "Function: " << Name << ", Size = " << Size << ", Addr = " << Addr << "\n"; DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); DILineInfoTable::iterator Begin = Lines.begin(); @@ -593,8 +616,10 @@ switch (Action) { case AC_Execute: return executeInput(); + case AC_PrintDebugLineInfo: + return printLineInfoForInput(true,true); case AC_PrintLineInfo: - return printLineInfoForInput(); + return printLineInfoForInput(true,false); case AC_Verify: return linkAndVerify(); }