blob: b5f346d14d2c2b1ae891689e1ae5d57fa545c8a9 [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
sewardj4d474d02008-02-11 11:34:59 +000011 Copyright (C) 2000-2008 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,
barta0b6b2c2008-07-07 06:49:24 +000077 "translate: fast SP updates identified: %'u (%s)",
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,
barta0b6b2c2008-07-07 06:49:24 +000082 "translate: generic_known SP updates identified: %'u (%s)",
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,
barta0b6b2c2008-07-07 06:49:24 +000087 "translate: generic_unknown SP updates identified: %'u (%s)",
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
701 && (seg->kind == SkAnonC || seg->kind == SkFileC)
702 && (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{
711 switch (VG_(clo_smc_check)) {
712 case Vg_SmcNone: return False;
713 case Vg_SmcAll: return True;
714 case Vg_SmcStack:
715 return seg
716 ? (seg->start <= VG_(get_SP)(tid)
717 && VG_(get_SP)(tid)+sizeof(Word)-1 <= seg->end)
718 : False;
719 break;
720 default:
721 vg_assert2(0, "unknown VG_(clo_smc_check) value");
722 }
723}
724
725
726/* This is a callback passed to LibVEX_Translate. It stops Vex from
727 chasing into function entry points that we wish to redirect.
728 Chasing across them obviously defeats the redirect mechanism, with
729 bad effects for Memcheck, Addrcheck, and possibly others.
sewardj447f2a12005-07-07 13:52:53 +0000730
731 Also, we must stop Vex chasing into blocks for which we might want
732 to self checking.
733*/
sewardj34593e52006-01-17 01:57:33 +0000734static Bool chase_into_ok ( void* closureV, Addr64 addr64 )
sewardj8b635a42004-11-22 19:01:47 +0000735{
sewardj34593e52006-01-17 01:57:33 +0000736 Addr addr = (Addr)addr64;
sewardj4a0009c2006-10-17 01:52:05 +0000737 NSegment const* seg = VG_(am_find_nsegment)(addr);
sewardj34593e52006-01-17 01:57:33 +0000738 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj45f4e7c2005-09-27 19:20:21 +0000739
sewardj447f2a12005-07-07 13:52:53 +0000740 /* Work through a list of possibilities why we might not want to
741 allow a chase. */
sewardj447f2a12005-07-07 13:52:53 +0000742
sewardj34593e52006-01-17 01:57:33 +0000743 /* Destination not in a plausible segment? */
sewardj45f4e7c2005-09-27 19:20:21 +0000744 if (!translations_allowable_from_seg(seg))
745 goto dontchase;
746
sewardj34593e52006-01-17 01:57:33 +0000747 /* Destination requires a self-check? */
748 if (self_check_required(seg, closure->tid))
749 goto dontchase;
sewardj447f2a12005-07-07 13:52:53 +0000750
751 /* Destination is redirected? */
sewardj0ec07f32006-01-12 12:32:32 +0000752 if (addr != VG_(redir_do_lookup)(addr, NULL))
sewardj447f2a12005-07-07 13:52:53 +0000753 goto dontchase;
754
sewardj4a0009c2006-10-17 01:52:05 +0000755# if defined(VG_PLAT_USES_PPCTOC)
756 /* This needs to be at the start of its own block. Don't chase. Re
757 ULong_to_Ptr, be careful to ensure we only compare 32 bits on a
758 32-bit target.*/
759 if (ULong_to_Ptr(addr64)
760 == (void*)&VG_(ppctoc_magic_redirect_return_stub))
sewardj34593e52006-01-17 01:57:33 +0000761 goto dontchase;
762# endif
763
sewardj5f76de02007-02-11 05:08:06 +0000764 /* overly conservative, but .. don't chase into the distinguished
765 address that m_transtab uses as an empty-slot marker for
766 VG_(tt_fast). */
767 if (addr == TRANSTAB_BOGUS_GUEST_ADDR)
768 goto dontchase;
769
sewardj447f2a12005-07-07 13:52:53 +0000770 /* well, ok then. go on and chase. */
771 return True;
772
773 vg_assert(0);
774 /*NOTREACHED*/
775
776 dontchase:
njn8a7b41b2007-09-23 00:51:24 +0000777 if (0) VG_(printf)("not chasing into 0x%lx\n", addr);
sewardj447f2a12005-07-07 13:52:53 +0000778 return False;
sewardj8b635a42004-11-22 19:01:47 +0000779}
780
sewardj447f2a12005-07-07 13:52:53 +0000781
sewardj4a0009c2006-10-17 01:52:05 +0000782/* --------------- helpers for with-TOC platforms --------------- */
783
784/* NOTE: with-TOC platforms are: ppc64-linux, ppc32-aix5, ppc64-aix5. */
sewardjdfbaa222006-01-18 04:25:20 +0000785
sewardjd68ac3e2006-01-20 14:31:57 +0000786static IRExpr* mkU64 ( ULong n ) {
sewardj34593e52006-01-17 01:57:33 +0000787 return IRExpr_Const(IRConst_U64(n));
788}
sewardjd68ac3e2006-01-20 14:31:57 +0000789static IRExpr* mkU32 ( UInt n ) {
790 return IRExpr_Const(IRConst_U32(n));
791}
sewardj4a0009c2006-10-17 01:52:05 +0000792
793#if defined(VG_PLAT_USES_PPCTOC)
sewardjd68ac3e2006-01-20 14:31:57 +0000794static IRExpr* mkU8 ( UChar n ) {
795 return IRExpr_Const(IRConst_U8(n));
796}
sewardj4a0009c2006-10-17 01:52:05 +0000797static IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) {
798 if (typeOfIRExpr(tyenv, e) == Ity_I32) {
799 return e;
800 } else {
801 vg_assert(typeOfIRExpr(tyenv, e) == Ity_I64);
802 return IRExpr_Unop(Iop_64to32, e);
803 }
804}
805
806/* Generate code to push word-typed expression 'e' onto this thread's
807 redir stack, checking for stack overflow and generating code to
808 bomb out if so. */
sewardj34593e52006-01-17 01:57:33 +0000809
sewardj0b9d74a2006-12-24 02:24:11 +0000810static void gen_PUSH ( IRSB* bb, IRExpr* e )
sewardj34593e52006-01-17 01:57:33 +0000811{
sewardj0b9d74a2006-12-24 02:24:11 +0000812 IRRegArray* descr;
813 IRTemp t1;
814 IRExpr* one;
sewardj34593e52006-01-17 01:57:33 +0000815
sewardj4a0009c2006-10-17 01:52:05 +0000816# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
817 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
818 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
819 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
820 Int offB_EMWARN = offsetof(VexGuestPPC64State,guest_EMWARN);
821 Bool is64 = True;
822 IRType ty_Word = Ity_I64;
823 IROp op_CmpNE = Iop_CmpNE64;
824 IROp op_Sar = Iop_Sar64;
825 IROp op_Sub = Iop_Sub64;
826 IROp op_Add = Iop_Add64;
827 IRExpr*(*mkU)(ULong) = mkU64;
828 vg_assert(VG_WORDSIZE == 8);
829# else
830 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
831 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
832 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
833 Int offB_EMWARN = offsetof(VexGuestPPC32State,guest_EMWARN);
834 Bool is64 = False;
835 IRType ty_Word = Ity_I32;
836 IROp op_CmpNE = Iop_CmpNE32;
837 IROp op_Sar = Iop_Sar32;
838 IROp op_Sub = Iop_Sub32;
839 IROp op_Add = Iop_Add32;
840 IRExpr*(*mkU)(UInt) = mkU32;
841 vg_assert(VG_WORDSIZE == 4);
842# endif
843
844 vg_assert(sizeof(void*) == VG_WORDSIZE);
845 vg_assert(sizeof(Word) == VG_WORDSIZE);
846 vg_assert(sizeof(Addr) == VG_WORDSIZE);
847
sewardj0b9d74a2006-12-24 02:24:11 +0000848 descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
sewardj4a0009c2006-10-17 01:52:05 +0000849 t1 = newIRTemp( bb->tyenv, ty_Word );
850 one = mkU(1);
851
852 vg_assert(typeOfIRExpr(bb->tyenv, e) == ty_Word);
sewardj34593e52006-01-17 01:57:33 +0000853
854 /* t1 = guest_REDIR_SP + 1 */
sewardj0b9d74a2006-12-24 02:24:11 +0000855 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000856 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000857 IRStmt_WrTmp(
sewardj34593e52006-01-17 01:57:33 +0000858 t1,
sewardj4a0009c2006-10-17 01:52:05 +0000859 IRExpr_Binop(op_Add, IRExpr_Get( offB_REDIR_SP, ty_Word ), one)
sewardj34593e52006-01-17 01:57:33 +0000860 )
861 );
862
sewardjd68ac3e2006-01-20 14:31:57 +0000863 /* Bomb out if t1 >=s stack_size, that is, (stack_size-1)-t1 <s 0.
864 The destination (0) is a bit bogus but it doesn't matter since
865 this is an unrecoverable error and will lead to Valgrind
866 shutting down. _EMWARN is set regardless - that's harmless
867 since is only has a meaning if the exit is taken. */
sewardj0b9d74a2006-12-24 02:24:11 +0000868 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000869 bb,
870 IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_overflow))
871 );
sewardj0b9d74a2006-12-24 02:24:11 +0000872 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000873 bb,
874 IRStmt_Exit(
875 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000876 op_CmpNE,
sewardjd68ac3e2006-01-20 14:31:57 +0000877 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000878 op_Sar,
sewardj0b9d74a2006-12-24 02:24:11 +0000879 IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_RdTmp(t1)),
sewardj4a0009c2006-10-17 01:52:05 +0000880 mkU8(8 * VG_WORDSIZE - 1)
sewardjd68ac3e2006-01-20 14:31:57 +0000881 ),
sewardj4a0009c2006-10-17 01:52:05 +0000882 mkU(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000883 ),
884 Ijk_EmFail,
sewardj4a0009c2006-10-17 01:52:05 +0000885 is64 ? IRConst_U64(0) : IRConst_U32(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000886 )
887 );
sewardj34593e52006-01-17 01:57:33 +0000888
889 /* guest_REDIR_SP = t1 */
sewardj0b9d74a2006-12-24 02:24:11 +0000890 addStmtToIRSB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_RdTmp(t1)));
sewardj34593e52006-01-17 01:57:33 +0000891
892 /* guest_REDIR_STACK[t1+0] = e */
sewardj4a0009c2006-10-17 01:52:05 +0000893 /* PutI/GetI have I32-typed indexes regardless of guest word size */
sewardj0b9d74a2006-12-24 02:24:11 +0000894 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000895 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000896 IRStmt_PutI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0, e)
sewardj34593e52006-01-17 01:57:33 +0000897 );
898}
899
sewardj4a0009c2006-10-17 01:52:05 +0000900
901/* Generate code to pop a word-sized value from this thread's redir
902 stack, binding it to a new temporary, which is returned. As with
903 gen_PUSH, an overflow check is also performed. */
904
sewardj0b9d74a2006-12-24 02:24:11 +0000905static IRTemp gen_POP ( IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +0000906{
sewardj4a0009c2006-10-17 01:52:05 +0000907# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
908 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
909 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
910 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
911 Int offB_EMWARN = offsetof(VexGuestPPC64State,guest_EMWARN);
912 Bool is64 = True;
913 IRType ty_Word = Ity_I64;
914 IROp op_CmpNE = Iop_CmpNE64;
915 IROp op_Sar = Iop_Sar64;
916 IROp op_Sub = Iop_Sub64;
917 IRExpr*(*mkU)(ULong) = mkU64;
918# else
919 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
920 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
921 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
922 Int offB_EMWARN = offsetof(VexGuestPPC32State,guest_EMWARN);
923 Bool is64 = False;
924 IRType ty_Word = Ity_I32;
925 IROp op_CmpNE = Iop_CmpNE32;
926 IROp op_Sar = Iop_Sar32;
927 IROp op_Sub = Iop_Sub32;
928 IRExpr*(*mkU)(UInt) = mkU32;
929# endif
sewardj34593e52006-01-17 01:57:33 +0000930
sewardj0b9d74a2006-12-24 02:24:11 +0000931 IRRegArray* descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
932 IRTemp t1 = newIRTemp( bb->tyenv, ty_Word );
933 IRTemp res = newIRTemp( bb->tyenv, ty_Word );
934 IRExpr* one = mkU(1);
sewardj4a0009c2006-10-17 01:52:05 +0000935
936 vg_assert(sizeof(void*) == VG_WORDSIZE);
937 vg_assert(sizeof(Word) == VG_WORDSIZE);
938 vg_assert(sizeof(Addr) == VG_WORDSIZE);
sewardj34593e52006-01-17 01:57:33 +0000939
940 /* t1 = guest_REDIR_SP */
sewardj0b9d74a2006-12-24 02:24:11 +0000941 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000942 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000943 IRStmt_WrTmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) )
sewardj34593e52006-01-17 01:57:33 +0000944 );
945
sewardjd68ac3e2006-01-20 14:31:57 +0000946 /* Bomb out if t1 < 0. Same comments as gen_PUSH apply. */
sewardj0b9d74a2006-12-24 02:24:11 +0000947 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000948 bb,
949 IRStmt_Put(offB_EMWARN, mkU32(EmWarn_PPC64_redir_underflow))
950 );
sewardj0b9d74a2006-12-24 02:24:11 +0000951 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +0000952 bb,
953 IRStmt_Exit(
954 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000955 op_CmpNE,
sewardjd68ac3e2006-01-20 14:31:57 +0000956 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +0000957 op_Sar,
sewardj0b9d74a2006-12-24 02:24:11 +0000958 IRExpr_RdTmp(t1),
sewardj4a0009c2006-10-17 01:52:05 +0000959 mkU8(8 * VG_WORDSIZE - 1)
sewardjd68ac3e2006-01-20 14:31:57 +0000960 ),
sewardj4a0009c2006-10-17 01:52:05 +0000961 mkU(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000962 ),
963 Ijk_EmFail,
sewardj4a0009c2006-10-17 01:52:05 +0000964 is64 ? IRConst_U64(0) : IRConst_U32(0)
sewardjd68ac3e2006-01-20 14:31:57 +0000965 )
966 );
sewardj34593e52006-01-17 01:57:33 +0000967
968 /* res = guest_REDIR_STACK[t1+0] */
sewardj4a0009c2006-10-17 01:52:05 +0000969 /* PutI/GetI have I32-typed indexes regardless of guest word size */
sewardj0b9d74a2006-12-24 02:24:11 +0000970 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000971 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000972 IRStmt_WrTmp(
sewardj34593e52006-01-17 01:57:33 +0000973 res,
sewardj0b9d74a2006-12-24 02:24:11 +0000974 IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0)
sewardj34593e52006-01-17 01:57:33 +0000975 )
976 );
977
978 /* guest_REDIR_SP = t1-1 */
sewardj0b9d74a2006-12-24 02:24:11 +0000979 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +0000980 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000981 IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(op_Sub, IRExpr_RdTmp(t1), one))
sewardj34593e52006-01-17 01:57:33 +0000982 );
983
984 return res;
985}
986
sewardj4a0009c2006-10-17 01:52:05 +0000987/* Generate code to push LR and R2 onto this thread's redir stack,
988 then set R2 to the new value (which is the TOC pointer to be used
989 for the duration of the replacement function, as determined by
990 m_debuginfo), and set LR to the magic return stub, so we get to
991 intercept the return and restore R2 and L2 to the values saved
992 here. */
993
sewardj0b9d74a2006-12-24 02:24:11 +0000994static void gen_push_and_set_LR_R2 ( IRSB* bb, Addr64 new_R2_value )
sewardj34593e52006-01-17 01:57:33 +0000995{
sewardj4a0009c2006-10-17 01:52:05 +0000996# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
997 Addr64 bogus_RA = (Addr64)&VG_(ppctoc_magic_redirect_return_stub);
998 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
999 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
sewardj34593e52006-01-17 01:57:33 +00001000 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) );
1001 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
sewardj0b9d74a2006-12-24 02:24:11 +00001002 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) );
1003 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) );
sewardj4a0009c2006-10-17 01:52:05 +00001004
1005# elif defined(VGP_ppc32_aix5)
1006 Addr32 bogus_RA = (Addr32)&VG_(ppctoc_magic_redirect_return_stub);
1007 Int offB_GPR2 = offsetof(VexGuestPPC32State,guest_GPR2);
1008 Int offB_LR = offsetof(VexGuestPPC32State,guest_LR);
1009 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I32) );
1010 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I32) );
sewardj0b9d74a2006-12-24 02:24:11 +00001011 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU32( bogus_RA )) );
1012 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU32( new_R2_value )) );
sewardj4a0009c2006-10-17 01:52:05 +00001013
1014# else
1015# error Platform is not TOC-afflicted, fortunately
1016# endif
sewardj34593e52006-01-17 01:57:33 +00001017}
1018
sewardj0b9d74a2006-12-24 02:24:11 +00001019static void gen_pop_R2_LR_then_bLR ( IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001020{
sewardj4a0009c2006-10-17 01:52:05 +00001021# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
1022 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1023 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
1024 IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I64 );
1025 IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I64 );
sewardj34593e52006-01-17 01:57:33 +00001026 /* Restore R2 */
1027 old_R2 = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001028 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
sewardj34593e52006-01-17 01:57:33 +00001029 /* Restore LR */
1030 old_LR = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001031 addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
sewardj34593e52006-01-17 01:57:33 +00001032 /* Branch to LR */
1033 /* re boring, we arrived here precisely because a wrapped fn did a
1034 blr (hence Ijk_Ret); so we should just mark this jump as Boring,
sewardj4a0009c2006-10-17 01:52:05 +00001035 else one _Call will have resulted in two _Rets. */
sewardj34593e52006-01-17 01:57:33 +00001036 bb->jumpkind = Ijk_Boring;
sewardj0b9d74a2006-12-24 02:24:11 +00001037 bb->next = IRExpr_Binop(Iop_And64, IRExpr_RdTmp(old_LR), mkU64(~(3ULL)));
sewardj4a0009c2006-10-17 01:52:05 +00001038
1039# elif defined(VGP_ppc32_aix5)
1040 Int offB_GPR2 = offsetof(VexGuestPPC32State,guest_GPR2);
1041 Int offB_LR = offsetof(VexGuestPPC32State,guest_LR);
1042 IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I32 );
1043 IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I32 );
1044 /* Restore R2 */
1045 old_R2 = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001046 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
sewardj4a0009c2006-10-17 01:52:05 +00001047 /* Restore LR */
1048 old_LR = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001049 addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
sewardj4a0009c2006-10-17 01:52:05 +00001050
1051 /* Branch to LR */
1052 /* re boring, we arrived here precisely because a wrapped fn did a
1053 blr (hence Ijk_Ret); so we should just mark this jump as Boring,
1054 else one _Call will have resulted in two _Rets. */
1055 bb->jumpkind = Ijk_Boring;
sewardj0b9d74a2006-12-24 02:24:11 +00001056 bb->next = IRExpr_Binop(Iop_And32, IRExpr_RdTmp(old_LR), mkU32(~3));
sewardj4a0009c2006-10-17 01:52:05 +00001057
1058# else
1059# error Platform is not TOC-afflicted, fortunately
1060# endif
sewardj34593e52006-01-17 01:57:33 +00001061}
1062
1063static
sewardj0b9d74a2006-12-24 02:24:11 +00001064Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001065{
sewardj0283bae2006-01-22 01:15:36 +00001066 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj0b9d74a2006-12-24 02:24:11 +00001067 /* Since we're creating the entire IRSB right here, give it a
sewardj0283bae2006-01-22 01:15:36 +00001068 proper IMark, as it won't get one any other way, and cachegrind
1069 will barf if it doesn't have one (fair enough really). */
sewardj0b9d74a2006-12-24 02:24:11 +00001070 addStmtToIRSB( bb, IRStmt_IMark( closure->readdr, 4 ) );
sewardj0283bae2006-01-22 01:15:36 +00001071 /* Generate the magic sequence:
1072 pop R2 from hidden stack
1073 pop LR from hidden stack
1074 goto LR
1075 */
sewardj34593e52006-01-17 01:57:33 +00001076 gen_pop_R2_LR_then_bLR(bb);
1077 return True; /* True == this is the entire BB; don't disassemble any
1078 real insns into it - just hand it directly to
1079 optimiser/instrumenter/backend. */
1080}
1081#endif
1082
sewardj4a0009c2006-10-17 01:52:05 +00001083/* --------------- END helpers for with-TOC platforms --------------- */
sewardj34593e52006-01-17 01:57:33 +00001084
sewardj4a0009c2006-10-17 01:52:05 +00001085
1086/* This is the IR preamble generator used for replacement
sewardj0283bae2006-01-22 01:15:36 +00001087 functions. It adds code to set the guest_NRADDR{_GPR2} to zero
sewardj34593e52006-01-17 01:57:33 +00001088 (technically not necessary, but facilitates detecting mixups in
sewardj0283bae2006-01-22 01:15:36 +00001089 which a replacement function has been erroneously declared using
1090 VG_REPLACE_FUNCTION_Z{U,Z} when instead it should have been written
1091 using VG_WRAP_FUNCTION_Z{U,Z}).
sewardj34593e52006-01-17 01:57:33 +00001092
sewardj4a0009c2006-10-17 01:52:05 +00001093 On with-TOC platforms the follow hacks are also done: LR and R2 are
1094 pushed onto a hidden stack, R2 is set to the correct value for the
1095 replacement function, and LR is set to point at the magic
1096 return-stub address. Setting LR causes the return of the
1097 wrapped/redirected function to lead to our magic return stub, which
1098 restores LR and R2 from said stack and returns for real.
sewardjdfbaa222006-01-18 04:25:20 +00001099
sewardjb8b79ad2008-03-03 01:35:41 +00001100 VG_(get_StackTrace_wrk) understands that the LR value may point to
1101 the return stub address, and that in that case it can get the real
1102 LR value from the hidden stack instead. */
sewardj34593e52006-01-17 01:57:33 +00001103static
sewardj0b9d74a2006-12-24 02:24:11 +00001104Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001105{
sewardj34593e52006-01-17 01:57:33 +00001106 Int nraddr_szB
1107 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1108 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
sewardj4a0009c2006-10-17 01:52:05 +00001109 vg_assert(nraddr_szB == VG_WORDSIZE);
sewardj0b9d74a2006-12-24 02:24:11 +00001110 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001111 bb,
1112 IRStmt_Put(
1113 offsetof(VexGuestArchState,guest_NRADDR),
sewardj0283bae2006-01-22 01:15:36 +00001114 nraddr_szB == 8 ? mkU64(0) : mkU32(0)
sewardj34593e52006-01-17 01:57:33 +00001115 )
1116 );
sewardj4a0009c2006-10-17 01:52:05 +00001117# if defined(VG_PLAT_USES_PPCTOC)
sewardj0283bae2006-01-22 01:15:36 +00001118 { VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj0b9d74a2006-12-24 02:24:11 +00001119 addStmtToIRSB(
sewardj0283bae2006-01-22 01:15:36 +00001120 bb,
1121 IRStmt_Put(
1122 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
sewardj4a0009c2006-10-17 01:52:05 +00001123 VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
sewardj0283bae2006-01-22 01:15:36 +00001124 )
1125 );
1126 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1127 }
sewardj34593e52006-01-17 01:57:33 +00001128# endif
1129 return False;
1130}
1131
1132/* Ditto, except set guest_NRADDR to nraddr (the un-redirected guest
1133 address). This is needed for function wrapping - so the wrapper
1134 can read _NRADDR and find the address of the function being
sewardj4a0009c2006-10-17 01:52:05 +00001135 wrapped. On toc-afflicted platforms we must also snarf r2. */
sewardj34593e52006-01-17 01:57:33 +00001136static
sewardj0b9d74a2006-12-24 02:24:11 +00001137Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001138{
1139 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1140 Int nraddr_szB
1141 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1142 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
sewardj4a0009c2006-10-17 01:52:05 +00001143 vg_assert(nraddr_szB == VG_WORDSIZE);
sewardj0b9d74a2006-12-24 02:24:11 +00001144 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001145 bb,
1146 IRStmt_Put(
1147 offsetof(VexGuestArchState,guest_NRADDR),
1148 nraddr_szB == 8
1149 ? IRExpr_Const(IRConst_U64( closure->nraddr ))
1150 : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
1151 )
1152 );
sewardj4a0009c2006-10-17 01:52:05 +00001153# if defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
1154 || defined(VGP_ppc64_aix5)
sewardj0b9d74a2006-12-24 02:24:11 +00001155 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001156 bb,
1157 IRStmt_Put(
1158 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1159 IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2),
sewardj4a0009c2006-10-17 01:52:05 +00001160 VG_WORDSIZE==8 ? Ity_I64 : Ity_I32)
sewardjd68ac3e2006-01-20 14:31:57 +00001161 )
1162 );
sewardj34593e52006-01-17 01:57:33 +00001163 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1164# endif
1165 return False;
1166}
1167
sewardj4a0009c2006-10-17 01:52:05 +00001168/* --- Helpers to do with PPC related stack redzones. --- */
1169
1170__attribute__((unused))
1171static Bool const_True ( Addr64 guest_addr )
1172{
1173 return True;
1174}
1175
1176__attribute__((unused))
1177static Bool bl_RZ_zap_ok_for_AIX ( Addr64 bl_target )
1178{
1179 /* paranoia */
1180 if (sizeof(void*) == 4)
1181 bl_target &= 0xFFFFFFFFULL;
1182
1183 /* don't zap the redzone for calls to millicode. */
1184 if (bl_target < 0x10000ULL)
1185 return False;
1186
1187 /* don't zap the redzone for calls to .$SAVEF14 .. .$SAVEF31.
1188 First we need to be reasonably sure we won't segfault by looking
1189 at the branch target. */
1190 { NSegment const*const seg = VG_(am_find_nsegment)( (Addr)bl_target );
1191 if (seg && seg->hasR) {
1192 switch ( *(UInt*)(Addr)bl_target ) {
1193 case 0xd9c1ff70: /* stfd f14,-144(r1) */
1194 case 0xd9e1ff78: /* stfd f15,-136(r1) */
1195 case 0xda01ff80: /* stfd f16,-128(r1) */
1196 case 0xda21ff88: /* stfd f17,-120(r1) */
1197 case 0xda41ff90: /* stfd f18,-112(r1) */
1198 case 0xda61ff98: /* stfd f19,-104(r1) */
1199 case 0xda81ffa0: /* stfd f20,-96(r1) */
1200 case 0xdaa1ffa8: /* stfd f21,-88(r1) */
1201 case 0xdac1ffb0: /* stfd f22,-80(r1) */
1202 case 0xdae1ffb8: /* stfd f23,-72(r1) */
1203 case 0xdb01ffc0: /* stfd f24,-64(r1) */
1204 case 0xdb21ffc8: /* stfd f25,-56(r1) */
1205 case 0xdb41ffd0: /* stfd f26,-48(r1) */
1206 case 0xdb61ffd8: /* stfd f27,-40(r1) */
1207 case 0xdb81ffe0: /* stfd f28,-32(r1) */
1208 case 0xdba1ffe8: /* stfd f29,-24(r1) */
1209 case 0xdbc1fff0: /* stfd f30,-16(r1) */
1210 case 0xdbe1fff8: /* stfd f31,-8(r1) */
1211 return False;
1212 }
1213 }
1214 }
1215 return True;
1216}
sewardj34593e52006-01-17 01:57:33 +00001217
1218/* --------------- main translation function --------------- */
1219
sewardj0ec07f32006-01-12 12:32:32 +00001220/* Note: see comments at top of m_redir.c for the Big Picture on how
1221 redirections are managed. */
1222
sewardj34593e52006-01-17 01:57:33 +00001223typedef
1224 enum {
1225 /* normal translation, redir neither requested nor inhibited */
1226 T_Normal,
1227 /* redir translation, function-wrap (set _NRADDR) style */
1228 T_Redir_Wrap,
1229 /* redir translation, replacement (don't set _NRADDR) style */
1230 T_Redir_Replace,
1231 /* a translation in which redir is specifically disallowed */
1232 T_NoRedir
1233 }
1234 T_Kind;
1235
1236/* Translate the basic block beginning at NRADDR, and add it to the
1237 translation cache & translation table. Unless
1238 DEBUGGING_TRANSLATION is true, in which case the call is being done
1239 for debugging purposes, so (a) throw away the translation once it
1240 is made, and (b) produce a load of debugging output. If
1241 ALLOW_REDIRECTION is False, do not attempt redirection of NRADDR,
1242 and also, put the resulting translation into the no-redirect tt/tc
1243 instead of the normal one.
1244
1245 TID is the identity of the thread requesting this translation.
1246*/
1247
sewardjfa8ec112005-01-19 11:55:34 +00001248Bool VG_(translate) ( ThreadId tid,
sewardj34593e52006-01-17 01:57:33 +00001249 Addr64 nraddr,
sewardjfa8ec112005-01-19 11:55:34 +00001250 Bool debugging_translation,
njn394213a2005-06-19 18:38:24 +00001251 Int debugging_verbosity,
sewardj0ec07f32006-01-12 12:32:32 +00001252 ULong bbs_done,
1253 Bool allow_redirection )
sewardjde4a1d02002-03-22 01:27:54 +00001254{
sewardj34593e52006-01-17 01:57:33 +00001255 Addr64 addr;
1256 T_Kind kind;
sewardje2d1e672005-11-12 23:10:48 +00001257 Int tmpbuf_used, verbosity, i;
1258 Bool notrace_until_done, do_self_check;
1259 UInt notrace_until_limit = 0;
sewardj0b9d74a2006-12-24 02:24:11 +00001260 Bool (*preamble_fn)(void*,IRSB*);
sewardje2d1e672005-11-12 23:10:48 +00001261 VexArch vex_arch;
1262 VexArchInfo vex_archinfo;
sewardj0b9d74a2006-12-24 02:24:11 +00001263 VexAbiInfo vex_abiinfo;
sewardje2d1e672005-11-12 23:10:48 +00001264 VexGuestExtents vge;
sewardj274807d2005-12-15 14:07:07 +00001265 VexTranslateArgs vta;
sewardje2d1e672005-11-12 23:10:48 +00001266 VexTranslateResult tres;
sewardj34593e52006-01-17 01:57:33 +00001267 VgCallbackClosure closure;
njn36932cb2005-05-11 22:45:48 +00001268
sewardj8b635a42004-11-22 19:01:47 +00001269 /* Make sure Vex is initialised right. */
sewardje2d1e672005-11-12 23:10:48 +00001270
sewardj8b635a42004-11-22 19:01:47 +00001271 static Bool vex_init_done = False;
1272
1273 if (!vex_init_done) {
1274 LibVEX_Init ( &failure_exit, &log_bytes,
1275 1, /* debug_paranoia */
1276 False, /* valgrind support */
1277 &VG_(clo_vex_control) );
1278 vex_init_done = True;
1279 }
1280
sewardj34593e52006-01-17 01:57:33 +00001281 /* Establish the translation kind and actual guest address to
1282 start from. Sets (addr,kind). */
sewardj0ec07f32006-01-12 12:32:32 +00001283 if (allow_redirection) {
sewardj34593e52006-01-17 01:57:33 +00001284 Bool isWrap;
1285 Addr64 tmp = VG_(redir_do_lookup)( nraddr, &isWrap );
1286 if (tmp == nraddr) {
1287 /* no redirection found */
1288 addr = nraddr;
1289 kind = T_Normal;
1290 } else {
1291 /* found a redirect */
1292 addr = tmp;
1293 kind = isWrap ? T_Redir_Wrap : T_Redir_Replace;
1294 }
sewardj0ec07f32006-01-12 12:32:32 +00001295 } else {
sewardj34593e52006-01-17 01:57:33 +00001296 addr = nraddr;
1297 kind = T_NoRedir;
sewardj0ec07f32006-01-12 12:32:32 +00001298 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001299
sewardj34593e52006-01-17 01:57:33 +00001300 /* Established: (nraddr, addr, kind) */
sewardj0ec07f32006-01-12 12:32:32 +00001301
sewardj34593e52006-01-17 01:57:33 +00001302 /* Printing redirection info. */
1303
1304 if ((kind == T_Redir_Wrap || kind == T_Redir_Replace)
sewardj0ec07f32006-01-12 12:32:32 +00001305 && (VG_(clo_verbosity) >= 2 || VG_(clo_trace_redir))) {
sewardjfa8ec112005-01-19 11:55:34 +00001306 Bool ok;
sewardj8b635a42004-11-22 19:01:47 +00001307 Char name1[64] = "";
1308 Char name2[64] = "";
sewardjfa8ec112005-01-19 11:55:34 +00001309 name1[0] = name2[0] = 0;
sewardj34593e52006-01-17 01:57:33 +00001310 ok = VG_(get_fnname_w_offset)(nraddr, name1, 64);
njnbe73f432005-03-26 21:34:45 +00001311 if (!ok) VG_(strcpy)(name1, "???");
sewardj34593e52006-01-17 01:57:33 +00001312 ok = VG_(get_fnname_w_offset)(addr, name2, 64);
njnbe73f432005-03-26 21:34:45 +00001313 if (!ok) VG_(strcpy)(name2, "???");
njn3f04d242005-03-20 18:21:14 +00001314 VG_(message)(Vg_DebugMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001315 "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)",
sewardj34593e52006-01-17 01:57:33 +00001316 nraddr, name1,
1317 addr, name2 );
nethercote59a122d2004-08-03 17:16:51 +00001318 }
sewardj25c7c3a2003-07-10 00:17:58 +00001319
sewardja60be0e2003-05-26 08:47:27 +00001320 /* If codegen tracing, don't start tracing until
1321 notrace_until_limit blocks have gone by. This avoids printing
1322 huge amounts of useless junk when all we want to see is the last
1323 few blocks translated prior to a failure. Set
1324 notrace_until_limit to be the number of translations to be made
1325 before --trace-codegen= style printing takes effect. */
sewardjfa8ec112005-01-19 11:55:34 +00001326 notrace_until_done
1327 = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +00001328
njn25e49d8e72002-09-23 09:36:25 +00001329 if (!debugging_translation)
sewardj45f4e7c2005-09-27 19:20:21 +00001330 VG_TRACK( pre_mem_read, Vg_CoreTranslate,
sewardj34593e52006-01-17 01:57:33 +00001331 tid, "(translator)", addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +00001332
sewardj85ac6d42005-02-23 11:36:56 +00001333 /* If doing any code printing, print a basic block start marker */
1334 if (VG_(clo_trace_flags) || debugging_translation) {
1335 Char fnname[64] = "";
sewardj34593e52006-01-17 01:57:33 +00001336 VG_(get_fnname_w_offset)(addr, fnname, 64);
sewardj85ac6d42005-02-23 11:36:56 +00001337 VG_(printf)(
njn394213a2005-06-19 18:38:24 +00001338 "==== BB %d %s(0x%llx) BBs exec'd %lld ====\n",
sewardj34593e52006-01-17 01:57:33 +00001339 VG_(get_bbs_translated)(), fnname, addr,
njn394213a2005-06-19 18:38:24 +00001340 bbs_done);
sewardj85ac6d42005-02-23 11:36:56 +00001341 }
1342
sewardj45f4e7c2005-09-27 19:20:21 +00001343 /* Are we allowed to translate here? */
1344
sewardj4a0009c2006-10-17 01:52:05 +00001345 { /* BEGIN new scope specially for 'seg' */
1346 NSegment const* seg = VG_(am_find_nsegment)(addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001347
sewardj5f76de02007-02-11 05:08:06 +00001348 if ( (!translations_allowable_from_seg(seg))
1349 || addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
sewardj4a0009c2006-10-17 01:52:05 +00001350 if (VG_(clo_trace_signals))
sewardja5940262007-09-10 16:28:38 +00001351 VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%llx)"
1352 " - throwing SEGV", addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001353 /* U R busted, sonny. Place your hands on your head and step
1354 away from the orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001355 /* Code address is bad - deliver a signal instead */
sewardj45f4e7c2005-09-27 19:20:21 +00001356 if (seg != NULL) {
1357 /* There's some kind of segment at the requested place, but we
1358 aren't allowed to execute code here. */
sewardj34593e52006-01-17 01:57:33 +00001359 VG_(synth_fault_perms)(tid, addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001360 } else {
1361 /* There is no segment at all; we are attempting to execute in
1362 the middle of nowhere. */
sewardj34593e52006-01-17 01:57:33 +00001363 VG_(synth_fault_mapping)(tid, addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001364 }
nethercote4d714382004-10-13 09:47:24 +00001365 return False;
sewardj45f4e7c2005-09-27 19:20:21 +00001366 }
sewardjde4a1d02002-03-22 01:27:54 +00001367
sewardj26412bd2005-07-07 10:05:05 +00001368 /* Do we want a self-checking translation? */
sewardj34593e52006-01-17 01:57:33 +00001369 do_self_check = self_check_required( seg, tid );
sewardj26412bd2005-07-07 10:05:05 +00001370
njn25e49d8e72002-09-23 09:36:25 +00001371 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +00001372 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +00001373 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +00001374 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +00001375 }
1376 else
sewardjfa8ec112005-01-19 11:55:34 +00001377 if ( (VG_(clo_trace_flags) > 0
sewardj167d4e32004-12-31 01:14:04 +00001378 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +00001379 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +00001380 }
njn25e49d8e72002-09-23 09:36:25 +00001381
sewardj34593e52006-01-17 01:57:33 +00001382 /* Figure out which preamble-mangling callback to send. */
1383 preamble_fn = NULL;
1384 if (kind == T_Redir_Replace)
1385 preamble_fn = mk_preamble__set_NRADDR_to_zero;
1386 else
1387 if (kind == T_Redir_Wrap)
1388 preamble_fn = mk_preamble__set_NRADDR_to_nraddr;
sewardj4a0009c2006-10-17 01:52:05 +00001389
1390# if defined(VG_PLAT_USES_PPCTOC)
1391 if (ULong_to_Ptr(nraddr)
1392 == (void*)&VG_(ppctoc_magic_redirect_return_stub)) {
sewardj34593e52006-01-17 01:57:33 +00001393 /* If entering the special return stub, this means a wrapped or
1394 redirected function is returning. Make this translation one
1395 which restores R2 and LR from the thread's hidden redir
1396 stack, and branch to the (restored) link register, thereby
1397 really causing the function to return. */
1398 vg_assert(kind == T_Normal);
1399 vg_assert(nraddr == addr);
sewardj4a0009c2006-10-17 01:52:05 +00001400 preamble_fn = mk_preamble__ppctoc_magic_return_stub;
1401 }
sewardj34593e52006-01-17 01:57:33 +00001402# endif
1403
sewardje2d1e672005-11-12 23:10:48 +00001404 /* ------ Actually do the translation. ------ */
njn51d827b2005-05-09 01:02:08 +00001405 tl_assert2(VG_(tdict).tool_instrument,
1406 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj7be55092005-08-01 23:25:55 +00001407
sewardje2d1e672005-11-12 23:10:48 +00001408 /* Get the CPU info established at startup. */
1409 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1410
sewardj0b9d74a2006-12-24 02:24:11 +00001411 /* Set up 'abiinfo' structure with stuff Vex needs to know about
sewardj4a0009c2006-10-17 01:52:05 +00001412 the guest and host ABIs. */
1413
sewardj0b9d74a2006-12-24 02:24:11 +00001414 LibVEX_default_VexAbiInfo( &vex_abiinfo );
1415 vex_abiinfo.guest_stack_redzone_size = VG_STACK_REDZONE_SZB;
sewardj4a0009c2006-10-17 01:52:05 +00001416
sewardjc0b20392008-12-04 00:07:30 +00001417# if defined(VGP_amd64_linux)
1418 vex_abiinfo.guest_amd64_assume_fs_is_zero = True;
1419# endif
sewardj4a0009c2006-10-17 01:52:05 +00001420# if defined(VGP_ppc32_linux)
sewardj0b9d74a2006-12-24 02:24:11 +00001421 vex_abiinfo.guest_ppc_zap_RZ_at_blr = False;
1422 vex_abiinfo.guest_ppc_zap_RZ_at_bl = NULL;
1423 vex_abiinfo.host_ppc32_regalign_int64_args = True;
sewardj4a0009c2006-10-17 01:52:05 +00001424# endif
1425# if defined(VGP_ppc64_linux)
sewardj0b9d74a2006-12-24 02:24:11 +00001426 vex_abiinfo.guest_ppc_zap_RZ_at_blr = True;
1427 vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True;
1428 vex_abiinfo.host_ppc_calls_use_fndescrs = True;
sewardj4a0009c2006-10-17 01:52:05 +00001429# endif
1430# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj0b9d74a2006-12-24 02:24:11 +00001431 vex_abiinfo.guest_ppc_zap_RZ_at_blr = False;
1432 vex_abiinfo.guest_ppc_zap_RZ_at_bl = bl_RZ_zap_ok_for_AIX;
1433 vex_abiinfo.guest_ppc_sc_continues_at_LR = True;
1434 vex_abiinfo.host_ppc_calls_use_fndescrs = True;
sewardj4a0009c2006-10-17 01:52:05 +00001435# endif
1436
sewardj34593e52006-01-17 01:57:33 +00001437 /* Set up closure args. */
1438 closure.tid = tid;
1439 closure.nraddr = nraddr;
1440 closure.readdr = addr;
sewardj7be55092005-08-01 23:25:55 +00001441
sewardj0ec07f32006-01-12 12:32:32 +00001442 /* Set up args for LibVEX_Translate. */
sewardj274807d2005-12-15 14:07:07 +00001443 vta.arch_guest = vex_arch;
1444 vta.archinfo_guest = vex_archinfo;
1445 vta.arch_host = vex_arch;
1446 vta.archinfo_host = vex_archinfo;
sewardj0b9d74a2006-12-24 02:24:11 +00001447 vta.abiinfo_both = vex_abiinfo;
sewardj34593e52006-01-17 01:57:33 +00001448 vta.guest_bytes = (UChar*)ULong_to_Ptr(addr);
1449 vta.guest_bytes_addr = (Addr64)addr;
1450 vta.callback_opaque = (void*)&closure;
sewardj274807d2005-12-15 14:07:07 +00001451 vta.chase_into_ok = chase_into_ok;
sewardj34593e52006-01-17 01:57:33 +00001452 vta.preamble_function = preamble_fn;
sewardj274807d2005-12-15 14:07:07 +00001453 vta.guest_extents = &vge;
1454 vta.host_bytes = tmpbuf;
1455 vta.host_bytes_size = N_TMPBUF;
1456 vta.host_bytes_used = &tmpbuf_used;
sewardj34593e52006-01-17 01:57:33 +00001457 { /* At this point we have to reconcile Vex's view of the
1458 instrumentation callback - which takes a void* first argument
1459 - with Valgrind's view, in which the first arg is a
1460 VgCallbackClosure*. Hence the following longwinded casts.
1461 They are entirely legal but longwinded so as to maximise the
1462 chance of the C typechecker picking up any type snafus. */
sewardj0b9d74a2006-12-24 02:24:11 +00001463 IRSB*(*f)(VgCallbackClosure*,
1464 IRSB*,VexGuestLayout*,VexGuestExtents*,
sewardj34593e52006-01-17 01:57:33 +00001465 IRType,IRType)
1466 = VG_(tdict).tool_instrument;
sewardj0b9d74a2006-12-24 02:24:11 +00001467 IRSB*(*g)(void*,
1468 IRSB*,VexGuestLayout*,VexGuestExtents*,
sewardj34593e52006-01-17 01:57:33 +00001469 IRType,IRType)
sewardj0b9d74a2006-12-24 02:24:11 +00001470 = (IRSB*(*)(void*,IRSB*,VexGuestLayout*,VexGuestExtents*,IRType,IRType))f;
sewardj34593e52006-01-17 01:57:33 +00001471 vta.instrument1 = g;
1472 }
1473 /* No need for type kludgery here. */
sewardj274807d2005-12-15 14:07:07 +00001474 vta.instrument2 = need_to_handle_SP_assignment()
1475 ? vg_SP_update_pass
1476 : NULL;
sewardj81651dc2007-08-28 06:05:20 +00001477 vta.finaltidy = VG_(needs).final_IR_tidy_pass
1478 ? VG_(tdict).tool_final_IR_tidy_pass
1479 : NULL;
sewardj274807d2005-12-15 14:07:07 +00001480 vta.do_self_check = do_self_check;
1481 vta.traceflags = verbosity;
1482
1483 /* Set up the dispatch-return info. For archs without a link
1484 register, vex generates a jump back to the specified dispatch
1485 address. Else, it just generates a branch-to-LR. */
1486# if defined(VGA_x86) || defined(VGA_amd64)
sewardj0ec07f32006-01-12 12:32:32 +00001487 vta.dispatch
1488 = (!allow_redirection)
1489 ? /* It's a no-redir translation. Will be run with the nonstandard
1490 dispatcher VG_(run_a_noredir_translation)
1491 and so needs a nonstandard return point. */
1492 (void*) &VG_(run_a_noredir_translation__return_point)
1493
1494 : /* normal translation. Uses VG_(run_innerloop). Return
1495 point depends on whether we're profiling bbs or not. */
1496 VG_(clo_profile_flags) > 0
1497 ? (void*) &VG_(run_innerloop__dispatch_profiled)
1498 : (void*) &VG_(run_innerloop__dispatch_unprofiled);
sewardj274807d2005-12-15 14:07:07 +00001499# elif defined(VGA_ppc32) || defined(VGA_ppc64)
1500 vta.dispatch = NULL;
1501# else
1502# error "Unknown arch"
1503# endif
1504
1505 /* Sheesh. Finally, actually _do_ the translation! */
1506 tres = LibVEX_Translate ( &vta );
njn25e49d8e72002-09-23 09:36:25 +00001507
sewardjbf426512005-01-17 18:35:30 +00001508 vg_assert(tres == VexTransOK);
sewardj8b635a42004-11-22 19:01:47 +00001509 vg_assert(tmpbuf_used <= N_TMPBUF);
1510 vg_assert(tmpbuf_used > 0);
sewardjde4a1d02002-03-22 01:27:54 +00001511
sewardj45f4e7c2005-09-27 19:20:21 +00001512 /* Tell aspacem of all segments that have had translations taken
1513 from them. Optimisation: don't re-look up vge.base[0] since seg
1514 should already point to it. */
1515
sewardj34593e52006-01-17 01:57:33 +00001516 vg_assert( vge.base[0] == (Addr64)addr );
sewardj4a0009c2006-10-17 01:52:05 +00001517 /* set 'translations taken from this segment' flag */
1518 VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
1519 } /* END new scope specially for 'seg' */
sewardj45f4e7c2005-09-27 19:20:21 +00001520
1521 for (i = 1; i < vge.n_used; i++) {
sewardj4a0009c2006-10-17 01:52:05 +00001522 NSegment const* seg
1523 = VG_(am_find_nsegment)( vge.base[i] );
1524 /* set 'translations taken from this segment' flag */
1525 VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
sewardj45f4e7c2005-09-27 19:20:21 +00001526 }
1527
nethercote59a122d2004-08-03 17:16:51 +00001528 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +00001529 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +00001530
1531 // If debugging, don't do anything with the translated block; we
1532 // only did this for the debugging output produced along the way.
1533 if (!debugging_translation) {
sewardj0ec07f32006-01-12 12:32:32 +00001534
sewardj34593e52006-01-17 01:57:33 +00001535 if (kind != T_NoRedir) {
sewardj0ec07f32006-01-12 12:32:32 +00001536 // Put it into the normal TT/TC structures. This is the
1537 // normal case.
1538
sewardj34593e52006-01-17 01:57:33 +00001539 // Note that we use nraddr (the non-redirected address), not
1540 // addr, which might have been changed by the redirection
sewardj0ec07f32006-01-12 12:32:32 +00001541 VG_(add_to_transtab)( &vge,
sewardj34593e52006-01-17 01:57:33 +00001542 nraddr,
sewardj0ec07f32006-01-12 12:32:32 +00001543 (Addr)(&tmpbuf[0]),
1544 tmpbuf_used,
1545 do_self_check );
1546 } else {
1547 VG_(add_to_unredir_transtab)( &vge,
sewardj34593e52006-01-17 01:57:33 +00001548 nraddr,
sewardj0ec07f32006-01-12 12:32:32 +00001549 (Addr)(&tmpbuf[0]),
1550 tmpbuf_used,
1551 do_self_check );
1552 }
sewardjde4a1d02002-03-22 01:27:54 +00001553 }
nethercote59a122d2004-08-03 17:16:51 +00001554
nethercote4d714382004-10-13 09:47:24 +00001555 return True;
sewardjde4a1d02002-03-22 01:27:54 +00001556}
1557
1558/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +00001559/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001560/*--------------------------------------------------------------------*/