MC/Mach-O: Use the SECTDIFF relocation type for (A - B + constant) where A is external.

- I'm not sure why, but this is what 'as' does.

llvm-svn: 98115
This commit is contained in:
Daniel Dunbar 2010-03-10 00:58:25 +00:00
parent 1dca62055a
commit 27b984ac85
2 changed files with 66 additions and 8 deletions

View File

@ -446,24 +446,27 @@ public:
// See <reloc.h>. // See <reloc.h>.
const MCSymbol *A = Target.getSymA(); 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() + llvm_report_error("symbol '" + A->getName() +
"' can not be undefined in a subtraction expression"); "' 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; uint32_t Value2 = 0;
if (const MCSymbol *B = Target.getSymB()) { 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() + llvm_report_error("symbol '" + B->getName() +
"' can not be undefined in a subtraction expression"); "' can not be undefined in a subtraction expression");
Type = RIT_LocalDifference; // FIXME: This change of type based on the external bit doesn't make much
Value2 = SD->getFragment()->getAddress() + SD->getOffset(); // 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. // The value which goes in the fixup is current value of the expression.
@ -488,7 +491,7 @@ public:
MRE.Word1 = Value; MRE.Word1 = Value;
Relocs.push_back(MRE); Relocs.push_back(MRE);
if (Type == RIT_LocalDifference) { if (Type == RIT_Difference || Type == RIT_LocalDifference) {
MachRelocationEntry MRE; MachRelocationEntry MRE;
MRE.Word0 = ((0 << 0) | MRE.Word0 = ((0 << 0) |
(RIT_Pair << 24) | (RIT_Pair << 24) |

View File

@ -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