blob: 4ec0043a77b6b84009ddbebb51dc1990231f1668 [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"
njn43b9a8a2005-05-10 04:37:01 +000034#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000035#include "pub_core_translate.h"
36#include "pub_core_transtab.h"
sewardjde4a1d02002-03-22 01:27:54 +000037
sewardjde4a1d02002-03-22 01:27:54 +000038
nethercotebee3fd92004-08-02 15:17:43 +000039/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +000040/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +000041/*------------------------------------------------------------*/
42
sewardj8b635a42004-11-22 19:01:47 +000043/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +000044
nethercote996901a2004-08-03 13:29:09 +000045/* For tools that want to know about %ESP changes, this pass adds
46 in the appropriate hooks. We have to do it after the tool's
47 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +000048 it adds in, and we must do it before register allocation because
49 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +000050 Thus we have it as an extra phase between the two.
51
52 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
53 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
54 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
55 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
56 instruction clobbers t_ESP, we don't track it anymore, and fall back to
57 the delta-is-unknown case. That case is also used when the delta is not
58 a nice small amount, or an unknown amount.
59*/
sewardjde4a1d02002-03-22 01:27:54 +000060
61static
sewardj8b635a42004-11-22 19:01:47 +000062IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +000063 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +000064{
sewardj7cf97ee2004-11-28 14:25:01 +000065 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +000066 IRDirty *dcall, *d;
67 IRStmt* st;
68 IRExpr* e;
69 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +000070 IRTemp curr;
71 IRType typeof_SP;
72 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +000073
sewardj8b635a42004-11-22 19:01:47 +000074 /* Set up BB */
75 IRBB* bb = emptyIRBB();
76 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
77 bb->next = dopyIRExpr(bb_in->next);
78 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +000079
sewardj7cf97ee2004-11-28 14:25:01 +000080 curr = IRTemp_INVALID;
81 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +000082
sewardj7cf97ee2004-11-28 14:25:01 +000083 sizeof_SP = layout->sizeof_SP;
84 offset_SP = layout->offset_SP;
85 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +000086 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +000087
sewardj8b635a42004-11-22 19:01:47 +000088# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
89# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +000090
sewardj8b635a42004-11-22 19:01:47 +000091# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +000092
sewardj8b635a42004-11-22 19:01:47 +000093# define GET_CONST(con) \
94 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
95 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +000096
sewardj8b635a42004-11-22 19:01:47 +000097# define DO(kind, syze) \
98 do { \
njn51d827b2005-05-09 01:02:08 +000099 if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000100 goto generic; \
101 \
102 /* I don't know if it's really necessary to say that the */ \
103 /* call reads the stack pointer. But anyway, we do. */ \
104 dcall = unsafeIRDirty_0_N( \
105 1/*regparms*/, \
106 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000107 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000108 mkIRExprVec_1(IRExpr_Tmp(curr)) \
109 ); \
110 dcall->nFxState = 1; \
111 dcall->fxState[0].fx = Ifx_Read; \
112 dcall->fxState[0].offset = layout->offset_SP; \
113 dcall->fxState[0].size = layout->sizeof_SP; \
114 \
115 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
116 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000117
sewardj8b635a42004-11-22 19:01:47 +0000118 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000119
sewardj8b635a42004-11-22 19:01:47 +0000120 st = bb_in->stmts[i];
121 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000122 continue;
123
sewardj8b635a42004-11-22 19:01:47 +0000124 /* t = Get(sp): curr = t, delta = 0 */
125 if (st->tag != Ist_Tmp) goto case2;
126 e = st->Ist.Tmp.data;
127 if (e->tag != Iex_Get) goto case2;
128 if (e->Iex.Get.offset != offset_SP) goto case2;
129 if (e->Iex.Get.ty != typeof_SP) goto case2;
130 curr = st->Ist.Tmp.tmp;
131 delta = 0;
132 addStmtToIRBB( bb, st );
133 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000134
sewardj8b635a42004-11-22 19:01:47 +0000135 case2:
136 /* t' = curr +/- const: curr = t', delta +=/-= const */
137 if (st->tag != Ist_Tmp) goto case3;
138 e = st->Ist.Tmp.data;
139 if (e->tag != Iex_Binop) goto case3;
140 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
141 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
142 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
143 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
144 curr = st->Ist.Tmp.tmp;
145 if (IS_ADD(e->Iex.Binop.op))
146 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
147 else
148 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
149 addStmtToIRBB( bb, st );
150 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000151
sewardj8b635a42004-11-22 19:01:47 +0000152 case3:
153 /* t' = curr: curr = t' */
154 if (st->tag != Ist_Tmp) goto case4;
155 e = st->Ist.Tmp.data;
156 if (e->tag != Iex_Tmp) goto case4;
157 if (e->Iex.Tmp.tmp != curr) goto case4;
158 curr = st->Ist.Tmp.tmp;
159 addStmtToIRBB( bb, st );
160 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000161
sewardj8b635a42004-11-22 19:01:47 +0000162 case4:
163 /* Put(sp) = curr */
164 if (st->tag != Ist_Put) goto case5;
165 if (st->Ist.Put.offset != offset_SP) goto case5;
166 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
167 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
168 switch (delta) {
169 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
170 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
171 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
172 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
173 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
174 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
175 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
176 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
177 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
178 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
179 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
180 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000181 }
sewardj8b635a42004-11-22 19:01:47 +0000182 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000183 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000184 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000185 /* Pass both the old and new SP values to this helper. */
186 old_SP = newIRTemp(bb->tyenv, typeof_SP);
187 addStmtToIRBB(
188 bb,
189 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
190 );
sewardjde4a1d02002-03-22 01:27:54 +0000191
sewardj2a99cf62004-11-24 10:44:19 +0000192 dcall = unsafeIRDirty_0_N(
193 2/*regparms*/,
194 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
195 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
196 );
sewardj8b635a42004-11-22 19:01:47 +0000197 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000198
199 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000200
sewardj8b635a42004-11-22 19:01:47 +0000201 curr = st->Ist.Put.data->Iex.Tmp.tmp;
202 delta = 0;
203 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000204 }
205
sewardj8b635a42004-11-22 19:01:47 +0000206 case5:
207 /* PutI or Dirty call which overlaps SP: complain. We can't
208 deal with SP changing in weird ways (well, we can, but not at
209 this time of night). */
210 if (st->tag == Ist_PutI) {
211 descr = st->Ist.PutI.descr;
212 minoff_ST = descr->base;
213 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
214 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
215 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000216 }
sewardj8b635a42004-11-22 19:01:47 +0000217 if (st->tag == Ist_Dirty) {
218 d = st->Ist.Dirty.details;
219 for (j = 0; j < d->nFxState; j++) {
220 minoff_ST = d->fxState[j].offset;
221 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
222 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
223 continue;
224 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
225 goto complain;
226 }
227 }
sewardjde4a1d02002-03-22 01:27:54 +0000228
sewardj8b635a42004-11-22 19:01:47 +0000229 /* well, not interesting. Just copy and keep going. */
230 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000231
sewardj8b635a42004-11-22 19:01:47 +0000232 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000233
sewardj8b635a42004-11-22 19:01:47 +0000234 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000235
sewardj8b635a42004-11-22 19:01:47 +0000236 complain:
237 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000238
239}
sewardj7c4b6042003-06-14 15:47:15 +0000240
sewardjde4a1d02002-03-22 01:27:54 +0000241
sewardjde4a1d02002-03-22 01:27:54 +0000242
sewardj8b635a42004-11-22 19:01:47 +0000243#if 0
244 for (i = 0; i < bb_in->stmts_used; i++) {
245 st = bb_in->stmts[i];
246 if (!st)
247 continue;
248 if (st->tag != Ist_Put)
249 goto boring;
250 offP = st->Ist.Put.offset;
251 if (offP != layout->offset_SP)
252 goto boring;
253 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
254 if (szP != layout->sizeof_SP)
255 goto boring;
256 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000257
sewardj8b635a42004-11-22 19:01:47 +0000258 /* I don't know if it's really necessary to say that the call reads
259 the stack pointer. But anyway, we do. */
260 dcall = unsafeIRDirty_0_N(
261 mkIRCallee(1, "VG_(unknown_esp_update)",
262 (HWord)&VG_(unknown_esp_update)),
263 mkIRExprVec_1(st->Ist.Put.data)
264 );
265 dcall->nFxState = 1;
266 dcall->fxState[0].fx = Ifx_Read;
267 dcall->fxState[0].offset = layout->offset_SP;
268 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000269
sewardj8b635a42004-11-22 19:01:47 +0000270 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
271
272 boring:
273 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000274 }
sewardj8b635a42004-11-22 19:01:47 +0000275#endif
276
sewardjde4a1d02002-03-22 01:27:54 +0000277
sewardjde4a1d02002-03-22 01:27:54 +0000278/*------------------------------------------------------------*/
279/*--- Main entry point for the JITter. ---*/
280/*------------------------------------------------------------*/
281
sewardj8b635a42004-11-22 19:01:47 +0000282/* Vex dumps the final code in here. Then we can copy it off
283 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000284#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000285static UChar tmpbuf[N_TMPBUF];
286
287/* Function pointers we must supply to LibVEX in order that it
288 can bomb out and emit messages under Valgrind's control. */
289__attribute__ ((noreturn))
290static
291void failure_exit ( void )
292{
sewardjbf426512005-01-17 18:35:30 +0000293 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000294 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000295}
296
297static
sewardjb5f6f512005-03-10 23:59:00 +0000298void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000299{
300 Int i;
301 for (i = 0; i < nbytes-3; i += 4)
302 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
303 for (; i < nbytes; i++)
304 VG_(printf)("%c", bytes[i]);
305}
306
nethercote59a122d2004-08-03 17:16:51 +0000307/* Translate the basic block beginning at orig_addr, and add it to
308 the translation cache & translation table. Unless 'debugging' is true,
309 in which case the call is being done for debugging purposes, so
310 (a) throw away the translation once it is made, and (b) produce a
311 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000312
nethercote59a122d2004-08-03 17:16:51 +0000313 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000314*/
sewardj8b635a42004-11-22 19:01:47 +0000315
316/* This stops Vex from chasing into function entry points that we wish
317 to redirect. Chasing across them obviously defeats the redirect
318 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
319 others. */
320static Bool chase_into_ok ( Addr64 addr64 )
321{
322 Addr addr = (Addr)addr64;
323 if (addr != VG_(code_redirect)(addr)) {
324 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
325 return False;
326 } else {
327 return True; /* ok to chase into 'addr' */
328 }
329}
330
njnbd2e75c2004-11-24 16:43:43 +0000331static Bool need_to_handle_SP_assignment(void)
332{
njn51d827b2005-05-09 01:02:08 +0000333 return ( VG_(tdict).track_new_mem_stack_4 ||
334 VG_(tdict).track_die_mem_stack_4 ||
335 VG_(tdict).track_new_mem_stack_8 ||
336 VG_(tdict).track_die_mem_stack_8 ||
337 VG_(tdict).track_new_mem_stack_12 ||
338 VG_(tdict).track_die_mem_stack_12 ||
339 VG_(tdict).track_new_mem_stack_16 ||
340 VG_(tdict).track_die_mem_stack_16 ||
341 VG_(tdict).track_new_mem_stack_32 ||
342 VG_(tdict).track_die_mem_stack_32 ||
343 VG_(tdict).track_new_mem_stack ||
344 VG_(tdict).track_die_mem_stack );
njnbd2e75c2004-11-24 16:43:43 +0000345}
346
sewardjfa8ec112005-01-19 11:55:34 +0000347Bool VG_(translate) ( ThreadId tid,
348 Addr64 orig_addr,
349 Bool debugging_translation,
350 Int debugging_verbosity )
sewardjde4a1d02002-03-22 01:27:54 +0000351{
sewardjfa8ec112005-01-19 11:55:34 +0000352 Addr64 redir, orig_addr0 = orig_addr;
353 Int tmpbuf_used, verbosity;
sewardjc771b292004-11-30 18:55:21 +0000354 Bool notrace_until_done;
355 UInt notrace_until_limit = 0;
356 Segment* seg;
sewardjfa8ec112005-01-19 11:55:34 +0000357 VexGuestExtents vge;
sewardjde4a1d02002-03-22 01:27:54 +0000358
njn36932cb2005-05-11 22:45:48 +0000359 /* Indicates what arch and subarch we are running on. */
360 static VexArch vex_arch = VexArch_INVALID;
361 static VexSubArch vex_subarch = VexSubArch_INVALID;
362
sewardj8b635a42004-11-22 19:01:47 +0000363 /* Make sure Vex is initialised right. */
sewardjbf426512005-01-17 18:35:30 +0000364 VexTranslateResult tres;
sewardj8b635a42004-11-22 19:01:47 +0000365 static Bool vex_init_done = False;
366
367 if (!vex_init_done) {
njn36932cb2005-05-11 22:45:48 +0000368 Bool ok = VGA_(getArchAndSubArch)( &vex_arch, &vex_subarch );
369 if (!ok) {
370 VG_(printf)("\n");
371 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
372 VG_(printf)(" Supported CPUs are:\n");
373 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
374 "AMD Athlon or above)\n");
375 VG_(printf)("\n");
376 VG_(exit)(1);
377 }
378 if (VG_(clo_verbosity) > 2) {
379 VG_(message)(Vg_DebugMsg,
380 "Host CPU: arch = %s, subarch = %s",
381 LibVEX_ppVexArch ( vex_arch ),
382 LibVEX_ppVexSubArch( vex_subarch ) );
383 }
384
sewardj8b635a42004-11-22 19:01:47 +0000385 LibVEX_Init ( &failure_exit, &log_bytes,
386 1, /* debug_paranoia */
387 False, /* valgrind support */
388 &VG_(clo_vex_control) );
389 vex_init_done = True;
390 }
391
392 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000393 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000394
sewardj25c7c3a2003-07-10 00:17:58 +0000395 /* Look in the code redirect table to see if we should
396 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000397 redir = VG_(code_redirect)(orig_addr);
398
nethercote59a122d2004-08-03 17:16:51 +0000399 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardjfa8ec112005-01-19 11:55:34 +0000400 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +0000401 Char name1[64] = "";
402 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +0000403 name1[0] = name2[0] = 0;
404 ok = VG_(get_fnname_w_offset)(orig_addr, name1, 64);
njnbe73f432005-03-26 21:34:45 +0000405 if (!ok) VG_(strcpy)(name1, "???");
sewardjfa8ec112005-01-19 11:55:34 +0000406 ok = VG_(get_fnname_w_offset)(redir, name2, 64);
njnbe73f432005-03-26 21:34:45 +0000407 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +0000408 VG_(message)(Vg_DebugMsg,
sewardjfa8ec112005-01-19 11:55:34 +0000409 "TRANSLATE: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj8b635a42004-11-22 19:01:47 +0000410 orig_addr, name1,
411 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000412 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000413 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000414
sewardja60be0e2003-05-26 08:47:27 +0000415 /* If codegen tracing, don't start tracing until
416 notrace_until_limit blocks have gone by. This avoids printing
417 huge amounts of useless junk when all we want to see is the last
418 few blocks translated prior to a failure. Set
419 notrace_until_limit to be the number of translations to be made
420 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +0000421 notrace_until_done
422 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000423
fitzhardinge98abfc72003-12-16 02:05:15 +0000424 seg = VG_(find_segment)(orig_addr);
425
njn25e49d8e72002-09-23 09:36:25 +0000426 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000427 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000428
sewardj85ac6d42005-02-23 11:36:56 +0000429 /* If doing any code printing, print a basic block start marker */
430 if (VG_(clo_trace_flags) || debugging_translation) {
431 Char fnname[64] = "";
432 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
433 VG_(printf)(
434 "==== BB %d %s(0x%llx) approx BBs exec'd %lld ====\n",
435 VG_(get_bbs_translated)(), fnname, orig_addr,
436 VG_(bbs_done));
437 }
438
fitzhardinge98abfc72003-12-16 02:05:15 +0000439 if (seg == NULL ||
440 !VG_(seg_contains)(seg, orig_addr, 1) ||
441 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000442 /* Code address is bad - deliver a signal instead */
sewardjb5f6f512005-03-10 23:59:00 +0000443 vg_assert(!VG_(is_addressable)(orig_addr, 1,
444 VKI_PROT_READ|VKI_PROT_EXEC));
fitzhardinge98abfc72003-12-16 02:05:15 +0000445
fitzhardinge98abfc72003-12-16 02:05:15 +0000446 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000447 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
448 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000449 } else
sewardj8b635a42004-11-22 19:01:47 +0000450 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000451
nethercote4d714382004-10-13 09:47:24 +0000452 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000453 } else
sewardj8b635a42004-11-22 19:01:47 +0000454 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000455
njn25e49d8e72002-09-23 09:36:25 +0000456 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000457 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +0000458 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +0000459 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +0000460 }
461 else
sewardjfa8ec112005-01-19 11:55:34 +0000462 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +0000463 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +0000464 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +0000465 }
njn25e49d8e72002-09-23 09:36:25 +0000466
sewardj8b635a42004-11-22 19:01:47 +0000467 /* Actually do the translation. */
njn51d827b2005-05-09 01:02:08 +0000468 tl_assert2(VG_(tdict).tool_instrument,
469 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj8b635a42004-11-22 19:01:47 +0000470 tres = LibVEX_Translate (
njn36932cb2005-05-11 22:45:48 +0000471 vex_arch, vex_subarch,
472 vex_arch, vex_subarch,
sewardjb5f6f512005-03-10 23:59:00 +0000473 (UChar*)ULong_to_Ptr(orig_addr),
sewardjfa8ec112005-01-19 11:55:34 +0000474 (Addr64)orig_addr,
sewardj8b635a42004-11-22 19:01:47 +0000475 chase_into_ok,
sewardjfa8ec112005-01-19 11:55:34 +0000476 &vge,
sewardj8b635a42004-11-22 19:01:47 +0000477 tmpbuf, N_TMPBUF, &tmpbuf_used,
njn51d827b2005-05-09 01:02:08 +0000478 VG_(tdict).tool_instrument,
njnbd2e75c2004-11-24 16:43:43 +0000479 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000480 ? vg_SP_update_pass
481 : NULL,
482 True, /* cleanup after instrumentation */
483 NULL,
sewardjc771b292004-11-30 18:55:21 +0000484 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000485 );
njn25e49d8e72002-09-23 09:36:25 +0000486
sewardjbf426512005-01-17 18:35:30 +0000487 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +0000488 vg_assert(tmpbuf_used <= N_TMPBUF);
489 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000490
sewardjc771b292004-11-30 18:55:21 +0000491#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000492
nethercote59a122d2004-08-03 17:16:51 +0000493 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +0000494 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000495
496 // If debugging, don't do anything with the translated block; we
497 // only did this for the debugging output produced along the way.
498 if (!debugging_translation) {
499 // Note that we use orig_addr0, not orig_addr, which might have been
500 // changed by the redirection
njn8bddf582005-05-13 23:40:55 +0000501 VG_(add_to_transtab)( &vge,
502 orig_addr0,
503 (Addr)(&tmpbuf[0]),
504 tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000505 }
nethercote59a122d2004-08-03 17:16:51 +0000506
njn25e49d8e72002-09-23 09:36:25 +0000507 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000508
509 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000510}
511
512/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +0000513/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000514/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000515