diff --git a/api/docs/bt.dox b/api/docs/bt.dox index 1ae0c7f96f2ebe538b1e39b196633222ec32eeea..4b347c6b84e88d425aad3556d27d9df2b0858adb 100644 --- a/api/docs/bt.dox +++ b/api/docs/bt.dox @@ -500,6 +500,8 @@ internal operation requires that we impose the following limitations: a basic block, and it must be the final application branch in the block. - The exit control-flow of a block ending in a system call cannot be changed. + - On AArch64, an ISB instruction (#OP_isb) must be the last instruction + in its block. Application instructions, or non-meta instructions, in addition to being processed (and followed if control flow), are also considered safe points diff --git a/core/arch/interp.c b/core/arch/interp.c index 0c992e91fe6a91bea50b0674c3469df9658f543a..d1ac010960b50aa5477103dc326c8ce187f6c24c 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -2907,6 +2907,13 @@ client_process_bb(dcontext_t *dcontext, build_bb_t *bb) "block's app sources (instr_set_translation() targets) " "must remain within original bounds"); +# ifdef AARCH64 + if (instr_get_opcode(inst) == OP_isb) { + CLIENT_ASSERT(inst == instrlist_last(bb->ilist), + "OP_isb must be last instruction in block"); + } +# endif + /* PR 307284: we didn't process syscalls and ints pre-client * so do so now to get bb->flags and bb->exit_type set */ @@ -3920,6 +3927,11 @@ build_bb_ilist(dcontext_t *dcontext, build_bb_t *bb) if (!bb_process_interrupt(dcontext, bb)) break; } +#ifdef AARCH64 + /* OP_isb, when mangled, has a potential side exit. */ + else if (instr_get_opcode(bb->instr) == OP_isb) + break; +#endif #if 0/*i#1313, i#1314*/ else if (instr_get_opcode(bb->instr) == OP_getsec) { /* XXX i#1313: if we support CPL0 in the future we'll need to diff --git a/core/arch/mangle_shared.c b/core/arch/mangle_shared.c index 513c9253ccec67e24b9637f2fe8ed1e706ddb7a4..52b1486c54315e29d8bc55748a7a592313daad34 100644 --- a/core/arch/mangle_shared.c +++ b/core/arch/mangle_shared.c @@ -908,7 +908,7 @@ mangle(dcontext_t *dcontext, instrlist_t *ilist, uint *flags INOUT, #ifdef AARCH64 if (instr_is_icache_op(instr) && instr_is_app(instr)) { next_instr = mangle_icache_op(dcontext, ilist, instr, next_instr, - get_app_instr_xl8(next_instr)); + get_app_instr_xl8(instr) + AARCH64_INSTR_SIZE); continue; } #endif diff --git a/core/lib/instrument_api.h b/core/lib/instrument_api.h index 9f15ce884985a0b648d9457f7fbf14d6092042cd..c513e10eacc3600cfd31aa60312916620165e87e 100644 --- a/core/lib/instrument_api.h +++ b/core/lib/instrument_api.h @@ -221,6 +221,8 @@ DR_API * - A system call or interrupt instruction can only be added * if it satisfies the above constraints: i.e., if it is the final * instruction in the block and the only system call or interrupt. + * - Any AArch64 #OP_isb instruction must be the last instruction + * in its block. * - All IT blocks must be legal. For example, application instructions * inside an IT block cannot be removed or added to without also * updating the OP_it instruction itself. Clients can use