Skip to content

Commit 617e268

Browse files
BKPepeliudf0716
authored andcommitted
luajit2: fix build and runtime on powerpc
luajit2 currently fails to link for powerpc: lj_vm.o emits PLT calls that force BSS-PLT, which the inline-PLT relocations emitted by GCC 12 and newer do not support. Add the same GOT-based fix that lang/lua/luajit has carried as 060-ppc-musl.patch since 2019. With that in place the package builds, but ipairs() and pairs() turn out to be broken on 32-bit big-endian soft-float targets. Both are regressions in luajit2's PPC64 patch and do not affect upstream LuaJIT. To be submitted to openresty/luajit2 as well. Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com> (cherry picked from commit a6b248d) (cherry picked from commit a6a052e)
1 parent bbf9974 commit 617e268

4 files changed

Lines changed: 227 additions & 1 deletion

lang/lua/luajit2/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk
33
PKG_NAME:=luajit2
44
PKG_SOURCE_DATE:=2026-02-27
55
PKG_VERSION:=2.1.$(subst -,.,$(PKG_SOURCE_DATE))
6-
PKG_RELEASE:=1
6+
PKG_RELEASE:=2
77

88
PKG_SOURCE_PROTO:=git
99
PKG_SOURCE_URL:=https://github.com/openresty/luajit2
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
From 2b0b4f7fdb5fdefd13c5cbdeb159881da3098c96 Mon Sep 17 00:00:00 2001
2+
From: Josef Schlehofer <pepe.schlehofer@gmail.com>
3+
Date: Sat, 15 Aug 2026 09:11:08 +0200
4+
Subject: [PATCH] PPC: Fix ipairs() on soft-float targets
5+
6+
The soft-float branch of the ipairs_aux fast function loads the array
7+
slot value from WORD_HI instead of WORD_LO. On big-endian targets,
8+
WORD_HI contains the itype while the value word is in WORD_LO, so the
9+
itype is loaded twice and the actual value is never loaded.
10+
11+
Every element therefore comes back carrying the itype in its payload.
12+
Numbers surface as -14, the LJ_TNUMX tag read as an int32. For GC
13+
types the payload is the GCref, so the tag becomes a fabricated
14+
pointer that tostring() then dereferences.
15+
16+
The original soft-float code used a hardcoded 4(TMP1), which is
17+
WORD_LO on big-endian. Commit 2763a421 ("Patch for PPC64 support")
18+
rewrote it as WORD_HI. Upstream LuaJIT is unaffected.
19+
20+
Reproducer on Turris 1.x (e500v2, 32-bit big-endian, soft-float):
21+
22+
$ luajit -e 'local s=0 for i,v in ipairs({10,20,30}) do s=s+v end print(s)'
23+
-42 -- expected 60
24+
25+
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
26+
---
27+
src/vm_ppc.dasc | 2 +-
28+
1 file changed, 1 insertion(+), 1 deletion(-)
29+
30+
--- a/src/vm_ppc.dasc
31+
+++ b/src/vm_ppc.dasc
32+
@@ -1833,7 +1833,7 @@ static void build_subroutines(BuildCtx *
33+
| lwz TMP2, WORD_HI(TMP1)
34+
|.else
35+
| lwzux TMP2, TMP1, TMP3
36+
- | lwz TMP3, WORD_HI(TMP1)
37+
+ | lwz TMP3, WORD_LO(TMP1)
38+
|.endif
39+
|1:
40+
| checknil TMP2
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
From 0abde25c632e6b3343d07d978d9cc4209fe05f58 Mon Sep 17 00:00:00 2001
2+
From: Josef Schlehofer <pepe.schlehofer@gmail.com>
3+
Date: Sat, 15 Aug 2026 09:11:08 +0200
4+
Subject: [PATCH] PPC: Fix pairs() over hash-less tables on soft-float targets
5+
6+
BC_ITERN checks the itype of the node value in RB to skip empty slots
7+
in the hash part. Upstream loads RB unconditionally before the FPU
8+
split; commit 2763a421 ("Patch for PPC64 support") moved that load
9+
into the FPU branch only. On soft-float builds, RB still contains
10+
RC*8 from the hash-part setup, so the nil check never succeeds and
11+
iterating a table whose hash part is empty yields one extra
12+
(nil, nil) pair.
13+
14+
Check CARG1 instead, which the soft-float branch already loads with
15+
the itype. The FPU branch is left untouched. Upstream LuaJIT is
16+
unaffected.
17+
18+
Reproducer on Turris 1.x (e500v2, 32-bit big-endian, soft-float):
19+
20+
$ luajit -e 'for k,v in pairs({7,8,9}) do print(k,v) end'
21+
1 7
22+
2 8
23+
3 9
24+
nil nil -- spurious
25+
26+
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
27+
---
28+
src/vm_ppc.dasc | 4 ++++
29+
1 file changed, 4 insertions(+)
30+
31+
--- a/src/vm_ppc.dasc
32+
+++ b/src/vm_ppc.dasc
33+
@@ -5807,7 +5807,11 @@ static void build_ins(BuildCtx *ctx, BCO
34+
| lwz CARG2, 4(CARG3)
35+
| add NODE:TMP3, TMP2, TMP3
36+
|.endif
37+
+ |.if FPU
38+
| checknil RB
39+
+ |.else
40+
+ | checknil CARG1
41+
+ |.endif
42+
| lwz INS, -4(PC)
43+
| beq >7
44+
|.if FPU
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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

Comments
 (0)