1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Create/destroy signal delivery frames.                       ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                         sigframe-arm-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
11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2000-2012 Nicholas Nethercote
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      njn@valgrind.org
13663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2004-2012 Paul Mackerras
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      paulus@samba.org
15663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2008-2012 Evan Geller
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gaze@bea.ms
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_arm_linux)
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h"
41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h"
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_sigframe.h"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h"
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h"
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_trampoline.h"
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h"      // VG_(discard_translations)
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* This uses the hack of dumping the vex guest state along with both
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   shadows in the frame, and restoring it afterwards from there,
58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   rather than pulling it out of the ucontext.  That means that signal
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   handlers which modify the ucontext and then return, expecting their
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   modifications to take effect, will have those modifications
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ignored.  This could be fixed properly with an hour or so more
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   effort. */
63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct vg_sig_private {
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt magicPI;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt sigNo_private;
68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VexGuestARMState vex;
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexGuestARMState vex_shadow1;
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexGuestARMState vex_shadow2;
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct sigframe {
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_ucontext uc;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned long retcode[2];
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vg_sig_private vp;
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct rt_sigframe {
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vki_siginfo_t info;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct sigframe sig;
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool extend ( ThreadState *tst, Addr addr, SizeT size )
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId        tid = tst->tid;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NSegment const* stackseg = NULL;
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stackseg = VG_(am_find_nsegment)(addr);
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 && stackseg)
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           addr, stackseg->start, stackseg->end);
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Vg_UserMsg,
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "Can't extend stack to %#lx during signal delivery for thread %d:",
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addr, tid);
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stackseg == NULL)
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "  no stack segment");
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "  too small or bad protection modes");
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* set SIGSEGV to default handler */
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(set_default_handler)(VKI_SIGSEGV);
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(synth_fault_mapping)(tid, addr);
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The whole process should be about to die, since the default
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    action of SIGSEGV to kill the whole process. */
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For tracking memory events, indicate the entire frame has been
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allocated. */
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             size + VG_STACK_REDZONE_SZB, tid );
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    UWord trapno, UWord err, const vki_sigset_t *set,
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    struct vki_ucontext *uc){
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState *tst = VG_(get_ThreadState)(tid);
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_sigcontext *sc = &uc->uc_mcontext;
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(uc, 0, sizeof(*uc));
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uc->uc_flags = 0;
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uc->uc_link = 0;
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uc->uc_sigmask = *set;
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uc->uc_stack = tst->altstack;
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SC2(reg,REG)  sc->arm_##reg = tst->arch.vex.guest_##REG
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r0,R0);
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r1,R1);
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r2,R2);
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r3,R3);
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r4,R4);
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r5,R5);
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r6,R6);
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r7,R7);
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r8,R8);
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r9,R9);
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(r10,R10);
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(fp,R11);
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(ip,R12);
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(sp,R13);
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(lr,R14);
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SC2(pc,R15T);
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef SC2
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sc->trap_no = trapno;
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sc->error_code = err;
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sc->fault_address = (UInt)si->_sifields._sigfault._addr;
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void build_sigframe(ThreadState *tst,
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            struct sigframe *frame,
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const vki_siginfo_t *siginfo,
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const struct vki_ucontext *siguc,
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            void *handler, UInt flags,
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const vki_sigset_t *mask,
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            void *restorer){
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord trapno;
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord err;
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  sigNo = siginfo->si_signo;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vg_sig_private *priv = &frame->vp;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (Addr)frame, offsetof(struct sigframe, vp));
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if(siguc) {
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      trapno = siguc->uc_mcontext.trap_no;
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      err = siguc->uc_mcontext.error_code;
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      trapno = 0;
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      err = 0;
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (Addr)frame, offsetof(struct sigframe, vp));
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv->magicPI = 0x31415927;
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv->sigNo_private = sigNo;
193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   priv->vex         = tst->arch.vex;
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv->vex_shadow1 = tst->arch.vex_shadow1;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   priv->vex_shadow2 = tst->arch.vex_shadow2;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* EXPORTED */
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sigframe_create)( ThreadId tid,
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Addr sp_top_of_frame,
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const vki_siginfo_t *siginfo,
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const struct vki_ucontext *siguc,
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           void *handler,
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UInt flags,
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const vki_sigset_t *mask,
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           void *restorer )
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   struct vg_sig_private *priv;
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr sp = sp_top_of_frame;
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState *tst;
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int sigNo = siginfo->si_signo;
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   Addr faultaddr;
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size;
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sizeof(struct sigframe);
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sp -= size;
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sp = VG_ROUNDDN(sp, 16);
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if(!extend(tst, sp, size))
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      I_die_here; // XXX Incorrect behavior
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flags & VKI_SA_SIGINFO){
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Track our writes to siginfo */
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "signal handler siginfo", (Addr)rsf,
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offsetof(struct rt_sigframe, sig));
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (Addr)rsf, offsetof(struct rt_sigframe, sig));
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      build_sigframe(tst, &rsf->sig, siginfo, siguc,
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             handler, flags, mask, restorer);
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tst->arch.vex.guest_R1 = (Addr)&rsf->info;
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tst->arch.vex.guest_R2 = (Addr)&rsf->sig.uc;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             handler, flags, mask, restorer);
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(set_SP)(tid, sp);
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sizeof(Addr));
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex.guest_R0  = sigNo;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flags & VKI_SA_RESTORER)
262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       tst->arch.vex.guest_R14 = (Addr)restorer;
263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       tst->arch.vex.guest_R14
265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          = (flags & VKI_SA_SIGINFO)
266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ? (Addr)&VG_(arm_linux_SUBST_FOR_rt_sigreturn)
267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            : (Addr)&VG_(arm_linux_SUBST_FOR_sigreturn);
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Destroying signal frames                             ---*/
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* EXPORTED */
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState *tst;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vg_sig_private *priv;
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr sp;
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt frame_size;
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_sigcontext *mc;
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int sigNo;
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool has_siginfo = isRT;
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_valid_tid)(tid));
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sp = tst->arch.vex.guest_R13;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (has_siginfo) {
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct rt_sigframe *frame = (struct rt_sigframe *)sp;
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      frame_size = sizeof(*frame);
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mc = &frame->sig.uc.uc_mcontext;
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      priv = &frame->sig.vp;
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(priv->magicPI == 0x31415927);
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tst->sig_mask = frame->sig.uc.uc_sigmask;
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct sigframe *frame = (struct sigframe *)sp;
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      frame_size = sizeof(*frame);
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mc = &frame->uc.uc_mcontext;
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      priv = &frame->vp;
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(priv->magicPI == 0x31415927);
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tst->sig_mask = frame->uc.uc_sigmask;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->tmp_sig_mask = tst->sig_mask;
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sigNo = priv->sigNo_private;
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //XXX: restore regs
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r0,R0);
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r1,R1);
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r2,R2);
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r3,R3);
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r4,R4);
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r5,R5);
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r6,R6);
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r7,R7);
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r8,R8);
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r9,R9);
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(r10,R10);
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(fp,R11);
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(ip,R12);
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(sp,R13);
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(lr,R14);
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REST(pc,R15T);
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef REST
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Uh, the next line makes all the REST() above pointless. */
336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tst->arch.vex         = priv->vex;
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex_shadow1 = priv->vex_shadow1;
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex_shadow2 = priv->vex_shadow2;
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frame_size + VG_STACK_REDZONE_SZB );
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_trace_signals))
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "vg_pop_signal_frame (thread %d): "
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   "isRT=%d valid magic; PC=%#x\n",
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   tid, has_siginfo, tst->arch.vex.guest_R15T);
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* tell the tools */
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( post_deliver_signal, tid, sigNo );
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGP_arm_linux)
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                     sigframe-arm-linux.c ---*/
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
359