From 89ebba5af6ffd81b419f10ec43d44fca7fecf1e4 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 17 May 2013 12:36:29 +0000 Subject: [PATCH] [PowerPC] Fix processing of ha16/lo16 fixups 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. llvm-svn: 182091 --- .../PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 2 -- .../MCTargetDesc/PPCELFObjectWriter.cpp | 6 +---- test/MC/PowerPC/ppc64-fixup-apply.s | 26 +++++++++++++++++++ test/MC/PowerPC/ppc64-fixups.s | 20 ++++++++++++++ 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index b1ac4a6f277..9ec5f0e0b54 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -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: diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 2508cc2f37a..5193dca2882 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -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; diff --git a/test/MC/PowerPC/ppc64-fixup-apply.s b/test/MC/PowerPC/ppc64-fixup-apply.s index a64052bc46b..fb75703b1c4 100644 --- a/test/MC/PowerPC/ppc64-fixup-apply.s +++ b/test/MC/PowerPC/ppc64-fixup-apply.s @@ -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 @@ -17,6 +24,25 @@ .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 diff --git a/test/MC/PowerPC/ppc64-fixups.s b/test/MC/PowerPC/ppc64-fixups.s index 06b2ffd303c..25c1736f101 100644 --- a/test/MC/PowerPC/ppc64-fixups.s +++ b/test/MC/PowerPC/ppc64-fixups.s @@ -27,6 +27,26 @@ # 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