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