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-2015 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#include "pub_core_threadstate.h"
37#include "pub_core_aspacemgr.h"
38#include "pub_core_libcbase.h"
39#include "pub_core_libcassert.h"
40#include "pub_core_libcprint.h"
41#include "pub_core_machine.h"
42#include "pub_core_options.h"
43#include "pub_core_sigframe.h"
44#include "pub_core_signals.h"
45#include "pub_core_tooliface.h"
46#include "pub_core_trampoline.h"
47#include "priv_sigframe.h"
48
49
50/* This uses the hack of dumping the vex guest state along with both
51   shadows in the frame, and restoring it afterwards from there,
52   rather than pulling it out of the ucontext.  That means that signal
53   handlers which modify the ucontext and then return, expecting their
54   modifications to take effect, will have those modifications
55   ignored.  This could be fixed properly with an hour or so more
56   effort. */
57
58/* This also always does the 'has siginfo' behaviour whether or
59   not it is requested. */
60
61struct vg_sig_private {
62   UInt magicPI;
63   UInt sigNo_private;
64   VexGuestARM64State vex;
65   VexGuestARM64State vex_shadow1;
66   VexGuestARM64State vex_shadow2;
67};
68
69struct sigframe {
70   struct vki_ucontext uc;
71   unsigned long retcode[2];
72   struct vg_sig_private vp;
73};
74
75struct rt_sigframe {
76   vki_siginfo_t info;
77   struct sigframe sig;
78};
79
80
81static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
82                            UWord trapno, UWord err, const vki_sigset_t *set,
83                            struct vki_ucontext *uc)
84{
85
86   ThreadState *tst = VG_(get_ThreadState)(tid);
87   struct vki_sigcontext *sc = &uc->uc_mcontext;
88
89   VG_(memset)(uc, 0, sizeof(*uc));
90
91   uc->uc_flags = 0;
92   uc->uc_link = 0;
93   uc->uc_sigmask = *set;
94   uc->uc_stack = tst->altstack;
95
96#  define SC2(reg)  sc->regs[reg] = tst->arch.vex.guest_X##reg
97   SC2(0);   SC2(1);   SC2(2);   SC2(3);
98   SC2(4);   SC2(5);   SC2(6);   SC2(7);
99   SC2(8);   SC2(9);   SC2(10);  SC2(11);
100   SC2(12);  SC2(13);  SC2(14);  SC2(15);
101   SC2(16);  SC2(17);  SC2(18);  SC2(19);
102   SC2(20);  SC2(21);  SC2(22);  SC2(23);
103   SC2(24);  SC2(25);  SC2(26);  SC2(27);
104   SC2(28);  SC2(29);  SC2(30);
105#  undef SC2
106   sc->sp = tst->arch.vex.guest_XSP;
107   sc->pc = tst->arch.vex.guest_PC;
108   sc->pstate = 0; /* slack .. could do better */
109
110   //sc->trap_no = trapno;
111   //sc->error_code = err;
112   sc->fault_address = (ULong)si->_sifields._sigfault._addr;
113}
114
115
116static void build_sigframe(ThreadState *tst,
117                           struct sigframe *frame,
118                           const vki_siginfo_t *siginfo,
119                           const struct vki_ucontext *siguc,
120                           void *handler, UInt flags,
121                           const vki_sigset_t *mask,
122                           void *restorer)
123{
124   UWord trapno;
125   UWord err;
126   Int   sigNo = siginfo->si_signo;
127   struct vg_sig_private *priv = &frame->vp;
128
129   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
130             (Addr)frame, offsetof(struct sigframe, vp));
131
132   if (siguc) {
133      trapno = 0; //siguc->uc_mcontext.trap_no;
134      err = 0; //siguc->uc_mcontext.error_code;
135   } else {
136      trapno = 0;
137      err = 0;
138   }
139
140   synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
141
142   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
143             (Addr)frame, offsetof(struct sigframe, vp));
144
145   priv->magicPI = 0x31415927;
146   priv->sigNo_private = sigNo;
147   priv->vex         = tst->arch.vex;
148   priv->vex_shadow1 = tst->arch.vex_shadow1;
149   priv->vex_shadow2 = tst->arch.vex_shadow2;
150}
151
152
153/* EXPORTED */
154void VG_(sigframe_create)( ThreadId tid,
155                           Bool on_altstack,
156                           Addr sp_top_of_frame,
157                           const vki_siginfo_t *siginfo,
158                           const struct vki_ucontext *siguc,
159                           void *handler,
160                           UInt flags,
161                           const vki_sigset_t *mask,
162                           void *restorer )
163{
164   ThreadState *tst;
165   Addr sp    = sp_top_of_frame;
166   Int  sigNo = siginfo->si_signo;
167   UInt size;
168
169   tst = VG_(get_ThreadState)(tid);
170
171   size = sizeof(struct rt_sigframe);
172
173   sp -= size;
174   sp = VG_ROUNDDN(sp, 16);
175
176   if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
177      return; // Give up.  No idea if this is correct
178
179   struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
180
181   /* Track our writes to siginfo */
182   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
183             "signal handler siginfo", (Addr)rsf,
184             offsetof(struct rt_sigframe, sig));
185
186   VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
187
188   if (sigNo == VKI_SIGILL && siginfo->si_code > 0) {
189      rsf->info._sifields._sigfault._addr
190        = (Addr*)(tst)->arch.vex.guest_PC;
191   }
192   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
193         (Addr)rsf, offsetof(struct rt_sigframe, sig));
194
195   build_sigframe(tst, &rsf->sig, siginfo, siguc,
196                       handler, flags, mask, restorer);
197   tst->arch.vex.guest_X1 = (Addr)&rsf->info;
198   tst->arch.vex.guest_X2 = (Addr)&rsf->sig.uc;
199
200   VG_(set_SP)(tid, sp);
201   VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
202             sizeof(Addr));
203   tst->arch.vex.guest_X0 = sigNo;
204
205   if (flags & VKI_SA_RESTORER)
206       tst->arch.vex.guest_X30 = (Addr)restorer;
207   else
208       tst->arch.vex.guest_X30
209          = (Addr)&VG_(arm64_linux_SUBST_FOR_rt_sigreturn);
210
211   tst->arch.vex.guest_PC = (Addr)handler;
212}
213
214
215/*------------------------------------------------------------*/
216/*--- Destroying signal frames                             ---*/
217/*------------------------------------------------------------*/
218
219/* EXPORTED */
220void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
221{
222   ThreadState *tst;
223   struct vg_sig_private *priv;
224   Addr sp;
225   UInt frame_size;
226//ZZ    struct vki_sigcontext *mc;
227   Int sigNo;
228   Bool has_siginfo = isRT;
229
230   vg_assert(VG_(is_valid_tid)(tid));
231   tst = VG_(get_ThreadState)(tid);
232   sp = tst->arch.vex.guest_XSP;
233
234//ZZ    if (has_siginfo) {
235      struct rt_sigframe *frame = (struct rt_sigframe *)sp;
236      frame_size = sizeof(*frame);
237      //mc = &frame->sig.uc.uc_mcontext;
238      priv = &frame->sig.vp;
239      vg_assert(priv->magicPI == 0x31415927);
240      tst->sig_mask = frame->sig.uc.uc_sigmask;
241//ZZ    } else {
242//ZZ       struct sigframe *frame = (struct sigframe *)sp;
243//ZZ       frame_size = sizeof(*frame);
244//ZZ       mc = &frame->uc.uc_mcontext;
245//ZZ       priv = &frame->vp;
246//ZZ       vg_assert(priv->magicPI == 0x31415927);
247//ZZ       tst->sig_mask = frame->uc.uc_sigmask;
248//ZZ       //VG_(printf)("Setting signmask to %08x%08x\n",
249//ZZ       //            tst->sig_mask[0],tst->sig_mask[1]);
250//ZZ    }
251   tst->tmp_sig_mask = tst->sig_mask;
252
253   sigNo = priv->sigNo_private;
254
255//ZZ     //XXX: restore regs
256//ZZ #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
257//ZZ    REST(r0,R0);
258//ZZ    REST(r1,R1);
259//ZZ    REST(r2,R2);
260//ZZ    REST(r3,R3);
261//ZZ    REST(r4,R4);
262//ZZ    REST(r5,R5);
263//ZZ    REST(r6,R6);
264//ZZ    REST(r7,R7);
265//ZZ    REST(r8,R8);
266//ZZ    REST(r9,R9);
267//ZZ    REST(r10,R10);
268//ZZ    REST(fp,R11);
269//ZZ    REST(ip,R12);
270//ZZ    REST(sp,R13);
271//ZZ    REST(lr,R14);
272//ZZ    REST(pc,R15T);
273//ZZ #  undef REST
274
275   /* Uh, the next line makes all the REST() above pointless. */
276   tst->arch.vex         = priv->vex;
277
278   tst->arch.vex_shadow1 = priv->vex_shadow1;
279   tst->arch.vex_shadow2 = priv->vex_shadow2;
280
281   VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
282             frame_size + VG_STACK_REDZONE_SZB );
283
284   if (VG_(clo_trace_signals))
285      VG_(message)(Vg_DebugMsg,
286                   "vg_pop_signal_frame (thread %u): "
287                   "isRT=%d valid magic; PC=%#llx\n",
288                   tid, has_siginfo, tst->arch.vex.guest_PC);
289
290   /* tell the tools */
291   VG_TRACK( post_deliver_signal, tid, sigNo );
292}
293
294#endif // defined(VGP_arm_linux)
295
296/*--------------------------------------------------------------------*/
297/*--- end                                   sigframe-arm64-linux.c ---*/
298/*--------------------------------------------------------------------*/
299