From 27b984ac855a0a880e4b51754d22f919b33cc900 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 10 Mar 2010 00:58:25 +0000 Subject: [PATCH] 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 --- llvm/lib/MC/MCAssembler.cpp | 19 +++++++----- llvm/test/MC/MachO/reloc-diff.s | 55 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 llvm/test/MC/MachO/reloc-diff.s diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index cf02cc15c5a8..b44cd1e69878 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -446,24 +446,27 @@ public: // See . 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/llvm/test/MC/MachO/reloc-diff.s b/llvm/test/MC/MachO/reloc-diff.s new file mode 100644 index 000000000000..601edba47b42 --- /dev/null +++ b/llvm/test/MC/MachO/reloc-diff.s @@ -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