main_main.c revision aa59f942f729b5c98703d84321265313daeb32b8
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
11#include "main/vex_globals.h"
12#include "main/vex_util.h"
13#include "host-generic/h_generic_regs.h"
14#include "host-x86/hdefs.h"
15#include "guest-x86/gdefs.h"
16#include "ir/iropt.h"
17
18
19/* This file contains the top level interface to the library. */
20
21/* --------- Initialise the library. --------- */
22
23/* Exported to library client. */
24
25void LibVEX_Init (
26   /* failure exit function */
27   __attribute__ ((noreturn))
28   void (*failure_exit) ( void ),
29   /* logging output function */
30   void (*log_bytes) ( Char*, Int nbytes ),
31   /* debug paranoia level */
32   Int debuglevel,
33   /* initial verbosity level */
34   Int verbosity,
35   /* Are we supporting valgrind checking? */
36   Bool valgrind_support,
37   /* Max # guest insns per bb */
38   Int guest_insns_per_bb
39)
40{
41   vassert(!vex_initdone);
42   vassert(failure_exit);
43   vassert(log_bytes);
44   vassert(debuglevel >= 0);
45   vassert(verbosity >= 0);
46   vassert(guest_insns_per_bb >= 1 && guest_insns_per_bb <= 100);
47
48   vex_failure_exit       = failure_exit;
49   vex_log_bytes          = log_bytes;
50   vex_debuglevel         = debuglevel;
51   vex_verbosity          = verbosity;
52   vex_valgrind_support   = valgrind_support;
53   vex_guest_insns_per_bb = guest_insns_per_bb;
54   vex_initdone           = True;
55   LibVEX_SetAllocMode ( AllocModeTEMPORARY );
56}
57
58
59/* --------- Make a translation. --------- */
60
61/* Exported to library client. */
62
63TranslateResult LibVEX_Translate (
64   /* The instruction sets we are translating from and to. */
65   InsnSet iset_guest,
66   InsnSet iset_host,
67   /* IN: the block to translate, and its guest address. */
68   UChar* guest_bytes,
69   Addr64 guest_bytes_addr,
70   /* OUT: the number of bytes actually read */
71   Int* guest_bytes_read,
72   /* IN: a place to put the resulting code, and its size */
73   UChar* host_bytes,
74   Int    host_bytes_size,
75   /* OUT: how much of the output area is used. */
76   Int* host_bytes_used,
77   /* IN: optionally, an instrumentation function. */
78   IRBB* (*instrument) ( IRBB* ),
79   /* IN: optionally, an access check function for guest code. */
80   Bool (*byte_accessible) ( Addr64 ),
81   /* IN: if > 0, use this verbosity for this bb */
82   Int  bb_verbosity
83)
84{
85   /* This the bundle of functions we need to do the back-end stuff
86      (insn selection, reg-alloc, assembly) whilst being insulated
87      from the target instruction set. */
88   HReg* available_real_regs;
89   Int   n_available_real_regs;
90   Bool         (*isMove)      (HInstr*, HReg*, HReg*);
91   void         (*getRegUsage) (HRegUsage*, HInstr*);
92   void         (*mapRegs)     (HRegRemap*, HInstr*);
93   HInstr*      (*genSpill)    ( HReg, Int );
94   HInstr*      (*genReload)   ( HReg, Int );
95   void         (*ppInstr)     ( HInstr* );
96   void         (*ppReg)       ( HReg );
97   HInstrArray* (*iselBB)      ( IRBB*, Addr64(*)(Char*) );
98   IRBB*        (*bbToIR)      ( UChar*, Addr64, Int*,
99                                         Bool(*)(Addr64), Bool );
100   Int          (*emit)        ( UChar*, Int, HInstr* );
101   Addr64       (*findHelper)  ( Char* );
102   IRExpr*      (*specHelper)  ( Char*, IRExpr** );
103
104   Bool         host_is_bigendian = False;
105   IRBB*        irbb;
106   HInstrArray* vcode;
107   HInstrArray* rcode;
108   Int          i, j, k, out_used, saved_verbosity;
109   UChar        insn_bytes[32];
110
111   available_real_regs    = NULL;
112   n_available_real_regs  = 0;
113   isMove                 = NULL;
114   getRegUsage            = NULL;
115   mapRegs                = NULL;
116   genSpill               = NULL;
117   genReload              = NULL;
118   ppInstr                = NULL;
119   ppReg                  = NULL;
120   iselBB                 = NULL;
121   bbToIR                 = NULL;
122   emit                   = NULL;
123   findHelper             = NULL;
124   specHelper             = NULL;
125
126   saved_verbosity = vex_verbosity;
127   if (bb_verbosity > 0)
128      vex_verbosity = bb_verbosity;
129
130   vassert(vex_initdone);
131   LibVEX_ClearTemporary(False);
132
133   /* First off, check that the guest and host insn sets
134      are supported. */
135   switch (iset_host) {
136      case InsnSetX86:
137         getAllocableRegs_X86 ( &n_available_real_regs,
138                                &available_real_regs );
139         isMove      = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
140         getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
141         mapRegs     = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
142         genSpill    = (HInstr*(*)(HReg,Int)) genSpill_X86;
143         genReload   = (HInstr*(*)(HReg,Int)) genReload_X86;
144         ppInstr     = (void(*)(HInstr*)) ppX86Instr;
145         ppReg       = (void(*)(HReg)) ppHRegX86;
146         iselBB      = iselBB_X86;
147         emit        = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
148	 host_is_bigendian = False;
149         break;
150      default:
151         vpanic("LibVEX_Translate: unsupported target insn set");
152   }
153
154   switch (iset_guest) {
155      case InsnSetX86:
156         bbToIR     = bbToIR_X86Instr;
157         findHelper = x86guest_findhelper;
158         specHelper = x86guest_spechelper;
159         break;
160      default:
161         vpanic("LibVEX_Translate: unsupported guest insn set");
162   }
163
164   irbb = bbToIR ( guest_bytes,
165		   guest_bytes_addr,
166		   guest_bytes_read,
167		   byte_accessible,
168		   host_is_bigendian );
169
170   if (irbb == NULL) {
171      /* Access failure. */
172      LibVEX_ClearTemporary(False);
173      vex_verbosity = saved_verbosity;
174      return TransAccessFail;
175   }
176
177   /* If debugging, show the raw guest bytes for this bb. */
178   if (vex_verbosity >= 2) {
179      UChar* p = guest_bytes;
180      vex_printf("\n");
181      vex_printf(". 0 %llx %d\n.", guest_bytes_addr, *guest_bytes_read );
182      for (i = 0; i < *guest_bytes_read; i++)
183         vex_printf(" %02x", (Int)p[i] );
184      vex_printf("\n");
185   }
186
187   /* Sanity check the initial IR. */
188   sanityCheckIRBB(irbb, Ity_I32);
189
190   /* Clean it up, hopefully a lot. */
191   irbb = do_iropt_BB ( irbb, specHelper );
192   sanityCheckIRBB(irbb, Ity_I32);
193
194   if (vex_verbosity > 0) {
195      vex_printf("\n-------- After IR optimisation --------\n");
196      ppIRBB ( irbb );
197      vex_printf("\n");
198   }
199
200   /* Get the thing instrumented. */
201   if (instrument)
202      irbb = (*instrument)(irbb);
203
204   /* Turn it into virtual-registerised code. */
205   vcode = iselBB ( irbb, findHelper );
206
207   if (vex_verbosity > 0) {
208      vex_printf("\n-------- Virtual registerised code --------\n");
209      for (i = 0; i < vcode->arr_used; i++) {
210         vex_printf("%3d   ", i);
211         ppInstr(vcode->arr[i]);
212         vex_printf("\n");
213      }
214      vex_printf("\n");
215   }
216
217   /* Register allocate. */
218   rcode = doRegisterAllocation ( vcode, available_real_regs,
219                  	       	  n_available_real_regs,
220			          isMove, getRegUsage, mapRegs,
221			          genSpill, genReload,
222				  ppInstr, ppReg );
223
224   if (vex_verbosity > 0) {
225      vex_printf("\n-------- Post-regalloc code --------\n");
226      for (i = 0; i < rcode->arr_used; i++) {
227         vex_printf("%3d   ", i);
228         ppInstr(rcode->arr[i]);
229         vex_printf("\n");
230      }
231      vex_printf("\n");
232   }
233
234   /* Assemble */
235   out_used = 0; /* tracks along the host_bytes array */
236   for (i = 0; i < rcode->arr_used; i++) {
237      if (vex_verbosity > 1) {
238         ppInstr(rcode->arr[i]);
239         vex_printf("\n");
240      }
241      j = (*emit)( insn_bytes, 32, rcode->arr[i] );
242      if (vex_verbosity > 1) {
243         for (k = 0; k < j; k++)
244	    if (insn_bytes[k] < 16)
245               vex_printf("0%x ",  (UInt)insn_bytes[k]);
246            else
247               vex_printf("%x ", (UInt)insn_bytes[k]);
248         vex_printf("\n\n");
249      }
250      if (out_used + j > host_bytes_size) {
251         LibVEX_ClearTemporary(False);
252         vex_verbosity = saved_verbosity;
253         return TransOutputFull;
254      }
255      for (k = 0; k < j; k++) {
256         host_bytes[out_used] = insn_bytes[k];
257         out_used++;
258      }
259      vassert(out_used <= host_bytes_size);
260   }
261   *host_bytes_used = out_used;
262
263   //   LibVEX_ClearTemporary(True);
264   LibVEX_ClearTemporary(False);
265
266   vex_verbosity = saved_verbosity;
267   return TransOK;
268}
269
270
271
272/*---------------------------------------------------------------*/
273/*--- end                                     main/vex_main.c ---*/
274/*---------------------------------------------------------------*/
275