[llvm] e8054f0 - [PPC32] Emit R_PPC_PLTREL24 for calls to dso_local ifunc

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 20 11:32:09 PST 2019


Author: Fangrui Song
Date: 2019-12-20T11:32:02-08:00
New Revision: e8054f0933701a885a42e4a240f050402d7930e0

URL: https://github.com/llvm/llvm-project/commit/e8054f0933701a885a42e4a240f050402d7930e0
DIFF: https://github.com/llvm/llvm-project/commit/e8054f0933701a885a42e4a240f050402d7930e0.diff

LOG: [PPC32] Emit R_PPC_PLTREL24 for calls to dso_local ifunc

  static void *ifunc(void) __attribute__((ifunc("resolver")));
  void foo() { ifunc(); }

The relocation produced by the ifunc() call:

1. gcc -msecure-plt -fPIC => R_PPC_PLTREL24 r_addend=0x8000
2. gcc -msecure-plt -PIE => R_PPC_PLTREL24 r_addend=0x8000
3. clang -msecure-plt -fPIC => R_PPC_PLTREL24 r_addend=0x8000
4. clang -msecure-plt -fPIE => R_PPC_REL24

4 is incorrect. The R_PPC_REL24 needs a call stub due to ifunc. If this
relocation is mixed with other R_PPC_PLTREL24(r_addend=0x8000) in a
function, both GNU ld and lld (after D71621 fix) may produce a wrong
result.

This patch fixes 4 to use R_PPC_PLTREL24, which matches GCC.
Both GNU ld and lld (after D71621) will be happy.

Reviewed By: sfertile

Differential Revision: https://reviews.llvm.org/D71649

Added: 
    llvm/test/CodeGen/PowerPC/ifunc.ll

Modified: 
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 3062dbb655f8..ad7c9ea4e6ca 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -5102,9 +5102,10 @@ static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG,
   auto isLocalCallee = [&]() {
     const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
     const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
+    const GlobalValue *GV = G ? G->getGlobal() : nullptr;
 
-    return DAG.getTarget().shouldAssumeDSOLocal(*Mod,
-                                                G ? G->getGlobal() : nullptr);
+    return DAG.getTarget().shouldAssumeDSOLocal(*Mod, GV) &&
+           !dyn_cast_or_null<GlobalIFunc>(GV);
   };
 
   // The PLT is only used in 32-bit ELF PIC mode.  Attempting to use the PLT in

diff  --git a/llvm/test/CodeGen/PowerPC/ifunc.ll b/llvm/test/CodeGen/PowerPC/ifunc.ll
new file mode 100644
index 000000000000..a964a2bac1c5
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/ifunc.ll
@@ -0,0 +1,25 @@
+; RUN: llc %s -o - -mtriple=powerpc | FileCheck --check-prefix=REL %s
+; RUN: llc %s -o - -mtriple=powerpc -relocation-model=pic | FileCheck --check-prefix=PLTREL %s
+; RUN: llc %s -o - -mtriple=powerpc64 | FileCheck --check-prefix=REL %s
+; RUN: llc %s -o - -mtriple=powerpc64 -relocation-model=pic | FileCheck --check-prefix=REL %s
+
+ at ifunc1 = dso_local ifunc void(), i8*()* @resolver
+ at ifunc2 = ifunc void(), i8*()* @resolver
+
+define i8* @resolver() { ret i8* null }
+
+define void @foo() #0 {
+  ; REL: bl ifunc1{{$}}
+  ; REL: bl ifunc2{{$}}
+  ; PLTREL: bl ifunc1 at PLT+32768
+  ; PLTREL: bl ifunc2 at PLT+32768
+  call void @ifunc1()
+  call void @ifunc2()
+  ret void
+}
+
+;; Use Secure PLT ABI for PPC32.
+attributes #0 = { "target-features"="+secure-plt" }
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"PIC Level", i32 2}


        


More information about the llvm-commits mailing list