[PowerPC] Fix processing of ha16/lo16 fixups
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Fri, 17 May 2013 12:36:29 +0000 (12:36 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Fri, 17 May 2013 12:36:29 +0000 (12:36 +0000)
The current PowerPC MC back end distinguishes between fixup_ppc_ha16
and fixup_ppc_lo16, which are determined by the instruction the fixup
applies to, and uses this distinction to decide whether a fixup ought
to resolve to the high or the low part of a symbol address.

This isn't quite correct, however.  It is valid -if unusual- assembler
to use, e.g.
  li 1, symbol@ha
or
  lis 1, symbol@l
Whether the high or the low part of the address is used depends solely
on the @ suffix, not on the instruction.

In addition, both
  li 1, symbol
and
  lis 1, symbol
are valid, assuming the symbol address fits into 16 bits; again, both
will then refer to the actual symbol value (so li will load the value
itself, while lis will load the value shifted by 16).

To fix this, two places need to be adapted.  If the fixup cannot be
resolved at assembler time, a relocation needs to be emitted via
PPCELFObjectWriter::getRelocType.  This routine already looks at
the VK_ type to determine the relocation.  The only problem is that
will reject any _LO modifier in a ha16 fixup and vice versa.  This
is simply incorrect; any of those modifiers ought to be accepted
for either fixup type.

If the fixup *can* be resolved at assembler time, adjustFixupValue
currently selects the high bits of the symbol value if the fixup
type is ha16.  Again, this is incorrect; see the above example
  lis 1, symbol

Now, in theory we'd have to respect a VK_ modifier here.  However,
in fact common code never even attempts to resolve symbol references
using any nontrivial VK_ modifier at assembler time; it will always
fall back to emitting a reloc and letting the linker handle it.

If this ever changes, presumably there'd have to be a target callback
to resolve VK_ modifiers.  We'd then have to handle @ha etc. there.

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

lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
test/MC/PowerPC/ppc64-fixup-apply.s
test/MC/PowerPC/ppc64-fixups.s

index b1ac4a6f277ebe256fb96adede6af95bb83bce32..9ec5f0e0b54c91ca13f37b698ed1a32867c5f215 100644 (file)
@@ -39,10 +39,8 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
     return Value & 0x3fffffc;
 #if 0
   case PPC::fixup_ppc_hi16:
-    return (Value >> 16) & 0xffff;
 #endif
   case PPC::fixup_ppc_ha16:
-    return ((Value >> 16) + ((Value & 0x8000) ? 1 : 0)) & 0xffff;
   case PPC::fixup_ppc_lo16:
     return Value & 0xffff;
   case PPC::fixup_ppc_lo16_ds:
index 2508cc2f37a5ec354a2c72667e477f831df54441..5193dca2882aef8ff66f0496e545f64e07da74bb 100644 (file)
@@ -82,6 +82,7 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
       Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
       break;
     case PPC::fixup_ppc_ha16:
+    case PPC::fixup_ppc_lo16:
       switch (Modifier) {
       default: llvm_unreachable("Unsupported Modifier");
       case MCSymbolRefExpr::VK_PPC_TPREL16_HA:
@@ -106,11 +107,6 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA:
         Type = ELF::R_PPC64_GOT_TLSLD16_HA;
         break;
-      }
-      break;
-    case PPC::fixup_ppc_lo16:
-      switch (Modifier) {
-      default: llvm_unreachable("Unsupported Modifier");
       case MCSymbolRefExpr::VK_PPC_TPREL16_LO:
         Type = ELF::R_PPC_TPREL16_LO;
         break;
index a64052bc46bdceaab949a260b05565127f966d8f..fb75703b1c4d88a126a7dc8ace8eb459d8b1451b 100644 (file)
@@ -5,6 +5,13 @@
 # This checks that fixups that can be resolved within the same
 # object file are applied correctly.
 
+.text
+
+addi 1, 1, target
+addis 1, 1, target
+
+.set target, 0x1234
+
 .data
 
 .quad v1
 .set v3, 0xbeef
 .set v4, 0x42
 
+# CHECK:       Section {
+# CHECK:         Name: .text
+# CHECK-NEXT:    Type: SHT_PROGBITS
+# CHECK-NEXT:    Flags [
+# CHECK-NEXT:      SHF_ALLOC
+# CHECK-NEXT:      SHF_EXECINSTR
+# CHECK-NEXT:    ]
+# CHECK-NEXT:    Address: 0x0
+# CHECK-NEXT:    Offset:
+# CHECK-NEXT:    Size: 8
+# CHECK-NEXT:    Link: 0
+# CHECK-NEXT:    Info: 0
+# CHECK-NEXT:    AddressAlignment: 4
+# CHECK-NEXT:    EntrySize: 0
+# CHECK-NEXT:    SectionData (
+# CHECK-NEXT:      0000: 38211234 3C211234
+# CHECK-NEXT:    )
+# CHECK-NEXT:  }
+
 # CHECK:        Section {
 # CHECK:          Name: .data
 # CHECK-NEXT:     Type: SHT_PROGBITS
index 06b2ffd303c82c425d34047a3bf579d891f7dc07..25c1736f10170c0074efab906464f4da463421b5 100644 (file)
 # CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_LO target 0x0
          addi 4, 3, target@l
 
+# CHECK: li 3, target@ha                 # encoding: [0x38,0x60,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@ha, kind: fixup_ppc_lo16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_HA target 0x0
+         li 3, target@ha
+
+# CHECK: lis 3, target@l                 # encoding: [0x3c,0x60,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@l, kind: fixup_ppc_ha16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_LO target 0x0
+         lis 3, target@l
+
+# CHECK: li 3, target                    # encoding: [0x38,0x60,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target, kind: fixup_ppc_lo16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16 target 0x0
+         li 3, target
+
+# CHECK: lis 3, target                   # encoding: [0x3c,0x60,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target, kind: fixup_ppc_ha16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16 target 0x0
+         lis 3, target
+
 # CHECK: lwz 1, target@l(3)              # encoding: [0x80,0x23,A,A]
 # CHECK-NEXT:                            #   fixup A - offset: 2, value: target@l, kind: fixup_ppc_lo16
 # CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_ADDR16_LO target 0x0