From: Julian Seward Date: Fri, 1 Jun 2012 16:09:50 +0000 (+0000) Subject: Enhance the guest state effects notation on IRDirty calls, so as to be X-Git-Tag: svn/VALGRIND_3_8_1^2~116 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6dfc911254040d69825036816dd2f8d0673b374b;p=thirdparty%2Fvalgrind.git Enhance the guest state effects notation on IRDirty calls, so as to be able to describe accesses to arrays of non-consecutive guest state sections. This is needed to describe the behaviour of FXSAVE and FXRSTOR in an environment where we also support AVX. The IRDirty struct has got smaller (112 bytes vs 136 before, for a 64 bit target) whilst holding more information. The new facility is then used to describe said FXSAVE and FXRSTOR on amd64. For x86 there is no change since we don't model AVX state for x86. git-svn-id: svn://svn.valgrind.org/vex/trunk@2362 --- diff --git a/VEX/priv/guest_amd64_toIR.c b/VEX/priv/guest_amd64_toIR.c index 1896b9cfa5..68760684b3 100644 --- a/VEX/priv/guest_amd64_toIR.c +++ b/VEX/priv/guest_amd64_toIR.c @@ -5174,6 +5174,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok, /* declare we're writing guest state */ d->nFxState = 4; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = OFFB_FTOP; @@ -5270,6 +5271,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok, /* declare we're reading guest state */ d->nFxState = 4; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Read; d->fxState[0].offset = OFFB_FTOP; @@ -5927,6 +5929,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok, /* declare we're writing guest state */ d->nFxState = 5; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = OFFB_FTOP; @@ -6150,6 +6153,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok, /* declare we're writing guest state */ d->nFxState = 5; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = OFFB_FTOP; @@ -6227,6 +6231,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok, /* declare we're reading guest state */ d->nFxState = 5; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Read; d->fxState[0].offset = OFFB_FTOP; @@ -11850,10 +11855,11 @@ Long dis_ESC_0F__SSE2 ( Bool* decode_OK, /* declare we're writing memory */ d->mFx = Ifx_Write; d->mAddr = mkexpr(addr); - d->mSize = 512; + d->mSize = 464; /* according to recent Intel docs */ /* declare we're reading guest state */ d->nFxState = 7; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Read; d->fxState[0].offset = OFFB_FTOP; @@ -11877,15 +11883,18 @@ Long dis_ESC_0F__SSE2 ( Bool* decode_OK, d->fxState[5].fx = Ifx_Read; d->fxState[5].offset = OFFB_YMM0; - d->fxState[5].size = 16 * sizeof(U128); + d->fxState[5].size = sizeof(U128); + /* plus 15 more of the above, spaced out in YMM sized steps */ + d->fxState[5].nRepeats = 15; + d->fxState[5].repeatLen = sizeof(U256); d->fxState[6].fx = Ifx_Read; d->fxState[6].offset = OFFB_SSEROUND; d->fxState[6].size = sizeof(ULong); /* Be paranoid ... this assertion tries to ensure the 16 %ymm - images are packed back-to-back. If not, the value of - d->fxState[5].size is wrong. */ + images are packed back-to-back. If not, the settings for + d->fxState[5] are wrong. */ vassert(32 == sizeof(U256)); vassert(OFFB_YMM15 == (OFFB_YMM0 + 15 * 32)); @@ -11925,10 +11934,11 @@ Long dis_ESC_0F__SSE2 ( Bool* decode_OK, /* declare we're reading memory */ d->mFx = Ifx_Read; d->mAddr = mkexpr(addr); - d->mSize = 512; + d->mSize = 464; /* according to recent Intel docs */ /* declare we're writing guest state */ d->nFxState = 7; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = OFFB_FTOP; @@ -11952,15 +11962,18 @@ Long dis_ESC_0F__SSE2 ( Bool* decode_OK, d->fxState[5].fx = Ifx_Write; d->fxState[5].offset = OFFB_YMM0; - d->fxState[5].size = 16 * sizeof(U128); + d->fxState[5].size = sizeof(U128); + /* plus 15 more of the above, spaced out in YMM sized steps */ + d->fxState[5].nRepeats = 15; + d->fxState[5].repeatLen = sizeof(U256); d->fxState[6].fx = Ifx_Write; d->fxState[6].offset = OFFB_SSEROUND; d->fxState[6].size = sizeof(ULong); /* Be paranoid ... this assertion tries to ensure the 16 %ymm - images are packed back-to-back. If not, the value of - d->fxState[5].size is wrong. */ + images are packed back-to-back. If not, the settings for + d->fxState[5] are wrong. */ vassert(32 == sizeof(U256)); vassert(OFFB_YMM15 == (OFFB_YMM0 + 15 * 32)); @@ -15399,6 +15412,7 @@ Long dis_ESC_0F38__SSE4 ( Bool* decode_OK, this roundabout scheme. */ d->needsBBP = True; d->nFxState = 2; + vex_bzero(&d->fxState, sizeof(d->fxState)); /* AES{ENC,ENCLAST,DEC,DECLAST} read both registers, and writes the second. AESIMC (0xDB) reads the first register, and writes the second. */ @@ -15644,6 +15658,7 @@ static Long dis_PCMPxSTRx ( VexAbiInfo* vbi, Prefix pfx, roundabout scheme. */ d->needsBBP = True; d->nFxState = 2; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Read; d->fxState[0].offset = gstOffL; d->fxState[0].size = sizeof(U128); @@ -16826,6 +16841,7 @@ Long dis_ESC_0F3A__SSE4 ( Bool* decode_OK, this roundabout scheme. */ d->needsBBP = True; d->nFxState = 2; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Read; d->fxState[0].offset = gstOffL; d->fxState[0].size = sizeof(U128); @@ -18656,6 +18672,7 @@ Long dis_ESC_0F ( /* declare guest state effects */ d->needsBBP = True; d->nFxState = 4; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Modify; d->fxState[0].offset = OFFB_RAX; d->fxState[0].size = 8; diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index d4ee47d85b..54a2c4d39d 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -12801,6 +12801,7 @@ static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr ) /* declare guest state effects */ d->needsBBP = True; d->nFxState = 1; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = vD_off; d->fxState[0].size = sizeof(U128); @@ -12834,6 +12835,7 @@ static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr ) /* declare guest state effects */ d->needsBBP = True; d->nFxState = 1; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = vD_off; d->fxState[0].size = sizeof(U128); diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 4cc4a159d4..17d31b3ad2 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -2120,10 +2120,12 @@ s390_irgen_00(UChar r1 __attribute__((unused)), mkIRExprVec_0()); d->needsBBP = 1; /* Need to pass pointer to guest state to helper */ + d->nFxState = 1; + vex_bzero(&d->fxState, sizeof(d->fxState)); + d->fxState[0].fx = Ifx_Modify; /* read then write */ d->fxState[0].offset = S390X_GUEST_OFFSET(guest_IA); d->fxState[0].size = sizeof(ULong); - d->nFxState = 1; stmt(IRStmt_Dirty(d)); @@ -10779,10 +10781,12 @@ s390_irgen_STFLE(IRTemp op2addr) d->needsBBP = 1; /* Need to pass pointer to guest state to helper */ + d->nFxState = 1; + vex_bzero(&d->fxState, sizeof(d->fxState)); + d->fxState[0].fx = Ifx_Modify; /* read then write */ d->fxState[0].offset = S390X_GUEST_OFFSET(guest_r0); d->fxState[0].size = sizeof(ULong); - d->nFxState = 1; d->mAddr = mkexpr(op2addr); /* Pretend all double words are written */ diff --git a/VEX/priv/guest_x86_toIR.c b/VEX/priv/guest_x86_toIR.c index 5cbb244ee6..2cbe442f58 100644 --- a/VEX/priv/guest_x86_toIR.c +++ b/VEX/priv/guest_x86_toIR.c @@ -3954,6 +3954,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) /* declare we're writing guest state */ d->nFxState = 4; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = OFFB_FTOP; @@ -4049,6 +4050,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) /* declare we're reading guest state */ d->nFxState = 4; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Read; d->fxState[0].offset = OFFB_FTOP; @@ -4738,6 +4740,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) /* declare we're writing guest state */ d->nFxState = 5; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = OFFB_FTOP; @@ -4942,6 +4945,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) /* declare we're writing guest state */ d->nFxState = 5; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = OFFB_FTOP; @@ -5000,6 +5004,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta ) /* declare we're reading guest state */ d->nFxState = 5; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Read; d->fxState[0].offset = OFFB_FTOP; @@ -8138,10 +8143,11 @@ DisResult disInstr_X86_WRK ( /* declare we're writing memory */ d->mFx = Ifx_Write; d->mAddr = mkexpr(addr); - d->mSize = 512; + d->mSize = 464; /* according to recent Intel docs */ /* declare we're reading guest state */ d->nFxState = 7; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Read; d->fxState[0].offset = OFFB_FTOP; @@ -8212,10 +8218,11 @@ DisResult disInstr_X86_WRK ( /* declare we're reading memory */ d->mFx = Ifx_Read; d->mAddr = mkexpr(addr); - d->mSize = 512; + d->mSize = 464; /* according to recent Intel docs */ /* declare we're writing guest state */ d->nFxState = 7; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Write; d->fxState[0].offset = OFFB_FTOP; @@ -14608,6 +14615,7 @@ DisResult disInstr_X86_WRK ( /* declare guest state effects */ d->needsBBP = True; d->nFxState = 4; + vex_bzero(&d->fxState, sizeof(d->fxState)); d->fxState[0].fx = Ifx_Modify; d->fxState[0].offset = OFFB_EAX; d->fxState[0].size = 4; diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c index 76173d2405..a4696328c6 100644 --- a/VEX/priv/host_s390_isel.c +++ b/VEX/priv/host_s390_isel.c @@ -2419,6 +2419,9 @@ s390_isel_stmt(ISelEnv *env, IRStmt *stmt) /* Invalidate tracked values of those guest state registers that are modified by this helper. */ for (i = 0; i < d->nFxState; ++i) { + /* JRS 1 June 2012: AFAICS, s390 guest doesn't use 'repeat' + descriptors in guest state effect descriptions. Hence: */ + vassert(d->fxState[i].nRepeats == 0 && d->fxState[i].repeatLen == 0); if ((d->fxState[i].fx == Ifx_Write || d->fxState[i].fx == Ifx_Modify)) { Int guest_reg = get_guest_reg(d->fxState[i].offset); if (guest_reg != GUEST_UNKNOWN) diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c index 502fc20fec..8571bdff16 100644 --- a/VEX/priv/ir_defs.c +++ b/VEX/priv/ir_defs.c @@ -1120,7 +1120,13 @@ void ppIRDirty ( IRDirty* d ) for (i = 0; i < d->nFxState; i++) { vex_printf(" "); ppIREffect(d->fxState[i].fx); - vex_printf("-gst(%d,%d)", d->fxState[i].offset, d->fxState[i].size); + vex_printf("-gst(%u,%u", (UInt)d->fxState[i].offset, + (UInt)d->fxState[i].size); + if (d->fxState[i].nRepeats > 0) { + vex_printf(",reps%u,step%u", (UInt)d->fxState[i].nRepeats, + (UInt)d->fxState[i].repeatLen); + } + vex_printf(")"); } vex_printf(" ::: "); ppIRCallee(d->cee); @@ -3567,6 +3573,15 @@ void tcStmt ( IRSB* bb, IRStmt* stmt, IRType gWordTy ) for (i = 0; i < d->nFxState; i++) { if (d->fxState[i].fx == Ifx_None) goto bad_dirty; if (d->fxState[i].size <= 0) goto bad_dirty; + if (d->fxState[i].nRepeats == 0) { + if (d->fxState[i].repeatLen != 0) goto bad_dirty; + } else { + if (d->fxState[i].repeatLen <= d->fxState[i].size) + goto bad_dirty; + /* the % is safe because of the .size check above */ + if ((d->fxState[i].repeatLen % d->fxState[i].size) != 0) + goto bad_dirty; + } } /* check types, minimally */ if (d->guard == NULL) goto bad_dirty; diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c index a65867d982..b3ab987b03 100644 --- a/VEX/priv/main_main.c +++ b/VEX/priv/main_main.c @@ -147,6 +147,7 @@ void LibVEX_Init ( vassert(8 == sizeof(Addr64)); vassert(16 == sizeof(U128)); vassert(16 == sizeof(V128)); + vassert(32 == sizeof(U256)); vassert(sizeof(void*) == 4 || sizeof(void*) == 8); vassert(sizeof(void*) == sizeof(int*)); diff --git a/VEX/priv/main_util.c b/VEX/priv/main_util.c index 618254b69a..7630d02513 100644 --- a/VEX/priv/main_util.c +++ b/VEX/priv/main_util.c @@ -254,6 +254,15 @@ Bool vex_streq ( const HChar* s1, const HChar* s2 ) } } +void vex_bzero ( void* sV, UInt n ) +{ + UInt i; + UChar* s = (UChar*)sV; + /* No laughing, please. Just don't call this too often. Thank you + for your attention. */ + for (i = 0; i < n; i++) s[i] = 0; +} + /* Convert N0 into ascii in BUF, which is assumed to be big enough (at least 67 bytes long). Observe BASE, SYNED and HEXCAPS. */ diff --git a/VEX/priv/main_util.h b/VEX/priv/main_util.h index 914dc64efb..6a2e6daf8d 100644 --- a/VEX/priv/main_util.h +++ b/VEX/priv/main_util.h @@ -75,7 +75,8 @@ extern UInt vex_sprintf ( HChar* buf, HChar *format, ... ); /* String ops */ extern Bool vex_streq ( const HChar* s1, const HChar* s2 ); -extern Int vex_strlen ( const HChar* str ); +extern Int vex_strlen ( const HChar* str ); +extern void vex_bzero ( void* s, UInt n ); /* Storage management: clear the area, and allocate from it. */ diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index ed5961732a..f88a094a96 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -1870,7 +1870,7 @@ extern void ppIRJumpKind ( IRJumpKind ); /* Effects on resources (eg. registers, memory locations) */ typedef enum { - Ifx_None = 0x17000, /* no effect */ + Ifx_None = 0x1700, /* no effect */ Ifx_Read, /* reads the resource */ Ifx_Write, /* writes the resource */ Ifx_Modify, /* modifies the resource */ @@ -1882,7 +1882,7 @@ extern void ppIREffect ( IREffect ); typedef - struct { + struct _IRDirty { /* What to call, and details of args/results */ IRCallee* cee; /* where to call */ IRExpr* guard; /* :: Ity_Bit. Controls whether call happens */ @@ -1898,10 +1898,26 @@ typedef Bool needsBBP; /* True => also pass guest state ptr to callee */ Int nFxState; /* must be 0 .. VEX_N_FXSTATE */ struct { - IREffect fx; /* read, write or modify? Ifx_None is invalid. */ - Int offset; - Int size; + IREffect fx:16; /* read, write or modify? Ifx_None is invalid. */ + UShort offset; + UShort size; + UChar nRepeats; + UChar repeatLen; } fxState[VEX_N_FXSTATE]; + /* The access can be repeated, as specified by nRepeats and + repeatLen. To describe only a single access, nRepeats and + repeatLen should be zero. Otherwise, repeatLen must be a + multiple of size and greater than size. */ + /* Overall, the parts of the guest state denoted by (offset, + size, nRepeats, repeatLen) is + [offset, +size) + and, if nRepeats > 0, + for (i = 1; i <= nRepeats; i++) + [offset + i * repeatLen, +size) + A convenient way to enumerate all segments is therefore + for (i = 0; i < 1 + nRepeats; i++) + [offset + i * repeatLen, +size) + */ } IRDirty; @@ -2051,6 +2067,7 @@ extern IRPutI* mkIRPutI ( IRRegArray* descr, IRExpr* ix, extern IRPutI* deepCopyIRPutI ( IRPutI* ); + /* ------------------ Statements ------------------ */ /* The different kinds of statements. Their meaning is explained