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*/
142typedef
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
244typedef 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. */
276extern
277void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state );
278
279
280/* Extract from the supplied VexGuestX86State structure the
281   corresponding native %eflags value. */
282extern
283UInt LibVEX_GuestX86_get_eflags ( /*IN*/const VexGuestX86State* vex_state );
284
285/* Put eflags into the given state. */
286extern
287void 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. */
292extern
293void
294LibVEX_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. */
300extern
301void 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. */
306extern
307VexEmNote LibVEX_GuestX86_put_x87 ( /*IN*/UChar* x87_state,
308                                    /*MOD*/VexGuestX86State* vex_state);
309
310/* Return mxcsr from the supplied VexGuestX86State structure. */
311extern
312UInt LibVEX_GuestX86_get_mxcsr ( /*IN*/VexGuestX86State* vex_state );
313
314/* Modify the given VexGuestX86State structure according to the passed mxcsr
315   value. */
316extern
317VexEmNote 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