]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_sigframe/sigframe-arm-linux.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_sigframe / sigframe-arm-linux.c
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-2010 Nicholas Nethercote
12       njn@valgrind.org
13    Copyright (C) 2004-2010 Paul Mackerras
14       paulus@samba.org
15    Copyright (C) 2008-2010 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 struct vg_sig_private {
57    UInt magicPI;
58    UInt sigNo_private;
59    VexGuestARMState vex_shadow1;
60    VexGuestARMState vex_shadow2;
61 };
62
63 struct sigframe {
64    struct vki_ucontext uc;
65    unsigned long retcode[2];
66    struct vg_sig_private vp;
67 };
68
69 struct rt_sigframe {
70    vki_siginfo_t info;
71    struct sigframe sig;
72 };
73
74 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
75 {
76    ThreadId        tid = tst->tid;
77    NSegment const* stackseg = NULL;
78
79    if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
80       stackseg = VG_(am_find_nsegment)(addr);
81       if (0 && stackseg)
82     VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
83            addr, stackseg->start, stackseg->end);
84    }
85
86    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
87       VG_(message)(
88          Vg_UserMsg,
89          "Can't extend stack to %#lx during signal delivery for thread %d:",
90          addr, tid);
91       if (stackseg == NULL)
92          VG_(message)(Vg_UserMsg, "  no stack segment");
93       else
94          VG_(message)(Vg_UserMsg, "  too small or bad protection modes");
95
96       /* set SIGSEGV to default handler */
97       VG_(set_default_handler)(VKI_SIGSEGV);
98       VG_(synth_fault_mapping)(tid, addr);
99
100       /* The whole process should be about to die, since the default
101     action of SIGSEGV to kill the whole process. */
102       return False;
103    }
104
105    /* For tracking memory events, indicate the entire frame has been
106       allocated. */
107    VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
108              size + VG_STACK_REDZONE_SZB, tid );
109
110    return True;
111 }
112
113 static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
114                     UWord trapno, UWord err, const vki_sigset_t *set, 
115                     struct vki_ucontext *uc){
116
117    ThreadState *tst = VG_(get_ThreadState)(tid);
118    struct vki_sigcontext *sc = &uc->uc_mcontext;
119
120    VG_(memset)(uc, 0, sizeof(*uc));
121
122    uc->uc_flags = 0;
123    uc->uc_link = 0;
124    uc->uc_sigmask = *set;
125    uc->uc_stack = tst->altstack;
126
127 #  define SC2(reg,REG)  sc->arm_##reg = tst->arch.vex.guest_##REG
128    SC2(r0,R0);
129    SC2(r1,R1);
130    SC2(r2,R2);
131    SC2(r3,R3);
132    SC2(r4,R4);
133    SC2(r5,R5);
134    SC2(r6,R6);
135    SC2(r7,R7);
136    SC2(r8,R8);
137    SC2(r9,R9);
138    SC2(r10,R10);
139    SC2(fp,R11);
140    SC2(ip,R12);
141    SC2(sp,R13);
142    SC2(lr,R14);
143    SC2(pc,R15T);
144 #  undef SC2
145
146    sc->trap_no = trapno;
147    sc->error_code = err;
148    sc->fault_address = (UInt)si->_sifields._sigfault._addr;
149 }
150
151
152 static void build_sigframe(ThreadState *tst,
153             struct sigframe *frame,
154             const vki_siginfo_t *siginfo,
155             const struct vki_ucontext *siguc,
156             void *handler, UInt flags,
157             const vki_sigset_t *mask,
158             void *restorer){
159
160    UWord trapno;
161    UWord err;
162    Int  sigNo = siginfo->si_signo;
163    struct vg_sig_private *priv = &frame->vp;
164
165    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
166          (Addr)frame, offsetof(struct sigframe, vp));
167
168    if(siguc) {
169       trapno = siguc->uc_mcontext.trap_no;
170       err = siguc->uc_mcontext.error_code;
171    } else {
172       trapno = 0;
173       err = 0;
174    }
175
176    synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
177
178    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
179          (Addr)frame, offsetof(struct sigframe, vp));
180
181    priv->magicPI = 0x31415927;
182    priv->sigNo_private = sigNo;
183    priv->vex_shadow1 = tst->arch.vex_shadow1;
184    priv->vex_shadow2 = tst->arch.vex_shadow2;
185
186 }
187
188
189
190 /* EXPORTED */
191 void VG_(sigframe_create)( ThreadId tid, 
192                            Addr sp_top_of_frame,
193                            const vki_siginfo_t *siginfo,
194                            const struct vki_ucontext *siguc,
195                            void *handler, 
196                            UInt flags,
197                            const vki_sigset_t *mask,
198                            void *restorer )
199 {
200 //   struct vg_sig_private *priv;
201    Addr sp = sp_top_of_frame;
202    ThreadState *tst;
203    Int sigNo = siginfo->si_signo;
204 //   Addr faultaddr;
205    UInt size;
206
207    tst = VG_(get_ThreadState)(tid);
208
209    size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
210       sizeof(struct sigframe);
211
212    sp -= size;
213    sp = VG_ROUNDDN(sp, 16);
214
215    if(!extend(tst, sp, size))
216       I_die_here; // XXX Incorrect behavior
217
218
219    if (flags & VKI_SA_SIGINFO){
220       struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
221       
222       /* Track our writes to siginfo */
223       VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
224             "signal handler siginfo", (Addr)rsf, 
225             offsetof(struct rt_sigframe, sig));
226
227       VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
228
229       if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
230          rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
231       }
232       VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
233             (Addr)rsf, offsetof(struct rt_sigframe, sig));
234
235       build_sigframe(tst, &rsf->sig, siginfo, siguc,
236                              handler, flags, mask, restorer);
237       tst->arch.vex.guest_R1 = (Addr)&rsf->info;
238       tst->arch.vex.guest_R2 = (Addr)&rsf->sig.uc;
239    }
240    else {
241       build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
242                              handler, flags, mask, restorer);
243    }
244
245    VG_(set_SP)(tid, sp);
246    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
247          sizeof(Addr));
248    tst->arch.vex.guest_R0  = sigNo; 
249
250    if (flags & VKI_SA_RESTORER)
251        tst->arch.vex.guest_R14 = (Addr) restorer; 
252
253    tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
254 }
255
256
257 /*------------------------------------------------------------*/
258 /*--- Destroying signal frames                             ---*/
259 /*------------------------------------------------------------*/
260
261 /* EXPORTED */
262 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
263 {
264    ThreadState *tst;
265    struct vg_sig_private *priv;
266    Addr sp;
267    UInt frame_size;
268    struct vki_sigcontext *mc;
269    Int sigNo;
270    Bool has_siginfo = isRT;
271
272    vg_assert(VG_(is_valid_tid)(tid));
273    tst = VG_(get_ThreadState)(tid);
274    sp = tst->arch.vex.guest_R13;
275
276    if (has_siginfo) {
277       struct rt_sigframe *frame = (struct rt_sigframe *)sp;
278       frame_size = sizeof(*frame);
279       mc = &frame->sig.uc.uc_mcontext;
280       priv = &frame->sig.vp;
281       vg_assert(priv->magicPI == 0x31415927);
282       tst->sig_mask = frame->sig.uc.uc_sigmask;
283    } else {
284       struct sigframe *frame = (struct sigframe *)sp;
285       frame_size = sizeof(*frame);
286       mc = &frame->uc.uc_mcontext;
287       priv = &frame->vp;
288       vg_assert(priv->magicPI == 0x31415927);
289       tst->sig_mask = frame->uc.uc_sigmask;
290       /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
291       tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
292       VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
293 */
294    }
295    tst->tmp_sig_mask = tst->sig_mask;
296
297    sigNo = priv->sigNo_private;
298
299     //XXX: restore regs
300 #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
301    REST(r0,R0);
302    REST(r1,R1);
303    REST(r2,R2);
304    REST(r3,R3);
305    REST(r4,R4);
306    REST(r5,R5);
307    REST(r6,R6);
308    REST(r7,R7);
309    REST(r8,R8);
310    REST(r9,R9);
311    REST(r10,R10);
312    REST(fp,R11);
313    REST(ip,R12);
314    REST(sp,R13);
315    REST(lr,R14);
316    REST(pc,R15T);
317 #  undef REST
318
319    tst->arch.vex_shadow1 = priv->vex_shadow1;
320    tst->arch.vex_shadow2 = priv->vex_shadow2;
321
322    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
323              frame_size + VG_STACK_REDZONE_SZB );
324              
325    if (VG_(clo_trace_signals))
326       VG_(message)(Vg_DebugMsg,
327                    "vg_pop_signal_frame (thread %d): "
328                    "isRT=%d valid magic; PC=%#x",
329                    tid, has_siginfo, tst->arch.vex.guest_R15T);
330
331    /* tell the tools */
332    VG_TRACK( post_deliver_signal, tid, sigNo );
333 }
334
335 #endif // defined(VGP_arm_linux)
336
337 /*--------------------------------------------------------------------*/
338 /*--- end                                     sigframe-arm-linux.c ---*/
339 /*--------------------------------------------------------------------*/