Back to home page

EIC code displayed by LXR

 
 

    


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 /*---------------------------------------------------------------*/