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-2017 Nicholas Nethercote
12       njn@valgrind.org
13    Copyright (C) 2004-2017 Paul Mackerras
14       paulus@samba.org
15    Copyright (C) 2008-2017 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.  Then, integer
58    registers, the SP and the PC are restored from the ucontext.  That
59    means that signal handlers which modify floating point registers or
60    in general any register state apart from R0 to R15 in the ucontext
61    and then return, expecting their modifications to take effect, will
62    have those modifications ignored. */
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 TO_CTX(reg,REG)  sc->arm_##reg = tst->arch.vex.guest_##REG
99    TO_CTX(r0,R0);   TO_CTX(r1,R1);   TO_CTX(r2,R2);   TO_CTX(r3,R3);
100    TO_CTX(r4,R4);   TO_CTX(r5,R5);   TO_CTX(r6,R6);   TO_CTX(r7,R7);
101    TO_CTX(r8,R8);   TO_CTX(r9,R9);   TO_CTX(r10,R10); TO_CTX(fp,R11);
102    TO_CTX(ip,R12);  TO_CTX(sp,R13);  TO_CTX(lr,R14);  TO_CTX(pc,R15T);
103 #  undef TO_CTX
104 
105    sc->trap_no = trapno;
106    sc->error_code = err;
107    sc->fault_address = (UInt)si->_sifields._sigfault._addr;
108 }
109 
110 
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)111 static void build_sigframe(ThreadState *tst,
112             struct sigframe *frame,
113             const vki_siginfo_t *siginfo,
114             const struct vki_ucontext *siguc,
115             void *handler, UInt flags,
116             const vki_sigset_t *mask,
117             void *restorer){
118 
119    UWord trapno;
120    UWord err;
121    Int  sigNo = siginfo->si_signo;
122    struct vg_sig_private *priv = &frame->vp;
123 
124    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
125          (Addr)frame, offsetof(struct sigframe, vp));
126 
127    if(siguc) {
128       trapno = siguc->uc_mcontext.trap_no;
129       err = siguc->uc_mcontext.error_code;
130    } else {
131       trapno = 0;
132       err = 0;
133    }
134 
135    synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
136 
137    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
138          (Addr)frame, offsetof(struct sigframe, vp));
139 
140    priv->magicPI = 0x31415927;
141    priv->sigNo_private = sigNo;
142    priv->vex         = tst->arch.vex;
143    priv->vex_shadow1 = tst->arch.vex_shadow1;
144    priv->vex_shadow2 = tst->arch.vex_shadow2;
145 
146 }
147 
148 
149 
150 /* EXPORTED */
VG_(sigframe_create)151 void VG_(sigframe_create)( ThreadId tid,
152                            Bool on_altstack,
153                            Addr sp_top_of_frame,
154                            const vki_siginfo_t *siginfo,
155                            const struct vki_ucontext *siguc,
156                            void *handler,
157                            UInt flags,
158                            const vki_sigset_t *mask,
159                            void *restorer )
160 {
161    Addr sp = sp_top_of_frame;
162    ThreadState *tst;
163    Int sigNo = siginfo->si_signo;
164    UInt size;
165 
166    tst = VG_(get_ThreadState)(tid);
167 
168    size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
169       sizeof(struct sigframe);
170 
171    sp -= size;
172    sp = VG_ROUNDDN(sp, 16);
173 
174    if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
175       I_die_here; // XXX Incorrect behavior
176 
177 
178    if (flags & VKI_SA_SIGINFO){
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_R12; /* IP */
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_R1 = (Addr)&rsf->info;
198       tst->arch.vex.guest_R2 = (Addr)&rsf->sig.uc;
199    }
200    else {
201       build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
202                              handler, flags, mask, restorer);
203    }
204 
205    VG_(set_SP)(tid, sp);
206    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
207          sizeof(Addr));
208    tst->arch.vex.guest_R0  = sigNo;
209 
210    if (flags & VKI_SA_RESTORER)
211        tst->arch.vex.guest_R14 = (Addr)restorer;
212    else
213        tst->arch.vex.guest_R14
214           = (flags & VKI_SA_SIGINFO)
215             ? (Addr)&VG_(arm_linux_SUBST_FOR_rt_sigreturn)
216             : (Addr)&VG_(arm_linux_SUBST_FOR_sigreturn);
217 
218    tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
219 
220    /* Regardless of what the state of ITSTATE was, it makes no sense
221       to enter the handler with the first 1-4 instructions possibly
222       predicated as "don't execute".  So set ITSTATE to [AL,AL,AL,AL]
223       before entering the handler. */
224    tst->arch.vex.guest_ITSTATE = 0;
225 
226    if (VG_(clo_trace_signals))
227       VG_(message)(Vg_DebugMsg,
228                    "VG_(sigframe_create): continuing in handler with PC=%#lx\n",
229                    (Addr)handler);
230 }
231 
232 
233 /*------------------------------------------------------------*/
234 /*--- Destroying signal frames                             ---*/
235 /*------------------------------------------------------------*/
236 
237 /* EXPORTED */
VG_(sigframe_destroy)238 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
239 {
240    ThreadState *tst;
241    struct vg_sig_private *priv;
242    Addr sp;
243    UInt frame_size;
244    Int sigNo;
245    Bool has_siginfo = isRT;
246 
247    struct rt_sigframe *rt_frame = NULL;
248 
249    vg_assert(VG_(is_valid_tid)(tid));
250    tst = VG_(get_ThreadState)(tid);
251    sp = tst->arch.vex.guest_R13;
252 
253    if (has_siginfo) {
254       struct rt_sigframe *frame = (struct rt_sigframe *)sp;
255       frame_size = sizeof(*frame);
256       priv = &frame->sig.vp;
257       vg_assert(priv->magicPI == 0x31415927);
258       tst->sig_mask = frame->sig.uc.uc_sigmask;
259       rt_frame = frame;
260    } else {
261       struct sigframe *frame = (struct sigframe *)sp;
262       frame_size = sizeof(*frame);
263       priv = &frame->vp;
264       vg_assert(priv->magicPI == 0x31415927);
265       tst->sig_mask = frame->uc.uc_sigmask;
266    }
267    tst->tmp_sig_mask = tst->sig_mask;
268 
269    sigNo = priv->sigNo_private;
270 
271    /* Restore the entire machine state from our private copy.  This
272       isn't really right, but we'll now move on to pick up at least
273       some changes that the signal handler may have made to the
274       sigcontext. */
275    tst->arch.vex         = priv->vex;
276    tst->arch.vex_shadow1 = priv->vex_shadow1;
277    tst->arch.vex_shadow2 = priv->vex_shadow2;
278 
279    if (has_siginfo) {
280       /* Pick up at least some state changes from the ucontext, just
281          in case the handler changed it.  The shadow values will be
282          wrong, but hey.  This restores the integer registers, the
283          program counter and stack pointer.  FP/Vector regs, and any
284          condition code, FP status/control bits, etc, are not
285          restored. */
286       vg_assert(rt_frame != NULL);
287       struct vki_sigcontext *sc = &rt_frame->sig.uc.uc_mcontext;
288       Bool handler_changed_pc = sc->arm_pc != tst->arch.vex.guest_R15T;
289 
290 #     define FROM_CTX(reg,REG)  tst->arch.vex.guest_##REG = sc->arm_##reg;
291       FROM_CTX(r0,R0);  FROM_CTX(r1,R1);  FROM_CTX(r2,R2);   FROM_CTX(r3,R3);
292       FROM_CTX(r4,R4);  FROM_CTX(r5,R5);  FROM_CTX(r6,R6);   FROM_CTX(r7,R7);
293       FROM_CTX(r8,R8);  FROM_CTX(r9,R9);  FROM_CTX(r10,R10); FROM_CTX(fp,R11);
294       FROM_CTX(ip,R12); FROM_CTX(sp,R13); FROM_CTX(lr,R14);  FROM_CTX(pc,R15T);
295 #     undef FROM_CTX
296 
297       /* A nasty ITSTATE hack -- apparently necessary as there doesn't
298          seem to be anywhere in the mcontext in which the ITSTATE is
299          stored.  If the handler appears to have changed the PC, set
300          ITSTATE to [AL,AL,AL,AL] on the basis that it would be nuts
301          to start executing code with an ITSTATE value that pertained
302          to some other code address.  Otherwise ITSTATE is restored
303          directly from the VEX state that we shoved on the stack when
304          creating the signal frame. */
305       if (handler_changed_pc) {
306          tst->arch.vex.guest_ITSTATE = 0;
307       }
308    }
309 
310    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
311              frame_size + VG_STACK_REDZONE_SZB );
312 
313    if (VG_(clo_trace_signals))
314       VG_(message)(Vg_DebugMsg,
315                    "vg_pop_signal_frame (thread %u): "
316                    "isRT=%d valid magic; PC=%#x\n",
317                    tid, has_siginfo, tst->arch.vex.guest_R15T);
318 
319    /* tell the tools */
320    VG_TRACK( post_deliver_signal, tid, sigNo );
321 }
322 
323 #endif // defined(VGP_arm_linux)
324 
325 /*--------------------------------------------------------------------*/
326 /*--- end                                     sigframe-arm-linux.c ---*/
327 /*--------------------------------------------------------------------*/
328