main_main.c revision f48ac19a67a98af44fe452c8c2be4192ac94b62d
1
2/*---------------------------------------------------------------*/
3/*---                                                         ---*/
4/*--- This file (main/vex_main.c) is                          ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
6/*---                                                         ---*/
7/*---------------------------------------------------------------*/
8
9#include "libvex.h"
10#include "libvex_guest_x86.h"
11
12#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"
17#include "ir/iropt.h"
18
19
20/* This file contains the top level interface to the library. */
21
22/* --------- Initialise the library. --------- */
23
24/* Exported to library client. */
25
26void 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
39void LibVEX_Init (
40   /* failure exit function */
41   __attribute__ ((noreturn))
42   void (*failure_exit) ( void ),
43   /* logging output function */
44   void (*log_bytes) ( Char*, Int nbytes ),
45   /* debug paranoia level */
46   Int debuglevel,
47   /* Are we supporting valgrind checking? */
48   Bool valgrind_support,
49   /* Control ... */
50   /*READONLY*/VexControl* vcon
51)
52{
53   /* First off, do enough minimal setup so that the following
54      assertions can fail in a sane fashion, if need be. */
55   vex_failure_exit = failure_exit;
56   vex_log_bytes    = log_bytes;
57
58   /* Now it's safe to check parameters for sanity. */
59   vassert(!vex_initdone);
60   vassert(failure_exit);
61   vassert(log_bytes);
62   vassert(debuglevel >= 0);
63
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);
73
74   /* All the guest state structs must have an 8-aligned size. */
75   vassert(0 == sizeof(VexGuestX86State) % 8);
76
77   /* 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 .. */
102   vex_debuglevel         = debuglevel;
103   vex_valgrind_support   = valgrind_support;
104   vex_control            = *vcon;
105   vex_initdone           = True;
106   LibVEX_SetAllocMode ( AllocModeTEMPORARY );
107}
108
109
110/* --------- Make a translation. --------- */
111
112/* Exported to library client. */
113
114TranslateResult LibVEX_Translate (
115   /* 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. */
119   UChar* guest_bytes,
120   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 */
124   UChar* host_bytes,
125   Int    host_bytes_size,
126   /* OUT: how much of the output area is used. */
127   Int* host_bytes_used,
128   /* IN: optionally, two instrumentation functions. */
129   IRBB* (*instrument1) ( IRBB*, VexGuestLayoutInfo* ),
130   IRBB* (*instrument2) ( IRBB*, VexGuestLayoutInfo* ),
131   HWord (*tool_findhelper) ( Char* ),
132   /* IN: optionally, an access check function for guest code. */
133   Bool (*byte_accessible) ( Addr64 ),
134   /* IN: debug: trace vex activity at various points */
135   Int  traceflags
136)
137{
138   /* This the bundle of functions we need to do the back-end stuff
139      (insn selection, reg-alloc, assembly) whilst being insulated
140      from the target instruction set. */
141   HReg* available_real_regs;
142   Int   n_available_real_regs;
143   Bool         (*isMove)      (HInstr*, HReg*, HReg*);
144   void         (*getRegUsage) (HRegUsage*, HInstr*);
145   void         (*mapRegs)     (HRegRemap*, HInstr*);
146   HInstr*      (*genSpill)    ( HReg, Int );
147   HInstr*      (*genReload)   ( HReg, Int );
148   void         (*ppInstr)     ( HInstr* );
149   void         (*ppReg)       ( HReg );
150   HInstrArray* (*iselBB)      ( IRBB*, HWord(*)(Char*), HWord(*)(Char*) );
151   IRBB*        (*bbToIR)      ( UChar*, Addr64, Int*,
152                                         Bool(*)(Addr64), Bool );
153   Int          (*emit)        ( UChar*, Int, HInstr* );
154   HWord        (*findHelper)  ( Char* );
155   IRExpr*      (*specHelper)  ( Char*, IRExpr** );
156   Bool         (*preciseMemExnsFn) ( Int, Int );
157
158   VexGuestLayoutInfo* guest_layout;
159   Bool                host_is_bigendian = False;
160   IRBB*               irbb;
161   HInstrArray*        vcode;
162   HInstrArray*        rcode;
163   Int                 i, j, k, out_used, guest_sizeB;
164   UChar               insn_bytes[32];
165   IRType              guest_word_size;
166
167   guest_layout           = NULL;
168   available_real_regs    = NULL;
169   n_available_real_regs  = 0;
170   isMove                 = NULL;
171   getRegUsage            = NULL;
172   mapRegs                = NULL;
173   genSpill               = NULL;
174   genReload              = NULL;
175   ppInstr                = NULL;
176   ppReg                  = NULL;
177   iselBB                 = NULL;
178   bbToIR                 = NULL;
179   emit                   = NULL;
180   findHelper             = NULL;
181   specHelper             = NULL;
182   preciseMemExnsFn       = NULL;
183   guest_word_size        = Ity_INVALID;
184
185   vex_traceflags = traceflags;
186
187   vassert(vex_initdone);
188   LibVEX_ClearTemporary(False);
189
190   /* First off, check that the guest and host insn sets
191      are supported. */
192   switch (iset_host) {
193      case InsnSetX86:
194         getAllocableRegs_X86 ( &n_available_real_regs,
195                                &available_real_regs );
196         isMove      = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
197         getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
198         mapRegs     = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
199         genSpill    = (HInstr*(*)(HReg,Int)) genSpill_X86;
200         genReload   = (HInstr*(*)(HReg,Int)) genReload_X86;
201         ppInstr     = (void(*)(HInstr*)) ppX86Instr;
202         ppReg       = (void(*)(HReg)) ppHRegX86;
203         iselBB      = iselBB_X86;
204         emit        = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
205	 host_is_bigendian = False;
206         break;
207      default:
208         vpanic("LibVEX_Translate: unsupported target insn set");
209   }
210
211   switch (iset_guest) {
212      case InsnSetX86:
213         preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
214         bbToIR           = bbToIR_X86Instr;
215         findHelper       = x86guest_findhelper;
216         specHelper       = x86guest_spechelper;
217         guest_sizeB      = sizeof(VexGuestX86State);
218	 guest_word_size  = Ity_I32;
219         guest_layout     = &x86guest_layout;
220         break;
221      default:
222         vpanic("LibVEX_Translate: unsupported guest insn set");
223   }
224
225   if (vex_traceflags & VEX_TRACE_FE)
226      vex_printf("\n------------------------"
227                   " Front end "
228                   "------------------------\n\n");
229
230   irbb = bbToIR ( guest_bytes,
231		   guest_bytes_addr,
232		   guest_bytes_read,
233		   byte_accessible,
234		   host_is_bigendian );
235
236   if (irbb == NULL) {
237      /* Access failure. */
238      LibVEX_ClearTemporary(False);
239      vex_traceflags = 0;
240      return TransAccessFail;
241   }
242
243   /* If debugging, show the raw guest bytes for this bb. */
244   if (vex_traceflags & VEX_TRACE_FE) {
245      UChar* p = guest_bytes;
246      vex_printf(". 0 %llx %d\n.", guest_bytes_addr, *guest_bytes_read );
247      for (i = 0; i < *guest_bytes_read; i++)
248         vex_printf(" %02x", (Int)p[i] );
249      vex_printf("\n\n");
250   }
251
252   /* Sanity check the initial IR. */
253   sanityCheckIRBB(irbb, guest_word_size);
254
255   /* Clean it up, hopefully a lot. */
256   irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
257                              guest_bytes_addr );
258   sanityCheckIRBB(irbb, guest_word_size);
259
260   if (vex_traceflags & VEX_TRACE_OPT1) {
261      vex_printf("\n------------------------"
262                   " After pre-instr IR optimisation "
263                   "------------------------\n\n");
264      ppIRBB ( irbb );
265      vex_printf("\n");
266   }
267
268   /* Get the thing instrumented. */
269   if (instrument1)
270      irbb = (*instrument1)(irbb, guest_layout);
271   if (instrument2)
272      irbb = (*instrument2)(irbb, guest_layout);
273
274   if (vex_traceflags & VEX_TRACE_INST) {
275      vex_printf("\n------------------------"
276                   " After instrumentation "
277                   "------------------------\n\n");
278      ppIRBB ( irbb );
279      vex_printf("\n");
280   }
281
282   if (instrument1 || instrument2)
283      sanityCheckIRBB(irbb, guest_word_size);
284
285   /* Turn it into virtual-registerised code. */
286   do_deadcode_BB( irbb );
287   do_treebuild_BB( irbb );
288
289   if (vex_traceflags & VEX_TRACE_TREES) {
290      vex_printf("\n------------------------"
291                   "  After tree-building "
292                   "------------------------\n\n");
293      ppIRBB ( irbb );
294      vex_printf("\n");
295   }
296
297   if (vex_traceflags & VEX_TRACE_VCODE)
298      vex_printf("\n------------------------"
299                   " Instruction selection "
300                   "------------------------\n");
301
302   vcode = iselBB ( irbb, findHelper, tool_findhelper );
303
304   if (vex_traceflags & VEX_TRACE_VCODE)
305      vex_printf("\n");
306
307#if 0
308   if (vex_traceflags & VEX_TRACE_VCODE) {
309      vex_printf("\n-------- Virtual registerised code --------\n");
310      for (i = 0; i < vcode->arr_used; i++) {
311         vex_printf("%3d   ", i);
312         ppInstr(vcode->arr[i]);
313         vex_printf("\n");
314      }
315      vex_printf("\n");
316   }
317#endif
318
319   /* Register allocate. */
320   rcode = doRegisterAllocation ( vcode, available_real_regs,
321                  	       	  n_available_real_regs,
322			          isMove, getRegUsage, mapRegs,
323			          genSpill, genReload, guest_sizeB,
324				  ppInstr, ppReg );
325
326   if (vex_traceflags & VEX_TRACE_RCODE) {
327      vex_printf("\n------------------------"
328                   " Register-allocated code "
329                   "------------------------\n\n");
330      for (i = 0; i < rcode->arr_used; i++) {
331         vex_printf("%3d   ", i);
332         ppInstr(rcode->arr[i]);
333         vex_printf("\n");
334      }
335      vex_printf("\n");
336   }
337
338   /* Assemble */
339   if (vex_traceflags & VEX_TRACE_ASM) {
340      vex_printf("\n------------------------"
341                   " Assembly "
342                   "------------------------\n\n");
343   }
344
345   out_used = 0; /* tracks along the host_bytes array */
346   for (i = 0; i < rcode->arr_used; i++) {
347      if (vex_traceflags & VEX_TRACE_ASM) {
348         ppInstr(rcode->arr[i]);
349         vex_printf("\n");
350      }
351      j = (*emit)( insn_bytes, 32, rcode->arr[i] );
352      if (vex_traceflags & VEX_TRACE_ASM) {
353         for (k = 0; k < j; k++)
354	    if (insn_bytes[k] < 16)
355               vex_printf("0%x ",  (UInt)insn_bytes[k]);
356            else
357               vex_printf("%x ", (UInt)insn_bytes[k]);
358         vex_printf("\n\n");
359      }
360      if (out_used + j > host_bytes_size) {
361         LibVEX_ClearTemporary(False);
362         vex_traceflags = 0;
363         return TransOutputFull;
364      }
365      for (k = 0; k < j; k++) {
366         host_bytes[out_used] = insn_bytes[k];
367         out_used++;
368      }
369      vassert(out_used <= host_bytes_size);
370   }
371   *host_bytes_used = out_used;
372
373   LibVEX_ClearTemporary(False);
374
375   vex_traceflags = 0;
376   return TransOK;
377}
378
379
380
381/*---------------------------------------------------------------*/
382/*--- end                                     main/vex_main.c ---*/
383/*---------------------------------------------------------------*/
384