diff options
author | Mike Pall <mike> | 2021-03-23 00:26:08 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2021-03-23 00:26:08 +0100 |
commit | dbb78630169a8106b355a5be8af627e98c362f1e (patch) | |
tree | a5db8abc676432cb66d36923f04aef1271c54e2e | |
parent | e131936133c58de4426c595db2341caf5a1665b5 (diff) | |
download | luajit-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.h | 48 | ||||
-rw-r--r-- | src/lj_mcode.c | 11 |
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. */ |
65 | static void asm_sparejump_setup(ASMState *as) | 65 | static 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 | ||
76 | static 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. */ |
81 | static void asm_exitstub_setup(ASMState *as) | 93 | static 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. */ |
315 | MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) | 315 | MCode *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. */ |