Addr64 guest_next;
Bool resteerOK;
DisResult dres;
+ IRStmt* imark;
static Int n_resteers = 0;
Int d_resteers = 0;
&& vge->n_used < 3
);
+ /* This is the %EIP of the instruction we're just about to deal
+ with. */
+ guest_eip_curr_instr = guest_eip_bbstart + delta;
+
+ /* This is the irbb statement array index of the first stmt in
+ this insn. That will always be the instruction-mark
+ descriptor. */
first_stmt_idx = irbb->stmts_used;
+ /* Add an instruction-mark statement. We won't know until after
+ disInstr how long the instruction is, so just put in a zero
+ length and we'll fix it up later. */
+ stmt( IRStmt_IMark( (Addr64)guest_eip_curr_instr, 0 ));
+
if (n_instrs > 0) {
/* for the first insn, the dispatch loop will have set
%EIP, but for all the others we have to do it ourselves. */
- stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_eip_bbstart + delta)) );
+ stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_eip_curr_instr)) );
}
- guest_eip_curr_instr = guest_eip_bbstart + delta;
-
+ /* Do the instruction. This may set insn_verbose to True, which
+ needs to be annulled. */
+ size = 0; /* just in case disInstr doesn't set it */
dres = disInstr( resteerOK, chase_into_ok,
delta, subarch_guest, &size, &guest_next );
insn_verbose = False;
+ /* 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 = size;
+
/* Print the resulting IR, if needed. */
if (vex_traceflags & VEX_TRACE_FE) {
for (i = first_stmt_idx; i < irbb->stmts_used; i++) {
addInstr(env, X86Instr_MFence(env->subarch));
return;
+ /* --------- INSTR MARK --------- */
+ /* Doesn't generate any executable code ... */
+ case Ist_IMark:
+ return;
+
/* --------- EXIT --------- */
case Ist_Exit: {
X86RI* dst;
void ppIRStmt ( IRStmt* s )
{
switch (s->tag) {
+ case Ist_IMark:
+ vex_printf("IMark(0x%llx, %d)", s->Ist.IMark.addr,
+ s->Ist.IMark.len);
+ break;
case Ist_Put:
vex_printf( "PUT(%d) = ", s->Ist.Put.offset);
ppIRExpr(s->Ist.Put.data);
/* Constructors -- IRStmt */
+IRStmt* IRStmt_IMark ( Addr64 addr, Int len ) {
+ IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
+ s->tag = Ist_IMark;
+ s->Ist.IMark.addr = addr;
+ s->Ist.IMark.len = len;
+ return s;
+}
IRStmt* IRStmt_Put ( Int off, IRExpr* data ) {
IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
s->tag = Ist_Put;
IRStmt* dopyIRStmt ( IRStmt* s )
{
switch (s->tag) {
+ case Ist_IMark:
+ return IRStmt_IMark(s->Ist.IMark.addr, s->Ist.IMark.len);
case Ist_Put:
return IRStmt_Put(s->Ist.Put.offset,
dopyIRExpr(s->Ist.Put.data));
if (di->mAddr && !isAtom(di->mAddr))
return False;
return True;
+ case Ist_IMark:
case Ist_MFence:
return True;
case Ist_Exit:
Int i;
IRDirty* d;
switch (stmt->tag) {
+ case Ist_IMark:
+ break;
case Ist_Put:
useBeforeDef_Expr(bb,stmt,stmt->Ist.Put.data,def_counts);
break;
IRDirty* d;
IRTypeEnv* tyenv = bb->tyenv;
switch (stmt->tag) {
+ case Ist_IMark:
+ /* Somewhat heuristic, but rule out totally implausible
+ instruction sizes. */
+ if (stmt->Ist.IMark.len < 0 || stmt->Ist.IMark.len > 20)
+ sanityCheckFail(bb,stmt,"IRStmt.IMark.len: implausible");
+ break;
case Ist_Put:
tcExpr( bb, stmt, stmt->Ist.Put.data, gWordTy );
if (typeOfIRExpr(tyenv,stmt->Ist.Put.data) == Ity_I1)
IRExpr *e1, *e2;
IRDirty *d, *d2;
switch (st->tag) {
+ case Ist_IMark:
+ addStmtToIRBB(bb, st);
+ break;
case Ist_Put:
if (isAtom(st->Ist.Put.data)) {
/* optimisation to reduce the amount of heap wasted
vassert(isAtom(st->Ist.PutI.data));
break;
+ case Ist_IMark:
+ break;
+
default:
vex_printf("\n");
ppIRStmt(st);
return IRStmt_Dirty(d2);
}
+ case Ist_IMark:
+ return IRStmt_IMark(st->Ist.IMark.addr, st->Ist.IMark.len);
+
case Ist_MFence:
return IRStmt_MFence();
for (i = 0; d->args[i] != NULL; i++)
addUses_Expr(set, d->args[i]);
return;
+ case Ist_IMark:
case Ist_MFence:
return;
case Ist_Exit:
getArrayBounds(pi->Ist.PutI.descr, &minoffP, &maxoffP);
switch (s2->tag) {
+ case Ist_IMark:
+ return False;
+
case Ist_MFence:
/* just be paranoid ... this should be rare. */
return True;
Int i;
IRDirty* d;
switch (st->tag) {
+ case Ist_IMark:
+ break;
case Ist_Put:
deltaIRExpr(st->Ist.Put.data, delta);
break;
for (i = 0; d->args[i]; i++)
occCount_Expr(env, d->args[i]);
return;
+ case Ist_IMark:
case Ist_MFence:
return;
case Ist_Exit:
st->Ist.Exit.jk,
st->Ist.Exit.dst
);
+ case Ist_IMark:
+ return IRStmt_IMark(st->Ist.IMark.addr, st->Ist.IMark.len);
case Ist_MFence:
return IRStmt_MFence();
case Ist_Dirty:
if (d->mFx != Ifx_None)
vassert(isAtom(d->mAddr));
break;
+ case Ist_IMark:
case Ist_MFence:
break;
case Ist_Exit:
/* The possible kinds of statements are as follows: */
typedef
enum {
+ Ist_IMark, /* instruction mark: describe addr/len of guest insn
+ whose IR follows */
Ist_Put, /* write guest state, fixed offset */
Ist_PutI, /* write guest state, run-time offset */
Ist_Tmp, /* assign value to temporary */
struct _IRStmt {
IRStmtTag tag;
union {
+ struct {
+ Addr64 addr;
+ Int len;
+ } IMark;
struct {
Int offset;
IRExpr* data;
}
IRStmt;
+extern IRStmt* IRStmt_IMark ( Addr64 addr, Int len );
extern IRStmt* IRStmt_Put ( Int off, IRExpr* data );
extern IRStmt* IRStmt_PutI ( IRArray* descr, IRExpr* ix, Int bias,
IRExpr* data );