blob: 0fa409ab5eafc1f64696245df7d985a7f6eb6953 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- The JITter proper: register allocation & code improvement ---*/
4/*--- vg_translate.c ---*/
5/*--------------------------------------------------------------------*/
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
nethercotef1e5e152004-09-01 23:58:16 +000032#include "core.h"
sewardj55f9d1a2005-04-25 11:11:44 +000033#include "pub_core_aspacemgr.h"
njn43b9a8a2005-05-10 04:37:01 +000034#include "pub_core_tooliface.h"
sewardjde4a1d02002-03-22 01:27:54 +000035
sewardjde4a1d02002-03-22 01:27:54 +000036
nethercotebee3fd92004-08-02 15:17:43 +000037/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +000038/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +000039/*------------------------------------------------------------*/
40
sewardj8b635a42004-11-22 19:01:47 +000041/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +000042
nethercote996901a2004-08-03 13:29:09 +000043/* For tools that want to know about %ESP changes, this pass adds
44 in the appropriate hooks. We have to do it after the tool's
45 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +000046 it adds in, and we must do it before register allocation because
47 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +000048 Thus we have it as an extra phase between the two.
49
50 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
51 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
52 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
53 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
54 instruction clobbers t_ESP, we don't track it anymore, and fall back to
55 the delta-is-unknown case. That case is also used when the delta is not
56 a nice small amount, or an unknown amount.
57*/
sewardjde4a1d02002-03-22 01:27:54 +000058
59static
sewardj8b635a42004-11-22 19:01:47 +000060IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +000061 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +000062{
sewardj7cf97ee2004-11-28 14:25:01 +000063 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +000064 IRDirty *dcall, *d;
65 IRStmt* st;
66 IRExpr* e;
67 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +000068 IRTemp curr;
69 IRType typeof_SP;
70 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +000071
sewardj8b635a42004-11-22 19:01:47 +000072 /* Set up BB */
73 IRBB* bb = emptyIRBB();
74 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
75 bb->next = dopyIRExpr(bb_in->next);
76 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +000077
sewardj7cf97ee2004-11-28 14:25:01 +000078 curr = IRTemp_INVALID;
79 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +000080
sewardj7cf97ee2004-11-28 14:25:01 +000081 sizeof_SP = layout->sizeof_SP;
82 offset_SP = layout->offset_SP;
83 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +000084 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +000085
sewardj8b635a42004-11-22 19:01:47 +000086# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
87# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +000088
sewardj8b635a42004-11-22 19:01:47 +000089# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +000090
sewardj8b635a42004-11-22 19:01:47 +000091# define GET_CONST(con) \
92 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
93 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +000094
sewardj8b635a42004-11-22 19:01:47 +000095# define DO(kind, syze) \
96 do { \
njn51d827b2005-05-09 01:02:08 +000097 if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +000098 goto generic; \
99 \
100 /* I don't know if it's really necessary to say that the */ \
101 /* call reads the stack pointer. But anyway, we do. */ \
102 dcall = unsafeIRDirty_0_N( \
103 1/*regparms*/, \
104 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000105 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000106 mkIRExprVec_1(IRExpr_Tmp(curr)) \
107 ); \
108 dcall->nFxState = 1; \
109 dcall->fxState[0].fx = Ifx_Read; \
110 dcall->fxState[0].offset = layout->offset_SP; \
111 dcall->fxState[0].size = layout->sizeof_SP; \
112 \
113 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
114 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000115
sewardj8b635a42004-11-22 19:01:47 +0000116 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000117
sewardj8b635a42004-11-22 19:01:47 +0000118 st = bb_in->stmts[i];
119 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000120 continue;
121
sewardj8b635a42004-11-22 19:01:47 +0000122 /* t = Get(sp): curr = t, delta = 0 */
123 if (st->tag != Ist_Tmp) goto case2;
124 e = st->Ist.Tmp.data;
125 if (e->tag != Iex_Get) goto case2;
126 if (e->Iex.Get.offset != offset_SP) goto case2;
127 if (e->Iex.Get.ty != typeof_SP) goto case2;
128 curr = st->Ist.Tmp.tmp;
129 delta = 0;
130 addStmtToIRBB( bb, st );
131 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000132
sewardj8b635a42004-11-22 19:01:47 +0000133 case2:
134 /* t' = curr +/- const: curr = t', delta +=/-= const */
135 if (st->tag != Ist_Tmp) goto case3;
136 e = st->Ist.Tmp.data;
137 if (e->tag != Iex_Binop) goto case3;
138 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
139 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
140 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
141 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
142 curr = st->Ist.Tmp.tmp;
143 if (IS_ADD(e->Iex.Binop.op))
144 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
145 else
146 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
147 addStmtToIRBB( bb, st );
148 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000149
sewardj8b635a42004-11-22 19:01:47 +0000150 case3:
151 /* t' = curr: curr = t' */
152 if (st->tag != Ist_Tmp) goto case4;
153 e = st->Ist.Tmp.data;
154 if (e->tag != Iex_Tmp) goto case4;
155 if (e->Iex.Tmp.tmp != curr) goto case4;
156 curr = st->Ist.Tmp.tmp;
157 addStmtToIRBB( bb, st );
158 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000159
sewardj8b635a42004-11-22 19:01:47 +0000160 case4:
161 /* Put(sp) = curr */
162 if (st->tag != Ist_Put) goto case5;
163 if (st->Ist.Put.offset != offset_SP) goto case5;
164 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
165 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
166 switch (delta) {
167 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
168 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
169 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
170 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
171 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
172 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
173 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
174 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
175 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
176 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
177 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
178 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000179 }
sewardj8b635a42004-11-22 19:01:47 +0000180 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000181 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000182 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000183 /* Pass both the old and new SP values to this helper. */
184 old_SP = newIRTemp(bb->tyenv, typeof_SP);
185 addStmtToIRBB(
186 bb,
187 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
188 );
sewardjde4a1d02002-03-22 01:27:54 +0000189
sewardj2a99cf62004-11-24 10:44:19 +0000190 dcall = unsafeIRDirty_0_N(
191 2/*regparms*/,
192 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
193 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
194 );
sewardj8b635a42004-11-22 19:01:47 +0000195 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000196
197 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000198
sewardj8b635a42004-11-22 19:01:47 +0000199 curr = st->Ist.Put.data->Iex.Tmp.tmp;
200 delta = 0;
201 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000202 }
203
sewardj8b635a42004-11-22 19:01:47 +0000204 case5:
205 /* PutI or Dirty call which overlaps SP: complain. We can't
206 deal with SP changing in weird ways (well, we can, but not at
207 this time of night). */
208 if (st->tag == Ist_PutI) {
209 descr = st->Ist.PutI.descr;
210 minoff_ST = descr->base;
211 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
212 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
213 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000214 }
sewardj8b635a42004-11-22 19:01:47 +0000215 if (st->tag == Ist_Dirty) {
216 d = st->Ist.Dirty.details;
217 for (j = 0; j < d->nFxState; j++) {
218 minoff_ST = d->fxState[j].offset;
219 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
220 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
221 continue;
222 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
223 goto complain;
224 }
225 }
sewardjde4a1d02002-03-22 01:27:54 +0000226
sewardj8b635a42004-11-22 19:01:47 +0000227 /* well, not interesting. Just copy and keep going. */
228 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000229
sewardj8b635a42004-11-22 19:01:47 +0000230 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000231
sewardj8b635a42004-11-22 19:01:47 +0000232 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000233
sewardj8b635a42004-11-22 19:01:47 +0000234 complain:
235 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000236
237}
sewardj7c4b6042003-06-14 15:47:15 +0000238
sewardjde4a1d02002-03-22 01:27:54 +0000239
sewardjde4a1d02002-03-22 01:27:54 +0000240
sewardj8b635a42004-11-22 19:01:47 +0000241#if 0
242 for (i = 0; i < bb_in->stmts_used; i++) {
243 st = bb_in->stmts[i];
244 if (!st)
245 continue;
246 if (st->tag != Ist_Put)
247 goto boring;
248 offP = st->Ist.Put.offset;
249 if (offP != layout->offset_SP)
250 goto boring;
251 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
252 if (szP != layout->sizeof_SP)
253 goto boring;
254 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000255
sewardj8b635a42004-11-22 19:01:47 +0000256 /* I don't know if it's really necessary to say that the call reads
257 the stack pointer. But anyway, we do. */
258 dcall = unsafeIRDirty_0_N(
259 mkIRCallee(1, "VG_(unknown_esp_update)",
260 (HWord)&VG_(unknown_esp_update)),
261 mkIRExprVec_1(st->Ist.Put.data)
262 );
263 dcall->nFxState = 1;
264 dcall->fxState[0].fx = Ifx_Read;
265 dcall->fxState[0].offset = layout->offset_SP;
266 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000267
sewardj8b635a42004-11-22 19:01:47 +0000268 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
269
270 boring:
271 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000272 }
sewardj8b635a42004-11-22 19:01:47 +0000273#endif
274
sewardjde4a1d02002-03-22 01:27:54 +0000275
sewardjde4a1d02002-03-22 01:27:54 +0000276/*------------------------------------------------------------*/
277/*--- Main entry point for the JITter. ---*/
278/*------------------------------------------------------------*/
279
sewardj8b635a42004-11-22 19:01:47 +0000280/* Vex dumps the final code in here. Then we can copy it off
281 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000282#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000283static UChar tmpbuf[N_TMPBUF];
284
285/* Function pointers we must supply to LibVEX in order that it
286 can bomb out and emit messages under Valgrind's control. */
287__attribute__ ((noreturn))
288static
289void failure_exit ( void )
290{
sewardjbf426512005-01-17 18:35:30 +0000291 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000292 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000293}
294
295static
sewardjb5f6f512005-03-10 23:59:00 +0000296void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000297{
298 Int i;
299 for (i = 0; i < nbytes-3; i += 4)
300 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
301 for (; i < nbytes; i++)
302 VG_(printf)("%c", bytes[i]);
303}
304
nethercote59a122d2004-08-03 17:16:51 +0000305/* Translate the basic block beginning at orig_addr, and add it to
306 the translation cache & translation table. Unless 'debugging' is true,
307 in which case the call is being done for debugging purposes, so
308 (a) throw away the translation once it is made, and (b) produce a
309 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000310
nethercote59a122d2004-08-03 17:16:51 +0000311 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000312*/
sewardj8b635a42004-11-22 19:01:47 +0000313
314/* This stops Vex from chasing into function entry points that we wish
315 to redirect. Chasing across them obviously defeats the redirect
316 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
317 others. */
318static Bool chase_into_ok ( Addr64 addr64 )
319{
320 Addr addr = (Addr)addr64;
321 if (addr != VG_(code_redirect)(addr)) {
322 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
323 return False;
324 } else {
325 return True; /* ok to chase into 'addr' */
326 }
327}
328
njnbd2e75c2004-11-24 16:43:43 +0000329static Bool need_to_handle_SP_assignment(void)
330{
njn51d827b2005-05-09 01:02:08 +0000331 return ( VG_(tdict).track_new_mem_stack_4 ||
332 VG_(tdict).track_die_mem_stack_4 ||
333 VG_(tdict).track_new_mem_stack_8 ||
334 VG_(tdict).track_die_mem_stack_8 ||
335 VG_(tdict).track_new_mem_stack_12 ||
336 VG_(tdict).track_die_mem_stack_12 ||
337 VG_(tdict).track_new_mem_stack_16 ||
338 VG_(tdict).track_die_mem_stack_16 ||
339 VG_(tdict).track_new_mem_stack_32 ||
340 VG_(tdict).track_die_mem_stack_32 ||
341 VG_(tdict).track_new_mem_stack ||
342 VG_(tdict).track_die_mem_stack );
njnbd2e75c2004-11-24 16:43:43 +0000343}
344
sewardjfa8ec112005-01-19 11:55:34 +0000345Bool VG_(translate) ( ThreadId tid,
346 Addr64 orig_addr,
347 Bool debugging_translation,
348 Int debugging_verbosity )
sewardjde4a1d02002-03-22 01:27:54 +0000349{
sewardjfa8ec112005-01-19 11:55:34 +0000350 Addr64 redir, orig_addr0 = orig_addr;
351 Int tmpbuf_used, verbosity;
sewardjc771b292004-11-30 18:55:21 +0000352 Bool notrace_until_done;
353 UInt notrace_until_limit = 0;
354 Segment* seg;
sewardjfa8ec112005-01-19 11:55:34 +0000355 VexGuestExtents vge;
sewardjde4a1d02002-03-22 01:27:54 +0000356
njn36932cb2005-05-11 22:45:48 +0000357 /* Indicates what arch and subarch we are running on. */
358 static VexArch vex_arch = VexArch_INVALID;
359 static VexSubArch vex_subarch = VexSubArch_INVALID;
360
sewardj8b635a42004-11-22 19:01:47 +0000361 /* Make sure Vex is initialised right. */
sewardjbf426512005-01-17 18:35:30 +0000362 VexTranslateResult tres;
sewardj8b635a42004-11-22 19:01:47 +0000363 static Bool vex_init_done = False;
364
365 if (!vex_init_done) {
njn36932cb2005-05-11 22:45:48 +0000366 Bool ok = VGA_(getArchAndSubArch)( &vex_arch, &vex_subarch );
367 if (!ok) {
368 VG_(printf)("\n");
369 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
370 VG_(printf)(" Supported CPUs are:\n");
371 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
372 "AMD Athlon or above)\n");
373 VG_(printf)("\n");
374 VG_(exit)(1);
375 }
376 if (VG_(clo_verbosity) > 2) {
377 VG_(message)(Vg_DebugMsg,
378 "Host CPU: arch = %s, subarch = %s",
379 LibVEX_ppVexArch ( vex_arch ),
380 LibVEX_ppVexSubArch( vex_subarch ) );
381 }
382
sewardj8b635a42004-11-22 19:01:47 +0000383 LibVEX_Init ( &failure_exit, &log_bytes,
384 1, /* debug_paranoia */
385 False, /* valgrind support */
386 &VG_(clo_vex_control) );
387 vex_init_done = True;
388 }
389
390 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000391 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000392
sewardj25c7c3a2003-07-10 00:17:58 +0000393 /* Look in the code redirect table to see if we should
394 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000395 redir = VG_(code_redirect)(orig_addr);
396
nethercote59a122d2004-08-03 17:16:51 +0000397 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardjfa8ec112005-01-19 11:55:34 +0000398 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +0000399 Char name1[64] = "";
400 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +0000401 name1[0] = name2[0] = 0;
402 ok = VG_(get_fnname_w_offset)(orig_addr, name1, 64);
njnbe73f432005-03-26 21:34:45 +0000403 if (!ok) VG_(strcpy)(name1, "???");
sewardjfa8ec112005-01-19 11:55:34 +0000404 ok = VG_(get_fnname_w_offset)(redir, name2, 64);
njnbe73f432005-03-26 21:34:45 +0000405 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +0000406 VG_(message)(Vg_DebugMsg,
sewardjfa8ec112005-01-19 11:55:34 +0000407 "TRANSLATE: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj8b635a42004-11-22 19:01:47 +0000408 orig_addr, name1,
409 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000410 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000411 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000412
sewardja60be0e2003-05-26 08:47:27 +0000413 /* If codegen tracing, don't start tracing until
414 notrace_until_limit blocks have gone by. This avoids printing
415 huge amounts of useless junk when all we want to see is the last
416 few blocks translated prior to a failure. Set
417 notrace_until_limit to be the number of translations to be made
418 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +0000419 notrace_until_done
420 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000421
fitzhardinge98abfc72003-12-16 02:05:15 +0000422 seg = VG_(find_segment)(orig_addr);
423
njn25e49d8e72002-09-23 09:36:25 +0000424 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000425 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000426
sewardj85ac6d42005-02-23 11:36:56 +0000427 /* If doing any code printing, print a basic block start marker */
428 if (VG_(clo_trace_flags) || debugging_translation) {
429 Char fnname[64] = "";
430 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
431 VG_(printf)(
432 "==== BB %d %s(0x%llx) approx BBs exec'd %lld ====\n",
433 VG_(get_bbs_translated)(), fnname, orig_addr,
434 VG_(bbs_done));
435 }
436
fitzhardinge98abfc72003-12-16 02:05:15 +0000437 if (seg == NULL ||
438 !VG_(seg_contains)(seg, orig_addr, 1) ||
439 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000440 /* Code address is bad - deliver a signal instead */
sewardjb5f6f512005-03-10 23:59:00 +0000441 vg_assert(!VG_(is_addressable)(orig_addr, 1,
442 VKI_PROT_READ|VKI_PROT_EXEC));
fitzhardinge98abfc72003-12-16 02:05:15 +0000443
fitzhardinge98abfc72003-12-16 02:05:15 +0000444 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000445 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
446 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000447 } else
sewardj8b635a42004-11-22 19:01:47 +0000448 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000449
nethercote4d714382004-10-13 09:47:24 +0000450 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000451 } else
sewardj8b635a42004-11-22 19:01:47 +0000452 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000453
njn25e49d8e72002-09-23 09:36:25 +0000454 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000455 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +0000456 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +0000457 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +0000458 }
459 else
sewardjfa8ec112005-01-19 11:55:34 +0000460 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +0000461 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +0000462 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +0000463 }
njn25e49d8e72002-09-23 09:36:25 +0000464
sewardj8b635a42004-11-22 19:01:47 +0000465 /* Actually do the translation. */
njn51d827b2005-05-09 01:02:08 +0000466 tl_assert2(VG_(tdict).tool_instrument,
467 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj8b635a42004-11-22 19:01:47 +0000468 tres = LibVEX_Translate (
njn36932cb2005-05-11 22:45:48 +0000469 vex_arch, vex_subarch,
470 vex_arch, vex_subarch,
sewardjb5f6f512005-03-10 23:59:00 +0000471 (UChar*)ULong_to_Ptr(orig_addr),
sewardjfa8ec112005-01-19 11:55:34 +0000472 (Addr64)orig_addr,
sewardj8b635a42004-11-22 19:01:47 +0000473 chase_into_ok,
sewardjfa8ec112005-01-19 11:55:34 +0000474 &vge,
sewardj8b635a42004-11-22 19:01:47 +0000475 tmpbuf, N_TMPBUF, &tmpbuf_used,
njn51d827b2005-05-09 01:02:08 +0000476 VG_(tdict).tool_instrument,
njnbd2e75c2004-11-24 16:43:43 +0000477 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000478 ? vg_SP_update_pass
479 : NULL,
480 True, /* cleanup after instrumentation */
481 NULL,
sewardjc771b292004-11-30 18:55:21 +0000482 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000483 );
njn25e49d8e72002-09-23 09:36:25 +0000484
sewardjbf426512005-01-17 18:35:30 +0000485 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +0000486 vg_assert(tmpbuf_used <= N_TMPBUF);
487 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000488
sewardjc771b292004-11-30 18:55:21 +0000489#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000490
nethercote59a122d2004-08-03 17:16:51 +0000491 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +0000492 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000493
494 // If debugging, don't do anything with the translated block; we
495 // only did this for the debugging output produced along the way.
496 if (!debugging_translation) {
497 // Note that we use orig_addr0, not orig_addr, which might have been
498 // changed by the redirection
sewardjfa8ec112005-01-19 11:55:34 +0000499 VG_(add_to_trans_tab)( &vge,
500 orig_addr0,
501 (Addr)(&tmpbuf[0]),
502 tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000503 }
nethercote59a122d2004-08-03 17:16:51 +0000504
njn25e49d8e72002-09-23 09:36:25 +0000505 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000506
507 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000508}
509
510/*--------------------------------------------------------------------*/
511/*--- end vg_translate.c ---*/
512/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000513