aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
authorNowar Gu <nowar100@gmail.com>2011-06-17 14:29:24 +0800
committerNowar Gu <nowar100@gmail.com>2011-06-20 15:49:07 +0800
commit907af0f20f58f2ea26da7ea64e1f094cd6880db7 (patch)
tree02007757de416c561df174d582205cebfa582801 /lib/ExecutionEngine
parent1d4f9a57447faa0142a1d0301e5ce550cfe60c4f (diff)
parentec324e5ae44025c6bdb930b78198f30f807e355b (diff)
downloadexternal_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.txt1
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp75
-rw-r--r--lib/ExecutionEngine/JIT/CMakeLists.txt1
-rw-r--r--lib/ExecutionEngine/JIT/JIT.cpp31
-rw-r--r--lib/ExecutionEngine/JIT/JIT.h13
-rw-r--r--lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp3
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp4
-rw-r--r--lib/ExecutionEngine/MCJIT/CMakeLists.txt1
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.cpp28
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.h12
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h18
-rw-r--r--lib/ExecutionEngine/MCJIT/TargetSelect.cpp91
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp458
-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());