Add RelocVisitor support for MachO
authorKeno Fischer <kfischer@college.harvard.edu>
Sat, 30 May 2015 19:44:53 +0000 (19:44 +0000)
committerKeno Fischer <kfischer@college.harvard.edu>
Sat, 30 May 2015 19:44:53 +0000 (19:44 +0000)
This commit adds partial support for MachO relocations to RelocVisitor.
A simple test case is added to show that relocations are indeed being
applied and that using llvm-dwarfdump on MachO files no longer errors.
Correctness is not yet tested, due to an unrelated bug in DebugInfo,
which will be fixed with appropriate testcase in a followup commit.

Differential Revision: http://reviews.llvm.org/D8148

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238663 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/MachO.h
include/llvm/Object/RelocVisitor.h
lib/Object/MachOObjectFile.cpp
test/DebugInfo/Inputs/test-multiple-macho.o [new file with mode: 0644]
test/DebugInfo/Inputs/test-simple-macho.o [new file with mode: 0644]
test/DebugInfo/debuglineinfo-macho.test [new file with mode: 0644]
tools/llvm-rtdyld/llvm-rtdyld.cpp

index 0a9b62c9055f73e05b22142e9c5ee79cd2f94152..0fe327d6adcad2f6cc52131cc3013ff2acbd353a 100644 (file)
@@ -246,6 +246,7 @@ public:
                            SmallVectorImpl<char> &Result) const override;
   std::error_code getRelocationHidden(DataRefImpl Rel,
                                       bool &Result) const override;
+  uint8_t getRelocationLength(DataRefImpl Rel) const;
 
   // MachO specific.
   std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
index 91eafd55ad766a49099e28ebfbdff6feca183fe4..02ffda5642d55e17e2c8ca0e3d44b3a785a5aa2e 100644 (file)
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachO.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ELF.h"
+#include "llvm/Support/MachO.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace llvm {
@@ -52,6 +54,8 @@ public:
       return visitELF(RelocType, R, Value);
     if (isa<COFFObjectFile>(ObjToVisit))
       return visitCOFF(RelocType, R, Value);
+    if (isa<MachOObjectFile>(ObjToVisit))
+      return visitMachO(RelocType, R, Value);
 
     HasError = true;
     return RelocToApply();
@@ -221,6 +225,20 @@ private:
     return RelocToApply();
   }
 
+  RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
+    switch (ObjToVisit.getArch()) {
+    default: break;
+    case Triple::x86_64:
+      switch (RelocType) {
+        default: break;
+        case MachO::X86_64_RELOC_UNSIGNED:
+          return visitMACHO_X86_64_UNSIGNED(R, Value);
+      }
+    }
+    HasError = true;
+    return RelocToApply();
+  }
+
   int64_t getELFAddend32LE(RelocationRef R) {
     const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile());
     DataRefImpl DRI = R.getRawDataRefImpl();
@@ -252,6 +270,12 @@ private:
     Obj->getRelocationAddend(DRI, Addend);
     return Addend;
   }
+
+  uint8_t getLengthMachO64(RelocationRef R) {
+    const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObjectFile());
+    return Obj->getRelocationLength(R.getRawDataRefImpl());
+  }
+
   /// Operations
 
   /// 386-ELF
@@ -413,6 +437,13 @@ private:
   RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
     return RelocToApply(Value, /*Width=*/8);
   }
+
+  // X86_64 MachO
+  RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
+    uint8_t Length = getLengthMachO64(R);
+    Length = 1<<Length;
+    return RelocToApply(Value, Length);
+  }
 };
 
 }
index 79f8100649881b2e9458616dd9011b3baf6e1a7a..439dceb323b7cce204e830a22626e00982675b11 100644 (file)
@@ -1004,6 +1004,11 @@ std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
   return object_error::success;
 }
 
+uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
+  MachO::any_relocation_info RE = getRelocation(Rel);
+  return getAnyRelocationLength(RE);
+}
+
 //
 // guessLibraryShortName() is passed a name of a dynamic library and returns a
 // guess on what the short name is.  Then name is returned as a substring of the
diff --git a/test/DebugInfo/Inputs/test-multiple-macho.o b/test/DebugInfo/Inputs/test-multiple-macho.o
new file mode 100644 (file)
index 0000000..428a1af
Binary files /dev/null and b/test/DebugInfo/Inputs/test-multiple-macho.o differ
diff --git a/test/DebugInfo/Inputs/test-simple-macho.o b/test/DebugInfo/Inputs/test-simple-macho.o
new file mode 100644 (file)
index 0000000..8ae4154
Binary files /dev/null and b/test/DebugInfo/Inputs/test-simple-macho.o differ
diff --git a/test/DebugInfo/debuglineinfo-macho.test b/test/DebugInfo/debuglineinfo-macho.test
new file mode 100644 (file)
index 0000000..a8dfe3c
--- /dev/null
@@ -0,0 +1,7 @@
+# Check that relocations get applied
+RUN: llvm-dwarfdump %p/Inputs/test-simple-macho.o | FileCheck %s
+RUN: llvm-dwarfdump %p/Inputs/test-multiple-macho.o | FileCheck %s
+RUN: llvm-rtdyld -printline %p/Inputs/test-multiple-macho.o | FileCheck %s
+RUN: llvm-rtdyld -printobjline %p/Inputs/test-multiple-macho.o | FileCheck %s
+
+CHECK-NOT: error: failed to compute relocation: X86_64_RELOC_UNSIGNED
index e87f1e2d4c19813f638595ebe3e7dc0b614a7e2b..defe98ae0f4322fbe37c047e717e2515094f5f7a 100644 (file)
@@ -47,6 +47,7 @@ InputFileList(cl::Positional, cl::ZeroOrMore,
 
 enum ActionType {
   AC_Execute,
+  AC_PrintObjectLineInfo,
   AC_PrintLineInfo,
   AC_PrintDebugLineInfo,
   AC_Verify
@@ -61,6 +62,8 @@ Action(cl::desc("Action to perform:"),
                              "Load, link, and print line information for each function."),
                   clEnumValN(AC_PrintDebugLineInfo, "printdebugline",
                              "Load, link, and print line information for each function using the debug object"),
+                  clEnumValN(AC_PrintObjectLineInfo, "printobjline",
+                             "Like -printlineinfo but does not load the object first"),
                   clEnumValN(AC_Verify, "verify",
                              "Load, link and verify the resulting memory image."),
                   clEnumValEnd));
@@ -622,9 +625,11 @@ int main(int argc, char **argv) {
   case AC_Execute:
     return executeInput();
   case AC_PrintDebugLineInfo:
-    return printLineInfoForInput(true,true);
+    return printLineInfoForInput(/* LoadObjects */ true,/* UseDebugObj */ true);
   case AC_PrintLineInfo:
-    return printLineInfoForInput(true,false);
+    return printLineInfoForInput(/* LoadObjects */ true,/* UseDebugObj */false);
+  case AC_PrintObjectLineInfo:
+    return printLineInfoForInput(/* LoadObjects */false,/* UseDebugObj */false);
   case AC_Verify:
     return linkAndVerify();
   }