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