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-2013 Nicholas Nethercote
13 Copyright (C) 2004-2013 Paul Mackerras
15 Copyright (C) 2008-2013 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 /* 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
65 struct vg_sig_private
{
69 VexGuestARMState vex_shadow1
;
70 VexGuestARMState vex_shadow2
;
74 struct vki_ucontext uc
;
75 unsigned long retcode
[2];
76 struct vg_sig_private vp
;
84 static Bool
extend ( ThreadState
*tst
, Addr addr
, SizeT size
)
86 ThreadId tid
= tst
->tid
;
87 NSegment
const* stackseg
= NULL
;
89 if (VG_(extend_stack
)(addr
, tst
->client_stack_szB
)) {
90 stackseg
= VG_(am_find_nsegment
)(addr
);
92 VG_(printf
)("frame=%#lx seg=%#lx-%#lx\n",
93 addr
, stackseg
->start
, stackseg
->end
);
96 if (stackseg
== NULL
|| !stackseg
->hasR
|| !stackseg
->hasW
) {
99 "Can't extend stack to %#lx during signal delivery for thread %d:",
101 if (stackseg
== NULL
)
102 VG_(message
)(Vg_UserMsg
, " no stack segment");
104 VG_(message
)(Vg_UserMsg
, " too small or bad protection modes");
106 /* set SIGSEGV to default handler */
107 VG_(set_default_handler
)(VKI_SIGSEGV
);
108 VG_(synth_fault_mapping
)(tid
, addr
);
110 /* The whole process should be about to die, since the default
111 action of SIGSEGV to kill the whole process. */
115 /* For tracking memory events, indicate the entire frame has been
117 VG_TRACK( new_mem_stack_signal
, addr
- VG_STACK_REDZONE_SZB
,
118 size
+ VG_STACK_REDZONE_SZB
, tid
);
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
){
127 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
128 struct vki_sigcontext
*sc
= &uc
->uc_mcontext
;
130 VG_(memset
)(uc
, 0, sizeof(*uc
));
134 uc
->uc_sigmask
= *set
;
135 uc
->uc_stack
= tst
->altstack
;
137 # define SC2(reg,REG) sc->arm_##reg = tst->arch.vex.guest_##REG
156 sc
->trap_no
= trapno
;
157 sc
->error_code
= err
;
158 sc
->fault_address
= (UInt
)si
->_sifields
._sigfault
._addr
;
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
,
172 Int sigNo
= siginfo
->si_signo
;
173 struct vg_sig_private
*priv
= &frame
->vp
;
175 VG_TRACK( pre_mem_write
, Vg_CoreSignal
, tst
->tid
, "signal handler frame",
176 (Addr
)frame
, offsetof(struct sigframe
, vp
));
179 trapno
= siguc
->uc_mcontext
.trap_no
;
180 err
= siguc
->uc_mcontext
.error_code
;
186 synth_ucontext(tst
->tid
, siginfo
, trapno
, err
, mask
, &frame
->uc
);
188 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
,
189 (Addr
)frame
, offsetof(struct sigframe
, vp
));
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
;
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
,
208 const vki_sigset_t
*mask
,
211 // struct vg_sig_private *priv;
212 Addr sp
= sp_top_of_frame
;
214 Int sigNo
= siginfo
->si_signo
;
218 tst
= VG_(get_ThreadState
)(tid
);
220 size
= flags
& VKI_SA_SIGINFO
? sizeof(struct rt_sigframe
) :
221 sizeof(struct sigframe
);
224 sp
= VG_ROUNDDN(sp
, 16);
226 if(!extend(tst
, sp
, size
))
227 I_die_here
; // XXX Incorrect behavior
230 if (flags
& VKI_SA_SIGINFO
){
231 struct rt_sigframe
*rsf
= (struct rt_sigframe
*)sp
;
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
));
238 VG_(memcpy
)(&rsf
->info
, siginfo
, sizeof(vki_siginfo_t
));
240 if(sigNo
== VKI_SIGILL
&& siginfo
->si_code
> 0) {
241 rsf
->info
._sifields
._sigfault
._addr
= (Addr
*) (tst
)->arch
.vex
.guest_R12
; /* IP */
243 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
, /* ^^^^^ */
244 (Addr
)rsf
, offsetof(struct rt_sigframe
, sig
));
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
;
252 build_sigframe(tst
, (struct sigframe
*)sp
, siginfo
, siguc
,
253 handler
, flags
, mask
, restorer
);
256 VG_(set_SP
)(tid
, sp
);
257 VG_TRACK( post_reg_write
, Vg_CoreSignal
, tid
, VG_O_STACK_PTR
,
259 tst
->arch
.vex
.guest_R0
= sigNo
;
261 if (flags
& VKI_SA_RESTORER
)
262 tst
->arch
.vex
.guest_R14
= (Addr
)restorer
;
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
);
269 tst
->arch
.vex
.guest_R15T
= (Addr
) handler
; /* R15 == PC */
273 /*------------------------------------------------------------*/
274 /*--- Destroying signal frames ---*/
275 /*------------------------------------------------------------*/
278 void VG_(sigframe_destroy
)( ThreadId tid
, Bool isRT
)
281 struct vg_sig_private
*priv
;
284 struct vki_sigcontext
*mc
;
286 Bool has_siginfo
= isRT
;
288 vg_assert(VG_(is_valid_tid
)(tid
));
289 tst
= VG_(get_ThreadState
)(tid
);
290 sp
= tst
->arch
.vex
.guest_R13
;
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
;
300 struct sigframe
*frame
= (struct sigframe
*)sp
;
301 frame_size
= sizeof(*frame
);
302 mc
= &frame
->uc
.uc_mcontext
;
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]);
311 tst
->tmp_sig_mask
= tst
->sig_mask
;
313 sigNo
= priv
->sigNo_private
;
316 # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
335 /* Uh, the next line makes all the REST() above pointless. */
336 tst
->arch
.vex
= priv
->vex
;
338 tst
->arch
.vex_shadow1
= priv
->vex_shadow1
;
339 tst
->arch
.vex_shadow2
= priv
->vex_shadow2
;
341 VG_TRACK( die_mem_stack_signal
, sp
- VG_STACK_REDZONE_SZB
,
342 frame_size
+ VG_STACK_REDZONE_SZB
);
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
);
351 VG_TRACK( post_deliver_signal
, tid
, sigNo
);
354 #endif // defined(VGP_arm_linux)
356 /*--------------------------------------------------------------------*/
357 /*--- end sigframe-arm-linux.c ---*/
358 /*--------------------------------------------------------------------*/