Fix crash in linux [rt_]sigaction wrapper with bad old/new sigaction handler.
[valgrind.git] / coregrind / m_translate.c
blob2d6d3bad4bc16aad00bca497a6b290980b85cc6b
2 /*--------------------------------------------------------------------*/
3 /*--- Interface to LibVEX_Translate, and the SP-update pass ---*/
4 /*--- m_translate.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2015 Julian Seward
12 jseward@acm.org
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.
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.
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.
29 The GNU General Public License is contained in the file COPYING.
32 #include "pub_core_basics.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_aspacemgr.h"
36 #include "pub_core_machine.h" // VG_(fnptr_to_fnentry)
37 // VG_(get_SP)
38 // VG_(machine_get_VexArchInfo)
39 #include "pub_core_libcbase.h"
40 #include "pub_core_libcassert.h"
41 #include "pub_core_libcprint.h"
42 #include "pub_core_options.h"
44 #include "pub_core_debuginfo.h" // VG_(get_fnname_w_offset)
45 #include "pub_core_redir.h" // VG_(redir_do_lookup)
47 #include "pub_core_signals.h" // VG_(synth_fault_{perms,mapping}
48 #include "pub_core_stacks.h" // VG_(unknown_SP_update*)()
49 #include "pub_core_tooliface.h" // VG_(tdict)
51 #include "pub_core_translate.h"
52 #include "pub_core_transtab.h"
53 #include "pub_core_dispatch.h" // VG_(run_innerloop__dispatch_{un}profiled)
54 // VG_(run_a_noredir_translation__return_point)
56 #include "pub_core_threadstate.h" // VexGuestArchState
57 #include "pub_core_trampoline.h" // VG_(ppctoc_magic_redirect_return_stub)
59 #include "pub_core_execontext.h" // VG_(make_depth_1_ExeContext_from_Addr)
61 #include "pub_core_gdbserver.h" // VG_(instrument_for_gdbserver_if_needed)
63 #include "libvex_emnote.h" // For PPC, EmWarn_PPC64_redir_underflow
65 /*------------------------------------------------------------*/
66 /*--- Stats ---*/
67 /*------------------------------------------------------------*/
69 static ULong n_SP_updates_fast = 0;
70 static ULong n_SP_updates_generic_known = 0;
71 static ULong n_SP_updates_generic_unknown = 0;
73 static ULong n_PX_VexRegUpdSpAtMemAccess = 0;
74 static ULong n_PX_VexRegUpdUnwindregsAtMemAccess = 0;
75 static ULong n_PX_VexRegUpdAllregsAtMemAccess = 0;
76 static ULong n_PX_VexRegUpdAllregsAtEachInsn = 0;
78 void VG_(print_translation_stats) ( void )
80 UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
81 + n_SP_updates_generic_unknown;
82 if (n_SP_updates == 0) {
83 VG_(message)(Vg_DebugMsg, "translate: no SP updates identified\n");
84 } else {
85 VG_(message)(Vg_DebugMsg,
86 "translate: fast SP updates identified: %'llu (%3.1f%%)\n",
87 n_SP_updates_fast, n_SP_updates_fast * 100.0 / n_SP_updates );
89 VG_(message)(Vg_DebugMsg,
90 "translate: generic_known SP updates identified: %'llu (%3.1f%%)\n",
91 n_SP_updates_generic_known,
92 n_SP_updates_generic_known * 100.0 / n_SP_updates );
94 VG_(message)(Vg_DebugMsg,
95 "translate: generic_unknown SP updates identified: %'llu (%3.1f%%)\n",
96 n_SP_updates_generic_unknown,
97 n_SP_updates_generic_unknown * 100.0 / n_SP_updates );
100 VG_(message)(Vg_DebugMsg,
101 "translate: PX: SPonly %'llu, UnwRegs %'llu, AllRegs %'llu, AllRegsAllInsns %'llu\n", n_PX_VexRegUpdSpAtMemAccess, n_PX_VexRegUpdUnwindregsAtMemAccess, n_PX_VexRegUpdAllregsAtMemAccess, n_PX_VexRegUpdAllregsAtEachInsn);
104 /*------------------------------------------------------------*/
105 /*--- %SP-update pass ---*/
106 /*------------------------------------------------------------*/
108 static Bool need_to_handle_SP_assignment(void)
110 return ( VG_(tdict).track_new_mem_stack_4 ||
111 VG_(tdict).track_die_mem_stack_4 ||
112 VG_(tdict).track_new_mem_stack_8 ||
113 VG_(tdict).track_die_mem_stack_8 ||
114 VG_(tdict).track_new_mem_stack_12 ||
115 VG_(tdict).track_die_mem_stack_12 ||
116 VG_(tdict).track_new_mem_stack_16 ||
117 VG_(tdict).track_die_mem_stack_16 ||
118 VG_(tdict).track_new_mem_stack_32 ||
119 VG_(tdict).track_die_mem_stack_32 ||
120 VG_(tdict).track_new_mem_stack_112 ||
121 VG_(tdict).track_die_mem_stack_112 ||
122 VG_(tdict).track_new_mem_stack_128 ||
123 VG_(tdict).track_die_mem_stack_128 ||
124 VG_(tdict).track_new_mem_stack_144 ||
125 VG_(tdict).track_die_mem_stack_144 ||
126 VG_(tdict).track_new_mem_stack_160 ||
127 VG_(tdict).track_die_mem_stack_160 ||
128 VG_(tdict).track_new_mem_stack ||
129 VG_(tdict).track_die_mem_stack );
132 // - The SP aliases are held in an array which is used as a circular buffer.
133 // This misses very few constant updates of SP (ie. < 0.1%) while using a
134 // small, constant structure that will also never fill up and cause
135 // execution to abort.
136 // - Unused slots have a .temp value of 'IRTemp_INVALID'.
137 // - 'next_SP_alias_slot' is the index where the next alias will be stored.
138 // - If the buffer fills, we circle around and start over-writing
139 // non-IRTemp_INVALID values. This is rare, and the overwriting of a
140 // value that would have subsequently be used is even rarer.
141 // - Every slot below next_SP_alias_slot holds a non-IRTemp_INVALID value.
142 // The rest either all won't (if we haven't yet circled around) or all
143 // will (if we have circled around).
145 typedef
146 struct {
147 IRTemp temp;
148 Long delta;
150 SP_Alias;
152 // With 32 slots the buffer fills very rarely -- eg. once in a run of GCC.
153 // And I've tested with smaller values and the wrap-around case works ok.
154 #define N_ALIASES 32
155 static SP_Alias SP_aliases[N_ALIASES];
156 static Int next_SP_alias_slot = 0;
158 static void clear_SP_aliases(void)
160 Int i;
161 for (i = 0; i < N_ALIASES; i++) {
162 SP_aliases[i].temp = IRTemp_INVALID;
163 SP_aliases[i].delta = 0;
165 next_SP_alias_slot = 0;
168 static void add_SP_alias(IRTemp temp, Long delta)
170 vg_assert(temp != IRTemp_INVALID);
171 SP_aliases[ next_SP_alias_slot ].temp = temp;
172 SP_aliases[ next_SP_alias_slot ].delta = delta;
173 next_SP_alias_slot++;
174 if (N_ALIASES == next_SP_alias_slot) next_SP_alias_slot = 0;
177 static Bool get_SP_delta(IRTemp temp, Long* delta)
179 Int i; // i must be signed!
180 vg_assert(IRTemp_INVALID != temp);
181 // Search backwards between current buffer position and the start.
182 for (i = next_SP_alias_slot-1; i >= 0; i--) {
183 if (temp == SP_aliases[i].temp) {
184 *delta = SP_aliases[i].delta;
185 return True;
188 // Search backwards between the end and the current buffer position.
189 for (i = N_ALIASES-1; i >= next_SP_alias_slot; i--) {
190 if (temp == SP_aliases[i].temp) {
191 *delta = SP_aliases[i].delta;
192 return True;
195 return False;
198 static void update_SP_aliases(Long delta)
200 Int i;
201 for (i = 0; i < N_ALIASES; i++) {
202 if (SP_aliases[i].temp == IRTemp_INVALID) {
203 return;
205 SP_aliases[i].delta += delta;
209 /* Given a guest IP, get an origin tag for a 1-element stack trace,
210 and wrap it up in an IR atom that can be passed as the origin-tag
211 value for a stack-adjustment helper function. */
212 static IRExpr* mk_ecu_Expr ( Addr guest_IP )
214 UInt ecu;
215 ExeContext* ec
216 = VG_(make_depth_1_ExeContext_from_Addr)( guest_IP );
217 vg_assert(ec);
218 ecu = VG_(get_ECU_from_ExeContext)( ec );
219 vg_assert(VG_(is_plausible_ECU)(ecu));
220 /* This is always safe to do, since ecu is only 32 bits, and
221 HWord is 32 or 64. */
222 return mkIRExpr_HWord( (HWord)ecu );
225 /* When gdbserver is activated, the translation of a block must
226 first be done by the tool function, then followed by a pass
227 which (if needed) instruments the code for gdbserver.
229 static
230 IRSB* tool_instrument_then_gdbserver_if_needed ( VgCallbackClosure* closureV,
231 IRSB* sb_in,
232 const VexGuestLayout* layout,
233 const VexGuestExtents* vge,
234 const VexArchInfo* vai,
235 IRType gWordTy,
236 IRType hWordTy )
238 return VG_(instrument_for_gdbserver_if_needed)
239 (VG_(tdict).tool_instrument (closureV,
240 sb_in,
241 layout,
242 vge,
243 vai,
244 gWordTy,
245 hWordTy),
246 layout,
247 vge,
248 gWordTy,
249 hWordTy);
252 /* For tools that want to know about SP changes, this pass adds
253 in the appropriate hooks. We have to do it after the tool's
254 instrumentation, so the tool doesn't have to worry about the C calls
255 it adds in, and we must do it before register allocation because
256 spilled temps make it much harder to work out the SP deltas.
257 This it is done with Vex's "second instrumentation" pass.
259 Basically, we look for GET(SP)/PUT(SP) pairs and track constant
260 increments/decrements of SP between them. (This requires tracking one or
261 more "aliases", which are not exact aliases but instead are tempregs
262 whose value is equal to the SP's plus or minus a known constant.)
263 If all the changes to SP leading up to a PUT(SP) are by known, small
264 constants, we can do a specific call to eg. new_mem_stack_4, otherwise
265 we fall back to the case that handles an unknown SP change.
267 There is some extra complexity to deal correctly with updates to
268 only parts of SP. Bizarre, but it has been known to happen.
270 static
271 IRSB* vg_SP_update_pass ( void* closureV,
272 IRSB* sb_in,
273 const VexGuestLayout* layout,
274 const VexGuestExtents* vge,
275 const VexArchInfo* vai,
276 IRType gWordTy,
277 IRType hWordTy )
279 Int i, j, k, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
280 Int first_SP, last_SP, first_Put, last_Put;
281 IRDirty *dcall, *d;
282 IRStmt* st;
283 IRExpr* e;
284 IRRegArray* descr;
285 IRType typeof_SP;
286 Long delta, con;
288 /* Set up stuff for tracking the guest IP */
289 Bool curr_IP_known = False;
290 Addr curr_IP = 0;
292 /* Set up BB */
293 IRSB* bb = emptyIRSB();
294 bb->tyenv = deepCopyIRTypeEnv(sb_in->tyenv);
295 bb->next = deepCopyIRExpr(sb_in->next);
296 bb->jumpkind = sb_in->jumpkind;
297 bb->offsIP = sb_in->offsIP;
299 delta = 0;
301 sizeof_SP = layout->sizeof_SP;
302 offset_SP = layout->offset_SP;
303 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
304 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
306 /* --- Start of #defines --- */
308 # define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
309 # define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
311 # define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
313 # define GET_CONST(con) \
314 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
315 : (Long)(con->Ico.U64))
317 # define DO_NEW(syze, tmpp) \
318 do { \
319 Bool vanilla, w_ecu; \
320 vg_assert(curr_IP_known); \
321 vanilla = NULL != VG_(tdict).track_new_mem_stack_##syze; \
322 w_ecu = NULL != VG_(tdict).track_new_mem_stack_##syze##_w_ECU; \
323 vg_assert(!(vanilla && w_ecu)); /* can't have both */ \
324 if (!(vanilla || w_ecu)) \
325 goto generic; \
327 /* I don't know if it's really necessary to say that the */ \
328 /* call reads the stack pointer. But anyway, we do. */ \
329 if (w_ecu) { \
330 dcall = unsafeIRDirty_0_N( \
331 2/*regparms*/, \
332 "track_new_mem_stack_" #syze "_w_ECU", \
333 VG_(fnptr_to_fnentry)( \
334 VG_(tdict).track_new_mem_stack_##syze##_w_ECU ), \
335 mkIRExprVec_2(IRExpr_RdTmp(tmpp), \
336 mk_ecu_Expr(curr_IP)) \
337 ); \
338 } else { \
339 dcall = unsafeIRDirty_0_N( \
340 1/*regparms*/, \
341 "track_new_mem_stack_" #syze , \
342 VG_(fnptr_to_fnentry)( \
343 VG_(tdict).track_new_mem_stack_##syze ), \
344 mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \
345 ); \
347 dcall->nFxState = 1; \
348 dcall->fxState[0].fx = Ifx_Read; \
349 dcall->fxState[0].offset = layout->offset_SP; \
350 dcall->fxState[0].size = layout->sizeof_SP; \
351 dcall->fxState[0].nRepeats = 0; \
352 dcall->fxState[0].repeatLen = 0; \
354 addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \
356 vg_assert(syze > 0); \
357 update_SP_aliases(syze); \
359 n_SP_updates_fast++; \
361 } while (0)
363 # define DO_DIE(syze, tmpp) \
364 do { \
365 if (!VG_(tdict).track_die_mem_stack_##syze) \
366 goto generic; \
368 /* I don't know if it's really necessary to say that the */ \
369 /* call reads the stack pointer. But anyway, we do. */ \
370 dcall = unsafeIRDirty_0_N( \
371 1/*regparms*/, \
372 "track_die_mem_stack_" #syze, \
373 VG_(fnptr_to_fnentry)( \
374 VG_(tdict).track_die_mem_stack_##syze ), \
375 mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \
376 ); \
377 dcall->nFxState = 1; \
378 dcall->fxState[0].fx = Ifx_Read; \
379 dcall->fxState[0].offset = layout->offset_SP; \
380 dcall->fxState[0].size = layout->sizeof_SP; \
381 dcall->fxState[0].nRepeats = 0; \
382 dcall->fxState[0].repeatLen = 0; \
384 addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \
386 vg_assert(syze > 0); \
387 update_SP_aliases(-(syze)); \
389 n_SP_updates_fast++; \
391 } while (0)
393 /* --- End of #defines --- */
395 clear_SP_aliases();
397 for (i = 0; i < sb_in->stmts_used; i++) {
399 st = sb_in->stmts[i];
401 if (st->tag == Ist_IMark) {
402 curr_IP_known = True;
403 curr_IP = st->Ist.IMark.addr;
406 /* t = Get(sp): curr = t, delta = 0 */
407 if (st->tag != Ist_WrTmp) goto case2;
408 e = st->Ist.WrTmp.data;
409 if (e->tag != Iex_Get) goto case2;
410 if (e->Iex.Get.offset != offset_SP) goto case2;
411 if (e->Iex.Get.ty != typeof_SP) goto case2;
412 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
413 add_SP_alias(st->Ist.WrTmp.tmp, 0);
414 addStmtToIRSB( bb, st );
415 continue;
417 case2:
418 /* t' = curr +/- const: curr = t', delta +=/-= const */
419 if (st->tag != Ist_WrTmp) goto case3;
420 e = st->Ist.WrTmp.data;
421 if (e->tag != Iex_Binop) goto case3;
422 if (e->Iex.Binop.arg1->tag != Iex_RdTmp) goto case3;
423 if (!get_SP_delta(e->Iex.Binop.arg1->Iex.RdTmp.tmp, &delta)) goto case3;
424 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
425 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
426 con = GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
427 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
428 if (IS_ADD(e->Iex.Binop.op)) {
429 add_SP_alias(st->Ist.WrTmp.tmp, delta + con);
430 } else {
431 add_SP_alias(st->Ist.WrTmp.tmp, delta - con);
433 addStmtToIRSB( bb, st );
434 continue;
436 case3:
437 /* t' = curr: curr = t' */
438 if (st->tag != Ist_WrTmp) goto case4;
439 e = st->Ist.WrTmp.data;
440 if (e->tag != Iex_RdTmp) goto case4;
441 if (!get_SP_delta(e->Iex.RdTmp.tmp, &delta)) goto case4;
442 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
443 add_SP_alias(st->Ist.WrTmp.tmp, delta);
444 addStmtToIRSB( bb, st );
445 continue;
447 case4:
448 /* Put(sp) = curr */
449 /* More generally, we must correctly handle a Put which writes
450 any part of SP, not just the case where all of SP is
451 written. */
452 if (st->tag != Ist_Put) goto case5;
453 first_SP = offset_SP;
454 last_SP = first_SP + sizeof_SP - 1;
455 first_Put = st->Ist.Put.offset;
456 last_Put = first_Put
457 + sizeofIRType( typeOfIRExpr( bb->tyenv, st->Ist.Put.data ))
458 - 1;
459 vg_assert(first_SP <= last_SP);
460 vg_assert(first_Put <= last_Put);
462 if (last_Put < first_SP || last_SP < first_Put)
463 goto case5; /* no overlap */
465 if (st->Ist.Put.data->tag == Iex_RdTmp
466 && get_SP_delta(st->Ist.Put.data->Iex.RdTmp.tmp, &delta)) {
467 IRTemp tttmp = st->Ist.Put.data->Iex.RdTmp.tmp;
468 /* Why should the following assertion hold? Because any
469 alias added by put_SP_alias must be of a temporary which
470 has the same type as typeof_SP, and whose value is a Get
471 at exactly offset_SP of size typeof_SP. Each call to
472 put_SP_alias is immediately preceded by an assertion that
473 we are putting in a binding for a correctly-typed
474 temporary. */
475 vg_assert( typeOfIRTemp(bb->tyenv, tttmp) == typeof_SP );
476 /* From the same type-and-offset-correctness argument, if
477 we found a useable alias, it must for an "exact" write of SP. */
478 vg_assert(first_SP == first_Put);
479 vg_assert(last_SP == last_Put);
480 switch (delta) {
481 case 0: addStmtToIRSB(bb,st); continue;
482 case 4: DO_DIE( 4, tttmp); addStmtToIRSB(bb,st); continue;
483 case -4: DO_NEW( 4, tttmp); addStmtToIRSB(bb,st); continue;
484 case 8: DO_DIE( 8, tttmp); addStmtToIRSB(bb,st); continue;
485 case -8: DO_NEW( 8, tttmp); addStmtToIRSB(bb,st); continue;
486 case 12: DO_DIE( 12, tttmp); addStmtToIRSB(bb,st); continue;
487 case -12: DO_NEW( 12, tttmp); addStmtToIRSB(bb,st); continue;
488 case 16: DO_DIE( 16, tttmp); addStmtToIRSB(bb,st); continue;
489 case -16: DO_NEW( 16, tttmp); addStmtToIRSB(bb,st); continue;
490 case 32: DO_DIE( 32, tttmp); addStmtToIRSB(bb,st); continue;
491 case -32: DO_NEW( 32, tttmp); addStmtToIRSB(bb,st); continue;
492 case 112: DO_DIE( 112, tttmp); addStmtToIRSB(bb,st); continue;
493 case -112: DO_NEW( 112, tttmp); addStmtToIRSB(bb,st); continue;
494 case 128: DO_DIE( 128, tttmp); addStmtToIRSB(bb,st); continue;
495 case -128: DO_NEW( 128, tttmp); addStmtToIRSB(bb,st); continue;
496 case 144: DO_DIE( 144, tttmp); addStmtToIRSB(bb,st); continue;
497 case -144: DO_NEW( 144, tttmp); addStmtToIRSB(bb,st); continue;
498 case 160: DO_DIE( 160, tttmp); addStmtToIRSB(bb,st); continue;
499 case -160: DO_NEW( 160, tttmp); addStmtToIRSB(bb,st); continue;
500 default:
501 /* common values for ppc64: 144 128 160 112 176 */
502 n_SP_updates_generic_known++;
503 goto generic;
505 } else {
506 /* Deal with an unknown update to SP. We're here because
507 either:
508 (1) the Put does not exactly cover SP; it is a partial update.
509 Highly unlikely, but has been known to happen for 16-bit
510 Windows apps running on Wine, doing 16-bit adjustments to
511 %sp.
512 (2) the Put does exactly cover SP, but we are unable to
513 determine how the value relates to the old SP. In any
514 case, we cannot assume that the Put.data value is a tmp;
515 we must assume it can be anything allowed in flat IR (tmp
516 or const).
518 IRTemp old_SP;
519 n_SP_updates_generic_unknown++;
521 // Nb: if all is well, this generic case will typically be
522 // called something like every 1000th SP update. If it's more than
523 // that, the above code may be missing some cases.
524 generic:
525 /* Pass both the old and new SP values to this helper. Also,
526 pass an origin tag, even if it isn't needed. */
527 old_SP = newIRTemp(bb->tyenv, typeof_SP);
528 addStmtToIRSB(
530 IRStmt_WrTmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
533 /* Now we know what the old value of SP is. But knowing the new
534 value is a bit tricky if there is a partial write. */
535 if (first_Put == first_SP && last_Put == last_SP) {
536 /* The common case, an exact write to SP. So st->Ist.Put.data
537 does hold the new value; simple. */
538 vg_assert(curr_IP_known);
539 if (NULL != VG_(tdict).track_new_mem_stack_w_ECU)
540 dcall = unsafeIRDirty_0_N(
541 3/*regparms*/,
542 "VG_(unknown_SP_update_w_ECU)",
543 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update_w_ECU) ),
544 mkIRExprVec_3( IRExpr_RdTmp(old_SP), st->Ist.Put.data,
545 mk_ecu_Expr(curr_IP) )
547 else
548 dcall = unsafeIRDirty_0_N(
549 2/*regparms*/,
550 "VG_(unknown_SP_update)",
551 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
552 mkIRExprVec_2( IRExpr_RdTmp(old_SP), st->Ist.Put.data )
555 addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
556 /* don't forget the original assignment */
557 addStmtToIRSB( bb, st );
558 } else {
559 /* We have a partial update to SP. We need to know what
560 the new SP will be, and hand that to the helper call,
561 but when the helper call happens, SP must hold the
562 value it had before the update. Tricky.
563 Therefore use the following kludge:
564 1. do the partial SP update (Put)
565 2. Get the new SP value into a tmp, new_SP
566 3. Put old_SP
567 4. Call the helper
568 5. Put new_SP
570 IRTemp new_SP;
571 /* 1 */
572 addStmtToIRSB( bb, st );
573 /* 2 */
574 new_SP = newIRTemp(bb->tyenv, typeof_SP);
575 addStmtToIRSB(
577 IRStmt_WrTmp( new_SP, IRExpr_Get(offset_SP, typeof_SP) )
579 /* 3 */
580 addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(old_SP) ));
581 /* 4 */
582 vg_assert(curr_IP_known);
583 if (NULL != VG_(tdict).track_new_mem_stack_w_ECU)
584 dcall = unsafeIRDirty_0_N(
585 3/*regparms*/,
586 "VG_(unknown_SP_update_w_ECU)",
587 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update_w_ECU) ),
588 mkIRExprVec_3( IRExpr_RdTmp(old_SP),
589 IRExpr_RdTmp(new_SP),
590 mk_ecu_Expr(curr_IP) )
592 else
593 dcall = unsafeIRDirty_0_N(
594 2/*regparms*/,
595 "VG_(unknown_SP_update)",
596 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
597 mkIRExprVec_2( IRExpr_RdTmp(old_SP),
598 IRExpr_RdTmp(new_SP) )
600 addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
601 /* 5 */
602 addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(new_SP) ));
605 /* Forget what we already know. */
606 clear_SP_aliases();
608 /* If this is a Put of a tmp that exactly updates SP,
609 start tracking aliases against this tmp. */
611 if (first_Put == first_SP && last_Put == last_SP
612 && st->Ist.Put.data->tag == Iex_RdTmp) {
613 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.Put.data->Iex.RdTmp.tmp)
614 == typeof_SP );
615 add_SP_alias(st->Ist.Put.data->Iex.RdTmp.tmp, 0);
617 continue;
620 case5:
621 /* PutI or Dirty call which overlaps SP: complain. We can't
622 deal with SP changing in weird ways (well, we can, but not at
623 this time of night). */
624 if (st->tag == Ist_PutI) {
625 descr = st->Ist.PutI.details->descr;
626 minoff_ST = descr->base;
627 maxoff_ST = descr->base
628 + descr->nElems * sizeofIRType(descr->elemTy) - 1;
629 if (!(offset_SP > maxoff_ST
630 || (offset_SP + sizeof_SP - 1) < minoff_ST))
631 goto complain;
633 if (st->tag == Ist_Dirty) {
634 d = st->Ist.Dirty.details;
635 for (j = 0; j < d->nFxState; j++) {
636 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
637 continue;
638 /* Enumerate the described state segments */
639 for (k = 0; k < 1 + d->fxState[j].nRepeats; k++) {
640 minoff_ST = d->fxState[j].offset + k * d->fxState[j].repeatLen;
641 maxoff_ST = minoff_ST + d->fxState[j].size - 1;
642 if (!(offset_SP > maxoff_ST
643 || (offset_SP + sizeof_SP - 1) < minoff_ST))
644 goto complain;
649 /* well, not interesting. Just copy and keep going. */
650 addStmtToIRSB( bb, st );
652 } /* for (i = 0; i < sb_in->stmts_used; i++) */
654 return bb;
656 complain:
657 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
659 #undef IS_ADD
660 #undef IS_SUB
661 #undef IS_ADD_OR_SUB
662 #undef GET_CONST
663 #undef DO_NEW
664 #undef DO_DIE
667 /*------------------------------------------------------------*/
668 /*--- Main entry point for the JITter. ---*/
669 /*------------------------------------------------------------*/
671 /* Extra comments re self-checking translations and self-modifying
672 code. (JRS 14 Oct 05).
674 There are 3 modes:
675 (1) no checking: all code assumed to be not self-modifying
676 (2) partial: known-problematic situations get a self-check
677 (3) full checking: all translations get a self-check
679 As currently implemented, the default is (2). (3) is always safe,
680 but very slow. (1) works mostly, but fails for gcc nested-function
681 code which uses trampolines on the stack; this situation is
682 detected and handled by (2).
684 ----------
686 A more robust and transparent solution, which is not currently
687 implemented, is a variant of (2): if a translation is made from an
688 area which aspacem says does not have 'w' permission, then it can
689 be non-self-checking. Otherwise, it needs a self-check.
691 This is complicated by Vex's basic-block chasing. If a self-check
692 is requested, then Vex will not chase over basic block boundaries
693 (it's too complex). However there is still a problem if it chases
694 from a non-'w' area into a 'w' area.
696 I think the right thing to do is:
698 - if a translation request starts in a 'w' area, ask for a
699 self-checking translation, and do not allow any chasing (make
700 chase_into_ok return False). Note that the latter is redundant
701 in the sense that Vex won't chase anyway in this situation.
703 - if a translation request starts in a non-'w' area, do not ask for
704 a self-checking translation. However, do not allow chasing (as
705 determined by chase_into_ok) to go into a 'w' area.
707 The result of this is that all code inside 'w' areas is self
708 checking.
710 To complete the trick, there is a caveat: we must watch the
711 client's mprotect calls. If pages are changed from non-'w' to 'w'
712 then we should throw away all translations which intersect the
713 affected area, so as to force them to be redone with self-checks.
715 ----------
717 The above outlines the conditions under which bb chasing is allowed
718 from a self-modifying-code point of view. There are other
719 situations pertaining to function redirection in which it is
720 necessary to disallow chasing, but those fall outside the scope of
721 this comment.
725 /* Vex dumps the final code in here. Then we can copy it off
726 wherever we like. */
727 /* 60000: should agree with assertion in VG_(add_to_transtab) in
728 m_transtab.c. */
729 #define N_TMPBUF 60000
730 static UChar tmpbuf[N_TMPBUF];
733 /* Function pointers we must supply to LibVEX in order that it
734 can bomb out and emit messages under Valgrind's control. */
735 __attribute__ ((noreturn))
736 static
737 void failure_exit ( void )
739 LibVEX_ShowAllocStats();
740 VG_(core_panic)("LibVEX called failure_exit().");
743 static
744 void log_bytes ( const HChar* bytes, SizeT nbytes )
746 SizeT i = 0;
747 if (nbytes >= 4)
748 for (; i < nbytes-3; i += 4)
749 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
750 for (; i < nbytes; i++)
751 VG_(printf)("%c", bytes[i]);
755 /* --------- Various helper functions for translation --------- */
757 /* Look for reasons to disallow making translations from the given
758 segment/addr. */
760 static Bool translations_allowable_from_seg ( NSegment const* seg, Addr addr )
762 # if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32) \
763 || defined(VGA_mips64) || defined(VGA_tilegx)
764 Bool allowR = True;
765 # else
766 Bool allowR = False;
767 # endif
768 return seg != NULL
769 && (seg->kind == SkAnonC || seg->kind == SkFileC || seg->kind == SkShmC)
770 && (seg->hasX
771 || (seg->hasR && (allowR
772 || VG_(has_gdbserver_breakpoint) (addr))));
773 /* If GDB/gdbsrv has inserted a breakpoint at addr, assume this is a valid
774 location to translate if seg is not executable but is readable.
775 This is needed for inferior function calls from GDB: GDB inserts a
776 breakpoint on the stack, and expects to regain control before the
777 breakpoint instruction at the breakpoint address is really
778 executed. For this, the breakpoint instruction must be translated
779 so as to have the call to gdbserver executed. */
783 /* Produce a bitmask stating which of the supplied extents needs a
784 self-check. See documentation of
785 VexTranslateArgs::needs_self_check for more details about the
786 return convention. */
788 static UInt needs_self_check ( void* closureV,
789 /*MAYBE_MOD*/VexRegisterUpdates* pxControl,
790 const VexGuestExtents* vge )
792 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
793 UInt i, bitset;
795 vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
796 bitset = 0;
798 /* Will we need to do a second pass in order to compute a
799 revised *pxControl value? */
800 Bool pxStatusMightChange
801 = /* "the user actually set it" */
802 VG_(clo_px_file_backed) != VexRegUpd_INVALID
803 /* "and they set it to something other than the default. */
804 && *pxControl != VG_(clo_px_file_backed);
806 /* First, compute |bitset|, which specifies which extent(s) need a
807 self check. Whilst we're at it, note any NSegments that we get,
808 so as to reduce the number of calls required to
809 VG_(am_find_nsegment) in a possible second pass. */
810 const NSegment *segs[3] = { NULL, NULL, NULL };
812 for (i = 0; i < vge->n_used; i++) {
813 Bool check = False;
814 Addr addr = vge->base[i];
815 SizeT len = vge->len[i];
816 NSegment const* segA = NULL;
818 # if defined(VGO_darwin)
819 // GrP fixme hack - dyld i386 IMPORT gets rewritten.
820 // To really do this correctly, we'd need to flush the
821 // translation cache whenever a segment became +WX.
822 segA = VG_(am_find_nsegment)(addr);
823 if (segA && segA->hasX && segA->hasW)
824 check = True;
825 # endif
827 if (!check) {
828 switch (VG_(clo_smc_check)) {
829 case Vg_SmcNone:
830 /* never check (except as per Darwin hack above) */
831 break;
832 case Vg_SmcAll:
833 /* always check */
834 check = True;
835 break;
836 case Vg_SmcStack: {
837 /* check if the address is in the same segment as this
838 thread's stack pointer */
839 Addr sp = VG_(get_SP)(closure->tid);
840 if (!segA) {
841 segA = VG_(am_find_nsegment)(addr);
843 NSegment const* segSP = VG_(am_find_nsegment)(sp);
844 if (segA && segSP && segA == segSP)
845 check = True;
846 break;
848 case Vg_SmcAllNonFile: {
849 /* check if any part of the extent is not in a
850 file-mapped segment */
851 if (!segA) {
852 segA = VG_(am_find_nsegment)(addr);
854 if (segA && segA->kind == SkFileC && segA->start <= addr
855 && (len == 0 || addr + len <= segA->end + 1)) {
856 /* in a file-mapped segment; skip the check */
857 } else {
858 check = True;
860 break;
862 default:
863 vg_assert(0);
867 if (check)
868 bitset |= (1 << i);
870 if (pxStatusMightChange && segA) {
871 vg_assert(i < sizeof(segs)/sizeof(segs[0]));
872 segs[i] = segA;
876 /* Now, possibly do a second pass, to see if the PX status might
877 change. This can happen if the user specified value via
878 --px-file-backed= which is different from the default PX value
879 specified via --vex-iropt-register-updates (also known by the
880 shorter alias --px-default). */
881 if (pxStatusMightChange) {
883 Bool allFileBacked = True;
884 for (i = 0; i < vge->n_used; i++) {
885 Addr addr = vge->base[i];
886 SizeT len = vge->len[i];
887 NSegment const* segA = segs[i];
888 if (!segA) {
889 /* If we don't have a cached value for |segA|, compute it now. */
890 segA = VG_(am_find_nsegment)(addr);
892 vg_assert(segA); /* Can this ever fail? */
893 if (segA && segA->kind == SkFileC && segA->start <= addr
894 && (len == 0 || addr + len <= segA->end + 1)) {
895 /* in a file-mapped segment */
896 } else {
897 /* not in a file-mapped segment, or we can't figure out
898 where it is */
899 allFileBacked = False;
900 break;
904 /* So, finally, if all the extents are in file backed segments, perform
905 the user-specified PX change. */
906 if (allFileBacked) {
907 *pxControl = VG_(clo_px_file_backed);
912 /* Update running PX stats, as it is difficult without these to
913 check that the system is behaving as expected. */
914 switch (*pxControl) {
915 case VexRegUpdSpAtMemAccess:
916 n_PX_VexRegUpdSpAtMemAccess++; break;
917 case VexRegUpdUnwindregsAtMemAccess:
918 n_PX_VexRegUpdUnwindregsAtMemAccess++; break;
919 case VexRegUpdAllregsAtMemAccess:
920 n_PX_VexRegUpdAllregsAtMemAccess++; break;
921 case VexRegUpdAllregsAtEachInsn:
922 n_PX_VexRegUpdAllregsAtEachInsn++; break;
923 default:
924 vg_assert(0);
927 return bitset;
931 /* This is a callback passed to LibVEX_Translate. It stops Vex from
932 chasing into function entry points that we wish to redirect.
933 Chasing across them obviously defeats the redirect mechanism, with
934 bad effects for Memcheck, Helgrind, DRD, Massif, and possibly others.
936 static Bool chase_into_ok ( void* closureV, Addr addr )
938 NSegment const* seg = VG_(am_find_nsegment)(addr);
940 /* Work through a list of possibilities why we might not want to
941 allow a chase. */
943 /* Destination not in a plausible segment? */
944 if (!translations_allowable_from_seg(seg, addr))
945 goto dontchase;
947 /* Destination is redirected? */
948 if (addr != VG_(redir_do_lookup)(addr, NULL))
949 goto dontchase;
951 # if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
952 /* This needs to be at the start of its own block. Don't chase. */
953 if (addr == (Addr)&VG_(ppctoc_magic_redirect_return_stub))
954 goto dontchase;
955 # endif
957 /* overly conservative, but .. don't chase into the distinguished
958 address that m_transtab uses as an empty-slot marker for
959 VG_(tt_fast). */
960 if (addr == TRANSTAB_BOGUS_GUEST_ADDR)
961 goto dontchase;
963 # if defined(VGA_s390x)
964 /* Never chase into an EX instruction. Generating IR for EX causes
965 a round-trip through the scheduler including VG_(discard_translations).
966 And that's expensive as shown by perf/tinycc.c:
967 Chasing into EX increases the number of EX translations from 21 to
968 102666 causing a 7x runtime increase for "none" and a 3.2x runtime
969 increase for memcheck. */
970 if (((UChar *)addr)[0] == 0x44 || /* EX */
971 ((UChar *)addr)[0] == 0xC6) /* EXRL */
972 goto dontchase;
973 # endif
975 /* well, ok then. go on and chase. */
976 return True;
978 vg_assert(0);
979 /*NOTREACHED*/
981 dontchase:
982 if (0) VG_(printf)("not chasing into 0x%lx\n", addr);
983 return False;
987 /* --------------- helpers for with-TOC platforms --------------- */
989 /* NOTE: with-TOC platforms are: ppc64-linux. */
991 static IRExpr* mkU64 ( ULong n ) {
992 return IRExpr_Const(IRConst_U64(n));
994 static IRExpr* mkU32 ( UInt n ) {
995 return IRExpr_Const(IRConst_U32(n));
998 #if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
999 static IRExpr* mkU8 ( UChar n ) {
1000 return IRExpr_Const(IRConst_U8(n));
1002 static IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) {
1003 if (typeOfIRExpr(tyenv, e) == Ity_I32) {
1004 return e;
1005 } else {
1006 vg_assert(typeOfIRExpr(tyenv, e) == Ity_I64);
1007 return IRExpr_Unop(Iop_64to32, e);
1011 /* Generate code to push word-typed expression 'e' onto this thread's
1012 redir stack, checking for stack overflow and generating code to
1013 bomb out if so. */
1015 static void gen_PUSH ( IRSB* bb, IRExpr* e )
1017 IRRegArray* descr;
1018 IRTemp t1;
1019 IRExpr* one;
1021 # if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1022 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
1023 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
1024 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
1025 Int offB_EMNOTE = offsetof(VexGuestPPC64State,guest_EMNOTE);
1026 Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA);
1027 Bool is64 = True;
1028 IRType ty_Word = Ity_I64;
1029 IROp op_CmpNE = Iop_CmpNE64;
1030 IROp op_Sar = Iop_Sar64;
1031 IROp op_Sub = Iop_Sub64;
1032 IROp op_Add = Iop_Add64;
1033 IRExpr*(*mkU)(ULong) = mkU64;
1034 vg_assert(VG_WORDSIZE == 8);
1035 # else
1036 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
1037 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
1038 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
1039 Int offB_EMNOTE = offsetof(VexGuestPPC32State,guest_EMNOTE);
1040 Int offB_CIA = offsetof(VexGuestPPC32State,guest_CIA);
1041 Bool is64 = False;
1042 IRType ty_Word = Ity_I32;
1043 IROp op_CmpNE = Iop_CmpNE32;
1044 IROp op_Sar = Iop_Sar32;
1045 IROp op_Sub = Iop_Sub32;
1046 IROp op_Add = Iop_Add32;
1047 IRExpr*(*mkU)(UInt) = mkU32;
1048 vg_assert(VG_WORDSIZE == 4);
1049 # endif
1051 vg_assert(sizeof(void*) == VG_WORDSIZE);
1052 vg_assert(sizeof(Word) == VG_WORDSIZE);
1053 vg_assert(sizeof(Addr) == VG_WORDSIZE);
1055 descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
1056 t1 = newIRTemp( bb->tyenv, ty_Word );
1057 one = mkU(1);
1059 vg_assert(typeOfIRExpr(bb->tyenv, e) == ty_Word);
1061 /* t1 = guest_REDIR_SP + 1 */
1062 addStmtToIRSB(
1063 bb,
1064 IRStmt_WrTmp(
1065 t1,
1066 IRExpr_Binop(op_Add, IRExpr_Get( offB_REDIR_SP, ty_Word ), one)
1070 /* Bomb out if t1 >=s stack_size, that is, (stack_size-1)-t1 <s 0.
1071 The destination (0) is a bit bogus but it doesn't matter since
1072 this is an unrecoverable error and will lead to Valgrind
1073 shutting down. _EMNOTE is set regardless - that's harmless
1074 since is only has a meaning if the exit is taken. */
1075 addStmtToIRSB(
1077 IRStmt_Put(offB_EMNOTE, mkU32(EmWarn_PPC64_redir_overflow))
1079 addStmtToIRSB(
1081 IRStmt_Exit(
1082 IRExpr_Binop(
1083 op_CmpNE,
1084 IRExpr_Binop(
1085 op_Sar,
1086 IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_RdTmp(t1)),
1087 mkU8(8 * VG_WORDSIZE - 1)
1089 mkU(0)
1091 Ijk_EmFail,
1092 is64 ? IRConst_U64(0) : IRConst_U32(0),
1093 offB_CIA
1097 /* guest_REDIR_SP = t1 */
1098 addStmtToIRSB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_RdTmp(t1)));
1100 /* guest_REDIR_STACK[t1+0] = e */
1101 /* PutI/GetI have I32-typed indexes regardless of guest word size */
1102 addStmtToIRSB(
1103 bb,
1104 IRStmt_PutI(mkIRPutI(descr,
1105 narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0, e)));
1109 /* Generate code to pop a word-sized value from this thread's redir
1110 stack, binding it to a new temporary, which is returned. As with
1111 gen_PUSH, an overflow check is also performed. */
1113 static IRTemp gen_POP ( IRSB* bb )
1115 # if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1116 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
1117 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
1118 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
1119 Int offB_EMNOTE = offsetof(VexGuestPPC64State,guest_EMNOTE);
1120 Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA);
1121 Bool is64 = True;
1122 IRType ty_Word = Ity_I64;
1123 IROp op_CmpNE = Iop_CmpNE64;
1124 IROp op_Sar = Iop_Sar64;
1125 IROp op_Sub = Iop_Sub64;
1126 IRExpr*(*mkU)(ULong) = mkU64;
1127 # else
1128 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
1129 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
1130 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
1131 Int offB_EMNOTE = offsetof(VexGuestPPC32State,guest_EMNOTE);
1132 Int offB_CIA = offsetof(VexGuestPPC32State,guest_CIA);
1133 Bool is64 = False;
1134 IRType ty_Word = Ity_I32;
1135 IROp op_CmpNE = Iop_CmpNE32;
1136 IROp op_Sar = Iop_Sar32;
1137 IROp op_Sub = Iop_Sub32;
1138 IRExpr*(*mkU)(UInt) = mkU32;
1139 # endif
1141 IRRegArray* descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
1142 IRTemp t1 = newIRTemp( bb->tyenv, ty_Word );
1143 IRTemp res = newIRTemp( bb->tyenv, ty_Word );
1144 IRExpr* one = mkU(1);
1146 vg_assert(sizeof(void*) == VG_WORDSIZE);
1147 vg_assert(sizeof(Word) == VG_WORDSIZE);
1148 vg_assert(sizeof(Addr) == VG_WORDSIZE);
1150 /* t1 = guest_REDIR_SP */
1151 addStmtToIRSB(
1152 bb,
1153 IRStmt_WrTmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) )
1156 /* Bomb out if t1 < 0. Same comments as gen_PUSH apply. */
1157 addStmtToIRSB(
1159 IRStmt_Put(offB_EMNOTE, mkU32(EmWarn_PPC64_redir_underflow))
1161 addStmtToIRSB(
1163 IRStmt_Exit(
1164 IRExpr_Binop(
1165 op_CmpNE,
1166 IRExpr_Binop(
1167 op_Sar,
1168 IRExpr_RdTmp(t1),
1169 mkU8(8 * VG_WORDSIZE - 1)
1171 mkU(0)
1173 Ijk_EmFail,
1174 is64 ? IRConst_U64(0) : IRConst_U32(0),
1175 offB_CIA
1179 /* res = guest_REDIR_STACK[t1+0] */
1180 /* PutI/GetI have I32-typed indexes regardless of guest word size */
1181 addStmtToIRSB(
1183 IRStmt_WrTmp(
1184 res,
1185 IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0)
1189 /* guest_REDIR_SP = t1-1 */
1190 addStmtToIRSB(
1191 bb,
1192 IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(op_Sub, IRExpr_RdTmp(t1), one))
1195 return res;
1198 #endif
1200 #if defined(VG_PLAT_USES_PPCTOC)
1202 /* Generate code to push LR and R2 onto this thread's redir stack,
1203 then set R2 to the new value (which is the TOC pointer to be used
1204 for the duration of the replacement function, as determined by
1205 m_debuginfo), and set LR to the magic return stub, so we get to
1206 intercept the return and restore R2 and L2 to the values saved
1207 here. */
1209 static void gen_push_and_set_LR_R2 ( IRSB* bb, Addr new_R2_value )
1211 # if defined(VGP_ppc64be_linux)
1212 Addr bogus_RA = (Addr)&VG_(ppctoc_magic_redirect_return_stub);
1213 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1214 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
1215 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) );
1216 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
1217 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) );
1218 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) );
1220 # else
1221 # error Platform is not TOC-afflicted, fortunately
1222 # endif
1224 #endif
1226 #if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
1228 static void gen_pop_R2_LR_then_bLR ( IRSB* bb )
1230 # if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1231 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1232 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
1233 Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA);
1234 IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I64 );
1235 IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I64 );
1236 /* Restore R2 */
1237 old_R2 = gen_POP( bb );
1238 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
1239 /* Restore LR */
1240 old_LR = gen_POP( bb );
1241 addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
1242 /* Branch to LR */
1243 /* re boring, we arrived here precisely because a wrapped fn did a
1244 blr (hence Ijk_Ret); so we should just mark this jump as Boring,
1245 else one _Call will have resulted in two _Rets. */
1246 bb->jumpkind = Ijk_Boring;
1247 bb->next = IRExpr_Binop(Iop_And64, IRExpr_RdTmp(old_LR), mkU64(~(3ULL)));
1248 bb->offsIP = offB_CIA;
1249 # else
1250 # error Platform is not TOC-afflicted, fortunately
1251 # endif
1253 #endif
1255 #if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
1257 static
1258 Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb )
1260 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1261 /* Since we're creating the entire IRSB right here, give it a
1262 proper IMark, as it won't get one any other way, and cachegrind
1263 will barf if it doesn't have one (fair enough really). */
1264 addStmtToIRSB( bb, IRStmt_IMark( closure->readdr, 4, 0 ) );
1265 /* Generate the magic sequence:
1266 pop R2 from hidden stack
1267 pop LR from hidden stack
1268 goto LR
1270 gen_pop_R2_LR_then_bLR(bb);
1271 return True; /* True == this is the entire BB; don't disassemble any
1272 real insns into it - just hand it directly to
1273 optimiser/instrumenter/backend. */
1275 #endif
1277 #if defined(VGP_ppc64le_linux)
1278 /* Generate code to push LR and R2 onto this thread's redir stack.
1279 Need to save R2 in case we redirect to a global entry point. The
1280 value of R2 is not preserved when entering the global entry point.
1281 Need to make sure R2 gets restored on return. Set LR to the magic
1282 return stub, so we get to intercept the return and restore R2 and
1283 L2 to the values saved here.
1285 The existing infrastruture for the TOC enabled architectures is
1286 being exploited here. So, we need to enable a number of the
1287 code sections used by VG_PLAT_USES_PPCTOC.
1290 static void gen_push_R2_and_set_LR ( IRSB* bb )
1292 Addr bogus_RA = (Addr)&VG_(ppctoc_magic_redirect_return_stub);
1293 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1294 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
1295 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) );
1296 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
1297 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) );
1299 # endif
1301 /* --------------- END helpers for with-TOC platforms --------------- */
1304 /* This is the IR preamble generator used for replacement
1305 functions. It adds code to set the guest_NRADDR{_GPR2} to zero
1306 (technically not necessary, but facilitates detecting mixups in
1307 which a replacement function has been erroneously declared using
1308 VG_REPLACE_FUNCTION_Z{U,Z} when instead it should have been written
1309 using VG_WRAP_FUNCTION_Z{U,Z}).
1311 On with-TOC platforms the follow hacks are also done: LR and R2 are
1312 pushed onto a hidden stack, R2 is set to the correct value for the
1313 replacement function, and LR is set to point at the magic
1314 return-stub address. Setting LR causes the return of the
1315 wrapped/redirected function to lead to our magic return stub, which
1316 restores LR and R2 from said stack and returns for real.
1318 VG_(get_StackTrace_wrk) understands that the LR value may point to
1319 the return stub address, and that in that case it can get the real
1320 LR value from the hidden stack instead. */
1321 static
1322 Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
1324 Int nraddr_szB
1325 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1326 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
1327 vg_assert(nraddr_szB == VG_WORDSIZE);
1328 addStmtToIRSB(
1330 IRStmt_Put(
1331 offsetof(VexGuestArchState,guest_NRADDR),
1332 nraddr_szB == 8 ? mkU64(0) : mkU32(0)
1335 // t9 needs to be set to point to the start of the redirected function.
1336 # if defined(VGP_mips32_linux)
1337 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1338 Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25);
1339 addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr)));
1340 # endif
1341 # if defined(VGP_mips64_linux)
1342 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1343 Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25);
1344 addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr)));
1345 # endif
1346 # if defined(VG_PLAT_USES_PPCTOC)
1347 { VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1348 addStmtToIRSB(
1350 IRStmt_Put(
1351 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1352 VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
1355 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1357 # endif
1359 #if defined(VGP_ppc64le_linux)
1360 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1361 Int offB_GPR12 = offsetof(VexGuestArchState, guest_GPR12);
1362 addStmtToIRSB(bb, IRStmt_Put(offB_GPR12, mkU64(closure->readdr)));
1363 addStmtToIRSB(bb,
1364 IRStmt_Put(
1365 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1366 VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
1369 gen_push_R2_and_set_LR ( bb );
1370 #endif
1371 return False;
1374 /* Ditto, except set guest_NRADDR to nraddr (the un-redirected guest
1375 address). This is needed for function wrapping - so the wrapper
1376 can read _NRADDR and find the address of the function being
1377 wrapped. On toc-afflicted platforms we must also snarf r2. */
1378 static
1379 Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb )
1381 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1382 Int nraddr_szB
1383 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1384 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
1385 vg_assert(nraddr_szB == VG_WORDSIZE);
1386 addStmtToIRSB(
1388 IRStmt_Put(
1389 offsetof(VexGuestArchState,guest_NRADDR),
1390 nraddr_szB == 8
1391 ? IRExpr_Const(IRConst_U64( closure->nraddr ))
1392 : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
1395 // t9 needs to be set to point to the start of the redirected function.
1396 # if defined(VGP_mips32_linux)
1397 Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25);
1398 addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr)));
1399 # endif
1400 # if defined(VGP_mips64_linux)
1401 Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25);
1402 addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr)));
1403 # endif
1404 # if defined(VG_PLAT_USES_PPCTOC)
1405 addStmtToIRSB(
1407 IRStmt_Put(
1408 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1409 IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2),
1410 VG_WORDSIZE==8 ? Ity_I64 : Ity_I32)
1413 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1414 # endif
1415 #if defined(VGP_ppc64le_linux)
1416 /* This saves the r2 before leaving the function. We need to move
1417 * guest_NRADDR_GPR2 back to R2 on return.
1419 Int offB_GPR12 = offsetof(VexGuestArchState, guest_GPR12);
1420 addStmtToIRSB(
1422 IRStmt_Put(
1423 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1424 IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2),
1425 VG_WORDSIZE==8 ? Ity_I64 : Ity_I32)
1428 addStmtToIRSB(bb, IRStmt_Put(offB_GPR12, mkU64(closure->readdr)));
1429 gen_push_R2_and_set_LR ( bb );
1430 #endif
1431 return False;
1434 /* --- Helpers to do with PPC related stack redzones. --- */
1436 __attribute__((unused))
1437 static Bool const_True ( Addr guest_addr )
1439 return True;
1442 /* --------------- main translation function --------------- */
1444 /* Note: see comments at top of m_redir.c for the Big Picture on how
1445 redirections are managed. */
1447 typedef
1448 enum {
1449 /* normal translation, redir neither requested nor inhibited */
1450 T_Normal,
1451 /* redir translation, function-wrap (set _NRADDR) style */
1452 T_Redir_Wrap,
1453 /* redir translation, replacement (don't set _NRADDR) style */
1454 T_Redir_Replace,
1455 /* a translation in which redir is specifically disallowed */
1456 T_NoRedir
1458 T_Kind;
1460 /* Translate the basic block beginning at NRADDR, and add it to the
1461 translation cache & translation table. Unless
1462 DEBUGGING_TRANSLATION is true, in which case the call is being done
1463 for debugging purposes, so (a) throw away the translation once it
1464 is made, and (b) produce a load of debugging output. If
1465 ALLOW_REDIRECTION is False, do not attempt redirection of NRADDR,
1466 and also, put the resulting translation into the no-redirect tt/tc
1467 instead of the normal one.
1469 TID is the identity of the thread requesting this translation.
1472 Bool VG_(translate) ( ThreadId tid,
1473 Addr nraddr,
1474 Bool debugging_translation,
1475 Int debugging_verbosity,
1476 ULong bbs_done,
1477 Bool allow_redirection )
1479 Addr addr;
1480 T_Kind kind;
1481 Int tmpbuf_used, verbosity, i;
1482 Bool (*preamble_fn)(void*,IRSB*);
1483 VexArch vex_arch;
1484 VexArchInfo vex_archinfo;
1485 VexAbiInfo vex_abiinfo;
1486 VexGuestExtents vge;
1487 VexTranslateArgs vta;
1488 VexTranslateResult tres;
1489 VgCallbackClosure closure;
1491 /* Make sure Vex is initialised right. */
1493 static Bool vex_init_done = False;
1495 if (!vex_init_done) {
1496 LibVEX_Init ( &failure_exit, &log_bytes,
1497 1, /* debug_paranoia */
1498 &VG_(clo_vex_control) );
1499 vex_init_done = True;
1502 /* Establish the translation kind and actual guest address to
1503 start from. Sets (addr,kind). */
1504 if (allow_redirection) {
1505 Bool isWrap;
1506 Addr tmp = VG_(redir_do_lookup)( nraddr, &isWrap );
1507 if (tmp == nraddr) {
1508 /* no redirection found */
1509 addr = nraddr;
1510 kind = T_Normal;
1511 } else {
1512 /* found a redirect */
1513 addr = tmp;
1514 kind = isWrap ? T_Redir_Wrap : T_Redir_Replace;
1516 } else {
1517 addr = nraddr;
1518 kind = T_NoRedir;
1521 /* Established: (nraddr, addr, kind) */
1523 /* Printing redirection info. */
1525 if ((kind == T_Redir_Wrap || kind == T_Redir_Replace)
1526 && (VG_(clo_verbosity) >= 2 || VG_(clo_trace_redir))) {
1527 Bool ok;
1528 const HChar *buf;
1529 const HChar *name2;
1531 /* Try also to get the soname (not the filename) of the "from"
1532 object. This makes it much easier to debug redirection
1533 problems. */
1534 const HChar* nraddr_soname = "???";
1535 DebugInfo* nraddr_di = VG_(find_DebugInfo)(nraddr);
1536 if (nraddr_di) {
1537 const HChar* t = VG_(DebugInfo_get_soname)(nraddr_di);
1538 if (t)
1539 nraddr_soname = t;
1542 ok = VG_(get_fnname_w_offset)(nraddr, &buf);
1543 if (!ok) buf = "???";
1544 // Stash away name1
1545 HChar name1[VG_(strlen)(buf) + 1];
1546 VG_(strcpy)(name1, buf);
1547 ok = VG_(get_fnname_w_offset)(addr, &name2);
1548 if (!ok) name2 = "???";
1550 VG_(message)(Vg_DebugMsg,
1551 "REDIR: 0x%lx (%s:%s) redirected to 0x%lx (%s)\n",
1552 nraddr, nraddr_soname, name1,
1553 addr, name2 );
1556 if (!debugging_translation)
1557 VG_TRACK( pre_mem_read, Vg_CoreTranslate,
1558 tid, "(translator)", addr, 1 );
1560 /* If doing any code printing, print a basic block start marker */
1561 if (VG_(clo_trace_flags) || debugging_translation) {
1562 const HChar* objname = "UNKNOWN_OBJECT";
1563 OffT objoff = 0;
1564 DebugInfo* di = VG_(find_DebugInfo)( addr );
1565 if (di) {
1566 objname = VG_(DebugInfo_get_filename)(di);
1567 objoff = addr - VG_(DebugInfo_get_text_bias)(di);
1569 vg_assert(objname);
1571 const HChar *fnname;
1572 Bool ok = VG_(get_fnname_w_offset)(addr, &fnname);
1573 if (!ok) fnname = "UNKNOWN_FUNCTION";
1574 VG_(printf)(
1575 "==== SB %u (evchecks %llu) [tid %u] 0x%lx %s %s%c0x%lx\n",
1576 VG_(get_bbs_translated)(), bbs_done, tid, addr,
1577 fnname, objname, objoff >= 0 ? '+' : '-',
1578 (UWord)(objoff >= 0 ? objoff : -objoff)
1582 /* Are we allowed to translate here? */
1584 { /* BEGIN new scope specially for 'seg' */
1585 NSegment const* seg = VG_(am_find_nsegment)(addr);
1587 if ( (!translations_allowable_from_seg(seg, addr))
1588 || addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
1589 if (VG_(clo_trace_signals))
1590 VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%lx)"
1591 " - throwing SEGV\n", addr);
1592 /* U R busted, sonny. Place your hands on your head and step
1593 away from the orig_addr. */
1594 /* Code address is bad - deliver a signal instead */
1595 if (seg != NULL) {
1596 /* There's some kind of segment at the requested place, but we
1597 aren't allowed to execute code here. */
1598 if (debugging_translation)
1599 VG_(printf)("translations not allowed here (segment not executable)"
1600 "(0x%lx)\n", addr);
1601 else
1602 VG_(synth_fault_perms)(tid, addr);
1603 } else {
1604 /* There is no segment at all; we are attempting to execute in
1605 the middle of nowhere. */
1606 if (debugging_translation)
1607 VG_(printf)("translations not allowed here (no segment)"
1608 "(0x%lx)\n", addr);
1609 else
1610 VG_(synth_fault_mapping)(tid, addr);
1612 return False;
1615 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
1616 verbosity = 0;
1617 if (debugging_translation) {
1618 verbosity = debugging_verbosity;
1620 else
1621 if ( (VG_(clo_trace_flags) > 0
1622 && VG_(get_bbs_translated)() <= VG_(clo_trace_notabove)
1623 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
1624 verbosity = VG_(clo_trace_flags);
1627 /* Figure out which preamble-mangling callback to send. */
1628 preamble_fn = NULL;
1629 if (kind == T_Redir_Replace)
1630 preamble_fn = mk_preamble__set_NRADDR_to_zero;
1631 else
1632 if (kind == T_Redir_Wrap)
1633 preamble_fn = mk_preamble__set_NRADDR_to_nraddr;
1635 /* LE we setup the LR */
1636 # if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
1637 if (nraddr == (Addr)&VG_(ppctoc_magic_redirect_return_stub)) {
1638 /* If entering the special return stub, this means a wrapped or
1639 redirected function is returning. Make this translation one
1640 which restores R2 and LR from the thread's hidden redir
1641 stack, and branch to the (restored) link register, thereby
1642 really causing the function to return. */
1643 vg_assert(kind == T_Normal);
1644 vg_assert(nraddr == addr);
1645 preamble_fn = mk_preamble__ppctoc_magic_return_stub;
1647 # endif
1649 /* ------ Actually do the translation. ------ */
1650 vg_assert2(VG_(tdict).tool_instrument,
1651 "you forgot to set VgToolInterface function 'tool_instrument'");
1653 /* Get the CPU info established at startup. */
1654 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1656 /* Set up 'abiinfo' structure with stuff Vex needs to know about
1657 the guest and host ABIs. */
1659 LibVEX_default_VexAbiInfo( &vex_abiinfo );
1660 vex_abiinfo.guest_stack_redzone_size = VG_STACK_REDZONE_SZB;
1662 # if defined(VGP_amd64_linux)
1663 vex_abiinfo.guest_amd64_assume_fs_is_const = True;
1664 vex_abiinfo.guest_amd64_assume_gs_is_const = True;
1665 # endif
1666 # if defined(VGP_amd64_darwin)
1667 vex_abiinfo.guest_amd64_assume_gs_is_const = True;
1668 # endif
1669 # if defined(VGP_ppc32_linux)
1670 vex_abiinfo.guest_ppc_zap_RZ_at_blr = False;
1671 vex_abiinfo.guest_ppc_zap_RZ_at_bl = NULL;
1672 # endif
1673 # if defined(VGP_ppc64be_linux)
1674 vex_abiinfo.guest_ppc_zap_RZ_at_blr = True;
1675 vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True;
1676 vex_abiinfo.host_ppc_calls_use_fndescrs = True;
1677 # endif
1678 # if defined(VGP_ppc64le_linux)
1679 vex_abiinfo.guest_ppc_zap_RZ_at_blr = True;
1680 vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True;
1681 vex_abiinfo.host_ppc_calls_use_fndescrs = False;
1682 # endif
1683 # if defined(VGP_amd64_solaris)
1684 vex_abiinfo.guest_amd64_assume_fs_is_const = True;
1685 # endif
1686 # if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
1687 ThreadArchState* arch = &VG_(threads)[tid].arch;
1688 vex_abiinfo.guest_mips_fp_mode64 =
1689 !!(arch->vex.guest_CP0_status & MIPS_CP0_STATUS_FR);
1690 # endif
1692 /* Set up closure args. */
1693 closure.tid = tid;
1694 closure.nraddr = nraddr;
1695 closure.readdr = addr;
1697 /* Set up args for LibVEX_Translate. */
1698 vta.arch_guest = vex_arch;
1699 vta.archinfo_guest = vex_archinfo;
1700 vta.arch_host = vex_arch;
1701 vta.archinfo_host = vex_archinfo;
1702 vta.abiinfo_both = vex_abiinfo;
1703 vta.callback_opaque = (void*)&closure;
1704 vta.guest_bytes = (UChar*)addr;
1705 vta.guest_bytes_addr = addr;
1706 vta.chase_into_ok = chase_into_ok;
1707 vta.guest_extents = &vge;
1708 vta.host_bytes = tmpbuf;
1709 vta.host_bytes_size = N_TMPBUF;
1710 vta.host_bytes_used = &tmpbuf_used;
1711 { /* At this point we have to reconcile Vex's view of the
1712 instrumentation callback - which takes a void* first argument
1713 - with Valgrind's view, in which the first arg is a
1714 VgCallbackClosure*. Hence the following longwinded casts.
1715 They are entirely legal but longwinded so as to maximise the
1716 chance of the C typechecker picking up any type snafus. */
1717 IRSB*(*f)(VgCallbackClosure*,
1718 IRSB*,const VexGuestLayout*,const VexGuestExtents*,
1719 const VexArchInfo*,IRType,IRType)
1720 = VG_(clo_vgdb) != Vg_VgdbNo
1721 ? tool_instrument_then_gdbserver_if_needed
1722 : VG_(tdict).tool_instrument;
1723 IRSB*(*g)(void*,
1724 IRSB*,const VexGuestLayout*,const VexGuestExtents*,
1725 const VexArchInfo*,IRType,IRType) = (__typeof__(g)) f;
1726 vta.instrument1 = g;
1728 /* No need for type kludgery here. */
1729 vta.instrument2 = need_to_handle_SP_assignment()
1730 ? vg_SP_update_pass
1731 : NULL;
1732 vta.finaltidy = VG_(needs).final_IR_tidy_pass
1733 ? VG_(tdict).tool_final_IR_tidy_pass
1734 : NULL;
1735 vta.needs_self_check = needs_self_check;
1736 vta.preamble_function = preamble_fn;
1737 vta.traceflags = verbosity;
1738 vta.sigill_diag = VG_(clo_sigill_diag);
1739 vta.addProfInc = VG_(clo_profyle_sbs) && kind != T_NoRedir;
1741 /* Set up the dispatch continuation-point info. If this is a
1742 no-redir translation then it cannot be chained, and the chain-me
1743 points are set to NULL to indicate that. The indir point must
1744 also be NULL, since we can't allow this translation to do an
1745 indir transfer -- that would take it back into the main
1746 translation cache too.
1748 All this is because no-redir translations live outside the main
1749 translation cache (in a secondary one) and chaining them would
1750 involve more adminstrative complexity that isn't worth the
1751 hassle, because we don't expect them to get used often. So
1752 don't bother. */
1753 if (allow_redirection) {
1754 vta.disp_cp_chain_me_to_slowEP
1755 = VG_(fnptr_to_fnentry)( &VG_(disp_cp_chain_me_to_slowEP) );
1756 vta.disp_cp_chain_me_to_fastEP
1757 = VG_(fnptr_to_fnentry)( &VG_(disp_cp_chain_me_to_fastEP) );
1758 vta.disp_cp_xindir
1759 = VG_(fnptr_to_fnentry)( &VG_(disp_cp_xindir) );
1760 } else {
1761 vta.disp_cp_chain_me_to_slowEP = NULL;
1762 vta.disp_cp_chain_me_to_fastEP = NULL;
1763 vta.disp_cp_xindir = NULL;
1765 /* This doesn't involve chaining and so is always allowable. */
1766 vta.disp_cp_xassisted
1767 = VG_(fnptr_to_fnentry)( &VG_(disp_cp_xassisted) );
1769 /* Sheesh. Finally, actually _do_ the translation! */
1770 tres = LibVEX_Translate ( &vta );
1772 vg_assert(tres.status == VexTransOK);
1773 vg_assert(tres.n_sc_extents >= 0 && tres.n_sc_extents <= 3);
1774 vg_assert(tmpbuf_used <= N_TMPBUF);
1775 vg_assert(tmpbuf_used > 0);
1776 } /* END new scope specially for 'seg' */
1778 /* Tell aspacem of all segments that have had translations taken
1779 from them. */
1780 for (i = 0; i < vge.n_used; i++) {
1781 VG_(am_set_segment_hasT)( vge.base[i] );
1784 /* Copy data at trans_addr into the translation cache. */
1785 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
1787 // If debugging, don't do anything with the translated block; we
1788 // only did this for the debugging output produced along the way.
1789 if (!debugging_translation) {
1791 if (kind != T_NoRedir) {
1792 // Put it into the normal TT/TC structures. This is the
1793 // normal case.
1795 // Note that we use nraddr (the non-redirected address), not
1796 // addr, which might have been changed by the redirection
1797 VG_(add_to_transtab)( &vge,
1798 nraddr,
1799 (Addr)(&tmpbuf[0]),
1800 tmpbuf_used,
1801 tres.n_sc_extents > 0,
1802 tres.offs_profInc,
1803 tres.n_guest_instrs );
1804 } else {
1805 vg_assert(tres.offs_profInc == -1); /* -1 == unset */
1806 VG_(add_to_unredir_transtab)( &vge,
1807 nraddr,
1808 (Addr)(&tmpbuf[0]),
1809 tmpbuf_used );
1813 return True;
1816 /*--------------------------------------------------------------------*/
1817 /*--- end ---*/
1818 /*--------------------------------------------------------------------*/