blob: 473d3cf465c962f74945bd26227ba530661b3ad9 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
sewardjbb686272006-01-22 20:12:45 +00003/*--- Interface to LibVEX_Translate, and the SP-update pass ---*/
njn3cbfbc12005-05-13 23:11:40 +00004/*--- m_translate.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005/*--------------------------------------------------------------------*/
6
7/*
njnb9c427c2004-12-01 14:14:42 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
sewardjde4a1d02002-03-22 01:27:54 +000010
sewardj9eecbbb2010-05-03 21:37:12 +000011 Copyright (C) 2000-2010 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
njnc7561b92005-06-19 01:24:32 +000032#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000033#include "pub_core_vki.h"
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
sewardje2d1e672005-11-12 23:10:48 +000035
sewardj0ec07f32006-01-12 12:32:32 +000036#include "pub_core_machine.h" // VG_(fnptr_to_fnentry)
37 // VG_(get_SP)
38 // VG_(machine_get_VexArchInfo)
njn97405b22005-06-02 03:39:33 +000039#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000040#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000041#include "pub_core_libcprint.h"
njn20242342005-05-16 23:31:24 +000042#include "pub_core_options.h"
sewardj45f4e7c2005-09-27 19:20:21 +000043
sewardj0ec07f32006-01-12 12:32:32 +000044#include "pub_core_debuginfo.h" // VG_(get_fnname_w_offset)
45#include "pub_core_redir.h" // VG_(redir_do_lookup)
sewardj45f4e7c2005-09-27 19:20:21 +000046
sewardj0ec07f32006-01-12 12:32:32 +000047#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)
50
njn8bddf582005-05-13 23:40:55 +000051#include "pub_core_translate.h"
52#include "pub_core_transtab.h"
sewardj0ec07f32006-01-12 12:32:32 +000053#include "pub_core_dispatch.h" // VG_(run_innerloop__dispatch_{un}profiled)
54 // VG_(run_a_noredir_translation__return_point)
sewardj274807d2005-12-15 14:07:07 +000055
sewardj6c591e12011-04-11 16:17:51 +000056#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
sewardj34593e52006-01-17 01:57:33 +000057#include "pub_core_threadstate.h" // VexGuestArchState
sewardj4a0009c2006-10-17 01:52:05 +000058#include "pub_core_trampoline.h" // VG_(ppctoc_magic_redirect_return_stub)
sewardj34593e52006-01-17 01:57:33 +000059
sewardj7cf4e6b2008-05-01 20:24:26 +000060#include "pub_core_execontext.h" // VG_(make_depth_1_ExeContext_from_Addr)
61
sewardj3b290482011-05-06 21:02:55 +000062#include "pub_core_gdbserver.h" // VG_(tool_instrument_then_gdbserver_if_needed)
sewardjde4a1d02002-03-22 01:27:54 +000063
njna1f783f2005-06-18 03:44:34 +000064/*------------------------------------------------------------*/
njn42c83552005-12-05 20:45:59 +000065/*--- Stats ---*/
66/*------------------------------------------------------------*/
67
68static UInt n_SP_updates_fast = 0;
69static UInt n_SP_updates_generic_known = 0;
70static UInt n_SP_updates_generic_unknown = 0;
71
72void VG_(print_translation_stats) ( void )
73{
74 Char buf[6];
75 UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
76 + n_SP_updates_generic_unknown;
77 VG_(percentify)(n_SP_updates_fast, n_SP_updates, 1, 6, buf);
78 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +000079 "translate: fast SP updates identified: %'u (%s)\n",
njn42c83552005-12-05 20:45:59 +000080 n_SP_updates_fast, buf );
81
82 VG_(percentify)(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf);
83 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +000084 "translate: generic_known SP updates identified: %'u (%s)\n",
njn42c83552005-12-05 20:45:59 +000085 n_SP_updates_generic_known, buf );
86
87 VG_(percentify)(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf);
88 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +000089 "translate: generic_unknown SP updates identified: %'u (%s)\n",
njn42c83552005-12-05 20:45:59 +000090 n_SP_updates_generic_unknown, buf );
91}
92
93/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +000094/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +000095/*------------------------------------------------------------*/
96
njna1f783f2005-06-18 03:44:34 +000097static Bool need_to_handle_SP_assignment(void)
98{
sewardjf5c8e372006-02-12 15:42:20 +000099 return ( VG_(tdict).track_new_mem_stack_4 ||
100 VG_(tdict).track_die_mem_stack_4 ||
101 VG_(tdict).track_new_mem_stack_8 ||
102 VG_(tdict).track_die_mem_stack_8 ||
103 VG_(tdict).track_new_mem_stack_12 ||
104 VG_(tdict).track_die_mem_stack_12 ||
105 VG_(tdict).track_new_mem_stack_16 ||
106 VG_(tdict).track_die_mem_stack_16 ||
107 VG_(tdict).track_new_mem_stack_32 ||
108 VG_(tdict).track_die_mem_stack_32 ||
109 VG_(tdict).track_new_mem_stack_112 ||
110 VG_(tdict).track_die_mem_stack_112 ||
111 VG_(tdict).track_new_mem_stack_128 ||
112 VG_(tdict).track_die_mem_stack_128 ||
113 VG_(tdict).track_new_mem_stack_144 ||
114 VG_(tdict).track_die_mem_stack_144 ||
115 VG_(tdict).track_new_mem_stack_160 ||
116 VG_(tdict).track_die_mem_stack_160 ||
117 VG_(tdict).track_new_mem_stack ||
118 VG_(tdict).track_die_mem_stack );
njna1f783f2005-06-18 03:44:34 +0000119}
120
njn5096a392005-12-13 20:05:00 +0000121// - The SP aliases are held in an array which is used as a circular buffer.
122// This misses very few constant updates of SP (ie. < 0.1%) while using a
123// small, constant structure that will also never fill up and cause
124// execution to abort.
125// - Unused slots have a .temp value of 'IRTemp_INVALID'.
126// - 'next_SP_alias_slot' is the index where the next alias will be stored.
127// - If the buffer fills, we circle around and start over-writing
128// non-IRTemp_INVALID values. This is rare, and the overwriting of a
129// value that would have subsequently be used is even rarer.
130// - Every slot below next_SP_alias_slot holds a non-IRTemp_INVALID value.
131// The rest either all won't (if we haven't yet circled around) or all
132// will (if we have circled around).
njn9b007f62003-04-07 14:40:25 +0000133
njn5096a392005-12-13 20:05:00 +0000134typedef
135 struct {
136 IRTemp temp;
137 Long delta;
138 }
139 SP_Alias;
140
141// With 32 slots the buffer fills very rarely -- eg. once in a run of GCC.
142// And I've tested with smaller values and the wrap-around case works ok.
143#define N_ALIASES 32
144static SP_Alias SP_aliases[N_ALIASES];
145static Int next_SP_alias_slot = 0;
146
147static void clear_SP_aliases(void)
148{
149 Int i;
150 for (i = 0; i < N_ALIASES; i++) {
151 SP_aliases[i].temp = IRTemp_INVALID;
152 SP_aliases[i].delta = 0;
153 }
154 next_SP_alias_slot = 0;
155}
156
157static void add_SP_alias(IRTemp temp, Long delta)
158{
159 vg_assert(temp != IRTemp_INVALID);
160 SP_aliases[ next_SP_alias_slot ].temp = temp;
161 SP_aliases[ next_SP_alias_slot ].delta = delta;
162 next_SP_alias_slot++;
163 if (N_ALIASES == next_SP_alias_slot) next_SP_alias_slot = 0;
164}
165
166static Bool get_SP_delta(IRTemp temp, ULong* delta)
167{
168 Int i; // i must be signed!
169 vg_assert(IRTemp_INVALID != temp);
170 // Search backwards between current buffer position and the start.
171 for (i = next_SP_alias_slot-1; i >= 0; i--) {
172 if (temp == SP_aliases[i].temp) {
173 *delta = SP_aliases[i].delta;
174 return True;
175 }
176 }
177 // Search backwards between the end and the current buffer position.
178 for (i = N_ALIASES-1; i >= next_SP_alias_slot; i--) {
179 if (temp == SP_aliases[i].temp) {
180 *delta = SP_aliases[i].delta;
181 return True;
182 }
183 }
184 return False;
185}
186
187static void update_SP_aliases(Long delta)
188{
189 Int i;
190 for (i = 0; i < N_ALIASES; i++) {
191 if (SP_aliases[i].temp == IRTemp_INVALID) {
192 return;
193 }
194 SP_aliases[i].delta += delta;
195 }
196}
197
sewardj7cf4e6b2008-05-01 20:24:26 +0000198/* Given a guest IP, get an origin tag for a 1-element stack trace,
199 and wrap it up in an IR atom that can be passed as the origin-tag
200 value for a stack-adjustment helper function. */
201static IRExpr* mk_ecu_Expr ( Addr64 guest_IP )
202{
203 UInt ecu;
204 ExeContext* ec
205 = VG_(make_depth_1_ExeContext_from_Addr)( (Addr)guest_IP );
206 vg_assert(ec);
207 ecu = VG_(get_ECU_from_ExeContext)( ec );
208 vg_assert(VG_(is_plausible_ECU)(ecu));
209 /* This is always safe to do, since ecu is only 32 bits, and
210 HWord is 32 or 64. */
211 return mkIRExpr_HWord( (HWord)ecu );
212}
213
sewardj3b290482011-05-06 21:02:55 +0000214/* When gdbserver is activated, the translation of a block must
215 first be done by the tool function, then followed by a pass
216 which (if needed) instruments the code for gdbserver.
217*/
218static
219IRSB* tool_instrument_then_gdbserver_if_needed ( VgCallbackClosure* closureV,
220 IRSB* sb_in,
221 VexGuestLayout* layout,
222 VexGuestExtents* vge,
223 IRType gWordTy,
224 IRType hWordTy )
225{
226 return VG_(instrument_for_gdbserver_if_needed)
227 (VG_(tdict).tool_instrument (closureV,
228 sb_in,
229 layout,
230 vge,
231 gWordTy,
232 hWordTy),
233 layout,
234 vge,
235 gWordTy,
236 hWordTy);
237}
njn5096a392005-12-13 20:05:00 +0000238
239/* For tools that want to know about SP changes, this pass adds
nethercote996901a2004-08-03 13:29:09 +0000240 in the appropriate hooks. We have to do it after the tool's
njn5096a392005-12-13 20:05:00 +0000241 instrumentation, so the tool doesn't have to worry about the C calls
njn9b007f62003-04-07 14:40:25 +0000242 it adds in, and we must do it before register allocation because
njn5096a392005-12-13 20:05:00 +0000243 spilled temps make it much harder to work out the SP deltas.
244 This it is done with Vex's "second instrumentation" pass.
sewardjde4a1d02002-03-22 01:27:54 +0000245
njn5096a392005-12-13 20:05:00 +0000246 Basically, we look for GET(SP)/PUT(SP) pairs and track constant
247 increments/decrements of SP between them. (This requires tracking one or
248 more "aliases", which are not exact aliases but instead are tempregs
249 whose value is equal to the SP's plus or minus a known constant.)
250 If all the changes to SP leading up to a PUT(SP) are by known, small
251 constants, we can do a specific call to eg. new_mem_stack_4, otherwise
252 we fall back to the case that handles an unknown SP change.
sewardj2831b512007-11-11 18:56:39 +0000253
254 There is some extra complexity to deal correctly with updates to
255 only parts of SP. Bizarre, but it has been known to happen.
njn5096a392005-12-13 20:05:00 +0000256*/
sewardjde4a1d02002-03-22 01:27:54 +0000257static
sewardj0b9d74a2006-12-24 02:24:11 +0000258IRSB* vg_SP_update_pass ( void* closureV,
259 IRSB* sb_in,
sewardj4ba057c2005-10-18 12:04:18 +0000260 VexGuestLayout* layout,
sewardj4ba057c2005-10-18 12:04:18 +0000261 VexGuestExtents* vge,
262 IRType gWordTy,
263 IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +0000264{
sewardj0b9d74a2006-12-24 02:24:11 +0000265 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj2831b512007-11-11 18:56:39 +0000266 Int first_SP, last_SP, first_Put, last_Put;
sewardj0b9d74a2006-12-24 02:24:11 +0000267 IRDirty *dcall, *d;
268 IRStmt* st;
269 IRExpr* e;
270 IRRegArray* descr;
271 IRType typeof_SP;
272 Long delta, con;
sewardjde4a1d02002-03-22 01:27:54 +0000273
sewardj7cf4e6b2008-05-01 20:24:26 +0000274 /* Set up stuff for tracking the guest IP */
275 Bool curr_IP_known = False;
276 Addr64 curr_IP = 0;
277
sewardj8b635a42004-11-22 19:01:47 +0000278 /* Set up BB */
sewardj0b9d74a2006-12-24 02:24:11 +0000279 IRSB* bb = emptyIRSB();
280 bb->tyenv = deepCopyIRTypeEnv(sb_in->tyenv);
281 bb->next = deepCopyIRExpr(sb_in->next);
282 bb->jumpkind = sb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +0000283
sewardj7cf97ee2004-11-28 14:25:01 +0000284 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000285
sewardj7cf97ee2004-11-28 14:25:01 +0000286 sizeof_SP = layout->sizeof_SP;
287 offset_SP = layout->offset_SP;
288 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +0000289 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +0000290
sewardj7cf4e6b2008-05-01 20:24:26 +0000291 /* --- Start of #defines --- */
292
sewardj8b635a42004-11-22 19:01:47 +0000293# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
294# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +0000295
sewardj8b635a42004-11-22 19:01:47 +0000296# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +0000297
sewardj8b635a42004-11-22 19:01:47 +0000298# define GET_CONST(con) \
299 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
300 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000301
sewardj7cf4e6b2008-05-01 20:24:26 +0000302# define DO_NEW(syze, tmpp) \
sewardj8b635a42004-11-22 19:01:47 +0000303 do { \
sewardj7cf4e6b2008-05-01 20:24:26 +0000304 Bool vanilla, w_ecu; \
305 vg_assert(curr_IP_known); \
306 vanilla = NULL != VG_(tdict).track_new_mem_stack_##syze; \
307 w_ecu = NULL != VG_(tdict).track_new_mem_stack_##syze##_w_ECU; \
308 vg_assert(!(vanilla && w_ecu)); /* can't have both */ \
309 if (!(vanilla || w_ecu)) \
310 goto generic; \
311 \
312 /* I don't know if it's really necessary to say that the */ \
313 /* call reads the stack pointer. But anyway, we do. */ \
314 if (w_ecu) { \
315 dcall = unsafeIRDirty_0_N( \
316 2/*regparms*/, \
317 "track_new_mem_stack_" #syze "_w_ECU", \
318 VG_(fnptr_to_fnentry)( \
319 VG_(tdict).track_new_mem_stack_##syze##_w_ECU ), \
320 mkIRExprVec_2(IRExpr_RdTmp(tmpp), \
321 mk_ecu_Expr(curr_IP)) \
322 ); \
323 } else { \
324 dcall = unsafeIRDirty_0_N( \
325 1/*regparms*/, \
326 "track_new_mem_stack_" #syze , \
327 VG_(fnptr_to_fnentry)( \
328 VG_(tdict).track_new_mem_stack_##syze ), \
329 mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \
330 ); \
331 } \
332 dcall->nFxState = 1; \
333 dcall->fxState[0].fx = Ifx_Read; \
334 dcall->fxState[0].offset = layout->offset_SP; \
335 dcall->fxState[0].size = layout->sizeof_SP; \
336 \
337 addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \
338 \
339 tl_assert(syze > 0); \
340 update_SP_aliases(syze); \
341 \
342 n_SP_updates_fast++; \
343 \
344 } while (0)
345
346# define DO_DIE(syze, tmpp) \
347 do { \
348 if (!VG_(tdict).track_die_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000349 goto generic; \
350 \
351 /* I don't know if it's really necessary to say that the */ \
352 /* call reads the stack pointer. But anyway, we do. */ \
353 dcall = unsafeIRDirty_0_N( \
354 1/*regparms*/, \
sewardj7cf4e6b2008-05-01 20:24:26 +0000355 "track_die_mem_stack_" #syze, \
sewardj53ee1fc2005-12-23 02:29:58 +0000356 VG_(fnptr_to_fnentry)( \
sewardj7cf4e6b2008-05-01 20:24:26 +0000357 VG_(tdict).track_die_mem_stack_##syze ), \
sewardj0b9d74a2006-12-24 02:24:11 +0000358 mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \
sewardj8b635a42004-11-22 19:01:47 +0000359 ); \
360 dcall->nFxState = 1; \
361 dcall->fxState[0].fx = Ifx_Read; \
362 dcall->fxState[0].offset = layout->offset_SP; \
363 dcall->fxState[0].size = layout->sizeof_SP; \
364 \
sewardj0b9d74a2006-12-24 02:24:11 +0000365 addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \
njn42c83552005-12-05 20:45:59 +0000366 \
sewardj7cf4e6b2008-05-01 20:24:26 +0000367 tl_assert(syze > 0); \
368 update_SP_aliases(-(syze)); \
njn5096a392005-12-13 20:05:00 +0000369 \
njn42c83552005-12-05 20:45:59 +0000370 n_SP_updates_fast++; \
371 \
sewardj8b635a42004-11-22 19:01:47 +0000372 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000373
sewardj7cf4e6b2008-05-01 20:24:26 +0000374 /* --- End of #defines --- */
375
njn5096a392005-12-13 20:05:00 +0000376 clear_SP_aliases();
377
sewardj0b9d74a2006-12-24 02:24:11 +0000378 for (i = 0; i < sb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000379
sewardj0b9d74a2006-12-24 02:24:11 +0000380 st = sb_in->stmts[i];
sewardjde4a1d02002-03-22 01:27:54 +0000381
sewardj7cf4e6b2008-05-01 20:24:26 +0000382 if (st->tag == Ist_IMark) {
383 curr_IP_known = True;
384 curr_IP = st->Ist.IMark.addr;
385 }
386
sewardj8b635a42004-11-22 19:01:47 +0000387 /* t = Get(sp): curr = t, delta = 0 */
sewardj0b9d74a2006-12-24 02:24:11 +0000388 if (st->tag != Ist_WrTmp) goto case2;
389 e = st->Ist.WrTmp.data;
sewardj8b635a42004-11-22 19:01:47 +0000390 if (e->tag != Iex_Get) goto case2;
391 if (e->Iex.Get.offset != offset_SP) goto case2;
392 if (e->Iex.Get.ty != typeof_SP) goto case2;
sewardj2831b512007-11-11 18:56:39 +0000393 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
sewardj0b9d74a2006-12-24 02:24:11 +0000394 add_SP_alias(st->Ist.WrTmp.tmp, 0);
395 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000396 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000397
sewardj8b635a42004-11-22 19:01:47 +0000398 case2:
399 /* t' = curr +/- const: curr = t', delta +=/-= const */
sewardj0b9d74a2006-12-24 02:24:11 +0000400 if (st->tag != Ist_WrTmp) goto case3;
401 e = st->Ist.WrTmp.data;
sewardj8b635a42004-11-22 19:01:47 +0000402 if (e->tag != Iex_Binop) goto case3;
sewardj0b9d74a2006-12-24 02:24:11 +0000403 if (e->Iex.Binop.arg1->tag != Iex_RdTmp) goto case3;
404 if (!get_SP_delta(e->Iex.Binop.arg1->Iex.RdTmp.tmp, &delta)) goto case3;
sewardj8b635a42004-11-22 19:01:47 +0000405 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
406 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
njn5096a392005-12-13 20:05:00 +0000407 con = GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
sewardj2831b512007-11-11 18:56:39 +0000408 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
njn5096a392005-12-13 20:05:00 +0000409 if (IS_ADD(e->Iex.Binop.op)) {
sewardj0b9d74a2006-12-24 02:24:11 +0000410 add_SP_alias(st->Ist.WrTmp.tmp, delta + con);
njn5096a392005-12-13 20:05:00 +0000411 } else {
sewardj0b9d74a2006-12-24 02:24:11 +0000412 add_SP_alias(st->Ist.WrTmp.tmp, delta - con);
njn5096a392005-12-13 20:05:00 +0000413 }
sewardj0b9d74a2006-12-24 02:24:11 +0000414 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000415 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000416
sewardj8b635a42004-11-22 19:01:47 +0000417 case3:
418 /* t' = curr: curr = t' */
sewardj0b9d74a2006-12-24 02:24:11 +0000419 if (st->tag != Ist_WrTmp) goto case4;
420 e = st->Ist.WrTmp.data;
421 if (e->tag != Iex_RdTmp) goto case4;
422 if (!get_SP_delta(e->Iex.RdTmp.tmp, &delta)) goto case4;
sewardj2831b512007-11-11 18:56:39 +0000423 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
sewardj0b9d74a2006-12-24 02:24:11 +0000424 add_SP_alias(st->Ist.WrTmp.tmp, delta);
425 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000426 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000427
sewardj8b635a42004-11-22 19:01:47 +0000428 case4:
429 /* Put(sp) = curr */
sewardj2831b512007-11-11 18:56:39 +0000430 /* More generally, we must correctly handle a Put which writes
431 any part of SP, not just the case where all of SP is
432 written. */
sewardj8b635a42004-11-22 19:01:47 +0000433 if (st->tag != Ist_Put) goto case5;
sewardj2831b512007-11-11 18:56:39 +0000434 first_SP = offset_SP;
435 last_SP = first_SP + sizeof_SP - 1;
436 first_Put = st->Ist.Put.offset;
437 last_Put = first_Put
438 + sizeofIRType( typeOfIRExpr( bb->tyenv, st->Ist.Put.data ))
439 - 1;
440 vg_assert(first_SP <= last_SP);
441 vg_assert(first_Put <= last_Put);
442
443 if (last_Put < first_SP || last_SP < first_Put)
444 goto case5; /* no overlap */
445
446 if (st->Ist.Put.data->tag == Iex_RdTmp
447 && get_SP_delta(st->Ist.Put.data->Iex.RdTmp.tmp, &delta)) {
sewardj0b9d74a2006-12-24 02:24:11 +0000448 IRTemp tttmp = st->Ist.Put.data->Iex.RdTmp.tmp;
sewardj2831b512007-11-11 18:56:39 +0000449 /* Why should the following assertion hold? Because any
450 alias added by put_SP_alias must be of a temporary which
451 has the same type as typeof_SP, and whose value is a Get
452 at exactly offset_SP of size typeof_SP. Each call to
453 put_SP_alias is immediately preceded by an assertion that
454 we are putting in a binding for a correctly-typed
455 temporary. */
456 vg_assert( typeOfIRTemp(bb->tyenv, tttmp) == typeof_SP );
457 /* From the same type-and-offset-correctness argument, if
458 we found a useable alias, it must for an "exact" write of SP. */
459 vg_assert(first_SP == first_Put);
460 vg_assert(last_SP == last_Put);
sewardj8b635a42004-11-22 19:01:47 +0000461 switch (delta) {
sewardj0b9d74a2006-12-24 02:24:11 +0000462 case 0: addStmtToIRSB(bb,st); continue;
sewardj7cf4e6b2008-05-01 20:24:26 +0000463 case 4: DO_DIE( 4, tttmp); addStmtToIRSB(bb,st); continue;
464 case -4: DO_NEW( 4, tttmp); addStmtToIRSB(bb,st); continue;
465 case 8: DO_DIE( 8, tttmp); addStmtToIRSB(bb,st); continue;
466 case -8: DO_NEW( 8, tttmp); addStmtToIRSB(bb,st); continue;
467 case 12: DO_DIE( 12, tttmp); addStmtToIRSB(bb,st); continue;
468 case -12: DO_NEW( 12, tttmp); addStmtToIRSB(bb,st); continue;
469 case 16: DO_DIE( 16, tttmp); addStmtToIRSB(bb,st); continue;
470 case -16: DO_NEW( 16, tttmp); addStmtToIRSB(bb,st); continue;
471 case 32: DO_DIE( 32, tttmp); addStmtToIRSB(bb,st); continue;
472 case -32: DO_NEW( 32, tttmp); addStmtToIRSB(bb,st); continue;
473 case 112: DO_DIE( 112, tttmp); addStmtToIRSB(bb,st); continue;
474 case -112: DO_NEW( 112, tttmp); addStmtToIRSB(bb,st); continue;
475 case 128: DO_DIE( 128, tttmp); addStmtToIRSB(bb,st); continue;
476 case -128: DO_NEW( 128, tttmp); addStmtToIRSB(bb,st); continue;
477 case 144: DO_DIE( 144, tttmp); addStmtToIRSB(bb,st); continue;
478 case -144: DO_NEW( 144, tttmp); addStmtToIRSB(bb,st); continue;
479 case 160: DO_DIE( 160, tttmp); addStmtToIRSB(bb,st); continue;
480 case -160: DO_NEW( 160, tttmp); addStmtToIRSB(bb,st); continue;
njn42c83552005-12-05 20:45:59 +0000481 default:
sewardjbb686272006-01-22 20:12:45 +0000482 /* common values for ppc64: 144 128 160 112 176 */
njn42c83552005-12-05 20:45:59 +0000483 n_SP_updates_generic_known++;
484 goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000485 }
sewardj8b635a42004-11-22 19:01:47 +0000486 } else {
sewardj2831b512007-11-11 18:56:39 +0000487 /* Deal with an unknown update to SP. We're here because
488 either:
489 (1) the Put does not exactly cover SP; it is a partial update.
490 Highly unlikely, but has been known to happen for 16-bit
491 Windows apps running on Wine, doing 16-bit adjustments to
492 %sp.
493 (2) the Put does exactly cover SP, but we are unable to
494 determine how the value relates to the old SP. In any
495 case, we cannot assume that the Put.data value is a tmp;
496 we must assume it can be anything allowed in flat IR (tmp
497 or const).
498 */
sewardj7cf4e6b2008-05-01 20:24:26 +0000499 IRTemp old_SP;
njn42c83552005-12-05 20:45:59 +0000500 n_SP_updates_generic_unknown++;
501
njn5096a392005-12-13 20:05:00 +0000502 // Nb: if all is well, this generic case will typically be
503 // called something like every 1000th SP update. If it's more than
504 // that, the above code may be missing some cases.
sewardj8b635a42004-11-22 19:01:47 +0000505 generic:
sewardj7cf4e6b2008-05-01 20:24:26 +0000506 /* Pass both the old and new SP values to this helper. Also,
507 pass an origin tag, even if it isn't needed. */
sewardj2a99cf62004-11-24 10:44:19 +0000508 old_SP = newIRTemp(bb->tyenv, typeof_SP);
sewardj0b9d74a2006-12-24 02:24:11 +0000509 addStmtToIRSB(
sewardj2a99cf62004-11-24 10:44:19 +0000510 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000511 IRStmt_WrTmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
sewardj2a99cf62004-11-24 10:44:19 +0000512 );
sewardjde4a1d02002-03-22 01:27:54 +0000513
sewardj2831b512007-11-11 18:56:39 +0000514 /* Now we know what the old value of SP is. But knowing the new
515 value is a bit tricky if there is a partial write. */
516 if (first_Put == first_SP && last_Put == last_SP) {
517 /* The common case, an exact write to SP. So st->Ist.Put.data
518 does hold the new value; simple. */
sewardj7cf4e6b2008-05-01 20:24:26 +0000519 vg_assert(curr_IP_known);
sewardj2831b512007-11-11 18:56:39 +0000520 dcall = unsafeIRDirty_0_N(
sewardj7cf4e6b2008-05-01 20:24:26 +0000521 3/*regparms*/,
sewardj2831b512007-11-11 18:56:39 +0000522 "VG_(unknown_SP_update)",
523 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
sewardj7cf4e6b2008-05-01 20:24:26 +0000524 mkIRExprVec_3( IRExpr_RdTmp(old_SP), st->Ist.Put.data,
525 mk_ecu_Expr(curr_IP) )
sewardj2831b512007-11-11 18:56:39 +0000526 );
527 addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
528 /* don't forget the original assignment */
529 addStmtToIRSB( bb, st );
530 } else {
531 /* We have a partial update to SP. We need to know what
532 the new SP will be, and hand that to the helper call,
533 but when the helper call happens, SP must hold the
534 value it had before the update. Tricky.
535 Therefore use the following kludge:
536 1. do the partial SP update (Put)
537 2. Get the new SP value into a tmp, new_SP
538 3. Put old_SP
539 4. Call the helper
540 5. Put new_SP
541 */
542 IRTemp new_SP;
543 /* 1 */
544 addStmtToIRSB( bb, st );
545 /* 2 */
546 new_SP = newIRTemp(bb->tyenv, typeof_SP);
547 addStmtToIRSB(
548 bb,
549 IRStmt_WrTmp( new_SP, IRExpr_Get(offset_SP, typeof_SP) )
550 );
551 /* 3 */
552 addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(old_SP) ));
553 /* 4 */
sewardj7cf4e6b2008-05-01 20:24:26 +0000554 vg_assert(curr_IP_known);
sewardj2831b512007-11-11 18:56:39 +0000555 dcall = unsafeIRDirty_0_N(
sewardj7cf4e6b2008-05-01 20:24:26 +0000556 3/*regparms*/,
sewardj2831b512007-11-11 18:56:39 +0000557 "VG_(unknown_SP_update)",
558 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
sewardj7cf4e6b2008-05-01 20:24:26 +0000559 mkIRExprVec_3( IRExpr_RdTmp(old_SP),
560 IRExpr_RdTmp(new_SP),
561 mk_ecu_Expr(curr_IP) )
sewardj2831b512007-11-11 18:56:39 +0000562 );
563 addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
564 /* 5 */
565 addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(new_SP) ));
566 }
sewardj2a99cf62004-11-24 10:44:19 +0000567
sewardj2831b512007-11-11 18:56:39 +0000568 /* Forget what we already know. */
njn5096a392005-12-13 20:05:00 +0000569 clear_SP_aliases();
sewardj2831b512007-11-11 18:56:39 +0000570
571 /* If this is a Put of a tmp that exactly updates SP,
572 start tracking aliases against this tmp. */
573
574 if (first_Put == first_SP && last_Put == last_SP
575 && st->Ist.Put.data->tag == Iex_RdTmp) {
576 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.Put.data->Iex.RdTmp.tmp)
577 == typeof_SP );
578 add_SP_alias(st->Ist.Put.data->Iex.RdTmp.tmp, 0);
579 }
sewardj8b635a42004-11-22 19:01:47 +0000580 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000581 }
582
sewardj8b635a42004-11-22 19:01:47 +0000583 case5:
584 /* PutI or Dirty call which overlaps SP: complain. We can't
585 deal with SP changing in weird ways (well, we can, but not at
586 this time of night). */
587 if (st->tag == Ist_PutI) {
588 descr = st->Ist.PutI.descr;
589 minoff_ST = descr->base;
sewardj2831b512007-11-11 18:56:39 +0000590 maxoff_ST = descr->base
591 + descr->nElems * sizeofIRType(descr->elemTy) - 1;
592 if (!(offset_SP > maxoff_ST
593 || (offset_SP + sizeof_SP - 1) < minoff_ST))
sewardj8b635a42004-11-22 19:01:47 +0000594 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000595 }
sewardj8b635a42004-11-22 19:01:47 +0000596 if (st->tag == Ist_Dirty) {
597 d = st->Ist.Dirty.details;
598 for (j = 0; j < d->nFxState; j++) {
599 minoff_ST = d->fxState[j].offset;
600 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
601 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
602 continue;
sewardj2831b512007-11-11 18:56:39 +0000603 if (!(offset_SP > maxoff_ST
604 || (offset_SP + sizeof_SP - 1) < minoff_ST))
sewardj8b635a42004-11-22 19:01:47 +0000605 goto complain;
606 }
607 }
sewardjde4a1d02002-03-22 01:27:54 +0000608
sewardj8b635a42004-11-22 19:01:47 +0000609 /* well, not interesting. Just copy and keep going. */
sewardj0b9d74a2006-12-24 02:24:11 +0000610 addStmtToIRSB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000611
sewardj0b9d74a2006-12-24 02:24:11 +0000612 } /* for (i = 0; i < sb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000613
sewardj8b635a42004-11-22 19:01:47 +0000614 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000615
sewardj8b635a42004-11-22 19:01:47 +0000616 complain:
617 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000618
sewardj7cf4e6b2008-05-01 20:24:26 +0000619#undef IS_ADD
620#undef IS_SUB
621#undef IS_ADD_OR_SUB
622#undef GET_CONST
623#undef DO_NEW
624#undef DO_DIE
sewardjde4a1d02002-03-22 01:27:54 +0000625}
sewardj7c4b6042003-06-14 15:47:15 +0000626
sewardjde4a1d02002-03-22 01:27:54 +0000627/*------------------------------------------------------------*/
628/*--- Main entry point for the JITter. ---*/
629/*------------------------------------------------------------*/
630
sewardjd2b70dc2005-10-14 17:22:31 +0000631/* Extra comments re self-checking translations and self-modifying
632 code. (JRS 14 Oct 05).
633
634 There are 3 modes:
635 (1) no checking: all code assumed to be not self-modifying
636 (2) partial: known-problematic situations get a self-check
637 (3) full checking: all translations get a self-check
638
639 As currently implemented, the default is (2). (3) is always safe,
640 but very slow. (1) works mostly, but fails for gcc nested-function
641 code which uses trampolines on the stack; this situation is
642 detected and handled by (2).
643
644 ----------
645
646 A more robust and transparent solution, which is not currently
647 implemented, is a variant of (2): if a translation is made from an
648 area which aspacem says does not have 'w' permission, then it can
649 be non-self-checking. Otherwise, it needs a self-check.
650
651 This is complicated by Vex's basic-block chasing. If a self-check
652 is requested, then Vex will not chase over basic block boundaries
653 (it's too complex). However there is still a problem if it chases
654 from a non-'w' area into a 'w' area.
655
656 I think the right thing to do is:
657
658 - if a translation request starts in a 'w' area, ask for a
659 self-checking translation, and do not allow any chasing (make
660 chase_into_ok return False). Note that the latter is redundant
661 in the sense that Vex won't chase anyway in this situation.
662
663 - if a translation request starts in a non-'w' area, do not ask for
664 a self-checking translation. However, do not allow chasing (as
665 determined by chase_into_ok) to go into a 'w' area.
666
667 The result of this is that all code inside 'w' areas is self
668 checking.
669
670 To complete the trick, there is a caveat: we must watch the
671 client's mprotect calls. If pages are changed from non-'w' to 'w'
672 then we should throw away all translations which intersect the
673 affected area, so as to force them to be redone with self-checks.
674
675 ----------
676
677 The above outlines the conditions under which bb chasing is allowed
678 from a self-modifying-code point of view. There are other
679 situations pertaining to function redirection in which it is
680 necessary to disallow chasing, but those fall outside the scope of
681 this comment.
682*/
683
sewardj34593e52006-01-17 01:57:33 +0000684
sewardj8b635a42004-11-22 19:01:47 +0000685/* Vex dumps the final code in here. Then we can copy it off
686 wherever we like. */
sewardj4a0009c2006-10-17 01:52:05 +0000687/* 60000: should agree with assertion in VG_(add_to_transtab) in
688 m_transtab.c. */
689#define N_TMPBUF 60000
sewardj8b635a42004-11-22 19:01:47 +0000690static UChar tmpbuf[N_TMPBUF];
691
sewardj34593e52006-01-17 01:57:33 +0000692
sewardj8b635a42004-11-22 19:01:47 +0000693/* Function pointers we must supply to LibVEX in order that it
694 can bomb out and emit messages under Valgrind's control. */
695__attribute__ ((noreturn))
696static
697void failure_exit ( void )
698{
sewardjbf426512005-01-17 18:35:30 +0000699 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000700 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000701}
702
703static
sewardjb5f6f512005-03-10 23:59:00 +0000704void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000705{
706 Int i;
707 for (i = 0; i < nbytes-3; i += 4)
708 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
709 for (; i < nbytes; i++)
710 VG_(printf)("%c", bytes[i]);
711}
712
njn25e49d8e72002-09-23 09:36:25 +0000713
sewardj34593e52006-01-17 01:57:33 +0000714/* --------- Various helper functions for translation --------- */
sewardj8b635a42004-11-22 19:01:47 +0000715
sewardj45f4e7c2005-09-27 19:20:21 +0000716/* Look for reasons to disallow making translations from the given
717 segment. */
718
sewardj4a0009c2006-10-17 01:52:05 +0000719static Bool translations_allowable_from_seg ( NSegment const* seg )
sewardj45f4e7c2005-09-27 19:20:21 +0000720{
sewardjb5b87402011-03-07 16:05:35 +0000721# if defined(VGA_x86) || defined(VGA_s390x)
sewardj45f4e7c2005-09-27 19:20:21 +0000722 Bool allowR = True;
723# else
724 Bool allowR = False;
725# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000726 return seg != NULL
tom1da86fe2009-10-12 13:53:12 +0000727 && (seg->kind == SkAnonC || seg->kind == SkFileC || seg->kind == SkShmC)
sewardj45f4e7c2005-09-27 19:20:21 +0000728 && (seg->hasX || (seg->hasR && allowR));
729}
730
731
sewardj6dbcc632011-06-07 21:39:28 +0000732/* Produce a bitmask stating which of the supplied extents needs a
733 self-check. See documentation of
734 VexTranslateArgs::needs_self_check for more details about the
735 return convention. */
sewardj45f4e7c2005-09-27 19:20:21 +0000736
sewardj6dbcc632011-06-07 21:39:28 +0000737static UInt needs_self_check ( void* closureV,
738 VexGuestExtents* vge )
sewardj34593e52006-01-17 01:57:33 +0000739{
sewardj6dbcc632011-06-07 21:39:28 +0000740 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
741 UInt i, bitset;
742
743 vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
744 bitset = 0;
745
746 for (i = 0; i < vge->n_used; i++) {
747 Bool check = False;
748 Addr addr = (Addr)vge->base[i];
749 SizeT len = (SizeT)vge->len[i];
750 NSegment const* segA = NULL;
751
752# if defined(VGO_darwin)
753 // GrP fixme hack - dyld i386 IMPORT gets rewritten.
754 // To really do this correctly, we'd need to flush the
755 // translation cache whenever a segment became +WX.
756 segA = VG_(am_find_nsegment)(addr);
757 if (segA && segA->hasX && segA->hasW)
758 check = True;
759# endif
760
761 if (!check) {
762 switch (VG_(clo_smc_check)) {
763 case Vg_SmcNone:
764 /* never check (except as per Darwin hack above) */
765 break;
766 case Vg_SmcAll:
767 /* always check */
768 check = True;
769 break;
770 case Vg_SmcStack: {
771 /* check if the address is in the same segment as this
772 thread's stack pointer */
773 Addr sp = VG_(get_SP)(closure->tid);
774 if (!segA) {
775 segA = VG_(am_find_nsegment)(addr);
776 }
777 NSegment const* segSP = VG_(am_find_nsegment)(sp);
778 if (segA && segSP && segA == segSP)
779 check = True;
780 break;
781 }
782 case Vg_SmcAllNonFile: {
783 /* check if any part of the extent is not in a
784 file-mapped segment */
785 if (!segA) {
786 segA = VG_(am_find_nsegment)(addr);
787 }
788 if (segA && segA->kind == SkFileC && segA->start <= addr
789 && (len == 0 || addr + len <= segA->end + 1)) {
790 /* in a file-mapped segment; skip the check */
791 } else {
792 check = True;
793 }
794 break;
795 }
796 default:
797 vg_assert(0);
798 }
799 }
800
801 if (check)
802 bitset |= (1 << i);
njnf76d27a2009-05-28 01:53:07 +0000803 }
sewardj6dbcc632011-06-07 21:39:28 +0000804
805 return bitset;
sewardj34593e52006-01-17 01:57:33 +0000806}
807
808
809/* This is a callback passed to LibVEX_Translate. It stops Vex from
810 chasing into function entry points that we wish to redirect.
811 Chasing across them obviously defeats the redirect mechanism, with
sewardj6dbcc632011-06-07 21:39:28 +0000812 bad effects for Memcheck, Helgrind, DRD, Massif, and possibly others.
sewardj447f2a12005-07-07 13:52:53 +0000813*/
sewardj34593e52006-01-17 01:57:33 +0000814static Bool chase_into_ok ( void* closureV, Addr64 addr64 )
sewardj8b635a42004-11-22 19:01:47 +0000815{
sewardj34593e52006-01-17 01:57:33 +0000816 Addr addr = (Addr)addr64;
sewardj4a0009c2006-10-17 01:52:05 +0000817 NSegment const* seg = VG_(am_find_nsegment)(addr);
sewardj45f4e7c2005-09-27 19:20:21 +0000818
sewardj447f2a12005-07-07 13:52:53 +0000819 /* Work through a list of possibilities why we might not want to
820 allow a chase. */
sewardj447f2a12005-07-07 13:52:53 +0000821
sewardj34593e52006-01-17 01:57:33 +0000822 /* Destination not in a plausible segment? */
sewardj45f4e7c2005-09-27 19:20:21 +0000823 if (!translations_allowable_from_seg(seg))
824 goto dontchase;
825
sewardj447f2a12005-07-07 13:52:53 +0000826 /* Destination is redirected? */
sewardj0ec07f32006-01-12 12:32:32 +0000827 if (addr != VG_(redir_do_lookup)(addr, NULL))
sewardj447f2a12005-07-07 13:52:53 +0000828 goto dontchase;
829
sewardj4a0009c2006-10-17 01:52:05 +0000830# if defined(VG_PLAT_USES_PPCTOC)
831 /* This needs to be at the start of its own block. Don't chase. Re
832 ULong_to_Ptr, be careful to ensure we only compare 32 bits on a
833 32-bit target.*/
834 if (ULong_to_Ptr(addr64)
835 == (void*)&VG_(ppctoc_magic_redirect_return_stub))
sewardj34593e52006-01-17 01:57:33 +0000836 goto dontchase;
837# endif
838
sewardj5f76de02007-02-11 05:08:06 +0000839 /* overly conservative, but .. don't chase into the distinguished
840 address that m_transtab uses as an empty-slot marker for
841 VG_(tt_fast). */
842 if (addr == TRANSTAB_BOGUS_GUEST_ADDR)
843 goto dontchase;
844
sewardj447f2a12005-07-07 13:52:53 +0000845 /* well, ok then. go on and chase. */
846 return True;
847
848 vg_assert(0);
849 /*NOTREACHED*/
850
851 dontchase:
njn8a7b41b2007-09-23 00:51:24 +0000852 if (0) VG_(printf)("not chasing into 0x%lx\n", addr);
sewardj447f2a12005-07-07 13:52:53 +0000853 return False;
sewardj8b635a42004-11-22 19:01:47 +0000854}
855
sewardj447f2a12005-07-07 13:52:53 +0000856
sewardj4a0009c2006-10-17 01:52:05 +0000857/* --------------- helpers for with-TOC platforms --------------- */
858
859/* NOTE: with-TOC platforms are: ppc64-linux, ppc32-aix5, ppc64-aix5. */
sewardjdfbaa222006-01-18 04:25:20 +0000860
sewardjd68ac3e2006-01-20 14:31:57 +0000861static IRExpr* mkU64 ( ULong n ) {
sewardj34593e52006-01-17 01:57:33 +0000862 return IRExpr_Const(IRConst_U64(n));
863}
sewardjd68ac3e2006-01-20 14:31:57 +0000864static IRExpr* mkU32 ( UInt n ) {
865 return IRExpr_Const(IRConst_U32(n));
866}
sewardj4a0009c2006-10-17 01:52:05 +0000867
868#if defined(VG_PLAT_USES_PPCTOC)
sewardjd68ac3e2006-01-20 14:31:57 +0000869static IRExpr* mkU8 ( UChar n ) {
870 return IRExpr_Const(IRConst_U8(n));
871}
sewardj4a0009c2006-10-17 01:52:05 +0000872static IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) {
873 if (typeOfIRExpr(tyenv, e) == Ity_I32) {
874 return e;
875 } else {
876 vg_assert(typeOfIRExpr(tyenv, e) == Ity_I64);
877 return IRExpr_Unop(Iop_64to32, e);
878 }
879}
880
881/* Generate code to push word-typed expression 'e' onto this thread's
882 redir stack, checking for stack overflow and generating code to
883 bomb out if so. */
sewardj34593e52006-01-17 01:57:33 +0000884
sewardj0b9d74a2006-12-24 02:24:11 +0000885static void gen_PUSH ( IRSB* bb, IRExpr* e )
sewardj34593e52006-01-17 01:57:33 +0000886{
sewardj0b9d74a2006-12-24 02:24:11 +0000887 IRRegArray* descr;
888 IRTemp t1;
889 IRExpr* one;
sewardj34593e52006-01-17 01:57:33 +0000890
sewardj4a0009c2006-10-17 01:52:05 +0000891# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
892 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
893 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
894 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
895 Int offB_EMWARN = offsetof(VexGuestPPC64State,guest_EMWARN);
896 Bool is64 = True;
897 IRType ty_Word = Ity_I64;
898 IROp op_CmpNE = Iop_CmpNE64;
899 IROp op_Sar = Iop_Sar64;
900 IROp op_Sub = Iop_Sub64;
901 IROp op_Add = Iop_Add64;
902 IRExpr*(*mkU)(ULong) = mkU64;
903 vg_assert(VG_WORDSIZE == 8);
904# else
905 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
906 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
907 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
908 Int offB_EMWARN = offsetof(VexGuestPPC32State,guest_EMWARN);
909 Bool is64 = False;
910 IRType ty_Word = Ity_I32;
911 IROp op_CmpNE = Iop_CmpNE32;
912 IROp op_Sar = Iop_Sar32;
913 IROp op_Sub = Iop_Sub32;
914 IROp op_Add = Iop_Add32;
915 IRExpr*(*mkU)(UInt) = mkU32;
916 vg_assert(VG_WORDSIZE == 4);
917# endif
918
919 vg_assert(sizeof(void*) == VG_WORDSIZE);
920 vg_assert(sizeof(Word) == VG_WORDSIZE);
921 vg_assert(sizeof(Addr) == VG_WORDSIZE);
922
sewardj0b9d74a2006-12-24 02:24:11 +0000923 descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
sewardj4a0009c2006-10-17 01:52:05 +0000924 t1 = newIRTemp( bb->tyenv, ty_Word );
925 one = mkU(1);
926
927 vg_assert(typeOfIRExpr(bb->tyenv, e) == ty_Word);
sewardj34593e52006-01-17 01:57:33 +0000928
929 /* t1 = guest_REDIR_SP + 1 */
sewardj0b9d74a2006-12-24 02:24:11 +0000930 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000931 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000932 IRStmt_WrTmp(
sewardj34593e52006-01-17 01:57:33 +0000933 t1,
sewardj4a0009c2006-10-17 01:52:05 +0000934 IRExpr_Binop(op_Add, IRExpr_Get( offB_REDIR_SP, ty_Word ), one)
sewardj34593e52006-01-17 01:57:33 +0000935 )
936 );
937
sewardjd68ac3e2006-01-20 14:31:57 +0000938 /* Bomb out if t1 >=s stack_size, that is, (stack_size-1)-t1 <s 0.
939 The destination (0) is a bit bogus but it doesn't matter since
940 this is an unrecoverable error and will lead to Valgrind
941 shutting down. _EMWARN is set regardless - that's harmless
942 since is only has a meaning if the exit is taken. */
sewardj0b9d74a2006-12-24 02:24:11 +0000943 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000944 bb,
945 IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_overflow))
946 );
sewardj0b9d74a2006-12-24 02:24:11 +0000947 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000948 bb,
949 IRStmt_Exit(
950 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000951 op_CmpNE,
sewardjd68ac3e2006-01-20 14:31:57 +0000952 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000953 op_Sar,
sewardj0b9d74a2006-12-24 02:24:11 +0000954 IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_RdTmp(t1)),
sewardj4a0009c2006-10-17 01:52:05 +0000955 mkU8(8 * VG_WORDSIZE - 1)
sewardjd68ac3e2006-01-20 14:31:57 +0000956 ),
sewardj4a0009c2006-10-17 01:52:05 +0000957 mkU(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000958 ),
959 Ijk_EmFail,
sewardj4a0009c2006-10-17 01:52:05 +0000960 is64 ? IRConst_U64(0) : IRConst_U32(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000961 )
962 );
sewardj34593e52006-01-17 01:57:33 +0000963
964 /* guest_REDIR_SP = t1 */
sewardj0b9d74a2006-12-24 02:24:11 +0000965 addStmtToIRSB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_RdTmp(t1)));
sewardj34593e52006-01-17 01:57:33 +0000966
967 /* guest_REDIR_STACK[t1+0] = e */
sewardj4a0009c2006-10-17 01:52:05 +0000968 /* PutI/GetI have I32-typed indexes regardless of guest word size */
sewardj0b9d74a2006-12-24 02:24:11 +0000969 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000970 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000971 IRStmt_PutI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0, e)
sewardj34593e52006-01-17 01:57:33 +0000972 );
973}
974
sewardj4a0009c2006-10-17 01:52:05 +0000975
976/* Generate code to pop a word-sized value from this thread's redir
977 stack, binding it to a new temporary, which is returned. As with
978 gen_PUSH, an overflow check is also performed. */
979
sewardj0b9d74a2006-12-24 02:24:11 +0000980static IRTemp gen_POP ( IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +0000981{
sewardj4a0009c2006-10-17 01:52:05 +0000982# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
983 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
984 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
985 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
986 Int offB_EMWARN = offsetof(VexGuestPPC64State,guest_EMWARN);
987 Bool is64 = True;
988 IRType ty_Word = Ity_I64;
989 IROp op_CmpNE = Iop_CmpNE64;
990 IROp op_Sar = Iop_Sar64;
991 IROp op_Sub = Iop_Sub64;
992 IRExpr*(*mkU)(ULong) = mkU64;
993# else
994 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
995 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
996 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
997 Int offB_EMWARN = offsetof(VexGuestPPC32State,guest_EMWARN);
998 Bool is64 = False;
999 IRType ty_Word = Ity_I32;
1000 IROp op_CmpNE = Iop_CmpNE32;
1001 IROp op_Sar = Iop_Sar32;
1002 IROp op_Sub = Iop_Sub32;
1003 IRExpr*(*mkU)(UInt) = mkU32;
1004# endif
sewardj34593e52006-01-17 01:57:33 +00001005
sewardj0b9d74a2006-12-24 02:24:11 +00001006 IRRegArray* descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
1007 IRTemp t1 = newIRTemp( bb->tyenv, ty_Word );
1008 IRTemp res = newIRTemp( bb->tyenv, ty_Word );
1009 IRExpr* one = mkU(1);
sewardj4a0009c2006-10-17 01:52:05 +00001010
1011 vg_assert(sizeof(void*) == VG_WORDSIZE);
1012 vg_assert(sizeof(Word) == VG_WORDSIZE);
1013 vg_assert(sizeof(Addr) == VG_WORDSIZE);
sewardj34593e52006-01-17 01:57:33 +00001014
1015 /* t1 = guest_REDIR_SP */
sewardj0b9d74a2006-12-24 02:24:11 +00001016 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001017 bb,
sewardj0b9d74a2006-12-24 02:24:11 +00001018 IRStmt_WrTmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) )
sewardj34593e52006-01-17 01:57:33 +00001019 );
1020
sewardjd68ac3e2006-01-20 14:31:57 +00001021 /* Bomb out if t1 < 0. Same comments as gen_PUSH apply. */
sewardj0b9d74a2006-12-24 02:24:11 +00001022 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001023 bb,
1024 IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_underflow))
1025 );
sewardj0b9d74a2006-12-24 02:24:11 +00001026 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001027 bb,
1028 IRStmt_Exit(
1029 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +00001030 op_CmpNE,
sewardjd68ac3e2006-01-20 14:31:57 +00001031 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +00001032 op_Sar,
sewardj0b9d74a2006-12-24 02:24:11 +00001033 IRExpr_RdTmp(t1),
sewardj4a0009c2006-10-17 01:52:05 +00001034 mkU8(8 * VG_WORDSIZE - 1)
sewardjd68ac3e2006-01-20 14:31:57 +00001035 ),
sewardj4a0009c2006-10-17 01:52:05 +00001036 mkU(0)
sewardjd68ac3e2006-01-20 14:31:57 +00001037 ),
1038 Ijk_EmFail,
sewardj4a0009c2006-10-17 01:52:05 +00001039 is64 ? IRConst_U64(0) : IRConst_U32(0)
sewardjd68ac3e2006-01-20 14:31:57 +00001040 )
1041 );
sewardj34593e52006-01-17 01:57:33 +00001042
1043 /* res = guest_REDIR_STACK[t1+0] */
sewardj4a0009c2006-10-17 01:52:05 +00001044 /* PutI/GetI have I32-typed indexes regardless of guest word size */
sewardj0b9d74a2006-12-24 02:24:11 +00001045 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001046 bb,
sewardj0b9d74a2006-12-24 02:24:11 +00001047 IRStmt_WrTmp(
sewardj34593e52006-01-17 01:57:33 +00001048 res,
sewardj0b9d74a2006-12-24 02:24:11 +00001049 IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0)
sewardj34593e52006-01-17 01:57:33 +00001050 )
1051 );
1052
1053 /* guest_REDIR_SP = t1-1 */
sewardj0b9d74a2006-12-24 02:24:11 +00001054 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001055 bb,
sewardj0b9d74a2006-12-24 02:24:11 +00001056 IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(op_Sub, IRExpr_RdTmp(t1), one))
sewardj34593e52006-01-17 01:57:33 +00001057 );
1058
1059 return res;
1060}
1061
sewardj4a0009c2006-10-17 01:52:05 +00001062/* Generate code to push LR and R2 onto this thread's redir stack,
1063 then set R2 to the new value (which is the TOC pointer to be used
1064 for the duration of the replacement function, as determined by
1065 m_debuginfo), and set LR to the magic return stub, so we get to
1066 intercept the return and restore R2 and L2 to the values saved
1067 here. */
1068
sewardj0b9d74a2006-12-24 02:24:11 +00001069static void gen_push_and_set_LR_R2 ( IRSB* bb, Addr64 new_R2_value )
sewardj34593e52006-01-17 01:57:33 +00001070{
sewardj4a0009c2006-10-17 01:52:05 +00001071# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
1072 Addr64 bogus_RA = (Addr64)&VG_(ppctoc_magic_redirect_return_stub);
1073 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1074 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
sewardj34593e52006-01-17 01:57:33 +00001075 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) );
1076 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
sewardj0b9d74a2006-12-24 02:24:11 +00001077 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) );
1078 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) );
sewardj4a0009c2006-10-17 01:52:05 +00001079
1080# elif defined(VGP_ppc32_aix5)
1081 Addr32 bogus_RA = (Addr32)&VG_(ppctoc_magic_redirect_return_stub);
1082 Int offB_GPR2 = offsetof(VexGuestPPC32State,guest_GPR2);
1083 Int offB_LR = offsetof(VexGuestPPC32State,guest_LR);
1084 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I32) );
1085 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I32) );
sewardj0b9d74a2006-12-24 02:24:11 +00001086 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU32( bogus_RA )) );
1087 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU32( new_R2_value )) );
sewardj4a0009c2006-10-17 01:52:05 +00001088
1089# else
1090# error Platform is not TOC-afflicted, fortunately
1091# endif
sewardj34593e52006-01-17 01:57:33 +00001092}
1093
sewardj0b9d74a2006-12-24 02:24:11 +00001094static void gen_pop_R2_LR_then_bLR ( IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001095{
sewardj4a0009c2006-10-17 01:52:05 +00001096# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
1097 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1098 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
1099 IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I64 );
1100 IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I64 );
sewardj34593e52006-01-17 01:57:33 +00001101 /* Restore R2 */
1102 old_R2 = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001103 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
sewardj34593e52006-01-17 01:57:33 +00001104 /* Restore LR */
1105 old_LR = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001106 addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
sewardj34593e52006-01-17 01:57:33 +00001107 /* Branch to LR */
1108 /* re boring, we arrived here precisely because a wrapped fn did a
1109 blr (hence Ijk_Ret); so we should just mark this jump as Boring,
sewardj4a0009c2006-10-17 01:52:05 +00001110 else one _Call will have resulted in two _Rets. */
sewardj34593e52006-01-17 01:57:33 +00001111 bb->jumpkind = Ijk_Boring;
sewardj0b9d74a2006-12-24 02:24:11 +00001112 bb->next = IRExpr_Binop(Iop_And64, IRExpr_RdTmp(old_LR), mkU64(~(3ULL)));
sewardj4a0009c2006-10-17 01:52:05 +00001113
1114# elif defined(VGP_ppc32_aix5)
1115 Int offB_GPR2 = offsetof(VexGuestPPC32State,guest_GPR2);
1116 Int offB_LR = offsetof(VexGuestPPC32State,guest_LR);
1117 IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I32 );
1118 IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I32 );
1119 /* Restore R2 */
1120 old_R2 = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001121 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
sewardj4a0009c2006-10-17 01:52:05 +00001122 /* Restore LR */
1123 old_LR = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001124 addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
sewardj4a0009c2006-10-17 01:52:05 +00001125
1126 /* Branch to LR */
1127 /* re boring, we arrived here precisely because a wrapped fn did a
1128 blr (hence Ijk_Ret); so we should just mark this jump as Boring,
1129 else one _Call will have resulted in two _Rets. */
1130 bb->jumpkind = Ijk_Boring;
sewardj0b9d74a2006-12-24 02:24:11 +00001131 bb->next = IRExpr_Binop(Iop_And32, IRExpr_RdTmp(old_LR), mkU32(~3));
sewardj4a0009c2006-10-17 01:52:05 +00001132
1133# else
1134# error Platform is not TOC-afflicted, fortunately
1135# endif
sewardj34593e52006-01-17 01:57:33 +00001136}
1137
1138static
sewardj0b9d74a2006-12-24 02:24:11 +00001139Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001140{
sewardj0283bae2006-01-22 01:15:36 +00001141 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj0b9d74a2006-12-24 02:24:11 +00001142 /* Since we're creating the entire IRSB right here, give it a
sewardj0283bae2006-01-22 01:15:36 +00001143 proper IMark, as it won't get one any other way, and cachegrind
1144 will barf if it doesn't have one (fair enough really). */
sewardj80e88b02011-05-28 15:34:17 +00001145 addStmtToIRSB( bb, IRStmt_IMark( closure->readdr, 4, 0 ) );
sewardj0283bae2006-01-22 01:15:36 +00001146 /* Generate the magic sequence:
1147 pop R2 from hidden stack
1148 pop LR from hidden stack
1149 goto LR
1150 */
sewardj34593e52006-01-17 01:57:33 +00001151 gen_pop_R2_LR_then_bLR(bb);
1152 return True; /* True == this is the entire BB; don't disassemble any
1153 real insns into it - just hand it directly to
1154 optimiser/instrumenter/backend. */
1155}
1156#endif
1157
sewardj4a0009c2006-10-17 01:52:05 +00001158/* --------------- END helpers for with-TOC platforms --------------- */
sewardj34593e52006-01-17 01:57:33 +00001159
sewardj4a0009c2006-10-17 01:52:05 +00001160
1161/* This is the IR preamble generator used for replacement
sewardj0283bae2006-01-22 01:15:36 +00001162 functions. It adds code to set the guest_NRADDR{_GPR2} to zero
sewardj34593e52006-01-17 01:57:33 +00001163 (technically not necessary, but facilitates detecting mixups in
sewardj0283bae2006-01-22 01:15:36 +00001164 which a replacement function has been erroneously declared using
1165 VG_REPLACE_FUNCTION_Z{U,Z} when instead it should have been written
1166 using VG_WRAP_FUNCTION_Z{U,Z}).
sewardj34593e52006-01-17 01:57:33 +00001167
sewardj4a0009c2006-10-17 01:52:05 +00001168 On with-TOC platforms the follow hacks are also done: LR and R2 are
1169 pushed onto a hidden stack, R2 is set to the correct value for the
1170 replacement function, and LR is set to point at the magic
1171 return-stub address. Setting LR causes the return of the
1172 wrapped/redirected function to lead to our magic return stub, which
1173 restores LR and R2 from said stack and returns for real.
sewardjdfbaa222006-01-18 04:25:20 +00001174
sewardjb8b79ad2008-03-03 01:35:41 +00001175 VG_(get_StackTrace_wrk) understands that the LR value may point to
1176 the return stub address, and that in that case it can get the real
1177 LR value from the hidden stack instead. */
sewardj34593e52006-01-17 01:57:33 +00001178static
sewardj0b9d74a2006-12-24 02:24:11 +00001179Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001180{
sewardj34593e52006-01-17 01:57:33 +00001181 Int nraddr_szB
1182 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1183 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
sewardj4a0009c2006-10-17 01:52:05 +00001184 vg_assert(nraddr_szB == VG_WORDSIZE);
sewardj0b9d74a2006-12-24 02:24:11 +00001185 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001186 bb,
1187 IRStmt_Put(
1188 offsetof(VexGuestArchState,guest_NRADDR),
sewardj0283bae2006-01-22 01:15:36 +00001189 nraddr_szB == 8 ? mkU64(0) : mkU32(0)
sewardj34593e52006-01-17 01:57:33 +00001190 )
1191 );
sewardj4a0009c2006-10-17 01:52:05 +00001192# if defined(VG_PLAT_USES_PPCTOC)
sewardj0283bae2006-01-22 01:15:36 +00001193 { VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj0b9d74a2006-12-24 02:24:11 +00001194 addStmtToIRSB(
sewardj0283bae2006-01-22 01:15:36 +00001195 bb,
1196 IRStmt_Put(
1197 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
sewardj4a0009c2006-10-17 01:52:05 +00001198 VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
sewardj0283bae2006-01-22 01:15:36 +00001199 )
1200 );
1201 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1202 }
sewardj34593e52006-01-17 01:57:33 +00001203# endif
1204 return False;
1205}
1206
1207/* Ditto, except set guest_NRADDR to nraddr (the un-redirected guest
1208 address). This is needed for function wrapping - so the wrapper
1209 can read _NRADDR and find the address of the function being
sewardj4a0009c2006-10-17 01:52:05 +00001210 wrapped. On toc-afflicted platforms we must also snarf r2. */
sewardj34593e52006-01-17 01:57:33 +00001211static
sewardj0b9d74a2006-12-24 02:24:11 +00001212Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001213{
1214 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1215 Int nraddr_szB
1216 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1217 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
sewardj4a0009c2006-10-17 01:52:05 +00001218 vg_assert(nraddr_szB == VG_WORDSIZE);
sewardj0b9d74a2006-12-24 02:24:11 +00001219 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001220 bb,
1221 IRStmt_Put(
1222 offsetof(VexGuestArchState,guest_NRADDR),
1223 nraddr_szB == 8
1224 ? IRExpr_Const(IRConst_U64( closure->nraddr ))
1225 : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
1226 )
1227 );
sewardj4a0009c2006-10-17 01:52:05 +00001228# if defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
1229 || defined(VGP_ppc64_aix5)
sewardj0b9d74a2006-12-24 02:24:11 +00001230 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001231 bb,
1232 IRStmt_Put(
1233 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1234 IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2),
sewardj4a0009c2006-10-17 01:52:05 +00001235 VG_WORDSIZE==8 ? Ity_I64 : Ity_I32)
sewardjd68ac3e2006-01-20 14:31:57 +00001236 )
1237 );
sewardj34593e52006-01-17 01:57:33 +00001238 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1239# endif
1240 return False;
1241}
1242
sewardj4a0009c2006-10-17 01:52:05 +00001243/* --- Helpers to do with PPC related stack redzones. --- */
1244
1245__attribute__((unused))
1246static Bool const_True ( Addr64 guest_addr )
1247{
1248 return True;
1249}
1250
1251__attribute__((unused))
1252static Bool bl_RZ_zap_ok_for_AIX ( Addr64 bl_target )
1253{
1254 /* paranoia */
1255 if (sizeof(void*) == 4)
1256 bl_target &= 0xFFFFFFFFULL;
1257
1258 /* don't zap the redzone for calls to millicode. */
1259 if (bl_target < 0x10000ULL)
1260 return False;
1261
1262 /* don't zap the redzone for calls to .$SAVEF14 .. .$SAVEF31.
1263 First we need to be reasonably sure we won't segfault by looking
1264 at the branch target. */
1265 { NSegment const*const seg = VG_(am_find_nsegment)( (Addr)bl_target );
1266 if (seg && seg->hasR) {
1267 switch ( *(UInt*)(Addr)bl_target ) {
1268 case 0xd9c1ff70: /* stfd f14,-144(r1) */
1269 case 0xd9e1ff78: /* stfd f15,-136(r1) */
1270 case 0xda01ff80: /* stfd f16,-128(r1) */
1271 case 0xda21ff88: /* stfd f17,-120(r1) */
1272 case 0xda41ff90: /* stfd f18,-112(r1) */
1273 case 0xda61ff98: /* stfd f19,-104(r1) */
1274 case 0xda81ffa0: /* stfd f20,-96(r1) */
1275 case 0xdaa1ffa8: /* stfd f21,-88(r1) */
1276 case 0xdac1ffb0: /* stfd f22,-80(r1) */
1277 case 0xdae1ffb8: /* stfd f23,-72(r1) */
1278 case 0xdb01ffc0: /* stfd f24,-64(r1) */
1279 case 0xdb21ffc8: /* stfd f25,-56(r1) */
1280 case 0xdb41ffd0: /* stfd f26,-48(r1) */
1281 case 0xdb61ffd8: /* stfd f27,-40(r1) */
1282 case 0xdb81ffe0: /* stfd f28,-32(r1) */
1283 case 0xdba1ffe8: /* stfd f29,-24(r1) */
1284 case 0xdbc1fff0: /* stfd f30,-16(r1) */
1285 case 0xdbe1fff8: /* stfd f31,-8(r1) */
1286 return False;
1287 }
1288 }
1289 }
1290 return True;
1291}
sewardj34593e52006-01-17 01:57:33 +00001292
1293/* --------------- main translation function --------------- */
1294
sewardj0ec07f32006-01-12 12:32:32 +00001295/* Note: see comments at top of m_redir.c for the Big Picture on how
1296 redirections are managed. */
1297
sewardj34593e52006-01-17 01:57:33 +00001298typedef
1299 enum {
1300 /* normal translation, redir neither requested nor inhibited */
1301 T_Normal,
1302 /* redir translation, function-wrap (set _NRADDR) style */
1303 T_Redir_Wrap,
1304 /* redir translation, replacement (don't set _NRADDR) style */
1305 T_Redir_Replace,
1306 /* a translation in which redir is specifically disallowed */
1307 T_NoRedir
1308 }
1309 T_Kind;
1310
1311/* Translate the basic block beginning at NRADDR, and add it to the
1312 translation cache & translation table. Unless
1313 DEBUGGING_TRANSLATION is true, in which case the call is being done
1314 for debugging purposes, so (a) throw away the translation once it
1315 is made, and (b) produce a load of debugging output. If
1316 ALLOW_REDIRECTION is False, do not attempt redirection of NRADDR,
1317 and also, put the resulting translation into the no-redirect tt/tc
1318 instead of the normal one.
1319
1320 TID is the identity of the thread requesting this translation.
1321*/
1322
sewardjfa8ec112005-01-19 11:55:34 +00001323Bool VG_(translate) ( ThreadId tid,
sewardj34593e52006-01-17 01:57:33 +00001324 Addr64 nraddr,
sewardjfa8ec112005-01-19 11:55:34 +00001325 Bool debugging_translation,
njn394213a2005-06-19 18:38:24 +00001326 Int debugging_verbosity,
sewardj0ec07f32006-01-12 12:32:32 +00001327 ULong bbs_done,
1328 Bool allow_redirection )
sewardjde4a1d02002-03-22 01:27:54 +00001329{
sewardj34593e52006-01-17 01:57:33 +00001330 Addr64 addr;
1331 T_Kind kind;
sewardje2d1e672005-11-12 23:10:48 +00001332 Int tmpbuf_used, verbosity, i;
sewardj0b9d74a2006-12-24 02:24:11 +00001333 Bool (*preamble_fn)(void*,IRSB*);
sewardje2d1e672005-11-12 23:10:48 +00001334 VexArch vex_arch;
1335 VexArchInfo vex_archinfo;
sewardj0b9d74a2006-12-24 02:24:11 +00001336 VexAbiInfo vex_abiinfo;
sewardje2d1e672005-11-12 23:10:48 +00001337 VexGuestExtents vge;
sewardj274807d2005-12-15 14:07:07 +00001338 VexTranslateArgs vta;
sewardje2d1e672005-11-12 23:10:48 +00001339 VexTranslateResult tres;
sewardj34593e52006-01-17 01:57:33 +00001340 VgCallbackClosure closure;
njn36932cb2005-05-11 22:45:48 +00001341
sewardj8b635a42004-11-22 19:01:47 +00001342 /* Make sure Vex is initialised right. */
sewardje2d1e672005-11-12 23:10:48 +00001343
sewardj8b635a42004-11-22 19:01:47 +00001344 static Bool vex_init_done = False;
1345
1346 if (!vex_init_done) {
1347 LibVEX_Init ( &failure_exit, &log_bytes,
1348 1, /* debug_paranoia */
1349 False, /* valgrind support */
1350 &VG_(clo_vex_control) );
1351 vex_init_done = True;
1352 }
1353
sewardj34593e52006-01-17 01:57:33 +00001354 /* Establish the translation kind and actual guest address to
1355 start from. Sets (addr,kind). */
sewardj0ec07f32006-01-12 12:32:32 +00001356 if (allow_redirection) {
sewardj34593e52006-01-17 01:57:33 +00001357 Bool isWrap;
1358 Addr64 tmp = VG_(redir_do_lookup)( nraddr, &isWrap );
1359 if (tmp == nraddr) {
1360 /* no redirection found */
1361 addr = nraddr;
1362 kind = T_Normal;
1363 } else {
1364 /* found a redirect */
1365 addr = tmp;
1366 kind = isWrap ? T_Redir_Wrap : T_Redir_Replace;
1367 }
sewardj0ec07f32006-01-12 12:32:32 +00001368 } else {
sewardj34593e52006-01-17 01:57:33 +00001369 addr = nraddr;
1370 kind = T_NoRedir;
sewardj0ec07f32006-01-12 12:32:32 +00001371 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001372
sewardj34593e52006-01-17 01:57:33 +00001373 /* Established: (nraddr, addr, kind) */
sewardj0ec07f32006-01-12 12:32:32 +00001374
sewardj34593e52006-01-17 01:57:33 +00001375 /* Printing redirection info. */
1376
1377 if ((kind == T_Redir_Wrap || kind == T_Redir_Replace)
sewardj0ec07f32006-01-12 12:32:32 +00001378 && (VG_(clo_verbosity) >= 2 || VG_(clo_trace_redir))) {
sewardjfa8ec112005-01-19 11:55:34 +00001379 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +00001380 Char name1[64] = "";
1381 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +00001382 name1[0] = name2[0] = 0;
sewardj34593e52006-01-17 01:57:33 +00001383 ok = VG_(get_fnname_w_offset)(nraddr, name1, 64);
njnbe73f432005-03-26 21:34:45 +00001384 if (!ok) VG_(strcpy)(name1, "???");
sewardj34593e52006-01-17 01:57:33 +00001385 ok = VG_(get_fnname_w_offset)(addr, name2, 64);
njnbe73f432005-03-26 21:34:45 +00001386 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +00001387 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +00001388 "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)\n",
sewardj34593e52006-01-17 01:57:33 +00001389 nraddr, name1,
1390 addr, name2 );
nethercote59a122d2004-08-03 17:16:51 +00001391 }
sewardj25c7c3a2003-07-10 00:17:58 +00001392
njn25e49d8e72002-09-23 09:36:25 +00001393 if (!debugging_translation)
sewardj45f4e7c2005-09-27 19:20:21 +00001394 VG_TRACK( pre_mem_read, Vg_CoreTranslate,
sewardj34593e52006-01-17 01:57:33 +00001395 tid, "(translator)", addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +00001396
sewardj85ac6d42005-02-23 11:36:56 +00001397 /* If doing any code printing, print a basic block start marker */
1398 if (VG_(clo_trace_flags) || debugging_translation) {
1399 Char fnname[64] = "";
sewardj34593e52006-01-17 01:57:33 +00001400 VG_(get_fnname_w_offset)(addr, fnname, 64);
sewardj85ac6d42005-02-23 11:36:56 +00001401 VG_(printf)(
sewardje7d46072010-03-03 22:55:42 +00001402 "==== SB %d [tid %d] %s(0x%llx) SBs exec'd %lld ====\n",
1403 VG_(get_bbs_translated)(), (Int)tid, fnname, addr,
njn394213a2005-06-19 18:38:24 +00001404 bbs_done);
sewardj85ac6d42005-02-23 11:36:56 +00001405 }
1406
sewardj45f4e7c2005-09-27 19:20:21 +00001407 /* Are we allowed to translate here? */
1408
sewardj4a0009c2006-10-17 01:52:05 +00001409 { /* BEGIN new scope specially for 'seg' */
1410 NSegment const* seg = VG_(am_find_nsegment)(addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001411
sewardj5f76de02007-02-11 05:08:06 +00001412 if ( (!translations_allowable_from_seg(seg))
1413 || addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
sewardj4a0009c2006-10-17 01:52:05 +00001414 if (VG_(clo_trace_signals))
sewardja5940262007-09-10 16:28:38 +00001415 VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%llx)"
sewardj738856f2009-07-15 14:48:32 +00001416 " - throwing SEGV\n", addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001417 /* U R busted, sonny. Place your hands on your head and step
1418 away from the orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001419 /* Code address is bad - deliver a signal instead */
sewardj45f4e7c2005-09-27 19:20:21 +00001420 if (seg != NULL) {
1421 /* There's some kind of segment at the requested place, but we
1422 aren't allowed to execute code here. */
sewardj3b290482011-05-06 21:02:55 +00001423 if (debugging_translation)
1424 VG_(printf)("translations not allowed here (segment not executable)"
1425 "(0x%llx)\n", addr);
1426 else
1427 VG_(synth_fault_perms)(tid, addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001428 } else {
1429 /* There is no segment at all; we are attempting to execute in
1430 the middle of nowhere. */
sewardj3b290482011-05-06 21:02:55 +00001431 if (debugging_translation)
1432 VG_(printf)("translations not allowed here (no segment)"
1433 "(0x%llx)\n", addr);
1434 else
1435 VG_(synth_fault_mapping)(tid, addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001436 }
nethercote4d714382004-10-13 09:47:24 +00001437 return False;
sewardj45f4e7c2005-09-27 19:20:21 +00001438 }
sewardjde4a1d02002-03-22 01:27:54 +00001439
njn25e49d8e72002-09-23 09:36:25 +00001440 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +00001441 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +00001442 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +00001443 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +00001444 }
1445 else
sewardjfa8ec112005-01-19 11:55:34 +00001446 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +00001447 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +00001448 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +00001449 }
njn25e49d8e72002-09-23 09:36:25 +00001450
sewardj34593e52006-01-17 01:57:33 +00001451 /* Figure out which preamble-mangling callback to send. */
1452 preamble_fn = NULL;
1453 if (kind == T_Redir_Replace)
1454 preamble_fn = mk_preamble__set_NRADDR_to_zero;
1455 else
1456 if (kind == T_Redir_Wrap)
1457 preamble_fn = mk_preamble__set_NRADDR_to_nraddr;
sewardj4a0009c2006-10-17 01:52:05 +00001458
1459# if defined(VG_PLAT_USES_PPCTOC)
1460 if (ULong_to_Ptr(nraddr)
1461 == (void*)&VG_(ppctoc_magic_redirect_return_stub)) {
sewardj34593e52006-01-17 01:57:33 +00001462 /* If entering the special return stub, this means a wrapped or
1463 redirected function is returning. Make this translation one
1464 which restores R2 and LR from the thread's hidden redir
1465 stack, and branch to the (restored) link register, thereby
1466 really causing the function to return. */
1467 vg_assert(kind == T_Normal);
1468 vg_assert(nraddr == addr);
sewardj4a0009c2006-10-17 01:52:05 +00001469 preamble_fn = mk_preamble__ppctoc_magic_return_stub;
1470 }
sewardj34593e52006-01-17 01:57:33 +00001471# endif
1472
sewardje2d1e672005-11-12 23:10:48 +00001473 /* ------ Actually do the translation. ------ */
njn51d827b2005-05-09 01:02:08 +00001474 tl_assert2(VG_(tdict).tool_instrument,
1475 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj7be55092005-08-01 23:25:55 +00001476
sewardje2d1e672005-11-12 23:10:48 +00001477 /* Get the CPU info established at startup. */
1478 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1479
sewardj0b9d74a2006-12-24 02:24:11 +00001480 /* Set up 'abiinfo' structure with stuff Vex needs to know about
sewardj4a0009c2006-10-17 01:52:05 +00001481 the guest and host ABIs. */
1482
sewardj0b9d74a2006-12-24 02:24:11 +00001483 LibVEX_default_VexAbiInfo( &vex_abiinfo );
1484 vex_abiinfo.guest_stack_redzone_size = VG_STACK_REDZONE_SZB;
sewardj4a0009c2006-10-17 01:52:05 +00001485
sewardjc0b20392008-12-04 00:07:30 +00001486# if defined(VGP_amd64_linux)
1487 vex_abiinfo.guest_amd64_assume_fs_is_zero = True;
1488# endif
njnf76d27a2009-05-28 01:53:07 +00001489# if defined(VGP_amd64_darwin)
1490 vex_abiinfo.guest_amd64_assume_gs_is_0x60 = True;
1491# endif
sewardj4a0009c2006-10-17 01:52:05 +00001492# if defined(VGP_ppc32_linux)
sewardj0b9d74a2006-12-24 02:24:11 +00001493 vex_abiinfo.guest_ppc_zap_RZ_at_blr = False;
1494 vex_abiinfo.guest_ppc_zap_RZ_at_bl = NULL;
1495 vex_abiinfo.host_ppc32_regalign_int64_args = True;
sewardj4a0009c2006-10-17 01:52:05 +00001496# endif
1497# if defined(VGP_ppc64_linux)
sewardj0b9d74a2006-12-24 02:24:11 +00001498 vex_abiinfo.guest_ppc_zap_RZ_at_blr = True;
1499 vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True;
1500 vex_abiinfo.host_ppc_calls_use_fndescrs = True;
sewardj4a0009c2006-10-17 01:52:05 +00001501# endif
1502# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj0b9d74a2006-12-24 02:24:11 +00001503 vex_abiinfo.guest_ppc_zap_RZ_at_blr = False;
1504 vex_abiinfo.guest_ppc_zap_RZ_at_bl = bl_RZ_zap_ok_for_AIX;
1505 vex_abiinfo.guest_ppc_sc_continues_at_LR = True;
1506 vex_abiinfo.host_ppc_calls_use_fndescrs = True;
sewardj4a0009c2006-10-17 01:52:05 +00001507# endif
1508
sewardj34593e52006-01-17 01:57:33 +00001509 /* Set up closure args. */
1510 closure.tid = tid;
1511 closure.nraddr = nraddr;
1512 closure.readdr = addr;
sewardj7be55092005-08-01 23:25:55 +00001513
sewardj0ec07f32006-01-12 12:32:32 +00001514 /* Set up args for LibVEX_Translate. */
sewardj274807d2005-12-15 14:07:07 +00001515 vta.arch_guest = vex_arch;
1516 vta.archinfo_guest = vex_archinfo;
1517 vta.arch_host = vex_arch;
1518 vta.archinfo_host = vex_archinfo;
sewardj0b9d74a2006-12-24 02:24:11 +00001519 vta.abiinfo_both = vex_abiinfo;
sewardj34593e52006-01-17 01:57:33 +00001520 vta.guest_bytes = (UChar*)ULong_to_Ptr(addr);
1521 vta.guest_bytes_addr = (Addr64)addr;
1522 vta.callback_opaque = (void*)&closure;
sewardj274807d2005-12-15 14:07:07 +00001523 vta.chase_into_ok = chase_into_ok;
sewardj34593e52006-01-17 01:57:33 +00001524 vta.preamble_function = preamble_fn;
sewardj274807d2005-12-15 14:07:07 +00001525 vta.guest_extents = &vge;
1526 vta.host_bytes = tmpbuf;
1527 vta.host_bytes_size = N_TMPBUF;
1528 vta.host_bytes_used = &tmpbuf_used;
sewardj34593e52006-01-17 01:57:33 +00001529 { /* At this point we have to reconcile Vex's view of the
1530 instrumentation callback - which takes a void* first argument
1531 - with Valgrind's view, in which the first arg is a
1532 VgCallbackClosure*. Hence the following longwinded casts.
1533 They are entirely legal but longwinded so as to maximise the
1534 chance of the C typechecker picking up any type snafus. */
sewardj0b9d74a2006-12-24 02:24:11 +00001535 IRSB*(*f)(VgCallbackClosure*,
1536 IRSB*,VexGuestLayout*,VexGuestExtents*,
sewardj34593e52006-01-17 01:57:33 +00001537 IRType,IRType)
sewardj3b290482011-05-06 21:02:55 +00001538 = VG_(clo_vgdb) != Vg_VgdbNo
1539 ? tool_instrument_then_gdbserver_if_needed
1540 : VG_(tdict).tool_instrument;
sewardj0b9d74a2006-12-24 02:24:11 +00001541 IRSB*(*g)(void*,
1542 IRSB*,VexGuestLayout*,VexGuestExtents*,
sewardj34593e52006-01-17 01:57:33 +00001543 IRType,IRType)
sewardj0b9d74a2006-12-24 02:24:11 +00001544 = (IRSB*(*)(void*,IRSB*,VexGuestLayout*,VexGuestExtents*,IRType,IRType))f;
sewardj34593e52006-01-17 01:57:33 +00001545 vta.instrument1 = g;
1546 }
1547 /* No need for type kludgery here. */
sewardj274807d2005-12-15 14:07:07 +00001548 vta.instrument2 = need_to_handle_SP_assignment()
1549 ? vg_SP_update_pass
1550 : NULL;
sewardj81651dc2007-08-28 06:05:20 +00001551 vta.finaltidy = VG_(needs).final_IR_tidy_pass
1552 ? VG_(tdict).tool_final_IR_tidy_pass
1553 : NULL;
sewardj6dbcc632011-06-07 21:39:28 +00001554 vta.needs_self_check = needs_self_check;
sewardj274807d2005-12-15 14:07:07 +00001555 vta.traceflags = verbosity;
1556
1557 /* Set up the dispatch-return info. For archs without a link
1558 register, vex generates a jump back to the specified dispatch
1559 address. Else, it just generates a branch-to-LR. */
sewardj0ec07f32006-01-12 12:32:32 +00001560
sewardj12740272011-05-29 09:34:30 +00001561# if defined(VGA_x86) || defined(VGA_amd64)
1562 if (!allow_redirection) {
1563 /* It's a no-redir translation. Will be run with the
1564 nonstandard dispatcher VG_(run_a_noredir_translation) and so
1565 needs a nonstandard return point. */
1566 vta.dispatch_assisted
1567 = (void*) &VG_(run_a_noredir_translation__return_point);
1568 vta.dispatch_unassisted
1569 = vta.dispatch_assisted;
1570 }
1571 else
1572 if (VG_(clo_profile_flags) > 0) {
1573 /* normal translation; although we're profiling. */
1574 vta.dispatch_assisted
1575 = (void*) &VG_(run_innerloop__dispatch_assisted_profiled);
1576 vta.dispatch_unassisted
1577 = (void*) &VG_(run_innerloop__dispatch_unassisted_profiled);
1578 }
1579 else {
1580 /* normal translation and we're not profiling (the normal case) */
1581 vta.dispatch_assisted
1582 = (void*) &VG_(run_innerloop__dispatch_assisted_unprofiled);
1583 vta.dispatch_unassisted
1584 = (void*) &VG_(run_innerloop__dispatch_unassisted_unprofiled);
1585 }
1586
sewardj59570ff2010-01-01 11:59:33 +00001587# elif defined(VGA_ppc32) || defined(VGA_ppc64) \
sewardjb5b87402011-03-07 16:05:35 +00001588 || defined(VGA_arm) || defined(VGA_s390x)
sewardj52805ff2011-05-30 06:29:39 +00001589 /* See comment in libvex.h. This target uses a
1590 return-to-link-register scheme to get back to the dispatcher, so
1591 both fields are NULL. */
1592 vta.dispatch_assisted = NULL;
1593 vta.dispatch_unassisted = NULL;
sewardj12740272011-05-29 09:34:30 +00001594
sewardj274807d2005-12-15 14:07:07 +00001595# else
1596# error "Unknown arch"
1597# endif
1598
1599 /* Sheesh. Finally, actually _do_ the translation! */
1600 tres = LibVEX_Translate ( &vta );
njn25e49d8e72002-09-23 09:36:25 +00001601
sewardj6dbcc632011-06-07 21:39:28 +00001602 vg_assert(tres.status == VexTransOK);
1603 vg_assert(tres.n_sc_extents >= 0 && tres.n_sc_extents <= 3);
sewardj8b635a42004-11-22 19:01:47 +00001604 vg_assert(tmpbuf_used <= N_TMPBUF);
1605 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +00001606
sewardj45f4e7c2005-09-27 19:20:21 +00001607 /* Tell aspacem of all segments that have had translations taken
1608 from them. Optimisation: don't re-look up vge.base[0] since seg
1609 should already point to it. */
1610
sewardj34593e52006-01-17 01:57:33 +00001611 vg_assert( vge.base[0] == (Addr64)addr );
sewardj4a0009c2006-10-17 01:52:05 +00001612 /* set 'translations taken from this segment' flag */
1613 VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
1614 } /* END new scope specially for 'seg' */
sewardj45f4e7c2005-09-27 19:20:21 +00001615
1616 for (i = 1; i < vge.n_used; i++) {
sewardj4a0009c2006-10-17 01:52:05 +00001617 NSegment const* seg
1618 = VG_(am_find_nsegment)( vge.base[i] );
1619 /* set 'translations taken from this segment' flag */
1620 VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
sewardj45f4e7c2005-09-27 19:20:21 +00001621 }
1622
nethercote59a122d2004-08-03 17:16:51 +00001623 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +00001624 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +00001625
1626 // If debugging, don't do anything with the translated block; we
1627 // only did this for the debugging output produced along the way.
1628 if (!debugging_translation) {
sewardj0ec07f32006-01-12 12:32:32 +00001629
sewardj34593e52006-01-17 01:57:33 +00001630 if (kind != T_NoRedir) {
sewardj0ec07f32006-01-12 12:32:32 +00001631 // Put it into the normal TT/TC structures. This is the
1632 // normal case.
1633
sewardj34593e52006-01-17 01:57:33 +00001634 // Note that we use nraddr (the non-redirected address), not
1635 // addr, which might have been changed by the redirection
sewardj0ec07f32006-01-12 12:32:32 +00001636 VG_(add_to_transtab)( &vge,
sewardj34593e52006-01-17 01:57:33 +00001637 nraddr,
sewardj0ec07f32006-01-12 12:32:32 +00001638 (Addr)(&tmpbuf[0]),
1639 tmpbuf_used,
sewardj6dbcc632011-06-07 21:39:28 +00001640 tres.n_sc_extents > 0 );
sewardj0ec07f32006-01-12 12:32:32 +00001641 } else {
1642 VG_(add_to_unredir_transtab)( &vge,
sewardj34593e52006-01-17 01:57:33 +00001643 nraddr,
sewardj0ec07f32006-01-12 12:32:32 +00001644 (Addr)(&tmpbuf[0]),
njn1dcee092009-02-24 03:07:37 +00001645 tmpbuf_used );
sewardj0ec07f32006-01-12 12:32:32 +00001646 }
sewardjde4a1d02002-03-22 01:27:54 +00001647 }
nethercote59a122d2004-08-03 17:16:51 +00001648
nethercote4d714382004-10-13 09:47:24 +00001649 return True;
sewardjde4a1d02002-03-22 01:27:54 +00001650}
1651
1652/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +00001653/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001654/*--------------------------------------------------------------------*/