diff options
| author | Nowar Gu <nowar100@gmail.com> | 2011-06-17 14:29:24 +0800 |
|---|---|---|
| committer | Nowar Gu <nowar100@gmail.com> | 2011-06-20 15:49:07 +0800 |
| commit | 907af0f20f58f2ea26da7ea64e1f094cd6880db7 (patch) | |
| tree | 02007757de416c561df174d582205cebfa582801 /lib/ExecutionEngine | |
| parent | 1d4f9a57447faa0142a1d0301e5ce550cfe60c4f (diff) | |
| parent | ec324e5ae44025c6bdb930b78198f30f807e355b (diff) | |
| download | external_llvm-907af0f20f58f2ea26da7ea64e1f094cd6880db7.zip external_llvm-907af0f20f58f2ea26da7ea64e1f094cd6880db7.tar.gz external_llvm-907af0f20f58f2ea26da7ea64e1f094cd6880db7.tar.bz2 | |
Merge upstream to r133240 at Fri. 17th Jun 2011.
Conflicts:
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/Target/ARM/ARMCodeEmitter.cpp
Diffstat (limited to 'lib/ExecutionEngine')
| -rw-r--r-- | lib/ExecutionEngine/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lib/ExecutionEngine/ExecutionEngine.cpp | 75 | ||||
| -rw-r--r-- | lib/ExecutionEngine/JIT/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lib/ExecutionEngine/JIT/JIT.cpp | 31 | ||||
| -rw-r--r-- | lib/ExecutionEngine/JIT/JIT.h | 13 | ||||
| -rw-r--r-- | lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp | 3 | ||||
| -rw-r--r-- | lib/ExecutionEngine/JIT/JITEmitter.cpp | 4 | ||||
| -rw-r--r-- | lib/ExecutionEngine/MCJIT/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lib/ExecutionEngine/MCJIT/MCJIT.cpp | 28 | ||||
| -rw-r--r-- | lib/ExecutionEngine/MCJIT/MCJIT.h | 12 | ||||
| -rw-r--r-- | lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h | 18 | ||||
| -rw-r--r-- | lib/ExecutionEngine/MCJIT/TargetSelect.cpp | 91 | ||||
| -rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 458 | ||||
| -rw-r--r-- | lib/ExecutionEngine/TargetSelect.cpp (renamed from lib/ExecutionEngine/JIT/TargetSelect.cpp) | 12 |
14 files changed, 386 insertions, 362 deletions
diff --git a/lib/ExecutionEngine/CMakeLists.txt b/lib/ExecutionEngine/CMakeLists.txt index 8bff265..58caae8 100644 --- a/lib/ExecutionEngine/CMakeLists.txt +++ b/lib/ExecutionEngine/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_library(LLVMExecutionEngine ExecutionEngine.cpp ExecutionEngineBindings.cpp + TargetSelect.cpp ) add_subdirectory(Interpreter) diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 13e07ac..7652090 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Host.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" #include <cmath> #include <cstring> using namespace llvm; @@ -42,20 +43,14 @@ ExecutionEngine *(*ExecutionEngine::JITCtor)( JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode, - CodeModel::Model CMM, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs) = 0; + TargetMachine *TM) = 0; ExecutionEngine *(*ExecutionEngine::MCJITCtor)( Module *M, std::string *ErrorStr, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode, - CodeModel::Model CMM, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs) = 0; + TargetMachine *TM) = 0; ExecutionEngine *(*ExecutionEngine::InterpCtor)(Module *M, std::string *ErrorStr) = 0; @@ -313,13 +308,17 @@ void ExecutionEngine::runStaticConstructorsDestructors(Module *module, // Should be an array of '{ i32, void ()* }' structs. The first value is // the init priority, which we ignore. + if (isa<ConstantAggregateZero>(GV->getInitializer())) + return; ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer()); for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + if (isa<ConstantAggregateZero>(InitList->getOperand(i))) + continue; ConstantStruct *CS = cast<ConstantStruct>(InitList->getOperand(i)); Constant *FP = CS->getOperand(1); if (FP->isNullValue()) - break; // Found a null terminator, exit. + continue; // Found a sentinal value, ignore. // Strip off constant expression casts. if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) @@ -415,6 +414,35 @@ ExecutionEngine *ExecutionEngine::create(Module *M, .create(); } +/// createJIT - This is the factory method for creating a JIT for the current +/// machine, it does not fall back to the interpreter. This takes ownership +/// of the module. +ExecutionEngine *ExecutionEngine::createJIT(Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM) { + if (ExecutionEngine::JITCtor == 0) { + if (ErrorStr) + *ErrorStr = "JIT has not been linked in."; + return 0; + } + + // Use the defaults for extra parameters. Users can use EngineBuilder to + // set them. + StringRef MArch = ""; + StringRef MCPU = ""; + SmallVector<std::string, 1> MAttrs; + + TargetMachine *TM = + EngineBuilder::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr); + if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; + TM->setCodeModel(CMM); + + return ExecutionEngine::JITCtor(M, ErrorStr, JMM, OptLevel, GVsWithCode, TM); +} + ExecutionEngine *EngineBuilder::create() { // 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. @@ -437,18 +465,21 @@ ExecutionEngine *EngineBuilder::create() { // Unless the interpreter was explicitly selected or the JIT is not linked, // try making a JIT. if (WhichEngine & EngineKind::JIT) { - if (UseMCJIT && ExecutionEngine::MCJITCtor) { - ExecutionEngine *EE = - ExecutionEngine::MCJITCtor(M, ErrorStr, JMM, OptLevel, - AllocateGVsWithCode, CMModel, - MArch, MCPU, MAttrs); - if (EE) return EE; - } else if (ExecutionEngine::JITCtor) { - ExecutionEngine *EE = - ExecutionEngine::JITCtor(M, ErrorStr, JMM, OptLevel, - AllocateGVsWithCode, CMModel, - MArch, MCPU, MAttrs); - if (EE) return EE; + if (TargetMachine *TM = + EngineBuilder::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr)) { + TM->setCodeModel(CMModel); + + if (UseMCJIT && ExecutionEngine::MCJITCtor) { + ExecutionEngine *EE = + ExecutionEngine::MCJITCtor(M, ErrorStr, JMM, OptLevel, + AllocateGVsWithCode, TM); + if (EE) return EE; + } else if (ExecutionEngine::JITCtor) { + ExecutionEngine *EE = + ExecutionEngine::JITCtor(M, ErrorStr, JMM, OptLevel, + AllocateGVsWithCode, TM); + if (EE) return EE; + } } } @@ -835,7 +866,7 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, case Type::PointerTyID: // Ensure 64 bit target pointers are fully initialized on 32 bit hosts. if (StoreBytes != sizeof(PointerTy)) - memset(Ptr, 0, StoreBytes); + memset(&(Ptr->PointerVal), 0, StoreBytes); *((PointerTy*)Ptr) = Val.PointerVal; break; diff --git a/lib/ExecutionEngine/JIT/CMakeLists.txt b/lib/ExecutionEngine/JIT/CMakeLists.txt index 42020d6..cefb0ae 100644 --- a/lib/ExecutionEngine/JIT/CMakeLists.txt +++ b/lib/ExecutionEngine/JIT/CMakeLists.txt @@ -9,5 +9,4 @@ add_llvm_library(LLVMJIT JITEmitter.cpp JITMemoryManager.cpp OProfileJITEventListener.cpp - TargetSelect.cpp ) diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index 56121c1..8fceaf2 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -203,39 +203,18 @@ void DarwinRegisterFrame(void* FrameBegin) { /// createJIT - This is the factory method for creating a JIT for the current /// machine, it does not fall back to the interpreter. This takes ownership /// of the module. -ExecutionEngine *ExecutionEngine::createJIT(Module *M, - std::string *ErrorStr, - JITMemoryManager *JMM, - CodeGenOpt::Level OptLevel, - bool GVsWithCode, - CodeModel::Model CMM) { - // Use the defaults for extra parameters. Users can use EngineBuilder to - // set them. - StringRef MArch = ""; - StringRef MCPU = ""; - SmallVector<std::string, 1> MAttrs; - return JIT::createJIT(M, ErrorStr, JMM, OptLevel, GVsWithCode, CMM, - MArch, MCPU, MAttrs); -} - ExecutionEngine *JIT::createJIT(Module *M, std::string *ErrorStr, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode, - CodeModel::Model CMM, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs) { + TargetMachine *TM) { // Try to register the program as a source of symbols to resolve against. + // + // FIXME: Don't do this here. sys::DynamicLibrary::LoadLibraryPermanently(0, NULL); - // Pick a target either via -march or by guessing the native arch. - TargetMachine *TM = JIT::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr); - if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; - TM->setCodeModel(CMM); - - // If the target supports JIT code generation, create a the JIT. + // If the target supports JIT code generation, create the JIT. if (TargetJITInfo *TJ = TM->getJITInfo()) { return new JIT(M, *TM, *TJ, JMM, OptLevel, GVsWithCode); } else { @@ -666,7 +645,7 @@ void JIT::jitTheFunction(Function *F, const MutexGuard &locked) { } /// getPointerToFunction - This method is used to get the address of the -/// specified function, compiling it if neccesary. +/// specified function, compiling it if necessary. /// void *JIT::getPointerToFunction(Function *F) { diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index b576c16..b879fc3 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -181,23 +181,12 @@ public: /// JITCodeEmitter *getCodeEmitter() const { return JCE; } - /// selectTarget - Pick a target either via -march or by guessing the native - /// arch. Add any CPU features specified via -mcpu or -mattr. - static TargetMachine *selectTarget(Module *M, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs, - std::string *Err); - static ExecutionEngine *createJIT(Module *M, std::string *ErrorStr, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode, - CodeModel::Model CMM, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs); + TargetMachine *TM); // Run the JIT on F and return information about the generated code void runJITOnFunction(Function *F, MachineCodeInfo *MCI = 0); diff --git a/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp b/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp index 3b5acb7..e71c20b 100644 --- a/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp +++ b/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp @@ -27,7 +27,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Mutex.h" #include <string> -#include <vector> namespace llvm { @@ -143,7 +142,7 @@ void JITDebugRegisterer::RegisterFunction(const Function *F, DebugInfo &I) { // Add a mapping from F to the entry and buffer, so we can delete this // info later. - FnMap[F] = std::make_pair<std::string, jit_code_entry*>(Buffer, JITCodeEntry); + FnMap[F] = std::make_pair(Buffer, JITCodeEntry); // Acquire the lock and do the registration. { diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index 3b4e750..d046b8a 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -128,7 +128,7 @@ namespace { return GlobalToIndirectSymMap; } - pair<void *, Function *> LookupFunctionFromCallSite( + std::pair<void *, Function *> LookupFunctionFromCallSite( const MutexGuard &locked, void *CallSite) const { assert(locked.holds(TheJIT->lock)); @@ -646,7 +646,7 @@ void *JITResolver::JITCompilerFn(void *Stub) { // The address given to us for the stub may not be exactly right, it might // be a little bit after the stub. As such, use upper_bound to find it. - pair<void*, Function*> I = + std::pair<void*, Function*> I = JR->state.LookupFunctionFromCallSite(locked, Stub); F = I.second; ActualPtr = I.first; diff --git a/lib/ExecutionEngine/MCJIT/CMakeLists.txt b/lib/ExecutionEngine/MCJIT/CMakeLists.txt index 6553079..38fdffa 100644 --- a/lib/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/lib/ExecutionEngine/MCJIT/CMakeLists.txt @@ -1,5 +1,4 @@ add_llvm_library(LLVMMCJIT MCJIT.cpp - TargetSelect.cpp Intercept.cpp ) diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 148e0d9..4475f4d 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -1,4 +1,4 @@ -//===-- MCJIT.cpp - MC-based Just-in-Time Compiler --------------------------===// +//===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===// // // The LLVM Compiler Infrastructure // @@ -38,27 +38,15 @@ ExecutionEngine *MCJIT::createJIT(Module *M, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode, - CodeModel::Model CMM, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs) { + TargetMachine *TM) { // Try to register the program as a source of symbols to resolve against. // // FIXME: Don't do this here. sys::DynamicLibrary::LoadLibraryPermanently(0, NULL); - // Pick a target either via -march or by guessing the native arch. - // - // FIXME: This should be lifted out of here, it isn't something which should - // be part of the JIT policy, rather the burden for this selection should be - // pushed to clients. - TargetMachine *TM = MCJIT::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr); - if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; - TM->setCodeModel(CMM); - // If the target supports JIT code generation, create the JIT. if (TargetJITInfo *TJ = TM->getJITInfo()) - return new MCJIT(M, TM, *TJ, new MCJITMemoryManager(JMM), OptLevel, + return new MCJIT(M, TM, *TJ, new MCJITMemoryManager(JMM, M), OptLevel, GVsWithCode); if (ErrorStr) @@ -93,6 +81,8 @@ MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji, Buffer.size())); if (Dyld.loadObject(MB)) report_fatal_error(Dyld.getErrorString()); + // Resolve any relocations. + Dyld.resolveRelocations(); } MCJIT::~MCJIT() { @@ -112,8 +102,12 @@ void *MCJIT::getPointerToFunction(Function *F) { return Addr; } - Twine Name = TM->getMCAsmInfo()->getGlobalPrefix() + F->getName(); - return (void*)Dyld.getSymbolAddress(Name.str()); + // FIXME: Should we be using the mangler for this? Probably. + StringRef BaseName = F->getName(); + if (BaseName[0] == '\1') + return (void*)Dyld.getSymbolAddress(BaseName.substr(1)); + return (void*)Dyld.getSymbolAddress((TM->getMCAsmInfo()->getGlobalPrefix() + + BaseName).str()); } void *MCJIT::recompileAndRelinkFunction(Function *F) { diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index 1b50766..b64c21a 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -76,22 +76,12 @@ public: MCJITCtor = createJIT; } - // FIXME: This routine is scheduled for termination. Do not use it. - static TargetMachine *selectTarget(Module *M, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs, - std::string *Err); - static ExecutionEngine *createJIT(Module *M, std::string *ErrorStr, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode, - CodeModel::Model CMM, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs); + TargetMachine *TM); // @} }; diff --git a/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h b/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h index 0108ecc..40bc031 100644 --- a/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h +++ b/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h @@ -26,13 +26,21 @@ class MCJITMemoryManager : public RTDyldMemoryManager { // FIXME: Multiple modules. Module *M; public: - MCJITMemoryManager(JITMemoryManager *jmm) : JMM(jmm) {} + MCJITMemoryManager(JITMemoryManager *jmm, Module *m) : JMM(jmm), M(m) {} // Allocate ActualSize bytes, or more, for the named function. Return // a pointer to the allocated memory and update Size to reflect how much // memory was acutally allocated. uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) { + // FIXME: This should really reference the MCAsmInfo to get the global + // prefix. + if (Name[0] == '_') ++Name; Function *F = M->getFunction(Name); + // Some ObjC names have a prefixed \01 in the IR. If we failed to find + // the symbol and it's of the ObjC conventions (starts with "-"), try + // prepending a \01 and see if we can find it that way. + if (!F && Name[0] == '-') + F = M->getFunction((Twine("\1") + Name).str()); assert(F && "No matching function in JIT IR Module!"); return JMM->startFunctionBody(F, Size); } @@ -41,7 +49,15 @@ public: // memory was actually used. void endFunctionBody(const char *Name, uint8_t *FunctionStart, uint8_t *FunctionEnd) { + // FIXME: This should really reference the MCAsmInfo to get the global + // prefix. + if (Name[0] == '_') ++Name; Function *F = M->getFunction(Name); + // Some ObjC names have a prefixed \01 in the IR. If we failed to find + // the symbol and it's of the ObjC conventions (starts with "-"), try + // prepending a \01 and see if we can find it that way. + if (!F && Name[0] == '-') + F = M->getFunction((Twine("\1") + Name).str()); assert(F && "No matching function in JIT IR Module!"); JMM->endFunctionBody(F, FunctionStart, FunctionEnd); } diff --git a/lib/ExecutionEngine/MCJIT/TargetSelect.cpp b/lib/ExecutionEngine/MCJIT/TargetSelect.cpp deleted file mode 100644 index 50f6593..0000000 --- a/lib/ExecutionEngine/MCJIT/TargetSelect.cpp +++ /dev/null @@ -1,91 +0,0 @@ -//===-- TargetSelect.cpp - Target Chooser Code ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This just asks the TargetRegistry for the appropriate JIT to use, and allows -// the user to specify a specific one on the commandline with -march=x. Clients -// should initialize targets prior to calling createJIT. -// -//===----------------------------------------------------------------------===// - -#include "MCJIT.h" -#include "llvm/Module.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Host.h" -#include "llvm/Target/SubtargetFeature.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegistry.h" -using namespace llvm; - -/// selectTarget - Pick a target either via -march or by guessing the native -/// arch. Add any CPU features specified via -mcpu or -mattr. -TargetMachine *MCJIT::selectTarget(Module *Mod, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs, - std::string *ErrorStr) { - Triple TheTriple(Mod->getTargetTriple()); - if (TheTriple.getTriple().empty()) - TheTriple.setTriple(sys::getHostTriple()); - - // Adjust the triple to match what the user requested. - const Target *TheTarget = 0; - if (!MArch.empty()) { - for (TargetRegistry::iterator it = TargetRegistry::begin(), - ie = TargetRegistry::end(); it != ie; ++it) { - if (MArch == it->getName()) { - TheTarget = &*it; - break; - } - } - - if (!TheTarget) { - *ErrorStr = "No available targets are compatible with this -march, " - "see -version for the available targets.\n"; - return 0; - } - - // Adjust the triple to match (if known), otherwise stick with the - // module/host triple. - Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); - if (Type != Triple::UnknownArch) - TheTriple.setArch(Type); - } else { - std::string Error; - TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error); - if (TheTarget == 0) { - if (ErrorStr) - *ErrorStr = Error; - return 0; - } - } - - if (!TheTarget->hasJIT()) { - errs() << "WARNING: This target JIT is not designed for the host you are" - << " running. If bad things happen, please choose a different " - << "-march switch.\n"; - } - - // Package up features to be passed to target/subtarget - std::string FeaturesStr; - if (!MCPU.empty() || !MAttrs.empty()) { - SubtargetFeatures Features; - Features.setCPU(MCPU); - for (unsigned i = 0; i != MAttrs.size(); ++i) - Features.AddFeature(MAttrs[i]); - FeaturesStr = Features.getString(); - } - - // Allocate a target... - TargetMachine *Target = - TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr); - assert(Target && "Could not allocate target machine!"); - return Target; -} diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 29fced4..eda4cbb 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -41,17 +41,38 @@ class RuntimeDyldImpl { // The MemoryManager to load objects into. RTDyldMemoryManager *MemMgr; + // FIXME: This all assumes we're dealing with external symbols for anything + // explicitly referenced. I.e., we can index by name and things + // will work out. In practice, this may not be the case, so we + // should find a way to effectively generalize. // For each function, we have a MemoryBlock of it's instruction data. StringMap<sys::MemoryBlock> Functions; // Master symbol table. As modules are loaded and external symbols are // resolved, their addresses are stored here. - StringMap<uint64_t> SymbolTable; - - // FIXME: Should have multiple data blocks, one for each loaded chunk of - // compiled code. - sys::MemoryBlock Data; + StringMap<uint8_t*> SymbolTable; + + // For each symbol, keep a list of relocations based on it. Anytime + // its address is reassigned (the JIT re-compiled the function, e.g.), + // the relocations get re-resolved. + struct RelocationEntry { + std::string Target; // Object this relocation is contained in. + uint64_t Offset; // Offset into the object for the relocation. + uint32_t Data; // Second word of the raw macho relocation entry. + int64_t Addend; // Addend encoded in the instruction itself, if any. + bool isResolved; // Has this relocation been resolved previously? + + RelocationEntry(StringRef t, uint64_t offset, uint32_t data, int64_t addend) + : Target(t), Offset(offset), Data(data), Addend(addend), + isResolved(false) {} + }; + typedef SmallVector<RelocationEntry, 4> RelocationList; + StringMap<RelocationList> Relocations; + + // FIXME: Also keep a map of all the relocations contained in an object. Use + // this to dynamically answer whether all of the relocations in it have + // been resolved or not. bool HasError; std::string ErrorStr; @@ -65,12 +86,11 @@ class RuntimeDyldImpl { void extractFunction(StringRef Name, uint8_t *StartAddress, uint8_t *EndAddress); - bool resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE, - SmallVectorImpl<void *> &SectionBases, - SmallVectorImpl<StringRef> &SymbolNames); - bool resolveX86_64Relocation(intptr_t Address, intptr_t Value, bool isPCRel, + bool resolveRelocation(uint8_t *Address, uint8_t *Value, bool isPCRel, + unsigned Type, unsigned Size); + bool resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel, unsigned Type, unsigned Size); - bool resolveARMRelocation(intptr_t Address, intptr_t Value, bool isPCRel, + bool resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel, unsigned Type, unsigned Size); bool loadSegment32(const MachOObject *Obj, @@ -85,13 +105,15 @@ public: bool loadObject(MemoryBuffer *InputBuffer); - uint64_t getSymbolAddress(StringRef Name) { + void *getSymbolAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - return (uint64_t)Functions.lookup(Name).base(); + return SymbolTable.lookup(Name); } - sys::MemoryBlock getMemoryBlock() { return Data; } + void resolveRelocations(); + + void reassignSymbolAddress(StringRef Name, uint8_t *Addr); // Is the linker in an error state? bool hasError() { return HasError; } @@ -107,75 +129,41 @@ void RuntimeDyldImpl::extractFunction(StringRef Name, uint8_t *StartAddress, uint8_t *EndAddress) { // Allocate memory for the function via the memory manager. uintptr_t Size = EndAddress - StartAddress + 1; - uint8_t *Mem = MemMgr->startFunctionBody(Name.data(), Size); + uintptr_t AllocSize = Size; + uint8_t *Mem = MemMgr->startFunctionBody(Name.data(), AllocSize); assert(Size >= (uint64_t)(EndAddress - StartAddress + 1) && "Memory manager failed to allocate enough memory!"); // Copy the function payload into the memory block. - memcpy(Mem, StartAddress, EndAddress - StartAddress + 1); + memcpy(Mem, StartAddress, Size); MemMgr->endFunctionBody(Name.data(), Mem, Mem + Size); // Remember where we put it. Functions[Name] = sys::MemoryBlock(Mem, Size); - DEBUG(dbgs() << " allocated to " << Mem << "\n"); + // Default the assigned address for this symbol to wherever this + // allocated it. + SymbolTable[Name] = Mem; + DEBUG(dbgs() << " allocated to [" << Mem << ", " << Mem + Size << "]\n"); } bool RuntimeDyldImpl:: -resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE, - SmallVectorImpl<void *> &SectionBases, - SmallVectorImpl<StringRef> &SymbolNames) { - // struct relocation_info { - // int32_t r_address; - // uint32_t r_symbolnum:24, - // r_pcrel:1, - // r_length:2, - // r_extern:1, - // r_type:4; - // }; - uint32_t SymbolNum = RE.Word1 & 0xffffff; // 24-bit value - bool isPCRel = (RE.Word1 >> 24) & 1; - unsigned Log2Size = (RE.Word1 >> 25) & 3; - bool isExtern = (RE.Word1 >> 27) & 1; - unsigned Type = (RE.Word1 >> 28) & 0xf; - if (RE.Word0 & macho::RF_Scattered) - return Error("NOT YET IMPLEMENTED: scattered relocations."); - - // The address requiring a relocation. - intptr_t Address = (intptr_t)SectionBases[BaseSection] + RE.Word0; - - // Figure out the target address of the relocation. If isExtern is true, - // this relocation references the symbol table, otherwise it references - // a section in the same object, numbered from 1 through NumSections - // (SectionBases is [0, NumSections-1]). - intptr_t Value; - if (isExtern) { - StringRef Name = SymbolNames[SymbolNum]; - if (SymbolTable.lookup(Name)) { - // The symbol is in our symbol table, so we can resolve it directly. - Value = (intptr_t)SymbolTable[Name]; - } else { - return Error("NOT YET IMPLEMENTED: relocations to pre-compiled code."); - } - DEBUG(dbgs() << "Resolve relocation(" << Type << ") from '" << Name - << "' to " << format("0x%x", Address) << ".\n"); - } else { - // For non-external relocations, the SymbolNum is actual a section number - // as described above. - Value = (intptr_t)SectionBases[SymbolNum - 1]; - } - - unsigned Size = 1 << Log2Size; +resolveRelocation(uint8_t *Address, uint8_t *Value, bool isPCRel, + unsigned Type, unsigned Size) { + // This just dispatches to the proper target specific routine. switch (CPUType) { default: assert(0 && "Unsupported CPU type!"); case mach::CTM_x86_64: - return resolveX86_64Relocation(Address, Value, isPCRel, Type, Size); + return resolveX86_64Relocation((uintptr_t)Address, (uintptr_t)Value, + isPCRel, Type, Size); case mach::CTM_ARM: - return resolveARMRelocation(Address, Value, isPCRel, Type, Size); + return resolveARMRelocation((uintptr_t)Address, (uintptr_t)Value, + isPCRel, Type, Size); } llvm_unreachable(""); } -bool RuntimeDyldImpl::resolveX86_64Relocation(intptr_t Address, intptr_t Value, - bool isPCRel, unsigned Type, - unsigned Size) { +bool RuntimeDyldImpl:: +resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, + bool isPCRel, unsigned Type, + unsigned Size) { // If the relocation is PC-relative, the value to be encoded is the // pointer difference. if (isPCRel) @@ -210,7 +198,7 @@ bool RuntimeDyldImpl::resolveX86_64Relocation(intptr_t Address, intptr_t Value, return false; } -bool RuntimeDyldImpl::resolveARMRelocation(intptr_t Address, intptr_t Value, +bool RuntimeDyldImpl::resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel, unsigned Type, unsigned Size) { // If the relocation is PC-relative, the value to be encoded is the @@ -225,6 +213,7 @@ bool RuntimeDyldImpl::resolveARMRelocation(intptr_t Address, intptr_t Value, switch(Type) { default: + llvm_unreachable("Invalid relocation type!"); case macho::RIT_Vanilla: { llvm_unreachable("Invalid relocation type!"); // Mask in the target value a byte at a time (we don't have an alignment @@ -236,10 +225,6 @@ bool RuntimeDyldImpl::resolveARMRelocation(intptr_t Address, intptr_t Value, } break; } - case macho::RIT_Pair: - case macho::RIT_Difference: - case macho::RIT_ARM_LocalDifference: - case macho::RIT_ARM_PreboundLazyPointer: case macho::RIT_ARM_Branch24Bit: { // Mask the value into the target address. We know instructions are // 32-bit aligned, so we can do it all at once. @@ -260,6 +245,10 @@ bool RuntimeDyldImpl::resolveARMRelocation(intptr_t Address, intptr_t Value, case macho::RIT_ARM_ThumbBranch32Bit: case macho::RIT_ARM_Half: case macho::RIT_ARM_HalfDifference: + case macho::RIT_Pair: + case macho::RIT_Difference: + case macho::RIT_ARM_LocalDifference: + case macho::RIT_ARM_PreboundLazyPointer: return Error("Relocation type not implemented yet!"); } return false; @@ -269,98 +258,137 @@ bool RuntimeDyldImpl:: loadSegment32(const MachOObject *Obj, const MachOObject::LoadCommandInfo *SegmentLCI, const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC) { - InMemoryStruct<macho::SegmentLoadCommand> Segment32LC; - Obj->ReadSegmentLoadCommand(*SegmentLCI, Segment32LC); - if (!Segment32LC) + InMemoryStruct<macho::SegmentLoadCommand> SegmentLC; + Obj->ReadSegmentLoadCommand(*SegmentLCI, SegmentLC); + if (!SegmentLC) return Error("unable to load segment load command"); - // Map the segment into memory. - std::string ErrorStr; - Data = sys::Memory::AllocateRWX(Segment32LC->VMSize, 0, &ErrorStr); - if (!Data.base()) - return Error("unable to allocate memory block: '" + ErrorStr + "'"); - memcpy(Data.base(), Obj->getData(Segment32LC->FileOffset, - Segment32LC->FileSize).data(), - Segment32LC->FileSize); - memset((char*)Data.base() + Segment32LC->FileSize, 0, - Segment32LC->VMSize - Segment32LC->FileSize); - - // Bind the section indices to addresses and record the relocations we - // need to resolve. - typedef std::pair<uint32_t, macho::RelocationEntry> RelocationMap; - SmallVector<RelocationMap, 64> Relocations; - - SmallVector<void *, 16> SectionBases; - for (unsigned i = 0; i != Segment32LC->NumSections; ++i) { + for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) { InMemoryStruct<macho::Section> Sect; - Obj->ReadSection(*SegmentLCI, i, Sect); - if (!Sect) - return Error("unable to load section: '" + Twine(i) + "'"); - - // Remember any relocations the section has so we can resolve them later. - for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) { - InMemoryStruct<macho::RelocationEntry> RE; - Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE); - Relocations.push_back(RelocationMap(j, *RE)); - } - - // FIXME: Improve check. -// if (Sect->Flags != 0x80000400) -// return Error("unsupported section type!"); - - SectionBases.push_back((char*) Data.base() + Sect->Address); - } + Obj->ReadSection(*SegmentLCI, SectNum, Sect); + if (!Sect) + return Error("unable to load section: '" + Twine(SectNum) + "'"); - // Bind all the symbols to address. Keep a record of the names for use - // by relocation resolution. - SmallVector<StringRef, 64> SymbolNames; - for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { - InMemoryStruct<macho::SymbolTableEntry> STE; - Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE); - if (!STE) - return Error("unable to read symbol: '" + Twine(i) + "'"); - // Get the symbol name. - StringRef Name = Obj->getStringAtIndex(STE->StringIndex); - SymbolNames.push_back(Name); - - // Just skip undefined symbols. They'll be loaded from whatever - // module they come from (or system dylib) when we resolve relocations - // involving them. - if (STE->SectionIndex == 0) + // FIXME: For the time being, we're only loading text segments. + if (Sect->Flags != 0x80000400) continue; - unsigned Index = STE->SectionIndex - 1; - if (Index >= Segment32LC->NumSections) - return Error("invalid section index for symbol: '" + Twine() + "'"); - - // Get the section base address. - void *SectionBase = SectionBases[Index]; + // Address and names of symbols in the section. + typedef std::pair<uint64_t, StringRef> SymbolEntry; + SmallVector<SymbolEntry, 64> Symbols; + // Index of all the names, in this section or not. Used when we're + // dealing with relocation entries. + SmallVector<StringRef, 64> SymbolNames; + for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { + InMemoryStruct<macho::SymbolTableEntry> STE; + Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE); + if (!STE) + return Error("unable to read symbol: '" + Twine(i) + "'"); + if (STE->SectionIndex > SegmentLC->NumSections) + return Error("invalid section index for symbol: '" + Twine(i) + "'"); + // Get the symbol name. + StringRef Name = Obj->getStringAtIndex(STE->StringIndex); + SymbolNames.push_back(Name); - // Get the symbol address. - uint64_t Address = (uint64_t)SectionBase + STE->Value; + // Just skip symbols not defined in this section. + if ((unsigned)STE->SectionIndex - 1 != SectNum) + continue; - // FIXME: Check the symbol type and flags. - if (STE->Type != 0xF) - return Error("unexpected symbol type!"); - if (STE->Flags != 0x0) - return Error("unexpected symbol type!"); + // FIXME: Check the symbol type and flags. + if (STE->Type != 0xF) // external, defined in this section. + continue; + // Flags == 0x8 marks a thumb function for ARM, which is fine as it + // doesn't require any special handling here. + if (STE->Flags != 0x0 && STE->Flags != 0x8) + continue; - DEBUG(dbgs() << "Symbol: '" << Name << "' @ " << Address << "\n"); + // Remember the symbol. + Symbols.push_back(SymbolEntry(STE->Value, Name)); - SymbolTable[Name] = Address; - } + DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << + (Sect->Address + STE->Value) << "\n"); + } + // Sort the symbols by address, just in case they didn't come in that way. + array_pod_sort(Symbols.begin(), Symbols.end()); - // Now resolve any relocations. - for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { - if (resolveRelocation(Relocations[i].first, Relocations[i].second, - SectionBases, SymbolNames)) - return true; - } + // If there weren't any functions (odd, but just in case...) + if (!Symbols.size()) + continue; - // We've loaded the section; now mark the functions in it as executable. - // FIXME: We really should use the MemoryManager for this. - sys::Memory::setRangeExecutable(Data.base(), Data.size()); + // Extract the function data. + uint8_t *Base = (uint8_t*)Obj->getData(SegmentLC->FileOffset, + SegmentLC->FileSize).data(); + for (unsigned i = 0, e = Symbols.size() - 1; i != e; ++i) { + uint64_t StartOffset = Sect->Address + Symbols[i].first; + uint64_t EndOffset = Symbols[i + 1].first - 1; + DEBUG(dbgs() << "Extracting function: " << Symbols[i].second + << " from [" << StartOffset << ", " << EndOffset << "]\n"); + extractFunction(Symbols[i].second, Base + StartOffset, Base + EndOffset); + } + // The last symbol we do after since the end address is calculated + // differently because there is no next symbol to reference. + uint64_t StartOffset = Symbols[Symbols.size() - 1].first; + uint64_t EndOffset = Sect->Size - 1; + DEBUG(dbgs() << "Extracting function: " << Symbols[Symbols.size()-1].second + << " from [" << StartOffset << ", " << EndOffset << "]\n"); + extractFunction(Symbols[Symbols.size()-1].second, + Base + StartOffset, Base + EndOffset); + // Now extract the relocation information for each function and process it. + for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) { + InMemoryStruct<macho::RelocationEntry> RE; + Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE); + if (RE->Word0 & macho::RF_Scattered) + return Error("NOT YET IMPLEMENTED: scattered relocations."); + // Word0 of the relocation is the offset into the section where the + // relocation should be applied. We need to translate that into an + // offset into a function since that's our atom. + uint32_t Offset = RE->Word0; + // Look for the function containing the address. This is used for JIT + // code, so the number of functions in section is almost always going + // to be very small (usually just one), so until we have use cases + // where that's not true, just use a trivial linear search. + unsigned SymbolNum; + unsigned NumSymbols = Symbols.size(); + assert(NumSymbols > 0 && Symbols[0].first <= Offset && + "No symbol containing relocation!"); + for (SymbolNum = 0; SymbolNum < NumSymbols - 1; ++SymbolNum) + if (Symbols[SymbolNum + 1].first > Offset) + break; + // Adjust the offset to be relative to the symbol. + Offset -= Symbols[SymbolNum].first; + // Get the name of the symbol containing the relocation. + StringRef TargetName = SymbolNames[SymbolNum]; + + bool isExtern = (RE->Word1 >> 27) & 1; + // Figure out the source symbol of the relocation. If isExtern is true, + // this relocation references the symbol table, otherwise it references + // a section in the same object, numbered from 1 through NumSections + // (SectionBases is [0, NumSections-1]). + // FIXME: Some targets (ARM) use internal relocations even for + // externally visible symbols, if the definition is in the same + // file as the reference. We need to convert those back to by-name + // references. We can resolve the address based on the section + // offset and see if we have a symbol at that address. If we do, + // use that; otherwise, puke. + if (!isExtern) + return Error("Internal relocations not supported."); + uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value + StringRef SourceName = SymbolNames[SourceNum]; + + // FIXME: Get the relocation addend from the target address. + + // Now store the relocation information. Associate it with the source + // symbol. + Relocations[SourceName].push_back(RelocationEntry(TargetName, + Offset, + RE->Word1, + 0 /*Addend*/)); + DEBUG(dbgs() << "Relocation at '" << TargetName << "' + " << Offset + << " from '" << SourceName << "(Word1: " + << format("0x%x", RE->Word1) << ")\n"); + } + } return false; } @@ -380,51 +408,55 @@ loadSegment64(const MachOObject *Obj, if (!Sect) return Error("unable to load section: '" + Twine(SectNum) + "'"); - // FIXME: Improve check. + // FIXME: For the time being, we're only loading text segments. if (Sect->Flags != 0x80000400) - return Error("unsupported section type!"); + continue; // Address and names of symbols in the section. typedef std::pair<uint64_t, StringRef> SymbolEntry; SmallVector<SymbolEntry, 64> Symbols; + // Index of all the names, in this section or not. Used when we're + // dealing with relocation entries. + SmallVector<StringRef, 64> SymbolNames; for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { InMemoryStruct<macho::Symbol64TableEntry> STE; Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE); if (!STE) return Error("unable to read symbol: '" + Twine(i) + "'"); if (STE->SectionIndex > Segment64LC->NumSections) - return Error("invalid section index for symbol: '" + Twine() + "'"); + return Error("invalid section index for symbol: '" + Twine(i) + "'"); + // Get the symbol name. + StringRef Name = Obj->getStringAtIndex(STE->StringIndex); + SymbolNames.push_back(Name); // Just skip symbols not defined in this section. - if (STE->SectionIndex - 1 != SectNum) + if ((unsigned)STE->SectionIndex - 1 != SectNum) continue; - // Get the symbol name. - StringRef Name = Obj->getStringAtIndex(STE->StringIndex); - // FIXME: Check the symbol type and flags. if (STE->Type != 0xF) // external, defined in this section. - return Error("unexpected symbol type!"); + continue; if (STE->Flags != 0x0) - return Error("unexpected symbol type!"); - - uint64_t BaseAddress = Sect->Address; - uint64_t Address = BaseAddress + STE->Value; + continue; // Remember the symbol. - Symbols.push_back(SymbolEntry(Address, Name)); + Symbols.push_back(SymbolEntry(STE->Value, Name)); - DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << Address << "\n"); + DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << + (Sect->Address + STE->Value) << "\n"); } - // Sort the symbols by address, just in case they didn't come in that - // way. + // Sort the symbols by address, just in case they didn't come in that way. array_pod_sort(Symbols.begin(), Symbols.end()); + // If there weren't any functions (odd, but just in case...) + if (!Symbols.size()) + continue; + // Extract the function data. uint8_t *Base = (uint8_t*)Obj->getData(Segment64LC->FileOffset, Segment64LC->FileSize).data(); for (unsigned i = 0, e = Symbols.size() - 1; i != e; ++i) { - uint64_t StartOffset = Symbols[i].first; + uint64_t StartOffset = Sect->Address + Symbols[i].first; uint64_t EndOffset = Symbols[i + 1].first - 1; DEBUG(dbgs() << "Extracting function: " << Symbols[i].second << " from [" << StartOffset << ", " << EndOffset << "]\n"); @@ -438,8 +470,56 @@ loadSegment64(const MachOObject *Obj, << " from [" << StartOffset << ", " << EndOffset << "]\n"); extractFunction(Symbols[Symbols.size()-1].second, Base + StartOffset, Base + EndOffset); - } + // Now extract the relocation information for each function and process it. + for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) { + InMemoryStruct<macho::RelocationEntry> RE; + Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE); + if (RE->Word0 & macho::RF_Scattered) + return Error("NOT YET IMPLEMENTED: scattered relocations."); + // Word0 of the relocation is the offset into the section where the + // relocation should be applied. We need to translate that into an + // offset into a function since that's our atom. + uint32_t Offset = RE->Word0; + // Look for the function containing the address. This is used for JIT + // code, so the number of functions in section is almost always going + // to be very small (usually just one), so until we have use cases + // where that's not true, just use a trivial linear search. + unsigned SymbolNum; + unsigned NumSymbols = Symbols.size(); + assert(NumSymbols > 0 && Symbols[0].first <= Offset && + "No symbol containing relocation!"); + for (SymbolNum = 0; SymbolNum < NumSymbols - 1; ++SymbolNum) + if (Symbols[SymbolNum + 1].first > Offset) + break; + // Adjust the offset to be relative to the symbol. + Offset -= Symbols[SymbolNum].first; + // Get the name of the symbol containing the relocation. + StringRef TargetName = SymbolNames[SymbolNum]; + + bool isExtern = (RE->Word1 >> 27) & 1; + // Figure out the source symbol of the relocation. If isExtern is true, + // this relocation references the symbol table, otherwise it references + // a section in the same object, numbered from 1 through NumSections + // (SectionBases is [0, NumSections-1]). + if (!isExtern) + return Error("Internal relocations not supported."); + uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value + StringRef SourceName = SymbolNames[SourceNum]; + + // FIXME: Get the relocation addend from the target address. + + // Now store the relocation information. Associate it with the source + // symbol. + Relocations[SourceName].push_back(RelocationEntry(TargetName, + Offset, + RE->Word1, + 0 /*Addend*/)); + DEBUG(dbgs() << "Relocation at '" << TargetName << "' + " << Offset + << " from '" << SourceName << "(Word1: " + << format("0x%x", RE->Word1) << ")\n"); + } + } return false; } @@ -530,6 +610,40 @@ bool RuntimeDyldImpl::loadObject(MemoryBuffer *InputBuffer) { return false; } +// Resolve the relocations for all symbols we currently know about. +void RuntimeDyldImpl::resolveRelocations() { + // Just iterate over the symbols in our symbol table and assign their + // addresses. + StringMap<uint8_t*>::iterator i = SymbolTable.begin(); + StringMap<uint8_t*>::iterator e = SymbolTable.end(); + for (;i != e; ++i) + reassignSymbolAddress(i->getKey(), i->getValue()); +} + +// Assign an address to a symbol name and resolve all the relocations +// associated with it. +void RuntimeDyldImpl::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { + // Assign the address in our symbol table. + SymbolTable[Name] = Addr; + + RelocationList &Relocs = Relocations[Name]; + for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { + RelocationEntry &RE = Relocs[i]; + uint8_t *Target = SymbolTable[RE.Target] + RE.Offset; + bool isPCRel = (RE.Data >> 24) & 1; + unsigned Type = (RE.Data >> 28) & 0xf; + unsigned Size = 1 << ((RE.Data >> 25) & 3); + + DEBUG(dbgs() << "Resolving relocation at '" << RE.Target + << "' + " << RE.Offset << " (" << format("%p", Target) << ")" + << " from '" << Name << " (" << format("%p", Addr) << ")" + << "(" << (isPCRel ? "pcrel" : "absolute") + << ", type: " << Type << ", Size: " << Size << ").\n"); + + resolveRelocation(Target, Addr, isPCRel, Type, Size); + RE.isResolved = true; + } +} //===----------------------------------------------------------------------===// // RuntimeDyld class implementation @@ -545,12 +659,16 @@ bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) { return Dyld->loadObject(InputBuffer); } -uint64_t RuntimeDyld::getSymbolAddress(StringRef Name) { +void *RuntimeDyld::getSymbolAddress(StringRef Name) { return Dyld->getSymbolAddress(Name); } -sys::MemoryBlock RuntimeDyld::getMemoryBlock() { - return Dyld->getMemoryBlock(); +void RuntimeDyld::resolveRelocations() { + Dyld->resolveRelocations(); +} + +void RuntimeDyld::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { + Dyld->reassignSymbolAddress(Name, Addr); } StringRef RuntimeDyld::getErrorString() { diff --git a/lib/ExecutionEngine/JIT/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp index 8d92ab0..a8822e5 100644 --- a/lib/ExecutionEngine/JIT/TargetSelect.cpp +++ b/lib/ExecutionEngine/TargetSelect.cpp @@ -13,7 +13,7 @@ // //===----------------------------------------------------------------------===// -#include "JIT.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/Module.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CommandLine.h" @@ -26,11 +26,11 @@ using namespace llvm; /// selectTarget - Pick a target either via -march or by guessing the native /// arch. Add any CPU features specified via -mcpu or -mattr. -TargetMachine *JIT::selectTarget(Module *Mod, - StringRef MArch, - StringRef MCPU, - const SmallVectorImpl<std::string>& MAttrs, - std::string *ErrorStr) { +TargetMachine *EngineBuilder::selectTarget(Module *Mod, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl<std::string>& MAttrs, + std::string *ErrorStr) { Triple TheTriple(Mod->getTargetTriple()); if (TheTriple.getTriple().empty()) TheTriple.setTriple(sys::getHostTriple()); |
