blob: d1dd4b7e01ae2f6532eea2d7c830bcfe74785713 [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"
njn899ce732005-06-21 00:28:11 +000033#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
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"
njn20242342005-05-16 23:31:24 +000039#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000040#include "pub_core_profile.h"
njn24a6efb2005-06-20 03:36:51 +000041#include "pub_core_redir.h" // For VG_(code_redirect)()
42#include "pub_core_signals.h" // For VG_(synth_fault_{perms,mapping})()
43#include "pub_core_tooliface.h" // For VG_(tdict)
njn8bddf582005-05-13 23:40:55 +000044#include "pub_core_translate.h"
45#include "pub_core_transtab.h"
sewardjde4a1d02002-03-22 01:27:54 +000046
njna1f783f2005-06-18 03:44:34 +000047/*------------------------------------------------------------*/
48/*--- Determining arch/subarch. ---*/
49/*------------------------------------------------------------*/
50
51// Returns the architecture and subarchitecture, or indicates
52// that this subarchitecture is unable to run Valgrind
53// Returns False to indicate we cannot proceed further.
54static Bool getArchAndSubArch( /*OUT*/VexArch* vex_arch,
55 /*OUT*/VexSubArch* vex_subarch )
56{
57#if defined(VGA_x86)
58 Bool have_sse0, have_sse1, have_sse2;
59 UInt eax, ebx, ecx, edx;
60
61 if (!VG_(has_cpuid)())
62 /* we can't do cpuid at all. Give up. */
63 return False;
64
65 VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
66 if (eax < 1)
67 /* we can't ask for cpuid(x) for x > 0. Give up. */
68 return False;
69
70 /* get capabilities bits into edx */
71 VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
72
73 have_sse0 = (edx & (1<<24)) != 0; /* True => have fxsave/fxrstor */
74 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
75 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
76
77 if (have_sse2 && have_sse1 && have_sse0) {
78 *vex_arch = VexArchX86;
79 *vex_subarch = VexSubArchX86_sse2;
80 return True;
81 }
82
83 if (have_sse1 && have_sse0) {
84 *vex_arch = VexArchX86;
85 *vex_subarch = VexSubArchX86_sse1;
86 return True;
87 }
88
89 if (have_sse0) {
90 *vex_arch = VexArchX86;
91 *vex_subarch = VexSubArchX86_sse0;
92 return True;
93 }
94
95 /* we need at least SSE state to operate. */
96 return False;
cerion85665ca2005-06-20 15:51:07 +000097
njna1f783f2005-06-18 03:44:34 +000098#elif defined(VGA_amd64)
99 vg_assert(VG_(has_cpuid)());
100 *vex_arch = VexArchAMD64;
101 *vex_subarch = VexSubArch_NONE;
102 return True;
cerion85665ca2005-06-20 15:51:07 +0000103
104#elif defined(VGA_ppc32)
105 *vex_arch = VexArchPPC32;
106 *vex_subarch = VexSubArchPPC32_noAV;
107 return True;
108
njna1f783f2005-06-18 03:44:34 +0000109#else
110# error Unknown architecture
111#endif
112}
113
sewardjde4a1d02002-03-22 01:27:54 +0000114
nethercotebee3fd92004-08-02 15:17:43 +0000115/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +0000116/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +0000117/*------------------------------------------------------------*/
118
njna1f783f2005-06-18 03:44:34 +0000119static Bool need_to_handle_SP_assignment(void)
120{
121 return ( VG_(tdict).track_new_mem_stack_4 ||
122 VG_(tdict).track_die_mem_stack_4 ||
123 VG_(tdict).track_new_mem_stack_8 ||
124 VG_(tdict).track_die_mem_stack_8 ||
125 VG_(tdict).track_new_mem_stack_12 ||
126 VG_(tdict).track_die_mem_stack_12 ||
127 VG_(tdict).track_new_mem_stack_16 ||
128 VG_(tdict).track_die_mem_stack_16 ||
129 VG_(tdict).track_new_mem_stack_32 ||
130 VG_(tdict).track_die_mem_stack_32 ||
131 VG_(tdict).track_new_mem_stack ||
132 VG_(tdict).track_die_mem_stack );
133}
134
sewardj8b635a42004-11-22 19:01:47 +0000135/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +0000136
nethercote996901a2004-08-03 13:29:09 +0000137/* For tools that want to know about %ESP changes, this pass adds
138 in the appropriate hooks. We have to do it after the tool's
139 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +0000140 it adds in, and we must do it before register allocation because
141 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +0000142 Thus we have it as an extra phase between the two.
143
144 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
145 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
146 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
147 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
148 instruction clobbers t_ESP, we don't track it anymore, and fall back to
149 the delta-is-unknown case. That case is also used when the delta is not
150 a nice small amount, or an unknown amount.
151*/
sewardjde4a1d02002-03-22 01:27:54 +0000152
153static
sewardj8b635a42004-11-22 19:01:47 +0000154IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +0000155 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +0000156{
sewardj7cf97ee2004-11-28 14:25:01 +0000157 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +0000158 IRDirty *dcall, *d;
159 IRStmt* st;
160 IRExpr* e;
161 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +0000162 IRTemp curr;
163 IRType typeof_SP;
164 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +0000165
sewardj8b635a42004-11-22 19:01:47 +0000166 /* Set up BB */
167 IRBB* bb = emptyIRBB();
168 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
169 bb->next = dopyIRExpr(bb_in->next);
170 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +0000171
sewardj7cf97ee2004-11-28 14:25:01 +0000172 curr = IRTemp_INVALID;
173 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000174
sewardj7cf97ee2004-11-28 14:25:01 +0000175 sizeof_SP = layout->sizeof_SP;
176 offset_SP = layout->offset_SP;
177 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +0000178 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +0000179
sewardj8b635a42004-11-22 19:01:47 +0000180# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
181# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +0000182
sewardj8b635a42004-11-22 19:01:47 +0000183# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +0000184
sewardj8b635a42004-11-22 19:01:47 +0000185# define GET_CONST(con) \
186 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
187 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000188
sewardj8b635a42004-11-22 19:01:47 +0000189# define DO(kind, syze) \
190 do { \
njn51d827b2005-05-09 01:02:08 +0000191 if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000192 goto generic; \
193 \
194 /* I don't know if it's really necessary to say that the */ \
195 /* call reads the stack pointer. But anyway, we do. */ \
196 dcall = unsafeIRDirty_0_N( \
197 1/*regparms*/, \
198 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000199 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000200 mkIRExprVec_1(IRExpr_Tmp(curr)) \
201 ); \
202 dcall->nFxState = 1; \
203 dcall->fxState[0].fx = Ifx_Read; \
204 dcall->fxState[0].offset = layout->offset_SP; \
205 dcall->fxState[0].size = layout->sizeof_SP; \
206 \
207 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
208 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000209
sewardj8b635a42004-11-22 19:01:47 +0000210 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000211
sewardj8b635a42004-11-22 19:01:47 +0000212 st = bb_in->stmts[i];
213 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000214 continue;
215
sewardj8b635a42004-11-22 19:01:47 +0000216 /* t = Get(sp): curr = t, delta = 0 */
217 if (st->tag != Ist_Tmp) goto case2;
218 e = st->Ist.Tmp.data;
219 if (e->tag != Iex_Get) goto case2;
220 if (e->Iex.Get.offset != offset_SP) goto case2;
221 if (e->Iex.Get.ty != typeof_SP) goto case2;
222 curr = st->Ist.Tmp.tmp;
223 delta = 0;
224 addStmtToIRBB( bb, st );
225 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000226
sewardj8b635a42004-11-22 19:01:47 +0000227 case2:
228 /* t' = curr +/- const: curr = t', delta +=/-= const */
229 if (st->tag != Ist_Tmp) goto case3;
230 e = st->Ist.Tmp.data;
231 if (e->tag != Iex_Binop) goto case3;
232 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
233 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
234 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
235 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
236 curr = st->Ist.Tmp.tmp;
237 if (IS_ADD(e->Iex.Binop.op))
238 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
239 else
240 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
241 addStmtToIRBB( bb, st );
242 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000243
sewardj8b635a42004-11-22 19:01:47 +0000244 case3:
245 /* t' = curr: curr = t' */
246 if (st->tag != Ist_Tmp) goto case4;
247 e = st->Ist.Tmp.data;
248 if (e->tag != Iex_Tmp) goto case4;
249 if (e->Iex.Tmp.tmp != curr) goto case4;
250 curr = st->Ist.Tmp.tmp;
251 addStmtToIRBB( bb, st );
252 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000253
sewardj8b635a42004-11-22 19:01:47 +0000254 case4:
255 /* Put(sp) = curr */
256 if (st->tag != Ist_Put) goto case5;
257 if (st->Ist.Put.offset != offset_SP) goto case5;
258 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
259 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
260 switch (delta) {
261 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
262 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
263 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
264 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
265 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
266 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
267 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
268 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
269 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
270 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
271 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
272 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000273 }
sewardj8b635a42004-11-22 19:01:47 +0000274 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000275 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000276 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000277 /* Pass both the old and new SP values to this helper. */
278 old_SP = newIRTemp(bb->tyenv, typeof_SP);
279 addStmtToIRBB(
280 bb,
281 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
282 );
sewardjde4a1d02002-03-22 01:27:54 +0000283
sewardj2a99cf62004-11-24 10:44:19 +0000284 dcall = unsafeIRDirty_0_N(
285 2/*regparms*/,
286 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
287 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
288 );
sewardj8b635a42004-11-22 19:01:47 +0000289 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000290
291 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000292
sewardj8b635a42004-11-22 19:01:47 +0000293 curr = st->Ist.Put.data->Iex.Tmp.tmp;
294 delta = 0;
295 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000296 }
297
sewardj8b635a42004-11-22 19:01:47 +0000298 case5:
299 /* PutI or Dirty call which overlaps SP: complain. We can't
300 deal with SP changing in weird ways (well, we can, but not at
301 this time of night). */
302 if (st->tag == Ist_PutI) {
303 descr = st->Ist.PutI.descr;
304 minoff_ST = descr->base;
305 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
306 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
307 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000308 }
sewardj8b635a42004-11-22 19:01:47 +0000309 if (st->tag == Ist_Dirty) {
310 d = st->Ist.Dirty.details;
311 for (j = 0; j < d->nFxState; j++) {
312 minoff_ST = d->fxState[j].offset;
313 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
314 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
315 continue;
316 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
317 goto complain;
318 }
319 }
sewardjde4a1d02002-03-22 01:27:54 +0000320
sewardj8b635a42004-11-22 19:01:47 +0000321 /* well, not interesting. Just copy and keep going. */
322 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000323
sewardj8b635a42004-11-22 19:01:47 +0000324 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000325
sewardj8b635a42004-11-22 19:01:47 +0000326 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000327
sewardj8b635a42004-11-22 19:01:47 +0000328 complain:
329 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000330
331}
sewardj7c4b6042003-06-14 15:47:15 +0000332
sewardjde4a1d02002-03-22 01:27:54 +0000333
sewardjde4a1d02002-03-22 01:27:54 +0000334
sewardj8b635a42004-11-22 19:01:47 +0000335#if 0
336 for (i = 0; i < bb_in->stmts_used; i++) {
337 st = bb_in->stmts[i];
338 if (!st)
339 continue;
340 if (st->tag != Ist_Put)
341 goto boring;
342 offP = st->Ist.Put.offset;
343 if (offP != layout->offset_SP)
344 goto boring;
345 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
346 if (szP != layout->sizeof_SP)
347 goto boring;
348 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000349
sewardj8b635a42004-11-22 19:01:47 +0000350 /* I don't know if it's really necessary to say that the call reads
351 the stack pointer. But anyway, we do. */
352 dcall = unsafeIRDirty_0_N(
353 mkIRCallee(1, "VG_(unknown_esp_update)",
354 (HWord)&VG_(unknown_esp_update)),
355 mkIRExprVec_1(st->Ist.Put.data)
356 );
357 dcall->nFxState = 1;
358 dcall->fxState[0].fx = Ifx_Read;
359 dcall->fxState[0].offset = layout->offset_SP;
360 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000361
sewardj8b635a42004-11-22 19:01:47 +0000362 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
363
364 boring:
365 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000366 }
sewardj8b635a42004-11-22 19:01:47 +0000367#endif
368
sewardjde4a1d02002-03-22 01:27:54 +0000369
sewardjde4a1d02002-03-22 01:27:54 +0000370/*------------------------------------------------------------*/
371/*--- Main entry point for the JITter. ---*/
372/*------------------------------------------------------------*/
373
sewardj8b635a42004-11-22 19:01:47 +0000374/* Vex dumps the final code in here. Then we can copy it off
375 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000376#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000377static UChar tmpbuf[N_TMPBUF];
378
379/* Function pointers we must supply to LibVEX in order that it
380 can bomb out and emit messages under Valgrind's control. */
381__attribute__ ((noreturn))
382static
383void failure_exit ( void )
384{
sewardjbf426512005-01-17 18:35:30 +0000385 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000386 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000387}
388
389static
sewardjb5f6f512005-03-10 23:59:00 +0000390void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000391{
392 Int i;
393 for (i = 0; i < nbytes-3; i += 4)
394 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
395 for (; i < nbytes; i++)
396 VG_(printf)("%c", bytes[i]);
397}
398
nethercote59a122d2004-08-03 17:16:51 +0000399/* Translate the basic block beginning at orig_addr, and add it to
400 the translation cache & translation table. Unless 'debugging' is true,
401 in which case the call is being done for debugging purposes, so
402 (a) throw away the translation once it is made, and (b) produce a
403 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000404
nethercote59a122d2004-08-03 17:16:51 +0000405 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000406*/
sewardj8b635a42004-11-22 19:01:47 +0000407
408/* This stops Vex from chasing into function entry points that we wish
409 to redirect. Chasing across them obviously defeats the redirect
410 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
411 others. */
412static Bool chase_into_ok ( Addr64 addr64 )
413{
414 Addr addr = (Addr)addr64;
415 if (addr != VG_(code_redirect)(addr)) {
416 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
417 return False;
418 } else {
419 return True; /* ok to chase into 'addr' */
420 }
421}
422
sewardjfa8ec112005-01-19 11:55:34 +0000423Bool VG_(translate) ( ThreadId tid,
424 Addr64 orig_addr,
425 Bool debugging_translation,
njn394213a2005-06-19 18:38:24 +0000426 Int debugging_verbosity,
427 ULong bbs_done )
sewardjde4a1d02002-03-22 01:27:54 +0000428{
sewardjfa8ec112005-01-19 11:55:34 +0000429 Addr64 redir, orig_addr0 = orig_addr;
430 Int tmpbuf_used, verbosity;
sewardjc771b292004-11-30 18:55:21 +0000431 Bool notrace_until_done;
432 UInt notrace_until_limit = 0;
433 Segment* seg;
sewardjfa8ec112005-01-19 11:55:34 +0000434 VexGuestExtents vge;
sewardjde4a1d02002-03-22 01:27:54 +0000435
njn36932cb2005-05-11 22:45:48 +0000436 /* Indicates what arch and subarch we are running on. */
437 static VexArch vex_arch = VexArch_INVALID;
438 static VexSubArch vex_subarch = VexSubArch_INVALID;
439
sewardj8b635a42004-11-22 19:01:47 +0000440 /* Make sure Vex is initialised right. */
sewardjbf426512005-01-17 18:35:30 +0000441 VexTranslateResult tres;
sewardj8b635a42004-11-22 19:01:47 +0000442 static Bool vex_init_done = False;
443
444 if (!vex_init_done) {
njna1f783f2005-06-18 03:44:34 +0000445 Bool ok = getArchAndSubArch( &vex_arch, &vex_subarch );
njn36932cb2005-05-11 22:45:48 +0000446 if (!ok) {
447 VG_(printf)("\n");
448 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
449 VG_(printf)(" Supported CPUs are:\n");
450 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
451 "AMD Athlon or above)\n");
452 VG_(printf)("\n");
453 VG_(exit)(1);
454 }
455 if (VG_(clo_verbosity) > 2) {
456 VG_(message)(Vg_DebugMsg,
457 "Host CPU: arch = %s, subarch = %s",
458 LibVEX_ppVexArch ( vex_arch ),
459 LibVEX_ppVexSubArch( vex_subarch ) );
460 }
461
sewardj8b635a42004-11-22 19:01:47 +0000462 LibVEX_Init ( &failure_exit, &log_bytes,
463 1, /* debug_paranoia */
464 False, /* valgrind support */
465 &VG_(clo_vex_control) );
466 vex_init_done = True;
467 }
468
469 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000470 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000471
sewardj25c7c3a2003-07-10 00:17:58 +0000472 /* Look in the code redirect table to see if we should
473 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000474 redir = VG_(code_redirect)(orig_addr);
475
nethercote59a122d2004-08-03 17:16:51 +0000476 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardjfa8ec112005-01-19 11:55:34 +0000477 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +0000478 Char name1[64] = "";
479 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +0000480 name1[0] = name2[0] = 0;
481 ok = VG_(get_fnname_w_offset)(orig_addr, name1, 64);
njnbe73f432005-03-26 21:34:45 +0000482 if (!ok) VG_(strcpy)(name1, "???");
sewardjfa8ec112005-01-19 11:55:34 +0000483 ok = VG_(get_fnname_w_offset)(redir, name2, 64);
njnbe73f432005-03-26 21:34:45 +0000484 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +0000485 VG_(message)(Vg_DebugMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000486 "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj8b635a42004-11-22 19:01:47 +0000487 orig_addr, name1,
488 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000489 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000490 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000491
sewardja60be0e2003-05-26 08:47:27 +0000492 /* If codegen tracing, don't start tracing until
493 notrace_until_limit blocks have gone by. This avoids printing
494 huge amounts of useless junk when all we want to see is the last
495 few blocks translated prior to a failure. Set
496 notrace_until_limit to be the number of translations to be made
497 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +0000498 notrace_until_done
499 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000500
fitzhardinge98abfc72003-12-16 02:05:15 +0000501 seg = VG_(find_segment)(orig_addr);
502
njn25e49d8e72002-09-23 09:36:25 +0000503 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000504 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000505
sewardj85ac6d42005-02-23 11:36:56 +0000506 /* If doing any code printing, print a basic block start marker */
507 if (VG_(clo_trace_flags) || debugging_translation) {
508 Char fnname[64] = "";
509 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
510 VG_(printf)(
njn394213a2005-06-19 18:38:24 +0000511 "==== BB %d %s(0x%llx) BBs exec'd %lld ====\n",
sewardj85ac6d42005-02-23 11:36:56 +0000512 VG_(get_bbs_translated)(), fnname, orig_addr,
njn394213a2005-06-19 18:38:24 +0000513 bbs_done);
sewardj85ac6d42005-02-23 11:36:56 +0000514 }
515
fitzhardinge98abfc72003-12-16 02:05:15 +0000516 if (seg == NULL ||
517 !VG_(seg_contains)(seg, orig_addr, 1) ||
518 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000519 /* Code address is bad - deliver a signal instead */
sewardjb5f6f512005-03-10 23:59:00 +0000520 vg_assert(!VG_(is_addressable)(orig_addr, 1,
521 VKI_PROT_READ|VKI_PROT_EXEC));
fitzhardinge98abfc72003-12-16 02:05:15 +0000522
fitzhardinge98abfc72003-12-16 02:05:15 +0000523 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000524 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
525 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000526 } else
sewardj8b635a42004-11-22 19:01:47 +0000527 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000528
nethercote4d714382004-10-13 09:47:24 +0000529 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000530 } else
sewardj8b635a42004-11-22 19:01:47 +0000531 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000532
njn25e49d8e72002-09-23 09:36:25 +0000533 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000534 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +0000535 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +0000536 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +0000537 }
538 else
sewardjfa8ec112005-01-19 11:55:34 +0000539 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +0000540 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +0000541 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +0000542 }
njn25e49d8e72002-09-23 09:36:25 +0000543
njn31513b42005-06-01 03:09:59 +0000544 VGP_PUSHCC(VgpVexTime);
545
sewardj8b635a42004-11-22 19:01:47 +0000546 /* Actually do the translation. */
njn51d827b2005-05-09 01:02:08 +0000547 tl_assert2(VG_(tdict).tool_instrument,
548 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj8b635a42004-11-22 19:01:47 +0000549 tres = LibVEX_Translate (
njn36932cb2005-05-11 22:45:48 +0000550 vex_arch, vex_subarch,
551 vex_arch, vex_subarch,
sewardjb5f6f512005-03-10 23:59:00 +0000552 (UChar*)ULong_to_Ptr(orig_addr),
sewardjfa8ec112005-01-19 11:55:34 +0000553 (Addr64)orig_addr,
sewardj8b635a42004-11-22 19:01:47 +0000554 chase_into_ok,
sewardjfa8ec112005-01-19 11:55:34 +0000555 &vge,
sewardj8b635a42004-11-22 19:01:47 +0000556 tmpbuf, N_TMPBUF, &tmpbuf_used,
njn51d827b2005-05-09 01:02:08 +0000557 VG_(tdict).tool_instrument,
njnbd2e75c2004-11-24 16:43:43 +0000558 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000559 ? vg_SP_update_pass
560 : NULL,
561 True, /* cleanup after instrumentation */
562 NULL,
sewardjc771b292004-11-30 18:55:21 +0000563 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000564 );
njn25e49d8e72002-09-23 09:36:25 +0000565
sewardjbf426512005-01-17 18:35:30 +0000566 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +0000567 vg_assert(tmpbuf_used <= N_TMPBUF);
568 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000569
njn31513b42005-06-01 03:09:59 +0000570 VGP_POPCC(VgpVexTime);
571
sewardjc771b292004-11-30 18:55:21 +0000572#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000573
nethercote59a122d2004-08-03 17:16:51 +0000574 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +0000575 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000576
577 // If debugging, don't do anything with the translated block; we
578 // only did this for the debugging output produced along the way.
579 if (!debugging_translation) {
580 // Note that we use orig_addr0, not orig_addr, which might have been
581 // changed by the redirection
njn8bddf582005-05-13 23:40:55 +0000582 VG_(add_to_transtab)( &vge,
583 orig_addr0,
584 (Addr)(&tmpbuf[0]),
585 tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000586 }
nethercote59a122d2004-08-03 17:16:51 +0000587
njn25e49d8e72002-09-23 09:36:25 +0000588 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000589
590 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000591}
592
593/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +0000594/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000595/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000596