|
| 1 | +From 3bc16e0b58704b8c3bd596b23d907516c7cc2493 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Clint Bland <bland.cr@gmail.com> |
| 3 | +Date: Thu, 14 Mar 2019 02:19:16 +0000 |
| 4 | +Subject: [PATCH] PPC: Call libm helpers via private GOT instead of the PLT |
| 5 | + |
| 6 | +A bl sym@plt call emitted by the VM assembler produces an |
| 7 | +R_PPC_PLTREL24 relocation with addend 0, which forces the linker to |
| 8 | +use BSS-PLT for the entire link. GCC 12 and newer emit inline-PLT |
| 9 | +relocations (R_PPC_PLTSEQ, R_PPC_PLTCALL, R_PPC_PLT16_*) that have no |
| 10 | +BSS-PLT equivalent, so linking libluajit.so fails outright: |
| 11 | + |
| 12 | + ld: bss-plt forced due to lj_vm.o |
| 13 | + ld: crtstuff.c:(.text+0x46): R_PPC_PLT16_HA relocation unsupported |
| 14 | + for bss-plt |
| 15 | + |
| 16 | +Route these calls through a private GOT stored in GG_State, the way |
| 17 | +the MIPS port already does. No PLT relocation is emitted, the linker |
| 18 | +selects secure-PLT and the link succeeds. |
| 19 | + |
| 20 | +Originally submitted upstream as LuaJIT/LuaJIT#486, against 2.0 and |
| 21 | +addressing LuaJIT/LuaJIT#481, and closed without being merged. OpenWrt |
| 22 | +has carried it for the upstream luajit package as 060-ppc-musl.patch |
| 23 | +since 2019, extended with the soft-float helpers the 2.1 branch needs |
| 24 | +in the GOT. Adapted here for luajit2 and verified on OpenWrt. |
| 25 | + |
| 26 | +Tested on Turris 1.x (e500v2, 32-bit big-endian, musl, soft-float) |
| 27 | +with BUILDMODE=dynamic. No R_PPC_PLTREL24 relocations remain, and the |
| 28 | +resulting binary runs correctly, including all libm calls routed |
| 29 | +through the new GOT. The previously produced dynamic binary crashed |
| 30 | +during startup. |
| 31 | + |
| 32 | +Co-authored-by: Josef Schlehofer <pepe.schlehofer@gmail.com> |
| 33 | +Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com> |
| 34 | +--- |
| 35 | + src/lj_dispatch.c | 11 ++++++++++- |
| 36 | + src/lj_dispatch.h | 32 +++++++++++++++++++++++++++++++- |
| 37 | + src/vm_ppc.dasc | 12 +++++++++++- |
| 38 | + 3 files changed, 52 insertions(+), 3 deletions(-) |
| 39 | + |
| 40 | +--- a/src/lj_dispatch.c |
| 41 | ++++ b/src/lj_dispatch.c |
| 42 | +@@ -56,6 +56,15 @@ static const ASMFunction dispatch_got[] |
| 43 | + #undef GOTFUNC |
| 44 | + #endif |
| 45 | + |
| 46 | ++#if LJ_TARGET_PPC && LJ_32 |
| 47 | ++#include <math.h> |
| 48 | ++#define GOTFUNC(name) (ASMFunction)name, |
| 49 | ++static const ASMFunction dispatch_got[] = { |
| 50 | ++ GOTDEF(GOTFUNC) |
| 51 | ++}; |
| 52 | ++#undef GOTFUNC |
| 53 | ++#endif |
| 54 | ++ |
| 55 | + /* Initialize instruction dispatch table and hot counters. */ |
| 56 | + void lj_dispatch_init(GG_State *GG) |
| 57 | + { |
| 58 | +@@ -76,7 +85,7 @@ void lj_dispatch_init(GG_State *GG) |
| 59 | + GG->g.bc_cfunc_ext = GG->g.bc_cfunc_int = BCINS_AD(BC_FUNCC, LUA_MINSTACK, 0); |
| 60 | + for (i = 0; i < GG_NUM_ASMFF; i++) |
| 61 | + GG->bcff[i] = BCINS_AD(BC__MAX+i, 0, 0); |
| 62 | +-#if LJ_TARGET_MIPS |
| 63 | ++#if LJ_TARGET_MIPS || (LJ_TARGET_PPC && LJ_32) |
| 64 | + memcpy(GG->got, dispatch_got, LJ_GOT__MAX*sizeof(ASMFunction *)); |
| 65 | + #endif |
| 66 | + } |
| 67 | +--- a/src/lj_dispatch.h |
| 68 | ++++ b/src/lj_dispatch.h |
| 69 | +@@ -66,6 +66,36 @@ GOTDEF(GOTENUM) |
| 70 | + }; |
| 71 | + #endif |
| 72 | + |
| 73 | ++#if LJ_TARGET_PPC && LJ_32 |
| 74 | ++/* Call libm/libgcc helpers via our own GOT instead of the PLT. A PLT call |
| 75 | ++** from the VM assembler forces the obsolete BSS-PLT for the whole link, |
| 76 | ++** which fails against secure-PLT objects emitted by GCC 12 and newer. |
| 77 | ++*/ |
| 78 | ++#if LJ_SOFTFP |
| 79 | ++#ifndef _LJ_IRCALL_H |
| 80 | ++extern double __ledf2(double a, double b); |
| 81 | ++extern double __adddf3(double a, double b); |
| 82 | ++extern double __subdf3(double a, double b); |
| 83 | ++extern double __muldf3(double a, double b); |
| 84 | ++extern double __divdf3(double a, double b); |
| 85 | ++#endif |
| 86 | ++#define SFGOTDEF(_) _(__ledf2) _(__adddf3) _(__subdf3) _(__muldf3) _(__divdf3) |
| 87 | ++#else |
| 88 | ++#define SFGOTDEF(_) |
| 89 | ++#endif |
| 90 | ++#define GOTDEF(_) \ |
| 91 | ++ _(floor) _(ceil) _(trunc) _(log) _(log10) _(exp) _(sin) _(cos) _(tan) \ |
| 92 | ++ _(asin) _(acos) _(atan) _(sinh) _(cosh) _(tanh) _(frexp) _(modf) _(atan2) \ |
| 93 | ++ _(pow) _(fmod) _(ldexp) _(sqrt) SFGOTDEF(_) |
| 94 | ++ |
| 95 | ++enum { |
| 96 | ++#define GOTENUM(name) LJ_GOT_##name, |
| 97 | ++GOTDEF(GOTENUM) |
| 98 | ++#undef GOTENUM |
| 99 | ++ LJ_GOT__MAX |
| 100 | ++}; |
| 101 | ++#endif |
| 102 | ++ |
| 103 | + /* Type of hot counter. Must match the code in the assembler VM. */ |
| 104 | + /* 16 bits are sufficient. Only 0.0015% overhead with maximum slot penalty. */ |
| 105 | + typedef uint16_t HotCount; |
| 106 | +@@ -93,7 +123,7 @@ typedef struct GG_State { |
| 107 | + /* Make g reachable via K12 encoded DISPATCH-relative addressing. */ |
| 108 | + uint8_t align1[(16-sizeof(global_State))&15]; |
| 109 | + #endif |
| 110 | +-#if LJ_TARGET_MIPS |
| 111 | ++#if LJ_TARGET_MIPS || (LJ_TARGET_PPC && LJ_32) |
| 112 | + ASMFunction got[LJ_GOT__MAX]; /* Global offset table. */ |
| 113 | + #endif |
| 114 | + #if LJ_HASJIT |
| 115 | +--- a/src/vm_ppc.dasc |
| 116 | ++++ b/src/vm_ppc.dasc |
| 117 | +@@ -50,7 +50,13 @@ |
| 118 | + |.macro blex, target; bl extern target; nop; .endmacro |
| 119 | + |.macro .toc, a, b; a, b; .endmacro |
| 120 | + |.else |
| 121 | +-|.macro blex, target; bl extern target@plt; .endmacro |
| 122 | ++|// Call via our own GOT to avoid PLT relocations, which force the obsolete |
| 123 | ++|// BSS-PLT on PPC32 and break linking against secure-PLT objects. |
| 124 | ++|.macro blex, target |
| 125 | ++| lwz TMP0, DISPATCH_GOT(target)(DISPATCH) |
| 126 | ++| mtctr TMP0 |
| 127 | ++| bctrl |
| 128 | ++|.endmacro |
| 129 | + |.macro .toc, a, b; .endmacro |
| 130 | + |.endif |
| 131 | + |.if OPD |
| 132 | +@@ -577,6 +583,10 @@ |
| 133 | + |// Assumes DISPATCH is relative to GL. |
| 134 | + #define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) |
| 135 | + #define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) |
| 136 | ++#if LJ_TARGET_PPC && LJ_32 |
| 137 | ++#define GG_DISP2GOT (GG_OFS(got) - GG_OFS(dispatch)) |
| 138 | ++#define DISPATCH_GOT(name) (GG_DISP2GOT + 4*LJ_GOT_##name) |
| 139 | ++#endif |
| 140 | + | |
| 141 | + #define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) |
| 142 | + | |
0 commit comments