MIPS: Fix handling of long-range spare jumps.

This commit is contained in:
Mike Pall 2021-03-23 00:26:08 +01:00
parent e131936133
commit dbb7863016
2 changed files with 34 additions and 25 deletions

View File

@ -64,19 +64,31 @@ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
/* Setup spare long-range jump slots per mcarea. */ /* Setup spare long-range jump slots per mcarea. */
static void asm_sparejump_setup(ASMState *as) static void asm_sparejump_setup(ASMState *as)
{ {
MCode *mxp = as->mcbot; MCode *mxp = as->mctop;
if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) { if ((char *)mxp == (char *)as->J->mcarea + as->J->szmcarea) {
mxp -= MIPS_SPAREJUMP*2;
lj_assertA(MIPSI_NOP == 0, "bad NOP"); lj_assertA(MIPSI_NOP == 0, "bad NOP");
memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode)); memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
mxp += MIPS_SPAREJUMP*2; as->mctop = mxp;
lj_assertA(mxp < as->mctop, "MIPS_SPAREJUMP too big");
lj_mcode_sync(as->mcbot, mxp);
lj_mcode_commitbot(as->J, mxp);
as->mcbot = mxp;
as->mclim = as->mcbot + MCLIM_REDZONE;
} }
} }
static MCode *asm_sparejump_use(MCode *mcarea, MCode tjump)
{
MCode *mxp = (MCode *)((char *)mcarea + ((MCLink *)mcarea)->size);
int slot = MIPS_SPAREJUMP;
while (slot--) {
mxp -= 2;
if (*mxp == tjump) {
return mxp;
} else if (*mxp == MIPSI_NOP) {
*mxp = tjump;
return mxp;
}
}
return NULL;
}
/* Setup exit stub after the end of each trace. */ /* Setup exit stub after the end of each trace. */
static void asm_exitstub_setup(ASMState *as) static void asm_exitstub_setup(ASMState *as)
{ {
@ -2704,21 +2716,17 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
patchbranch: patchbranch:
p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu); p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
*p = MIPSI_NOP; /* Replace the load of the exit number. */ *p = MIPSI_NOP; /* Replace the load of the exit number. */
cstop = p; cstop = p+1;
if (!cstart) cstart = p-1; if (!cstart) cstart = p-1;
} else { /* Branch out of range. Use spare jump slot in mcarea. */ } else { /* Branch out of range. Use spare jump slot in mcarea. */
int i; MCode *mcjump = asm_sparejump_use(mcarea, tjump);
for (i = (int)(sizeof(MCLink)/sizeof(MCode)); if (mcjump) {
i < (int)(sizeof(MCLink)/sizeof(MCode)+MIPS_SPAREJUMP*2); lj_mcode_sync(mcjump, mcjump+1);
i += 2) { delta = mcjump - p;
if (mcarea[i] == tjump) { if (((delta + 0x8000) >> 16) == 0) {
delta = mcarea+i - p;
goto patchbranch;
} else if (mcarea[i] == MIPSI_NOP) {
mcarea[i] = tjump;
cstart = mcarea+i;
delta = mcarea+i - p;
goto patchbranch; goto patchbranch;
} else {
lj_assertJ(0, "spare jump out of range: -Osizemcode too big");
} }
} }
/* Ignore jump slot overflow. Child trace is simply not attached. */ /* Ignore jump slot overflow. Child trace is simply not attached. */

View File

@ -314,21 +314,21 @@ void lj_mcode_abort(jit_State *J)
/* Set/reset protection to allow patching of MCode areas. */ /* Set/reset protection to allow patching of MCode areas. */
MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish)
{ {
#if LUAJIT_SECURITY_MCODE == 0
UNUSED(J); UNUSED(ptr); UNUSED(finish);
return NULL;
#else
if (finish) { if (finish) {
#if LUAJIT_SECURITY_MCODE
if (J->mcarea == ptr) if (J->mcarea == ptr)
mcode_protect(J, MCPROT_RUN); mcode_protect(J, MCPROT_RUN);
else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN))) else if (LJ_UNLIKELY(mcode_setprot(ptr, ((MCLink *)ptr)->size, MCPROT_RUN)))
mcode_protfail(J); mcode_protfail(J);
#endif
return NULL; return NULL;
} else { } else {
MCode *mc = J->mcarea; MCode *mc = J->mcarea;
/* Try current area first to use the protection cache. */ /* Try current area first to use the protection cache. */
if (ptr >= mc && ptr < (MCode *)((char *)mc + J->szmcarea)) { if (ptr >= mc && ptr < (MCode *)((char *)mc + J->szmcarea)) {
#if LUAJIT_SECURITY_MCODE
mcode_protect(J, MCPROT_GEN); mcode_protect(J, MCPROT_GEN);
#endif
return mc; return mc;
} }
/* Otherwise search through the list of MCode areas. */ /* Otherwise search through the list of MCode areas. */
@ -336,13 +336,14 @@ MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish)
mc = ((MCLink *)mc)->next; mc = ((MCLink *)mc)->next;
lj_assertJ(mc != NULL, "broken MCode area chain"); lj_assertJ(mc != NULL, "broken MCode area chain");
if (ptr >= mc && ptr < (MCode *)((char *)mc + ((MCLink *)mc)->size)) { if (ptr >= mc && ptr < (MCode *)((char *)mc + ((MCLink *)mc)->size)) {
#if LUAJIT_SECURITY_MCODE
if (LJ_UNLIKELY(mcode_setprot(mc, ((MCLink *)mc)->size, MCPROT_GEN))) if (LJ_UNLIKELY(mcode_setprot(mc, ((MCLink *)mc)->size, MCPROT_GEN)))
mcode_protfail(J); mcode_protfail(J);
#endif
return mc; return mc;
} }
} }
} }
#endif
} }
/* Limit of MCode reservation reached. */ /* Limit of MCode reservation reached. */