1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Create/destroy signal delivery frames.                       ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                       sigframe-ppc64-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
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2004-2013 Paul Mackerras
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      paulus@samba.org
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_ppc64_linux)
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h"
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_sigframe.h"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h"
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_trampoline.h"
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h"      // VG_(discard_translations)
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This module creates and removes signal frames for signal deliveries
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on ppc64-linux.
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note, this file contains kernel-specific knowledge in the form of
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'struct sigframe' and 'struct rt_sigframe'.  How does that relate
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to the vki kernel interface stuff?
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   onto the client's stack.  This contains a subsidiary
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vki_ucontext.  That holds the vcpu's state across the signal,
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so that the sighandler can mess with the vcpu state if it
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   really wants.
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   FIXME: sigcontexting is basically broken for the moment.  When
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delivering a signal, the integer registers and %eflags are
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   correctly written into the sigcontext, however the FP and SSE state
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is not.  When returning from a signal, only the integer registers
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are restored from the sigcontext; the rest of the CPU state is
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   restored to what it was before the signal.
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This will be fixed.
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Signal frame layouts                                 ---*/
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A structure in which to save the application's registers
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// during the execution of signal handlers.
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// On ppc64-linux, rt_sigframe is used for all signals.
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// In theory, so long as we get the arguments to the handler function
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// right, it doesn't matter what the exact layout of the rest of the
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// frame is.  Unfortunately, things like gcc's exception unwinding
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// make assumptions about the locations of various parts of the frame,
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// so we need to duplicate it exactly.
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Many of these byzantine details derived from
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   linux-2.6.13/arch/ppc64/kernel/signal.c */
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TRAMP_SIZE 6 /* who knows why - it only needs to be 2. */
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Structure containing bits of information that we want to save
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on signal delivery. */
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct vg_sig_private {
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  magicPI;
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sigNo_private;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong _unused; /* makes the struct size be zero % 16 */
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexGuestPPC64State vex_shadow1;
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexGuestPPC64State vex_shadow2;
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Structure put on stack for all signal handlers. */
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct rt_sigframe {
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_ucontext   uc;
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong                 _unused[2];
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt                  tramp[TRAMP_SIZE];
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_siginfo*   pinfo;
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*                 puc;
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vki_siginfo_t         info;
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vg_sig_private priv;
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar                 abigap[288];
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SET_SIGNAL_LR(zztst, zzval)                          \
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do { tst->arch.vex.guest_LR = (zzval);                    \
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                offsetof(VexGuestPPC64State,guest_LR),       \
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sizeof(UWord) );                             \
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } while (0)
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SET_SIGNAL_GPR(zztst, zzn, zzval)                    \
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do { tst->arch.vex.guest_GPR##zzn = (zzval);              \
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                offsetof(VexGuestPPC64State,guest_GPR##zzn), \
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sizeof(UWord) );                             \
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } while (0)
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extend the stack segment downwards if needed so as to ensure the
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new signal frames are mapped to something.  Return a Bool
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   indicating whether or not the operation was successful.
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool extend ( ThreadState *tst, Addr addr, SizeT size )
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId        tid = tst->tid;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NSegment const* stackseg = NULL;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stackseg = VG_(am_find_nsegment)(addr);
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 && stackseg)
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     addr, stackseg->start, stackseg->end);
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Vg_UserMsg,
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "Can't extend stack to %#lx during signal delivery for thread %d:\n",
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addr, tid);
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stackseg == NULL)
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "  no stack segment\n");
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "  too small or bad protection modes\n");
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* set SIGSEGV to default handler */
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(set_default_handler)(VKI_SIGSEGV);
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(synth_fault_mapping)(tid, addr);
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The whole process should be about to die, since the default
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 action of SIGSEGV to kill the whole process. */
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For tracking memory events, indicate the entire frame has been
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allocated. */
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             size + VG_STACK_REDZONE_SZB, tid );
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* EXPORTED */
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sigframe_create)( ThreadId tid,
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Addr sp_top_of_frame,
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const vki_siginfo_t *siginfo,
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const struct vki_ucontext *siguc,
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           void *handler,
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UInt flags,
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const vki_sigset_t *mask,
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		           void *restorer )
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vg_sig_private* priv;
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr sp;
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState* tst;
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int sigNo = siginfo->si_signo;
193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Addr faultaddr; */ /* UNUSED */
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct rt_sigframe* frame;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Stack must be 16-byte aligned */
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_16_ALIGNED(sizeof(struct vg_sig_private)));
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_16_ALIGNED(sizeof(struct rt_sigframe)));
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sp_top_of_frame &= ~0xf;
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sp = sp_top_of_frame - sizeof(struct rt_sigframe);
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!extend(tst, sp, sp_top_of_frame - sp))
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_16_ALIGNED(sp));
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame = (struct rt_sigframe *) sp;
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* clear it (conservatively) */
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(frame, 0, sizeof(*frame));
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /////////
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->pinfo = &frame->info;
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->puc = &frame->uc;
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_flags = 0;
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_link = 0;
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /////////
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up the stack chain pointer */
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             sp, sizeof(UWord) );
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *(Addr *)sp = tst->arch.vex.guest_GPR1;
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             sp, sizeof(UWord) );
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* UNUSED:
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      faultaddr = tst->arch.vex.guest_CIA;
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   */
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memcpy)(&frame->info, siginfo, sizeof(*siginfo));
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (Addr)&frame->info, sizeof(frame->info) );
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_flags = 0;
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_link  = 0;
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_stack = tst->altstack;
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_sigmask = tst->sig_mask;
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (Addr)(&frame->uc), sizeof(frame->uc) );
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define DO(gpr)  frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr] \
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      = tst->arch.vex.guest_GPR##gpr
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef DO
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP]     = tst->arch.vex.guest_CIA;
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR]     = 0xf032;   /* pretty arbitrary */
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_mcontext.gp_regs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR]     = tst->arch.vex.guest_CTR;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK]     = tst->arch.vex.guest_LR;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_mcontext.gp_regs[VKI_PT_XER]     = LibVEX_GuestPPC64_get_XER(
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                      &tst->arch.vex);
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR]     = LibVEX_GuestPPC64_get_CR(
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                      &tst->arch.vex);
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //mc->mc_gregs[VKI_PT_MQ]      = 0;
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //mc->mc_gregs[VKI_PT_TRAP]    = 0;
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //mc->mc_gregs[VKI_PT_DAR]     = fault_addr;
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //mc->mc_gregs[VKI_PT_DSISR]   = 0;
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //mc->mc_gregs[VKI_PT_RESULT]  = 0;
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* XXX should do FP and vector regs */
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* set up signal return trampoline */
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* NB.  5 Sept 07.  mc->mc_pad[0..1] used to contain a the code to
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      which the signal handler returns, and it just did sys_sigreturn
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      or sys_rt_sigreturn.  But this doesn't work if the stack is
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      non-executable, and it isn't consistent with the x86-linux and
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      amd64-linux scheme for removing the stack frame.  So instead be
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      consistent and use a stub in m_trampoline.  Then it doesn't
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      matter whether or not the (guest) stack is executable.  This
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fixes #149519 and #145837. */
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->tramp[0] = 0; /* invalid */
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame->tramp[1] = 0; /* invalid */
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid,
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (Addr)&frame->tramp, sizeof(frame->tramp));
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* invalidate any translation of this area */
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(discard_translations)( (Addr64)&frame->tramp[0],
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              sizeof(frame->tramp), "stack_mcontext" );
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* set the signal handler to return to the trampoline */
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_SIGNAL_LR(tst, (Addr)&VG_(ppc64_linux_SUBST_FOR_rt_sigreturn));
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Stack pointer for the handler .. (note, back chain set
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      earlier) */
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_SIGNAL_GPR(tid, 1, sp);
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Args for the handler .. */
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_SIGNAL_GPR(tid, 3, sigNo);
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_SIGNAL_GPR(tid, 4, (Addr) &frame->info);
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_SIGNAL_GPR(tid, 5, (Addr) &frame->uc);
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* the kernel sets this, though it doesn't seem to be in the ABI */
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_SIGNAL_GPR(tid, 6, (Addr) &frame->info);
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Handler is in fact a standard ppc64-linux function descriptor,
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      so extract the function entry point and also the toc ptr to use. */
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_SIGNAL_GPR(tid, 2, (Addr) ((ULong*)handler)[1]);
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex.guest_CIA = (Addr) ((ULong*)handler)[0];
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv = &frame->priv;
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv->magicPI       = 0x31415927;
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv->sigNo_private = sigNo;
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv->vex_shadow1   = tst->arch.vex_shadow1;
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv->vex_shadow2   = tst->arch.vex_shadow2;
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("pushed signal frame; %%R1 now = %#lx, "
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "next %%CIA = %#llx, status=%d\n",
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  sp, tst->arch.vex.guest_CIA, tst->status);
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Destroying signal frames                             ---*/
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* EXPORTED */
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState *tst;
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vg_sig_private *priv;
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr sp;
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt frame_size;
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct rt_sigframe *frame;
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int sigNo;
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool has_siginfo = isRT;
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_valid_tid)(tid));
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check that the stack frame looks valid */
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sp = tst->arch.vex.guest_GPR1;
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_16_ALIGNED(sp));
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* JRS 17 Nov 05: This code used to check that *sp -- which should
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have been set by the stwu at the start of the handler -- points
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to just above the frame (ie, the previous frame).  However, that
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      isn't valid when delivering signals on alt stacks.  So I removed
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it.  The frame is still sanity-checked using the priv->magicPI
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      field. */
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame = (struct rt_sigframe *)sp;
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame_size = sizeof(*frame);
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv = &frame->priv;
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(priv->magicPI == 0x31415927);
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->sig_mask = frame->uc.uc_sigmask;
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->tmp_sig_mask = tst->sig_mask;
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sigNo = priv->sigNo_private;
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define DO(gpr)  tst->arch.vex.guest_GPR##gpr \
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      = frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr]
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef DO
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex.guest_CIA = frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP];
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LibVEX_GuestPPC64_put_CR( frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR],
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             &tst->arch.vex );
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex.guest_LR  = frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK];
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex.guest_CTR = frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR];
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LibVEX_GuestPPC64_put_XER( frame->uc.uc_mcontext.gp_regs[VKI_PT_XER],
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              &tst->arch.vex );
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex_shadow1 = priv->vex_shadow1;
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex_shadow2 = priv->vex_shadow2;
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK(die_mem_stack_signal, sp, frame_size);
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_trace_signals))
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "vg_pop_signal_frame (thread %d): isRT=%d "
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "valid magic; EIP=%#llx\n",
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   tid, has_siginfo, tst->arch.vex.guest_CIA);
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* tell the tools */
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( post_deliver_signal, tid, sigNo );
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGP_ppc64_linux)
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
396