blob: 87b3cae29a785c99001e1da7ff5c2db4b7481d5c [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
sewardj34593e52006-01-17 01:57:33 +000056#include "pub_core_threadstate.h" // VexGuestArchState
sewardj4a0009c2006-10-17 01:52:05 +000057#include "pub_core_trampoline.h" // VG_(ppctoc_magic_redirect_return_stub)
sewardj34593e52006-01-17 01:57:33 +000058
sewardj7cf4e6b2008-05-01 20:24:26 +000059#include "pub_core_execontext.h" // VG_(make_depth_1_ExeContext_from_Addr)
60
sewardjde4a1d02002-03-22 01:27:54 +000061
njna1f783f2005-06-18 03:44:34 +000062/*------------------------------------------------------------*/
njn42c83552005-12-05 20:45:59 +000063/*--- Stats ---*/
64/*------------------------------------------------------------*/
65
66static UInt n_SP_updates_fast = 0;
67static UInt n_SP_updates_generic_known = 0;
68static UInt n_SP_updates_generic_unknown = 0;
69
70void VG_(print_translation_stats) ( void )
71{
72 Char buf[6];
73 UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
74 + n_SP_updates_generic_unknown;
75 VG_(percentify)(n_SP_updates_fast, n_SP_updates, 1, 6, buf);
76 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +000077 "translate: fast SP updates identified: %'u (%s)\n",
njn42c83552005-12-05 20:45:59 +000078 n_SP_updates_fast, buf );
79
80 VG_(percentify)(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf);
81 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +000082 "translate: generic_known SP updates identified: %'u (%s)\n",
njn42c83552005-12-05 20:45:59 +000083 n_SP_updates_generic_known, buf );
84
85 VG_(percentify)(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf);
86 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +000087 "translate: generic_unknown SP updates identified: %'u (%s)\n",
njn42c83552005-12-05 20:45:59 +000088 n_SP_updates_generic_unknown, buf );
89}
90
91/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +000092/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +000093/*------------------------------------------------------------*/
94
njna1f783f2005-06-18 03:44:34 +000095static Bool need_to_handle_SP_assignment(void)
96{
sewardjf5c8e372006-02-12 15:42:20 +000097 return ( VG_(tdict).track_new_mem_stack_4 ||
98 VG_(tdict).track_die_mem_stack_4 ||
99 VG_(tdict).track_new_mem_stack_8 ||
100 VG_(tdict).track_die_mem_stack_8 ||
101 VG_(tdict).track_new_mem_stack_12 ||
102 VG_(tdict).track_die_mem_stack_12 ||
103 VG_(tdict).track_new_mem_stack_16 ||
104 VG_(tdict).track_die_mem_stack_16 ||
105 VG_(tdict).track_new_mem_stack_32 ||
106 VG_(tdict).track_die_mem_stack_32 ||
107 VG_(tdict).track_new_mem_stack_112 ||
108 VG_(tdict).track_die_mem_stack_112 ||
109 VG_(tdict).track_new_mem_stack_128 ||
110 VG_(tdict).track_die_mem_stack_128 ||
111 VG_(tdict).track_new_mem_stack_144 ||
112 VG_(tdict).track_die_mem_stack_144 ||
113 VG_(tdict).track_new_mem_stack_160 ||
114 VG_(tdict).track_die_mem_stack_160 ||
115 VG_(tdict).track_new_mem_stack ||
116 VG_(tdict).track_die_mem_stack );
njna1f783f2005-06-18 03:44:34 +0000117}
118
njn5096a392005-12-13 20:05:00 +0000119// - The SP aliases are held in an array which is used as a circular buffer.
120// This misses very few constant updates of SP (ie. < 0.1%) while using a
121// small, constant structure that will also never fill up and cause
122// execution to abort.
123// - Unused slots have a .temp value of 'IRTemp_INVALID'.
124// - 'next_SP_alias_slot' is the index where the next alias will be stored.
125// - If the buffer fills, we circle around and start over-writing
126// non-IRTemp_INVALID values. This is rare, and the overwriting of a
127// value that would have subsequently be used is even rarer.
128// - Every slot below next_SP_alias_slot holds a non-IRTemp_INVALID value.
129// The rest either all won't (if we haven't yet circled around) or all
130// will (if we have circled around).
njn9b007f62003-04-07 14:40:25 +0000131
njn5096a392005-12-13 20:05:00 +0000132typedef
133 struct {
134 IRTemp temp;
135 Long delta;
136 }
137 SP_Alias;
138
139// With 32 slots the buffer fills very rarely -- eg. once in a run of GCC.
140// And I've tested with smaller values and the wrap-around case works ok.
141#define N_ALIASES 32
142static SP_Alias SP_aliases[N_ALIASES];
143static Int next_SP_alias_slot = 0;
144
145static void clear_SP_aliases(void)
146{
147 Int i;
148 for (i = 0; i < N_ALIASES; i++) {
149 SP_aliases[i].temp = IRTemp_INVALID;
150 SP_aliases[i].delta = 0;
151 }
152 next_SP_alias_slot = 0;
153}
154
155static void add_SP_alias(IRTemp temp, Long delta)
156{
157 vg_assert(temp != IRTemp_INVALID);
158 SP_aliases[ next_SP_alias_slot ].temp = temp;
159 SP_aliases[ next_SP_alias_slot ].delta = delta;
160 next_SP_alias_slot++;
161 if (N_ALIASES == next_SP_alias_slot) next_SP_alias_slot = 0;
162}
163
164static Bool get_SP_delta(IRTemp temp, ULong* delta)
165{
166 Int i; // i must be signed!
167 vg_assert(IRTemp_INVALID != temp);
168 // Search backwards between current buffer position and the start.
169 for (i = next_SP_alias_slot-1; i >= 0; i--) {
170 if (temp == SP_aliases[i].temp) {
171 *delta = SP_aliases[i].delta;
172 return True;
173 }
174 }
175 // Search backwards between the end and the current buffer position.
176 for (i = N_ALIASES-1; i >= next_SP_alias_slot; i--) {
177 if (temp == SP_aliases[i].temp) {
178 *delta = SP_aliases[i].delta;
179 return True;
180 }
181 }
182 return False;
183}
184
185static void update_SP_aliases(Long delta)
186{
187 Int i;
188 for (i = 0; i < N_ALIASES; i++) {
189 if (SP_aliases[i].temp == IRTemp_INVALID) {
190 return;
191 }
192 SP_aliases[i].delta += delta;
193 }
194}
195
sewardj7cf4e6b2008-05-01 20:24:26 +0000196/* Given a guest IP, get an origin tag for a 1-element stack trace,
197 and wrap it up in an IR atom that can be passed as the origin-tag
198 value for a stack-adjustment helper function. */
199static IRExpr* mk_ecu_Expr ( Addr64 guest_IP )
200{
201 UInt ecu;
202 ExeContext* ec
203 = VG_(make_depth_1_ExeContext_from_Addr)( (Addr)guest_IP );
204 vg_assert(ec);
205 ecu = VG_(get_ECU_from_ExeContext)( ec );
206 vg_assert(VG_(is_plausible_ECU)(ecu));
207 /* This is always safe to do, since ecu is only 32 bits, and
208 HWord is 32 or 64. */
209 return mkIRExpr_HWord( (HWord)ecu );
210}
211
njn5096a392005-12-13 20:05:00 +0000212
213/* For tools that want to know about SP changes, this pass adds
nethercote996901a2004-08-03 13:29:09 +0000214 in the appropriate hooks. We have to do it after the tool's
njn5096a392005-12-13 20:05:00 +0000215 instrumentation, so the tool doesn't have to worry about the C calls
njn9b007f62003-04-07 14:40:25 +0000216 it adds in, and we must do it before register allocation because
njn5096a392005-12-13 20:05:00 +0000217 spilled temps make it much harder to work out the SP deltas.
218 This it is done with Vex's "second instrumentation" pass.
sewardjde4a1d02002-03-22 01:27:54 +0000219
njn5096a392005-12-13 20:05:00 +0000220 Basically, we look for GET(SP)/PUT(SP) pairs and track constant
221 increments/decrements of SP between them. (This requires tracking one or
222 more "aliases", which are not exact aliases but instead are tempregs
223 whose value is equal to the SP's plus or minus a known constant.)
224 If all the changes to SP leading up to a PUT(SP) are by known, small
225 constants, we can do a specific call to eg. new_mem_stack_4, otherwise
226 we fall back to the case that handles an unknown SP change.
sewardj2831b512007-11-11 18:56:39 +0000227
228 There is some extra complexity to deal correctly with updates to
229 only parts of SP. Bizarre, but it has been known to happen.
njn5096a392005-12-13 20:05:00 +0000230*/
sewardjde4a1d02002-03-22 01:27:54 +0000231static
sewardj0b9d74a2006-12-24 02:24:11 +0000232IRSB* vg_SP_update_pass ( void* closureV,
233 IRSB* sb_in,
sewardj4ba057c2005-10-18 12:04:18 +0000234 VexGuestLayout* layout,
sewardj4ba057c2005-10-18 12:04:18 +0000235 VexGuestExtents* vge,
236 IRType gWordTy,
237 IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +0000238{
sewardj0b9d74a2006-12-24 02:24:11 +0000239 Int i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj2831b512007-11-11 18:56:39 +0000240 Int first_SP, last_SP, first_Put, last_Put;
sewardj0b9d74a2006-12-24 02:24:11 +0000241 IRDirty *dcall, *d;
242 IRStmt* st;
243 IRExpr* e;
244 IRRegArray* descr;
245 IRType typeof_SP;
246 Long delta, con;
sewardjde4a1d02002-03-22 01:27:54 +0000247
sewardj7cf4e6b2008-05-01 20:24:26 +0000248 /* Set up stuff for tracking the guest IP */
249 Bool curr_IP_known = False;
250 Addr64 curr_IP = 0;
251
sewardj8b635a42004-11-22 19:01:47 +0000252 /* Set up BB */
sewardj0b9d74a2006-12-24 02:24:11 +0000253 IRSB* bb = emptyIRSB();
254 bb->tyenv = deepCopyIRTypeEnv(sb_in->tyenv);
255 bb->next = deepCopyIRExpr(sb_in->next);
256 bb->jumpkind = sb_in->jumpkind;
sewardjde4a1d02002-03-22 01:27:54 +0000257
sewardj7cf97ee2004-11-28 14:25:01 +0000258 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000259
sewardj7cf97ee2004-11-28 14:25:01 +0000260 sizeof_SP = layout->sizeof_SP;
261 offset_SP = layout->offset_SP;
262 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +0000263 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +0000264
sewardj7cf4e6b2008-05-01 20:24:26 +0000265 /* --- Start of #defines --- */
266
sewardj8b635a42004-11-22 19:01:47 +0000267# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
268# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +0000269
sewardj8b635a42004-11-22 19:01:47 +0000270# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +0000271
sewardj8b635a42004-11-22 19:01:47 +0000272# define GET_CONST(con) \
273 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
274 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000275
sewardj7cf4e6b2008-05-01 20:24:26 +0000276# define DO_NEW(syze, tmpp) \
sewardj8b635a42004-11-22 19:01:47 +0000277 do { \
sewardj7cf4e6b2008-05-01 20:24:26 +0000278 Bool vanilla, w_ecu; \
279 vg_assert(curr_IP_known); \
280 vanilla = NULL != VG_(tdict).track_new_mem_stack_##syze; \
281 w_ecu = NULL != VG_(tdict).track_new_mem_stack_##syze##_w_ECU; \
282 vg_assert(!(vanilla && w_ecu)); /* can't have both */ \
283 if (!(vanilla || w_ecu)) \
284 goto generic; \
285 \
286 /* I don't know if it's really necessary to say that the */ \
287 /* call reads the stack pointer. But anyway, we do. */ \
288 if (w_ecu) { \
289 dcall = unsafeIRDirty_0_N( \
290 2/*regparms*/, \
291 "track_new_mem_stack_" #syze "_w_ECU", \
292 VG_(fnptr_to_fnentry)( \
293 VG_(tdict).track_new_mem_stack_##syze##_w_ECU ), \
294 mkIRExprVec_2(IRExpr_RdTmp(tmpp), \
295 mk_ecu_Expr(curr_IP)) \
296 ); \
297 } else { \
298 dcall = unsafeIRDirty_0_N( \
299 1/*regparms*/, \
300 "track_new_mem_stack_" #syze , \
301 VG_(fnptr_to_fnentry)( \
302 VG_(tdict).track_new_mem_stack_##syze ), \
303 mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \
304 ); \
305 } \
306 dcall->nFxState = 1; \
307 dcall->fxState[0].fx = Ifx_Read; \
308 dcall->fxState[0].offset = layout->offset_SP; \
309 dcall->fxState[0].size = layout->sizeof_SP; \
310 \
311 addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \
312 \
313 tl_assert(syze > 0); \
314 update_SP_aliases(syze); \
315 \
316 n_SP_updates_fast++; \
317 \
318 } while (0)
319
320# define DO_DIE(syze, tmpp) \
321 do { \
322 if (!VG_(tdict).track_die_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000323 goto generic; \
324 \
325 /* I don't know if it's really necessary to say that the */ \
326 /* call reads the stack pointer. But anyway, we do. */ \
327 dcall = unsafeIRDirty_0_N( \
328 1/*regparms*/, \
sewardj7cf4e6b2008-05-01 20:24:26 +0000329 "track_die_mem_stack_" #syze, \
sewardj53ee1fc2005-12-23 02:29:58 +0000330 VG_(fnptr_to_fnentry)( \
sewardj7cf4e6b2008-05-01 20:24:26 +0000331 VG_(tdict).track_die_mem_stack_##syze ), \
sewardj0b9d74a2006-12-24 02:24:11 +0000332 mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \
sewardj8b635a42004-11-22 19:01:47 +0000333 ); \
334 dcall->nFxState = 1; \
335 dcall->fxState[0].fx = Ifx_Read; \
336 dcall->fxState[0].offset = layout->offset_SP; \
337 dcall->fxState[0].size = layout->sizeof_SP; \
338 \
sewardj0b9d74a2006-12-24 02:24:11 +0000339 addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \
njn42c83552005-12-05 20:45:59 +0000340 \
sewardj7cf4e6b2008-05-01 20:24:26 +0000341 tl_assert(syze > 0); \
342 update_SP_aliases(-(syze)); \
njn5096a392005-12-13 20:05:00 +0000343 \
njn42c83552005-12-05 20:45:59 +0000344 n_SP_updates_fast++; \
345 \
sewardj8b635a42004-11-22 19:01:47 +0000346 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000347
sewardj7cf4e6b2008-05-01 20:24:26 +0000348 /* --- End of #defines --- */
349
njn5096a392005-12-13 20:05:00 +0000350 clear_SP_aliases();
351
sewardj0b9d74a2006-12-24 02:24:11 +0000352 for (i = 0; i < sb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000353
sewardj0b9d74a2006-12-24 02:24:11 +0000354 st = sb_in->stmts[i];
sewardjde4a1d02002-03-22 01:27:54 +0000355
sewardj7cf4e6b2008-05-01 20:24:26 +0000356 if (st->tag == Ist_IMark) {
357 curr_IP_known = True;
358 curr_IP = st->Ist.IMark.addr;
359 }
360
sewardj8b635a42004-11-22 19:01:47 +0000361 /* t = Get(sp): curr = t, delta = 0 */
sewardj0b9d74a2006-12-24 02:24:11 +0000362 if (st->tag != Ist_WrTmp) goto case2;
363 e = st->Ist.WrTmp.data;
sewardj8b635a42004-11-22 19:01:47 +0000364 if (e->tag != Iex_Get) goto case2;
365 if (e->Iex.Get.offset != offset_SP) goto case2;
366 if (e->Iex.Get.ty != typeof_SP) goto case2;
sewardj2831b512007-11-11 18:56:39 +0000367 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
sewardj0b9d74a2006-12-24 02:24:11 +0000368 add_SP_alias(st->Ist.WrTmp.tmp, 0);
369 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000370 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000371
sewardj8b635a42004-11-22 19:01:47 +0000372 case2:
373 /* t' = curr +/- const: curr = t', delta +=/-= const */
sewardj0b9d74a2006-12-24 02:24:11 +0000374 if (st->tag != Ist_WrTmp) goto case3;
375 e = st->Ist.WrTmp.data;
sewardj8b635a42004-11-22 19:01:47 +0000376 if (e->tag != Iex_Binop) goto case3;
sewardj0b9d74a2006-12-24 02:24:11 +0000377 if (e->Iex.Binop.arg1->tag != Iex_RdTmp) goto case3;
378 if (!get_SP_delta(e->Iex.Binop.arg1->Iex.RdTmp.tmp, &delta)) goto case3;
sewardj8b635a42004-11-22 19:01:47 +0000379 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
380 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
njn5096a392005-12-13 20:05:00 +0000381 con = GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
sewardj2831b512007-11-11 18:56:39 +0000382 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
njn5096a392005-12-13 20:05:00 +0000383 if (IS_ADD(e->Iex.Binop.op)) {
sewardj0b9d74a2006-12-24 02:24:11 +0000384 add_SP_alias(st->Ist.WrTmp.tmp, delta + con);
njn5096a392005-12-13 20:05:00 +0000385 } else {
sewardj0b9d74a2006-12-24 02:24:11 +0000386 add_SP_alias(st->Ist.WrTmp.tmp, delta - con);
njn5096a392005-12-13 20:05:00 +0000387 }
sewardj0b9d74a2006-12-24 02:24:11 +0000388 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000389 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000390
sewardj8b635a42004-11-22 19:01:47 +0000391 case3:
392 /* t' = curr: curr = t' */
sewardj0b9d74a2006-12-24 02:24:11 +0000393 if (st->tag != Ist_WrTmp) goto case4;
394 e = st->Ist.WrTmp.data;
395 if (e->tag != Iex_RdTmp) goto case4;
396 if (!get_SP_delta(e->Iex.RdTmp.tmp, &delta)) goto case4;
sewardj2831b512007-11-11 18:56:39 +0000397 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
sewardj0b9d74a2006-12-24 02:24:11 +0000398 add_SP_alias(st->Ist.WrTmp.tmp, delta);
399 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000400 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000401
sewardj8b635a42004-11-22 19:01:47 +0000402 case4:
403 /* Put(sp) = curr */
sewardj2831b512007-11-11 18:56:39 +0000404 /* More generally, we must correctly handle a Put which writes
405 any part of SP, not just the case where all of SP is
406 written. */
sewardj8b635a42004-11-22 19:01:47 +0000407 if (st->tag != Ist_Put) goto case5;
sewardj2831b512007-11-11 18:56:39 +0000408 first_SP = offset_SP;
409 last_SP = first_SP + sizeof_SP - 1;
410 first_Put = st->Ist.Put.offset;
411 last_Put = first_Put
412 + sizeofIRType( typeOfIRExpr( bb->tyenv, st->Ist.Put.data ))
413 - 1;
414 vg_assert(first_SP <= last_SP);
415 vg_assert(first_Put <= last_Put);
416
417 if (last_Put < first_SP || last_SP < first_Put)
418 goto case5; /* no overlap */
419
420 if (st->Ist.Put.data->tag == Iex_RdTmp
421 && get_SP_delta(st->Ist.Put.data->Iex.RdTmp.tmp, &delta)) {
sewardj0b9d74a2006-12-24 02:24:11 +0000422 IRTemp tttmp = st->Ist.Put.data->Iex.RdTmp.tmp;
sewardj2831b512007-11-11 18:56:39 +0000423 /* Why should the following assertion hold? Because any
424 alias added by put_SP_alias must be of a temporary which
425 has the same type as typeof_SP, and whose value is a Get
426 at exactly offset_SP of size typeof_SP. Each call to
427 put_SP_alias is immediately preceded by an assertion that
428 we are putting in a binding for a correctly-typed
429 temporary. */
430 vg_assert( typeOfIRTemp(bb->tyenv, tttmp) == typeof_SP );
431 /* From the same type-and-offset-correctness argument, if
432 we found a useable alias, it must for an "exact" write of SP. */
433 vg_assert(first_SP == first_Put);
434 vg_assert(last_SP == last_Put);
sewardj8b635a42004-11-22 19:01:47 +0000435 switch (delta) {
sewardj0b9d74a2006-12-24 02:24:11 +0000436 case 0: addStmtToIRSB(bb,st); continue;
sewardj7cf4e6b2008-05-01 20:24:26 +0000437 case 4: DO_DIE( 4, tttmp); addStmtToIRSB(bb,st); continue;
438 case -4: DO_NEW( 4, tttmp); addStmtToIRSB(bb,st); continue;
439 case 8: DO_DIE( 8, tttmp); addStmtToIRSB(bb,st); continue;
440 case -8: DO_NEW( 8, tttmp); addStmtToIRSB(bb,st); continue;
441 case 12: DO_DIE( 12, tttmp); addStmtToIRSB(bb,st); continue;
442 case -12: DO_NEW( 12, tttmp); addStmtToIRSB(bb,st); continue;
443 case 16: DO_DIE( 16, tttmp); addStmtToIRSB(bb,st); continue;
444 case -16: DO_NEW( 16, tttmp); addStmtToIRSB(bb,st); continue;
445 case 32: DO_DIE( 32, tttmp); addStmtToIRSB(bb,st); continue;
446 case -32: DO_NEW( 32, tttmp); addStmtToIRSB(bb,st); continue;
447 case 112: DO_DIE( 112, tttmp); addStmtToIRSB(bb,st); continue;
448 case -112: DO_NEW( 112, tttmp); addStmtToIRSB(bb,st); continue;
449 case 128: DO_DIE( 128, tttmp); addStmtToIRSB(bb,st); continue;
450 case -128: DO_NEW( 128, tttmp); addStmtToIRSB(bb,st); continue;
451 case 144: DO_DIE( 144, tttmp); addStmtToIRSB(bb,st); continue;
452 case -144: DO_NEW( 144, tttmp); addStmtToIRSB(bb,st); continue;
453 case 160: DO_DIE( 160, tttmp); addStmtToIRSB(bb,st); continue;
454 case -160: DO_NEW( 160, tttmp); addStmtToIRSB(bb,st); continue;
njn42c83552005-12-05 20:45:59 +0000455 default:
sewardjbb686272006-01-22 20:12:45 +0000456 /* common values for ppc64: 144 128 160 112 176 */
njn42c83552005-12-05 20:45:59 +0000457 n_SP_updates_generic_known++;
458 goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000459 }
sewardj8b635a42004-11-22 19:01:47 +0000460 } else {
sewardj2831b512007-11-11 18:56:39 +0000461 /* Deal with an unknown update to SP. We're here because
462 either:
463 (1) the Put does not exactly cover SP; it is a partial update.
464 Highly unlikely, but has been known to happen for 16-bit
465 Windows apps running on Wine, doing 16-bit adjustments to
466 %sp.
467 (2) the Put does exactly cover SP, but we are unable to
468 determine how the value relates to the old SP. In any
469 case, we cannot assume that the Put.data value is a tmp;
470 we must assume it can be anything allowed in flat IR (tmp
471 or const).
472 */
sewardj7cf4e6b2008-05-01 20:24:26 +0000473 IRTemp old_SP;
njn42c83552005-12-05 20:45:59 +0000474 n_SP_updates_generic_unknown++;
475
njn5096a392005-12-13 20:05:00 +0000476 // Nb: if all is well, this generic case will typically be
477 // called something like every 1000th SP update. If it's more than
478 // that, the above code may be missing some cases.
sewardj8b635a42004-11-22 19:01:47 +0000479 generic:
sewardj7cf4e6b2008-05-01 20:24:26 +0000480 /* Pass both the old and new SP values to this helper. Also,
481 pass an origin tag, even if it isn't needed. */
sewardj2a99cf62004-11-24 10:44:19 +0000482 old_SP = newIRTemp(bb->tyenv, typeof_SP);
sewardj0b9d74a2006-12-24 02:24:11 +0000483 addStmtToIRSB(
sewardj2a99cf62004-11-24 10:44:19 +0000484 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000485 IRStmt_WrTmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
sewardj2a99cf62004-11-24 10:44:19 +0000486 );
sewardjde4a1d02002-03-22 01:27:54 +0000487
sewardj2831b512007-11-11 18:56:39 +0000488 /* Now we know what the old value of SP is. But knowing the new
489 value is a bit tricky if there is a partial write. */
490 if (first_Put == first_SP && last_Put == last_SP) {
491 /* The common case, an exact write to SP. So st->Ist.Put.data
492 does hold the new value; simple. */
sewardj7cf4e6b2008-05-01 20:24:26 +0000493 vg_assert(curr_IP_known);
sewardj2831b512007-11-11 18:56:39 +0000494 dcall = unsafeIRDirty_0_N(
sewardj7cf4e6b2008-05-01 20:24:26 +0000495 3/*regparms*/,
sewardj2831b512007-11-11 18:56:39 +0000496 "VG_(unknown_SP_update)",
497 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
sewardj7cf4e6b2008-05-01 20:24:26 +0000498 mkIRExprVec_3( IRExpr_RdTmp(old_SP), st->Ist.Put.data,
499 mk_ecu_Expr(curr_IP) )
sewardj2831b512007-11-11 18:56:39 +0000500 );
501 addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
502 /* don't forget the original assignment */
503 addStmtToIRSB( bb, st );
504 } else {
505 /* We have a partial update to SP. We need to know what
506 the new SP will be, and hand that to the helper call,
507 but when the helper call happens, SP must hold the
508 value it had before the update. Tricky.
509 Therefore use the following kludge:
510 1. do the partial SP update (Put)
511 2. Get the new SP value into a tmp, new_SP
512 3. Put old_SP
513 4. Call the helper
514 5. Put new_SP
515 */
516 IRTemp new_SP;
517 /* 1 */
518 addStmtToIRSB( bb, st );
519 /* 2 */
520 new_SP = newIRTemp(bb->tyenv, typeof_SP);
521 addStmtToIRSB(
522 bb,
523 IRStmt_WrTmp( new_SP, IRExpr_Get(offset_SP, typeof_SP) )
524 );
525 /* 3 */
526 addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(old_SP) ));
527 /* 4 */
sewardj7cf4e6b2008-05-01 20:24:26 +0000528 vg_assert(curr_IP_known);
sewardj2831b512007-11-11 18:56:39 +0000529 dcall = unsafeIRDirty_0_N(
sewardj7cf4e6b2008-05-01 20:24:26 +0000530 3/*regparms*/,
sewardj2831b512007-11-11 18:56:39 +0000531 "VG_(unknown_SP_update)",
532 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
sewardj7cf4e6b2008-05-01 20:24:26 +0000533 mkIRExprVec_3( IRExpr_RdTmp(old_SP),
534 IRExpr_RdTmp(new_SP),
535 mk_ecu_Expr(curr_IP) )
sewardj2831b512007-11-11 18:56:39 +0000536 );
537 addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
538 /* 5 */
539 addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(new_SP) ));
540 }
sewardj2a99cf62004-11-24 10:44:19 +0000541
sewardj2831b512007-11-11 18:56:39 +0000542 /* Forget what we already know. */
njn5096a392005-12-13 20:05:00 +0000543 clear_SP_aliases();
sewardj2831b512007-11-11 18:56:39 +0000544
545 /* If this is a Put of a tmp that exactly updates SP,
546 start tracking aliases against this tmp. */
547
548 if (first_Put == first_SP && last_Put == last_SP
549 && st->Ist.Put.data->tag == Iex_RdTmp) {
550 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.Put.data->Iex.RdTmp.tmp)
551 == typeof_SP );
552 add_SP_alias(st->Ist.Put.data->Iex.RdTmp.tmp, 0);
553 }
sewardj8b635a42004-11-22 19:01:47 +0000554 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000555 }
556
sewardj8b635a42004-11-22 19:01:47 +0000557 case5:
558 /* PutI or Dirty call which overlaps SP: complain. We can't
559 deal with SP changing in weird ways (well, we can, but not at
560 this time of night). */
561 if (st->tag == Ist_PutI) {
562 descr = st->Ist.PutI.descr;
563 minoff_ST = descr->base;
sewardj2831b512007-11-11 18:56:39 +0000564 maxoff_ST = descr->base
565 + descr->nElems * sizeofIRType(descr->elemTy) - 1;
566 if (!(offset_SP > maxoff_ST
567 || (offset_SP + sizeof_SP - 1) < minoff_ST))
sewardj8b635a42004-11-22 19:01:47 +0000568 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000569 }
sewardj8b635a42004-11-22 19:01:47 +0000570 if (st->tag == Ist_Dirty) {
571 d = st->Ist.Dirty.details;
572 for (j = 0; j < d->nFxState; j++) {
573 minoff_ST = d->fxState[j].offset;
574 maxoff_ST = d->fxState[j].offset + d->fxState[j].size - 1;
575 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
576 continue;
sewardj2831b512007-11-11 18:56:39 +0000577 if (!(offset_SP > maxoff_ST
578 || (offset_SP + sizeof_SP - 1) < minoff_ST))
sewardj8b635a42004-11-22 19:01:47 +0000579 goto complain;
580 }
581 }
sewardjde4a1d02002-03-22 01:27:54 +0000582
sewardj8b635a42004-11-22 19:01:47 +0000583 /* well, not interesting. Just copy and keep going. */
sewardj0b9d74a2006-12-24 02:24:11 +0000584 addStmtToIRSB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000585
sewardj0b9d74a2006-12-24 02:24:11 +0000586 } /* for (i = 0; i < sb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000587
sewardj8b635a42004-11-22 19:01:47 +0000588 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000589
sewardj8b635a42004-11-22 19:01:47 +0000590 complain:
591 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000592
sewardj7cf4e6b2008-05-01 20:24:26 +0000593#undef IS_ADD
594#undef IS_SUB
595#undef IS_ADD_OR_SUB
596#undef GET_CONST
597#undef DO_NEW
598#undef DO_DIE
sewardjde4a1d02002-03-22 01:27:54 +0000599}
sewardj7c4b6042003-06-14 15:47:15 +0000600
sewardjde4a1d02002-03-22 01:27:54 +0000601/*------------------------------------------------------------*/
602/*--- Main entry point for the JITter. ---*/
603/*------------------------------------------------------------*/
604
sewardjd2b70dc2005-10-14 17:22:31 +0000605/* Extra comments re self-checking translations and self-modifying
606 code. (JRS 14 Oct 05).
607
608 There are 3 modes:
609 (1) no checking: all code assumed to be not self-modifying
610 (2) partial: known-problematic situations get a self-check
611 (3) full checking: all translations get a self-check
612
613 As currently implemented, the default is (2). (3) is always safe,
614 but very slow. (1) works mostly, but fails for gcc nested-function
615 code which uses trampolines on the stack; this situation is
616 detected and handled by (2).
617
618 ----------
619
620 A more robust and transparent solution, which is not currently
621 implemented, is a variant of (2): if a translation is made from an
622 area which aspacem says does not have 'w' permission, then it can
623 be non-self-checking. Otherwise, it needs a self-check.
624
625 This is complicated by Vex's basic-block chasing. If a self-check
626 is requested, then Vex will not chase over basic block boundaries
627 (it's too complex). However there is still a problem if it chases
628 from a non-'w' area into a 'w' area.
629
630 I think the right thing to do is:
631
632 - if a translation request starts in a 'w' area, ask for a
633 self-checking translation, and do not allow any chasing (make
634 chase_into_ok return False). Note that the latter is redundant
635 in the sense that Vex won't chase anyway in this situation.
636
637 - if a translation request starts in a non-'w' area, do not ask for
638 a self-checking translation. However, do not allow chasing (as
639 determined by chase_into_ok) to go into a 'w' area.
640
641 The result of this is that all code inside 'w' areas is self
642 checking.
643
644 To complete the trick, there is a caveat: we must watch the
645 client's mprotect calls. If pages are changed from non-'w' to 'w'
646 then we should throw away all translations which intersect the
647 affected area, so as to force them to be redone with self-checks.
648
649 ----------
650
651 The above outlines the conditions under which bb chasing is allowed
652 from a self-modifying-code point of view. There are other
653 situations pertaining to function redirection in which it is
654 necessary to disallow chasing, but those fall outside the scope of
655 this comment.
656*/
657
sewardj34593e52006-01-17 01:57:33 +0000658
sewardj8b635a42004-11-22 19:01:47 +0000659/* Vex dumps the final code in here. Then we can copy it off
660 wherever we like. */
sewardj4a0009c2006-10-17 01:52:05 +0000661/* 60000: should agree with assertion in VG_(add_to_transtab) in
662 m_transtab.c. */
663#define N_TMPBUF 60000
sewardj8b635a42004-11-22 19:01:47 +0000664static UChar tmpbuf[N_TMPBUF];
665
sewardj34593e52006-01-17 01:57:33 +0000666
sewardj8b635a42004-11-22 19:01:47 +0000667/* Function pointers we must supply to LibVEX in order that it
668 can bomb out and emit messages under Valgrind's control. */
669__attribute__ ((noreturn))
670static
671void failure_exit ( void )
672{
sewardjbf426512005-01-17 18:35:30 +0000673 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000674 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000675}
676
677static
sewardjb5f6f512005-03-10 23:59:00 +0000678void log_bytes ( HChar* bytes, Int nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000679{
680 Int i;
681 for (i = 0; i < nbytes-3; i += 4)
682 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
683 for (; i < nbytes; i++)
684 VG_(printf)("%c", bytes[i]);
685}
686
njn25e49d8e72002-09-23 09:36:25 +0000687
sewardj34593e52006-01-17 01:57:33 +0000688/* --------- Various helper functions for translation --------- */
sewardj8b635a42004-11-22 19:01:47 +0000689
sewardj45f4e7c2005-09-27 19:20:21 +0000690/* Look for reasons to disallow making translations from the given
691 segment. */
692
sewardj4a0009c2006-10-17 01:52:05 +0000693static Bool translations_allowable_from_seg ( NSegment const* seg )
sewardj45f4e7c2005-09-27 19:20:21 +0000694{
695# if defined(VGA_x86)
696 Bool allowR = True;
697# else
698 Bool allowR = False;
699# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000700 return seg != NULL
tom1da86fe2009-10-12 13:53:12 +0000701 && (seg->kind == SkAnonC || seg->kind == SkFileC || seg->kind == SkShmC)
sewardj45f4e7c2005-09-27 19:20:21 +0000702 && (seg->hasX || (seg->hasR && allowR));
703}
704
705
sewardj34593e52006-01-17 01:57:33 +0000706/* Is a self-check required for a translation of a guest address
707 inside segment SEG when requested by thread TID ? */
sewardj45f4e7c2005-09-27 19:20:21 +0000708
sewardj4a0009c2006-10-17 01:52:05 +0000709static Bool self_check_required ( NSegment const* seg, ThreadId tid )
sewardj34593e52006-01-17 01:57:33 +0000710{
njnf76d27a2009-05-28 01:53:07 +0000711#if defined(VGO_darwin)
712 // GrP fixme hack - dyld i386 IMPORT gets rewritten
713 // to really do this correctly, we'd need to flush the
714 // translation cache whenever a segment became +WX
715 if (seg->hasX && seg->hasW) {
716 return True;
717 }
718#endif
sewardj34593e52006-01-17 01:57:33 +0000719 switch (VG_(clo_smc_check)) {
720 case Vg_SmcNone: return False;
721 case Vg_SmcAll: return True;
722 case Vg_SmcStack:
723 return seg
724 ? (seg->start <= VG_(get_SP)(tid)
725 && VG_(get_SP)(tid)+sizeof(Word)-1 <= seg->end)
726 : False;
727 break;
728 default:
729 vg_assert2(0, "unknown VG_(clo_smc_check) value");
730 }
731}
732
733
734/* This is a callback passed to LibVEX_Translate. It stops Vex from
735 chasing into function entry points that we wish to redirect.
736 Chasing across them obviously defeats the redirect mechanism, with
737 bad effects for Memcheck, Addrcheck, and possibly others.
sewardj447f2a12005-07-07 13:52:53 +0000738
739 Also, we must stop Vex chasing into blocks for which we might want
740 to self checking.
741*/
sewardj34593e52006-01-17 01:57:33 +0000742static Bool chase_into_ok ( void* closureV, Addr64 addr64 )
sewardj8b635a42004-11-22 19:01:47 +0000743{
sewardj34593e52006-01-17 01:57:33 +0000744 Addr addr = (Addr)addr64;
sewardj4a0009c2006-10-17 01:52:05 +0000745 NSegment const* seg = VG_(am_find_nsegment)(addr);
sewardj34593e52006-01-17 01:57:33 +0000746 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj45f4e7c2005-09-27 19:20:21 +0000747
sewardj447f2a12005-07-07 13:52:53 +0000748 /* Work through a list of possibilities why we might not want to
749 allow a chase. */
sewardj447f2a12005-07-07 13:52:53 +0000750
sewardj34593e52006-01-17 01:57:33 +0000751 /* Destination not in a plausible segment? */
sewardj45f4e7c2005-09-27 19:20:21 +0000752 if (!translations_allowable_from_seg(seg))
753 goto dontchase;
754
sewardj447f2a12005-07-07 13:52:53 +0000755 /* Destination is redirected? */
sewardj0ec07f32006-01-12 12:32:32 +0000756 if (addr != VG_(redir_do_lookup)(addr, NULL))
sewardj447f2a12005-07-07 13:52:53 +0000757 goto dontchase;
758
sewardj4a0009c2006-10-17 01:52:05 +0000759# if defined(VG_PLAT_USES_PPCTOC)
760 /* This needs to be at the start of its own block. Don't chase. Re
761 ULong_to_Ptr, be careful to ensure we only compare 32 bits on a
762 32-bit target.*/
763 if (ULong_to_Ptr(addr64)
764 == (void*)&VG_(ppctoc_magic_redirect_return_stub))
sewardj34593e52006-01-17 01:57:33 +0000765 goto dontchase;
766# endif
767
sewardj5f76de02007-02-11 05:08:06 +0000768 /* overly conservative, but .. don't chase into the distinguished
769 address that m_transtab uses as an empty-slot marker for
770 VG_(tt_fast). */
771 if (addr == TRANSTAB_BOGUS_GUEST_ADDR)
772 goto dontchase;
773
sewardj447f2a12005-07-07 13:52:53 +0000774 /* well, ok then. go on and chase. */
775 return True;
776
777 vg_assert(0);
778 /*NOTREACHED*/
779
780 dontchase:
njn8a7b41b2007-09-23 00:51:24 +0000781 if (0) VG_(printf)("not chasing into 0x%lx\n", addr);
sewardj447f2a12005-07-07 13:52:53 +0000782 return False;
sewardj8b635a42004-11-22 19:01:47 +0000783}
784
sewardj447f2a12005-07-07 13:52:53 +0000785
sewardj4a0009c2006-10-17 01:52:05 +0000786/* --------------- helpers for with-TOC platforms --------------- */
787
788/* NOTE: with-TOC platforms are: ppc64-linux, ppc32-aix5, ppc64-aix5. */
sewardjdfbaa222006-01-18 04:25:20 +0000789
sewardjd68ac3e2006-01-20 14:31:57 +0000790static IRExpr* mkU64 ( ULong n ) {
sewardj34593e52006-01-17 01:57:33 +0000791 return IRExpr_Const(IRConst_U64(n));
792}
sewardjd68ac3e2006-01-20 14:31:57 +0000793static IRExpr* mkU32 ( UInt n ) {
794 return IRExpr_Const(IRConst_U32(n));
795}
sewardj4a0009c2006-10-17 01:52:05 +0000796
797#if defined(VG_PLAT_USES_PPCTOC)
sewardjd68ac3e2006-01-20 14:31:57 +0000798static IRExpr* mkU8 ( UChar n ) {
799 return IRExpr_Const(IRConst_U8(n));
800}
sewardj4a0009c2006-10-17 01:52:05 +0000801static IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) {
802 if (typeOfIRExpr(tyenv, e) == Ity_I32) {
803 return e;
804 } else {
805 vg_assert(typeOfIRExpr(tyenv, e) == Ity_I64);
806 return IRExpr_Unop(Iop_64to32, e);
807 }
808}
809
810/* Generate code to push word-typed expression 'e' onto this thread's
811 redir stack, checking for stack overflow and generating code to
812 bomb out if so. */
sewardj34593e52006-01-17 01:57:33 +0000813
sewardj0b9d74a2006-12-24 02:24:11 +0000814static void gen_PUSH ( IRSB* bb, IRExpr* e )
sewardj34593e52006-01-17 01:57:33 +0000815{
sewardj0b9d74a2006-12-24 02:24:11 +0000816 IRRegArray* descr;
817 IRTemp t1;
818 IRExpr* one;
sewardj34593e52006-01-17 01:57:33 +0000819
sewardj4a0009c2006-10-17 01:52:05 +0000820# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
821 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
822 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
823 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
824 Int offB_EMWARN = offsetof(VexGuestPPC64State,guest_EMWARN);
825 Bool is64 = True;
826 IRType ty_Word = Ity_I64;
827 IROp op_CmpNE = Iop_CmpNE64;
828 IROp op_Sar = Iop_Sar64;
829 IROp op_Sub = Iop_Sub64;
830 IROp op_Add = Iop_Add64;
831 IRExpr*(*mkU)(ULong) = mkU64;
832 vg_assert(VG_WORDSIZE == 8);
833# else
834 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
835 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
836 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
837 Int offB_EMWARN = offsetof(VexGuestPPC32State,guest_EMWARN);
838 Bool is64 = False;
839 IRType ty_Word = Ity_I32;
840 IROp op_CmpNE = Iop_CmpNE32;
841 IROp op_Sar = Iop_Sar32;
842 IROp op_Sub = Iop_Sub32;
843 IROp op_Add = Iop_Add32;
844 IRExpr*(*mkU)(UInt) = mkU32;
845 vg_assert(VG_WORDSIZE == 4);
846# endif
847
848 vg_assert(sizeof(void*) == VG_WORDSIZE);
849 vg_assert(sizeof(Word) == VG_WORDSIZE);
850 vg_assert(sizeof(Addr) == VG_WORDSIZE);
851
sewardj0b9d74a2006-12-24 02:24:11 +0000852 descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
sewardj4a0009c2006-10-17 01:52:05 +0000853 t1 = newIRTemp( bb->tyenv, ty_Word );
854 one = mkU(1);
855
856 vg_assert(typeOfIRExpr(bb->tyenv, e) == ty_Word);
sewardj34593e52006-01-17 01:57:33 +0000857
858 /* t1 = guest_REDIR_SP + 1 */
sewardj0b9d74a2006-12-24 02:24:11 +0000859 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000860 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000861 IRStmt_WrTmp(
sewardj34593e52006-01-17 01:57:33 +0000862 t1,
sewardj4a0009c2006-10-17 01:52:05 +0000863 IRExpr_Binop(op_Add, IRExpr_Get( offB_REDIR_SP, ty_Word ), one)
sewardj34593e52006-01-17 01:57:33 +0000864 )
865 );
866
sewardjd68ac3e2006-01-20 14:31:57 +0000867 /* Bomb out if t1 >=s stack_size, that is, (stack_size-1)-t1 <s 0.
868 The destination (0) is a bit bogus but it doesn't matter since
869 this is an unrecoverable error and will lead to Valgrind
870 shutting down. _EMWARN is set regardless - that's harmless
871 since is only has a meaning if the exit is taken. */
sewardj0b9d74a2006-12-24 02:24:11 +0000872 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000873 bb,
874 IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_overflow))
875 );
sewardj0b9d74a2006-12-24 02:24:11 +0000876 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000877 bb,
878 IRStmt_Exit(
879 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000880 op_CmpNE,
sewardjd68ac3e2006-01-20 14:31:57 +0000881 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000882 op_Sar,
sewardj0b9d74a2006-12-24 02:24:11 +0000883 IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_RdTmp(t1)),
sewardj4a0009c2006-10-17 01:52:05 +0000884 mkU8(8 * VG_WORDSIZE - 1)
sewardjd68ac3e2006-01-20 14:31:57 +0000885 ),
sewardj4a0009c2006-10-17 01:52:05 +0000886 mkU(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000887 ),
888 Ijk_EmFail,
sewardj4a0009c2006-10-17 01:52:05 +0000889 is64 ? IRConst_U64(0) : IRConst_U32(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000890 )
891 );
sewardj34593e52006-01-17 01:57:33 +0000892
893 /* guest_REDIR_SP = t1 */
sewardj0b9d74a2006-12-24 02:24:11 +0000894 addStmtToIRSB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_RdTmp(t1)));
sewardj34593e52006-01-17 01:57:33 +0000895
896 /* guest_REDIR_STACK[t1+0] = e */
sewardj4a0009c2006-10-17 01:52:05 +0000897 /* PutI/GetI have I32-typed indexes regardless of guest word size */
sewardj0b9d74a2006-12-24 02:24:11 +0000898 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000899 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000900 IRStmt_PutI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0, e)
sewardj34593e52006-01-17 01:57:33 +0000901 );
902}
903
sewardj4a0009c2006-10-17 01:52:05 +0000904
905/* Generate code to pop a word-sized value from this thread's redir
906 stack, binding it to a new temporary, which is returned. As with
907 gen_PUSH, an overflow check is also performed. */
908
sewardj0b9d74a2006-12-24 02:24:11 +0000909static IRTemp gen_POP ( IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +0000910{
sewardj4a0009c2006-10-17 01:52:05 +0000911# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
912 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
913 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
914 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
915 Int offB_EMWARN = offsetof(VexGuestPPC64State,guest_EMWARN);
916 Bool is64 = True;
917 IRType ty_Word = Ity_I64;
918 IROp op_CmpNE = Iop_CmpNE64;
919 IROp op_Sar = Iop_Sar64;
920 IROp op_Sub = Iop_Sub64;
921 IRExpr*(*mkU)(ULong) = mkU64;
922# else
923 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
924 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
925 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
926 Int offB_EMWARN = offsetof(VexGuestPPC32State,guest_EMWARN);
927 Bool is64 = False;
928 IRType ty_Word = Ity_I32;
929 IROp op_CmpNE = Iop_CmpNE32;
930 IROp op_Sar = Iop_Sar32;
931 IROp op_Sub = Iop_Sub32;
932 IRExpr*(*mkU)(UInt) = mkU32;
933# endif
sewardj34593e52006-01-17 01:57:33 +0000934
sewardj0b9d74a2006-12-24 02:24:11 +0000935 IRRegArray* descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
936 IRTemp t1 = newIRTemp( bb->tyenv, ty_Word );
937 IRTemp res = newIRTemp( bb->tyenv, ty_Word );
938 IRExpr* one = mkU(1);
sewardj4a0009c2006-10-17 01:52:05 +0000939
940 vg_assert(sizeof(void*) == VG_WORDSIZE);
941 vg_assert(sizeof(Word) == VG_WORDSIZE);
942 vg_assert(sizeof(Addr) == VG_WORDSIZE);
sewardj34593e52006-01-17 01:57:33 +0000943
944 /* t1 = guest_REDIR_SP */
sewardj0b9d74a2006-12-24 02:24:11 +0000945 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000946 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000947 IRStmt_WrTmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) )
sewardj34593e52006-01-17 01:57:33 +0000948 );
949
sewardjd68ac3e2006-01-20 14:31:57 +0000950 /* Bomb out if t1 < 0. Same comments as gen_PUSH apply. */
sewardj0b9d74a2006-12-24 02:24:11 +0000951 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000952 bb,
953 IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_underflow))
954 );
sewardj0b9d74a2006-12-24 02:24:11 +0000955 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000956 bb,
957 IRStmt_Exit(
958 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000959 op_CmpNE,
sewardjd68ac3e2006-01-20 14:31:57 +0000960 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000961 op_Sar,
sewardj0b9d74a2006-12-24 02:24:11 +0000962 IRExpr_RdTmp(t1),
sewardj4a0009c2006-10-17 01:52:05 +0000963 mkU8(8 * VG_WORDSIZE - 1)
sewardjd68ac3e2006-01-20 14:31:57 +0000964 ),
sewardj4a0009c2006-10-17 01:52:05 +0000965 mkU(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000966 ),
967 Ijk_EmFail,
sewardj4a0009c2006-10-17 01:52:05 +0000968 is64 ? IRConst_U64(0) : IRConst_U32(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000969 )
970 );
sewardj34593e52006-01-17 01:57:33 +0000971
972 /* res = guest_REDIR_STACK[t1+0] */
sewardj4a0009c2006-10-17 01:52:05 +0000973 /* PutI/GetI have I32-typed indexes regardless of guest word size */
sewardj0b9d74a2006-12-24 02:24:11 +0000974 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000975 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000976 IRStmt_WrTmp(
sewardj34593e52006-01-17 01:57:33 +0000977 res,
sewardj0b9d74a2006-12-24 02:24:11 +0000978 IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0)
sewardj34593e52006-01-17 01:57:33 +0000979 )
980 );
981
982 /* guest_REDIR_SP = t1-1 */
sewardj0b9d74a2006-12-24 02:24:11 +0000983 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000984 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000985 IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(op_Sub, IRExpr_RdTmp(t1), one))
sewardj34593e52006-01-17 01:57:33 +0000986 );
987
988 return res;
989}
990
sewardj4a0009c2006-10-17 01:52:05 +0000991/* Generate code to push LR and R2 onto this thread's redir stack,
992 then set R2 to the new value (which is the TOC pointer to be used
993 for the duration of the replacement function, as determined by
994 m_debuginfo), and set LR to the magic return stub, so we get to
995 intercept the return and restore R2 and L2 to the values saved
996 here. */
997
sewardj0b9d74a2006-12-24 02:24:11 +0000998static void gen_push_and_set_LR_R2 ( IRSB* bb, Addr64 new_R2_value )
sewardj34593e52006-01-17 01:57:33 +0000999{
sewardj4a0009c2006-10-17 01:52:05 +00001000# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
1001 Addr64 bogus_RA = (Addr64)&VG_(ppctoc_magic_redirect_return_stub);
1002 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1003 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
sewardj34593e52006-01-17 01:57:33 +00001004 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) );
1005 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
sewardj0b9d74a2006-12-24 02:24:11 +00001006 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) );
1007 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) );
sewardj4a0009c2006-10-17 01:52:05 +00001008
1009# elif defined(VGP_ppc32_aix5)
1010 Addr32 bogus_RA = (Addr32)&VG_(ppctoc_magic_redirect_return_stub);
1011 Int offB_GPR2 = offsetof(VexGuestPPC32State,guest_GPR2);
1012 Int offB_LR = offsetof(VexGuestPPC32State,guest_LR);
1013 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I32) );
1014 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I32) );
sewardj0b9d74a2006-12-24 02:24:11 +00001015 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU32( bogus_RA )) );
1016 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU32( new_R2_value )) );
sewardj4a0009c2006-10-17 01:52:05 +00001017
1018# else
1019# error Platform is not TOC-afflicted, fortunately
1020# endif
sewardj34593e52006-01-17 01:57:33 +00001021}
1022
sewardj0b9d74a2006-12-24 02:24:11 +00001023static void gen_pop_R2_LR_then_bLR ( IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001024{
sewardj4a0009c2006-10-17 01:52:05 +00001025# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
1026 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1027 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
1028 IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I64 );
1029 IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I64 );
sewardj34593e52006-01-17 01:57:33 +00001030 /* Restore R2 */
1031 old_R2 = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001032 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
sewardj34593e52006-01-17 01:57:33 +00001033 /* Restore LR */
1034 old_LR = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001035 addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
sewardj34593e52006-01-17 01:57:33 +00001036 /* Branch to LR */
1037 /* re boring, we arrived here precisely because a wrapped fn did a
1038 blr (hence Ijk_Ret); so we should just mark this jump as Boring,
sewardj4a0009c2006-10-17 01:52:05 +00001039 else one _Call will have resulted in two _Rets. */
sewardj34593e52006-01-17 01:57:33 +00001040 bb->jumpkind = Ijk_Boring;
sewardj0b9d74a2006-12-24 02:24:11 +00001041 bb->next = IRExpr_Binop(Iop_And64, IRExpr_RdTmp(old_LR), mkU64(~(3ULL)));
sewardj4a0009c2006-10-17 01:52:05 +00001042
1043# elif defined(VGP_ppc32_aix5)
1044 Int offB_GPR2 = offsetof(VexGuestPPC32State,guest_GPR2);
1045 Int offB_LR = offsetof(VexGuestPPC32State,guest_LR);
1046 IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I32 );
1047 IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I32 );
1048 /* Restore R2 */
1049 old_R2 = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001050 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
sewardj4a0009c2006-10-17 01:52:05 +00001051 /* Restore LR */
1052 old_LR = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001053 addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
sewardj4a0009c2006-10-17 01:52:05 +00001054
1055 /* Branch to LR */
1056 /* re boring, we arrived here precisely because a wrapped fn did a
1057 blr (hence Ijk_Ret); so we should just mark this jump as Boring,
1058 else one _Call will have resulted in two _Rets. */
1059 bb->jumpkind = Ijk_Boring;
sewardj0b9d74a2006-12-24 02:24:11 +00001060 bb->next = IRExpr_Binop(Iop_And32, IRExpr_RdTmp(old_LR), mkU32(~3));
sewardj4a0009c2006-10-17 01:52:05 +00001061
1062# else
1063# error Platform is not TOC-afflicted, fortunately
1064# endif
sewardj34593e52006-01-17 01:57:33 +00001065}
1066
1067static
sewardj0b9d74a2006-12-24 02:24:11 +00001068Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001069{
sewardj0283bae2006-01-22 01:15:36 +00001070 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj0b9d74a2006-12-24 02:24:11 +00001071 /* Since we're creating the entire IRSB right here, give it a
sewardj0283bae2006-01-22 01:15:36 +00001072 proper IMark, as it won't get one any other way, and cachegrind
1073 will barf if it doesn't have one (fair enough really). */
sewardj0b9d74a2006-12-24 02:24:11 +00001074 addStmtToIRSB( bb, IRStmt_IMark( closure->readdr, 4 ) );
sewardj0283bae2006-01-22 01:15:36 +00001075 /* Generate the magic sequence:
1076 pop R2 from hidden stack
1077 pop LR from hidden stack
1078 goto LR
1079 */
sewardj34593e52006-01-17 01:57:33 +00001080 gen_pop_R2_LR_then_bLR(bb);
1081 return True; /* True == this is the entire BB; don't disassemble any
1082 real insns into it - just hand it directly to
1083 optimiser/instrumenter/backend. */
1084}
1085#endif
1086
sewardj4a0009c2006-10-17 01:52:05 +00001087/* --------------- END helpers for with-TOC platforms --------------- */
sewardj34593e52006-01-17 01:57:33 +00001088
sewardj4a0009c2006-10-17 01:52:05 +00001089
1090/* This is the IR preamble generator used for replacement
sewardj0283bae2006-01-22 01:15:36 +00001091 functions. It adds code to set the guest_NRADDR{_GPR2} to zero
sewardj34593e52006-01-17 01:57:33 +00001092 (technically not necessary, but facilitates detecting mixups in
sewardj0283bae2006-01-22 01:15:36 +00001093 which a replacement function has been erroneously declared using
1094 VG_REPLACE_FUNCTION_Z{U,Z} when instead it should have been written
1095 using VG_WRAP_FUNCTION_Z{U,Z}).
sewardj34593e52006-01-17 01:57:33 +00001096
sewardj4a0009c2006-10-17 01:52:05 +00001097 On with-TOC platforms the follow hacks are also done: LR and R2 are
1098 pushed onto a hidden stack, R2 is set to the correct value for the
1099 replacement function, and LR is set to point at the magic
1100 return-stub address. Setting LR causes the return of the
1101 wrapped/redirected function to lead to our magic return stub, which
1102 restores LR and R2 from said stack and returns for real.
sewardjdfbaa222006-01-18 04:25:20 +00001103
sewardjb8b79ad2008-03-03 01:35:41 +00001104 VG_(get_StackTrace_wrk) understands that the LR value may point to
1105 the return stub address, and that in that case it can get the real
1106 LR value from the hidden stack instead. */
sewardj34593e52006-01-17 01:57:33 +00001107static
sewardj0b9d74a2006-12-24 02:24:11 +00001108Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001109{
sewardj34593e52006-01-17 01:57:33 +00001110 Int nraddr_szB
1111 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1112 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
sewardj4a0009c2006-10-17 01:52:05 +00001113 vg_assert(nraddr_szB == VG_WORDSIZE);
sewardj0b9d74a2006-12-24 02:24:11 +00001114 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001115 bb,
1116 IRStmt_Put(
1117 offsetof(VexGuestArchState,guest_NRADDR),
sewardj0283bae2006-01-22 01:15:36 +00001118 nraddr_szB == 8 ? mkU64(0) : mkU32(0)
sewardj34593e52006-01-17 01:57:33 +00001119 )
1120 );
sewardj4a0009c2006-10-17 01:52:05 +00001121# if defined(VG_PLAT_USES_PPCTOC)
sewardj0283bae2006-01-22 01:15:36 +00001122 { VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj0b9d74a2006-12-24 02:24:11 +00001123 addStmtToIRSB(
sewardj0283bae2006-01-22 01:15:36 +00001124 bb,
1125 IRStmt_Put(
1126 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
sewardj4a0009c2006-10-17 01:52:05 +00001127 VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
sewardj0283bae2006-01-22 01:15:36 +00001128 )
1129 );
1130 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1131 }
sewardj34593e52006-01-17 01:57:33 +00001132# endif
1133 return False;
1134}
1135
1136/* Ditto, except set guest_NRADDR to nraddr (the un-redirected guest
1137 address). This is needed for function wrapping - so the wrapper
1138 can read _NRADDR and find the address of the function being
sewardj4a0009c2006-10-17 01:52:05 +00001139 wrapped. On toc-afflicted platforms we must also snarf r2. */
sewardj34593e52006-01-17 01:57:33 +00001140static
sewardj0b9d74a2006-12-24 02:24:11 +00001141Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001142{
1143 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1144 Int nraddr_szB
1145 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1146 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
sewardj4a0009c2006-10-17 01:52:05 +00001147 vg_assert(nraddr_szB == VG_WORDSIZE);
sewardj0b9d74a2006-12-24 02:24:11 +00001148 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001149 bb,
1150 IRStmt_Put(
1151 offsetof(VexGuestArchState,guest_NRADDR),
1152 nraddr_szB == 8
1153 ? IRExpr_Const(IRConst_U64( closure->nraddr ))
1154 : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
1155 )
1156 );
sewardj4a0009c2006-10-17 01:52:05 +00001157# if defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
1158 || defined(VGP_ppc64_aix5)
sewardj0b9d74a2006-12-24 02:24:11 +00001159 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001160 bb,
1161 IRStmt_Put(
1162 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1163 IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2),
sewardj4a0009c2006-10-17 01:52:05 +00001164 VG_WORDSIZE==8 ? Ity_I64 : Ity_I32)
sewardjd68ac3e2006-01-20 14:31:57 +00001165 )
1166 );
sewardj34593e52006-01-17 01:57:33 +00001167 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1168# endif
1169 return False;
1170}
1171
sewardj4a0009c2006-10-17 01:52:05 +00001172/* --- Helpers to do with PPC related stack redzones. --- */
1173
1174__attribute__((unused))
1175static Bool const_True ( Addr64 guest_addr )
1176{
1177 return True;
1178}
1179
1180__attribute__((unused))
1181static Bool bl_RZ_zap_ok_for_AIX ( Addr64 bl_target )
1182{
1183 /* paranoia */
1184 if (sizeof(void*) == 4)
1185 bl_target &= 0xFFFFFFFFULL;
1186
1187 /* don't zap the redzone for calls to millicode. */
1188 if (bl_target < 0x10000ULL)
1189 return False;
1190
1191 /* don't zap the redzone for calls to .$SAVEF14 .. .$SAVEF31.
1192 First we need to be reasonably sure we won't segfault by looking
1193 at the branch target. */
1194 { NSegment const*const seg = VG_(am_find_nsegment)( (Addr)bl_target );
1195 if (seg && seg->hasR) {
1196 switch ( *(UInt*)(Addr)bl_target ) {
1197 case 0xd9c1ff70: /* stfd f14,-144(r1) */
1198 case 0xd9e1ff78: /* stfd f15,-136(r1) */
1199 case 0xda01ff80: /* stfd f16,-128(r1) */
1200 case 0xda21ff88: /* stfd f17,-120(r1) */
1201 case 0xda41ff90: /* stfd f18,-112(r1) */
1202 case 0xda61ff98: /* stfd f19,-104(r1) */
1203 case 0xda81ffa0: /* stfd f20,-96(r1) */
1204 case 0xdaa1ffa8: /* stfd f21,-88(r1) */
1205 case 0xdac1ffb0: /* stfd f22,-80(r1) */
1206 case 0xdae1ffb8: /* stfd f23,-72(r1) */
1207 case 0xdb01ffc0: /* stfd f24,-64(r1) */
1208 case 0xdb21ffc8: /* stfd f25,-56(r1) */
1209 case 0xdb41ffd0: /* stfd f26,-48(r1) */
1210 case 0xdb61ffd8: /* stfd f27,-40(r1) */
1211 case 0xdb81ffe0: /* stfd f28,-32(r1) */
1212 case 0xdba1ffe8: /* stfd f29,-24(r1) */
1213 case 0xdbc1fff0: /* stfd f30,-16(r1) */
1214 case 0xdbe1fff8: /* stfd f31,-8(r1) */
1215 return False;
1216 }
1217 }
1218 }
1219 return True;
1220}
sewardj34593e52006-01-17 01:57:33 +00001221
1222/* --------------- main translation function --------------- */
1223
sewardj0ec07f32006-01-12 12:32:32 +00001224/* Note: see comments at top of m_redir.c for the Big Picture on how
1225 redirections are managed. */
1226
sewardj34593e52006-01-17 01:57:33 +00001227typedef
1228 enum {
1229 /* normal translation, redir neither requested nor inhibited */
1230 T_Normal,
1231 /* redir translation, function-wrap (set _NRADDR) style */
1232 T_Redir_Wrap,
1233 /* redir translation, replacement (don't set _NRADDR) style */
1234 T_Redir_Replace,
1235 /* a translation in which redir is specifically disallowed */
1236 T_NoRedir
1237 }
1238 T_Kind;
1239
1240/* Translate the basic block beginning at NRADDR, and add it to the
1241 translation cache & translation table. Unless
1242 DEBUGGING_TRANSLATION is true, in which case the call is being done
1243 for debugging purposes, so (a) throw away the translation once it
1244 is made, and (b) produce a load of debugging output. If
1245 ALLOW_REDIRECTION is False, do not attempt redirection of NRADDR,
1246 and also, put the resulting translation into the no-redirect tt/tc
1247 instead of the normal one.
1248
1249 TID is the identity of the thread requesting this translation.
1250*/
1251
sewardjfa8ec112005-01-19 11:55:34 +00001252Bool VG_(translate) ( ThreadId tid,
sewardj34593e52006-01-17 01:57:33 +00001253 Addr64 nraddr,
sewardjfa8ec112005-01-19 11:55:34 +00001254 Bool debugging_translation,
njn394213a2005-06-19 18:38:24 +00001255 Int debugging_verbosity,
sewardj0ec07f32006-01-12 12:32:32 +00001256 ULong bbs_done,
1257 Bool allow_redirection )
sewardjde4a1d02002-03-22 01:27:54 +00001258{
sewardj34593e52006-01-17 01:57:33 +00001259 Addr64 addr;
1260 T_Kind kind;
sewardje2d1e672005-11-12 23:10:48 +00001261 Int tmpbuf_used, verbosity, i;
1262 Bool notrace_until_done, do_self_check;
1263 UInt notrace_until_limit = 0;
sewardj0b9d74a2006-12-24 02:24:11 +00001264 Bool (*preamble_fn)(void*,IRSB*);
sewardje2d1e672005-11-12 23:10:48 +00001265 VexArch vex_arch;
1266 VexArchInfo vex_archinfo;
sewardj0b9d74a2006-12-24 02:24:11 +00001267 VexAbiInfo vex_abiinfo;
sewardje2d1e672005-11-12 23:10:48 +00001268 VexGuestExtents vge;
sewardj274807d2005-12-15 14:07:07 +00001269 VexTranslateArgs vta;
sewardje2d1e672005-11-12 23:10:48 +00001270 VexTranslateResult tres;
sewardj34593e52006-01-17 01:57:33 +00001271 VgCallbackClosure closure;
njn36932cb2005-05-11 22:45:48 +00001272
sewardj8b635a42004-11-22 19:01:47 +00001273 /* Make sure Vex is initialised right. */
sewardje2d1e672005-11-12 23:10:48 +00001274
sewardj8b635a42004-11-22 19:01:47 +00001275 static Bool vex_init_done = False;
1276
1277 if (!vex_init_done) {
1278 LibVEX_Init ( &failure_exit, &log_bytes,
1279 1, /* debug_paranoia */
1280 False, /* valgrind support */
1281 &VG_(clo_vex_control) );
1282 vex_init_done = True;
1283 }
1284
sewardj34593e52006-01-17 01:57:33 +00001285 /* Establish the translation kind and actual guest address to
1286 start from. Sets (addr,kind). */
sewardj0ec07f32006-01-12 12:32:32 +00001287 if (allow_redirection) {
sewardj34593e52006-01-17 01:57:33 +00001288 Bool isWrap;
1289 Addr64 tmp = VG_(redir_do_lookup)( nraddr, &isWrap );
1290 if (tmp == nraddr) {
1291 /* no redirection found */
1292 addr = nraddr;
1293 kind = T_Normal;
1294 } else {
1295 /* found a redirect */
1296 addr = tmp;
1297 kind = isWrap ? T_Redir_Wrap : T_Redir_Replace;
1298 }
sewardj0ec07f32006-01-12 12:32:32 +00001299 } else {
sewardj34593e52006-01-17 01:57:33 +00001300 addr = nraddr;
1301 kind = T_NoRedir;
sewardj0ec07f32006-01-12 12:32:32 +00001302 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001303
sewardj34593e52006-01-17 01:57:33 +00001304 /* Established: (nraddr, addr, kind) */
sewardj0ec07f32006-01-12 12:32:32 +00001305
sewardj34593e52006-01-17 01:57:33 +00001306 /* Printing redirection info. */
1307
1308 if ((kind == T_Redir_Wrap || kind == T_Redir_Replace)
sewardj0ec07f32006-01-12 12:32:32 +00001309 && (VG_(clo_verbosity) >= 2 || VG_(clo_trace_redir))) {
sewardjfa8ec112005-01-19 11:55:34 +00001310 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +00001311 Char name1[64] = "";
1312 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +00001313 name1[0] = name2[0] = 0;
sewardj34593e52006-01-17 01:57:33 +00001314 ok = VG_(get_fnname_w_offset)(nraddr, name1, 64);
njnbe73f432005-03-26 21:34:45 +00001315 if (!ok) VG_(strcpy)(name1, "???");
sewardj34593e52006-01-17 01:57:33 +00001316 ok = VG_(get_fnname_w_offset)(addr, name2, 64);
njnbe73f432005-03-26 21:34:45 +00001317 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +00001318 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +00001319 "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)\n",
sewardj34593e52006-01-17 01:57:33 +00001320 nraddr, name1,
1321 addr, name2 );
nethercote59a122d2004-08-03 17:16:51 +00001322 }
sewardj25c7c3a2003-07-10 00:17:58 +00001323
sewardja60be0e2003-05-26 08:47:27 +00001324 /* If codegen tracing, don't start tracing until
1325 notrace_until_limit blocks have gone by. This avoids printing
1326 huge amounts of useless junk when all we want to see is the last
1327 few blocks translated prior to a failure. Set
1328 notrace_until_limit to be the number of translations to be made
1329 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +00001330 notrace_until_done
1331 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +00001332
njn25e49d8e72002-09-23 09:36:25 +00001333 if (!debugging_translation)
sewardj45f4e7c2005-09-27 19:20:21 +00001334 VG_TRACK( pre_mem_read, Vg_CoreTranslate,
sewardj34593e52006-01-17 01:57:33 +00001335 tid, "(translator)", addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +00001336
sewardj85ac6d42005-02-23 11:36:56 +00001337 /* If doing any code printing, print a basic block start marker */
1338 if (VG_(clo_trace_flags) || debugging_translation) {
1339 Char fnname[64] = "";
sewardj34593e52006-01-17 01:57:33 +00001340 VG_(get_fnname_w_offset)(addr, fnname, 64);
sewardj85ac6d42005-02-23 11:36:56 +00001341 VG_(printf)(
sewardje7d46072010-03-03 22:55:42 +00001342 "==== SB %d [tid %d] %s(0x%llx) SBs exec'd %lld ====\n",
1343 VG_(get_bbs_translated)(), (Int)tid, fnname, addr,
njn394213a2005-06-19 18:38:24 +00001344 bbs_done);
sewardj85ac6d42005-02-23 11:36:56 +00001345 }
1346
sewardj45f4e7c2005-09-27 19:20:21 +00001347 /* Are we allowed to translate here? */
1348
sewardj4a0009c2006-10-17 01:52:05 +00001349 { /* BEGIN new scope specially for 'seg' */
1350 NSegment const* seg = VG_(am_find_nsegment)(addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001351
sewardj5f76de02007-02-11 05:08:06 +00001352 if ( (!translations_allowable_from_seg(seg))
1353 || addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
sewardj4a0009c2006-10-17 01:52:05 +00001354 if (VG_(clo_trace_signals))
sewardja5940262007-09-10 16:28:38 +00001355 VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%llx)"
sewardj738856f2009-07-15 14:48:32 +00001356 " - throwing SEGV\n", addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001357 /* U R busted, sonny. Place your hands on your head and step
1358 away from the orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001359 /* Code address is bad - deliver a signal instead */
sewardj45f4e7c2005-09-27 19:20:21 +00001360 if (seg != NULL) {
1361 /* There's some kind of segment at the requested place, but we
1362 aren't allowed to execute code here. */
sewardj34593e52006-01-17 01:57:33 +00001363 VG_(synth_fault_perms)(tid, addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001364 } else {
1365 /* There is no segment at all; we are attempting to execute in
1366 the middle of nowhere. */
sewardj34593e52006-01-17 01:57:33 +00001367 VG_(synth_fault_mapping)(tid, addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001368 }
nethercote4d714382004-10-13 09:47:24 +00001369 return False;
sewardj45f4e7c2005-09-27 19:20:21 +00001370 }
sewardjde4a1d02002-03-22 01:27:54 +00001371
sewardj26412bd2005-07-07 10:05:05 +00001372 /* Do we want a self-checking translation? */
sewardj34593e52006-01-17 01:57:33 +00001373 do_self_check = self_check_required( seg, tid );
sewardj26412bd2005-07-07 10:05:05 +00001374
njn25e49d8e72002-09-23 09:36:25 +00001375 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +00001376 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +00001377 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +00001378 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +00001379 }
1380 else
sewardjfa8ec112005-01-19 11:55:34 +00001381 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +00001382 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +00001383 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +00001384 }
njn25e49d8e72002-09-23 09:36:25 +00001385
sewardj34593e52006-01-17 01:57:33 +00001386 /* Figure out which preamble-mangling callback to send. */
1387 preamble_fn = NULL;
1388 if (kind == T_Redir_Replace)
1389 preamble_fn = mk_preamble__set_NRADDR_to_zero;
1390 else
1391 if (kind == T_Redir_Wrap)
1392 preamble_fn = mk_preamble__set_NRADDR_to_nraddr;
sewardj4a0009c2006-10-17 01:52:05 +00001393
1394# if defined(VG_PLAT_USES_PPCTOC)
1395 if (ULong_to_Ptr(nraddr)
1396 == (void*)&VG_(ppctoc_magic_redirect_return_stub)) {
sewardj34593e52006-01-17 01:57:33 +00001397 /* If entering the special return stub, this means a wrapped or
1398 redirected function is returning. Make this translation one
1399 which restores R2 and LR from the thread's hidden redir
1400 stack, and branch to the (restored) link register, thereby
1401 really causing the function to return. */
1402 vg_assert(kind == T_Normal);
1403 vg_assert(nraddr == addr);
sewardj4a0009c2006-10-17 01:52:05 +00001404 preamble_fn = mk_preamble__ppctoc_magic_return_stub;
1405 }
sewardj34593e52006-01-17 01:57:33 +00001406# endif
1407
sewardje2d1e672005-11-12 23:10:48 +00001408 /* ------ Actually do the translation. ------ */
njn51d827b2005-05-09 01:02:08 +00001409 tl_assert2(VG_(tdict).tool_instrument,
1410 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj7be55092005-08-01 23:25:55 +00001411
sewardje2d1e672005-11-12 23:10:48 +00001412 /* Get the CPU info established at startup. */
1413 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1414
sewardj0b9d74a2006-12-24 02:24:11 +00001415 /* Set up 'abiinfo' structure with stuff Vex needs to know about
sewardj4a0009c2006-10-17 01:52:05 +00001416 the guest and host ABIs. */
1417
sewardj0b9d74a2006-12-24 02:24:11 +00001418 LibVEX_default_VexAbiInfo( &vex_abiinfo );
1419 vex_abiinfo.guest_stack_redzone_size = VG_STACK_REDZONE_SZB;
sewardj4a0009c2006-10-17 01:52:05 +00001420
sewardjc0b20392008-12-04 00:07:30 +00001421# if defined(VGP_amd64_linux)
1422 vex_abiinfo.guest_amd64_assume_fs_is_zero = True;
1423# endif
njnf76d27a2009-05-28 01:53:07 +00001424# if defined(VGP_amd64_darwin)
1425 vex_abiinfo.guest_amd64_assume_gs_is_0x60 = True;
1426# endif
sewardj4a0009c2006-10-17 01:52:05 +00001427# if defined(VGP_ppc32_linux)
sewardj0b9d74a2006-12-24 02:24:11 +00001428 vex_abiinfo.guest_ppc_zap_RZ_at_blr = False;
1429 vex_abiinfo.guest_ppc_zap_RZ_at_bl = NULL;
1430 vex_abiinfo.host_ppc32_regalign_int64_args = True;
sewardj4a0009c2006-10-17 01:52:05 +00001431# endif
1432# if defined(VGP_ppc64_linux)
sewardj0b9d74a2006-12-24 02:24:11 +00001433 vex_abiinfo.guest_ppc_zap_RZ_at_blr = True;
1434 vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True;
1435 vex_abiinfo.host_ppc_calls_use_fndescrs = True;
sewardj4a0009c2006-10-17 01:52:05 +00001436# endif
1437# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj0b9d74a2006-12-24 02:24:11 +00001438 vex_abiinfo.guest_ppc_zap_RZ_at_blr = False;
1439 vex_abiinfo.guest_ppc_zap_RZ_at_bl = bl_RZ_zap_ok_for_AIX;
1440 vex_abiinfo.guest_ppc_sc_continues_at_LR = True;
1441 vex_abiinfo.host_ppc_calls_use_fndescrs = True;
sewardj4a0009c2006-10-17 01:52:05 +00001442# endif
1443
sewardj34593e52006-01-17 01:57:33 +00001444 /* Set up closure args. */
1445 closure.tid = tid;
1446 closure.nraddr = nraddr;
1447 closure.readdr = addr;
sewardj7be55092005-08-01 23:25:55 +00001448
sewardj0ec07f32006-01-12 12:32:32 +00001449 /* Set up args for LibVEX_Translate. */
sewardj274807d2005-12-15 14:07:07 +00001450 vta.arch_guest = vex_arch;
1451 vta.archinfo_guest = vex_archinfo;
1452 vta.arch_host = vex_arch;
1453 vta.archinfo_host = vex_archinfo;
sewardj0b9d74a2006-12-24 02:24:11 +00001454 vta.abiinfo_both = vex_abiinfo;
sewardj34593e52006-01-17 01:57:33 +00001455 vta.guest_bytes = (UChar*)ULong_to_Ptr(addr);
1456 vta.guest_bytes_addr = (Addr64)addr;
1457 vta.callback_opaque = (void*)&closure;
sewardj274807d2005-12-15 14:07:07 +00001458 vta.chase_into_ok = chase_into_ok;
sewardj34593e52006-01-17 01:57:33 +00001459 vta.preamble_function = preamble_fn;
sewardj274807d2005-12-15 14:07:07 +00001460 vta.guest_extents = &vge;
1461 vta.host_bytes = tmpbuf;
1462 vta.host_bytes_size = N_TMPBUF;
1463 vta.host_bytes_used = &tmpbuf_used;
sewardj34593e52006-01-17 01:57:33 +00001464 { /* At this point we have to reconcile Vex's view of the
1465 instrumentation callback - which takes a void* first argument
1466 - with Valgrind's view, in which the first arg is a
1467 VgCallbackClosure*. Hence the following longwinded casts.
1468 They are entirely legal but longwinded so as to maximise the
1469 chance of the C typechecker picking up any type snafus. */
sewardj0b9d74a2006-12-24 02:24:11 +00001470 IRSB*(*f)(VgCallbackClosure*,
1471 IRSB*,VexGuestLayout*,VexGuestExtents*,
sewardj34593e52006-01-17 01:57:33 +00001472 IRType,IRType)
1473 = VG_(tdict).tool_instrument;
sewardj0b9d74a2006-12-24 02:24:11 +00001474 IRSB*(*g)(void*,
1475 IRSB*,VexGuestLayout*,VexGuestExtents*,
sewardj34593e52006-01-17 01:57:33 +00001476 IRType,IRType)
sewardj0b9d74a2006-12-24 02:24:11 +00001477 = (IRSB*(*)(void*,IRSB*,VexGuestLayout*,VexGuestExtents*,IRType,IRType))f;
sewardj34593e52006-01-17 01:57:33 +00001478 vta.instrument1 = g;
1479 }
1480 /* No need for type kludgery here. */
sewardj274807d2005-12-15 14:07:07 +00001481 vta.instrument2 = need_to_handle_SP_assignment()
1482 ? vg_SP_update_pass
1483 : NULL;
sewardj81651dc2007-08-28 06:05:20 +00001484 vta.finaltidy = VG_(needs).final_IR_tidy_pass
1485 ? VG_(tdict).tool_final_IR_tidy_pass
1486 : NULL;
sewardj274807d2005-12-15 14:07:07 +00001487 vta.do_self_check = do_self_check;
1488 vta.traceflags = verbosity;
1489
1490 /* Set up the dispatch-return info. For archs without a link
1491 register, vex generates a jump back to the specified dispatch
1492 address. Else, it just generates a branch-to-LR. */
1493# if defined(VGA_x86) || defined(VGA_amd64)
sewardj0ec07f32006-01-12 12:32:32 +00001494 vta.dispatch
1495 = (!allow_redirection)
1496 ? /* It's a no-redir translation. Will be run with the nonstandard
1497 dispatcher VG_(run_a_noredir_translation)
1498 and so needs a nonstandard return point. */
1499 (void*) &VG_(run_a_noredir_translation__return_point)
1500
1501 : /* normal translation. Uses VG_(run_innerloop). Return
1502 point depends on whether we're profiling bbs or not. */
1503 VG_(clo_profile_flags) > 0
1504 ? (void*) &VG_(run_innerloop__dispatch_profiled)
1505 : (void*) &VG_(run_innerloop__dispatch_unprofiled);
sewardj59570ff2010-01-01 11:59:33 +00001506# elif defined(VGA_ppc32) || defined(VGA_ppc64) \
1507 || defined(VGA_arm)
sewardj274807d2005-12-15 14:07:07 +00001508 vta.dispatch = NULL;
1509# else
1510# error "Unknown arch"
1511# endif
1512
1513 /* Sheesh. Finally, actually _do_ the translation! */
1514 tres = LibVEX_Translate ( &vta );
njn25e49d8e72002-09-23 09:36:25 +00001515
sewardjbf426512005-01-17 18:35:30 +00001516 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +00001517 vg_assert(tmpbuf_used <= N_TMPBUF);
1518 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +00001519
sewardj45f4e7c2005-09-27 19:20:21 +00001520 /* Tell aspacem of all segments that have had translations taken
1521 from them. Optimisation: don't re-look up vge.base[0] since seg
1522 should already point to it. */
1523
sewardj34593e52006-01-17 01:57:33 +00001524 vg_assert( vge.base[0] == (Addr64)addr );
sewardj4a0009c2006-10-17 01:52:05 +00001525 /* set 'translations taken from this segment' flag */
1526 VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
1527 } /* END new scope specially for 'seg' */
sewardj45f4e7c2005-09-27 19:20:21 +00001528
1529 for (i = 1; i < vge.n_used; i++) {
sewardj4a0009c2006-10-17 01:52:05 +00001530 NSegment const* seg
1531 = VG_(am_find_nsegment)( vge.base[i] );
1532 /* set 'translations taken from this segment' flag */
1533 VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
sewardj45f4e7c2005-09-27 19:20:21 +00001534 }
1535
nethercote59a122d2004-08-03 17:16:51 +00001536 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +00001537 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +00001538
1539 // If debugging, don't do anything with the translated block; we
1540 // only did this for the debugging output produced along the way.
1541 if (!debugging_translation) {
sewardj0ec07f32006-01-12 12:32:32 +00001542
sewardj34593e52006-01-17 01:57:33 +00001543 if (kind != T_NoRedir) {
sewardj0ec07f32006-01-12 12:32:32 +00001544 // Put it into the normal TT/TC structures. This is the
1545 // normal case.
1546
sewardj34593e52006-01-17 01:57:33 +00001547 // Note that we use nraddr (the non-redirected address), not
1548 // addr, which might have been changed by the redirection
sewardj0ec07f32006-01-12 12:32:32 +00001549 VG_(add_to_transtab)( &vge,
sewardj34593e52006-01-17 01:57:33 +00001550 nraddr,
sewardj0ec07f32006-01-12 12:32:32 +00001551 (Addr)(&tmpbuf[0]),
1552 tmpbuf_used,
1553 do_self_check );
1554 } else {
1555 VG_(add_to_unredir_transtab)( &vge,
sewardj34593e52006-01-17 01:57:33 +00001556 nraddr,
sewardj0ec07f32006-01-12 12:32:32 +00001557 (Addr)(&tmpbuf[0]),
njn1dcee092009-02-24 03:07:37 +00001558 tmpbuf_used );
sewardj0ec07f32006-01-12 12:32:32 +00001559 }
sewardjde4a1d02002-03-22 01:27:54 +00001560 }
nethercote59a122d2004-08-03 17:16:51 +00001561
nethercote4d714382004-10-13 09:47:24 +00001562 return True;
sewardjde4a1d02002-03-22 01:27:54 +00001563}
1564
1565/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +00001566/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001567/*--------------------------------------------------------------------*/