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