blob: 18be7ab5c067544041c3a0f75265f77cf96157bd [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
nethercotebb1c9912004-01-04 16:43:23 +000011 Copyright (C) 2000-2004 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"
sewardjde4a1d02002-03-22 01:27:54 +000033
sewardjde4a1d02002-03-22 01:27:54 +000034
nethercotebee3fd92004-08-02 15:17:43 +000035/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +000036/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +000037/*------------------------------------------------------------*/
38
sewardj8b635a42004-11-22 19:01:47 +000039/* NOTE: this comment is out of date */
njn9b007f62003-04-07 14:40:25 +000040
nethercote996901a2004-08-03 13:29:09 +000041/* For tools that want to know about %ESP changes, this pass adds
42 in the appropriate hooks. We have to do it after the tool's
43 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +000044 it adds in, and we must do it before register allocation because
45 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +000046 Thus we have it as an extra phase between the two.
47
48 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
49 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
50 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
51 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
52 instruction clobbers t_ESP, we don't track it anymore, and fall back to
53 the delta-is-unknown case. That case is also used when the delta is not
54 a nice small amount, or an unknown amount.
55*/
sewardjde4a1d02002-03-22 01:27:54 +000056
57static
sewardj8b635a42004-11-22 19:01:47 +000058IRBB* vg_SP_update_pass ( IRBB* bb_in, VexGuestLayout* layout,
59 IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +000060{
sewardj7cf97ee2004-11-28 14:25:01 +000061 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj8b635a42004-11-22 19:01:47 +000062 IRDirty *dcall, *d;
63 IRStmt* st;
64 IRExpr* e;
65 IRArray* descr;
sewardj7cf97ee2004-11-28 14:25:01 +000066 IRTemp curr;
67 IRType typeof_SP;
68 Long delta;
sewardjde4a1d02002-03-22 01:27:54 +000069
sewardj8b635a42004-11-22 19:01:47 +000070 /* Set up BB */
71 IRBB* bb = emptyIRBB();
72 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
73 bb->next = dopyIRExpr(bb_in->next);
74 bb->jumpkind = bb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +000075
sewardj7cf97ee2004-11-28 14:25:01 +000076 curr = IRTemp_INVALID;
77 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +000078
sewardj7cf97ee2004-11-28 14:25:01 +000079 sizeof_SP = layout->sizeof_SP;
80 offset_SP = layout->offset_SP;
81 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +000082 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +000083
sewardj8b635a42004-11-22 19:01:47 +000084# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
85# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +000086
sewardj8b635a42004-11-22 19:01:47 +000087# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +000088
sewardj8b635a42004-11-22 19:01:47 +000089# define GET_CONST(con) \
90 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
91 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +000092
sewardj8b635a42004-11-22 19:01:47 +000093# define DO(kind, syze) \
94 do { \
95 if (!VG_(defined_##kind##_mem_stack_##syze)()) \
96 goto generic; \
97 \
98 /* I don't know if it's really necessary to say that the */ \
99 /* call reads the stack pointer. But anyway, we do. */ \
100 dcall = unsafeIRDirty_0_N( \
101 1/*regparms*/, \
102 "track_" #kind "_mem_stack_" #syze, \
103 VG_(tool_interface) \
104 .track_##kind##_mem_stack_##syze, \
105 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. */
281#define N_TMPBUF 10000
282static 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{
290 LibVEX_ClearTemporary(True);
sewardjc621f762004-11-26 13:49:59 +0000291 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000292}
293
294static
295void log_bytes ( Char* bytes, Int nbytes )
296{
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
nethercote4d714382004-10-13 09:47:24 +0000346Bool VG_(translate) ( ThreadId tid, Addr orig_addr,
nethercote59a122d2004-08-03 17:16:51 +0000347 Bool debugging_translation )
sewardjde4a1d02002-03-22 01:27:54 +0000348{
sewardjc771b292004-11-30 18:55:21 +0000349 Addr redir, orig_addr0 = orig_addr;
350 Int orig_size, tmpbuf_used, verbosity;
351 Bool notrace_until_done;
352 UInt notrace_until_limit = 0;
353 Segment* seg;
sewardjde4a1d02002-03-22 01:27:54 +0000354
sewardj8b635a42004-11-22 19:01:47 +0000355 /* Make sure Vex is initialised right. */
356 TranslateResult tres;
357 static Bool vex_init_done = False;
358
359 if (!vex_init_done) {
360 LibVEX_Init ( &failure_exit, &log_bytes,
361 1, /* debug_paranoia */
362 False, /* valgrind support */
363 &VG_(clo_vex_control) );
364 vex_init_done = True;
365 }
366
367 /* profiling ... */
sewardjde4a1d02002-03-22 01:27:54 +0000368 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +0000369
sewardj25c7c3a2003-07-10 00:17:58 +0000370 /* Look in the code redirect table to see if we should
371 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000372 redir = VG_(code_redirect)(orig_addr);
373
nethercote59a122d2004-08-03 17:16:51 +0000374 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
sewardj8b635a42004-11-22 19:01:47 +0000375 Char name1[64] = "";
376 Char name2[64] = "";
377 VG_(get_fnname_w_offset)(orig_addr, name1, 64);
378 VG_(get_fnname_w_offset)(redir, name2, 64);
sewardjc771b292004-11-30 18:55:21 +0000379 name1[63] = name2[63] = 0;
fitzhardinge98abfc72003-12-16 02:05:15 +0000380 VG_(message)(Vg_UserMsg,
sewardj8b635a42004-11-22 19:01:47 +0000381 "TRANSLATE: %p (%s) redirected to %p (%s)",
382 orig_addr, name1,
383 redir, name2 );
nethercote59a122d2004-08-03 17:16:51 +0000384 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000385 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +0000386
sewardja60be0e2003-05-26 08:47:27 +0000387 /* If codegen tracing, don't start tracing until
388 notrace_until_limit blocks have gone by. This avoids printing
389 huge amounts of useless junk when all we want to see is the last
390 few blocks translated prior to a failure. Set
391 notrace_until_limit to be the number of translations to be made
392 before --trace-codegen= style printing takes effect. */
nethercote92e7b7f2004-08-07 17:52:25 +0000393 notrace_until_done = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +0000394
fitzhardinge98abfc72003-12-16 02:05:15 +0000395 seg = VG_(find_segment)(orig_addr);
396
njn25e49d8e72002-09-23 09:36:25 +0000397 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +0000398 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +0000399
fitzhardinge98abfc72003-12-16 02:05:15 +0000400 if (seg == NULL ||
401 !VG_(seg_contains)(seg, orig_addr, 1) ||
402 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000403 /* Code address is bad - deliver a signal instead */
404 vg_assert(!VG_(is_addressable)(orig_addr, 1));
405
fitzhardinge98abfc72003-12-16 02:05:15 +0000406 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
sewardj8b635a42004-11-22 19:01:47 +0000407 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
408 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +0000409 } else
sewardj8b635a42004-11-22 19:01:47 +0000410 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +0000411
nethercote4d714382004-10-13 09:47:24 +0000412 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000413 } else
sewardj8b635a42004-11-22 19:01:47 +0000414 seg->flags |= SF_CODE; /* contains cached code */
sewardjde4a1d02002-03-22 01:27:54 +0000415
njn25e49d8e72002-09-23 09:36:25 +0000416 /* If doing any code printing, print a basic block start marker */
sewardj8b635a42004-11-22 19:01:47 +0000417 if (VG_(clo_trace_codegen)) {
njn25e49d8e72002-09-23 09:36:25 +0000418 Char fnname[64] = "";
sewardj8b635a42004-11-22 19:01:47 +0000419 VG_(get_fnname_w_offset)(orig_addr, fnname, 64);
njn25e49d8e72002-09-23 09:36:25 +0000420 VG_(printf)(
sewardj8b635a42004-11-22 19:01:47 +0000421 "==== BB %d %s(%p) approx BBs exec'd %llu ====\n",
nethercote92e7b7f2004-08-07 17:52:25 +0000422 VG_(get_bbs_translated)(), fnname, orig_addr,
njn25e49d8e72002-09-23 09:36:25 +0000423 VG_(bbs_done));
424 }
425
426 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +0000427 verbosity = 0;
428 if ( debugging_translation
429 || (VG_(clo_trace_codegen) > 0
430 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) ))
431 verbosity = VG_(clo_trace_codegen);
njn25e49d8e72002-09-23 09:36:25 +0000432
sewardj8b635a42004-11-22 19:01:47 +0000433 /* Actually do the translation. */
434 tres = LibVEX_Translate (
njn09aa1282004-11-30 23:39:13 +0000435 InsnSetArch, InsnSetArch,
sewardj8b635a42004-11-22 19:01:47 +0000436 (Char*)orig_addr, (Addr64)orig_addr,
437 chase_into_ok,
438 &orig_size,
439 tmpbuf, N_TMPBUF, &tmpbuf_used,
440 TL_(instrument),
njnbd2e75c2004-11-24 16:43:43 +0000441 need_to_handle_SP_assignment()
sewardj8b635a42004-11-22 19:01:47 +0000442 ? vg_SP_update_pass
443 : NULL,
444 True, /* cleanup after instrumentation */
445 NULL,
sewardjc771b292004-11-30 18:55:21 +0000446 verbosity
sewardj8b635a42004-11-22 19:01:47 +0000447 );
njn25e49d8e72002-09-23 09:36:25 +0000448
sewardj8b635a42004-11-22 19:01:47 +0000449 vg_assert(tres == TransOK);
450 vg_assert(tmpbuf_used <= N_TMPBUF);
451 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000452
sewardjc771b292004-11-30 18:55:21 +0000453#undef DECIDE_IF_PRINTING_CODEGEN
njn25e49d8e72002-09-23 09:36:25 +0000454
nethercote59a122d2004-08-03 17:16:51 +0000455 /* Copy data at trans_addr into the translation cache. */
456 /* Since the .orig_size and .trans_size fields are UShort, be paranoid. */
sewardj8b635a42004-11-22 19:01:47 +0000457 vg_assert(orig_size > 0 && orig_size < 65536);
458 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +0000459
460 // If debugging, don't do anything with the translated block; we
461 // only did this for the debugging output produced along the way.
462 if (!debugging_translation) {
463 // Note that we use orig_addr0, not orig_addr, which might have been
464 // changed by the redirection
sewardj8b635a42004-11-22 19:01:47 +0000465 VG_(add_to_trans_tab)( orig_addr0, orig_size,
466 (Addr)(&tmpbuf[0]), tmpbuf_used );
sewardjde4a1d02002-03-22 01:27:54 +0000467 }
nethercote59a122d2004-08-03 17:16:51 +0000468
njn25e49d8e72002-09-23 09:36:25 +0000469 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +0000470
471 return True;
sewardjde4a1d02002-03-22 01:27:54 +0000472}
473
474/*--------------------------------------------------------------------*/
475/*--- end vg_translate.c ---*/
476/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +0000477