From 07611f4dbd4f725e3e23c45fc7b4889e28b0b5fc Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Sat, 6 Aug 2005 11:45:02 +0000 Subject: [PATCH] Track the status of the %EFLAGS.AC (alignment check) bit, but otherwise ignore it. This fixes a crash induced by incorrect CPU identification. git-svn-id: svn://svn.valgrind.org/vex/trunk@1319 --- VEX/priv/guest-x86/ghelpers.c | 40 ++++++++++++++++------------- VEX/priv/guest-x86/toIR.c | 48 ++++++++++++++++++++++++++++++++--- VEX/priv/main/vex_main.c | 2 ++ VEX/pub/libvex.h | 2 +- VEX/pub/libvex_emwarn.h | 3 +++ VEX/pub/libvex_guest_x86.h | 17 +++++++++---- 6 files changed, 85 insertions(+), 27 deletions(-) diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index ef3b4baa0d..db3487f11a 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -737,6 +737,8 @@ UInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state ) eflags |= (1<<10); if (vex_state->guest_IDFLAG == 1) eflags |= (1<<21); + if (vex_state->guest_ACFLAG == 1) + eflags |= (1<<18); return eflags; } @@ -1973,6 +1975,7 @@ void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ) vex_state->guest_CC_NDEP = 0; vex_state->guest_DFLAG = 1; /* forwards */ vex_state->guest_IDFLAG = 0; + vex_state->guest_ACFLAG = 0; vex_state->guest_EIP = 0; @@ -2072,7 +2075,7 @@ VexGuestLayout /* Describe any sections to be regarded by Memcheck as 'always-defined'. */ - .n_alwaysDefd = 21, + .n_alwaysDefd = 22, /* flags thunk: OP and NDEP are always defd, whereas DEP1 and DEP2 have to be tracked. See detailed comment in @@ -2082,23 +2085,24 @@ VexGuestLayout /* 1 */ ALWAYSDEFD(guest_CC_NDEP), /* 2 */ ALWAYSDEFD(guest_DFLAG), /* 3 */ ALWAYSDEFD(guest_IDFLAG), - /* 4 */ ALWAYSDEFD(guest_EIP), - /* 5 */ ALWAYSDEFD(guest_FTOP), - /* 6 */ ALWAYSDEFD(guest_FPTAG), - /* 7 */ ALWAYSDEFD(guest_FPROUND), - /* 8 */ ALWAYSDEFD(guest_FC3210), - /* 9 */ ALWAYSDEFD(guest_CS), - /* 10 */ ALWAYSDEFD(guest_DS), - /* 11 */ ALWAYSDEFD(guest_ES), - /* 12 */ ALWAYSDEFD(guest_FS), - /* 13 */ ALWAYSDEFD(guest_GS), - /* 14 */ ALWAYSDEFD(guest_SS), - /* 15 */ ALWAYSDEFD(guest_LDT), - /* 16 */ ALWAYSDEFD(guest_GDT), - /* 17 */ ALWAYSDEFD(guest_EMWARN), - /* 18 */ ALWAYSDEFD(guest_SSEROUND), - /* 19 */ ALWAYSDEFD(guest_TISTART), - /* 20 */ ALWAYSDEFD(guest_TILEN) + /* 4 */ ALWAYSDEFD(guest_ACFLAG), + /* 5 */ ALWAYSDEFD(guest_EIP), + /* 6 */ ALWAYSDEFD(guest_FTOP), + /* 7 */ ALWAYSDEFD(guest_FPTAG), + /* 8 */ ALWAYSDEFD(guest_FPROUND), + /* 9 */ ALWAYSDEFD(guest_FC3210), + /* 10 */ ALWAYSDEFD(guest_CS), + /* 11 */ ALWAYSDEFD(guest_DS), + /* 12 */ ALWAYSDEFD(guest_ES), + /* 13 */ ALWAYSDEFD(guest_FS), + /* 14 */ ALWAYSDEFD(guest_GS), + /* 15 */ ALWAYSDEFD(guest_SS), + /* 16 */ ALWAYSDEFD(guest_LDT), + /* 17 */ ALWAYSDEFD(guest_GDT), + /* 18 */ ALWAYSDEFD(guest_EMWARN), + /* 19 */ ALWAYSDEFD(guest_SSEROUND), + /* 20 */ ALWAYSDEFD(guest_TISTART), + /* 21 */ ALWAYSDEFD(guest_TILEN) } }; diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 4976847c15..d8e8ba90f4 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -81,6 +81,13 @@ only way to observe eflags[1], a proper fix would be to make that bit be set by PUSHF. + The state of %eflags.AC (alignment check, bit 18) is recorded by + the simulation (viz, if you set it with popf then a pushf produces + the value you set it to), but it is otherwise ignored. In + particular, setting it to 1 does NOT cause alignment checking to + happen. Programs that set it to 1 and then rely on the resulting + SIGBUSs to inform them of misaligned accesses will not work. + This module uses global variables and so is not MT-safe (if that should ever become relevant). @@ -181,6 +188,7 @@ static IRBB* irbb; #define OFFB_FPTAGS offsetof(VexGuestX86State,guest_FPTAG[0]) #define OFFB_DFLAG offsetof(VexGuestX86State,guest_DFLAG) #define OFFB_IDFLAG offsetof(VexGuestX86State,guest_IDFLAG) +#define OFFB_ACFLAG offsetof(VexGuestX86State,guest_ACFLAG) #define OFFB_FTOP offsetof(VexGuestX86State,guest_FTOP) #define OFFB_FC3210 offsetof(VexGuestX86State,guest_FC3210) #define OFFB_FPROUND offsetof(VexGuestX86State,guest_FPROUND) @@ -10944,7 +10952,7 @@ DisResult disInstr_X86_WRK ( mkU32(0xFFFFFFFF))) ); - /* And set the ID flag */ + /* Set the ID flag */ stmt( IRStmt_Put( OFFB_IDFLAG, IRExpr_Mux0X( @@ -10956,6 +10964,30 @@ DisResult disInstr_X86_WRK ( mkU32(1))) ); + /* And set the AC flag. If setting it 1 to, emit an emulation + warning. */ + stmt( IRStmt_Put( + OFFB_ACFLAG, + IRExpr_Mux0X( + unop(Iop_32to8, + binop(Iop_And32, + binop(Iop_Shr32, mkexpr(t1), mkU8(18)), + mkU32(1))), + mkU32(0), + mkU32(1))) + ); + + put_emwarn( mkU32(EmWarn_X86_acFlag) ); + stmt( + IRStmt_Exit( + binop( Iop_CmpNE32, + binop(Iop_And32, mkexpr(t1), mkU32(1<<18)), + mkU32(0) ), + Ijk_EmWarn, + IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta) + ) + ); + DIP("popf%c\n", nameISize(sz)); break; @@ -11100,11 +11132,21 @@ DisResult disInstr_X86_WRK ( mkU32(1<<21))) ); + /* And patch in the AC flag. */ + t5 = newTemp(Ity_I32); + assign( t5, binop(Iop_Or32, + mkexpr(t4), + binop(Iop_And32, + binop(Iop_Shl32, IRExpr_Get(OFFB_ACFLAG,Ity_I32), + mkU8(18)), + mkU32(1<<18))) + ); + /* if sz==2, the stored value needs to be narrowed. */ if (sz == 2) - storeLE( mkexpr(t1), unop(Iop_32to16,mkexpr(t4)) ); + storeLE( mkexpr(t1), unop(Iop_32to16,mkexpr(t5)) ); else - storeLE( mkexpr(t1), mkexpr(t4) ); + storeLE( mkexpr(t1), mkexpr(t5) ); DIP("pushf%c\n", nameISize(sz)); break; diff --git a/VEX/priv/main/vex_main.c b/VEX/priv/main/vex_main.c index 609375c01f..f1589c39e9 100644 --- a/VEX/priv/main/vex_main.c +++ b/VEX/priv/main/vex_main.c @@ -614,6 +614,8 @@ HChar* LibVEX_EmWarn_string ( VexEmWarn ew ) return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)"; case EmWarn_X86_daz: return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)"; + case EmWarn_X86_acFlag: + return "Setting %eflags.ac (setting noted but ignored)"; case EmWarn_PPC32exns: return "Unmasking PPC32 FP exceptions"; default: diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index bd87bd13b4..97cb8aa9dc 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -182,7 +182,7 @@ extern void LibVEX_ShowAllocStats ( void ); /* The max number of guest state chunks which we can describe as always defined (for the benefit of Memcheck). */ -#define VEXGLO_N_ALWAYSDEFD 21 +#define VEXGLO_N_ALWAYSDEFD 22 typedef struct { diff --git a/VEX/pub/libvex_emwarn.h b/VEX/pub/libvex_emwarn.h index 51abcbf27b..8ef6c8d8df 100644 --- a/VEX/pub/libvex_emwarn.h +++ b/VEX/pub/libvex_emwarn.h @@ -83,6 +83,9 @@ typedef /* setting mxcsr.daz is not supported */ EmWarn_X86_daz, + + /* settings to %eflags.ac (alignment check) are noted but ignored */ + EmWarn_X86_acFlag, /* unmasking PPC32 FP exceptions is not supported */ EmWarn_PPC32exns, diff --git a/VEX/pub/libvex_guest_x86.h b/VEX/pub/libvex_guest_x86.h index 377064cad5..5bfa36838e 100644 --- a/VEX/pub/libvex_guest_x86.h +++ b/VEX/pub/libvex_guest_x86.h @@ -160,6 +160,7 @@ typedef UInt guest_EBP; UInt guest_ESI; UInt guest_EDI; /* 28 */ + /* 4-word thunk used to calculate O S Z A C P flags. */ UInt guest_CC_OP; /* 32 */ UInt guest_CC_DEP1; @@ -169,17 +170,22 @@ typedef UInt guest_DFLAG; /* 48 */ /* Bit 21 (ID) of eflags stored here, as either 0 or 1. */ UInt guest_IDFLAG; /* 52 */ + /* Bit 18 (AC) of eflags stored here, as either 0 or 1. */ + UInt guest_ACFLAG; /* 56 */ + /* EIP */ - UInt guest_EIP; /* 56 */ + UInt guest_EIP; /* 60 */ + /* FPU */ - UInt guest_FTOP; /* 60 */ ULong guest_FPREG[8]; /* 64 */ UChar guest_FPTAG[8]; /* 128 */ UInt guest_FPROUND; /* 136 */ UInt guest_FC3210; /* 140 */ + UInt guest_FTOP; /* 144 */ + /* SSE */ - UInt guest_SSEROUND; /* 144 */ - U128 guest_XMM0; /* 148 */ + UInt guest_SSEROUND; /* 148 */ + U128 guest_XMM0; /* 152 */ U128 guest_XMM1; U128 guest_XMM2; U128 guest_XMM3; @@ -187,6 +193,7 @@ typedef U128 guest_XMM5; U128 guest_XMM6; U128 guest_XMM7; + /* Segment registers. */ UShort guest_CS; UShort guest_DS; @@ -212,7 +219,7 @@ typedef UInt guest_TILEN; /* Padding to make it have an 8-aligned size */ - UInt padding; + /* UInt padding; */ } VexGuestX86State; -- 2.47.3