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-2011 Nicholas Nethercote
12      njn@valgrind.org
13   Copyright (C) 2004-2011 Paul Mackerras
14      paulus@samba.org
15   Copyright (C) 2008-2011 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
264   tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
265}
266
267
268/*------------------------------------------------------------*/
269/*--- Destroying signal frames                             ---*/
270/*------------------------------------------------------------*/
271
272/* EXPORTED */
273void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
274{
275   ThreadState *tst;
276   struct vg_sig_private *priv;
277   Addr sp;
278   UInt frame_size;
279   struct vki_sigcontext *mc;
280   Int sigNo;
281   Bool has_siginfo = isRT;
282
283   vg_assert(VG_(is_valid_tid)(tid));
284   tst = VG_(get_ThreadState)(tid);
285   sp = tst->arch.vex.guest_R13;
286
287   if (has_siginfo) {
288      struct rt_sigframe *frame = (struct rt_sigframe *)sp;
289      frame_size = sizeof(*frame);
290      mc = &frame->sig.uc.uc_mcontext;
291      priv = &frame->sig.vp;
292      vg_assert(priv->magicPI == 0x31415927);
293      tst->sig_mask = frame->sig.uc.uc_sigmask;
294   } else {
295      struct sigframe *frame = (struct sigframe *)sp;
296      frame_size = sizeof(*frame);
297      mc = &frame->uc.uc_mcontext;
298      priv = &frame->vp;
299      vg_assert(priv->magicPI == 0x31415927);
300      tst->sig_mask = frame->uc.uc_sigmask;
301      /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
302      tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
303      VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
304*/
305   }
306   tst->tmp_sig_mask = tst->sig_mask;
307
308   sigNo = priv->sigNo_private;
309
310    //XXX: restore regs
311#  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
312   REST(r0,R0);
313   REST(r1,R1);
314   REST(r2,R2);
315   REST(r3,R3);
316   REST(r4,R4);
317   REST(r5,R5);
318   REST(r6,R6);
319   REST(r7,R7);
320   REST(r8,R8);
321   REST(r9,R9);
322   REST(r10,R10);
323   REST(fp,R11);
324   REST(ip,R12);
325   REST(sp,R13);
326   REST(lr,R14);
327   REST(pc,R15T);
328#  undef REST
329
330   /* Uh, the next line makes all the REST() above pointless. */
331   tst->arch.vex         = priv->vex;
332
333   tst->arch.vex_shadow1 = priv->vex_shadow1;
334   tst->arch.vex_shadow2 = priv->vex_shadow2;
335
336   VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
337             frame_size + VG_STACK_REDZONE_SZB );
338
339   if (VG_(clo_trace_signals))
340      VG_(message)(Vg_DebugMsg,
341                   "vg_pop_signal_frame (thread %d): "
342                   "isRT=%d valid magic; PC=%#x\n",
343                   tid, has_siginfo, tst->arch.vex.guest_R15T);
344
345   /* tell the tools */
346   VG_TRACK( post_deliver_signal, tid, sigNo );
347}
348
349#endif // defined(VGP_arm_linux)
350
351/*--------------------------------------------------------------------*/
352/*--- end                                     sigframe-arm-linux.c ---*/
353/*--------------------------------------------------------------------*/
354