1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Interface to LibVEX_Translate, and the SP-update pass ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- m_translate.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2000-2013 Julian Seward 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" // VG_(fnptr_to_fnentry) 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(get_SP) 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(machine_get_VexArchInfo) 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h" // VG_(get_fnname_w_offset) 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_redir.h" // VG_(redir_do_lookup) 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h" // VG_(synth_fault_{perms,mapping} 48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_stacks.h" // VG_(unknown_SP_update*)() 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" // VG_(tdict) 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_translate.h" 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h" 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_dispatch.h" // VG_(run_innerloop__dispatch_{un}profiled) 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(run_a_noredir_translation__return_point) 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" // VexGuestArchState 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_trampoline.h" // VG_(ppctoc_magic_redirect_return_stub) 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_execontext.h" // VG_(make_depth_1_ExeContext_from_Addr) 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_gdbserver.h" // VG_(tool_instrument_then_gdbserver_if_needed) 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex_emnote.h" // For PPC, EmWarn_PPC64_redir_underflow 65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Stats ---*/ 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_SP_updates_fast = 0; 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_SP_updates_generic_known = 0; 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt n_SP_updates_generic_unknown = 0; 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(print_translation_stats) ( void ) 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar buf[7]; 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + n_SP_updates_generic_unknown; 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(percentify)(n_SP_updates_fast, n_SP_updates, 1, 6, buf); 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "translate: fast SP updates identified: %'u (%s)\n", 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SP_updates_fast, buf ); 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(percentify)(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf); 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "translate: generic_known SP updates identified: %'u (%s)\n", 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SP_updates_generic_known, buf ); 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(percentify)(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf); 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "translate: generic_unknown SP updates identified: %'u (%s)\n", 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SP_updates_generic_unknown, buf ); 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- %SP-update pass ---*/ 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool need_to_handle_SP_assignment(void) 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ( VG_(tdict).track_new_mem_stack_4 || 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_4 || 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_8 || 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_8 || 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_12 || 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_12 || 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_16 || 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_16 || 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_32 || 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_32 || 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_112 || 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_112 || 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_128 || 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_128 || 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_144 || 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_144 || 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_160 || 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_160 || 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack || 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack ); 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - The SP aliases are held in an array which is used as a circular buffer. 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This misses very few constant updates of SP (ie. < 0.1%) while using a 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// small, constant structure that will also never fill up and cause 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// execution to abort. 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Unused slots have a .temp value of 'IRTemp_INVALID'. 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - 'next_SP_alias_slot' is the index where the next alias will be stored. 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - If the buffer fills, we circle around and start over-writing 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// non-IRTemp_INVALID values. This is rare, and the overwriting of a 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// value that would have subsequently be used is even rarer. 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Every slot below next_SP_alias_slot holds a non-IRTemp_INVALID value. 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The rest either all won't (if we haven't yet circled around) or all 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// will (if we have circled around). 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp temp; 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long delta; 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SP_Alias; 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// With 32 slots the buffer fills very rarely -- eg. once in a run of GCC. 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// And I've tested with smaller values and the wrap-around case works ok. 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_ALIASES 32 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SP_Alias SP_aliases[N_ALIASES]; 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int next_SP_alias_slot = 0; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void clear_SP_aliases(void) 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < N_ALIASES; i++) { 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SP_aliases[i].temp = IRTemp_INVALID; 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SP_aliases[i].delta = 0; 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown next_SP_alias_slot = 0; 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_SP_alias(IRTemp temp, Long delta) 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(temp != IRTemp_INVALID); 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SP_aliases[ next_SP_alias_slot ].temp = temp; 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SP_aliases[ next_SP_alias_slot ].delta = delta; 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown next_SP_alias_slot++; 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (N_ALIASES == next_SP_alias_slot) next_SP_alias_slot = 0; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool get_SP_delta(IRTemp temp, Long* delta) 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; // i must be signed! 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(IRTemp_INVALID != temp); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Search backwards between current buffer position and the start. 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = next_SP_alias_slot-1; i >= 0; i--) { 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (temp == SP_aliases[i].temp) { 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *delta = SP_aliases[i].delta; 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Search backwards between the end and the current buffer position. 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = N_ALIASES-1; i >= next_SP_alias_slot; i--) { 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (temp == SP_aliases[i].temp) { 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *delta = SP_aliases[i].delta; 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void update_SP_aliases(Long delta) 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < N_ALIASES; i++) { 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (SP_aliases[i].temp == IRTemp_INVALID) { 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SP_aliases[i].delta += delta; 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given a guest IP, get an origin tag for a 1-element stack trace, 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and wrap it up in an IR atom that can be passed as the origin-tag 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value for a stack-adjustment helper function. */ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_ecu_Expr ( Addr64 guest_IP ) 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ecu; 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* ec 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(make_depth_1_ExeContext_from_Addr)( (Addr)guest_IP ); 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ec); 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ecu = VG_(get_ECU_from_ExeContext)( ec ); 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_plausible_ECU)(ecu)); 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is always safe to do, since ecu is only 32 bits, and 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord is 32 or 64. */ 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mkIRExpr_HWord( (HWord)ecu ); 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* When gdbserver is activated, the translation of a block must 217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov first be done by the tool function, then followed by a pass 218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov which (if needed) instruments the code for gdbserver. 219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/ 220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic 221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRSB* tool_instrument_then_gdbserver_if_needed ( VgCallbackClosure* closureV, 222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRSB* sb_in, 223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VexGuestLayout* layout, 224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VexGuestExtents* vge, 225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexArchInfo* vai, 226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRType gWordTy, 227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRType hWordTy ) 228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return VG_(instrument_for_gdbserver_if_needed) 230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (VG_(tdict).tool_instrument (closureV, 231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sb_in, 232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout, 233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vge, 234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vai, 235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gWordTy, 236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov hWordTy), 237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov layout, 238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vge, 239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov gWordTy, 240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov hWordTy); 241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For tools that want to know about SP changes, this pass adds 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in the appropriate hooks. We have to do it after the tool's 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrumentation, so the tool doesn't have to worry about the C calls 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it adds in, and we must do it before register allocation because 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spilled temps make it much harder to work out the SP deltas. 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This it is done with Vex's "second instrumentation" pass. 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Basically, we look for GET(SP)/PUT(SP) pairs and track constant 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown increments/decrements of SP between them. (This requires tracking one or 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown more "aliases", which are not exact aliases but instead are tempregs 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whose value is equal to the SP's plus or minus a known constant.) 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If all the changes to SP leading up to a PUT(SP) are by known, small 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown constants, we can do a specific call to eg. new_mem_stack_4, otherwise 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we fall back to the case that handles an unknown SP change. 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There is some extra complexity to deal correctly with updates to 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown only parts of SP. Bizarre, but it has been known to happen. 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* vg_SP_update_pass ( void* closureV, 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB* sb_in, 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestLayout* layout, 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestExtents* vge, 266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexArchInfo* vai, 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType gWordTy, 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType hWordTy ) 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int i, j, k, minoff_ST, maxoff_ST, sizeof_SP, offset_SP; 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int first_SP, last_SP, first_Put, last_Put; 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty *dcall, *d; 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt* st; 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* e; 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRRegArray* descr; 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType typeof_SP; 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long delta, con; 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up stuff for tracking the guest IP */ 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool curr_IP_known = False; 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr64 curr_IP = 0; 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up BB */ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB* bb = emptyIRSB(); 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->tyenv = deepCopyIRTypeEnv(sb_in->tyenv); 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->next = deepCopyIRExpr(sb_in->next); 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->jumpkind = sb_in->jumpkind; 288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng bb->offsIP = sb_in->offsIP; 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delta = 0; 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof_SP = layout->sizeof_SP; 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset_SP = layout->offset_SP; 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof_SP == 4 || sizeof_SP == 8); 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- Start of #defines --- */ 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64)) 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64)) 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op)) 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define GET_CONST(con) \ 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32) \ 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : (Long)(con->Ico.U64)) 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define DO_NEW(syze, tmpp) \ 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool vanilla, w_ecu; \ 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(curr_IP_known); \ 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vanilla = NULL != VG_(tdict).track_new_mem_stack_##syze; \ 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w_ecu = NULL != VG_(tdict).track_new_mem_stack_##syze##_w_ECU; \ 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!(vanilla && w_ecu)); /* can't have both */ \ 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(vanilla || w_ecu)) \ 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto generic; \ 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* I don't know if it's really necessary to say that the */ \ 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* call reads the stack pointer. But anyway, we do. */ \ 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (w_ecu) { \ 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall = unsafeIRDirty_0_N( \ 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2/*regparms*/, \ 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "track_new_mem_stack_" #syze "_w_ECU", \ 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( \ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_##syze##_w_ECU ), \ 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_2(IRExpr_RdTmp(tmpp), \ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mk_ecu_Expr(curr_IP)) \ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); \ 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { \ 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall = unsafeIRDirty_0_N( \ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1/*regparms*/, \ 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "track_new_mem_stack_" #syze , \ 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( \ 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_new_mem_stack_##syze ), \ 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \ 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); \ 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall->nFxState = 1; \ 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall->fxState[0].fx = Ifx_Read; \ 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall->fxState[0].offset = layout->offset_SP; \ 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall->fxState[0].size = layout->sizeof_SP; \ 342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dcall->fxState[0].nRepeats = 0; \ 343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dcall->fxState[0].repeatLen = 0; \ 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(syze > 0); \ 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown update_SP_aliases(syze); \ 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SP_updates_fast++; \ 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define DO_DIE(syze, tmpp) \ 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(tdict).track_die_mem_stack_##syze) \ 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto generic; \ 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* I don't know if it's really necessary to say that the */ \ 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* call reads the stack pointer. But anyway, we do. */ \ 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall = unsafeIRDirty_0_N( \ 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1/*regparms*/, \ 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "track_die_mem_stack_" #syze, \ 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fnptr_to_fnentry)( \ 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tdict).track_die_mem_stack_##syze ), \ 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkIRExprVec_1(IRExpr_RdTmp(tmpp)) \ 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); \ 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall->nFxState = 1; \ 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall->fxState[0].fx = Ifx_Read; \ 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall->fxState[0].offset = layout->offset_SP; \ 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dcall->fxState[0].size = layout->sizeof_SP; \ 372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dcall->fxState[0].nRepeats = 0; \ 373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dcall->fxState[0].repeatLen = 0; \ 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); \ 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(syze > 0); \ 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown update_SP_aliases(-(syze)); \ 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SP_updates_fast++; \ 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- End of #defines --- */ 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clear_SP_aliases(); 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < sb_in->stmts_used; i++) { 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown st = sb_in->stmts[i]; 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag == Ist_IMark) { 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_IP_known = True; 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr_IP = st->Ist.IMark.addr; 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* t = Get(sp): curr = t, delta = 0 */ 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag != Ist_WrTmp) goto case2; 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e = st->Ist.WrTmp.data; 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag != Iex_Get) goto case2; 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Get.offset != offset_SP) goto case2; 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Get.ty != typeof_SP) goto case2; 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP ); 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_SP_alias(st->Ist.WrTmp.tmp, 0); 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, st ); 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case2: 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* t' = curr +/- const: curr = t', delta +=/-= const */ 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag != Ist_WrTmp) goto case3; 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e = st->Ist.WrTmp.data; 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag != Iex_Binop) goto case3; 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg1->tag != Iex_RdTmp) goto case3; 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!get_SP_delta(e->Iex.Binop.arg1->Iex.RdTmp.tmp, &delta)) goto case3; 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3; 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3; 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown con = GET_CONST(e->Iex.Binop.arg2->Iex.Const.con); 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP ); 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (IS_ADD(e->Iex.Binop.op)) { 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_SP_alias(st->Ist.WrTmp.tmp, delta + con); 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_SP_alias(st->Ist.WrTmp.tmp, delta - con); 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, st ); 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case3: 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* t' = curr: curr = t' */ 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag != Ist_WrTmp) goto case4; 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e = st->Ist.WrTmp.data; 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag != Iex_RdTmp) goto case4; 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!get_SP_delta(e->Iex.RdTmp.tmp, &delta)) goto case4; 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.WrTmp.tmp) == typeof_SP ); 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_SP_alias(st->Ist.WrTmp.tmp, delta); 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, st ); 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case4: 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Put(sp) = curr */ 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* More generally, we must correctly handle a Put which writes 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any part of SP, not just the case where all of SP is 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown written. */ 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag != Ist_Put) goto case5; 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown first_SP = offset_SP; 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last_SP = first_SP + sizeof_SP - 1; 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown first_Put = st->Ist.Put.offset; 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last_Put = first_Put 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + sizeofIRType( typeOfIRExpr( bb->tyenv, st->Ist.Put.data )) 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - 1; 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(first_SP <= last_SP); 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(first_Put <= last_Put); 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (last_Put < first_SP || last_SP < first_Put) 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto case5; /* no overlap */ 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->Ist.Put.data->tag == Iex_RdTmp 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && get_SP_delta(st->Ist.Put.data->Iex.RdTmp.tmp, &delta)) { 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp tttmp = st->Ist.Put.data->Iex.RdTmp.tmp; 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Why should the following assertion hold? Because any 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alias added by put_SP_alias must be of a temporary which 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown has the same type as typeof_SP, and whose value is a Get 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown at exactly offset_SP of size typeof_SP. Each call to 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown put_SP_alias is immediately preceded by an assertion that 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we are putting in a binding for a correctly-typed 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temporary. */ 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( typeOfIRTemp(bb->tyenv, tttmp) == typeof_SP ); 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* From the same type-and-offset-correctness argument, if 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we found a useable alias, it must for an "exact" write of SP. */ 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(first_SP == first_Put); 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(last_SP == last_Put); 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (delta) { 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0: addStmtToIRSB(bb,st); continue; 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 4: DO_DIE( 4, tttmp); addStmtToIRSB(bb,st); continue; 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -4: DO_NEW( 4, tttmp); addStmtToIRSB(bb,st); continue; 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 8: DO_DIE( 8, tttmp); addStmtToIRSB(bb,st); continue; 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -8: DO_NEW( 8, tttmp); addStmtToIRSB(bb,st); continue; 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 12: DO_DIE( 12, tttmp); addStmtToIRSB(bb,st); continue; 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -12: DO_NEW( 12, tttmp); addStmtToIRSB(bb,st); continue; 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 16: DO_DIE( 16, tttmp); addStmtToIRSB(bb,st); continue; 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -16: DO_NEW( 16, tttmp); addStmtToIRSB(bb,st); continue; 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 32: DO_DIE( 32, tttmp); addStmtToIRSB(bb,st); continue; 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -32: DO_NEW( 32, tttmp); addStmtToIRSB(bb,st); continue; 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 112: DO_DIE( 112, tttmp); addStmtToIRSB(bb,st); continue; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -112: DO_NEW( 112, tttmp); addStmtToIRSB(bb,st); continue; 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 128: DO_DIE( 128, tttmp); addStmtToIRSB(bb,st); continue; 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -128: DO_NEW( 128, tttmp); addStmtToIRSB(bb,st); continue; 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 144: DO_DIE( 144, tttmp); addStmtToIRSB(bb,st); continue; 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -144: DO_NEW( 144, tttmp); addStmtToIRSB(bb,st); continue; 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 160: DO_DIE( 160, tttmp); addStmtToIRSB(bb,st); continue; 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case -160: DO_NEW( 160, tttmp); addStmtToIRSB(bb,st); continue; 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* common values for ppc64: 144 128 160 112 176 */ 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SP_updates_generic_known++; 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto generic; 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Deal with an unknown update to SP. We're here because 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown either: 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (1) the Put does not exactly cover SP; it is a partial update. 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Highly unlikely, but has been known to happen for 16-bit 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Windows apps running on Wine, doing 16-bit adjustments to 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown %sp. 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (2) the Put does exactly cover SP, but we are unable to 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown determine how the value relates to the old SP. In any 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case, we cannot assume that the Put.data value is a tmp; 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we must assume it can be anything allowed in flat IR (tmp 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or const). 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp old_SP; 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_SP_updates_generic_unknown++; 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: if all is well, this generic case will typically be 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // called something like every 1000th SP update. If it's more than 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // that, the above code may be missing some cases. 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generic: 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Pass both the old and new SP values to this helper. Also, 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pass an origin tag, even if it isn't needed. */ 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_SP = newIRTemp(bb->tyenv, typeof_SP); 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_WrTmp( old_SP, IRExpr_Get(offset_SP, typeof_SP) ) 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we know what the old value of SP is. But knowing the new 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value is a bit tricky if there is a partial write. */ 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (first_Put == first_SP && last_Put == last_SP) { 527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The common case, an exact write to SP. So st->Ist.Put.data 528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov does hold the new value; simple. */ 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(curr_IP_known); 530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (NULL != VG_(tdict).track_new_mem_stack_w_ECU) 531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov dcall = unsafeIRDirty_0_N( 532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3/*regparms*/, 533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "VG_(unknown_SP_update_w_ECU)", 534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update_w_ECU) ), 535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mkIRExprVec_3( IRExpr_RdTmp(old_SP), st->Ist.Put.data, 536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mk_ecu_Expr(curr_IP) ) 537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ); 538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else 539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov dcall = unsafeIRDirty_0_N( 540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2/*regparms*/, 541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "VG_(unknown_SP_update)", 542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ), 543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mkIRExprVec_2( IRExpr_RdTmp(old_SP), st->Ist.Put.data ) 544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ); 545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* don't forget the original assignment */ 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, st ); 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We have a partial update to SP. We need to know what 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the new SP will be, and hand that to the helper call, 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but when the helper call happens, SP must hold the 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value it had before the update. Tricky. 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Therefore use the following kludge: 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1. do the partial SP update (Put) 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2. Get the new SP value into a tmp, new_SP 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3. Put old_SP 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4. Call the helper 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5. Put new_SP 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp new_SP; 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 1 */ 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, st ); 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 2 */ 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_SP = newIRTemp(bb->tyenv, typeof_SP); 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_WrTmp( new_SP, IRExpr_Get(offset_SP, typeof_SP) ) 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 3 */ 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(old_SP) )); 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 4 */ 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(curr_IP_known); 574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (NULL != VG_(tdict).track_new_mem_stack_w_ECU) 575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov dcall = unsafeIRDirty_0_N( 576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3/*regparms*/, 577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "VG_(unknown_SP_update_w_ECU)", 578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update_w_ECU) ), 579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mkIRExprVec_3( IRExpr_RdTmp(old_SP), 580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr_RdTmp(new_SP), 581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mk_ecu_Expr(curr_IP) ) 582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ); 583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else 584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov dcall = unsafeIRDirty_0_N( 585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2/*regparms*/, 586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "VG_(unknown_SP_update)", 587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ), 588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mkIRExprVec_2( IRExpr_RdTmp(old_SP), 589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr_RdTmp(new_SP) ) 590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ); 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Dirty(dcall) ); 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 5 */ 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(new_SP) )); 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Forget what we already know. */ 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clear_SP_aliases(); 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this is a Put of a tmp that exactly updates SP, 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start tracking aliases against this tmp. */ 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (first_Put == first_SP && last_Put == last_SP 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && st->Ist.Put.data->tag == Iex_RdTmp) { 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( typeOfIRTemp(bb->tyenv, st->Ist.Put.data->Iex.RdTmp.tmp) 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == typeof_SP ); 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_SP_alias(st->Ist.Put.data->Iex.RdTmp.tmp, 0); 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case5: 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* PutI or Dirty call which overlaps SP: complain. We can't 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deal with SP changing in weird ways (well, we can, but not at 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this time of night). */ 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag == Ist_PutI) { 616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng descr = st->Ist.PutI.details->descr; 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown minoff_ST = descr->base; 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown maxoff_ST = descr->base 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + descr->nElems * sizeofIRType(descr->elemTy) - 1; 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(offset_SP > maxoff_ST 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (offset_SP + sizeof_SP - 1) < minoff_ST)) 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto complain; 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (st->tag == Ist_Dirty) { 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = st->Ist.Dirty.details; 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < d->nFxState; j++) { 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->fxState[j].fx == Ifx_Read || d->fxState[j].fx == Ifx_None) 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Enumerate the described state segments */ 630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (k = 0; k < 1 + d->fxState[j].nRepeats; k++) { 631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng minoff_ST = d->fxState[j].offset + k * d->fxState[j].repeatLen; 632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng maxoff_ST = minoff_ST + d->fxState[j].size - 1; 633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (!(offset_SP > maxoff_ST 634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || (offset_SP + sizeof_SP - 1) < minoff_ST)) 635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng goto complain; 636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* well, not interesting. Just copy and keep going. */ 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, st ); 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* for (i = 0; i < sb_in->stmts_used; i++) */ 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return bb; 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain: 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("vg_SP_update_pass: PutI or Dirty which overlaps SP"); 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef IS_ADD 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef IS_SUB 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef IS_ADD_OR_SUB 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef GET_CONST 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DO_NEW 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DO_DIE 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Main entry point for the JITter. ---*/ 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extra comments re self-checking translations and self-modifying 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code. (JRS 14 Oct 05). 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There are 3 modes: 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (1) no checking: all code assumed to be not self-modifying 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (2) partial: known-problematic situations get a self-check 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (3) full checking: all translations get a self-check 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown As currently implemented, the default is (2). (3) is always safe, 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but very slow. (1) works mostly, but fails for gcc nested-function 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code which uses trampolines on the stack; this situation is 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown detected and handled by (2). 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ---------- 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A more robust and transparent solution, which is not currently 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown implemented, is a variant of (2): if a translation is made from an 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown area which aspacem says does not have 'w' permission, then it can 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be non-self-checking. Otherwise, it needs a self-check. 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This is complicated by Vex's basic-block chasing. If a self-check 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is requested, then Vex will not chase over basic block boundaries 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (it's too complex). However there is still a problem if it chases 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from a non-'w' area into a 'w' area. 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I think the right thing to do is: 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if a translation request starts in a 'w' area, ask for a 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown self-checking translation, and do not allow any chasing (make 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chase_into_ok return False). Note that the latter is redundant 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in the sense that Vex won't chase anyway in this situation. 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if a translation request starts in a non-'w' area, do not ask for 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a self-checking translation. However, do not allow chasing (as 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown determined by chase_into_ok) to go into a 'w' area. 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The result of this is that all code inside 'w' areas is self 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown checking. 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown To complete the trick, there is a caveat: we must watch the 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client's mprotect calls. If pages are changed from non-'w' to 'w' 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then we should throw away all translations which intersect the 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown affected area, so as to force them to be redone with self-checks. 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ---------- 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The above outlines the conditions under which bb chasing is allowed 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from a self-modifying-code point of view. There are other 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown situations pertaining to function redirection in which it is 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown necessary to disallow chasing, but those fall outside the scope of 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this comment. 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vex dumps the final code in here. Then we can copy it off 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wherever we like. */ 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 60000: should agree with assertion in VG_(add_to_transtab) in 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_transtab.c. */ 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_TMPBUF 60000 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar tmpbuf[N_TMPBUF]; 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Function pointers we must supply to LibVEX in order that it 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown can bomb out and emit messages under Valgrind's control. */ 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__ ((noreturn)) 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid failure_exit ( void ) 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_ShowAllocStats(); 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("LibVEX called failure_exit()."); 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid log_bytes ( HChar* bytes, Int nbytes ) 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nbytes-3; i += 4) 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%c%c%c%c", bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]); 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (; i < nbytes; i++) 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%c", bytes[i]); 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Various helper functions for translation --------- */ 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Look for reasons to disallow making translations from the given 748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov segment/addr. */ 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool translations_allowable_from_seg ( NSegment const* seg, Addr addr ) 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# if defined(VGA_x86) || defined(VGA_s390x) || defined(VGA_mips32) \ 753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || defined(VGA_mips64) 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool allowR = True; 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool allowR = False; 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return seg != NULL 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (seg->kind == SkAnonC || seg->kind == SkFileC || seg->kind == SkShmC) 760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && (seg->hasX 761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || (seg->hasR && (allowR 762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || VG_(has_gdbserver_breakpoint) (addr)))); 763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* If GDB/gdbsrv has inserted a breakpoint at addr, assume this is a valid 764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov location to translate if seg is not executable but is readable. 765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov This is needed for inferior function calls from GDB: GDB inserts a 766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov breakpoint on the stack, and expects to regain control before the 767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov breakpoint instruction at the breakpoint address is really 768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov executed. For this, the breakpoint instruction must be translated 769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov so as to have the call to gdbserver executed. */ 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Produce a bitmask stating which of the supplied extents needs a 774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov self-check. See documentation of 775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VexTranslateArgs::needs_self_check for more details about the 776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return convention. */ 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt needs_self_check ( void* closureV, 779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VexGuestExtents* vge ) 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VgCallbackClosure* closure = (VgCallbackClosure*)closureV; 782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UInt i, bitset; 783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(vge->n_used >= 1 && vge->n_used <= 3); 785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov bitset = 0; 786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; i < vge->n_used; i++) { 788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool check = False; 789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr addr = (Addr)vge->base[i]; 790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT len = (SizeT)vge->len[i]; 791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NSegment const* segA = NULL; 792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_darwin) 794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // GrP fixme hack - dyld i386 IMPORT gets rewritten. 795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // To really do this correctly, we'd need to flush the 796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // translation cache whenever a segment became +WX. 797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov segA = VG_(am_find_nsegment)(addr); 798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (segA && segA->hasX && segA->hasW) 799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov check = True; 800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!check) { 803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov switch (VG_(clo_smc_check)) { 804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Vg_SmcNone: 805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* never check (except as per Darwin hack above) */ 806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Vg_SmcAll: 808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* always check */ 809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov check = True; 810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Vg_SmcStack: { 812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* check if the address is in the same segment as this 813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov thread's stack pointer */ 814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr sp = VG_(get_SP)(closure->tid); 815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!segA) { 816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov segA = VG_(am_find_nsegment)(addr); 817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NSegment const* segSP = VG_(am_find_nsegment)(sp); 819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (segA && segSP && segA == segSP) 820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov check = True; 821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Vg_SmcAllNonFile: { 824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* check if any part of the extent is not in a 825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov file-mapped segment */ 826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!segA) { 827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov segA = VG_(am_find_nsegment)(addr); 828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (segA && segA->kind == SkFileC && segA->start <= addr 830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && (len == 0 || addr + len <= segA->end + 1)) { 831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* in a file-mapped segment; skip the check */ 832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov check = True; 834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov default: 838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(0); 839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (check) 843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov bitset |= (1 << i); 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return bitset; 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is a callback passed to LibVEX_Translate. It stops Vex from 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chasing into function entry points that we wish to redirect. 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Chasing across them obviously defeats the redirect mechanism, with 853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov bad effects for Memcheck, Helgrind, DRD, Massif, and possibly others. 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool chase_into_ok ( void* closureV, Addr64 addr64 ) 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addr = (Addr)addr64; 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg = VG_(am_find_nsegment)(addr); 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Work through a list of possibilities why we might not want to 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allow a chase. */ 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Destination not in a plausible segment? */ 864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!translations_allowable_from_seg(seg, addr)) 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto dontchase; 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Destination is redirected? */ 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (addr != VG_(redir_do_lookup)(addr, NULL)) 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto dontchase; 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_PLAT_USES_PPCTOC) 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This needs to be at the start of its own block. Don't chase. Re 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong_to_Ptr, be careful to ensure we only compare 32 bits on a 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32-bit target.*/ 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ULong_to_Ptr(addr64) 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == (void*)&VG_(ppctoc_magic_redirect_return_stub)) 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto dontchase; 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* overly conservative, but .. don't chase into the distinguished 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address that m_transtab uses as an empty-slot marker for 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tt_fast). */ 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (addr == TRANSTAB_BOGUS_GUEST_ADDR) 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto dontchase; 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGA_s390x) 887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Never chase into an EX instruction. Generating IR for EX causes 888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a round-trip through the scheduler including VG_(discard_translations). 889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov And that's expensive as shown by perf/tinycc.c: 890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Chasing into EX increases the number of EX translations from 21 to 891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 102666 causing a 7x runtime increase for "none" and a 3.2x runtime 892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov increase for memcheck. */ 893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (((UChar *)ULong_to_Ptr(addr))[0] == 0x44 || /* EX */ 894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ((UChar *)ULong_to_Ptr(addr))[0] == 0xC6) /* EXRL */ 895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov goto dontchase; 896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* well, ok then. go on and chase. */ 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dontchase: 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("not chasing into 0x%lx\n", addr); 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------- helpers for with-TOC platforms --------------- */ 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* NOTE: with-TOC platforms are: ppc64-linux. */ 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU64 ( ULong n ) { 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Const(IRConst_U64(n)); 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU32 ( UInt n ) { 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Const(IRConst_U32(n)); 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VG_PLAT_USES_PPCTOC) 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU8 ( UChar n ) { 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Const(IRConst_U8(n)); 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) { 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (typeOfIRExpr(tyenv, e) == Ity_I32) { 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return e; 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(typeOfIRExpr(tyenv, e) == Ity_I64); 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Unop(Iop_64to32, e); 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to push word-typed expression 'e' onto this thread's 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redir stack, checking for stack overflow and generating code to 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bomb out if so. */ 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_PUSH ( IRSB* bb, IRExpr* e ) 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRRegArray* descr; 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp t1; 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* one; 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGP_ppc64_linux) 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE; 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP); 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK); 948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int offB_EMNOTE = offsetof(VexGuestPPC64State,guest_EMNOTE); 949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA); 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is64 = True; 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty_Word = Ity_I64; 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_CmpNE = Iop_CmpNE64; 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Sar = Iop_Sar64; 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Sub = Iop_Sub64; 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Add = Iop_Add64; 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr*(*mkU)(ULong) = mkU64; 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_WORDSIZE == 8); 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE; 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP); 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK); 962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int offB_EMNOTE = offsetof(VexGuestPPC32State,guest_EMNOTE); 963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offB_CIA = offsetof(VexGuestPPC32State,guest_CIA); 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is64 = False; 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty_Word = Ity_I32; 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_CmpNE = Iop_CmpNE32; 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Sar = Iop_Sar32; 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Sub = Iop_Sub32; 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Add = Iop_Add32; 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr*(*mkU)(UInt) = mkU32; 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_WORDSIZE == 4); 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof(void*) == VG_WORDSIZE); 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof(Word) == VG_WORDSIZE); 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof(Addr) == VG_WORDSIZE); 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size ); 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t1 = newIRTemp( bb->tyenv, ty_Word ); 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown one = mkU(1); 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(typeOfIRExpr(bb->tyenv, e) == ty_Word); 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* t1 = guest_REDIR_SP + 1 */ 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_WrTmp( 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t1, 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Binop(op_Add, IRExpr_Get( offB_REDIR_SP, ty_Word ), one) 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Bomb out if t1 >=s stack_size, that is, (stack_size-1)-t1 <s 0. 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The destination (0) is a bit bogus but it doesn't matter since 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this is an unrecoverable error and will lead to Valgrind 996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov shutting down. _EMNOTE is set regardless - that's harmless 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown since is only has a meaning if the exit is taken. */ 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRStmt_Put(offB_EMNOTE, mkU32(EmWarn_PPC64_redir_overflow)) 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_Exit( 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Binop( 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op_CmpNE, 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Binop( 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op_Sar, 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_RdTmp(t1)), 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(8 * VG_WORDSIZE - 1) 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU(0) 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ijk_EmFail, 1015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is64 ? IRConst_U64(0) : IRConst_U32(0), 1016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng offB_CIA 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* guest_REDIR_SP = t1 */ 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_RdTmp(t1))); 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* guest_REDIR_STACK[t1+0] = e */ 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* PutI/GetI have I32-typed indexes regardless of guest word size */ 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRStmt_PutI(mkIRPutI(descr, 1028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0, e))); 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to pop a word-sized value from this thread's redir 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack, binding it to a new temporary, which is returned. As with 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gen_PUSH, an overflow check is also performed. */ 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp gen_POP ( IRSB* bb ) 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGP_ppc64_linux) 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int stack_size = VEX_GUEST_PPC64_REDIR_STACK_SIZE; 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_REDIR_SP = offsetof(VexGuestPPC64State,guest_REDIR_SP); 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_REDIR_STACK = offsetof(VexGuestPPC64State,guest_REDIR_STACK); 1042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int offB_EMNOTE = offsetof(VexGuestPPC64State,guest_EMNOTE); 1043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA); 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is64 = True; 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty_Word = Ity_I64; 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_CmpNE = Iop_CmpNE64; 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Sar = Iop_Sar64; 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Sub = Iop_Sub64; 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr*(*mkU)(ULong) = mkU64; 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int stack_size = VEX_GUEST_PPC32_REDIR_STACK_SIZE; 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_REDIR_SP = offsetof(VexGuestPPC32State,guest_REDIR_SP); 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_REDIR_STACK = offsetof(VexGuestPPC32State,guest_REDIR_STACK); 1054436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int offB_EMNOTE = offsetof(VexGuestPPC32State,guest_EMNOTE); 1055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offB_CIA = offsetof(VexGuestPPC32State,guest_CIA); 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is64 = False; 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty_Word = Ity_I32; 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_CmpNE = Iop_CmpNE32; 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Sar = Iop_Sar32; 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IROp op_Sub = Iop_Sub32; 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr*(*mkU)(UInt) = mkU32; 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRRegArray* descr = mkIRRegArray( offB_REDIR_STACK, ty_Word, stack_size ); 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp t1 = newIRTemp( bb->tyenv, ty_Word ); 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp res = newIRTemp( bb->tyenv, ty_Word ); 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* one = mkU(1); 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof(void*) == VG_WORDSIZE); 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof(Word) == VG_WORDSIZE); 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof(Addr) == VG_WORDSIZE); 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* t1 = guest_REDIR_SP */ 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_WrTmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) ) 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Bomb out if t1 < 0. Same comments as gen_PUSH apply. */ 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1082436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRStmt_Put(offB_EMNOTE, mkU32(EmWarn_PPC64_redir_underflow)) 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_Exit( 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Binop( 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op_CmpNE, 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Binop( 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op_Sar, 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_RdTmp(t1), 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(8 * VG_WORDSIZE - 1) 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU(0) 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ijk_EmFail, 1097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is64 ? IRConst_U64(0) : IRConst_U32(0), 1098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng offB_CIA 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* res = guest_REDIR_STACK[t1+0] */ 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* PutI/GetI have I32-typed indexes regardless of guest word size */ 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_WrTmp( 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_RdTmp(t1)), 0) 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* guest_REDIR_SP = t1-1 */ 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(op_Sub, IRExpr_RdTmp(t1), one)) 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to push LR and R2 onto this thread's redir stack, 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then set R2 to the new value (which is the TOC pointer to be used 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the duration of the replacement function, as determined by 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_debuginfo), and set LR to the magic return stub, so we get to 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown intercept the return and restore R2 and L2 to the values saved 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown here. */ 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_push_and_set_LR_R2 ( IRSB* bb, Addr64 new_R2_value ) 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGP_ppc64_linux) 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr64 bogus_RA = (Addr64)&VG_(ppctoc_magic_redirect_return_stub); 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2); 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_LR = offsetof(VexGuestPPC64State,guest_LR); 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) ); 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) ); 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) ); 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) ); 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Platform is not TOC-afflicted, fortunately 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_pop_R2_LR_then_bLR ( IRSB* bb ) 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGP_ppc64_linux) 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_GPR2 = offsetof(VexGuestPPC64State,guest_GPR2); 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int offB_LR = offsetof(VexGuestPPC64State,guest_LR); 1149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offB_CIA = offsetof(VexGuestPPC64State,guest_CIA); 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp old_R2 = newIRTemp( bb->tyenv, Ity_I64 ); 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp old_LR = newIRTemp( bb->tyenv, Ity_I64 ); 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Restore R2 */ 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_R2 = gen_POP( bb ); 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Put( offB_GPR2, IRExpr_RdTmp(old_R2)) ); 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Restore LR */ 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_LR = gen_POP( bb ); 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( bb, IRStmt_Put( offB_LR, IRExpr_RdTmp(old_LR)) ); 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Branch to LR */ 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* re boring, we arrived here precisely because a wrapped fn did a 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blr (hence Ijk_Ret); so we should just mark this jump as Boring, 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else one _Call will have resulted in two _Rets. */ 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb->jumpkind = Ijk_Boring; 1163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng bb->next = IRExpr_Binop(Iop_And64, IRExpr_RdTmp(old_LR), mkU64(~(3ULL))); 1164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng bb->offsIP = offB_CIA; 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Platform is not TOC-afflicted, fortunately 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRSB* bb ) 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgCallbackClosure* closure = (VgCallbackClosure*)closureV; 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Since we're creating the entire IRSB right here, give it a 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown proper IMark, as it won't get one any other way, and cachegrind 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will barf if it doesn't have one (fair enough really). */ 1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addStmtToIRSB( bb, IRStmt_IMark( closure->readdr, 4, 0 ) ); 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Generate the magic sequence: 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pop R2 from hidden stack 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pop LR from hidden stack 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto LR 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gen_pop_R2_LR_then_bLR(bb); 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; /* True == this is the entire BB; don't disassemble any 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown real insns into it - just hand it directly to 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown optimiser/instrumenter/backend. */ 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------- END helpers for with-TOC platforms --------------- */ 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the IR preamble generator used for replacement 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown functions. It adds code to set the guest_NRADDR{_GPR2} to zero 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (technically not necessary, but facilitates detecting mixups in 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which a replacement function has been erroneously declared using 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_REPLACE_FUNCTION_Z{U,Z} when instead it should have been written 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown using VG_WRAP_FUNCTION_Z{U,Z}). 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown On with-TOC platforms the follow hacks are also done: LR and R2 are 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pushed onto a hidden stack, R2 is set to the correct value for the 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown replacement function, and LR is set to point at the magic 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return-stub address. Setting LR causes the return of the 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wrapped/redirected function to lead to our magic return stub, which 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restores LR and R2 from said stack and returns for real. 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_StackTrace_wrk) understands that the LR value may point to 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the return stub address, and that in that case it can get the real 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LR value from the hidden stack instead. */ 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool mk_preamble__set_NRADDR_to_zero ( void* closureV, IRSB* bb ) 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nraddr_szB 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = sizeof(((VexGuestArchState*)0)->guest_NRADDR); 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(nraddr_szB == 4 || nraddr_szB == 8); 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(nraddr_szB == VG_WORDSIZE); 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_Put( 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offsetof(VexGuestArchState,guest_NRADDR), 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nraddr_szB == 8 ? mkU64(0) : mkU32(0) 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // t9 needs to be set to point to the start of the redirected function. 1225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# if defined(VGP_mips32_linux) 1226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VgCallbackClosure* closure = (VgCallbackClosure*)closureV; 1227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25); 1228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr))); 1229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# endif 1230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# if defined(VGP_mips64_linux) 1231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VgCallbackClosure* closure = (VgCallbackClosure*)closureV; 1232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25); 1233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr))); 1234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_PLAT_USES_PPCTOC) 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { VgCallbackClosure* closure = (VgCallbackClosure*)closureV; 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_Put( 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offsetof(VexGuestArchState,guest_NRADDR_GPR2), 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_WORDSIZE==8 ? mkU64(0) : mkU32(0) 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) ); 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Ditto, except set guest_NRADDR to nraddr (the un-redirected guest 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address). This is needed for function wrapping - so the wrapper 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown can read _NRADDR and find the address of the function being 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wrapped. On toc-afflicted platforms we must also snarf r2. */ 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRSB* bb ) 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgCallbackClosure* closure = (VgCallbackClosure*)closureV; 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nraddr_szB 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = sizeof(((VexGuestArchState*)0)->guest_NRADDR); 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(nraddr_szB == 4 || nraddr_szB == 8); 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(nraddr_szB == VG_WORDSIZE); 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_Put( 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offsetof(VexGuestArchState,guest_NRADDR), 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nraddr_szB == 8 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? IRExpr_Const(IRConst_U64( closure->nraddr )) 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : IRExpr_Const(IRConst_U32( (UInt)closure->nraddr )) 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // t9 needs to be set to point to the start of the redirected function. 1272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# if defined(VGP_mips32_linux) 1273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int offB_GPR25 = offsetof(VexGuestMIPS32State, guest_r25); 1274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU32(closure->readdr))); 1275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# endif 1276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# if defined(VGP_mips64_linux) 1277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int offB_GPR25 = offsetof(VexGuestMIPS64State, guest_r25); 1278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addStmtToIRSB(bb, IRStmt_Put(offB_GPR25, mkU64(closure->readdr))); 1279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 1280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGP_ppc64_linux) 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addStmtToIRSB( 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bb, 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRStmt_Put( 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offsetof(VexGuestArchState,guest_NRADDR_GPR2), 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2), 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_WORDSIZE==8 ? Ity_I64 : Ity_I32) 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) ); 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Helpers to do with PPC related stack redzones. --- */ 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool const_True ( Addr64 guest_addr ) 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------- main translation function --------------- */ 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note: see comments at top of m_redir.c for the Big Picture on how 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redirections are managed. */ 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enum { 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* normal translation, redir neither requested nor inhibited */ 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T_Normal, 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* redir translation, function-wrap (set _NRADDR) style */ 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T_Redir_Wrap, 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* redir translation, replacement (don't set _NRADDR) style */ 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T_Redir_Replace, 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* a translation in which redir is specifically disallowed */ 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T_NoRedir 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T_Kind; 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate the basic block beginning at NRADDR, and add it to the 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translation cache & translation table. Unless 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEBUGGING_TRANSLATION is true, in which case the call is being done 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for debugging purposes, so (a) throw away the translation once it 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is made, and (b) produce a load of debugging output. If 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ALLOW_REDIRECTION is False, do not attempt redirection of NRADDR, 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and also, put the resulting translation into the no-redirect tt/tc 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instead of the normal one. 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TID is the identity of the thread requesting this translation. 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(translate) ( ThreadId tid, 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr64 nraddr, 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debugging_translation, 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int debugging_verbosity, 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong bbs_done, 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool allow_redirection ) 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr64 addr; 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown T_Kind kind; 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int tmpbuf_used, verbosity, i; 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool (*preamble_fn)(void*,IRSB*); 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexArch vex_arch; 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexArchInfo vex_archinfo; 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexAbiInfo vex_abiinfo; 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestExtents vge; 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexTranslateArgs vta; 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexTranslateResult tres; 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgCallbackClosure closure; 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure Vex is initialised right. */ 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool vex_init_done = False; 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!vex_init_done) { 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_Init ( &failure_exit, &log_bytes, 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1, /* debug_paranoia */ 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False, /* valgrind support */ 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &VG_(clo_vex_control) ); 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_init_done = True; 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Establish the translation kind and actual guest address to 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start from. Sets (addr,kind). */ 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (allow_redirection) { 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isWrap; 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr64 tmp = VG_(redir_do_lookup)( nraddr, &isWrap ); 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmp == nraddr) { 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no redirection found */ 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr = nraddr; 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kind = T_Normal; 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* found a redirect */ 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr = tmp; 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kind = isWrap ? T_Redir_Wrap : T_Redir_Replace; 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr = nraddr; 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kind = T_NoRedir; 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Established: (nraddr, addr, kind) */ 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Printing redirection info. */ 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((kind == T_Redir_Wrap || kind == T_Redir_Replace) 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (VG_(clo_verbosity) >= 2 || VG_(clo_trace_redir))) { 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 1389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar name1[512] = ""; 1390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar name2[512] = ""; 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name1[0] = name2[0] = 0; 1392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ok = VG_(get_fnname_w_offset)(nraddr, name1, 512); 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) VG_(strcpy)(name1, "???"); 1394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ok = VG_(get_fnname_w_offset)(addr, name2, 512); 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) VG_(strcpy)(name2, "???"); 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "REDIR: 0x%llx (%s) redirected to 0x%llx (%s)\n", 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nraddr, name1, 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr, name2 ); 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!debugging_translation) 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( pre_mem_read, Vg_CoreTranslate, 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, "(translator)", addr, 1 ); 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If doing any code printing, print a basic block start marker */ 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_flags) || debugging_translation) { 1408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar fnname[512] = "UNKNOWN_FUNCTION"; 1409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(get_fnname_w_offset)(addr, fnname, 512); 1410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* objname = "UNKNOWN_OBJECT"; 1411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov OffT objoff = 0; 1412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov DebugInfo* di = VG_(find_DebugInfo)( addr ); 1413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (di) { 1414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov objname = VG_(DebugInfo_get_filename)(di); 1415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov objoff = addr - VG_(DebugInfo_get_text_bias)(di); 1416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(objname); 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "==== SB %d (evchecks %lld) [tid %d] 0x%llx %s %s+0x%llx\n", 1420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(get_bbs_translated)(), bbs_done, (Int)tid, addr, 1421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fnname, objname, (ULong)objoff 1422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ); 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Are we allowed to translate here? */ 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { /* BEGIN new scope specially for 'seg' */ 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg = VG_(am_find_nsegment)(addr); 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if ( (!translations_allowable_from_seg(seg, addr)) 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || addr == TRANSTAB_BOGUS_GUEST_ADDR ) { 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%llx)" 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " - throwing SEGV\n", addr); 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* U R busted, sonny. Place your hands on your head and step 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown away from the orig_addr. */ 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Code address is bad - deliver a signal instead */ 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg != NULL) { 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's some kind of segment at the requested place, but we 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aren't allowed to execute code here. */ 1441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (debugging_translation) 1442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("translations not allowed here (segment not executable)" 1443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "(0x%llx)\n", addr); 1444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(synth_fault_perms)(tid, addr); 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There is no segment at all; we are attempting to execute in 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the middle of nowhere. */ 1449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (debugging_translation) 1450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("translations not allowed here (no segment)" 1451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "(0x%llx)\n", addr); 1452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(synth_fault_mapping)(tid, addr); 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */ 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown verbosity = 0; 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debugging_translation) { 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown verbosity = debugging_verbosity; 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (VG_(clo_trace_flags) > 0 1465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && VG_(get_bbs_translated)() <= VG_(clo_trace_notabove) 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && VG_(get_bbs_translated)() >= VG_(clo_trace_notbelow) )) { 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown verbosity = VG_(clo_trace_flags); 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out which preamble-mangling callback to send. */ 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preamble_fn = NULL; 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (kind == T_Redir_Replace) 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preamble_fn = mk_preamble__set_NRADDR_to_zero; 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (kind == T_Redir_Wrap) 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preamble_fn = mk_preamble__set_NRADDR_to_nraddr; 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_PLAT_USES_PPCTOC) 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ULong_to_Ptr(nraddr) 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == (void*)&VG_(ppctoc_magic_redirect_return_stub)) { 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If entering the special return stub, this means a wrapped or 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redirected function is returning. Make this translation one 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which restores R2 and LR from the thread's hidden redir 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack, and branch to the (restored) link register, thereby 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown really causing the function to return. */ 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(kind == T_Normal); 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(nraddr == addr); 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preamble_fn = mk_preamble__ppctoc_magic_return_stub; 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------ Actually do the translation. ------ */ 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert2(VG_(tdict).tool_instrument, 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "you forgot to set VgToolInterface function 'tool_instrument'"); 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the CPU info established at startup. */ 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo ); 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up 'abiinfo' structure with stuff Vex needs to know about 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the guest and host ABIs. */ 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_default_VexAbiInfo( &vex_abiinfo ); 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.guest_stack_redzone_size = VG_STACK_REDZONE_SZB; 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_amd64_linux) 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.guest_amd64_assume_fs_is_zero = True; 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_amd64_darwin) 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.guest_amd64_assume_gs_is_0x60 = True; 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_ppc32_linux) 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.guest_ppc_zap_RZ_at_blr = False; 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.guest_ppc_zap_RZ_at_bl = NULL; 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.host_ppc32_regalign_int64_args = True; 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_ppc64_linux) 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.guest_ppc_zap_RZ_at_blr = True; 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.guest_ppc_zap_RZ_at_bl = const_True; 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_abiinfo.host_ppc_calls_use_fndescrs = True; 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up closure args. */ 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown closure.tid = tid; 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown closure.nraddr = nraddr; 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown closure.readdr = addr; 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up args for LibVEX_Translate. */ 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.arch_guest = vex_arch; 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.archinfo_guest = vex_archinfo; 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.arch_host = vex_arch; 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.archinfo_host = vex_archinfo; 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.abiinfo_both = vex_abiinfo; 1533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.callback_opaque = (void*)&closure; 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.guest_bytes = (UChar*)ULong_to_Ptr(addr); 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.guest_bytes_addr = (Addr64)addr; 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.chase_into_ok = chase_into_ok; 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.guest_extents = &vge; 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.host_bytes = tmpbuf; 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.host_bytes_size = N_TMPBUF; 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vta.host_bytes_used = &tmpbuf_used; 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { /* At this point we have to reconcile Vex's view of the 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instrumentation callback - which takes a void* first argument 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - with Valgrind's view, in which the first arg is a 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgCallbackClosure*. Hence the following longwinded casts. 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown They are entirely legal but longwinded so as to maximise the 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chance of the C typechecker picking up any type snafus. */ 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB*(*f)(VgCallbackClosure*, 1548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRSB*,VexGuestLayout*,VexGuestExtents*, VexArchInfo*, 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType,IRType) 1550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = VG_(clo_vgdb) != Vg_VgdbNo 1551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ? tool_instrument_then_gdbserver_if_needed 1552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov : VG_(tdict).tool_instrument; 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRSB*(*g)(void*, 1554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRSB*,VexGuestLayout*,VexGuestExtents*,VexArchInfo*, 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType,IRType) 1556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov = (IRSB*(*)(void*,IRSB*,VexGuestLayout*,VexGuestExtents*, 1557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexArchInfo*,IRType,IRType))f; 1558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.instrument1 = g; 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* No need for type kludgery here. */ 1561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.instrument2 = need_to_handle_SP_assignment() 1562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ? vg_SP_update_pass 1563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng : NULL; 1564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.finaltidy = VG_(needs).final_IR_tidy_pass 1565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ? VG_(tdict).tool_final_IR_tidy_pass 1566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng : NULL; 1567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.needs_self_check = needs_self_check; 1568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.preamble_function = preamble_fn; 1569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.traceflags = verbosity; 1570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vta.sigill_diag = VG_(clo_sigill_diag); 1571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vta.addProfInc = VG_(clo_profyle_sbs) && kind != T_NoRedir; 1572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Set up the dispatch continuation-point info. If this is a 1574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng no-redir translation then it cannot be chained, and the chain-me 1575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng points are set to NULL to indicate that. The indir point must 1576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng also be NULL, since we can't allow this translation to do an 1577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng indir transfer -- that would take it back into the main 1578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng translation cache too. 1579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng All this is because no-redir translations live outside the main 1581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng translation cache (in a secondary one) and chaining them would 1582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng involve more adminstrative complexity that isn't worth the 1583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hassle, because we don't expect them to get used often. So 1584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng don't bother. */ 1585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (allow_redirection) { 1586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.disp_cp_chain_me_to_slowEP 1587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = VG_(fnptr_to_fnentry)( &VG_(disp_cp_chain_me_to_slowEP) ); 1588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.disp_cp_chain_me_to_fastEP 1589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = VG_(fnptr_to_fnentry)( &VG_(disp_cp_chain_me_to_fastEP) ); 1590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.disp_cp_xindir 1591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = VG_(fnptr_to_fnentry)( &VG_(disp_cp_xindir) ); 1592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 1593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.disp_cp_chain_me_to_slowEP = NULL; 1594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.disp_cp_chain_me_to_fastEP = NULL; 1595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.disp_cp_xindir = NULL; 1596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* This doesn't involve chaining and so is always allowable. */ 1598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vta.disp_cp_xassisted 1599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = VG_(fnptr_to_fnentry)( &VG_(disp_cp_xassisted) ); 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sheesh. Finally, actually _do_ the translation! */ 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tres = LibVEX_Translate ( &vta ); 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(tres.status == VexTransOK); 1605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(tres.n_sc_extents >= 0 && tres.n_sc_extents <= 3); 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tmpbuf_used <= N_TMPBUF); 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tmpbuf_used > 0); 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Tell aspacem of all segments that have had translations taken 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from them. Optimisation: don't re-look up vge.base[0] since seg 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should already point to it. */ 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( vge.base[0] == (Addr64)addr ); 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set 'translations taken from this segment' flag */ 1615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( seg ); 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* END new scope specially for 'seg' */ 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i < vge.n_used; i++) { 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(am_find_nsegment)( vge.base[i] ); 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set 'translations taken from this segment' flag */ 1622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( seg ); 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy data at trans_addr into the translation cache. */ 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tmpbuf_used > 0 && tmpbuf_used < 65536); 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If debugging, don't do anything with the translated block; we 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // only did this for the debugging output produced along the way. 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!debugging_translation) { 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (kind != T_NoRedir) { 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Put it into the normal TT/TC structures. This is the 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // normal case. 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Note that we use nraddr (the non-redirected address), not 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // addr, which might have been changed by the redirection 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(add_to_transtab)( &vge, 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nraddr, 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)(&tmpbuf[0]), 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpbuf_used, 1642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tres.n_sc_extents > 0, 1643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tres.offs_profInc, 1644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tres.n_guest_instrs, 1645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_arch ); 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(tres.offs_profInc == -1); /* -1 == unset */ 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(add_to_unredir_transtab)( &vge, 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nraddr, 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)(&tmpbuf[0]), 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpbuf_used ); 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1661