blob: c2babb3c65769ffa4d2c3dd1df9da39e27b0cfa1 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- The JITter proper: register allocation & code improvement ---*/
njn3cbfbc12005-05-13 23:11:40 +00004/*--- m_translate.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005/*--------------------------------------------------------------------*/
6
7/*
njnb9c427c2004-12-01 14:14:42 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
sewardjde4a1d02002-03-22 01:27:54 +000010
njn53612422005-03-12 16:22:54 +000011 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
njnc7561b92005-06-19 01:24:32 +000032#include "pub_core_basics.h"
sewardj55f9d1a2005-04-25 11:11:44 +000033#include "pub_core_aspacemgr.h"
njn68980862005-06-18 18:31:26 +000034#include "pub_core_cpuid.h"
njn97405b22005-06-02 03:39:33 +000035#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000036#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000037#include "pub_core_libcprint.h"
njn20242342005-05-16 23:31:24 +000038#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000039#include "pub_core_profile.h"
njn24a6efb2005-06-20 03:36:51 +000040#include "pub_core_redir.h" // For VG_(code_redirect)()
41#include "pub_core_signals.h" // For VG_(synth_fault_{perms,mapping})()
42#include "pub_core_tooliface.h" // For VG_(tdict)
njn8bddf582005-05-13 23:40:55 +000043#include "pub_core_translate.h"
44#include "pub_core_transtab.h"
sewardjde4a1d02002-03-22 01:27:54 +000045
njna1f783f2005-06-18 03:44:34 +000046/*------------------------------------------------------------*/
47/*--- Determining arch/subarch. ---*/
48/*------------------------------------------------------------*/
49
50// Returns the architecture and subarchitecture, or indicates
51// that this subarchitecture is unable to run Valgrind
52// Returns False to indicate we cannot proceed further.
53static Bool getArchAndSubArch( /*OUT*/VexArch* vex_arch,
54 /*OUT*/VexSubArch* vex_subarch )
55{
56#if defined(VGA_x86)
57 Bool have_sse0, have_sse1, have_sse2;
58 UInt eax, ebx, ecx, edx;
59
60 if (!VG_(has_cpuid)())
61 /* we can't do cpuid at all. Give up. */
62 return False;
63
64 VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
65 if (eax < 1)
66 /* we can't ask for cpuid(x) for x > 0. Give up. */
67 return False;
68
69 /* get capabilities bits into edx */
70 VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
71
72 have_sse0 = (edx & (1<<24)) != 0; /* True => have fxsave/fxrstor */
73 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
74 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
75
76 if (have_sse2 && have_sse1 && have_sse0) {
77 *vex_arch = VexArchX86;
78 *vex_subarch = VexSubArchX86_sse2;
79 return True;
80 }
81
82 if (have_sse1 && have_sse0) {
83 *vex_arch = VexArchX86;
84 *vex_subarch = VexSubArchX86_sse1;
85 return True;
86 }
87
88 if (have_sse0) {
89 *vex_arch = VexArchX86;
90 *vex_subarch = VexSubArchX86_sse0;
91 return True;
92 }
93
94 /* we need at least SSE state to operate. */
95 return False;
96#elif defined(VGA_amd64)
97 vg_assert(VG_(has_cpuid)());
98 *vex_arch = VexArchAMD64;
99 *vex_subarch = VexSubArch_NONE;
100 return True;
101#else
102# error Unknown architecture
103#endif
104}
105
sewardjde4a1d02002-03-22 01:27:54 +0000106
nethercotebee3fd92004-08-02 15:17:43 +0000107/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +0000108/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +0000109/*------------------------------------------------------------*/
110
njna1f783f2005-06-18 03:44:34 +0000111static Bool need_to_handle_SP_assignment(void)
112{
113 return ( VG_(tdict).track_new_mem_stack_4 ||
114 VG_(tdict).track_die_mem_stack_4 ||
115 VG_(tdict).track_new_mem_stack_8 ||
116 VG_(tdict).track_die_mem_stack_8 ||
117 VG_(tdict).track_new_mem_stack_12 ||
118 VG_(tdict).track_die_mem_stack_12 ||
119 VG_(tdict).track_new_mem_stack_16 ||
120 VG_(tdict).track_die_mem_stack_16 ||
121 VG_(tdict).track_new_mem_stack_32 ||
122 VG_(tdict).track_die_mem_stack_32 ||
123 VG_(tdict).track_new_mem_stack ||
124 VG_(tdict).track_die_mem_stack );
125}
126
sewardj8b635a42004-11-22 19:01:47 +0000127/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +0000128
nethercote996901a2004-08-03 13:29:09 +0000129/* For tools that want to know about %ESP changes, this pass adds
130 in the appropriate hooks. We have to do it after the tool's
131 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +0000132 it adds in, and we must do it before register allocation because
133 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +0000134 Thus we have it as an extra phase between the two.
135
136 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
137 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
138 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
139 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
140 instruction clobbers t_ESP, we don't track it anymore, and fall back to
141 the delta-is-unknown case. That case is also used when the delta is not
142 a nice small amount, or an unknown amount.
143*/
sewardjde4a1d02002-03-22 01:27:54 +0000144
145static
sewardj8b635a42004-11-22 19:01:47 +0000146IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +0000147 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +0000148{
sewardj7cf97ee2004-11-28 14:25:01 +0000149 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +0000150 IRDirty *dcall, *d;
151 IRStmt* st;
152 IRExpr* e;
153 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +0000154 IRTemp curr;
155 IRType typeof_SP;
156 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +0000157
sewardj8b635a42004-11-22 19:01:47 +0000158 /* Set up BB */
159 IRBB* bb = emptyIRBB();
160 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
161 bb->next = dopyIRExpr(bb_in->next);
162 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +0000163
sewardj7cf97ee2004-11-28 14:25:01 +0000164 curr = IRTemp_INVALID;
165 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000166
sewardj7cf97ee2004-11-28 14:25:01 +0000167 sizeof_SP = layout->sizeof_SP;
168 offset_SP = layout->offset_SP;
169 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +0000170 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +0000171
sewardj8b635a42004-11-22 19:01:47 +0000172# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
173# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +0000174
sewardj8b635a42004-11-22 19:01:47 +0000175# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +0000176
sewardj8b635a42004-11-22 19:01:47 +0000177# define GET_CONST(con) \
178 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
179 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000180
sewardj8b635a42004-11-22 19:01:47 +0000181# define DO(kind, syze) \
182 do { \
njn51d827b2005-05-09 01:02:08 +0000183 if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000184 goto generic; \
185 \
186 /* I don't know if it's really necessary to say that the */ \
187 /* call reads the stack pointer. But anyway, we do. */ \
188 dcall = unsafeIRDirty_0_N( \
189 1/*regparms*/, \
190 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000191 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000192 mkIRExprVec_1(IRExpr_Tmp(curr)) \
193 ); \
194 dcall->nFxState = 1; \
195 dcall->fxState[0].fx = Ifx_Read; \
196 dcall->fxState[0].offset = layout->offset_SP; \
197 dcall->fxState[0].size = layout->sizeof_SP; \
198 \
199 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
200 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000201
sewardj8b635a42004-11-22 19:01:47 +0000202 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000203
sewardj8b635a42004-11-22 19:01:47 +0000204 st = bb_in->stmts[i];
205 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000206 continue;
207
sewardj8b635a42004-11-22 19:01:47 +0000208 /* t = Get(sp): curr = t, delta = 0 */
209 if (st->tag != Ist_Tmp) goto case2;
210 e = st->Ist.Tmp.data;
211 if (e->tag != Iex_Get) goto case2;
212 if (e->Iex.Get.offset != offset_SP) goto case2;
213 if (e->Iex.Get.ty != typeof_SP) goto case2;
214 curr = st->Ist.Tmp.tmp;
215 delta = 0;
216 addStmtToIRBB( bb, st );
217 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000218
sewardj8b635a42004-11-22 19:01:47 +0000219 case2:
220 /* t' = curr +/- const: curr = t', delta +=/-= const */
221 if (st->tag != Ist_Tmp) goto case3;
222 e = st->Ist.Tmp.data;
223 if (e->tag != Iex_Binop) goto case3;
224 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
225 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
226 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
227 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
228 curr = st->Ist.Tmp.tmp;
229 if (IS_ADD(e->Iex.Binop.op))
230 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
231 else
232 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
233 addStmtToIRBB( bb, st );
234 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000235
sewardj8b635a42004-11-22 19:01:47 +0000236 case3:
237 /* t' = curr: curr = t' */
238 if (st->tag != Ist_Tmp) goto case4;
239 e = st->Ist.Tmp.data;
240 if (e->tag != Iex_Tmp) goto case4;
241 if (e->Iex.Tmp.tmp != curr) goto case4;
242 curr = st->Ist.Tmp.tmp;
243 addStmtToIRBB( bb, st );
244 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000245
sewardj8b635a42004-11-22 19:01:47 +0000246 case4:
247 /* Put(sp) = curr */
248 if (st->tag != Ist_Put) goto case5;
249 if (st->Ist.Put.offset != offset_SP) goto case5;
250 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
251 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
252 switch (delta) {
253 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
254 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
255 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
256 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
257 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
258 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
259 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
260 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
261 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
262 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
263 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
264 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000265 }
sewardj8b635a42004-11-22 19:01:47 +0000266 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000267 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000268 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000269 /* Pass both the old and new SP values to this helper. */
270 old_SP = newIRTemp(bb->tyenv, typeof_SP);
271 addStmtToIRBB(
272 bb,
273 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
274 );
sewardjde4a1d02002-03-22 01:27:54 +0000275
sewardj2a99cf62004-11-24 10:44:19 +0000276 dcall = unsafeIRDirty_0_N(
277 2/*regparms*/,
278 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
279 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
280 );
sewardj8b635a42004-11-22 19:01:47 +0000281 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000282
283 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000284
sewardj8b635a42004-11-22 19:01:47 +0000285 curr = st->Ist.Put.data->Iex.Tmp.tmp;
286 delta = 0;
287 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000288 }
289
sewardj8b635a42004-11-22 19:01:47 +0000290 case5:
291 /* PutI or Dirty call which overlaps SP: complain. We can't
292 deal with SP changing in weird ways (well, we can, but not at
293 this time of night). */
294 if (st->tag == Ist_PutI) {
295 descr = st->Ist.PutI.descr;
296 minoff_ST = descr->base;
297 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
298 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
299 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000300 }
sewardj8b635a42004-11-22 19:01:47 +0000301 if (st->tag == Ist_Dirty) {
302 d = st->Ist.Dirty.details;
303 for (j = 0; j < d->nFxState; j++) {
304 minoff_ST = d->fxState[j].offset;
305 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
306 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
307 continue;
308 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
309 goto complain;
310 }
311 }
sewardjde4a1d02002-03-22 01:27:54 +0000312
sewardj8b635a42004-11-22 19:01:47 +0000313 /* well, not interesting. Just copy and keep going. */
314 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000315
sewardj8b635a42004-11-22 19:01:47 +0000316 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000317
sewardj8b635a42004-11-22 19:01:47 +0000318 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000319
sewardj8b635a42004-11-22 19:01:47 +0000320 complain:
321 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000322
323}
sewardj7c4b6042003-06-14 15:47:15 +0000324
sewardjde4a1d02002-03-22 01:27:54 +0000325
sewardjde4a1d02002-03-22 01:27:54 +0000326
sewardj8b635a42004-11-22 19:01:47 +0000327#if 0
328 for (i = 0; i < bb_in->stmts_used; i++) {
329 st = bb_in->stmts[i];
330 if (!st)
331 continue;
332 if (st->tag != Ist_Put)
333 goto boring;
334 offP = st->Ist.Put.offset;
335 if (offP != layout->offset_SP)
336 goto boring;
337 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
338 if (szP != layout->sizeof_SP)
339 goto boring;
340 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000341
sewardj8b635a42004-11-22 19:01:47 +0000342 /* I don't know if it's really necessary to say that the call reads
343 the stack pointer. But anyway, we do. */
344 dcall = unsafeIRDirty_0_N(
345 mkIRCallee(1, "VG_(unknown_esp_update)",
346 (HWord)&VG_(unknown_esp_update)),
347 mkIRExprVec_1(st->Ist.Put.data)
348 );
349 dcall->nFxState = 1;
350 dcall->fxState[0].fx = Ifx_Read;
351 dcall->fxState[0].offset = layout->offset_SP;
352 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000353
sewardj8b635a42004-11-22 19:01:47 +0000354 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
355
356 boring:
357 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000358 }
sewardj8b635a42004-11-22 19:01:47 +0000359#endif
360
sewardjde4a1d02002-03-22 01:27:54 +0000361
sewardjde4a1d02002-03-22 01:27:54 +0000362/*------------------------------------------------------------*/
363/*--- Main entry point for the JITter. ---*/
364/*------------------------------------------------------------*/
365
sewardj8b635a42004-11-22 19:01:47 +0000366/* Vex dumps the final code in here. Then we can copy it off
367 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000368#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000369static UChar tmpbuf[N_TMPBUF];
370
371/* Function pointers we must supply to LibVEX in order that it
372 can bomb out and emit messages under Valgrind's control. */
373__attribute__ ((noreturn))
374static
375void failure_exit ( void )
376{
sewardjbf426512005-01-17 18:35:30 +0000377 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000378 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000379}
380
381static
sewardjb5f6f512005-03-10 23:59:00 +0000382void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000383{
384 Int i;
385 for (i = 0; i < nbytes-3; i += 4)
386 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
387 for (; i < nbytes; i++)
388 VG_(printf)("%c", bytes[i]);
389}
390
nethercote59a122d2004-08-03 17:16:51 +0000391/* Translate the basic block beginning at orig_addr, and add it to
392 the translation cache & translation table. Unless 'debugging' is true,
393 in which case the call is being done for debugging purposes, so
394 (a) throw away the translation once it is made, and (b) produce a
395 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000396
nethercote59a122d2004-08-03 17:16:51 +0000397 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000398*/
sewardj8b635a42004-11-22 19:01:47 +0000399
400/* This stops Vex from chasing into function entry points that we wish
401 to redirect. Chasing across them obviously defeats the redirect
402 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
403 others. */
404static Bool chase_into_ok ( Addr64 addr64 )
405{
406 Addr addr = (Addr)addr64;
407 if (addr != VG_(code_redirect)(addr)) {
408 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
409 return False;
410 } else {
411 return True; /* ok to chase into 'addr' */
412 }
413}
414
sewardjfa8ec112005-01-19 11:55:34 +0000415Bool VG_(translate) ( ThreadId tid,
416 Addr64 orig_addr,
417 Bool debugging_translation,
njn394213a2005-06-19 18:38:24 +0000418 Int debugging_verbosity,
419 ULong bbs_done )
sewardjde4a1d02002-03-22 01:27:54 +0000420{
sewardjfa8ec112005-01-19 11:55:34 +0000421 Addr64 redir, orig_addr0 = orig_addr;
422 Int tmpbuf_used, verbosity;
sewardjc771b292004-11-30 18:55:21 +0000423 Bool notrace_until_done;
424 UInt notrace_until_limit = 0;
425 Segment* seg;
sewardjfa8ec112005-01-19 11:55:34 +0000426 VexGuestExtents vge;
sewardjde4a1d02002-03-22 01:27:54 +0000427
njn36932cb2005-05-11 22:45:48 +0000428 /* Indicates what arch and subarch we are running on. */
429 static VexArch vex_arch = VexArch_INVALID;
430 static VexSubArch vex_subarch = VexSubArch_INVALID;
431
sewardj8b635a42004-11-22 19:01:47 +0000432 /* Make sure Vex is initialised right. */
sewardjbf426512005-01-17 18:35:30 +0000433 VexTranslateResult tres;
sewardj8b635a42004-11-22 19:01:47 +0000434 static Bool vex_init_done = False;
435
436 if (!vex_init_done) {
njna1f783f2005-06-18 03:44:34 +0000437 Bool ok = getArchAndSubArch( &vex_arch, &vex_subarch );
njn36932cb2005-05-11 22:45:48 +0000438 if (!ok) {
439 VG_(printf)("\n");
440 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
441 VG_(printf)(" Supported CPUs are:\n");
442 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
443 "AMD Athlon or above)\n");
444 VG_(printf)("\n");
445 VG_(exit)(1);
446 }
447 if (VG_(clo_verbosity) > 2) {
448 VG_(message)(Vg_DebugMsg,
449 "Host CPU: arch = %s, subarch = %s",
450 LibVEX_ppVexArch ( vex_arch ),
451 LibVEX_ppVexSubArch( vex_subarch ) );
452 }
453
sewardj8b635a42004-11-22 19:01:47 +0000454 LibVEX_Init ( &failure_exit, &log_bytes,
455 1, /* debug_paranoia */
456 False, /* valgrind support */
457 &VG_(clo_vex_control) );
458 vex_init_done = True;
459 }
460
461 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000462 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000463
sewardj25c7c3a2003-07-10 00:17:58 +0000464 /* Look in the code redirect table to see if we should
465 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000466 redir = VG_(code_redirect)(orig_addr);
467
nethercote59a122d2004-08-03 17:16:51 +0000468 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardjfa8ec112005-01-19 11:55:34 +0000469 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +0000470 Char name1[64] = "";
471 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +0000472 name1[0] = name2[0] = 0;
473 ok = VG_(get_fnname_w_offset)(orig_addr, name1, 64);
njnbe73f432005-03-26 21:34:45 +0000474 if (!ok) VG_(strcpy)(name1, "???");
sewardjfa8ec112005-01-19 11:55:34 +0000475 ok = VG_(get_fnname_w_offset)(redir, name2, 64);
njnbe73f432005-03-26 21:34:45 +0000476 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +0000477 VG_(message)(Vg_DebugMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000478 "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj8b635a42004-11-22 19:01:47 +0000479 orig_addr, name1,
480 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000481 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000482 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000483
sewardja60be0e2003-05-26 08:47:27 +0000484 /* If codegen tracing, don't start tracing until
485 notrace_until_limit blocks have gone by. This avoids printing
486 huge amounts of useless junk when all we want to see is the last
487 few blocks translated prior to a failure. Set
488 notrace_until_limit to be the number of translations to be made
489 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +0000490 notrace_until_done
491 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000492
fitzhardinge98abfc72003-12-16 02:05:15 +0000493 seg = VG_(find_segment)(orig_addr);
494
njn25e49d8e72002-09-23 09:36:25 +0000495 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000496 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000497
sewardj85ac6d42005-02-23 11:36:56 +0000498 /* If doing any code printing, print a basic block start marker */
499 if (VG_(clo_trace_flags) || debugging_translation) {
500 Char fnname[64] = "";
501 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
502 VG_(printf)(
njn394213a2005-06-19 18:38:24 +0000503 "==== BB %d %s(0x%llx) BBs exec'd %lld ====\n",
sewardj85ac6d42005-02-23 11:36:56 +0000504 VG_(get_bbs_translated)(), fnname, orig_addr,
njn394213a2005-06-19 18:38:24 +0000505 bbs_done);
sewardj85ac6d42005-02-23 11:36:56 +0000506 }
507
fitzhardinge98abfc72003-12-16 02:05:15 +0000508 if (seg == NULL ||
509 !VG_(seg_contains)(seg, orig_addr, 1) ||
510 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000511 /* Code address is bad - deliver a signal instead */
sewardjb5f6f512005-03-10 23:59:00 +0000512 vg_assert(!VG_(is_addressable)(orig_addr, 1,
513 VKI_PROT_READ|VKI_PROT_EXEC));
fitzhardinge98abfc72003-12-16 02:05:15 +0000514
fitzhardinge98abfc72003-12-16 02:05:15 +0000515 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000516 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
517 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000518 } else
sewardj8b635a42004-11-22 19:01:47 +0000519 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000520
nethercote4d714382004-10-13 09:47:24 +0000521 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000522 } else
sewardj8b635a42004-11-22 19:01:47 +0000523 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000524
njn25e49d8e72002-09-23 09:36:25 +0000525 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000526 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +0000527 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +0000528 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +0000529 }
530 else
sewardjfa8ec112005-01-19 11:55:34 +0000531 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +0000532 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +0000533 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +0000534 }
njn25e49d8e72002-09-23 09:36:25 +0000535
njn31513b42005-06-01 03:09:59 +0000536 VGP_PUSHCC(VgpVexTime);
537
sewardj8b635a42004-11-22 19:01:47 +0000538 /* Actually do the translation. */
njn51d827b2005-05-09 01:02:08 +0000539 tl_assert2(VG_(tdict).tool_instrument,
540 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj8b635a42004-11-22 19:01:47 +0000541 tres = LibVEX_Translate (
njn36932cb2005-05-11 22:45:48 +0000542 vex_arch, vex_subarch,
543 vex_arch, vex_subarch,
sewardjb5f6f512005-03-10 23:59:00 +0000544 (UChar*)ULong_to_Ptr(orig_addr),
sewardjfa8ec112005-01-19 11:55:34 +0000545 (Addr64)orig_addr,
sewardj8b635a42004-11-22 19:01:47 +0000546 chase_into_ok,
sewardjfa8ec112005-01-19 11:55:34 +0000547 &vge,
sewardj8b635a42004-11-22 19:01:47 +0000548 tmpbuf, N_TMPBUF, &tmpbuf_used,
njn51d827b2005-05-09 01:02:08 +0000549 VG_(tdict).tool_instrument,
njnbd2e75c2004-11-24 16:43:43 +0000550 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000551 ? vg_SP_update_pass
552 : NULL,
553 True, /* cleanup after instrumentation */
554 NULL,
sewardjc771b292004-11-30 18:55:21 +0000555 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000556 );
njn25e49d8e72002-09-23 09:36:25 +0000557
sewardjbf426512005-01-17 18:35:30 +0000558 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +0000559 vg_assert(tmpbuf_used <= N_TMPBUF);
560 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000561
njn31513b42005-06-01 03:09:59 +0000562 VGP_POPCC(VgpVexTime);
563
sewardjc771b292004-11-30 18:55:21 +0000564#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000565
nethercote59a122d2004-08-03 17:16:51 +0000566 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +0000567 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000568
569 // If debugging, don't do anything with the translated block; we
570 // only did this for the debugging output produced along the way.
571 if (!debugging_translation) {
572 // Note that we use orig_addr0, not orig_addr, which might have been
573 // changed by the redirection
njn8bddf582005-05-13 23:40:55 +0000574 VG_(add_to_transtab)( &vge,
575 orig_addr0,
576 (Addr)(&tmpbuf[0]),
577 tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000578 }
nethercote59a122d2004-08-03 17:16:51 +0000579
njn25e49d8e72002-09-23 09:36:25 +0000580 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000581
582 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000583}
584
585/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +0000586/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000587/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000588