aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2021-03-23 00:26:08 +0100
committerMike Pall <mike>2021-03-23 00:26:08 +0100
commitdbb78630169a8106b355a5be8af627e98c362f1e (patch)
treea5db8abc676432cb66d36923f04aef1271c54e2e
parente131936133c58de4426c595db2341caf5a1665b5 (diff)
downloadluajit-dbb78630169a8106b355a5be8af627e98c362f1e.tar.gz
luajit-dbb78630169a8106b355a5be8af627e98c362f1e.tar.bz2
luajit-dbb78630169a8106b355a5be8af627e98c362f1e.zip
MIPS: Fix handling of long-range spare jumps.
-rw-r--r--src/lj_asm_mips.h48
-rw-r--r--src/lj_mcode.c11
2 files changed, 34 insertions, 25 deletions
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index 321d63c0..a3ab2f8e 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -64,19 +64,31 @@ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
64/* Setup spare long-range jump slots per mcarea. */ 64/* Setup spare long-range jump slots per mcarea. */
65static void asm_sparejump_setup(ASMState *as) 65static void asm_sparejump_setup(ASMState *as)
66{ 66{
67 MCode *mxp = as->mcbot; 67 MCode *mxp = as->mctop;
68 if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) { 68 if ((char *)mxp == (char *)as->J->mcarea + as->J->szmcarea) {
69 mxp -= MIPS_SPAREJUMP*2;
69 lj_assertA(MIPSI_NOP == 0, "bad NOP"); 70 lj_assertA(MIPSI_NOP == 0, "bad NOP");
70 memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode)); 71 memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
71 mxp += MIPS_SPAREJUMP*2; 72 as->mctop = mxp;
72 lj_assertA(mxp < as->mctop, "MIPS_SPAREJUMP too big");
73 lj_mcode_sync(as->mcbot, mxp);
74 lj_mcode_commitbot(as->J, mxp);
75 as->mcbot = mxp;
76 as->mclim = as->mcbot + MCLIM_REDZONE;
77 } 73 }
78} 74}
79 75
76static MCode *asm_sparejump_use(MCode *mcarea, MCode tjump)
77{
78 MCode *mxp = (MCode *)((char *)mcarea + ((MCLink *)mcarea)->size);
79 int slot = MIPS_SPAREJUMP;
80 while (slot--) {
81 mxp -= 2;
82 if (*mxp == tjump) {
83 return mxp;
84 } else if (*mxp == MIPSI_NOP) {
85 *mxp = tjump;
86 return mxp;
87 }
88 }
89 return NULL;
90}
91
80/* Setup exit stub after the end of each trace. */ 92/* Setup exit stub after the end of each trace. */
81static void asm_exitstub_setup(ASMState *as) 93static void asm_exitstub_setup(ASMState *as)
82{ 94{
@@ -2704,21 +2716,17 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2704 patchbranch: 2716 patchbranch:
2705 p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu); 2717 p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
2706 *p = MIPSI_NOP; /* Replace the load of the exit number. */ 2718 *p = MIPSI_NOP; /* Replace the load of the exit number. */
2707 cstop = p; 2719 cstop = p+1;
2708 if (!cstart) cstart = p-1; 2720 if (!cstart) cstart = p-1;
2709 } else { /* Branch out of range. Use spare jump slot in mcarea. */ 2721 } else { /* Branch out of range. Use spare jump slot in mcarea. */
2710 int i; 2722 MCode *mcjump = asm_sparejump_use(mcarea, tjump);
2711 for (i = (int)(sizeof(MCLink)/sizeof(MCode)); 2723 if (mcjump) {
2712 i < (int)(sizeof(MCLink)/sizeof(MCode)+MIPS_SPAREJUMP*2); 2724 lj_mcode_sync(mcjump, mcjump+1);
2713 i += 2) { 2725 delta = mcjump - p;
2714 if (mcarea[i] == tjump) { 2726 if (((delta + 0x8000) >> 16) == 0) {
2715 delta = mcarea+i - p;
2716 goto patchbranch;
2717 } else if (mcarea[i] == MIPSI_NOP) {
2718 mcarea[i] = tjump;
2719 cstart = mcarea+i;
2720 delta = mcarea+i - p;
2721 goto patchbranch; 2727 goto patchbranch;
2728 } else {
2729 lj_assertJ(0, "spare jump out of range: -Osizemcode too big");
2722 } 2730 }
2723 } 2731 }
2724 /* Ignore jump slot overflow. Child trace is simply not attached. */ 2732 /* Ignore jump slot overflow. Child trace is simply not attached. */
diff --git a/src/lj_mcode.c b/src/lj_mcode.c
index 9ce1deec..fc67eaee 100644
--- a/src/lj_mcode.c
+++ b/src/lj_mcode.c
@@ -314,21 +314,21 @@ void lj_mcode_abort(jit_State *J)
314/* Set/reset protection to allow patching of MCode areas. */ 314/* Set/reset protection to allow patching of MCode areas. */
315MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) 315MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish)
316{ 316{
317#if LUAJIT_SECURITY_MCODE == 0
318 UNUSED(J); UNUSED(ptr); UNUSED(finish);
319 return NULL;
320#else
321 if (finish) { 317 if (finish) {
318#if LUAJIT_SECURITY_MCODE
322 if (J->mcarea == ptr) 319 if (J->mcarea == ptr)
323 mcode_protect(J, MCPROT_RUN); 320 mcode_protect(J, MCPROT_RUN);
324 else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN))) 321 else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN)))
325 mcode_protfail(J); 322 mcode_protfail(J);
323#endif
326 return NULL; 324 return NULL;
327 } else { 325 } else {
328 MCode *mc = J->mcarea; 326 MCode *mc = J->mcarea;
329 /* Try current area first to use the protection cache. */ 327 /* Try current area first to use the protection cache. */
330 if (ptr >= mc && ptr < (MCode *)((char *)mc + J->szmcarea)) { 328 if (ptr >= mc && ptr < (MCode *)((char *)mc + J->szmcarea)) {
329#if LUAJIT_SECURITY_MCODE
331 mcode_protect(J, MCPROT_GEN); 330 mcode_protect(J, MCPROT_GEN);
331#endif
332 return mc; 332 return mc;
333 } 333 }
334 /* Otherwise search through the list of MCode areas. */ 334 /* Otherwise search through the list of MCode areas. */
@@ -336,13 +336,14 @@ MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish)
336 mc = ((MCLink *)mc)->next; 336 mc = ((MCLink *)mc)->next;
337 lj_assertJ(mc != NULL, "broken MCode area chain"); 337 lj_assertJ(mc != NULL, "broken MCode area chain");
338 if (ptr >= mc && ptr < (MCode *)((char *)mc + ((MCLink *)mc)->size)) { 338 if (ptr >= mc && ptr < (MCode *)((char *)mc + ((MCLink *)mc)->size)) {
339#if LUAJIT_SECURITY_MCODE
339 if (LJ_UNLIKELY(mcode_setprot(mc, ((MCLink *)mc)->size, MCPROT_GEN))) 340 if (LJ_UNLIKELY(mcode_setprot(mc, ((MCLink *)mc)->size, MCPROT_GEN)))
340 mcode_protfail(J); 341 mcode_protfail(J);
342#endif
341 return mc; 343 return mc;
342 } 344 }
343 } 345 }
344 } 346 }
345#endif
346} 347}
347 348
348/* Limit of MCode reservation reached. */ 349/* Limit of MCode reservation reached. */