blob: 9da8aaeb21a35e348e131f0d1c7df8f92cfac7b0 [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
nethercotef1e5e152004-09-01 23:58:16 +000032#include "core.h"
sewardj55f9d1a2005-04-25 11:11:44 +000033#include "pub_core_aspacemgr.h"
njn97405b22005-06-02 03:39:33 +000034#include "pub_core_libcbase.h"
njn36a20fa2005-06-03 03:08:39 +000035#include "pub_core_libcprint.h"
njn04e16982005-05-31 00:23:43 +000036#include "pub_core_main.h" // for VG_(bbs_done)
njn20242342005-05-16 23:31:24 +000037#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000038#include "pub_core_profile.h"
njnd1af0032005-05-29 17:01:48 +000039#include "pub_core_redir.h"
njn0c246472005-05-31 01:00:08 +000040#include "pub_core_signals.h"
njn43b9a8a2005-05-10 04:37:01 +000041#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000042#include "pub_core_translate.h"
43#include "pub_core_transtab.h"
sewardjde4a1d02002-03-22 01:27:54 +000044
sewardjde4a1d02002-03-22 01:27:54 +000045
nethercotebee3fd92004-08-02 15:17:43 +000046/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +000047/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +000048/*------------------------------------------------------------*/
49
sewardj8b635a42004-11-22 19:01:47 +000050/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +000051
nethercote996901a2004-08-03 13:29:09 +000052/* For tools that want to know about %ESP changes, this pass adds
53 in the appropriate hooks. We have to do it after the tool's
54 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +000055 it adds in, and we must do it before register allocation because
56 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +000057 Thus we have it as an extra phase between the two.
58
59 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
60 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
61 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
62 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
63 instruction clobbers t_ESP, we don't track it anymore, and fall back to
64 the delta-is-unknown case. That case is also used when the delta is not
65 a nice small amount, or an unknown amount.
66*/
sewardjde4a1d02002-03-22 01:27:54 +000067
68static
sewardj8b635a42004-11-22 19:01:47 +000069IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +000070 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +000071{
sewardj7cf97ee2004-11-28 14:25:01 +000072 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +000073 IRDirty *dcall, *d;
74 IRStmt* st;
75 IRExpr* e;
76 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +000077 IRTemp curr;
78 IRType typeof_SP;
79 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +000080
sewardj8b635a42004-11-22 19:01:47 +000081 /* Set up BB */
82 IRBB* bb = emptyIRBB();
83 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
84 bb->next = dopyIRExpr(bb_in->next);
85 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +000086
sewardj7cf97ee2004-11-28 14:25:01 +000087 curr = IRTemp_INVALID;
88 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +000089
sewardj7cf97ee2004-11-28 14:25:01 +000090 sizeof_SP = layout->sizeof_SP;
91 offset_SP = layout->offset_SP;
92 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +000093 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +000094
sewardj8b635a42004-11-22 19:01:47 +000095# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
96# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +000097
sewardj8b635a42004-11-22 19:01:47 +000098# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +000099
sewardj8b635a42004-11-22 19:01:47 +0000100# define GET_CONST(con) \
101 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
102 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000103
sewardj8b635a42004-11-22 19:01:47 +0000104# define DO(kind, syze) \
105 do { \
njn51d827b2005-05-09 01:02:08 +0000106 if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000107 goto generic; \
108 \
109 /* I don't know if it's really necessary to say that the */ \
110 /* call reads the stack pointer. But anyway, we do. */ \
111 dcall = unsafeIRDirty_0_N( \
112 1/*regparms*/, \
113 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000114 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000115 mkIRExprVec_1(IRExpr_Tmp(curr)) \
116 ); \
117 dcall->nFxState = 1; \
118 dcall->fxState[0].fx = Ifx_Read; \
119 dcall->fxState[0].offset = layout->offset_SP; \
120 dcall->fxState[0].size = layout->sizeof_SP; \
121 \
122 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
123 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000124
sewardj8b635a42004-11-22 19:01:47 +0000125 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000126
sewardj8b635a42004-11-22 19:01:47 +0000127 st = bb_in->stmts[i];
128 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000129 continue;
130
sewardj8b635a42004-11-22 19:01:47 +0000131 /* t = Get(sp): curr = t, delta = 0 */
132 if (st->tag != Ist_Tmp) goto case2;
133 e = st->Ist.Tmp.data;
134 if (e->tag != Iex_Get) goto case2;
135 if (e->Iex.Get.offset != offset_SP) goto case2;
136 if (e->Iex.Get.ty != typeof_SP) goto case2;
137 curr = st->Ist.Tmp.tmp;
138 delta = 0;
139 addStmtToIRBB( bb, st );
140 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000141
sewardj8b635a42004-11-22 19:01:47 +0000142 case2:
143 /* t' = curr +/- const: curr = t', delta +=/-= const */
144 if (st->tag != Ist_Tmp) goto case3;
145 e = st->Ist.Tmp.data;
146 if (e->tag != Iex_Binop) goto case3;
147 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
148 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
149 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
150 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
151 curr = st->Ist.Tmp.tmp;
152 if (IS_ADD(e->Iex.Binop.op))
153 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
154 else
155 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
156 addStmtToIRBB( bb, st );
157 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000158
sewardj8b635a42004-11-22 19:01:47 +0000159 case3:
160 /* t' = curr: curr = t' */
161 if (st->tag != Ist_Tmp) goto case4;
162 e = st->Ist.Tmp.data;
163 if (e->tag != Iex_Tmp) goto case4;
164 if (e->Iex.Tmp.tmp != curr) goto case4;
165 curr = st->Ist.Tmp.tmp;
166 addStmtToIRBB( bb, st );
167 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000168
sewardj8b635a42004-11-22 19:01:47 +0000169 case4:
170 /* Put(sp) = curr */
171 if (st->tag != Ist_Put) goto case5;
172 if (st->Ist.Put.offset != offset_SP) goto case5;
173 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
174 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
175 switch (delta) {
176 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
177 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
178 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
179 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
180 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
181 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
182 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
183 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
184 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
185 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
186 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
187 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000188 }
sewardj8b635a42004-11-22 19:01:47 +0000189 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000190 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000191 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000192 /* Pass both the old and new SP values to this helper. */
193 old_SP = newIRTemp(bb->tyenv, typeof_SP);
194 addStmtToIRBB(
195 bb,
196 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
197 );
sewardjde4a1d02002-03-22 01:27:54 +0000198
sewardj2a99cf62004-11-24 10:44:19 +0000199 dcall = unsafeIRDirty_0_N(
200 2/*regparms*/,
201 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
202 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
203 );
sewardj8b635a42004-11-22 19:01:47 +0000204 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000205
206 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000207
sewardj8b635a42004-11-22 19:01:47 +0000208 curr = st->Ist.Put.data->Iex.Tmp.tmp;
209 delta = 0;
210 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000211 }
212
sewardj8b635a42004-11-22 19:01:47 +0000213 case5:
214 /* PutI or Dirty call which overlaps SP: complain. We can't
215 deal with SP changing in weird ways (well, we can, but not at
216 this time of night). */
217 if (st->tag == Ist_PutI) {
218 descr = st->Ist.PutI.descr;
219 minoff_ST = descr->base;
220 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
221 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
222 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000223 }
sewardj8b635a42004-11-22 19:01:47 +0000224 if (st->tag == Ist_Dirty) {
225 d = st->Ist.Dirty.details;
226 for (j = 0; j < d->nFxState; j++) {
227 minoff_ST = d->fxState[j].offset;
228 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
229 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
230 continue;
231 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
232 goto complain;
233 }
234 }
sewardjde4a1d02002-03-22 01:27:54 +0000235
sewardj8b635a42004-11-22 19:01:47 +0000236 /* well, not interesting. Just copy and keep going. */
237 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000238
sewardj8b635a42004-11-22 19:01:47 +0000239 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000240
sewardj8b635a42004-11-22 19:01:47 +0000241 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000242
sewardj8b635a42004-11-22 19:01:47 +0000243 complain:
244 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000245
246}
sewardj7c4b6042003-06-14 15:47:15 +0000247
sewardjde4a1d02002-03-22 01:27:54 +0000248
sewardjde4a1d02002-03-22 01:27:54 +0000249
sewardj8b635a42004-11-22 19:01:47 +0000250#if 0
251 for (i = 0; i < bb_in->stmts_used; i++) {
252 st = bb_in->stmts[i];
253 if (!st)
254 continue;
255 if (st->tag != Ist_Put)
256 goto boring;
257 offP = st->Ist.Put.offset;
258 if (offP != layout->offset_SP)
259 goto boring;
260 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
261 if (szP != layout->sizeof_SP)
262 goto boring;
263 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000264
sewardj8b635a42004-11-22 19:01:47 +0000265 /* I don't know if it's really necessary to say that the call reads
266 the stack pointer. But anyway, we do. */
267 dcall = unsafeIRDirty_0_N(
268 mkIRCallee(1, "VG_(unknown_esp_update)",
269 (HWord)&VG_(unknown_esp_update)),
270 mkIRExprVec_1(st->Ist.Put.data)
271 );
272 dcall->nFxState = 1;
273 dcall->fxState[0].fx = Ifx_Read;
274 dcall->fxState[0].offset = layout->offset_SP;
275 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000276
sewardj8b635a42004-11-22 19:01:47 +0000277 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
278
279 boring:
280 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000281 }
sewardj8b635a42004-11-22 19:01:47 +0000282#endif
283
sewardjde4a1d02002-03-22 01:27:54 +0000284
sewardjde4a1d02002-03-22 01:27:54 +0000285/*------------------------------------------------------------*/
286/*--- Main entry point for the JITter. ---*/
287/*------------------------------------------------------------*/
288
sewardj8b635a42004-11-22 19:01:47 +0000289/* Vex dumps the final code in here. Then we can copy it off
290 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000291#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000292static UChar tmpbuf[N_TMPBUF];
293
294/* Function pointers we must supply to LibVEX in order that it
295 can bomb out and emit messages under Valgrind's control. */
296__attribute__ ((noreturn))
297static
298void failure_exit ( void )
299{
sewardjbf426512005-01-17 18:35:30 +0000300 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000301 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000302}
303
304static
sewardjb5f6f512005-03-10 23:59:00 +0000305void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000306{
307 Int i;
308 for (i = 0; i < nbytes-3; i += 4)
309 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
310 for (; i < nbytes; i++)
311 VG_(printf)("%c", bytes[i]);
312}
313
nethercote59a122d2004-08-03 17:16:51 +0000314/* Translate the basic block beginning at orig_addr, and add it to
315 the translation cache & translation table. Unless 'debugging' is true,
316 in which case the call is being done for debugging purposes, so
317 (a) throw away the translation once it is made, and (b) produce a
318 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000319
nethercote59a122d2004-08-03 17:16:51 +0000320 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000321*/
sewardj8b635a42004-11-22 19:01:47 +0000322
323/* This stops Vex from chasing into function entry points that we wish
324 to redirect. Chasing across them obviously defeats the redirect
325 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
326 others. */
327static Bool chase_into_ok ( Addr64 addr64 )
328{
329 Addr addr = (Addr)addr64;
330 if (addr != VG_(code_redirect)(addr)) {
331 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
332 return False;
333 } else {
334 return True; /* ok to chase into 'addr' */
335 }
336}
337
njnbd2e75c2004-11-24 16:43:43 +0000338static Bool need_to_handle_SP_assignment(void)
339{
njn51d827b2005-05-09 01:02:08 +0000340 return ( VG_(tdict).track_new_mem_stack_4 ||
341 VG_(tdict).track_die_mem_stack_4 ||
342 VG_(tdict).track_new_mem_stack_8 ||
343 VG_(tdict).track_die_mem_stack_8 ||
344 VG_(tdict).track_new_mem_stack_12 ||
345 VG_(tdict).track_die_mem_stack_12 ||
346 VG_(tdict).track_new_mem_stack_16 ||
347 VG_(tdict).track_die_mem_stack_16 ||
348 VG_(tdict).track_new_mem_stack_32 ||
349 VG_(tdict).track_die_mem_stack_32 ||
350 VG_(tdict).track_new_mem_stack ||
351 VG_(tdict).track_die_mem_stack );
njnbd2e75c2004-11-24 16:43:43 +0000352}
353
sewardjfa8ec112005-01-19 11:55:34 +0000354Bool VG_(translate) ( ThreadId tid,
355 Addr64 orig_addr,
356 Bool debugging_translation,
357 Int debugging_verbosity )
sewardjde4a1d02002-03-22 01:27:54 +0000358{
sewardjfa8ec112005-01-19 11:55:34 +0000359 Addr64 redir, orig_addr0 = orig_addr;
360 Int tmpbuf_used, verbosity;
sewardjc771b292004-11-30 18:55:21 +0000361 Bool notrace_until_done;
362 UInt notrace_until_limit = 0;
363 Segment* seg;
sewardjfa8ec112005-01-19 11:55:34 +0000364 VexGuestExtents vge;
sewardjde4a1d02002-03-22 01:27:54 +0000365
njn36932cb2005-05-11 22:45:48 +0000366 /* Indicates what arch and subarch we are running on. */
367 static VexArch vex_arch = VexArch_INVALID;
368 static VexSubArch vex_subarch = VexSubArch_INVALID;
369
sewardj8b635a42004-11-22 19:01:47 +0000370 /* Make sure Vex is initialised right. */
sewardjbf426512005-01-17 18:35:30 +0000371 VexTranslateResult tres;
sewardj8b635a42004-11-22 19:01:47 +0000372 static Bool vex_init_done = False;
373
374 if (!vex_init_done) {
njn36932cb2005-05-11 22:45:48 +0000375 Bool ok = VGA_(getArchAndSubArch)( &vex_arch, &vex_subarch );
376 if (!ok) {
377 VG_(printf)("\n");
378 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
379 VG_(printf)(" Supported CPUs are:\n");
380 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
381 "AMD Athlon or above)\n");
382 VG_(printf)("\n");
383 VG_(exit)(1);
384 }
385 if (VG_(clo_verbosity) > 2) {
386 VG_(message)(Vg_DebugMsg,
387 "Host CPU: arch = %s, subarch = %s",
388 LibVEX_ppVexArch ( vex_arch ),
389 LibVEX_ppVexSubArch( vex_subarch ) );
390 }
391
sewardj8b635a42004-11-22 19:01:47 +0000392 LibVEX_Init ( &failure_exit, &log_bytes,
393 1, /* debug_paranoia */
394 False, /* valgrind support */
395 &VG_(clo_vex_control) );
396 vex_init_done = True;
397 }
398
399 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000400 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000401
sewardj25c7c3a2003-07-10 00:17:58 +0000402 /* Look in the code redirect table to see if we should
403 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000404 redir = VG_(code_redirect)(orig_addr);
405
nethercote59a122d2004-08-03 17:16:51 +0000406 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardjfa8ec112005-01-19 11:55:34 +0000407 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +0000408 Char name1[64] = "";
409 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +0000410 name1[0] = name2[0] = 0;
411 ok = VG_(get_fnname_w_offset)(orig_addr, name1, 64);
njnbe73f432005-03-26 21:34:45 +0000412 if (!ok) VG_(strcpy)(name1, "???");
sewardjfa8ec112005-01-19 11:55:34 +0000413 ok = VG_(get_fnname_w_offset)(redir, name2, 64);
njnbe73f432005-03-26 21:34:45 +0000414 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +0000415 VG_(message)(Vg_DebugMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000416 "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj8b635a42004-11-22 19:01:47 +0000417 orig_addr, name1,
418 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000419 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000420 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000421
sewardja60be0e2003-05-26 08:47:27 +0000422 /* If codegen tracing, don't start tracing until
423 notrace_until_limit blocks have gone by. This avoids printing
424 huge amounts of useless junk when all we want to see is the last
425 few blocks translated prior to a failure. Set
426 notrace_until_limit to be the number of translations to be made
427 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +0000428 notrace_until_done
429 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000430
fitzhardinge98abfc72003-12-16 02:05:15 +0000431 seg = VG_(find_segment)(orig_addr);
432
njn25e49d8e72002-09-23 09:36:25 +0000433 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000434 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000435
sewardj85ac6d42005-02-23 11:36:56 +0000436 /* If doing any code printing, print a basic block start marker */
437 if (VG_(clo_trace_flags) || debugging_translation) {
438 Char fnname[64] = "";
439 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
440 VG_(printf)(
441 "==== BB %d %s(0x%llx) approx BBs exec'd %lld ====\n",
442 VG_(get_bbs_translated)(), fnname, orig_addr,
443 VG_(bbs_done));
444 }
445
fitzhardinge98abfc72003-12-16 02:05:15 +0000446 if (seg == NULL ||
447 !VG_(seg_contains)(seg, orig_addr, 1) ||
448 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000449 /* Code address is bad - deliver a signal instead */
sewardjb5f6f512005-03-10 23:59:00 +0000450 vg_assert(!VG_(is_addressable)(orig_addr, 1,
451 VKI_PROT_READ|VKI_PROT_EXEC));
fitzhardinge98abfc72003-12-16 02:05:15 +0000452
fitzhardinge98abfc72003-12-16 02:05:15 +0000453 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000454 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
455 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000456 } else
sewardj8b635a42004-11-22 19:01:47 +0000457 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000458
nethercote4d714382004-10-13 09:47:24 +0000459 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000460 } else
sewardj8b635a42004-11-22 19:01:47 +0000461 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000462
njn25e49d8e72002-09-23 09:36:25 +0000463 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000464 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +0000465 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +0000466 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +0000467 }
468 else
sewardjfa8ec112005-01-19 11:55:34 +0000469 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +0000470 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +0000471 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +0000472 }
njn25e49d8e72002-09-23 09:36:25 +0000473
njn31513b42005-06-01 03:09:59 +0000474 VGP_PUSHCC(VgpVexTime);
475
sewardj8b635a42004-11-22 19:01:47 +0000476 /* Actually do the translation. */
njn51d827b2005-05-09 01:02:08 +0000477 tl_assert2(VG_(tdict).tool_instrument,
478 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj8b635a42004-11-22 19:01:47 +0000479 tres = LibVEX_Translate (
njn36932cb2005-05-11 22:45:48 +0000480 vex_arch, vex_subarch,
481 vex_arch, vex_subarch,
sewardjb5f6f512005-03-10 23:59:00 +0000482 (UChar*)ULong_to_Ptr(orig_addr),
sewardjfa8ec112005-01-19 11:55:34 +0000483 (Addr64)orig_addr,
sewardj8b635a42004-11-22 19:01:47 +0000484 chase_into_ok,
sewardjfa8ec112005-01-19 11:55:34 +0000485 &vge,
sewardj8b635a42004-11-22 19:01:47 +0000486 tmpbuf, N_TMPBUF, &tmpbuf_used,
njn51d827b2005-05-09 01:02:08 +0000487 VG_(tdict).tool_instrument,
njnbd2e75c2004-11-24 16:43:43 +0000488 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000489 ? vg_SP_update_pass
490 : NULL,
491 True, /* cleanup after instrumentation */
492 NULL,
sewardjc771b292004-11-30 18:55:21 +0000493 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000494 );
njn25e49d8e72002-09-23 09:36:25 +0000495
sewardjbf426512005-01-17 18:35:30 +0000496 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +0000497 vg_assert(tmpbuf_used <= N_TMPBUF);
498 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000499
njn31513b42005-06-01 03:09:59 +0000500 VGP_POPCC(VgpVexTime);
501
sewardjc771b292004-11-30 18:55:21 +0000502#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000503
nethercote59a122d2004-08-03 17:16:51 +0000504 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +0000505 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000506
507 // If debugging, don't do anything with the translated block; we
508 // only did this for the debugging output produced along the way.
509 if (!debugging_translation) {
510 // Note that we use orig_addr0, not orig_addr, which might have been
511 // changed by the redirection
njn8bddf582005-05-13 23:40:55 +0000512 VG_(add_to_transtab)( &vge,
513 orig_addr0,
514 (Addr)(&tmpbuf[0]),
515 tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000516 }
nethercote59a122d2004-08-03 17:16:51 +0000517
njn25e49d8e72002-09-23 09:36:25 +0000518 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000519
520 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000521}
522
523/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +0000524/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000525/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000526