blob: 7e229e879667319149b2ef49768797577a69c659 [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"
njn20242342005-05-16 23:31:24 +000039#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000040#include "pub_core_profile.h"
njnd1af0032005-05-29 17:01:48 +000041#include "pub_core_redir.h"
njn0c246472005-05-31 01:00:08 +000042#include "pub_core_signals.h"
njn43b9a8a2005-05-10 04:37:01 +000043#include "pub_core_tooliface.h"
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;
97#elif defined(VGA_amd64)
98 vg_assert(VG_(has_cpuid)());
99 *vex_arch = VexArchAMD64;
100 *vex_subarch = VexSubArch_NONE;
101 return True;
102#else
103# error Unknown architecture
104#endif
105}
106
sewardjde4a1d02002-03-22 01:27:54 +0000107
nethercotebee3fd92004-08-02 15:17:43 +0000108/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +0000109/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +0000110/*------------------------------------------------------------*/
111
njna1f783f2005-06-18 03:44:34 +0000112static Bool need_to_handle_SP_assignment(void)
113{
114 return ( VG_(tdict).track_new_mem_stack_4 ||
115 VG_(tdict).track_die_mem_stack_4 ||
116 VG_(tdict).track_new_mem_stack_8 ||
117 VG_(tdict).track_die_mem_stack_8 ||
118 VG_(tdict).track_new_mem_stack_12 ||
119 VG_(tdict).track_die_mem_stack_12 ||
120 VG_(tdict).track_new_mem_stack_16 ||
121 VG_(tdict).track_die_mem_stack_16 ||
122 VG_(tdict).track_new_mem_stack_32 ||
123 VG_(tdict).track_die_mem_stack_32 ||
124 VG_(tdict).track_new_mem_stack ||
125 VG_(tdict).track_die_mem_stack );
126}
127
sewardj8b635a42004-11-22 19:01:47 +0000128/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +0000129
nethercote996901a2004-08-03 13:29:09 +0000130/* For tools that want to know about %ESP changes, this pass adds
131 in the appropriate hooks. We have to do it after the tool's
132 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +0000133 it adds in, and we must do it before register allocation because
134 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +0000135 Thus we have it as an extra phase between the two.
136
137 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
138 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
139 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
140 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
141 instruction clobbers t_ESP, we don't track it anymore, and fall back to
142 the delta-is-unknown case. That case is also used when the delta is not
143 a nice small amount, or an unknown amount.
144*/
sewardjde4a1d02002-03-22 01:27:54 +0000145
146static
sewardj8b635a42004-11-22 19:01:47 +0000147IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +0000148 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +0000149{
sewardj7cf97ee2004-11-28 14:25:01 +0000150 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +0000151 IRDirty *dcall, *d;
152 IRStmt* st;
153 IRExpr* e;
154 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +0000155 IRTemp curr;
156 IRType typeof_SP;
157 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +0000158
sewardj8b635a42004-11-22 19:01:47 +0000159 /* Set up BB */
160 IRBB* bb = emptyIRBB();
161 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
162 bb->next = dopyIRExpr(bb_in->next);
163 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +0000164
sewardj7cf97ee2004-11-28 14:25:01 +0000165 curr = IRTemp_INVALID;
166 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000167
sewardj7cf97ee2004-11-28 14:25:01 +0000168 sizeof_SP = layout->sizeof_SP;
169 offset_SP = layout->offset_SP;
170 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +0000171 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +0000172
sewardj8b635a42004-11-22 19:01:47 +0000173# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
174# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +0000175
sewardj8b635a42004-11-22 19:01:47 +0000176# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +0000177
sewardj8b635a42004-11-22 19:01:47 +0000178# define GET_CONST(con) \
179 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
180 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000181
sewardj8b635a42004-11-22 19:01:47 +0000182# define DO(kind, syze) \
183 do { \
njn51d827b2005-05-09 01:02:08 +0000184 if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000185 goto generic; \
186 \
187 /* I don't know if it's really necessary to say that the */ \
188 /* call reads the stack pointer. But anyway, we do. */ \
189 dcall = unsafeIRDirty_0_N( \
190 1/*regparms*/, \
191 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000192 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000193 mkIRExprVec_1(IRExpr_Tmp(curr)) \
194 ); \
195 dcall->nFxState = 1; \
196 dcall->fxState[0].fx = Ifx_Read; \
197 dcall->fxState[0].offset = layout->offset_SP; \
198 dcall->fxState[0].size = layout->sizeof_SP; \
199 \
200 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
201 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000202
sewardj8b635a42004-11-22 19:01:47 +0000203 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000204
sewardj8b635a42004-11-22 19:01:47 +0000205 st = bb_in->stmts[i];
206 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000207 continue;
208
sewardj8b635a42004-11-22 19:01:47 +0000209 /* t = Get(sp): curr = t, delta = 0 */
210 if (st->tag != Ist_Tmp) goto case2;
211 e = st->Ist.Tmp.data;
212 if (e->tag != Iex_Get) goto case2;
213 if (e->Iex.Get.offset != offset_SP) goto case2;
214 if (e->Iex.Get.ty != typeof_SP) goto case2;
215 curr = st->Ist.Tmp.tmp;
216 delta = 0;
217 addStmtToIRBB( bb, st );
218 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000219
sewardj8b635a42004-11-22 19:01:47 +0000220 case2:
221 /* t' = curr +/- const: curr = t', delta +=/-= const */
222 if (st->tag != Ist_Tmp) goto case3;
223 e = st->Ist.Tmp.data;
224 if (e->tag != Iex_Binop) goto case3;
225 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
226 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
227 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
228 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
229 curr = st->Ist.Tmp.tmp;
230 if (IS_ADD(e->Iex.Binop.op))
231 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
232 else
233 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
234 addStmtToIRBB( bb, st );
235 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000236
sewardj8b635a42004-11-22 19:01:47 +0000237 case3:
238 /* t' = curr: curr = t' */
239 if (st->tag != Ist_Tmp) goto case4;
240 e = st->Ist.Tmp.data;
241 if (e->tag != Iex_Tmp) goto case4;
242 if (e->Iex.Tmp.tmp != curr) goto case4;
243 curr = st->Ist.Tmp.tmp;
244 addStmtToIRBB( bb, st );
245 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000246
sewardj8b635a42004-11-22 19:01:47 +0000247 case4:
248 /* Put(sp) = curr */
249 if (st->tag != Ist_Put) goto case5;
250 if (st->Ist.Put.offset != offset_SP) goto case5;
251 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
252 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
253 switch (delta) {
254 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
255 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
256 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
257 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
258 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
259 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
260 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
261 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
262 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
263 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
264 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
265 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000266 }
sewardj8b635a42004-11-22 19:01:47 +0000267 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000268 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000269 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000270 /* Pass both the old and new SP values to this helper. */
271 old_SP = newIRTemp(bb->tyenv, typeof_SP);
272 addStmtToIRBB(
273 bb,
274 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
275 );
sewardjde4a1d02002-03-22 01:27:54 +0000276
sewardj2a99cf62004-11-24 10:44:19 +0000277 dcall = unsafeIRDirty_0_N(
278 2/*regparms*/,
279 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
280 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
281 );
sewardj8b635a42004-11-22 19:01:47 +0000282 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000283
284 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000285
sewardj8b635a42004-11-22 19:01:47 +0000286 curr = st->Ist.Put.data->Iex.Tmp.tmp;
287 delta = 0;
288 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000289 }
290
sewardj8b635a42004-11-22 19:01:47 +0000291 case5:
292 /* PutI or Dirty call which overlaps SP: complain. We can't
293 deal with SP changing in weird ways (well, we can, but not at
294 this time of night). */
295 if (st->tag == Ist_PutI) {
296 descr = st->Ist.PutI.descr;
297 minoff_ST = descr->base;
298 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
299 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
300 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000301 }
sewardj8b635a42004-11-22 19:01:47 +0000302 if (st->tag == Ist_Dirty) {
303 d = st->Ist.Dirty.details;
304 for (j = 0; j < d->nFxState; j++) {
305 minoff_ST = d->fxState[j].offset;
306 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
307 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
308 continue;
309 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
310 goto complain;
311 }
312 }
sewardjde4a1d02002-03-22 01:27:54 +0000313
sewardj8b635a42004-11-22 19:01:47 +0000314 /* well, not interesting. Just copy and keep going. */
315 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000316
sewardj8b635a42004-11-22 19:01:47 +0000317 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000318
sewardj8b635a42004-11-22 19:01:47 +0000319 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000320
sewardj8b635a42004-11-22 19:01:47 +0000321 complain:
322 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000323
324}
sewardj7c4b6042003-06-14 15:47:15 +0000325
sewardjde4a1d02002-03-22 01:27:54 +0000326
sewardjde4a1d02002-03-22 01:27:54 +0000327
sewardj8b635a42004-11-22 19:01:47 +0000328#if 0
329 for (i = 0; i < bb_in->stmts_used; i++) {
330 st = bb_in->stmts[i];
331 if (!st)
332 continue;
333 if (st->tag != Ist_Put)
334 goto boring;
335 offP = st->Ist.Put.offset;
336 if (offP != layout->offset_SP)
337 goto boring;
338 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
339 if (szP != layout->sizeof_SP)
340 goto boring;
341 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000342
sewardj8b635a42004-11-22 19:01:47 +0000343 /* I don't know if it's really necessary to say that the call reads
344 the stack pointer. But anyway, we do. */
345 dcall = unsafeIRDirty_0_N(
346 mkIRCallee(1, "VG_(unknown_esp_update)",
347 (HWord)&VG_(unknown_esp_update)),
348 mkIRExprVec_1(st->Ist.Put.data)
349 );
350 dcall->nFxState = 1;
351 dcall->fxState[0].fx = Ifx_Read;
352 dcall->fxState[0].offset = layout->offset_SP;
353 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000354
sewardj8b635a42004-11-22 19:01:47 +0000355 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
356
357 boring:
358 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000359 }
sewardj8b635a42004-11-22 19:01:47 +0000360#endif
361
sewardjde4a1d02002-03-22 01:27:54 +0000362
sewardjde4a1d02002-03-22 01:27:54 +0000363/*------------------------------------------------------------*/
364/*--- Main entry point for the JITter. ---*/
365/*------------------------------------------------------------*/
366
sewardj8b635a42004-11-22 19:01:47 +0000367/* Vex dumps the final code in here. Then we can copy it off
368 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000369#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000370static UChar tmpbuf[N_TMPBUF];
371
372/* Function pointers we must supply to LibVEX in order that it
373 can bomb out and emit messages under Valgrind's control. */
374__attribute__ ((noreturn))
375static
376void failure_exit ( void )
377{
sewardjbf426512005-01-17 18:35:30 +0000378 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000379 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000380}
381
382static
sewardjb5f6f512005-03-10 23:59:00 +0000383void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000384{
385 Int i;
386 for (i = 0; i < nbytes-3; i += 4)
387 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
388 for (; i < nbytes; i++)
389 VG_(printf)("%c", bytes[i]);
390}
391
nethercote59a122d2004-08-03 17:16:51 +0000392/* Translate the basic block beginning at orig_addr, and add it to
393 the translation cache & translation table. Unless 'debugging' is true,
394 in which case the call is being done for debugging purposes, so
395 (a) throw away the translation once it is made, and (b) produce a
396 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000397
nethercote59a122d2004-08-03 17:16:51 +0000398 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000399*/
sewardj8b635a42004-11-22 19:01:47 +0000400
401/* This stops Vex from chasing into function entry points that we wish
402 to redirect. Chasing across them obviously defeats the redirect
403 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
404 others. */
405static Bool chase_into_ok ( Addr64 addr64 )
406{
407 Addr addr = (Addr)addr64;
408 if (addr != VG_(code_redirect)(addr)) {
409 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
410 return False;
411 } else {
412 return True; /* ok to chase into 'addr' */
413 }
414}
415
sewardjfa8ec112005-01-19 11:55:34 +0000416Bool VG_(translate) ( ThreadId tid,
417 Addr64 orig_addr,
418 Bool debugging_translation,
njn394213a2005-06-19 18:38:24 +0000419 Int debugging_verbosity,
420 ULong bbs_done )
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)(
njn394213a2005-06-19 18:38:24 +0000504 "==== BB %d %s(0x%llx) BBs exec'd %lld ====\n",
sewardj85ac6d42005-02-23 11:36:56 +0000505 VG_(get_bbs_translated)(), fnname, orig_addr,
njn394213a2005-06-19 18:38:24 +0000506 bbs_done);
sewardj85ac6d42005-02-23 11:36:56 +0000507 }
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