[PowerPC] Fix @got references to local symbols
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 1 Jul 2013 18:19:56 +0000 (18:19 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 1 Jul 2013 18:19:56 +0000 (18:19 +0000)
A @got reference must always result in a relocation, so that
the linker has a chance to set up the GOT entry, even if the
symbol happens to be local.

Add a PPCELFObjectWriter::ExplicitRelSym routine that enforces
a relocation to be emitted for GOT references.

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

lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
test/MC/PowerPC/ppc64-fixup-explicit.s [new file with mode: 0644]

index c2bf25166991b908957829e8022e591ba3ab95da..c26b5458d385b57d8c50a4e3735368b6004f377a 100644 (file)
@@ -30,6 +30,11 @@ namespace {
     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
                                   bool IsPCRel, bool IsRelocWithSymbol,
                                   int64_t Addend) const;
+    virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
+                                           const MCValue &Target,
+                                           const MCFragment &F,
+                                           const MCFixup &Fixup,
+                                           bool IsPCRel) const;
     virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
                                                     const MCFixup &Fixup,
                                                     bool IsPCRel) const;
@@ -328,6 +333,35 @@ unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
   return getRelocTypeInner(Target, Fixup, IsPCRel);
 }
 
+const MCSymbol *PPCELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
+                                                   const MCValue &Target,
+                                                   const MCFragment &F,
+                                                   const MCFixup &Fixup,
+                                                   bool IsPCRel) const {
+  assert(Target.getSymA() && "SymA cannot be 0");
+  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
+    MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
+
+  bool EmitThisSym;
+  switch (Modifier) {
+  // GOT references always need a relocation, even if the
+  // target symbol is local.
+  case MCSymbolRefExpr::VK_GOT:
+  case MCSymbolRefExpr::VK_PPC_GOT_LO:
+  case MCSymbolRefExpr::VK_PPC_GOT_HI:
+  case MCSymbolRefExpr::VK_PPC_GOT_HA:
+    EmitThisSym = true;
+    break;
+  default:
+    EmitThisSym = false;
+    break;
+  } 
+
+  if (EmitThisSym)
+    return &Target.getSymA()->getSymbol().AliasedSymbol();
+  return NULL;
+}
+
 const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target,
                                                             const MCFixup &Fixup,
                                                             bool IsPCRel) const {
diff --git a/test/MC/PowerPC/ppc64-fixup-explicit.s b/test/MC/PowerPC/ppc64-fixup-explicit.s
new file mode 100644 (file)
index 0000000..217e057
--- /dev/null
@@ -0,0 +1,46 @@
+
+# RUN: llvm-mc -triple powerpc64-unknown-unknown --show-encoding %s | FileCheck %s
+
+# RUN: llvm-mc -triple powerpc64-unknown-unknown -filetype=obj %s | \
+# RUN: llvm-readobj -r | FileCheck %s -check-prefix=REL
+
+# GOT references must result in explicit relocations
+# even if the target symbol is local.
+
+target:
+
+# CHECK: addi 4, 3, target@GOT           # encoding: [0x38,0x83,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@GOT, kind: fixup_ppc_half16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_GOT16 target 0x0
+         addi 4, 3, target@got  
+
+# CHECK: ld 1, target@GOT(2)             # encoding: [0xe8,0x22,A,0bAAAAAA00]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@GOT, kind: fixup_ppc_half16ds
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_GOT16_DS target 0x0
+         ld 1, target@got(2)
+
+# CHECK: addis 3, 2, target@got@ha       # encoding: [0x3c,0x62,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@got@ha, kind: fixup_ppc_half16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_GOT16_HA target 0x0
+         addis 3, 2, target@got@ha
+
+# CHECK: addi 4, 3, target@got@l         # encoding: [0x38,0x83,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@got@l, kind: fixup_ppc_half16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_GOT16_LO target 0x0
+         addi 4, 3, target@got@l
+
+# CHECK: addis 3, 2, target@got@h        # encoding: [0x3c,0x62,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@got@h, kind: fixup_ppc_half16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_GOT16_HI target 0x0
+         addis 3, 2, target@got@h
+
+# CHECK: lwz 1, target@got@l(3)          # encoding: [0x80,0x23,A,A]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@got@l, kind: fixup_ppc_half16
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_GOT16_LO target 0x0
+         lwz 1, target@got@l(3)
+
+# CHECK: ld 1, target@got@l(3)           # encoding: [0xe8,0x23,A,0bAAAAAA00]
+# CHECK-NEXT:                            #   fixup A - offset: 2, value: target@got@l, kind: fixup_ppc_half16ds
+# CHECK-REL:                             0x{{[0-9A-F]*[26AE]}} R_PPC64_GOT16_LO_DS target 0x0
+         ld 1, target@got@l(3)
+