blob: 499023eb497b446c455e72d9e7e8536c37fe8f85 [file] [log] [blame]
sewardj59570ff2010-01-01 11:59:33 +00001
2/*--------------------------------------------------------------------*/
3/*--- Create/destroy signal delivery frames. ---*/
4/*--- sigframe-arm-linux.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
Elliott Hughesed398002017-06-21 14:41:24 -070011 Copyright (C) 2000-2017 Nicholas Nethercote
sewardj59570ff2010-01-01 11:59:33 +000012 njn@valgrind.org
Elliott Hughesed398002017-06-21 14:41:24 -070013 Copyright (C) 2004-2017 Paul Mackerras
sewardj59570ff2010-01-01 11:59:33 +000014 paulus@samba.org
Elliott Hughesed398002017-06-21 14:41:24 -070015 Copyright (C) 2008-2017 Evan Geller
sewardj59570ff2010-01-01 11:59:33 +000016 gaze@bea.ms
17
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.
22
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.
27
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
31 02111-1307, USA.
32
33 The GNU General Public License is contained in the file COPYING.
34*/
35
36#if defined(VGP_arm_linux)
37
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"
florian01fcf6a2015-04-18 10:33:54 +000052#include "priv_sigframe.h"
sewardj59570ff2010-01-01 11:59:33 +000053
54
sewardj320dee22011-09-10 09:10:03 +000055/* 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
61 effort. */
62
63
sewardj59570ff2010-01-01 11:59:33 +000064struct vg_sig_private {
65 UInt magicPI;
66 UInt sigNo_private;
sewardj320dee22011-09-10 09:10:03 +000067 VexGuestARMState vex;
sewardj59570ff2010-01-01 11:59:33 +000068 VexGuestARMState vex_shadow1;
69 VexGuestARMState vex_shadow2;
70};
71
72struct sigframe {
73 struct vki_ucontext uc;
74 unsigned long retcode[2];
75 struct vg_sig_private vp;
76};
77
78struct rt_sigframe {
79 vki_siginfo_t info;
80 struct sigframe sig;
81};
82
sewardj59570ff2010-01-01 11:59:33 +000083
84static 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){
87
88 ThreadState *tst = VG_(get_ThreadState)(tid);
89 struct vki_sigcontext *sc = &uc->uc_mcontext;
90
91 VG_(memset)(uc, 0, sizeof(*uc));
92
93 uc->uc_flags = 0;
94 uc->uc_link = 0;
95 uc->uc_sigmask = *set;
96 uc->uc_stack = tst->altstack;
97
98# define SC2(reg,REG) sc->arm_##reg = tst->arch.vex.guest_##REG
99 SC2(r0,R0);
100 SC2(r1,R1);
101 SC2(r2,R2);
102 SC2(r3,R3);
103 SC2(r4,R4);
104 SC2(r5,R5);
105 SC2(r6,R6);
106 SC2(r7,R7);
107 SC2(r8,R8);
108 SC2(r9,R9);
109 SC2(r10,R10);
110 SC2(fp,R11);
111 SC2(ip,R12);
112 SC2(sp,R13);
113 SC2(lr,R14);
sewardj9dcfdff2010-08-22 12:00:40 +0000114 SC2(pc,R15T);
sewardj59570ff2010-01-01 11:59:33 +0000115# undef SC2
116
117 sc->trap_no = trapno;
118 sc->error_code = err;
119 sc->fault_address = (UInt)si->_sifields._sigfault._addr;
120}
121
122
123static 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,
129 void *restorer){
130
131 UWord trapno;
132 UWord err;
133 Int sigNo = siginfo->si_signo;
134 struct vg_sig_private *priv = &frame->vp;
135
136 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
137 (Addr)frame, offsetof(struct sigframe, vp));
138
139 if(siguc) {
140 trapno = siguc->uc_mcontext.trap_no;
141 err = siguc->uc_mcontext.error_code;
142 } else {
143 trapno = 0;
144 err = 0;
145 }
146
147 synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
148
149 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
150 (Addr)frame, offsetof(struct sigframe, vp));
151
152 priv->magicPI = 0x31415927;
153 priv->sigNo_private = sigNo;
sewardj320dee22011-09-10 09:10:03 +0000154 priv->vex = tst->arch.vex;
sewardj59570ff2010-01-01 11:59:33 +0000155 priv->vex_shadow1 = tst->arch.vex_shadow1;
156 priv->vex_shadow2 = tst->arch.vex_shadow2;
157
158}
159
160
161
162/* EXPORTED */
163void VG_(sigframe_create)( ThreadId tid,
sewardj8eb8bab2015-07-21 14:44:28 +0000164 Bool on_altstack,
sewardj59570ff2010-01-01 11:59:33 +0000165 Addr sp_top_of_frame,
166 const vki_siginfo_t *siginfo,
167 const struct vki_ucontext *siguc,
168 void *handler,
169 UInt flags,
170 const vki_sigset_t *mask,
171 void *restorer )
172{
173// struct vg_sig_private *priv;
174 Addr sp = sp_top_of_frame;
175 ThreadState *tst;
176 Int sigNo = siginfo->si_signo;
177// Addr faultaddr;
178 UInt size;
179
180 tst = VG_(get_ThreadState)(tid);
181
182 size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
183 sizeof(struct sigframe);
184
185 sp -= size;
186 sp = VG_ROUNDDN(sp, 16);
187
florian7d4a28b2015-04-23 15:20:00 +0000188 if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
sewardj59570ff2010-01-01 11:59:33 +0000189 I_die_here; // XXX Incorrect behavior
190
191
192 if (flags & VKI_SA_SIGINFO){
193 struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
194
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));
199
200 VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
201
202 if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
203 rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
204 }
205 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
206 (Addr)rsf, offsetof(struct rt_sigframe, sig));
207
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;
212 }
sewardj9dcfdff2010-08-22 12:00:40 +0000213 else {
sewardj59570ff2010-01-01 11:59:33 +0000214 build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
215 handler, flags, mask, restorer);
sewardj9dcfdff2010-08-22 12:00:40 +0000216 }
sewardj59570ff2010-01-01 11:59:33 +0000217
218 VG_(set_SP)(tid, sp);
219 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
220 sizeof(Addr));
sewardj9dcfdff2010-08-22 12:00:40 +0000221 tst->arch.vex.guest_R0 = sigNo;
sewardj59570ff2010-01-01 11:59:33 +0000222
sewardj9dcfdff2010-08-22 12:00:40 +0000223 if (flags & VKI_SA_RESTORER)
sewardjbc33be62011-11-20 09:35:51 +0000224 tst->arch.vex.guest_R14 = (Addr)restorer;
225 else
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);
sewardj59570ff2010-01-01 11:59:33 +0000230
sewardj9dcfdff2010-08-22 12:00:40 +0000231 tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
sewardj9bd33012015-03-05 11:24:05 +0000232
233 if (VG_(clo_trace_signals))
234 VG_(message)(Vg_DebugMsg,
sewardjbba930d2015-06-05 10:03:56 +0000235 "VG_(sigframe_create): continuing in handler with PC=%#lx\n",
sewardj9bd33012015-03-05 11:24:05 +0000236 (Addr)handler);
sewardj59570ff2010-01-01 11:59:33 +0000237}
238
239
240/*------------------------------------------------------------*/
241/*--- Destroying signal frames ---*/
242/*------------------------------------------------------------*/
243
244/* EXPORTED */
245void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
246{
247 ThreadState *tst;
248 struct vg_sig_private *priv;
249 Addr sp;
250 UInt frame_size;
sewardj59570ff2010-01-01 11:59:33 +0000251 Int sigNo;
252 Bool has_siginfo = isRT;
253
254 vg_assert(VG_(is_valid_tid)(tid));
255 tst = VG_(get_ThreadState)(tid);
256 sp = tst->arch.vex.guest_R13;
257
258 if (has_siginfo) {
259 struct rt_sigframe *frame = (struct rt_sigframe *)sp;
260 frame_size = sizeof(*frame);
sewardj59570ff2010-01-01 11:59:33 +0000261 priv = &frame->sig.vp;
262 vg_assert(priv->magicPI == 0x31415927);
263 tst->sig_mask = frame->sig.uc.uc_sigmask;
264 } else {
265 struct sigframe *frame = (struct sigframe *)sp;
266 frame_size = sizeof(*frame);
sewardj59570ff2010-01-01 11:59:33 +0000267 priv = &frame->vp;
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]);
273*/
274 }
275 tst->tmp_sig_mask = tst->sig_mask;
276
277 sigNo = priv->sigNo_private;
278
florian486372b2015-08-06 09:34:20 +0000279//ZZ //XXX: restore regs
280//ZZ # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
281//ZZ REST(r0,R0);
282//ZZ REST(r1,R1);
283//ZZ REST(r2,R2);
284//ZZ REST(r3,R3);
285//ZZ REST(r4,R4);
286//ZZ REST(r5,R5);
287//ZZ REST(r6,R6);
288//ZZ REST(r7,R7);
289//ZZ REST(r8,R8);
290//ZZ REST(r9,R9);
291//ZZ REST(r10,R10);
292//ZZ REST(fp,R11);
293//ZZ REST(ip,R12);
294//ZZ REST(sp,R13);
295//ZZ REST(lr,R14);
296//ZZ REST(pc,R15T);
297//ZZ # undef REST
sewardj59570ff2010-01-01 11:59:33 +0000298
sewardj320dee22011-09-10 09:10:03 +0000299 /* Uh, the next line makes all the REST() above pointless. */
300 tst->arch.vex = priv->vex;
301
sewardj59570ff2010-01-01 11:59:33 +0000302 tst->arch.vex_shadow1 = priv->vex_shadow1;
303 tst->arch.vex_shadow2 = priv->vex_shadow2;
304
305 VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
306 frame_size + VG_STACK_REDZONE_SZB );
307
308 if (VG_(clo_trace_signals))
309 VG_(message)(Vg_DebugMsg,
florian97f1d332015-08-06 09:00:48 +0000310 "vg_pop_signal_frame (thread %u): "
sewardj320dee22011-09-10 09:10:03 +0000311 "isRT=%d valid magic; PC=%#x\n",
sewardj9dcfdff2010-08-22 12:00:40 +0000312 tid, has_siginfo, tst->arch.vex.guest_R15T);
sewardj59570ff2010-01-01 11:59:33 +0000313
314 /* tell the tools */
315 VG_TRACK( post_deliver_signal, tid, sigNo );
316}
317
318#endif // defined(VGP_arm_linux)
319
320/*--------------------------------------------------------------------*/
321/*--- end sigframe-arm-linux.c ---*/
322/*--------------------------------------------------------------------*/