[llvm-commits] [llvm] r128173 - /llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp

Jim Grosbach grosbach at apple.com
Wed Mar 23 15:06:06 PDT 2011


Author: grosbach
Date: Wed Mar 23 17:06:06 2011
New Revision: 128173

URL: http://llvm.org/viewvc/llvm-project?rev=128173&view=rev
Log:
Split out relocation resolution into target-specific bits.

Modified:
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=128173&r1=128172&r2=128173&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Wed Mar 23 17:06:06 2011
@@ -31,6 +31,9 @@
 
 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 @@
   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 @@
     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 @@
   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 @@
   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 @@
   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:





More information about the llvm-commits mailing list