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_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)
56 struct vg_sig_private {
59 VexGuestARMState vex_shadow1;
60 VexGuestARMState vex_shadow2;
64 struct vki_ucontext uc;
65 unsigned long retcode[2];
66 struct vg_sig_private vp;
74 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
76 ThreadId tid = tst->tid;
77 NSegment const* stackseg = NULL;
79 if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
80 stackseg = VG_(am_find_nsegment)(addr);
82 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
83 addr, stackseg->start, stackseg->end);
86 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
89 "Can't extend stack to %#lx during signal delivery for thread %d:",
92 VG_(message)(Vg_UserMsg, " no stack segment");
94 VG_(message)(Vg_UserMsg, " too small or bad protection modes");
96 /* set SIGSEGV to default handler */
97 VG_(set_default_handler)(VKI_SIGSEGV);
98 VG_(synth_fault_mapping)(tid, addr);
100 /* The whole process should be about to die, since the default
101 action of SIGSEGV to kill the whole process. */
105 /* For tracking memory events, indicate the entire frame has been
107 VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
108 size + VG_STACK_REDZONE_SZB, tid );
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){
117 ThreadState *tst = VG_(get_ThreadState)(tid);
118 struct vki_sigcontext *sc = &uc->uc_mcontext;
120 VG_(memset)(uc, 0, sizeof(*uc));
124 uc->uc_sigmask = *set;
125 uc->uc_stack = tst->altstack;
127 # define SC2(reg,REG) sc->arm_##reg = tst->arch.vex.guest_##REG
146 sc->trap_no = trapno;
147 sc->error_code = err;
148 sc->fault_address = (UInt)si->_sifields._sigfault._addr;
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,
162 Int sigNo = siginfo->si_signo;
163 struct vg_sig_private *priv = &frame->vp;
165 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
166 (Addr)frame, offsetof(struct sigframe, vp));
169 trapno = siguc->uc_mcontext.trap_no;
170 err = siguc->uc_mcontext.error_code;
176 synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
178 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
179 (Addr)frame, offsetof(struct sigframe, vp));
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;
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,
197 const vki_sigset_t *mask,
200 // struct vg_sig_private *priv;
201 Addr sp = sp_top_of_frame;
203 Int sigNo = siginfo->si_signo;
207 tst = VG_(get_ThreadState)(tid);
209 size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
210 sizeof(struct sigframe);
213 sp = VG_ROUNDDN(sp, 16);
215 if(!extend(tst, sp, size))
216 I_die_here; // XXX Incorrect behavior
219 if (flags & VKI_SA_SIGINFO){
220 struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
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));
227 VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
229 if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
230 rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
232 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
233 (Addr)rsf, offsetof(struct rt_sigframe, sig));
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;
241 build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
242 handler, flags, mask, restorer);
245 VG_(set_SP)(tid, sp);
246 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
248 tst->arch.vex.guest_R0 = sigNo;
250 if (flags & VKI_SA_RESTORER)
251 tst->arch.vex.guest_R14 = (Addr) restorer;
253 tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
257 /*------------------------------------------------------------*/
258 /*--- Destroying signal frames ---*/
259 /*------------------------------------------------------------*/
262 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
265 struct vg_sig_private *priv;
268 struct vki_sigcontext *mc;
270 Bool has_siginfo = isRT;
272 vg_assert(VG_(is_valid_tid)(tid));
273 tst = VG_(get_ThreadState)(tid);
274 sp = tst->arch.vex.guest_R13;
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;
284 struct sigframe *frame = (struct sigframe *)sp;
285 frame_size = sizeof(*frame);
286 mc = &frame->uc.uc_mcontext;
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]);
295 tst->tmp_sig_mask = tst->sig_mask;
297 sigNo = priv->sigNo_private;
300 # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
319 tst->arch.vex_shadow1 = priv->vex_shadow1;
320 tst->arch.vex_shadow2 = priv->vex_shadow2;
322 VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
323 frame_size + VG_STACK_REDZONE_SZB );
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);
332 VG_TRACK( post_deliver_signal, tid, sigNo );
335 #endif // defined(VGP_arm_linux)
337 /*--------------------------------------------------------------------*/
338 /*--- end sigframe-arm-linux.c ---*/
339 /*--------------------------------------------------------------------*/