2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-arm-linux.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2010 Nicholas Nethercote
13 Copyright (C) 2004-2010 Paul Mackerras
15 Copyright (C) 2008-2010 Evan Geller
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.
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.
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
33 The GNU General Public License is contained in the file COPYING.
36 #if defined(VGP_arm_linux)
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 "pub_core_transtab.h" // VG_(discard_translations)
55 struct vg_sig_private {
58 VexGuestARMState vex_shadow1;
59 VexGuestARMState vex_shadow2;
63 struct vki_ucontext uc;
64 unsigned long retcode[2];
65 struct vg_sig_private vp;
73 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
75 ThreadId tid = tst->tid;
76 NSegment const* stackseg = NULL;
78 if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
79 stackseg = VG_(am_find_nsegment)(addr);
81 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
82 addr, stackseg->start, stackseg->end);
85 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
88 "Can't extend stack to %#lx during signal delivery for thread %d:",
91 VG_(message)(Vg_UserMsg, " no stack segment");
93 VG_(message)(Vg_UserMsg, " too small or bad protection modes");
95 /* set SIGSEGV to default handler */
96 VG_(set_default_handler)(VKI_SIGSEGV);
97 VG_(synth_fault_mapping)(tid, addr);
99 /* The whole process should be about to die, since the default
100 action of SIGSEGV to kill the whole process. */
104 /* For tracking memory events, indicate the entire frame has been
106 VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
107 size + VG_STACK_REDZONE_SZB, tid );
112 static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
113 UWord trapno, UWord err, const vki_sigset_t *set,
114 struct vki_ucontext *uc){
116 ThreadState *tst = VG_(get_ThreadState)(tid);
117 struct vki_sigcontext *sc = &uc->uc_mcontext;
119 VG_(memset)(uc, 0, sizeof(*uc));
123 uc->uc_sigmask = *set;
124 uc->uc_stack = tst->altstack;
126 # define SC2(reg,REG) sc->arm_##reg = tst->arch.vex.guest_##REG
145 sc->trap_no = trapno;
146 sc->error_code = err;
147 sc->fault_address = (UInt)si->_sifields._sigfault._addr;
151 static void build_sigframe(ThreadState *tst,
152 struct sigframe *frame,
153 const vki_siginfo_t *siginfo,
154 const struct vki_ucontext *siguc,
155 void *handler, UInt flags,
156 const vki_sigset_t *mask,
161 Int sigNo = siginfo->si_signo;
162 struct vg_sig_private *priv = &frame->vp;
164 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
165 (Addr)frame, offsetof(struct sigframe, vp));
168 trapno = siguc->uc_mcontext.trap_no;
169 err = siguc->uc_mcontext.error_code;
175 synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
177 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
178 (Addr)frame, offsetof(struct sigframe, vp));
180 priv->magicPI = 0x31415927;
181 priv->sigNo_private = sigNo;
182 priv->vex_shadow1 = tst->arch.vex_shadow1;
183 priv->vex_shadow2 = tst->arch.vex_shadow2;
190 void VG_(sigframe_create)( ThreadId tid,
191 Addr sp_top_of_frame,
192 const vki_siginfo_t *siginfo,
193 const struct vki_ucontext *siguc,
196 const vki_sigset_t *mask,
199 // struct vg_sig_private *priv;
200 Addr sp = sp_top_of_frame;
202 Int sigNo = siginfo->si_signo;
206 tst = VG_(get_ThreadState)(tid);
208 size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
209 sizeof(struct sigframe);
212 sp = VG_ROUNDDN(sp, 16);
214 if(!extend(tst, sp, size))
215 I_die_here; // XXX Incorrect behavior
218 if (flags & VKI_SA_SIGINFO){
219 struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
221 /* Track our writes to siginfo */
222 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, /* VVVVV */
223 "signal handler siginfo", (Addr)rsf,
224 offsetof(struct rt_sigframe, sig));
226 VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
228 if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
229 rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
231 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
232 (Addr)rsf, offsetof(struct rt_sigframe, sig));
234 build_sigframe(tst, &rsf->sig, siginfo, siguc,
235 handler, flags, mask, restorer);
236 tst->arch.vex.guest_R1 = (Addr)&rsf->info;
237 tst->arch.vex.guest_R2 = (Addr)&rsf->sig.uc;
240 build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
241 handler, flags, mask, restorer);
244 VG_(set_SP)(tid, sp);
245 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
247 tst->arch.vex.guest_R0 = sigNo;
249 if(flags & VKI_SA_RESTORER)
250 tst->arch.vex.guest_R14 = (Addr) restorer;
252 tst->arch.vex.guest_R15 = (Addr) handler; /* R15 == PC */
256 /*------------------------------------------------------------*/
257 /*--- Destroying signal frames ---*/
258 /*------------------------------------------------------------*/
261 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
264 struct vg_sig_private *priv;
267 struct vki_sigcontext *mc;
269 Bool has_siginfo = isRT;
271 vg_assert(VG_(is_valid_tid)(tid));
272 tst = VG_(get_ThreadState)(tid);
273 sp = tst->arch.vex.guest_R13;
276 struct rt_sigframe *frame = (struct rt_sigframe *)sp;
277 frame_size = sizeof(*frame);
278 mc = &frame->sig.uc.uc_mcontext;
279 priv = &frame->sig.vp;
280 vg_assert(priv->magicPI == 0x31415927);
281 tst->sig_mask = frame->sig.uc.uc_sigmask;
283 struct sigframe *frame = (struct sigframe *)sp;
284 frame_size = sizeof(*frame);
285 mc = &frame->uc.uc_mcontext;
287 vg_assert(priv->magicPI == 0x31415927);
288 tst->sig_mask = frame->uc.uc_sigmask;
289 /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
290 tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
291 VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
294 tst->tmp_sig_mask = tst->sig_mask;
296 sigNo = priv->sigNo_private;
299 # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
318 tst->arch.vex_shadow1 = priv->vex_shadow1;
319 tst->arch.vex_shadow2 = priv->vex_shadow2;
321 VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
322 frame_size + VG_STACK_REDZONE_SZB );
324 if (VG_(clo_trace_signals))
325 VG_(message)(Vg_DebugMsg,
326 "vg_pop_signal_frame (thread %d): isRT=%d valid magic; PC=%#x",
327 tid, has_siginfo, tst->arch.vex.guest_R15);
330 VG_TRACK( post_deliver_signal, tid, sigNo );
333 #endif // defined(VGP_arm_linux)
335 /*--------------------------------------------------------------------*/
336 /*--- end sigframe-arm-linux.c ---*/
337 /*--------------------------------------------------------------------*/