• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2015 Nicholas Nethercote
12       njn@valgrind.org
13    Copyright (C) 2004-2015 Paul Mackerras
14       paulus@samba.org
15    Copyright (C) 2008-2015 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                            Bool on_altstack,
165                            Addr sp_top_of_frame,
166                            const vki_siginfo_t *siginfo,
167                            const struct vki_ucontext *siguc,
168                            void *handler,
169                            UInt flags,
170                            const vki_sigset_t *mask,
171                            void *restorer )
172 {
173 //   struct vg_sig_private *priv;
174    Addr sp = sp_top_of_frame;
175    ThreadState *tst;
176    Int sigNo = siginfo->si_signo;
177 //   Addr faultaddr;
178    UInt size;
179 
180    tst = VG_(get_ThreadState)(tid);
181 
182    size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
183       sizeof(struct sigframe);
184 
185    sp -= size;
186    sp = VG_ROUNDDN(sp, 16);
187 
188    if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
189       I_die_here; // XXX Incorrect behavior
190 
191 
192    if (flags & VKI_SA_SIGINFO){
193       struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
194 
195       /* Track our writes to siginfo */
196       VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
197             "signal handler siginfo", (Addr)rsf,
198             offsetof(struct rt_sigframe, sig));
199 
200       VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
201 
202       if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
203          rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
204       }
205       VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
206             (Addr)rsf, offsetof(struct rt_sigframe, sig));
207 
208       build_sigframe(tst, &rsf->sig, siginfo, siguc,
209                              handler, flags, mask, restorer);
210       tst->arch.vex.guest_R1 = (Addr)&rsf->info;
211       tst->arch.vex.guest_R2 = (Addr)&rsf->sig.uc;
212    }
213    else {
214       build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
215                              handler, flags, mask, restorer);
216    }
217 
218    VG_(set_SP)(tid, sp);
219    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
220          sizeof(Addr));
221    tst->arch.vex.guest_R0  = sigNo;
222 
223    if (flags & VKI_SA_RESTORER)
224        tst->arch.vex.guest_R14 = (Addr)restorer;
225    else
226        tst->arch.vex.guest_R14
227           = (flags & VKI_SA_SIGINFO)
228             ? (Addr)&VG_(arm_linux_SUBST_FOR_rt_sigreturn)
229             : (Addr)&VG_(arm_linux_SUBST_FOR_sigreturn);
230 
231    tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
232 
233    if (VG_(clo_trace_signals))
234       VG_(message)(Vg_DebugMsg,
235                    "VG_(sigframe_create): continuing in handler with PC=%#lx\n",
236                    (Addr)handler);
237 }
238 
239 
240 /*------------------------------------------------------------*/
241 /*--- Destroying signal frames                             ---*/
242 /*------------------------------------------------------------*/
243 
244 /* EXPORTED */
VG_(sigframe_destroy)245 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
246 {
247    ThreadState *tst;
248    struct vg_sig_private *priv;
249    Addr sp;
250    UInt frame_size;
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       priv = &frame->sig.vp;
262       vg_assert(priv->magicPI == 0x31415927);
263       tst->sig_mask = frame->sig.uc.uc_sigmask;
264    } else {
265       struct sigframe *frame = (struct sigframe *)sp;
266       frame_size = sizeof(*frame);
267       priv = &frame->vp;
268       vg_assert(priv->magicPI == 0x31415927);
269       tst->sig_mask = frame->uc.uc_sigmask;
270       /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
271       tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
272       VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
273 */
274    }
275    tst->tmp_sig_mask = tst->sig_mask;
276 
277    sigNo = priv->sigNo_private;
278 
279 //ZZ     //XXX: restore regs
280 //ZZ #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
281 //ZZ    REST(r0,R0);
282 //ZZ    REST(r1,R1);
283 //ZZ    REST(r2,R2);
284 //ZZ    REST(r3,R3);
285 //ZZ    REST(r4,R4);
286 //ZZ    REST(r5,R5);
287 //ZZ    REST(r6,R6);
288 //ZZ    REST(r7,R7);
289 //ZZ    REST(r8,R8);
290 //ZZ    REST(r9,R9);
291 //ZZ    REST(r10,R10);
292 //ZZ    REST(fp,R11);
293 //ZZ    REST(ip,R12);
294 //ZZ    REST(sp,R13);
295 //ZZ    REST(lr,R14);
296 //ZZ    REST(pc,R15T);
297 //ZZ #  undef REST
298 
299    /* Uh, the next line makes all the REST() above pointless. */
300    tst->arch.vex         = priv->vex;
301 
302    tst->arch.vex_shadow1 = priv->vex_shadow1;
303    tst->arch.vex_shadow2 = priv->vex_shadow2;
304 
305    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
306              frame_size + VG_STACK_REDZONE_SZB );
307 
308    if (VG_(clo_trace_signals))
309       VG_(message)(Vg_DebugMsg,
310                    "vg_pop_signal_frame (thread %u): "
311                    "isRT=%d valid magic; PC=%#x\n",
312                    tid, has_siginfo, tst->arch.vex.guest_R15T);
313 
314    /* tell the tools */
315    VG_TRACK( post_deliver_signal, tid, sigNo );
316 }
317 
318 #endif // defined(VGP_arm_linux)
319 
320 /*--------------------------------------------------------------------*/
321 /*--- end                                     sigframe-arm-linux.c ---*/
322 /*--------------------------------------------------------------------*/
323