• 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-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 
65 struct vg_sig_private {
66    UInt magicPI;
67    UInt sigNo_private;
68    VexGuestARMState vex;
69    VexGuestARMState vex_shadow1;
70    VexGuestARMState vex_shadow2;
71 };
72 
73 struct sigframe {
74    struct vki_ucontext uc;
75    unsigned long retcode[2];
76    struct vg_sig_private vp;
77 };
78 
79 struct rt_sigframe {
80    vki_siginfo_t info;
81    struct sigframe sig;
82 };
83 
extend(ThreadState * tst,Addr addr,SizeT size)84 static 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 
synth_ucontext(ThreadId tid,const vki_siginfo_t * si,UWord trapno,UWord err,const vki_sigset_t * set,struct vki_ucontext * uc)123 static 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 
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)162 static 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 */
VG_(sigframe_create)202 void 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 */
VG_(sigframe_destroy)278 void 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