1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Create/destroy signal delivery frames. ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- sigframe-amd64-linux.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2000-2013 Nicholas Nethercote 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown njn@valgrind.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#if defined(VGP_amd64_linux) 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 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_machine.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_trampoline.h" 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_sigframe.h" /* self */ 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This module creates and removes signal frames for signal deliveries 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown on amd64-linux. 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note, this file contains kernel-specific knowledge in the form of 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'struct rt_sigframe'. How does that relate to the vki kernel 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interface stuff? 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A 'struct rtsigframe' is pushed onto the client's stack. This 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown contains a subsidiary vki_ucontext. That holds the vcpu's state 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown across the signal, so that the sighandler can mess with the vcpu 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state if it really wants. 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FIXME: sigcontexting is basically broken for the moment. When 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delivering a signal, the integer registers and %rflags are 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown correctly written into the sigcontext, however the FP and SSE state 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is not. When returning from a signal, only the integer registers 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are restored from the sigcontext; the rest of the CPU state is 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restored to what it was before the signal. 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This will be fixed. 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Signal frame layouts ---*/ 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A structure in which to save the application's registers 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// during the execution of signal handlers. 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// In theory, so long as we get the arguments to the handler function 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// right, it doesn't matter what the exact layout of the rest of the 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// frame is. Unfortunately, things like gcc's exception unwinding 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// make assumptions about the locations of various parts of the frame, 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// so we need to duplicate it exactly. 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Valgrind-specific parts of the signal frame */ 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct vg_sigframe 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sanity check word. */ 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt magicPI; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt handlerflags; /* flags for signal handler */ 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Safely-saved version of sigNo, as described above. */ 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo_private; 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* XXX This is wrong. Surely we should store the shadow values 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown into the shadow memory behind the actual values? */ 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State vex_shadow1; 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State vex_shadow2; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* HACK ALERT */ 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State vex; 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* end HACK ALERT */ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* saved signal mask to be restored when handler returns */ 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t mask; 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sanity check word. Is the highest-addressed word; do not 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown move!*/ 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt magicE; 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct rt_sigframe 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sig handler's return address */ 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr retaddr; 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ucontext */ 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext uContext; 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* siginfo */ 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_siginfo_t sigInfo; 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _vki_fpstate fpstate; 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_sigframe vg; 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /*------------------------------------------------------------*/ 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /*--- Signal operations ---*/ 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /*------------------------------------------------------------*/ 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /* 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: Great gobs of FP state conversion taken wholesale from 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: linux/arch/i386/kernel/i387.c 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: */ 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /* 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: * FXSR floating point environment conversions. 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: */ 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: #define X86_FXSR_MAGIC 0x0000 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /* 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: * FPU tag word conversions. 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: */ 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned int tmp; /* to avoid 16 bit prefixes in the code */ 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /* Transform each pair of bits into 01 (valid) or 00 (empty) */ 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tmp = ~twd; 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /* and move the valid bits to the lower byte. */ 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: return tmp; 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static unsigned long twd_fxsr_to_i387( const struct i387_fxsave_struct *fxsave ) 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: struct _vki_fpxreg *st = NULL; 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long twd = (unsigned long) fxsave->twd; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long tag; 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long ret = 0xffff0000u; 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: int i; 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: for ( i = 0 ; i < 8 ; i++ ) { 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: if ( twd & 0x1 ) { 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: st = (struct _vki_fpxreg *) FPREG_ADDR( fxsave, i ); 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: switch ( st->exponent & 0x7fff ) { 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: case 0x7fff: 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tag = 2; /* Special */ 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: break; 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: case 0x0000: 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: if ( !st->significand[0] && 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: !st->significand[1] && 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: !st->significand[2] && 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: !st->significand[3] ) { 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tag = 1; /* Zero */ 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } else { 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tag = 2; /* Special */ 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: break; 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: default: 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: if ( st->significand[3] & 0x8000 ) { 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tag = 0; /* Valid */ 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } else { 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tag = 2; /* Special */ 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: break; 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } else { 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tag = 3; /* Empty */ 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: ret |= (tag << (2 * i)); 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: twd = twd >> 1; 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: return ret; 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static void convert_fxsr_to_user( struct _vki_fpstate *buf, 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: const struct i387_fxsave_struct *fxsave ) 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long env[7]; 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: struct _vki_fpreg *to; 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: struct _vki_fpxreg *from; 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: int i; 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: env[2] = twd_fxsr_to_i387(fxsave); 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: env[3] = fxsave->fip; 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: env[5] = fxsave->foo; 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: env[6] = fxsave->fos; 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: VG_(memcpy)(buf, env, 7 * sizeof(unsigned long)); 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: to = &buf->_st[0]; 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: from = (struct _vki_fpxreg *) &fxsave->st_space[0]; 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: for ( i = 0 ; i < 8 ; i++, to++, from++ ) { 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long __user *t = (unsigned long __user *)to; 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long *f = (unsigned long *)from; 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: t[0] = f[0]; 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: t[1] = f[1]; 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: to->exponent = from->exponent; 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static void convert_fxsr_from_user( struct i387_fxsave_struct *fxsave, 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: const struct _vki_fpstate *buf ) 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long env[7]; 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: struct _vki_fpxreg *to; 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: const struct _vki_fpreg *from; 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: int i; 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: VG_(memcpy)(env, buf, 7 * sizeof(long)); 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fxsave->cwd = (unsigned short)(env[0] & 0xffff); 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fxsave->swd = (unsigned short)(env[1] & 0xffff); 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fxsave->fip = env[3]; 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16); 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fxsave->fcs = (env[4] & 0xffff); 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fxsave->foo = env[5]; 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fxsave->fos = env[6]; 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: to = (struct _vki_fpxreg *) &fxsave->st_space[0]; 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: from = &buf->_st[0]; 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: for ( i = 0 ; i < 8 ; i++, to++, from++ ) { 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long *t = (unsigned long *)to; 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: unsigned long __user *f = (unsigned long __user *)from; 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: t[0] = f[0]; 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: t[1] = f[1]; 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: to->exponent = from->exponent; 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static inline void save_i387_fsave( arch_thread_t *regs, struct _vki_fpstate *buf ) 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: struct i387_fsave_struct *fs = ®s->m_sse.fsave; 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: fs->status = fs->swd; 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: VG_(memcpy)(buf, fs, sizeof(*fs)); 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static void save_i387_fxsave( arch_thread_t *regs, struct _vki_fpstate *buf ) 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: const struct i387_fxsave_struct *fx = ®s->m_sse.fxsave; 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: convert_fxsr_to_user( buf, fx ); 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: buf->status = fx->swd; 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: buf->magic = X86_FXSR_MAGIC; 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: VG_(memcpy)(buf->_fxsr_env, fx, sizeof(struct i387_fxsave_struct)); 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static void save_i387( arch_thread_t *regs, struct _vki_fpstate *buf ) 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: if ( VG_(have_ssestate) ) 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: save_i387_fxsave( regs, buf ); 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: else 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: save_i387_fsave( regs, buf ); 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static inline void restore_i387_fsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf ) 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: VG_(memcpy)( ®s->m_sse.fsave, buf, sizeof(struct i387_fsave_struct) ); 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static void restore_i387_fxsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf ) 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: VG_(memcpy)(®s->m_sse.fxsave, &buf->_fxsr_env[0], 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: sizeof(struct i387_fxsave_struct) ); 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: /* mxcsr reserved bits must be masked to zero for security reasons */ 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: regs->m_sse.fxsave.mxcsr &= 0xffbf; 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: convert_fxsr_from_user( ®s->m_sse.fxsave, buf ); 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: static void restore_i387( arch_thread_t *regs, const struct _vki_fpstate __user *buf ) 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: { 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: if ( VG_(have_ssestate) ) { 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: restore_i387_fxsave( regs, buf ); 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } else { 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: restore_i387_fsave( regs, buf ); 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: } 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Creating signal frames ---*/ 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create a plausible-looking sigcontext from the thread's 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vex guest state. NOTE: does not fill in the FP or SSE 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bits of sigcontext at the moment. 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid synth_ucontext(ThreadId tid, const vki_siginfo_t *si, 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord trapno, UWord err, const vki_sigset_t *set, 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_ucontext *uc, struct _vki_fpstate *fpstate) 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sigcontext *sc = &uc->uc_mcontext; 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(uc, 0, sizeof(*uc)); 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc->uc_flags = 0; 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc->uc_link = 0; 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc->uc_sigmask = *set; 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uc->uc_stack = tst->altstack; 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sc->fpstate = fpstate; 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: save_i387(&tst->arch, fpstate); 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(r8,R8); 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(r9,R9); 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(r10,R10); 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(r11,R11); 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(r12,R12); 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(r13,R13); 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(r14,R14); 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(r15,R15); 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rdi,RDI); 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rsi,RSI); 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rbp,RBP); 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rbx,RBX); 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rdx,RDX); 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rax,RAX); 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rcx,RCX); 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rsp,RSP); 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SC2(rip,RIP); 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sc->eflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex); 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: SC2(cs,CS); 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: SC2(gs,GS); 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: SC2(fs,FS); 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sc->trapno = trapno; 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sc->err = err; 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef SC2 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sc->cr2 = (UWord)si->_sifields._sigfault._addr; 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extend the stack segment downwards if needed so as to ensure the 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new signal frames are mapped to something. Return a Bool 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown indicating whether or not the operation was successful. 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = tst->tid; 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* stackseg = NULL; 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(extend_stack)(addr, tst->client_stack_szB)) { 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stackseg = VG_(am_find_nsegment)(addr); 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && stackseg) 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("frame=%#lx seg=%#lx-%#lx\n", 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr, stackseg->start, stackseg->end); 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) { 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vg_UserMsg, 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Can't extend stack to %#lx during signal delivery for thread %d:\n", 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addr, tid); 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stackseg == NULL) 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, " no stack segment\n"); 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, " too small or bad protection modes\n"); 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set SIGSEGV to default handler */ 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_default_handler)(VKI_SIGSEGV); 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_fault_mapping)(tid, addr); 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The whole process should be about to die, since the default 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown action of SIGSEGV to kill the whole process. */ 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For tracking memory events, indicate the entire frame has been 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated. */ 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size + VG_STACK_REDZONE_SZB, tid ); 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build the Valgrind-specific part of a signal frame. */ 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void build_vg_sigframe(struct vg_sigframe *frame, 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst, 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *mask, 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt flags, 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo) 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->sigNo_private = sigNo; 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->magicPI = 0x31415927; 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->vex_shadow1 = tst->arch.vex_shadow1; 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->vex_shadow2 = tst->arch.vex_shadow2; 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* HACK ALERT */ 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->vex = tst->arch.vex; 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* end HACK ALERT */ 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->mask = tst->sig_mask; 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->handlerflags = flags; 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->magicE = 0x27182818; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr build_rt_sigframe(ThreadState *tst, 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr rsp_top_of_frame, 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_siginfo_t *siginfo, 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct vki_ucontext *siguc, 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *handler, UInt flags, 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *mask, 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *restorer) 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct rt_sigframe *frame; 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr rsp = rsp_top_of_frame; 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo = siginfo->si_signo; 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord trapno; 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord err; 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsp -= sizeof(*frame); 455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov rsp = VG_ROUNDDN(rsp, 16) - 8; 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame = (struct rt_sigframe *)rsp; 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!extend(tst, rsp, sizeof(*frame))) 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rsp_top_of_frame; 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* retaddr, siginfo, uContext fields are to be written */ 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "rt signal handler frame", 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsp, offsetof(struct rt_sigframe, vg) ); 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (flags & VKI_SA_RESTORER) 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->retaddr = (Addr)restorer; 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->retaddr = (Addr)&VG_(amd64_linux_SUBST_FOR_rt_sigreturn); 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (siguc) { 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trapno = siguc->uc_mcontext.trapno; 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = siguc->uc_mcontext.err; 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trapno = 0; 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err = 0; 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t)); 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SIGILL defines addr to be the faulting address */ 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sigNo == VKI_SIGILL && siginfo->si_code > 0) 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->sigInfo._sifields._sigfault._addr 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (void*)tst->arch.vex.guest_RIP; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown synth_ucontext(tst->tid, siginfo, trapno, err, mask, 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &frame->uContext, &frame->fpstate); 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsp, offsetof(struct rt_sigframe, vg) ); 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo); 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rsp; 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sigframe_create)( ThreadId tid, 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr rsp_top_of_frame, 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_siginfo_t *siginfo, 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct vki_ucontext *siguc, 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *handler, 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt flags, 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const vki_sigset_t *mask, 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *restorer ) 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr rsp; 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct rt_sigframe *frame; 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst = VG_(get_ThreadState)(tid); 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsp = build_rt_sigframe(tst, rsp_top_of_frame, siginfo, siguc, 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler, flags, mask, restorer); 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame = (struct rt_sigframe *)rsp; 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set the thread so it will next run the handler. */ 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tst->m_rsp = rsp; also notify the tool we've updated RSP */ 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_SP)(tid, rsp); 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_(printf)("handler = %p\n", handler); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RIP = (Addr) handler; 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RDI = (ULong) siginfo->si_signo; 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RSI = (Addr) &frame->sigInfo; 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RDX = (Addr) &frame->uContext; 524eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov /* And tell the tool that these registers have been written. */ 525eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, 526eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov offsetof(VexGuestAMD64State,guest_RIP), sizeof(UWord) ); 527eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, 528eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov offsetof(VexGuestAMD64State,guest_RDI), sizeof(UWord) ); 529eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, 530eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov offsetof(VexGuestAMD64State,guest_RSI), sizeof(UWord) ); 531eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, 532eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov offsetof(VexGuestAMD64State,guest_RDX), sizeof(UWord) ); 533eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This thread needs to be marked runnable, but we leave that the 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caller to do. */ 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("pushed signal frame; %%RSP now = %#lx, " 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "next %%RIP = %#llx, status=%d\n", 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsp, tst->arch.vex.guest_RIP, tst->status); 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Destroying signal frames ---*/ 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return False and don't do anything, just set the client to take a 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segfault, if it looks like the frame is corrupted. */ 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool restore_vg_sigframe ( ThreadState *tst, 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_sigframe *frame, Int *sigNo ) 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (frame->magicPI != 0x31415927 || 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frame->magicE != 0x27182818) { 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Thread %d return signal frame " 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "corrupted. Killing process.\n", 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->tid); 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_default_handler)(VKI_SIGSEGV); 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_fault)(tst->tid); 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *sigNo = VKI_SIGSEGV; 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->sig_mask = frame->mask; 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->tmp_sig_mask = frame->mask; 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex_shadow1 = frame->vex_shadow1; 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex_shadow2 = frame->vex_shadow2; 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* HACK ALERT */ 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex = frame->vex; 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* end HACK ALERT */ 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *sigNo = frame->sigNo_private; 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid restore_sigcontext( ThreadState *tst, 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sigcontext *sc, 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _vki_fpstate *fpstate ) 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RAX = sc->rax; 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RCX = sc->rcx; 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RDX = sc->rdx; 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RBX = sc->rbx; 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RBP = sc->rbp; 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RSP = sc->rsp; 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RSI = sc->rsi; 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RDI = sc->rdi; 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_R8 = sc->r8; 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_R9 = sc->r9; 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_R10 = sc->r10; 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_R11 = sc->r11; 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_R12 = sc->r12; 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_R13 = sc->r13; 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_R14 = sc->r14; 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_R15 = sc->r15; 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tst->arch.vex.guest_rflags = sc->rflags; 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->arch.vex.guest_RIP = sc->rip; 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tst->arch.vex.guest_CS = sc->cs; 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tst->arch.vex.guest_FS = sc->fs; 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: tst->arch.vex.guest_GS = sc->gs; 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//:: restore_i387(&tst->arch, fpstate); 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT restore_rt_sigframe ( ThreadState *tst, 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct rt_sigframe *frame, Int *sigNo ) 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (restore_vg_sigframe(tst, &frame->vg, sigNo)) 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate); 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sizeof(*frame); 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sigframe_destroy)( ThreadId tid, Bool isRT ) 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr rsp; 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState* tst; 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT size; 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sigNo; 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(isRT); 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Correctly reestablish the frame base address. */ 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsp = tst->arch.vex.guest_RSP; 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size = restore_rt_sigframe(tst, (struct rt_sigframe *)rsp, &sigNo); 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( die_mem_stack_signal, rsp - VG_STACK_REDZONE_SZB, 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size + VG_STACK_REDZONE_SZB ); 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vg_DebugMsg, 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VG_(signal_return) (thread %d): isRT=%d valid magic; RIP=%#llx\n", 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, isRT, tst->arch.vex.guest_RIP); 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tell the tools */ 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_deliver_signal, tid, sigNo ); 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGP_amd64_linux) 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 652