MC/Mach-O: Use the SECTDIFF relocation type for (A - B + constant) where A is external.
authorDaniel Dunbar <daniel@zuster.org>
Wed, 10 Mar 2010 00:58:25 +0000 (00:58 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 10 Mar 2010 00:58:25 +0000 (00:58 +0000)
 - I'm not sure why, but this is what 'as' does.

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

lib/MC/MCAssembler.cpp
test/MC/MachO/reloc-diff.s [new file with mode: 0644]

index cf02cc15c5a8b5096fb4a692c92361edc122f050..b44cd1e6987855900532ec66ec59de69d1ae9509 100644 (file)
@@ -446,24 +446,27 @@ public:
 
     // See <reloc.h>.
     const MCSymbol *A = Target.getSymA();
-    MCSymbolData *SD = SymbolMap.lookup(A);
+    MCSymbolData *A_SD = SymbolMap.lookup(A);
 
-    if (!SD->getFragment())
+    if (!A_SD->getFragment())
       llvm_report_error("symbol '" + A->getName() +
                         "' can not be undefined in a subtraction expression");
 
-    uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset();
+    uint32_t Value = A_SD->getFragment()->getAddress() + A_SD->getOffset();
     uint32_t Value2 = 0;
 
     if (const MCSymbol *B = Target.getSymB()) {
-      MCSymbolData *SD = SymbolMap.lookup(B);
+      MCSymbolData *B_SD = SymbolMap.lookup(B);
 
-      if (!SD->getFragment())
+      if (!B_SD->getFragment())
         llvm_report_error("symbol '" + B->getName() +
                           "' can not be undefined in a subtraction expression");
 
-      Type = RIT_LocalDifference;
-      Value2 = SD->getFragment()->getAddress() + SD->getOffset();
+      // FIXME: This change of type based on the external bit doesn't make much
+      // sense, it seems to be redundant with the other information in the
+      // relocation entry.
+      Type = A_SD->isExternal() ? RIT_Difference : RIT_LocalDifference;
+      Value2 = B_SD->getFragment()->getAddress() + B_SD->getOffset();
     }
 
     // The value which goes in the fixup is current value of the expression.
@@ -488,7 +491,7 @@ public:
     MRE.Word1 = Value;
     Relocs.push_back(MRE);
 
-    if (Type == RIT_LocalDifference) {
+    if (Type == RIT_Difference || Type == RIT_LocalDifference) {
       MachRelocationEntry MRE;
       MRE.Word0 = ((0         <<  0) |
                    (RIT_Pair  << 24) |
diff --git a/test/MC/MachO/reloc-diff.s b/test/MC/MachO/reloc-diff.s
new file mode 100644 (file)
index 0000000..601edba
--- /dev/null
@@ -0,0 +1,55 @@
+// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
+
+// CHECK: # Relocation 0
+// CHECK: (('word-0', 0xa2000014),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 1
+// CHECK: (('word-0', 0xa1000000),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 2
+// CHECK: (('word-0', 0xa4000010),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 3
+// CHECK: (('word-0', 0xa1000000),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 4
+// CHECK: (('word-0', 0xa400000c),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 5
+// CHECK: (('word-0', 0xa1000000),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 6
+// CHECK: (('word-0', 0xa4000008),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 7
+// CHECK: (('word-0', 0xa1000000),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 8
+// CHECK: (('word-0', 0xa4000004),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 9
+// CHECK: (('word-0', 0xa1000000),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 10
+// CHECK: (('word-0', 0xa2000000),
+// CHECK:  ('word-1', 0x0)),
+// CHECK: # Relocation 11
+// CHECK: (('word-0', 0xa1000000),
+// CHECK:  ('word-1', 0x0)),
+// CHECK-NEXT: ])
+
+_local_def:
+        .globl _external_def
+_external_def:
+Ltemp:
+        ret
+        
+        .data
+        .long _external_def - _local_def
+        .long Ltemp - _local_def
+
+        .long _local_def - _external_def
+        .long Ltemp - _external_def
+
+        .long _local_def - Ltemp
+        .long _external_def - Ltemp