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