diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/ExecutionEngine | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/ExecutionEngine')
30 files changed, 1358 insertions, 1114 deletions
diff --git a/lib/ExecutionEngine/EventListenerCommon.h b/lib/ExecutionEngine/EventListenerCommon.h index 314db8b..66645d7 100644 --- a/lib/ExecutionEngine/EventListenerCommon.h +++ b/lib/ExecutionEngine/EventListenerCommon.h @@ -15,10 +15,10 @@ #define EVENT_LISTENER_COMMON_H #include "llvm/ADT/DenseMap.h" -#include "llvm/DebugInfo.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Path.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 2a610d5..4768e67 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -14,23 +14,23 @@ #define DEBUG_TYPE "jit" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Host.h" #include "llvm/Support/MutexGuard.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include <cmath> @@ -97,7 +97,7 @@ public: return static_cast<char*>(RawMemory) + sizeof(GVMemoryBlock); } - virtual void deleted() { + void deleted() override { // We allocated with operator new and with some extra memory hanging off the // end, so don't just delete this. I'm not sure if this is actually // required. @@ -443,7 +443,7 @@ ExecutionEngine *ExecutionEngine::createJIT(Module *M, } ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { - OwningPtr<TargetMachine> TheTM(TM); // Take ownership. + std::unique_ptr<TargetMachine> TheTM(TM); // Take ownership. // Make sure we can resolve symbols in the program as well. The zero arg // to the function tells DynamicLibrary to load the program, not a library. @@ -486,12 +486,12 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { if (UseMCJIT && ExecutionEngine::MCJITCtor) { ExecutionEngine *EE = ExecutionEngine::MCJITCtor(M, ErrorStr, MCJMM ? MCJMM : JMM, - AllocateGVsWithCode, TheTM.take()); + AllocateGVsWithCode, TheTM.release()); if (EE) return EE; } else if (ExecutionEngine::JITCtor) { ExecutionEngine *EE = ExecutionEngine::JITCtor(M, ErrorStr, JMM, - AllocateGVsWithCode, TheTM.take()); + AllocateGVsWithCode, TheTM.release()); if (EE) return EE; } } @@ -590,8 +590,8 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { case Instruction::GetElementPtr: { // Compute the index GenericValue Result = getConstantValue(Op0); - APInt Offset(TD->getPointerSizeInBits(), 0); - cast<GEPOperator>(CE)->accumulateConstantOffset(*TD, Offset); + APInt Offset(DL->getPointerSizeInBits(), 0); + cast<GEPOperator>(CE)->accumulateConstantOffset(*DL, Offset); char* tmp = (char*) Result.PointerVal; Result = PTOGV(tmp + Offset.getSExtValue()); @@ -678,16 +678,16 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { } case Instruction::PtrToInt: { GenericValue GV = getConstantValue(Op0); - uint32_t PtrWidth = TD->getTypeSizeInBits(Op0->getType()); + uint32_t PtrWidth = DL->getTypeSizeInBits(Op0->getType()); assert(PtrWidth <= 64 && "Bad pointer width"); GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal)); - uint32_t IntWidth = TD->getTypeSizeInBits(CE->getType()); + uint32_t IntWidth = DL->getTypeSizeInBits(CE->getType()); GV.IntVal = GV.IntVal.zextOrTrunc(IntWidth); return GV; } case Instruction::IntToPtr: { GenericValue GV = getConstantValue(Op0); - uint32_t PtrWidth = TD->getTypeSizeInBits(CE->getType()); + uint32_t PtrWidth = DL->getTypeSizeInBits(CE->getType()); GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width"); GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue())); @@ -1211,9 +1211,7 @@ void ExecutionEngine::emitGlobals() { } // If the existing global is strong, never replace it. - if (GVEntry->hasExternalLinkage() || - GVEntry->hasDLLImportLinkage() || - GVEntry->hasDLLExportLinkage()) + if (GVEntry->hasExternalLinkage()) continue; // Otherwise, we know it's linkonce/weak, replace it if this is a strong diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index 2d34eea..db3dead 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -43,6 +43,11 @@ inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) { return reinterpret_cast<LLVMTargetLibraryInfoRef>(X); } +inline LLVMTargetMachineRef wrap(const TargetMachine *P) { + return + reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P)); +} + /*===-- Operations on generic values --------------------------------------===*/ LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, @@ -323,6 +328,11 @@ LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { return wrap(unwrap(EE)->getDataLayout()); } +LLVMTargetMachineRef +LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE) { + return wrap(unwrap(EE)->getTargetMachine()); +} + void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void* Addr) { unwrap(EE)->addGlobalMapping(unwrap<GlobalValue>(Global), Addr); @@ -350,17 +360,17 @@ public: SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions, void *Opaque); virtual ~SimpleBindingMemoryManager(); - - virtual uint8_t *allocateCodeSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName); - virtual uint8_t *allocateDataSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName, bool isReadOnly); + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override; + + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, + bool isReadOnly) override; + + bool finalizeMemory(std::string *ErrMsg) override; - virtual bool finalizeMemory(std::string *ErrMsg); - private: SimpleBindingMMFunctions Functions; void *Opaque; diff --git a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index 7dc295f..2ca4e3e 100644 --- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -16,11 +16,10 @@ #include "llvm/ExecutionEngine/JITEventListener.h" #define DEBUG_TYPE "amplifier-jit-event-listener" -#include "llvm/DebugInfo.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Metadata.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/ExecutionEngine/ObjectImage.h" @@ -28,7 +27,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Errno.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include "EventListenerCommon.h" #include "IntelJITEventsWrapper.h" @@ -40,7 +39,7 @@ namespace { class IntelJITEventListener : public JITEventListener { typedef DenseMap<void*, unsigned int> MethodIDMap; - OwningPtr<IntelJITEventsWrapper> Wrapper; + std::unique_ptr<IntelJITEventsWrapper> Wrapper; MethodIDMap MethodIDs; FilenameCache Filenames; diff --git a/lib/ExecutionEngine/IntelJITEvents/jitprofiling.h b/lib/ExecutionEngine/IntelJITEvents/jitprofiling.h index f08e287..8d16ee8 100644 --- a/lib/ExecutionEngine/IntelJITEvents/jitprofiling.h +++ b/lib/ExecutionEngine/IntelJITEvents/jitprofiling.h @@ -164,10 +164,10 @@ typedef struct _iJIT_Method_NIDS typedef struct _LineNumberInfo { - /* x86 Offset from the begining of the method*/ - unsigned int Offset; - - /* source line number from the begining of the source file */ + /* x86 Offset from the beginning of the method*/ + unsigned int Offset; + + /* source line number from the beginning of the source file */ unsigned int LineNumber; } *pLineNumberInfo, LineNumberInfo; @@ -191,9 +191,9 @@ typedef struct _iJIT_Method_Load unsigned int method_size; /* Line Table size in number of entries - Zero if none */ - unsigned int line_number_size; - - /* Pointer to the begining of the line numbers info array */ + unsigned int line_number_size; + + /* Pointer to the beginning of the line numbers info array */ pLineNumberInfo line_number_table; /* unique class ID */ diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 5de0659..8a80285 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -18,11 +18,11 @@ #include "llvm/CodeGen/IntrinsicLowering.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/MathExtras.h" #include <algorithm> #include <cmath> @@ -1120,7 +1120,7 @@ void Interpreter::visitCallSite(CallSite CS) { callFunction((Function*)GVTOP(SRC), ArgVals); } -// auxilary function for shift operations +// auxiliary function for shift operations static unsigned getShiftAmount(uint64_t orgShiftAmount, llvm::APInt valueToShift) { unsigned valueWidth = valueToShift.getBitWidth(); diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/lib/ExecutionEngine/Interpreter/Interpreter.cpp index 9ee9d94..6d4f6f7 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.cpp +++ b/lib/ExecutionEngine/Interpreter/Interpreter.cpp @@ -34,9 +34,12 @@ extern "C" void LLVMLinkInInterpreter() { } /// ExecutionEngine *Interpreter::create(Module *M, std::string* ErrStr) { // Tell this Module to materialize everything and release the GVMaterializer. - if (M->MaterializeAllPermanently(ErrStr)) + if (error_code EC = M->materializeAllPermanently()) { + if (ErrStr) + *ErrStr = EC.message(); // We got an error, just return 0 return 0; + } return new Interpreter(M); } diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 98269ef..2e93cae 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -16,10 +16,10 @@ #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" -#include "llvm/InstVisitor.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -112,11 +112,11 @@ public: /// run - Start execution with the specified function and arguments. /// - virtual GenericValue runFunction(Function *F, - const std::vector<GenericValue> &ArgValues); + GenericValue runFunction(Function *F, + const std::vector<GenericValue> &ArgValues) override; - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) override { // FIXME: not implemented. return 0; } @@ -124,13 +124,13 @@ public: /// recompileAndRelinkFunction - For the interpreter, functions are always /// up-to-date. /// - virtual void *recompileAndRelinkFunction(Function *F) { + void *recompileAndRelinkFunction(Function *F) override { return getPointerToFunction(F); } /// freeMachineCodeForFunction - The interpreter does not generate any code. /// - void freeMachineCodeForFunction(Function *F) { } + void freeMachineCodeForFunction(Function *F) override { } // Methods used to execute code: // Place a call on the stack @@ -212,8 +212,8 @@ private: // Helper functions // void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); - void *getPointerToFunction(Function *F) { return (void*)F; } - void *getPointerToBasicBlock(BasicBlock *BB) { return (void*)BB; } + void *getPointerToFunction(Function *F) override { return (void*)F; } + void *getPointerToBasicBlock(BasicBlock *BB) override { return (void*)BB; } void initializeExecutionEngine() { } void initializeExternalFunctions(); diff --git a/lib/ExecutionEngine/Interpreter/LLVMBuild.txt b/lib/ExecutionEngine/Interpreter/LLVMBuild.txt index 327b320..5af77e5 100644 --- a/lib/ExecutionEngine/Interpreter/LLVMBuild.txt +++ b/lib/ExecutionEngine/Interpreter/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = Interpreter parent = ExecutionEngine -required_libraries = CodeGen Core ExecutionEngine Support Target +required_libraries = CodeGen Core ExecutionEngine Support diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index 246a675..d3ad77b 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" @@ -151,7 +152,8 @@ JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, // Add target data MutexGuard locked(lock); FunctionPassManager &PM = jitstate->getPM(locked); - PM.add(new DataLayout(*TM.getDataLayout())); + M->setDataLayout(TM.getDataLayout()); + PM.add(new DataLayoutPass(M)); // Turn the machine code intermediate representation into bytes in memory that // may be executed. @@ -183,7 +185,8 @@ void JIT::addModule(Module *M) { jitstate = new JITState(M); FunctionPassManager &PM = jitstate->getPM(locked); - PM.add(new DataLayout(*TM.getDataLayout())); + M->setDataLayout(TM.getDataLayout()); + PM.add(new DataLayoutPass(M)); // Turn the machine code intermediate representation into bytes in memory // that may be executed. @@ -214,7 +217,8 @@ bool JIT::removeModule(Module *M) { jitstate = new JITState(Modules[0]); FunctionPassManager &PM = jitstate->getPM(locked); - PM.add(new DataLayout(*TM.getDataLayout())); + M->setDataLayout(TM.getDataLayout()); + PM.add(new DataLayoutPass(M)); // Turn the machine code intermediate representation into bytes in memory // that may be executed. @@ -446,9 +450,8 @@ void JIT::runJITOnFunction(Function *F, MachineCodeInfo *MCI) { MachineCodeInfo *const MCI; public: MCIListener(MachineCodeInfo *mci) : MCI(mci) {} - virtual void NotifyFunctionEmitted(const Function &, - void *Code, size_t Size, - const EmittedFunctionDetails &) { + void NotifyFunctionEmitted(const Function &, void *Code, size_t Size, + const EmittedFunctionDetails &) override { MCI->setAddress(Code); MCI->setSize(Size); } diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index 2ae155b..b1b0768 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -15,8 +15,8 @@ #define JIT_H #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/PassManager.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { @@ -106,16 +106,16 @@ public: RM, CMM); } - virtual void addModule(Module *M); + void addModule(Module *M) override; /// removeModule - Remove a Module from the list of modules. Returns true if /// M is found. - virtual bool removeModule(Module *M); + bool removeModule(Module *M) override; /// runFunction - Start execution with the specified function and arguments. /// - virtual GenericValue runFunction(Function *F, - const std::vector<GenericValue> &ArgValues); + GenericValue runFunction(Function *F, + const std::vector<GenericValue> &ArgValues) override; /// getPointerToNamedFunction - This method returns the address of the /// specified function by using the MemoryManager. As such it is only @@ -125,8 +125,8 @@ public: /// found, this function silently returns a null pointer. Otherwise, /// it prints a message to stderr and aborts. /// - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) override; // CompilationCallback - Invoked the first time that a call site is found, // which causes lazy compilation of the target function. @@ -136,7 +136,7 @@ public: /// getPointerToFunction - This returns the address of the specified function, /// compiling it if necessary. /// - void *getPointerToFunction(Function *F); + void *getPointerToFunction(Function *F) override; /// addPointerToBasicBlock - Adds address of the specific basic block. void addPointerToBasicBlock(const BasicBlock *BB, void *Addr); @@ -146,18 +146,18 @@ public: /// getPointerToBasicBlock - This returns the address of the specified basic /// block, assuming function is compiled. - void *getPointerToBasicBlock(BasicBlock *BB); + void *getPointerToBasicBlock(BasicBlock *BB) override; /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. - void *getOrEmitGlobalVariable(const GlobalVariable *GV); + void *getOrEmitGlobalVariable(const GlobalVariable *GV) override; /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. /// - void *getPointerToFunctionOrStub(Function *F); + void *getPointerToFunctionOrStub(Function *F) override; /// recompileAndRelinkFunction - This method is used to force a function /// which has already been compiled, to be compiled again, possibly @@ -165,12 +165,12 @@ public: /// with a branch to the new copy. If there was no old copy, this acts /// just like JIT::getPointerToFunction(). /// - void *recompileAndRelinkFunction(Function *F); + void *recompileAndRelinkFunction(Function *F) override; /// freeMachineCodeForFunction - deallocate memory used to code-generate this /// Function. /// - void freeMachineCodeForFunction(Function *F); + void freeMachineCodeForFunction(Function *F) override; /// addPendingFunction - while jitting non-lazily, a called but non-codegen'd /// function was encountered. Add it to a pending list to be processed after @@ -189,10 +189,13 @@ public: TargetMachine *TM); // Run the JIT on F and return information about the generated code - void runJITOnFunction(Function *F, MachineCodeInfo *MCI = 0); + void runJITOnFunction(Function *F, MachineCodeInfo *MCI = 0) override; + + void RegisterJITEventListener(JITEventListener *L) override; + void UnregisterJITEventListener(JITEventListener *L) override; + + TargetMachine *getTargetMachine() override { return &TM; } - virtual void RegisterJITEventListener(JITEventListener *L); - virtual void UnregisterJITEventListener(JITEventListener *L); /// These functions correspond to the methods on JITEventListener. They /// iterate over the registered listeners and call the corresponding method on /// each. @@ -217,7 +220,7 @@ private: protected: /// getMemoryforGV - Allocate memory for a global variable. - virtual char* getMemoryForGV(const GlobalVariable* GV); + char* getMemoryForGV(const GlobalVariable* GV) override; }; diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index acbbfa1..9d215ec 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -15,11 +15,9 @@ #define DEBUG_TYPE "jit" #include "JIT.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" -#include "llvm/ADT/ValueMap.h" #include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/CodeGen/MachineCodeInfo.h" #include "llvm/CodeGen/MachineConstantPool.h" @@ -27,21 +25,22 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRelocation.h" -#include "llvm/DebugInfo.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Disassembler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Memory.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetJITInfo.h" @@ -376,8 +375,8 @@ namespace { JITResolver &getJITResolver() { return Resolver; } - virtual void startFunction(MachineFunction &F); - virtual bool finishFunction(MachineFunction &F); + void startFunction(MachineFunction &F) override; + bool finishFunction(MachineFunction &F) override; void emitConstantPool(MachineConstantPool *MCP); void initJumpTableInfo(MachineJumpTableInfo *MJTI); @@ -387,24 +386,23 @@ namespace { unsigned StubSize, unsigned Alignment = 1); void startGVStub(void *Buffer, unsigned StubSize); void finishGVStub(); - virtual void *allocIndirectGV(const GlobalValue *GV, - const uint8_t *Buffer, size_t Size, - unsigned Alignment); + void *allocIndirectGV(const GlobalValue *GV, const uint8_t *Buffer, + size_t Size, unsigned Alignment) override; /// allocateSpace - Reserves space in the current block if any, or /// allocate a new one of the given size. - virtual void *allocateSpace(uintptr_t Size, unsigned Alignment); + void *allocateSpace(uintptr_t Size, unsigned Alignment) override; /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace, /// this method does not allocate memory in the current output buffer, /// because a global may live longer than the current function. - virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment); + void *allocateGlobal(uintptr_t Size, unsigned Alignment) override; - virtual void addRelocation(const MachineRelocation &MR) { + void addRelocation(const MachineRelocation &MR) override { Relocations.push_back(MR); } - virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { + void StartMachineBasicBlock(MachineBasicBlock *MBB) override { if (MBBLocations.size() <= (unsigned)MBB->getNumber()) MBBLocations.resize((MBB->getNumber()+1)*2); MBBLocations[MBB->getNumber()] = getCurrentPCValue(); @@ -415,10 +413,11 @@ namespace { << (void*) getCurrentPCValue() << "]\n"); } - virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const; - virtual uintptr_t getJumpTableEntryAddress(unsigned Entry) const; + uintptr_t getConstantPoolEntryAddress(unsigned Entry) const override; + uintptr_t getJumpTableEntryAddress(unsigned Entry) const override; - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const{ + uintptr_t + getMachineBasicBlockAddress(MachineBasicBlock *MBB) const override { assert(MBBLocations.size() > (unsigned)MBB->getNumber() && MBBLocations[MBB->getNumber()] && "MBB not emitted!"); return MBBLocations[MBB->getNumber()]; @@ -433,22 +432,22 @@ namespace { /// function body. void deallocateMemForFunction(const Function *F); - virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn); + void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) override; - virtual void emitLabel(MCSymbol *Label) { + void emitLabel(MCSymbol *Label) override { LabelLocations[Label] = getCurrentPCValue(); } - virtual DenseMap<MCSymbol*, uintptr_t> *getLabelLocations() { + DenseMap<MCSymbol*, uintptr_t> *getLabelLocations() override { return &LabelLocations; } - virtual uintptr_t getLabelAddress(MCSymbol *Label) const { + uintptr_t getLabelAddress(MCSymbol *Label) const override { assert(LabelLocations.count(Label) && "Label not emitted!"); return LabelLocations.find(Label)->second; } - virtual void setModuleInfo(MachineModuleInfo* Info) { + void setModuleInfo(MachineModuleInfo* Info) override { MMI = Info; } @@ -689,7 +688,7 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, return TheJIT->getOrEmitGlobalVariable(GV); if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) - return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); + return TheJIT->getPointerToGlobal(GA->getAliasedGlobal()); // If we have already compiled the function, return a pointer to its body. Function *F = cast<Function>(V); diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index f58d31b..0d1ea02 100644 --- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -274,8 +274,8 @@ namespace { public: JITSlabAllocator(DefaultJITMemoryManager &jmm) : JMM(jmm) { } virtual ~JITSlabAllocator() { } - virtual MemSlab *Allocate(size_t Size); - virtual void Deallocate(MemSlab *Slab); + MemSlab *Allocate(size_t Size) override; + void Deallocate(MemSlab *Slab) override; }; /// DefaultJITMemoryManager - Manage memory for the JIT code generation. @@ -285,7 +285,21 @@ namespace { /// middle of emitting a function, and we don't know how large the function we /// are emitting is. class DefaultJITMemoryManager : public JITMemoryManager { + public: + /// DefaultCodeSlabSize - When we have to go map more memory, we allocate at + /// least this much unless more is requested. Currently, in 512k slabs. + static const size_t DefaultCodeSlabSize = 512 * 1024; + + /// DefaultSlabSize - Allocate globals and stubs into slabs of 64K (probably + /// 16 pages) unless we get an allocation above SizeThreshold. + static const size_t DefaultSlabSize = 64 * 1024; + /// DefaultSizeThreshold - For any allocation larger than 16K (probably + /// 4 pages), we should allocate a separate slab to avoid wasted space at + /// the end of a normal slab. + static const size_t DefaultSizeThreshold = 16 * 1024; + + private: // Whether to poison freed memory. bool PoisonMemory; @@ -300,8 +314,8 @@ namespace { // confuse them with the blocks of memory described above. std::vector<sys::MemoryBlock> CodeSlabs; JITSlabAllocator BumpSlabAllocator; - BumpPtrAllocator StubAllocator; - BumpPtrAllocator DataAllocator; + BumpPtrAllocatorImpl<DefaultSlabSize, DefaultSizeThreshold> StubAllocator; + BumpPtrAllocatorImpl<DefaultSlabSize, DefaultSizeThreshold> DataAllocator; // Circular list of free blocks. FreeRangeHeader *FreeMemoryList; @@ -318,37 +332,26 @@ namespace { /// last slab it allocated, so that subsequent allocations follow it. sys::MemoryBlock allocateNewSlab(size_t size); - /// DefaultCodeSlabSize - When we have to go map more memory, we allocate at - /// least this much unless more is requested. - static const size_t DefaultCodeSlabSize; - - /// DefaultSlabSize - Allocate data into slabs of this size unless we get - /// an allocation above SizeThreshold. - static const size_t DefaultSlabSize; - - /// DefaultSizeThreshold - For any allocation larger than this threshold, we - /// should allocate a separate slab. - static const size_t DefaultSizeThreshold; - /// getPointerToNamedFunction - This method returns the address of the /// specified function by using the dlsym function call. - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) override; - void AllocateGOT(); + void AllocateGOT() override; // Testing methods. - virtual bool CheckInvariants(std::string &ErrorStr); - size_t GetDefaultCodeSlabSize() { return DefaultCodeSlabSize; } - size_t GetDefaultDataSlabSize() { return DefaultSlabSize; } - size_t GetDefaultStubSlabSize() { return DefaultSlabSize; } - unsigned GetNumCodeSlabs() { return CodeSlabs.size(); } - unsigned GetNumDataSlabs() { return DataAllocator.GetNumSlabs(); } - unsigned GetNumStubSlabs() { return StubAllocator.GetNumSlabs(); } + bool CheckInvariants(std::string &ErrorStr) override; + size_t GetDefaultCodeSlabSize() override { return DefaultCodeSlabSize; } + size_t GetDefaultDataSlabSize() override { return DefaultSlabSize; } + size_t GetDefaultStubSlabSize() override { return DefaultSlabSize; } + unsigned GetNumCodeSlabs() override { return CodeSlabs.size(); } + unsigned GetNumDataSlabs() override { return DataAllocator.GetNumSlabs(); } + unsigned GetNumStubSlabs() override { return StubAllocator.GetNumSlabs(); } /// startFunctionBody - When a function starts, allocate a block of free /// executable memory, returning a pointer to it and its actual size. - uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize) { + uint8_t *startFunctionBody(const Function *F, + uintptr_t &ActualSize) override { FreeRangeHeader* candidateBlock = FreeMemoryList; FreeRangeHeader* head = FreeMemoryList; @@ -422,7 +425,7 @@ namespace { /// endFunctionBody - The function F is now allocated, and takes the memory /// in the range [FunctionStart,FunctionEnd). void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { + uint8_t *FunctionEnd) override { assert(FunctionEnd > FunctionStart); assert(FunctionStart == (uint8_t *)(CurBlock+1) && "Mismatched function start/end!"); @@ -435,7 +438,7 @@ namespace { /// allocateSpace - Allocate a memory block of the given size. This method /// cannot be called between calls to startFunctionBody and endFunctionBody. - uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { + uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) override { CurBlock = FreeMemoryList; FreeMemoryList = FreeMemoryList->AllocateBlock(); @@ -453,18 +456,19 @@ namespace { /// allocateStub - Allocate memory for a function stub. uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) { + unsigned Alignment) override { return (uint8_t*)StubAllocator.Allocate(StubSize, Alignment); } /// allocateGlobal - Allocate memory for a global. - uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { + uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) override { return (uint8_t*)DataAllocator.Allocate(Size, Alignment); } /// allocateCodeSection - Allocate memory for a code section. uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, StringRef SectionName) { + unsigned SectionID, + StringRef SectionName) override { // Grow the required block size to account for the block header Size += sizeof(*CurBlock); @@ -511,15 +515,15 @@ namespace { /// allocateDataSection - Allocate memory for a data section. uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, - bool IsReadOnly) { + bool IsReadOnly) override { return (uint8_t*)DataAllocator.Allocate(Size, Alignment); } - bool finalizeMemory(std::string *ErrMsg) { + bool finalizeMemory(std::string *ErrMsg) override { return false; } - uint8_t *getGOTBase() const { + uint8_t *getGOTBase() const override { return GOTBase; } @@ -539,28 +543,26 @@ namespace { /// deallocateFunctionBody - Deallocate all memory for the specified /// function body. - void deallocateFunctionBody(void *Body) { + void deallocateFunctionBody(void *Body) override { if (Body) deallocateBlock(Body); } /// setMemoryWritable - When code generation is in progress, /// the code pages may need permissions changed. - void setMemoryWritable() - { + void setMemoryWritable() override { for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i) sys::Memory::setWritable(CodeSlabs[i]); } /// setMemoryExecutable - When code generation is done and we're ready to /// start execution, the code pages may need permissions changed. - void setMemoryExecutable() - { + void setMemoryExecutable() override { for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i) sys::Memory::setExecutable(CodeSlabs[i]); } /// setPoisonMemory - Controls whether we write garbage over freed memory. /// - void setPoisonMemory(bool poison) { + void setPoisonMemory(bool poison) override { PoisonMemory = poison; } }; @@ -588,8 +590,8 @@ DefaultJITMemoryManager::DefaultJITMemoryManager() #endif LastSlab(0, 0), BumpSlabAllocator(*this), - StubAllocator(DefaultSlabSize, DefaultSizeThreshold, BumpSlabAllocator), - DataAllocator(DefaultSlabSize, DefaultSizeThreshold, BumpSlabAllocator) { + StubAllocator(BumpSlabAllocator), + DataAllocator(BumpSlabAllocator) { // Allocate space for code. sys::MemoryBlock MemBlock = allocateNewSlab(DefaultCodeSlabSize); @@ -902,11 +904,6 @@ JITMemoryManager *JITMemoryManager::CreateDefaultMemManager() { return new DefaultJITMemoryManager(); } -// Allocate memory for code in 512K slabs. -const size_t DefaultJITMemoryManager::DefaultCodeSlabSize = 512 * 1024; - -// Allocate globals and stubs in slabs of 64K. (probably 16 pages) -const size_t DefaultJITMemoryManager::DefaultSlabSize = 64 * 1024; - -// Waste at most 16K at the end of each bump slab. (probably 4 pages) -const size_t DefaultJITMemoryManager::DefaultSizeThreshold = 16 * 1024; +const size_t DefaultJITMemoryManager::DefaultCodeSlabSize; +const size_t DefaultJITMemoryManager::DefaultSlabSize; +const size_t DefaultJITMemoryManager::DefaultSizeThreshold; diff --git a/lib/ExecutionEngine/JIT/LLVMBuild.txt b/lib/ExecutionEngine/JIT/LLVMBuild.txt index ca2a565..dd22f1b 100644 --- a/lib/ExecutionEngine/JIT/LLVMBuild.txt +++ b/lib/ExecutionEngine/JIT/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = JIT parent = ExecutionEngine -required_libraries = CodeGen Core ExecutionEngine MC RuntimeDyld Support Target +required_libraries = CodeGen Core ExecutionEngine Support diff --git a/lib/ExecutionEngine/LLVMBuild.txt b/lib/ExecutionEngine/LLVMBuild.txt index 1f94a4f..6dc75af 100644 --- a/lib/ExecutionEngine/LLVMBuild.txt +++ b/lib/ExecutionEngine/LLVMBuild.txt @@ -22,4 +22,4 @@ subdirectories = Interpreter JIT MCJIT RuntimeDyld IntelJITEvents OProfileJIT type = Library name = ExecutionEngine parent = Libraries -required_libraries = Core MC Support Target +required_libraries = Core MC Support diff --git a/lib/ExecutionEngine/MCJIT/LLVMBuild.txt b/lib/ExecutionEngine/MCJIT/LLVMBuild.txt index 900460b..90f4d2f 100644 --- a/lib/ExecutionEngine/MCJIT/LLVMBuild.txt +++ b/lib/ExecutionEngine/MCJIT/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = MCJIT parent = ExecutionEngine -required_libraries = Core ExecutionEngine RuntimeDyld Support Target JIT +required_libraries = Core ExecutionEngine RuntimeDyld Support Target diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 195c458..49b6727 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -14,17 +14,20 @@ #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/ObjectImage.h" -#include "llvm/PassManager.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/Object/Archive.h" +#include "llvm/PassManager.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MutexGuard.h" +#include "llvm/Target/TargetLowering.h" using namespace llvm; @@ -77,15 +80,24 @@ MCJIT::~MCJIT() { Modules.clear(); Dyld.deregisterEHFrames(); - LoadedObjectMap::iterator it, end = LoadedObjects.end(); - for (it = LoadedObjects.begin(); it != end; ++it) { - ObjectImage *Obj = it->second; + LoadedObjectList::iterator it, end; + for (it = LoadedObjects.begin(), end = LoadedObjects.end(); it != end; ++it) { + ObjectImage *Obj = *it; if (Obj) { NotifyFreeingObject(*Obj); delete Obj; } } LoadedObjects.clear(); + + + SmallVector<object::Archive *, 2>::iterator ArIt, ArEnd; + for (ArIt = Archives.begin(), ArEnd = Archives.end(); ArIt != ArEnd; ++ArIt) { + object::Archive *A = *ArIt; + delete A; + } + Archives.clear(); + delete TM; } @@ -101,6 +113,21 @@ bool MCJIT::removeModule(Module *M) { +void MCJIT::addObjectFile(object::ObjectFile *Obj) { + ObjectImage *LoadedObject = Dyld.loadObject(Obj); + if (!LoadedObject || Dyld.hasError()) + report_fatal_error(Dyld.getErrorString()); + + LoadedObjects.push_back(LoadedObject); + + NotifyObjectEmitted(*LoadedObject); +} + +void MCJIT::addArchive(object::Archive *A) { + Archives.push_back(A); +} + + void MCJIT::setObjectCache(ObjectCache* NewCache) { MutexGuard locked(lock); ObjCache = NewCache; @@ -115,10 +142,11 @@ ObjectBufferStream* MCJIT::emitObject(Module *M) { PassManager PM; - PM.add(new DataLayout(*TM->getDataLayout())); + M->setDataLayout(TM->getDataLayout()); + PM.add(new DataLayoutPass(M)); // The RuntimeDyld will take ownership of this shortly - OwningPtr<ObjectBufferStream> CompiledObject(new ObjectBufferStream()); + std::unique_ptr<ObjectBufferStream> CompiledObject(new ObjectBufferStream()); // Turn the machine code intermediate representation into bytes in memory // that may be executed. @@ -136,11 +164,11 @@ ObjectBufferStream* MCJIT::emitObject(Module *M) { if (ObjCache) { // MemoryBuffer is a thin wrapper around the actual memory, so it's OK // to create a temporary object here and delete it after the call. - OwningPtr<MemoryBuffer> MB(CompiledObject->getMemBuffer()); + std::unique_ptr<MemoryBuffer> MB(CompiledObject->getMemBuffer()); ObjCache->notifyObjectCompiled(M, MB.get()); } - return CompiledObject.take(); + return CompiledObject.release(); } void MCJIT::generateCodeForModule(Module *M) { @@ -155,12 +183,12 @@ void MCJIT::generateCodeForModule(Module *M) { if (OwnedModules.hasModuleBeenLoaded(M)) return; - OwningPtr<ObjectBuffer> ObjectToLoad; + std::unique_ptr<ObjectBuffer> ObjectToLoad; // Try to load the pre-compiled object from cache if possible if (0 != ObjCache) { - OwningPtr<MemoryBuffer> PreCompiledObject(ObjCache->getObject(M)); + std::unique_ptr<MemoryBuffer> PreCompiledObject(ObjCache->getObject(M)); if (0 != PreCompiledObject.get()) - ObjectToLoad.reset(new ObjectBuffer(PreCompiledObject.take())); + ObjectToLoad.reset(new ObjectBuffer(PreCompiledObject.release())); } // If the cache did not contain a suitable object, compile the object @@ -170,9 +198,9 @@ void MCJIT::generateCodeForModule(Module *M) { } // Load the object into the dynamic linker. - // MCJIT now owns the ObjectImage pointer (via its LoadedObjects map). - ObjectImage *LoadedObject = Dyld.loadObject(ObjectToLoad.take()); - LoadedObjects[M] = LoadedObject; + // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list). + ObjectImage *LoadedObject = Dyld.loadObject(ObjectToLoad.release()); + LoadedObjects.push_back(LoadedObject); if (!LoadedObject) report_fatal_error(Dyld.getErrorString()); @@ -231,11 +259,10 @@ void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { } uint64_t MCJIT::getExistingSymbolAddress(const std::string &Name) { - // Check with the RuntimeDyld to see if we already have this symbol. - if (Name[0] == '\1') - return Dyld.getSymbolLoadAddress(Name.substr(1)); - return Dyld.getSymbolLoadAddress((TM->getMCAsmInfo()->getGlobalPrefix() - + Name)); + Mangler Mang(TM->getDataLayout()); + SmallString<128> FullName; + Mang.getNameWithPrefix(FullName, Name); + return Dyld.getSymbolLoadAddress(FullName); } Module *MCJIT::findModuleForSymbol(const std::string &Name, @@ -271,6 +298,27 @@ uint64_t MCJIT::getSymbolAddress(const std::string &Name, if (Addr) return Addr; + SmallVector<object::Archive*, 2>::iterator I, E; + for (I = Archives.begin(), E = Archives.end(); I != E; ++I) { + object::Archive *A = *I; + // Look for our symbols in each Archive + object::Archive::child_iterator ChildIt = A->findSym(Name); + if (ChildIt != A->child_end()) { + std::unique_ptr<object::Binary> ChildBin; + // FIXME: Support nested archives? + if (!ChildIt->getAsBinary(ChildBin) && ChildBin->isObject()) { + object::ObjectFile *OF = reinterpret_cast<object::ObjectFile *>( + ChildBin.release()); + // This causes the object file to be loaded. + addObjectFile(OF); + // The address should be here now. + Addr = getExistingSymbolAddress(Name); + if (Addr) + return Addr; + } + } + } + // If it hasn't already been generated, see if it's in one of our modules. Module *M = findModuleForSymbol(Name, CheckFunctionsOnly); if (!M) @@ -320,15 +368,13 @@ void *MCJIT::getPointerToFunction(Function *F) { return NULL; // FIXME: Should the Dyld be retaining module information? Probably not. - // FIXME: Should we be using the mangler for this? Probably. // // This is the accessor for the target address, so make sure to check the // load address of the symbol, not the local address. - StringRef BaseName = F->getName(); - if (BaseName[0] == '\1') - return (void*)Dyld.getSymbolLoadAddress(BaseName.substr(1)); - return (void*)Dyld.getSymbolLoadAddress((TM->getMCAsmInfo()->getGlobalPrefix() - + BaseName).str()); + Mangler Mang(TM->getDataLayout()); + SmallString<128> Name; + TM->getNameWithPrefix(Name, F, Mang); + return (void*)Dyld.getSymbolLoadAddress(Name); } void *MCJIT::recompileAndRelinkFunction(Function *F) { diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index 86b478b..066eceb 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -31,43 +31,53 @@ public: LinkingMemoryManager(MCJIT *Parent, RTDyldMemoryManager *MM) : ParentEngine(Parent), ClientMM(MM) {} - virtual uint64_t getSymbolAddress(const std::string &Name); + uint64_t getSymbolAddress(const std::string &Name) override; // Functions deferred to client memory manager - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, StringRef SectionName) { + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override { return ClientMM->allocateCodeSection(Size, Alignment, SectionID, SectionName); } - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, StringRef SectionName, - bool IsReadOnly) { + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, + bool IsReadOnly) override { return ClientMM->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly); } - virtual void notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *Obj) { + void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO, + uintptr_t DataSizeRW) override { + return ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); + } + + bool needsToReserveAllocationSpace() override { + return ClientMM->needsToReserveAllocationSpace(); + } + + void notifyObjectLoaded(ExecutionEngine *EE, + const ObjectImage *Obj) override { ClientMM->notifyObjectLoaded(EE, Obj); } - virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) { + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override { ClientMM->registerEHFrames(Addr, LoadAddr, Size); } - virtual void deregisterEHFrames(uint8_t *Addr, - uint64_t LoadAddr, - size_t Size) { + void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override { ClientMM->deregisterEHFrames(Addr, LoadAddr, Size); } - virtual bool finalizeMemory(std::string *ErrMsg = 0) { + bool finalizeMemory(std::string *ErrMsg = 0) override { return ClientMM->finalizeMemory(ErrMsg); } private: MCJIT *ParentEngine; - OwningPtr<RTDyldMemoryManager> ClientMM; + std::unique_ptr<RTDyldMemoryManager> ClientMM; }; // About Module states: added->loaded->finalized. @@ -206,8 +216,10 @@ class MCJIT : public ExecutionEngine { OwningModuleContainer OwnedModules; - typedef DenseMap<Module *, ObjectImage *> LoadedObjectMap; - LoadedObjectMap LoadedObjects; + SmallVector<object::Archive*, 2> Archives; + + typedef SmallVector<ObjectImage *, 2> LoadedObjectList; + LoadedObjectList LoadedObjects; // An optional ObjectCache to be notified of compiled objects and used to // perform lookup of pre-compiled code to avoid re-compilation. @@ -226,18 +238,24 @@ public: /// @name ExecutionEngine interface implementation /// @{ - virtual void addModule(Module *M); - virtual bool removeModule(Module *M); + void addModule(Module *M) override; + void addObjectFile(object::ObjectFile *O) override; + void addArchive(object::Archive *O) override; + bool removeModule(Module *M) override; /// FindFunctionNamed - Search all of the active modules to find the one that /// defines FnName. This is very slow operation and shouldn't be used for /// general code. - virtual Function *FindFunctionNamed(const char *FnName); + Function *FindFunctionNamed(const char *FnName) override; /// Sets the object manager that MCJIT should use to avoid compilation. - virtual void setObjectCache(ObjectCache *manager); + void setObjectCache(ObjectCache *manager) override; + + void setProcessAllSections(bool ProcessAllSections) override { + Dyld.setProcessAllSections(ProcessAllSections); + } - virtual void generateCodeForModule(Module *M); + void generateCodeForModule(Module *M) override; /// finalizeObject - ensure the module is fully processed and is usable. /// @@ -248,7 +266,7 @@ public: /// object. /// Is it OK to finalize a set of modules, add modules and finalize again. // FIXME: Do we really need both of these? - virtual void finalizeObject(); + void finalizeObject() override; virtual void finalizeModule(Module *); void finalizeLoadedModules(); @@ -256,18 +274,18 @@ public: /// the static constructors or destructors for a program. /// /// \param isDtors - Run the destructors instead of constructors. - void runStaticConstructorsDestructors(bool isDtors); + void runStaticConstructorsDestructors(bool isDtors) override; - virtual void *getPointerToBasicBlock(BasicBlock *BB); + void *getPointerToBasicBlock(BasicBlock *BB) override; - virtual void *getPointerToFunction(Function *F); + void *getPointerToFunction(Function *F) override; - virtual void *recompileAndRelinkFunction(Function *F); + void *recompileAndRelinkFunction(Function *F) override; - virtual void freeMachineCodeForFunction(Function *F); + void freeMachineCodeForFunction(Function *F) override; - virtual GenericValue runFunction(Function *F, - const std::vector<GenericValue> &ArgValues); + GenericValue runFunction(Function *F, + const std::vector<GenericValue> &ArgValues) override; /// getPointerToNamedFunction - This method returns the address of the /// specified function by using the dlsym function call. As such it is only @@ -277,25 +295,27 @@ public: /// found, this function silently returns a null pointer. Otherwise, /// it prints a message to stderr and aborts. /// - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) override; /// mapSectionAddress - map a section to its target address space value. /// Map the address of a JIT section as returned from the memory manager /// to the address in the target process as the running code will see it. /// This is the address which will be used for relocation resolution. - virtual void mapSectionAddress(const void *LocalAddress, - uint64_t TargetAddress) { + void mapSectionAddress(const void *LocalAddress, + uint64_t TargetAddress) override { Dyld.mapSectionAddress(LocalAddress, TargetAddress); } - virtual void RegisterJITEventListener(JITEventListener *L); - virtual void UnregisterJITEventListener(JITEventListener *L); + void RegisterJITEventListener(JITEventListener *L) override; + void UnregisterJITEventListener(JITEventListener *L) override; // If successful, these function will implicitly finalize all loaded objects. // To get a function address within MCJIT without causing a finalize, use // getSymbolAddress. - virtual uint64_t getGlobalValueAddress(const std::string &Name); - virtual uint64_t getFunctionAddress(const std::string &Name); + uint64_t getGlobalValueAddress(const std::string &Name) override; + uint64_t getFunctionAddress(const std::string &Name) override; + + TargetMachine *getTargetMachine() override { return TM; } /// @} /// @name (Private) Registration Interfaces @@ -322,7 +342,7 @@ protected: /// emitObject -- Generate a JITed object in memory from the specified module /// Currently, MCJIT only supports a single module and the module passed to /// this function call is expected to be the contained module. The module - /// is passed as a parameter here to prepare for multiple module support in + /// is passed as a parameter here to prepare for multiple module support in /// the future. ObjectBufferStream* emitObject(Module *M); diff --git a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp index cf90e77..f1dd5a6 100644 --- a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp +++ b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp @@ -78,7 +78,7 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, sys::Memory::MF_WRITE, ec); if (ec) { - // FIXME: Add error propogation to the interface. + // FIXME: Add error propagation to the interface. return NULL; } diff --git a/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp index f11df82..87cef2e 100644 --- a/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp +++ b/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp @@ -16,9 +16,8 @@ #include "llvm/ExecutionEngine/JITEventListener.h" #define DEBUG_TYPE "oprofile-jit-event-listener" -#include "llvm/DebugInfo.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/OProfileWrapper.h" @@ -229,7 +228,8 @@ void OProfileJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { namespace llvm { JITEventListener *JITEventListener::createOProfileJITEventListener() { - static OwningPtr<OProfileWrapper> JITProfilingWrapper(new OProfileWrapper); + static std::unique_ptr<OProfileWrapper> JITProfilingWrapper( + new OProfileWrapper); return new OProfileJITEventListener(*JITProfilingWrapper); } diff --git a/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp b/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp index 61d8dc2..6702e20 100644 --- a/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp +++ b/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp @@ -15,12 +15,12 @@ #define DEBUG_TYPE "oprofile-wrapper" #include "llvm/ExecutionEngine/OProfileWrapper.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" #include <cstring> #include <dirent.h> #include <fcntl.h> diff --git a/lib/ExecutionEngine/RTDyldMemoryManager.cpp b/lib/ExecutionEngine/RTDyldMemoryManager.cpp index 26e1fdd..1646937 100644 --- a/lib/ExecutionEngine/RTDyldMemoryManager.cpp +++ b/lib/ExecutionEngine/RTDyldMemoryManager.cpp @@ -15,7 +15,6 @@ #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" - #include <cstdlib> #ifdef __linux__ diff --git a/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp b/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp index 603c526..1d0e9b3 100644 --- a/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp @@ -13,6 +13,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" +#include "llvm/Support/ManagedStatic.h" using namespace llvm; @@ -47,7 +48,13 @@ extern "C" { struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; // Debuggers puts a breakpoint in this function. - LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { } + LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { + // The noinline and the asm prevent calls to this function from being + // optimized out. +#if !defined(_MSC_VER) + asm volatile("":::"memory"); +#endif + } } @@ -78,12 +85,12 @@ public: /// Creates an entry in the JIT registry for the buffer @p Object, /// which must contain an object file in executable memory with any /// debug information for the debugger. - void registerObject(const ObjectBuffer &Object); + void registerObject(const ObjectBuffer &Object) override; /// Removes the internal registration of @p Object, and /// frees associated resources. /// Returns true if @p Object was found in ObjectBufferMap. - bool deregisterObject(const ObjectBuffer &Object); + bool deregisterObject(const ObjectBuffer &Object) override; private: /// Deregister the debug info for the given object file from the debugger @@ -96,9 +103,8 @@ private: /// modify global variables. llvm::sys::Mutex JITDebugLock; -/// Acquire the lock and do the registration. +/// Do the registration. void NotifyDebugger(jit_code_entry* JITCodeEntry) { - llvm::MutexGuard locked(JITDebugLock); __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; // Insert this entry at the head of the list. @@ -115,7 +121,8 @@ void NotifyDebugger(jit_code_entry* JITCodeEntry) { GDBJITRegistrar::~GDBJITRegistrar() { // Free all registered object files. - for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end(); + llvm::MutexGuard locked(JITDebugLock); + for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end(); I != E; ++I) { // Call the private method that doesn't update the map so our iterator // doesn't break. @@ -130,6 +137,7 @@ void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) { size_t Size = Object.getBufferSize(); assert(Buffer && "Attempt to register a null object with a debugger."); + llvm::MutexGuard locked(JITDebugLock); assert(ObjectBufferMap.find(Buffer) == ObjectBufferMap.end() && "Second attempt to perform debug registration."); jit_code_entry* JITCodeEntry = new jit_code_entry(); @@ -149,6 +157,7 @@ void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) { bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) { const char *Buffer = Object.getBufferStart(); + llvm::MutexGuard locked(JITDebugLock); RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer); if (I != ObjectBufferMap.end()) { @@ -164,9 +173,8 @@ void GDBJITRegistrar::deregisterObjectInternal( jit_code_entry*& JITCodeEntry = I->second.second; - // Acquire the lock and do the unregistration. + // Do the unregistration. { - llvm::MutexGuard locked(JITDebugLock); __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; // Remove the jit_code_entry from the linked list. @@ -193,22 +201,14 @@ void GDBJITRegistrar::deregisterObjectInternal( JITCodeEntry = NULL; } +llvm::ManagedStatic<GDBJITRegistrar> TheRegistrar; + } // end namespace namespace llvm { JITRegistrar& JITRegistrar::getGDBRegistrar() { - static GDBJITRegistrar* sRegistrar = NULL; - if (sRegistrar == NULL) { - // The mutex is here so that it won't slow down access once the registrar - // is instantiated - llvm::MutexGuard locked(JITDebugLock); - // Check again to be sure another thread didn't create this while we waited - if (sRegistrar == NULL) { - sRegistrar = new GDBJITRegistrar; - } - } - return *sRegistrar; + return *TheRegistrar; } } // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h b/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h index 9cbde5d..3693c69 100644 --- a/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h +++ b/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h @@ -1,6 +1,6 @@ //===-- ObjectImageCommon.h - Format independent executuable object image -===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. @@ -20,10 +20,14 @@ namespace llvm { +namespace object { + class ObjectFile; +} + class ObjectImageCommon : public ObjectImage { ObjectImageCommon(); // = delete ObjectImageCommon(const ObjectImageCommon &other); // = delete - virtual void anchor(); + void anchor() override; protected: object::ObjectFile *ObjFile; @@ -40,40 +44,42 @@ public: ObjectImageCommon(ObjectBuffer* Input) : ObjectImage(Input) // saves Input as Buffer and takes ownership { - ObjFile = object::ObjectFile::createObjectFile(Buffer->getMemBuffer()); + ObjFile = + object::ObjectFile::createObjectFile(Buffer->getMemBuffer()).get(); } + ObjectImageCommon(object::ObjectFile* Input) + : ObjectImage(NULL), ObjFile(Input) {} virtual ~ObjectImageCommon() { delete ObjFile; } - virtual object::symbol_iterator begin_symbols() const - { return ObjFile->begin_symbols(); } - virtual object::symbol_iterator end_symbols() const - { return ObjFile->end_symbols(); } + object::symbol_iterator begin_symbols() const override + { return ObjFile->symbol_begin(); } + object::symbol_iterator end_symbols() const override + { return ObjFile->symbol_end(); } - virtual object::section_iterator begin_sections() const - { return ObjFile->begin_sections(); } - virtual object::section_iterator end_sections() const - { return ObjFile->end_sections(); } + object::section_iterator begin_sections() const override + { return ObjFile->section_begin(); } + object::section_iterator end_sections() const override + { return ObjFile->section_end(); } - virtual /* Triple::ArchType */ unsigned getArch() const - { return ObjFile->getArch(); } + /* Triple::ArchType */ unsigned getArch() const override + { return ObjFile->getArch(); } - virtual StringRef getData() const { return ObjFile->getData(); } + StringRef getData() const override { return ObjFile->getData(); } - virtual object::ObjectFile* getObjectFile() const { return ObjFile; } + object::ObjectFile* getObjectFile() const override { return ObjFile; } // Subclasses can override these methods to update the image with loaded // addresses for sections and common symbols - virtual void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) {} - virtual void updateSymbolAddress(const object::SymbolRef &Sym, uint64_t Addr) - {} + void updateSectionAddress(const object::SectionRef &Sec, + uint64_t Addr) override {} + void updateSymbolAddress(const object::SymbolRef &Sym, + uint64_t Addr) override {} // Subclasses can override these methods to provide JIT debugging support - virtual void registerWithDebugger() {} - virtual void deregisterWithDebugger() {} + void registerWithDebugger() override {} + void deregisterWithDebugger() override {} }; } // end namespace llvm #endif // LLVM_RUNTIMEDYLD_OBJECT_IMAGE_H - diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 161135a..986d3a0 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -18,10 +18,9 @@ #include "RuntimeDyldELF.h" #include "RuntimeDyldImpl.h" #include "RuntimeDyldMachO.h" -#include "llvm/Support/FileSystem.h" +#include "llvm/Object/ELF.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Object/ELF.h" using namespace llvm; using namespace llvm::object; @@ -36,11 +35,9 @@ void ObjectImageCommon::anchor() {} namespace llvm { -void RuntimeDyldImpl::registerEHFrames() { -} +void RuntimeDyldImpl::registerEHFrames() {} -void RuntimeDyldImpl::deregisterEHFrames() { -} +void RuntimeDyldImpl::deregisterEHFrames() {} // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { @@ -56,9 +53,8 @@ void RuntimeDyldImpl::resolveRelocations() { // symbol for the relocation is located. The SectionID in the relocation // entry provides the section to which the relocation will be applied. uint64_t Addr = Sections[i].LoadAddress; - DEBUG(dbgs() << "Resolving relocations Section #" << i - << "\t" << format("%p", (uint8_t *)Addr) - << "\n"); + DEBUG(dbgs() << "Resolving relocations Section #" << i << "\t" + << format("%p", (uint8_t *)Addr) << "\n"); resolveRelocationList(Relocations[i], Addr); Relocations.erase(i); } @@ -76,22 +72,24 @@ void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress, llvm_unreachable("Attempting to remap address of unknown section!"); } -// Subclasses can implement this method to create specialized image instances. -// The caller owns the pointer that is returned. -ObjectImage *RuntimeDyldImpl::createObjectImage(ObjectBuffer *InputBuffer) { - return new ObjectImageCommon(InputBuffer); -} - -ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { +ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { MutexGuard locked(lock); - OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer)); - if (!obj) - report_fatal_error("Unable to create object image from memory buffer!"); + std::unique_ptr<ObjectImage> Obj(InputObject); + if (!Obj) + return NULL; // Save information about our target - Arch = (Triple::ArchType)obj->getArch(); - IsTargetLittleEndian = obj->getObjectFile()->isLittleEndian(); + Arch = (Triple::ArchType)Obj->getArch(); + IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian(); + + // Compute the memory size required to load all sections to be loaded + // and pass this information to the memory manager + if (MemMgr->needsToReserveAllocationSpace()) { + uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; + computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW); + MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); + } // Symbols found in this object StringMap<SymbolLoc> LocalSymbols; @@ -103,29 +101,26 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { // Maximum required total memory to allocate all common symbols uint64_t CommonSize = 0; - error_code err; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); - for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols(); - i != e; i.increment(err)) { - Check(err); + for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E; + ++I) { object::SymbolRef::Type SymType; StringRef Name; - Check(i->getType(SymType)); - Check(i->getName(Name)); + Check(I->getType(SymType)); + Check(I->getName(Name)); - uint32_t flags; - Check(i->getFlags(flags)); + uint32_t Flags = I->getFlags(); - bool isCommon = flags & SymbolRef::SF_Common; - if (isCommon) { + bool IsCommon = Flags & SymbolRef::SF_Common; + if (IsCommon) { // Add the common symbols to a list. We'll allocate them all below. uint32_t Align; - Check(i->getAlignment(Align)); + Check(I->getAlignment(Align)); uint64_t Size = 0; - Check(i->getSize(Size)); + Check(I->getSize(Size)); CommonSize += Size + Align; - CommonSymbols[*i] = CommonSymbolInfo(Size, Align); + CommonSymbols[*I] = CommonSymbolInfo(Size, Align); } else { if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || @@ -133,21 +128,22 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { uint64_t FileOffset; StringRef SectionData; bool IsCode; - section_iterator si = obj->end_sections(); - Check(i->getFileOffset(FileOffset)); - Check(i->getSection(si)); - if (si == obj->end_sections()) continue; - Check(si->getContents(SectionData)); - Check(si->isText(IsCode)); - const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + - (uintptr_t)FileOffset; - uintptr_t SectOffset = (uintptr_t)(SymPtr - - (const uint8_t*)SectionData.begin()); - unsigned SectionID = findOrEmitSection(*obj, *si, IsCode, LocalSections); + section_iterator SI = Obj->end_sections(); + Check(I->getFileOffset(FileOffset)); + Check(I->getSection(SI)); + if (SI == Obj->end_sections()) + continue; + Check(SI->getContents(SectionData)); + Check(SI->isText(IsCode)); + const uint8_t *SymPtr = + (const uint8_t *)Obj->getData().data() + (uintptr_t)FileOffset; + uintptr_t SectOffset = + (uintptr_t)(SymPtr - (const uint8_t *)SectionData.begin()); + unsigned SectionID = + findOrEmitSection(*Obj, *SI, IsCode, LocalSections); LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) - << " flags: " << flags - << " SID: " << SectionID + << " flags: " << Flags << " SID: " << SectionID << " Offset: " << format("%p", SectOffset)); GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); } @@ -157,39 +153,177 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { // Allocate common symbols if (CommonSize != 0) - emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols); + emitCommonSymbols(*Obj, CommonSymbols, CommonSize, LocalSymbols); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); - for (section_iterator si = obj->begin_sections(), - se = obj->end_sections(); si != se; si.increment(err)) { - Check(err); - bool isFirstRelocation = true; + for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections(); + SI != SE; ++SI) { unsigned SectionID = 0; StubMap Stubs; - section_iterator RelocatedSection = si->getRelocatedSection(); - - for (relocation_iterator i = si->begin_relocations(), - e = si->end_relocations(); i != e; i.increment(err)) { - Check(err); - - // If it's the first relocation in this section, find its SectionID - if (isFirstRelocation) { - SectionID = - findOrEmitSection(*obj, *RelocatedSection, true, LocalSections); - DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); - isFirstRelocation = false; - } + section_iterator RelocatedSection = SI->getRelocatedSection(); - processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols, - Stubs); - } + if (SI->relocation_empty() && !ProcessAllSections) + continue; + + bool IsCode = false; + Check(RelocatedSection->isText(IsCode)); + SectionID = + findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections); + DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); + + for (relocation_iterator I = SI->relocation_begin(), + E = SI->relocation_end(); I != E;) + I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols, + Stubs); } // Give the subclasses a chance to tie-up any loose ends. finalizeLoad(LocalSections); - return obj.take(); + return Obj.release(); +} + +// A helper method for computeTotalAllocSize. +// Computes the memory size required to allocate sections with the given sizes, +// assuming that all sections are allocated with the given alignment +static uint64_t +computeAllocationSizeForSections(std::vector<uint64_t> &SectionSizes, + uint64_t Alignment) { + uint64_t TotalSize = 0; + for (size_t Idx = 0, Cnt = SectionSizes.size(); Idx < Cnt; Idx++) { + uint64_t AlignedSize = + (SectionSizes[Idx] + Alignment - 1) / Alignment * Alignment; + TotalSize += AlignedSize; + } + return TotalSize; +} + +// Compute an upper bound of the memory size that is required to load all +// sections +void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, + uint64_t &CodeSize, + uint64_t &DataSizeRO, + uint64_t &DataSizeRW) { + // Compute the size of all sections required for execution + std::vector<uint64_t> CodeSectionSizes; + std::vector<uint64_t> ROSectionSizes; + std::vector<uint64_t> RWSectionSizes; + uint64_t MaxAlignment = sizeof(void *); + + // Collect sizes of all sections to be loaded; + // also determine the max alignment of all sections + for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + SI != SE; ++SI) { + const SectionRef &Section = *SI; + + bool IsRequired; + Check(Section.isRequiredForExecution(IsRequired)); + + // Consider only the sections that are required to be loaded for execution + if (IsRequired) { + uint64_t DataSize = 0; + uint64_t Alignment64 = 0; + bool IsCode = false; + bool IsReadOnly = false; + StringRef Name; + Check(Section.getSize(DataSize)); + Check(Section.getAlignment(Alignment64)); + Check(Section.isText(IsCode)); + Check(Section.isReadOnlyData(IsReadOnly)); + Check(Section.getName(Name)); + unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; + + uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section); + uint64_t SectionSize = DataSize + StubBufSize; + + // The .eh_frame section (at least on Linux) needs an extra four bytes + // padded + // with zeroes added at the end. For MachO objects, this section has a + // slightly different name, so this won't have any effect for MachO + // objects. + if (Name == ".eh_frame") + SectionSize += 4; + + if (SectionSize > 0) { + // save the total size of the section + if (IsCode) { + CodeSectionSizes.push_back(SectionSize); + } else if (IsReadOnly) { + ROSectionSizes.push_back(SectionSize); + } else { + RWSectionSizes.push_back(SectionSize); + } + // update the max alignment + if (Alignment > MaxAlignment) { + MaxAlignment = Alignment; + } + } + } + } + + // Compute the size of all common symbols + uint64_t CommonSize = 0; + for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; + ++I) { + uint32_t Flags = I->getFlags(); + if (Flags & SymbolRef::SF_Common) { + // Add the common symbols to a list. We'll allocate them all below. + uint64_t Size = 0; + Check(I->getSize(Size)); + CommonSize += Size; + } + } + if (CommonSize != 0) { + RWSectionSizes.push_back(CommonSize); + } + + // Compute the required allocation space for each different type of sections + // (code, read-only data, read-write data) assuming that all sections are + // allocated with the max alignment. Note that we cannot compute with the + // individual alignments of the sections, because then the required size + // depends on the order, in which the sections are allocated. + CodeSize = computeAllocationSizeForSections(CodeSectionSizes, MaxAlignment); + DataSizeRO = computeAllocationSizeForSections(ROSectionSizes, MaxAlignment); + DataSizeRW = computeAllocationSizeForSections(RWSectionSizes, MaxAlignment); +} + +// compute stub buffer size for the given section +unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, + const SectionRef &Section) { + unsigned StubSize = getMaxStubSize(); + if (StubSize == 0) { + return 0; + } + // FIXME: this is an inefficient way to handle this. We should computed the + // necessary section allocation size in loadObject by walking all the sections + // once. + unsigned StubBufSize = 0; + for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + SI != SE; ++SI) { + section_iterator RelSecI = SI->getRelocatedSection(); + if (!(RelSecI == Section)) + continue; + + for (const RelocationRef &Reloc : SI->relocations()) { + (void)Reloc; + StubBufSize += StubSize; + } + } + + // Get section data size and alignment + uint64_t Alignment64; + uint64_t DataSize; + Check(Section.getSize(DataSize)); + Check(Section.getAlignment(Alignment64)); + + // Add stubbuf size alignment + unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; + unsigned StubAlignment = getStubAlignment(); + unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment); + if (StubAlignment > EndAlignment) + StubBufSize += StubAlignment - EndAlignment; + return StubBufSize; } void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, @@ -198,22 +332,20 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, SymbolTableMap &SymbolTable) { // Allocate memory for the section unsigned SectionID = Sections.size(); - uint8_t *Addr = MemMgr->allocateDataSection( - TotalSize, sizeof(void*), SectionID, StringRef(), false); + uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void *), + SectionID, StringRef(), false); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; Sections.push_back(SectionEntry(StringRef(), Addr, TotalSize, 0)); memset(Addr, 0, TotalSize); - DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID - << " new addr: " << format("%p", Addr) - << " DataSize: " << TotalSize - << "\n"); + DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID << " new addr: " + << format("%p", Addr) << " DataSize: " << TotalSize << "\n"); // Assign the address of each symbol for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(), - itEnd = CommonSymbols.end(); it != itEnd; it++) { + itEnd = CommonSymbols.end(); it != itEnd; ++it) { uint64_t Size = it->second.first; uint64_t Align = it->second.second; StringRef Name; @@ -223,8 +355,8 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align); Addr += AlignOffset; Offset += AlignOffset; - DEBUG(dbgs() << "Allocating common symbol " << Name << " address " << - format("%p\n", Addr)); + DEBUG(dbgs() << "Allocating common symbol " << Name << " address " + << format("%p\n", Addr)); } Obj.updateSymbolAddress(it->first, (uint64_t)Addr); SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset); @@ -234,30 +366,7 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, } unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, - const SectionRef &Section, - bool IsCode) { - - unsigned StubBufSize = 0, - StubSize = getMaxStubSize(); - error_code err; - const ObjectFile *ObjFile = Obj.getObjectFile(); - // FIXME: this is an inefficient way to handle this. We should computed the - // necessary section allocation size in loadObject by walking all the sections - // once. - if (StubSize > 0) { - for (section_iterator SI = ObjFile->begin_sections(), - SE = ObjFile->end_sections(); - SI != SE; SI.increment(err), Check(err)) { - section_iterator RelSecI = SI->getRelocatedSection(); - if (!(RelSecI == Section)) - continue; - - for (relocation_iterator I = SI->begin_relocations(), - E = SI->end_relocations(); I != E; I.increment(err), Check(err)) { - StubBufSize += StubSize; - } - } - } + const SectionRef &Section, bool IsCode) { StringRef data; uint64_t Alignment64; @@ -271,6 +380,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, bool IsReadOnly; uint64_t DataSize; unsigned PaddingSize = 0; + unsigned StubBufSize = 0; StringRef Name; Check(Section.isRequiredForExecution(IsRequired)); Check(Section.isVirtual(IsVirtual)); @@ -278,12 +388,8 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, Check(Section.isReadOnlyData(IsReadOnly)); Check(Section.getSize(DataSize)); Check(Section.getName(Name)); - if (StubSize > 0) { - unsigned StubAlignment = getStubAlignment(); - unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment); - if (StubAlignment > EndAlignment) - StubBufSize += StubAlignment - EndAlignment; - } + + StubBufSize = computeSectionStubBufSize(Obj, Section); // The .eh_frame section (at least on Linux) needs an extra four bytes padded // with zeroes added at the end. For MachO objects, this section has a @@ -291,7 +397,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, if (Name == ".eh_frame") PaddingSize = 4; - unsigned Allocate; + uintptr_t Allocate; unsigned SectionID = Sections.size(); uint8_t *Addr; const char *pData = 0; @@ -300,10 +406,10 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, // Leave those where they are. if (IsRequired) { Allocate = DataSize + PaddingSize + StubBufSize; - Addr = IsCode - ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, Name) - : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, Name, - IsReadOnly); + Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, + Name) + : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, + Name, IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); @@ -324,30 +430,22 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, DataSize += PaddingSize; } - DEBUG(dbgs() << "emitSection SectionID: " << SectionID - << " Name: " << Name + DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", pData) << " new addr: " << format("%p", Addr) - << " DataSize: " << DataSize - << " StubBufSize: " << StubBufSize - << " Allocate: " << Allocate - << "\n"); + << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize + << " Allocate: " << Allocate << "\n"); Obj.updateSectionAddress(Section, (uint64_t)Addr); - } - else { + } else { // Even if we didn't load the section, we need to record an entry for it // to handle later processing (and by 'handle' I mean don't do anything // with these sections). Allocate = 0; Addr = 0; - DEBUG(dbgs() << "emitSection SectionID: " << SectionID - << " Name: " << Name - << " obj addr: " << format("%p", data.data()) - << " new addr: 0" - << " DataSize: " << DataSize - << " StubBufSize: " << StubBufSize - << " Allocate: " << Allocate - << "\n"); + DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name + << " obj addr: " << format("%p", data.data()) << " new addr: 0" + << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize + << " Allocate: " << Allocate << "\n"); } Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData)); @@ -380,8 +478,7 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE, // Relocation by symbol. If the symbol is found in the global symbol table, // create an appropriate section relocation. Otherwise, add it to // ExternalSymbolRelocations. - SymbolTableMap::const_iterator Loc = - GlobalSymbolTable.find(SymbolName); + SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(SymbolName); if (Loc == GlobalSymbolTable.end()) { ExternalSymbolRelocations[SymbolName].push_back(RE); } else { @@ -393,11 +490,11 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE, } uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { - if (Arch == Triple::aarch64) { + if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) { // This stub has to be able to access the full address space, // since symbol lookup won't necessarily find a handy, in-range, // PLT stub for functions which could be anywhere. - uint32_t *StubAddr = (uint32_t*)Addr; + uint32_t *StubAddr = (uint32_t *)Addr; // Stub can use ip0 (== x16) to calculate address *StubAddr = 0xd2e00010; // movz ip0, #:abs_g3:<addr> @@ -411,14 +508,14 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { *StubAddr = 0xd61f0200; // br ip0 return Addr; - } else if (Arch == Triple::arm) { + } else if (Arch == Triple::arm || Arch == Triple::armeb) { // TODO: There is only ARM far stub now. We should add the Thumb stub, // and stubs for branches Thumb - ARM and ARM - Thumb. - uint32_t *StubAddr = (uint32_t*)Addr; + uint32_t *StubAddr = (uint32_t *)Addr; *StubAddr = 0xe51ff004; // ldr pc,<label> - return (uint8_t*)++StubAddr; + return (uint8_t *)++StubAddr; } else if (Arch == Triple::mipsel || Arch == Triple::mips) { - uint32_t *StubAddr = (uint32_t*)Addr; + uint32_t *StubAddr = (uint32_t *)Addr; // 0: 3c190000 lui t9,%hi(addr). // 4: 27390000 addiu t9,t9,%lo(addr). // 8: 03200008 jr t9. @@ -496,29 +593,30 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs, } void RuntimeDyldImpl::resolveExternalSymbols() { - while(!ExternalSymbolRelocations.empty()) { + while (!ExternalSymbolRelocations.empty()) { StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin(); StringRef Name = i->first(); if (Name.size() == 0) { // This is an absolute symbol, use an address of zero. - DEBUG(dbgs() << "Resolving absolute relocations." << "\n"); + DEBUG(dbgs() << "Resolving absolute relocations." + << "\n"); RelocationList &Relocs = i->second; resolveRelocationList(Relocs, 0); } else { uint64_t Addr = 0; SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name); if (Loc == GlobalSymbolTable.end()) { - // This is an external symbol, try to get its address from - // MemoryManager. - Addr = MemMgr->getSymbolAddress(Name.data()); - // The call to getSymbolAddress may have caused additional modules to - // be loaded, which may have added new entries to the - // ExternalSymbolRelocations map. Consquently, we need to update our - // iterator. This is also why retrieval of the relocation list - // associated with this symbol is deferred until below this point. - // New entries may have been added to the relocation list. - i = ExternalSymbolRelocations.find(Name); + // This is an external symbol, try to get its address from + // MemoryManager. + Addr = MemMgr->getSymbolAddress(Name.data()); + // The call to getSymbolAddress may have caused additional modules to + // be loaded, which may have added new entries to the + // ExternalSymbolRelocations map. Consquently, we need to update our + // iterator. This is also why retrieval of the relocation list + // associated with this symbol is deferred until below this point. + // New entries may have been added to the relocation list. + i = ExternalSymbolRelocations.find(Name); } else { // We found the symbol in our global table. It was probably in a // Module that we loaded previously. @@ -529,12 +627,11 @@ void RuntimeDyldImpl::resolveExternalSymbols() { // FIXME: Implement error handling that doesn't kill the host program! if (!Addr) report_fatal_error("Program used external function '" + Name + - "' which could not be resolved!"); + "' which could not be resolved!"); updateGOTEntries(Name, Addr); - DEBUG(dbgs() << "Resolving relocations Name: " << Name - << "\t" << format("0x%lx", Addr) - << "\n"); + DEBUG(dbgs() << "Resolving relocations Name: " << Name << "\t" + << format("0x%lx", Addr) << "\n"); // This list may have been updated when we called getSymbolAddress, so // don't change this code to get the list earlier. RelocationList &Relocs = i->second; @@ -545,7 +642,6 @@ void RuntimeDyldImpl::resolveExternalSymbols() { } } - //===----------------------------------------------------------------------===// // RuntimeDyld class implementation RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { @@ -557,51 +653,89 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { // permissions are applied. Dyld = 0; MM = mm; + ProcessAllSections = false; +} + +RuntimeDyld::~RuntimeDyld() { delete Dyld; } + +static std::unique_ptr<RuntimeDyldELF> +createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections) { + std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM)); + Dyld->setProcessAllSections(ProcessAllSections); + return Dyld; } -RuntimeDyld::~RuntimeDyld() { - delete Dyld; +static std::unique_ptr<RuntimeDyldMachO> +createRuntimeDyldMachO(RTDyldMemoryManager *MM, bool ProcessAllSections) { + std::unique_ptr<RuntimeDyldMachO> Dyld(new RuntimeDyldMachO(MM)); + Dyld->setProcessAllSections(ProcessAllSections); + return Dyld; +} + +ObjectImage *RuntimeDyld::loadObject(ObjectFile *InputObject) { + std::unique_ptr<ObjectImage> InputImage; + + if (InputObject->isELF()) { + InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(InputObject)); + if (!Dyld) + Dyld = createRuntimeDyldELF(MM, ProcessAllSections).release(); + } else if (InputObject->isMachO()) { + InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(InputObject)); + if (!Dyld) + Dyld = createRuntimeDyldMachO(MM, ProcessAllSections).release(); + } else + report_fatal_error("Incompatible object format!"); + + if (!Dyld->isCompatibleFile(InputObject)) + report_fatal_error("Incompatible object format!"); + + Dyld->loadObject(InputImage.get()); + return InputImage.release(); } ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) { - if (!Dyld) { - sys::fs::file_magic Type = - sys::fs::identify_magic(InputBuffer->getBuffer()); - switch (Type) { - case sys::fs::file_magic::elf_relocatable: - case sys::fs::file_magic::elf_executable: - case sys::fs::file_magic::elf_shared_object: - case sys::fs::file_magic::elf_core: - Dyld = new RuntimeDyldELF(MM); - break; - case sys::fs::file_magic::macho_object: - case sys::fs::file_magic::macho_executable: - case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: - case sys::fs::file_magic::macho_core: - case sys::fs::file_magic::macho_preload_executable: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib: - case sys::fs::file_magic::macho_dynamic_linker: - case sys::fs::file_magic::macho_bundle: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: - case sys::fs::file_magic::macho_dsym_companion: - Dyld = new RuntimeDyldMachO(MM); - break; - case sys::fs::file_magic::unknown: - case sys::fs::file_magic::bitcode: - case sys::fs::file_magic::archive: - case sys::fs::file_magic::coff_object: - case sys::fs::file_magic::coff_import_library: - case sys::fs::file_magic::pecoff_executable: - case sys::fs::file_magic::macho_universal_binary: - case sys::fs::file_magic::windows_resource: - report_fatal_error("Incompatible object format!"); - } - } else { - if (!Dyld->isCompatibleFormat(InputBuffer)) - report_fatal_error("Incompatible object format!"); + std::unique_ptr<ObjectImage> InputImage; + sys::fs::file_magic Type = sys::fs::identify_magic(InputBuffer->getBuffer()); + + switch (Type) { + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::elf_executable: + case sys::fs::file_magic::elf_shared_object: + case sys::fs::file_magic::elf_core: + InputImage.reset(RuntimeDyldELF::createObjectImage(InputBuffer)); + if (!Dyld) + Dyld = createRuntimeDyldELF(MM, ProcessAllSections).release(); + break; + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::macho_executable: + case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: + case sys::fs::file_magic::macho_core: + case sys::fs::file_magic::macho_preload_executable: + case sys::fs::file_magic::macho_dynamically_linked_shared_lib: + case sys::fs::file_magic::macho_dynamic_linker: + case sys::fs::file_magic::macho_bundle: + case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: + case sys::fs::file_magic::macho_dsym_companion: + InputImage.reset(RuntimeDyldMachO::createObjectImage(InputBuffer)); + if (!Dyld) + Dyld = createRuntimeDyldMachO(MM, ProcessAllSections).release(); + break; + case sys::fs::file_magic::unknown: + case sys::fs::file_magic::bitcode: + case sys::fs::file_magic::archive: + case sys::fs::file_magic::coff_object: + case sys::fs::file_magic::coff_import_library: + case sys::fs::file_magic::pecoff_executable: + case sys::fs::file_magic::macho_universal_binary: + case sys::fs::file_magic::windows_resource: + report_fatal_error("Incompatible object format!"); } - return Dyld->loadObject(InputBuffer); + if (!Dyld->isCompatibleFormat(InputBuffer)) + report_fatal_error("Incompatible object format!"); + + Dyld->loadObject(InputImage.get()); + return InputImage.release(); } void *RuntimeDyld::getSymbolAddress(StringRef Name) { @@ -616,12 +750,9 @@ uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) { return Dyld->getSymbolLoadAddress(Name); } -void RuntimeDyld::resolveRelocations() { - Dyld->resolveRelocations(); -} +void RuntimeDyld::resolveRelocations() { Dyld->resolveRelocations(); } -void RuntimeDyld::reassignSectionAddress(unsigned SectionID, - uint64_t Addr) { +void RuntimeDyld::reassignSectionAddress(unsigned SectionID, uint64_t Addr) { Dyld->reassignSectionAddress(SectionID, Addr); } @@ -630,9 +761,9 @@ void RuntimeDyld::mapSectionAddress(const void *LocalAddress, Dyld->mapSectionAddress(LocalAddress, TargetAddress); } -StringRef RuntimeDyld::getErrorString() { - return Dyld->getErrorString(); -} +bool RuntimeDyld::hasError() { return Dyld->hasError(); } + +StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); } void RuntimeDyld::registerEHFrames() { if (Dyld) diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index f2c69fc..3204b81 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -16,7 +16,6 @@ #include "JITRegistrar.h" #include "ObjectImageCommon.h" #include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" @@ -25,35 +24,31 @@ #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/MemoryBuffer.h" + using namespace llvm; using namespace llvm::object; namespace { -static inline -error_code check(error_code Err) { +static inline error_code check(error_code Err) { if (Err) { report_fatal_error(Err.message()); } return Err; } -template<class ELFT> -class DyldELFObject - : public ELFObjectFile<ELFT> { +template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; typedef Elf_Sym_Impl<ELFT> Elf_Sym; - typedef - Elf_Rel_Impl<ELFT, false> Elf_Rel; - typedef - Elf_Rel_Impl<ELFT, true> Elf_Rela; + typedef Elf_Rel_Impl<ELFT, false> Elf_Rel; + typedef Elf_Rel_Impl<ELFT, true> Elf_Rela; typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr; - typedef typename ELFDataTypeTypedefHelper< - ELFT>::value_type addr_type; + typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type; public: DyldELFObject(MemoryBuffer *Wrapper, error_code &ec); @@ -63,84 +58,74 @@ public: // Methods for type inquiry through isa, cast and dyn_cast static inline bool classof(const Binary *v) { - return (isa<ELFObjectFile<ELFT> >(v) - && classof(cast<ELFObjectFile - <ELFT> >(v))); + return (isa<ELFObjectFile<ELFT>>(v) && + classof(cast<ELFObjectFile<ELFT>>(v))); } - static inline bool classof( - const ELFObjectFile<ELFT> *v) { + static inline bool classof(const ELFObjectFile<ELFT> *v) { return v->isDyldType(); } }; -template<class ELFT> -class ELFObjectImage : public ObjectImageCommon { - protected: - DyldELFObject<ELFT> *DyldObj; - bool Registered; - - public: - ELFObjectImage(ObjectBuffer *Input, - DyldELFObject<ELFT> *Obj) - : ObjectImageCommon(Input, Obj), - DyldObj(Obj), - Registered(false) {} - - virtual ~ELFObjectImage() { - if (Registered) - deregisterWithDebugger(); - } +template <class ELFT> class ELFObjectImage : public ObjectImageCommon { +protected: + DyldELFObject<ELFT> *DyldObj; + bool Registered; - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - virtual void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) - { - DyldObj->updateSectionAddress(Sec, Addr); - } +public: + ELFObjectImage(ObjectBuffer *Input, DyldELFObject<ELFT> *Obj) + : ObjectImageCommon(Input, Obj), DyldObj(Obj), Registered(false) {} - virtual void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) - { - DyldObj->updateSymbolAddress(Sym, Addr); - } + virtual ~ELFObjectImage() { + if (Registered) + deregisterWithDebugger(); + } - virtual void registerWithDebugger() - { - JITRegistrar::getGDBRegistrar().registerObject(*Buffer); - Registered = true; - } - virtual void deregisterWithDebugger() - { - JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer); - } + // Subclasses can override these methods to update the image with loaded + // addresses for sections and common symbols + void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) override { + DyldObj->updateSectionAddress(Sec, Addr); + } + + void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) override { + DyldObj->updateSymbolAddress(Sym, Addr); + } + + void registerWithDebugger() override { + JITRegistrar::getGDBRegistrar().registerObject(*Buffer); + Registered = true; + } + void deregisterWithDebugger() override { + JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer); + } }; // The MemoryBuffer passed into this constructor is just a wrapper around the // actual memory. Ultimately, the Binary parent class will take ownership of // this MemoryBuffer object but not the underlying memory. -template<class ELFT> +template <class ELFT> DyldELFObject<ELFT>::DyldELFObject(MemoryBuffer *Wrapper, error_code &ec) - : ELFObjectFile<ELFT>(Wrapper, ec) { + : ELFObjectFile<ELFT>(Wrapper, ec) { this->isDyldELFObject = true; } -template<class ELFT> +template <class ELFT> void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec, uint64_t Addr) { DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); - Elf_Shdr *shdr = const_cast<Elf_Shdr*>( - reinterpret_cast<const Elf_Shdr *>(ShdrRef.p)); + Elf_Shdr *shdr = + const_cast<Elf_Shdr *>(reinterpret_cast<const Elf_Shdr *>(ShdrRef.p)); // This assumes the address passed in matches the target address bitness // The template-based type cast handles everything else. shdr->sh_addr = static_cast<addr_type>(Addr); } -template<class ELFT> +template <class ELFT> void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr) { - Elf_Sym *sym = const_cast<Elf_Sym*>( - ELFObjectFile<ELFT>::getSymbol(SymRef.getRawDataRefImpl())); + Elf_Sym *sym = const_cast<Elf_Sym *>( + ELFObjectFile<ELFT>::getSymbol(SymRef.getRawDataRefImpl())); // This assumes the address passed in matches the target address bitness // The template-based type cast handles everything else. @@ -178,60 +163,85 @@ void RuntimeDyldELF::deregisterEHFrames() { RegisteredEHFrameSections.clear(); } +ObjectImage * +RuntimeDyldELF::createObjectImageFromFile(object::ObjectFile *ObjFile) { + if (!ObjFile) + return NULL; + + error_code ec; + MemoryBuffer *Buffer = + MemoryBuffer::getMemBuffer(ObjFile->getData(), "", false); + + if (ObjFile->getBytesInAddress() == 4 && ObjFile->isLittleEndian()) { + DyldELFObject<ELFType<support::little, 2, false>> *Obj = + new DyldELFObject<ELFType<support::little, 2, false>>(Buffer, ec); + return new ELFObjectImage<ELFType<support::little, 2, false>>(NULL, Obj); + } else if (ObjFile->getBytesInAddress() == 4 && !ObjFile->isLittleEndian()) { + DyldELFObject<ELFType<support::big, 2, false>> *Obj = + new DyldELFObject<ELFType<support::big, 2, false>>(Buffer, ec); + return new ELFObjectImage<ELFType<support::big, 2, false>>(NULL, Obj); + } else if (ObjFile->getBytesInAddress() == 8 && !ObjFile->isLittleEndian()) { + DyldELFObject<ELFType<support::big, 2, true>> *Obj = + new DyldELFObject<ELFType<support::big, 2, true>>(Buffer, ec); + return new ELFObjectImage<ELFType<support::big, 2, true>>(NULL, Obj); + } else if (ObjFile->getBytesInAddress() == 8 && ObjFile->isLittleEndian()) { + DyldELFObject<ELFType<support::little, 2, true>> *Obj = + new DyldELFObject<ELFType<support::little, 2, true>>(Buffer, ec); + return new ELFObjectImage<ELFType<support::little, 2, true>>(NULL, Obj); + } else + llvm_unreachable("Unexpected ELF format"); +} + ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) { if (Buffer->getBufferSize() < ELF::EI_NIDENT) llvm_unreachable("Unexpected ELF object size"); - std::pair<unsigned char, unsigned char> Ident = std::make_pair( - (uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS], - (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]); + std::pair<unsigned char, unsigned char> Ident = + std::make_pair((uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS], + (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]); error_code ec; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) { - DyldELFObject<ELFType<support::little, 4, false> > *Obj = - new DyldELFObject<ELFType<support::little, 4, false> >( - Buffer->getMemBuffer(), ec); - return new ELFObjectImage<ELFType<support::little, 4, false> >(Buffer, Obj); - } - else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) { - DyldELFObject<ELFType<support::big, 4, false> > *Obj = - new DyldELFObject<ELFType<support::big, 4, false> >( - Buffer->getMemBuffer(), ec); - return new ELFObjectImage<ELFType<support::big, 4, false> >(Buffer, Obj); - } - else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) { - DyldELFObject<ELFType<support::big, 8, true> > *Obj = - new DyldELFObject<ELFType<support::big, 8, true> >( - Buffer->getMemBuffer(), ec); - return new ELFObjectImage<ELFType<support::big, 8, true> >(Buffer, Obj); - } - else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { - DyldELFObject<ELFType<support::little, 8, true> > *Obj = - new DyldELFObject<ELFType<support::little, 8, true> >( - Buffer->getMemBuffer(), ec); - return new ELFObjectImage<ELFType<support::little, 8, true> >(Buffer, Obj); - } - else + DyldELFObject<ELFType<support::little, 4, false>> *Obj = + new DyldELFObject<ELFType<support::little, 4, false>>( + Buffer->getMemBuffer(), ec); + return new ELFObjectImage<ELFType<support::little, 4, false>>(Buffer, Obj); + } else if (Ident.first == ELF::ELFCLASS32 && + Ident.second == ELF::ELFDATA2MSB) { + DyldELFObject<ELFType<support::big, 4, false>> *Obj = + new DyldELFObject<ELFType<support::big, 4, false>>( + Buffer->getMemBuffer(), ec); + return new ELFObjectImage<ELFType<support::big, 4, false>>(Buffer, Obj); + } else if (Ident.first == ELF::ELFCLASS64 && + Ident.second == ELF::ELFDATA2MSB) { + DyldELFObject<ELFType<support::big, 8, true>> *Obj = + new DyldELFObject<ELFType<support::big, 8, true>>( + Buffer->getMemBuffer(), ec); + return new ELFObjectImage<ELFType<support::big, 8, true>>(Buffer, Obj); + } else if (Ident.first == ELF::ELFCLASS64 && + Ident.second == ELF::ELFDATA2LSB) { + DyldELFObject<ELFType<support::little, 8, true>> *Obj = + new DyldELFObject<ELFType<support::little, 8, true>>( + Buffer->getMemBuffer(), ec); + return new ELFObjectImage<ELFType<support::little, 8, true>>(Buffer, Obj); + } else llvm_unreachable("Unexpected ELF format"); } -RuntimeDyldELF::~RuntimeDyldELF() { -} +RuntimeDyldELF::~RuntimeDyldELF() {} void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend, + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend, uint64_t SymOffset) { switch (Type) { default: llvm_unreachable("Relocation type not implemented yet!"); - break; + break; case ELF::R_X86_64_64: { - uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset); + uint64_t *Target = reinterpret_cast<uint64_t *>(Section.Address + Offset); *Target = Value + Addend; - DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) - << " at " << format("%p\n",Target)); + DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at " + << format("%p\n", Target)); break; } case ELF::R_X86_64_32: @@ -239,20 +249,20 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, Value += Addend; assert((Type == ELF::R_X86_64_32 && (Value <= UINT32_MAX)) || (Type == ELF::R_X86_64_32S && - ((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN))); + ((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN))); uint32_t TruncatedAddr = (Value & 0xFFFFFFFF); - uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); + uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset); *Target = TruncatedAddr; - DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) - << " at " << format("%p\n",Target)); + DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at " + << format("%p\n", Target)); break; } case ELF::R_X86_64_GOTPCREL: { // findGOTEntry returns the 'G + GOT' part of the relocation calculation // based on the load/target address of the GOT (not the current/local addr). uint64_t GOTAddr = findGOTEntry(Value, SymOffset); - uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); - uint64_t FinalAddress = Section.LoadAddress + Offset; + uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset); + uint64_t FinalAddress = Section.LoadAddress + Offset; // The processRelocationRef method combines the symbol offset and the addend // and in most cases that's what we want. For this relocation type, we need // the raw addend, so we subtract the symbol offset to get it. @@ -265,10 +275,10 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, case ELF::R_X86_64_PC32: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version - uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress - + Offset); - uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); - uint64_t FinalAddress = Section.LoadAddress + Offset; + uint32_t *Placeholder = + reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); + uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset); + uint64_t FinalAddress = Section.LoadAddress + Offset; int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress; assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); @@ -278,10 +288,10 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, case ELF::R_X86_64_PC64: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version - uint64_t *Placeholder = reinterpret_cast<uint64_t*>(Section.ObjAddress - + Offset); - uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset); - uint64_t FinalAddress = Section.LoadAddress + Offset; + uint64_t *Placeholder = + reinterpret_cast<uint64_t *>(Section.ObjAddress + Offset); + uint64_t *Target = reinterpret_cast<uint64_t *>(Section.Address + Offset); + uint64_t FinalAddress = Section.LoadAddress + Offset; *Target = *Placeholder + Value + Addend - FinalAddress; break; } @@ -289,53 +299,48 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, } void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section, - uint64_t Offset, - uint32_t Value, - uint32_t Type, - int32_t Addend) { + uint64_t Offset, uint32_t Value, + uint32_t Type, int32_t Addend) { switch (Type) { case ELF::R_386_32: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version - uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress - + Offset); - uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); + uint32_t *Placeholder = + reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); + uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset); *Target = *Placeholder + Value + Addend; break; } case ELF::R_386_PC32: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version - uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress - + Offset); - uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset); - uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); + uint32_t *Placeholder = + reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); + uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset); + uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress; *Target = RealOffset; break; - } - default: - // There are other relocation types, but it appears these are the - // only ones currently used by the LLVM ELF object writer - llvm_unreachable("Relocation type not implemented yet!"); - break; + } + default: + // There are other relocation types, but it appears these are the + // only ones currently used by the LLVM ELF object writer + llvm_unreachable("Relocation type not implemented yet!"); + break; } } void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend) { - uint32_t *TargetPtr = reinterpret_cast<uint32_t*>(Section.Address + Offset); + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend) { + uint32_t *TargetPtr = reinterpret_cast<uint32_t *>(Section.Address + Offset); uint64_t FinalAddress = Section.LoadAddress + Offset; DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x" << format("%llx", Section.Address + Offset) - << " FinalAddress: 0x" << format("%llx",FinalAddress) - << " Value: 0x" << format("%llx",Value) - << " Type: 0x" << format("%x",Type) - << " Addend: 0x" << format("%llx",Addend) + << " FinalAddress: 0x" << format("%llx", FinalAddress) + << " Value: 0x" << format("%llx", Value) << " Type: 0x" + << format("%x", Type) << " Addend: 0x" << format("%llx", Addend) << "\n"); switch (Type) { @@ -343,7 +348,8 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, llvm_unreachable("Relocation type not implemented yet!"); break; case ELF::R_AARCH64_ABS64: { - uint64_t *TargetPtr = reinterpret_cast<uint64_t*>(Section.Address + Offset); + uint64_t *TargetPtr = + reinterpret_cast<uint64_t *>(Section.Address + Offset); *TargetPtr = Value + Addend; break; } @@ -419,35 +425,77 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, assert((*TargetPtr >> 21 & 0x3) == 0 && "invalid shift for relocation"); break; } + case ELF::R_AARCH64_ADR_PREL_PG_HI21: { + // Operation: Page(S+A) - Page(P) + uint64_t Result = + ((Value + Addend) & ~0xfffULL) - (FinalAddress & ~0xfffULL); + + // Check that -2^32 <= X < 2^32 + assert(static_cast<int64_t>(Result) >= (-1LL << 32) && + static_cast<int64_t>(Result) < (1LL << 32) && + "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)); + 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)); + break; + } + 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)); + break; + } } } void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, - uint64_t Offset, - uint32_t Value, - uint32_t Type, - int32_t Addend) { + uint64_t Offset, uint32_t Value, + uint32_t Type, int32_t Addend) { // TODO: Add Thumb relocations. - uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress + - Offset); - uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset); + uint32_t *Placeholder = + reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); + uint32_t *TargetPtr = (uint32_t *)(Section.Address + Offset); uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); Value += Addend; DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " << Section.Address + Offset - << " FinalAddress: " << format("%p",FinalAddress) - << " Value: " << format("%x",Value) - << " Type: " << format("%x",Type) - << " Addend: " << format("%x",Addend) - << "\n"); + << " FinalAddress: " << format("%p", FinalAddress) << " Value: " + << format("%x", Value) << " Type: " << format("%x", Type) + << " Addend: " << format("%x", Addend) << "\n"); - switch(Type) { + switch (Type) { default: llvm_unreachable("Not implemented relocation type!"); + case ELF::R_ARM_NONE: + break; // Write a 32bit value to relocation address, taking into account the // implicit addend encoded in the target. + case ELF::R_ARM_PREL31: case ELF::R_ARM_TARGET1: case ELF::R_ARM_ABS32: *TargetPtr = *Placeholder + Value; @@ -475,8 +523,8 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, *TargetPtr |= ((Value >> 12) & 0xF) << 16; break; // Write 24 bit relative value to the branch instruction. - case ELF::R_ARM_PC24 : // Fall through. - case ELF::R_ARM_CALL : // Fall through. + case ELF::R_ARM_PC24: // Fall through. + case ELF::R_ARM_CALL: // Fall through. case ELF::R_ARM_JUMP24: { int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8); RelValue = (RelValue & 0x03FFFFFC) >> 2; @@ -496,25 +544,20 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, } void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, - uint64_t Offset, - uint32_t Value, - uint32_t Type, - int32_t Addend) { - uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress + - Offset); - uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset); + uint64_t Offset, uint32_t Value, + uint32_t Type, int32_t Addend) { + uint32_t *Placeholder = + reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); + uint32_t *TargetPtr = (uint32_t *)(Section.Address + Offset); Value += Addend; DEBUG(dbgs() << "resolveMipselocation, LocalAddress: " - << Section.Address + Offset - << " FinalAddress: " - << format("%p",Section.LoadAddress + Offset) - << " Value: " << format("%x",Value) - << " Type: " << format("%x",Type) - << " Addend: " << format("%x",Addend) - << "\n"); + << Section.Address + Offset << " FinalAddress: " + << format("%p", Section.LoadAddress + Offset) << " Value: " + << format("%x", Value) << " Type: " << format("%x", Type) + << " Addend: " << format("%x", Addend) << "\n"); - switch(Type) { + switch (Type) { default: llvm_unreachable("Not implemented relocation type!"); break; @@ -522,13 +565,13 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, *TargetPtr = Value + (*Placeholder); break; case ELF::R_MIPS_26: - *TargetPtr = ((*Placeholder) & 0xfc000000) | (( Value & 0x0fffffff) >> 2); + *TargetPtr = ((*Placeholder) & 0xfc000000) | ((Value & 0x0fffffff) >> 2); break; case ELF::R_MIPS_HI16: // Get the higher 16-bits. Also add 1 if bit 15 is 1. Value += ((*Placeholder) & 0x0000ffff) << 16; - *TargetPtr = ((*Placeholder) & 0xffff0000) | - (((Value + 0x8000) >> 16) & 0xffff); + *TargetPtr = + ((*Placeholder) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); break; case ELF::R_MIPS_LO16: Value += ((*Placeholder) & 0x0000ffff); @@ -539,13 +582,13 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, // are used for internal JIT purpose. These relocations are similar to // R_MIPS_HI16 and R_MIPS_LO16, but they do not take any addend into // account. - *TargetPtr = ((*TargetPtr) & 0xffff0000) | - (((Value + 0x8000) >> 16) & 0xffff); + *TargetPtr = + ((*TargetPtr) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); break; case ELF::R_MIPS_UNUSED2: *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff); break; - } + } } // Return the .TOC. section address to R_PPC64_TOC relocations. @@ -555,9 +598,7 @@ uint64_t RuntimeDyldELF::findPPC64TOC() const { SectionList::const_iterator it = Sections.begin(); SectionList::const_iterator ite = Sections.end(); for (; it != ite; ++it) { - if (it->Name == ".got" || - it->Name == ".toc" || - it->Name == ".tocbss" || + if (it->Name == ".got" || it->Name == ".toc" || it->Name == ".tocbss" || it->Name == ".plt") break; } @@ -570,7 +611,7 @@ uint64_t RuntimeDyldELF::findPPC64TOC() const { // directly. it = Sections.begin(); } - assert (it != ite); + assert(it != ite); // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 // thus permitting a full 64 Kbytes segment. return it->LoadAddress + 0x8000; @@ -583,10 +624,8 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, RelocationValueRef &Rel) { // Get the ELF symbol value (st_value) to compare with Relocation offset in // .opd entries - - error_code err; - for (section_iterator si = Obj.begin_sections(), - se = Obj.end_sections(); si != se; si.increment(err)) { + for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections(); + si != se; ++si) { section_iterator RelSecI = si->getRelocatedSection(); if (RelSecI == Obj.end_sections()) continue; @@ -596,16 +635,15 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, if (RelSectionName != ".opd") continue; - for (relocation_iterator i = si->begin_relocations(), - e = si->end_relocations(); i != e;) { - check(err); - + for (relocation_iterator i = si->relocation_begin(), + e = si->relocation_end(); + i != e;) { // The R_PPC64_ADDR64 relocation indicates the first field // of a .opd entry uint64_t TypeFunc; check(i->getType(TypeFunc)); if (TypeFunc != ELF::R_PPC64_ADDR64) { - i.increment(err); + ++i; continue; } @@ -615,10 +653,9 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, int64_t Addend; check(getELFRelocationAddend(*i, Addend)); - i = i.increment(err); + ++i; if (i == e) break; - check(err); // Just check if following relocation is a R_PPC64_TOC uint64_t TypeTOC; @@ -634,7 +671,9 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, section_iterator tsi(Obj.end_sections()); check(TargetSymbol->getSection(tsi)); - Rel.SectionID = findOrEmitSection(Obj, (*tsi), true, LocalSections); + bool IsCode = false; + tsi->isText(IsCode); + Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections); Rel.Addend = (intptr_t)Addend; return; } @@ -646,65 +685,53 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, // and #highest(value) macros defined in section 4.5.1. Relocation Types // in PPC-elf64abi document. // -static inline -uint16_t applyPPClo (uint64_t value) -{ - return value & 0xffff; -} +static inline uint16_t applyPPClo(uint64_t value) { return value & 0xffff; } -static inline -uint16_t applyPPChi (uint64_t value) -{ +static inline uint16_t applyPPChi(uint64_t value) { return (value >> 16) & 0xffff; } -static inline -uint16_t applyPPChigher (uint64_t value) -{ +static inline uint16_t applyPPChigher(uint64_t value) { return (value >> 32) & 0xffff; } -static inline -uint16_t applyPPChighest (uint64_t value) -{ +static inline uint16_t applyPPChighest(uint64_t value) { return (value >> 48) & 0xffff; } void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend) { - uint8_t* LocalAddress = Section.Address + Offset; + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend) { + uint8_t *LocalAddress = Section.Address + Offset; switch (Type) { default: llvm_unreachable("Relocation type not implemented yet!"); - break; - case ELF::R_PPC64_ADDR16_LO : - writeInt16BE(LocalAddress, applyPPClo (Value + Addend)); break; - case ELF::R_PPC64_ADDR16_HI : - writeInt16BE(LocalAddress, applyPPChi (Value + Addend)); + case ELF::R_PPC64_ADDR16_LO: + writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); + break; + case ELF::R_PPC64_ADDR16_HI: + writeInt16BE(LocalAddress, applyPPChi(Value + Addend)); break; - case ELF::R_PPC64_ADDR16_HIGHER : - writeInt16BE(LocalAddress, applyPPChigher (Value + Addend)); + case ELF::R_PPC64_ADDR16_HIGHER: + writeInt16BE(LocalAddress, applyPPChigher(Value + Addend)); break; - case ELF::R_PPC64_ADDR16_HIGHEST : - writeInt16BE(LocalAddress, applyPPChighest (Value + Addend)); + case ELF::R_PPC64_ADDR16_HIGHEST: + writeInt16BE(LocalAddress, applyPPChighest(Value + Addend)); break; - case ELF::R_PPC64_ADDR14 : { + case ELF::R_PPC64_ADDR14: { assert(((Value + Addend) & 3) == 0); // Preserve the AA/LK bits in the branch instruction - uint8_t aalk = *(LocalAddress+3); + uint8_t aalk = *(LocalAddress + 3); writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc)); } break; - case ELF::R_PPC64_ADDR32 : { + case ELF::R_PPC64_ADDR32: { int32_t Result = static_cast<int32_t>(Value + Addend); if (SignExtend32<32>(Result) != Result) llvm_unreachable("Relocation R_PPC64_ADDR32 overflow"); writeInt32BE(LocalAddress, Result); } break; - case ELF::R_PPC64_REL24 : { + case ELF::R_PPC64_REL24: { uint64_t FinalAddress = (Section.LoadAddress + Offset); int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend); if (SignExtend32<24>(delta) != delta) @@ -712,7 +739,7 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, // Generates a 'bl <address>' instruction writeInt32BE(LocalAddress, 0x48000001 | (delta & 0x03FFFFFC)); } break; - case ELF::R_PPC64_REL32 : { + case ELF::R_PPC64_REL32: { uint64_t FinalAddress = (Section.LoadAddress + Offset); int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend); if (SignExtend32<32>(delta) != delta) @@ -724,18 +751,18 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, uint64_t Delta = Value - FinalAddress + Addend; writeInt64BE(LocalAddress, Delta); } break; - case ELF::R_PPC64_ADDR64 : + case ELF::R_PPC64_ADDR64: writeInt64BE(LocalAddress, Value + Addend); break; - case ELF::R_PPC64_TOC : + case ELF::R_PPC64_TOC: writeInt64BE(LocalAddress, findPPC64TOC()); break; - case ELF::R_PPC64_TOC16 : { + case ELF::R_PPC64_TOC16: { uint64_t TOCStart = findPPC64TOC(); Value = applyPPClo((Value + Addend) - TOCStart); writeInt16BE(LocalAddress, applyPPClo(Value)); } break; - case ELF::R_PPC64_TOC16_DS : { + case ELF::R_PPC64_TOC16_DS: { uint64_t TOCStart = findPPC64TOC(); Value = ((Value + Addend) - TOCStart); writeInt16BE(LocalAddress, applyPPClo(Value)); @@ -744,10 +771,8 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, } void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend) { + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend) { uint8_t *LocalAddress = Section.Address + Offset; switch (Type) { default: @@ -807,66 +832,61 @@ void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE, } void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend, + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend, uint64_t SymOffset) { switch (Arch) { case Triple::x86_64: resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset); break; case Triple::x86: - resolveX86Relocation(Section, Offset, - (uint32_t)(Value & 0xffffffffL), Type, + resolveX86Relocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; case Triple::aarch64: + case Triple::aarch64_be: resolveAArch64Relocation(Section, Offset, Value, Type, Addend); break; - case Triple::arm: // Fall through. + case Triple::arm: // Fall through. + case Triple::armeb: case Triple::thumb: - resolveARMRelocation(Section, Offset, - (uint32_t)(Value & 0xffffffffL), Type, + case Triple::thumbeb: + resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; - case Triple::mips: // Fall through. + case Triple::mips: // Fall through. case Triple::mipsel: - resolveMIPSRelocation(Section, Offset, - (uint32_t)(Value & 0xffffffffL), Type, - (uint32_t)(Addend & 0xffffffffL)); + resolveMIPSRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), + Type, (uint32_t)(Addend & 0xffffffffL)); break; - case Triple::ppc64: // Fall through. + case Triple::ppc64: // Fall through. case Triple::ppc64le: resolvePPC64Relocation(Section, Offset, Value, Type, Addend); break; case Triple::systemz: resolveSystemZRelocation(Section, Offset, Value, Type, Addend); break; - default: llvm_unreachable("Unsupported CPU type!"); + default: + llvm_unreachable("Unsupported CPU type!"); } } -void RuntimeDyldELF::processRelocationRef(unsigned SectionID, - RelocationRef RelI, - ObjectImage &Obj, - ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, - StubMap &Stubs) { +relocation_iterator RuntimeDyldELF::processRelocationRef( + unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, + ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, + StubMap &Stubs) { uint64_t RelType; - Check(RelI.getType(RelType)); + Check(RelI->getType(RelType)); int64_t Addend; - Check(getELFRelocationAddend(RelI, Addend)); - symbol_iterator Symbol = RelI.getSymbol(); + Check(getELFRelocationAddend(*RelI, Addend)); + symbol_iterator Symbol = RelI->getSymbol(); // Obtain the symbol name which is referenced in the relocation StringRef TargetName; if (Symbol != Obj.end_symbols()) Symbol->getName(TargetName); - DEBUG(dbgs() << "\t\tRelType: " << RelType - << " Addend: " << Addend - << " TargetName: " << TargetName - << "\n"); + DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend + << " TargetName: " << TargetName << "\n"); RelocationValueRef Value; // First search for the symbol in the local symbol table SymbolTableMap::const_iterator lsi = Symbols.end(); @@ -890,53 +910,48 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, Value.Addend = gsi->second.second + Addend; } else { switch (SymType) { - case SymbolRef::ST_Debug: { - // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously - // and can be changed by another developers. Maybe best way is add - // a new symbol type ST_Section to SymbolRef and use it. - section_iterator si(Obj.end_sections()); - Symbol->getSection(si); - if (si == Obj.end_sections()) - llvm_unreachable("Symbol section not found, bad object file format!"); - DEBUG(dbgs() << "\t\tThis is section symbol\n"); - // Default to 'true' in case isText fails (though it never does). - bool isCode = true; - si->isText(isCode); - Value.SectionID = findOrEmitSection(Obj, - (*si), - isCode, - ObjSectionToID); - Value.Addend = Addend; - break; - } - case SymbolRef::ST_Data: - case SymbolRef::ST_Unknown: { - Value.SymbolName = TargetName.data(); - Value.Addend = Addend; - - // Absolute relocations will have a zero symbol ID (STN_UNDEF), which - // will manifest here as a NULL symbol name. - // We can set this as a valid (but empty) symbol name, and rely - // on addRelocationForSymbol to handle this. - if (!Value.SymbolName) - Value.SymbolName = ""; - break; - } - default: - llvm_unreachable("Unresolved symbol type!"); - break; + case SymbolRef::ST_Debug: { + // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously + // and can be changed by another developers. Maybe best way is add + // a new symbol type ST_Section to SymbolRef and use it. + section_iterator si(Obj.end_sections()); + Symbol->getSection(si); + if (si == Obj.end_sections()) + llvm_unreachable("Symbol section not found, bad object file format!"); + DEBUG(dbgs() << "\t\tThis is section symbol\n"); + // Default to 'true' in case isText fails (though it never does). + bool isCode = true; + si->isText(isCode); + Value.SectionID = findOrEmitSection(Obj, (*si), isCode, ObjSectionToID); + Value.Addend = Addend; + break; + } + case SymbolRef::ST_Data: + case SymbolRef::ST_Unknown: { + Value.SymbolName = TargetName.data(); + Value.Addend = Addend; + + // Absolute relocations will have a zero symbol ID (STN_UNDEF), which + // will manifest here as a NULL symbol name. + // We can set this as a valid (but empty) symbol name, and rely + // on addRelocationForSymbol to handle this. + if (!Value.SymbolName) + Value.SymbolName = ""; + break; + } + default: + llvm_unreachable("Unresolved symbol type!"); + break; } } } uint64_t Offset; - Check(RelI.getOffset(Offset)); + Check(RelI->getOffset(Offset)); - DEBUG(dbgs() << "\t\tSectionID: " << SectionID - << " Offset: " << Offset + DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset << "\n"); if (Arch == Triple::aarch64 && - (RelType == ELF::R_AARCH64_CALL26 || - RelType == ELF::R_AARCH64_JUMP26)) { + (RelType == ELF::R_AARCH64_CALL26 || RelType == ELF::R_AARCH64_JUMP26)) { // This is an AArch64 branch relocation, need to use a stub function. DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation."); SectionEntry &Section = Sections[SectionID]; @@ -944,24 +959,21 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, // Look for an existing stub. StubMap::const_iterator i = Stubs.find(Value); if (i != Stubs.end()) { - resolveRelocation(Section, Offset, - (uint64_t)Section.Address + i->second, RelType, 0); + resolveRelocation(Section, Offset, (uint64_t)Section.Address + i->second, + RelType, 0); DEBUG(dbgs() << " Stub function found\n"); } else { // Create a new stub function. DEBUG(dbgs() << " Create a new stub function\n"); Stubs[Value] = Section.StubOffset; - uint8_t *StubTargetAddr = createStubFunction(Section.Address + - Section.StubOffset); + uint8_t *StubTargetAddr = + createStubFunction(Section.Address + Section.StubOffset); - RelocationEntry REmovz_g3(SectionID, - StubTargetAddr - Section.Address, + RelocationEntry REmovz_g3(SectionID, StubTargetAddr - Section.Address, ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend); - RelocationEntry REmovk_g2(SectionID, - StubTargetAddr - Section.Address + 4, + RelocationEntry REmovk_g2(SectionID, StubTargetAddr - Section.Address + 4, ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend); - RelocationEntry REmovk_g1(SectionID, - StubTargetAddr - Section.Address + 8, + RelocationEntry REmovk_g1(SectionID, StubTargetAddr - Section.Address + 8, ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend); RelocationEntry REmovk_g0(SectionID, StubTargetAddr - Section.Address + 12, @@ -979,14 +991,13 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, addRelocationForSection(REmovk_g0, Value.SectionID); } resolveRelocation(Section, Offset, - (uint64_t)Section.Address + Section.StubOffset, - RelType, 0); + (uint64_t)Section.Address + Section.StubOffset, RelType, + 0); Section.StubOffset += getMaxStubSize(); } } else if (Arch == Triple::arm && - (RelType == ELF::R_ARM_PC24 || - RelType == ELF::R_ARM_CALL || - RelType == ELF::R_ARM_JUMP24)) { + (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL || + RelType == ELF::R_ARM_JUMP24)) { // This is an ARM branch relocation, need to use a stub function. DEBUG(dbgs() << "\t\tThis is an ARM branch relocation."); SectionEntry &Section = Sections[SectionID]; @@ -994,15 +1005,15 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, // Look for an existing stub. StubMap::const_iterator i = Stubs.find(Value); if (i != Stubs.end()) { - resolveRelocation(Section, Offset, - (uint64_t)Section.Address + i->second, RelType, 0); + resolveRelocation(Section, Offset, (uint64_t)Section.Address + i->second, + RelType, 0); DEBUG(dbgs() << " Stub function found\n"); } else { // Create a new stub function. DEBUG(dbgs() << " Create a new stub function\n"); Stubs[Value] = Section.StubOffset; - uint8_t *StubTargetAddr = createStubFunction(Section.Address + - Section.StubOffset); + uint8_t *StubTargetAddr = + createStubFunction(Section.Address + Section.StubOffset); RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, ELF::R_ARM_PRIVATE_0, Value.Addend); if (Value.SymbolName) @@ -1011,8 +1022,8 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, addRelocationForSection(RE, Value.SectionID); resolveRelocation(Section, Offset, - (uint64_t)Section.Address + Section.StubOffset, - RelType, 0); + (uint64_t)Section.Address + Section.StubOffset, RelType, + 0); Section.StubOffset += getMaxStubSize(); } } else if ((Arch == Triple::mipsel || Arch == Triple::mips) && @@ -1038,15 +1049,13 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, // Create a new stub function. DEBUG(dbgs() << " Create a new stub function\n"); Stubs[Value] = Section.StubOffset; - uint8_t *StubTargetAddr = createStubFunction(Section.Address + - Section.StubOffset); + uint8_t *StubTargetAddr = + createStubFunction(Section.Address + Section.StubOffset); // Creating Hi and Lo relocations for the filled stub instructions. - RelocationEntry REHi(SectionID, - StubTargetAddr - Section.Address, + RelocationEntry REHi(SectionID, StubTargetAddr - Section.Address, ELF::R_MIPS_UNUSED1, Value.Addend); - RelocationEntry RELo(SectionID, - StubTargetAddr - Section.Address + 4, + RelocationEntry RELo(SectionID, StubTargetAddr - Section.Address + 4, ELF::R_MIPS_UNUSED2, Value.Addend); if (Value.SymbolName) { @@ -1070,7 +1079,8 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, uint8_t *Target = Section.Address + Offset; bool RangeOverflow = false; if (SymType != SymbolRef::ST_Unknown) { - // A function call may points to the .opd entry, so the final symbol value + // A function call may points to the .opd entry, so the final symbol + // value // in calculated based in the relocation values in .opd section. findOPDEntrySection(Obj, ObjSectionToID, Value); uint8_t *RelocTarget = Sections[Value.SectionID].Address + Value.Addend; @@ -1099,46 +1109,42 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, // Create a new stub function. DEBUG(dbgs() << " Create a new stub function\n"); Stubs[Value] = Section.StubOffset; - uint8_t *StubTargetAddr = createStubFunction(Section.Address + - Section.StubOffset); + uint8_t *StubTargetAddr = + createStubFunction(Section.Address + Section.StubOffset); RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, ELF::R_PPC64_ADDR64, Value.Addend); // Generates the 64-bits address loads as exemplified in section // 4.5.1 in PPC64 ELF ABI. - RelocationEntry REhst(SectionID, - StubTargetAddr - Section.Address + 2, + RelocationEntry REhst(SectionID, StubTargetAddr - Section.Address + 2, ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend); - RelocationEntry REhr(SectionID, - StubTargetAddr - Section.Address + 6, + RelocationEntry REhr(SectionID, StubTargetAddr - Section.Address + 6, ELF::R_PPC64_ADDR16_HIGHER, Value.Addend); - RelocationEntry REh(SectionID, - StubTargetAddr - Section.Address + 14, + RelocationEntry REh(SectionID, StubTargetAddr - Section.Address + 14, ELF::R_PPC64_ADDR16_HI, Value.Addend); - RelocationEntry REl(SectionID, - StubTargetAddr - Section.Address + 18, + RelocationEntry REl(SectionID, StubTargetAddr - Section.Address + 18, ELF::R_PPC64_ADDR16_LO, Value.Addend); if (Value.SymbolName) { addRelocationForSymbol(REhst, Value.SymbolName); - addRelocationForSymbol(REhr, Value.SymbolName); - addRelocationForSymbol(REh, Value.SymbolName); - addRelocationForSymbol(REl, Value.SymbolName); + addRelocationForSymbol(REhr, Value.SymbolName); + addRelocationForSymbol(REh, Value.SymbolName); + addRelocationForSymbol(REl, Value.SymbolName); } else { addRelocationForSection(REhst, Value.SectionID); - addRelocationForSection(REhr, Value.SectionID); - addRelocationForSection(REh, Value.SectionID); - addRelocationForSection(REl, Value.SectionID); + addRelocationForSection(REhr, Value.SectionID); + addRelocationForSection(REh, Value.SectionID); + addRelocationForSection(REl, Value.SectionID); } resolveRelocation(Section, Offset, (uint64_t)Section.Address + Section.StubOffset, RelType, 0); - if (SymType == SymbolRef::ST_Unknown) - // Restore the TOC for external calls - writeInt32BE(Target+4, 0xE8410028); // ld r2,40(r1) Section.StubOffset += getMaxStubSize(); } + if (SymType == SymbolRef::ST_Unknown) + // Restore the TOC for external calls + writeInt32BE(Target + 4, 0xE8410028); // ld r2,40(r1) } } else { RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); @@ -1153,8 +1159,7 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, addRelocationForSection(RE, Value.SectionID); } } else if (Arch == Triple::systemz && - (RelType == ELF::R_390_PLT32DBL || - RelType == ELF::R_390_GOTENT)) { + (RelType == ELF::R_390_PLT32DBL || RelType == ELF::R_390_GOTENT)) { // Create function stubs for both PLT and GOT references, regardless of // whether the GOT reference is to data or code. The stub contains the // full address of the symbol, as needed by GOT references, and the @@ -1179,14 +1184,14 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, uintptr_t BaseAddress = uintptr_t(Section.Address); uintptr_t StubAlignment = getStubAlignment(); - StubAddress = (BaseAddress + Section.StubOffset + - StubAlignment - 1) & -StubAlignment; + StubAddress = (BaseAddress + Section.StubOffset + StubAlignment - 1) & + -StubAlignment; unsigned StubOffset = StubAddress - BaseAddress; Stubs[Value] = StubOffset; createStubFunction((uint8_t *)StubAddress); - RelocationEntry RE(SectionID, StubOffset + 8, - ELF::R_390_64, Value.Addend - Addend); + RelocationEntry RE(SectionID, StubOffset + 8, ELF::R_390_64, + Value.Addend - Addend); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -1195,15 +1200,17 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, } if (RelType == ELF::R_390_GOTENT) - resolveRelocation(Section, Offset, StubAddress + 8, - ELF::R_390_PC32DBL, Addend); + resolveRelocation(Section, Offset, StubAddress + 8, ELF::R_390_PC32DBL, + Addend); else resolveRelocation(Section, Offset, StubAddress, RelType, Addend); } else if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_PLT32) { - // The way the PLT relocations normally work is that the linker allocates the + // The way the PLT relocations normally work is that the linker allocates + // the // PLT and this relocation makes a PC-relative call into the PLT. The PLT - // entry will then jump to an address provided by the GOT. On first call, the - // GOT address will point back into PLT code that resolves the symbol. After + // entry will then jump to an address provided by the GOT. On first call, + // the + // GOT address will point back into PLT code that resolves the symbol. After // the first call, the GOT entry points to the actual function. // // For local functions we're ignoring all of that here and just replacing @@ -1229,8 +1236,8 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, uintptr_t BaseAddress = uintptr_t(Section.Address); uintptr_t StubAlignment = getStubAlignment(); - StubAddress = (BaseAddress + Section.StubOffset + - StubAlignment - 1) & -StubAlignment; + StubAddress = (BaseAddress + Section.StubOffset + StubAlignment - 1) & + -StubAlignment; unsigned StubOffset = StubAddress - BaseAddress; Stubs[Value] = StubOffset; createStubFunction((uint8_t *)StubAddress); @@ -1239,8 +1246,8 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, GOTEntries.push_back(Value); // Make our stub function a relative call to the GOT entry. - RelocationEntry RE(SectionID, StubOffset + 2, - ELF::R_X86_64_GOTPCREL, -4); + RelocationEntry RE(SectionID, StubOffset + 2, ELF::R_X86_64_GOTPCREL, + -4); addRelocationForSymbol(RE, Value.SymbolName); // Bump our stub offset counter @@ -1248,8 +1255,8 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, } // Make the target call a call into the stub table. - resolveRelocation(Section, Offset, StubAddress, - ELF::R_X86_64_PC32, Addend); + resolveRelocation(Section, Offset, StubAddress, ELF::R_X86_64_PC32, + Addend); } else { RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend, Value.Offset); @@ -1265,12 +1272,13 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, else addRelocationForSection(RE, Value.SectionID); } + return ++RelI; } void RuntimeDyldELF::updateGOTEntries(StringRef Name, uint64_t Addr) { - SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator it; - SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator end = GOTs.end(); + SmallVectorImpl<std::pair<SID, GOTRelocations>>::iterator it; + SmallVectorImpl<std::pair<SID, GOTRelocations>>::iterator end = GOTs.end(); for (it = GOTs.begin(); it != end; ++it) { GOTRelocations &GOTEntries = it->second; @@ -1301,18 +1309,19 @@ size_t RuntimeDyldELF::getGOTEntrySize() { case Triple::mipsel: Result = sizeof(uint32_t); break; - default: llvm_unreachable("Unsupported CPU type!"); + default: + llvm_unreachable("Unsupported CPU type!"); } return Result; } -uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, - uint64_t Offset) { +uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) { const size_t GOTEntrySize = getGOTEntrySize(); - SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator it; - SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator end = GOTs.end(); + SmallVectorImpl<std::pair<SID, GOTRelocations>>::const_iterator it; + SmallVectorImpl<std::pair<SID, GOTRelocations>>::const_iterator end = + GOTs.end(); int GOTIndex = -1; for (it = GOTs.begin(); it != end; ++it) { @@ -1342,11 +1351,11 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, if (GOTIndex != -1) { if (GOTEntrySize == sizeof(uint64_t)) { - uint64_t *LocalGOTAddr = (uint64_t*)getSectionAddress(GOTSectionID); + uint64_t *LocalGOTAddr = (uint64_t *)getSectionAddress(GOTSectionID); // Fill in this entry with the address of the symbol being referenced. LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset; } else { - uint32_t *LocalGOTAddr = (uint32_t*)getSectionAddress(GOTSectionID); + uint32_t *LocalGOTAddr = (uint32_t *)getSectionAddress(GOTSectionID); // Fill in this entry with the address of the symbol being referenced. LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset); } @@ -1380,8 +1389,7 @@ void RuntimeDyldELF::finalizeLoad(ObjSectionToIDMap &SectionMap) { // needed when GOT-based relocations are applied. memset(Addr, 0, TotalSize); } - } - else { + } else { report_fatal_error("Unable to allocate memory for GOT!"); } @@ -1401,6 +1409,12 @@ void RuntimeDyldELF::finalizeLoad(ObjSectionToIDMap &SectionMap) { bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const { if (Buffer->getBufferSize() < strlen(ELF::ElfMagic)) return false; - return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; + return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, + strlen(ELF::ElfMagic))) == 0; } + +bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile *Obj) const { + return Obj->isELF(); +} + } // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 3adf827..27db5cd 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -22,67 +22,43 @@ using namespace llvm; namespace llvm { namespace { - // Helper for extensive error checking in debug builds. - error_code Check(error_code Err) { - if (Err) { - report_fatal_error(Err.message()); - } - return Err; +// Helper for extensive error checking in debug builds. +error_code Check(error_code Err) { + if (Err) { + report_fatal_error(Err.message()); } + return Err; +} } // end anonymous namespace class RuntimeDyldELF : public RuntimeDyldImpl { - void resolveRelocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend, - uint64_t SymOffset=0); - - void resolveX86_64Relocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend, + void resolveRelocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend, + uint64_t SymOffset = 0); + + void resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend, uint64_t SymOffset); - void resolveX86Relocation(const SectionEntry &Section, - uint64_t Offset, - uint32_t Value, - uint32_t Type, - int32_t Addend); - - void resolveAArch64Relocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend); - - 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 resolvePPC64Relocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend); - - void resolveSystemZRelocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend); - - unsigned getMaxStubSize() { + void resolveX86Relocation(const SectionEntry &Section, uint64_t Offset, + uint32_t Value, uint32_t Type, int32_t Addend); + + void resolveAArch64Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend); + + 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 resolvePPC64Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend); + + void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend); + + unsigned getMaxStubSize() override { if (Arch == Triple::aarch64) return 20; // movz; movk; movk; movk; br if (Arch == Triple::arm || Arch == Triple::thumb) @@ -99,7 +75,7 @@ class RuntimeDyldELF : public RuntimeDyldImpl { return 0; } - unsigned getStubAlignment() { + unsigned getStubAlignment() override { if (Arch == Triple::systemz) return 8; else @@ -107,16 +83,15 @@ class RuntimeDyldELF : public RuntimeDyldImpl { } uint64_t findPPC64TOC() const; - void findOPDEntrySection(ObjectImage &Obj, - ObjSectionToIDMap &LocalSections, + void findOPDEntrySection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset); size_t getGOTEntrySize(); - virtual void updateGOTEntries(StringRef Name, uint64_t Addr); + void updateGOTEntries(StringRef Name, uint64_t Addr) override; - // Relocation entries for symbols whose position-independant offset is + // Relocation entries for symbols whose position-independent offset is // updated in a global offset table. typedef SmallVector<RelocationValueRef, 2> GOTRelocations; GOTRelocations GOTEntries; // List of entries requiring finalization. @@ -129,22 +104,22 @@ class RuntimeDyldELF : public RuntimeDyldImpl { SmallVector<SID, 2> RegisteredEHFrameSections; public: - RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) - {} - - virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value); - virtual void processRelocationRef(unsigned SectionID, - RelocationRef RelI, - ObjectImage &Obj, - ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, - StubMap &Stubs); - virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const; - virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); - virtual void registerEHFrames(); - virtual void deregisterEHFrames(); - virtual void finalizeLoad(ObjSectionToIDMap &SectionMap); + RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} + + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override; + relocation_iterator + processRelocationRef(unsigned SectionID, relocation_iterator RelI, + ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, + const SymbolTableMap &Symbols, StubMap &Stubs) override; + bool isCompatibleFormat(const ObjectBuffer *Buffer) const override; + bool isCompatibleFile(const object::ObjectFile *Buffer) const override; + void registerEHFrames() override; + void deregisterEHFrames() override; + void finalizeLoad(ObjSectionToIDMap &SectionMap) override; virtual ~RuntimeDyldELF(); + + static ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); + static ObjectImage *createObjectImageFromFile(object::ObjectFile *Obj); }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 3014b30..c153ee1 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -39,7 +39,6 @@ namespace llvm { class ObjectBuffer; class Twine; - /// SectionEntry - represents a section emitted into memory by the dynamic /// linker. class SectionEntry { @@ -69,8 +68,9 @@ public: SectionEntry(StringRef name, uint8_t *address, size_t size, uintptr_t objAddress) - : Name(name), Address(address), Size(size), LoadAddress((uintptr_t)address), - StubOffset(size), ObjAddress(objAddress) {} + : Name(name), Address(address), Size(size), + LoadAddress((uintptr_t)address), StubOffset(size), + ObjAddress(objAddress) {} }; /// RelocationEntry - used to represent relocations internally in the dynamic @@ -101,33 +101,33 @@ public: unsigned Size; 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) {} + : SectionID(id), Offset(offset), RelType(type), Addend(addend), + SymOffset(0), IsPCRel(false), Size(0) {} 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) {} + : SectionID(id), Offset(offset), RelType(type), Addend(addend), + SymOffset(symoffset), IsPCRel(false), Size(0) {} 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) {} + : SectionID(id), Offset(offset), RelType(type), Addend(addend), + SymOffset(0), IsPCRel(IsPCRel), Size(Size) {} }; class RelocationValueRef { public: - unsigned SectionID; - uint64_t Offset; - int64_t Addend; + unsigned SectionID; + uint64_t Offset; + int64_t Addend; const char *SymbolName; - RelocationValueRef(): SectionID(0), Offset(0), Addend(0), SymbolName(0) {} + RelocationValueRef() : SectionID(0), Offset(0), Addend(0), SymbolName(0) {} inline bool operator==(const RelocationValueRef &Other) const { return SectionID == Other.SectionID && Offset == Other.Offset && Addend == Other.Addend && SymbolName == Other.SymbolName; } - inline bool operator <(const RelocationValueRef &Other) const { + inline bool operator<(const RelocationValueRef &Other) const { if (SectionID != Other.SectionID) return SectionID < Other.SectionID; if (Offset != Other.Offset) @@ -149,7 +149,7 @@ protected: SectionList Sections; typedef unsigned SID; // Type for SectionIDs - #define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) +#define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) // Keep a map of sections from object file to the SectionID which // references it. @@ -187,6 +187,10 @@ protected: Triple::ArchType Arch; bool IsTargetLittleEndian; + // True if all sections should be passed to the memory manager, false if only + // sections containing relocations should be. Defaults to 'false'. + bool ProcessAllSections; + // This mutex prevents simultaneously loading objects from two different // threads. This keeps us from having to protect individual data structures // and guarantees that section allocation requests to the memory manager @@ -217,52 +221,49 @@ protected: } uint8_t *getSectionAddress(unsigned SectionID) { - return (uint8_t*)Sections[SectionID].Address; + return (uint8_t *)Sections[SectionID].Address; } void writeInt16BE(uint8_t *Addr, uint16_t Value) { if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); - *Addr = (Value >> 8) & 0xFF; - *(Addr+1) = Value & 0xFF; + *Addr = (Value >> 8) & 0xFF; + *(Addr + 1) = Value & 0xFF; } void writeInt32BE(uint8_t *Addr, uint32_t Value) { if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); - *Addr = (Value >> 24) & 0xFF; - *(Addr+1) = (Value >> 16) & 0xFF; - *(Addr+2) = (Value >> 8) & 0xFF; - *(Addr+3) = Value & 0xFF; + *Addr = (Value >> 24) & 0xFF; + *(Addr + 1) = (Value >> 16) & 0xFF; + *(Addr + 2) = (Value >> 8) & 0xFF; + *(Addr + 3) = Value & 0xFF; } void writeInt64BE(uint8_t *Addr, uint64_t Value) { if (IsTargetLittleEndian) Value = sys::SwapByteOrder(Value); - *Addr = (Value >> 56) & 0xFF; - *(Addr+1) = (Value >> 48) & 0xFF; - *(Addr+2) = (Value >> 40) & 0xFF; - *(Addr+3) = (Value >> 32) & 0xFF; - *(Addr+4) = (Value >> 24) & 0xFF; - *(Addr+5) = (Value >> 16) & 0xFF; - *(Addr+6) = (Value >> 8) & 0xFF; - *(Addr+7) = Value & 0xFF; + *Addr = (Value >> 56) & 0xFF; + *(Addr + 1) = (Value >> 48) & 0xFF; + *(Addr + 2) = (Value >> 40) & 0xFF; + *(Addr + 3) = (Value >> 32) & 0xFF; + *(Addr + 4) = (Value >> 24) & 0xFF; + *(Addr + 5) = (Value >> 16) & 0xFF; + *(Addr + 6) = (Value >> 8) & 0xFF; + *(Addr + 7) = Value & 0xFF; } /// \brief Given the common symbols discovered in the object file, emit a /// new section for them and update the symbol mappings in the object and /// symbol table. - void emitCommonSymbols(ObjectImage &Obj, - const CommonSymbolMap &CommonSymbols, - uint64_t TotalSize, - SymbolTableMap &SymbolTable); + void emitCommonSymbols(ObjectImage &Obj, const CommonSymbolMap &CommonSymbols, + uint64_t TotalSize, SymbolTableMap &SymbolTable); /// \brief Emits section data from the object file to the MemoryManager. /// \param IsCode if it's true then allocateCodeSection() will be /// used for emits, else allocateDataSection() will be used. /// \return SectionID. - unsigned emitSection(ObjectImage &Obj, - const SectionRef &Section, + unsigned emitSection(ObjectImage &Obj, const SectionRef &Section, bool IsCode); /// \brief Find Section in LocalSections. If the secton is not found - emit @@ -270,10 +271,8 @@ protected: /// \param IsCode if it's true then allocateCodeSection() will be /// used for emmits, else allocateDataSection() will be used. /// \return SectionID. - unsigned findOrEmitSection(ObjectImage &Obj, - const SectionRef &Section, - bool IsCode, - ObjSectionToIDMap &LocalSections); + unsigned findOrEmitSection(ObjectImage &Obj, const SectionRef &Section, + bool IsCode, ObjSectionToIDMap &LocalSections); // \brief Add a relocation entry that uses the given section. void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID); @@ -284,7 +283,7 @@ protected: /// \brief Emits long jump instruction to Addr. /// \return Pointer to the memory area for emitting target address. - uint8_t* createStubFunction(uint8_t *Addr); + uint8_t *createStubFunction(uint8_t *Addr); /// \brief Resolves relocations from Relocs list with address from Value. void resolveRelocationList(const RelocationList &Relocs, uint64_t Value); @@ -294,14 +293,14 @@ protected: /// \param Value Target symbol address to apply the relocation action virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value) = 0; - /// \brief Parses the object file relocation and stores it to Relocations - /// or SymbolRelocations (this depends on the object file type). - virtual void processRelocationRef(unsigned SectionID, - RelocationRef RelI, - ObjectImage &Obj, - ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, - StubMap &Stubs) = 0; + /// \brief Parses one or more object file relocations (some object files use + /// relocation pairs) and stores it to Relocations or SymbolRelocations + /// (this depends on the object file type). + /// \return Iterator to the next relocation that needs to be parsed. + virtual relocation_iterator + processRelocationRef(unsigned SectionID, relocation_iterator RelI, + ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, + const SymbolTableMap &Symbols, StubMap &Stubs) = 0; /// \brief Resolve relocations to external symbols. void resolveExternalSymbols(); @@ -310,13 +309,26 @@ protected: // The base class does nothing. ELF overrides this. virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {} - virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); + // \brief Compute an upper bound of the memory that is required to load all + // sections + void computeTotalAllocSize(ObjectImage &Obj, uint64_t &CodeSize, + uint64_t &DataSizeRO, uint64_t &DataSizeRW); + + // \brief Compute the stub buffer size required for a section + unsigned computeSectionStubBufSize(ObjectImage &Obj, + const SectionRef &Section); + public: - RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {} + RuntimeDyldImpl(RTDyldMemoryManager *mm) + : MemMgr(mm), ProcessAllSections(false), HasError(false) {} virtual ~RuntimeDyldImpl(); - ObjectImage *loadObject(ObjectBuffer *InputBuffer); + void setProcessAllSections(bool ProcessAllSections) { + this->ProcessAllSections = ProcessAllSections; + } + + ObjectImage *loadObject(ObjectImage *InputObject); void *getSymbolAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. @@ -354,6 +366,7 @@ public: StringRef getErrorString() { return ErrorStr; } virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; + virtual bool isCompatibleFile(const ObjectFile *Obj) const = 0; virtual void registerEHFrames(); @@ -364,5 +377,4 @@ public: } // end namespace llvm - #endif diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 5b92867..7eae9c2 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -13,7 +13,6 @@ #define DEBUG_TYPE "dyld" #include "RuntimeDyldMachO.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" using namespace llvm; @@ -21,18 +20,19 @@ using namespace llvm::object; namespace llvm { -static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, intptr_t DeltaForEH) { - uint32_t Length = *((uint32_t*)P); +static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, + intptr_t DeltaForEH) { + uint32_t Length = *((uint32_t *)P); P += 4; unsigned char *Ret = P + Length; - uint32_t Offset = *((uint32_t*)P); + uint32_t Offset = *((uint32_t *)P); if (Offset == 0) // is a CIE return Ret; P += 4; - intptr_t FDELocation = *((intptr_t*)P); + intptr_t FDELocation = *((intptr_t *)P); intptr_t NewLocation = FDELocation - DeltaForText; - *((intptr_t*)P) = NewLocation; + *((intptr_t *)P) = NewLocation; P += sizeof(intptr_t); // Skip the FDE address range @@ -41,16 +41,16 @@ static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, intptr uint8_t Augmentationsize = *P; P += 1; if (Augmentationsize != 0) { - intptr_t LSDA = *((intptr_t*)P); + intptr_t LSDA = *((intptr_t *)P); intptr_t NewLSDA = LSDA - DeltaForEH; - *((intptr_t*)P) = NewLSDA; + *((intptr_t *)P) = NewLSDA; } return Ret; } static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { - intptr_t ObjDistance = A->ObjAddress - B->ObjAddress; + intptr_t ObjDistance = A->ObjAddress - B->ObjAddress; intptr_t MemDistance = A->LoadAddress - B->LoadAddress; return ObjDistance - MemDistance; } @@ -77,12 +77,11 @@ void RuntimeDyldMachO::registerEHFrames() { unsigned char *P = EHFrame->Address; unsigned char *End = P + EHFrame->Size; - do { + do { P = processFDE(P, DeltaForText, DeltaForEH); - } while(P != End); + } while (P != End); - MemMgr->registerEHFrames(EHFrame->Address, - EHFrame->LoadAddress, + MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, EHFrame->Size); } UnregisteredEHFrameSections.clear(); @@ -104,9 +103,8 @@ void RuntimeDyldMachO::finalizeLoad(ObjSectionToIDMap &SectionMap) { else if (Name == "__gcc_except_tab") ExceptTabSID = i->second; } - UnregisteredEHFrameSections.push_back(EHFrameRelatedSections(EHFrameSID, - TextSID, - ExceptTabSID)); + UnregisteredEHFrameSections.push_back( + EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); } // The target location for the relocation is described by RE.SectionID and @@ -137,67 +135,49 @@ void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE, } void RuntimeDyldMachO::resolveRelocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend, - bool isPCRel, - unsigned LogSize) { + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend, + bool isPCRel, unsigned LogSize) { uint8_t *LocalAddress = Section.Address + Offset; uint64_t FinalAddress = Section.LoadAddress + Offset; unsigned MachoType = Type; unsigned Size = 1 << LogSize; - DEBUG(dbgs() << "resolveRelocation LocalAddress: " - << format("%p", LocalAddress) - << " FinalAddress: " << format("%p", FinalAddress) - << " Value: " << format("%p", Value) - << " Addend: " << Addend - << " isPCRel: " << isPCRel - << " MachoType: " << MachoType - << " Size: " << Size - << "\n"); + DEBUG(dbgs() << "resolveRelocation LocalAddress: " + << format("%p", LocalAddress) + << " FinalAddress: " << format("%p", FinalAddress) + << " Value: " << format("%p", Value) << " Addend: " << Addend + << " isPCRel: " << isPCRel << " MachoType: " << MachoType + << " Size: " << Size << "\n"); // This just dispatches to the proper target specific routine. switch (Arch) { - default: llvm_unreachable("Unsupported CPU type!"); + default: + llvm_unreachable("Unsupported CPU type!"); case Triple::x86_64: - resolveX86_64Relocation(LocalAddress, - FinalAddress, - (uintptr_t)Value, - isPCRel, - MachoType, - Size, - Addend); + resolveX86_64Relocation(LocalAddress, FinalAddress, (uintptr_t)Value, + isPCRel, MachoType, Size, Addend); break; case Triple::x86: - resolveI386Relocation(LocalAddress, - FinalAddress, - (uintptr_t)Value, - isPCRel, - MachoType, - Size, - Addend); + resolveI386Relocation(LocalAddress, FinalAddress, (uintptr_t)Value, isPCRel, + MachoType, Size, Addend); break; - case Triple::arm: // Fall through. + case Triple::arm: // Fall through. case Triple::thumb: - resolveARMRelocation(LocalAddress, - FinalAddress, - (uintptr_t)Value, - isPCRel, - MachoType, - Size, - Addend); + resolveARMRelocation(LocalAddress, FinalAddress, (uintptr_t)Value, isPCRel, + MachoType, Size, Addend); + break; + case Triple::arm64: + resolveARM64Relocation(LocalAddress, FinalAddress, (uintptr_t)Value, + isPCRel, MachoType, Size, Addend); break; } } bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress, uint64_t FinalAddress, - uint64_t Value, - bool isPCRel, - unsigned Type, - unsigned Size, + uint64_t Value, bool isPCRel, + unsigned Type, unsigned Size, int64_t Addend) { if (isPCRel) Value -= FinalAddress + 4; // see resolveX86_64Relocation @@ -223,10 +203,8 @@ bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress, bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, uint64_t FinalAddress, - uint64_t Value, - bool isPCRel, - unsigned Type, - unsigned Size, + uint64_t Value, bool isPCRel, + unsigned Type, unsigned Size, int64_t Addend) { // If the relocation is PC-relative, the value to be encoded is the // pointer difference. @@ -235,7 +213,7 @@ bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, // address. Is that expected? Only for branches, perhaps? Value -= FinalAddress + 4; - switch(Type) { + switch (Type) { default: llvm_unreachable("Invalid relocation type!"); case MachO::X86_64_RELOC_SIGNED_1: @@ -247,7 +225,7 @@ bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, Value += Addend; // Mask in the target value a byte at a time (we don't have an alignment // guarantee for the target address, so this is safest). - uint8_t *p = (uint8_t*)LocalAddress; + uint8_t *p = (uint8_t *)LocalAddress; for (unsigned i = 0; i < Size; ++i) { *p++ = (uint8_t)Value; Value >>= 8; @@ -264,10 +242,8 @@ bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, uint64_t FinalAddress, - uint64_t Value, - bool isPCRel, - unsigned Type, - unsigned Size, + uint64_t Value, bool isPCRel, + unsigned Type, unsigned Size, int64_t Addend) { // If the relocation is PC-relative, the value to be encoded is the // pointer difference. @@ -279,13 +255,13 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, Value -= 8; } - switch(Type) { + switch (Type) { default: llvm_unreachable("Invalid relocation type!"); case MachO::ARM_RELOC_VANILLA: { // Mask in the target value a byte at a time (we don't have an alignment // guarantee for the target address, so this is safest). - uint8_t *p = (uint8_t*)LocalAddress; + uint8_t *p = (uint8_t *)LocalAddress; for (unsigned i = 0; i < Size; ++i) { *p++ = (uint8_t)Value; Value >>= 8; @@ -295,7 +271,7 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, case MachO::ARM_RELOC_BR24: { // Mask the value into the target address. We know instructions are // 32-bit aligned, so we can do it all at once. - uint32_t *p = (uint32_t*)LocalAddress; + uint32_t *p = (uint32_t *)LocalAddress; // The low two bits of the value are not encoded. Value >>= 2; // Mask the value to 24 bits. @@ -321,15 +297,63 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, return false; } -void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, - RelocationRef RelI, - ObjectImage &Obj, - ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, - StubMap &Stubs) { +bool RuntimeDyldMachO::resolveARM64Relocation(uint8_t *LocalAddress, + uint64_t FinalAddress, + uint64_t Value, bool isPCRel, + unsigned Type, unsigned Size, + int64_t Addend) { + // If the relocation is PC-relative, the value to be encoded is the + // pointer difference. + if (isPCRel) + Value -= FinalAddress; + + switch (Type) { + default: + llvm_unreachable("Invalid relocation type!"); + case MachO::ARM64_RELOC_UNSIGNED: { + // Mask in the target value a byte at a time (we don't have an alignment + // guarantee for the target address, so this is safest). + uint8_t *p = (uint8_t *)LocalAddress; + for (unsigned i = 0; i < Size; ++i) { + *p++ = (uint8_t)Value; + Value >>= 8; + } + break; + } + case MachO::ARM64_RELOC_BRANCH26: { + // Mask the value into the target address. We know instructions are + // 32-bit aligned, so we can do it all at once. + uint32_t *p = (uint32_t *)LocalAddress; + // The low two bits of the value are not encoded. + Value >>= 2; + // Mask the value to 26 bits. + Value &= 0x3ffffff; + // Insert the value into the instruction. + *p = (*p & ~0x3ffffff) | Value; + break; + } + case MachO::ARM64_RELOC_SUBTRACTOR: + case MachO::ARM64_RELOC_PAGE21: + case MachO::ARM64_RELOC_PAGEOFF12: + case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: + case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: + case MachO::ARM64_RELOC_POINTER_TO_GOT: + case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: + case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: + case MachO::ARM64_RELOC_ADDEND: + return Error("Relocation type not implemented yet!"); + } + return false; +} + +relocation_iterator RuntimeDyldMachO::processRelocationRef( + unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, + ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, + StubMap &Stubs) { const ObjectFile *OF = Obj.getObjectFile(); - const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF); - MachO::any_relocation_info RE= MachO->getRelocation(RelI.getRawDataRefImpl()); + const MachOObjectFile *MachO = static_cast<const MachOObjectFile *>(OF); + MachO::any_relocation_info RE = + MachO->getRelocation(RelI->getRawDataRefImpl()); uint32_t RelType = MachO->getAnyRelocationType(RE); @@ -340,7 +364,7 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, // Note: This will fail horribly where the relocations *do* need to be // applied, but that was already the case. if (MachO->isRelocationScattered(RE)) - return; + return ++RelI; RelocationValueRef Value; SectionEntry &Section = Sections[SectionID]; @@ -349,7 +373,7 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, bool IsPCRel = MachO->getAnyRelocationPCRel(RE); unsigned Size = MachO->getAnyRelocationLength(RE); uint64_t Offset; - RelI.getOffset(Offset); + RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; unsigned NumBytes = 1 << Size; uint64_t Addend = 0; @@ -357,7 +381,7 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, if (isExtern) { // Obtain the symbol name which is referenced in the relocation - symbol_iterator Symbol = RelI.getSymbol(); + symbol_iterator Symbol = RelI->getSymbol(); StringRef TargetName; Symbol->getName(TargetName); // First search for the symbol in the local symbol table @@ -367,7 +391,8 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, Value.Addend = lsi->second.second + Addend; } else { // Search for the symbol in the global symbol table - SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data()); + SymbolTableMap::const_iterator gsi = + GlobalSymbolTable.find(TargetName.data()); if (gsi != GlobalSymbolTable.end()) { Value.SectionID = gsi->second.first; Value.Addend = gsi->second.second + Addend; @@ -378,10 +403,14 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, } } else { SectionRef Sec = MachO->getRelocationSection(RE); - Value.SectionID = findOrEmitSection(Obj, Sec, true, ObjSectionToID); + bool IsCode = false; + Sec.isText(IsCode); + Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr; Sec.getAddress(Addr); Value.Addend = Addend - Addr; + if (IsPCRel) + Value.Addend += Offset + NumBytes; } if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT || @@ -406,21 +435,19 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, } resolveRelocation(Section, Offset, (uint64_t)Addr, MachO::X86_64_RELOC_UNSIGNED, Value.Addend, true, 2); - } else if (Arch == Triple::arm && - (RelType & 0xf) == MachO::ARM_RELOC_BR24) { + } else if (Arch == Triple::arm && (RelType & 0xf) == MachO::ARM_RELOC_BR24) { // This is an ARM branch relocation, need to use a stub function. // Look up for existing stub. StubMap::const_iterator i = Stubs.find(Value); if (i != Stubs.end()) - resolveRelocation(Section, Offset, - (uint64_t)Section.Address + i->second, + resolveRelocation(Section, Offset, (uint64_t)Section.Address + i->second, RelType, 0, IsPCRel, Size); else { // Create a new stub function. Stubs[Value] = Section.StubOffset; - uint8_t *StubTargetAddr = createStubFunction(Section.Address + - Section.StubOffset); + uint8_t *StubTargetAddr = + createStubFunction(Section.Address + Section.StubOffset); RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, MachO::GENERIC_RELOC_VANILLA, Value.Addend); if (Value.SymbolName) @@ -428,31 +455,38 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, else addRelocationForSection(RE, Value.SectionID); resolveRelocation(Section, Offset, - (uint64_t)Section.Address + Section.StubOffset, - RelType, 0, IsPCRel, Size); + (uint64_t)Section.Address + Section.StubOffset, RelType, + 0, IsPCRel, Size); Section.StubOffset += getMaxStubSize(); } } else { - RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, - IsPCRel, Size); + RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, IsPCRel, Size); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); } + return ++RelI; } - -bool RuntimeDyldMachO::isCompatibleFormat( - const ObjectBuffer *InputBuffer) const { +bool +RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const { if (InputBuffer->getBufferSize() < 4) return false; StringRef Magic(InputBuffer->getBufferStart(), 4); - if (Magic == "\xFE\xED\xFA\xCE") return true; - if (Magic == "\xCE\xFA\xED\xFE") return true; - if (Magic == "\xFE\xED\xFA\xCF") return true; - if (Magic == "\xCF\xFA\xED\xFE") return true; + if (Magic == "\xFE\xED\xFA\xCE") + return true; + if (Magic == "\xCE\xFA\xED\xFE") + return true; + if (Magic == "\xFE\xED\xFA\xCF") + return true; + if (Magic == "\xCF\xFA\xED\xFE") + return true; return false; } +bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const { + return Obj->isMachO(); +} + } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index bbf6aa9..1006176 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -14,6 +14,7 @@ #ifndef LLVM_RUNTIME_DYLD_MACHO_H #define LLVM_RUNTIME_DYLD_MACHO_H +#include "ObjectImageCommon.h" #include "RuntimeDyldImpl.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/Object/MachO.h" @@ -22,40 +23,26 @@ using namespace llvm; using namespace llvm::object; - namespace llvm { class RuntimeDyldMachO : public RuntimeDyldImpl { - bool resolveI386Relocation(uint8_t *LocalAddress, - uint64_t FinalAddress, - uint64_t Value, - bool isPCRel, - unsigned Type, - unsigned Size, - int64_t Addend); - bool resolveX86_64Relocation(uint8_t *LocalAddress, - uint64_t FinalAddress, - uint64_t Value, - bool isPCRel, - unsigned Type, - unsigned Size, - int64_t Addend); - bool resolveARMRelocation(uint8_t *LocalAddress, - uint64_t FinalAddress, - uint64_t Value, - bool isPCRel, - unsigned Type, - unsigned Size, - int64_t Addend); + bool resolveI386Relocation(uint8_t *LocalAddress, uint64_t FinalAddress, + uint64_t Value, bool isPCRel, unsigned Type, + unsigned Size, int64_t Addend); + bool resolveX86_64Relocation(uint8_t *LocalAddress, uint64_t FinalAddress, + uint64_t Value, bool isPCRel, unsigned Type, + unsigned Size, int64_t Addend); + bool resolveARMRelocation(uint8_t *LocalAddress, uint64_t FinalAddress, + uint64_t Value, bool isPCRel, unsigned Type, + unsigned Size, int64_t Addend); + bool resolveARM64Relocation(uint8_t *LocalAddress, uint64_t FinalAddress, + uint64_t Value, bool IsPCRel, unsigned Type, + unsigned Size, int64_t Addend); - void resolveRelocation(const SectionEntry &Section, - uint64_t Offset, - uint64_t Value, - uint32_t Type, - int64_t Addend, - bool isPCRel, - unsigned Size); + void resolveRelocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend, + bool isPCRel, unsigned Size); - unsigned getMaxStubSize() { + unsigned getMaxStubSize() override { if (Arch == Triple::arm || Arch == Triple::thumb) return 8; // 32-bit instruction and 32-bit address else if (Arch == Triple::x86_64) @@ -64,16 +51,15 @@ class RuntimeDyldMachO : public RuntimeDyldImpl { return 0; } - unsigned getStubAlignment() { - return 1; - } + unsigned getStubAlignment() override { return 1; } struct EHFrameRelatedSections { - EHFrameRelatedSections() : EHFrameSID(RTDYLD_INVALID_SECTION_ID), - TextSID(RTDYLD_INVALID_SECTION_ID), - ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {} - EHFrameRelatedSections(SID EH, SID T, SID Ex) - : EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {} + EHFrameRelatedSections() + : EHFrameSID(RTDYLD_INVALID_SECTION_ID), + TextSID(RTDYLD_INVALID_SECTION_ID), + ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {} + EHFrameRelatedSections(SID EH, SID T, SID Ex) + : EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {} SID EHFrameSID; SID TextSID; SID ExceptTabSID; @@ -83,19 +69,28 @@ class RuntimeDyldMachO : public RuntimeDyldImpl { // in a table until we receive a request to register all unregistered // EH frame sections with the memory manager. SmallVector<EHFrameRelatedSections, 2> UnregisteredEHFrameSections; + public: RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} - virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value); - virtual void processRelocationRef(unsigned SectionID, - RelocationRef RelI, - ObjectImage &Obj, - ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, - StubMap &Stubs); - virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const; - virtual void registerEHFrames(); - virtual void finalizeLoad(ObjSectionToIDMap &SectionMap); + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override; + relocation_iterator + processRelocationRef(unsigned SectionID, relocation_iterator RelI, + ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, + const SymbolTableMap &Symbols, StubMap &Stubs) override; + bool isCompatibleFormat(const ObjectBuffer *Buffer) const override; + bool isCompatibleFile(const object::ObjectFile *Obj) const override; + void registerEHFrames() override; + void finalizeLoad(ObjSectionToIDMap &SectionMap) override; + + static ObjectImage *createObjectImage(ObjectBuffer *InputBuffer) { + return new ObjectImageCommon(InputBuffer); + } + + static ObjectImage * + createObjectImageFromFile(object::ObjectFile *InputObject) { + return new ObjectImageCommon(InputObject); + } }; } // end namespace llvm |