vx32impl.h - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       vx32impl.h (8008B)
       ---
            1 #ifndef VX32_IMPL_H
            2 #define VX32_IMPL_H
            3 
            4 #include <setjmp.h>
            5 #include <sys/signal.h>
            6 #include <ucontext.h>
            7 
            8 // Parameters tweakable for performance
            9 #define VXPROCSMAX        256                // Max # of vxprocs per host proc
           10 #define VXCODEALIGN        16                // Alignment for translated code
           11 #define VXCODEBUFSIZE        (1024*1024)        // Code buffer size (XX make variabale)
           12 #define VXENTRYHASHLEN        32768                // # entrypoints in entry hash table
           13 
           14 // VX memory access permissions have a granularity of 4KB pages.
           15 #define VXPAGESHIFT        12
           16 #define VXPAGESIZE        (1 << VXPAGESHIFT)                // 4KB
           17 #define VXPAGETRUNC(v)        ((uint32_t)(v) & ~(VXPAGESIZE-1))
           18 #define VXPAGEROUND(v)        VXPAGETRUNC((uint32_t)(v) + (VXPAGESIZE-1))
           19 
           20 // The x86 EFLAGS TF bit
           21 #define EFLAGS_TF        0x100
           22 
           23 // VX signal handler return values
           24 #define VXSIG_ERROR        0
           25 #define VXSIG_SINGLESTEP        1
           26 #define VXSIG_TRAP        2
           27 #define VXSIG_SAVE_EAX 0x04
           28 #define VXSIG_SAVE_ECX 0x08
           29 #define VXSIG_SAVE_EDX 0x10
           30 #define VXSIG_SAVE_EBX 0x20
           31 #define VXSIG_SAVE_ESP 0x40
           32 #define VXSIG_SAVE_EBP 0x80
           33 #define VXSIG_SAVE_ESI 0x100
           34 #define VXSIG_SAVE_EDI 0x200
           35 #define VXSIG_SAVE_EFLAGS 0x400
           36 #define VXSIG_SAVE_ALL 0x7FC
           37 #define VXSIG_ADD_COUNT_TO_ESP 0x800
           38 #define VXSIG_SAVE_EBX_AS_EIP 0x1000
           39 #define VXSIG_INC_ECX 0x2000
           40 
           41 #define VXSIG_COUNT_SHIFT 16
           42 
           43 // This is an mmap() flag that we need on 64-bit hosts
           44 // to map our translation state in the low 4GB of address space.
           45 // On 32-bit hosts of course it doesn't exist and isn't needed.
           46 #ifndef MAP_32BIT
           47 #define MAP_32BIT        0
           48 #endif
           49 #define VX_MMAP_FLAGS        MAP_32BIT
           50 
           51 // XX for FreeBSD
           52 #ifndef MAP_ANONYMOUS
           53 #define MAP_ANONYMOUS MAP_ANON
           54 #endif
           55 
           56 // LDT selectors that we set up on x86-64 hosts
           57 // to allow us to run 32-bit code in compatibility mode.
           58 #define FLATCODE        (0+4+3)                // 4 = LDT, 3 = RPL
           59 #define FLATDATA        (8+4+3)
           60 
           61 typedef struct vxinsn vxinsn;
           62 
           63 // Translated instruction
           64 struct vxinsn
           65 {
           66         uint8_t                itype;
           67         uint8_t                srcofs;                // Offset in original vx32 code
           68         uint8_t                dstofs;                // Offset in translated x86 code
           69         uint8_t                dstlen;                // Dest x86 code size for this insn
           70 };
           71 
           72 // Instruction types for vxinsn.itype
           73 #define VXI_NOTRANS        0x00                // Simple, no translation required
           74 #define VXI_JUMP        0x02                // Direct jump/branch
           75 #define VXI_CALL        0x03                // Direct call
           76 #define VXI_JUMP8        0x04                // 8-bit jump/branch
           77 #define VXI_JUMPIND        0x05                // Indirect jump
           78 #define VXI_CALLIND        0x06                // Indirect call
           79 #define VXI_RETURN        0x07                // Return
           80 #define VXI_RETURN_IMM        0x08        // Return with immediate pop count
           81 #define VXI_TRAP        0x09                // Trapping instruction
           82 #define VXI_ENDFRAG        0x0A                // Terminate this fragment
           83 #define VXI_LOOP        0x0B        // Loop
           84 #define VXI_LOOPZ        0x0C        // Loopz/loope
           85 #define VXI_LOOPNZ        0x0D        // Loopnz/loopne
           86 
           87 // Limits for vxinsn.srcofs and vxinsn.dstofs
           88 #define VXSRCOFS_MAX        255
           89 #define VXDSTOFS_MAX        255
           90 
           91 // Each translated fragment consists of:
           92 //        - A struct vxfrag header
           93 //        - A translation summary table containing ninsn vxinsn structs.
           94 //        - The translated code fragment itself, as laid out in the table.
           95 //        - Any trampoline code required by jumps within the fragment.
           96 typedef struct vxfrag {
           97         uint32_t        eip;                // Original EIP in emulated vx32 code
           98         uint8_t                ninsn;                // Number of translated vx32 insns
           99         struct vxinsn        insn[0];        // Beginning of vxinsn table
          100 } vxfrag;
          101 
          102 // Macro to find the beginning of translated code in a fragment
          103 #define FRAGCODE(f)        ((uint8_t*)&(f)->insn[(f)->ninsn])
          104 
          105 #define VXEMU_MAGIC        0xbaf07d5c
          106 
          107 // The vx32-EIP-to-translated-entrypoint hash table
          108 // consists of vxentry structures.
          109 // Each vxentry maps a EIP value in the original vx32 code
          110 // to a corresponding EIP in translated code.
          111 // Empty entries are indicated by *dstip* being 0.
          112 // (Zero is theoretically, though unlikely in practice, a valid vx32 EIP.)
          113 typedef struct vxentry {
          114         uint32_t        srceip;
          115         uint32_t        dsteip;
          116 } vxentry;
          117 
          118 #ifdef __APPLE__
          119 struct i386_thread_state;
          120 int vx32_getcontext(struct i386_thread_state*);
          121 #endif
          122 #ifdef __linux__
          123 int vx32_getcontext(mcontext_t*);
          124 #endif
          125 
          126 // Emulation state for vx32-to-x86 translation.
          127 // This is the header for a variable-length structure;
          128 // the variable-length part is the vx32 EIP lookup hash table (etab),
          129 // followed by the instruction translation buffer.
          130 // While running a particular vxproc,
          131 // we always keep the %ds,%es,%ss segment registers loaded with a data segment
          132 // that allows access only to the emulated address space region, and
          133 // we always keep the %fs register loaded with a special data segment
          134 // whose base and limit correspond to the address and size of this state area.
          135 // This way the emulation code can always access the emulation state
          136 // at fixed displacements without having to use any general-purpose registers.
          137 struct vxemu {
          138         uint32_t        magic;
          139 
          140         // Back pointer to vxproc
          141         vxproc        *proc;
          142         vxmmap        *mem;
          143 
          144         // Data segment and vxemu selectors for this vx32 process
          145         uint32_t        datasel;
          146         uint32_t        emusel;
          147 
          148         // Cache of what the last modify_ldt set up.
          149         uintptr_t        ldt_base;
          150         uint32_t        ldt_size;
          151 
          152         // Pointer to this vxemu struct itself,
          153         // for use when accessing vxemu struct via %fs segment register.
          154         uint32_t        emuptr;
          155 
          156         // vx32 virtual CPU state
          157         vxcpu cpu;
          158         uint32_t        cpu_trap;        // pending trap
          159         uint32_t        saved_trap;        // trap to trigger after single-step
          160         int        nsinglestep;
          161 
          162 #if defined(__FreeBSD__) || defined(__linux__)
          163         mcontext_t                *trapenv;
          164 #elif defined(__APPLE__)
          165         struct i386_thread_state *trapenv;
          166 #else
          167         sigjmp_buf        *trapenv;
          168 #endif
          169 
          170         // General emulation state
          171         uint32_t        emuflags;        // Emulation flags (see below)
          172         uint32_t        jmpinfo;        // for jump insn backpatching
          173 
          174         // Max # of instructions to execute before returning
          175         uint32_t        insncount;
          176 
          177         // Instruction scanning/translation state
          178         struct vxfrag        *txfrag;        // frag currently under construction
          179         uint8_t                *ininst;        // current instruction being scanned
          180 
          181         // Last guest fragment translated (debugging)
          182         uint8_t                *guestfrag;
          183         uint8_t                *guestfragend;
          184 
          185         // Save area for host segment registers while running VX code
          186         uint16_t        host_ss;        // host ss
          187         uint16_t        host_ds;        // host ds
          188         uint16_t        host_es;        // host es
          189         uint16_t        host_vs;        // host fs/gs (which is os-dependent)
          190 
          191 #ifdef        __i386                // x86-32
          192 
          193         // Save area for the host's esp while running emulated code
          194         uint32_t        host_esp;
          195 
          196 #else                        // x86-64
          197 
          198         // Save area for the host's rsp while running emulated code
          199         uint64_t        host_rsp;
          200 
          201         // Far pointers for switching to and from 32-bit compatibility mode
          202         struct {
          203                 uint32_t ofs;
          204                 uint16_t sel;
          205         } runptr, retptr;
          206 
          207 #endif                        // x86-64
          208 
          209         // Translated code buffer.
          210         // We write code frags into it from the bottom up, increasing codefree.
          211         // Each frag consists of a vxfrag, a translation summary, and the code.
          212         // We also keep a table of offsets of all the vxfrag headers,
          213         // starting at the top of the codebuf and working down, via codetab.
          214         // The frag header offsets are thus stored in opposite order
          215         // as the target code fragments themselves,
          216         // and the codefree and codefrags pointers work towared each other
          217         // until they collide, at which point the translation buffer is reset.
          218         void                *codebuf;
          219         void                *codefree;
          220         void                *codetab;
          221         void                *codetop;
          222 
          223         // Hash table for looking up entrypoints in original code
          224         uint32_t        etablen;        // Number of entries (power of two)
          225         uint32_t        etabmask;        // etablen-1
          226         uint32_t        etabcnt;        // Number of entries currently in use
          227         struct vxentry        etab[0];        // Must be last!
          228 };
          229 
          230 // Hash function for entrypoint hash table.
          231 // Keep it consistent with assembly code in x86asm.S!
          232 #define etabhash(va)        (((((va) >> 10) + (va)) >> 10) - (va))
          233 
          234 // Emulation flags (emuflags)
          235 #define EMU_FP                0x01        // Enable SSE2 scalar floating-point
          236 #define EMU_VFP                0x02        // Enable vector floating-point
          237 #define EMU_VINT        0x04        // Enable vector integer arithmetic
          238 
          239 int vxemu_init(vxproc*);
          240 void vxemu_free(vxemu*);
          241 int vxemu_map(vxemu*, vxmmap*);
          242 
          243 void vxemu_flush(vxemu*);
          244 
          245 int        vxrun(vxemu*, uint32_t dsteip);
          246 void        vxrun_nullfrag(void);
          247 void        vxrun_setup(vxemu*);
          248 void        vxrun_cleanup(vxemu*);
          249 void        vxprint(char*, ...);
          250 
          251 int        vx32_sighandler(int, siginfo_t*, void*);
          252 int        vxemu_sighandler(vxemu*, uint32_t);
          253 
          254 #define USED(x) if(x){}        /* shut up gcc not-used warning */
          255 
          256 #endif  // VX32_IMPL_H
          257