aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/CMakeLists.txt1
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp17
-rw-r--r--lib/ExecutionEngine/ExecutionEngineBindings.cpp114
-rw-r--r--lib/ExecutionEngine/JIT/CMakeLists.txt1
-rw-r--r--lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp596
-rw-r--r--lib/ExecutionEngine/JIT/JITDwarfEmitter.h77
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp52
-rw-r--r--lib/ExecutionEngine/JIT/JITMemoryManager.cpp28
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.cpp25
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.h9
-rw-r--r--lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp64
-rw-r--r--lib/ExecutionEngine/RTDyldMemoryManager.cpp118
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp128
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp335
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h12
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h21
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp93
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h1
18 files changed, 779 insertions, 913 deletions
diff --git a/lib/ExecutionEngine/CMakeLists.txt b/lib/ExecutionEngine/CMakeLists.txt
index cb11bfe..3102c7b 100644
--- a/lib/ExecutionEngine/CMakeLists.txt
+++ b/lib/ExecutionEngine/CMakeLists.txt
@@ -3,6 +3,7 @@
add_llvm_library(LLVMExecutionEngine
ExecutionEngine.cpp
ExecutionEngineBindings.cpp
+ RTDyldMemoryManager.cpp
TargetSelect.cpp
)
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index e43ba4f..0191636 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -14,6 +14,7 @@
#define DEBUG_TYPE "jit"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ExecutionEngine/GenericValue.h"
@@ -47,7 +48,7 @@ ExecutionEngine *(*ExecutionEngine::JITCtor)(
ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
Module *M,
std::string *ErrorStr,
- JITMemoryManager *JMM,
+ RTDyldMemoryManager *MCJMM,
bool GVsWithCode,
TargetMachine *TM) = 0;
ExecutionEngine *(*ExecutionEngine::InterpCtor)(Module *M,
@@ -455,10 +456,12 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr))
return 0;
+ assert(!(JMM && MCJMM));
+
// If the user specified a memory manager but didn't specify which engine to
// create, we assume they only want the JIT, and we fail if they only want
// the interpreter.
- if (JMM) {
+ if (JMM || MCJMM) {
if (WhichEngine & EngineKind::JIT)
WhichEngine = EngineKind::JIT;
else {
@@ -467,6 +470,14 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
return 0;
}
}
+
+ if (MCJMM && ! UseMCJIT) {
+ if (ErrorStr)
+ *ErrorStr =
+ "Cannot create a legacy JIT with a runtime dyld memory "
+ "manager.";
+ return 0;
+ }
// Unless the interpreter was explicitly selected or the JIT is not linked,
// try making a JIT.
@@ -480,7 +491,7 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
if (UseMCJIT && ExecutionEngine::MCJITCtor) {
ExecutionEngine *EE =
- ExecutionEngine::MCJITCtor(M, ErrorStr, JMM,
+ ExecutionEngine::MCJITCtor(M, ErrorStr, MCJMM ? MCJMM : JMM,
AllocateGVsWithCode, TheTM.take());
if (EE) return EE;
} else if (ExecutionEngine::JITCtor) {
diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp
index f9b08a0..88e73bf 100644
--- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp
+++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp
@@ -15,6 +15,7 @@
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ErrorHandling.h"
@@ -157,10 +158,8 @@ LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions,
size_t SizeOfPassedOptions) {
LLVMMCJITCompilerOptions options;
- options.OptLevel = 0;
+ memset(&options, 0, sizeof(options)); // Most fields are zero by default.
options.CodeModel = LLVMCodeModelJITDefault;
- options.NoFramePointerElim = false;
- options.EnableFastISel = false;
memcpy(PassedOptions, &options,
std::min(sizeof(options), SizeOfPassedOptions));
@@ -199,6 +198,8 @@ LLVMBool LLVMCreateMCJITCompilerForModule(
.setOptLevel((CodeGenOpt::Level)options.OptLevel)
.setCodeModel(unwrap(options.CodeModel))
.setTargetOptions(targetOptions);
+ if (options.MCJMM)
+ builder.setMCJITMemoryManager(unwrap(options.MCJMM));
if (ExecutionEngine *JIT = builder.create()) {
*OutJIT = wrap(JIT);
return 0;
@@ -332,3 +333,110 @@ void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) {
return unwrap(EE)->getPointerToGlobal(unwrap<GlobalValue>(Global));
}
+
+/*===-- Operations on memory managers -------------------------------------===*/
+
+namespace {
+
+struct SimpleBindingMMFunctions {
+ uint8_t *(*AllocateCodeSection)(void *Opaque,
+ uintptr_t Size, unsigned Alignment,
+ unsigned SectionID);
+ uint8_t *(*AllocateDataSection)(void *Opaque,
+ uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, LLVMBool IsReadOnly);
+ LLVMBool (*FinalizeMemory)(void *Opaque, char **ErrMsg);
+ void (*Destroy)(void *Opaque);
+};
+
+class SimpleBindingMemoryManager : public RTDyldMemoryManager {
+public:
+ SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions,
+ void *Opaque);
+ virtual ~SimpleBindingMemoryManager();
+
+ virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID);
+
+ virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ bool isReadOnly);
+
+ virtual bool finalizeMemory(std::string *ErrMsg);
+
+private:
+ SimpleBindingMMFunctions Functions;
+ void *Opaque;
+};
+
+SimpleBindingMemoryManager::SimpleBindingMemoryManager(
+ const SimpleBindingMMFunctions& Functions,
+ void *Opaque)
+ : Functions(Functions), Opaque(Opaque) {
+ assert(Functions.AllocateCodeSection &&
+ "No AllocateCodeSection function provided!");
+ assert(Functions.AllocateDataSection &&
+ "No AllocateDataSection function provided!");
+ assert(Functions.FinalizeMemory &&
+ "No FinalizeMemory function provided!");
+ assert(Functions.Destroy &&
+ "No Destroy function provided!");
+}
+
+SimpleBindingMemoryManager::~SimpleBindingMemoryManager() {
+ Functions.Destroy(Opaque);
+}
+
+uint8_t *SimpleBindingMemoryManager::allocateCodeSection(
+ uintptr_t Size, unsigned Alignment, unsigned SectionID) {
+ return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID);
+}
+
+uint8_t *SimpleBindingMemoryManager::allocateDataSection(
+ uintptr_t Size, unsigned Alignment, unsigned SectionID, bool isReadOnly) {
+ return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID,
+ isReadOnly);
+}
+
+bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) {
+ char *errMsgCString = 0;
+ bool result = Functions.FinalizeMemory(Opaque, &errMsgCString);
+ assert((result || !errMsgCString) &&
+ "Did not expect an error message if FinalizeMemory succeeded");
+ if (errMsgCString) {
+ if (ErrMsg)
+ *ErrMsg = errMsgCString;
+ free(errMsgCString);
+ }
+ return result;
+}
+
+} // anonymous namespace
+
+LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager(
+ void *Opaque,
+ uint8_t *(*AllocateCodeSection)(void *Opaque,
+ uintptr_t Size, unsigned Alignment,
+ unsigned SectionID),
+ uint8_t *(*AllocateDataSection)(void *Opaque,
+ uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, LLVMBool IsReadOnly),
+ LLVMBool (*FinalizeMemory)(void *Opaque, char **ErrMsg),
+ void (*Destroy)(void *Opaque)) {
+
+ if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory ||
+ !Destroy)
+ return NULL;
+
+ SimpleBindingMMFunctions functions;
+ functions.AllocateCodeSection = AllocateCodeSection;
+ functions.AllocateDataSection = AllocateDataSection;
+ functions.FinalizeMemory = FinalizeMemory;
+ functions.Destroy = Destroy;
+ return wrap(new SimpleBindingMemoryManager(functions, Opaque));
+}
+
+void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM) {
+ delete unwrap(MM);
+}
+
diff --git a/lib/ExecutionEngine/JIT/CMakeLists.txt b/lib/ExecutionEngine/JIT/CMakeLists.txt
index 52bb389..e16baed 100644
--- a/lib/ExecutionEngine/JIT/CMakeLists.txt
+++ b/lib/ExecutionEngine/JIT/CMakeLists.txt
@@ -3,7 +3,6 @@ add_definitions(-DENABLE_X86_JIT)
add_llvm_library(LLVMJIT
JIT.cpp
- JITDwarfEmitter.cpp
JITEmitter.cpp
JITMemoryManager.cpp
)
diff --git a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
deleted file mode 100644
index 35d2b8b..0000000
--- a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-//===----- JITDwarfEmitter.cpp - Write dwarf tables into memory -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a JITDwarfEmitter object that is used by the JIT to
-// write dwarf tables to memory.
-//
-//===----------------------------------------------------------------------===//
-
-#include "JITDwarfEmitter.h"
-#include "JIT.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/CodeGen/JITCodeEmitter.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/ExecutionEngine/JITMemoryManager.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/Function.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MachineLocation.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Target/TargetFrameLowering.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-using namespace llvm;
-
-JITDwarfEmitter::JITDwarfEmitter(JIT& theJit) : MMI(0), Jit(theJit) {}
-
-
-unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F,
- JITCodeEmitter& jce,
- unsigned char* StartFunction,
- unsigned char* EndFunction,
- unsigned char* &EHFramePtr) {
- assert(MMI && "MachineModuleInfo not registered!");
-
- const TargetMachine& TM = F.getTarget();
- TD = TM.getDataLayout();
- stackGrowthDirection = TM.getFrameLowering()->getStackGrowthDirection();
- RI = TM.getRegisterInfo();
- MAI = TM.getMCAsmInfo();
- JCE = &jce;
-
- unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction,
- EndFunction);
-
- unsigned char* Result = 0;
-
- const std::vector<const Function *> Personalities = MMI->getPersonalities();
- EHFramePtr = EmitCommonEHFrame(Personalities[MMI->getPersonalityIndex()]);
-
- Result = EmitEHFrame(Personalities[MMI->getPersonalityIndex()], EHFramePtr,
- StartFunction, EndFunction, ExceptionTable);
-
- return Result;
-}
-
-
-void
-JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr,
- const std::vector<MachineMove> &Moves) const {
- unsigned PointerSize = TD->getPointerSize();
- int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ?
- PointerSize : -PointerSize;
- MCSymbol *BaseLabel = 0;
-
- for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
- const MachineMove &Move = Moves[i];
- MCSymbol *Label = Move.getLabel();
-
- // Throw out move if the label is invalid.
- if (Label && (*JCE->getLabelLocations())[Label] == 0)
- continue;
-
- intptr_t LabelPtr = 0;
- if (Label) LabelPtr = JCE->getLabelAddress(Label);
-
- const MachineLocation &Dst = Move.getDestination();
- const MachineLocation &Src = Move.getSource();
-
- // Advance row if new location.
- if (BaseLabelPtr && Label && BaseLabel != Label) {
- JCE->emitByte(dwarf::DW_CFA_advance_loc4);
- JCE->emitInt32(LabelPtr - BaseLabelPtr);
-
- BaseLabel = Label;
- BaseLabelPtr = LabelPtr;
- }
-
- // If advancing cfa.
- if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
- if (!Src.isReg()) {
- if (Src.getReg() == MachineLocation::VirtualFP) {
- JCE->emitByte(dwarf::DW_CFA_def_cfa_offset);
- } else {
- JCE->emitByte(dwarf::DW_CFA_def_cfa);
- JCE->emitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), true));
- }
-
- JCE->emitULEB128Bytes(-Src.getOffset());
- } else {
- llvm_unreachable("Machine move not supported yet.");
- }
- } else if (Src.isReg() &&
- Src.getReg() == MachineLocation::VirtualFP) {
- if (Dst.isReg()) {
- JCE->emitByte(dwarf::DW_CFA_def_cfa_register);
- JCE->emitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), true));
- } else {
- llvm_unreachable("Machine move not supported yet.");
- }
- } else {
- unsigned Reg = RI->getDwarfRegNum(Src.getReg(), true);
- int Offset = Dst.getOffset() / stackGrowth;
-
- if (Offset < 0) {
- JCE->emitByte(dwarf::DW_CFA_offset_extended_sf);
- JCE->emitULEB128Bytes(Reg);
- JCE->emitSLEB128Bytes(Offset);
- } else if (Reg < 64) {
- JCE->emitByte(dwarf::DW_CFA_offset + Reg);
- JCE->emitULEB128Bytes(Offset);
- } else {
- JCE->emitByte(dwarf::DW_CFA_offset_extended);
- JCE->emitULEB128Bytes(Reg);
- JCE->emitULEB128Bytes(Offset);
- }
- }
- }
-}
-
-/// SharedTypeIds - How many leading type ids two landing pads have in common.
-static unsigned SharedTypeIds(const LandingPadInfo *L,
- const LandingPadInfo *R) {
- const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
- unsigned LSize = LIds.size(), RSize = RIds.size();
- unsigned MinSize = LSize < RSize ? LSize : RSize;
- unsigned Count = 0;
-
- for (; Count != MinSize; ++Count)
- if (LIds[Count] != RIds[Count])
- return Count;
-
- return Count;
-}
-
-
-/// PadLT - Order landing pads lexicographically by type id.
-static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) {
- const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
- unsigned LSize = LIds.size(), RSize = RIds.size();
- unsigned MinSize = LSize < RSize ? LSize : RSize;
-
- for (unsigned i = 0; i != MinSize; ++i)
- if (LIds[i] != RIds[i])
- return LIds[i] < RIds[i];
-
- return LSize < RSize;
-}
-
-namespace {
-
-/// ActionEntry - Structure describing an entry in the actions table.
-struct ActionEntry {
- int ValueForTypeID; // The value to write - may not be equal to the type id.
- int NextAction;
- struct ActionEntry *Previous;
-};
-
-/// PadRange - Structure holding a try-range and the associated landing pad.
-struct PadRange {
- // The index of the landing pad.
- unsigned PadIndex;
- // The index of the begin and end labels in the landing pad's label lists.
- unsigned RangeIndex;
-};
-
-typedef DenseMap<MCSymbol*, PadRange> RangeMapType;
-
-/// CallSiteEntry - Structure describing an entry in the call-site table.
-struct CallSiteEntry {
- MCSymbol *BeginLabel; // zero indicates the start of the function.
- MCSymbol *EndLabel; // zero indicates the end of the function.
- MCSymbol *PadLabel; // zero indicates that there is no landing pad.
- unsigned Action;
-};
-
-}
-
-unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF,
- unsigned char* StartFunction,
- unsigned char* EndFunction) const {
- assert(MMI && "MachineModuleInfo not registered!");
-
- // Map all labels and get rid of any dead landing pads.
- MMI->TidyLandingPads(JCE->getLabelLocations());
-
- const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
- const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
- const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
- if (PadInfos.empty()) return 0;
-
- // Sort the landing pads in order of their type ids. This is used to fold
- // duplicate actions.
- SmallVector<const LandingPadInfo *, 64> LandingPads;
- LandingPads.reserve(PadInfos.size());
- for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
- LandingPads.push_back(&PadInfos[i]);
- std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
-
- // Negative type ids index into FilterIds, positive type ids index into
- // TypeInfos. The value written for a positive type id is just the type
- // id itself. For a negative type id, however, the value written is the
- // (negative) byte offset of the corresponding FilterIds entry. The byte
- // offset is usually equal to the type id, because the FilterIds entries
- // are written using a variable width encoding which outputs one byte per
- // entry as long as the value written is not too large, but can differ.
- // This kind of complication does not occur for positive type ids because
- // type infos are output using a fixed width encoding.
- // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i].
- SmallVector<int, 16> FilterOffsets;
- FilterOffsets.reserve(FilterIds.size());
- int Offset = -1;
- for(std::vector<unsigned>::const_iterator I = FilterIds.begin(),
- E = FilterIds.end(); I != E; ++I) {
- FilterOffsets.push_back(Offset);
- Offset -= MCAsmInfo::getULEB128Size(*I);
- }
-
- // Compute the actions table and gather the first action index for each
- // landing pad site.
- SmallVector<ActionEntry, 32> Actions;
- SmallVector<unsigned, 64> FirstActions;
- FirstActions.reserve(LandingPads.size());
-
- int FirstAction = 0;
- unsigned SizeActions = 0;
- for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
- const LandingPadInfo *LP = LandingPads[i];
- const std::vector<int> &TypeIds = LP->TypeIds;
- const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0;
- unsigned SizeSiteActions = 0;
-
- if (NumShared < TypeIds.size()) {
- unsigned SizeAction = 0;
- ActionEntry *PrevAction = 0;
-
- if (NumShared) {
- const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size();
- assert(Actions.size());
- PrevAction = &Actions.back();
- SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) +
- MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID);
- for (unsigned j = NumShared; j != SizePrevIds; ++j) {
- SizeAction -= MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID);
- SizeAction += -PrevAction->NextAction;
- PrevAction = PrevAction->Previous;
- }
- }
-
- // Compute the actions.
- for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) {
- int TypeID = TypeIds[I];
- assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
- int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
- unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID);
-
- int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
- SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction);
- SizeSiteActions += SizeAction;
-
- ActionEntry Action = {ValueForTypeID, NextAction, PrevAction};
- Actions.push_back(Action);
-
- PrevAction = &Actions.back();
- }
-
- // Record the first action of the landing pad site.
- FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
- } // else identical - re-use previous FirstAction
-
- FirstActions.push_back(FirstAction);
-
- // Compute this sites contribution to size.
- SizeActions += SizeSiteActions;
- }
-
- // Compute the call-site table. Entries must be ordered by address.
- SmallVector<CallSiteEntry, 64> CallSites;
-
- RangeMapType PadMap;
- for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
- const LandingPadInfo *LandingPad = LandingPads[i];
- for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
- MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
- assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
- PadRange P = { i, j };
- PadMap[BeginLabel] = P;
- }
- }
-
- bool MayThrow = false;
- MCSymbol *LastLabel = 0;
- for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
- I != E; ++I) {
- for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
- MI != E; ++MI) {
- if (!MI->isLabel()) {
- MayThrow |= MI->isCall();
- continue;
- }
-
- MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol();
- assert(BeginLabel && "Invalid label!");
-
- if (BeginLabel == LastLabel)
- MayThrow = false;
-
- RangeMapType::iterator L = PadMap.find(BeginLabel);
-
- if (L == PadMap.end())
- continue;
-
- PadRange P = L->second;
- const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
-
- assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
- "Inconsistent landing pad map!");
-
- // If some instruction between the previous try-range and this one may
- // throw, create a call-site entry with no landing pad for the region
- // between the try-ranges.
- if (MayThrow) {
- CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
- CallSites.push_back(Site);
- }
-
- LastLabel = LandingPad->EndLabels[P.RangeIndex];
- CallSiteEntry Site = {BeginLabel, LastLabel,
- LandingPad->LandingPadLabel, FirstActions[P.PadIndex]};
-
- assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel &&
- "Invalid landing pad!");
-
- // Try to merge with the previous call-site.
- if (CallSites.size()) {
- CallSiteEntry &Prev = CallSites.back();
- if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
- // Extend the range of the previous entry.
- Prev.EndLabel = Site.EndLabel;
- continue;
- }
- }
-
- // Otherwise, create a new call-site.
- CallSites.push_back(Site);
- }
- }
- // If some instruction between the previous try-range and the end of the
- // function may throw, create a call-site entry with no landing pad for the
- // region following the try-range.
- if (MayThrow) {
- CallSiteEntry Site = {LastLabel, 0, 0, 0};
- CallSites.push_back(Site);
- }
-
- // Final tallies.
- unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start.
- sizeof(int32_t) + // Site length.
- sizeof(int32_t)); // Landing pad.
- for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
- SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action);
-
- unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize();
-
- unsigned TypeOffset = sizeof(int8_t) + // Call site format
- // Call-site table length
- MCAsmInfo::getULEB128Size(SizeSites) +
- SizeSites + SizeActions + SizeTypes;
-
- // Begin the exception table.
- JCE->emitAlignmentWithFill(4, 0);
- // Asm->EOL("Padding");
-
- unsigned char* DwarfExceptionTable = (unsigned char*)JCE->getCurrentPCValue();
-
- // Emit the header.
- JCE->emitByte(dwarf::DW_EH_PE_omit);
- // Asm->EOL("LPStart format (DW_EH_PE_omit)");
- JCE->emitByte(dwarf::DW_EH_PE_absptr);
- // Asm->EOL("TType format (DW_EH_PE_absptr)");
- JCE->emitULEB128Bytes(TypeOffset);
- // Asm->EOL("TType base offset");
- JCE->emitByte(dwarf::DW_EH_PE_udata4);
- // Asm->EOL("Call site format (DW_EH_PE_udata4)");
- JCE->emitULEB128Bytes(SizeSites);
- // Asm->EOL("Call-site table length");
-
- // Emit the landing pad site information.
- for (unsigned i = 0; i < CallSites.size(); ++i) {
- CallSiteEntry &S = CallSites[i];
- intptr_t BeginLabelPtr = 0;
- intptr_t EndLabelPtr = 0;
-
- if (!S.BeginLabel) {
- BeginLabelPtr = (intptr_t)StartFunction;
- JCE->emitInt32(0);
- } else {
- BeginLabelPtr = JCE->getLabelAddress(S.BeginLabel);
- JCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction);
- }
-
- // Asm->EOL("Region start");
-
- if (!S.EndLabel)
- EndLabelPtr = (intptr_t)EndFunction;
- else
- EndLabelPtr = JCE->getLabelAddress(S.EndLabel);
-
- JCE->emitInt32(EndLabelPtr - BeginLabelPtr);
- //Asm->EOL("Region length");
-
- if (!S.PadLabel) {
- JCE->emitInt32(0);
- } else {
- unsigned PadLabelPtr = JCE->getLabelAddress(S.PadLabel);
- JCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction);
- }
- // Asm->EOL("Landing pad");
-
- JCE->emitULEB128Bytes(S.Action);
- // Asm->EOL("Action");
- }
-
- // Emit the actions.
- for (unsigned I = 0, N = Actions.size(); I != N; ++I) {
- ActionEntry &Action = Actions[I];
-
- JCE->emitSLEB128Bytes(Action.ValueForTypeID);
- //Asm->EOL("TypeInfo index");
- JCE->emitSLEB128Bytes(Action.NextAction);
- //Asm->EOL("Next action");
- }
-
- // Emit the type ids.
- for (unsigned M = TypeInfos.size(); M; --M) {
- const GlobalVariable *GV = TypeInfos[M - 1];
-
- if (GV) {
- if (TD->getPointerSize() == sizeof(int32_t))
- JCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV));
- else
- JCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV));
- } else {
- if (TD->getPointerSize() == sizeof(int32_t))
- JCE->emitInt32(0);
- else
- JCE->emitInt64(0);
- }
- // Asm->EOL("TypeInfo");
- }
-
- // Emit the filter typeids.
- for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) {
- unsigned TypeID = FilterIds[j];
- JCE->emitULEB128Bytes(TypeID);
- //Asm->EOL("Filter TypeInfo index");
- }
-
- JCE->emitAlignmentWithFill(4, 0);
-
- return DwarfExceptionTable;
-}
-
-unsigned char*
-JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const {
- unsigned PointerSize = TD->getPointerSize();
- int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ?
- PointerSize : -PointerSize;
-
- unsigned char* StartCommonPtr = (unsigned char*)JCE->getCurrentPCValue();
- // EH Common Frame header
- JCE->allocateSpace(4, 0);
- unsigned char* FrameCommonBeginPtr = (unsigned char*)JCE->getCurrentPCValue();
- JCE->emitInt32((int)0);
- JCE->emitByte(dwarf::DW_CIE_VERSION);
- JCE->emitString(Personality ? "zPLR" : "zR");
- JCE->emitULEB128Bytes(1);
- JCE->emitSLEB128Bytes(stackGrowth);
- JCE->emitByte(RI->getDwarfRegNum(RI->getRARegister(), true));
-
- if (Personality) {
- // Augmentation Size: 3 small ULEBs of one byte each, and the personality
- // function which size is PointerSize.
- JCE->emitULEB128Bytes(3 + PointerSize);
-
- // We set the encoding of the personality as direct encoding because we use
- // the function pointer. The encoding is not relative because the current
- // PC value may be bigger than the personality function pointer.
- if (PointerSize == 4) {
- JCE->emitByte(dwarf::DW_EH_PE_sdata4);
- JCE->emitInt32(((intptr_t)Jit.getPointerToGlobal(Personality)));
- } else {
- JCE->emitByte(dwarf::DW_EH_PE_sdata8);
- JCE->emitInt64(((intptr_t)Jit.getPointerToGlobal(Personality)));
- }
-
- // LSDA encoding: This must match the encoding used in EmitEHFrame ()
- if (PointerSize == 4)
- JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4);
- else
- JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8);
- JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4);
- } else {
- JCE->emitULEB128Bytes(1);
- JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4);
- }
-
- EmitFrameMoves(0, MAI->getInitialFrameState());
-
- JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop);
-
- JCE->emitInt32At((uintptr_t*)StartCommonPtr,
- (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() -
- FrameCommonBeginPtr));
-
- return StartCommonPtr;
-}
-
-
-unsigned char*
-JITDwarfEmitter::EmitEHFrame(const Function* Personality,
- unsigned char* StartCommonPtr,
- unsigned char* StartFunction,
- unsigned char* EndFunction,
- unsigned char* ExceptionTable) const {
- unsigned PointerSize = TD->getPointerSize();
-
- // EH frame header.
- unsigned char* StartEHPtr = (unsigned char*)JCE->getCurrentPCValue();
- JCE->allocateSpace(4, 0);
- unsigned char* FrameBeginPtr = (unsigned char*)JCE->getCurrentPCValue();
- // FDE CIE Offset
- JCE->emitInt32(FrameBeginPtr - StartCommonPtr);
- JCE->emitInt32(StartFunction - (unsigned char*)JCE->getCurrentPCValue());
- JCE->emitInt32(EndFunction - StartFunction);
-
- // If there is a personality and landing pads then point to the language
- // specific data area in the exception table.
- if (Personality) {
- JCE->emitULEB128Bytes(PointerSize == 4 ? 4 : 8);
-
- if (PointerSize == 4) {
- if (!MMI->getLandingPads().empty())
- JCE->emitInt32(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue());
- else
- JCE->emitInt32((int)0);
- } else {
- if (!MMI->getLandingPads().empty())
- JCE->emitInt64(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue());
- else
- JCE->emitInt64((int)0);
- }
- } else {
- JCE->emitULEB128Bytes(0);
- }
-
- // Indicate locations of function specific callee saved registers in
- // frame.
- EmitFrameMoves((intptr_t)StartFunction, MMI->getFrameMoves());
-
- JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop);
-
- // Indicate the size of the table
- JCE->emitInt32At((uintptr_t*)StartEHPtr,
- (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() -
- StartEHPtr));
-
- // Double zeroes for the unwind runtime
- if (PointerSize == 8) {
- JCE->emitInt64(0);
- JCE->emitInt64(0);
- } else {
- JCE->emitInt32(0);
- JCE->emitInt32(0);
- }
-
- return StartEHPtr;
-}
diff --git a/lib/ExecutionEngine/JIT/JITDwarfEmitter.h b/lib/ExecutionEngine/JIT/JITDwarfEmitter.h
deleted file mode 100644
index 98ac340..0000000
--- a/lib/ExecutionEngine/JIT/JITDwarfEmitter.h
+++ /dev/null
@@ -1,77 +0,0 @@
-//===------ JITDwarfEmitter.h - Write dwarf tables into memory ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a JITDwarfEmitter object that is used by the JIT to
-// write dwarf tables to memory.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
-#define LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
-
-#include "llvm/Support/DataTypes.h"
-#include <vector>
-
-namespace llvm {
-
-class Function;
-class JIT;
-class JITCodeEmitter;
-class MachineFunction;
-class MachineModuleInfo;
-class MachineMove;
-class MCAsmInfo;
-class DataLayout;
-class TargetMachine;
-class TargetRegisterInfo;
-
-class JITDwarfEmitter {
- const DataLayout* TD;
- JITCodeEmitter* JCE;
- const TargetRegisterInfo* RI;
- const MCAsmInfo *MAI;
- MachineModuleInfo* MMI;
- JIT& Jit;
- bool stackGrowthDirection;
-
- unsigned char* EmitExceptionTable(MachineFunction* MF,
- unsigned char* StartFunction,
- unsigned char* EndFunction) const;
-
- void EmitFrameMoves(intptr_t BaseLabelPtr,
- const std::vector<MachineMove> &Moves) const;
-
- unsigned char* EmitCommonEHFrame(const Function* Personality) const;
-
- unsigned char* EmitEHFrame(const Function* Personality,
- unsigned char* StartBufferPtr,
- unsigned char* StartFunction,
- unsigned char* EndFunction,
- unsigned char* ExceptionTable) const;
-
-public:
-
- JITDwarfEmitter(JIT& jit);
-
- unsigned char* EmitDwarfTable(MachineFunction& F,
- JITCodeEmitter& JCE,
- unsigned char* StartFunction,
- unsigned char* EndFunction,
- unsigned char* &EHFramePtr);
-
-
- void setModuleInfo(MachineModuleInfo* Info) {
- MMI = Info;
- }
-};
-
-
-} // end namespace llvm
-
-#endif // LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index c273876..acbbfa1 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -14,7 +14,6 @@
#define DEBUG_TYPE "jit"
#include "JIT.h"
-#include "JITDwarfEmitter.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -325,9 +324,6 @@ namespace {
/// Resolver - This contains info about the currently resolved functions.
JITResolver Resolver;
- /// DE - The dwarf emitter for the jit.
- OwningPtr<JITDwarfEmitter> DE;
-
/// LabelLocations - This vector is a mapping from Label ID's to their
/// address.
DenseMap<MCSymbol*, uintptr_t> LabelLocations;
@@ -363,22 +359,16 @@ namespace {
/// Instance of the JIT
JIT *TheJIT;
- bool JITExceptionHandling;
-
public:
JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM)
: SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0),
- EmittedFunctions(this), TheJIT(&jit),
- JITExceptionHandling(TM.Options.JITExceptionHandling) {
+ EmittedFunctions(this), TheJIT(&jit) {
MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
if (jit.getJITInfo().needsGOT()) {
MemMgr->AllocateGOT();
DEBUG(dbgs() << "JIT is managing a GOT\n");
}
- if (JITExceptionHandling) {
- DE.reset(new JITDwarfEmitter(jit));
- }
}
~JITEmitter() {
delete MemMgr;
@@ -460,7 +450,6 @@ namespace {
virtual void setModuleInfo(MachineModuleInfo* Info) {
MMI = Info;
- if (DE.get()) DE->setModuleInfo(Info);
}
private:
@@ -964,40 +953,6 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
}
});
- if (JITExceptionHandling) {
- uintptr_t ActualSize = 0;
- SavedBufferBegin = BufferBegin;
- SavedBufferEnd = BufferEnd;
- SavedCurBufferPtr = CurBufferPtr;
- uint8_t *FrameRegister;
-
- while (true) {
- BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
- ActualSize);
- BufferEnd = BufferBegin+ActualSize;
- EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
- uint8_t *EhStart;
- FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, EhStart);
-
- // If the buffer was large enough to hold the table then we are done.
- if (CurBufferPtr != BufferEnd)
- break;
-
- // Try again with twice as much space.
- ActualSize = (CurBufferPtr - BufferBegin) * 2;
- MemMgr->deallocateExceptionTable(BufferBegin);
- }
- MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
- FrameRegister);
- BufferBegin = SavedBufferBegin;
- BufferEnd = SavedBufferEnd;
- CurBufferPtr = SavedCurBufferPtr;
-
- if (JITExceptionHandling) {
- TheJIT->RegisterTable(F.getFunction(), FrameRegister);
- }
- }
-
if (MMI)
MMI->EndFunction();
@@ -1027,15 +982,10 @@ void JITEmitter::deallocateMemForFunction(const Function *F) {
Emitted = EmittedFunctions.find(F);
if (Emitted != EmittedFunctions.end()) {
MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody);
- MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable);
TheJIT->NotifyFreeingMachineCode(Emitted->second.Code);
EmittedFunctions.erase(Emitted);
}
-
- if (JITExceptionHandling) {
- TheJIT->DeregisterTable(F);
- }
}
diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
index 66aeb77..6a1db16 100644
--- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
+++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
@@ -509,30 +509,10 @@ namespace {
return (uint8_t*)DataAllocator.Allocate(Size, Alignment);
}
- bool applyPermissions(std::string *ErrMsg) {
+ bool finalizeMemory(std::string *ErrMsg) {
return false;
}
- /// startExceptionTable - Use startFunctionBody to allocate memory for the
- /// function's exception table.
- uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
- return startFunctionBody(F, ActualSize);
- }
-
- /// endExceptionTable - The exception table of F is now allocated,
- /// and takes the memory in the range [TableStart,TableEnd).
- void endExceptionTable(const Function *F, uint8_t *TableStart,
- uint8_t *TableEnd, uint8_t* FrameRegister) {
- assert(TableEnd > TableStart);
- assert(TableStart == (uint8_t *)(CurBlock+1) &&
- "Mismatched table start/end!");
-
- uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock;
-
- // Release the memory at the end of this block that isn't needed.
- FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
- }
-
uint8_t *getGOTBase() const {
return GOTBase;
}
@@ -557,12 +537,6 @@ namespace {
if (Body) deallocateBlock(Body);
}
- /// deallocateExceptionTable - Deallocate memory for the specified
- /// exception table.
- void deallocateExceptionTable(void *ET) {
- if (ET) deallocateBlock(ET);
- }
-
/// setMemoryWritable - When code generation is in progress,
/// the code pages may need permissions changed.
void setMemoryWritable()
diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp
index ccaa72a..e861938 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp
+++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp
@@ -39,7 +39,7 @@ extern "C" void LLVMLinkInMCJIT() {
ExecutionEngine *MCJIT::createJIT(Module *M,
std::string *ErrorStr,
- JITMemoryManager *JMM,
+ RTDyldMemoryManager *MemMgr,
bool GVsWithCode,
TargetMachine *TM) {
// Try to register the program as a source of symbols to resolve against.
@@ -47,14 +47,14 @@ ExecutionEngine *MCJIT::createJIT(Module *M,
// FIXME: Don't do this here.
sys::DynamicLibrary::LoadLibraryPermanently(0, NULL);
- return new MCJIT(M, TM, JMM ? JMM : new SectionMemoryManager(), GVsWithCode);
+ return new MCJIT(M, TM, MemMgr ? MemMgr : new SectionMemoryManager(),
+ GVsWithCode);
}
MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM,
bool AllocateGVsWithCode)
- : ExecutionEngine(m), TM(tm), Ctx(0),
- MemMgr(MM ? MM : new SectionMemoryManager()), Dyld(MemMgr),
- IsLoaded(false), M(m), ObjCache(0) {
+ : ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(MM), Dyld(MM),
+ IsLoaded(false), M(m), ObjCache(0) {
setDataLayout(TM->getDataLayout());
}
@@ -168,18 +168,17 @@ void MCJIT::finalizeObject() {
// If the call to Dyld.resolveRelocations() is removed from loadObject()
// we'll need to do that here.
loadObject(M);
-
- // Set page permissions.
- MemMgr->applyPermissions();
-
- return;
+ } else {
+ // Resolve any relocations.
+ Dyld.resolveRelocations();
}
- // Resolve any relocations.
- Dyld.resolveRelocations();
+ StringRef EHData = Dyld.getEHFrameSection();
+ if (!EHData.empty())
+ MemMgr->registerEHFrames(EHData);
// Set page permissions.
- MemMgr->applyPermissions();
+ MemMgr->finalizeMemory();
}
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h
index 8c4bf6e..a899d4f 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.h
+++ b/lib/ExecutionEngine/MCJIT/MCJIT.h
@@ -52,6 +52,13 @@ public:
/// Sets the object manager that MCJIT should use to avoid compilation.
virtual void setObjectCache(ObjectCache *manager);
+ /// finalizeObject - ensure the module is fully processed and is usable.
+ ///
+ /// It is the user-level function for completing the process of making the
+ /// object usable for execution. It should be called after sections within an
+ /// object have been relocated using mapSectionAddress. When this method is
+ /// called the MCJIT execution engine will reapply relocations for a loaded
+ /// object.
virtual void finalizeObject();
virtual void *getPointerToBasicBlock(BasicBlock *BB);
@@ -98,7 +105,7 @@ public:
static ExecutionEngine *createJIT(Module *M,
std::string *ErrorStr,
- JITMemoryManager *JMM,
+ RTDyldMemoryManager *MemMgr,
bool GVsWithCode,
TargetMachine *TM);
diff --git a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
index da93124..650832e 100644
--- a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
+++ b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
@@ -14,19 +14,8 @@
#include "llvm/Config/config.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/MathExtras.h"
-#ifdef __linux__
- // These includes used by SectionMemoryManager::getPointerToNamedFunction()
- // for Glibc trickery. See comments in this function for more information.
- #ifdef HAVE_SYS_STAT_H
- #include <sys/stat.h>
- #endif
- #include <fcntl.h>
- #include <unistd.h>
-#endif
-
namespace llvm {
uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
@@ -111,7 +100,7 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup,
return (uint8_t*)Addr;
}
-bool SectionMemoryManager::applyPermissions(std::string *ErrMsg)
+bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg)
{
// FIXME: Should in-progress permissions be reverted if an error occurs?
error_code ec;
@@ -167,57 +156,6 @@ void SectionMemoryManager::invalidateInstructionCache() {
CodeMem.AllocatedMem[i].size());
}
-static int jit_noop() {
- return 0;
-}
-
-void *SectionMemoryManager::getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure) {
-#if defined(__linux__)
- //===--------------------------------------------------------------------===//
- // Function stubs that are invoked instead of certain library calls
- //
- // Force the following functions to be linked in to anything that uses the
- // JIT. This is a hack designed to work around the all-too-clever Glibc
- // strategy of making these functions work differently when inlined vs. when
- // not inlined, and hiding their real definitions in a separate archive file
- // that the dynamic linker can't see. For more info, search for
- // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
- if (Name == "stat") return (void*)(intptr_t)&stat;
- if (Name == "fstat") return (void*)(intptr_t)&fstat;
- if (Name == "lstat") return (void*)(intptr_t)&lstat;
- if (Name == "stat64") return (void*)(intptr_t)&stat64;
- if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
- if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
- if (Name == "atexit") return (void*)(intptr_t)&atexit;
- if (Name == "mknod") return (void*)(intptr_t)&mknod;
-#endif // __linux__
-
- // We should not invoke parent's ctors/dtors from generated main()!
- // On Mingw and Cygwin, the symbol __main is resolved to
- // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
- // (and register wrong callee's dtors with atexit(3)).
- // We expect ExecutionEngine::runStaticConstructorsDestructors()
- // is called before ExecutionEngine::runFunctionAsMain() is called.
- if (Name == "__main") return (void*)(intptr_t)&jit_noop;
-
- const char *NameStr = Name.c_str();
- void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
- if (Ptr) return Ptr;
-
- // If it wasn't found and if it starts with an underscore ('_') character,
- // try again without the underscore.
- if (NameStr[0] == '_') {
- Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
- if (Ptr) return Ptr;
- }
-
- if (AbortOnFailure)
- report_fatal_error("Program used external function '" + Name +
- "' which could not be resolved!");
- return 0;
-}
-
SectionMemoryManager::~SectionMemoryManager() {
for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i)
sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]);
diff --git a/lib/ExecutionEngine/RTDyldMemoryManager.cpp b/lib/ExecutionEngine/RTDyldMemoryManager.cpp
new file mode 100644
index 0000000..4e76457
--- /dev/null
+++ b/lib/ExecutionEngine/RTDyldMemoryManager.cpp
@@ -0,0 +1,118 @@
+//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the runtime dynamic memory manager base class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include <cstdlib>
+
+#ifdef __linux__
+ // These includes used by RTDyldMemoryManager::getPointerToNamedFunction()
+ // for Glibc trickery. See comments in this function for more information.
+ #ifdef HAVE_SYS_STAT_H
+ #include <sys/stat.h>
+ #endif
+ #include <fcntl.h>
+ #include <unistd.h>
+#endif
+
+namespace llvm {
+
+RTDyldMemoryManager::~RTDyldMemoryManager() {}
+
+// Determine whether we can register EH tables.
+#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \
+ !defined(__USING_SJLJ_EXCEPTIONS__))
+#define HAVE_EHTABLE_SUPPORT 1
+#else
+#define HAVE_EHTABLE_SUPPORT 0
+#endif
+
+#if HAVE_EHTABLE_SUPPORT
+extern "C" void __register_frame(void*);
+
+static const char *processFDE(const char *Entry) {
+ const char *P = Entry;
+ uint32_t Length = *((const uint32_t *)P);
+ P += 4;
+ uint32_t Offset = *((const uint32_t *)P);
+ if (Offset != 0)
+ __register_frame(const_cast<char *>(Entry));
+ return P + Length;
+}
+#endif
+
+void RTDyldMemoryManager::registerEHFrames(StringRef SectionData) {
+#if HAVE_EHTABLE_SUPPORT
+ const char *P = SectionData.data();
+ const char *End = SectionData.data() + SectionData.size();
+ do {
+ P = processFDE(P);
+ } while(P != End);
+#endif
+}
+
+static int jit_noop() {
+ return 0;
+}
+
+void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure) {
+#if defined(__linux__)
+ //===--------------------------------------------------------------------===//
+ // Function stubs that are invoked instead of certain library calls
+ //
+ // Force the following functions to be linked in to anything that uses the
+ // JIT. This is a hack designed to work around the all-too-clever Glibc
+ // strategy of making these functions work differently when inlined vs. when
+ // not inlined, and hiding their real definitions in a separate archive file
+ // that the dynamic linker can't see. For more info, search for
+ // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
+ if (Name == "stat") return (void*)(intptr_t)&stat;
+ if (Name == "fstat") return (void*)(intptr_t)&fstat;
+ if (Name == "lstat") return (void*)(intptr_t)&lstat;
+ if (Name == "stat64") return (void*)(intptr_t)&stat64;
+ if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
+ if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
+ if (Name == "atexit") return (void*)(intptr_t)&atexit;
+ if (Name == "mknod") return (void*)(intptr_t)&mknod;
+#endif // __linux__
+
+ // We should not invoke parent's ctors/dtors from generated main()!
+ // On Mingw and Cygwin, the symbol __main is resolved to
+ // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
+ // (and register wrong callee's dtors with atexit(3)).
+ // We expect ExecutionEngine::runStaticConstructorsDestructors()
+ // is called before ExecutionEngine::runFunctionAsMain() is called.
+ if (Name == "__main") return (void*)(intptr_t)&jit_noop;
+
+ const char *NameStr = Name.c_str();
+ void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
+ if (Ptr) return Ptr;
+
+ // If it wasn't found and if it starts with an underscore ('_') character,
+ // try again without the underscore.
+ if (NameStr[0] == '_') {
+ Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
+ if (Ptr) return Ptr;
+ }
+
+ if (AbortOnFailure)
+ report_fatal_error("Program used external function '" + Name +
+ "' which could not be resolved!");
+ return 0;
+}
+
+} // namespace llvm
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 7b32db7..f0bd4e3 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -17,18 +17,22 @@
#include "RuntimeDyldELF.h"
#include "RuntimeDyldImpl.h"
#include "RuntimeDyldMachO.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/Path.h"
+#include "llvm/Object/ELF.h"
using namespace llvm;
using namespace llvm::object;
// Empty out-of-line virtual destructor as the key function.
-RTDyldMemoryManager::~RTDyldMemoryManager() {}
RuntimeDyldImpl::~RuntimeDyldImpl() {}
namespace llvm {
+StringRef RuntimeDyldImpl::getEHFrameSection() {
+ return StringRef();
+}
+
// Resolve the relocations for all symbols we currently know about.
void RuntimeDyldImpl::resolveRelocations() {
// First, resolve relocations associated with external symbols.
@@ -143,6 +147,7 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
bool isFirstRelocation = true;
unsigned SectionID = 0;
StubMap Stubs;
+ section_iterator RelocatedSection = si->getRelocatedSection();
for (relocation_iterator i = si->begin_relocations(),
e = si->end_relocations(); i != e; i.increment(err)) {
@@ -150,7 +155,8 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
// If it's the first relocation in this section, find its SectionID
if (isFirstRelocation) {
- SectionID = findOrEmitSection(*obj, *si, true, LocalSections);
+ SectionID =
+ findOrEmitSection(*obj, *RelocatedSection, true, LocalSections);
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
isFirstRelocation = false;
}
@@ -174,7 +180,7 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
if (!Addr)
report_fatal_error("Unable to allocate memory for common symbols!");
uint64_t Offset = 0;
- Sections.push_back(SectionEntry(StringRef(), Addr, TotalSize, TotalSize, 0));
+ Sections.push_back(SectionEntry(StringRef(), Addr, TotalSize, 0));
memset(Addr, 0, TotalSize);
DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID
@@ -211,11 +217,25 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
unsigned StubBufSize = 0,
StubSize = getMaxStubSize();
error_code err;
+ const ObjectFile *ObjFile = Obj.getObjectFile();
+ // FIXME: this is an inefficient way to handle this. We should computed the
+ // necessary section allocation size in loadObject by walking all the sections
+ // once.
if (StubSize > 0) {
- for (relocation_iterator i = Section.begin_relocations(),
- e = Section.end_relocations(); i != e; i.increment(err), Check(err))
- StubBufSize += StubSize;
+ for (section_iterator SI = ObjFile->begin_sections(),
+ SE = ObjFile->end_sections();
+ SI != SE; SI.increment(err), Check(err)) {
+ section_iterator RelSecI = SI->getRelocatedSection();
+ if (!(RelSecI == Section))
+ continue;
+
+ for (relocation_iterator I = SI->begin_relocations(),
+ E = SI->end_relocations(); I != E; I.increment(err), Check(err)) {
+ StubBufSize += StubSize;
+ }
+ }
}
+
StringRef data;
uint64_t Alignment64;
Check(Section.getContents(data));
@@ -234,6 +254,12 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
Check(Section.isReadOnlyData(IsReadOnly));
Check(Section.getSize(DataSize));
Check(Section.getName(Name));
+ if (StubSize > 0) {
+ unsigned StubAlignment = getStubAlignment();
+ unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
+ if (StubAlignment > EndAlignment)
+ StubBufSize += StubAlignment - EndAlignment;
+ }
unsigned Allocate;
unsigned SectionID = Sections.size();
@@ -286,8 +312,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
<< "\n");
}
- Sections.push_back(SectionEntry(Name, Addr, Allocate, DataSize,
- (uintptr_t)pData));
+ Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
return SectionID;
}
@@ -330,7 +355,25 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE,
}
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
- if (Arch == Triple::arm) {
+ if (Arch == Triple::aarch64) {
+ // This stub has to be able to access the full address space,
+ // since symbol lookup won't necessarily find a handy, in-range,
+ // PLT stub for functions which could be anywhere.
+ uint32_t *StubAddr = (uint32_t*)Addr;
+
+ // Stub can use ip0 (== x16) to calculate address
+ *StubAddr = 0xd2e00010; // movz ip0, #:abs_g3:<addr>
+ StubAddr++;
+ *StubAddr = 0xf2c00010; // movk ip0, #:abs_g2_nc:<addr>
+ StubAddr++;
+ *StubAddr = 0xf2a00010; // movk ip0, #:abs_g1_nc:<addr>
+ StubAddr++;
+ *StubAddr = 0xf2800010; // movk ip0, #:abs_g0_nc:<addr>
+ StubAddr++;
+ *StubAddr = 0xd61f0200; // br ip0
+
+ return Addr;
+ } else if (Arch == Triple::arm) {
// TODO: There is only ARM far stub now. We should add the Thumb stub,
// and stubs for branches Thumb - ARM and ARM - Thumb.
uint32_t *StubAddr = (uint32_t*)Addr;
@@ -371,6 +414,13 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
writeInt32BE(Addr+40, 0x4E800420); // bctr
return Addr;
+ } else if (Arch == Triple::systemz) {
+ writeInt16BE(Addr, 0xC418); // lgrl %r1,.+8
+ writeInt16BE(Addr+2, 0x0000);
+ writeInt16BE(Addr+4, 0x0004);
+ writeInt16BE(Addr+6, 0x07F1); // brc 15,%r1
+ // 8-byte address stored at Addr + 8
+ return Addr;
}
return Addr;
}
@@ -451,33 +501,33 @@ RuntimeDyld::~RuntimeDyld() {
ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) {
if (!Dyld) {
- sys::LLVMFileType type = sys::IdentifyFileType(
- InputBuffer->getBufferStart(),
- static_cast<unsigned>(InputBuffer->getBufferSize()));
- switch (type) {
- case sys::ELF_Relocatable_FileType:
- case sys::ELF_Executable_FileType:
- case sys::ELF_SharedObject_FileType:
- case sys::ELF_Core_FileType:
- Dyld = new RuntimeDyldELF(MM);
- break;
- case sys::Mach_O_Object_FileType:
- case sys::Mach_O_Executable_FileType:
- case sys::Mach_O_FixedVirtualMemorySharedLib_FileType:
- case sys::Mach_O_Core_FileType:
- case sys::Mach_O_PreloadExecutable_FileType:
- case sys::Mach_O_DynamicallyLinkedSharedLib_FileType:
- case sys::Mach_O_DynamicLinker_FileType:
- case sys::Mach_O_Bundle_FileType:
- case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType:
- case sys::Mach_O_DSYMCompanion_FileType:
- Dyld = new RuntimeDyldMachO(MM);
- break;
- case sys::Unknown_FileType:
- case sys::Bitcode_FileType:
- case sys::Archive_FileType:
- case sys::COFF_FileType:
- report_fatal_error("Incompatible object format!");
+ sys::fs::file_magic Type =
+ sys::fs::identify_magic(InputBuffer->getBuffer());
+ switch (Type) {
+ case sys::fs::file_magic::elf_relocatable:
+ case sys::fs::file_magic::elf_executable:
+ case sys::fs::file_magic::elf_shared_object:
+ case sys::fs::file_magic::elf_core:
+ Dyld = new RuntimeDyldELF(MM);
+ break;
+ case sys::fs::file_magic::macho_object:
+ case sys::fs::file_magic::macho_executable:
+ case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib:
+ case sys::fs::file_magic::macho_core:
+ case sys::fs::file_magic::macho_preload_executable:
+ case sys::fs::file_magic::macho_dynamically_linked_shared_lib:
+ case sys::fs::file_magic::macho_dynamic_linker:
+ case sys::fs::file_magic::macho_bundle:
+ case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
+ case sys::fs::file_magic::macho_dsym_companion:
+ Dyld = new RuntimeDyldMachO(MM);
+ break;
+ case sys::fs::file_magic::unknown:
+ case sys::fs::file_magic::bitcode:
+ case sys::fs::file_magic::archive:
+ case sys::fs::file_magic::coff_object:
+ case sys::fs::file_magic::pecoff_executable:
+ report_fatal_error("Incompatible object format!");
}
} else {
if (!Dyld->isCompatibleFormat(InputBuffer))
@@ -513,4 +563,8 @@ StringRef RuntimeDyld::getErrorString() {
return Dyld->getErrorString();
}
+StringRef RuntimeDyld::getEHFrameSection() {
+ return Dyld->getEHFrameSection();
+}
+
} // end namespace llvm
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index c5bad8e..722ed10 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -151,6 +151,14 @@ void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef,
namespace llvm {
+StringRef RuntimeDyldELF::getEHFrameSection() {
+ for (int i = 0, e = Sections.size(); i != e; ++i) {
+ if (Sections[i].Name == ".eh_frame")
+ return StringRef((const char*)Sections[i].Address, Sections[i].Size);
+ }
+ return StringRef();
+}
+
ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) {
if (Buffer->getBufferSize() < ELF::EI_NIDENT)
llvm_unreachable("Unexpected ELF object size");
@@ -269,12 +277,114 @@ void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section,
}
}
+void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend) {
+ uint32_t *TargetPtr = reinterpret_cast<uint32_t*>(Section.Address + Offset);
+ uint64_t FinalAddress = Section.LoadAddress + Offset;
+
+ DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x"
+ << format("%llx", Section.Address + Offset)
+ << " FinalAddress: 0x" << format("%llx",FinalAddress)
+ << " Value: 0x" << format("%llx",Value)
+ << " Type: 0x" << format("%x",Type)
+ << " Addend: 0x" << format("%llx",Addend)
+ << "\n");
+
+ switch (Type) {
+ default:
+ llvm_unreachable("Relocation type not implemented yet!");
+ break;
+ case ELF::R_AARCH64_ABS64: {
+ uint64_t *TargetPtr = reinterpret_cast<uint64_t*>(Section.Address + Offset);
+ *TargetPtr = Value + Addend;
+ break;
+ }
+ case ELF::R_AARCH64_PREL32: {
+ uint64_t Result = Value + Addend - FinalAddress;
+ assert(static_cast<int64_t>(Result) >= INT32_MIN &&
+ static_cast<int64_t>(Result) <= UINT32_MAX);
+ *TargetPtr = static_cast<uint32_t>(Result & 0xffffffffU);
+ break;
+ }
+ case ELF::R_AARCH64_CALL26: // fallthrough
+ case ELF::R_AARCH64_JUMP26: {
+ // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the
+ // calculation.
+ uint64_t BranchImm = Value + Addend - FinalAddress;
+
+ // "Check that -2^27 <= result < 2^27".
+ assert(-(1LL << 27) <= static_cast<int64_t>(BranchImm) &&
+ static_cast<int64_t>(BranchImm) < (1LL << 27));
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xfc000000U;
+ // Immediate goes in bits 25:0 of B and BL.
+ *TargetPtr |= static_cast<uint32_t>(BranchImm & 0xffffffcU) >> 2;
+ break;
+ }
+ case ELF::R_AARCH64_MOVW_UABS_G3: {
+ uint64_t Result = Value + Addend;
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xff80001fU;
+ // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
+ *TargetPtr |= Result >> (48 - 5);
+ // Shift is "lsl #48", in bits 22:21
+ *TargetPtr |= 3 << 21;
+ break;
+ }
+ case ELF::R_AARCH64_MOVW_UABS_G2_NC: {
+ uint64_t Result = Value + Addend;
+
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xff80001fU;
+ // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
+ *TargetPtr |= ((Result & 0xffff00000000ULL) >> (32 - 5));
+ // Shift is "lsl #32", in bits 22:21
+ *TargetPtr |= 2 << 21;
+ break;
+ }
+ case ELF::R_AARCH64_MOVW_UABS_G1_NC: {
+ uint64_t Result = Value + Addend;
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xff80001fU;
+ // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
+ *TargetPtr |= ((Result & 0xffff0000U) >> (16 - 5));
+ // Shift is "lsl #16", in bits 22:21
+ *TargetPtr |= 1 << 21;
+ break;
+ }
+ case ELF::R_AARCH64_MOVW_UABS_G0_NC: {
+ uint64_t Result = Value + Addend;
+
+ // AArch64 code is emitted with .rela relocations. The data already in any
+ // bits affected by the relocation on entry is garbage.
+ *TargetPtr &= 0xff80001fU;
+ // Immediate goes in bits 20:5 of MOVZ/MOVK instruction
+ *TargetPtr |= ((Result & 0xffffU) << 5);
+ // Shift is "lsl #0", in bits 22:21. No action needed.
+ break;
+ }
+ }
+}
+
void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
uint64_t Offset,
uint32_t Value,
uint32_t Type,
int32_t Addend) {
// TODO: Add Thumb relocations.
+ uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress +
+ Offset);
uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
Value += Addend;
@@ -293,44 +403,51 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
// Write a 32bit value to relocation address, taking into account the
// implicit addend encoded in the target.
- case ELF::R_ARM_TARGET1 :
- case ELF::R_ARM_ABS32 :
- *TargetPtr += Value;
+ case ELF::R_ARM_TARGET1:
+ case ELF::R_ARM_ABS32:
+ *TargetPtr = *Placeholder + Value;
break;
-
// Write first 16 bit of 32 bit value to the mov instruction.
// Last 4 bit should be shifted.
- case ELF::R_ARM_MOVW_ABS_NC :
+ case ELF::R_ARM_MOVW_ABS_NC:
// We are not expecting any other addend in the relocation address.
// Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2
// non-contiguous fields.
- assert((*TargetPtr & 0x000F0FFF) == 0);
+ assert((*Placeholder & 0x000F0FFF) == 0);
Value = Value & 0xFFFF;
- *TargetPtr |= Value & 0xFFF;
+ *TargetPtr = *Placeholder | (Value & 0xFFF);
*TargetPtr |= ((Value >> 12) & 0xF) << 16;
break;
-
// Write last 16 bit of 32 bit value to the mov instruction.
// Last 4 bit should be shifted.
- case ELF::R_ARM_MOVT_ABS :
+ case ELF::R_ARM_MOVT_ABS:
// We are not expecting any other addend in the relocation address.
// Use 0x000F0FFF for the same reason as R_ARM_MOVW_ABS_NC.
- assert((*TargetPtr & 0x000F0FFF) == 0);
+ assert((*Placeholder & 0x000F0FFF) == 0);
+
Value = (Value >> 16) & 0xFFFF;
- *TargetPtr |= Value & 0xFFF;
+ *TargetPtr = *Placeholder | (Value & 0xFFF);
*TargetPtr |= ((Value >> 12) & 0xF) << 16;
break;
-
// Write 24 bit relative value to the branch instruction.
case ELF::R_ARM_PC24 : // Fall through.
case ELF::R_ARM_CALL : // Fall through.
- case ELF::R_ARM_JUMP24 :
+ case ELF::R_ARM_JUMP24: {
int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8);
RelValue = (RelValue & 0x03FFFFFC) >> 2;
+ assert((*TargetPtr & 0xFFFFFF) == 0xFFFFFE);
*TargetPtr &= 0xFF000000;
*TargetPtr |= RelValue;
break;
}
+ case ELF::R_ARM_PRIVATE_0:
+ // This relocation is reserved by the ARM ELF ABI for internal use. We
+ // appropriate it here to act as an R_ARM_ABS32 without any addend for use
+ // in the stubs created during JIT (which can't put an addend into the
+ // original object file).
+ *TargetPtr = Value;
+ break;
+ }
}
void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
@@ -412,9 +529,13 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
error_code err;
for (section_iterator si = Obj.begin_sections(),
se = Obj.end_sections(); si != se; si.increment(err)) {
- StringRef SectionName;
- check(si->getName(SectionName));
- if (SectionName != ".opd")
+ section_iterator RelSecI = si->getRelocatedSection();
+ if (RelSecI == Obj.end_sections())
+ continue;
+
+ StringRef RelSectionName;
+ check(RelSecI->getName(RelSectionName));
+ if (RelSectionName != ".opd")
continue;
for (relocation_iterator i = si->begin_relocations(),
@@ -430,12 +551,11 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
continue;
}
- SymbolRef TargetSymbol;
uint64_t TargetSymbolOffset;
- int64_t TargetAdditionalInfo;
- check(i->getSymbol(TargetSymbol));
+ symbol_iterator TargetSymbol = i->getSymbol();
check(i->getOffset(TargetSymbolOffset));
- check(i->getAdditionalInfo(TargetAdditionalInfo));
+ int64_t Addend;
+ check(getELFRelocationAddend(*i, Addend));
i = i.increment(err);
if (i == e)
@@ -455,9 +575,9 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
continue;
section_iterator tsi(Obj.end_sections());
- check(TargetSymbol.getSection(tsi));
+ check(TargetSymbol->getSection(tsi));
Rel.SectionID = findOrEmitSection(Obj, (*tsi), true, LocalSections);
- Rel.Addend = (intptr_t)TargetAdditionalInfo;
+ Rel.Addend = (intptr_t)Addend;
return;
}
}
@@ -541,6 +661,11 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,
llvm_unreachable("Relocation R_PPC64_REL32 overflow");
writeInt32BE(LocalAddress, delta);
} break;
+ case ELF::R_PPC64_REL64: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ uint64_t Delta = Value - FinalAddress + Addend;
+ writeInt64BE(LocalAddress, Delta);
+ } break;
case ELF::R_PPC64_ADDR64 :
writeInt64BE(LocalAddress, Value + Addend);
break;
@@ -560,6 +685,42 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,
}
}
+void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend) {
+ uint8_t *LocalAddress = Section.Address + Offset;
+ switch (Type) {
+ default:
+ llvm_unreachable("Relocation type not implemented yet!");
+ break;
+ case ELF::R_390_PC16DBL:
+ case ELF::R_390_PLT16DBL: {
+ int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
+ assert(int16_t(Delta / 2) * 2 == Delta && "R_390_PC16DBL overflow");
+ writeInt16BE(LocalAddress, Delta / 2);
+ break;
+ }
+ case ELF::R_390_PC32DBL:
+ case ELF::R_390_PLT32DBL: {
+ int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
+ assert(int32_t(Delta / 2) * 2 == Delta && "R_390_PC32DBL overflow");
+ writeInt32BE(LocalAddress, Delta / 2);
+ break;
+ }
+ case ELF::R_390_PC32: {
+ int64_t Delta = (Value + Addend) - (Section.LoadAddress + Offset);
+ assert(int32_t(Delta) == Delta && "R_390_PC32 overflow");
+ writeInt32BE(LocalAddress, Delta);
+ break;
+ }
+ case ELF::R_390_64:
+ writeInt64BE(LocalAddress, Value + Addend);
+ break;
+ }
+}
+
void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE,
uint64_t Value) {
const SectionEntry &Section = Sections[RE.SectionID];
@@ -580,6 +741,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
(uint32_t)(Value & 0xffffffffL), Type,
(uint32_t)(Addend & 0xffffffffL));
break;
+ case Triple::aarch64:
+ resolveAArch64Relocation(Section, Offset, Value, Type, Addend);
+ break;
case Triple::arm: // Fall through.
case Triple::thumb:
resolveARMRelocation(Section, Offset,
@@ -595,6 +759,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
case Triple::ppc64:
resolvePPC64Relocation(Section, Offset, Value, Type, Addend);
break;
+ case Triple::systemz:
+ resolveSystemZRelocation(Section, Offset, Value, Type, Addend);
+ break;
default: llvm_unreachable("Unsupported CPU type!");
}
}
@@ -608,29 +775,33 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
uint64_t RelType;
Check(RelI.getType(RelType));
int64_t Addend;
- Check(RelI.getAdditionalInfo(Addend));
- SymbolRef Symbol;
- Check(RelI.getSymbol(Symbol));
+ Check(getELFRelocationAddend(RelI, Addend));
+ symbol_iterator Symbol = RelI.getSymbol();
// Obtain the symbol name which is referenced in the relocation
StringRef TargetName;
- Symbol.getName(TargetName);
+ if (Symbol != Obj.end_symbols())
+ Symbol->getName(TargetName);
DEBUG(dbgs() << "\t\tRelType: " << RelType
<< " Addend: " << Addend
<< " TargetName: " << TargetName
<< "\n");
RelocationValueRef Value;
// First search for the symbol in the local symbol table
- SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
- SymbolRef::Type SymType;
- Symbol.getType(SymType);
+ SymbolTableMap::const_iterator lsi = Symbols.end();
+ SymbolRef::Type SymType = SymbolRef::ST_Unknown;
+ if (Symbol != Obj.end_symbols()) {
+ lsi = Symbols.find(TargetName.data());
+ Symbol->getType(SymType);
+ }
if (lsi != Symbols.end()) {
Value.SectionID = lsi->second.first;
Value.Addend = lsi->second.second + Addend;
} else {
// Search for the symbol in the global symbol table
- SymbolTableMap::const_iterator gsi =
- GlobalSymbolTable.find(TargetName.data());
+ SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
+ if (Symbol != Obj.end_symbols())
+ gsi = GlobalSymbolTable.find(TargetName.data());
if (gsi != GlobalSymbolTable.end()) {
Value.SectionID = gsi->second.first;
Value.Addend = gsi->second.second + Addend;
@@ -641,7 +812,7 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
// and can be changed by another developers. Maybe best way is add
// a new symbol type ST_Section to SymbolRef and use it.
section_iterator si(Obj.end_sections());
- Symbol.getSection(si);
+ Symbol->getSection(si);
if (si == Obj.end_sections())
llvm_unreachable("Symbol section not found, bad object file format!");
DEBUG(dbgs() << "\t\tThis is section symbol\n");
@@ -672,7 +843,56 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
DEBUG(dbgs() << "\t\tSectionID: " << SectionID
<< " Offset: " << Offset
<< "\n");
- if (Arch == Triple::arm &&
+ if (Arch == Triple::aarch64 &&
+ (RelType == ELF::R_AARCH64_CALL26 ||
+ RelType == ELF::R_AARCH64_JUMP26)) {
+ // This is an AArch64 branch relocation, need to use a stub function.
+ DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation.");
+ SectionEntry &Section = Sections[SectionID];
+
+ // Look for an existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ if (i != Stubs.end()) {
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + i->second, RelType, 0);
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+ Section.StubOffset);
+
+ RelocationEntry REmovz_g3(SectionID,
+ StubTargetAddr - Section.Address,
+ ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend);
+ RelocationEntry REmovk_g2(SectionID,
+ StubTargetAddr - Section.Address + 4,
+ ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend);
+ RelocationEntry REmovk_g1(SectionID,
+ StubTargetAddr - Section.Address + 8,
+ ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend);
+ RelocationEntry REmovk_g0(SectionID,
+ StubTargetAddr - Section.Address + 12,
+ ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend);
+
+ if (Value.SymbolName) {
+ addRelocationForSymbol(REmovz_g3, Value.SymbolName);
+ addRelocationForSymbol(REmovk_g2, Value.SymbolName);
+ addRelocationForSymbol(REmovk_g1, Value.SymbolName);
+ addRelocationForSymbol(REmovk_g0, Value.SymbolName);
+ } else {
+ addRelocationForSection(REmovz_g3, Value.SectionID);
+ addRelocationForSection(REmovk_g2, Value.SectionID);
+ addRelocationForSection(REmovk_g1, Value.SectionID);
+ addRelocationForSection(REmovk_g0, Value.SectionID);
+ }
+ resolveRelocation(Section, Offset,
+ (uint64_t)Section.Address + Section.StubOffset,
+ RelType, 0);
+ Section.StubOffset += getMaxStubSize();
+ }
+ } else if (Arch == Triple::arm &&
(RelType == ELF::R_ARM_PC24 ||
RelType == ELF::R_ARM_CALL ||
RelType == ELF::R_ARM_JUMP24)) {
@@ -693,7 +913,7 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
uint8_t *StubTargetAddr = createStubFunction(Section.Address +
Section.StubOffset);
RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
- ELF::R_ARM_ABS32, Value.Addend);
+ ELF::R_ARM_PRIVATE_0, Value.Addend);
if (Value.SymbolName)
addRelocationForSymbol(RE, Value.SymbolName);
else
@@ -839,6 +1059,53 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
else
addRelocationForSection(RE, Value.SectionID);
}
+ } else if (Arch == Triple::systemz &&
+ (RelType == ELF::R_390_PLT32DBL ||
+ RelType == ELF::R_390_GOTENT)) {
+ // Create function stubs for both PLT and GOT references, regardless of
+ // whether the GOT reference is to data or code. The stub contains the
+ // full address of the symbol, as needed by GOT references, and the
+ // executable part only adds an overhead of 8 bytes.
+ //
+ // We could try to conserve space by allocating the code and data
+ // parts of the stub separately. However, as things stand, we allocate
+ // a stub for every relocation, so using a GOT in JIT code should be
+ // no less space efficient than using an explicit constant pool.
+ DEBUG(dbgs() << "\t\tThis is a SystemZ indirect relocation.");
+ SectionEntry &Section = Sections[SectionID];
+
+ // Look for an existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ uintptr_t StubAddress;
+ if (i != Stubs.end()) {
+ StubAddress = uintptr_t(Section.Address) + i->second;
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+
+ uintptr_t BaseAddress = uintptr_t(Section.Address);
+ uintptr_t StubAlignment = getStubAlignment();
+ StubAddress = (BaseAddress + Section.StubOffset +
+ StubAlignment - 1) & -StubAlignment;
+ unsigned StubOffset = StubAddress - BaseAddress;
+
+ Stubs[Value] = StubOffset;
+ createStubFunction((uint8_t *)StubAddress);
+ RelocationEntry RE(SectionID, StubOffset + 8,
+ ELF::R_390_64, Value.Addend - Addend);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ Section.StubOffset = StubOffset + getMaxStubSize();
+ }
+
+ if (RelType == ELF::R_390_GOTENT)
+ resolveRelocation(Section, Offset, StubAddress + 8,
+ ELF::R_390_PC32DBL, Addend);
+ else
+ resolveRelocation(Section, Offset, StubAddress, RelType, Addend);
} else {
RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
if (Value.SymbolName)
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
index 102b1c6..794c7ec 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
@@ -49,6 +49,12 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
uint32_t Type,
int32_t Addend);
+ void resolveAArch64Relocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend);
+
void resolveARMRelocation(const SectionEntry &Section,
uint64_t Offset,
uint32_t Value,
@@ -67,6 +73,11 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
uint32_t Type,
int64_t Addend);
+ void resolveSystemZRelocation(const SectionEntry &Section,
+ uint64_t Offset,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend);
uint64_t findPPC64TOC() const;
void findOPDEntrySection(ObjectImage &Obj,
@@ -85,6 +96,7 @@ public:
StubMap &Stubs);
virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const;
virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
+ virtual StringRef getEHFrameSection();
virtual ~RuntimeDyldELF();
};
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index 51873b1..383ffab 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -49,7 +49,7 @@ public:
/// Address - address in the linker's memory where the section resides.
uint8_t *Address;
- /// Size - section size.
+ /// Size - section size. Doesn't include the stubs.
size_t Size;
/// LoadAddress - the address of the section in the target process's memory.
@@ -67,9 +67,9 @@ public:
uintptr_t ObjAddress;
SectionEntry(StringRef name, uint8_t *address, size_t size,
- uintptr_t stubOffset, uintptr_t objAddress)
+ uintptr_t objAddress)
: Name(name), Address(address), Size(size), LoadAddress((uintptr_t)address),
- StubOffset(stubOffset), ObjAddress(objAddress) {}
+ StubOffset(size), ObjAddress(objAddress) {}
};
/// RelocationEntry - used to represent relocations internally in the dynamic
@@ -166,16 +166,29 @@ protected:
Triple::ArchType Arch;
inline unsigned getMaxStubSize() {
+ if (Arch == Triple::aarch64)
+ return 20; // movz; movk; movk; movk; br
if (Arch == Triple::arm || Arch == Triple::thumb)
return 8; // 32-bit instruction and 32-bit address
else if (Arch == Triple::mipsel || Arch == Triple::mips)
return 16;
else if (Arch == Triple::ppc64)
return 44;
+ else if (Arch == Triple::x86_64)
+ return 8; // GOT
+ else if (Arch == Triple::systemz)
+ return 16;
else
return 0;
}
+ inline unsigned getStubAlignment() {
+ if (Arch == Triple::systemz)
+ return 8;
+ else
+ return 1;
+ }
+
bool HasError;
std::string ErrorStr;
@@ -321,6 +334,8 @@ public:
StringRef getErrorString() { return ErrorStr; }
virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0;
+
+ virtual StringRef getEHFrameSection();
};
} // end namespace llvm
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
index b3467a9..0384b32 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
@@ -21,6 +21,69 @@ using namespace llvm::object;
namespace llvm {
+static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, intptr_t DeltaForEH) {
+ uint32_t Length = *((uint32_t*)P);
+ P += 4;
+ unsigned char *Ret = P + Length;
+ uint32_t Offset = *((uint32_t*)P);
+ if (Offset == 0) // is a CIE
+ return Ret;
+
+ P += 4;
+ intptr_t FDELocation = *((intptr_t*)P);
+ intptr_t NewLocation = FDELocation - DeltaForText;
+ *((intptr_t*)P) = NewLocation;
+ P += sizeof(intptr_t);
+
+ // Skip the FDE address range
+ P += sizeof(intptr_t);
+
+ uint8_t Augmentationsize = *P;
+ P += 1;
+ if (Augmentationsize != 0) {
+ intptr_t LSDA = *((intptr_t*)P);
+ intptr_t NewLSDA = LSDA - DeltaForEH;
+ *((intptr_t*)P) = NewLSDA;
+ }
+
+ return Ret;
+}
+
+static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) {
+ intptr_t ObjDistance = A->ObjAddress - B->ObjAddress;
+ intptr_t MemDistance = A->LoadAddress - B->LoadAddress;
+ return ObjDistance - MemDistance;
+}
+
+StringRef RuntimeDyldMachO::getEHFrameSection() {
+ SectionEntry *Text = NULL;
+ SectionEntry *EHFrame = NULL;
+ SectionEntry *ExceptTab = NULL;
+ for (int i = 0, e = Sections.size(); i != e; ++i) {
+ if (Sections[i].Name == "__eh_frame")
+ EHFrame = &Sections[i];
+ else if (Sections[i].Name == "__text")
+ Text = &Sections[i];
+ else if (Sections[i].Name == "__gcc_except_tab")
+ ExceptTab = &Sections[i];
+ }
+ if (Text == NULL || EHFrame == NULL)
+ return StringRef();
+
+ intptr_t DeltaForText = computeDelta(Text, EHFrame);
+ intptr_t DeltaForEH = 0;
+ if (ExceptTab)
+ DeltaForEH = computeDelta(ExceptTab, EHFrame);
+
+ unsigned char *P = EHFrame->Address;
+ unsigned char *End = P + EHFrame->Size;
+ do {
+ P = processFDE(P, DeltaForText, DeltaForEH);
+ } while(P != End);
+
+ return StringRef((char*)EHFrame->Address, EHFrame->Size);
+}
+
void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE,
uint64_t Value) {
const SectionEntry &Section = Sections[RE.SectionID];
@@ -239,10 +302,9 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID,
if (isExtern) {
// Obtain the symbol name which is referenced in the relocation
- SymbolRef Symbol;
- RelI.getSymbol(Symbol);
+ symbol_iterator Symbol = RelI.getSymbol();
StringRef TargetName;
- Symbol.getName(TargetName);
+ Symbol->getName(TargetName);
// First search for the symbol in the local symbol table
SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
if (lsi != Symbols.end()) {
@@ -267,7 +329,30 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID,
Value.Addend = Addend - Addr;
}
- if (Arch == Triple::arm && (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) {
+ if (Arch == Triple::x86_64 && RelType == macho::RIT_X86_64_GOT) {
+ assert(IsPCRel);
+ assert(Size == 2);
+ StubMap::const_iterator i = Stubs.find(Value);
+ uint8_t *Addr;
+ if (i != Stubs.end()) {
+ Addr = Section.Address + i->second;
+ } else {
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *GOTEntry = Section.Address + Section.StubOffset;
+ RelocationEntry RE(SectionID, Section.StubOffset,
+ macho::RIT_X86_64_Unsigned, Value.Addend - 4, false,
+ 3);
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
+ Section.StubOffset += 8;
+ Addr = GOTEntry;
+ }
+ resolveRelocation(Section, Offset, (uint64_t)Addr,
+ macho::RIT_X86_64_Unsigned, 4, true, 2);
+ } else if (Arch == Triple::arm &&
+ (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) {
// This is an ARM branch relocation, need to use a stub function.
// Look up for existing stub.
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
index 8da6e35..df8d3bb 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
@@ -65,6 +65,7 @@ public:
const SymbolTableMap &Symbols,
StubMap &Stubs);
virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const;
+ virtual StringRef getEHFrameSection();
};
} // end namespace llvm