From: Stefan Maksimovic Date: Fri, 17 Apr 2020 17:54:58 +0000 (+0000) Subject: mips: treat delay slot as part of the previous instruction X-Git-Tag: VALGRIND_3_16_0~52 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ddc311558e11c47a06ba996a7d075b336726fc0b;p=thirdparty%2Fvalgrind.git mips: treat delay slot as part of the previous instruction Do so by recursively calling disInstr_MIPS_WRK() if the instruction currently being disassembled is a branch/jump, effectively combining them into one IR instruction. A notable change is that the branch/jump + delay slot combination now forms an eight-byte instruction. This is related to KDE #417187. This fixes drd/tests/annotate_hbefore on mips. --- diff --git a/VEX/priv/guest_mips_toIR.c b/VEX/priv/guest_mips_toIR.c index 87f53e3347..d915487af0 100644 --- a/VEX/priv/guest_mips_toIR.c +++ b/VEX/priv/guest_mips_toIR.c @@ -24799,23 +24799,33 @@ static DisResult disInstr_MIPS_WRK ( Long delta64, DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins); if (delta != 0) { - if (branch_or_jump(guest_code + delta - 4)) { - if (lastn == NULL && bstmt == NULL) { - vassert(0); - } else { - dres.whatNext = Dis_StopHere; - - if (lastn != NULL) { - delay_slot_jump = True; - } else if (bstmt != NULL) { - delay_slot_branch = True; - } - } + if (branch_or_jump(guest_code + delta - 4) + && (lastn != NULL || bstmt != NULL)) { + dres.whatNext = Dis_StopHere; + delay_slot_jump = (lastn != NULL); + delay_slot_branch = (bstmt != NULL); } - if (branch_or_link_likely(guest_code + delta - 4)) { - likely_delay_slot = True; - } + likely_delay_slot = (lastn != NULL) + && branch_or_link_likely(guest_code + delta - 4); + } + + // Emit an Illegal instruction in case a branch/jump + // instruction is encountered in the delay slot + // of an another branch/jump + if ((delay_slot_branch || likely_delay_slot || delay_slot_jump) && + (branch_or_jump(guest_code + delta) || + branch_or_link_likely(guest_code + delta))) { + if (mode64) + putPC(mkU64(guest_PC_curr_instr + 4)); + else + putPC(mkU32(guest_PC_curr_instr + 4)); + + dres.jk_StopHere = Ijk_SigILL; + dres.whatNext = Dis_StopHere; + lastn = NULL; + bstmt = NULL; + return dres; } /* Spot "Special" instructions (see comment at top of file). */ @@ -25028,14 +25038,23 @@ decode_failure: decode_success: + dres.len = 4; + DIP("\n"); + /* All decode successes end up here. */ switch (dres.whatNext) { case Dis_Continue: - if (mode64) - putPC(mkU64(guest_PC_curr_instr + 4)); - else - putPC(mkU32(guest_PC_curr_instr + 4)); - + if (branch_or_jump(guest_code + delta) || + branch_or_link_likely(guest_code + delta)) { + guest_PC_curr_instr += 4; + dres = disInstr_MIPS_WRK(delta64 + 4, archinfo, abiinfo, sigill_diag); + dres.len = 8; + } else { + if (mode64) + putPC(mkU64(guest_PC_curr_instr + 4)); + else + putPC(mkU32(guest_PC_curr_instr + 4)); + } break; case Dis_StopHere: @@ -25058,9 +25077,6 @@ decode_success: else putPC(mkU32(guest_PC_curr_instr + 4)); } - dres.len = 4; - - DIP("\n"); return dres; diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h index 4779eea015..25e125653b 100644 --- a/include/pub_tool_machine.h +++ b/include/pub_tool_machine.h @@ -92,13 +92,13 @@ #elif defined(VGP_mips32_linux) # define VG_MIN_INSTR_SZB 4 -# define VG_MAX_INSTR_SZB 4 +# define VG_MAX_INSTR_SZB 8 # define VG_CLREQ_SZB 20 # define VG_STACK_REDZONE_SZB 0 #elif defined(VGP_mips64_linux) # define VG_MIN_INSTR_SZB 4 -# define VG_MAX_INSTR_SZB 4 +# define VG_MAX_INSTR_SZB 8 # define VG_CLREQ_SZB 20 # define VG_STACK_REDZONE_SZB 0