blob: d64914d19a1eba24fe769f620290a77fcc42a44a [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"
33#include "pub_core_threadstate.h" // needed for pub_core_main.h
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
njn68980862005-06-18 18:31:26 +000035#include "pub_core_cpuid.h"
njn97405b22005-06-02 03:39:33 +000036#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000037#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000038#include "pub_core_libcprint.h"
njn04e16982005-05-31 00:23:43 +000039#include "pub_core_main.h" // for VG_(bbs_done)
njn20242342005-05-16 23:31:24 +000040#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000041#include "pub_core_profile.h"
njnd1af0032005-05-29 17:01:48 +000042#include "pub_core_redir.h"
njn0c246472005-05-31 01:00:08 +000043#include "pub_core_signals.h"
njn43b9a8a2005-05-10 04:37:01 +000044#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000045#include "pub_core_translate.h"
46#include "pub_core_transtab.h"
sewardjde4a1d02002-03-22 01:27:54 +000047
njna1f783f2005-06-18 03:44:34 +000048/*------------------------------------------------------------*/
49/*--- Determining arch/subarch. ---*/
50/*------------------------------------------------------------*/
51
52// Returns the architecture and subarchitecture, or indicates
53// that this subarchitecture is unable to run Valgrind
54// Returns False to indicate we cannot proceed further.
55static Bool getArchAndSubArch( /*OUT*/VexArch* vex_arch,
56 /*OUT*/VexSubArch* vex_subarch )
57{
58#if defined(VGA_x86)
59 Bool have_sse0, have_sse1, have_sse2;
60 UInt eax, ebx, ecx, edx;
61
62 if (!VG_(has_cpuid)())
63 /* we can't do cpuid at all. Give up. */
64 return False;
65
66 VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
67 if (eax < 1)
68 /* we can't ask for cpuid(x) for x > 0. Give up. */
69 return False;
70
71 /* get capabilities bits into edx */
72 VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
73
74 have_sse0 = (edx & (1<<24)) != 0; /* True => have fxsave/fxrstor */
75 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
76 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
77
78 if (have_sse2 && have_sse1 && have_sse0) {
79 *vex_arch = VexArchX86;
80 *vex_subarch = VexSubArchX86_sse2;
81 return True;
82 }
83
84 if (have_sse1 && have_sse0) {
85 *vex_arch = VexArchX86;
86 *vex_subarch = VexSubArchX86_sse1;
87 return True;
88 }
89
90 if (have_sse0) {
91 *vex_arch = VexArchX86;
92 *vex_subarch = VexSubArchX86_sse0;
93 return True;
94 }
95
96 /* we need at least SSE state to operate. */
97 return False;
98#elif defined(VGA_amd64)
99 vg_assert(VG_(has_cpuid)());
100 *vex_arch = VexArchAMD64;
101 *vex_subarch = VexSubArch_NONE;
102 return True;
103#else
104# error Unknown architecture
105#endif
106}
107
sewardjde4a1d02002-03-22 01:27:54 +0000108
nethercotebee3fd92004-08-02 15:17:43 +0000109/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +0000110/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +0000111/*------------------------------------------------------------*/
112
njna1f783f2005-06-18 03:44:34 +0000113static Bool need_to_handle_SP_assignment(void)
114{
115 return ( VG_(tdict).track_new_mem_stack_4 ||
116 VG_(tdict).track_die_mem_stack_4 ||
117 VG_(tdict).track_new_mem_stack_8 ||
118 VG_(tdict).track_die_mem_stack_8 ||
119 VG_(tdict).track_new_mem_stack_12 ||
120 VG_(tdict).track_die_mem_stack_12 ||
121 VG_(tdict).track_new_mem_stack_16 ||
122 VG_(tdict).track_die_mem_stack_16 ||
123 VG_(tdict).track_new_mem_stack_32 ||
124 VG_(tdict).track_die_mem_stack_32 ||
125 VG_(tdict).track_new_mem_stack ||
126 VG_(tdict).track_die_mem_stack );
127}
128
sewardj8b635a42004-11-22 19:01:47 +0000129/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +0000130
nethercote996901a2004-08-03 13:29:09 +0000131/* For tools that want to know about %ESP changes, this pass adds
132 in the appropriate hooks. We have to do it after the tool's
133 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +0000134 it adds in, and we must do it before register allocation because
135 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +0000136 Thus we have it as an extra phase between the two.
137
138 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
139 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
140 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
141 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
142 instruction clobbers t_ESP, we don't track it anymore, and fall back to
143 the delta-is-unknown case. That case is also used when the delta is not
144 a nice small amount, or an unknown amount.
145*/
sewardjde4a1d02002-03-22 01:27:54 +0000146
147static
sewardj8b635a42004-11-22 19:01:47 +0000148IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +0000149 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +0000150{
sewardj7cf97ee2004-11-28 14:25:01 +0000151 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +0000152 IRDirty *dcall, *d;
153 IRStmt* st;
154 IRExpr* e;
155 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +0000156 IRTemp curr;
157 IRType typeof_SP;
158 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +0000159
sewardj8b635a42004-11-22 19:01:47 +0000160 /* Set up BB */
161 IRBB* bb = emptyIRBB();
162 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
163 bb->next = dopyIRExpr(bb_in->next);
164 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +0000165
sewardj7cf97ee2004-11-28 14:25:01 +0000166 curr = IRTemp_INVALID;
167 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000168
sewardj7cf97ee2004-11-28 14:25:01 +0000169 sizeof_SP = layout->sizeof_SP;
170 offset_SP = layout->offset_SP;
171 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +0000172 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +0000173
sewardj8b635a42004-11-22 19:01:47 +0000174# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
175# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +0000176
sewardj8b635a42004-11-22 19:01:47 +0000177# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +0000178
sewardj8b635a42004-11-22 19:01:47 +0000179# define GET_CONST(con) \
180 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
181 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000182
sewardj8b635a42004-11-22 19:01:47 +0000183# define DO(kind, syze) \
184 do { \
njn51d827b2005-05-09 01:02:08 +0000185 if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000186 goto generic; \
187 \
188 /* I don't know if it's really necessary to say that the */ \
189 /* call reads the stack pointer. But anyway, we do. */ \
190 dcall = unsafeIRDirty_0_N( \
191 1/*regparms*/, \
192 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000193 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000194 mkIRExprVec_1(IRExpr_Tmp(curr)) \
195 ); \
196 dcall->nFxState = 1; \
197 dcall->fxState[0].fx = Ifx_Read; \
198 dcall->fxState[0].offset = layout->offset_SP; \
199 dcall->fxState[0].size = layout->sizeof_SP; \
200 \
201 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
202 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000203
sewardj8b635a42004-11-22 19:01:47 +0000204 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000205
sewardj8b635a42004-11-22 19:01:47 +0000206 st = bb_in->stmts[i];
207 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000208 continue;
209
sewardj8b635a42004-11-22 19:01:47 +0000210 /* t = Get(sp): curr = t, delta = 0 */
211 if (st->tag != Ist_Tmp) goto case2;
212 e = st->Ist.Tmp.data;
213 if (e->tag != Iex_Get) goto case2;
214 if (e->Iex.Get.offset != offset_SP) goto case2;
215 if (e->Iex.Get.ty != typeof_SP) goto case2;
216 curr = st->Ist.Tmp.tmp;
217 delta = 0;
218 addStmtToIRBB( bb, st );
219 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000220
sewardj8b635a42004-11-22 19:01:47 +0000221 case2:
222 /* t' = curr +/- const: curr = t', delta +=/-= const */
223 if (st->tag != Ist_Tmp) goto case3;
224 e = st->Ist.Tmp.data;
225 if (e->tag != Iex_Binop) goto case3;
226 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
227 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
228 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
229 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
230 curr = st->Ist.Tmp.tmp;
231 if (IS_ADD(e->Iex.Binop.op))
232 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
233 else
234 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
235 addStmtToIRBB( bb, st );
236 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000237
sewardj8b635a42004-11-22 19:01:47 +0000238 case3:
239 /* t' = curr: curr = t' */
240 if (st->tag != Ist_Tmp) goto case4;
241 e = st->Ist.Tmp.data;
242 if (e->tag != Iex_Tmp) goto case4;
243 if (e->Iex.Tmp.tmp != curr) goto case4;
244 curr = st->Ist.Tmp.tmp;
245 addStmtToIRBB( bb, st );
246 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000247
sewardj8b635a42004-11-22 19:01:47 +0000248 case4:
249 /* Put(sp) = curr */
250 if (st->tag != Ist_Put) goto case5;
251 if (st->Ist.Put.offset != offset_SP) goto case5;
252 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
253 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
254 switch (delta) {
255 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
256 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
257 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
258 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
259 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
260 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
261 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
262 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
263 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
264 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
265 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
266 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000267 }
sewardj8b635a42004-11-22 19:01:47 +0000268 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000269 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000270 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000271 /* Pass both the old and new SP values to this helper. */
272 old_SP = newIRTemp(bb->tyenv, typeof_SP);
273 addStmtToIRBB(
274 bb,
275 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
276 );
sewardjde4a1d02002-03-22 01:27:54 +0000277
sewardj2a99cf62004-11-24 10:44:19 +0000278 dcall = unsafeIRDirty_0_N(
279 2/*regparms*/,
280 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
281 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
282 );
sewardj8b635a42004-11-22 19:01:47 +0000283 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000284
285 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000286
sewardj8b635a42004-11-22 19:01:47 +0000287 curr = st->Ist.Put.data->Iex.Tmp.tmp;
288 delta = 0;
289 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000290 }
291
sewardj8b635a42004-11-22 19:01:47 +0000292 case5:
293 /* PutI or Dirty call which overlaps SP: complain. We can't
294 deal with SP changing in weird ways (well, we can, but not at
295 this time of night). */
296 if (st->tag == Ist_PutI) {
297 descr = st->Ist.PutI.descr;
298 minoff_ST = descr->base;
299 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
300 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
301 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000302 }
sewardj8b635a42004-11-22 19:01:47 +0000303 if (st->tag == Ist_Dirty) {
304 d = st->Ist.Dirty.details;
305 for (j = 0; j < d->nFxState; j++) {
306 minoff_ST = d->fxState[j].offset;
307 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
308 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
309 continue;
310 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
311 goto complain;
312 }
313 }
sewardjde4a1d02002-03-22 01:27:54 +0000314
sewardj8b635a42004-11-22 19:01:47 +0000315 /* well, not interesting. Just copy and keep going. */
316 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000317
sewardj8b635a42004-11-22 19:01:47 +0000318 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000319
sewardj8b635a42004-11-22 19:01:47 +0000320 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000321
sewardj8b635a42004-11-22 19:01:47 +0000322 complain:
323 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000324
325}
sewardj7c4b6042003-06-14 15:47:15 +0000326
sewardjde4a1d02002-03-22 01:27:54 +0000327
sewardjde4a1d02002-03-22 01:27:54 +0000328
sewardj8b635a42004-11-22 19:01:47 +0000329#if 0
330 for (i = 0; i < bb_in->stmts_used; i++) {
331 st = bb_in->stmts[i];
332 if (!st)
333 continue;
334 if (st->tag != Ist_Put)
335 goto boring;
336 offP = st->Ist.Put.offset;
337 if (offP != layout->offset_SP)
338 goto boring;
339 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
340 if (szP != layout->sizeof_SP)
341 goto boring;
342 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000343
sewardj8b635a42004-11-22 19:01:47 +0000344 /* I don't know if it's really necessary to say that the call reads
345 the stack pointer. But anyway, we do. */
346 dcall = unsafeIRDirty_0_N(
347 mkIRCallee(1, "VG_(unknown_esp_update)",
348 (HWord)&VG_(unknown_esp_update)),
349 mkIRExprVec_1(st->Ist.Put.data)
350 );
351 dcall->nFxState = 1;
352 dcall->fxState[0].fx = Ifx_Read;
353 dcall->fxState[0].offset = layout->offset_SP;
354 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000355
sewardj8b635a42004-11-22 19:01:47 +0000356 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
357
358 boring:
359 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000360 }
sewardj8b635a42004-11-22 19:01:47 +0000361#endif
362
sewardjde4a1d02002-03-22 01:27:54 +0000363
sewardjde4a1d02002-03-22 01:27:54 +0000364/*------------------------------------------------------------*/
365/*--- Main entry point for the JITter. ---*/
366/*------------------------------------------------------------*/
367
sewardj8b635a42004-11-22 19:01:47 +0000368/* Vex dumps the final code in here. Then we can copy it off
369 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000370#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000371static UChar tmpbuf[N_TMPBUF];
372
373/* Function pointers we must supply to LibVEX in order that it
374 can bomb out and emit messages under Valgrind's control. */
375__attribute__ ((noreturn))
376static
377void failure_exit ( void )
378{
sewardjbf426512005-01-17 18:35:30 +0000379 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000380 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000381}
382
383static
sewardjb5f6f512005-03-10 23:59:00 +0000384void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000385{
386 Int i;
387 for (i = 0; i < nbytes-3; i += 4)
388 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
389 for (; i < nbytes; i++)
390 VG_(printf)("%c", bytes[i]);
391}
392
nethercote59a122d2004-08-03 17:16:51 +0000393/* Translate the basic block beginning at orig_addr, and add it to
394 the translation cache & translation table. Unless 'debugging' is true,
395 in which case the call is being done for debugging purposes, so
396 (a) throw away the translation once it is made, and (b) produce a
397 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000398
nethercote59a122d2004-08-03 17:16:51 +0000399 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000400*/
sewardj8b635a42004-11-22 19:01:47 +0000401
402/* This stops Vex from chasing into function entry points that we wish
403 to redirect. Chasing across them obviously defeats the redirect
404 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
405 others. */
406static Bool chase_into_ok ( Addr64 addr64 )
407{
408 Addr addr = (Addr)addr64;
409 if (addr != VG_(code_redirect)(addr)) {
410 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
411 return False;
412 } else {
413 return True; /* ok to chase into 'addr' */
414 }
415}
416
sewardjfa8ec112005-01-19 11:55:34 +0000417Bool VG_(translate) ( ThreadId tid,
418 Addr64 orig_addr,
419 Bool debugging_translation,
420 Int debugging_verbosity )
sewardjde4a1d02002-03-22 01:27:54 +0000421{
sewardjfa8ec112005-01-19 11:55:34 +0000422 Addr64 redir, orig_addr0 = orig_addr;
423 Int tmpbuf_used, verbosity;
sewardjc771b292004-11-30 18:55:21 +0000424 Bool notrace_until_done;
425 UInt notrace_until_limit = 0;
426 Segment* seg;
sewardjfa8ec112005-01-19 11:55:34 +0000427 VexGuestExtents vge;
sewardjde4a1d02002-03-22 01:27:54 +0000428
njn36932cb2005-05-11 22:45:48 +0000429 /* Indicates what arch and subarch we are running on. */
430 static VexArch vex_arch = VexArch_INVALID;
431 static VexSubArch vex_subarch = VexSubArch_INVALID;
432
sewardj8b635a42004-11-22 19:01:47 +0000433 /* Make sure Vex is initialised right. */
sewardjbf426512005-01-17 18:35:30 +0000434 VexTranslateResult tres;
sewardj8b635a42004-11-22 19:01:47 +0000435 static Bool vex_init_done = False;
436
437 if (!vex_init_done) {
njna1f783f2005-06-18 03:44:34 +0000438 Bool ok = getArchAndSubArch( &vex_arch, &vex_subarch );
njn36932cb2005-05-11 22:45:48 +0000439 if (!ok) {
440 VG_(printf)("\n");
441 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
442 VG_(printf)(" Supported CPUs are:\n");
443 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
444 "AMD Athlon or above)\n");
445 VG_(printf)("\n");
446 VG_(exit)(1);
447 }
448 if (VG_(clo_verbosity) > 2) {
449 VG_(message)(Vg_DebugMsg,
450 "Host CPU: arch = %s, subarch = %s",
451 LibVEX_ppVexArch ( vex_arch ),
452 LibVEX_ppVexSubArch( vex_subarch ) );
453 }
454
sewardj8b635a42004-11-22 19:01:47 +0000455 LibVEX_Init ( &failure_exit, &log_bytes,
456 1, /* debug_paranoia */
457 False, /* valgrind support */
458 &VG_(clo_vex_control) );
459 vex_init_done = True;
460 }
461
462 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000463 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000464
sewardj25c7c3a2003-07-10 00:17:58 +0000465 /* Look in the code redirect table to see if we should
466 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000467 redir = VG_(code_redirect)(orig_addr);
468
nethercote59a122d2004-08-03 17:16:51 +0000469 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardjfa8ec112005-01-19 11:55:34 +0000470 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +0000471 Char name1[64] = "";
472 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +0000473 name1[0] = name2[0] = 0;
474 ok = VG_(get_fnname_w_offset)(orig_addr, name1, 64);
njnbe73f432005-03-26 21:34:45 +0000475 if (!ok) VG_(strcpy)(name1, "???");
sewardjfa8ec112005-01-19 11:55:34 +0000476 ok = VG_(get_fnname_w_offset)(redir, name2, 64);
njnbe73f432005-03-26 21:34:45 +0000477 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +0000478 VG_(message)(Vg_DebugMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000479 "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj8b635a42004-11-22 19:01:47 +0000480 orig_addr, name1,
481 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000482 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000483 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000484
sewardja60be0e2003-05-26 08:47:27 +0000485 /* If codegen tracing, don't start tracing until
486 notrace_until_limit blocks have gone by. This avoids printing
487 huge amounts of useless junk when all we want to see is the last
488 few blocks translated prior to a failure. Set
489 notrace_until_limit to be the number of translations to be made
490 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +0000491 notrace_until_done
492 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000493
fitzhardinge98abfc72003-12-16 02:05:15 +0000494 seg = VG_(find_segment)(orig_addr);
495
njn25e49d8e72002-09-23 09:36:25 +0000496 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000497 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000498
sewardj85ac6d42005-02-23 11:36:56 +0000499 /* If doing any code printing, print a basic block start marker */
500 if (VG_(clo_trace_flags) || debugging_translation) {
501 Char fnname[64] = "";
502 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
503 VG_(printf)(
504 "==== BB %d %s(0x%llx) approx BBs exec'd %lld ====\n",
505 VG_(get_bbs_translated)(), fnname, orig_addr,
506 VG_(bbs_done));
507 }
508
fitzhardinge98abfc72003-12-16 02:05:15 +0000509 if (seg == NULL ||
510 !VG_(seg_contains)(seg, orig_addr, 1) ||
511 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000512 /* Code address is bad - deliver a signal instead */
sewardjb5f6f512005-03-10 23:59:00 +0000513 vg_assert(!VG_(is_addressable)(orig_addr, 1,
514 VKI_PROT_READ|VKI_PROT_EXEC));
fitzhardinge98abfc72003-12-16 02:05:15 +0000515
fitzhardinge98abfc72003-12-16 02:05:15 +0000516 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000517 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
518 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000519 } else
sewardj8b635a42004-11-22 19:01:47 +0000520 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000521
nethercote4d714382004-10-13 09:47:24 +0000522 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000523 } else
sewardj8b635a42004-11-22 19:01:47 +0000524 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000525
njn25e49d8e72002-09-23 09:36:25 +0000526 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000527 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +0000528 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +0000529 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +0000530 }
531 else
sewardjfa8ec112005-01-19 11:55:34 +0000532 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +0000533 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +0000534 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +0000535 }
njn25e49d8e72002-09-23 09:36:25 +0000536
njn31513b42005-06-01 03:09:59 +0000537 VGP_PUSHCC(VgpVexTime);
538
sewardj8b635a42004-11-22 19:01:47 +0000539 /* Actually do the translation. */
njn51d827b2005-05-09 01:02:08 +0000540 tl_assert2(VG_(tdict).tool_instrument,
541 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj8b635a42004-11-22 19:01:47 +0000542 tres = LibVEX_Translate (
njn36932cb2005-05-11 22:45:48 +0000543 vex_arch, vex_subarch,
544 vex_arch, vex_subarch,
sewardjb5f6f512005-03-10 23:59:00 +0000545 (UChar*)ULong_to_Ptr(orig_addr),
sewardjfa8ec112005-01-19 11:55:34 +0000546 (Addr64)orig_addr,
sewardj8b635a42004-11-22 19:01:47 +0000547 chase_into_ok,
sewardjfa8ec112005-01-19 11:55:34 +0000548 &vge,
sewardj8b635a42004-11-22 19:01:47 +0000549 tmpbuf, N_TMPBUF, &tmpbuf_used,
njn51d827b2005-05-09 01:02:08 +0000550 VG_(tdict).tool_instrument,
njnbd2e75c2004-11-24 16:43:43 +0000551 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000552 ? vg_SP_update_pass
553 : NULL,
554 True, /* cleanup after instrumentation */
555 NULL,
sewardjc771b292004-11-30 18:55:21 +0000556 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000557 );
njn25e49d8e72002-09-23 09:36:25 +0000558
sewardjbf426512005-01-17 18:35:30 +0000559 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +0000560 vg_assert(tmpbuf_used <= N_TMPBUF);
561 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000562
njn31513b42005-06-01 03:09:59 +0000563 VGP_POPCC(VgpVexTime);
564
sewardjc771b292004-11-30 18:55:21 +0000565#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000566
nethercote59a122d2004-08-03 17:16:51 +0000567 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +0000568 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000569
570 // If debugging, don't do anything with the translated block; we
571 // only did this for the debugging output produced along the way.
572 if (!debugging_translation) {
573 // Note that we use orig_addr0, not orig_addr, which might have been
574 // changed by the redirection
njn8bddf582005-05-13 23:40:55 +0000575 VG_(add_to_transtab)( &vge,
576 orig_addr0,
577 (Addr)(&tmpbuf[0]),
578 tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000579 }
nethercote59a122d2004-08-03 17:16:51 +0000580
njn25e49d8e72002-09-23 09:36:25 +0000581 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000582
583 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000584}
585
586/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +0000587/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000588/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000589