blob: eb4d9409b8173ebdca79ef64b288665309ee26c0 [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"
njn04e16982005-05-31 00:23:43 +000035#include "pub_core_main.h" // for VG_(bbs_done)
njn20242342005-05-16 23:31:24 +000036#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000037#include "pub_core_profile.h"
njnd1af0032005-05-29 17:01:48 +000038#include "pub_core_redir.h"
njn0c246472005-05-31 01:00:08 +000039#include "pub_core_signals.h"
njn43b9a8a2005-05-10 04:37:01 +000040#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000041#include "pub_core_translate.h"
42#include "pub_core_transtab.h"
sewardjde4a1d02002-03-22 01:27:54 +000043
sewardjde4a1d02002-03-22 01:27:54 +000044
nethercotebee3fd92004-08-02 15:17:43 +000045/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +000046/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +000047/*------------------------------------------------------------*/
48
sewardj8b635a42004-11-22 19:01:47 +000049/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +000050
nethercote996901a2004-08-03 13:29:09 +000051/* For tools that want to know about %ESP changes, this pass adds
52 in the appropriate hooks. We have to do it after the tool's
53 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +000054 it adds in, and we must do it before register allocation because
55 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +000056 Thus we have it as an extra phase between the two.
57
58 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
59 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
60 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
61 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
62 instruction clobbers t_ESP, we don't track it anymore, and fall back to
63 the delta-is-unknown case. That case is also used when the delta is not
64 a nice small amount, or an unknown amount.
65*/
sewardjde4a1d02002-03-22 01:27:54 +000066
67static
sewardj8b635a42004-11-22 19:01:47 +000068IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +000069 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +000070{
sewardj7cf97ee2004-11-28 14:25:01 +000071 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +000072 IRDirty *dcall, *d;
73 IRStmt* st;
74 IRExpr* e;
75 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +000076 IRTemp curr;
77 IRType typeof_SP;
78 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +000079
sewardj8b635a42004-11-22 19:01:47 +000080 /* Set up BB */
81 IRBB* bb = emptyIRBB();
82 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
83 bb->next = dopyIRExpr(bb_in->next);
84 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +000085
sewardj7cf97ee2004-11-28 14:25:01 +000086 curr = IRTemp_INVALID;
87 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +000088
sewardj7cf97ee2004-11-28 14:25:01 +000089 sizeof_SP = layout->sizeof_SP;
90 offset_SP = layout->offset_SP;
91 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +000092 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +000093
sewardj8b635a42004-11-22 19:01:47 +000094# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
95# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +000096
sewardj8b635a42004-11-22 19:01:47 +000097# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +000098
sewardj8b635a42004-11-22 19:01:47 +000099# define GET_CONST(con) \
100 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
101 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000102
sewardj8b635a42004-11-22 19:01:47 +0000103# define DO(kind, syze) \
104 do { \
njn51d827b2005-05-09 01:02:08 +0000105 if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000106 goto generic; \
107 \
108 /* I don't know if it's really necessary to say that the */ \
109 /* call reads the stack pointer. But anyway, we do. */ \
110 dcall = unsafeIRDirty_0_N( \
111 1/*regparms*/, \
112 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000113 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000114 mkIRExprVec_1(IRExpr_Tmp(curr)) \
115 ); \
116 dcall->nFxState = 1; \
117 dcall->fxState[0].fx = Ifx_Read; \
118 dcall->fxState[0].offset = layout->offset_SP; \
119 dcall->fxState[0].size = layout->sizeof_SP; \
120 \
121 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
122 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000123
sewardj8b635a42004-11-22 19:01:47 +0000124 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000125
sewardj8b635a42004-11-22 19:01:47 +0000126 st = bb_in->stmts[i];
127 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000128 continue;
129
sewardj8b635a42004-11-22 19:01:47 +0000130 /* t = Get(sp): curr = t, delta = 0 */
131 if (st->tag != Ist_Tmp) goto case2;
132 e = st->Ist.Tmp.data;
133 if (e->tag != Iex_Get) goto case2;
134 if (e->Iex.Get.offset != offset_SP) goto case2;
135 if (e->Iex.Get.ty != typeof_SP) goto case2;
136 curr = st->Ist.Tmp.tmp;
137 delta = 0;
138 addStmtToIRBB( bb, st );
139 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000140
sewardj8b635a42004-11-22 19:01:47 +0000141 case2:
142 /* t' = curr +/- const: curr = t', delta +=/-= const */
143 if (st->tag != Ist_Tmp) goto case3;
144 e = st->Ist.Tmp.data;
145 if (e->tag != Iex_Binop) goto case3;
146 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
147 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
148 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
149 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
150 curr = st->Ist.Tmp.tmp;
151 if (IS_ADD(e->Iex.Binop.op))
152 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
153 else
154 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
155 addStmtToIRBB( bb, st );
156 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000157
sewardj8b635a42004-11-22 19:01:47 +0000158 case3:
159 /* t' = curr: curr = t' */
160 if (st->tag != Ist_Tmp) goto case4;
161 e = st->Ist.Tmp.data;
162 if (e->tag != Iex_Tmp) goto case4;
163 if (e->Iex.Tmp.tmp != curr) goto case4;
164 curr = st->Ist.Tmp.tmp;
165 addStmtToIRBB( bb, st );
166 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000167
sewardj8b635a42004-11-22 19:01:47 +0000168 case4:
169 /* Put(sp) = curr */
170 if (st->tag != Ist_Put) goto case5;
171 if (st->Ist.Put.offset != offset_SP) goto case5;
172 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
173 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
174 switch (delta) {
175 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
176 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
177 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
178 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
179 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
180 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
181 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
182 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
183 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
184 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
185 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
186 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000187 }
sewardj8b635a42004-11-22 19:01:47 +0000188 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000189 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000190 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000191 /* Pass both the old and new SP values to this helper. */
192 old_SP = newIRTemp(bb->tyenv, typeof_SP);
193 addStmtToIRBB(
194 bb,
195 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
196 );
sewardjde4a1d02002-03-22 01:27:54 +0000197
sewardj2a99cf62004-11-24 10:44:19 +0000198 dcall = unsafeIRDirty_0_N(
199 2/*regparms*/,
200 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
201 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
202 );
sewardj8b635a42004-11-22 19:01:47 +0000203 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000204
205 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000206
sewardj8b635a42004-11-22 19:01:47 +0000207 curr = st->Ist.Put.data->Iex.Tmp.tmp;
208 delta = 0;
209 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000210 }
211
sewardj8b635a42004-11-22 19:01:47 +0000212 case5:
213 /* PutI or Dirty call which overlaps SP: complain. We can't
214 deal with SP changing in weird ways (well, we can, but not at
215 this time of night). */
216 if (st->tag == Ist_PutI) {
217 descr = st->Ist.PutI.descr;
218 minoff_ST = descr->base;
219 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
220 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
221 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000222 }
sewardj8b635a42004-11-22 19:01:47 +0000223 if (st->tag == Ist_Dirty) {
224 d = st->Ist.Dirty.details;
225 for (j = 0; j < d->nFxState; j++) {
226 minoff_ST = d->fxState[j].offset;
227 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
228 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
229 continue;
230 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
231 goto complain;
232 }
233 }
sewardjde4a1d02002-03-22 01:27:54 +0000234
sewardj8b635a42004-11-22 19:01:47 +0000235 /* well, not interesting. Just copy and keep going. */
236 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000237
sewardj8b635a42004-11-22 19:01:47 +0000238 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000239
sewardj8b635a42004-11-22 19:01:47 +0000240 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000241
sewardj8b635a42004-11-22 19:01:47 +0000242 complain:
243 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000244
245}
sewardj7c4b6042003-06-14 15:47:15 +0000246
sewardjde4a1d02002-03-22 01:27:54 +0000247
sewardjde4a1d02002-03-22 01:27:54 +0000248
sewardj8b635a42004-11-22 19:01:47 +0000249#if 0
250 for (i = 0; i < bb_in->stmts_used; i++) {
251 st = bb_in->stmts[i];
252 if (!st)
253 continue;
254 if (st->tag != Ist_Put)
255 goto boring;
256 offP = st->Ist.Put.offset;
257 if (offP != layout->offset_SP)
258 goto boring;
259 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
260 if (szP != layout->sizeof_SP)
261 goto boring;
262 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000263
sewardj8b635a42004-11-22 19:01:47 +0000264 /* I don't know if it's really necessary to say that the call reads
265 the stack pointer. But anyway, we do. */
266 dcall = unsafeIRDirty_0_N(
267 mkIRCallee(1, "VG_(unknown_esp_update)",
268 (HWord)&VG_(unknown_esp_update)),
269 mkIRExprVec_1(st->Ist.Put.data)
270 );
271 dcall->nFxState = 1;
272 dcall->fxState[0].fx = Ifx_Read;
273 dcall->fxState[0].offset = layout->offset_SP;
274 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000275
sewardj8b635a42004-11-22 19:01:47 +0000276 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
277
278 boring:
279 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000280 }
sewardj8b635a42004-11-22 19:01:47 +0000281#endif
282
sewardjde4a1d02002-03-22 01:27:54 +0000283
sewardjde4a1d02002-03-22 01:27:54 +0000284/*------------------------------------------------------------*/
285/*--- Main entry point for the JITter. ---*/
286/*------------------------------------------------------------*/
287
sewardj8b635a42004-11-22 19:01:47 +0000288/* Vex dumps the final code in here. Then we can copy it off
289 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000290#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000291static UChar tmpbuf[N_TMPBUF];
292
293/* Function pointers we must supply to LibVEX in order that it
294 can bomb out and emit messages under Valgrind's control. */
295__attribute__ ((noreturn))
296static
297void failure_exit ( void )
298{
sewardjbf426512005-01-17 18:35:30 +0000299 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000300 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000301}
302
303static
sewardjb5f6f512005-03-10 23:59:00 +0000304void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000305{
306 Int i;
307 for (i = 0; i < nbytes-3; i += 4)
308 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
309 for (; i < nbytes; i++)
310 VG_(printf)("%c", bytes[i]);
311}
312
nethercote59a122d2004-08-03 17:16:51 +0000313/* Translate the basic block beginning at orig_addr, and add it to
314 the translation cache & translation table. Unless 'debugging' is true,
315 in which case the call is being done for debugging purposes, so
316 (a) throw away the translation once it is made, and (b) produce a
317 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000318
nethercote59a122d2004-08-03 17:16:51 +0000319 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000320*/
sewardj8b635a42004-11-22 19:01:47 +0000321
322/* This stops Vex from chasing into function entry points that we wish
323 to redirect. Chasing across them obviously defeats the redirect
324 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
325 others. */
326static Bool chase_into_ok ( Addr64 addr64 )
327{
328 Addr addr = (Addr)addr64;
329 if (addr != VG_(code_redirect)(addr)) {
330 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
331 return False;
332 } else {
333 return True; /* ok to chase into 'addr' */
334 }
335}
336
njnbd2e75c2004-11-24 16:43:43 +0000337static Bool need_to_handle_SP_assignment(void)
338{
njn51d827b2005-05-09 01:02:08 +0000339 return ( VG_(tdict).track_new_mem_stack_4 ||
340 VG_(tdict).track_die_mem_stack_4 ||
341 VG_(tdict).track_new_mem_stack_8 ||
342 VG_(tdict).track_die_mem_stack_8 ||
343 VG_(tdict).track_new_mem_stack_12 ||
344 VG_(tdict).track_die_mem_stack_12 ||
345 VG_(tdict).track_new_mem_stack_16 ||
346 VG_(tdict).track_die_mem_stack_16 ||
347 VG_(tdict).track_new_mem_stack_32 ||
348 VG_(tdict).track_die_mem_stack_32 ||
349 VG_(tdict).track_new_mem_stack ||
350 VG_(tdict).track_die_mem_stack );
njnbd2e75c2004-11-24 16:43:43 +0000351}
352
sewardjfa8ec112005-01-19 11:55:34 +0000353Bool VG_(translate) ( ThreadId tid,
354 Addr64 orig_addr,
355 Bool debugging_translation,
356 Int debugging_verbosity )
sewardjde4a1d02002-03-22 01:27:54 +0000357{
sewardjfa8ec112005-01-19 11:55:34 +0000358 Addr64 redir, orig_addr0 = orig_addr;
359 Int tmpbuf_used, verbosity;
sewardjc771b292004-11-30 18:55:21 +0000360 Bool notrace_until_done;
361 UInt notrace_until_limit = 0;
362 Segment* seg;
sewardjfa8ec112005-01-19 11:55:34 +0000363 VexGuestExtents vge;
sewardjde4a1d02002-03-22 01:27:54 +0000364
njn36932cb2005-05-11 22:45:48 +0000365 /* Indicates what arch and subarch we are running on. */
366 static VexArch vex_arch = VexArch_INVALID;
367 static VexSubArch vex_subarch = VexSubArch_INVALID;
368
sewardj8b635a42004-11-22 19:01:47 +0000369 /* Make sure Vex is initialised right. */
sewardjbf426512005-01-17 18:35:30 +0000370 VexTranslateResult tres;
sewardj8b635a42004-11-22 19:01:47 +0000371 static Bool vex_init_done = False;
372
373 if (!vex_init_done) {
njn36932cb2005-05-11 22:45:48 +0000374 Bool ok = VGA_(getArchAndSubArch)( &vex_arch, &vex_subarch );
375 if (!ok) {
376 VG_(printf)("\n");
377 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
378 VG_(printf)(" Supported CPUs are:\n");
379 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
380 "AMD Athlon or above)\n");
381 VG_(printf)("\n");
382 VG_(exit)(1);
383 }
384 if (VG_(clo_verbosity) > 2) {
385 VG_(message)(Vg_DebugMsg,
386 "Host CPU: arch = %s, subarch = %s",
387 LibVEX_ppVexArch ( vex_arch ),
388 LibVEX_ppVexSubArch( vex_subarch ) );
389 }
390
sewardj8b635a42004-11-22 19:01:47 +0000391 LibVEX_Init ( &failure_exit, &log_bytes,
392 1, /* debug_paranoia */
393 False, /* valgrind support */
394 &VG_(clo_vex_control) );
395 vex_init_done = True;
396 }
397
398 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000399 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000400
sewardj25c7c3a2003-07-10 00:17:58 +0000401 /* Look in the code redirect table to see if we should
402 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000403 redir = VG_(code_redirect)(orig_addr);
404
nethercote59a122d2004-08-03 17:16:51 +0000405 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardjfa8ec112005-01-19 11:55:34 +0000406 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +0000407 Char name1[64] = "";
408 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +0000409 name1[0] = name2[0] = 0;
410 ok = VG_(get_fnname_w_offset)(orig_addr, name1, 64);
njnbe73f432005-03-26 21:34:45 +0000411 if (!ok) VG_(strcpy)(name1, "???");
sewardjfa8ec112005-01-19 11:55:34 +0000412 ok = VG_(get_fnname_w_offset)(redir, name2, 64);
njnbe73f432005-03-26 21:34:45 +0000413 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +0000414 VG_(message)(Vg_DebugMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000415 "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj8b635a42004-11-22 19:01:47 +0000416 orig_addr, name1,
417 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000418 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000419 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000420
sewardja60be0e2003-05-26 08:47:27 +0000421 /* If codegen tracing, don't start tracing until
422 notrace_until_limit blocks have gone by. This avoids printing
423 huge amounts of useless junk when all we want to see is the last
424 few blocks translated prior to a failure. Set
425 notrace_until_limit to be the number of translations to be made
426 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +0000427 notrace_until_done
428 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000429
fitzhardinge98abfc72003-12-16 02:05:15 +0000430 seg = VG_(find_segment)(orig_addr);
431
njn25e49d8e72002-09-23 09:36:25 +0000432 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000433 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000434
sewardj85ac6d42005-02-23 11:36:56 +0000435 /* If doing any code printing, print a basic block start marker */
436 if (VG_(clo_trace_flags) || debugging_translation) {
437 Char fnname[64] = "";
438 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
439 VG_(printf)(
440 "==== BB %d %s(0x%llx) approx BBs exec'd %lld ====\n",
441 VG_(get_bbs_translated)(), fnname, orig_addr,
442 VG_(bbs_done));
443 }
444
fitzhardinge98abfc72003-12-16 02:05:15 +0000445 if (seg == NULL ||
446 !VG_(seg_contains)(seg, orig_addr, 1) ||
447 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000448 /* Code address is bad - deliver a signal instead */
sewardjb5f6f512005-03-10 23:59:00 +0000449 vg_assert(!VG_(is_addressable)(orig_addr, 1,
450 VKI_PROT_READ|VKI_PROT_EXEC));
fitzhardinge98abfc72003-12-16 02:05:15 +0000451
fitzhardinge98abfc72003-12-16 02:05:15 +0000452 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000453 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
454 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000455 } else
sewardj8b635a42004-11-22 19:01:47 +0000456 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000457
nethercote4d714382004-10-13 09:47:24 +0000458 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000459 } else
sewardj8b635a42004-11-22 19:01:47 +0000460 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000461
njn25e49d8e72002-09-23 09:36:25 +0000462 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000463 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +0000464 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +0000465 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +0000466 }
467 else
sewardjfa8ec112005-01-19 11:55:34 +0000468 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +0000469 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +0000470 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +0000471 }
njn25e49d8e72002-09-23 09:36:25 +0000472
njn31513b42005-06-01 03:09:59 +0000473 VGP_PUSHCC(VgpVexTime);
474
sewardj8b635a42004-11-22 19:01:47 +0000475 /* Actually do the translation. */
njn51d827b2005-05-09 01:02:08 +0000476 tl_assert2(VG_(tdict).tool_instrument,
477 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj8b635a42004-11-22 19:01:47 +0000478 tres = LibVEX_Translate (
njn36932cb2005-05-11 22:45:48 +0000479 vex_arch, vex_subarch,
480 vex_arch, vex_subarch,
sewardjb5f6f512005-03-10 23:59:00 +0000481 (UChar*)ULong_to_Ptr(orig_addr),
sewardjfa8ec112005-01-19 11:55:34 +0000482 (Addr64)orig_addr,
sewardj8b635a42004-11-22 19:01:47 +0000483 chase_into_ok,
sewardjfa8ec112005-01-19 11:55:34 +0000484 &vge,
sewardj8b635a42004-11-22 19:01:47 +0000485 tmpbuf, N_TMPBUF, &tmpbuf_used,
njn51d827b2005-05-09 01:02:08 +0000486 VG_(tdict).tool_instrument,
njnbd2e75c2004-11-24 16:43:43 +0000487 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000488 ? vg_SP_update_pass
489 : NULL,
490 True, /* cleanup after instrumentation */
491 NULL,
sewardjc771b292004-11-30 18:55:21 +0000492 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000493 );
njn25e49d8e72002-09-23 09:36:25 +0000494
sewardjbf426512005-01-17 18:35:30 +0000495 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +0000496 vg_assert(tmpbuf_used <= N_TMPBUF);
497 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000498
njn31513b42005-06-01 03:09:59 +0000499 VGP_POPCC(VgpVexTime);
500
sewardjc771b292004-11-30 18:55:21 +0000501#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000502
nethercote59a122d2004-08-03 17:16:51 +0000503 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +0000504 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000505
506 // If debugging, don't do anything with the translated block; we
507 // only did this for the debugging output produced along the way.
508 if (!debugging_translation) {
509 // Note that we use orig_addr0, not orig_addr, which might have been
510 // changed by the redirection
njn8bddf582005-05-13 23:40:55 +0000511 VG_(add_to_transtab)( &vge,
512 orig_addr0,
513 (Addr)(&tmpbuf[0]),
514 tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000515 }
nethercote59a122d2004-08-03 17:16:51 +0000516
njn25e49d8e72002-09-23 09:36:25 +0000517 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000518
519 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000520}
521
522/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +0000523/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000524/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000525