blob: b6c31ac7e4656f495b4f9cea7c2fc2d23a2442d5 [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"
sewardjde4a1d02002-03-22 01:27:54 +000034
sewardjde4a1d02002-03-22 01:27:54 +000035
nethercotebee3fd92004-08-02 15:17:43 +000036/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +000037/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +000038/*------------------------------------------------------------*/
39
sewardj8b635a42004-11-22 19:01:47 +000040/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +000041
nethercote996901a2004-08-03 13:29:09 +000042/* For tools that want to know about %ESP changes, this pass adds
43 in the appropriate hooks. We have to do it after the tool's
44 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +000045 it adds in, and we must do it before register allocation because
46 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +000047 Thus we have it as an extra phase between the two.
48
49 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
50 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
51 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
52 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
53 instruction clobbers t_ESP, we don't track it anymore, and fall back to
54 the delta-is-unknown case. That case is also used when the delta is not
55 a nice small amount, or an unknown amount.
56*/
sewardjde4a1d02002-03-22 01:27:54 +000057
58static
sewardj8b635a42004-11-22 19:01:47 +000059IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
njn8786e532005-03-24 04:35:11 +000060 IRType gWordTy, IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +000061{
sewardj7cf97ee2004-11-28 14:25:01 +000062 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +000063 IRDirty *dcall, *d;
64 IRStmt* st;
65 IRExpr* e;
66 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +000067 IRTemp curr;
68 IRType typeof_SP;
69 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +000070
sewardj8b635a42004-11-22 19:01:47 +000071 /* Set up BB */
72 IRBB* bb = emptyIRBB();
73 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
74 bb->next = dopyIRExpr(bb_in->next);
75 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +000076
sewardj7cf97ee2004-11-28 14:25:01 +000077 curr = IRTemp_INVALID;
78 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +000079
sewardj7cf97ee2004-11-28 14:25:01 +000080 sizeof_SP = layout->sizeof_SP;
81 offset_SP = layout->offset_SP;
82 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +000083 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +000084
sewardj8b635a42004-11-22 19:01:47 +000085# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
86# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +000087
sewardj8b635a42004-11-22 19:01:47 +000088# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +000089
sewardj8b635a42004-11-22 19:01:47 +000090# define GET_CONST(con) \
91 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
92 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +000093
sewardj8b635a42004-11-22 19:01:47 +000094# define DO(kind, syze) \
95 do { \
96 if (!VG_(defined_##kind##_mem_stack_##syze)()) \
97 goto generic; \
98 \
99 /* I don't know if it's really necessary to say that the */ \
100 /* call reads the stack pointer. But anyway, we do. */ \
101 dcall = unsafeIRDirty_0_N( \
102 1/*regparms*/, \
103 "track_" #kind "_mem_stack_" #syze, \
njncf81d552005-03-31 04:52:26 +0000104 VG_(tdict).track_##kind##_mem_stack_##syze, \
sewardj8b635a42004-11-22 19:01:47 +0000105 mkIRExprVec_1(IRExpr_Tmp(curr)) \
106 ); \
107 dcall->nFxState = 1; \
108 dcall->fxState[0].fx = Ifx_Read; \
109 dcall->fxState[0].offset = layout->offset_SP; \
110 dcall->fxState[0].size = layout->sizeof_SP; \
111 \
112 addStmtToIRBB( bb, IRStmt_Dirty(dcall) ); \
113 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000114
sewardj8b635a42004-11-22 19:01:47 +0000115 for (i = 0; i < bb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000116
sewardj8b635a42004-11-22 19:01:47 +0000117 st = bb_in->stmts[i];
118 if (!st)
sewardjde4a1d02002-03-22 01:27:54 +0000119 continue;
120
sewardj8b635a42004-11-22 19:01:47 +0000121 /* t = Get(sp): curr = t, delta = 0 */
122 if (st->tag != Ist_Tmp) goto case2;
123 e = st->Ist.Tmp.data;
124 if (e->tag != Iex_Get) goto case2;
125 if (e->Iex.Get.offset != offset_SP) goto case2;
126 if (e->Iex.Get.ty != typeof_SP) goto case2;
127 curr = st->Ist.Tmp.tmp;
128 delta = 0;
129 addStmtToIRBB( bb, st );
130 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000131
sewardj8b635a42004-11-22 19:01:47 +0000132 case2:
133 /* t' = curr +/- const: curr = t', delta +=/-= const */
134 if (st->tag != Ist_Tmp) goto case3;
135 e = st->Ist.Tmp.data;
136 if (e->tag != Iex_Binop) goto case3;
137 if (e->Iex.Binop.arg1->tag != Iex_Tmp) goto case3;
138 if (e->Iex.Binop.arg1->Iex.Tmp.tmp != curr) goto case3;
139 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
140 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
141 curr = st->Ist.Tmp.tmp;
142 if (IS_ADD(e->Iex.Binop.op))
143 delta += GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
144 else
145 delta -= GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
146 addStmtToIRBB( bb, st );
147 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000148
sewardj8b635a42004-11-22 19:01:47 +0000149 case3:
150 /* t' = curr: curr = t' */
151 if (st->tag != Ist_Tmp) goto case4;
152 e = st->Ist.Tmp.data;
153 if (e->tag != Iex_Tmp) goto case4;
154 if (e->Iex.Tmp.tmp != curr) goto case4;
155 curr = st->Ist.Tmp.tmp;
156 addStmtToIRBB( bb, st );
157 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000158
sewardj8b635a42004-11-22 19:01:47 +0000159 case4:
160 /* Put(sp) = curr */
161 if (st->tag != Ist_Put) goto case5;
162 if (st->Ist.Put.offset != offset_SP) goto case5;
163 if (st->Ist.Put.data->tag != Iex_Tmp) goto case5;
164 if (st->Ist.Put.data->Iex.Tmp.tmp == curr) {
165 switch (delta) {
166 case 0: addStmtToIRBB(bb,st); delta = 0; continue;
167 case 4: DO(die, 4); addStmtToIRBB(bb,st); delta = 0; continue;
168 case -4: DO(new, 4); addStmtToIRBB(bb,st); delta = 0; continue;
169 case 8: DO(die, 8); addStmtToIRBB(bb,st); delta = 0; continue;
170 case -8: DO(new, 8); addStmtToIRBB(bb,st); delta = 0; continue;
171 case 12: DO(die, 12); addStmtToIRBB(bb,st); delta = 0; continue;
172 case -12: DO(new, 12); addStmtToIRBB(bb,st); delta = 0; continue;
173 case 16: DO(die, 16); addStmtToIRBB(bb,st); delta = 0; continue;
174 case -16: DO(new, 16); addStmtToIRBB(bb,st); delta = 0; continue;
175 case 32: DO(die, 32); addStmtToIRBB(bb,st); delta = 0; continue;
176 case -32: DO(new, 32); addStmtToIRBB(bb,st); delta = 0; continue;
177 default: goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000178 }
sewardj8b635a42004-11-22 19:01:47 +0000179 } else {
sewardj2a99cf62004-11-24 10:44:19 +0000180 IRTemp old_SP;
sewardj8b635a42004-11-22 19:01:47 +0000181 generic:
sewardj2a99cf62004-11-24 10:44:19 +0000182 /* Pass both the old and new SP values to this helper. */
183 old_SP = newIRTemp(bb->tyenv, typeof_SP);
184 addStmtToIRBB(
185 bb,
186 IRStmt_Tmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
187 );
sewardjde4a1d02002-03-22 01:27:54 +0000188
sewardj2a99cf62004-11-24 10:44:19 +0000189 dcall = unsafeIRDirty_0_N(
190 2/*regparms*/,
191 "VG_(unknown_SP_update)", &VG_(unknown_SP_update),
192 mkIRExprVec_2( IRExpr_Tmp(old_SP), st->Ist.Put.data )
193 );
sewardj8b635a42004-11-22 19:01:47 +0000194 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
sewardj2a99cf62004-11-24 10:44:19 +0000195
196 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000197
sewardj8b635a42004-11-22 19:01:47 +0000198 curr = st->Ist.Put.data->Iex.Tmp.tmp;
199 delta = 0;
200 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000201 }
202
sewardj8b635a42004-11-22 19:01:47 +0000203 case5:
204 /* PutI or Dirty call which overlaps SP: complain. We can't
205 deal with SP changing in weird ways (well, we can, but not at
206 this time of night). */
207 if (st->tag == Ist_PutI) {
208 descr = st->Ist.PutI.descr;
209 minoff_ST = descr->base;
210 maxoff_ST = descr->base + descr->nElems * sizeofIRType(descr->elemTy) - 1;
211 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
212 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000213 }
sewardj8b635a42004-11-22 19:01:47 +0000214 if (st->tag == Ist_Dirty) {
215 d = st->Ist.Dirty.details;
216 for (j = 0; j < d->nFxState; j++) {
217 minoff_ST = d->fxState[j].offset;
218 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
219 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
220 continue;
221 if (!(offset_SP > maxoff_ST || (offset_SP + sizeof_SP - 1) < minoff_ST))
222 goto complain;
223 }
224 }
sewardjde4a1d02002-03-22 01:27:54 +0000225
sewardj8b635a42004-11-22 19:01:47 +0000226 /* well, not interesting. Just copy and keep going. */
227 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000228
sewardj8b635a42004-11-22 19:01:47 +0000229 } /* for (i = 0; i < bb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000230
sewardj8b635a42004-11-22 19:01:47 +0000231 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000232
sewardj8b635a42004-11-22 19:01:47 +0000233 complain:
234 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000235
236}
sewardj7c4b6042003-06-14 15:47:15 +0000237
sewardjde4a1d02002-03-22 01:27:54 +0000238
sewardjde4a1d02002-03-22 01:27:54 +0000239
sewardj8b635a42004-11-22 19:01:47 +0000240#if 0
241 for (i = 0; i < bb_in->stmts_used; i++) {
242 st = bb_in->stmts[i];
243 if (!st)
244 continue;
245 if (st->tag != Ist_Put)
246 goto boring;
247 offP = st->Ist.Put.offset;
248 if (offP != layout->offset_SP)
249 goto boring;
250 szP = sizeofIRType(typeOfIRExpr(bb_in->tyenv, st->Ist.Put.data));
251 if (szP != layout->sizeof_SP)
252 goto boring;
253 vg_assert(isAtom(st->Ist.Put.data));
sewardj97ced732002-03-25 00:07:36 +0000254
sewardj8b635a42004-11-22 19:01:47 +0000255 /* I don't know if it's really necessary to say that the call reads
256 the stack pointer. But anyway, we do. */
257 dcall = unsafeIRDirty_0_N(
258 mkIRCallee(1, "VG_(unknown_esp_update)",
259 (HWord)&VG_(unknown_esp_update)),
260 mkIRExprVec_1(st->Ist.Put.data)
261 );
262 dcall->nFxState = 1;
263 dcall->fxState[0].fx = Ifx_Read;
264 dcall->fxState[0].offset = layout->offset_SP;
265 dcall->fxState[0].size = layout->sizeof_SP;
sewardj97ced732002-03-25 00:07:36 +0000266
sewardj8b635a42004-11-22 19:01:47 +0000267 addStmtToIRBB( bb, IRStmt_Dirty(dcall) );
268
269 boring:
270 addStmtToIRBB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000271 }
sewardj8b635a42004-11-22 19:01:47 +0000272#endif
273
sewardjde4a1d02002-03-22 01:27:54 +0000274
sewardjde4a1d02002-03-22 01:27:54 +0000275/*------------------------------------------------------------*/
276/*--- Main entry point for the JITter. ---*/
277/*------------------------------------------------------------*/
278
sewardj8b635a42004-11-22 19:01:47 +0000279/* Vex dumps the final code in here. Then we can copy it off
280 wherever we like. */
sewardjfb154a52005-03-31 15:48:57 +0000281#define N_TMPBUF 20000
sewardj8b635a42004-11-22 19:01:47 +0000282static UChar tmpbuf[N_TMPBUF];
283
284/* Function pointers we must supply to LibVEX in order that it
285 can bomb out and emit messages under Valgrind's control. */
286__attribute__ ((noreturn))
287static
288void failure_exit ( void )
289{
sewardjbf426512005-01-17 18:35:30 +0000290 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000291 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000292}
293
294static
sewardjb5f6f512005-03-10 23:59:00 +0000295void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000296{
297 Int i;
298 for (i = 0; i < nbytes-3; i += 4)
299 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
300 for (; i < nbytes; i++)
301 VG_(printf)("%c", bytes[i]);
302}
303
nethercote59a122d2004-08-03 17:16:51 +0000304/* Translate the basic block beginning at orig_addr, and add it to
305 the translation cache & translation table. Unless 'debugging' is true,
306 in which case the call is being done for debugging purposes, so
307 (a) throw away the translation once it is made, and (b) produce a
308 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +0000309
nethercote59a122d2004-08-03 17:16:51 +0000310 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +0000311*/
sewardj8b635a42004-11-22 19:01:47 +0000312
313/* This stops Vex from chasing into function entry points that we wish
314 to redirect. Chasing across them obviously defeats the redirect
315 mechanism, with bad effects for Memcheck, Addrcheck, and possibly
316 others. */
317static Bool chase_into_ok ( Addr64 addr64 )
318{
319 Addr addr = (Addr)addr64;
320 if (addr != VG_(code_redirect)(addr)) {
321 if (0) VG_(printf)("not chasing into 0x%x\n", addr);
322 return False;
323 } else {
324 return True; /* ok to chase into 'addr' */
325 }
326}
327
njnbd2e75c2004-11-24 16:43:43 +0000328static Bool need_to_handle_SP_assignment(void)
329{
330 return ( VG_(defined_new_mem_stack_4)() ||
331 VG_(defined_die_mem_stack_4)() ||
332 VG_(defined_new_mem_stack_8)() ||
333 VG_(defined_die_mem_stack_8)() ||
334 VG_(defined_new_mem_stack_12)() ||
335 VG_(defined_die_mem_stack_12)() ||
336 VG_(defined_new_mem_stack_16)() ||
337 VG_(defined_die_mem_stack_16)() ||
338 VG_(defined_new_mem_stack_32)() ||
339 VG_(defined_die_mem_stack_32)() ||
340 VG_(defined_new_mem_stack)() ||
341 VG_(defined_die_mem_stack)()
342 );
343}
344
345
sewardjfa8ec112005-01-19 11:55:34 +0000346Bool VG_(translate) ( ThreadId tid,
347 Addr64 orig_addr,
348 Bool debugging_translation,
349 Int debugging_verbosity )
sewardjde4a1d02002-03-22 01:27:54 +0000350{
sewardjfa8ec112005-01-19 11:55:34 +0000351 Addr64 redir, orig_addr0 = orig_addr;
352 Int tmpbuf_used, verbosity;
sewardjc771b292004-11-30 18:55:21 +0000353 Bool notrace_until_done;
354 UInt notrace_until_limit = 0;
355 Segment* seg;
sewardjfa8ec112005-01-19 11:55:34 +0000356 VexGuestExtents vge;
sewardjde4a1d02002-03-22 01:27:54 +0000357
sewardj8b635a42004-11-22 19:01:47 +0000358 /* Make sure Vex is initialised right. */
sewardjbf426512005-01-17 18:35:30 +0000359 VexTranslateResult tres;
sewardj8b635a42004-11-22 19:01:47 +0000360 static Bool vex_init_done = False;
361
362 if (!vex_init_done) {
363 LibVEX_Init ( &failure_exit, &log_bytes,
364 1, /* debug_paranoia */
365 False, /* valgrind support */
366 &VG_(clo_vex_control) );
367 vex_init_done = True;
368 }
369
370 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000371 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000372
sewardj25c7c3a2003-07-10 00:17:58 +0000373 /* Look in the code redirect table to see if we should
374 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000375 redir = VG_(code_redirect)(orig_addr);
376
nethercote59a122d2004-08-03 17:16:51 +0000377 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardjfa8ec112005-01-19 11:55:34 +0000378 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +0000379 Char name1[64] = "";
380 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +0000381 name1[0] = name2[0] = 0;
382 ok = VG_(get_fnname_w_offset)(orig_addr, name1, 64);
njnbe73f432005-03-26 21:34:45 +0000383 if (!ok) VG_(strcpy)(name1, "???");
sewardjfa8ec112005-01-19 11:55:34 +0000384 ok = VG_(get_fnname_w_offset)(redir, name2, 64);
njnbe73f432005-03-26 21:34:45 +0000385 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +0000386 VG_(message)(Vg_DebugMsg,
sewardjfa8ec112005-01-19 11:55:34 +0000387 "TRANSLATE: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj8b635a42004-11-22 19:01:47 +0000388 orig_addr, name1,
389 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000390 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000391 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000392
sewardja60be0e2003-05-26 08:47:27 +0000393 /* If codegen tracing, don't start tracing until
394 notrace_until_limit blocks have gone by. This avoids printing
395 huge amounts of useless junk when all we want to see is the last
396 few blocks translated prior to a failure. Set
397 notrace_until_limit to be the number of translations to be made
398 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +0000399 notrace_until_done
400 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000401
fitzhardinge98abfc72003-12-16 02:05:15 +0000402 seg = VG_(find_segment)(orig_addr);
403
njn25e49d8e72002-09-23 09:36:25 +0000404 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000405 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000406
sewardj85ac6d42005-02-23 11:36:56 +0000407 /* If doing any code printing, print a basic block start marker */
408 if (VG_(clo_trace_flags) || debugging_translation) {
409 Char fnname[64] = "";
410 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
411 VG_(printf)(
412 "==== BB %d %s(0x%llx) approx BBs exec'd %lld ====\n",
413 VG_(get_bbs_translated)(), fnname, orig_addr,
414 VG_(bbs_done));
415 }
416
fitzhardinge98abfc72003-12-16 02:05:15 +0000417 if (seg == NULL ||
418 !VG_(seg_contains)(seg, orig_addr, 1) ||
419 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000420 /* Code address is bad - deliver a signal instead */
sewardjb5f6f512005-03-10 23:59:00 +0000421 vg_assert(!VG_(is_addressable)(orig_addr, 1,
422 VKI_PROT_READ|VKI_PROT_EXEC));
fitzhardinge98abfc72003-12-16 02:05:15 +0000423
fitzhardinge98abfc72003-12-16 02:05:15 +0000424 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000425 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
426 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000427 } else
sewardj8b635a42004-11-22 19:01:47 +0000428 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000429
nethercote4d714382004-10-13 09:47:24 +0000430 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000431 } else
sewardj8b635a42004-11-22 19:01:47 +0000432 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000433
njn25e49d8e72002-09-23 09:36:25 +0000434 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000435 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +0000436 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +0000437 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +0000438 }
439 else
sewardjfa8ec112005-01-19 11:55:34 +0000440 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +0000441 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +0000442 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +0000443 }
njn25e49d8e72002-09-23 09:36:25 +0000444
sewardj8b635a42004-11-22 19:01:47 +0000445 /* Actually do the translation. */
446 tres = LibVEX_Translate (
sewardj51ac0872004-12-21 01:20:49 +0000447 VG_(vex_arch), VG_(vex_subarch),
448 VG_(vex_arch), VG_(vex_subarch),
sewardjb5f6f512005-03-10 23:59:00 +0000449 (UChar*)ULong_to_Ptr(orig_addr),
sewardjfa8ec112005-01-19 11:55:34 +0000450 (Addr64)orig_addr,
sewardj8b635a42004-11-22 19:01:47 +0000451 chase_into_ok,
sewardjfa8ec112005-01-19 11:55:34 +0000452 &vge,
sewardj8b635a42004-11-22 19:01:47 +0000453 tmpbuf, N_TMPBUF, &tmpbuf_used,
454 TL_(instrument),
njnbd2e75c2004-11-24 16:43:43 +0000455 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000456 ? vg_SP_update_pass
457 : NULL,
458 True, /* cleanup after instrumentation */
459 NULL,
sewardjc771b292004-11-30 18:55:21 +0000460 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000461 );
njn25e49d8e72002-09-23 09:36:25 +0000462
sewardjbf426512005-01-17 18:35:30 +0000463 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +0000464 vg_assert(tmpbuf_used <= N_TMPBUF);
465 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000466
sewardjc771b292004-11-30 18:55:21 +0000467#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000468
nethercote59a122d2004-08-03 17:16:51 +0000469 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +0000470 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000471
472 // If debugging, don't do anything with the translated block; we
473 // only did this for the debugging output produced along the way.
474 if (!debugging_translation) {
475 // Note that we use orig_addr0, not orig_addr, which might have been
476 // changed by the redirection
sewardjfa8ec112005-01-19 11:55:34 +0000477 VG_(add_to_trans_tab)( &vge,
478 orig_addr0,
479 (Addr)(&tmpbuf[0]),
480 tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000481 }
nethercote59a122d2004-08-03 17:16:51 +0000482
njn25e49d8e72002-09-23 09:36:25 +0000483 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000484
485 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000486}
487
488/*--------------------------------------------------------------------*/
489/*--- end vg_translate.c ---*/
490/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000491