blob: 06069e486b57349a4b901629a97e1e72ca16a0c9 [file] [log] [blame]
Jeff Browned07e002011-02-03 17:46:23 -08001
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
Ben Cheng663860b2013-01-31 15:38:14 -080011 Copyright (C) 2000-2012 Nicholas Nethercote
Jeff Browned07e002011-02-03 17:46:23 -080012 njn@valgrind.org
Ben Cheng663860b2013-01-31 15:38:14 -080013 Copyright (C) 2004-2012 Paul Mackerras
Jeff Browned07e002011-02-03 17:46:23 -080014 paulus@samba.org
Ben Cheng663860b2013-01-31 15:38:14 -080015 Copyright (C) 2008-2012 Evan Geller
Jeff Browned07e002011-02-03 17:46:23 -080016 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"
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +040041#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
Jeff Browned07e002011-02-03 17:46:23 -080042#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)
54
55
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +040056/* 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
62 effort. */
63
64
Jeff Browned07e002011-02-03 17:46:23 -080065struct vg_sig_private {
66 UInt magicPI;
67 UInt sigNo_private;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +040068 VexGuestARMState vex;
Jeff Browned07e002011-02-03 17:46:23 -080069 VexGuestARMState vex_shadow1;
70 VexGuestARMState vex_shadow2;
71};
72
73struct sigframe {
74 struct vki_ucontext uc;
75 unsigned long retcode[2];
76 struct vg_sig_private vp;
77};
78
79struct rt_sigframe {
80 vki_siginfo_t info;
81 struct sigframe sig;
82};
83
84static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
85{
86 ThreadId tid = tst->tid;
87 NSegment const* stackseg = NULL;
88
89 if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
90 stackseg = VG_(am_find_nsegment)(addr);
91 if (0 && stackseg)
92 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
93 addr, stackseg->start, stackseg->end);
94 }
95
96 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
97 VG_(message)(
98 Vg_UserMsg,
99 "Can't extend stack to %#lx during signal delivery for thread %d:",
100 addr, tid);
101 if (stackseg == NULL)
102 VG_(message)(Vg_UserMsg, " no stack segment");
103 else
104 VG_(message)(Vg_UserMsg, " too small or bad protection modes");
105
106 /* set SIGSEGV to default handler */
107 VG_(set_default_handler)(VKI_SIGSEGV);
108 VG_(synth_fault_mapping)(tid, addr);
109
110 /* The whole process should be about to die, since the default
111 action of SIGSEGV to kill the whole process. */
112 return False;
113 }
114
115 /* For tracking memory events, indicate the entire frame has been
116 allocated. */
117 VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
118 size + VG_STACK_REDZONE_SZB, tid );
119
120 return True;
121}
122
123static 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){
126
127 ThreadState *tst = VG_(get_ThreadState)(tid);
128 struct vki_sigcontext *sc = &uc->uc_mcontext;
129
130 VG_(memset)(uc, 0, sizeof(*uc));
131
132 uc->uc_flags = 0;
133 uc->uc_link = 0;
134 uc->uc_sigmask = *set;
135 uc->uc_stack = tst->altstack;
136
137# define SC2(reg,REG) sc->arm_##reg = tst->arch.vex.guest_##REG
138 SC2(r0,R0);
139 SC2(r1,R1);
140 SC2(r2,R2);
141 SC2(r3,R3);
142 SC2(r4,R4);
143 SC2(r5,R5);
144 SC2(r6,R6);
145 SC2(r7,R7);
146 SC2(r8,R8);
147 SC2(r9,R9);
148 SC2(r10,R10);
149 SC2(fp,R11);
150 SC2(ip,R12);
151 SC2(sp,R13);
152 SC2(lr,R14);
153 SC2(pc,R15T);
154# undef SC2
155
156 sc->trap_no = trapno;
157 sc->error_code = err;
158 sc->fault_address = (UInt)si->_sifields._sigfault._addr;
159}
160
161
162static 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,
168 void *restorer){
169
170 UWord trapno;
171 UWord err;
172 Int sigNo = siginfo->si_signo;
173 struct vg_sig_private *priv = &frame->vp;
174
175 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
176 (Addr)frame, offsetof(struct sigframe, vp));
177
178 if(siguc) {
179 trapno = siguc->uc_mcontext.trap_no;
180 err = siguc->uc_mcontext.error_code;
181 } else {
182 trapno = 0;
183 err = 0;
184 }
185
186 synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
187
188 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
189 (Addr)frame, offsetof(struct sigframe, vp));
190
191 priv->magicPI = 0x31415927;
192 priv->sigNo_private = sigNo;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400193 priv->vex = tst->arch.vex;
Jeff Browned07e002011-02-03 17:46:23 -0800194 priv->vex_shadow1 = tst->arch.vex_shadow1;
195 priv->vex_shadow2 = tst->arch.vex_shadow2;
196
197}
198
199
200
201/* EXPORTED */
202void VG_(sigframe_create)( ThreadId tid,
203 Addr sp_top_of_frame,
204 const vki_siginfo_t *siginfo,
205 const struct vki_ucontext *siguc,
206 void *handler,
207 UInt flags,
208 const vki_sigset_t *mask,
209 void *restorer )
210{
211// struct vg_sig_private *priv;
212 Addr sp = sp_top_of_frame;
213 ThreadState *tst;
214 Int sigNo = siginfo->si_signo;
215// Addr faultaddr;
216 UInt size;
217
218 tst = VG_(get_ThreadState)(tid);
219
220 size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
221 sizeof(struct sigframe);
222
223 sp -= size;
224 sp = VG_ROUNDDN(sp, 16);
225
226 if(!extend(tst, sp, size))
227 I_die_here; // XXX Incorrect behavior
228
229
230 if (flags & VKI_SA_SIGINFO){
231 struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
232
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));
237
238 VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
239
240 if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
241 rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
242 }
243 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
244 (Addr)rsf, offsetof(struct rt_sigframe, sig));
245
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;
250 }
251 else {
252 build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
253 handler, flags, mask, restorer);
254 }
255
256 VG_(set_SP)(tid, sp);
257 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
258 sizeof(Addr));
259 tst->arch.vex.guest_R0 = sigNo;
260
261 if (flags & VKI_SA_RESTORER)
Ben Cheng663860b2013-01-31 15:38:14 -0800262 tst->arch.vex.guest_R14 = (Addr)restorer;
263 else
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);
Jeff Browned07e002011-02-03 17:46:23 -0800268
269 tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
270}
271
272
273/*------------------------------------------------------------*/
274/*--- Destroying signal frames ---*/
275/*------------------------------------------------------------*/
276
277/* EXPORTED */
278void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
279{
280 ThreadState *tst;
281 struct vg_sig_private *priv;
282 Addr sp;
283 UInt frame_size;
284 struct vki_sigcontext *mc;
285 Int sigNo;
286 Bool has_siginfo = isRT;
287
288 vg_assert(VG_(is_valid_tid)(tid));
289 tst = VG_(get_ThreadState)(tid);
290 sp = tst->arch.vex.guest_R13;
291
292 if (has_siginfo) {
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;
299 } else {
300 struct sigframe *frame = (struct sigframe *)sp;
301 frame_size = sizeof(*frame);
302 mc = &frame->uc.uc_mcontext;
303 priv = &frame->vp;
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]);
309*/
310 }
311 tst->tmp_sig_mask = tst->sig_mask;
312
313 sigNo = priv->sigNo_private;
314
315 //XXX: restore regs
316# define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
317 REST(r0,R0);
318 REST(r1,R1);
319 REST(r2,R2);
320 REST(r3,R3);
321 REST(r4,R4);
322 REST(r5,R5);
323 REST(r6,R6);
324 REST(r7,R7);
325 REST(r8,R8);
326 REST(r9,R9);
327 REST(r10,R10);
328 REST(fp,R11);
329 REST(ip,R12);
330 REST(sp,R13);
331 REST(lr,R14);
332 REST(pc,R15T);
333# undef REST
334
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400335 /* Uh, the next line makes all the REST() above pointless. */
336 tst->arch.vex = priv->vex;
337
Jeff Browned07e002011-02-03 17:46:23 -0800338 tst->arch.vex_shadow1 = priv->vex_shadow1;
339 tst->arch.vex_shadow2 = priv->vex_shadow2;
340
341 VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
342 frame_size + VG_STACK_REDZONE_SZB );
343
344 if (VG_(clo_trace_signals))
345 VG_(message)(Vg_DebugMsg,
346 "vg_pop_signal_frame (thread %d): "
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400347 "isRT=%d valid magic; PC=%#x\n",
Jeff Browned07e002011-02-03 17:46:23 -0800348 tid, has_siginfo, tst->arch.vex.guest_R15T);
349
350 /* tell the tools */
351 VG_TRACK( post_deliver_signal, tid, sigNo );
352}
353
354#endif // defined(VGP_arm_linux)
355
356/*--------------------------------------------------------------------*/
357/*--- end sigframe-arm-linux.c ---*/
358/*--------------------------------------------------------------------*/