1
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
11 Copyright (C) 2000-2013 Nicholas Nethercote
12 njn@valgrind.org
13 Copyright (C) 2004-2013 Paul Mackerras
14 paulus@samba.org
15 Copyright (C) 2008-2013 Evan Geller
16 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"
52 #include "priv_sigframe.h"
53
54
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
61 effort. */
62
63
64 struct vg_sig_private {
65 UInt magicPI;
66 UInt sigNo_private;
67 VexGuestARMState vex;
68 VexGuestARMState vex_shadow1;
69 VexGuestARMState vex_shadow2;
70 };
71
72 struct sigframe {
73 struct vki_ucontext uc;
74 unsigned long retcode[2];
75 struct vg_sig_private vp;
76 };
77
78 struct rt_sigframe {
79 vki_siginfo_t info;
80 struct sigframe sig;
81 };
82
83
synth_ucontext(ThreadId tid,const vki_siginfo_t * si,UWord trapno,UWord err,const vki_sigset_t * set,struct vki_ucontext * uc)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){
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);
114 SC2(pc,R15T);
115 # 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
build_sigframe(ThreadState * tst,struct sigframe * frame,const vki_siginfo_t * siginfo,const struct vki_ucontext * siguc,void * handler,UInt flags,const vki_sigset_t * mask,void * restorer)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,
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;
154 priv->vex = tst->arch.vex;
155 priv->vex_shadow1 = tst->arch.vex_shadow1;
156 priv->vex_shadow2 = tst->arch.vex_shadow2;
157
158 }
159
160
161
162 /* EXPORTED */
VG_(sigframe_create)163 void VG_(sigframe_create)( ThreadId tid,
164 Addr sp_top_of_frame,
165 const vki_siginfo_t *siginfo,
166 const struct vki_ucontext *siguc,
167 void *handler,
168 UInt flags,
169 const vki_sigset_t *mask,
170 void *restorer )
171 {
172 // struct vg_sig_private *priv;
173 Addr sp = sp_top_of_frame;
174 ThreadState *tst;
175 Int sigNo = siginfo->si_signo;
176 // Addr faultaddr;
177 UInt size;
178
179 tst = VG_(get_ThreadState)(tid);
180
181 size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
182 sizeof(struct sigframe);
183
184 sp -= size;
185 sp = VG_ROUNDDN(sp, 16);
186
187 if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
188 I_die_here; // XXX Incorrect behavior
189
190
191 if (flags & VKI_SA_SIGINFO){
192 struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
193
194 /* Track our writes to siginfo */
195 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, /* VVVVV */
196 "signal handler siginfo", (Addr)rsf,
197 offsetof(struct rt_sigframe, sig));
198
199 VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
200
201 if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
202 rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
203 }
204 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
205 (Addr)rsf, offsetof(struct rt_sigframe, sig));
206
207 build_sigframe(tst, &rsf->sig, siginfo, siguc,
208 handler, flags, mask, restorer);
209 tst->arch.vex.guest_R1 = (Addr)&rsf->info;
210 tst->arch.vex.guest_R2 = (Addr)&rsf->sig.uc;
211 }
212 else {
213 build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
214 handler, flags, mask, restorer);
215 }
216
217 VG_(set_SP)(tid, sp);
218 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
219 sizeof(Addr));
220 tst->arch.vex.guest_R0 = sigNo;
221
222 if (flags & VKI_SA_RESTORER)
223 tst->arch.vex.guest_R14 = (Addr)restorer;
224 else
225 tst->arch.vex.guest_R14
226 = (flags & VKI_SA_SIGINFO)
227 ? (Addr)&VG_(arm_linux_SUBST_FOR_rt_sigreturn)
228 : (Addr)&VG_(arm_linux_SUBST_FOR_sigreturn);
229
230 tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
231
232 if (VG_(clo_trace_signals))
233 VG_(message)(Vg_DebugMsg,
234 "VG_(sigframe_create): continuing in handler with PC=%#x\n",
235 (Addr)handler);
236 }
237
238
239 /*------------------------------------------------------------*/
240 /*--- Destroying signal frames ---*/
241 /*------------------------------------------------------------*/
242
243 /* EXPORTED */
VG_(sigframe_destroy)244 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
245 {
246 ThreadState *tst;
247 struct vg_sig_private *priv;
248 Addr sp;
249 UInt frame_size;
250 struct vki_sigcontext *mc;
251 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);
261 mc = &frame->sig.uc.uc_mcontext;
262 priv = &frame->sig.vp;
263 vg_assert(priv->magicPI == 0x31415927);
264 tst->sig_mask = frame->sig.uc.uc_sigmask;
265 } else {
266 struct sigframe *frame = (struct sigframe *)sp;
267 frame_size = sizeof(*frame);
268 mc = &frame->uc.uc_mcontext;
269 priv = &frame->vp;
270 vg_assert(priv->magicPI == 0x31415927);
271 tst->sig_mask = frame->uc.uc_sigmask;
272 /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
273 tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
274 VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
275 */
276 }
277 tst->tmp_sig_mask = tst->sig_mask;
278
279 sigNo = priv->sigNo_private;
280
281 //XXX: restore regs
282 # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
283 REST(r0,R0);
284 REST(r1,R1);
285 REST(r2,R2);
286 REST(r3,R3);
287 REST(r4,R4);
288 REST(r5,R5);
289 REST(r6,R6);
290 REST(r7,R7);
291 REST(r8,R8);
292 REST(r9,R9);
293 REST(r10,R10);
294 REST(fp,R11);
295 REST(ip,R12);
296 REST(sp,R13);
297 REST(lr,R14);
298 REST(pc,R15T);
299 # undef REST
300
301 /* Uh, the next line makes all the REST() above pointless. */
302 tst->arch.vex = priv->vex;
303
304 tst->arch.vex_shadow1 = priv->vex_shadow1;
305 tst->arch.vex_shadow2 = priv->vex_shadow2;
306
307 VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
308 frame_size + VG_STACK_REDZONE_SZB );
309
310 if (VG_(clo_trace_signals))
311 VG_(message)(Vg_DebugMsg,
312 "vg_pop_signal_frame (thread %d): "
313 "isRT=%d valid magic; PC=%#x\n",
314 tid, has_siginfo, tst->arch.vex.guest_R15T);
315
316 /* tell the tools */
317 VG_TRACK( post_deliver_signal, tid, sigNo );
318 }
319
320 #endif // defined(VGP_arm_linux)
321
322 /*--------------------------------------------------------------------*/
323 /*--- end sigframe-arm-linux.c ---*/
324 /*--------------------------------------------------------------------*/
325