diff options
author | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
commit | 60b571e49a90d38697b3aca23020d9da42fc7d7f (patch) | |
tree | 99351324c24d6cb146b6285b6caffa4d26fce188 /contrib/llvm/lib/ExecutionEngine | |
parent | bea1b22c7a9bce1dfdd73e6e5b65bc4752215180 (diff) | |
download | FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.zip FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.tar.gz |
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release:
MFC r309142 (by emaste):
Add WITH_LLD_AS_LD build knob
If set it installs LLD as /usr/bin/ld. LLD (as of version 3.9) is not
capable of linking the world and kernel, but can self-host and link many
substantial applications. GNU ld continues to be used for the world and
kernel build, regardless of how this knob is set.
It is on by default for arm64, and off for all other CPU architectures.
Sponsored by: The FreeBSD Foundation
MFC r310840:
Reapply 310775, now it also builds correctly if lldb is disabled:
Move llvm-objdump from CLANG_EXTRAS to installed by default
We currently install three tools from binutils 2.17.50: as, ld, and
objdump. Work is underway to migrate to a permissively-licensed
tool-chain, with one goal being the retirement of binutils 2.17.50.
LLVM's llvm-objdump is intended to be compatible with GNU objdump
although it is currently missing some options and may have formatting
differences. Enable it by default for testing and further investigation.
It may later be changed to install as /usr/bin/objdump, it becomes a
fully viable replacement.
Reviewed by: emaste
Differential Revision: https://reviews.freebsd.org/D8879
MFC r312855 (by emaste):
Rename LLD_AS_LD to LLD_IS_LD, for consistency with CLANG_IS_CC
Reported by: Dan McGregor <dan.mcgregor usask.ca>
MFC r313559 | glebius | 2017-02-10 18:34:48 +0100 (Fri, 10 Feb 2017) | 5 lines
Don't check struct rtentry on FreeBSD, it is an internal kernel structure.
On other systems it may be API structure for SIOCADDRT/SIOCDELRT.
Reviewed by: emaste, dim
MFC r314152 (by jkim):
Remove an assembler flag, which is redundant since r309124. The upstream
took care of it by introducing a macro NO_EXEC_STACK_DIRECTIVE.
http://llvm.org/viewvc/llvm-project?rev=273500&view=rev
Reviewed by: dim
MFC r314564:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
4.0.0 (branches/release_40 296509). The release will follow soon.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Also note that as of 4.0.0, lld should be able to link the base system
on amd64 and aarch64. See the WITH_LLD_IS_LLD setting in src.conf(5).
Though please be aware that this is work in progress.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/4.0.0/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Jan Beich, Antoine Brodin and Eric Fiselier for
their help.
Relnotes: yes
Exp-run: antoine
PR: 215969, 216008
MFC r314708:
For now, revert r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
This commit is the cause of excessive compile times on skein_block.c
(and possibly other files) during kernel builds on amd64.
We never saw the problematic behavior described in this upstream commit,
so for now it is better to revert it. An upstream bug has been filed
here: https://bugs.llvm.org/show_bug.cgi?id=32142
Reported by: mjg
MFC r314795:
Reapply r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
Pull in r296992 from upstream llvm trunk (by Sanjoy Das):
[SCEV] Decrease the recursion threshold for CompareValueComplexity
Fixes PR32142.
r287232 accidentally increased the recursion threshold for
CompareValueComplexity from 2 to 32. This change reverses that
change by introducing a separate flag for CompareValueComplexity's
threshold.
The latter revision fixes the excessive compile times for skein_block.c.
MFC r314907 | mmel | 2017-03-08 12:40:27 +0100 (Wed, 08 Mar 2017) | 7 lines
Unbreak ARMv6 world.
The new compiler_rt library imported with clang 4.0.0 have several fatal
issues (non-functional __udivsi3 for example) with ARM specific instrict
functions. As temporary workaround, until upstream solve these problems,
disable all thumb[1][2] related feature.
MFC r315016:
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release.
We were already very close to the last release candidate, so this is a
pretty minor update.
Relnotes: yes
MFC r316005:
Revert r314907, and pull in r298713 from upstream compiler-rt trunk (by
Weiming Zhao):
builtins: Select correct code fragments when compiling for Thumb1/Thum2/ARM ISA.
Summary:
Value of __ARM_ARCH_ISA_THUMB isn't based on the actual compilation
mode (-mthumb, -marm), it reflect's capability of given CPU.
Due to this:
- use __tbumb__ and __thumb2__ insteand of __ARM_ARCH_ISA_THUMB
- use '.thumb' directive consistently in all affected files
- decorate all thumb functions using
DEFINE_COMPILERRT_THUMB_FUNCTION()
---------
Note: This patch doesn't fix broken Thumb1 variant of __udivsi3 !
Reviewers: weimingz, rengolin, compnerd
Subscribers: aemerson, dim
Differential Revision: https://reviews.llvm.org/D30938
Discussed with: mmel
Diffstat (limited to 'contrib/llvm/lib/ExecutionEngine')
38 files changed, 889 insertions, 663 deletions
diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp index a8e68bf..b4bed32 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -48,12 +49,13 @@ STATISTIC(NumGlobals , "Number of global vars initialized"); ExecutionEngine *(*ExecutionEngine::MCJITCtor)( std::unique_ptr<Module> M, std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr, - std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + + std::shared_ptr<JITSymbolResolver> Resolver, std::unique_ptr<TargetMachine> TM) = nullptr; ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)( std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr, - std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + std::shared_ptr<JITSymbolResolver> Resolver, std::unique_ptr<TargetMachine> TM) = nullptr; ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M, @@ -61,6 +63,8 @@ ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M, void JITEventListener::anchor() {} +void ObjectCache::anchor() {} + void ExecutionEngine::Init(std::unique_ptr<Module> M) { CompilingLazily = false; GVCompilationDisabled = false; @@ -151,7 +155,7 @@ bool ExecutionEngine::removeModule(Module *M) { return false; } -Function *ExecutionEngine::FindFunctionNamed(const char *FnName) { +Function *ExecutionEngine::FindFunctionNamed(StringRef FnName) { for (unsigned i = 0, e = Modules.size(); i != e; ++i) { Function *F = Modules[i]->getFunction(FnName); if (F && !F->isDeclaration()) @@ -160,7 +164,7 @@ Function *ExecutionEngine::FindFunctionNamed(const char *FnName) { return nullptr; } -GlobalVariable *ExecutionEngine::FindGlobalVariableNamed(const char *Name, bool AllowInternal) { +GlobalVariable *ExecutionEngine::FindGlobalVariableNamed(StringRef Name, bool AllowInternal) { for (unsigned i = 0, e = Modules.size(); i != e; ++i) { GlobalVariable *GV = Modules[i]->getGlobalVariable(Name,AllowInternal); if (GV && !GV->isDeclaration()) @@ -366,7 +370,7 @@ void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE, void ExecutionEngine::runStaticConstructorsDestructors(Module &module, bool isDtors) { - const char *Name = isDtors ? "llvm.global_dtors" : "llvm.global_ctors"; + StringRef Name(isDtors ? "llvm.global_dtors" : "llvm.global_ctors"); GlobalVariable *GV = module.getNamedGlobal(Name); // If this global has internal linkage, or if it has a use, then it must be @@ -499,8 +503,8 @@ EngineBuilder::setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM) { } EngineBuilder& -EngineBuilder::setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR) { - Resolver = std::shared_ptr<RuntimeDyld::SymbolResolver>(std::move(SR)); +EngineBuilder::setSymbolResolver(std::unique_ptr<JITSymbolResolver> SR) { + Resolver = std::shared_ptr<JITSymbolResolver>(std::move(SR)); return *this; } @@ -688,7 +692,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { else if (CE->getType()->isDoubleTy()) GV.DoubleVal = GV.IntVal.roundToDouble(); else if (CE->getType()->isX86_FP80Ty()) { - APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended); + APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended()); (void)apf.convertFromAPInt(GV.IntVal, false, APFloat::rmNearestTiesToEven); @@ -703,7 +707,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { else if (CE->getType()->isDoubleTy()) GV.DoubleVal = GV.IntVal.signedRoundToDouble(); else if (CE->getType()->isX86_FP80Ty()) { - APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended); + APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended()); (void)apf.convertFromAPInt(GV.IntVal, true, APFloat::rmNearestTiesToEven); @@ -720,7 +724,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { else if (Op0->getType()->isDoubleTy()) GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth); else if (Op0->getType()->isX86_FP80Ty()) { - APFloat apf = APFloat(APFloat::x87DoubleExtended, GV.IntVal); + APFloat apf = APFloat(APFloat::x87DoubleExtended(), GV.IntVal); uint64_t v; bool ignored; (void)apf.convertToInteger(&v, BitWidth, diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp index d6b209a..1d7c6e7 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -187,7 +187,7 @@ LLVMBool LLVMCreateMCJITCompilerForModule( // NoFramePointerElim. for (auto &F : *Mod) { auto Attrs = F.getAttributes(); - auto Value = options.NoFramePointerElim ? "true" : "false"; + StringRef Value(options.NoFramePointerElim ? "true" : "false"); Attrs = Attrs.addAttribute(F.getContext(), AttributeSet::FunctionIndex, "no-frame-pointer-elim", Value); F.setAttributes(Attrs); diff --git a/contrib/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp b/contrib/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp index 1ab6203..dad099d 100644 --- a/contrib/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp +++ b/contrib/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp @@ -69,16 +69,6 @@ struct RegisteredObjectInfo { OwningBinary<ObjectFile> Obj) : Size(Size), Entry(Entry), Obj(std::move(Obj)) {} - RegisteredObjectInfo(RegisteredObjectInfo &&Other) - : Size(Other.Size), Entry(Other.Entry), Obj(std::move(Other.Obj)) {} - - RegisteredObjectInfo& operator=(RegisteredObjectInfo &&Other) { - Size = Other.Size; - Entry = Other.Entry; - Obj = std::move(Other.Obj); - return *this; - } - std::size_t Size; jit_code_entry *Entry; OwningBinary<ObjectFile> Obj; diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp index 1eb4f7d..923f6e7 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -999,7 +999,7 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, uint64_t Total = 0; for (; I != E; ++I) { - if (StructType *STy = dyn_cast<StructType>(*I)) { + if (StructType *STy = I.getStructTypeOrNull()) { const StructLayout *SLO = getDataLayout().getStructLayout(STy); const ConstantInt *CPU = cast<ConstantInt>(I.getOperand()); @@ -1007,7 +1007,6 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, Total += SLO->getElementOffset(Index); } else { - SequentialType *ST = cast<SequentialType>(*I); // Get the index number for the array... which must be long type... GenericValue IdxGV = getOperandValue(I.getOperand(), SF); @@ -1020,7 +1019,7 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, assert(BitWidth == 64 && "Invalid index type for getelementptr"); Idx = (int64_t)IdxGV.IntVal.getZExtValue(); } - Total += getDataLayout().getTypeAllocSize(ST->getElementType()) * Idx; + Total += getDataLayout().getTypeAllocSize(I.getIndexedType()) * Idx; } } diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp index 441f0eb..ee75bee 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -20,20 +20,31 @@ //===----------------------------------------------------------------------===// #include "Interpreter.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Config/config.h" // Detect libffi +#include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Module.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/UniqueLock.h" +#include <cassert> #include <cmath> #include <csignal> +#include <cstdint> #include <cstdio> #include <cstring> #include <map> +#include <string> +#include <utility> +#include <vector> #ifdef HAVE_FFI_CALL #ifdef HAVE_FFI_H @@ -290,7 +301,6 @@ GenericValue Interpreter::callExternalFunction(Function *F, return GenericValue(); } - //===----------------------------------------------------------------------===// // Functions "exported" to the running application... // @@ -331,7 +341,7 @@ static GenericValue lle_X_sprintf(FunctionType *FT, // close enough for now. GenericValue GV; GV.IntVal = APInt(32, strlen(FmtStr)); - while (1) { + while (true) { switch (*FmtStr) { case 0: return GV; // Null terminator... default: // Normal nonspecial character diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp index bc7da2e..9818adf 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp @@ -35,9 +35,13 @@ extern "C" void LLVMLinkInInterpreter() { } ExecutionEngine *Interpreter::create(std::unique_ptr<Module> M, std::string *ErrStr) { // Tell this Module to materialize everything and release the GVMaterializer. - if (std::error_code EC = M->materializeAll()) { + if (Error Err = M->materializeAll()) { + std::string Msg; + handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { + Msg = EIB.message(); + }); if (ErrStr) - *ErrStr = EC.message(); + *ErrStr = Msg; // We got an error, just return 0 return nullptr; } diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h index 2e5a867..5c16448 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -41,12 +41,9 @@ class AllocaHolder { public: AllocaHolder() {} - // Make this type move-only. Define explicit move special members for MSVC. - AllocaHolder(AllocaHolder &&RHS) : Allocations(std::move(RHS.Allocations)) {} - AllocaHolder &operator=(AllocaHolder &&RHS) { - Allocations = std::move(RHS.Allocations); - return *this; - } + // Make this type move-only. + AllocaHolder(AllocaHolder &&) = default; + AllocaHolder &operator=(AllocaHolder &&RHS) = default; ~AllocaHolder() { for (void *Allocation : Allocations) @@ -72,22 +69,6 @@ struct ExecutionContext { AllocaHolder Allocas; // Track memory allocated by alloca ExecutionContext() : CurFunction(nullptr), CurBB(nullptr), CurInst(nullptr) {} - - ExecutionContext(ExecutionContext &&O) - : CurFunction(O.CurFunction), CurBB(O.CurBB), CurInst(O.CurInst), - Caller(O.Caller), Values(std::move(O.Values)), - VarArgs(std::move(O.VarArgs)), Allocas(std::move(O.Allocas)) {} - - ExecutionContext &operator=(ExecutionContext &&O) { - CurFunction = O.CurFunction; - CurBB = O.CurBB; - CurInst = O.CurInst; - Caller = O.Caller; - Values = std::move(O.Values); - VarArgs = std::move(O.VarArgs); - Allocas = std::move(O.Allocas); - return *this; - } }; // Interpreter - This class represents the entirety of the interpreter. diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 7fb328b..ff8749f 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -29,8 +29,6 @@ using namespace llvm; -void ObjectCache::anchor() {} - namespace { static struct RegisterJIT { @@ -46,7 +44,7 @@ ExecutionEngine* MCJIT::createJIT(std::unique_ptr<Module> M, std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr, - std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + std::shared_ptr<JITSymbolResolver> Resolver, std::unique_ptr<TargetMachine> TM) { // Try to register the program as a source of symbols to resolve against. // @@ -67,7 +65,7 @@ MCJIT::createJIT(std::unique_ptr<Module> M, MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> TM, std::shared_ptr<MCJITMemoryManager> MemMgr, - std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver) + std::shared_ptr<JITSymbolResolver> Resolver) : ExecutionEngine(TM->createDataLayout(), std::move(M)), TM(std::move(TM)), Ctx(nullptr), MemMgr(std::move(MemMgr)), Resolver(*this, std::move(Resolver)), Dyld(*this->MemMgr, this->Resolver), @@ -276,20 +274,21 @@ void MCJIT::finalizeModule(Module *M) { finalizeLoadedModules(); } -RuntimeDyld::SymbolInfo MCJIT::findExistingSymbol(const std::string &Name) { - SmallString<128> FullName; - Mangler::getNameWithPrefix(FullName, Name, getDataLayout()); - - if (void *Addr = getPointerToGlobalIfAvailable(FullName)) - return RuntimeDyld::SymbolInfo(static_cast<uint64_t>( - reinterpret_cast<uintptr_t>(Addr)), - JITSymbolFlags::Exported); +JITSymbol MCJIT::findExistingSymbol(const std::string &Name) { + if (void *Addr = getPointerToGlobalIfAvailable(Name)) + return JITSymbol(static_cast<uint64_t>( + reinterpret_cast<uintptr_t>(Addr)), + JITSymbolFlags::Exported); - return Dyld.getSymbol(FullName); + return Dyld.getSymbol(Name); } Module *MCJIT::findModuleForSymbol(const std::string &Name, bool CheckFunctionsOnly) { + StringRef DemangledName = Name; + if (DemangledName[0] == getDataLayout().getGlobalPrefix()) + DemangledName = DemangledName.substr(1); + MutexGuard locked(lock); // If it hasn't already been generated, see if it's in one of our modules. @@ -297,11 +296,11 @@ Module *MCJIT::findModuleForSymbol(const std::string &Name, E = OwnedModules.end_added(); I != E; ++I) { Module *M = *I; - Function *F = M->getFunction(Name); + Function *F = M->getFunction(DemangledName); if (F && !F->isDeclaration()) return M; if (!CheckFunctionsOnly) { - GlobalVariable *G = M->getGlobalVariable(Name); + GlobalVariable *G = M->getGlobalVariable(DemangledName); if (G && !G->isDeclaration()) return M; // FIXME: Do we need to worry about global aliases? @@ -313,11 +312,16 @@ Module *MCJIT::findModuleForSymbol(const std::string &Name, uint64_t MCJIT::getSymbolAddress(const std::string &Name, bool CheckFunctionsOnly) { - return findSymbol(Name, CheckFunctionsOnly).getAddress(); + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, getDataLayout()); + } + return findSymbol(MangledName, CheckFunctionsOnly).getAddress(); } -RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name, - bool CheckFunctionsOnly) { +JITSymbol MCJIT::findSymbol(const std::string &Name, + bool CheckFunctionsOnly) { MutexGuard locked(lock); // First, check to see if we already have this symbol. @@ -367,7 +371,7 @@ RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name, if (LazyFunctionCreator) { auto Addr = static_cast<uint64_t>( reinterpret_cast<uintptr_t>(LazyFunctionCreator(Name))); - return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported); + return JITSymbol(Addr, JITSymbolFlags::Exported); } return nullptr; @@ -442,7 +446,7 @@ void MCJIT::runStaticConstructorsDestructors(bool isDtors) { isDtors, OwnedModules.begin_finalized(), OwnedModules.end_finalized()); } -Function *MCJIT::FindFunctionNamedInModulePtrSet(const char *FnName, +Function *MCJIT::FindFunctionNamedInModulePtrSet(StringRef FnName, ModulePtrSet::iterator I, ModulePtrSet::iterator E) { for (; I != E; ++I) { @@ -453,7 +457,7 @@ Function *MCJIT::FindFunctionNamedInModulePtrSet(const char *FnName, return nullptr; } -GlobalVariable *MCJIT::FindGlobalVariableNamedInModulePtrSet(const char *Name, +GlobalVariable *MCJIT::FindGlobalVariableNamedInModulePtrSet(StringRef Name, bool AllowInternal, ModulePtrSet::iterator I, ModulePtrSet::iterator E) { @@ -466,7 +470,7 @@ GlobalVariable *MCJIT::FindGlobalVariableNamedInModulePtrSet(const char *Name, } -Function *MCJIT::FindFunctionNamed(const char *FnName) { +Function *MCJIT::FindFunctionNamed(StringRef FnName) { Function *F = FindFunctionNamedInModulePtrSet( FnName, OwnedModules.begin_added(), OwnedModules.end_added()); if (!F) @@ -478,7 +482,7 @@ Function *MCJIT::FindFunctionNamed(const char *FnName) { return F; } -GlobalVariable *MCJIT::FindGlobalVariableNamed(const char *Name, bool AllowInternal) { +GlobalVariable *MCJIT::FindGlobalVariableNamed(StringRef Name, bool AllowInternal) { GlobalVariable *GV = FindGlobalVariableNamedInModulePtrSet( Name, AllowInternal, OwnedModules.begin_added(), OwnedModules.end_added()); if (!GV) @@ -587,7 +591,10 @@ GenericValue MCJIT::runFunction(Function *F, ArrayRef<GenericValue> ArgValues) { } } - llvm_unreachable("Full-featured argument passing not supported yet!"); + report_fatal_error("MCJIT::runFunction does not support full-featured " + "argument passing. Please use " + "ExecutionEngine::getFunctionAddress and cast the result " + "to the desired function pointer type."); } void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) { @@ -622,7 +629,7 @@ void MCJIT::UnregisterJITEventListener(JITEventListener *L) { if (!L) return; MutexGuard locked(lock); - auto I = std::find(EventListeners.rbegin(), EventListeners.rend(), L); + auto I = find(reverse(EventListeners), L); if (I != EventListeners.rend()) { std::swap(*I, EventListeners.back()); EventListeners.pop_back(); @@ -644,13 +651,9 @@ void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) { L->NotifyFreeingObject(Obj); } -RuntimeDyld::SymbolInfo +JITSymbol LinkingSymbolResolver::findSymbol(const std::string &Name) { auto Result = ParentEngine.findSymbol(Name, false); - // If the symbols wasn't found and it begins with an underscore, try again - // without the underscore. - if (!Result && Name[0] == '_') - Result = ParentEngine.findSymbol(Name.substr(1), false); if (Result) return Result; if (ParentEngine.isSymbolSearchingDisabled()) diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h index e25f76c..daf578f 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -26,23 +26,22 @@ class MCJIT; // functions across modules that it owns. It aggregates the memory manager // that is passed in to the MCJIT constructor and defers most functionality // to that object. -class LinkingSymbolResolver : public RuntimeDyld::SymbolResolver { +class LinkingSymbolResolver : public JITSymbolResolver { public: LinkingSymbolResolver(MCJIT &Parent, - std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver) + std::shared_ptr<JITSymbolResolver> Resolver) : ParentEngine(Parent), ClientResolver(std::move(Resolver)) {} - RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override; + JITSymbol findSymbol(const std::string &Name) override; // MCJIT doesn't support logical dylibs. - RuntimeDyld::SymbolInfo - findSymbolInLogicalDylib(const std::string &Name) override { + JITSymbol findSymbolInLogicalDylib(const std::string &Name) override { return nullptr; } private: MCJIT &ParentEngine; - std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver; + std::shared_ptr<JITSymbolResolver> ClientResolver; }; // About Module states: added->loaded->finalized. @@ -68,7 +67,7 @@ private: class MCJIT : public ExecutionEngine { MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm, std::shared_ptr<MCJITMemoryManager> MemMgr, - std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver); + std::shared_ptr<JITSymbolResolver> Resolver); typedef llvm::SmallPtrSet<Module *, 4> ModulePtrSet; @@ -195,11 +194,11 @@ class MCJIT : public ExecutionEngine { // perform lookup of pre-compiled code to avoid re-compilation. ObjectCache *ObjCache; - Function *FindFunctionNamedInModulePtrSet(const char *FnName, + Function *FindFunctionNamedInModulePtrSet(StringRef FnName, ModulePtrSet::iterator I, ModulePtrSet::iterator E); - GlobalVariable *FindGlobalVariableNamedInModulePtrSet(const char *Name, + GlobalVariable *FindGlobalVariableNamedInModulePtrSet(StringRef Name, bool AllowInternal, ModulePtrSet::iterator I, ModulePtrSet::iterator E); @@ -222,12 +221,12 @@ public: /// FindFunctionNamed - Search all of the active modules to find the function that /// defines FnName. This is very slow operation and shouldn't be used for /// general code. - Function *FindFunctionNamed(const char *FnName) override; + Function *FindFunctionNamed(StringRef FnName) override; /// FindGlobalVariableNamed - Search all of the active modules to find the /// global variable that defines Name. This is very slow operation and /// shouldn't be used for general code. - GlobalVariable *FindGlobalVariableNamed(const char *Name, + GlobalVariable *FindGlobalVariableNamed(StringRef Name, bool AllowInternal = false) override; /// Sets the object manager that MCJIT should use to avoid compilation. @@ -305,16 +304,22 @@ public: createJIT(std::unique_ptr<Module> M, std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr, - std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + std::shared_ptr<JITSymbolResolver> Resolver, std::unique_ptr<TargetMachine> TM); // @} - RuntimeDyld::SymbolInfo findSymbol(const std::string &Name, - bool CheckFunctionsOnly); + // Takes a mangled name and returns the corresponding JITSymbol (if a + // definition of that mangled name has been added to the JIT). + JITSymbol findSymbol(const std::string &Name, bool CheckFunctionsOnly); + // DEPRECATED - Please use findSymbol instead. + // // This is not directly exposed via the ExecutionEngine API, but it is // used by the LinkingMemoryManager. + // + // getSymbolAddress takes an unmangled name and returns the corresponding + // JITSymbol if a definition of the name has been added to the JIT. uint64_t getSymbolAddress(const std::string &Name, bool CheckFunctionsOnly); @@ -330,9 +335,8 @@ protected: const RuntimeDyld::LoadedObjectInfo &L); void NotifyFreeingObject(const object::ObjectFile& Obj); - RuntimeDyld::SymbolInfo findExistingSymbol(const std::string &Name); - Module *findModuleForSymbol(const std::string &Name, - bool CheckFunctionsOnly); + JITSymbol findExistingSymbol(const std::string &Name); + Module *findModuleForSymbol(const std::string &Name, bool CheckFunctionsOnly); }; } // end llvm namespace diff --git a/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp b/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp index 324d071..57b5d85 100644 --- a/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp +++ b/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp @@ -88,15 +88,15 @@ void OProfileJITEventListener::NotifyObjectEmitted( // Use symbol info to iterate functions in the object. for (const std::pair<SymbolRef, uint64_t> &P : computeSymbolSizes(DebugObj)) { SymbolRef Sym = P.first; - if (Sym.getType() != SymbolRef::ST_Function) + if (!Sym.getType() || *Sym.getType() != SymbolRef::ST_Function) continue; - ErrorOr<StringRef> NameOrErr = Sym.getName(); - if (NameOrErr.getError()) + Expected<StringRef> NameOrErr = Sym.getName(); + if (!NameOrErr) continue; StringRef Name = *NameOrErr; - ErrorOr<uint64_t> AddrOrErr = Sym.getAddress(); - if (AddrOrErr.getError()) + Expected<uint64_t> AddrOrErr = Sym.getAddress(); + if (!AddrOrErr) continue; uint64_t Addr = *AddrOrErr; uint64_t Size = P.second; @@ -128,9 +128,9 @@ void OProfileJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { for (symbol_iterator I = DebugObj.symbol_begin(), E = DebugObj.symbol_end(); I != E; ++I) { - if (I->getType() == SymbolRef::ST_Function) { - ErrorOr<uint64_t> AddrOrErr = I->getAddress(); - if (AddrOrErr.getError()) + if (I->getType() && *I->getType() == SymbolRef::ST_Function) { + Expected<uint64_t> AddrOrErr = I->getAddress(); + if (!AddrOrErr) continue; uint64_t Addr = *AddrOrErr; diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/contrib/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index 6f7c29f..711b887 100644 --- a/contrib/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -24,7 +24,7 @@ void IndirectStubsManager::anchor() {} std::unique_ptr<JITCompileCallbackManager> createLocalCompileCallbackManager(const Triple &T, - TargetAddress ErrorHandlerAddress) { + JITTargetAddress ErrorHandlerAddress) { switch (T.getArch()) { default: return nullptr; @@ -71,7 +71,7 @@ createLocalIndirectStubsManagerBuilder(const Triple &T) { } } -Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr) { +Constant* createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr) { Constant *AddrIntVal = ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr); Constant *AddrPtrVal = @@ -241,5 +241,14 @@ GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA, return NewA; } +void cloneModuleFlagsMetadata(Module &Dst, const Module &Src, + ValueToValueMapTy &VMap) { + auto *MFs = Src.getModuleFlagsMetadata(); + if (!MFs) + return; + for (auto *MF : MFs->operands()) + Dst.addModuleFlag(MapMetadata(MF, VMap)); +} + } // End namespace orc. } // End namespace llvm. diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp b/contrib/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp index 57666a9..8f2d6fd 100644 --- a/contrib/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp @@ -14,12 +14,11 @@ namespace llvm { namespace orc { -RuntimeDyld::SymbolInfo NullResolver::findSymbol(const std::string &Name) { +JITSymbol NullResolver::findSymbol(const std::string &Name) { llvm_unreachable("Unexpected cross-object symbol reference"); } -RuntimeDyld::SymbolInfo -NullResolver::findSymbolInLogicalDylib(const std::string &Name) { +JITSymbol NullResolver::findSymbolInLogicalDylib(const std::string &Name) { llvm_unreachable("Unexpected cross-object symbol reference"); } diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/contrib/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index 9ae9b20..a74fae7 100644 --- a/contrib/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/contrib/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -44,8 +44,8 @@ private: class GenericHandle { public: virtual ~GenericHandle() {} - virtual orc::JITSymbol findSymbolIn(const std::string &Name, - bool ExportedSymbolsOnly) = 0; + virtual JITSymbol findSymbolIn(const std::string &Name, + bool ExportedSymbolsOnly) = 0; virtual void removeModule() = 0; }; @@ -54,8 +54,8 @@ private: GenericHandleImpl(LayerT &Layer, typename LayerT::ModuleSetHandleT Handle) : Layer(Layer), Handle(std::move(Handle)) {} - orc::JITSymbol findSymbolIn(const std::string &Name, - bool ExportedSymbolsOnly) override { + JITSymbol findSymbolIn(const std::string &Name, + bool ExportedSymbolsOnly) override { return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly); } @@ -109,55 +109,56 @@ public: } template <typename PtrTy> - static PtrTy fromTargetAddress(orc::TargetAddress Addr) { + static PtrTy fromTargetAddress(JITTargetAddress Addr) { return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr)); } - orc::TargetAddress + JITTargetAddress createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx) { auto CCInfo = CCMgr->getCompileCallback(); - CCInfo.setCompileAction([=]() -> orc::TargetAddress { + CCInfo.setCompileAction([=]() -> JITTargetAddress { return Callback(wrap(this), CallbackCtx); }); return CCInfo.getAddress(); } LLVMOrcErrorCode createIndirectStub(StringRef StubName, - orc::TargetAddress Addr) { + JITTargetAddress Addr) { return mapError( IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported)); } LLVMOrcErrorCode setIndirectStubPointer(StringRef Name, - orc::TargetAddress Addr) { + JITTargetAddress Addr) { return mapError(IndirectStubsMgr->updatePointer(Name, Addr)); } - std::unique_ptr<RuntimeDyld::SymbolResolver> + std::unique_ptr<JITSymbolResolver> createResolver(LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx) { return orc::createLambdaResolver( - [this, ExternalResolver, ExternalResolverCtx](const std::string &Name) { + [this, ExternalResolver, ExternalResolverCtx](const std::string &Name) + -> JITSymbol { // Search order: // 1. JIT'd symbols. // 2. Runtime overrides. // 3. External resolver (if present). if (auto Sym = CODLayer.findSymbol(Name, true)) - return Sym.toRuntimeDyldSymbol(); + return Sym; if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) return Sym; if (ExternalResolver) - return RuntimeDyld::SymbolInfo( + return JITSymbol( ExternalResolver(Name.c_str(), ExternalResolverCtx), llvm::JITSymbolFlags::Exported); - return RuntimeDyld::SymbolInfo(nullptr); + return JITSymbol(nullptr); }, [](const std::string &Name) { - return RuntimeDyld::SymbolInfo(nullptr); + return JITSymbol(nullptr); }); } @@ -222,14 +223,14 @@ public: FreeHandleIndexes.push_back(H); } - orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly)) return Sym; return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly); } - orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, - bool ExportedSymbolsOnly) { + JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly); } diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/OrcError.cpp b/contrib/llvm/lib/ExecutionEngine/Orc/OrcError.cpp index 22f1303..c531fe3 100644 --- a/contrib/llvm/lib/ExecutionEngine/Orc/OrcError.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Orc/OrcError.cpp @@ -25,7 +25,7 @@ namespace { // deal with the Error value directly, rather than converting to error_code. class OrcErrorCategory : public std::error_category { public: - const char *name() const LLVM_NOEXCEPT override { return "orc"; } + const char *name() const noexcept override { return "orc"; } std::string message(int condition) const override { switch (static_cast<OrcErrorCode>(condition)) { @@ -39,10 +39,14 @@ public: return "Remote indirect stubs owner does not exist"; case OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse: return "Remote indirect stubs owner Id already in use"; + case OrcErrorCode::RPCResponseAbandoned: + return "RPC response abandoned"; case OrcErrorCode::UnexpectedRPCCall: return "Unexpected RPC call"; case OrcErrorCode::UnexpectedRPCResponse: return "Unexpected RPC response"; + case OrcErrorCode::UnknownRPCFunction: + return "Unknown RPC function"; } llvm_unreachable("Unhandled error code"); } diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index d108307..af70960 100644 --- a/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -14,18 +14,40 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Mangler.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <algorithm> +#include <map> +#include <memory> +#include <set> +#include <string> +#include <vector> namespace llvm { namespace orc { class OrcMCJITReplacement : public ExecutionEngine { - // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are // expecting - see finalizeMemory. @@ -111,17 +133,18 @@ class OrcMCJITReplacement : public ExecutionEngine { std::shared_ptr<MCJITMemoryManager> ClientMM; }; - class LinkingResolver : public RuntimeDyld::SymbolResolver { + class LinkingResolver : public JITSymbolResolver { public: LinkingResolver(OrcMCJITReplacement &M) : M(M) {} - RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override { - return M.findMangledSymbol(Name); + JITSymbol findSymbol(const std::string &Name) override { + return M.ClientResolver->findSymbol(Name); } - RuntimeDyld::SymbolInfo - findSymbolInLogicalDylib(const std::string &Name) override { - return M.ClientResolver->findSymbol(Name); + JITSymbol findSymbolInLogicalDylib(const std::string &Name) override { + if (auto Sym = M.findMangledSymbol(Name)) + return Sym; + return M.ClientResolver->findSymbolInLogicalDylib(Name); } private: @@ -133,7 +156,7 @@ private: static ExecutionEngine * createOrcMCJITReplacement(std::string *ErrorMsg, std::shared_ptr<MCJITMemoryManager> MemMgr, - std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + std::shared_ptr<JITSymbolResolver> Resolver, std::unique_ptr<TargetMachine> TM) { return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver), std::move(TM)); @@ -146,7 +169,7 @@ public: OrcMCJITReplacement( std::shared_ptr<MCJITMemoryManager> MemMgr, - std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver, + std::shared_ptr<JITSymbolResolver> ClientResolver, std::unique_ptr<TargetMachine> TM) : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)), MemMgr(*this, std::move(MemMgr)), Resolver(*this), @@ -193,7 +216,7 @@ public: return findSymbol(Name).getAddress(); } - RuntimeDyld::SymbolInfo findSymbol(StringRef Name) { + JITSymbol findSymbol(StringRef Name) { return findMangledSymbol(Mangle(Name)); } @@ -242,14 +265,13 @@ public: } private: - - RuntimeDyld::SymbolInfo findMangledSymbol(StringRef Name) { + JITSymbol findMangledSymbol(StringRef Name) { if (auto Sym = LazyEmitLayer.findSymbol(Name, false)) - return Sym.toRuntimeDyldSymbol(); + return Sym; if (auto Sym = ClientResolver->findSymbol(Name)) return Sym; if (auto Sym = scanArchives(Name)) - return Sym.toRuntimeDyldSymbol(); + return Sym; return nullptr; } @@ -305,7 +327,6 @@ private: } private: - static const object::ObjectFile& getObject(const object::ObjectFile &Obj) { return Obj; } @@ -322,6 +343,7 @@ private: class NotifyFinalizedT { public: NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {} + void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) { M.UnfinalizedSections.erase(H); } @@ -346,7 +368,7 @@ private: std::unique_ptr<TargetMachine> TM; MCJITReplacementMemMgr MemMgr; LinkingResolver Resolver; - std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver; + std::shared_ptr<JITSymbolResolver> ClientResolver; Mangler Mang; NotifyObjectLoadedT NotifyObjectLoaded; @@ -373,7 +395,7 @@ private: std::vector<object::OwningBinary<object::Archive>> Archives; }; -} // End namespace orc. -} // End namespace llvm. +} // end namespace orc +} // end namespace llvm #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp b/contrib/llvm/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp deleted file mode 100644 index d1a021a..0000000 --- a/contrib/llvm/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp +++ /dev/null @@ -1,53 +0,0 @@ -//===------- OrcRemoteTargetRPCAPI.cpp - ORC Remote API utilities ---------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" - -namespace llvm { -namespace orc { -namespace remote { - -#define FUNCNAME(X) \ - case X ## Id: \ - return #X - -const char *OrcRemoteTargetRPCAPI::getJITFuncIdName(JITFuncId Id) { - switch (Id) { - case InvalidId: - return "*** Invalid JITFuncId ***"; - FUNCNAME(CallIntVoid); - FUNCNAME(CallMain); - FUNCNAME(CallVoidVoid); - FUNCNAME(CreateRemoteAllocator); - FUNCNAME(CreateIndirectStubsOwner); - FUNCNAME(DeregisterEHFrames); - FUNCNAME(DestroyRemoteAllocator); - FUNCNAME(DestroyIndirectStubsOwner); - FUNCNAME(EmitIndirectStubs); - FUNCNAME(EmitResolverBlock); - FUNCNAME(EmitTrampolineBlock); - FUNCNAME(GetSymbolAddress); - FUNCNAME(GetRemoteInfo); - FUNCNAME(ReadMem); - FUNCNAME(RegisterEHFrames); - FUNCNAME(ReserveMem); - FUNCNAME(RequestCompile); - FUNCNAME(SetProtections); - FUNCNAME(TerminateSession); - FUNCNAME(WriteMem); - FUNCNAME(WritePtr); - }; - return nullptr; -} - -#undef FUNCNAME - -} // end namespace remote -} // end namespace orc -} // end namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp new file mode 100644 index 0000000..8769dcf --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp @@ -0,0 +1,41 @@ +//===----------- JITSymbol.cpp - JITSymbol class implementation -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// JITSymbol class implementation plus helper functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/Object/SymbolicFile.h" + +using namespace llvm; + +JITSymbolFlags llvm::JITSymbolFlags::fromGlobalValue(const GlobalValue &GV) { + JITSymbolFlags Flags = JITSymbolFlags::None; + if (GV.hasWeakLinkage() || GV.hasLinkOnceLinkage()) + Flags |= JITSymbolFlags::Weak; + if (GV.hasCommonLinkage()) + Flags |= JITSymbolFlags::Common; + if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility()) + Flags |= JITSymbolFlags::Exported; + return Flags; +} + +JITSymbolFlags +llvm::JITSymbolFlags::fromObjectSymbol(const object::BasicSymbolRef &Symbol) { + JITSymbolFlags Flags = JITSymbolFlags::None; + if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak) + Flags |= JITSymbolFlags::Weak; + if (Symbol.getFlags() & object::BasicSymbolRef::SF_Common) + Flags |= JITSymbolFlags::Common; + if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported) + Flags |= JITSymbolFlags::Exported; + return Flags; +} diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp index e39acc7..de73fbd 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp @@ -97,7 +97,8 @@ static const char *processFDE(const char *Entry, bool isDeregister) { void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr, size_t Size) { // On OS X OS X __register_frame takes a single FDE as an argument. - // See http://lists.llvm.org/pipermail/llvm-dev/2013-April/061768.html + // See http://lists.llvm.org/pipermail/llvm-dev/2013-April/061737.html + // and projects/libunwind/src/UnwindLevel1-gcc-ext.c. const char *P = (const char *)Addr; const char *End = P + Size; do { diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 1dfbe31..63b56f7 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -39,7 +39,7 @@ enum RuntimeDyldErrorCode { // deal with the Error value directly, rather than converting to error_code. class RuntimeDyldErrorCategory : public std::error_category { public: - const char *name() const LLVM_NOEXCEPT override { return "runtimedyld"; } + const char *name() const noexcept override { return "runtimedyld"; } std::string message(int Condition) const override { switch (static_cast<RuntimeDyldErrorCode>(Condition)) { @@ -205,6 +205,10 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { ++I) { uint32_t Flags = I->getFlags(); + // Skip undefined symbols. + if (Flags & SymbolRef::SF_Undefined) + continue; + if (Flags & SymbolRef::SF_Common) CommonSymbols.push_back(*I); else { @@ -224,11 +228,25 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { return NameOrErr.takeError(); // Compute JIT symbol flags. - JITSymbolFlags RTDyldSymFlags = JITSymbolFlags::None; - if (Flags & SymbolRef::SF_Weak) - RTDyldSymFlags |= JITSymbolFlags::Weak; - if (Flags & SymbolRef::SF_Exported) - RTDyldSymFlags |= JITSymbolFlags::Exported; + JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(*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 + // definition will). If there's no strong definition, make this definition + // strong. + if (JITSymFlags.isWeak()) { + // First check whether there's already a definition in this instance. + // FIXME: Override existing weak definitions with strong ones. + if (GlobalSymbolTable.count(Name)) + continue; + // Then check the symbol resolver to see if there's a definition + // elsewhere in this logical dylib. + if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) + if (Sym.getFlags().isStrongDefinition()) + continue; + // else + JITSymFlags &= ~JITSymbolFlags::Weak; + } if (Flags & SymbolRef::SF_Absolute && SymType != object::SymbolRef::ST_File) { @@ -245,7 +263,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { << format("%p", (uintptr_t)Addr) << " flags: " << Flags << "\n"); GlobalSymbolTable[Name] = - SymbolTableEntry(SectionID, Addr, RTDyldSymFlags); + SymbolTableEntry(SectionID, Addr, JITSymFlags); } else if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown || @@ -278,7 +296,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { << format("%p", (uintptr_t)SectOffset) << " flags: " << Flags << "\n"); GlobalSymbolTable[Name] = - SymbolTableEntry(SectionID, SectOffset, RTDyldSymFlags); + SymbolTableEntry(SectionID, SectOffset, JITSymFlags); } } } @@ -584,13 +602,19 @@ Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, return NameOrErr.takeError(); // Skip common symbols already elsewhere. - if (GlobalSymbolTable.count(Name) || - Resolver.findSymbolInLogicalDylib(Name)) { + if (GlobalSymbolTable.count(Name)) { DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name << "'\n"); continue; } + if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) { + if (!Sym.getFlags().isCommon()) { + DEBUG(dbgs() << "\tSkipping common symbol '" << Name + << "' in favor of stronger definition.\n"); + continue; + } + } uint32_t Align = Sym.getAlignment(); uint64_t Size = Sym.getCommonSize(); @@ -628,16 +652,11 @@ Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, Addr += AlignOffset; Offset += AlignOffset; } - uint32_t Flags = Sym.getFlags(); - JITSymbolFlags RTDyldSymFlags = JITSymbolFlags::None; - if (Flags & SymbolRef::SF_Weak) - RTDyldSymFlags |= JITSymbolFlags::Weak; - if (Flags & SymbolRef::SF_Exported) - RTDyldSymFlags |= JITSymbolFlags::Exported; + JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(Sym); DEBUG(dbgs() << "Allocating common symbol " << Name << " address " << format("%p", Addr) << "\n"); GlobalSymbolTable[Name] = - SymbolTableEntry(SectionID, Offset, RTDyldSymFlags); + SymbolTableEntry(SectionID, Offset, JITSymFlags); Offset += Size; Addr += Size; } @@ -974,10 +993,10 @@ uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( } void RuntimeDyld::MemoryManager::anchor() {} -void RuntimeDyld::SymbolResolver::anchor() {} +void JITSymbolResolver::anchor() {} RuntimeDyld::RuntimeDyld(RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : MemMgr(MemMgr), Resolver(Resolver) { // FIXME: There's a potential issue lurking here if a single instance of // RuntimeDyld is used to load multiple objects. The current implementation @@ -994,8 +1013,8 @@ RuntimeDyld::~RuntimeDyld() {} static std::unique_ptr<RuntimeDyldCOFF> createRuntimeDyldCOFF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver, - bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { + JITSymbolResolver &Resolver, bool ProcessAllSections, + RuntimeDyldCheckerImpl *Checker) { std::unique_ptr<RuntimeDyldCOFF> Dyld = RuntimeDyldCOFF::create(Arch, MM, Resolver); Dyld->setProcessAllSections(ProcessAllSections); @@ -1004,10 +1023,11 @@ createRuntimeDyldCOFF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, } static std::unique_ptr<RuntimeDyldELF> -createRuntimeDyldELF(RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver, - bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { - std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM, Resolver)); +createRuntimeDyldELF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, + JITSymbolResolver &Resolver, bool ProcessAllSections, + RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr<RuntimeDyldELF> Dyld = + RuntimeDyldELF::create(Arch, MM, Resolver); Dyld->setProcessAllSections(ProcessAllSections); Dyld->setRuntimeDyldChecker(Checker); return Dyld; @@ -1015,7 +1035,7 @@ createRuntimeDyldELF(RuntimeDyld::MemoryManager &MM, static std::unique_ptr<RuntimeDyldMachO> createRuntimeDyldMachO(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver, + JITSymbolResolver &Resolver, bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { std::unique_ptr<RuntimeDyldMachO> Dyld = @@ -1029,7 +1049,9 @@ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> RuntimeDyld::loadObject(const ObjectFile &Obj) { if (!Dyld) { if (Obj.isELF()) - Dyld = createRuntimeDyldELF(MemMgr, Resolver, ProcessAllSections, Checker); + Dyld = + createRuntimeDyldELF(static_cast<Triple::ArchType>(Obj.getArch()), + MemMgr, Resolver, ProcessAllSections, Checker); else if (Obj.isMachO()) Dyld = createRuntimeDyldMachO( static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver, @@ -1056,7 +1078,7 @@ void *RuntimeDyld::getSymbolLocalAddress(StringRef Name) const { return Dyld->getSymbolLocalAddress(Name); } -RuntimeDyld::SymbolInfo RuntimeDyld::getSymbol(StringRef Name) const { +JITEvaluatedSymbol RuntimeDyld::getSymbol(StringRef Name) const { if (!Dyld) return nullptr; return Dyld->getSymbol(Name); diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp index 24bd9a0..1bd28ef 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -44,7 +44,7 @@ namespace llvm { std::unique_ptr<RuntimeDyldCOFF> llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver) { + JITSymbolResolver &Resolver) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF."); case Triple::x86: diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h index 03a91f6..729a358 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h @@ -33,11 +33,11 @@ public: static std::unique_ptr<RuntimeDyldCOFF> create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver); + JITSymbolResolver &Resolver); protected: RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldImpl(MemMgr, Resolver) {} uint64_t getSymbolOffset(const SymbolRef &Sym); }; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index 090b9a3..7bfa794 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -217,7 +217,7 @@ private: // given symbol and get the value of the requested operand. // Returns an error if the instruction cannot be decoded, or the requested // operand is not an immediate. - // On success, retuns a pair containing the value of the operand, plus + // On success, returns a pair containing the value of the operand, plus // the expression remaining to be evaluated. std::pair<EvalResult, StringRef> evalDecodeOperand(StringRef Expr) const { if (!Expr.startswith("(")) @@ -463,7 +463,7 @@ private: Expr.substr(FirstNonDigit)); } - // Evaluate a constant numeric expression (hexidecimal or decimal) and + // Evaluate a constant numeric expression (hexadecimal or decimal) and // return a pair containing the result, and the expression remaining to be // evaluated. std::pair<EvalResult, StringRef> evalNumberExpr(StringRef Expr) const { diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 9cbdb13..05615d3 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -13,6 +13,7 @@ #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" @@ -27,9 +28,34 @@ using namespace llvm; using namespace llvm::object; +using namespace llvm::support::endian; #define DEBUG_TYPE "dyld" +static void or32le(void *P, int32_t V) { write32le(P, read32le(P) | V); } + +static void or32AArch64Imm(void *L, uint64_t Imm) { + or32le(L, (Imm & 0xFFF) << 10); +} + +template <class T> static void write(bool isBE, void *P, T V) { + isBE ? write<T, support::big>(P, V) : write<T, support::little>(P, V); +} + +static void write32AArch64Addr(void *L, uint64_t Imm) { + uint32_t ImmLo = (Imm & 0x3) << 29; + uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; + uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); + write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi); +} + +// Return the bits [Start, End] from Val shifted Start bits. +// For instance, getBits(0xF0, 4, 8) returns 0xF. +static uint64_t getBits(uint64_t Val, int Start, int End) { + uint64_t Mask = ((uint64_t)1 << (End + 1 - Start)) - 1; + return (Val >> Start) & Mask; +} + namespace { template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> { @@ -184,7 +210,7 @@ LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { namespace llvm { RuntimeDyldELF::RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldImpl(MemMgr, Resolver), GOTSectionID(0), CurrentGOTIndex(0) {} RuntimeDyldELF::~RuntimeDyldELF() {} @@ -211,6 +237,21 @@ void RuntimeDyldELF::deregisterEHFrames() { RegisteredEHFrameSections.clear(); } +std::unique_ptr<RuntimeDyldELF> +llvm::RuntimeDyldELF::create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + JITSymbolResolver &Resolver) { + switch (Arch) { + default: + return make_unique<RuntimeDyldELF>(MemMgr, Resolver); + case Triple::mips: + case Triple::mipsel: + case Triple::mips64: + case Triple::mips64el: + return make_unique<RuntimeDyldELFMips>(MemMgr, Resolver); + } +} + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> RuntimeDyldELF::loadObject(const object::ObjectFile &O) { if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) @@ -309,6 +350,8 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, uint32_t *TargetPtr = reinterpret_cast<uint32_t *>(Section.getAddressWithOffset(Offset)); uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + // Data should use target endian. Code should always use little endian. + bool isBE = Arch == Triple::aarch64_be; DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x" << format("%llx", Section.getAddressWithOffset(Offset)) @@ -321,19 +364,19 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, default: llvm_unreachable("Relocation type not implemented yet!"); break; - case ELF::R_AARCH64_ABS64: { - uint64_t *TargetPtr = - reinterpret_cast<uint64_t *>(Section.getAddressWithOffset(Offset)); - *TargetPtr = Value + Addend; + case ELF::R_AARCH64_ABS64: + write(isBE, TargetPtr, Value + Addend); break; - } case ELF::R_AARCH64_PREL32: { uint64_t Result = Value + Addend - FinalAddress; assert(static_cast<int64_t>(Result) >= INT32_MIN && static_cast<int64_t>(Result) <= UINT32_MAX); - *TargetPtr = static_cast<uint32_t>(Result & 0xffffffffU); + write(isBE, TargetPtr, static_cast<uint32_t>(Result & 0xffffffffU)); break; } + case ELF::R_AARCH64_PREL64: + write(isBE, TargetPtr, Value + Addend - FinalAddress); + break; case ELF::R_AARCH64_CALL26: // fallthrough case ELF::R_AARCH64_JUMP26: { // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the @@ -342,62 +385,21 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // "Check that -2^27 <= result < 2^27". assert(isInt<28>(BranchImm)); - - // AArch64 code is emitted with .rela relocations. The data already in any - // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xfc000000U; - // Immediate goes in bits 25:0 of B and BL. - *TargetPtr |= static_cast<uint32_t>(BranchImm & 0xffffffcU) >> 2; + or32le(TargetPtr, (BranchImm & 0x0FFFFFFC) >> 2); break; } - case ELF::R_AARCH64_MOVW_UABS_G3: { - uint64_t Result = Value + Addend; - - // AArch64 code is emitted with .rela relocations. The data already in any - // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xffe0001fU; - // Immediate goes in bits 20:5 of MOVZ/MOVK instruction - *TargetPtr |= Result >> (48 - 5); - // Shift must be "lsl #48", in bits 22:21 - assert((*TargetPtr >> 21 & 0x3) == 3 && "invalid shift for relocation"); + case ELF::R_AARCH64_MOVW_UABS_G3: + or32le(TargetPtr, ((Value + Addend) & 0xFFFF000000000000) >> 43); break; - } - case ELF::R_AARCH64_MOVW_UABS_G2_NC: { - uint64_t Result = Value + Addend; - - // AArch64 code is emitted with .rela relocations. The data already in any - // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xffe0001fU; - // Immediate goes in bits 20:5 of MOVZ/MOVK instruction - *TargetPtr |= ((Result & 0xffff00000000ULL) >> (32 - 5)); - // Shift must be "lsl #32", in bits 22:21 - assert((*TargetPtr >> 21 & 0x3) == 2 && "invalid shift for relocation"); + case ELF::R_AARCH64_MOVW_UABS_G2_NC: + or32le(TargetPtr, ((Value + Addend) & 0xFFFF00000000) >> 27); break; - } - case ELF::R_AARCH64_MOVW_UABS_G1_NC: { - uint64_t Result = Value + Addend; - - // AArch64 code is emitted with .rela relocations. The data already in any - // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xffe0001fU; - // Immediate goes in bits 20:5 of MOVZ/MOVK instruction - *TargetPtr |= ((Result & 0xffff0000U) >> (16 - 5)); - // Shift must be "lsl #16", in bits 22:2 - assert((*TargetPtr >> 21 & 0x3) == 1 && "invalid shift for relocation"); + case ELF::R_AARCH64_MOVW_UABS_G1_NC: + or32le(TargetPtr, ((Value + Addend) & 0xFFFF0000) >> 11); break; - } - case ELF::R_AARCH64_MOVW_UABS_G0_NC: { - uint64_t Result = Value + Addend; - - // AArch64 code is emitted with .rela relocations. The data already in any - // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xffe0001fU; - // Immediate goes in bits 20:5 of MOVZ/MOVK instruction - *TargetPtr |= ((Result & 0xffffU) << 5); - // Shift must be "lsl #0", in bits 22:21. - assert((*TargetPtr >> 21 & 0x3) == 0 && "invalid shift for relocation"); + case ELF::R_AARCH64_MOVW_UABS_G0_NC: + or32le(TargetPtr, ((Value + Addend) & 0xFFFF) << 5); break; - } case ELF::R_AARCH64_ADR_PREL_PG_HI21: { // Operation: Page(S+A) - Page(P) uint64_t Result = @@ -406,40 +408,30 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // Check that -2^32 <= X < 2^32 assert(isInt<33>(Result) && "overflow check failed for relocation"); - // AArch64 code is emitted with .rela relocations. The data already in any - // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0x9f00001fU; // Immediate goes in bits 30:29 + 5:23 of ADRP instruction, taken // from bits 32:12 of X. - *TargetPtr |= ((Result & 0x3000U) << (29 - 12)); - *TargetPtr |= ((Result & 0x1ffffc000ULL) >> (14 - 5)); + write32AArch64Addr(TargetPtr, Result >> 12); break; } - case ELF::R_AARCH64_LDST32_ABS_LO12_NC: { + case ELF::R_AARCH64_ADD_ABS_LO12_NC: + // Operation: S + A + // Immediate goes in bits 21:10 of LD/ST instruction, taken + // from bits 11:0 of X + or32AArch64Imm(TargetPtr, Value + Addend); + break; + case ELF::R_AARCH64_LDST32_ABS_LO12_NC: // Operation: S + A - uint64_t Result = Value + Addend; - - // AArch64 code is emitted with .rela relocations. The data already in any - // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xffc003ffU; // Immediate goes in bits 21:10 of LD/ST instruction, taken // from bits 11:2 of X - *TargetPtr |= ((Result & 0xffc) << (10 - 2)); + or32AArch64Imm(TargetPtr, getBits(Value + Addend, 2, 11)); break; - } - case ELF::R_AARCH64_LDST64_ABS_LO12_NC: { + case ELF::R_AARCH64_LDST64_ABS_LO12_NC: // Operation: S + A - uint64_t Result = Value + Addend; - - // AArch64 code is emitted with .rela relocations. The data already in any - // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xffc003ffU; // Immediate goes in bits 21:10 of LD/ST instruction, taken // from bits 11:3 of X - *TargetPtr |= ((Result & 0xff8) << (10 - 3)); + or32AArch64Imm(TargetPtr, getBits(Value + Addend, 3, 11)); break; } - } } void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, @@ -463,10 +455,15 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, case ELF::R_ARM_NONE: break; + // Write a 31bit signed offset case ELF::R_ARM_PREL31: + support::ulittle32_t::ref{TargetPtr} = + (support::ulittle32_t::ref{TargetPtr} & 0x80000000) | + ((Value - FinalAddress) & ~0x80000000); + break; case ELF::R_ARM_TARGET1: case ELF::R_ARM_ABS32: - *TargetPtr = Value; + support::ulittle32_t::ref{TargetPtr} = Value; break; // Write first 16 bit of 32 bit value to the mov instruction. // Last 4 bit should be shifted. @@ -476,9 +473,9 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, Value = Value & 0xFFFF; else if (Type == ELF::R_ARM_MOVT_ABS) Value = (Value >> 16) & 0xFFFF; - *TargetPtr &= ~0x000F0FFF; - *TargetPtr |= Value & 0xFFF; - *TargetPtr |= ((Value >> 12) & 0xF) << 16; + support::ulittle32_t::ref{TargetPtr} = + (support::ulittle32_t::ref{TargetPtr} & ~0x000F0FFF) | (Value & 0xFFF) | + (((Value >> 12) & 0xF) << 16); break; // Write 24 bit relative value to the branch instruction. case ELF::R_ARM_PC24: // Fall through. @@ -486,298 +483,26 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, case ELF::R_ARM_JUMP24: int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8); RelValue = (RelValue & 0x03FFFFFC) >> 2; - assert((*TargetPtr & 0xFFFFFF) == 0xFFFFFE); - *TargetPtr &= 0xFF000000; - *TargetPtr |= RelValue; + assert((support::ulittle32_t::ref{TargetPtr} & 0xFFFFFF) == 0xFFFFFE); + support::ulittle32_t::ref{TargetPtr} = + (support::ulittle32_t::ref{TargetPtr} & 0xFF000000) | RelValue; break; } } -void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, - uint64_t Offset, uint32_t Value, - uint32_t Type, int32_t Addend) { - uint8_t *TargetPtr = Section.getAddressWithOffset(Offset); - Value += Addend; - - DEBUG(dbgs() << "resolveMIPSRelocation, LocalAddress: " - << Section.getAddressWithOffset(Offset) << " FinalAddress: " - << format("%p", Section.getLoadAddressWithOffset(Offset)) - << " Value: " << format("%x", Value) - << " Type: " << format("%x", Type) - << " Addend: " << format("%x", Addend) << "\n"); - - uint32_t Insn = readBytesUnaligned(TargetPtr, 4); - - switch (Type) { - default: - llvm_unreachable("Not implemented relocation type!"); - break; - case ELF::R_MIPS_32: - writeBytesUnaligned(Value, TargetPtr, 4); - break; - case ELF::R_MIPS_26: - Insn &= 0xfc000000; - Insn |= (Value & 0x0fffffff) >> 2; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - case ELF::R_MIPS_HI16: - // Get the higher 16-bits. Also add 1 if bit 15 is 1. - Insn &= 0xffff0000; - Insn |= ((Value + 0x8000) >> 16) & 0xffff; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - case ELF::R_MIPS_LO16: - Insn &= 0xffff0000; - Insn |= Value & 0xffff; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - case ELF::R_MIPS_PC32: { - uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - writeBytesUnaligned(Value - FinalAddress, (uint8_t *)TargetPtr, 4); - break; - } - case ELF::R_MIPS_PC16: { - uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - Insn &= 0xffff0000; - Insn |= ((Value - FinalAddress) >> 2) & 0xffff; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - } - case ELF::R_MIPS_PC19_S2: { - uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - Insn &= 0xfff80000; - Insn |= ((Value - (FinalAddress & ~0x3)) >> 2) & 0x7ffff; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - } - case ELF::R_MIPS_PC21_S2: { - uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - Insn &= 0xffe00000; - Insn |= ((Value - FinalAddress) >> 2) & 0x1fffff; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - } - case ELF::R_MIPS_PC26_S2: { - uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - Insn &= 0xfc000000; - Insn |= ((Value - FinalAddress) >> 2) & 0x3ffffff; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - } - case ELF::R_MIPS_PCHI16: { - uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - Insn &= 0xffff0000; - Insn |= ((Value - FinalAddress + 0x8000) >> 16) & 0xffff; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - } - case ELF::R_MIPS_PCLO16: { - uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - Insn &= 0xffff0000; - Insn |= (Value - FinalAddress) & 0xffff; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - } - } -} - void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) { if (Arch == Triple::UnknownArch || !StringRef(Triple::getArchTypePrefix(Arch)).equals("mips")) { IsMipsO32ABI = false; + IsMipsN32ABI = false; IsMipsN64ABI = false; return; } unsigned AbiVariant; Obj.getPlatformFlags(AbiVariant); IsMipsO32ABI = AbiVariant & ELF::EF_MIPS_ABI_O32; + IsMipsN32ABI = AbiVariant & ELF::EF_MIPS_ABI2; IsMipsN64ABI = Obj.getFileFormatName().equals("ELF64-mips"); - if (AbiVariant & ELF::EF_MIPS_ABI2) - llvm_unreachable("Mips N32 ABI is not supported yet"); -} - -void RuntimeDyldELF::resolveMIPS64Relocation(const SectionEntry &Section, - uint64_t Offset, uint64_t Value, - uint32_t Type, int64_t Addend, - uint64_t SymOffset, - SID SectionID) { - uint32_t r_type = Type & 0xff; - uint32_t r_type2 = (Type >> 8) & 0xff; - uint32_t r_type3 = (Type >> 16) & 0xff; - - // RelType is used to keep information for which relocation type we are - // applying relocation. - uint32_t RelType = r_type; - int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value, - RelType, Addend, - SymOffset, SectionID); - if (r_type2 != ELF::R_MIPS_NONE) { - RelType = r_type2; - CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType, - CalculatedValue, SymOffset, - SectionID); - } - if (r_type3 != ELF::R_MIPS_NONE) { - RelType = r_type3; - CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType, - CalculatedValue, SymOffset, - SectionID); - } - applyMIPS64Relocation(Section.getAddressWithOffset(Offset), CalculatedValue, - RelType); -} - -int64_t -RuntimeDyldELF::evaluateMIPS64Relocation(const SectionEntry &Section, - uint64_t Offset, uint64_t Value, - uint32_t Type, int64_t Addend, - uint64_t SymOffset, SID SectionID) { - - DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x" - << format("%llx", Section.getAddressWithOffset(Offset)) - << " FinalAddress: 0x" - << format("%llx", Section.getLoadAddressWithOffset(Offset)) - << " Value: 0x" << format("%llx", Value) << " Type: 0x" - << format("%x", Type) << " Addend: 0x" << format("%llx", Addend) - << " SymOffset: " << format("%x", SymOffset) << "\n"); - - switch (Type) { - default: - llvm_unreachable("Not implemented relocation type!"); - break; - case ELF::R_MIPS_JALR: - case ELF::R_MIPS_NONE: - break; - case ELF::R_MIPS_32: - case ELF::R_MIPS_64: - return Value + Addend; - case ELF::R_MIPS_26: - return ((Value + Addend) >> 2) & 0x3ffffff; - case ELF::R_MIPS_GPREL16: { - uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]); - return Value + Addend - (GOTAddr + 0x7ff0); - } - case ELF::R_MIPS_SUB: - return Value - Addend; - case ELF::R_MIPS_HI16: - // Get the higher 16-bits. Also add 1 if bit 15 is 1. - return ((Value + Addend + 0x8000) >> 16) & 0xffff; - case ELF::R_MIPS_LO16: - return (Value + Addend) & 0xffff; - case ELF::R_MIPS_CALL16: - case ELF::R_MIPS_GOT_DISP: - case ELF::R_MIPS_GOT_PAGE: { - uint8_t *LocalGOTAddr = - getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset; - uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, 8); - - Value += Addend; - if (Type == ELF::R_MIPS_GOT_PAGE) - Value = (Value + 0x8000) & ~0xffff; - - if (GOTEntry) - assert(GOTEntry == Value && - "GOT entry has two different addresses."); - else - writeBytesUnaligned(Value, LocalGOTAddr, 8); - - return (SymOffset - 0x7ff0) & 0xffff; - } - case ELF::R_MIPS_GOT_OFST: { - int64_t page = (Value + Addend + 0x8000) & ~0xffff; - return (Value + Addend - page) & 0xffff; - } - case ELF::R_MIPS_GPREL32: { - uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]); - return Value + Addend - (GOTAddr + 0x7ff0); - } - case ELF::R_MIPS_PC16: { - uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - return ((Value + Addend - FinalAddress) >> 2) & 0xffff; - } - case ELF::R_MIPS_PC32: { - uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - return Value + Addend - FinalAddress; - } - case ELF::R_MIPS_PC18_S3: { - uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff; - } - case ELF::R_MIPS_PC19_S2: { - uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff; - } - case ELF::R_MIPS_PC21_S2: { - uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff; - } - case ELF::R_MIPS_PC26_S2: { - uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff; - } - case ELF::R_MIPS_PCHI16: { - uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff; - } - case ELF::R_MIPS_PCLO16: { - uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); - return (Value + Addend - FinalAddress) & 0xffff; - } - } - return 0; -} - -void RuntimeDyldELF::applyMIPS64Relocation(uint8_t *TargetPtr, - int64_t CalculatedValue, - uint32_t Type) { - uint32_t Insn = readBytesUnaligned(TargetPtr, 4); - - switch (Type) { - default: - break; - case ELF::R_MIPS_32: - case ELF::R_MIPS_GPREL32: - case ELF::R_MIPS_PC32: - writeBytesUnaligned(CalculatedValue & 0xffffffff, TargetPtr, 4); - break; - case ELF::R_MIPS_64: - case ELF::R_MIPS_SUB: - writeBytesUnaligned(CalculatedValue, TargetPtr, 8); - break; - case ELF::R_MIPS_26: - case ELF::R_MIPS_PC26_S2: - Insn = (Insn & 0xfc000000) | CalculatedValue; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - case ELF::R_MIPS_GPREL16: - Insn = (Insn & 0xffff0000) | (CalculatedValue & 0xffff); - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - case ELF::R_MIPS_HI16: - case ELF::R_MIPS_LO16: - case ELF::R_MIPS_PCHI16: - case ELF::R_MIPS_PCLO16: - case ELF::R_MIPS_PC16: - case ELF::R_MIPS_CALL16: - case ELF::R_MIPS_GOT_DISP: - case ELF::R_MIPS_GOT_PAGE: - case ELF::R_MIPS_GOT_OFST: - Insn = (Insn & 0xffff0000) | CalculatedValue; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - case ELF::R_MIPS_PC18_S3: - Insn = (Insn & 0xfffc0000) | CalculatedValue; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - case ELF::R_MIPS_PC19_S2: - Insn = (Insn & 0xfff80000) | CalculatedValue; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - case ELF::R_MIPS_PC21_S2: - Insn = (Insn & 0xffe00000) | CalculatedValue; - writeBytesUnaligned(Insn, TargetPtr, 4); - break; - } } // Return the .TOC. section and offset. @@ -1124,19 +849,6 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; - case Triple::mips: // Fall through. - case Triple::mipsel: - case Triple::mips64: - case Triple::mips64el: - if (IsMipsO32ABI) - resolveMIPSRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), - Type, (uint32_t)(Addend & 0xffffffffL)); - else if (IsMipsN64ABI) - resolveMIPS64Relocation(Section, Offset, Value, Type, Addend, SymOffset, - SectionID); - else - llvm_unreachable("Mips ABI not handled"); - break; case Triple::ppc: resolvePPC32Relocation(Section, Offset, Value, Type, Addend); break; @@ -1187,6 +899,48 @@ uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType, return ELF::R_MIPS_NONE; } +// Sometimes we don't need to create thunk for a branch. +// This typically happens when branch target is located +// in the same object file. In such case target is either +// a weak symbol or symbol in a different executable section. +// This function checks if branch target is located in the +// same object file and if distance between source and target +// fits R_AARCH64_CALL26 relocation. If both conditions are +// met, it emits direct jump to the target and returns true. +// Otherwise false is returned and thunk is created. +bool RuntimeDyldELF::resolveAArch64ShortBranch( + unsigned SectionID, relocation_iterator RelI, + const RelocationValueRef &Value) { + uint64_t Address; + if (Value.SymbolName) { + auto Loc = GlobalSymbolTable.find(Value.SymbolName); + + // Don't create direct branch for external symbols. + if (Loc == GlobalSymbolTable.end()) + return false; + + const auto &SymInfo = Loc->second; + Address = + uint64_t(Sections[SymInfo.getSectionID()].getLoadAddressWithOffset( + SymInfo.getOffset())); + } else { + Address = uint64_t(Sections[Value.SectionID].getLoadAddress()); + } + uint64_t Offset = RelI->getOffset(); + uint64_t SourceAddress = Sections[SectionID].getLoadAddressWithOffset(Offset); + + // R_AARCH64_CALL26 requires immediate to be in range -2^27 <= imm < 2^27 + // If distance between source and target is out of range then we should + // create thunk. + if (!isInt<28>(Address + Value.Addend - SourceAddress)) + return false; + + resolveRelocation(Sections[SectionID], Offset, Address, RelI->getType(), + Value.Addend); + + return true; +} + Expected<relocation_iterator> RuntimeDyldELF::processRelocationRef( unsigned SectionID, relocation_iterator RelI, const ObjectFile &O, @@ -1258,6 +1012,7 @@ RuntimeDyldELF::processRelocationRef( break; } case SymbolRef::ST_Data: + case SymbolRef::ST_Function: case SymbolRef::ST_Unknown: { Value.SymbolName = TargetName.data(); Value.Addend = Addend; @@ -1293,7 +1048,7 @@ RuntimeDyldELF::processRelocationRef( (uint64_t)Section.getAddressWithOffset(i->second), RelType, 0); DEBUG(dbgs() << " Stub function found\n"); - } else { + } else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) { // Create a new stub function. DEBUG(dbgs() << " Create a new stub function\n"); Stubs[Value] = Section.getStubOffset(); @@ -1468,7 +1223,7 @@ RuntimeDyldELF::processRelocationRef( Value.Addend += SignExtend32<28>((Opcode & 0x03ffffff) << 2); processSimpleRelocation(SectionID, Offset, RelType, Value); } - } else if (IsMipsN64ABI) { + } else if (IsMipsN32ABI || IsMipsN64ABI) { uint32_t r_type = RelType & 0xff; RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE @@ -1805,7 +1560,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() { case Triple::mipsel: case Triple::mips64: case Triple::mips64el: - if (IsMipsO32ABI) + if (IsMipsO32ABI || IsMipsN32ABI) Result = sizeof(uint32_t); else if (IsMipsN64ABI) Result = sizeof(uint64_t); @@ -1870,7 +1625,7 @@ Error RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, // For now, initialize all GOT entries to zero. We'll fill them in as // needed when GOT-based relocations are applied. memset(Addr, 0, TotalSize); - if (IsMipsN64ABI) { + if (IsMipsN32ABI || IsMipsN64ABI) { // To correctly resolve Mips GOT relocations, we need a mapping from // object's sections to GOTs. for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 82931b9..d1867d0 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -40,12 +40,12 @@ class RuntimeDyldELF : public RuntimeDyldImpl { void resolveAArch64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend); + bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI, + const RelocationValueRef &Value); + void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend); - void resolveMIPSRelocation(const SectionEntry &Section, uint64_t Offset, - uint32_t Value, uint32_t Type, int32_t Addend); - void resolvePPC32Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend); @@ -55,18 +55,6 @@ class RuntimeDyldELF : public RuntimeDyldImpl { void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend); - void resolveMIPS64Relocation(const SectionEntry &Section, uint64_t Offset, - uint64_t Value, uint32_t Type, int64_t Addend, - uint64_t SymOffset, SID SectionID); - - int64_t evaluateMIPS64Relocation(const SectionEntry &Section, - uint64_t Offset, uint64_t Value, - uint32_t Type, int64_t Addend, - uint64_t SymOffset, SID SectionID); - - void applyMIPS64Relocation(uint8_t *TargetPtr, int64_t CalculatedValue, - uint32_t Type); - unsigned getMaxStubSize() override { if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) return 20; // movz; movk; movk; movk; br @@ -99,9 +87,10 @@ class RuntimeDyldELF : public RuntimeDyldImpl { Error findOPDEntrySection(const ELFObjectFileBase &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); - +protected: size_t getGOTEntrySize(); +private: SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; } // Allocate no GOT entries for use in the given section. @@ -138,10 +127,12 @@ class RuntimeDyldELF : public RuntimeDyldImpl { // that consume more than one slot) unsigned CurrentGOTIndex; +protected: // A map from section to a GOT section that has entries for section's GOT // relocations. (Mips64 specific) DenseMap<SID, SID> SectionToGOTMap; +private: // A map to avoid duplicate got entries (Mips64 specific) StringMap<uint64_t> GOTSymbolOffsets; @@ -159,9 +150,13 @@ class RuntimeDyldELF : public RuntimeDyldImpl { public: RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver); + JITSymbolResolver &Resolver); ~RuntimeDyldELF() override; + static std::unique_ptr<RuntimeDyldELF> + create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, + JITSymbolResolver &Resolver); + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> loadObject(const object::ObjectFile &O) override; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 76bd3fc..279d0de 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -149,26 +149,41 @@ public: /// The size of this relocation (MachO specific). unsigned Size; + // COFF specific. + bool IsTargetThumbFunc; + RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend) : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(0), IsPCRel(false), Size(0) {} + SymOffset(0), IsPCRel(false), Size(0), IsTargetThumbFunc(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, uint64_t symoffset) : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(symoffset), IsPCRel(false), Size(0) {} + SymOffset(symoffset), IsPCRel(false), Size(0), + IsTargetThumbFunc(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, bool IsPCRel, unsigned Size) : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(0), IsPCRel(IsPCRel), Size(Size) {} + SymOffset(0), IsPCRel(IsPCRel), Size(Size), IsTargetThumbFunc(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, uint64_t SectionBOffset, bool IsPCRel, unsigned Size) : SectionID(id), Offset(offset), RelType(type), Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel), - Size(Size) { + Size(Size), IsTargetThumbFunc(false) { + Sections.SectionA = SectionA; + Sections.SectionB = SectionB; + } + + RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, + unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, + uint64_t SectionBOffset, bool IsPCRel, unsigned Size, + bool IsTargetThumbFunc) + : SectionID(id), Offset(offset), RelType(type), + Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel), + Size(Size), IsTargetThumbFunc(IsTargetThumbFunc) { Sections.SectionA = SectionA; Sections.SectionB = SectionB; } @@ -199,20 +214,23 @@ public: }; /// @brief Symbol info for RuntimeDyld. -class SymbolTableEntry : public JITSymbolBase { +class SymbolTableEntry { public: SymbolTableEntry() - : JITSymbolBase(JITSymbolFlags::None), Offset(0), SectionID(0) {} + : Offset(0), SectionID(0) {} SymbolTableEntry(unsigned SectionID, uint64_t Offset, JITSymbolFlags Flags) - : JITSymbolBase(Flags), Offset(Offset), SectionID(SectionID) {} + : Offset(Offset), SectionID(SectionID), Flags(Flags) {} unsigned getSectionID() const { return SectionID; } uint64_t getOffset() const { return Offset; } + JITSymbolFlags getFlags() const { return Flags; } + private: uint64_t Offset; unsigned SectionID; + JITSymbolFlags Flags; }; typedef StringMap<SymbolTableEntry> RTDyldSymbolTable; @@ -227,7 +245,7 @@ protected: RuntimeDyld::MemoryManager &MemMgr; // The symbol resolver to use for external symbols. - RuntimeDyld::SymbolResolver &Resolver; + JITSymbolResolver &Resolver; // Attached RuntimeDyldChecker instance. Null if no instance attached. RuntimeDyldCheckerImpl *Checker; @@ -272,6 +290,7 @@ protected: Triple::ArchType Arch; bool IsTargetLittleEndian; bool IsMipsO32ABI; + bool IsMipsN32ABI; bool IsMipsN64ABI; // True if all sections should be passed to the memory manager, false if only @@ -335,6 +354,7 @@ protected: virtual void setMipsABI(const ObjectFile &Obj) { IsMipsO32ABI = false; + IsMipsN32ABI = false; IsMipsN64ABI = false; } @@ -420,7 +440,7 @@ protected: public: RuntimeDyldImpl(RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : MemMgr(MemMgr), Resolver(Resolver), Checker(nullptr), ProcessAllSections(false), HasError(false) { } @@ -451,7 +471,7 @@ public: return getSectionAddress(SymInfo.getSectionID()) + SymInfo.getOffset(); } - RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const { + JITEvaluatedSymbol getSymbol(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); @@ -462,7 +482,7 @@ public: if (SymEntry.getSectionID() != AbsoluteSymbolSection) SectionAddr = getSectionLoadAddress(SymEntry.getSectionID()); uint64_t TargetAddr = SectionAddr + SymEntry.getOffset(); - return RuntimeDyld::SymbolInfo(TargetAddr, SymEntry.getFlags()); + return JITEvaluatedSymbol(TargetAddr, SymEntry.getFlags()); } void resolveRelocations(); diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index fd109ae..00541e8 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -343,7 +343,7 @@ void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { std::unique_ptr<RuntimeDyldMachO> RuntimeDyldMachO::create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver) { + JITSymbolResolver &Resolver) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldMachO."); diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 30f3bb3..67a5020 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -50,7 +50,7 @@ protected: SmallVector<EHFrameRelatedSections, 2> UnregisteredEHFrameSections; RuntimeDyldMachO(RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldImpl(MemMgr, Resolver) {} /// This convenience method uses memcpy to extract a contiguous addend (the @@ -124,7 +124,7 @@ public: static std::unique_ptr<RuntimeDyldMachO> create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver); + JITSymbolResolver &Resolver); std::unique_ptr<RuntimeDyld::LoadedObjectInfo> loadObject(const object::ObjectFile &O) override; @@ -152,7 +152,7 @@ private: public: RuntimeDyldMachOCRTPBase(RuntimeDyld::MemoryManager &MemMgr, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldMachO(MemMgr, Resolver) {} Error finalizeLoad(const ObjectFile &Obj, diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h index 44fda87..0398413 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h @@ -25,7 +25,7 @@ namespace llvm { class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF { public: RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldCOFF(MM, Resolver) {} unsigned getMaxStubSize() override { diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h index ff7d1d4..8c6af0b 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h @@ -22,10 +22,30 @@ namespace llvm { +static bool isThumbFunc(symbol_iterator Symbol, const ObjectFile &Obj, + section_iterator Section) { + Expected<SymbolRef::Type> SymTypeOrErr = Symbol->getType(); + if (!SymTypeOrErr) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, ""); + OS.flush(); + report_fatal_error(Buf); + } + + if (*SymTypeOrErr != SymbolRef::ST_Function) + return false; + + // We check the IMAGE_SCN_MEM_16BIT flag in the section of the symbol to tell + // if it's thumb or not + return cast<COFFObjectFile>(Obj).getCOFFSection(*Section)->Characteristics & + COFF::IMAGE_SCN_MEM_16BIT; +} + class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF { public: RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldCOFF(MM, Resolver) {} unsigned getMaxStubSize() override { @@ -92,12 +112,22 @@ public: else return TargetSectionIDOrErr.takeError(); + // We need to find out if the relocation is relative to a thumb function + // so that we include the ISA selection bit when resolve the relocation + bool IsTargetThumbFunc = isThumbFunc(Symbol, Obj, Section); + switch (RelType) { default: llvm_unreachable("unsupported relocation type"); case COFF::IMAGE_REL_ARM_ABSOLUTE: // This relocation is ignored. break; - case COFF::IMAGE_REL_ARM_ADDR32: + case COFF::IMAGE_REL_ARM_ADDR32: { + RelocationEntry RE = RelocationEntry( + SectionID, Offset, RelType, Addend, TargetSectionID, + getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc); + addRelocationForSection(RE, TargetSectionID); + break; + } case COFF::IMAGE_REL_ARM_ADDR32NB: { RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, @@ -118,9 +148,9 @@ public: break; } case COFF::IMAGE_REL_ARM_MOV32T: { - RelocationEntry RE = - RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, - getSymbolOffset(*Symbol), 0, 0, false, 0); + RelocationEntry RE = RelocationEntry( + SectionID, Offset, RelType, Addend, TargetSectionID, + getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc); addRelocationForSection(RE, TargetSectionID); break; } @@ -142,6 +172,7 @@ public: void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { const auto Section = Sections[RE.SectionID]; uint8_t *Target = Section.getAddressWithOffset(RE.Offset); + int ISASelectionBit = RE.IsTargetThumbFunc ? 1 : 0; switch (RE.RelType) { default: llvm_unreachable("unsupported relocation type"); @@ -154,6 +185,7 @@ public: RE.Sections.SectionA == static_cast<uint32_t>(-1) ? 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 && @@ -178,6 +210,7 @@ public: << " RelType: IMAGE_REL_ARM_ADDR32NB" << " TargetSection: " << RE.Sections.SectionA << " Value: " << format("0x%08" PRIx32, Result) << '\n'); + Result |= ISASelectionBit; writeBytesUnaligned(Result, Target, 4); break; } @@ -225,10 +258,11 @@ public: Bytes[0] |= ((Immediate & 0xf000) >> 12); Bytes[1] |= ((Immediate & 0x0800) >> 11); Bytes[2] |= ((Immediate & 0x00ff) >> 0); - Bytes[3] |= ((Immediate & 0x0700) >> 8); + Bytes[3] |= (((Immediate & 0x0700) >> 8) << 4); }; - EncodeImmediate(&Target[0], static_cast<uint32_t>(Result) >> 00); + EncodeImmediate(&Target[0], + (static_cast<uint32_t>(Result) >> 00) | ISASelectionBit); EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16); break; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h index df8681d..109beb3 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h @@ -33,7 +33,7 @@ private: public: RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldCOFF(MM, Resolver) {} unsigned getMaxStubSize() override { diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp new file mode 100644 index 0000000..cae4d69 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp @@ -0,0 +1,312 @@ +//===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RuntimeDyldELFMips.h" +#include "llvm/Support/ELF.h" + +#define DEBUG_TYPE "dyld" + +void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE, + uint64_t Value) { + const SectionEntry &Section = Sections[RE.SectionID]; + if (IsMipsO32ABI) + resolveMIPSO32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend); + else if (IsMipsN32ABI) { + resolveMIPSN32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, + RE.SymOffset, RE.SectionID); + } else if (IsMipsN64ABI) + resolveMIPSN64Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, + RE.SymOffset, RE.SectionID); + else + llvm_unreachable("Mips ABI not handled"); +} + +uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE, + uint64_t Value, + uint64_t Addend) { + if (IsMipsN32ABI) { + const SectionEntry &Section = Sections[RE.SectionID]; + Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType, + Addend, RE.SymOffset, RE.SectionID); + return Value; + } + llvm_unreachable("Not reachable"); +} + +void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE, + uint64_t Value) { + if (IsMipsN32ABI) { + const SectionEntry &Section = Sections[RE.SectionID]; + applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value, + RE.RelType); + return; + } + llvm_unreachable("Not reachable"); +} + +int64_t +RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, + uint32_t Type) { + + DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x" + << format("%llx", Section.getAddressWithOffset(Offset)) + << " FinalAddress: 0x" + << format("%llx", Section.getLoadAddressWithOffset(Offset)) + << " Value: 0x" << format("%llx", Value) << " Type: 0x" + << format("%x", Type) << "\n"); + + switch (Type) { + default: + llvm_unreachable("Unknown relocation type!"); + return Value; + case ELF::R_MIPS_32: + return Value; + case ELF::R_MIPS_26: + return Value >> 2; + case ELF::R_MIPS_HI16: + // Get the higher 16-bits. Also add 1 if bit 15 is 1. + return (Value + 0x8000) >> 16; + case ELF::R_MIPS_LO16: + return Value; + case ELF::R_MIPS_PC32: { + uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return Value - FinalAddress; + } + case ELF::R_MIPS_PC16: { + uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return (Value - FinalAddress) >> 2; + } + case ELF::R_MIPS_PC19_S2: { + uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return (Value - (FinalAddress & ~0x3)) >> 2; + } + case ELF::R_MIPS_PC21_S2: { + uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return (Value - FinalAddress) >> 2; + } + case ELF::R_MIPS_PC26_S2: { + uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return (Value - FinalAddress) >> 2; + } + case ELF::R_MIPS_PCHI16: { + uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return (Value - FinalAddress + 0x8000) >> 16; + } + case ELF::R_MIPS_PCLO16: { + uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return Value - FinalAddress; + } + } +} + +int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation( + const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, + int64_t Addend, uint64_t SymOffset, SID SectionID) { + + DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x" + << format("%llx", Section.getAddressWithOffset(Offset)) + << " FinalAddress: 0x" + << format("%llx", Section.getLoadAddressWithOffset(Offset)) + << " Value: 0x" << format("%llx", Value) << " Type: 0x" + << format("%x", Type) << " Addend: 0x" << format("%llx", Addend) + << " SymOffset: " << format("%x", SymOffset) << "\n"); + + switch (Type) { + default: + llvm_unreachable("Not implemented relocation type!"); + break; + case ELF::R_MIPS_JALR: + case ELF::R_MIPS_NONE: + break; + case ELF::R_MIPS_32: + case ELF::R_MIPS_64: + return Value + Addend; + case ELF::R_MIPS_26: + return ((Value + Addend) >> 2) & 0x3ffffff; + case ELF::R_MIPS_GPREL16: { + uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]); + return Value + Addend - (GOTAddr + 0x7ff0); + } + case ELF::R_MIPS_SUB: + return Value - Addend; + case ELF::R_MIPS_HI16: + // Get the higher 16-bits. Also add 1 if bit 15 is 1. + return ((Value + Addend + 0x8000) >> 16) & 0xffff; + case ELF::R_MIPS_LO16: + return (Value + Addend) & 0xffff; + case ELF::R_MIPS_CALL16: + case ELF::R_MIPS_GOT_DISP: + case ELF::R_MIPS_GOT_PAGE: { + uint8_t *LocalGOTAddr = + getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset; + uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize()); + + Value += Addend; + if (Type == ELF::R_MIPS_GOT_PAGE) + Value = (Value + 0x8000) & ~0xffff; + + if (GOTEntry) + assert(GOTEntry == Value && + "GOT entry has two different addresses."); + else + writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize()); + + return (SymOffset - 0x7ff0) & 0xffff; + } + case ELF::R_MIPS_GOT_OFST: { + int64_t page = (Value + Addend + 0x8000) & ~0xffff; + return (Value + Addend - page) & 0xffff; + } + case ELF::R_MIPS_GPREL32: { + uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]); + return Value + Addend - (GOTAddr + 0x7ff0); + } + case ELF::R_MIPS_PC16: { + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return ((Value + Addend - FinalAddress) >> 2) & 0xffff; + } + case ELF::R_MIPS_PC32: { + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return Value + Addend - FinalAddress; + } + case ELF::R_MIPS_PC18_S3: { + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff; + } + case ELF::R_MIPS_PC19_S2: { + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff; + } + case ELF::R_MIPS_PC21_S2: { + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff; + } + case ELF::R_MIPS_PC26_S2: { + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff; + } + case ELF::R_MIPS_PCHI16: { + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff; + } + case ELF::R_MIPS_PCLO16: { + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + return (Value + Addend - FinalAddress) & 0xffff; + } + } + return 0; +} + +void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value, + uint32_t Type) { + uint32_t Insn = readBytesUnaligned(TargetPtr, 4); + + switch (Type) { + default: + llvm_unreachable("Unknown relocation type!"); + break; + case ELF::R_MIPS_GPREL16: + case ELF::R_MIPS_HI16: + case ELF::R_MIPS_LO16: + case ELF::R_MIPS_PC16: + case ELF::R_MIPS_PCHI16: + case ELF::R_MIPS_PCLO16: + case ELF::R_MIPS_CALL16: + case ELF::R_MIPS_GOT_DISP: + case ELF::R_MIPS_GOT_PAGE: + case ELF::R_MIPS_GOT_OFST: + Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff); + writeBytesUnaligned(Insn, TargetPtr, 4); + break; + case ELF::R_MIPS_PC18_S3: + Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff); + writeBytesUnaligned(Insn, TargetPtr, 4); + break; + case ELF::R_MIPS_PC19_S2: + Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff); + writeBytesUnaligned(Insn, TargetPtr, 4); + break; + case ELF::R_MIPS_PC21_S2: + Insn = (Insn & 0xffe00000) | (Value & 0x001fffff); + writeBytesUnaligned(Insn, TargetPtr, 4); + break; + case ELF::R_MIPS_26: + case ELF::R_MIPS_PC26_S2: + Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff); + writeBytesUnaligned(Insn, TargetPtr, 4); + break; + case ELF::R_MIPS_32: + case ELF::R_MIPS_GPREL32: + case ELF::R_MIPS_PC32: + writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4); + break; + case ELF::R_MIPS_64: + case ELF::R_MIPS_SUB: + writeBytesUnaligned(Value, TargetPtr, 8); + break; + } +} + +void RuntimeDyldELFMips::resolveMIPSN32Relocation( + const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, + int64_t Addend, uint64_t SymOffset, SID SectionID) { + int64_t CalculatedValue = evaluateMIPS64Relocation( + Section, Offset, Value, Type, Addend, SymOffset, SectionID); + applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue, + Type); +} + +void RuntimeDyldELFMips::resolveMIPSN64Relocation( + const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, + int64_t Addend, uint64_t SymOffset, SID SectionID) { + uint32_t r_type = Type & 0xff; + uint32_t r_type2 = (Type >> 8) & 0xff; + uint32_t r_type3 = (Type >> 16) & 0xff; + + // RelType is used to keep information for which relocation type we are + // applying relocation. + uint32_t RelType = r_type; + int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value, + RelType, Addend, + SymOffset, SectionID); + if (r_type2 != ELF::R_MIPS_NONE) { + RelType = r_type2; + CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType, + CalculatedValue, SymOffset, + SectionID); + } + if (r_type3 != ELF::R_MIPS_NONE) { + RelType = r_type3; + CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType, + CalculatedValue, SymOffset, + SectionID); + } + applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue, + RelType); +} + +void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section, + uint64_t Offset, + uint32_t Value, uint32_t Type, + int32_t Addend) { + uint8_t *TargetPtr = Section.getAddressWithOffset(Offset); + Value += Addend; + + DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: " + << Section.getAddressWithOffset(Offset) << " FinalAddress: " + << format("%p", Section.getLoadAddressWithOffset(Offset)) + << " Value: " << format("%x", Value) + << " Type: " << format("%x", Type) + << " Addend: " << format("%x", Addend) << "\n"); + + Value = evaluateMIPS32Relocation(Section, Offset, Value, Type); + + applyMIPSRelocation(TargetPtr, Value, Type); +} diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.h new file mode 100644 index 0000000..ce54a27 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.h @@ -0,0 +1,68 @@ +//===-- RuntimeDyldELFMips.h ---- ELF/Mips specific code. -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDELFMIPS_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDELFMIPS_H + +#include "../RuntimeDyldELF.h" +#include <string> + +#define DEBUG_TYPE "dyld" + +namespace llvm { + +class RuntimeDyldELFMips : public RuntimeDyldELF { +public: + + typedef uint64_t TargetPtrT; + + RuntimeDyldELFMips(RuntimeDyld::MemoryManager &MM, + JITSymbolResolver &Resolver) + : RuntimeDyldELF(MM, Resolver) {} + + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override; + +protected: + void resolveMIPSO32Relocation(const SectionEntry &Section, uint64_t Offset, + uint32_t Value, uint32_t Type, int32_t Addend); + void resolveMIPSN32Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend, + uint64_t SymOffset, SID SectionID); + void resolveMIPSN64Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend, + uint64_t SymOffset, SID SectionID); + +private: + /// \brief A object file specific relocation resolver + /// \param RE The relocation to be resolved + /// \param Value Target symbol address to apply the relocation action + uint64_t evaluateRelocation(const RelocationEntry &RE, uint64_t Value, + uint64_t Addend); + + /// \brief A object file specific relocation resolver + /// \param RE The relocation to be resolved + /// \param Value Target symbol address to apply the relocation action + void applyRelocation(const RelocationEntry &RE, uint64_t Value); + + int64_t evaluateMIPS32Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type); + int64_t evaluateMIPS64Relocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend, + uint64_t SymOffset, SID SectionID); + + void applyMIPSRelocation(uint8_t *TargetPtr, int64_t CalculatedValue, + uint32_t Type); + +}; +} + +#undef DEBUG_TYPE + +#endif diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index 63598f1..97cbc15 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -24,7 +24,7 @@ public: typedef uint64_t TargetPtrT; RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } @@ -97,7 +97,8 @@ public: (void)p; assert((*p & 0x3B000000) == 0x39000000 && "Only expected load / store instructions."); - } // fall-through + LLVM_FALLTHROUGH; + } case MachO::ARM64_RELOC_PAGEOFF12: { // Verify that the relocation points to one of the expected load / store // or add / sub instructions. @@ -196,7 +197,8 @@ public: assert((*p & 0x3B000000) == 0x39000000 && "Only expected load / store instructions."); (void)p; - } // fall-through + LLVM_FALLTHROUGH; + } case MachO::ARM64_RELOC_PAGEOFF12: { // Verify that the relocation points to one of the expected load / store // or add / sub instructions. diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 0abf9da..adca0ee 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -27,7 +27,7 @@ public: typedef uint32_t TargetPtrT; RuntimeDyldMachOARM(RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 2c79b3f..c42f175 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -24,7 +24,7 @@ public: typedef uint32_t TargetPtrT; RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 0; } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index bc48229..32fd3ef 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -24,7 +24,7 @@ public: typedef uint64_t TargetPtrT; RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager &MM, - RuntimeDyld::SymbolResolver &Resolver) + JITSymbolResolver &Resolver) : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/contrib/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp b/contrib/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp index 1ad5f17..50478ea 100644 --- a/contrib/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp +++ b/contrib/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp @@ -196,8 +196,8 @@ SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup, // Remove all blocks which are now empty MemGroup.FreeMem.erase( - std::remove_if(MemGroup.FreeMem.begin(), MemGroup.FreeMem.end(), - [](FreeMemBlock &FreeMB) { return FreeMB.Free.size() == 0; }), + remove_if(MemGroup.FreeMem, + [](FreeMemBlock &FreeMB) { return FreeMB.Free.size() == 0; }), MemGroup.FreeMem.end()); return std::error_code(); diff --git a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp index b45f0c8..6e2973c 100644 --- a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp +++ b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp @@ -48,9 +48,8 @@ TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple, // Adjust the triple to match what the user requested. const Target *TheTarget = nullptr; if (!MArch.empty()) { - auto I = std::find_if( - TargetRegistry::targets().begin(), TargetRegistry::targets().end(), - [&](const Target &T) { return MArch == T.getName(); }); + auto I = find_if(TargetRegistry::targets(), + [&](const Target &T) { return MArch == T.getName(); }); if (I == TargetRegistry::targets().end()) { if (ErrorStr) |