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, see <http://www.gnu.org/licenses/>.
31 The GNU General Public License is contained in the file COPYING.
34 #if defined(VGP_arm_linux)
36 #include "pub_core_basics.h"
37 #include "pub_core_vki.h"
38 #include "pub_core_vkiscnums.h"
39 #include "pub_core_threadstate.h"
40 #include "pub_core_aspacemgr.h"
41 #include "pub_core_libcbase.h"
42 #include "pub_core_libcassert.h"
43 #include "pub_core_libcprint.h"
44 #include "pub_core_machine.h"
45 #include "pub_core_options.h"
46 #include "pub_core_sigframe.h"
47 #include "pub_core_signals.h"
48 #include "pub_core_tooliface.h"
49 #include "pub_core_trampoline.h"
50 #include "priv_sigframe.h"
53 /* This uses the hack of dumping the vex guest state along with both
54 shadows in the frame, and restoring it afterwards from there,
55 rather than pulling it out of the ucontext. Then, integer
56 registers, the SP and the PC are restored from the ucontext. That
57 means that signal handlers which modify floating point registers or
58 in general any register state apart from R0 to R15 in the ucontext
59 and then return, expecting their modifications to take effect, will
60 have those modifications ignored. */
62 struct vg_sig_private
{
66 VexGuestARMState vex_shadow1
;
67 VexGuestARMState vex_shadow2
;
71 struct vki_ucontext uc
;
72 unsigned long retcode
[2];
73 struct vg_sig_private vp
;
82 static void synth_ucontext( ThreadId tid
, const vki_siginfo_t
*si
,
83 UWord trapno
, UWord err
, const vki_sigset_t
*set
,
84 struct vki_ucontext
*uc
){
86 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
87 struct vki_sigcontext
*sc
= &uc
->uc_mcontext
;
89 VG_(memset
)(uc
, 0, sizeof(*uc
));
93 uc
->uc_sigmask
= *set
;
94 uc
->uc_stack
= tst
->altstack
;
96 # define TO_CTX(reg,REG) sc->arm_##reg = tst->arch.vex.guest_##REG
97 TO_CTX(r0
,R0
); TO_CTX(r1
,R1
); TO_CTX(r2
,R2
); TO_CTX(r3
,R3
);
98 TO_CTX(r4
,R4
); TO_CTX(r5
,R5
); TO_CTX(r6
,R6
); TO_CTX(r7
,R7
);
99 TO_CTX(r8
,R8
); TO_CTX(r9
,R9
); TO_CTX(r10
,R10
); TO_CTX(fp
,R11
);
100 TO_CTX(ip
,R12
); TO_CTX(sp
,R13
); TO_CTX(lr
,R14
); TO_CTX(pc
,R15T
);
103 sc
->trap_no
= trapno
;
104 sc
->error_code
= err
;
105 sc
->fault_address
= (UInt
)si
->_sifields
._sigfault
._addr
;
109 static void build_sigframe(ThreadState
*tst
,
110 struct sigframe
*frame
,
111 const vki_siginfo_t
*siginfo
,
112 const struct vki_ucontext
*siguc
,
113 void *handler
, UInt flags
,
114 const vki_sigset_t
*mask
,
119 Int sigNo
= siginfo
->si_signo
;
120 struct vg_sig_private
*priv
= &frame
->vp
;
122 VG_TRACK( pre_mem_write
, Vg_CoreSignal
, tst
->tid
, "signal handler frame",
123 (Addr
)frame
, offsetof(struct sigframe
, vp
));
126 trapno
= siguc
->uc_mcontext
.trap_no
;
127 err
= siguc
->uc_mcontext
.error_code
;
133 synth_ucontext(tst
->tid
, siginfo
, trapno
, err
, mask
, &frame
->uc
);
135 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
,
136 (Addr
)frame
, offsetof(struct sigframe
, vp
));
138 priv
->magicPI
= 0x31415927;
139 priv
->sigNo_private
= sigNo
;
140 priv
->vex
= tst
->arch
.vex
;
141 priv
->vex_shadow1
= tst
->arch
.vex_shadow1
;
142 priv
->vex_shadow2
= tst
->arch
.vex_shadow2
;
149 void VG_(sigframe_create
)( ThreadId tid
,
151 Addr sp_top_of_frame
,
152 const vki_siginfo_t
*siginfo
,
153 const struct vki_ucontext
*siguc
,
156 const vki_sigset_t
*mask
,
159 Addr sp
= sp_top_of_frame
;
161 Int sigNo
= siginfo
->si_signo
;
164 tst
= VG_(get_ThreadState
)(tid
);
166 size
= flags
& VKI_SA_SIGINFO
? sizeof(struct rt_sigframe
) :
167 sizeof(struct sigframe
);
170 sp
= VG_ROUNDDN(sp
, 16);
172 if (! ML_(sf_maybe_extend_stack
)(tst
, sp
, size
, flags
))
173 I_die_here
; // XXX Incorrect behavior
176 if (flags
& VKI_SA_SIGINFO
){
177 struct rt_sigframe
*rsf
= (struct rt_sigframe
*)sp
;
179 /* Track our writes to siginfo */
180 VG_TRACK( pre_mem_write
, Vg_CoreSignal
, tst
->tid
, /* VVVVV */
181 "signal handler siginfo", (Addr
)rsf
,
182 offsetof(struct rt_sigframe
, sig
));
184 VG_(memcpy
)(&rsf
->info
, siginfo
, sizeof(vki_siginfo_t
));
186 if(sigNo
== VKI_SIGILL
&& siginfo
->si_code
> 0) {
187 rsf
->info
._sifields
._sigfault
._addr
188 = (Addr
*) (tst
)->arch
.vex
.guest_R12
; /* IP */
190 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
, /* ^^^^^ */
191 (Addr
)rsf
, offsetof(struct rt_sigframe
, sig
));
193 build_sigframe(tst
, &rsf
->sig
, siginfo
, siguc
,
194 handler
, flags
, mask
, restorer
);
195 tst
->arch
.vex
.guest_R1
= (Addr
)&rsf
->info
;
196 tst
->arch
.vex
.guest_R2
= (Addr
)&rsf
->sig
.uc
;
199 build_sigframe(tst
, (struct sigframe
*)sp
, siginfo
, siguc
,
200 handler
, flags
, mask
, restorer
);
203 VG_(set_SP
)(tid
, sp
);
204 VG_TRACK( post_reg_write
, Vg_CoreSignal
, tid
, VG_O_STACK_PTR
,
206 tst
->arch
.vex
.guest_R0
= sigNo
;
208 if (flags
& VKI_SA_RESTORER
)
209 tst
->arch
.vex
.guest_R14
= (Addr
)restorer
;
211 tst
->arch
.vex
.guest_R14
212 = (flags
& VKI_SA_SIGINFO
)
213 ? (Addr
)&VG_(arm_linux_SUBST_FOR_rt_sigreturn
)
214 : (Addr
)&VG_(arm_linux_SUBST_FOR_sigreturn
);
216 tst
->arch
.vex
.guest_R15T
= (Addr
) handler
; /* R15 == PC */
218 /* Regardless of what the state of ITSTATE was, it makes no sense
219 to enter the handler with the first 1-4 instructions possibly
220 predicated as "don't execute". So set ITSTATE to [AL,AL,AL,AL]
221 before entering the handler. */
222 tst
->arch
.vex
.guest_ITSTATE
= 0;
224 if (VG_(clo_trace_signals
))
225 VG_(message
)(Vg_DebugMsg
,
226 "VG_(sigframe_create): continuing in handler with PC=%#lx\n",
231 /*------------------------------------------------------------*/
232 /*--- Destroying signal frames ---*/
233 /*------------------------------------------------------------*/
236 void VG_(sigframe_destroy
)( ThreadId tid
, Bool isRT
)
239 struct vg_sig_private
*priv
;
243 Bool has_siginfo
= isRT
;
245 struct rt_sigframe
*rt_frame
= NULL
;
247 vg_assert(VG_(is_valid_tid
)(tid
));
248 tst
= VG_(get_ThreadState
)(tid
);
249 sp
= tst
->arch
.vex
.guest_R13
;
252 struct rt_sigframe
*frame
= (struct rt_sigframe
*)sp
;
253 frame_size
= sizeof(*frame
);
254 priv
= &frame
->sig
.vp
;
255 vg_assert(priv
->magicPI
== 0x31415927);
256 tst
->sig_mask
= frame
->sig
.uc
.uc_sigmask
;
259 struct sigframe
*frame
= (struct sigframe
*)sp
;
260 frame_size
= sizeof(*frame
);
262 vg_assert(priv
->magicPI
== 0x31415927);
263 tst
->sig_mask
= frame
->uc
.uc_sigmask
;
265 tst
->tmp_sig_mask
= tst
->sig_mask
;
267 sigNo
= priv
->sigNo_private
;
269 /* Restore the entire machine state from our private copy. This
270 isn't really right, but we'll now move on to pick up at least
271 some changes that the signal handler may have made to the
273 tst
->arch
.vex
= priv
->vex
;
274 tst
->arch
.vex_shadow1
= priv
->vex_shadow1
;
275 tst
->arch
.vex_shadow2
= priv
->vex_shadow2
;
278 /* Pick up at least some state changes from the ucontext, just
279 in case the handler changed it. The shadow values will be
280 wrong, but hey. This restores the integer registers, the
281 program counter and stack pointer. FP/Vector regs, and any
282 condition code, FP status/control bits, etc, are not
284 vg_assert(rt_frame
!= NULL
);
285 struct vki_sigcontext
*sc
= &rt_frame
->sig
.uc
.uc_mcontext
;
286 Bool handler_changed_pc
= sc
->arm_pc
!= tst
->arch
.vex
.guest_R15T
;
288 # define FROM_CTX(reg,REG) tst->arch.vex.guest_##REG = sc->arm_##reg;
289 FROM_CTX(r0
,R0
); FROM_CTX(r1
,R1
); FROM_CTX(r2
,R2
); FROM_CTX(r3
,R3
);
290 FROM_CTX(r4
,R4
); FROM_CTX(r5
,R5
); FROM_CTX(r6
,R6
); FROM_CTX(r7
,R7
);
291 FROM_CTX(r8
,R8
); FROM_CTX(r9
,R9
); FROM_CTX(r10
,R10
); FROM_CTX(fp
,R11
);
292 FROM_CTX(ip
,R12
); FROM_CTX(sp
,R13
); FROM_CTX(lr
,R14
); FROM_CTX(pc
,R15T
);
295 /* A nasty ITSTATE hack -- apparently necessary as there doesn't
296 seem to be anywhere in the mcontext in which the ITSTATE is
297 stored. If the handler appears to have changed the PC, set
298 ITSTATE to [AL,AL,AL,AL] on the basis that it would be nuts
299 to start executing code with an ITSTATE value that pertained
300 to some other code address. Otherwise ITSTATE is restored
301 directly from the VEX state that we shoved on the stack when
302 creating the signal frame. */
303 if (handler_changed_pc
) {
304 tst
->arch
.vex
.guest_ITSTATE
= 0;
308 VG_TRACK( die_mem_stack_signal
, sp
- VG_STACK_REDZONE_SZB
,
309 frame_size
+ VG_STACK_REDZONE_SZB
);
311 if (VG_(clo_trace_signals
))
312 VG_(message
)(Vg_DebugMsg
,
313 "vg_pop_signal_frame (thread %u): "
314 "isRT=%d valid magic; PC=%#x\n",
315 tid
, has_siginfo
, tst
->arch
.vex
.guest_R15T
);
318 VG_TRACK( post_deliver_signal
, tid
, sigNo
);
321 #endif // defined(VGP_arm_linux)
323 /*--------------------------------------------------------------------*/
324 /*--- end sigframe-arm-linux.c ---*/
325 /*--------------------------------------------------------------------*/