diff options
Diffstat (limited to 'llvm/lib/ExecutionEngine/RuntimeDyld')
12 files changed, 280 insertions, 129 deletions
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp index 4e2d0f422f39b..0f6f9efe11027 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp @@ -14,11 +14,14 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalValue.h" +#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/Object/ObjectFile.h" using namespace llvm; JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) { + assert(GV.hasName() && "Can't get flags for anonymous symbol"); + JITSymbolFlags Flags = JITSymbolFlags::None; if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage()) Flags |= JITSymbolFlags::Weak; @@ -33,17 +36,48 @@ JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) { isa<Function>(cast<GlobalAlias>(GV).getAliasee())) Flags |= JITSymbolFlags::Callable; + // Check for a linker-private-global-prefix on the symbol name, in which + // case it must be marked as non-exported. + if (auto *M = GV.getParent()) { + const auto &DL = M->getDataLayout(); + StringRef LPGP = DL.getLinkerPrivateGlobalPrefix(); + if (!LPGP.empty() && GV.getName().front() == '\01' && + GV.getName().substr(1).startswith(LPGP)) + Flags &= ~JITSymbolFlags::Exported; + } + + return Flags; +} + +JITSymbolFlags llvm::JITSymbolFlags::fromSummary(GlobalValueSummary *S) { + JITSymbolFlags Flags = JITSymbolFlags::None; + auto L = S->linkage(); + if (GlobalValue::isWeakLinkage(L) || GlobalValue::isLinkOnceLinkage(L)) + Flags |= JITSymbolFlags::Weak; + if (GlobalValue::isCommonLinkage(L)) + Flags |= JITSymbolFlags::Common; + if (GlobalValue::isExternalLinkage(L) || GlobalValue::isExternalWeakLinkage(L)) + Flags |= JITSymbolFlags::Exported; + + if (isa<FunctionSummary>(S)) + Flags |= JITSymbolFlags::Callable; + return Flags; } Expected<JITSymbolFlags> llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) { + Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags(); + if (!SymbolFlagsOrErr) + // TODO: Test this error. + return SymbolFlagsOrErr.takeError(); + JITSymbolFlags Flags = JITSymbolFlags::None; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Weak) Flags |= JITSymbolFlags::Weak; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Common) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Common) Flags |= JITSymbolFlags::Common; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Exported) Flags |= JITSymbolFlags::Exported; auto SymbolType = Symbol.getType(); @@ -58,8 +92,12 @@ llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) { ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) { + Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags(); + if (!SymbolFlagsOrErr) + // TODO: Actually report errors helpfully. + report_fatal_error(SymbolFlagsOrErr.takeError()); ARMJITSymbolFlags Flags; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Thumb) Flags |= ARMJITSymbolFlags::Thumb; return Flags; } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 2df71a5e5e741..7e9b0690cceab 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -214,8 +214,12 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { { JITSymbolResolver::LookupSet Symbols; for (auto &Sym : Obj.symbols()) { - uint32_t Flags = Sym.getFlags(); - if ((Flags & SymbolRef::SF_Common) || (Flags & SymbolRef::SF_Weak)) { + Expected<uint32_t> FlagsOrErr = Sym.getFlags(); + if (!FlagsOrErr) + // TODO: Test this error. + return FlagsOrErr.takeError(); + if ((*FlagsOrErr & SymbolRef::SF_Common) || + (*FlagsOrErr & SymbolRef::SF_Weak)) { // Get symbol name. if (auto NameOrErr = Sym.getName()) Symbols.insert(*NameOrErr); @@ -234,10 +238,13 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { LLVM_DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - uint32_t Flags = I->getFlags(); + Expected<uint32_t> FlagsOrErr = I->getFlags(); + if (!FlagsOrErr) + // TODO: Test this error. + return FlagsOrErr.takeError(); // Skip undefined symbols. - if (Flags & SymbolRef::SF_Undefined) + if (*FlagsOrErr & SymbolRef::SF_Undefined) continue; // Get the symbol type. @@ -287,7 +294,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { } } - if (Flags & SymbolRef::SF_Absolute && + if (*FlagsOrErr & SymbolRef::SF_Absolute && SymType != object::SymbolRef::ST_File) { uint64_t Addr = 0; if (auto AddrOrErr = I->getAddress()) @@ -300,7 +307,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { LLVM_DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name << " SID: " << SectionID << " Offset: " << format("%p", (uintptr_t)Addr) - << " flags: " << Flags << "\n"); + << " flags: " << *FlagsOrErr << "\n"); GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, Addr, *JITSymFlags); } else if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || @@ -332,7 +339,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { LLVM_DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << " SID: " << SectionID << " Offset: " << format("%p", (uintptr_t)SectOffset) - << " flags: " << Flags << "\n"); + << " flags: " << *FlagsOrErr << "\n"); GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, SectOffset, *JITSymFlags); } @@ -592,8 +599,11 @@ Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, uint32_t CommonAlign = 1; for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - uint32_t Flags = I->getFlags(); - if (Flags & SymbolRef::SF_Common) { + Expected<uint32_t> FlagsOrErr = I->getFlags(); + if (!FlagsOrErr) + // TODO: Test this error. + return FlagsOrErr.takeError(); + if (*FlagsOrErr & SymbolRef::SF_Common) { // Add the common symbols to a list. We'll allocate them all below. uint64_t Size = I->getCommonSize(); uint32_t Align = I->getAlignment(); @@ -1190,16 +1200,16 @@ Error RuntimeDyldImpl::resolveExternalSymbols() { void RuntimeDyldImpl::finalizeAsync( std::unique_ptr<RuntimeDyldImpl> This, - unique_function<void(Error)> OnEmitted, - std::unique_ptr<MemoryBuffer> UnderlyingBuffer) { + unique_function<void(object::OwningBinary<object::ObjectFile>, Error)> + OnEmitted, + object::OwningBinary<object::ObjectFile> O) { auto SharedThis = std::shared_ptr<RuntimeDyldImpl>(std::move(This)); auto PostResolveContinuation = - [SharedThis, OnEmitted = std::move(OnEmitted), - UnderlyingBuffer = std::move(UnderlyingBuffer)]( + [SharedThis, OnEmitted = std::move(OnEmitted), O = std::move(O)]( Expected<JITSymbolResolver::LookupResult> Result) mutable { if (!Result) { - OnEmitted(Result.takeError()); + OnEmitted(std::move(O), Result.takeError()); return; } @@ -1213,10 +1223,11 @@ void RuntimeDyldImpl::finalizeAsync( SharedThis->registerEHFrames(); std::string ErrMsg; if (SharedThis->MemMgr.finalizeMemory(&ErrMsg)) - OnEmitted(make_error<StringError>(std::move(ErrMsg), + OnEmitted(std::move(O), + make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode())); else - OnEmitted(Error::success()); + OnEmitted(std::move(O), Error::success()); }; JITSymbolResolver::LookupSet Symbols; @@ -1403,32 +1414,35 @@ void RuntimeDyld::deregisterEHFrames() { // FIXME: Kill this with fire once we have a new JIT linker: this is only here // so that we can re-use RuntimeDyld's implementation without twisting the // interface any further for ORC's purposes. -void jitLinkForORC(object::ObjectFile &Obj, - std::unique_ptr<MemoryBuffer> UnderlyingBuffer, - RuntimeDyld::MemoryManager &MemMgr, - JITSymbolResolver &Resolver, bool ProcessAllSections, - unique_function<Error( - std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObj, - std::map<StringRef, JITEvaluatedSymbol>)> - OnLoaded, - unique_function<void(Error)> OnEmitted) { +void jitLinkForORC( + object::OwningBinary<object::ObjectFile> O, + RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver, + bool ProcessAllSections, + unique_function< + Error(const object::ObjectFile &Obj, + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObj, + std::map<StringRef, JITEvaluatedSymbol>)> + OnLoaded, + unique_function<void(object::OwningBinary<object::ObjectFile>, Error)> + OnEmitted) { RuntimeDyld RTDyld(MemMgr, Resolver); RTDyld.setProcessAllSections(ProcessAllSections); - auto Info = RTDyld.loadObject(Obj); + auto Info = RTDyld.loadObject(*O.getBinary()); if (RTDyld.hasError()) { - OnEmitted(make_error<StringError>(RTDyld.getErrorString(), - inconvertibleErrorCode())); + OnEmitted(std::move(O), make_error<StringError>(RTDyld.getErrorString(), + inconvertibleErrorCode())); return; } - if (auto Err = OnLoaded(std::move(Info), RTDyld.getSymbolTable())) - OnEmitted(std::move(Err)); + if (auto Err = + OnLoaded(*O.getBinary(), std::move(Info), RTDyld.getSymbolTable())) + OnEmitted(std::move(O), std::move(Err)); RuntimeDyldImpl::finalizeAsync(std::move(RTDyld.Dyld), std::move(OnEmitted), - std::move(UnderlyingBuffer)); + std::move(O)); } } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp index 6e3cd7cd2cfcc..1d8f1ac8ac8af 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/FormatVariadic.h" using namespace llvm; using namespace llvm::object; @@ -75,7 +76,42 @@ RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) { uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) { // The value in a relocatable COFF object is the offset. - return Sym.getValue(); + return cantFail(Sym.getValue()); +} + +uint64_t RuntimeDyldCOFF::getDLLImportOffset(unsigned SectionID, StubMap &Stubs, + StringRef Name, + bool SetSectionIDMinus1) { + LLVM_DEBUG(dbgs() << "Getting DLLImport entry for " << Name << "... "); + assert(Name.startswith(getImportSymbolPrefix()) && "Not a DLLImport symbol?"); + RelocationValueRef Reloc; + Reloc.SymbolName = Name.data(); + auto I = Stubs.find(Reloc); + if (I != Stubs.end()) { + LLVM_DEBUG(dbgs() << format("{0:x8}", I->second) << "\n"); + return I->second; + } + + assert(SectionID < Sections.size() && "SectionID out of range"); + auto &Sec = Sections[SectionID]; + auto EntryOffset = alignTo(Sec.getStubOffset(), PointerSize); + Sec.advanceStubOffset(EntryOffset + PointerSize - Sec.getStubOffset()); + Stubs[Reloc] = EntryOffset; + + RelocationEntry RE(SectionID, EntryOffset, PointerReloc, 0, false, + Log2_64(PointerSize)); + // Hack to tell I386/Thumb resolveRelocation that this isn't section relative. + if (SetSectionIDMinus1) + RE.Sections.SectionA = -1; + addRelocationForSymbol(RE, Name.drop_front(getImportSymbolPrefix().size())); + + LLVM_DEBUG({ + dbgs() << "Creating entry at " + << formatv("{0:x16} + {1:x8} ( {2:x16} )", Sec.getLoadAddress(), + EntryOffset, Sec.getLoadAddress() + EntryOffset) + << "\n"; + }); + return EntryOffset; } bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const { diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h index 4efd18a2e6c57..41ee06c15448f 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h @@ -36,9 +36,22 @@ public: protected: RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr, - JITSymbolResolver &Resolver) - : RuntimeDyldImpl(MemMgr, Resolver) {} + JITSymbolResolver &Resolver, unsigned PointerSize, + uint32_t PointerReloc) + : RuntimeDyldImpl(MemMgr, Resolver), PointerSize(PointerSize), + PointerReloc(PointerReloc) { + assert((PointerSize == 4 || PointerSize == 8) && "Unexpected pointer size"); + } + uint64_t getSymbolOffset(const SymbolRef &Sym); + uint64_t getDLLImportOffset(unsigned SectionID, StubMap &Stubs, + StringRef Name, bool SetSectionIDMinus1 = false); + + static constexpr StringRef getImportSymbolPrefix() { return "__imp_"; } + +private: + unsigned PointerSize; + uint32_t PointerReloc; }; } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index 2ac0586ff3247..e5e512672daa1 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -9,6 +9,7 @@ #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "RuntimeDyldCheckerImpl.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCInst.h" @@ -704,10 +705,11 @@ bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix, bool DidAllTestsPass = true; unsigned NumRules = 0; + std::string CheckExpr; const char *LineStart = MemBuf->getBufferStart(); // Eat whitespace. - while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart)) + while (LineStart != MemBuf->getBufferEnd() && isSpace(*LineStart)) ++LineStart; while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') { @@ -717,14 +719,23 @@ bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix, ++LineEnd; StringRef Line(LineStart, LineEnd - LineStart); - if (Line.startswith(RulePrefix)) { - DidAllTestsPass &= check(Line.substr(RulePrefix.size())); - ++NumRules; + if (Line.startswith(RulePrefix)) + CheckExpr += Line.substr(RulePrefix.size()).str(); + + // If there's a check expr string... + if (!CheckExpr.empty()) { + // ... and it's complete then run it, otherwise remove the trailer '\'. + if (CheckExpr.back() != '\\') { + DidAllTestsPass &= check(CheckExpr); + CheckExpr.clear(); + ++NumRules; + } else + CheckExpr.pop_back(); } // Eat whitespace. LineStart = LineEnd; - while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart)) + while (LineStart != MemBuf->getBufferEnd() && isSpace(*LineStart)) ++LineStart; } return DidAllTestsPass && (NumRules != 0); diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 440ab4174a565..7c39ddc8b1da0 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -399,6 +399,13 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, case ELF::R_AARCH64_ABS64: write(isBE, TargetPtr, Value + Addend); break; + case ELF::R_AARCH64_PLT32: { + uint64_t Result = Value + Addend - FinalAddress; + assert(static_cast<int64_t>(Result) >= INT32_MIN && + static_cast<int64_t>(Result) <= INT32_MAX); + write(isBE, TargetPtr, static_cast<uint32_t>(Result)); + break; + } case ELF::R_AARCH64_PREL32: { uint64_t Result = Value + Addend - FinalAddress; assert(static_cast<int64_t>(Result) >= INT32_MIN && @@ -554,7 +561,7 @@ void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) { IsMipsO32ABI = AbiVariant & ELF::EF_MIPS_ABI_O32; IsMipsN32ABI = AbiVariant & ELF::EF_MIPS_ABI2; } - IsMipsN64ABI = Obj.getFileFormatName().equals("ELF64-mips"); + IsMipsN64ABI = Obj.getFileFormatName().equals("elf64-mips"); } // Return the .TOC. section and offset. diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index ef0784e2273b8..31892b7466e62 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -88,12 +88,13 @@ class RuntimeDyldELF : public RuntimeDyldImpl { void setMipsABI(const ObjectFile &Obj) override; - Error findPPC64TOCSection(const ELFObjectFileBase &Obj, + Error findPPC64TOCSection(const object::ELFObjectFileBase &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); - Error findOPDEntrySection(const ELFObjectFileBase &Obj, + Error findOPDEntrySection(const object::ELFObjectFileBase &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); + protected: size_t getGOTEntrySize() override; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index cec7b92b8c48e..a9346536fd095 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -26,6 +26,7 @@ #include "llvm/Support/Host.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/SwapByteOrder.h" +#include <deque> #include <map> #include <system_error> #include <unordered_map> @@ -35,8 +36,6 @@ using namespace llvm::object; namespace llvm { -class Twine; - #define UNIMPLEMENTED_RELOC(RelType) \ case RelType: \ return make_error<RuntimeDyldError>("Unimplemented relocation: " #RelType) @@ -74,7 +73,7 @@ class SectionEntry { public: SectionEntry(StringRef name, uint8_t *address, size_t size, size_t allocationSize, uintptr_t objAddress) - : Name(name), Address(address), Size(size), + : Name(std::string(name)), Address(address), Size(size), LoadAddress(reinterpret_cast<uintptr_t>(address)), StubOffset(size), AllocationSize(allocationSize), ObjAddress(objAddress) { // AllocationSize is used only in asserts, prevent an "unused private field" @@ -190,13 +189,11 @@ public: class RelocationValueRef { public: - unsigned SectionID; - uint64_t Offset; - int64_t Addend; - const char *SymbolName; + unsigned SectionID = 0; + uint64_t Offset = 0; + int64_t Addend = 0; + const char *SymbolName = nullptr; bool IsStubThumb = false; - RelocationValueRef() : SectionID(0), Offset(0), Addend(0), - SymbolName(nullptr) {} inline bool operator==(const RelocationValueRef &Other) const { return SectionID == Other.SectionID && Offset == Other.Offset && @@ -251,7 +248,9 @@ protected: // A list of all sections emitted by the dynamic linker. These sections are // referenced in the code by means of their index in this list - SectionID. - typedef SmallVector<SectionEntry, 64> SectionList; + // Because references may be kept while the list grows, use a container that + // guarantees reference stability. + typedef std::deque<SectionEntry> SectionList; SectionList Sections; typedef unsigned SID; // Type for SectionIDs @@ -319,32 +318,18 @@ protected: std::string ErrorStr; void writeInt16BE(uint8_t *Addr, uint16_t Value) { - if (IsTargetLittleEndian) - sys::swapByteOrder(Value); - *Addr = (Value >> 8) & 0xFF; - *(Addr + 1) = Value & 0xFF; + llvm::support::endian::write<uint16_t, llvm::support::unaligned>( + Addr, Value, IsTargetLittleEndian ? support::little : support::big); } void writeInt32BE(uint8_t *Addr, uint32_t Value) { - if (IsTargetLittleEndian) - sys::swapByteOrder(Value); - *Addr = (Value >> 24) & 0xFF; - *(Addr + 1) = (Value >> 16) & 0xFF; - *(Addr + 2) = (Value >> 8) & 0xFF; - *(Addr + 3) = Value & 0xFF; + llvm::support::endian::write<uint32_t, llvm::support::unaligned>( + Addr, Value, IsTargetLittleEndian ? support::little : support::big); } void writeInt64BE(uint8_t *Addr, uint64_t Value) { - if (IsTargetLittleEndian) - sys::swapByteOrder(Value); - *Addr = (Value >> 56) & 0xFF; - *(Addr + 1) = (Value >> 48) & 0xFF; - *(Addr + 2) = (Value >> 40) & 0xFF; - *(Addr + 3) = (Value >> 32) & 0xFF; - *(Addr + 4) = (Value >> 24) & 0xFF; - *(Addr + 5) = (Value >> 16) & 0xFF; - *(Addr + 6) = (Value >> 8) & 0xFF; - *(Addr + 7) = Value & 0xFF; + llvm::support::endian::write<uint64_t, llvm::support::unaligned>( + Addr, Value, IsTargetLittleEndian ? support::little : support::big); } virtual void setMipsABI(const ObjectFile &Obj) { @@ -548,9 +533,11 @@ public: void resolveLocalRelocations(); - static void finalizeAsync(std::unique_ptr<RuntimeDyldImpl> This, - unique_function<void(Error)> OnEmitted, - std::unique_ptr<MemoryBuffer> UnderlyingBuffer); + static void finalizeAsync( + std::unique_ptr<RuntimeDyldImpl> This, + unique_function<void(object::OwningBinary<object::ObjectFile>, Error)> + OnEmitted, + object::OwningBinary<object::ObjectFile> O); void reassignSectionAddress(unsigned SectionID, uint64_t Addr); diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h index a94f54f50ac46..14510e56b35a7 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFAArch64.h @@ -89,7 +89,8 @@ private: public: RuntimeDyldCOFFAArch64(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver) - : RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {} + : RuntimeDyldCOFF(MM, Resolver, 8, COFF::IMAGE_REL_ARM64_ADDR64), + ImageBase(0) {} unsigned getStubAlignment() override { return 8; } @@ -161,7 +162,7 @@ public: uint64_t Offset = RelI->getOffset(); // If there is no section, this must be an external reference. - const bool IsExtern = Section == Obj.section_end(); + bool IsExtern = Section == Obj.section_end(); // Determine the Addend used to adjust the relocation value. uint64_t Addend = 0; @@ -169,6 +170,24 @@ public: uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset; uint8_t *Displacement = (uint8_t *)ObjTarget; + unsigned TargetSectionID = -1; + uint64_t TargetOffset = -1; + + if (TargetName.startswith(getImportSymbolPrefix())) { + TargetSectionID = SectionID; + TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName); + TargetName = StringRef(); + IsExtern = false; + } else if (!IsExtern) { + if (auto TargetSectionIDOrErr = findOrEmitSection( + Obj, *Section, Section->isText(), ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); + + TargetOffset = getSymbolOffset(*Symbol); + } + switch (RelType) { case COFF::IMAGE_REL_ARM64_ADDR32: case COFF::IMAGE_REL_ARM64_ADDR32NB: @@ -224,18 +243,10 @@ public: << TargetName << " Addend " << Addend << "\n"); #endif - unsigned TargetSectionID = -1; if (IsExtern) { RelocationEntry RE(SectionID, Offset, RelType, Addend); addRelocationForSymbol(RE, TargetName); } else { - if (auto TargetSectionIDOrErr = findOrEmitSection( - Obj, *Section, Section->isText(), ObjSectionToID)) { - TargetSectionID = *TargetSectionIDOrErr; - } else - return TargetSectionIDOrErr.takeError(); - - uint64_t TargetOffset = getSymbolOffset(*Symbol); RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); addRelocationForSection(RE, TargetSectionID); } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h index 40910bea0c364..03c38260bece8 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h @@ -25,7 +25,7 @@ class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF { public: RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver) - : RuntimeDyldCOFF(MM, Resolver) {} + : RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_I386_DIR32) {} unsigned getMaxStubSize() const override { return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad @@ -53,10 +53,28 @@ public: if (!SectionOrErr) return SectionOrErr.takeError(); auto Section = *SectionOrErr; + bool IsExtern = Section == Obj.section_end(); uint64_t RelType = RelI->getType(); uint64_t Offset = RelI->getOffset(); + unsigned TargetSectionID = -1; + uint64_t TargetOffset = -1; + if (TargetName.startswith(getImportSymbolPrefix())) { + TargetSectionID = SectionID; + TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true); + TargetName = StringRef(); + IsExtern = false; + } else if (!IsExtern) { + if (auto TargetSectionIDOrErr = findOrEmitSection( + Obj, *Section, Section->isText(), ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); + if (RelType != COFF::IMAGE_REL_I386_SECTION) + TargetOffset = getSymbolOffset(*Symbol); + } + // Determine the Addend used to adjust the relocation value. uint64_t Addend = 0; SectionEntry &AddendSection = Sections[SectionID]; @@ -83,16 +101,10 @@ public: << " RelType: " << RelTypeName << " TargetName: " << TargetName << " Addend " << Addend << "\n"); - unsigned TargetSectionID = -1; - if (Section == Obj.section_end()) { + if (IsExtern) { RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); addRelocationForSymbol(RE, TargetName); } else { - if (auto TargetSectionIDOrErr = - findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID)) - TargetSectionID = *TargetSectionIDOrErr; - else - return TargetSectionIDOrErr.takeError(); switch (RelType) { case COFF::IMAGE_REL_I386_ABSOLUTE: @@ -103,7 +115,7 @@ public: case COFF::IMAGE_REL_I386_REL32: { RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, - getSymbolOffset(*Symbol), 0, 0, false, 0); + TargetOffset, 0, 0, false, 0); addRelocationForSection(RE, TargetSectionID); break; } @@ -114,15 +126,14 @@ public: break; } case COFF::IMAGE_REL_I386_SECREL: { - RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, - getSymbolOffset(*Symbol) + Addend); + RelocationEntry RE = + RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend); addRelocationForSection(RE, TargetSectionID); break; } default: llvm_unreachable("unsupported relocation type"); } - } return ++RelI; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h index bb2e9626e0b07..721f2b14829a7 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h @@ -48,7 +48,7 @@ class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF { public: RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver) - : RuntimeDyldCOFF(MM, Resolver) {} + : RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_ARM_ADDR32) {} unsigned getMaxStubSize() const override { return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding @@ -103,16 +103,29 @@ public: << " RelType: " << RelTypeName << " TargetName: " << TargetName << " Addend " << Addend << "\n"); + bool IsExtern = Section == Obj.section_end(); unsigned TargetSectionID = -1; - if (Section == Obj.section_end()) { - RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); - addRelocationForSymbol(RE, TargetName); - } else { + uint64_t TargetOffset = -1; + + if (TargetName.startswith(getImportSymbolPrefix())) { + TargetSectionID = SectionID; + TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true); + TargetName = StringRef(); + IsExtern = false; + } else if (!IsExtern) { if (auto TargetSectionIDOrErr = findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID)) TargetSectionID = *TargetSectionIDOrErr; else return TargetSectionIDOrErr.takeError(); + if (RelType != COFF::IMAGE_REL_ARM_SECTION) + TargetOffset = getSymbolOffset(*Symbol); + } + + if (IsExtern) { + RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); + addRelocationForSymbol(RE, TargetName); + } else { // We need to find out if the relocation is relative to a thumb function // so that we include the ISA selection bit when resolve the relocation @@ -124,16 +137,16 @@ public: // This relocation is ignored. break; case COFF::IMAGE_REL_ARM_ADDR32: { - RelocationEntry RE = RelocationEntry( - SectionID, Offset, RelType, Addend, TargetSectionID, - getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc); + RelocationEntry RE = + RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, + TargetOffset, 0, 0, false, 0, IsTargetThumbFunc); addRelocationForSection(RE, TargetSectionID); break; } case COFF::IMAGE_REL_ARM_ADDR32NB: { RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, - getSymbolOffset(*Symbol), 0, 0, false, 0); + TargetOffset, 0, 0, false, 0); addRelocationForSection(RE, TargetSectionID); break; } @@ -144,24 +157,23 @@ public: break; } case COFF::IMAGE_REL_ARM_SECREL: { - RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, - getSymbolOffset(*Symbol) + Addend); + RelocationEntry RE = + RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend); addRelocationForSection(RE, TargetSectionID); break; } case COFF::IMAGE_REL_ARM_MOV32T: { - RelocationEntry RE = RelocationEntry( - SectionID, Offset, RelType, Addend, TargetSectionID, - getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc); + RelocationEntry RE = + RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, + TargetOffset, 0, 0, false, 0, IsTargetThumbFunc); addRelocationForSection(RE, TargetSectionID); break; } case COFF::IMAGE_REL_ARM_BRANCH20T: case COFF::IMAGE_REL_ARM_BRANCH24T: case COFF::IMAGE_REL_ARM_BLX23T: { - RelocationEntry RE = - RelocationEntry(SectionID, Offset, RelType, - getSymbolOffset(*Symbol) + Addend, true, 0); + RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, + TargetOffset + Addend, true, 0); addRelocationForSection(RE, TargetSectionID); break; } @@ -256,7 +268,6 @@ public: EncodeImmediate(&Target[0], (static_cast<uint32_t>(Result) >> 00) | ISASelectionBit); EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16); - break; } case COFF::IMAGE_REL_ARM_BRANCH20T: { diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h index dc4af08583de7..ebe3ca33d3089 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h @@ -56,7 +56,8 @@ private: public: RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver) - : RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {} + : RuntimeDyldCOFF(MM, Resolver, 8, COFF::IMAGE_REL_AMD64_ADDR64), + ImageBase(0) {} unsigned getStubAlignment() override { return 1; } @@ -202,7 +203,7 @@ public: return SectionOrError.takeError(); object::section_iterator SecI = *SectionOrError; // If there is no section, this must be an external reference. - const bool IsExtern = SecI == Obj.section_end(); + bool IsExtern = SecI == Obj.section_end(); // Determine the Addend used to adjust the relocation value. uint64_t RelType = RelI->getType(); @@ -214,7 +215,25 @@ public: Expected<StringRef> TargetNameOrErr = Symbol->getName(); if (!TargetNameOrErr) return TargetNameOrErr.takeError(); + StringRef TargetName = *TargetNameOrErr; + unsigned TargetSectionID = 0; + uint64_t TargetOffset = 0; + + if (TargetName.startswith(getImportSymbolPrefix())) { + assert(IsExtern && "DLLImport not marked extern?"); + TargetSectionID = SectionID; + TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName); + TargetName = StringRef(); + IsExtern = false; + } else if (!IsExtern) { + if (auto TargetSectionIDOrErr = + findOrEmitSection(Obj, *SecI, SecI->isText(), ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); + TargetOffset = getSymbolOffset(*Symbol); + } switch (RelType) { @@ -253,14 +272,6 @@ public: RelocationEntry RE(SectionID, Offset, RelType, Addend); addRelocationForSymbol(RE, TargetName); } else { - bool IsCode = SecI->isText(); - unsigned TargetSectionID; - if (auto TargetSectionIDOrErr = - findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID)) - TargetSectionID = *TargetSectionIDOrErr; - else - return TargetSectionIDOrErr.takeError(); - uint64_t TargetOffset = getSymbolOffset(*Symbol); RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); addRelocationForSection(RE, TargetSectionID); } |