summaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2011-03-23 22:06:06 +0000
committerJim Grosbach <grosbach@apple.com>2011-03-23 22:06:06 +0000
commita8287e322f94ddd66fcb9ae26c4b37e02bd1f796 (patch)
treec22ab19735477e71cdd96484708412a470bb0005 /lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
parent741ad15e26d1717433f326743800f30c63c6a9c1 (diff)
downloadllvm-a8287e322f94ddd66fcb9ae26c4b37e02bd1f796.tar.gz
llvm-a8287e322f94ddd66fcb9ae26c4b37e02bd1f796.tar.bz2
llvm-a8287e322f94ddd66fcb9ae26c4b37e02bd1f796.tar.xz
Split out relocation resolution into target-specific bits.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128173 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp')
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp74
1 files changed, 71 insertions, 3 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 5c52e5be74..38107f6f69 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -31,6 +31,9 @@ using namespace llvm::object;
namespace llvm {
class RuntimeDyldImpl {
+ unsigned CPUType;
+ unsigned CPUSubtype;
+
// Master symbol table. As modules are loaded and external symbols are
// resolved, their addresses are stored here.
StringMap<void*> SymbolTable;
@@ -52,6 +55,10 @@ class RuntimeDyldImpl {
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,
+ unsigned Type, unsigned Size);
+ bool resolveARMRelocation(intptr_t Address, intptr_t Value, bool isPCRel,
+ unsigned Type, unsigned Size);
bool loadSegment32(const MachOObject *Obj,
const MachOObject::LoadCommandInfo *SegmentLCI,
@@ -128,6 +135,20 @@ resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE,
Value = (intptr_t)SectionBases[SymbolNum - 1];
}
+ unsigned Size = 1 << Log2Size;
+ switch (CPUType) {
+ default: assert(0 && "Unsupported CPU type!");
+ case mach::CTM_x86_64:
+ return resolveX86_64Relocation(Address, Value, isPCRel, Type, Size);
+ case mach::CTM_ARM:
+ return resolveARMRelocation(Address, Value, isPCRel, Type, Size);
+ }
+ llvm_unreachable("");
+}
+
+bool RuntimeDyldImpl::resolveX86_64Relocation(intptr_t Address, intptr_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)
@@ -142,9 +163,8 @@ resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE,
case macho::RIT_X86_64_Branch: {
// Mask in the target value a byte at a time (we don't have an alignment
// guarantee for the target address, so this is safest).
- unsigned Len = 1 << Log2Size;
uint8_t *p = (uint8_t*)Address;
- for (unsigned i = 0; i < Len; ++i) {
+ for (unsigned i = 0; i < Size; ++i) {
*p++ = (uint8_t)Value;
Value >>= 8;
}
@@ -163,6 +183,46 @@ resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE,
return false;
}
+bool RuntimeDyldImpl::resolveARMRelocation(intptr_t Address, intptr_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) {
+ Value -= Address;
+ // ARM PCRel relocations have an effective-PC offset of two instructions
+ // (four bytes in Thumb mode, 8 bytes in ARM mode).
+ // FIXME: For now, assume ARM mode.
+ Value -= 8;
+ }
+
+ switch(Type) {
+ default:
+ 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
+ // guarantee for the target address, so this is safest).
+ uint8_t *p = (uint8_t*)Address;
+ for (unsigned i = 0; i < Size; ++i) {
+ *p++ = (uint8_t)Value;
+ Value >>= 8;
+ }
+ return false;
+ }
+ case macho::RIT_Pair:
+ case macho::RIT_Difference:
+ case macho::RIT_ARM_LocalDifference:
+ case macho::RIT_ARM_PreboundLazyPointer:
+ case macho::RIT_ARM_Branch24Bit:
+ case macho::RIT_ARM_ThumbBranch22Bit:
+ case macho::RIT_ARM_ThumbBranch32Bit:
+ case macho::RIT_ARM_Half:
+ case macho::RIT_ARM_HalfDifference:
+ return Error("Relocation type not implemented yet!");
+ }
+ return false;
+}
+
bool RuntimeDyldImpl::
loadSegment32(const MachOObject *Obj,
const MachOObject::LoadCommandInfo *SegmentLCI,
@@ -352,10 +412,18 @@ bool RuntimeDyldImpl::loadObject(MemoryBuffer *InputBuffer) {
if (!Obj)
return Error("unable to load object: '" + ErrorStr + "'");
+ // Get the CPU type information from the header.
+ const macho::Header &Header = Obj->getHeader();
+
+ // FIXME: Error checking that the loaded object is compatible with
+ // the system we're running on.
+ CPUType = Header.CPUType;
+ CPUSubtype = Header.CPUSubtype;
+
// Validate that the load commands match what we expect.
const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0,
*DysymtabLCI = 0;
- for (unsigned i = 0; i != Obj->getHeader().NumLoadCommands; ++i) {
+ for (unsigned i = 0; i != Header.NumLoadCommands; ++i) {
const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i);
switch (LCI.Command.Type) {
case macho::LCT_Segment: