blob: 62680cb9bd317c1c980e11044a32a9d03dde1dca [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
sewardjb3a1e4b2015-08-21 11:32:26 +000011 Copyright (C) 2000-2015 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}
philipped5fb89d2013-01-13 13:59:17 +000048#include "pub_core_stacks.h" // VG_(unknown_SP_update*)()
sewardj0ec07f32006-01-12 12:32:32 +000049#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
florian3c0c9472014-09-24 12:06:55 +000061#include "pub_core_gdbserver.h" // VG_(instrument_for_gdbserver_if_needed)
sewardjde4a1d02002-03-22 01:27:54 +000062
philippe3fad65b2012-10-02 20:35:21 +000063#include "libvex_emnote.h" // For PPC, EmWarn_PPC64_redir_underflow
64
njna1f783f2005-06-18 03:44:34 +000065/*------------------------------------------------------------*/
njn42c83552005-12-05 20:45:59 +000066/*--- Stats ---*/
67/*------------------------------------------------------------*/
68
sewardj8d47a612015-02-05 12:59:46 +000069static ULong n_SP_updates_fast = 0;
70static ULong n_SP_updates_generic_known = 0;
71static ULong n_SP_updates_generic_unknown = 0;
72
73static ULong n_PX_VexRegUpdSpAtMemAccess = 0;
74static ULong n_PX_VexRegUpdUnwindregsAtMemAccess = 0;
75static ULong n_PX_VexRegUpdAllregsAtMemAccess = 0;
76static ULong n_PX_VexRegUpdAllregsAtEachInsn = 0;
njn42c83552005-12-05 20:45:59 +000077
78void VG_(print_translation_stats) ( void )
79{
njn42c83552005-12-05 20:45:59 +000080 UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
81 + n_SP_updates_generic_unknown;
florian227a1ec2014-12-12 19:32:10 +000082 if (n_SP_updates == 0) {
83 VG_(message)(Vg_DebugMsg, "translate: no SP updates identified\n");
sewardj8d47a612015-02-05 12:59:46 +000084 } else {
85 VG_(message)(Vg_DebugMsg,
86 "translate: fast SP updates identified: %'llu (%3.1f%%)\n",
87 n_SP_updates_fast, n_SP_updates_fast * 100.0 / n_SP_updates );
88
89 VG_(message)(Vg_DebugMsg,
90 "translate: generic_known SP updates identified: %'llu (%3.1f%%)\n",
91 n_SP_updates_generic_known,
92 n_SP_updates_generic_known * 100.0 / n_SP_updates );
93
94 VG_(message)(Vg_DebugMsg,
95 "translate: generic_unknown SP updates identified: %'llu (%3.1f%%)\n",
96 n_SP_updates_generic_unknown,
97 n_SP_updates_generic_unknown * 100.0 / n_SP_updates );
florian227a1ec2014-12-12 19:32:10 +000098 }
njn42c83552005-12-05 20:45:59 +000099
njn42c83552005-12-05 20:45:59 +0000100 VG_(message)(Vg_DebugMsg,
sewardj8d47a612015-02-05 12:59:46 +0000101 "translate: PX: SPonly %'llu, UnwRegs %'llu, AllRegs %'llu, AllRegsAllInsns %'llu\n", n_PX_VexRegUpdSpAtMemAccess, n_PX_VexRegUpdUnwindregsAtMemAccess, n_PX_VexRegUpdAllregsAtMemAccess, n_PX_VexRegUpdAllregsAtEachInsn);
njn42c83552005-12-05 20:45:59 +0000102}
103
104/*------------------------------------------------------------*/
sewardj8b635a42004-11-22 19:01:47 +0000105/*--- %SP-update pass ---*/
nethercotebee3fd92004-08-02 15:17:43 +0000106/*------------------------------------------------------------*/
107
njna1f783f2005-06-18 03:44:34 +0000108static Bool need_to_handle_SP_assignment(void)
109{
sewardjf5c8e372006-02-12 15:42:20 +0000110 return ( VG_(tdict).track_new_mem_stack_4 ||
111 VG_(tdict).track_die_mem_stack_4 ||
112 VG_(tdict).track_new_mem_stack_8 ||
113 VG_(tdict).track_die_mem_stack_8 ||
114 VG_(tdict).track_new_mem_stack_12 ||
115 VG_(tdict).track_die_mem_stack_12 ||
116 VG_(tdict).track_new_mem_stack_16 ||
117 VG_(tdict).track_die_mem_stack_16 ||
118 VG_(tdict).track_new_mem_stack_32 ||
119 VG_(tdict).track_die_mem_stack_32 ||
120 VG_(tdict).track_new_mem_stack_112 ||
121 VG_(tdict).track_die_mem_stack_112 ||
122 VG_(tdict).track_new_mem_stack_128 ||
123 VG_(tdict).track_die_mem_stack_128 ||
124 VG_(tdict).track_new_mem_stack_144 ||
125 VG_(tdict).track_die_mem_stack_144 ||
126 VG_(tdict).track_new_mem_stack_160 ||
127 VG_(tdict).track_die_mem_stack_160 ||
128 VG_(tdict).track_new_mem_stack ||
129 VG_(tdict).track_die_mem_stack );
njna1f783f2005-06-18 03:44:34 +0000130}
131
njn5096a392005-12-13 20:05:00 +0000132// - The SP aliases are held in an array which is used as a circular buffer.
133// This misses very few constant updates of SP (ie. < 0.1%) while using a
134// small, constant structure that will also never fill up and cause
135// execution to abort.
136// - Unused slots have a .temp value of 'IRTemp_INVALID'.
137// - 'next_SP_alias_slot' is the index where the next alias will be stored.
138// - If the buffer fills, we circle around and start over-writing
139// non-IRTemp_INVALID values. This is rare, and the overwriting of a
140// value that would have subsequently be used is even rarer.
141// - Every slot below next_SP_alias_slot holds a non-IRTemp_INVALID value.
142// The rest either all won't (if we haven't yet circled around) or all
143// will (if we have circled around).
njn9b007f62003-04-07 14:40:25 +0000144
njn5096a392005-12-13 20:05:00 +0000145typedef
146 struct {
147 IRTemp temp;
148 Long delta;
149 }
150 SP_Alias;
151
152// With 32 slots the buffer fills very rarely -- eg. once in a run of GCC.
153// And I've tested with smaller values and the wrap-around case works ok.
154#define N_ALIASES 32
155static SP_Alias SP_aliases[N_ALIASES];
156static Int next_SP_alias_slot = 0;
157
158static void clear_SP_aliases(void)
159{
160 Int i;
161 for (i = 0; i < N_ALIASES; i++) {
162 SP_aliases[i].temp = IRTemp_INVALID;
163 SP_aliases[i].delta = 0;
164 }
165 next_SP_alias_slot = 0;
166}
167
168static void add_SP_alias(IRTemp temp, Long delta)
169{
170 vg_assert(temp != IRTemp_INVALID);
171 SP_aliases[ next_SP_alias_slot ].temp = temp;
172 SP_aliases[ next_SP_alias_slot ].delta = delta;
173 next_SP_alias_slot++;
174 if (N_ALIASES == next_SP_alias_slot) next_SP_alias_slot = 0;
175}
176
florian19f91bb2012-11-10 22:29:54 +0000177static Bool get_SP_delta(IRTemp temp, Long* delta)
njn5096a392005-12-13 20:05:00 +0000178{
179 Int i; // i must be signed!
180 vg_assert(IRTemp_INVALID != temp);
181 // Search backwards between current buffer position and the start.
182 for (i = next_SP_alias_slot-1; i >= 0; i--) {
183 if (temp == SP_aliases[i].temp) {
184 *delta = SP_aliases[i].delta;
185 return True;
186 }
187 }
188 // Search backwards between the end and the current buffer position.
189 for (i = N_ALIASES-1; i >= next_SP_alias_slot; i--) {
190 if (temp == SP_aliases[i].temp) {
191 *delta = SP_aliases[i].delta;
192 return True;
193 }
194 }
195 return False;
196}
197
198static void update_SP_aliases(Long delta)
199{
200 Int i;
201 for (i = 0; i < N_ALIASES; i++) {
202 if (SP_aliases[i].temp == IRTemp_INVALID) {
203 return;
204 }
205 SP_aliases[i].delta += delta;
206 }
207}
208
sewardj7cf4e6b2008-05-01 20:24:26 +0000209/* Given a guest IP, get an origin tag for a 1-element stack trace,
210 and wrap it up in an IR atom that can be passed as the origin-tag
211 value for a stack-adjustment helper function. */
florianf466eef2015-01-02 17:32:40 +0000212static IRExpr* mk_ecu_Expr ( Addr guest_IP )
sewardj7cf4e6b2008-05-01 20:24:26 +0000213{
214 UInt ecu;
215 ExeContext* ec
florianf466eef2015-01-02 17:32:40 +0000216 = VG_(make_depth_1_ExeContext_from_Addr)( guest_IP );
sewardj7cf4e6b2008-05-01 20:24:26 +0000217 vg_assert(ec);
218 ecu = VG_(get_ECU_from_ExeContext)( ec );
219 vg_assert(VG_(is_plausible_ECU)(ecu));
220 /* This is always safe to do, since ecu is only 32 bits, and
221 HWord is 32 or 64. */
222 return mkIRExpr_HWord( (HWord)ecu );
223}
224
sewardj3b290482011-05-06 21:02:55 +0000225/* When gdbserver is activated, the translation of a block must
226 first be done by the tool function, then followed by a pass
227 which (if needed) instruments the code for gdbserver.
228*/
229static
230IRSB* tool_instrument_then_gdbserver_if_needed ( VgCallbackClosure* closureV,
florian3c0c9472014-09-24 12:06:55 +0000231 IRSB* sb_in,
232 const VexGuestLayout* layout,
233 const VexGuestExtents* vge,
234 const VexArchInfo* vai,
sewardj3b290482011-05-06 21:02:55 +0000235 IRType gWordTy,
236 IRType hWordTy )
237{
238 return VG_(instrument_for_gdbserver_if_needed)
239 (VG_(tdict).tool_instrument (closureV,
240 sb_in,
241 layout,
242 vge,
florianca503be2012-10-07 21:59:42 +0000243 vai,
sewardj3b290482011-05-06 21:02:55 +0000244 gWordTy,
245 hWordTy),
246 layout,
247 vge,
248 gWordTy,
249 hWordTy);
250}
njn5096a392005-12-13 20:05:00 +0000251
252/* For tools that want to know about SP changes, this pass adds
nethercote996901a2004-08-03 13:29:09 +0000253 in the appropriate hooks. We have to do it after the tool's
njn5096a392005-12-13 20:05:00 +0000254 instrumentation, so the tool doesn't have to worry about the C calls
njn9b007f62003-04-07 14:40:25 +0000255 it adds in, and we must do it before register allocation because
njn5096a392005-12-13 20:05:00 +0000256 spilled temps make it much harder to work out the SP deltas.
257 This it is done with Vex's "second instrumentation" pass.
sewardjde4a1d02002-03-22 01:27:54 +0000258
njn5096a392005-12-13 20:05:00 +0000259 Basically, we look for GET(SP)/PUT(SP) pairs and track constant
260 increments/decrements of SP between them. (This requires tracking one or
261 more "aliases", which are not exact aliases but instead are tempregs
262 whose value is equal to the SP's plus or minus a known constant.)
263 If all the changes to SP leading up to a PUT(SP) are by known, small
264 constants, we can do a specific call to eg. new_mem_stack_4, otherwise
265 we fall back to the case that handles an unknown SP change.
sewardj2831b512007-11-11 18:56:39 +0000266
267 There is some extra complexity to deal correctly with updates to
268 only parts of SP. Bizarre, but it has been known to happen.
njn5096a392005-12-13 20:05:00 +0000269*/
sewardjde4a1d02002-03-22 01:27:54 +0000270static
sewardj0b9d74a2006-12-24 02:24:11 +0000271IRSB* vg_SP_update_pass ( void* closureV,
272 IRSB* sb_in,
florian3c0c9472014-09-24 12:06:55 +0000273 const VexGuestLayout* layout,
274 const VexGuestExtents* vge,
275 const VexArchInfo* vai,
sewardj4ba057c2005-10-18 12:04:18 +0000276 IRType gWordTy,
277 IRType hWordTy )
sewardjde4a1d02002-03-22 01:27:54 +0000278{
sewardj2eecb742012-06-01 16:11:41 +0000279 Int i, j, k, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
sewardj2831b512007-11-11 18:56:39 +0000280 Int first_SP, last_SP, first_Put, last_Put;
sewardj0b9d74a2006-12-24 02:24:11 +0000281 IRDirty *dcall, *d;
282 IRStmt* st;
283 IRExpr* e;
284 IRRegArray* descr;
285 IRType typeof_SP;
286 Long delta, con;
sewardjde4a1d02002-03-22 01:27:54 +0000287
sewardj7cf4e6b2008-05-01 20:24:26 +0000288 /* Set up stuff for tracking the guest IP */
289 Bool curr_IP_known = False;
florianf466eef2015-01-02 17:32:40 +0000290 Addr curr_IP = 0;
sewardj7cf4e6b2008-05-01 20:24:26 +0000291
sewardj8b635a42004-11-22 19:01:47 +0000292 /* Set up BB */
sewardj0b9d74a2006-12-24 02:24:11 +0000293 IRSB* bb = emptyIRSB();
294 bb->tyenv = deepCopyIRTypeEnv(sb_in->tyenv);
295 bb->next = deepCopyIRExpr(sb_in->next);
296 bb->jumpkind = sb_in->jumpkind;
sewardj291849f2012-04-20 23:58:55 +0000297 bb->offsIP = sb_in->offsIP;
sewardjde4a1d02002-03-22 01:27:54 +0000298
sewardj7cf97ee2004-11-28 14:25:01 +0000299 delta = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000300
sewardj7cf97ee2004-11-28 14:25:01 +0000301 sizeof_SP = layout->sizeof_SP;
302 offset_SP = layout->offset_SP;
303 typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
sewardj8b635a42004-11-22 19:01:47 +0000304 vg_assert(sizeof_SP == 4 || sizeof_SP == 8);
sewardjde4a1d02002-03-22 01:27:54 +0000305
sewardj7cf4e6b2008-05-01 20:24:26 +0000306 /* --- Start of #defines --- */
307
sewardj8b635a42004-11-22 19:01:47 +0000308# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
309# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))
sewardjde4a1d02002-03-22 01:27:54 +0000310
sewardj8b635a42004-11-22 19:01:47 +0000311# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))
sewardjde4a1d02002-03-22 01:27:54 +0000312
sewardj8b635a42004-11-22 19:01:47 +0000313# define GET_CONST(con) \
314 (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \
315 : (Long)(con->Ico.U64))
sewardjde4a1d02002-03-22 01:27:54 +0000316
sewardj7cf4e6b2008-05-01 20:24:26 +0000317# define DO_NEW(syze, tmpp) \
sewardj8b635a42004-11-22 19:01:47 +0000318 do { \
sewardj7cf4e6b2008-05-01 20:24:26 +0000319 Bool vanilla, w_ecu; \
320 vg_assert(curr_IP_known); \
321 vanilla = NULL != VG_(tdict).track_new_mem_stack_##syze; \
322 w_ecu = NULL != VG_(tdict).track_new_mem_stack_##syze##_w_ECU; \
323 vg_assert(!(vanilla && w_ecu)); /* can't have both */ \
324 if (!(vanilla || w_ecu)) \
325 goto generic; \
326 \
327 /* I don't know if it's really necessary to say that the */ \
328 /* call reads the stack pointer. But anyway, we do. */ \
329 if (w_ecu) { \
330 dcall = unsafeIRDirty_0_N( \
331 2/*regparms*/, \
332 "track_new_mem_stack_" #syze "_w_ECU", \
333 VG_(fnptr_to_fnentry)( \
334 VG_(tdict).track_new_mem_stack_##syze##_w_ECU ), \
335 mkIRExprVec_2(IRExpr_RdTmp(tmpp), \
336 mk_ecu_Expr(curr_IP)) \
337 ); \
338 } else { \
339 dcall = unsafeIRDirty_0_N( \
340 1/*regparms*/, \
341 "track_new_mem_stack_" #syze , \
342 VG_(fnptr_to_fnentry)( \
343 VG_(tdict).track_new_mem_stack_##syze ), \
344 mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \
345 ); \
346 } \
347 dcall->nFxState = 1; \
348 dcall->fxState[0].fx = Ifx_Read; \
349 dcall->fxState[0].offset = layout->offset_SP; \
350 dcall->fxState[0].size = layout->sizeof_SP; \
sewardj2eecb742012-06-01 16:11:41 +0000351 dcall->fxState[0].nRepeats = 0; \
352 dcall->fxState[0].repeatLen = 0; \
sewardj7cf4e6b2008-05-01 20:24:26 +0000353 \
354 addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \
355 \
floriane2800c92014-09-15 20:57:45 +0000356 vg_assert(syze > 0); \
sewardj7cf4e6b2008-05-01 20:24:26 +0000357 update_SP_aliases(syze); \
358 \
359 n_SP_updates_fast++; \
360 \
361 } while (0)
362
363# define DO_DIE(syze, tmpp) \
364 do { \
365 if (!VG_(tdict).track_die_mem_stack_##syze) \
sewardj8b635a42004-11-22 19:01:47 +0000366 goto generic; \
367 \
368 /* I don't know if it's really necessary to say that the */ \
369 /* call reads the stack pointer. But anyway, we do. */ \
370 dcall = unsafeIRDirty_0_N( \
371 1/*regparms*/, \
sewardj7cf4e6b2008-05-01 20:24:26 +0000372 "track_die_mem_stack_" #syze, \
sewardj53ee1fc2005-12-23 02:29:58 +0000373 VG_(fnptr_to_fnentry)( \
sewardj7cf4e6b2008-05-01 20:24:26 +0000374 VG_(tdict).track_die_mem_stack_##syze ), \
sewardj0b9d74a2006-12-24 02:24:11 +0000375 mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \
sewardj8b635a42004-11-22 19:01:47 +0000376 ); \
377 dcall->nFxState = 1; \
378 dcall->fxState[0].fx = Ifx_Read; \
379 dcall->fxState[0].offset = layout->offset_SP; \
380 dcall->fxState[0].size = layout->sizeof_SP; \
sewardj2eecb742012-06-01 16:11:41 +0000381 dcall->fxState[0].nRepeats = 0; \
382 dcall->fxState[0].repeatLen = 0; \
sewardj8b635a42004-11-22 19:01:47 +0000383 \
sewardj0b9d74a2006-12-24 02:24:11 +0000384 addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \
njn42c83552005-12-05 20:45:59 +0000385 \
floriane2800c92014-09-15 20:57:45 +0000386 vg_assert(syze > 0); \
sewardj7cf4e6b2008-05-01 20:24:26 +0000387 update_SP_aliases(-(syze)); \
njn5096a392005-12-13 20:05:00 +0000388 \
njn42c83552005-12-05 20:45:59 +0000389 n_SP_updates_fast++; \
390 \
sewardj8b635a42004-11-22 19:01:47 +0000391 } while (0)
sewardjde4a1d02002-03-22 01:27:54 +0000392
sewardj7cf4e6b2008-05-01 20:24:26 +0000393 /* --- End of #defines --- */
394
njn5096a392005-12-13 20:05:00 +0000395 clear_SP_aliases();
396
sewardj0b9d74a2006-12-24 02:24:11 +0000397 for (i = 0; i < sb_in->stmts_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000398
sewardj0b9d74a2006-12-24 02:24:11 +0000399 st = sb_in->stmts[i];
sewardjde4a1d02002-03-22 01:27:54 +0000400
sewardj7cf4e6b2008-05-01 20:24:26 +0000401 if (st->tag == Ist_IMark) {
402 curr_IP_known = True;
403 curr_IP = st->Ist.IMark.addr;
404 }
405
sewardj8b635a42004-11-22 19:01:47 +0000406 /* t = Get(sp): curr = t, delta = 0 */
sewardj0b9d74a2006-12-24 02:24:11 +0000407 if (st->tag != Ist_WrTmp) goto case2;
408 e = st->Ist.WrTmp.data;
sewardj8b635a42004-11-22 19:01:47 +0000409 if (e->tag != Iex_Get) goto case2;
410 if (e->Iex.Get.offset != offset_SP) goto case2;
411 if (e->Iex.Get.ty != typeof_SP) goto case2;
sewardj2831b512007-11-11 18:56:39 +0000412 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
sewardj0b9d74a2006-12-24 02:24:11 +0000413 add_SP_alias(st->Ist.WrTmp.tmp, 0);
414 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000415 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000416
sewardj8b635a42004-11-22 19:01:47 +0000417 case2:
418 /* t' = curr +/- const: curr = t', delta +=/-= const */
sewardj0b9d74a2006-12-24 02:24:11 +0000419 if (st->tag != Ist_WrTmp) goto case3;
420 e = st->Ist.WrTmp.data;
sewardj8b635a42004-11-22 19:01:47 +0000421 if (e->tag != Iex_Binop) goto case3;
sewardj0b9d74a2006-12-24 02:24:11 +0000422 if (e->Iex.Binop.arg1->tag != Iex_RdTmp) goto case3;
423 if (!get_SP_delta(e->Iex.Binop.arg1->Iex.RdTmp.tmp, &delta)) goto case3;
sewardj8b635a42004-11-22 19:01:47 +0000424 if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
425 if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
njn5096a392005-12-13 20:05:00 +0000426 con = GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
sewardj2831b512007-11-11 18:56:39 +0000427 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
njn5096a392005-12-13 20:05:00 +0000428 if (IS_ADD(e->Iex.Binop.op)) {
sewardj0b9d74a2006-12-24 02:24:11 +0000429 add_SP_alias(st->Ist.WrTmp.tmp, delta + con);
njn5096a392005-12-13 20:05:00 +0000430 } else {
sewardj0b9d74a2006-12-24 02:24:11 +0000431 add_SP_alias(st->Ist.WrTmp.tmp, delta - con);
njn5096a392005-12-13 20:05:00 +0000432 }
sewardj0b9d74a2006-12-24 02:24:11 +0000433 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000434 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000435
sewardj8b635a42004-11-22 19:01:47 +0000436 case3:
437 /* t' = curr: curr = t' */
sewardj0b9d74a2006-12-24 02:24:11 +0000438 if (st->tag != Ist_WrTmp) goto case4;
439 e = st->Ist.WrTmp.data;
440 if (e->tag != Iex_RdTmp) goto case4;
441 if (!get_SP_delta(e->Iex.RdTmp.tmp, &delta)) goto case4;
sewardj2831b512007-11-11 18:56:39 +0000442 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP );
sewardj0b9d74a2006-12-24 02:24:11 +0000443 add_SP_alias(st->Ist.WrTmp.tmp, delta);
444 addStmtToIRSB( bb, st );
sewardj8b635a42004-11-22 19:01:47 +0000445 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000446
sewardj8b635a42004-11-22 19:01:47 +0000447 case4:
448 /* Put(sp) = curr */
sewardj2831b512007-11-11 18:56:39 +0000449 /* More generally, we must correctly handle a Put which writes
450 any part of SP, not just the case where all of SP is
451 written. */
sewardj8b635a42004-11-22 19:01:47 +0000452 if (st->tag != Ist_Put) goto case5;
sewardj2831b512007-11-11 18:56:39 +0000453 first_SP = offset_SP;
454 last_SP = first_SP + sizeof_SP - 1;
455 first_Put = st->Ist.Put.offset;
456 last_Put = first_Put
457 + sizeofIRType( typeOfIRExpr( bb->tyenv, st->Ist.Put.data ))
458 - 1;
459 vg_assert(first_SP <= last_SP);
460 vg_assert(first_Put <= last_Put);
461
462 if (last_Put < first_SP || last_SP < first_Put)
463 goto case5; /* no overlap */
464
465 if (st->Ist.Put.data->tag == Iex_RdTmp
466 && get_SP_delta(st->Ist.Put.data->Iex.RdTmp.tmp, &delta)) {
sewardj0b9d74a2006-12-24 02:24:11 +0000467 IRTemp tttmp = st->Ist.Put.data->Iex.RdTmp.tmp;
sewardj2831b512007-11-11 18:56:39 +0000468 /* Why should the following assertion hold? Because any
469 alias added by put_SP_alias must be of a temporary which
470 has the same type as typeof_SP, and whose value is a Get
471 at exactly offset_SP of size typeof_SP. Each call to
472 put_SP_alias is immediately preceded by an assertion that
473 we are putting in a binding for a correctly-typed
474 temporary. */
475 vg_assert( typeOfIRTemp(bb->tyenv, tttmp) == typeof_SP );
476 /* From the same type-and-offset-correctness argument, if
477 we found a useable alias, it must for an "exact" write of SP. */
478 vg_assert(first_SP == first_Put);
479 vg_assert(last_SP == last_Put);
sewardj8b635a42004-11-22 19:01:47 +0000480 switch (delta) {
sewardj0b9d74a2006-12-24 02:24:11 +0000481 case 0: addStmtToIRSB(bb,st); continue;
sewardj7cf4e6b2008-05-01 20:24:26 +0000482 case 4: DO_DIE( 4, tttmp); addStmtToIRSB(bb,st); continue;
483 case -4: DO_NEW( 4, tttmp); addStmtToIRSB(bb,st); continue;
484 case 8: DO_DIE( 8, tttmp); addStmtToIRSB(bb,st); continue;
485 case -8: DO_NEW( 8, tttmp); addStmtToIRSB(bb,st); continue;
486 case 12: DO_DIE( 12, tttmp); addStmtToIRSB(bb,st); continue;
487 case -12: DO_NEW( 12, tttmp); addStmtToIRSB(bb,st); continue;
488 case 16: DO_DIE( 16, tttmp); addStmtToIRSB(bb,st); continue;
489 case -16: DO_NEW( 16, tttmp); addStmtToIRSB(bb,st); continue;
490 case 32: DO_DIE( 32, tttmp); addStmtToIRSB(bb,st); continue;
491 case -32: DO_NEW( 32, tttmp); addStmtToIRSB(bb,st); continue;
492 case 112: DO_DIE( 112, tttmp); addStmtToIRSB(bb,st); continue;
493 case -112: DO_NEW( 112, tttmp); addStmtToIRSB(bb,st); continue;
494 case 128: DO_DIE( 128, tttmp); addStmtToIRSB(bb,st); continue;
495 case -128: DO_NEW( 128, tttmp); addStmtToIRSB(bb,st); continue;
496 case 144: DO_DIE( 144, tttmp); addStmtToIRSB(bb,st); continue;
497 case -144: DO_NEW( 144, tttmp); addStmtToIRSB(bb,st); continue;
498 case 160: DO_DIE( 160, tttmp); addStmtToIRSB(bb,st); continue;
499 case -160: DO_NEW( 160, tttmp); addStmtToIRSB(bb,st); continue;
njn42c83552005-12-05 20:45:59 +0000500 default:
sewardjbb686272006-01-22 20:12:45 +0000501 /* common values for ppc64: 144 128 160 112 176 */
njn42c83552005-12-05 20:45:59 +0000502 n_SP_updates_generic_known++;
503 goto generic;
sewardjde4a1d02002-03-22 01:27:54 +0000504 }
sewardj8b635a42004-11-22 19:01:47 +0000505 } else {
sewardj2831b512007-11-11 18:56:39 +0000506 /* Deal with an unknown update to SP. We're here because
507 either:
508 (1) the Put does not exactly cover SP; it is a partial update.
509 Highly unlikely, but has been known to happen for 16-bit
510 Windows apps running on Wine, doing 16-bit adjustments to
511 %sp.
512 (2) the Put does exactly cover SP, but we are unable to
513 determine how the value relates to the old SP. In any
514 case, we cannot assume that the Put.data value is a tmp;
515 we must assume it can be anything allowed in flat IR (tmp
516 or const).
517 */
sewardj7cf4e6b2008-05-01 20:24:26 +0000518 IRTemp old_SP;
njn42c83552005-12-05 20:45:59 +0000519 n_SP_updates_generic_unknown++;
520
njn5096a392005-12-13 20:05:00 +0000521 // Nb: if all is well, this generic case will typically be
522 // called something like every 1000th SP update. If it's more than
523 // that, the above code may be missing some cases.
sewardj8b635a42004-11-22 19:01:47 +0000524 generic:
sewardj7cf4e6b2008-05-01 20:24:26 +0000525 /* Pass both the old and new SP values to this helper. Also,
526 pass an origin tag, even if it isn't needed. */
sewardj2a99cf62004-11-24 10:44:19 +0000527 old_SP = newIRTemp(bb->tyenv, typeof_SP);
sewardj0b9d74a2006-12-24 02:24:11 +0000528 addStmtToIRSB(
sewardj2a99cf62004-11-24 10:44:19 +0000529 bb,
sewardj0b9d74a2006-12-24 02:24:11 +0000530 IRStmt_WrTmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) )
sewardj2a99cf62004-11-24 10:44:19 +0000531 );
sewardjde4a1d02002-03-22 01:27:54 +0000532
sewardj2831b512007-11-11 18:56:39 +0000533 /* Now we know what the old value of SP is. But knowing the new
534 value is a bit tricky if there is a partial write. */
535 if (first_Put == first_SP && last_Put == last_SP) {
philipped5fb89d2013-01-13 13:59:17 +0000536 /* The common case, an exact write to SP. So st->Ist.Put.data
537 does hold the new value; simple. */
sewardj7cf4e6b2008-05-01 20:24:26 +0000538 vg_assert(curr_IP_known);
philipped5fb89d2013-01-13 13:59:17 +0000539 if (NULL != VG_(tdict).track_new_mem_stack_w_ECU)
540 dcall = unsafeIRDirty_0_N(
541 3/*regparms*/,
542 "VG_(unknown_SP_update_w_ECU)",
543 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update_w_ECU) ),
544 mkIRExprVec_3( IRExpr_RdTmp(old_SP), st->Ist.Put.data,
545 mk_ecu_Expr(curr_IP) )
546 );
547 else
548 dcall = unsafeIRDirty_0_N(
549 2/*regparms*/,
550 "VG_(unknown_SP_update)",
551 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
552 mkIRExprVec_2( IRExpr_RdTmp(old_SP), st->Ist.Put.data )
553 );
554
sewardj2831b512007-11-11 18:56:39 +0000555 addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
556 /* don't forget the original assignment */
557 addStmtToIRSB( bb, st );
558 } else {
559 /* We have a partial update to SP. We need to know what
560 the new SP will be, and hand that to the helper call,
561 but when the helper call happens, SP must hold the
562 value it had before the update. Tricky.
563 Therefore use the following kludge:
564 1. do the partial SP update (Put)
565 2. Get the new SP value into a tmp, new_SP
566 3. Put old_SP
567 4. Call the helper
568 5. Put new_SP
569 */
570 IRTemp new_SP;
571 /* 1 */
572 addStmtToIRSB( bb, st );
573 /* 2 */
574 new_SP = newIRTemp(bb->tyenv, typeof_SP);
575 addStmtToIRSB(
576 bb,
577 IRStmt_WrTmp( new_SP, IRExpr_Get(offset_SP, typeof_SP) )
578 );
579 /* 3 */
580 addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(old_SP) ));
581 /* 4 */
sewardj7cf4e6b2008-05-01 20:24:26 +0000582 vg_assert(curr_IP_known);
philipped5fb89d2013-01-13 13:59:17 +0000583 if (NULL != VG_(tdict).track_new_mem_stack_w_ECU)
584 dcall = unsafeIRDirty_0_N(
585 3/*regparms*/,
586 "VG_(unknown_SP_update_w_ECU)",
587 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update_w_ECU) ),
588 mkIRExprVec_3( IRExpr_RdTmp(old_SP),
589 IRExpr_RdTmp(new_SP),
590 mk_ecu_Expr(curr_IP) )
591 );
592 else
593 dcall = unsafeIRDirty_0_N(
594 2/*regparms*/,
595 "VG_(unknown_SP_update)",
596 VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
597 mkIRExprVec_2( IRExpr_RdTmp(old_SP),
598 IRExpr_RdTmp(new_SP) )
599 );
sewardj2831b512007-11-11 18:56:39 +0000600 addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
601 /* 5 */
602 addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(new_SP) ));
603 }
sewardj2a99cf62004-11-24 10:44:19 +0000604
sewardj2831b512007-11-11 18:56:39 +0000605 /* Forget what we already know. */
njn5096a392005-12-13 20:05:00 +0000606 clear_SP_aliases();
sewardj2831b512007-11-11 18:56:39 +0000607
608 /* If this is a Put of a tmp that exactly updates SP,
609 start tracking aliases against this tmp. */
610
611 if (first_Put == first_SP && last_Put == last_SP
612 && st->Ist.Put.data->tag == Iex_RdTmp) {
613 vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.Put.data->Iex.RdTmp.tmp)
614 == typeof_SP );
615 add_SP_alias(st->Ist.Put.data->Iex.RdTmp.tmp, 0);
616 }
sewardj8b635a42004-11-22 19:01:47 +0000617 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000618 }
619
sewardj8b635a42004-11-22 19:01:47 +0000620 case5:
621 /* PutI or Dirty call which overlaps SP: complain. We can't
622 deal with SP changing in weird ways (well, we can, but not at
623 this time of night). */
624 if (st->tag == Ist_PutI) {
floriand39b0222012-05-31 15:48:13 +0000625 descr = st->Ist.PutI.details->descr;
sewardj8b635a42004-11-22 19:01:47 +0000626 minoff_ST = descr->base;
sewardj2831b512007-11-11 18:56:39 +0000627 maxoff_ST = descr->base
628 + descr->nElems * sizeofIRType(descr->elemTy) - 1;
629 if (!(offset_SP > maxoff_ST
630 || (offset_SP + sizeof_SP - 1) < minoff_ST))
sewardj8b635a42004-11-22 19:01:47 +0000631 goto complain;
sewardjde4a1d02002-03-22 01:27:54 +0000632 }
sewardj8b635a42004-11-22 19:01:47 +0000633 if (st->tag == Ist_Dirty) {
634 d = st->Ist.Dirty.details;
635 for (j = 0; j < d->nFxState; j++) {
sewardj8b635a42004-11-22 19:01:47 +0000636 if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None)
637 continue;
sewardj2eecb742012-06-01 16:11:41 +0000638 /* Enumerate the described state segments */
639 for (k = 0; k < 1 + d->fxState[j].nRepeats; k++) {
640 minoff_ST = d->fxState[j].offset + k * d->fxState[j].repeatLen;
641 maxoff_ST = minoff_ST + d->fxState[j].size - 1;
642 if (!(offset_SP > maxoff_ST
643 || (offset_SP + sizeof_SP - 1) < minoff_ST))
644 goto complain;
645 }
sewardj8b635a42004-11-22 19:01:47 +0000646 }
647 }
sewardjde4a1d02002-03-22 01:27:54 +0000648
sewardj8b635a42004-11-22 19:01:47 +0000649 /* well, not interesting. Just copy and keep going. */
sewardj0b9d74a2006-12-24 02:24:11 +0000650 addStmtToIRSB( bb, st );
sewardjde4a1d02002-03-22 01:27:54 +0000651
sewardj0b9d74a2006-12-24 02:24:11 +0000652 } /* for (i = 0; i < sb_in->stmts_used; i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000653
sewardj8b635a42004-11-22 19:01:47 +0000654 return bb;
sewardjde4a1d02002-03-22 01:27:54 +0000655
sewardj8b635a42004-11-22 19:01:47 +0000656 complain:
657 VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP");
sewardjde4a1d02002-03-22 01:27:54 +0000658
sewardj7cf4e6b2008-05-01 20:24:26 +0000659#undef IS_ADD
660#undef IS_SUB
661#undef IS_ADD_OR_SUB
662#undef GET_CONST
663#undef DO_NEW
664#undef DO_DIE
sewardjde4a1d02002-03-22 01:27:54 +0000665}
sewardj7c4b6042003-06-14 15:47:15 +0000666
sewardjde4a1d02002-03-22 01:27:54 +0000667/*------------------------------------------------------------*/
668/*--- Main entry point for the JITter. ---*/
669/*------------------------------------------------------------*/
670
sewardjd2b70dc2005-10-14 17:22:31 +0000671/* Extra comments re self-checking translations and self-modifying
672 code. (JRS 14 Oct 05).
673
674 There are 3 modes:
675 (1) no checking: all code assumed to be not self-modifying
676 (2) partial: known-problematic situations get a self-check
677 (3) full checking: all translations get a self-check
678
679 As currently implemented, the default is (2). (3) is always safe,
680 but very slow. (1) works mostly, but fails for gcc nested-function
681 code which uses trampolines on the stack; this situation is
682 detected and handled by (2).
683
684 ----------
685
686 A more robust and transparent solution, which is not currently
687 implemented, is a variant of (2): if a translation is made from an
688 area which aspacem says does not have 'w' permission, then it can
689 be non-self-checking. Otherwise, it needs a self-check.
690
691 This is complicated by Vex's basic-block chasing. If a self-check
692 is requested, then Vex will not chase over basic block boundaries
693 (it's too complex). However there is still a problem if it chases
694 from a non-'w' area into a 'w' area.
695
696 I think the right thing to do is:
697
698 - if a translation request starts in a 'w' area, ask for a
699 self-checking translation, and do not allow any chasing (make
700 chase_into_ok return False). Note that the latter is redundant
701 in the sense that Vex won't chase anyway in this situation.
702
703 - if a translation request starts in a non-'w' area, do not ask for
704 a self-checking translation. However, do not allow chasing (as
705 determined by chase_into_ok) to go into a 'w' area.
706
707 The result of this is that all code inside 'w' areas is self
708 checking.
709
710 To complete the trick, there is a caveat: we must watch the
711 client's mprotect calls. If pages are changed from non-'w' to 'w'
712 then we should throw away all translations which intersect the
713 affected area, so as to force them to be redone with self-checks.
714
715 ----------
716
717 The above outlines the conditions under which bb chasing is allowed
718 from a self-modifying-code point of view. There are other
719 situations pertaining to function redirection in which it is
720 necessary to disallow chasing, but those fall outside the scope of
721 this comment.
722*/
723
sewardj34593e52006-01-17 01:57:33 +0000724
sewardj8b635a42004-11-22 19:01:47 +0000725/* Vex dumps the final code in here. Then we can copy it off
726 wherever we like. */
sewardj4a0009c2006-10-17 01:52:05 +0000727/* 60000: should agree with assertion in VG_(add_to_transtab) in
728 m_transtab.c. */
729#define N_TMPBUF 60000
sewardj8b635a42004-11-22 19:01:47 +0000730static UChar tmpbuf[N_TMPBUF];
731
sewardj34593e52006-01-17 01:57:33 +0000732
sewardj8b635a42004-11-22 19:01:47 +0000733/* Function pointers we must supply to LibVEX in order that it
734 can bomb out and emit messages under Valgrind's control. */
735__attribute__ ((noreturn))
736static
737void failure_exit ( void )
738{
sewardjbf426512005-01-17 18:35:30 +0000739 LibVEX_ShowAllocStats();
sewardjc621f762004-11-26 13:49:59 +0000740 VG_(core_panic)("LibVEX called failure_exit().");
sewardj8b635a42004-11-22 19:01:47 +0000741}
742
743static
florian09b54fb2014-12-29 20:23:11 +0000744void log_bytes ( const HChar* bytes, SizeT nbytes )
sewardj8b635a42004-11-22 19:01:47 +0000745{
florian09b54fb2014-12-29 20:23:11 +0000746 SizeT i = 0;
747 if (nbytes >= 4)
748 for (; i < nbytes-3; i += 4)
749 VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]);
sewardj8b635a42004-11-22 19:01:47 +0000750 for (; i < nbytes; i++)
751 VG_(printf)("%c", bytes[i]);
752}
753
njn25e49d8e72002-09-23 09:36:25 +0000754
sewardj34593e52006-01-17 01:57:33 +0000755/* --------- Various helper functions for translation --------- */
sewardj8b635a42004-11-22 19:01:47 +0000756
sewardj45f4e7c2005-09-27 19:20:21 +0000757/* Look for reasons to disallow making translations from the given
philippe02320982013-05-02 22:06:31 +0000758 segment/addr. */
sewardj45f4e7c2005-09-27 19:20:21 +0000759
philippe02320982013-05-02 22:06:31 +0000760static Bool translations_allowable_from_seg ( NSegment const* seg, Addr addr )
sewardj45f4e7c2005-09-27 19:20:21 +0000761{
sewardj112711a2015-04-10 12:30:09 +0000762# if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32) \
763 || defined(VGA_mips64) || defined(VGA_tilegx)
sewardj45f4e7c2005-09-27 19:20:21 +0000764 Bool allowR = True;
765# else
766 Bool allowR = False;
767# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000768 return seg != NULL
tom1da86fe2009-10-12 13:53:12 +0000769 && (seg->kind == SkAnonC || seg->kind == SkFileC || seg->kind == SkShmC)
philippe02320982013-05-02 22:06:31 +0000770 && (seg->hasX
771 || (seg->hasR && (allowR
772 || VG_(has_gdbserver_breakpoint) (addr))));
773 /* If GDB/gdbsrv has inserted a breakpoint at addr, assume this is a valid
774 location to translate if seg is not executable but is readable.
775 This is needed for inferior function calls from GDB: GDB inserts a
776 breakpoint on the stack, and expects to regain control before the
777 breakpoint instruction at the breakpoint address is really
778 executed. For this, the breakpoint instruction must be translated
779 so as to have the call to gdbserver executed. */
sewardj45f4e7c2005-09-27 19:20:21 +0000780}
781
782
sewardj6dbcc632011-06-07 21:39:28 +0000783/* Produce a bitmask stating which of the supplied extents needs a
784 self-check. See documentation of
785 VexTranslateArgs::needs_self_check for more details about the
786 return convention. */
sewardj45f4e7c2005-09-27 19:20:21 +0000787
sewardj6dbcc632011-06-07 21:39:28 +0000788static UInt needs_self_check ( void* closureV,
sewardj8d47a612015-02-05 12:59:46 +0000789 /*MAYBE_MOD*/VexRegisterUpdates* pxControl,
florian3c0c9472014-09-24 12:06:55 +0000790 const VexGuestExtents* vge )
sewardj34593e52006-01-17 01:57:33 +0000791{
sewardj6dbcc632011-06-07 21:39:28 +0000792 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
793 UInt i, bitset;
794
795 vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
796 bitset = 0;
797
sewardj8d47a612015-02-05 12:59:46 +0000798 /* Will we need to do a second pass in order to compute a
799 revised *pxControl value? */
800 Bool pxStatusMightChange
801 = /* "the user actually set it" */
802 VG_(clo_px_file_backed) != VexRegUpd_INVALID
803 /* "and they set it to something other than the default. */
804 && *pxControl != VG_(clo_px_file_backed);
805
806 /* First, compute |bitset|, which specifies which extent(s) need a
807 self check. Whilst we're at it, note any NSegments that we get,
808 so as to reduce the number of calls required to
809 VG_(am_find_nsegment) in a possible second pass. */
florian4367abe2015-02-28 09:22:09 +0000810 const NSegment *segs[3] = { NULL, NULL, NULL };
sewardj8d47a612015-02-05 12:59:46 +0000811
sewardj6dbcc632011-06-07 21:39:28 +0000812 for (i = 0; i < vge->n_used; i++) {
813 Bool check = False;
florianddd61ff2015-01-04 17:20:45 +0000814 Addr addr = vge->base[i];
815 SizeT len = vge->len[i];
sewardj6dbcc632011-06-07 21:39:28 +0000816 NSegment const* segA = NULL;
817
818# if defined(VGO_darwin)
819 // GrP fixme hack - dyld i386 IMPORT gets rewritten.
820 // To really do this correctly, we'd need to flush the
821 // translation cache whenever a segment became +WX.
822 segA = VG_(am_find_nsegment)(addr);
823 if (segA && segA->hasX && segA->hasW)
824 check = True;
825# endif
826
827 if (!check) {
828 switch (VG_(clo_smc_check)) {
829 case Vg_SmcNone:
830 /* never check (except as per Darwin hack above) */
831 break;
832 case Vg_SmcAll:
833 /* always check */
834 check = True;
835 break;
836 case Vg_SmcStack: {
837 /* check if the address is in the same segment as this
838 thread's stack pointer */
839 Addr sp = VG_(get_SP)(closure->tid);
840 if (!segA) {
841 segA = VG_(am_find_nsegment)(addr);
842 }
843 NSegment const* segSP = VG_(am_find_nsegment)(sp);
844 if (segA && segSP && segA == segSP)
845 check = True;
846 break;
847 }
848 case Vg_SmcAllNonFile: {
849 /* check if any part of the extent is not in a
850 file-mapped segment */
851 if (!segA) {
852 segA = VG_(am_find_nsegment)(addr);
853 }
854 if (segA && segA->kind == SkFileC && segA->start <= addr
855 && (len == 0 || addr + len <= segA->end + 1)) {
856 /* in a file-mapped segment; skip the check */
857 } else {
858 check = True;
859 }
860 break;
861 }
862 default:
863 vg_assert(0);
864 }
865 }
866
867 if (check)
868 bitset |= (1 << i);
sewardj8d47a612015-02-05 12:59:46 +0000869
870 if (pxStatusMightChange && segA) {
871 vg_assert(i < sizeof(segs)/sizeof(segs[0]));
872 segs[i] = segA;
873 }
874 }
875
876 /* Now, possibly do a second pass, to see if the PX status might
877 change. This can happen if the user specified value via
878 --px-file-backed= which is different from the default PX value
879 specified via --vex-iropt-register-updates (also known by the
880 shorter alias --px-default). */
881 if (pxStatusMightChange) {
882
883 Bool allFileBacked = True;
884 for (i = 0; i < vge->n_used; i++) {
885 Addr addr = vge->base[i];
886 SizeT len = vge->len[i];
887 NSegment const* segA = segs[i];
888 if (!segA) {
889 /* If we don't have a cached value for |segA|, compute it now. */
890 segA = VG_(am_find_nsegment)(addr);
891 }
892 vg_assert(segA); /* Can this ever fail? */
893 if (segA && segA->kind == SkFileC && segA->start <= addr
894 && (len == 0 || addr + len <= segA->end + 1)) {
895 /* in a file-mapped segment */
896 } else {
897 /* not in a file-mapped segment, or we can't figure out
898 where it is */
899 allFileBacked = False;
900 break;
901 }
902 }
903
904 /* So, finally, if all the extents are in file backed segments, perform
905 the user-specified PX change. */
906 if (allFileBacked) {
907 *pxControl = VG_(clo_px_file_backed);
908 }
909
910 }
911
912 /* Update running PX stats, as it is difficult without these to
913 check that the system is behaving as expected. */
914 switch (*pxControl) {
915 case VexRegUpdSpAtMemAccess:
916 n_PX_VexRegUpdSpAtMemAccess++; break;
917 case VexRegUpdUnwindregsAtMemAccess:
918 n_PX_VexRegUpdUnwindregsAtMemAccess++; break;
919 case VexRegUpdAllregsAtMemAccess:
920 n_PX_VexRegUpdAllregsAtMemAccess++; break;
921 case VexRegUpdAllregsAtEachInsn:
922 n_PX_VexRegUpdAllregsAtEachInsn++; break;
923 default:
924 vg_assert(0);
njnf76d27a2009-05-28 01:53:07 +0000925 }
sewardj6dbcc632011-06-07 21:39:28 +0000926
927 return bitset;
sewardj34593e52006-01-17 01:57:33 +0000928}
929
930
931/* This is a callback passed to LibVEX_Translate. It stops Vex from
932 chasing into function entry points that we wish to redirect.
933 Chasing across them obviously defeats the redirect mechanism, with
sewardj6dbcc632011-06-07 21:39:28 +0000934 bad effects for Memcheck, Helgrind, DRD, Massif, and possibly others.
sewardj447f2a12005-07-07 13:52:53 +0000935*/
florian9b3da112014-12-31 12:11:15 +0000936static Bool chase_into_ok ( void* closureV, Addr addr )
sewardj8b635a42004-11-22 19:01:47 +0000937{
sewardj4a0009c2006-10-17 01:52:05 +0000938 NSegment const* seg = VG_(am_find_nsegment)(addr);
sewardj45f4e7c2005-09-27 19:20:21 +0000939
sewardj447f2a12005-07-07 13:52:53 +0000940 /* Work through a list of possibilities why we might not want to
941 allow a chase. */
sewardj447f2a12005-07-07 13:52:53 +0000942
sewardj34593e52006-01-17 01:57:33 +0000943 /* Destination not in a plausible segment? */
philippe02320982013-05-02 22:06:31 +0000944 if (!translations_allowable_from_seg(seg, addr))
sewardj45f4e7c2005-09-27 19:20:21 +0000945 goto dontchase;
946
sewardj447f2a12005-07-07 13:52:53 +0000947 /* Destination is redirected? */
sewardj0ec07f32006-01-12 12:32:32 +0000948 if (addr != VG_(redir_do_lookup)(addr, NULL))
sewardj447f2a12005-07-07 13:52:53 +0000949 goto dontchase;
950
carllcae0cc22014-08-07 23:17:29 +0000951# if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
florian9b3da112014-12-31 12:11:15 +0000952 /* This needs to be at the start of its own block. Don't chase. */
953 if (addr == (Addr)&VG_(ppctoc_magic_redirect_return_stub))
sewardj34593e52006-01-17 01:57:33 +0000954 goto dontchase;
955# endif
956
sewardj5f76de02007-02-11 05:08:06 +0000957 /* overly conservative, but .. don't chase into the distinguished
958 address that m_transtab uses as an empty-slot marker for
959 VG_(tt_fast). */
960 if (addr == TRANSTAB_BOGUS_GUEST_ADDR)
961 goto dontchase;
962
floriancabcace2011-07-16 02:09:36 +0000963# if defined(VGA_s390x)
964 /* Never chase into an EX instruction. Generating IR for EX causes
965 a round-trip through the scheduler including VG_(discard_translations).
966 And that's expensive as shown by perf/tinycc.c:
967 Chasing into EX increases the number of EX translations from 21 to
968 102666 causing a 7x runtime increase for "none" and a 3.2x runtime
969 increase for memcheck. */
florian9b3da112014-12-31 12:11:15 +0000970 if (((UChar *)addr)[0] == 0x44 || /* EX */
971 ((UChar *)addr)[0] == 0xC6) /* EXRL */
972 goto dontchase;
floriancabcace2011-07-16 02:09:36 +0000973# endif
974
sewardj447f2a12005-07-07 13:52:53 +0000975 /* well, ok then. go on and chase. */
976 return True;
977
978 vg_assert(0);
979 /*NOTREACHED*/
980
981 dontchase:
njn8a7b41b2007-09-23 00:51:24 +0000982 if (0) VG_(printf)("not chasing into 0x%lx\n", addr);
sewardj447f2a12005-07-07 13:52:53 +0000983 return False;
sewardj8b635a42004-11-22 19:01:47 +0000984}
985
sewardj447f2a12005-07-07 13:52:53 +0000986
sewardj4a0009c2006-10-17 01:52:05 +0000987/* --------------- helpers for with-TOC platforms --------------- */
988
sewardj6e9de462011-06-28 07:25:29 +0000989/* NOTE: with-TOC platforms are: ppc64-linux. */
sewardjdfbaa222006-01-18 04:25:20 +0000990
sewardjd68ac3e2006-01-20 14:31:57 +0000991static IRExpr* mkU64 ( ULong n ) {
sewardj34593e52006-01-17 01:57:33 +0000992 return IRExpr_Const(IRConst_U64(n));
993}
sewardjd68ac3e2006-01-20 14:31:57 +0000994static IRExpr* mkU32 ( UInt n ) {
995 return IRExpr_Const(IRConst_U32(n));
996}
sewardj4a0009c2006-10-17 01:52:05 +0000997
carllcae0cc22014-08-07 23:17:29 +0000998#if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000999static IRExpr* mkU8 ( UChar n ) {
1000 return IRExpr_Const(IRConst_U8(n));
1001}
sewardj4a0009c2006-10-17 01:52:05 +00001002static IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) {
1003 if (typeOfIRExpr(tyenv, e) == Ity_I32) {
1004 return e;
1005 } else {
1006 vg_assert(typeOfIRExpr(tyenv, e) == Ity_I64);
1007 return IRExpr_Unop(Iop_64to32, e);
1008 }
1009}
1010
1011/* Generate code to push word-typed expression 'e' onto this thread's
1012 redir stack, checking for stack overflow and generating code to
1013 bomb out if so. */
sewardj34593e52006-01-17 01:57:33 +00001014
sewardj0b9d74a2006-12-24 02:24:11 +00001015static void gen_PUSH ( IRSB* bb, IRExpr* e )
sewardj34593e52006-01-17 01:57:33 +00001016{
sewardj0b9d74a2006-12-24 02:24:11 +00001017 IRRegArray* descr;
1018 IRTemp t1;
1019 IRExpr* one;
sewardj34593e52006-01-17 01:57:33 +00001020
carllcae0cc22014-08-07 23:17:29 +00001021# if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
sewardj4a0009c2006-10-17 01:52:05 +00001022 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
1023 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
1024 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
florian2e497412012-08-26 03:22:09 +00001025 Int offB_EMNOTE = offsetof(VexGuestPPC64State,guest_EMNOTE);
sewardj291849f2012-04-20 23:58:55 +00001026 Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA);
sewardj4a0009c2006-10-17 01:52:05 +00001027 Bool is64 = True;
1028 IRType ty_Word = Ity_I64;
1029 IROp op_CmpNE = Iop_CmpNE64;
1030 IROp op_Sar = Iop_Sar64;
1031 IROp op_Sub = Iop_Sub64;
1032 IROp op_Add = Iop_Add64;
1033 IRExpr*(*mkU)(ULong) = mkU64;
1034 vg_assert(VG_WORDSIZE == 8);
1035# else
1036 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
1037 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
1038 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
florian2e497412012-08-26 03:22:09 +00001039 Int offB_EMNOTE = offsetof(VexGuestPPC32State,guest_EMNOTE);
sewardj291849f2012-04-20 23:58:55 +00001040 Int offB_CIA = offsetof(VexGuestPPC32State,guest_CIA);
sewardj4a0009c2006-10-17 01:52:05 +00001041 Bool is64 = False;
1042 IRType ty_Word = Ity_I32;
1043 IROp op_CmpNE = Iop_CmpNE32;
1044 IROp op_Sar = Iop_Sar32;
1045 IROp op_Sub = Iop_Sub32;
1046 IROp op_Add = Iop_Add32;
1047 IRExpr*(*mkU)(UInt) = mkU32;
1048 vg_assert(VG_WORDSIZE == 4);
1049# endif
1050
1051 vg_assert(sizeof(void*) == VG_WORDSIZE);
1052 vg_assert(sizeof(Word) == VG_WORDSIZE);
1053 vg_assert(sizeof(Addr) == VG_WORDSIZE);
1054
sewardj0b9d74a2006-12-24 02:24:11 +00001055 descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
sewardj4a0009c2006-10-17 01:52:05 +00001056 t1 = newIRTemp( bb->tyenv, ty_Word );
1057 one = mkU(1);
1058
1059 vg_assert(typeOfIRExpr(bb->tyenv, e) == ty_Word);
sewardj34593e52006-01-17 01:57:33 +00001060
1061 /* t1 = guest_REDIR_SP + 1 */
sewardj0b9d74a2006-12-24 02:24:11 +00001062 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001063 bb,
sewardj0b9d74a2006-12-24 02:24:11 +00001064 IRStmt_WrTmp(
sewardj34593e52006-01-17 01:57:33 +00001065 t1,
sewardj4a0009c2006-10-17 01:52:05 +00001066 IRExpr_Binop(op_Add, IRExpr_Get( offB_REDIR_SP, ty_Word ), one)
sewardj34593e52006-01-17 01:57:33 +00001067 )
1068 );
1069
sewardjd68ac3e2006-01-20 14:31:57 +00001070 /* Bomb out if t1 >=s stack_size, that is, (stack_size-1)-t1 <s 0.
1071 The destination (0) is a bit bogus but it doesn't matter since
1072 this is an unrecoverable error and will lead to Valgrind
florian2e497412012-08-26 03:22:09 +00001073 shutting down. _EMNOTE is set regardless - that's harmless
sewardjd68ac3e2006-01-20 14:31:57 +00001074 since is only has a meaning if the exit is taken. */
sewardj0b9d74a2006-12-24 02:24:11 +00001075 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001076 bb,
florian2e497412012-08-26 03:22:09 +00001077 IRStmt_Put(offB_EMNOTE, mkU32(EmWarn_PPC64_redir_overflow))
sewardjd68ac3e2006-01-20 14:31:57 +00001078 );
sewardj0b9d74a2006-12-24 02:24:11 +00001079 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001080 bb,
1081 IRStmt_Exit(
1082 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +00001083 op_CmpNE,
sewardjd68ac3e2006-01-20 14:31:57 +00001084 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +00001085 op_Sar,
sewardj0b9d74a2006-12-24 02:24:11 +00001086 IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_RdTmp(t1)),
sewardj4a0009c2006-10-17 01:52:05 +00001087 mkU8(8 * VG_WORDSIZE - 1)
sewardjd68ac3e2006-01-20 14:31:57 +00001088 ),
sewardj4a0009c2006-10-17 01:52:05 +00001089 mkU(0)
sewardjd68ac3e2006-01-20 14:31:57 +00001090 ),
1091 Ijk_EmFail,
sewardj291849f2012-04-20 23:58:55 +00001092 is64 ? IRConst_U64(0) : IRConst_U32(0),
1093 offB_CIA
sewardjd68ac3e2006-01-20 14:31:57 +00001094 )
1095 );
sewardj34593e52006-01-17 01:57:33 +00001096
1097 /* guest_REDIR_SP = t1 */
sewardj0b9d74a2006-12-24 02:24:11 +00001098 addStmtToIRSB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_RdTmp(t1)));
sewardj34593e52006-01-17 01:57:33 +00001099
1100 /* guest_REDIR_STACK[t1+0] = e */
sewardj4a0009c2006-10-17 01:52:05 +00001101 /* PutI/GetI have I32-typed indexes regardless of guest word size */
sewardj0b9d74a2006-12-24 02:24:11 +00001102 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001103 bb,
floriand39b0222012-05-31 15:48:13 +00001104 IRStmt_PutI(mkIRPutI(descr,
1105 narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0, e)));
sewardj34593e52006-01-17 01:57:33 +00001106}
1107
sewardj4a0009c2006-10-17 01:52:05 +00001108
1109/* Generate code to pop a word-sized value from this thread's redir
1110 stack, binding it to a new temporary, which is returned. As with
1111 gen_PUSH, an overflow check is also performed. */
1112
sewardj0b9d74a2006-12-24 02:24:11 +00001113static IRTemp gen_POP ( IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001114{
carllcae0cc22014-08-07 23:17:29 +00001115# if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
sewardj4a0009c2006-10-17 01:52:05 +00001116 Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE;
1117 Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP);
1118 Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK);
florian2e497412012-08-26 03:22:09 +00001119 Int offB_EMNOTE = offsetof(VexGuestPPC64State,guest_EMNOTE);
sewardj291849f2012-04-20 23:58:55 +00001120 Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA);
sewardj4a0009c2006-10-17 01:52:05 +00001121 Bool is64 = True;
1122 IRType ty_Word = Ity_I64;
1123 IROp op_CmpNE = Iop_CmpNE64;
1124 IROp op_Sar = Iop_Sar64;
1125 IROp op_Sub = Iop_Sub64;
1126 IRExpr*(*mkU)(ULong) = mkU64;
1127# else
1128 Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE;
1129 Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP);
1130 Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK);
florian2e497412012-08-26 03:22:09 +00001131 Int offB_EMNOTE = offsetof(VexGuestPPC32State,guest_EMNOTE);
sewardj291849f2012-04-20 23:58:55 +00001132 Int offB_CIA = offsetof(VexGuestPPC32State,guest_CIA);
sewardj4a0009c2006-10-17 01:52:05 +00001133 Bool is64 = False;
1134 IRType ty_Word = Ity_I32;
1135 IROp op_CmpNE = Iop_CmpNE32;
1136 IROp op_Sar = Iop_Sar32;
1137 IROp op_Sub = Iop_Sub32;
1138 IRExpr*(*mkU)(UInt) = mkU32;
1139# endif
sewardj34593e52006-01-17 01:57:33 +00001140
sewardj0b9d74a2006-12-24 02:24:11 +00001141 IRRegArray* descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size );
1142 IRTemp t1 = newIRTemp( bb->tyenv, ty_Word );
1143 IRTemp res = newIRTemp( bb->tyenv, ty_Word );
1144 IRExpr* one = mkU(1);
sewardj4a0009c2006-10-17 01:52:05 +00001145
1146 vg_assert(sizeof(void*) == VG_WORDSIZE);
1147 vg_assert(sizeof(Word) == VG_WORDSIZE);
1148 vg_assert(sizeof(Addr) == VG_WORDSIZE);
sewardj34593e52006-01-17 01:57:33 +00001149
1150 /* t1 = guest_REDIR_SP */
sewardj0b9d74a2006-12-24 02:24:11 +00001151 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001152 bb,
sewardj0b9d74a2006-12-24 02:24:11 +00001153 IRStmt_WrTmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) )
sewardj34593e52006-01-17 01:57:33 +00001154 );
1155
sewardjd68ac3e2006-01-20 14:31:57 +00001156 /* Bomb out if t1 < 0. Same comments as gen_PUSH apply. */
sewardj0b9d74a2006-12-24 02:24:11 +00001157 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001158 bb,
florian2e497412012-08-26 03:22:09 +00001159 IRStmt_Put(offB_EMNOTE, mkU32(EmWarn_PPC64_redir_underflow))
sewardjd68ac3e2006-01-20 14:31:57 +00001160 );
sewardj0b9d74a2006-12-24 02:24:11 +00001161 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001162 bb,
1163 IRStmt_Exit(
1164 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +00001165 op_CmpNE,
sewardjd68ac3e2006-01-20 14:31:57 +00001166 IRExpr_Binop(
sewardj4a0009c2006-10-17 01:52:05 +00001167 op_Sar,
sewardj0b9d74a2006-12-24 02:24:11 +00001168 IRExpr_RdTmp(t1),
sewardj4a0009c2006-10-17 01:52:05 +00001169 mkU8(8 * VG_WORDSIZE - 1)
sewardjd68ac3e2006-01-20 14:31:57 +00001170 ),
sewardj4a0009c2006-10-17 01:52:05 +00001171 mkU(0)
sewardjd68ac3e2006-01-20 14:31:57 +00001172 ),
1173 Ijk_EmFail,
sewardj291849f2012-04-20 23:58:55 +00001174 is64 ? IRConst_U64(0) : IRConst_U32(0),
1175 offB_CIA
sewardjd68ac3e2006-01-20 14:31:57 +00001176 )
1177 );
sewardj34593e52006-01-17 01:57:33 +00001178
1179 /* res = guest_REDIR_STACK[t1+0] */
sewardj4a0009c2006-10-17 01:52:05 +00001180 /* PutI/GetI have I32-typed indexes regardless of guest word size */
sewardj0b9d74a2006-12-24 02:24:11 +00001181 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001182 bb,
sewardj0b9d74a2006-12-24 02:24:11 +00001183 IRStmt_WrTmp(
sewardj34593e52006-01-17 01:57:33 +00001184 res,
sewardj0b9d74a2006-12-24 02:24:11 +00001185 IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0)
sewardj34593e52006-01-17 01:57:33 +00001186 )
1187 );
1188
1189 /* guest_REDIR_SP = t1-1 */
sewardj0b9d74a2006-12-24 02:24:11 +00001190 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001191 bb,
sewardj0b9d74a2006-12-24 02:24:11 +00001192 IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(op_Sub, IRExpr_RdTmp(t1), one))
sewardj34593e52006-01-17 01:57:33 +00001193 );
1194
1195 return res;
1196}
1197
carll582d5822014-08-07 23:35:54 +00001198#endif
1199
1200#if defined(VG_PLAT_USES_PPCTOC)
1201
sewardj4a0009c2006-10-17 01:52:05 +00001202/* Generate code to push LR and R2 onto this thread's redir stack,
1203 then set R2 to the new value (which is the TOC pointer to be used
1204 for the duration of the replacement function, as determined by
1205 m_debuginfo), and set LR to the magic return stub, so we get to
1206 intercept the return and restore R2 and L2 to the values saved
1207 here. */
1208
florianddd61ff2015-01-04 17:20:45 +00001209static void gen_push_and_set_LR_R2 ( IRSB* bb, Addr new_R2_value )
sewardj34593e52006-01-17 01:57:33 +00001210{
carllcae0cc22014-08-07 23:17:29 +00001211# if defined(VGP_ppc64be_linux)
florianddd61ff2015-01-04 17:20:45 +00001212 Addr bogus_RA = (Addr)&VG_(ppctoc_magic_redirect_return_stub);
sewardj4a0009c2006-10-17 01:52:05 +00001213 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1214 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
sewardj34593e52006-01-17 01:57:33 +00001215 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) );
1216 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
sewardj0b9d74a2006-12-24 02:24:11 +00001217 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) );
1218 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) );
sewardj4a0009c2006-10-17 01:52:05 +00001219
sewardj4a0009c2006-10-17 01:52:05 +00001220# else
1221# error Platform is not TOC-afflicted, fortunately
1222# endif
sewardj34593e52006-01-17 01:57:33 +00001223}
carll582d5822014-08-07 23:35:54 +00001224#endif
1225
1226#if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
sewardj34593e52006-01-17 01:57:33 +00001227
sewardj0b9d74a2006-12-24 02:24:11 +00001228static void gen_pop_R2_LR_then_bLR ( IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001229{
carllcae0cc22014-08-07 23:17:29 +00001230# if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
sewardj4a0009c2006-10-17 01:52:05 +00001231 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1232 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
sewardj291849f2012-04-20 23:58:55 +00001233 Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA);
sewardj4a0009c2006-10-17 01:52:05 +00001234 IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I64 );
1235 IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I64 );
sewardj34593e52006-01-17 01:57:33 +00001236 /* Restore R2 */
1237 old_R2 = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001238 addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) );
sewardj34593e52006-01-17 01:57:33 +00001239 /* Restore LR */
1240 old_LR = gen_POP( bb );
sewardj0b9d74a2006-12-24 02:24:11 +00001241 addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) );
sewardj34593e52006-01-17 01:57:33 +00001242 /* Branch to LR */
1243 /* re boring, we arrived here precisely because a wrapped fn did a
1244 blr (hence Ijk_Ret); so we should just mark this jump as Boring,
sewardj4a0009c2006-10-17 01:52:05 +00001245 else one _Call will have resulted in two _Rets. */
sewardj34593e52006-01-17 01:57:33 +00001246 bb->jumpkind = Ijk_Boring;
sewardj291849f2012-04-20 23:58:55 +00001247 bb->next = IRExpr_Binop(Iop_And64, IRExpr_RdTmp(old_LR), mkU64(~(3ULL)));
1248 bb->offsIP = offB_CIA;
sewardj4a0009c2006-10-17 01:52:05 +00001249# else
1250# error Platform is not TOC-afflicted, fortunately
1251# endif
sewardj34593e52006-01-17 01:57:33 +00001252}
carll582d5822014-08-07 23:35:54 +00001253#endif
1254
1255#if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
sewardj34593e52006-01-17 01:57:33 +00001256
1257static
sewardj0b9d74a2006-12-24 02:24:11 +00001258Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001259{
sewardj0283bae2006-01-22 01:15:36 +00001260 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj0b9d74a2006-12-24 02:24:11 +00001261 /* Since we're creating the entire IRSB right here, give it a
sewardj0283bae2006-01-22 01:15:36 +00001262 proper IMark, as it won't get one any other way, and cachegrind
1263 will barf if it doesn't have one (fair enough really). */
sewardj80e88b02011-05-28 15:34:17 +00001264 addStmtToIRSB( bb, IRStmt_IMark( closure->readdr, 4, 0 ) );
sewardj0283bae2006-01-22 01:15:36 +00001265 /* Generate the magic sequence:
1266 pop R2 from hidden stack
1267 pop LR from hidden stack
1268 goto LR
1269 */
sewardj34593e52006-01-17 01:57:33 +00001270 gen_pop_R2_LR_then_bLR(bb);
1271 return True; /* True == this is the entire BB; don't disassemble any
1272 real insns into it - just hand it directly to
1273 optimiser/instrumenter/backend. */
1274}
1275#endif
1276
carll582d5822014-08-07 23:35:54 +00001277#if defined(VGP_ppc64le_linux)
1278/* Generate code to push LR and R2 onto this thread's redir stack.
1279 Need to save R2 in case we redirect to a global entry point. The
1280 value of R2 is not preserved when entering the global entry point.
1281 Need to make sure R2 gets restored on return. Set LR to the magic
1282 return stub, so we get to intercept the return and restore R2 and
1283 L2 to the values saved here.
1284
1285 The existing infrastruture for the TOC enabled architectures is
1286 being exploited here. So, we need to enable a number of the
1287 code sections used by VG_PLAT_USES_PPCTOC.
1288*/
1289
1290static void gen_push_R2_and_set_LR ( IRSB* bb )
1291{
florianddd61ff2015-01-04 17:20:45 +00001292 Addr bogus_RA = (Addr)&VG_(ppctoc_magic_redirect_return_stub);
carll582d5822014-08-07 23:35:54 +00001293 Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2);
1294 Int offB_LR = offsetof(VexGuestPPC64State,guest_LR);
1295 gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) );
1296 gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
1297 addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) );
1298}
1299# endif
1300
sewardj4a0009c2006-10-17 01:52:05 +00001301/* --------------- END helpers for with-TOC platforms --------------- */
sewardj34593e52006-01-17 01:57:33 +00001302
sewardj4a0009c2006-10-17 01:52:05 +00001303
1304/* This is the IR preamble generator used for replacement
sewardj0283bae2006-01-22 01:15:36 +00001305 functions. It adds code to set the guest_NRADDR{_GPR2} to zero
sewardj34593e52006-01-17 01:57:33 +00001306 (technically not necessary, but facilitates detecting mixups in
sewardj0283bae2006-01-22 01:15:36 +00001307 which a replacement function has been erroneously declared using
1308 VG_REPLACE_FUNCTION_Z{U,Z} when instead it should have been written
1309 using VG_WRAP_FUNCTION_Z{U,Z}).
sewardj34593e52006-01-17 01:57:33 +00001310
sewardj4a0009c2006-10-17 01:52:05 +00001311 On with-TOC platforms the follow hacks are also done: LR and R2 are
1312 pushed onto a hidden stack, R2 is set to the correct value for the
1313 replacement function, and LR is set to point at the magic
1314 return-stub address. Setting LR causes the return of the
1315 wrapped/redirected function to lead to our magic return stub, which
1316 restores LR and R2 from said stack and returns for real.
sewardjdfbaa222006-01-18 04:25:20 +00001317
sewardjb8b79ad2008-03-03 01:35:41 +00001318 VG_(get_StackTrace_wrk) understands that the LR value may point to
1319 the return stub address, and that in that case it can get the real
1320 LR value from the hidden stack instead. */
sewardj34593e52006-01-17 01:57:33 +00001321static
sewardj0b9d74a2006-12-24 02:24:11 +00001322Bool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001323{
sewardj34593e52006-01-17 01:57:33 +00001324 Int nraddr_szB
1325 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1326 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
sewardj4a0009c2006-10-17 01:52:05 +00001327 vg_assert(nraddr_szB == VG_WORDSIZE);
sewardj0b9d74a2006-12-24 02:24:11 +00001328 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001329 bb,
1330 IRStmt_Put(
1331 offsetof(VexGuestArchState,guest_NRADDR),
sewardj0283bae2006-01-22 01:15:36 +00001332 nraddr_szB == 8 ? mkU64(0) : mkU32(0)
sewardj34593e52006-01-17 01:57:33 +00001333 )
1334 );
sewardj5db15402012-06-07 09:13:21 +00001335 // t9 needs to be set to point to the start of the redirected function.
petarj4df0bfc2013-02-27 23:17:33 +00001336# if defined(VGP_mips32_linux)
sewardj5db15402012-06-07 09:13:21 +00001337 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
petarj4df0bfc2013-02-27 23:17:33 +00001338 Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25);
1339 addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr)));
1340# endif
1341# if defined(VGP_mips64_linux)
1342 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1343 Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25);
1344 addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr)));
sewardj5db15402012-06-07 09:13:21 +00001345# endif
sewardj4a0009c2006-10-17 01:52:05 +00001346# if defined(VG_PLAT_USES_PPCTOC)
sewardj0283bae2006-01-22 01:15:36 +00001347 { VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
sewardj0b9d74a2006-12-24 02:24:11 +00001348 addStmtToIRSB(
sewardj0283bae2006-01-22 01:15:36 +00001349 bb,
1350 IRStmt_Put(
1351 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
sewardj4a0009c2006-10-17 01:52:05 +00001352 VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
sewardj0283bae2006-01-22 01:15:36 +00001353 )
1354 );
1355 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1356 }
sewardj34593e52006-01-17 01:57:33 +00001357# endif
carll582d5822014-08-07 23:35:54 +00001358
1359#if defined(VGP_ppc64le_linux)
1360 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1361 Int offB_GPR12 = offsetof(VexGuestArchState, guest_GPR12);
1362 addStmtToIRSB(bb, IRStmt_Put(offB_GPR12, mkU64(closure->readdr)));
1363 addStmtToIRSB(bb,
1364 IRStmt_Put(
1365 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1366 VG_WORDSIZE==8 ? mkU64(0) : mkU32(0)
1367 )
1368 );
1369 gen_push_R2_and_set_LR ( bb );
1370#endif
sewardj34593e52006-01-17 01:57:33 +00001371 return False;
1372}
1373
1374/* Ditto, except set guest_NRADDR to nraddr (the un-redirected guest
1375 address). This is needed for function wrapping - so the wrapper
1376 can read _NRADDR and find the address of the function being
sewardj4a0009c2006-10-17 01:52:05 +00001377 wrapped. On toc-afflicted platforms we must also snarf r2. */
sewardj34593e52006-01-17 01:57:33 +00001378static
sewardj0b9d74a2006-12-24 02:24:11 +00001379Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb )
sewardj34593e52006-01-17 01:57:33 +00001380{
1381 VgCallbackClosure* closure = (VgCallbackClosure*)closureV;
1382 Int nraddr_szB
1383 = sizeof(((VexGuestArchState*)0)->guest_NRADDR);
1384 vg_assert(nraddr_szB == 4 || nraddr_szB == 8);
sewardj4a0009c2006-10-17 01:52:05 +00001385 vg_assert(nraddr_szB == VG_WORDSIZE);
sewardj0b9d74a2006-12-24 02:24:11 +00001386 addStmtToIRSB(
sewardj34593e52006-01-17 01:57:33 +00001387 bb,
1388 IRStmt_Put(
1389 offsetof(VexGuestArchState,guest_NRADDR),
1390 nraddr_szB == 8
1391 ? IRExpr_Const(IRConst_U64( closure->nraddr ))
1392 : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
1393 )
1394 );
sewardj5db15402012-06-07 09:13:21 +00001395 // t9 needs to be set to point to the start of the redirected function.
petarj4df0bfc2013-02-27 23:17:33 +00001396# if defined(VGP_mips32_linux)
1397 Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25);
1398 addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr)));
1399# endif
1400# if defined(VGP_mips64_linux)
1401 Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25);
1402 addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr)));
sewardj5db15402012-06-07 09:13:21 +00001403# endif
carll8bea0912014-12-17 21:41:58 +00001404# if defined(VG_PLAT_USES_PPCTOC)
sewardj0b9d74a2006-12-24 02:24:11 +00001405 addStmtToIRSB(
sewardjd68ac3e2006-01-20 14:31:57 +00001406 bb,
1407 IRStmt_Put(
1408 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1409 IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2),
sewardj4a0009c2006-10-17 01:52:05 +00001410 VG_WORDSIZE==8 ? Ity_I64 : Ity_I32)
sewardjd68ac3e2006-01-20 14:31:57 +00001411 )
1412 );
sewardj34593e52006-01-17 01:57:33 +00001413 gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
1414# endif
carll582d5822014-08-07 23:35:54 +00001415#if defined(VGP_ppc64le_linux)
1416 /* This saves the r2 before leaving the function. We need to move
1417 * guest_NRADDR_GPR2 back to R2 on return.
1418 */
1419 Int offB_GPR12 = offsetof(VexGuestArchState, guest_GPR12);
1420 addStmtToIRSB(
1421 bb,
1422 IRStmt_Put(
1423 offsetof(VexGuestArchState,guest_NRADDR_GPR2),
1424 IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2),
1425 VG_WORDSIZE==8 ? Ity_I64 : Ity_I32)
1426 )
1427 );
1428 addStmtToIRSB(bb, IRStmt_Put(offB_GPR12, mkU64(closure->readdr)));
1429 gen_push_R2_and_set_LR ( bb );
1430#endif
sewardj34593e52006-01-17 01:57:33 +00001431 return False;
1432}
1433
sewardj4a0009c2006-10-17 01:52:05 +00001434/* --- Helpers to do with PPC related stack redzones. --- */
1435
1436__attribute__((unused))
florianddd61ff2015-01-04 17:20:45 +00001437static Bool const_True ( Addr guest_addr )
sewardj4a0009c2006-10-17 01:52:05 +00001438{
1439 return True;
1440}
1441
sewardj34593e52006-01-17 01:57:33 +00001442/* --------------- main translation function --------------- */
1443
sewardj0ec07f32006-01-12 12:32:32 +00001444/* Note: see comments at top of m_redir.c for the Big Picture on how
1445 redirections are managed. */
1446
sewardj34593e52006-01-17 01:57:33 +00001447typedef
1448 enum {
1449 /* normal translation, redir neither requested nor inhibited */
1450 T_Normal,
1451 /* redir translation, function-wrap (set _NRADDR) style */
1452 T_Redir_Wrap,
1453 /* redir translation, replacement (don't set _NRADDR) style */
1454 T_Redir_Replace,
1455 /* a translation in which redir is specifically disallowed */
1456 T_NoRedir
1457 }
1458 T_Kind;
1459
1460/* Translate the basic block beginning at NRADDR, and add it to the
1461 translation cache & translation table. Unless
1462 DEBUGGING_TRANSLATION is true, in which case the call is being done
1463 for debugging purposes, so (a) throw away the translation once it
1464 is made, and (b) produce a load of debugging output. If
1465 ALLOW_REDIRECTION is False, do not attempt redirection of NRADDR,
1466 and also, put the resulting translation into the no-redirect tt/tc
1467 instead of the normal one.
1468
1469 TID is the identity of the thread requesting this translation.
1470*/
1471
sewardjfa8ec112005-01-19 11:55:34 +00001472Bool VG_(translate) ( ThreadId tid,
florianddd61ff2015-01-04 17:20:45 +00001473 Addr nraddr,
sewardjfa8ec112005-01-19 11:55:34 +00001474 Bool debugging_translation,
njn394213a2005-06-19 18:38:24 +00001475 Int debugging_verbosity,
sewardj0ec07f32006-01-12 12:32:32 +00001476 ULong bbs_done,
1477 Bool allow_redirection )
sewardjde4a1d02002-03-22 01:27:54 +00001478{
florianddd61ff2015-01-04 17:20:45 +00001479 Addr addr;
sewardj34593e52006-01-17 01:57:33 +00001480 T_Kind kind;
sewardje2d1e672005-11-12 23:10:48 +00001481 Int tmpbuf_used, verbosity, i;
sewardj0b9d74a2006-12-24 02:24:11 +00001482 Bool (*preamble_fn)(void*,IRSB*);
sewardje2d1e672005-11-12 23:10:48 +00001483 VexArch vex_arch;
1484 VexArchInfo vex_archinfo;
sewardj0b9d74a2006-12-24 02:24:11 +00001485 VexAbiInfo vex_abiinfo;
sewardje2d1e672005-11-12 23:10:48 +00001486 VexGuestExtents vge;
sewardj274807d2005-12-15 14:07:07 +00001487 VexTranslateArgs vta;
sewardje2d1e672005-11-12 23:10:48 +00001488 VexTranslateResult tres;
sewardj34593e52006-01-17 01:57:33 +00001489 VgCallbackClosure closure;
njn36932cb2005-05-11 22:45:48 +00001490
sewardj8b635a42004-11-22 19:01:47 +00001491 /* Make sure Vex is initialised right. */
sewardje2d1e672005-11-12 23:10:48 +00001492
sewardj8b635a42004-11-22 19:01:47 +00001493 static Bool vex_init_done = False;
1494
1495 if (!vex_init_done) {
1496 LibVEX_Init ( &failure_exit, &log_bytes,
1497 1, /* debug_paranoia */
sewardj8b635a42004-11-22 19:01:47 +00001498 &VG_(clo_vex_control) );
1499 vex_init_done = True;
1500 }
1501
sewardj34593e52006-01-17 01:57:33 +00001502 /* Establish the translation kind and actual guest address to
1503 start from. Sets (addr,kind). */
sewardj0ec07f32006-01-12 12:32:32 +00001504 if (allow_redirection) {
sewardj34593e52006-01-17 01:57:33 +00001505 Bool isWrap;
florianddd61ff2015-01-04 17:20:45 +00001506 Addr tmp = VG_(redir_do_lookup)( nraddr, &isWrap );
sewardj34593e52006-01-17 01:57:33 +00001507 if (tmp == nraddr) {
1508 /* no redirection found */
1509 addr = nraddr;
1510 kind = T_Normal;
1511 } else {
1512 /* found a redirect */
1513 addr = tmp;
1514 kind = isWrap ? T_Redir_Wrap : T_Redir_Replace;
1515 }
sewardj0ec07f32006-01-12 12:32:32 +00001516 } else {
sewardj34593e52006-01-17 01:57:33 +00001517 addr = nraddr;
1518 kind = T_NoRedir;
sewardj0ec07f32006-01-12 12:32:32 +00001519 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001520
sewardj34593e52006-01-17 01:57:33 +00001521 /* Established: (nraddr, addr, kind) */
sewardj0ec07f32006-01-12 12:32:32 +00001522
sewardj34593e52006-01-17 01:57:33 +00001523 /* Printing redirection info. */
1524
1525 if ((kind == T_Redir_Wrap || kind == T_Redir_Replace)
sewardj0ec07f32006-01-12 12:32:32 +00001526 && (VG_(clo_verbosity) >= 2 || VG_(clo_trace_redir))) {
sewardjfa8ec112005-01-19 11:55:34 +00001527 Bool ok;
florian46cc0452014-10-25 19:20:38 +00001528 const HChar *buf;
1529 const HChar *name2;
1530
sewardj80d9c8f2014-06-17 20:37:08 +00001531 /* Try also to get the soname (not the filename) of the "from"
1532 object. This makes it much easier to debug redirection
1533 problems. */
1534 const HChar* nraddr_soname = "???";
1535 DebugInfo* nraddr_di = VG_(find_DebugInfo)(nraddr);
1536 if (nraddr_di) {
1537 const HChar* t = VG_(DebugInfo_get_soname)(nraddr_di);
1538 if (t)
1539 nraddr_soname = t;
1540 }
florian46cc0452014-10-25 19:20:38 +00001541
1542 ok = VG_(get_fnname_w_offset)(nraddr, &buf);
1543 if (!ok) buf = "???";
1544 // Stash away name1
1545 HChar name1[VG_(strlen)(buf) + 1];
1546 VG_(strcpy)(name1, buf);
1547 ok = VG_(get_fnname_w_offset)(addr, &name2);
1548 if (!ok) name2 = "???";
1549
njn3f04d242005-03-20 18:21:14 +00001550 VG_(message)(Vg_DebugMsg,
florianddd61ff2015-01-04 17:20:45 +00001551 "REDIR: 0x%lx (%s:%s) redirected to 0x%lx (%s)\n",
sewardj80d9c8f2014-06-17 20:37:08 +00001552 nraddr, nraddr_soname, name1,
sewardj34593e52006-01-17 01:57:33 +00001553 addr, name2 );
nethercote59a122d2004-08-03 17:16:51 +00001554 }
sewardj25c7c3a2003-07-10 00:17:58 +00001555
njn25e49d8e72002-09-23 09:36:25 +00001556 if (!debugging_translation)
sewardj45f4e7c2005-09-27 19:20:21 +00001557 VG_TRACK( pre_mem_read, Vg_CoreTranslate,
sewardj34593e52006-01-17 01:57:33 +00001558 tid, "(translator)", addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +00001559
sewardj85ac6d42005-02-23 11:36:56 +00001560 /* If doing any code printing, print a basic block start marker */
1561 if (VG_(clo_trace_flags) || debugging_translation) {
florian19f91bb2012-11-10 22:29:54 +00001562 const HChar* objname = "UNKNOWN_OBJECT";
sewardj227fd912011-10-21 04:59:56 +00001563 OffT objoff = 0;
1564 DebugInfo* di = VG_(find_DebugInfo)( addr );
1565 if (di) {
1566 objname = VG_(DebugInfo_get_filename)(di);
1567 objoff = addr - VG_(DebugInfo_get_text_bias)(di);
1568 }
1569 vg_assert(objname);
florian46cc0452014-10-25 19:20:38 +00001570
1571 const HChar *fnname;
1572 Bool ok = VG_(get_fnname_w_offset)(addr, &fnname);
1573 if (!ok) fnname = "UNKNOWN_FUNCTION";
sewardj85ac6d42005-02-23 11:36:56 +00001574 VG_(printf)(
floriana5e06c32015-08-05 21:16:09 +00001575 "==== SB %u (evchecks %llu) [tid %u] 0x%lx %s %s%c0x%lx\n",
1576 VG_(get_bbs_translated)(), bbs_done, tid, addr,
1577 fnname, objname, objoff >= 0 ? '+' : '-',
1578 (UWord)(objoff >= 0 ? objoff : -objoff)
sewardj227fd912011-10-21 04:59:56 +00001579 );
sewardj85ac6d42005-02-23 11:36:56 +00001580 }
1581
sewardj45f4e7c2005-09-27 19:20:21 +00001582 /* Are we allowed to translate here? */
1583
sewardj4a0009c2006-10-17 01:52:05 +00001584 { /* BEGIN new scope specially for 'seg' */
1585 NSegment const* seg = VG_(am_find_nsegment)(addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001586
philippe02320982013-05-02 22:06:31 +00001587 if ( (!translations_allowable_from_seg(seg, addr))
sewardj5f76de02007-02-11 05:08:06 +00001588 || addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
sewardj4a0009c2006-10-17 01:52:05 +00001589 if (VG_(clo_trace_signals))
florianddd61ff2015-01-04 17:20:45 +00001590 VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%lx)"
sewardj738856f2009-07-15 14:48:32 +00001591 " - throwing SEGV\n", addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001592 /* U R busted, sonny. Place your hands on your head and step
1593 away from the orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001594 /* Code address is bad - deliver a signal instead */
sewardj45f4e7c2005-09-27 19:20:21 +00001595 if (seg != NULL) {
1596 /* There's some kind of segment at the requested place, but we
1597 aren't allowed to execute code here. */
sewardj3b290482011-05-06 21:02:55 +00001598 if (debugging_translation)
1599 VG_(printf)("translations not allowed here (segment not executable)"
florianddd61ff2015-01-04 17:20:45 +00001600 "(0x%lx)\n", addr);
sewardj3b290482011-05-06 21:02:55 +00001601 else
1602 VG_(synth_fault_perms)(tid, addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001603 } else {
1604 /* There is no segment at all; we are attempting to execute in
1605 the middle of nowhere. */
sewardj3b290482011-05-06 21:02:55 +00001606 if (debugging_translation)
1607 VG_(printf)("translations not allowed here (no segment)"
florianddd61ff2015-01-04 17:20:45 +00001608 "(0x%lx)\n", addr);
sewardj3b290482011-05-06 21:02:55 +00001609 else
1610 VG_(synth_fault_mapping)(tid, addr);
sewardj45f4e7c2005-09-27 19:20:21 +00001611 }
nethercote4d714382004-10-13 09:47:24 +00001612 return False;
sewardj45f4e7c2005-09-27 19:20:21 +00001613 }
sewardjde4a1d02002-03-22 01:27:54 +00001614
njn25e49d8e72002-09-23 09:36:25 +00001615 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardjc771b292004-11-30 18:55:21 +00001616 verbosity = 0;
sewardj167d4e32004-12-31 01:14:04 +00001617 if (debugging_translation) {
sewardjfa8ec112005-01-19 11:55:34 +00001618 verbosity = debugging_verbosity;
sewardj167d4e32004-12-31 01:14:04 +00001619 }
1620 else
sewardjfa8ec112005-01-19 11:55:34 +00001621 if ( (VG_(clo_trace_flags) > 0
florian29e022d2012-07-02 21:13:34 +00001622 && VG_(get_bbs_translated)() <= VG_(clo_trace_notabove)
sewardj167d4e32004-12-31 01:14:04 +00001623 && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) {
sewardjfa8ec112005-01-19 11:55:34 +00001624 verbosity = VG_(clo_trace_flags);
sewardj167d4e32004-12-31 01:14:04 +00001625 }
njn25e49d8e72002-09-23 09:36:25 +00001626
sewardj34593e52006-01-17 01:57:33 +00001627 /* Figure out which preamble-mangling callback to send. */
1628 preamble_fn = NULL;
1629 if (kind == T_Redir_Replace)
1630 preamble_fn = mk_preamble__set_NRADDR_to_zero;
1631 else
1632 if (kind == T_Redir_Wrap)
1633 preamble_fn = mk_preamble__set_NRADDR_to_nraddr;
sewardj4a0009c2006-10-17 01:52:05 +00001634
carll582d5822014-08-07 23:35:54 +00001635 /* LE we setup the LR */
1636# if defined(VG_PLAT_USES_PPCTOC) || defined(VGP_ppc64le_linux)
florianddd61ff2015-01-04 17:20:45 +00001637 if (nraddr == (Addr)&VG_(ppctoc_magic_redirect_return_stub)) {
sewardj34593e52006-01-17 01:57:33 +00001638 /* If entering the special return stub, this means a wrapped or
1639 redirected function is returning. Make this translation one
1640 which restores R2 and LR from the thread's hidden redir
1641 stack, and branch to the (restored) link register, thereby
1642 really causing the function to return. */
1643 vg_assert(kind == T_Normal);
1644 vg_assert(nraddr == addr);
sewardj4a0009c2006-10-17 01:52:05 +00001645 preamble_fn = mk_preamble__ppctoc_magic_return_stub;
1646 }
sewardj34593e52006-01-17 01:57:33 +00001647# endif
1648
sewardje2d1e672005-11-12 23:10:48 +00001649 /* ------ Actually do the translation. ------ */
floriane2800c92014-09-15 20:57:45 +00001650 vg_assert2(VG_(tdict).tool_instrument,
njn51d827b2005-05-09 01:02:08 +00001651 "you forgot to set VgToolInterface function 'tool_instrument'");
sewardj7be55092005-08-01 23:25:55 +00001652
sewardje2d1e672005-11-12 23:10:48 +00001653 /* Get the CPU info established at startup. */
1654 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1655
sewardj0b9d74a2006-12-24 02:24:11 +00001656 /* Set up 'abiinfo' structure with stuff Vex needs to know about
sewardj4a0009c2006-10-17 01:52:05 +00001657 the guest and host ABIs. */
1658
sewardj0b9d74a2006-12-24 02:24:11 +00001659 LibVEX_default_VexAbiInfo( &vex_abiinfo );
1660 vex_abiinfo.guest_stack_redzone_size = VG_STACK_REDZONE_SZB;
sewardj4a0009c2006-10-17 01:52:05 +00001661
sewardjc0b20392008-12-04 00:07:30 +00001662# if defined(VGP_amd64_linux)
philippe8e785772014-12-17 00:00:11 +00001663 vex_abiinfo.guest_amd64_assume_fs_is_const = True;
1664 vex_abiinfo.guest_amd64_assume_gs_is_const = True;
sewardjc0b20392008-12-04 00:07:30 +00001665# endif
njnf76d27a2009-05-28 01:53:07 +00001666# if defined(VGP_amd64_darwin)
philippe8e785772014-12-17 00:00:11 +00001667 vex_abiinfo.guest_amd64_assume_gs_is_const = True;
njnf76d27a2009-05-28 01:53:07 +00001668# endif
sewardj4a0009c2006-10-17 01:52:05 +00001669# if defined(VGP_ppc32_linux)
sewardj0b9d74a2006-12-24 02:24:11 +00001670 vex_abiinfo.guest_ppc_zap_RZ_at_blr = False;
1671 vex_abiinfo.guest_ppc_zap_RZ_at_bl = NULL;
sewardj4a0009c2006-10-17 01:52:05 +00001672# endif
carllcae0cc22014-08-07 23:17:29 +00001673# if defined(VGP_ppc64be_linux)
sewardj0b9d74a2006-12-24 02:24:11 +00001674 vex_abiinfo.guest_ppc_zap_RZ_at_blr = True;
1675 vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True;
1676 vex_abiinfo.host_ppc_calls_use_fndescrs = True;
sewardj4a0009c2006-10-17 01:52:05 +00001677# endif
carll582d5822014-08-07 23:35:54 +00001678# if defined(VGP_ppc64le_linux)
1679 vex_abiinfo.guest_ppc_zap_RZ_at_blr = True;
1680 vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True;
1681 vex_abiinfo.host_ppc_calls_use_fndescrs = False;
1682# endif
sewardj8eb8bab2015-07-21 14:44:28 +00001683# if defined(VGP_amd64_solaris)
1684 vex_abiinfo.guest_amd64_assume_fs_is_const = True;
1685# endif
sewardj4a0009c2006-10-17 01:52:05 +00001686
sewardj34593e52006-01-17 01:57:33 +00001687 /* Set up closure args. */
1688 closure.tid = tid;
1689 closure.nraddr = nraddr;
1690 closure.readdr = addr;
sewardj7be55092005-08-01 23:25:55 +00001691
sewardj0ec07f32006-01-12 12:32:32 +00001692 /* Set up args for LibVEX_Translate. */
sewardj274807d2005-12-15 14:07:07 +00001693 vta.arch_guest = vex_arch;
1694 vta.archinfo_guest = vex_archinfo;
1695 vta.arch_host = vex_arch;
1696 vta.archinfo_host = vex_archinfo;
sewardj0b9d74a2006-12-24 02:24:11 +00001697 vta.abiinfo_both = vex_abiinfo;
sewardj291849f2012-04-20 23:58:55 +00001698 vta.callback_opaque = (void*)&closure;
florianddd61ff2015-01-04 17:20:45 +00001699 vta.guest_bytes = (UChar*)addr;
florian2d4ba292015-01-02 11:45:57 +00001700 vta.guest_bytes_addr = addr;
sewardj274807d2005-12-15 14:07:07 +00001701 vta.chase_into_ok = chase_into_ok;
1702 vta.guest_extents = &vge;
1703 vta.host_bytes = tmpbuf;
1704 vta.host_bytes_size = N_TMPBUF;
1705 vta.host_bytes_used = &tmpbuf_used;
sewardj34593e52006-01-17 01:57:33 +00001706 { /* At this point we have to reconcile Vex's view of the
1707 instrumentation callback - which takes a void* first argument
1708 - with Valgrind's view, in which the first arg is a
1709 VgCallbackClosure*. Hence the following longwinded casts.
1710 They are entirely legal but longwinded so as to maximise the
1711 chance of the C typechecker picking up any type snafus. */
sewardj0b9d74a2006-12-24 02:24:11 +00001712 IRSB*(*f)(VgCallbackClosure*,
florian3c0c9472014-09-24 12:06:55 +00001713 IRSB*,const VexGuestLayout*,const VexGuestExtents*,
1714 const VexArchInfo*,IRType,IRType)
sewardj3b290482011-05-06 21:02:55 +00001715 = VG_(clo_vgdb) != Vg_VgdbNo
1716 ? tool_instrument_then_gdbserver_if_needed
1717 : VG_(tdict).tool_instrument;
sewardj0b9d74a2006-12-24 02:24:11 +00001718 IRSB*(*g)(void*,
florian3c0c9472014-09-24 12:06:55 +00001719 IRSB*,const VexGuestLayout*,const VexGuestExtents*,
floriand4fbf142014-10-09 16:44:30 +00001720 const VexArchInfo*,IRType,IRType) = (__typeof__(g)) f;
sewardj291849f2012-04-20 23:58:55 +00001721 vta.instrument1 = g;
sewardj34593e52006-01-17 01:57:33 +00001722 }
1723 /* No need for type kludgery here. */
sewardj291849f2012-04-20 23:58:55 +00001724 vta.instrument2 = need_to_handle_SP_assignment()
1725 ? vg_SP_update_pass
1726 : NULL;
1727 vta.finaltidy = VG_(needs).final_IR_tidy_pass
1728 ? VG_(tdict).tool_final_IR_tidy_pass
1729 : NULL;
1730 vta.needs_self_check = needs_self_check;
1731 vta.preamble_function = preamble_fn;
1732 vta.traceflags = verbosity;
sewardjc30cd9b2012-12-06 18:08:54 +00001733 vta.sigill_diag = VG_(clo_sigill_diag);
sewardj17c5e2e2012-12-28 09:12:14 +00001734 vta.addProfInc = VG_(clo_profyle_sbs) && kind != T_NoRedir;
sewardj274807d2005-12-15 14:07:07 +00001735
sewardj291849f2012-04-20 23:58:55 +00001736 /* Set up the dispatch continuation-point info. If this is a
1737 no-redir translation then it cannot be chained, and the chain-me
1738 points are set to NULL to indicate that. The indir point must
1739 also be NULL, since we can't allow this translation to do an
1740 indir transfer -- that would take it back into the main
1741 translation cache too.
sewardj0ec07f32006-01-12 12:32:32 +00001742
sewardj291849f2012-04-20 23:58:55 +00001743 All this is because no-redir translations live outside the main
1744 translation cache (in a secondary one) and chaining them would
1745 involve more adminstrative complexity that isn't worth the
1746 hassle, because we don't expect them to get used often. So
1747 don't bother. */
1748 if (allow_redirection) {
1749 vta.disp_cp_chain_me_to_slowEP
1750 = VG_(fnptr_to_fnentry)( &VG_(disp_cp_chain_me_to_slowEP) );
1751 vta.disp_cp_chain_me_to_fastEP
1752 = VG_(fnptr_to_fnentry)( &VG_(disp_cp_chain_me_to_fastEP) );
1753 vta.disp_cp_xindir
1754 = VG_(fnptr_to_fnentry)( &VG_(disp_cp_xindir) );
1755 } else {
1756 vta.disp_cp_chain_me_to_slowEP = NULL;
1757 vta.disp_cp_chain_me_to_fastEP = NULL;
1758 vta.disp_cp_xindir = NULL;
sewardj12740272011-05-29 09:34:30 +00001759 }
sewardj291849f2012-04-20 23:58:55 +00001760 /* This doesn't involve chaining and so is always allowable. */
1761 vta.disp_cp_xassisted
1762 = VG_(fnptr_to_fnentry)( &VG_(disp_cp_xassisted) );
sewardj274807d2005-12-15 14:07:07 +00001763
1764 /* Sheesh. Finally, actually _do_ the translation! */
1765 tres = LibVEX_Translate ( &vta );
njn25e49d8e72002-09-23 09:36:25 +00001766
sewardj6dbcc632011-06-07 21:39:28 +00001767 vg_assert(tres.status == VexTransOK);
1768 vg_assert(tres.n_sc_extents >= 0 && tres.n_sc_extents <= 3);
sewardj8b635a42004-11-22 19:01:47 +00001769 vg_assert(tmpbuf_used <= N_TMPBUF);
1770 vg_assert(tmpbuf_used > 0);
sewardj4a0009c2006-10-17 01:52:05 +00001771 } /* END new scope specially for 'seg' */
sewardj45f4e7c2005-09-27 19:20:21 +00001772
florian2fa66ce2015-03-07 23:01:14 +00001773 /* Tell aspacem of all segments that have had translations taken
1774 from them. */
1775 for (i = 0; i < vge.n_used; i++) {
1776 VG_(am_set_segment_hasT)( vge.base[i] );
sewardj45f4e7c2005-09-27 19:20:21 +00001777 }
1778
nethercote59a122d2004-08-03 17:16:51 +00001779 /* Copy data at trans_addr into the translation cache. */
sewardj8b635a42004-11-22 19:01:47 +00001780 vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536);
nethercote59a122d2004-08-03 17:16:51 +00001781
1782 // If debugging, don't do anything with the translated block; we
1783 // only did this for the debugging output produced along the way.
1784 if (!debugging_translation) {
sewardj0ec07f32006-01-12 12:32:32 +00001785
sewardj34593e52006-01-17 01:57:33 +00001786 if (kind != T_NoRedir) {
sewardj0ec07f32006-01-12 12:32:32 +00001787 // Put it into the normal TT/TC structures. This is the
1788 // normal case.
1789
sewardj34593e52006-01-17 01:57:33 +00001790 // Note that we use nraddr (the non-redirected address), not
1791 // addr, which might have been changed by the redirection
sewardj0ec07f32006-01-12 12:32:32 +00001792 VG_(add_to_transtab)( &vge,
sewardj34593e52006-01-17 01:57:33 +00001793 nraddr,
sewardj0ec07f32006-01-12 12:32:32 +00001794 (Addr)(&tmpbuf[0]),
1795 tmpbuf_used,
sewardj291849f2012-04-20 23:58:55 +00001796 tres.n_sc_extents > 0,
1797 tres.offs_profInc,
sewardj59731422014-07-24 12:45:24 +00001798 tres.n_guest_instrs );
sewardj0ec07f32006-01-12 12:32:32 +00001799 } else {
sewardj291849f2012-04-20 23:58:55 +00001800 vg_assert(tres.offs_profInc == -1); /* -1 == unset */
sewardj0ec07f32006-01-12 12:32:32 +00001801 VG_(add_to_unredir_transtab)( &vge,
sewardj34593e52006-01-17 01:57:33 +00001802 nraddr,
sewardj0ec07f32006-01-12 12:32:32 +00001803 (Addr)(&tmpbuf[0]),
njn1dcee092009-02-24 03:07:37 +00001804 tmpbuf_used );
sewardj0ec07f32006-01-12 12:32:32 +00001805 }
sewardjde4a1d02002-03-22 01:27:54 +00001806 }
nethercote59a122d2004-08-03 17:16:51 +00001807
nethercote4d714382004-10-13 09:47:24 +00001808 return True;
sewardjde4a1d02002-03-22 01:27:54 +00001809}
1810
1811/*--------------------------------------------------------------------*/
njn3cbfbc12005-05-13 23:11:40 +00001812/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001813/*--------------------------------------------------------------------*/