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