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