1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/
3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- Create/destroy signal delivery frames.                       ---*/
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*---                                       sigframe-arm64-linux.c ---*/
5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/
6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*
8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This file is part of Valgrind, a dynamic binary instrumentation
9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   framework.
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2013-2013 OpenWorks
12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      info@open-works.net
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This program is free software; you can redistribute it and/or
15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   modify it under the terms of the GNU General Public License as
16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   published by the Free Software Foundation; either version 2 of the
17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   License, or (at your option) any later version.
18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This program is distributed in the hope that it will be useful, but
20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   WITHOUT ANY WARRANTY; without even the implied warranty of
21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   General Public License for more details.
23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   You should have received a copy of the GNU General Public License
25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   along with this program; if not, write to the Free Software
26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   02111-1307, USA.
28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   The GNU General Public License is contained in the file COPYING.
30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined(VGP_arm64_linux)
33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_basics.h"
35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_vki.h"
36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ #include "pub_core_vkiscnums.h"
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_threadstate.h"
39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_aspacemgr.h"
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcbase.h"
41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcassert.h"
42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_libcprint.h"
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_machine.h"
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_options.h"
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_sigframe.h"
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_signals.h"
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_tooliface.h"
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_trampoline.h"
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ #include "pub_core_transtab.h"      // VG_(discard_translations)
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* This uses the hack of dumping the vex guest state along with both
53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   shadows in the frame, and restoring it afterwards from there,
54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   rather than pulling it out of the ucontext.  That means that signal
55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   handlers which modify the ucontext and then return, expecting their
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   modifications to take effect, will have those modifications
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ignored.  This could be fixed properly with an hour or so more
58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   effort. */
59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* This also always does the 'has siginfo' behaviour whether or
61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   not it is requested. */
62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstruct vg_sig_private {
64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt magicPI;
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt sigNo_private;
66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VexGuestARM64State vex;
67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VexGuestARM64State vex_shadow1;
68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VexGuestARM64State vex_shadow2;
69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov};
70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstruct sigframe {
72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct vki_ucontext uc;
73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   unsigned long retcode[2];
74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct vg_sig_private vp;
75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov};
76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstruct rt_sigframe {
78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vki_siginfo_t info;
79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct sigframe sig;
80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov};
81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool extend ( ThreadState *tst, Addr addr, SizeT size )
83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ThreadId        tid = tst->tid;
85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   NSegment const* stackseg = NULL;
86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      stackseg = VG_(am_find_nsegment)(addr);
89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (0 && stackseg)
90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     addr, stackseg->start, stackseg->end);
92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(message)(
96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Vg_UserMsg,
97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         "Can't extend stack to %#lx during signal delivery for thread %d:",
98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addr, tid);
99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (stackseg == NULL)
100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(message)(Vg_UserMsg, "  no stack segment");
101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      else
102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(message)(Vg_UserMsg, "  too small or bad protection modes");
103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* set SIGSEGV to default handler */
105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(set_default_handler)(VKI_SIGSEGV);
106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(synth_fault_mapping)(tid, addr);
107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* The whole process should be about to die, since the default
109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         action of SIGSEGV to kill the whole process. */
110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return False;
111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* For tracking memory events, indicate the entire frame has been
114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      allocated. */
115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             size + VG_STACK_REDZONE_SZB, tid );
117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return True;
119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            UWord trapno, UWord err, const vki_sigset_t *set,
123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            struct vki_ucontext *uc)
124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ThreadState *tst = VG_(get_ThreadState)(tid);
127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct vki_sigcontext *sc = &uc->uc_mcontext;
128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(memset)(uc, 0, sizeof(*uc));
130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   uc->uc_flags = 0;
132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   uc->uc_link = 0;
133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   uc->uc_sigmask = *set;
134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   uc->uc_stack = tst->altstack;
135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define SC2(reg)  sc->regs[reg] = tst->arch.vex.guest_X##reg
137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SC2(0);   SC2(1);   SC2(2);   SC2(3);
138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SC2(4);   SC2(5);   SC2(6);   SC2(7);
139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SC2(8);   SC2(9);   SC2(10);  SC2(11);
140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SC2(12);  SC2(13);  SC2(14);  SC2(15);
141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SC2(16);  SC2(17);  SC2(18);  SC2(19);
142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SC2(20);  SC2(21);  SC2(22);  SC2(23);
143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SC2(24);  SC2(25);  SC2(26);  SC2(27);
144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SC2(28);  SC2(29);  SC2(30);
145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  undef SC2
146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sc->sp = tst->arch.vex.guest_XSP;
147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sc->pc = tst->arch.vex.guest_PC;
148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sc->pstate = 0; /* slack .. could do better */
149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //sc->trap_no = trapno;
151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //sc->error_code = err;
152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sc->fault_address = (ULong)si->_sifields._sigfault._addr;
153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void build_sigframe(ThreadState *tst,
157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           struct sigframe *frame,
158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           const vki_siginfo_t *siginfo,
159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           const struct vki_ucontext *siguc,
160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           void *handler, UInt flags,
161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           const vki_sigset_t *mask,
162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           void *restorer)
163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UWord trapno;
165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UWord err;
166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int   sigNo = siginfo->si_signo;
167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct vg_sig_private *priv = &frame->vp;
168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             (Addr)frame, offsetof(struct sigframe, vp));
171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (siguc) {
173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      trapno = 0; //siguc->uc_mcontext.trap_no;
174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      err = 0; //siguc->uc_mcontext.error_code;
175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      trapno = 0;
177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      err = 0;
178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             (Addr)frame, offsetof(struct sigframe, vp));
184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   priv->magicPI = 0x31415927;
186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   priv->sigNo_private = sigNo;
187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   priv->vex         = tst->arch.vex;
188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   priv->vex_shadow1 = tst->arch.vex_shadow1;
189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   priv->vex_shadow2 = tst->arch.vex_shadow2;
190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* EXPORTED */
194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid VG_(sigframe_create)( ThreadId tid,
195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           Addr sp_top_of_frame,
196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           const vki_siginfo_t *siginfo,
197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           const struct vki_ucontext *siguc,
198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           void *handler,
199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           UInt flags,
200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           const vki_sigset_t *mask,
201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           void *restorer )
202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ThreadState *tst;
204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Addr sp    = sp_top_of_frame;
205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int  sigNo = siginfo->si_signo;
206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt size;
207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst = VG_(get_ThreadState)(tid);
209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   size = sizeof(struct rt_sigframe);
211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sp -= size;
213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sp = VG_ROUNDDN(sp, 16);
214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (!extend(tst, sp, size))
216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return; // Give up.  No idea if this is correct
217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Track our writes to siginfo */
221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             "signal handler siginfo", (Addr)rsf,
223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             offsetof(struct rt_sigframe, sig));
224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (sigNo == VKI_SIGILL && siginfo->si_code > 0) {
228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      rsf->info._sifields._sigfault._addr
229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        = (Addr*)(tst)->arch.vex.guest_PC;
230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         (Addr)rsf, offsetof(struct rt_sigframe, sig));
233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   build_sigframe(tst, &rsf->sig, siginfo, siguc,
235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       handler, flags, mask, restorer);
236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst->arch.vex.guest_X1 = (Addr)&rsf->info;
237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst->arch.vex.guest_X2 = (Addr)&rsf->sig.uc;
238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(set_SP)(tid, sp);
240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             sizeof(Addr));
242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst->arch.vex.guest_X0 = sigNo;
243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (flags & VKI_SA_RESTORER)
245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       tst->arch.vex.guest_X30 = (Addr)restorer;
246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else
247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       tst->arch.vex.guest_X30
248436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          = (Addr)&VG_(arm64_linux_SUBST_FOR_rt_sigreturn);
249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst->arch.vex.guest_PC = (Addr)handler;
251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*------------------------------------------------------------*/
255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- Destroying signal frames                             ---*/
256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*------------------------------------------------------------*/
257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* EXPORTED */
259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ThreadState *tst;
262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   struct vg_sig_private *priv;
263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Addr sp;
264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt frame_size;
265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    struct vki_sigcontext *mc;
266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int sigNo;
267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Bool has_siginfo = isRT;
268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vg_assert(VG_(is_valid_tid)(tid));
270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst = VG_(get_ThreadState)(tid);
271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sp = tst->arch.vex.guest_XSP;
272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (has_siginfo) {
274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      struct rt_sigframe *frame = (struct rt_sigframe *)sp;
275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      frame_size = sizeof(*frame);
276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      //mc = &frame->sig.uc.uc_mcontext;
277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      priv = &frame->sig.vp;
278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vg_assert(priv->magicPI == 0x31415927);
279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tst->sig_mask = frame->sig.uc.uc_sigmask;
280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    } else {
281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       struct sigframe *frame = (struct sigframe *)sp;
282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       frame_size = sizeof(*frame);
283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       mc = &frame->uc.uc_mcontext;
284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       priv = &frame->vp;
285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       vg_assert(priv->magicPI == 0x31415927);
286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       tst->sig_mask = frame->uc.uc_sigmask;
287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       //VG_(printf)("Setting signmask to %08x%08x\n",
288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       //            tst->sig_mask[0],tst->sig_mask[1]);
289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    }
290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst->tmp_sig_mask = tst->sig_mask;
291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sigNo = priv->sigNo_private;
293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ     //XXX: restore regs
295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r0,R0);
297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r1,R1);
298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r2,R2);
299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r3,R3);
300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r4,R4);
301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r5,R5);
302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r6,R6);
303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r7,R7);
304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r8,R8);
305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r9,R9);
306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(r10,R10);
307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(fp,R11);
308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(ip,R12);
309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(sp,R13);
310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(lr,R14);
311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    REST(pc,R15T);
312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ #  undef REST
313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Uh, the next line makes all the REST() above pointless. */
315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst->arch.vex         = priv->vex;
316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst->arch.vex_shadow1 = priv->vex_shadow1;
318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tst->arch.vex_shadow2 = priv->vex_shadow2;
319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             frame_size + VG_STACK_REDZONE_SZB );
322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (VG_(clo_trace_signals))
324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(message)(Vg_DebugMsg,
325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   "vg_pop_signal_frame (thread %d): "
326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   "isRT=%d valid magic; PC=%#llx\n",
327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   tid, has_siginfo, tst->arch.vex.guest_PC);
328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* tell the tools */
330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_TRACK( post_deliver_signal, tid, sigNo );
331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif // defined(VGP_arm_linux)
334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/
336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- end                                   sigframe-arm64-linux.c ---*/
337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--------------------------------------------------------------------*/
338