From: Julian Seward Date: Sun, 24 Oct 2004 22:31:25 +0000 (+0000) Subject: x86 guest: implement more convincing version of CPUID, using a dirty X-Git-Tag: svn/VALGRIND_3_0_1^2~925 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d0ffe0faec57ccf1a0918217c0d610bc3b714a87;p=thirdparty%2Fvalgrind.git x86 guest: implement more convincing version of CPUID, using a dirty helper to modify guest state. Fix the oversight that dirty helpers don't currently have access to guest state by passing a pointer to it as the first argument to all dirty helpers. git-svn-id: svn://svn.valgrind.org/vex/trunk@409 --- diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index 7dea804603..8ba9b31b3d 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -24,8 +24,9 @@ static UInt calculate_FXAM ( UInt tag, ULong dbl ); static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ); /* --- DIRTY HELPERS --- */ -static ULong loadF80le ( UInt ); -static void storeF80le ( UInt, ULong ); +static ULong loadF80le ( VexGuestX86State*, UInt ); +static void storeF80le ( VexGuestX86State*, UInt, ULong ); +static void dirtyhelper_CPUID ( VexGuestX86State* st ); /* This file contains helper functions for x86 guest code. @@ -617,6 +618,8 @@ Addr64 x86guest_findhelper ( Char* function_name ) return (Addr64)(Addr32)(& loadF80le); if (vex_streq(function_name, "calculate_RCR")) return (Addr64)(Addr32)(& calculate_RCR); + if (vex_streq(function_name, "dirtyhelper_CPUID")) + return (Addr64)(Addr32)(& dirtyhelper_CPUID); vex_printf("\nx86 guest: can't find helper: %s\n", function_name); vpanic("x86guest_findhelper"); } @@ -1195,7 +1198,7 @@ static void convert_f80le_to_f64le ( /*IN*/UChar* f80, /*OUT*/UChar* f64 ) /* CALLED FROM GENERATED CODE */ /* DIRTY HELPER (reads guest memory) */ -static ULong loadF80le ( UInt addrU ) +static ULong loadF80le ( VexGuestX86State* st, UInt addrU ) { ULong f64; convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 ); @@ -1204,7 +1207,7 @@ static ULong loadF80le ( UInt addrU ) /* CALLED FROM GENERATED CODE */ /* DIRTY HELPER (writes guest memory) */ -static void storeF80le ( UInt addrU, ULong f64 ) +static void storeF80le ( VexGuestX86State* st, UInt addrU, ULong f64 ) { convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU ); } @@ -1417,7 +1420,25 @@ static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz ) return (((ULong)eflags_in) << 32) | ((ULong)arg); } + +/* CALLED FROM GENERATED CODE */ +/* DIRTY HELPER (modifies guest state) */ +/* Claim to be a P54C P133 (pre-MMX Pentium) */ +static void dirtyhelper_CPUID ( VexGuestX86State* st ) +{ + if (st->guest_EAX == 0) { + st->guest_EAX = 0x1; + st->guest_EBX = 0x756e6547; + st->guest_ECX = 0x6c65746e; + st->guest_EDX = 0x49656e69; + } else { + st->guest_EAX = 0x52b; + st->guest_EBX = 0x0; + st->guest_ECX = 0x0; + st->guest_EDX = 0x1bf; + } +} + /*---------------------------------------------------------------*/ /*--- end guest-x86/ghelpers.c ---*/ /*---------------------------------------------------------------*/ - diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 181cbd5a38..77febb5759 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -211,6 +211,9 @@ IRBB* bbToIR_X86Instr ( UChar* x86code, #define OFFB_FPREGS offsetof(VexGuestX86State,guest_FPREG[0]) #define OFFB_FPTAGS offsetof(VexGuestX86State,guest_FPTAG[0]) #define OFFB_EAX offsetof(VexGuestX86State,guest_EAX) +#define OFFB_EBX offsetof(VexGuestX86State,guest_EBX) +#define OFFB_ECX offsetof(VexGuestX86State,guest_ECX) +#define OFFB_EDX offsetof(VexGuestX86State,guest_EDX) #define OFFB_CC_OP offsetof(VexGuestX86State,guest_CC_OP) #define OFFB_CC_SRC offsetof(VexGuestX86State,guest_CC_SRC) #define OFFB_CC_DST offsetof(VexGuestX86State,guest_CC_DST) @@ -3981,8 +3984,9 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) break; case 5: { /* FLD extended-real */ - /* Uses dirty helper: ULong loadF80le ( UInt ) */ - /* addr holds the address. First, do a dirty call to + /* Uses dirty helper: + ULong loadF80le ( VexGuestX86State*, UInt ) + addr holds the address. First, do a dirty call to get hold of the data. */ /* give details of args, and where to call */ IRDirty* d; @@ -8858,13 +8862,41 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, //-- /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */ - case 0xA2: /* CPUID */ - vex_printf("vex x86->IR: hacked CPUID\n"); - putIReg(4, R_EAX, mkU32(0)); - putIReg(4, R_EBX, mkU32(0x756e6547)); - putIReg(4, R_ECX, mkU32(0x49656e69)); - putIReg(4, R_EDX, mkU32(0x6c65746e)); + case 0xA2: { /* CPUID */ + /* Uses dirty helper: + void dirtyhelper_CPUID ( VexGuestX86State* ) + declared to mod eax, wr ebx, ecx, edx + */ + /* give details of args, and where to call */ + IRDirty* d; + d = emptyIRDirty(); + d->name = "dirtyhelper_CPUID"; + d->args = LibVEX_Alloc(1 * sizeof(IRTemp)); + d->args[0] = NULL; + d->tmp = INVALID_IRTEMP; + /* declare that we're not accessing memory */ + d->mFx = Ifx_None; + d->mAddr = NULL; + d->mSize = 0; + /* declare guest state effects */ + d->nFxState = 4; + d->fxState[0].fx = Ifx_Modify; + d->fxState[0].offset = OFFB_EAX; + d->fxState[0].size = 4; + d->fxState[1].fx = Ifx_Write; + d->fxState[1].offset = OFFB_EBX; + d->fxState[1].size = 4; + d->fxState[2].fx = Ifx_Write; + d->fxState[2].offset = OFFB_ECX; + d->fxState[2].size = 4; + d->fxState[3].fx = Ifx_Write; + d->fxState[3].offset = OFFB_EDX; + d->fxState[3].size = 4; + /* execute the dirty call, side-effecting guest state */ + stmt( IRStmt_Dirty(d) ); break; + } + //-- if (!VG_(cpu_has_feature)(VG_X86_FEAT_CPUID)) //-- goto decode_failure; //-- diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index 37d26a9d2d..be4436cb27 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -2134,6 +2134,11 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) for (i = n_args-1; i >= 0; i--) n_arg_ws += pushArg(env, d->args[i]); + /* and finally the leftmost argument, the guest state pointer, + which is in %ebp. */ + addInstr(env, X86Instr_Push(X86RMI_Reg(hregX86_EBP()))); + n_arg_ws++; + /* call the helper, and get the args off the stack afterwards. */ callHelperAndClearArgs( env, d->name, n_arg_ws );