|
|
|||
File indexing completed on 2026-09-25 09:31:50
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 3 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 UInt paddingSeg; 0195 /* LDT/GDT stuff. */ 0196 ULong guest_LDT; /* host addr, a VexGuestX86SegDescr* */ 0197 ULong guest_GDT; /* host addr, a VexGuestX86SegDescr* */ 0198 0199 /* Emulation notes */ 0200 UInt guest_EMNOTE; 0201 0202 /* For clflush/clinval: record start and length of area */ 0203 UInt guest_CMSTART; 0204 UInt guest_CMLEN; 0205 0206 /* Used to record the unredirected guest address at the start of 0207 a translation whose start has been redirected. By reading 0208 this pseudo-register shortly afterwards, the translation can 0209 find out what the corresponding no-redirection address was. 0210 Note, this is only set for wrap-style redirects, not for 0211 replace-style ones. */ 0212 UInt guest_NRADDR; 0213 0214 /* Used for Darwin syscall dispatching. */ 0215 UInt guest_SC_CLASS; 0216 0217 0218 /* Padding to make it have an 16-aligned size */ 0219 UInt padding1; 0220 UInt padding2; 0221 UInt padding3; 0222 } 0223 VexGuestX86State; 0224 0225 _Static_assert(sizeof(VexGuestX86State)%16 == 0, "sizeof VexGuestX86State is not a multiple of 16"); 0226 0227 #define VEX_GUEST_X86_LDT_NENT /*64*/ 8192 /* use complete LDT */ 0228 #define VEX_GUEST_X86_GDT_NENT /*16*/ 8192 /* use complete GDT */ 0229 0230 0231 /*---------------------------------------------------------------*/ 0232 /*--- Types for x86 guest stuff. ---*/ 0233 /*---------------------------------------------------------------*/ 0234 0235 /* VISIBLE TO LIBRARY CLIENT */ 0236 0237 /* This is the hardware-format for a segment descriptor, ie what the 0238 x86 actually deals with. It is 8 bytes long. It's ugly. */ 0239 0240 typedef struct { 0241 union { 0242 struct { 0243 UShort LimitLow; 0244 UShort BaseLow; 0245 UInt BaseMid : 8; 0246 UInt Type : 5; 0247 UInt Dpl : 2; 0248 UInt Pres : 1; 0249 UInt LimitHi : 4; 0250 UInt Sys : 1; 0251 UInt Reserved_0 : 1; 0252 UInt Default_Big : 1; 0253 UInt Granularity : 1; 0254 UInt BaseHi : 8; 0255 } Bits; 0256 struct { 0257 UInt word1; 0258 UInt word2; 0259 } Words; 0260 } 0261 LdtEnt; 0262 } VexGuestX86SegDescr; 0263 0264 0265 /*---------------------------------------------------------------*/ 0266 /*--- Utility functions for x86 guest stuff. ---*/ 0267 /*---------------------------------------------------------------*/ 0268 0269 /* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */ 0270 0271 /* Initialise all guest x86 state. The FPU is put in default mode. */ 0272 extern 0273 void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ); 0274 0275 0276 /* Extract from the supplied VexGuestX86State structure the 0277 corresponding native %eflags value. */ 0278 extern 0279 UInt LibVEX_GuestX86_get_eflags ( /*IN*/const VexGuestX86State* vex_state ); 0280 0281 /* Put eflags into the given state. */ 0282 extern 0283 void LibVEX_GuestX86_put_eflags ( UInt eflags, 0284 /*MOD*/VexGuestX86State* vex_state ); 0285 0286 /* Set the carry flag in the given state to 'new_carry_flag', which 0287 should be zero or one. */ 0288 extern 0289 void 0290 LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag, 0291 /*MOD*/VexGuestX86State* vex_state ); 0292 0293 /* Do x87 save from the supplied VexGuestX86State structure and store the 0294 result at the given address which represents a buffer of at least 108 0295 bytes. */ 0296 extern 0297 void LibVEX_GuestX86_get_x87 ( /*IN*/VexGuestX86State* vex_state, 0298 /*OUT*/UChar* x87_state ); 0299 0300 /* Do x87 restore from the supplied address and store read values to the given 0301 VexGuestX86State structure. */ 0302 extern 0303 VexEmNote LibVEX_GuestX86_put_x87 ( /*IN*/UChar* x87_state, 0304 /*MOD*/VexGuestX86State* vex_state); 0305 0306 /* Return mxcsr from the supplied VexGuestX86State structure. */ 0307 extern 0308 UInt LibVEX_GuestX86_get_mxcsr ( /*IN*/VexGuestX86State* vex_state ); 0309 0310 /* Modify the given VexGuestX86State structure according to the passed mxcsr 0311 value. */ 0312 extern 0313 VexEmNote LibVEX_GuestX86_put_mxcsr ( /*IN*/UInt mxcsr, 0314 /*MOD*/VexGuestX86State* vex_state); 0315 0316 #endif /* ndef __LIBVEX_PUB_GUEST_X86_H */ 0317 0318 /*---------------------------------------------------------------*/ 0319 /*--- libvex_guest_x86.h ---*/ 0320 /*---------------------------------------------------------------*/
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|