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