📄 bb_to_ir.c
字号:
/* Finally, actually disassemble an instruction. */ dres = dis_instr_fn ( irbb, need_to_put_IP, resteerOKfn, callback_opaque, guest_code, delta, guest_IP_curr_instr, arch_guest, archinfo_guest, host_bigendian ); /* stay sane ... */ vassert(dres.whatNext == Dis_StopHere || dres.whatNext == Dis_Continue || dres.whatNext == Dis_Resteer); vassert(dres.len >= 0 && dres.len <= 20); if (dres.whatNext != Dis_Resteer) vassert(dres.continueAt == 0); /* Fill in the insn-mark length field. */ vassert(first_stmt_idx >= 0 && first_stmt_idx < irbb->stmts_used); imark = irbb->stmts[first_stmt_idx]; vassert(imark); vassert(imark->tag == Ist_IMark); vassert(imark->Ist.IMark.len == 0); imark->Ist.IMark.len = toUInt(dres.len); /* Print the resulting IR, if needed. */ if (vex_traceflags & VEX_TRACE_FE) { for (i = first_stmt_idx; i < irbb->stmts_used; i++) { vex_printf(" "); ppIRStmt(irbb->stmts[i]); vex_printf("\n"); } } /* If dis_instr_fn terminated the BB at this point, check it also filled in the irbb->next field. */ if (dres.whatNext == Dis_StopHere) { vassert(irbb->next != NULL); if (debug_print) { vex_printf(" "); vex_printf( "goto {"); ppIRJumpKind(irbb->jumpkind); vex_printf( "} "); ppIRExpr( irbb->next ); vex_printf( "\n"); } } /* Update the VexGuestExtents we are constructing. */ /* If vex_control.guest_max_insns is required to be < 100 and each insn is at max 20 bytes long, this limit of 5000 then seems reasonable since the max possible extent length will be 100 * 20 == 2000. */ vassert(vge->len[vge->n_used-1] < 5000); vge->len[vge->n_used-1] = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len )); n_instrs++; if (debug_print) vex_printf("\n"); /* Advance delta (inconspicuous but very important :-) */ delta += (Long)dres.len; switch (dres.whatNext) { case Dis_Continue: vassert(irbb->next == NULL); if (n_instrs < vex_control.guest_max_insns) { /* keep going */ } else { /* We have to stop. */ irbb->next = IRExpr_Const( guest_word_type == Ity_I32 ? IRConst_U32(toUInt(guest_IP_bbstart+delta)) : IRConst_U64(guest_IP_bbstart+delta) ); goto done; } break; case Dis_StopHere: vassert(irbb->next != NULL); goto done; case Dis_Resteer: /* Check that we actually allowed a resteer .. */ vassert(resteerOK); vassert(irbb->next == NULL); /* figure out a new delta to continue at. */ vassert(resteerOKfn(callback_opaque,dres.continueAt)); delta = dres.continueAt - guest_IP_bbstart; /* we now have to start a new extent slot. */ vge->n_used++; vassert(vge->n_used <= 3); vge->base[vge->n_used-1] = dres.continueAt; vge->len[vge->n_used-1] = 0; n_resteers++; d_resteers++; if (0 && (n_resteers & 0xFF) == 0) vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n", n_resteers, d_resteers, dres.continueAt, delta); break; default: vpanic("bb_to_IR"); } } /*NOTREACHED*/ vassert(0); done: /* We're done. The only thing that might need attending to is that a self-checking preamble may need to be created. */ if (do_self_check) { UInt len2check, adler32; IRTemp tistart_tmp, tilen_tmp; vassert(vge->n_used == 1); len2check = vge->len[0]; if (len2check == 0) len2check = 1; adler32 = genericg_compute_adler32( (HWord)guest_code, len2check ); /* Set TISTART and TILEN. These will describe to the despatcher the area of guest code to invalidate should we exit with a self-check failure. */ tistart_tmp = newIRTemp(irbb->tyenv, guest_word_type); tilen_tmp = newIRTemp(irbb->tyenv, guest_word_type); irbb->stmts[selfcheck_idx+0] = IRStmt_Tmp(tistart_tmp, IRExpr_Const(guest_IP_bbstart_IRConst) ); irbb->stmts[selfcheck_idx+1] = IRStmt_Tmp(tilen_tmp, guest_word_type==Ity_I32 ? IRExpr_Const(IRConst_U32(len2check)) : IRExpr_Const(IRConst_U64(len2check)) ); irbb->stmts[selfcheck_idx+2] = IRStmt_Put( offB_TISTART, IRExpr_Tmp(tistart_tmp) ); irbb->stmts[selfcheck_idx+3] = IRStmt_Put( offB_TILEN, IRExpr_Tmp(tilen_tmp) ); irbb->stmts[selfcheck_idx+4] = IRStmt_Exit( IRExpr_Binop( Iop_CmpNE32, mkIRExprCCall( Ity_I32, 2/*regparms*/, "genericg_compute_adler32",#if defined(__powerpc__) && defined(__powerpc64__) (void*)((ULong*)(&genericg_compute_adler32))[0],#else &genericg_compute_adler32,#endif mkIRExprVec_2( mkIRExpr_HWord( (HWord)guest_code ), mkIRExpr_HWord( (HWord)len2check ) ) ), IRExpr_Const(IRConst_U32(adler32)) ), Ijk_TInval, guest_IP_bbstart_IRConst ); } return irbb;}/*------------------------------------------------------------- A support routine for doing self-checking translations. -------------------------------------------------------------*//* CLEAN HELPER *//* CALLED FROM GENERATED CODE *//* Compute the Adler32 checksum of host memory at [addr .. addr+len-1]. This presumably holds guest code. Note this is not a proper implementation of Adler32 in that it fails to mod the counts with 65521 every 5552 bytes, but we really never expect to get anywhere near that many bytes to deal with. This fn is called once for every use of a self-checking translation, so it needs to be as fast as possible. */__attribute((regparm(2)))static UInt genericg_compute_adler32 ( HWord addr, HWord len ){ UInt s1 = 1; UInt s2 = 0; UChar* buf = (UChar*)addr; while (len >= 4) { s1 += buf[0]; s2 += s1; s1 += buf[1]; s2 += s1; s1 += buf[2]; s2 += s1; s1 += buf[3]; s2 += s1; buf += 4; len -= 4; } while (len > 0) { s1 += buf[0]; s2 += s1; len--; buf++; } return (s2 << 16) + s1;}/*--------------------------------------------------------------------*//*--- end guest-generic/bb_to_IR.c ---*//*--------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -