|
||||
File indexing completed on 2025-01-18 10:13:29
0001 0002 /*---------------------------------------------------------------*/ 0003 /*--- begin libvex_guest_x86.h ---*/ 0004 /*---------------------------------------------------------------*/ 0005 0006 /* 0007 This file is part of Valgrind, a dynamic binary instrumentation 0008 framework. 0009 0010 Copyright (C) 2004-2017 OpenWorks LLP 0011 info@open-works.net 0012 0013 This program is free software; you can redistribute it and/or 0014 modify it under the terms of the GNU General Public License as 0015 published by the Free Software Foundation; either version 2 of the 0016 License, or (at your option) any later version. 0017 0018 This program is distributed in the hope that it will be useful, but 0019 WITHOUT ANY WARRANTY; without even the implied warranty of 0020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0021 General Public License for more details. 0022 0023 You should have received a copy of the GNU General Public License 0024 along with this program; if not, see <http://www.gnu.org/licenses/>. 0025 0026 The GNU General Public License is contained in the file COPYING. 0027 0028 Neither the names of the U.S. Department of Energy nor the 0029 University of California nor the names of its contributors may be 0030 used to endorse or promote products derived from this software 0031 without prior written permission. 0032 */ 0033 0034 #ifndef __LIBVEX_PUB_GUEST_X86_H 0035 #define __LIBVEX_PUB_GUEST_X86_H 0036 0037 #include "libvex_basictypes.h" 0038 #include "libvex_emnote.h" 0039 0040 0041 /*---------------------------------------------------------------*/ 0042 /*--- Vex's representation of the x86 CPU state. ---*/ 0043 /*---------------------------------------------------------------*/ 0044 0045 /* The integer parts should be pretty straightforward. */ 0046 0047 /* Hmm, subregisters. The simulated state is stored in memory in the 0048 host's byte ordering, so we can't say here what the offsets of %ax, 0049 %al, %ah etc are since that depends on the host's byte ordering, 0050 which we don't know. */ 0051 0052 /* FPU. For now, just simulate 8 64-bit registers, their tags, and 0053 the reg-stack top pointer, of which only the least significant 0054 three bits are relevant. 0055 0056 The model is: 0057 F0 .. F7 are the 8 registers. FTOP[2:0] contains the 0058 index of the current 'stack top' -- pretty meaningless, but 0059 still. FTOP is a 32-bit value. FTOP[31:3] can be anything 0060 (not guaranteed to be zero). 0061 0062 When a value is pushed onto the stack, ftop is first replaced by 0063 (ftop-1) & 7, and then F[ftop] is assigned the value. 0064 0065 When a value is popped off the stack, the value is read from 0066 F[ftop], and then ftop is replaced by (ftop+1) & 7. 0067 0068 In general, a reference to a register ST(i) actually references 0069 F[ (ftop+i) & 7 ]. 0070 0071 FTAG0 .. FTAG0+7 are the tags. Each is a byte, zero means empty, 0072 non-zero means non-empty. 0073 0074 The general rule appears to be that a read or modify of a register 0075 gets a stack underflow fault if the register is empty. A write of 0076 a register (only a write, not a modify) gets a stack overflow fault 0077 if the register is full. Note that "over" vs "under" is pretty 0078 meaningless since the FP stack pointer can move around arbitrarily, 0079 so it's really just two different kinds of exceptions: 0080 register-empty and register full. 0081 0082 Naturally Intel (in its infinite wisdom) has seen fit to throw in 0083 some ad-hoc inconsistencies to the fault-generation rules of the 0084 above para, just to complicate everything. Known inconsistencies: 0085 0086 * fxam can read a register in any state without taking an underflow 0087 fault. 0088 0089 * fst from st(0) to st(i) does not take an overflow fault even if the 0090 destination is already full. 0091 0092 FPROUND[1:0] is the FPU's notional rounding mode, encoded as per 0093 the IRRoundingMode type (see libvex_ir.h). This just happens to be 0094 the Intel encoding. Note carefully, the rounding mode is only 0095 observed on float-to-int conversions, and on float-to-float 0096 rounding, but not for general float-to-float operations, which are 0097 always rounded-to-nearest. 0098 0099 Loads/stores of the FPU control word are faked accordingly -- on 0100 loads, everything except the rounding mode is ignored, and on 0101 stores, you get a vanilla control world (0x037F) with the rounding 0102 mode patched in. Hence the only values you can get are 0x037F, 0103 0x077F, 0x0B7F or 0x0F7F. Vex will emit an emulation warning if 0104 you try and load a control word which either (1) unmasks FP 0105 exceptions, or (2) changes the default (80-bit) precision. 0106 0107 FC3210 contains the C3, C2, C1 and C0 bits in the same place they 0108 are in the FPU's status word. (bits 14, 10, 9, 8 respectively). 0109 All other bits should be zero. The relevant mask to select just 0110 those bits is 0x4700. To select C3, C2 and C0 only, the mask is 0111 0x4500. 0112 0113 SSEROUND[1:0] is the SSE unit's notional rounding mode, encoded as 0114 per the IRRoundingMode type. As with the FPU control word, the 0115 rounding mode is the only part of %MXCSR that Vex observes. On 0116 storing %MXCSR, you will get a vanilla word (0x1F80) with the 0117 rounding mode patched in. Hence the only values you will get are 0118 0x1F80, 0x3F80, 0x5F80 or 0x7F80. Vex will emit an emulation 0119 warning if you try and load a control word which either (1) unmasks 0120 any exceptions, (2) sets FZ (flush-to-zero) to 1, or (3) sets DAZ 0121 (denormals-are-zeroes) to 1. 0122 0123 Segments: initial prefixes of local and global segment descriptor 0124 tables are modelled. guest_LDT is either zero (NULL) or points in 0125 the host address space to an array of VEX_GUEST_X86_LDT_NENT 0126 descriptors, which have the type VexGuestX86SegDescr, defined 0127 below. Similarly, guest_GDT is either zero or points in the host 0128 address space to an array of VEX_GUEST_X86_GDT_NENT descriptors. 0129 The only place where these are used are in the helper function 0130 x86g_use_seg(). LibVEX's client is responsible for pointing 0131 guest_LDT and guest_GDT at suitable tables. The contents of these 0132 tables are expected not to change during the execution of any given 0133 superblock, but they may validly be changed by LibVEX's client in 0134 between superblock executions. 0135 0136 Since x86g_use_seg() only expects these tables to have 0137 VEX_GUEST_X86_{LDT,GDT}_NENT entries, LibVEX's client should not 0138 attempt to write entries beyond those limits. 0139 */ 0140 typedef 0141 struct { 0142 /* Event check fail addr and counter. */ 0143 UInt host_EvC_FAILADDR; /* 0 */ 0144 UInt host_EvC_COUNTER; /* 4 */ 0145 UInt guest_EAX; /* 8 */ 0146 UInt guest_ECX; 0147 UInt guest_EDX; 0148 UInt guest_EBX; 0149 UInt guest_ESP; 0150 UInt guest_EBP; 0151 UInt guest_ESI; 0152 UInt guest_EDI; /* 36 */ 0153 0154 /* 4-word thunk used to calculate O S Z A C P flags. */ 0155 UInt guest_CC_OP; /* 40 */ 0156 UInt guest_CC_DEP1; 0157 UInt guest_CC_DEP2; 0158 UInt guest_CC_NDEP; /* 52 */ 0159 /* The D flag is stored here, encoded as either -1 or +1 */ 0160 UInt guest_DFLAG; /* 56 */ 0161 /* Bit 21 (ID) of eflags stored here, as either 0 or 1. */ 0162 UInt guest_IDFLAG; /* 60 */ 0163 /* Bit 18 (AC) of eflags stored here, as either 0 or 1. */ 0164 UInt guest_ACFLAG; /* 64 */ 0165 0166 /* EIP */ 0167 UInt guest_EIP; /* 68 */ 0168 0169 /* FPU */ 0170 ULong guest_FPREG[8]; /* 72 */ 0171 UChar guest_FPTAG[8]; /* 136 */ 0172 UInt guest_FPROUND; /* 144 */ 0173 UInt guest_FC3210; /* 148 */ 0174 UInt guest_FTOP; /* 152 */ 0175 0176 /* SSE */ 0177 UInt guest_SSEROUND; /* 156 */ 0178 U128 guest_XMM0; /* 160 */ 0179 U128 guest_XMM1; 0180 U128 guest_XMM2; 0181 U128 guest_XMM3; 0182 U128 guest_XMM4; 0183 U128 guest_XMM5; 0184 U128 guest_XMM6; 0185 U128 guest_XMM7; 0186 0187 /* Segment registers. */ 0188 UShort guest_CS; 0189 UShort guest_DS; 0190 UShort guest_ES; 0191 UShort guest_FS; 0192 UShort guest_GS; 0193 UShort guest_SS; 0194 /* LDT/GDT stuff. */ 0195 ULong guest_LDT; /* host addr, a VexGuestX86SegDescr* */ 0196 ULong guest_GDT; /* host addr, a VexGuestX86SegDescr* */ 0197 0198 /* Emulation notes */ 0199 UInt guest_EMNOTE; 0200 0201 /* For clflush/clinval: record start and length of area */ 0202 UInt guest_CMSTART; 0203 UInt guest_CMLEN; 0204 0205 /* Used to record the unredirected guest address at the start of 0206 a translation whose start has been redirected. By reading 0207 this pseudo-register shortly afterwards, the translation can 0208 find out what the corresponding no-redirection address was. 0209 Note, this is only set for wrap-style redirects, not for 0210 replace-style ones. */ 0211 UInt guest_NRADDR; 0212 0213 /* Used for Darwin syscall dispatching. */ 0214 UInt guest_SC_CLASS; 0215 0216 /* Needed for Darwin (but mandated for all guest architectures): 0217 EIP at the last syscall insn (int 0x80/81/82, sysenter, 0218 syscall). Used when backing up to restart a syscall that has 0219 been interrupted by a signal. */ 0220 UInt guest_IP_AT_SYSCALL; 0221 0222 /* Padding to make it have an 16-aligned size */ 0223 UInt padding1; 0224 UInt padding2; 0225 UInt padding3; 0226 } 0227 VexGuestX86State; 0228 0229 #define VEX_GUEST_X86_LDT_NENT /*64*/ 8192 /* use complete LDT */ 0230 #define VEX_GUEST_X86_GDT_NENT /*16*/ 8192 /* use complete GDT */ 0231 0232 0233 /*---------------------------------------------------------------*/ 0234 /*--- Types for x86 guest stuff. ---*/ 0235 /*---------------------------------------------------------------*/ 0236 0237 /* VISIBLE TO LIBRARY CLIENT */ 0238 0239 /* This is the hardware-format for a segment descriptor, ie what the 0240 x86 actually deals with. It is 8 bytes long. It's ugly. */ 0241 0242 typedef struct { 0243 union { 0244 struct { 0245 UShort LimitLow; 0246 UShort BaseLow; 0247 UInt BaseMid : 8; 0248 UInt Type : 5; 0249 UInt Dpl : 2; 0250 UInt Pres : 1; 0251 UInt LimitHi : 4; 0252 UInt Sys : 1; 0253 UInt Reserved_0 : 1; 0254 UInt Default_Big : 1; 0255 UInt Granularity : 1; 0256 UInt BaseHi : 8; 0257 } Bits; 0258 struct { 0259 UInt word1; 0260 UInt word2; 0261 } Words; 0262 } 0263 LdtEnt; 0264 } VexGuestX86SegDescr; 0265 0266 0267 /*---------------------------------------------------------------*/ 0268 /*--- Utility functions for x86 guest stuff. ---*/ 0269 /*---------------------------------------------------------------*/ 0270 0271 /* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */ 0272 0273 /* Initialise all guest x86 state. The FPU is put in default mode. */ 0274 extern 0275 void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ); 0276 0277 0278 /* Extract from the supplied VexGuestX86State structure the 0279 corresponding native %eflags value. */ 0280 extern 0281 UInt LibVEX_GuestX86_get_eflags ( /*IN*/const VexGuestX86State* vex_state ); 0282 0283 /* Put eflags into the given state. */ 0284 extern 0285 void LibVEX_GuestX86_put_eflags ( UInt eflags, 0286 /*MOD*/VexGuestX86State* vex_state ); 0287 0288 /* Set the carry flag in the given state to 'new_carry_flag', which 0289 should be zero or one. */ 0290 extern 0291 void 0292 LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag, 0293 /*MOD*/VexGuestX86State* vex_state ); 0294 0295 #if defined(VGO_freebsd) || defined(VGO_darwin) 0296 extern void _______VVVVVVVV_after_LibVEX_GuestX86_put_eflag_c_VVVVVVVV_______ (void); 0297 extern Addr addr_x86g_calculate_eflags_all_WRK; 0298 extern Addr addr________VVVVVVVV_x86g_calculate_eflags_all_WRK_VVVVVVVV_______; 0299 #endif 0300 0301 /* Do x87 save from the supplied VexGuestX86State structure and store the 0302 result at the given address which represents a buffer of at least 108 0303 bytes. */ 0304 extern 0305 void LibVEX_GuestX86_get_x87 ( /*IN*/VexGuestX86State* vex_state, 0306 /*OUT*/UChar* x87_state ); 0307 0308 /* Do x87 restore from the supplied address and store read values to the given 0309 VexGuestX86State structure. */ 0310 extern 0311 VexEmNote LibVEX_GuestX86_put_x87 ( /*IN*/UChar* x87_state, 0312 /*MOD*/VexGuestX86State* vex_state); 0313 0314 /* Return mxcsr from the supplied VexGuestX86State structure. */ 0315 extern 0316 UInt LibVEX_GuestX86_get_mxcsr ( /*IN*/VexGuestX86State* vex_state ); 0317 0318 /* Modify the given VexGuestX86State structure according to the passed mxcsr 0319 value. */ 0320 extern 0321 VexEmNote LibVEX_GuestX86_put_mxcsr ( /*IN*/UInt mxcsr, 0322 /*MOD*/VexGuestX86State* vex_state); 0323 0324 #endif /* ndef __LIBVEX_PUB_GUEST_X86_H */ 0325 0326 /*---------------------------------------------------------------*/ 0327 /*--- libvex_guest_x86.h ---*/ 0328 /*---------------------------------------------------------------*/
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |