summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ExecutionEngine
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
commitc80099aa042d0c3aa27d407283a39e6a01e9b027 (patch)
treeb8b026ebefa687b2496eb6d31c3d25bdd3b31387 /llvm/lib/ExecutionEngine
parent8543d4f8a108ba318a55c293ac85d208ec6dce7b (diff)
downloadbcm5719-llvm-c80099aa042d0c3aa27d407283a39e6a01e9b027.tar.gz
bcm5719-llvm-c80099aa042d0c3aa27d407283a39e6a01e9b027.zip
Split out relocation resolution into target-specific bits.
llvm-svn: 128173
Diffstat (limited to 'llvm/lib/ExecutionEngine')
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp74
1 files changed, 71 insertions, 3 deletions
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 5c52e5be74d..38107f6f694 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/llvm/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:
OpenPOWER on IntegriCloud