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