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