vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | 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