extern
DisResult disInstr_AMD64 ( IRBB* irbb,
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( void*, Addr64 ),
+ void* callback_opaque,
UChar* guest_code,
Long delta,
Addr64 guest_IP,
static
DisResult disInstr_AMD64_WRK (
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
+ void* callback_opaque,
Long delta64,
VexArchInfo* archinfo
)
putIReg64(R_RSP, mkexpr(t1));
storeLE( mkexpr(t1), mkU64(guest_RIP_bbstart+delta));
make_redzone_AbiHint(t1, "call-d32");
- if (resteerOkFn((Addr64)d64)) {
+ if (resteerOkFn( callback_opaque, (Addr64)d64) ) {
/* follow into the call target. */
dres.whatNext = Dis_Resteer;
dres.continueAt = d64;
goto decode_failure; /* JRS added 2004 July 11 */
d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta);
delta++;
- if (resteerOkFn(d64)) {
+ if (resteerOkFn(callback_opaque,d64)) {
dres.whatNext = Dis_Resteer;
dres.continueAt = d64;
} else {
goto decode_failure; /* JRS added 2004 July 11 */
d64 = (guest_RIP_bbstart+delta+sz) + getSDisp(sz,delta);
delta += sz;
- if (resteerOkFn(d64)) {
+ if (resteerOkFn(callback_opaque,d64)) {
dres.whatNext = Dis_Resteer;
dres.continueAt = d64;
} else {
DisResult disInstr_AMD64 ( IRBB* irbb_IN,
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( void*, Addr64 ),
+ void* callback_opaque,
UChar* guest_code_IN,
Long delta,
Addr64 guest_IP,
guest_RIP_next_assumed = 0;
guest_RIP_next_mustcheck = False;
- dres = disInstr_AMD64_WRK ( put_IP, resteerOkFn,
+ dres = disInstr_AMD64_WRK ( put_IP, resteerOkFn, callback_opaque,
delta, archinfo );
/* If disInstr_AMD64_WRK tried to figure out the next rip, check it
static UInt genericg_compute_adler32 ( HWord addr, HWord len );
/* Small helpers */
-static Bool const_False ( Addr64 a ) { return False; }
+static Bool const_False ( void* callback_opaque, Addr64 a ) {
+ return False;
+}
/* Disassemble a complete basic block, starting at guest_IP_start,
returning a new IRBB. The disassembler may chase across basic
do_self_check indicates that the caller needs a self-checking
translation.
- do_set_NRADDR indicates that the unredirected guest address for
- this BB should be written to the guest's NRADDR pseudo-register.
-
- offB_TIADDR, offB_TILEN and offB_NRADDR are the offsets of
- guest_TIADDR, guest_TILEN and guest_NRADDR. Since this routine has
- to work for any guest state, without knowing what it is, those
- offsets have to passed in.
+ preamble_function is a callback which allows the caller to add
+ its own IR preamble (following the self-check, if any). May be
+ NULL. If non-NULL, the IRBB under construction is handed to
+ this function, which presumably adds IR statements to it. The
+ callback may optionally complete the block and direct bb_to_IR
+ not to disassemble any instructions into it; this is indicated
+ by the callback returning True.
+
+ offB_TIADDR and offB_TILEN are the offsets of guest_TIADDR and
+ guest_TILEN. Since this routine has to work for any guest state,
+ without knowing what it is, those offsets have to passed in.
+
+ callback_opaque is a caller-supplied pointer to data which the
+ callbacks may want to see. Vex has no idea what it is.
+ (In fact it's a VgInstrumentClosure.)
*/
IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
+ /*IN*/ void* callback_opaque,
/*IN*/ DisOneInstrFn dis_instr_fn,
/*IN*/ UChar* guest_code,
/*IN*/ Addr64 guest_IP_bbstart,
- /*IN*/ Addr64 guest_IP_bbstart_noredir,
- /*IN*/ Bool (*chase_into_ok)(Addr64),
+ /*IN*/ Bool (*chase_into_ok)(void*,Addr64),
/*IN*/ Bool host_bigendian,
/*IN*/ VexArchInfo* archinfo_guest,
/*IN*/ IRType guest_word_type,
/*IN*/ Bool do_self_check,
- /*IN*/ Bool do_set_NRADDR,
+ /*IN*/ Bool (*preamble_function)(void*,IRBB*),
/*IN*/ Int offB_TISTART,
- /*IN*/ Int offB_TILEN,
- /*IN*/ Int offB_NRADDR )
+ /*IN*/ Int offB_TILEN )
{
Long delta;
Int i, n_instrs, first_stmt_idx;
IRBB* irbb;
Addr64 guest_IP_curr_instr;
IRConst* guest_IP_bbstart_IRConst = NULL;
- IRConst* guest_IP_bbstart_noredir_IRConst = NULL;
- Bool (*resteerOKfn)(Addr64) = NULL;
+ Bool (*resteerOKfn)(void*,Addr64) = NULL;
debug_print = toBool(vex_traceflags & VEX_TRACE_FE);
: IRConst_U64(guest_IP_bbstart);
}
- if (do_set_NRADDR) {
- guest_IP_bbstart_noredir_IRConst
- = guest_word_type==Ity_I32
- ? IRConst_U32(toUInt(guest_IP_bbstart_noredir))
- : IRConst_U64(guest_IP_bbstart_noredir);
- }
-
/* If asked to make a self-checking translation, leave 5 spaces
in which to put the check statements. We'll fill them in later
when we know the length and adler32 of the area to check. */
addStmtToIRBB( irbb, IRStmt_NoOp() );
}
- /* Set guest_NRADDR if asked to. This records the unredirected
- guest address of this bb, so that it can later be read (and so
- used by a function wrapper to get to the function itself. */
- if (do_set_NRADDR) {
- /* set guest_NRADDR to guest_IP_bbstart_noredir */
- addStmtToIRBB(
- irbb,
- IRStmt_Put( offB_NRADDR,
- IRExpr_Const(guest_IP_bbstart_noredir_IRConst))
- );
+ /* If the caller supplied a function to add its own preamble, use
+ it now. */
+ if (preamble_function) {
+ Bool stopNow = preamble_function( callback_opaque, irbb );
+ if (stopNow) {
+ /* The callback has completed the IR block without any guest
+ insns being disassembled into it, so just return it at
+ this point, even if a self-check was requested - as there
+ is nothing to self-check. The five self-check no-ops will
+ still be in place, but they are harmless. */
+ return irbb;
+ }
}
/* Process instructions. */
dres = dis_instr_fn ( irbb,
need_to_put_IP,
resteerOKfn,
+ callback_opaque,
guest_code,
delta,
guest_IP_curr_instr,
vassert(resteerOK);
vassert(irbb->next == NULL);
/* figure out a new delta to continue at. */
- vassert(resteerOKfn(dres.continueAt));
+ vassert(resteerOKfn(callback_opaque,dres.continueAt));
delta = dres.continueAt - guest_IP_bbstart;
/* we now have to start a new extent slot. */
vge->n_used++;
/*IN*/ Bool put_IP,
/* Return True iff resteering to the given addr is allowed */
- /*IN*/ Bool (*resteerOkFn) ( Addr64 ),
+ /*IN*/ Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
+
+ /* Vex-opaque data passed to all caller (valgrind) supplied
+ callbacks. */
+ /*IN*/ void* callback_opaque,
/* Where is the guest code? */
/*IN*/ UChar* guest_code,
/* See detailed comment in bb_to_IR.c. */
extern
IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
+ /*IN*/ void* closure_opaque,
/*IN*/ DisOneInstrFn dis_instr_fn,
/*IN*/ UChar* guest_code,
/*IN*/ Addr64 guest_IP_bbstart,
- /*IN*/ Addr64 guest_IP_bbstart_noredir,
- /*IN*/ Bool (*chase_into_ok)(Addr64),
+ /*IN*/ Bool (*chase_into_ok)(void*,Addr64),
/*IN*/ Bool host_bigendian,
/*IN*/ VexArchInfo* archinfo_guest,
/*IN*/ IRType guest_word_type,
/*IN*/ Bool do_self_check,
- /*IN*/ Bool do_set_NRADDR,
+ /*IN*/ Bool (*preamble_function)(void*,IRBB*),
/*IN*/ Int offB_TISTART,
- /*IN*/ Int offB_TILEN,
- /*IN*/ Int offB_NRADDR );
+ /*IN*/ Int offB_TILEN );
#endif /* ndef GENERIC_BB_TO_IR_H */
extern
DisResult disInstr_PPC ( IRBB* irbb,
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( void*, Addr64 ),
+ void* callback_opaque,
UChar* guest_code,
Long delta,
Addr64 guest_IP,
vassert(begin < 32);
vassert(end < 32);
UInt m1 = ((UInt)(-1)) << begin;
- UInt m2 = ((UInt)(-1)) << (end + 1);
+ UInt m2 = ((UInt)(-1)) << end << 1;
UInt mask = m1 ^ m2;
if (begin > end) mask = ~mask; // wrap mask
return mask;
vassert(begin < 64);
vassert(end < 64);
ULong m1 = ((ULong)(-1)) << begin;
- ULong m2 = ((ULong)(-1)) << (end + 1);
+ ULong m2 = ((ULong)(-1)) << end << 1;
ULong mask = m1 ^ m2;
if (begin > end) mask = ~mask; // wrap mask
return mask;
*/
static Bool dis_branch ( UInt theInstr,
/*OUT*/DisResult* dres,
- Bool (*resteerOkFn)(Addr64) )
+ Bool (*resteerOkFn)(void*,Addr64),
+ void* callback_opaque )
{
UChar opc1 = ifieldOPC(theInstr);
UChar BO = ifieldRegDS(theInstr);
if (flag_LK)
putGST( PPC_GST_LR, e_nia );
- if (resteerOkFn(tgt)) {
+ if (resteerOkFn( callback_opaque, tgt )) {
dres->whatNext = Dis_Resteer;
dres->continueAt = tgt;
} else {
static
DisResult disInstr_PPC_WRK (
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
+ void* callback_opaque,
Long delta64,
VexArchInfo* archinfo
)
/* Branch Instructions */
case 0x12: case 0x10: // b, bc
- if (dis_branch(theInstr, &dres, resteerOkFn)) goto decode_success;
+ if (dis_branch(theInstr, &dres, resteerOkFn, callback_opaque))
+ goto decode_success;
goto decode_failure;
/* System Linkage Instructions */
/* Branch Instructions */
case 0x210: case 0x010: // bcctr, bclr
- if (dis_branch(theInstr, &dres, resteerOkFn)) goto decode_success;
+ if (dis_branch(theInstr, &dres, resteerOkFn, callback_opaque))
+ goto decode_success;
goto decode_failure;
/* Memory Synchronization Instructions */
DisResult disInstr_PPC ( IRBB* irbb_IN,
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( void*, Addr64 ),
+ void* callback_opaque,
UChar* guest_code_IN,
Long delta,
Addr64 guest_IP,
guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta);
- dres = disInstr_PPC_WRK ( put_IP, resteerOkFn,
+ dres = disInstr_PPC_WRK ( put_IP, resteerOkFn, callback_opaque,
delta, archinfo );
return dres;
extern
DisResult disInstr_X86 ( IRBB* irbb,
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( void*, Addr64 ),
+ void* callback_opaque,
UChar* guest_code,
Long delta,
Addr64 guest_IP,
static
DisResult disInstr_X86_WRK (
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
+ void* callback_opaque,
Long delta64,
VexArchInfo* archinfo
)
assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
putIReg(4, R_ESP, mkexpr(t1));
storeLE( mkexpr(t1), mkU32(guest_EIP_bbstart+delta));
- if (resteerOkFn((Addr64)(Addr32)d32)) {
+ if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32 )) {
/* follow into the call target. */
dres.whatNext = Dis_Resteer;
dres.continueAt = (Addr64)(Addr32)d32;
case 0xEB: /* Jb (jump, byte offset) */
d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
delta++;
- if (resteerOkFn((Addr64)(Addr32)d32)) {
+ if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
dres.whatNext = Dis_Resteer;
dres.continueAt = (Addr64)(Addr32)d32;
} else {
vassert(sz == 4); /* JRS added 2004 July 11 */
d32 = (((Addr32)guest_EIP_bbstart)+delta+sz) + getSDisp(sz,delta);
delta += sz;
- if (resteerOkFn((Addr64)(Addr32)d32)) {
+ if (resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
dres.whatNext = Dis_Resteer;
dres.continueAt = (Addr64)(Addr32)d32;
} else {
case 0x7F: /* JGb/JNLEb (jump greater) */
d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
delta++;
- if (0 && resteerOkFn((Addr64)(Addr32)d32)) {
+ if (0 && resteerOkFn( callback_opaque, (Addr64)(Addr32)d32) ) {
/* Unused experimental hack: speculatively follow one arm
of a conditional branch. */
/* Assume the branch is taken. So we need to emit a
DisResult disInstr_X86 ( IRBB* irbb_IN,
Bool put_IP,
- Bool (*resteerOkFn) ( Addr64 ),
+ Bool (*resteerOkFn) ( void*, Addr64 ),
+ void* callback_opaque,
UChar* guest_code_IN,
Long delta,
Addr64 guest_IP,
guest_EIP_curr_instr = (Addr32)guest_IP;
guest_EIP_bbstart = (Addr32)toUInt(guest_IP - delta);
- dres = disInstr_X86_WRK ( put_IP, resteerOkFn,
+ dres = disInstr_X86_WRK ( put_IP, resteerOkFn, callback_opaque,
delta, archinfo );
return dres;
HInstrArray* vcode;
HInstrArray* rcode;
Int i, j, k, out_used, guest_sizeB;
- Int offB_TISTART, offB_TILEN, offB_NRADDR;
+ Int offB_TISTART, offB_TILEN;
UChar insn_bytes[32];
IRType guest_word_type;
IRType host_word_type;
offB_TISTART = 0;
offB_TILEN = 0;
mode64 = False;
- offB_NRADDR = 0;
vex_traceflags = vta->traceflags;
guest_layout = &x86guest_layout;
offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
- offB_NRADDR = offsetof(VexGuestX86State,guest_NRADDR);
vassert(vta->archinfo_guest.subarch == VexSubArchX86_sse0
|| vta->archinfo_guest.subarch == VexSubArchX86_sse1
|| vta->archinfo_guest.subarch == VexSubArchX86_sse2);
guest_layout = &amd64guest_layout;
offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
- offB_NRADDR = offsetof(VexGuestAMD64State,guest_NRADDR);
vassert(vta->archinfo_guest.subarch == VexSubArch_NONE);
vassert(0 == sizeof(VexGuestAMD64State) % 8);
vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
guest_layout = &armGuest_layout;
offB_TISTART = 0; /* hack ... arm has bitrot */
offB_TILEN = 0; /* hack ... arm has bitrot */
- offB_NRADDR = 0; /* hack ... arm has bitrot */
vassert(vta->archinfo_guest.subarch == VexSubArchARM_v4);
break;
guest_layout = &ppc32Guest_layout;
offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
- offB_NRADDR = offsetof(VexGuestPPC32State,guest_NRADDR);
vassert(vta->archinfo_guest.subarch == VexSubArchPPC32_I
|| vta->archinfo_guest.subarch == VexSubArchPPC32_FI
|| vta->archinfo_guest.subarch == VexSubArchPPC32_VFI);
|| vta->archinfo_guest.subarch == VexSubArchPPC64_VFI);
vassert(0 == sizeof(VexGuestPPC64State) % 16);
vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
- vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
+ vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
+ vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
break;
default:
"------------------------\n\n");
irbb = bb_to_IR ( vta->guest_extents,
+ vta->callback_opaque,
disInstrFn,
vta->guest_bytes,
vta->guest_bytes_addr,
- vta->guest_bytes_addr_noredir,
vta->chase_into_ok,
host_is_bigendian,
&vta->archinfo_guest,
guest_word_type,
vta->do_self_check,
- vta->do_set_NRADDR,
+ vta->preamble_function,
offB_TISTART,
- offB_TILEN,
- offB_NRADDR );
+ offB_TILEN );
vexAllocSanityCheck();
/* Get the thing instrumented. */
if (vta->instrument1)
- irbb = vta->instrument1(irbb, guest_layout,
- vta->guest_bytes_addr_noredir,
+ irbb = vta->instrument1(vta->callback_opaque,
+ irbb, guest_layout,
vta->guest_extents,
guest_word_type, host_word_type);
vexAllocSanityCheck();
if (vta->instrument2)
- irbb = vta->instrument2(irbb, guest_layout,
- vta->guest_bytes_addr_noredir,
+ irbb = vta->instrument2(vta->callback_opaque,
+ irbb, guest_layout,
vta->guest_extents,
guest_word_type, host_word_type);
VexArch arch_host;
VexArchInfo archinfo_host;
+ /* IN: an opaque value which is passed as the first arg to all
+ callback functions supplied in this struct. Vex has no idea
+ what's at the other end of this pointer. */
+ void* callback_opaque;
+
/* IN: the block to translate, and its guest address. */
/* where are the actual bytes in the host's address space? */
UChar* guest_bytes;
/* where do the bytes really come from in the guest's aspace?
- This is the post-redirection guest address. */
+ This is the post-redirection guest address. Not that Vex
+ understands anything about redirection; that is all done on
+ the Valgrind side. */
Addr64 guest_bytes_addr;
- /* where do the bytes claim to come from in the guest address
- space? (what guest entry point address do they correspond
- to?) This is the pre-redirection guest address. */
- Addr64 guest_bytes_addr_noredir;
/* Is it OK to chase into this guest address? May not be
NULL. */
- Bool (*chase_into_ok) ( Addr64 );
+ Bool (*chase_into_ok) ( /*callback_opaque*/void*, Addr64 );
/* OUT: which bits of guest code actually got translated */
VexGuestExtents* guest_extents;
/* IN: optionally, two instrumentation functions. May be
NULL. */
- IRBB* (*instrument1) ( IRBB*, VexGuestLayout*,
- Addr64, VexGuestExtents*,
+ IRBB* (*instrument1) ( /*callback_opaque*/void*,
+ IRBB*,
+ VexGuestLayout*,
+ VexGuestExtents*,
IRType gWordTy, IRType hWordTy );
- IRBB* (*instrument2) ( IRBB*, VexGuestLayout*,
- Addr64, VexGuestExtents*,
+ IRBB* (*instrument2) ( /*callback_opaque*/void*,
+ IRBB*,
+ VexGuestLayout*,
+ VexGuestExtents*,
IRType gWordTy, IRType hWordTy );
/* IN: should this translation be self-checking? default: False */
Bool do_self_check;
- /* IN: should this translation set guest_NRADDR? */
- Bool do_set_NRADDR;
+
+ /* IN: optionally, a callback which allows the caller to add its
+ own IR preamble following the self-check and any other
+ VEX-generated preamble, if any. May be NULL. If non-NULL,
+ the IRBB under construction is handed to this function, which
+ presumably adds IR statements to it. The callback may
+ optionally complete the block and direct bb_to_IR not to
+ disassemble any instructions into it; this is indicated by
+ the callback returning True.
+ */
+ Bool (*preamble_function)(/*callback_opaque*/void*, IRBB*);
/* IN: debug: trace vex activity at various points */
Int traceflags;
static IRBB* mc_instrument ( IRBB*, VexGuestLayout*, IRType, IRType );
#endif
-static Bool chase_into_not_ok ( Addr64 dst ) { return False; }
+static Bool chase_into_not_ok ( void* opaque, Addr64 dst ) { return False; }
int main ( int argc, char** argv )
{
#endif
vta.guest_bytes = origbuf;
vta.guest_bytes_addr = (Addr64)orig_addr;
- vta.guest_bytes_addr_noredir = (Addr64)orig_addr;
+ vta.callback_opaque = NULL;
vta.chase_into_ok = chase_into_not_ok;
vta.guest_extents = &vge;
vta.host_bytes = transbuf;
vta.instrument2 = NULL;
#endif
vta.do_self_check = False;
- vta.do_set_NRADDR = False;
+ vta.preamble_function = NULL;
vta.traceflags = TEST_FLAGS;
#if 1 /* x86, amd64 hosts */
vta.dispatch = (void*)0x12345678;