Home | History | Annotate | Download | only in pub
      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-2015 OpenWorks LLP
     11       info (at) 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       HWord  guest_LDT; /* host addr, a VexGuestX86SegDescr* */
    198       HWord  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    }
    227    VexGuestX86State;
    228 
    229 #define VEX_GUEST_X86_LDT_NENT /*64*/ 8192 /* use complete LDT */
    230 #define VEX_GUEST_X86_GDT_NENT /*16*/ 8192 /* use complete GDT */
    231 
    232 
    233 /*---------------------------------------------------------------*/
    234 /*--- Types for x86 guest stuff.                              ---*/
    235 /*---------------------------------------------------------------*/
    236 
    237 /* VISIBLE TO LIBRARY CLIENT */
    238 
    239 /* This is the hardware-format for a segment descriptor, ie what the
    240    x86 actually deals with.  It is 8 bytes long.  It's ugly. */
    241 
    242 typedef struct {
    243     union {
    244        struct {
    245           UShort  LimitLow;
    246           UShort  BaseLow;
    247           UInt    BaseMid         : 8;
    248           UInt    Type            : 5;
    249           UInt    Dpl             : 2;
    250           UInt    Pres            : 1;
    251           UInt    LimitHi         : 4;
    252           UInt    Sys             : 1;
    253           UInt    Reserved_0      : 1;
    254           UInt    Default_Big     : 1;
    255           UInt    Granularity     : 1;
    256           UInt    BaseHi          : 8;
    257        } Bits;
    258        struct {
    259           UInt word1;
    260           UInt word2;
    261        } Words;
    262     }
    263     LdtEnt;
    264 } VexGuestX86SegDescr;
    265 
    266 
    267 /*---------------------------------------------------------------*/
    268 /*--- Utility functions for x86 guest stuff.                  ---*/
    269 /*---------------------------------------------------------------*/
    270 
    271 /* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */
    272 
    273 /* Initialise all guest x86 state.  The FPU is put in default mode. */
    274 extern
    275 void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state );
    276 
    277 
    278 /* Extract from the supplied VexGuestX86State structure the
    279    corresponding native %eflags value. */
    280 extern
    281 UInt LibVEX_GuestX86_get_eflags ( /*IN*/const VexGuestX86State* vex_state );
    282 
    283 /* Put eflags into the given state. */
    284 extern
    285 void LibVEX_GuestX86_put_eflags ( UInt eflags,
    286                                   /*MOD*/VexGuestX86State* vex_state );
    287 
    288 /* Set the carry flag in the given state to 'new_carry_flag', which
    289    should be zero or one. */
    290 extern
    291 void
    292 LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag,
    293                               /*MOD*/VexGuestX86State* vex_state );
    294 
    295 /* Do x87 save from the supplied VexGuestX86State structure and store the
    296    result at the given address which represents a buffer of at least 108
    297    bytes. */
    298 extern
    299 void LibVEX_GuestX86_get_x87 ( /*IN*/VexGuestX86State* vex_state,
    300                                /*OUT*/UChar* x87_state );
    301 
    302 /* Do x87 restore from the supplied address and store read values to the given
    303    VexGuestX86State structure. */
    304 extern
    305 VexEmNote LibVEX_GuestX86_put_x87 ( /*IN*/UChar* x87_state,
    306                                     /*MOD*/VexGuestX86State* vex_state);
    307 
    308 /* Return mxcsr from the supplied VexGuestX86State structure. */
    309 extern
    310 UInt LibVEX_GuestX86_get_mxcsr ( /*IN*/VexGuestX86State* vex_state );
    311 
    312 /* Modify the given VexGuestX86State structure according to the passed mxcsr
    313    value. */
    314 extern
    315 VexEmNote LibVEX_GuestX86_put_mxcsr ( /*IN*/UInt mxcsr,
    316                                       /*MOD*/VexGuestX86State* vex_state);
    317 
    318 #endif /* ndef __LIBVEX_PUB_GUEST_X86_H */
    319 
    320 /*---------------------------------------------------------------*/
    321 /*---                                      libvex_guest_x86.h ---*/
    322 /*---------------------------------------------------------------*/
    323