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-2017 Nicholas Nethercote
13 Copyright (C) 2004-2017 Paul Mackerras
15 Copyright (C) 2008-2017 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 "priv_sigframe.h"
55 /* This uses the hack of dumping the vex guest state along with both
56 shadows in the frame, and restoring it afterwards from there,
57 rather than pulling it out of the ucontext. That means that signal
58 handlers which modify the ucontext and then return, expecting their
59 modifications to take effect, will have those modifications
60 ignored. This could be fixed properly with an hour or so more
64 struct vg_sig_private
{
68 VexGuestARMState vex_shadow1
;
69 VexGuestARMState vex_shadow2
;
73 struct vki_ucontext uc
;
74 unsigned long retcode
[2];
75 struct vg_sig_private vp
;
84 static void synth_ucontext( ThreadId tid
, const vki_siginfo_t
*si
,
85 UWord trapno
, UWord err
, const vki_sigset_t
*set
,
86 struct vki_ucontext
*uc
){
88 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
89 struct vki_sigcontext
*sc
= &uc
->uc_mcontext
;
91 VG_(memset
)(uc
, 0, sizeof(*uc
));
95 uc
->uc_sigmask
= *set
;
96 uc
->uc_stack
= tst
->altstack
;
98 # define SC2(reg,REG) sc->arm_##reg = tst->arch.vex.guest_##REG
117 sc
->trap_no
= trapno
;
118 sc
->error_code
= err
;
119 sc
->fault_address
= (UInt
)si
->_sifields
._sigfault
._addr
;
123 static void build_sigframe(ThreadState
*tst
,
124 struct sigframe
*frame
,
125 const vki_siginfo_t
*siginfo
,
126 const struct vki_ucontext
*siguc
,
127 void *handler
, UInt flags
,
128 const vki_sigset_t
*mask
,
133 Int sigNo
= siginfo
->si_signo
;
134 struct vg_sig_private
*priv
= &frame
->vp
;
136 VG_TRACK( pre_mem_write
, Vg_CoreSignal
, tst
->tid
, "signal handler frame",
137 (Addr
)frame
, offsetof(struct sigframe
, vp
));
140 trapno
= siguc
->uc_mcontext
.trap_no
;
141 err
= siguc
->uc_mcontext
.error_code
;
147 synth_ucontext(tst
->tid
, siginfo
, trapno
, err
, mask
, &frame
->uc
);
149 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
,
150 (Addr
)frame
, offsetof(struct sigframe
, vp
));
152 priv
->magicPI
= 0x31415927;
153 priv
->sigNo_private
= sigNo
;
154 priv
->vex
= tst
->arch
.vex
;
155 priv
->vex_shadow1
= tst
->arch
.vex_shadow1
;
156 priv
->vex_shadow2
= tst
->arch
.vex_shadow2
;
163 void VG_(sigframe_create
)( ThreadId tid
,
165 Addr sp_top_of_frame
,
166 const vki_siginfo_t
*siginfo
,
167 const struct vki_ucontext
*siguc
,
170 const vki_sigset_t
*mask
,
173 // struct vg_sig_private *priv;
174 Addr sp
= sp_top_of_frame
;
176 Int sigNo
= siginfo
->si_signo
;
180 tst
= VG_(get_ThreadState
)(tid
);
182 size
= flags
& VKI_SA_SIGINFO
? sizeof(struct rt_sigframe
) :
183 sizeof(struct sigframe
);
186 sp
= VG_ROUNDDN(sp
, 16);
188 if (! ML_(sf_maybe_extend_stack
)(tst
, sp
, size
, flags
))
189 I_die_here
; // XXX Incorrect behavior
192 if (flags
& VKI_SA_SIGINFO
){
193 struct rt_sigframe
*rsf
= (struct rt_sigframe
*)sp
;
195 /* Track our writes to siginfo */
196 VG_TRACK( pre_mem_write
, Vg_CoreSignal
, tst
->tid
, /* VVVVV */
197 "signal handler siginfo", (Addr
)rsf
,
198 offsetof(struct rt_sigframe
, sig
));
200 VG_(memcpy
)(&rsf
->info
, siginfo
, sizeof(vki_siginfo_t
));
202 if(sigNo
== VKI_SIGILL
&& siginfo
->si_code
> 0) {
203 rsf
->info
._sifields
._sigfault
._addr
= (Addr
*) (tst
)->arch
.vex
.guest_R12
; /* IP */
205 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
, /* ^^^^^ */
206 (Addr
)rsf
, offsetof(struct rt_sigframe
, sig
));
208 build_sigframe(tst
, &rsf
->sig
, siginfo
, siguc
,
209 handler
, flags
, mask
, restorer
);
210 tst
->arch
.vex
.guest_R1
= (Addr
)&rsf
->info
;
211 tst
->arch
.vex
.guest_R2
= (Addr
)&rsf
->sig
.uc
;
214 build_sigframe(tst
, (struct sigframe
*)sp
, siginfo
, siguc
,
215 handler
, flags
, mask
, restorer
);
218 VG_(set_SP
)(tid
, sp
);
219 VG_TRACK( post_reg_write
, Vg_CoreSignal
, tid
, VG_O_STACK_PTR
,
221 tst
->arch
.vex
.guest_R0
= sigNo
;
223 if (flags
& VKI_SA_RESTORER
)
224 tst
->arch
.vex
.guest_R14
= (Addr
)restorer
;
226 tst
->arch
.vex
.guest_R14
227 = (flags
& VKI_SA_SIGINFO
)
228 ? (Addr
)&VG_(arm_linux_SUBST_FOR_rt_sigreturn
)
229 : (Addr
)&VG_(arm_linux_SUBST_FOR_sigreturn
);
231 tst
->arch
.vex
.guest_R15T
= (Addr
) handler
; /* R15 == PC */
233 if (VG_(clo_trace_signals
))
234 VG_(message
)(Vg_DebugMsg
,
235 "VG_(sigframe_create): continuing in handler with PC=%#lx\n",
240 /*------------------------------------------------------------*/
241 /*--- Destroying signal frames ---*/
242 /*------------------------------------------------------------*/
245 void VG_(sigframe_destroy
)( ThreadId tid
, Bool isRT
)
248 struct vg_sig_private
*priv
;
252 Bool has_siginfo
= isRT
;
254 vg_assert(VG_(is_valid_tid
)(tid
));
255 tst
= VG_(get_ThreadState
)(tid
);
256 sp
= tst
->arch
.vex
.guest_R13
;
259 struct rt_sigframe
*frame
= (struct rt_sigframe
*)sp
;
260 frame_size
= sizeof(*frame
);
261 priv
= &frame
->sig
.vp
;
262 vg_assert(priv
->magicPI
== 0x31415927);
263 tst
->sig_mask
= frame
->sig
.uc
.uc_sigmask
;
265 struct sigframe
*frame
= (struct sigframe
*)sp
;
266 frame_size
= sizeof(*frame
);
268 vg_assert(priv
->magicPI
== 0x31415927);
269 tst
->sig_mask
= frame
->uc
.uc_sigmask
;
270 /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
271 tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
272 VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
275 tst
->tmp_sig_mask
= tst
->sig_mask
;
277 sigNo
= priv
->sigNo_private
;
279 //ZZ //XXX: restore regs
280 //ZZ # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
299 /* Uh, the next line makes all the REST() above pointless. */
300 tst
->arch
.vex
= priv
->vex
;
302 tst
->arch
.vex_shadow1
= priv
->vex_shadow1
;
303 tst
->arch
.vex_shadow2
= priv
->vex_shadow2
;
305 VG_TRACK( die_mem_stack_signal
, sp
- VG_STACK_REDZONE_SZB
,
306 frame_size
+ VG_STACK_REDZONE_SZB
);
308 if (VG_(clo_trace_signals
))
309 VG_(message
)(Vg_DebugMsg
,
310 "vg_pop_signal_frame (thread %u): "
311 "isRT=%d valid magic; PC=%#x\n",
312 tid
, has_siginfo
, tst
->arch
.vex
.guest_R15T
);
315 VG_TRACK( post_deliver_signal
, tid
, sigNo
);
318 #endif // defined(VGP_arm_linux)
320 /*--------------------------------------------------------------------*/
321 /*--- end sigframe-arm-linux.c ---*/
322 /*--------------------------------------------------------------------*/