summaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/ExecutionEngine
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp2
-rw-r--r--lib/ExecutionEngine/ExecutionEngineBindings.cpp4
-rw-r--r--lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp2
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.cpp1
-rw-r--r--lib/ExecutionEngine/Orc/IndirectionUtils.cpp13
-rw-r--r--lib/ExecutionEngine/Orc/OrcABISupport.cpp3
-rw-r--r--lib/ExecutionEngine/Orc/OrcCBindings.cpp22
-rw-r--r--lib/ExecutionEngine/Orc/OrcCBindingsStack.h117
-rw-r--r--lib/ExecutionEngine/Orc/OrcError.cpp2
-rw-r--r--lib/ExecutionEngine/Orc/OrcMCJITReplacement.h16
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp8
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp78
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp187
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h4
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h38
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp4
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h3
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h24
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h36
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp11
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h142
-rw-r--r--lib/ExecutionEngine/SectionMemoryManager.cpp95
-rw-r--r--lib/ExecutionEngine/TargetSelect.cpp10
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;
}