diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
| commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
| tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/ExecutionEngine | |
| parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) | |
Notes
Diffstat (limited to 'lib/ExecutionEngine')
23 files changed, 609 insertions, 213 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 2ee72f9a8c16..c59885753a8f 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -476,7 +476,7 @@ EngineBuilder::EngineBuilder() : EngineBuilder(nullptr) {} EngineBuilder::EngineBuilder(std::unique_ptr<Module> M) : M(std::move(M)), WhichEngine(EngineKind::Either), ErrorStr(nullptr), OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr), - CMModel(CodeModel::JITDefault), UseOrcMCJITReplacement(false) { + UseOrcMCJITReplacement(false) { // IR module verification is enabled by default in debug builds, and disabled // by default in release builds. #ifndef NDEBUG diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index e956dbebaffe..20251c23b17c 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -198,8 +198,10 @@ LLVMBool LLVMCreateMCJITCompilerForModule( builder.setEngineKind(EngineKind::JIT) .setErrorStr(&Error) .setOptLevel((CodeGenOpt::Level)options.OptLevel) - .setCodeModel(unwrap(options.CodeModel)) .setTargetOptions(targetOptions); + bool JIT; + if (Optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT)) + builder.setCodeModel(*CM); if (options.MCJMM) builder.setMCJITMemoryManager( std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM))); diff --git a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index a7b1fe206f10..cb6dd5e57283 100644 --- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -104,7 +104,7 @@ void IntelJITEventListener::NotifyObjectEmitted( // Get the address of the object image for use as a unique identifier const void* ObjData = DebugObj.getData().data(); - DIContext* Context = new DWARFContextInMemory(DebugObj); + std::unique_ptr<DIContext> Context = DWARFContext::create(DebugObj); MethodAddressVector Functions; // Use symbol info to iterate functions in the object. diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 1164d60ffc10..f7b8a3b657ee 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -19,7 +19,6 @@ #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DynamicLibrary.h" diff --git a/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index e3a456849f90..68397beae63a 100644 --- a/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -28,6 +28,11 @@ createLocalCompileCallbackManager(const Triple &T, switch (T.getArch()) { default: return nullptr; + case Triple::aarch64: { + typedef orc::LocalJITCompileCallbackManager<orc::OrcAArch64> CCMgrT; + return llvm::make_unique<CCMgrT>(ErrorHandlerAddress); + } + case Triple::x86: { typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT; return llvm::make_unique<CCMgrT>(ErrorHandlerAddress); @@ -42,6 +47,7 @@ createLocalCompileCallbackManager(const Triple &T, return llvm::make_unique<CCMgrT>(ErrorHandlerAddress); } } + } } @@ -50,6 +56,12 @@ createLocalIndirectStubsManagerBuilder(const Triple &T) { switch (T.getArch()) { default: return nullptr; + case Triple::aarch64: + return [](){ + return llvm::make_unique< + orc::LocalIndirectStubsManager<orc::OrcAArch64>>(); + }; + case Triple::x86: return [](){ return llvm::make_unique< @@ -68,6 +80,7 @@ createLocalIndirectStubsManagerBuilder(const Triple &T) { orc::LocalIndirectStubsManager<orc::OrcX86_64_SysV>>(); }; } + } } diff --git a/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/lib/ExecutionEngine/Orc/OrcABISupport.cpp index 9869b6c7050c..e3c968157976 100644 --- a/lib/ExecutionEngine/Orc/OrcABISupport.cpp +++ b/lib/ExecutionEngine/Orc/OrcABISupport.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/OrcABISupport.h" -#include "llvm/ADT/Triple.h" #include "llvm/Support/Process.h" namespace llvm { @@ -117,7 +116,7 @@ void OrcAArch64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) { Trampolines[3 * I + 0] = 0xaa1e03f1; // mov x17, x30 - Trampolines[3 * I + 1] = 0x58000010 | (OffsetToPtr << 3); // mov x16, Lptr + Trampolines[3 * I + 1] = 0x58000010 | (OffsetToPtr << 3); // adr x16, Lptr Trampolines[3 * I + 2] = 0xd63f0200; // blr x16 } diff --git a/lib/ExecutionEngine/Orc/OrcCBindings.cpp b/lib/ExecutionEngine/Orc/OrcCBindings.cpp index de80cb1d0dd4..f945acaf95ee 100644 --- a/lib/ExecutionEngine/Orc/OrcCBindings.cpp +++ b/lib/ExecutionEngine/Orc/OrcCBindings.cpp @@ -20,16 +20,6 @@ void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod) { delete unwrap(SharedMod); } -LLVMSharedObjectBufferRef -LLVMOrcMakeSharedObjectBuffer(LLVMMemoryBufferRef ObjBuffer) { - return wrap(new std::shared_ptr<MemoryBuffer>(unwrap(ObjBuffer))); -} - -void -LLVMOrcDisposeSharedObjectBufferRef(LLVMSharedObjectBufferRef SharedObjBuffer) { - delete unwrap(SharedObjBuffer); -} - LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) { TargetMachine *TM2(unwrap(TM)); @@ -105,6 +95,18 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, return J.addIRModuleLazy(*RetHandle, *M, SymbolResolver, SymbolResolverCtx); } +LLVMOrcErrorCode +LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMMemoryBufferRef Obj, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx) { + OrcCBindingsStack &J = *unwrap(JITStack); + std::unique_ptr<MemoryBuffer> O(unwrap(Obj)); + return J.addObject(*RetHandle, std::move(O), SymbolResolver, + SymbolResolverCtx); +} + LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H) { OrcCBindingsStack &J = *unwrap(JITStack); diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index e38decf94f3e..405970e063d8 100644 --- a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -44,26 +44,12 @@ class OrcCBindingsStack; DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr<Module>, LLVMSharedModuleRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr<MemoryBuffer>, - LLVMSharedObjectBufferRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) -class OrcCBindingsStack { -public: - - using CompileCallbackMgr = orc::JITCompileCallbackManager; - using ObjLayerT = orc::RTDyldObjectLinkingLayer; - using CompileLayerT = orc::IRCompileLayer<ObjLayerT, orc::SimpleCompiler>; - using CODLayerT = - orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>; +namespace detail { - using CallbackManagerBuilder = - std::function<std::unique_ptr<CompileCallbackMgr>()>; - using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT; - -private: class GenericHandle { public: virtual ~GenericHandle() = default; @@ -90,13 +76,56 @@ private: typename LayerT::ModuleHandleT Handle; }; - template <typename LayerT> + template <> + class GenericHandleImpl<orc::RTDyldObjectLinkingLayer> + : public GenericHandle { + private: + using LayerT = orc::RTDyldObjectLinkingLayer; + public: + + GenericHandleImpl(LayerT &Layer, typename LayerT::ObjHandleT Handle) + : Layer(Layer), Handle(std::move(Handle)) {} + + JITSymbol findSymbolIn(const std::string &Name, + bool ExportedSymbolsOnly) override { + return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly); + } + + Error removeModule() override { return Layer.removeObject(Handle); } + + private: + LayerT &Layer; + typename LayerT::ObjHandleT Handle; + }; + + + template <typename LayerT, typename HandleT> std::unique_ptr<GenericHandleImpl<LayerT>> - createGenericHandle(LayerT &Layer, typename LayerT::ModuleHandleT Handle) { + createGenericHandle(LayerT &Layer, HandleT Handle) { return llvm::make_unique<GenericHandleImpl<LayerT>>(Layer, std::move(Handle)); } +} // end namespace detail + +class OrcCBindingsStack { +public: + + using CompileCallbackMgr = orc::JITCompileCallbackManager; + using ObjLayerT = orc::RTDyldObjectLinkingLayer; + using CompileLayerT = orc::IRCompileLayer<ObjLayerT, orc::SimpleCompiler>; + using CODLayerT = + orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>; + + using CallbackManagerBuilder = + std::function<std::unique_ptr<CompileCallbackMgr>()>; + + using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT; + +private: + + using OwningObject = object::OwningBinary<object::ObjectFile>; + public: using ModuleHandleT = unsigned; @@ -145,12 +174,15 @@ public: createLazyCompileCallback(JITTargetAddress &RetAddr, LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx) { - auto CCInfo = CCMgr->getCompileCallback(); - CCInfo.setCompileAction([=]() -> JITTargetAddress { - return Callback(wrap(this), CallbackCtx); - }); - RetAddr = CCInfo.getAddress(); - return LLVMOrcErrSuccess; + if (auto CCInfoOrErr = CCMgr->getCompileCallback()) { + auto &CCInfo = *CCInfoOrErr; + CCInfo.setCompileAction([=]() -> JITTargetAddress { + return Callback(wrap(this), CallbackCtx); + }); + RetAddr = CCInfo.getAddress(); + return LLVMOrcErrSuccess; + } else + return mapError(CCInfoOrErr.takeError()); } LLVMOrcErrorCode createIndirectStub(StringRef StubName, @@ -263,6 +295,33 @@ public: return LLVMOrcErrSuccess; } + LLVMOrcErrorCode addObject(ModuleHandleT &RetHandle, + std::unique_ptr<MemoryBuffer> ObjBuffer, + LLVMOrcSymbolResolverFn ExternalResolver, + void *ExternalResolverCtx) { + if (auto ObjOrErr = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef())) { + auto &Obj = *ObjOrErr; + auto OwningObj = + std::make_shared<OwningObject>(std::move(Obj), std::move(ObjBuffer)); + + // Create the resolver. + auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx); + + ModuleHandleT H; + if (auto HOrErr = ObjectLayer.addObject(std::move(OwningObj), + std::move(Resolver))) + H = createHandle(ObjectLayer, *HOrErr); + else + return mapError(HOrErr.takeError()); + + RetHandle = H; + + return LLVMOrcErrSuccess; + } else + return mapError(ObjOrErr.takeError()); + } + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly)) @@ -298,17 +357,19 @@ public: const std::string &getErrorMessage() const { return ErrMsg; } private: - template <typename LayerT> - unsigned createHandle(LayerT &Layer, typename LayerT::ModuleHandleT Handle) { + template <typename LayerT, typename HandleT> + unsigned createHandle(LayerT &Layer, HandleT Handle) { unsigned NewHandle; if (!FreeHandleIndexes.empty()) { NewHandle = FreeHandleIndexes.back(); FreeHandleIndexes.pop_back(); - GenericHandles[NewHandle] = createGenericHandle(Layer, std::move(Handle)); + GenericHandles[NewHandle] = + detail::createGenericHandle(Layer, std::move(Handle)); return NewHandle; } else { NewHandle = GenericHandles.size(); - GenericHandles.push_back(createGenericHandle(Layer, std::move(Handle))); + GenericHandles.push_back( + detail::createGenericHandle(Layer, std::move(Handle))); } return NewHandle; } @@ -335,7 +396,7 @@ private: CompileLayerT CompileLayer; CODLayerT CODLayer; - std::vector<std::unique_ptr<GenericHandle>> GenericHandles; + std::vector<std::unique_ptr<detail::GenericHandle>> GenericHandles; std::vector<unsigned> FreeHandleIndexes; orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; diff --git a/lib/ExecutionEngine/Orc/OrcError.cpp b/lib/ExecutionEngine/Orc/OrcError.cpp index df2d320e0f7a..c218cb9a523c 100644 --- a/lib/ExecutionEngine/Orc/OrcError.cpp +++ b/lib/ExecutionEngine/Orc/OrcError.cpp @@ -54,6 +54,8 @@ public: case OrcErrorCode::UnknownErrorCodeFromRemote: return "Unknown error returned from remote RPC function " "(Use StringError to get error message)"; + case OrcErrorCode::UnknownResourceHandle: + return "Unknown resource handle"; } llvm_unreachable("Unhandled error code"); } diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 346a40405ff1..1dc8d4ac7bc5 100644 --- a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -225,9 +225,9 @@ public: bool removeModule(Module *M) override { for (auto I = LocalModules.begin(), E = LocalModules.end(); I != E; ++I) { if (I->get() == M) { - ShouldDelete[M] = false; - LocalModules.erase(I); - return true; + ShouldDelete[M] = false; + LocalModules.erase(I); + return true; } } return false; @@ -341,7 +341,7 @@ private: void operator()(RTDyldObjectLinkingLayerBase::ObjHandleT H, const RTDyldObjectLinkingLayer::ObjectPtr &Obj, - const LoadedObjectInfo &Info) const { + const RuntimeDyld::LoadedObjectInfo &Info) const { M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad); M.SectionsAllocatedSinceLastLoad = SectionAddrSet(); M.MemMgr->notifyObjectLoaded(&M, *Obj->getBinary()); @@ -381,6 +381,12 @@ private: std::shared_ptr<JITSymbolResolver> ClientResolver; Mangler Mang; + // IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr + // delete blocks in LocalModules refer to the ShouldDelete map, so + // LocalModules needs to be destructed before ShouldDelete. + std::map<Module*, bool> ShouldDelete; + std::vector<std::shared_ptr<Module>> LocalModules; + NotifyObjectLoadedT NotifyObjectLoaded; NotifyFinalizedT NotifyFinalized; @@ -402,8 +408,6 @@ private: std::map<ObjectLayerT::ObjHandleT, SectionAddrSet, ObjHandleCompare> UnfinalizedSections; - std::map<Module*, bool> ShouldDelete; - std::vector<std::shared_ptr<Module>> LocalModules; std::vector<object::OwningBinary<object::Archive>> Archives; }; diff --git a/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp b/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp index 8769dcf73747..87059ef2b88f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp @@ -39,3 +39,11 @@ llvm::JITSymbolFlags::fromObjectSymbol(const object::BasicSymbolRef &Symbol) { Flags |= JITSymbolFlags::Exported; return Flags; } + +ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol( + const object::BasicSymbolRef &Symbol) { + ARMJITSymbolFlags Flags; + if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb) + Flags |= ARMJITSymbolFlags::Thumb; + return Flags; +} diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 8198836f7a0c..c5e4dfa1e536 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -233,7 +233,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { return NameOrErr.takeError(); // Compute JIT symbol flags. - JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(*I); + JITSymbolFlags JITSymFlags = getJITSymbolFlags(*I); // If this is a weak definition, check to see if there's a strong one. // If there is, skip this symbol (we won't be providing it: the strong @@ -616,6 +616,10 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst, } } +JITSymbolFlags RuntimeDyldImpl::getJITSymbolFlags(const BasicSymbolRef &SR) { + return JITSymbolFlags::fromObjectSymbol(SR); +} + Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, CommonSymbolList &CommonSymbols) { if (CommonSymbols.empty()) @@ -685,7 +689,7 @@ Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, Addr += AlignOffset; Offset += AlignOffset; } - JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(Sym); + JITSymbolFlags JITSymFlags = getJITSymbolFlags(Sym); DEBUG(dbgs() << "Allocating common symbol " << Name << " address " << format("%p", Addr) << "\n"); GlobalSymbolTable[Name] = @@ -746,8 +750,11 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj, // Code section alignment needs to be at least as high as stub alignment or // padding calculations may by incorrect when the section is remapped to a // higher alignment. - if (IsCode) + if (IsCode) { Alignment = std::max(Alignment, getStubAlignment()); + if (StubBufSize > 0) + PaddingSize += getStubAlignment() - 1; + } // Some sections, such as debug info, don't need to be loaded for execution. // Process those only if explicitly requested. @@ -771,8 +778,13 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj, // Fill in any extra bytes we allocated for padding if (PaddingSize != 0) { memset(Addr + DataSize, 0, PaddingSize); - // Update the DataSize variable so that the stub offset is set correctly. + // Update the DataSize variable to include padding. DataSize += PaddingSize; + + // Align DataSize to stub alignment if we have any stubs (PaddingSize will + // have been increased above to account for this). + if (StubBufSize > 0) + DataSize &= ~(getStubAlignment() - 1); } DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name @@ -864,9 +876,9 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr, } else if (Arch == Triple::arm || Arch == Triple::armeb) { // TODO: There is only ARM far stub now. We should add the Thumb stub, // and stubs for branches Thumb - ARM and ARM - Thumb. - writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,<label> + writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc, [pc, #-4] return Addr + 4; - } else if (IsMipsO32ABI) { + } else if (IsMipsO32ABI || IsMipsN32ABI) { // 0: 3c190000 lui t9,%hi(addr). // 4: 27390000 addiu t9,t9,%lo(addr). // 8: 03200008 jr t9. @@ -874,13 +886,39 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr, const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000; const unsigned NopInstr = 0x0; unsigned JrT9Instr = 0x03200008; - if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_32R6) - JrT9Instr = 0x03200009; + if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_32R6 || + (AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_64R6) + JrT9Instr = 0x03200009; writeBytesUnaligned(LuiT9Instr, Addr, 4); - writeBytesUnaligned(AdduiT9Instr, Addr+4, 4); - writeBytesUnaligned(JrT9Instr, Addr+8, 4); - writeBytesUnaligned(NopInstr, Addr+12, 4); + writeBytesUnaligned(AdduiT9Instr, Addr + 4, 4); + writeBytesUnaligned(JrT9Instr, Addr + 8, 4); + writeBytesUnaligned(NopInstr, Addr + 12, 4); + return Addr; + } else if (IsMipsN64ABI) { + // 0: 3c190000 lui t9,%highest(addr). + // 4: 67390000 daddiu t9,t9,%higher(addr). + // 8: 0019CC38 dsll t9,t9,16. + // c: 67390000 daddiu t9,t9,%hi(addr). + // 10: 0019CC38 dsll t9,t9,16. + // 14: 67390000 daddiu t9,t9,%lo(addr). + // 18: 03200008 jr t9. + // 1c: 00000000 nop. + const unsigned LuiT9Instr = 0x3c190000, DaddiuT9Instr = 0x67390000, + DsllT9Instr = 0x19CC38; + const unsigned NopInstr = 0x0; + unsigned JrT9Instr = 0x03200008; + if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_64R6) + JrT9Instr = 0x03200009; + + writeBytesUnaligned(LuiT9Instr, Addr, 4); + writeBytesUnaligned(DaddiuT9Instr, Addr + 4, 4); + writeBytesUnaligned(DsllT9Instr, Addr + 8, 4); + writeBytesUnaligned(DaddiuT9Instr, Addr + 12, 4); + writeBytesUnaligned(DsllT9Instr, Addr + 16, 4); + writeBytesUnaligned(DaddiuT9Instr, Addr + 20, 4); + writeBytesUnaligned(JrT9Instr, Addr + 24, 4); + writeBytesUnaligned(NopInstr, Addr + 28, 4); return Addr; } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { // Depending on which version of the ELF ABI is in use, we need to @@ -971,15 +1009,17 @@ Error RuntimeDyldImpl::resolveExternalSymbols() { resolveRelocationList(Relocs, 0); } else { uint64_t Addr = 0; + JITSymbolFlags Flags; RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name); if (Loc == GlobalSymbolTable.end()) { // This is an external symbol, try to get its address from the symbol // resolver. // First search for the symbol in this logical dylib. if (auto Sym = Resolver.findSymbolInLogicalDylib(Name.data())) { - if (auto AddrOrErr = Sym.getAddress()) + if (auto AddrOrErr = Sym.getAddress()) { Addr = *AddrOrErr; - else + Flags = Sym.getFlags(); + } else return AddrOrErr.takeError(); } else if (auto Err = Sym.takeError()) return Err; @@ -987,9 +1027,10 @@ Error RuntimeDyldImpl::resolveExternalSymbols() { // If that fails, try searching for an external symbol. if (!Addr) { if (auto Sym = Resolver.findSymbol(Name.data())) { - if (auto AddrOrErr = Sym.getAddress()) + if (auto AddrOrErr = Sym.getAddress()) { Addr = *AddrOrErr; - else + Flags = Sym.getFlags(); + } else return AddrOrErr.takeError(); } else if (auto Err = Sym.takeError()) return Err; @@ -1007,6 +1048,7 @@ Error RuntimeDyldImpl::resolveExternalSymbols() { const auto &SymInfo = Loc->second; Addr = getSectionLoadAddress(SymInfo.getSectionID()) + SymInfo.getOffset(); + Flags = SymInfo.getFlags(); } // FIXME: Implement error handling that doesn't kill the host program! @@ -1017,6 +1059,12 @@ Error RuntimeDyldImpl::resolveExternalSymbols() { // If Resolver returned UINT64_MAX, the client wants to handle this symbol // manually and we shouldn't resolve its relocations. if (Addr != UINT64_MAX) { + + // Tweak the address based on the symbol flags if necessary. + // For example, this is used by RuntimeDyldMachOARM to toggle the low bit + // if the target symbol is Thumb. + Addr = modifyAddressBasedOnFlags(Addr, Flags); + DEBUG(dbgs() << "Resolving relocations Name: " << Name << "\t" << format("0x%lx", Addr) << "\n"); // This list may have been updated when we called getSymbolAddress, so diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 77c968401c16..c0047d0cde6a 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -14,17 +14,14 @@ #include "RuntimeDyldELF.h" #include "RuntimeDyldCheckerImpl.h" #include "Targets/RuntimeDyldELFMips.h" -#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCStreamer.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/TargetRegistry.h" using namespace llvm; using namespace llvm::object; @@ -70,8 +67,11 @@ template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> { typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type; + DyldELFObject(ELFObjectFile<ELFT> &&Obj); + public: - DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec); + static Expected<std::unique_ptr<DyldELFObject>> + create(MemoryBufferRef Wrapper); void updateSectionAddress(const SectionRef &Sec, uint64_t Addr); @@ -93,12 +93,23 @@ public: // actual memory. Ultimately, the Binary parent class will take ownership of // this MemoryBuffer object but not the underlying memory. template <class ELFT> -DyldELFObject<ELFT>::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC) - : ELFObjectFile<ELFT>(Wrapper, EC) { +DyldELFObject<ELFT>::DyldELFObject(ELFObjectFile<ELFT> &&Obj) + : ELFObjectFile<ELFT>(std::move(Obj)) { this->isDyldELFObject = true; } template <class ELFT> +Expected<std::unique_ptr<DyldELFObject<ELFT>>> +DyldELFObject<ELFT>::create(MemoryBufferRef Wrapper) { + auto Obj = ELFObjectFile<ELFT>::create(Wrapper); + if (auto E = Obj.takeError()) + return std::move(E); + std::unique_ptr<DyldELFObject<ELFT>> Ret( + new DyldELFObject<ELFT>(std::move(*Obj))); + return std::move(Ret); +} + +template <class ELFT> void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec, uint64_t Addr) { DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); @@ -134,16 +145,18 @@ public: }; template <typename ELFT> -std::unique_ptr<DyldELFObject<ELFT>> -createRTDyldELFObject(MemoryBufferRef Buffer, - const ObjectFile &SourceObject, - const LoadedELFObjectInfo &L, - std::error_code &ec) { +static Expected<std::unique_ptr<DyldELFObject<ELFT>>> +createRTDyldELFObject(MemoryBufferRef Buffer, const ObjectFile &SourceObject, + const LoadedELFObjectInfo &L) { typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type; - std::unique_ptr<DyldELFObject<ELFT>> Obj = - llvm::make_unique<DyldELFObject<ELFT>>(Buffer, ec); + Expected<std::unique_ptr<DyldELFObject<ELFT>>> ObjOrErr = + DyldELFObject<ELFT>::create(Buffer); + if (Error E = ObjOrErr.takeError()) + return std::move(E); + + std::unique_ptr<DyldELFObject<ELFT>> Obj = std::move(*ObjOrErr); // Iterate over all sections in the object. auto SI = SourceObject.section_begin(); @@ -164,41 +177,35 @@ createRTDyldELFObject(MemoryBufferRef Buffer, ++SI; } - return Obj; + return std::move(Obj); } -OwningBinary<ObjectFile> createELFDebugObject(const ObjectFile &Obj, - const LoadedELFObjectInfo &L) { +static OwningBinary<ObjectFile> +createELFDebugObject(const ObjectFile &Obj, const LoadedELFObjectInfo &L) { assert(Obj.isELF() && "Not an ELF object file."); std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName()); - std::error_code ec; - - std::unique_ptr<ObjectFile> DebugObj; - if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) { - typedef ELFType<support::little, false> ELF32LE; - DebugObj = createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), Obj, L, - ec); - } else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) { - typedef ELFType<support::big, false> ELF32BE; - DebugObj = createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), Obj, L, - ec); - } else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) { - typedef ELFType<support::big, true> ELF64BE; - DebugObj = createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), Obj, L, - ec); - } else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) { - typedef ELFType<support::little, true> ELF64LE; - DebugObj = createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), Obj, L, - ec); - } else + Expected<std::unique_ptr<ObjectFile>> DebugObj(nullptr); + handleAllErrors(DebugObj.takeError()); + if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) + DebugObj = + createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), Obj, L); + else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) + DebugObj = + createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), Obj, L); + else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) + DebugObj = + createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), Obj, L); + else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) + DebugObj = + createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), Obj, L); + else llvm_unreachable("Unexpected ELF format"); - assert(!ec && "Could not construct copy ELF object file"); - - return OwningBinary<ObjectFile>(std::move(DebugObj), std::move(Buffer)); + handleAllErrors(DebugObj.takeError()); + return OwningBinary<ObjectFile>(std::move(*DebugObj), std::move(Buffer)); } OwningBinary<ObjectFile> @@ -355,6 +362,18 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, default: llvm_unreachable("Relocation type not implemented yet!"); break; + case ELF::R_AARCH64_ABS16: { + uint64_t Result = Value + Addend; + assert(static_cast<int64_t>(Result) >= INT16_MIN && Result < UINT16_MAX); + write(isBE, TargetPtr, static_cast<uint16_t>(Result & 0xffffU)); + break; + } + case ELF::R_AARCH64_ABS32: { + uint64_t Result = Value + Addend; + assert(static_cast<int64_t>(Result) >= INT32_MIN && Result < UINT32_MAX); + write(isBE, TargetPtr, static_cast<uint32_t>(Result & 0xffffffffU)); + break; + } case ELF::R_AARCH64_ABS64: write(isBE, TargetPtr, Value + Addend); break; @@ -590,7 +609,7 @@ Error RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj, if (auto AddendOrErr = i->getAddend()) Addend = *AddendOrErr; else - return errorCodeToError(AddendOrErr.getError()); + return AddendOrErr.takeError(); ++i; if (i == e) @@ -1058,8 +1077,11 @@ RuntimeDyldELF::processRelocationRef( ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) { const auto &Obj = cast<ELFObjectFileBase>(O); uint64_t RelType = RelI->getType(); - ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(*RelI).getAddend(); - int64_t Addend = AddendOrErr ? *AddendOrErr : 0; + int64_t Addend = 0; + if (Expected<int64_t> AddendOrErr = ELFRelocationRef(*RelI).getAddend()) + Addend = *AddendOrErr; + else + consumeError(AddendOrErr.takeError()); elf_symbol_iterator Symbol = RelI->getSymbol(); // Obtain the symbol name which is referenced in the relocation @@ -1252,8 +1274,7 @@ RuntimeDyldELF::processRelocationRef( if (Value.SymbolName) { addRelocationForSymbol(REHi, Value.SymbolName); addRelocationForSymbol(RELo, Value.SymbolName); - } - else { + } else { addRelocationForSection(REHi, Value.SectionID); addRelocationForSection(RELo, Value.SectionID); } @@ -1313,11 +1334,81 @@ RuntimeDyldELF::processRelocationRef( RE.SymOffset = allocateGOTEntries(1); GOTSymbolOffsets[TargetName] = RE.SymOffset; } + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + } else if (RelType == ELF::R_MIPS_26) { + // This is an Mips branch relocation, need to use a stub function. + DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); + SectionEntry &Section = Sections[SectionID]; + + // Look up for existing stub. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + RelocationEntry RE(SectionID, Offset, RelType, i->second); + addRelocationForSection(RE, SectionID); + DEBUG(dbgs() << " Stub function found\n"); + } else { + // Create a new stub function. + DEBUG(dbgs() << " Create a new stub function\n"); + Stubs[Value] = Section.getStubOffset(); + + unsigned AbiVariant; + O.getPlatformFlags(AbiVariant); + + uint8_t *StubTargetAddr = createStubFunction( + Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant); + + if (IsMipsN32ABI) { + // Creating Hi and Lo relocations for the filled stub instructions. + RelocationEntry REHi(SectionID, StubTargetAddr - Section.getAddress(), + ELF::R_MIPS_HI16, Value.Addend); + RelocationEntry RELo(SectionID, + StubTargetAddr - Section.getAddress() + 4, + ELF::R_MIPS_LO16, Value.Addend); + if (Value.SymbolName) { + addRelocationForSymbol(REHi, Value.SymbolName); + addRelocationForSymbol(RELo, Value.SymbolName); + } else { + addRelocationForSection(REHi, Value.SectionID); + addRelocationForSection(RELo, Value.SectionID); + } + } else { + // Creating Highest, Higher, Hi and Lo relocations for the filled stub + // instructions. + RelocationEntry REHighest(SectionID, + StubTargetAddr - Section.getAddress(), + ELF::R_MIPS_HIGHEST, Value.Addend); + RelocationEntry REHigher(SectionID, + StubTargetAddr - Section.getAddress() + 4, + ELF::R_MIPS_HIGHER, Value.Addend); + RelocationEntry REHi(SectionID, + StubTargetAddr - Section.getAddress() + 12, + ELF::R_MIPS_HI16, Value.Addend); + RelocationEntry RELo(SectionID, + StubTargetAddr - Section.getAddress() + 20, + ELF::R_MIPS_LO16, Value.Addend); + if (Value.SymbolName) { + addRelocationForSymbol(REHighest, Value.SymbolName); + addRelocationForSymbol(REHigher, Value.SymbolName); + addRelocationForSymbol(REHi, Value.SymbolName); + addRelocationForSymbol(RELo, Value.SymbolName); + } else { + addRelocationForSection(REHighest, Value.SectionID); + addRelocationForSection(REHigher, Value.SectionID); + addRelocationForSection(REHi, Value.SectionID); + addRelocationForSection(RELo, Value.SectionID); + } + } + RelocationEntry RE(SectionID, Offset, RelType, Section.getStubOffset()); + addRelocationForSection(RE, SectionID); + Section.advanceStubOffset(getMaxStubSize()); + } + } else { + processSimpleRelocation(SectionID, Offset, RelType, Value); } - if (Value.SymbolName) - addRelocationForSymbol(RE, Value.SymbolName); - else - addRelocationForSection(RE, Value.SectionID); + } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { if (RelType == ELF::R_PPC64_REL24) { // Determine ABI variant in use for this object. diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index fb5da6dd8bbb..f37bd0bbaea6 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -66,8 +66,10 @@ class RuntimeDyldELF : public RuntimeDyldImpl { return 20; // movz; movk; movk; movk; br if (Arch == Triple::arm || Arch == Triple::thumb) return 8; // 32-bit instruction and 32-bit address - else if (IsMipsO32ABI) + else if (IsMipsO32ABI || IsMipsN32ABI) return 16; + else if (IsMipsN64ABI) + return 32; else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) return 44; else if (Arch == Triple::x86_64) diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 95b04fd93251..e046a8504e9f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -149,8 +149,8 @@ public: /// The size of this relocation (MachO specific). unsigned Size; - // COFF specific. - bool IsTargetThumbFunc; + // ARM (MachO and COFF) specific. + bool IsTargetThumbFunc = false; RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend) : SectionID(id), Offset(offset), RelType(type), Addend(addend), @@ -195,12 +195,14 @@ public: uint64_t Offset; int64_t Addend; const char *SymbolName; + 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 && - Addend == Other.Addend && SymbolName == Other.SymbolName; + Addend == Other.Addend && SymbolName == Other.SymbolName && + IsStubThumb == Other.IsStubThumb; } inline bool operator<(const RelocationValueRef &Other) const { if (SectionID != Other.SectionID) @@ -209,6 +211,8 @@ public: return Offset < Other.Offset; if (Addend != Other.Addend) return Addend < Other.Addend; + if (IsStubThumb != Other.IsStubThumb) + return IsStubThumb < Other.IsStubThumb; return SymbolName < Other.SymbolName; } }; @@ -216,21 +220,21 @@ public: /// @brief Symbol info for RuntimeDyld. class SymbolTableEntry { public: - SymbolTableEntry() - : Offset(0), SectionID(0) {} + SymbolTableEntry() = default; SymbolTableEntry(unsigned SectionID, uint64_t Offset, JITSymbolFlags Flags) : Offset(Offset), SectionID(SectionID), Flags(Flags) {} unsigned getSectionID() const { return SectionID; } uint64_t getOffset() const { return Offset; } + void setOffset(uint64_t NewOffset) { Offset = NewOffset; } JITSymbolFlags getFlags() const { return Flags; } private: - uint64_t Offset; - unsigned SectionID; - JITSymbolFlags Flags; + uint64_t Offset = 0; + unsigned SectionID = 0; + JITSymbolFlags Flags = JITSymbolFlags::None; }; typedef StringMap<SymbolTableEntry> RTDyldSymbolTable; @@ -365,6 +369,18 @@ protected: /// Dst. void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const; + /// Generate JITSymbolFlags from a libObject symbol. + virtual JITSymbolFlags getJITSymbolFlags(const BasicSymbolRef &Sym); + + /// Modify the given target address based on the given symbol flags. + /// This can be used by subclasses to tweak addresses based on symbol flags, + /// For example: the MachO/ARM target uses it to set the low bit if the target + /// is a thumb symbol. + virtual uint64_t modifyAddressBasedOnFlags(uint64_t Addr, + JITSymbolFlags Flags) const { + return Addr; + } + /// \brief Given the common symbols discovered in the object file, emit a /// new section for them and update the symbol mappings in the object and /// symbol table. @@ -493,6 +509,12 @@ public: if (SymEntry.getSectionID() != AbsoluteSymbolSection) SectionAddr = getSectionLoadAddress(SymEntry.getSectionID()); uint64_t TargetAddr = SectionAddr + SymEntry.getOffset(); + + // FIXME: Have getSymbol should return the actual address and the client + // modify it based on the flags. This will require clients to be + // aware of the target architecture, which we should build + // infrastructure for. + TargetAddr = modifyAddressBasedOnFlags(TargetAddr, SymEntry.getFlags()); return JITEvaluatedSymbol(TargetAddr, SymEntry.getFlags()); } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 80e9c7ac18aa..b0561f68edb3 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -55,7 +55,8 @@ Expected<relocation_iterator> RuntimeDyldMachO::processScatteredVANILLA( unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, - RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { + RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID, + bool TargetIsLocalThumbFunc) { const MachOObjectFile &Obj = static_cast<const MachOObjectFile&>(BaseObjT); MachO::any_relocation_info RE = @@ -85,6 +86,7 @@ RuntimeDyldMachO::processScatteredVANILLA( Addend -= SectionBaseAddr; RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size); + R.IsTargetThumbFunc = TargetIsLocalThumbFunc; addRelocationForSection(R, TargetSectionID); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 67a5020fc4f9..d71ca4e54953 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -83,7 +83,8 @@ protected: Expected<relocation_iterator> processScatteredVANILLA(unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, - RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID); + RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID, + bool TargetIsLocalThumbFunc = false); /// Construct a RelocationValueRef representing the relocation target. /// For Symbols in known sections, this will return a RelocationValueRef diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h index 901f77865ba1..04678f224466 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h @@ -144,10 +144,7 @@ public: ? Value : Sections[RE.Sections.SectionA].getLoadAddressWithOffset( RE.Addend); - assert(static_cast<int32_t>(Result) <= INT32_MAX && - "relocation overflow"); - assert(static_cast<int32_t>(Result) >= INT32_MIN && - "relocation underflow"); + assert(Result <= UINT32_MAX && "relocation overflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_I386_DIR32" << " TargetSection: " << RE.Sections.SectionA @@ -161,10 +158,7 @@ public: uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) - Sections[0].getLoadAddress(); - assert(static_cast<int32_t>(Result) <= INT32_MAX && - "relocation overflow"); - assert(static_cast<int32_t>(Result) >= INT32_MIN && - "relocation underflow"); + assert(Result <= UINT32_MAX && "relocation overflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_I386_DIR32NB" << " TargetSection: " << RE.Sections.SectionA @@ -178,9 +172,9 @@ public: ? Value : Sections[RE.Sections.SectionA].getLoadAddress(); Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset; - assert(static_cast<int32_t>(Result) <= INT32_MAX && + assert(static_cast<int64_t>(Result) <= INT32_MAX && "relocation overflow"); - assert(static_cast<int32_t>(Result) >= INT32_MIN && + assert(static_cast<int64_t>(Result) >= INT32_MIN && "relocation underflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_I386_REL32" @@ -191,10 +185,8 @@ public: } case COFF::IMAGE_REL_I386_SECTION: // 16-bit section index of the section that contains the target. - assert(static_cast<int32_t>(RE.SectionID) <= INT16_MAX && + assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX && "relocation overflow"); - assert(static_cast<int32_t>(RE.SectionID) >= INT16_MIN && - "relocation underflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_I386_SECTION Value: " << RE.SectionID << '\n'); @@ -202,14 +194,12 @@ public: break; case COFF::IMAGE_REL_I386_SECREL: // 32-bit offset of the target from the beginning of its section. - assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX && "relocation overflow"); - assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && - "relocation underflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_I386_SECREL Value: " << RE.Addend << '\n'); - writeBytesUnaligned(RE.Addend, Target, 2); + writeBytesUnaligned(RE.Addend, Target, 4); break; default: llvm_unreachable("unsupported relocation type"); diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h index 3e4b0c8f75bb..9000435764df 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h @@ -186,10 +186,7 @@ public: ? Value : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend); Result |= ISASelectionBit; - assert(static_cast<int32_t>(Result) <= INT32_MAX && - "relocation overflow"); - assert(static_cast<int32_t>(Result) >= INT32_MIN && - "relocation underflow"); + assert(Result <= UINT32_MAX && "relocation overflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_ARM_ADDR32" << " TargetSection: " << RE.Sections.SectionA @@ -202,10 +199,7 @@ public: // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() - Sections[0].getLoadAddress() + RE.Addend; - assert(static_cast<int32_t>(Result) <= INT32_MAX && - "relocation overflow"); - assert(static_cast<int32_t>(Result) >= INT32_MIN && - "relocation underflow"); + assert(Result <= UINT32_MAX && "relocation overflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_ARM_ADDR32NB" << " TargetSection: " << RE.Sections.SectionA @@ -216,10 +210,8 @@ public: } case COFF::IMAGE_REL_ARM_SECTION: // 16-bit section index of the section that contains the target. - assert(static_cast<int32_t>(RE.SectionID) <= INT16_MAX && + assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX && "relocation overflow"); - assert(static_cast<int32_t>(RE.SectionID) >= INT16_MIN && - "relocation underflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_ARM_SECTION Value: " << RE.SectionID << '\n'); @@ -227,10 +219,8 @@ public: break; case COFF::IMAGE_REL_ARM_SECREL: // 32-bit offset of the target from the beginning of its section. - assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX && "relocation overflow"); - assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && - "relocation underflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend << '\n'); @@ -240,10 +230,7 @@ public: // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair. uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend); - assert(static_cast<int32_t>(Result) <= INT32_MAX && - "relocation overflow"); - assert(static_cast<int32_t>(Result) >= INT32_MIN && - "relocation underflow"); + assert(Result <= UINT32_MAX && "relocation overflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_ARM_MOV32T" << " TargetSection: " << RE.Sections.SectionA @@ -271,9 +258,9 @@ public: // The most significant 20-bits of the signed 21-bit relative displacement uint64_t Value = RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; - assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX && "relocation overflow"); - assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && + assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN && "relocation underflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_ARM_BRANCH20T" @@ -286,9 +273,9 @@ public: // The most significant 24-bits of the signed 25-bit relative displacement uint64_t Value = RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; - assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX && "relocation overflow"); - assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && + assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN && "relocation underflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_ARM_BRANCH24T" @@ -301,9 +288,9 @@ public: // The most significant 24-bits of the signed 25-bit relative displacement uint64_t Value = RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; - assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX && "relocation overflow"); - assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && + assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN && "relocation underflow"); DEBUG(dbgs() << "\t\tOffset: " << RE.Offset << " RelType: IMAGE_REL_ARM_BLX23T" @@ -321,4 +308,3 @@ public: } #endif - diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp index 926996d6f7b3..fe0f48e66a81 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp @@ -116,6 +116,8 @@ int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation( << format("%llx", Section.getLoadAddressWithOffset(Offset)) << " Value: 0x" << format("%llx", Value) << " Type: 0x" << format("%x", Type) << " Addend: 0x" << format("%llx", Addend) + << " Offset: " << format("%llx" PRIx64, Offset) + << " SID: " << format("%d", SectionID) << " SymOffset: " << format("%x", SymOffset) << "\n"); switch (Type) { @@ -141,6 +143,10 @@ int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation( return ((Value + Addend + 0x8000) >> 16) & 0xffff; case ELF::R_MIPS_LO16: return (Value + Addend) & 0xffff; + case ELF::R_MIPS_HIGHER: + return ((Value + Addend + 0x80008000) >> 32) & 0xffff; + case ELF::R_MIPS_HIGHEST: + return ((Value + Addend + 0x800080008000) >> 48) & 0xffff; case ELF::R_MIPS_CALL16: case ELF::R_MIPS_GOT_DISP: case ELF::R_MIPS_GOT_PAGE: { @@ -215,6 +221,8 @@ void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value, case ELF::R_MIPS_GPREL16: case ELF::R_MIPS_HI16: case ELF::R_MIPS_LO16: + case ELF::R_MIPS_HIGHER: + case ELF::R_MIPS_HIGHEST: case ELF::R_MIPS_PC16: case ELF::R_MIPS_PCHI16: case ELF::R_MIPS_PCLO16: @@ -304,7 +312,8 @@ void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section, << format("%p", Section.getLoadAddressWithOffset(Offset)) << " Value: " << format("%x", Value) << " Type: " << format("%x", Type) - << " Addend: " << format("%x", Addend) << "\n"); + << " Addend: " << format("%x", Addend) + << " SymOffset: " << format("%x", Offset) << "\n"); Value = evaluateMIPS32Relocation(Section, Offset, Value, Type); diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 43461de4c491..990629de2f1d 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -34,7 +34,20 @@ public: unsigned getStubAlignment() override { return 4; } - int64_t decodeAddend(const RelocationEntry &RE) const { + JITSymbolFlags getJITSymbolFlags(const BasicSymbolRef &SR) override { + auto Flags = RuntimeDyldImpl::getJITSymbolFlags(SR); + Flags.getTargetFlags() = ARMJITSymbolFlags::fromObjectSymbol(SR); + return Flags; + } + + uint64_t modifyAddressBasedOnFlags(uint64_t Addr, + JITSymbolFlags Flags) const override { + if (Flags.getTargetFlags() & ARMJITSymbolFlags::Thumb) + Addr |= 0x1; + return Addr; + } + + Expected<int64_t> decodeAddend(const RelocationEntry &RE) const { const SectionEntry &Section = Sections[RE.SectionID]; uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); @@ -47,6 +60,27 @@ public: // Now we've got the shifted immediate, shift by 2, sign extend and ret. return SignExtend32<26>(Temp << 2); } + + case MachO::ARM_THUMB_RELOC_BR22: { + // This is a pair of instructions whose operands combine to provide 22 + // bits of displacement: + // Encoding for high bits 1111 0XXX XXXX XXXX + // Encoding for low bits 1111 1XXX XXXX XXXX + uint16_t HighInsn = readBytesUnaligned(LocalAddress, 2); + if ((HighInsn & 0xf800) != 0xf000) + return make_error<StringError>("Unrecognized thumb branch encoding " + "(BR22 high bits)", + inconvertibleErrorCode()); + + uint16_t LowInsn = readBytesUnaligned(LocalAddress + 2, 2); + if ((LowInsn & 0xf800) != 0xf800) + return make_error<StringError>("Unrecognized thumb branch encoding " + "(BR22 low bits)", + inconvertibleErrorCode()); + + return SignExtend64<23>(((HighInsn & 0x7ff) << 12) | + ((LowInsn & 0x7ff) << 1)); + } } } @@ -61,12 +95,35 @@ public: Obj.getRelocation(RelI->getRawDataRefImpl()); uint32_t RelType = Obj.getAnyRelocationType(RelInfo); + // Set to true for thumb functions in this (or previous) TUs. + // Will be used to set the TargetIsThumbFunc member on the relocation entry. + bool TargetIsLocalThumbFunc = false; + if (Obj.getPlainRelocationExternal(RelInfo)) { + auto Symbol = RelI->getSymbol(); + StringRef TargetName; + if (auto TargetNameOrErr = Symbol->getName()) + TargetName = *TargetNameOrErr; + else + return TargetNameOrErr.takeError(); + + // If the target is external but the value doesn't have a name then we've + // converted the value to a section/offset pair, but we still need to set + // the IsTargetThumbFunc bit, so look the value up in the globla symbol table. + auto EntryItr = GlobalSymbolTable.find(TargetName); + if (EntryItr != GlobalSymbolTable.end()) { + TargetIsLocalThumbFunc = + EntryItr->second.getFlags().getTargetFlags() & + ARMJITSymbolFlags::Thumb; + } + } + if (Obj.isRelocationScattered(RelInfo)) { if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF) return processHALFSECTDIFFRelocation(SectionID, RelI, Obj, ObjSectionToID); else if (RelType == MachO::GENERIC_RELOC_VANILLA) - return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); + return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID, + TargetIsLocalThumbFunc); else return ++RelI; } @@ -77,7 +134,6 @@ public: UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_SECTDIFF); UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_LOCAL_SECTDIFF); UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PB_LA_PTR); - UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_RELOC_BR22); UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_32BIT_BRANCH); UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_HALF); default: @@ -89,17 +145,30 @@ public: } RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); - RE.Addend = decodeAddend(RE); + if (auto AddendOrErr = decodeAddend(RE)) + RE.Addend = *AddendOrErr; + else + return AddendOrErr.takeError(); + RE.IsTargetThumbFunc = TargetIsLocalThumbFunc; + RelocationValueRef Value; if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) Value = *ValueOrErr; else return ValueOrErr.takeError(); + // If this is a branch from a thumb function (BR22) then make sure we mark + // the value as being a thumb stub: we don't want to mix it up with an ARM + // stub targeting the same function. + if (RE.RelType == MachO::ARM_THUMB_RELOC_BR22) + Value.IsStubThumb = TargetIsLocalThumbFunc; + if (RE.IsPCRel) - makeValueAddendPCRel(Value, RelI, 8); + makeValueAddendPCRel(Value, RelI, + (RE.RelType == MachO::ARM_THUMB_RELOC_BR22) ? 4 : 8); - if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) + if (RE.RelType == MachO::ARM_RELOC_BR24 || + RE.RelType == MachO::ARM_THUMB_RELOC_BR22) processBranchRelocation(RE, Value, Stubs); else { RE.Addend = Value.Offset; @@ -124,12 +193,30 @@ public: Value -= FinalAddress; // ARM PCRel relocations have an effective-PC offset of two instructions // (four bytes in Thumb mode, 8 bytes in ARM mode). - // FIXME: For now, assume ARM mode. - Value -= 8; + Value -= (RE.RelType == MachO::ARM_THUMB_RELOC_BR22) ? 4 : 8; } switch (RE.RelType) { + case MachO::ARM_THUMB_RELOC_BR22: { + Value += RE.Addend; + uint16_t HighInsn = readBytesUnaligned(LocalAddress, 2); + assert((HighInsn & 0xf800) == 0xf000 && + "Unrecognized thumb branch encoding (BR22 high bits)"); + HighInsn = (HighInsn & 0xf800) | ((Value >> 12) & 0x7ff); + + uint16_t LowInsn = readBytesUnaligned(LocalAddress + 2, 2); + assert((LowInsn & 0xf800) != 0xf8000 && + "Unrecognized thumb branch encoding (BR22 low bits)"); + LowInsn = (LowInsn & 0xf800) | ((Value >> 1) & 0x7ff); + + writeBytesUnaligned(HighInsn, LocalAddress, 2); + writeBytesUnaligned(LowInsn, LocalAddress + 2, 2); + break; + } + case MachO::ARM_RELOC_VANILLA: + if (RE.IsTargetThumbFunc) + Value |= 0x01; writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); break; case MachO::ARM_RELOC_BR24: { @@ -158,10 +245,19 @@ public: Value = SectionABase - SectionBBase + RE.Addend; if (RE.Size & 0x1) // :upper16: Value = (Value >> 16); + + bool IsThumb = RE.Size & 0x2; + Value &= 0xffff; uint32_t Insn = readBytesUnaligned(LocalAddress, 4); - Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff); + + if (IsThumb) + Insn = (Insn & 0x8f00fbf0) | ((Value & 0xf000) >> 12) | + ((Value & 0x0800) >> 1) | ((Value & 0x0700) << 20) | + ((Value & 0x00ff) << 16); + else + Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff); writeBytesUnaligned(Insn, LocalAddress, 4); break; } @@ -196,17 +292,26 @@ private: Addr = Section.getAddressWithOffset(i->second); } else { // Create a new stub function. + assert(Section.getStubOffset() % 4 == 0 && "Misaligned stub"); Stubs[Value] = Section.getStubOffset(); - uint8_t *StubTargetAddr = createStubFunction( - Section.getAddressWithOffset(Section.getStubOffset())); + uint32_t StubOpcode = 0; + if (RE.RelType == MachO::ARM_RELOC_BR24) + StubOpcode = 0xe51ff004; // ldr pc, [pc, #-4] + else if (RE.RelType == MachO::ARM_THUMB_RELOC_BR22) + StubOpcode = 0xf000f8df; // ldr pc, [pc] + else + llvm_unreachable("Unrecognized relocation"); + Addr = Section.getAddressWithOffset(Section.getStubOffset()); + writeBytesUnaligned(StubOpcode, Addr, 4); + uint8_t *StubTargetAddr = Addr + 4; RelocationEntry StubRE( RE.SectionID, StubTargetAddr - Section.getAddress(), MachO::GENERIC_RELOC_VANILLA, Value.Offset, false, 2); + StubRE.IsTargetThumbFunc = RE.IsTargetThumbFunc; if (Value.SymbolName) addRelocationForSymbol(StubRE, Value.SymbolName); else addRelocationForSection(StubRE, Value.SectionID); - Addr = Section.getAddressWithOffset(Section.getStubOffset()); Section.advanceStubOffset(getMaxStubSize()); } RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0, @@ -223,14 +328,12 @@ private: MachO::any_relocation_info RE = MachO.getRelocation(RelI->getRawDataRefImpl()); - // For a half-diff relocation the length bits actually record whether this // is a movw/movt, and whether this is arm or thumb. // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1). // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1). unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE); - if (HalfDiffKindBits & 0x2) - llvm_unreachable("Thumb not yet supported."); + bool IsThumb = HalfDiffKindBits & 0x2; SectionEntry &Section = Sections[SectionID]; uint32_t RelocType = MachO.getAnyRelocationType(RE); @@ -238,7 +341,14 @@ private: uint64_t Offset = RelI->getOffset(); uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); int64_t Immediate = readBytesUnaligned(LocalAddress, 4); // Copy the whole instruction out. - Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff); + + if (IsThumb) + Immediate = ((Immediate & 0x0000000f) << 12) | + ((Immediate & 0x00000400) << 1) | + ((Immediate & 0x70000000) >> 20) | + ((Immediate & 0x00ff0000) >> 16); + else + Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff); ++RelI; MachO::any_relocation_info RE2 = diff --git a/lib/ExecutionEngine/SectionMemoryManager.cpp b/lib/ExecutionEngine/SectionMemoryManager.cpp index 8904475f084f..2dc66a1502f8 100644 --- a/lib/ExecutionEngine/SectionMemoryManager.cpp +++ b/lib/ExecutionEngine/SectionMemoryManager.cpp @@ -25,28 +25,43 @@ uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size, StringRef SectionName, bool IsReadOnly) { if (IsReadOnly) - return allocateSection(RODataMem, Size, Alignment); - return allocateSection(RWDataMem, Size, Alignment); + return allocateSection(SectionMemoryManager::AllocationPurpose::ROData, + Size, Alignment); + return allocateSection(SectionMemoryManager::AllocationPurpose::RWData, Size, + Alignment); } uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) { - return allocateSection(CodeMem, Size, Alignment); + return allocateSection(SectionMemoryManager::AllocationPurpose::Code, Size, + Alignment); } -uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, - uintptr_t Size, - unsigned Alignment) { +uint8_t *SectionMemoryManager::allocateSection( + SectionMemoryManager::AllocationPurpose Purpose, uintptr_t Size, + unsigned Alignment) { if (!Alignment) Alignment = 16; assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power of two."); - uintptr_t RequiredSize = Alignment * ((Size + Alignment - 1)/Alignment + 1); + uintptr_t RequiredSize = Alignment * ((Size + Alignment - 1) / Alignment + 1); uintptr_t Addr = 0; + MemoryGroup &MemGroup = [&]() -> MemoryGroup & { + switch (Purpose) { + case AllocationPurpose::Code: + return CodeMem; + case AllocationPurpose::ROData: + return RODataMem; + case AllocationPurpose::RWData: + return RWDataMem; + } + llvm_unreachable("Unknown SectionMemoryManager::AllocationPurpose"); + }(); + // Look in the list of free memory regions and use a block there if one // is available. for (FreeMemBlock &FreeMB : MemGroup.FreeMem) { @@ -64,13 +79,16 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, // modify it rather than creating a new one FreeMB.PendingPrefixIndex = MemGroup.PendingMem.size() - 1; } else { - sys::MemoryBlock &PendingMB = MemGroup.PendingMem[FreeMB.PendingPrefixIndex]; - PendingMB = sys::MemoryBlock(PendingMB.base(), Addr + Size - (uintptr_t)PendingMB.base()); + sys::MemoryBlock &PendingMB = + MemGroup.PendingMem[FreeMB.PendingPrefixIndex]; + PendingMB = sys::MemoryBlock(PendingMB.base(), + Addr + Size - (uintptr_t)PendingMB.base()); } // Remember how much free space is now left in this block - FreeMB.Free = sys::MemoryBlock((void *)(Addr + Size), EndOfBlock - Addr - Size); - return (uint8_t*)Addr; + FreeMB.Free = + sys::MemoryBlock((void *)(Addr + Size), EndOfBlock - Addr - Size); + return (uint8_t *)Addr; } } @@ -84,11 +102,9 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, // FIXME: Initialize the Near member for each memory group to avoid // interleaving. std::error_code ec; - sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(RequiredSize, - &MemGroup.Near, - sys::Memory::MF_READ | - sys::Memory::MF_WRITE, - ec); + sys::MemoryBlock MB = MMapper.allocateMappedMemory( + Purpose, RequiredSize, &MemGroup.Near, + sys::Memory::MF_READ | sys::Memory::MF_WRITE, ec); if (ec) { // FIXME: Add error propagation to the interface. return nullptr; @@ -110,20 +126,19 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, // The allocateMappedMemory may allocate much more memory than we need. In // this case, we store the unused memory as a free memory block. - unsigned FreeSize = EndOfBlock-Addr-Size; + unsigned FreeSize = EndOfBlock - Addr - Size; if (FreeSize > 16) { FreeMemBlock FreeMB; - FreeMB.Free = sys::MemoryBlock((void*)(Addr + Size), FreeSize); + FreeMB.Free = sys::MemoryBlock((void *)(Addr + Size), FreeSize); FreeMB.PendingPrefixIndex = (unsigned)-1; MemGroup.FreeMem.push_back(FreeMB); } // Return aligned address - return (uint8_t*)Addr; + return (uint8_t *)Addr; } -bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg) -{ +bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg) { // FIXME: Should in-progress permissions be reverted if an error occurs? std::error_code ec; @@ -167,7 +182,8 @@ static sys::MemoryBlock trimBlockToPageSize(sys::MemoryBlock M) { TrimmedSize -= StartOverlap; TrimmedSize -= TrimmedSize % PageSize; - sys::MemoryBlock Trimmed((void *)((uintptr_t)M.base() + StartOverlap), TrimmedSize); + sys::MemoryBlock Trimmed((void *)((uintptr_t)M.base() + StartOverlap), + TrimmedSize); assert(((uintptr_t)Trimmed.base() % PageSize) == 0); assert((Trimmed.size() % PageSize) == 0); @@ -176,12 +192,11 @@ static sys::MemoryBlock trimBlockToPageSize(sys::MemoryBlock M) { return Trimmed; } - std::error_code SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup, unsigned Permissions) { for (sys::MemoryBlock &MB : MemGroup.PendingMem) - if (std::error_code EC = sys::Memory::protectMappedMemory(MB, Permissions)) + if (std::error_code EC = MMapper.protectMappedMemory(MB, Permissions)) return EC; MemGroup.PendingMem.clear(); @@ -211,8 +226,38 @@ void SectionMemoryManager::invalidateInstructionCache() { SectionMemoryManager::~SectionMemoryManager() { for (MemoryGroup *Group : {&CodeMem, &RWDataMem, &RODataMem}) { for (sys::MemoryBlock &Block : Group->AllocatedMem) - sys::Memory::releaseMappedMemory(Block); + MMapper.releaseMappedMemory(Block); } } +SectionMemoryManager::MemoryMapper::~MemoryMapper() {} + +namespace { +// Trivial implementation of SectionMemoryManager::MemoryMapper that just calls +// into sys::Memory. +class DefaultMMapper final : public SectionMemoryManager::MemoryMapper { +public: + sys::MemoryBlock + allocateMappedMemory(SectionMemoryManager::AllocationPurpose Purpose, + size_t NumBytes, const sys::MemoryBlock *const NearBlock, + unsigned Flags, std::error_code &EC) override { + return sys::Memory::allocateMappedMemory(NumBytes, NearBlock, Flags, EC); + } + + std::error_code protectMappedMemory(const sys::MemoryBlock &Block, + unsigned Flags) override { + return sys::Memory::protectMappedMemory(Block, Flags); + } + + std::error_code releaseMappedMemory(sys::MemoryBlock &M) override { + return sys::Memory::releaseMappedMemory(M); + } +}; + +DefaultMMapper DefaultMMapperInstance; +} // namespace + +SectionMemoryManager::SectionMemoryManager(MemoryMapper *MM) + : MMapper(MM ? *MM : DefaultMMapperInstance) {} + } // namespace llvm diff --git a/lib/ExecutionEngine/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp index 6e2973c04e5d..18dfa4e3c319 100644 --- a/lib/ExecutionEngine/TargetSelect.cpp +++ b/lib/ExecutionEngine/TargetSelect.cpp @@ -92,11 +92,11 @@ TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple, } // Allocate a target... - TargetMachine *Target = TheTarget->createTargetMachine(TheTriple.getTriple(), - MCPU, FeaturesStr, - Options, - RelocModel, CMModel, - OptLevel); + TargetMachine *Target = + TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, + Options, RelocModel, CMModel, OptLevel, + /*JIT*/ true); + Target->Options.EmulatedTLS = EmulatedTLS; assert(Target && "Could not allocate target machine!"); return Target; } |
