branch hereby becomes inactive.
git-svn-id: svn://svn.valgrind.org/vex/trunk@1536
initialise them anyway. */
vex_state->guest_TISTART = 0;
vex_state->guest_TILEN = 0;
+
+ vex_state->guest_NRADDR = 0;
}
sto{s,sb,sw,sd,sq}
xlat{,b} */
+/* "Special" instructions.
+
+ This instruction decoder can decode three special instructions
+ which mean nothing natively (are no-ops as far as regs/mem are
+ concerned) but have meaning for supporting Valgrind. A special
+ instruction is flagged by the 16-byte preamble 48C1C703 48C1C70D
+ 48C1C73D 48C1C733 (in the standard interpretation, that means: rolq
+ $3, %rdi; rolq $13, %rdi; rolq $61, %rdi; rolq $51, %rdi).
+ Following that, one of the following 3 are allowed (standard
+ interpretation in parentheses):
+
+ 4887DB (xchgq %rbx,%rbx) %RDX = client_request ( %RAX )
+ 4887C9 (xchgq %rcx,%rcx) %RAX = guest_NRADDR
+ 4887D2 (xchgq %rdx,%rdx) call-noredir *%RAX
+
+ Any other bytes following the 16-byte preamble are illegal and
+ constitute a failure in instruction decoding. This all assumes
+ that the preamble will never occur except in specific code
+ fragments designed for Valgrind to catch.
+
+ No prefixes may precede a "Special" instruction. */
+
/* Translates AMD64 code to IR. */
#include "libvex_basictypes.h"
#define OFFB_TISTART offsetof(VexGuestAMD64State,guest_TISTART)
#define OFFB_TILEN offsetof(VexGuestAMD64State,guest_TILEN)
+#define OFFB_NRADDR offsetof(VexGuestAMD64State,guest_NRADDR)
+
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
if (put_IP)
stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_curr_instr)) );
- /* Spot the client-request magic sequence. */
+ /* Spot "Special" instructions (see comment at top of file). */
{
UChar* code = (UChar*)(guest_code + delta);
- /* Spot this:
- C1C01D roll $29, %eax
- C1C003 roll $3, %eax
- C1C81B rorl $27, %eax
- C1C805 rorl $5, %eax
- C1C00D roll $13, %eax
- C1C013 roll $19, %eax
+ /* Spot the 16-byte preamble:
+ 48C1C703 rolq $3, %rdi
+ 48C1C70D rolq $13, %rdi
+ 48C1C73D rolq $61, %rdi
+ 48C1C733 rolq $51, %rdi
*/
- if (code[ 0] == 0xC1 && code[ 1] == 0xC0 && code[ 2] == 0x1D &&
- code[ 3] == 0xC1 && code[ 4] == 0xC0 && code[ 5] == 0x03 &&
- code[ 6] == 0xC1 && code[ 7] == 0xC8 && code[ 8] == 0x1B &&
- code[ 9] == 0xC1 && code[10] == 0xC8 && code[11] == 0x05 &&
- code[12] == 0xC1 && code[13] == 0xC0 && code[14] == 0x0D &&
- code[15] == 0xC1 && code[16] == 0xC0 && code[17] == 0x13
- ) {
- DIP("%%edx = client_request ( %%eax )\n");
- delta += 18;
- jmp_lit(Ijk_ClientReq, guest_RIP_bbstart+delta);
- dres.whatNext = Dis_StopHere;
- goto decode_success;
+ if (code[ 0] == 0x48 && code[ 1] == 0xC1 && code[ 2] == 0xC7
+ && code[ 3] == 0x03 &&
+ code[ 4] == 0x48 && code[ 5] == 0xC1 && code[ 6] == 0xC7
+ && code[ 7] == 0x0D &&
+ code[ 8] == 0x48 && code[ 9] == 0xC1 && code[10] == 0xC7
+ && code[11] == 0x3D &&
+ code[12] == 0x48 && code[13] == 0xC1 && code[14] == 0xC7
+ && code[15] == 0x33) {
+ /* Got a "Special" instruction preamble. Which one is it? */
+ if (code[16] == 0x48 && code[17] == 0x87
+ && code[18] == 0xDB /* xchgq %rbx,%rbx */) {
+ /* %RDX = client_request ( %RAX ) */
+ DIP("%%rdx = client_request ( %%rax )\n");
+ delta += 19;
+ jmp_lit(Ijk_ClientReq, guest_RIP_bbstart+delta);
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+ }
+ else
+ if (code[16] == 0x48 && code[17] == 0x87
+ && code[18] == 0xC9 /* xchgq %rcx,%rcx */) {
+ /* %RAX = guest_NRADDR */
+ DIP("%%rax = guest_NRADDR\n");
+ delta += 19;
+ putIRegRAX(8, IRExpr_Get( OFFB_NRADDR, Ity_I64 ));
+ goto decode_success;
+ }
+ else
+ if (code[16] == 0x48 && code[17] == 0x87
+ && code[18] == 0xD2 /* xchgq %rdx,%rdx */) {
+ /* call-noredir *%RAX */
+ DIP("call-noredir *%%rax\n");
+ delta += 19;
+ t1 = newTemp(Ity_I64);
+ assign(t1, getIRegRAX(8));
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
+ putIReg64(R_RSP, mkexpr(t2));
+ storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta));
+ jmp_treg(Ijk_NoRedir,t1);
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+ }
+ /* We don't know what it is. */
+ goto decode_failure;
+ /*NOTREACHED*/
}
}
__attribute((regparm(2)))
static UInt genericg_compute_adler32 ( HWord addr, HWord len );
+/* Small helpers */
+static Bool const_False ( Addr64 a ) { return False; }
-/* Disassemble a complete basic block, starting at guest_IP_bbstart,
+/* Disassemble a complete basic block, starting at guest_IP_start,
returning a new IRBB. The disassembler may chase across basic
block boundaries if it wishes and if chase_into_ok allows it.
The precise guest address ranges from which code has been taken
do_self_check indicates that the caller needs a self-checking
translation.
- 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.
-*/
+ do_set_NRADDR indicates that the unredirected guest address for
+ this BB should be written to the guest's NRADDR pseudo-register.
-static Bool const_False ( Addr64 a ) { return False; }
+ 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.
+*/
IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
/*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 host_bigendian,
/*IN*/ VexArchInfo* archinfo_guest,
/*IN*/ IRType guest_word_type,
/*IN*/ Bool do_self_check,
+ /*IN*/ Bool do_set_NRADDR,
/*IN*/ Int offB_TISTART,
- /*IN*/ Int offB_TILEN )
+ /*IN*/ Int offB_TILEN,
+ /*IN*/ Int offB_NRADDR )
{
Long delta;
Int i, n_instrs, first_stmt_idx;
Int selfcheck_idx = 0;
IRBB* irbb;
Addr64 guest_IP_curr_instr;
+ IRConst* guest_IP_bbstart_IRConst = NULL;
+ IRConst* guest_IP_bbstart_noredir_IRConst = NULL;
Bool (*resteerOKfn)(Addr64) = NULL;
delta = 0;
n_instrs = 0;
- /* If asked to make a self-checking translation, leave a 5 spaces
+ /* Guest addresses as IRConsts. Used in the two self-checks
+ generated. */
+ if (do_self_check) {
+ guest_IP_bbstart_IRConst
+ = guest_word_type==Ity_I32
+ ? IRConst_U32(toUInt(guest_IP_bbstart))
+ : 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. */
if (do_self_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))
+ );
+ }
+
/* Process instructions. */
while (True) {
vassert(n_instrs < vex_control.guest_max_insns);
vassert(dres.whatNext == Dis_StopHere
|| dres.whatNext == Dis_Continue
|| dres.whatNext == Dis_Resteer);
- vassert(dres.len >= 0 && dres.len <= 18);
+ vassert(dres.len >= 0 && dres.len <= 20);
if (dres.whatNext != Dis_Resteer)
vassert(dres.continueAt == 0);
if (do_self_check) {
UInt len2check, adler32;
- IRConst* guest_IP_bbstart_IRConst;
IRTemp tistart_tmp, tilen_tmp;
vassert(vge->n_used == 1);
adler32 = genericg_compute_adler32( (HWord)guest_code, len2check );
- guest_IP_bbstart_IRConst
- = guest_word_type==Ity_I32
- ? IRConst_U32(toUInt(guest_IP_bbstart))
- : IRConst_U64(guest_IP_bbstart);
-
/* 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. */
/*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 host_bigendian,
/*IN*/ VexArchInfo* archinfo_guest,
/*IN*/ IRType guest_word_type,
/*IN*/ Bool do_self_check,
+ /*IN*/ Bool do_set_NRADDR,
/*IN*/ Int offB_TISTART,
- /*IN*/ Int offB_TILEN );
+ /*IN*/ Int offB_TILEN,
+ /*IN*/ Int offB_NRADDR );
#endif /* ndef GENERIC_BB_TO_IR_H */
vex_state->guest_EMWARN = EmWarn_NONE;
+ vex_state->guest_RESVN = 0;
+
vex_state->guest_TISTART = 0;
vex_state->guest_TILEN = 0;
- vex_state->guest_RESVN = 0;
+ vex_state->guest_NRADDR = 0;
}
vex_state->guest_EMWARN = EmWarn_NONE;
+ vex_state->guest_RESVN = 0;
+
vex_state->guest_TISTART = 0;
vex_state->guest_TILEN = 0;
- vex_state->guest_RESVN = 0;
+ vex_state->guest_NRADDR = 0;
}
results would then be zeroed, too.
*/
+/* "Special" instructions.
+
+ This instruction decoder can decode three special instructions
+ which mean nothing natively (are no-ops as far as regs/mem are
+ concerned) but have meaning for supporting Valgrind. A special
+ instruction is flagged by the 16-byte preamble 54001800 54006800
+ 5400E800 54009800 (in the standard interpretation, that means:
+ rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0; rlwinm 0,0,29,0,0; rlwinm
+ 0,0,19,0,0). Following that, one of the following 3 are allowed
+ (standard interpretation in parentheses):
+
+ 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 )
+ 7C421378 (or 2,2,2) %R3 = guest_NRADDR
+ 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11
+
+ Any other bytes following the 16-byte preamble are illegal and
+ constitute a failure in instruction decoding. This all assumes
+ that the preamble will never occur except in specific code
+ fragments designed for Valgrind to catch.
+*/
+
/* Translates PPC32/64 code to IR. */
#define OFFB_TISTART offsetofPPCGuestState(guest_TISTART)
#define OFFB_TILEN offsetofPPCGuestState(guest_TILEN)
#define OFFB_RESVN offsetofPPCGuestState(guest_RESVN)
-
+#define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR)
/*------------------------------------------------------------*/
if (put_IP)
putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
- /* Spot the client-request magic sequence. */
- // Essentially a v. unlikely sequence of noops that we can catch
+ /* Spot "Special" instructions (see comment at top of file). */
if (mode64) {
/* Spot the magic sequence, 64-bit mode */
UChar* code = (UChar*)(&guest_code[delta]);
goto decode_success;
}
} else {
- /* Spot the magic sequence, 32-bit mode */
- UChar* code = (UChar*)(&guest_code[delta]);
-
- /* Spot this:
- 0x7C03D808 tw 0,3,27 => trap word if (0) => nop
- 0x5400E800 rlwinm 0,0,29,0,0 => r0 = rotl(r0,29)
- 0x54001800 rlwinm 0,0, 3,0,0 => r0 = rotl(r0, 3)
- 0x54006800 rlwinm 0,0,13,0,0 => r0 = rotl(r0,13)
- 0x54009800 rlwinm 0,0,19,0,0 => r0 = rotl(r0,19)
- 0x60000000 nop
+ UChar* code = (UChar*)(guest_code + delta);
+ /* Spot the 16-byte preamble:
+ 54001800 rlwinm 0,0,3,0,0
+ 54006800 rlwinm 0,0,13,0,0
+ 5400E800 rlwinm 0,0,29,0,0
+ 54009800 rlwinm 0,0,19,0,0
*/
- if (getUIntBigendianly(code+ 0) == 0x7C03D808 &&
- getUIntBigendianly(code+ 4) == 0x5400E800 &&
- getUIntBigendianly(code+ 8) == 0x54001800 &&
- getUIntBigendianly(code+12) == 0x54006800 &&
- getUIntBigendianly(code+16) == 0x54009800 &&
- getUIntBigendianly(code+20) == 0x60000000) {
- DIP("%%r3 = client_request ( %%r31 )\n");
- dres.len = 24;
- delta += 24;
-
- irbb->next = mkSzImm( ty, guest_CIA_bbstart + delta );
- irbb->jumpkind = Ijk_ClientReq;
- dres.whatNext = Dis_StopHere;
- goto decode_success;
+ if (getUIntBigendianly(code+ 0) == 0x54001800 &&
+ getUIntBigendianly(code+ 4) == 0x54006800 &&
+ getUIntBigendianly(code+ 8) == 0x5400E800 &&
+ getUIntBigendianly(code+12) == 0x54009800) {
+ /* Got a "Special" instruction preamble. Which one is it? */
+ if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
+ /* %R3 = client_request ( %R4 ) */
+ DIP("r3 = client_request ( %%r4 )\n");
+ delta += 20;
+ irbb->next = mkSzImm( ty, guest_CIA_bbstart + delta );
+ irbb->jumpkind = Ijk_ClientReq;
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+ }
+ else
+ if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
+ /* %R3 = guest_NRADDR */
+ DIP("r3 = guest_NRADDR\n");
+ delta += 20;
+ dres.len = 20;
+ putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
+ goto decode_success;
+ }
+ else
+ if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
+ /* branch-and-link-to-noredir %R11 */
+ DIP("branch-and-link-to-noredir r11\n");
+ delta += 20;
+ putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + delta) );
+ irbb->next = getIReg(11);
+ irbb->jumpkind = Ijk_NoRedir;
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+ }
+ /* We don't know what it is. Set opc1/opc2 so decode_failure
+ can print the insn following the Special-insn preamble. */
+ theInstr = getUIntBigendianly(code+16);
+ opc1 = ifieldOPC(theInstr);
+ opc2 = ifieldOPClo10(theInstr);
+ goto decode_failure;
+ /*NOTREACHED*/
}
}
/* All decode successes end up here. */
DIP("\n");
- dres.len = 4;
+ if (dres.len == 0) {
+ dres.len = 4;
+ } else {
+ vassert(dres.len == 20);
+ }
return dres;
}
/* SSE2 has a 'clflush' cache-line-invalidator which uses these. */
vex_state->guest_TISTART = 0;
vex_state->guest_TILEN = 0;
+
+ vex_state->guest_NRADDR = 0;
}
way through bbs as usual.
*/
+/* "Special" instructions.
+
+ This instruction decoder can decode three special instructions
+ which mean nothing natively (are no-ops as far as regs/mem are
+ concerned) but have meaning for supporting Valgrind. A special
+ instruction is flagged by the 12-byte preamble C1C703 C1C70D C1C71D
+ C1C713 (in the standard interpretation, that means: roll $3, %edi;
+ roll $13, %edi; roll $29, %edi; roll $19, %edi). Following that,
+ one of the following 3 are allowed (standard interpretation in
+ parentheses):
+
+ 87DB (xchgl %ebx,%ebx) %EDX = client_request ( %EAX )
+ 87C9 (xchgl %ecx,%ecx) %EAX = guest_NRADDR
+ 87D2 (xchgl %edx,%edx) call-noredir *%EAX
+
+ Any other bytes following the 12-byte preamble are illegal and
+ constitute a failure in instruction decoding. This all assumes
+ that the preamble will never occur except in specific code
+ fragments designed for Valgrind to catch.
+
+ No prefixes may precede a "Special" instruction.
+*/
+
+
/* Translates x86 code to IR. */
#include "libvex_basictypes.h"
#define OFFB_TISTART offsetof(VexGuestX86State,guest_TISTART)
#define OFFB_TILEN offsetof(VexGuestX86State,guest_TILEN)
+#define OFFB_NRADDR offsetof(VexGuestX86State,guest_NRADDR)
+
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
if (put_IP)
stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_EIP_curr_instr)) );
- /* Spot the client-request magic sequence. */
+ /* Spot "Special" instructions (see comment at top of file). */
{
UChar* code = (UChar*)(guest_code + delta);
- /* Spot this:
- C1C01D roll $29, %eax
- C1C003 roll $3, %eax
- C1C81B rorl $27, %eax
- C1C805 rorl $5, %eax
- C1C00D roll $13, %eax
- C1C013 roll $19, %eax
+ /* Spot the 12-byte preamble:
+ C1C703 roll $3, %edi
+ C1C70D roll $13, %edi
+ C1C71D roll $29, %edi
+ C1C713 roll $19, %edi
*/
- if (code[ 0] == 0xC1 && code[ 1] == 0xC0 && code[ 2] == 0x1D &&
- code[ 3] == 0xC1 && code[ 4] == 0xC0 && code[ 5] == 0x03 &&
- code[ 6] == 0xC1 && code[ 7] == 0xC8 && code[ 8] == 0x1B &&
- code[ 9] == 0xC1 && code[10] == 0xC8 && code[11] == 0x05 &&
- code[12] == 0xC1 && code[13] == 0xC0 && code[14] == 0x0D &&
- code[15] == 0xC1 && code[16] == 0xC0 && code[17] == 0x13
- ) {
- DIP("%%edx = client_request ( %%eax )\n");
- delta += 18;
- jmp_lit(Ijk_ClientReq, guest_EIP_bbstart+delta);
- dres.whatNext = Dis_StopHere;
- goto decode_success;
+ if (code[ 0] == 0xC1 && code[ 1] == 0xC7 && code[ 2] == 0x03 &&
+ code[ 3] == 0xC1 && code[ 4] == 0xC7 && code[ 5] == 0x0D &&
+ code[ 6] == 0xC1 && code[ 7] == 0xC7 && code[ 8] == 0x1D &&
+ code[ 9] == 0xC1 && code[10] == 0xC7 && code[11] == 0x13) {
+ /* Got a "Special" instruction preamble. Which one is it? */
+ if (code[12] == 0x87 && code[13] == 0xDB /* xchgl %ebx,%ebx */) {
+ /* %EDX = client_request ( %EAX ) */
+ DIP("%%edx = client_request ( %%eax )\n");
+ delta += 14;
+ jmp_lit(Ijk_ClientReq, guest_EIP_bbstart+delta);
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+ }
+ else
+ if (code[12] == 0x87 && code[13] == 0xC9 /* xchgl %ecx,%ecx */) {
+ /* %EAX = guest_NRADDR */
+ DIP("%%eax = guest_NRADDR\n");
+ delta += 14;
+ putIReg(4, R_EAX, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
+ goto decode_success;
+ }
+ else
+ if (code[12] == 0x87 && code[13] == 0xD2 /* xchgl %edx,%edx */) {
+ /* call-noredir *%EAX */
+ DIP("call-noredir *%%eax\n");
+ delta += 14;
+ t1 = newTemp(Ity_I32);
+ assign(t1, getIReg(4,R_EAX));
+ t2 = newTemp(Ity_I32);
+ assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
+ putIReg(4, R_ESP, mkexpr(t2));
+ storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta));
+ jmp_treg(Ijk_NoRedir,t1);
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+ }
+ /* We don't know what it is. */
+ goto decode_failure;
+ /*NOTREACHED*/
}
}
+ /* Deal with prefixes. */
/* Skip a LOCK prefix. */
/* 2005 Jan 06: the following insns are observed to sometimes
have a LOCK prefix:
case Ijk_TInval:
*p++ = 0xBD;
p = emit32(p, VEX_TRC_JMP_TINVAL); break;
+ case Ijk_NoRedir:
+ *p++ = 0xBD;
+ p = emit32(p, VEX_TRC_JMP_NOREDIR); break;
case Ijk_Ret:
case Ijk_Call:
case Ijk_Boring:
case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break;
case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break;
case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break;
+ case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break;
case Ijk_Ret:
case Ijk_Call:
case Ijk_Boring:
case Ijk_TInval:
*p++ = 0xBD;
p = emit32(p, VEX_TRC_JMP_TINVAL); break;
+ case Ijk_NoRedir:
+ *p++ = 0xBD;
+ p = emit32(p, VEX_TRC_JMP_NOREDIR); break;
case Ijk_Sys_sysenter:
*p++ = 0xBD;
p = emit32(p, VEX_TRC_JMP_SYS_SYSENTER); break;
case Ijk_NoDecode: vex_printf("NoDecode"); break;
case Ijk_MapFail: vex_printf("MapFail"); break;
case Ijk_TInval: vex_printf("Invalidate"); break;
+ case Ijk_NoRedir: vex_printf("NoRedir"); break;
case Ijk_Sys_syscall: vex_printf("Sys_syscall"); break;
case Ijk_Sys_int32: vex_printf("Sys_int32"); break;
case Ijk_Sys_int128: vex_printf("Sys_int128"); break;
HInstrArray* vcode;
HInstrArray* rcode;
Int i, j, k, out_used, guest_sizeB;
- Int offB_TISTART, offB_TILEN;
+ Int offB_TISTART, offB_TILEN, offB_NRADDR;
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);
vassert(0 == sizeof(VexGuestX86State) % 8);
- vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART ) == 4);
- vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
+ vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
+ vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
+ vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
break;
case VexArchAMD64:
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);
- vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
+ vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
+ vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
break;
case VexArchARM:
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);
vassert(0 == sizeof(VexGuestPPC32State) % 8);
vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
- vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
+ vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
+ vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
break;
case VexArchPPC64:
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,
offB_TISTART,
- offB_TILEN );
+ offB_TILEN,
+ offB_NRADDR );
vexAllocSanityCheck();
/* 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: debug: trace vex activity at various points */
Int traceflags;
extern
VexTranslateResult LibVEX_Translate ( VexTranslateArgs* );
-
/* A subtlety re interaction between self-checking translations and
bb-chasing. The supplied chase_into_ok function should say NO
(False) when presented with any address for which you might want to
ALL GUEST ARCHITECTURES
~~~~~~~~~~~~~~~~~~~~~~~
- The architecture must contain two pseudo-registers, guest_TISTART
+ The guest state must contain two pseudo-registers, guest_TISTART
and guest_TILEN. These are used to pass the address of areas of
guest code, translations of which are to be invalidated, back to
the despatcher. Both pseudo-regs must have size equal to the guest
word size.
+
+ The architecture must a third pseudo-register, guest_NRADDR, also
+ guest-word-sized. This is used to record the unredirected guest
+ address at the start of a translation whose start has been
+ redirected. By reading this pseudo-register shortly afterwards,
+ the translation can find out what the corresponding no-redirection
+ address was. Note, this is only set for wrap-style redirects, not
+ for replace-style ones.
*/
#endif /* ndef __LIBVEX_H */
ULong guest_TISTART;
ULong guest_TILEN;
+ /* Used to record the unredirected guest address at the start of
+ a translation whose start has been redirected. By reading
+ this pseudo-register shortly afterwards, the translation can
+ find out what the corresponding no-redirection address was.
+ Note, this is only set for wrap-style redirects, not for
+ replace-style ones. */
+ ULong guest_NRADDR;
+
/* Padding to make it have an 8-aligned size */
/* UInt padding; */
}
/* Emulation warnings */
/* 940 */ UInt guest_EMWARN;
- /* For icbi: record start and length of area to invalidate */
- /* 944 */ UInt guest_TISTART;
- /* 948 */ UInt guest_TILEN;
-
/* For lwarx/stwcx.: 0 == no reservation exists, non-0 == a
reservation exists. */
- /* 952 */ UInt guest_RESVN;
+ /* 944 */ UInt guest_RESVN;
+
+ /* For icbi: record start and length of area to invalidate */
+ /* 948 */ UInt guest_TISTART;
+ /* 952 */ UInt guest_TILEN;
+
+ /* Used to record the unredirected guest address at the start of
+ a translation whose start has been redirected. By reading
+ this pseudo-register shortly afterwards, the translation can
+ find out what the corresponding no-redirection address was.
+ Note, this is only set for wrap-style redirects, not for
+ replace-style ones. */
+ /* 956 */ UInt guest_NRADDR;
/* Padding to make it have an 8-aligned size */
/* 956 */ UInt padding;
reservation exists. */
/* 1104 */ ULong guest_RESVN;
- /* Padding to make it have an 16-aligned size */
- /* 1112 */ ULong padding2;
- /* 1120 */
+ /* Used to record the unredirected guest address at the start of
+ a translation whose start has been redirected. By reading
+ this pseudo-register shortly afterwards, the translation can
+ find out what the corresponding no-redirection address was.
+ Note, this is only set for wrap-style redirects, not for
+ replace-style ones. */
+ /* 1112 */ ULong guest_NRADDR;
+
+ /* Padding to make it have an 8-aligned size */
+ /* UInt padding; */
}
VexGuestPPC64State;
/* Emulation warnings */
UInt guest_EMWARN;
- /* Translation-invalidation area description. Not used on x86
- (there is no invalidate-icache insn), but needed so as to
- allow users of the library to uniformly assume that the guest
- state contains these two fields -- otherwise there is
- compilation breakage. On x86, these two fields are set to
- zero by LibVEX_GuestX86_initialise and then should be ignored
- forever thereafter. */
+ /* For clflush: record start and length of area to invalidate */
UInt guest_TISTART;
UInt guest_TILEN;
+ /* Used to record the unredirected guest address at the start of
+ a translation whose start has been redirected. By reading
+ this pseudo-register shortly afterwards, the translation can
+ find out what the corresponding no-redirection address was.
+ Note, this is only set for wrap-style redirects, not for
+ replace-style ones. */
+ UInt guest_NRADDR;
+
/* Padding to make it have an 8-aligned size */
- /* UInt padding; */
+ UInt padding;
}
VexGuestX86State;
Ijk_NoDecode, /* next instruction cannot be decoded */
Ijk_MapFail, /* Vex-provided address translation failed */
Ijk_TInval, /* Invalidate translations before continuing. */
+ Ijk_NoRedir, /* Jump to un-redirected guest addr */
/* Unfortunately, various guest-dependent syscall kinds. They
all mean: do a syscall before continuing. */
Ijk_Sys_syscall, /* amd64 'syscall', ppc 'sc' */
#define VEX_TRC_JMP_TINVAL 61 /* invalidate translations before
continuing */
+#define VEX_TRC_JMP_NOREDIR 81 /* jump to undirected guest addr */
#define VEX_TRC_JMP_EMWARN 63 /* deliver emulation warning before
continuing */
#define VEX_TRC_JMP_CLIENTREQ 65 /* do a client req before continuing */
vta.instrument2 = NULL;
#endif
vta.do_self_check = False;
+ vta.do_set_NRADDR = False;
vta.traceflags = TEST_FLAGS;
#if 1 /* x86, amd64 hosts */
vta.dispatch = (void*)0x12345678;