blob: f3b76d5169b064ee66c9a03777e446ef1b5446f7 [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardjc0ee2ed2004-07-27 10:29:41 +00004/*--- This file (main/vex_main.c) is ---*/
sewardj35421a32004-07-05 13:12:34 +00005/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
sewardj887a11a2004-07-05 17:26:47 +00009#include "libvex.h"
sewardj81ec4182004-10-25 23:15:52 +000010#include "libvex_guest_x86.h"
sewardjf13a16a2004-07-05 17:10:14 +000011
sewardjc0ee2ed2004-07-27 10:29:41 +000012#include "main/vex_globals.h"
13#include "main/vex_util.h"
14#include "host-generic/h_generic_regs.h"
15#include "host-x86/hdefs.h"
16#include "guest-x86/gdefs.h"
sewardjedf4d692004-08-17 13:52:58 +000017#include "ir/iropt.h"
sewardj35421a32004-07-05 13:12:34 +000018
19
20/* This file contains the top level interface to the library. */
21
22/* --------- Initialise the library. --------- */
23
24/* Exported to library client. */
25
sewardj08613742004-10-25 13:01:45 +000026void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
27{
28 vcon->iropt_verbosity = 0;
29 vcon->iropt_level = 2;
30 vcon->iropt_precise_memory_exns = False;
31 vcon->iropt_unroll_thresh = 120;
32 vcon->guest_max_insns = 50;
33 vcon->guest_chase_thresh = 10;
34}
35
36
37/* Exported to library client. */
38
sewardj887a11a2004-07-05 17:26:47 +000039void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000040 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000041 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000042 void (*failure_exit) ( void ),
43 /* logging output function */
44 void (*log_bytes) ( Char*, Int nbytes ),
45 /* debug paranoia level */
46 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +000047 /* Are we supporting valgrind checking? */
48 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +000049 /* Control ... */
50 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +000051)
52{
sewardj08613742004-10-25 13:01:45 +000053 /* First off, do enough minimal setup so that the following
54 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +000055 vex_failure_exit = failure_exit;
56 vex_log_bytes = log_bytes;
57
58 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +000059 vassert(!vex_initdone);
60 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +000061 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +000062 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +000063
64 vassert(vcon->iropt_verbosity >= 0);
65 vassert(vcon->iropt_level >= 0);
66 vassert(vcon->iropt_level <= 2);
67 vassert(vcon->iropt_unroll_thresh >= 0);
68 vassert(vcon->iropt_unroll_thresh <= 400);
69 vassert(vcon->guest_max_insns >= 1);
70 vassert(vcon->guest_max_insns <= 100);
71 vassert(vcon->guest_chase_thresh >= 0);
72 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj443cd9d2004-07-18 23:06:45 +000073
sewardj81ec4182004-10-25 23:15:52 +000074 /* All the guest state structs must have an 8-aligned size. */
75 vassert(0 == sizeof(VexGuestX86State) % 8);
76
sewardjea602bc2004-10-14 21:40:12 +000077 /* Check that Vex has been built with sizes of basic types as
78 stated in priv/libvex_basictypes.h. Failure of any of these is
79 a serious configuration error and should be corrected
80 immediately. If any of these assertions fail you can fully
81 expect Vex not to work properly, if at all. */
82
83 vassert(1 == sizeof(UChar));
84 vassert(1 == sizeof(Char));
85 vassert(2 == sizeof(UShort));
86 vassert(2 == sizeof(Short));
87 vassert(4 == sizeof(UInt));
88 vassert(4 == sizeof(Int));
89 vassert(8 == sizeof(ULong));
90 vassert(8 == sizeof(Long));
91 vassert(4 == sizeof(Float));
92 vassert(8 == sizeof(Double));
93 vassert(1 == sizeof(Bool));
94 vassert(4 == sizeof(Addr32));
95 vassert(8 == sizeof(Addr64));
96
97 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
98 vassert(sizeof(void*) == sizeof(int*));
99 vassert(sizeof(void*) == sizeof(HWord));
100
101 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000102 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000103 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000104 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000105 vex_initdone = True;
106 LibVEX_SetAllocMode ( AllocModeTEMPORARY );
sewardj35421a32004-07-05 13:12:34 +0000107}
108
109
110/* --------- Make a translation. --------- */
111
112/* Exported to library client. */
113
sewardj887a11a2004-07-05 17:26:47 +0000114TranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +0000115 /* The instruction sets we are translating from and to. */
116 InsnSet iset_guest,
117 InsnSet iset_host,
118 /* IN: the block to translate, and its guest address. */
sewardj81bd5502004-07-21 18:49:27 +0000119 UChar* guest_bytes,
sewardj35421a32004-07-05 13:12:34 +0000120 Addr64 guest_bytes_addr,
121 /* OUT: the number of bytes actually read */
122 Int* guest_bytes_read,
123 /* IN: a place to put the resulting code, and its size */
sewardj81bd5502004-07-21 18:49:27 +0000124 UChar* host_bytes,
125 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +0000126 /* OUT: how much of the output area is used. */
127 Int* host_bytes_used,
sewardj49651f42004-10-28 22:11:04 +0000128 /* IN: optionally, two instrumentation functions. */
sewardjeeac8412004-11-02 00:26:55 +0000129 IRBB* (*instrument1) ( IRBB*, VexGuestLayout* ),
130 IRBB* (*instrument2) ( IRBB*, VexGuestLayout* ),
sewardj35421a32004-07-05 13:12:34 +0000131 /* IN: optionally, an access check function for guest code. */
sewardj58800ff2004-07-28 01:51:10 +0000132 Bool (*byte_accessible) ( Addr64 ),
sewardjf48ac192004-10-29 00:41:29 +0000133 /* IN: debug: trace vex activity at various points */
134 Int traceflags
sewardj35421a32004-07-05 13:12:34 +0000135)
136{
sewardj81bd5502004-07-21 18:49:27 +0000137 /* This the bundle of functions we need to do the back-end stuff
138 (insn selection, reg-alloc, assembly) whilst being insulated
139 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000140 HReg* available_real_regs;
141 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +0000142 Bool (*isMove) (HInstr*, HReg*, HReg*);
143 void (*getRegUsage) (HRegUsage*, HInstr*);
144 void (*mapRegs) (HRegRemap*, HInstr*);
145 HInstr* (*genSpill) ( HReg, Int );
146 HInstr* (*genReload) ( HReg, Int );
147 void (*ppInstr) ( HInstr* );
148 void (*ppReg) ( HReg );
sewardj8ea867b2004-10-30 19:03:02 +0000149 HInstrArray* (*iselBB) ( IRBB* );
sewardj443cd9d2004-07-18 23:06:45 +0000150 IRBB* (*bbToIR) ( UChar*, Addr64, Int*,
151 Bool(*)(Addr64), Bool );
sewardj81bd5502004-07-21 18:49:27 +0000152 Int (*emit) ( UChar*, Int, HInstr* );
sewardj84ff0652004-08-23 16:16:08 +0000153 IRExpr* (*specHelper) ( Char*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000154 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000155
sewardjeeac8412004-11-02 00:26:55 +0000156 VexGuestLayout* guest_layout;
157 Bool host_is_bigendian = False;
158 IRBB* irbb;
159 HInstrArray* vcode;
160 HInstrArray* rcode;
161 Int i, j, k, out_used, guest_sizeB;
162 UChar insn_bytes[32];
163 IRType guest_word_size;
sewardjf13a16a2004-07-05 17:10:14 +0000164
sewardj49651f42004-10-28 22:11:04 +0000165 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000166 available_real_regs = NULL;
167 n_available_real_regs = 0;
168 isMove = NULL;
169 getRegUsage = NULL;
170 mapRegs = NULL;
171 genSpill = NULL;
172 genReload = NULL;
173 ppInstr = NULL;
174 ppReg = NULL;
175 iselBB = NULL;
176 bbToIR = NULL;
177 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000178 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000179 preciseMemExnsFn = NULL;
sewardjc5fc7aa2004-10-27 23:00:55 +0000180 guest_word_size = Ity_INVALID;
sewardj36ca5132004-07-24 13:12:23 +0000181
sewardjf48ac192004-10-29 00:41:29 +0000182 vex_traceflags = traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000183
sewardj35421a32004-07-05 13:12:34 +0000184 vassert(vex_initdone);
sewardj443cd9d2004-07-18 23:06:45 +0000185 LibVEX_ClearTemporary(False);
sewardjf13a16a2004-07-05 17:10:14 +0000186
187 /* First off, check that the guest and host insn sets
188 are supported. */
189 switch (iset_host) {
190 case InsnSetX86:
191 getAllocableRegs_X86 ( &n_available_real_regs,
192 &available_real_regs );
193 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
194 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
195 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
196 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
197 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000198 ppInstr = (void(*)(HInstr*)) ppX86Instr;
199 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000200 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000201 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardjc9a65702004-07-07 16:32:57 +0000202 host_is_bigendian = False;
sewardjf13a16a2004-07-05 17:10:14 +0000203 break;
204 default:
sewardj887a11a2004-07-05 17:26:47 +0000205 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000206 }
207
208 switch (iset_guest) {
209 case InsnSetX86:
sewardj8d2291c2004-10-25 14:50:21 +0000210 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
211 bbToIR = bbToIR_X86Instr;
sewardj8d2291c2004-10-25 14:50:21 +0000212 specHelper = x86guest_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000213 guest_sizeB = sizeof(VexGuestX86State);
sewardjc5fc7aa2004-10-27 23:00:55 +0000214 guest_word_size = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000215 guest_layout = &x86guest_layout;
sewardjf13a16a2004-07-05 17:10:14 +0000216 break;
217 default:
sewardj887a11a2004-07-05 17:26:47 +0000218 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000219 }
220
sewardjf48ac192004-10-29 00:41:29 +0000221 if (vex_traceflags & VEX_TRACE_FE)
222 vex_printf("\n------------------------"
223 " Front end "
224 "------------------------\n\n");
225
sewardjf13a16a2004-07-05 17:10:14 +0000226 irbb = bbToIR ( guest_bytes,
227 guest_bytes_addr,
228 guest_bytes_read,
sewardjc9a65702004-07-07 16:32:57 +0000229 byte_accessible,
230 host_is_bigendian );
sewardjf13a16a2004-07-05 17:10:14 +0000231
232 if (irbb == NULL) {
233 /* Access failure. */
sewardj443cd9d2004-07-18 23:06:45 +0000234 LibVEX_ClearTemporary(False);
sewardjf48ac192004-10-29 00:41:29 +0000235 vex_traceflags = 0;
sewardjf13a16a2004-07-05 17:10:14 +0000236 return TransAccessFail;
237 }
sewardjaa59f942004-10-09 09:34:36 +0000238
239 /* If debugging, show the raw guest bytes for this bb. */
sewardjf48ac192004-10-29 00:41:29 +0000240 if (vex_traceflags & VEX_TRACE_FE) {
sewardjaa59f942004-10-09 09:34:36 +0000241 UChar* p = guest_bytes;
sewardjaa59f942004-10-09 09:34:36 +0000242 vex_printf(". 0 %llx %d\n.", guest_bytes_addr, *guest_bytes_read );
243 for (i = 0; i < *guest_bytes_read; i++)
244 vex_printf(" %02x", (Int)p[i] );
sewardjf48ac192004-10-29 00:41:29 +0000245 vex_printf("\n\n");
sewardjaa59f942004-10-09 09:34:36 +0000246 }
247
248 /* Sanity check the initial IR. */
sewardjc5fc7aa2004-10-27 23:00:55 +0000249 sanityCheckIRBB(irbb, guest_word_size);
sewardje8e9d732004-07-16 21:03:45 +0000250
sewardjedf4d692004-08-17 13:52:58 +0000251 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000252 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
253 guest_bytes_addr );
sewardjc5fc7aa2004-10-27 23:00:55 +0000254 sanityCheckIRBB(irbb, guest_word_size);
sewardjedf4d692004-08-17 13:52:58 +0000255
sewardjf48ac192004-10-29 00:41:29 +0000256 if (vex_traceflags & VEX_TRACE_OPT1) {
257 vex_printf("\n------------------------"
258 " After pre-instr IR optimisation "
259 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000260 ppIRBB ( irbb );
261 vex_printf("\n");
262 }
263
sewardjf13a16a2004-07-05 17:10:14 +0000264 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000265 if (instrument1)
266 irbb = (*instrument1)(irbb, guest_layout);
267 if (instrument2)
268 irbb = (*instrument2)(irbb, guest_layout);
269
sewardjf48ac192004-10-29 00:41:29 +0000270 if (vex_traceflags & VEX_TRACE_INST) {
271 vex_printf("\n------------------------"
272 " After instrumentation "
273 "------------------------\n\n");
274 ppIRBB ( irbb );
275 vex_printf("\n");
276 }
277
sewardj49651f42004-10-28 22:11:04 +0000278 if (instrument1 || instrument2)
sewardjc5fc7aa2004-10-27 23:00:55 +0000279 sanityCheckIRBB(irbb, guest_word_size);
sewardjf13a16a2004-07-05 17:10:14 +0000280
281 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000282 do_deadcode_BB( irbb );
283 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000284
285 if (vex_traceflags & VEX_TRACE_TREES) {
286 vex_printf("\n------------------------"
287 " After tree-building "
288 "------------------------\n\n");
289 ppIRBB ( irbb );
290 vex_printf("\n");
291 }
292
293 if (vex_traceflags & VEX_TRACE_VCODE)
294 vex_printf("\n------------------------"
295 " Instruction selection "
296 "------------------------\n");
297
sewardj8ea867b2004-10-30 19:03:02 +0000298 vcode = iselBB ( irbb );
sewardjf13a16a2004-07-05 17:10:14 +0000299
sewardjf48ac192004-10-29 00:41:29 +0000300 if (vex_traceflags & VEX_TRACE_VCODE)
301 vex_printf("\n");
302
sewardjf48ac192004-10-29 00:41:29 +0000303 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000304 for (i = 0; i < vcode->arr_used; i++) {
305 vex_printf("%3d ", i);
306 ppInstr(vcode->arr[i]);
307 vex_printf("\n");
308 }
sewardjfbcaf332004-07-08 01:46:01 +0000309 vex_printf("\n");
310 }
sewardjfbcaf332004-07-08 01:46:01 +0000311
sewardjf13a16a2004-07-05 17:10:14 +0000312 /* Register allocate. */
313 rcode = doRegisterAllocation ( vcode, available_real_regs,
314 n_available_real_regs,
315 isMove, getRegUsage, mapRegs,
sewardj81ec4182004-10-25 23:15:52 +0000316 genSpill, genReload, guest_sizeB,
sewardj2b515872004-07-05 20:50:45 +0000317 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000318
sewardjf48ac192004-10-29 00:41:29 +0000319 if (vex_traceflags & VEX_TRACE_RCODE) {
320 vex_printf("\n------------------------"
321 " Register-allocated code "
322 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000323 for (i = 0; i < rcode->arr_used; i++) {
324 vex_printf("%3d ", i);
325 ppInstr(rcode->arr[i]);
326 vex_printf("\n");
327 }
sewardjfbcaf332004-07-08 01:46:01 +0000328 vex_printf("\n");
329 }
sewardjfbcaf332004-07-08 01:46:01 +0000330
sewardj81bd5502004-07-21 18:49:27 +0000331 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000332 if (vex_traceflags & VEX_TRACE_ASM) {
333 vex_printf("\n------------------------"
334 " Assembly "
335 "------------------------\n\n");
336 }
337
sewardj81bd5502004-07-21 18:49:27 +0000338 out_used = 0; /* tracks along the host_bytes array */
339 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000340 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000341 ppInstr(rcode->arr[i]);
342 vex_printf("\n");
343 }
sewardj81bd5502004-07-21 18:49:27 +0000344 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000345 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000346 for (k = 0; k < j; k++)
sewardj86898e82004-07-22 17:26:12 +0000347 if (insn_bytes[k] < 16)
348 vex_printf("0%x ", (UInt)insn_bytes[k]);
349 else
350 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000351 vex_printf("\n\n");
352 }
sewardj81bd5502004-07-21 18:49:27 +0000353 if (out_used + j > host_bytes_size) {
354 LibVEX_ClearTemporary(False);
sewardjf48ac192004-10-29 00:41:29 +0000355 vex_traceflags = 0;
sewardj81bd5502004-07-21 18:49:27 +0000356 return TransOutputFull;
357 }
358 for (k = 0; k < j; k++) {
359 host_bytes[out_used] = insn_bytes[k];
360 out_used++;
361 }
362 vassert(out_used <= host_bytes_size);
363 }
364 *host_bytes_used = out_used;
365
sewardj1f40a0a2004-07-21 12:28:07 +0000366 LibVEX_ClearTemporary(False);
sewardjf13a16a2004-07-05 17:10:14 +0000367
sewardjf48ac192004-10-29 00:41:29 +0000368 vex_traceflags = 0;
sewardj35421a32004-07-05 13:12:34 +0000369 return TransOK;
370}
371
372
373
374/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000375/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000376/*---------------------------------------------------------------*/