1 2 /*---------------------------------------------------------------*/ 3 /*--- begin libvex_guest_x86.h ---*/ 4 /*---------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2013 OpenWorks LLP 11 info@open-works.net 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34 */ 35 36 #ifndef __LIBVEX_PUB_GUEST_X86_H 37 #define __LIBVEX_PUB_GUEST_X86_H 38 39 #include "libvex_basictypes.h" 40 41 42 /*---------------------------------------------------------------*/ 43 /*--- Vex's representation of the x86 CPU state. ---*/ 44 /*---------------------------------------------------------------*/ 45 46 /* The integer parts should be pretty straightforward. */ 47 48 /* Hmm, subregisters. The simulated state is stored in memory in the 49 host's byte ordering, so we can't say here what the offsets of %ax, 50 %al, %ah etc are since that depends on the host's byte ordering, 51 which we don't know. */ 52 53 /* FPU. For now, just simulate 8 64-bit registers, their tags, and 54 the reg-stack top pointer, of which only the least significant 55 three bits are relevant. 56 57 The model is: 58 F0 .. F7 are the 8 registers. FTOP[2:0] contains the 59 index of the current 'stack top' -- pretty meaningless, but 60 still. FTOP is a 32-bit value. FTOP[31:3] can be anything 61 (not guaranteed to be zero). 62 63 When a value is pushed onto the stack, ftop is first replaced by 64 (ftop-1) & 7, and then F[ftop] is assigned the value. 65 66 When a value is popped off the stack, the value is read from 67 F[ftop], and then ftop is replaced by (ftop+1) & 7. 68 69 In general, a reference to a register ST(i) actually references 70 F[ (ftop+i) & 7 ]. 71 72 FTAG0 .. FTAG0+7 are the tags. Each is a byte, zero means empty, 73 non-zero means non-empty. 74 75 The general rule appears to be that a read or modify of a register 76 gets a stack underflow fault if the register is empty. A write of 77 a register (only a write, not a modify) gets a stack overflow fault 78 if the register is full. Note that "over" vs "under" is pretty 79 meaningless since the FP stack pointer can move around arbitrarily, 80 so it's really just two different kinds of exceptions: 81 register-empty and register full. 82 83 Naturally Intel (in its infinite wisdom) has seen fit to throw in 84 some ad-hoc inconsistencies to the fault-generation rules of the 85 above para, just to complicate everything. Known inconsistencies: 86 87 * fxam can read a register in any state without taking an underflow 88 fault. 89 90 * fst from st(0) to st(i) does not take an overflow fault even if the 91 destination is already full. 92 93 FPROUND[1:0] is the FPU's notional rounding mode, encoded as per 94 the IRRoundingMode type (see libvex_ir.h). This just happens to be 95 the Intel encoding. Note carefully, the rounding mode is only 96 observed on float-to-int conversions, and on float-to-float 97 rounding, but not for general float-to-float operations, which are 98 always rounded-to-nearest. 99 100 Loads/stores of the FPU control word are faked accordingly -- on 101 loads, everything except the rounding mode is ignored, and on 102 stores, you get a vanilla control world (0x037F) with the rounding 103 mode patched in. Hence the only values you can get are 0x037F, 104 0x077F, 0x0B7F or 0x0F7F. Vex will emit an emulation warning if 105 you try and load a control word which either (1) unmasks FP 106 exceptions, or (2) changes the default (80-bit) precision. 107 108 FC3210 contains the C3, C2, C1 and C0 bits in the same place they 109 are in the FPU's status word. (bits 14, 10, 9, 8 respectively). 110 All other bits should be zero. The relevant mask to select just 111 those bits is 0x4700. To select C3, C2 and C0 only, the mask is 112 0x4500. 113 114 SSEROUND[1:0] is the SSE unit's notional rounding mode, encoded as 115 per the IRRoundingMode type. As with the FPU control word, the 116 rounding mode is the only part of %MXCSR that Vex observes. On 117 storing %MXCSR, you will get a vanilla word (0x1F80) with the 118 rounding mode patched in. Hence the only values you will get are 119 0x1F80, 0x3F80, 0x5F80 or 0x7F80. Vex will emit an emulation 120 warning if you try and load a control word which either (1) unmasks 121 any exceptions, (2) sets FZ (flush-to-zero) to 1, or (3) sets DAZ 122 (denormals-are-zeroes) to 1. 123 124 Segments: initial prefixes of local and global segment descriptor 125 tables are modelled. guest_LDT is either zero (NULL) or points in 126 the host address space to an array of VEX_GUEST_X86_LDT_NENT 127 descriptors, which have the type VexGuestX86SegDescr, defined 128 below. Similarly, guest_GDT is either zero or points in the host 129 address space to an array of VEX_GUEST_X86_GDT_NENT descriptors. 130 The only place where these are used are in the helper function 131 x86g_use_seg(). LibVEX's client is responsible for pointing 132 guest_LDT and guest_GDT at suitable tables. The contents of these 133 tables are expected not to change during the execution of any given 134 superblock, but they may validly be changed by LibVEX's client in 135 between superblock executions. 136 137 Since x86g_use_seg() only expects these tables to have 138 VEX_GUEST_X86_{LDT,GDT}_NENT entries, LibVEX's client should not 139 attempt to write entries beyond those limits. 140 */ 141 typedef 142 struct { 143 /* Event check fail addr and counter. */ 144 UInt host_EvC_FAILADDR; /* 0 */ 145 UInt host_EvC_COUNTER; /* 4 */ 146 UInt guest_EAX; /* 8 */ 147 UInt guest_ECX; 148 UInt guest_EDX; 149 UInt guest_EBX; 150 UInt guest_ESP; 151 UInt guest_EBP; 152 UInt guest_ESI; 153 UInt guest_EDI; /* 36 */ 154 155 /* 4-word thunk used to calculate O S Z A C P flags. */ 156 UInt guest_CC_OP; /* 40 */ 157 UInt guest_CC_DEP1; 158 UInt guest_CC_DEP2; 159 UInt guest_CC_NDEP; /* 52 */ 160 /* The D flag is stored here, encoded as either -1 or +1 */ 161 UInt guest_DFLAG; /* 56 */ 162 /* Bit 21 (ID) of eflags stored here, as either 0 or 1. */ 163 UInt guest_IDFLAG; /* 60 */ 164 /* Bit 18 (AC) of eflags stored here, as either 0 or 1. */ 165 UInt guest_ACFLAG; /* 64 */ 166 167 /* EIP */ 168 UInt guest_EIP; /* 68 */ 169 170 /* FPU */ 171 ULong guest_FPREG[8]; /* 72 */ 172 UChar guest_FPTAG[8]; /* 136 */ 173 UInt guest_FPROUND; /* 144 */ 174 UInt guest_FC3210; /* 148 */ 175 UInt guest_FTOP; /* 152 */ 176 177 /* SSE */ 178 UInt guest_SSEROUND; /* 156 */ 179 U128 guest_XMM0; /* 160 */ 180 U128 guest_XMM1; 181 U128 guest_XMM2; 182 U128 guest_XMM3; 183 U128 guest_XMM4; 184 U128 guest_XMM5; 185 U128 guest_XMM6; 186 U128 guest_XMM7; 187 188 /* Segment registers. */ 189 UShort guest_CS; 190 UShort guest_DS; 191 UShort guest_ES; 192 UShort guest_FS; 193 UShort guest_GS; 194 UShort guest_SS; 195 /* LDT/GDT stuff. */ 196 HWord guest_LDT; /* host addr, a VexGuestX86SegDescr* */ 197 HWord guest_GDT; /* host addr, a VexGuestX86SegDescr* */ 198 199 /* Emulation notes */ 200 UInt guest_EMNOTE; 201 202 /* For clflush/clinval: record start and length of area */ 203 UInt guest_CMSTART; 204 UInt guest_CMLEN; 205 206 /* Used to record the unredirected guest address at the start of 207 a translation whose start has been redirected. By reading 208 this pseudo-register shortly afterwards, the translation can 209 find out what the corresponding no-redirection address was. 210 Note, this is only set for wrap-style redirects, not for 211 replace-style ones. */ 212 UInt guest_NRADDR; 213 214 /* Used for Darwin syscall dispatching. */ 215 UInt guest_SC_CLASS; 216 217 /* Needed for Darwin (but mandated for all guest architectures): 218 EIP at the last syscall insn (int 0x80/81/82, sysenter, 219 syscall). Used when backing up to restart a syscall that has 220 been interrupted by a signal. */ 221 UInt guest_IP_AT_SYSCALL; 222 223 /* Padding to make it have an 16-aligned size */ 224 UInt padding1; 225 } 226 VexGuestX86State; 227 228 #define VEX_GUEST_X86_LDT_NENT /*64*/ 8192 /* use complete LDT */ 229 #define VEX_GUEST_X86_GDT_NENT /*16*/ 8192 /* use complete GDT */ 230 231 232 /*---------------------------------------------------------------*/ 233 /*--- Types for x86 guest stuff. ---*/ 234 /*---------------------------------------------------------------*/ 235 236 /* VISIBLE TO LIBRARY CLIENT */ 237 238 /* This is the hardware-format for a segment descriptor, ie what the 239 x86 actually deals with. It is 8 bytes long. It's ugly. */ 240 241 typedef struct { 242 union { 243 struct { 244 UShort LimitLow; 245 UShort BaseLow; 246 UInt BaseMid : 8; 247 UInt Type : 5; 248 UInt Dpl : 2; 249 UInt Pres : 1; 250 UInt LimitHi : 4; 251 UInt Sys : 1; 252 UInt Reserved_0 : 1; 253 UInt Default_Big : 1; 254 UInt Granularity : 1; 255 UInt BaseHi : 8; 256 } Bits; 257 struct { 258 UInt word1; 259 UInt word2; 260 } Words; 261 } 262 LdtEnt; 263 } VexGuestX86SegDescr; 264 265 266 /*---------------------------------------------------------------*/ 267 /*--- Utility functions for x86 guest stuff. ---*/ 268 /*---------------------------------------------------------------*/ 269 270 /* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */ 271 272 /* Initialise all guest x86 state. The FPU is put in default mode. */ 273 extern 274 void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ); 275 276 277 /* Extract from the supplied VexGuestX86State structure the 278 corresponding native %eflags value. */ 279 extern 280 UInt LibVEX_GuestX86_get_eflags ( /*IN*/const VexGuestX86State* vex_state ); 281 282 /* Set the carry flag in the given state to 'new_carry_flag', which 283 should be zero or one. */ 284 extern 285 void 286 LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag, 287 /*MOD*/VexGuestX86State* vex_state ); 288 289 #endif /* ndef __LIBVEX_PUB_GUEST_X86_H */ 290 291 /*---------------------------------------------------------------*/ 292 /*--- libvex_guest_x86.h ---*/ 293 /*---------------------------------------------------------------*/ 294