1
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-arm64-linux.c ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright (C) 2013-2013 OpenWorks
12 info@open-works.net
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30 */
31
32 #if defined(VGP_arm64_linux)
33
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_threadstate.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_libcbase.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_machine.h"
42 #include "pub_core_options.h"
43 #include "pub_core_sigframe.h"
44 #include "pub_core_signals.h"
45 #include "pub_core_tooliface.h"
46 #include "pub_core_trampoline.h"
47 #include "priv_sigframe.h"
48
49
50 /* This uses the hack of dumping the vex guest state along with both
51 shadows in the frame, and restoring it afterwards from there,
52 rather than pulling it out of the ucontext. That means that signal
53 handlers which modify the ucontext and then return, expecting their
54 modifications to take effect, will have those modifications
55 ignored. This could be fixed properly with an hour or so more
56 effort. */
57
58 /* This also always does the 'has siginfo' behaviour whether or
59 not it is requested. */
60
61 struct vg_sig_private {
62 UInt magicPI;
63 UInt sigNo_private;
64 VexGuestARM64State vex;
65 VexGuestARM64State vex_shadow1;
66 VexGuestARM64State vex_shadow2;
67 };
68
69 struct sigframe {
70 struct vki_ucontext uc;
71 unsigned long retcode[2];
72 struct vg_sig_private vp;
73 };
74
75 struct rt_sigframe {
76 vki_siginfo_t info;
77 struct sigframe sig;
78 };
79
80
synth_ucontext(ThreadId tid,const vki_siginfo_t * si,UWord trapno,UWord err,const vki_sigset_t * set,struct vki_ucontext * uc)81 static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
82 UWord trapno, UWord err, const vki_sigset_t *set,
83 struct vki_ucontext *uc)
84 {
85
86 ThreadState *tst = VG_(get_ThreadState)(tid);
87 struct vki_sigcontext *sc = &uc->uc_mcontext;
88
89 VG_(memset)(uc, 0, sizeof(*uc));
90
91 uc->uc_flags = 0;
92 uc->uc_link = 0;
93 uc->uc_sigmask = *set;
94 uc->uc_stack = tst->altstack;
95
96 # define SC2(reg) sc->regs[reg] = tst->arch.vex.guest_X##reg
97 SC2(0); SC2(1); SC2(2); SC2(3);
98 SC2(4); SC2(5); SC2(6); SC2(7);
99 SC2(8); SC2(9); SC2(10); SC2(11);
100 SC2(12); SC2(13); SC2(14); SC2(15);
101 SC2(16); SC2(17); SC2(18); SC2(19);
102 SC2(20); SC2(21); SC2(22); SC2(23);
103 SC2(24); SC2(25); SC2(26); SC2(27);
104 SC2(28); SC2(29); SC2(30);
105 # undef SC2
106 sc->sp = tst->arch.vex.guest_XSP;
107 sc->pc = tst->arch.vex.guest_PC;
108 sc->pstate = 0; /* slack .. could do better */
109
110 //sc->trap_no = trapno;
111 //sc->error_code = err;
112 sc->fault_address = (ULong)si->_sifields._sigfault._addr;
113 }
114
115
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)116 static void build_sigframe(ThreadState *tst,
117 struct sigframe *frame,
118 const vki_siginfo_t *siginfo,
119 const struct vki_ucontext *siguc,
120 void *handler, UInt flags,
121 const vki_sigset_t *mask,
122 void *restorer)
123 {
124 UWord trapno;
125 UWord err;
126 Int sigNo = siginfo->si_signo;
127 struct vg_sig_private *priv = &frame->vp;
128
129 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
130 (Addr)frame, offsetof(struct sigframe, vp));
131
132 if (siguc) {
133 trapno = 0; //siguc->uc_mcontext.trap_no;
134 err = 0; //siguc->uc_mcontext.error_code;
135 } else {
136 trapno = 0;
137 err = 0;
138 }
139
140 synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
141
142 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
143 (Addr)frame, offsetof(struct sigframe, vp));
144
145 priv->magicPI = 0x31415927;
146 priv->sigNo_private = sigNo;
147 priv->vex = tst->arch.vex;
148 priv->vex_shadow1 = tst->arch.vex_shadow1;
149 priv->vex_shadow2 = tst->arch.vex_shadow2;
150 }
151
152
153 /* EXPORTED */
VG_(sigframe_create)154 void VG_(sigframe_create)( ThreadId tid,
155 Addr sp_top_of_frame,
156 const vki_siginfo_t *siginfo,
157 const struct vki_ucontext *siguc,
158 void *handler,
159 UInt flags,
160 const vki_sigset_t *mask,
161 void *restorer )
162 {
163 ThreadState *tst;
164 Addr sp = sp_top_of_frame;
165 Int sigNo = siginfo->si_signo;
166 UInt size;
167
168 tst = VG_(get_ThreadState)(tid);
169
170 size = sizeof(struct rt_sigframe);
171
172 sp -= size;
173 sp = VG_ROUNDDN(sp, 16);
174
175 if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
176 return; // Give up. No idea if this is correct
177
178 struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
179
180 /* Track our writes to siginfo */
181 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, /* VVVVV */
182 "signal handler siginfo", (Addr)rsf,
183 offsetof(struct rt_sigframe, sig));
184
185 VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
186
187 if (sigNo == VKI_SIGILL && siginfo->si_code > 0) {
188 rsf->info._sifields._sigfault._addr
189 = (Addr*)(tst)->arch.vex.guest_PC;
190 }
191 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
192 (Addr)rsf, offsetof(struct rt_sigframe, sig));
193
194 build_sigframe(tst, &rsf->sig, siginfo, siguc,
195 handler, flags, mask, restorer);
196 tst->arch.vex.guest_X1 = (Addr)&rsf->info;
197 tst->arch.vex.guest_X2 = (Addr)&rsf->sig.uc;
198
199 VG_(set_SP)(tid, sp);
200 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
201 sizeof(Addr));
202 tst->arch.vex.guest_X0 = sigNo;
203
204 if (flags & VKI_SA_RESTORER)
205 tst->arch.vex.guest_X30 = (Addr)restorer;
206 else
207 tst->arch.vex.guest_X30
208 = (Addr)&VG_(arm64_linux_SUBST_FOR_rt_sigreturn);
209
210 tst->arch.vex.guest_PC = (Addr)handler;
211 }
212
213
214 /*------------------------------------------------------------*/
215 /*--- Destroying signal frames ---*/
216 /*------------------------------------------------------------*/
217
218 /* EXPORTED */
VG_(sigframe_destroy)219 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
220 {
221 ThreadState *tst;
222 struct vg_sig_private *priv;
223 Addr sp;
224 UInt frame_size;
225 //ZZ struct vki_sigcontext *mc;
226 Int sigNo;
227 Bool has_siginfo = isRT;
228
229 vg_assert(VG_(is_valid_tid)(tid));
230 tst = VG_(get_ThreadState)(tid);
231 sp = tst->arch.vex.guest_XSP;
232
233 //ZZ if (has_siginfo) {
234 struct rt_sigframe *frame = (struct rt_sigframe *)sp;
235 frame_size = sizeof(*frame);
236 //mc = &frame->sig.uc.uc_mcontext;
237 priv = &frame->sig.vp;
238 vg_assert(priv->magicPI == 0x31415927);
239 tst->sig_mask = frame->sig.uc.uc_sigmask;
240 //ZZ } else {
241 //ZZ struct sigframe *frame = (struct sigframe *)sp;
242 //ZZ frame_size = sizeof(*frame);
243 //ZZ mc = &frame->uc.uc_mcontext;
244 //ZZ priv = &frame->vp;
245 //ZZ vg_assert(priv->magicPI == 0x31415927);
246 //ZZ tst->sig_mask = frame->uc.uc_sigmask;
247 //ZZ //VG_(printf)("Setting signmask to %08x%08x\n",
248 //ZZ // tst->sig_mask[0],tst->sig_mask[1]);
249 //ZZ }
250 tst->tmp_sig_mask = tst->sig_mask;
251
252 sigNo = priv->sigNo_private;
253
254 //ZZ //XXX: restore regs
255 //ZZ # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg;
256 //ZZ REST(r0,R0);
257 //ZZ REST(r1,R1);
258 //ZZ REST(r2,R2);
259 //ZZ REST(r3,R3);
260 //ZZ REST(r4,R4);
261 //ZZ REST(r5,R5);
262 //ZZ REST(r6,R6);
263 //ZZ REST(r7,R7);
264 //ZZ REST(r8,R8);
265 //ZZ REST(r9,R9);
266 //ZZ REST(r10,R10);
267 //ZZ REST(fp,R11);
268 //ZZ REST(ip,R12);
269 //ZZ REST(sp,R13);
270 //ZZ REST(lr,R14);
271 //ZZ REST(pc,R15T);
272 //ZZ # undef REST
273
274 /* Uh, the next line makes all the REST() above pointless. */
275 tst->arch.vex = priv->vex;
276
277 tst->arch.vex_shadow1 = priv->vex_shadow1;
278 tst->arch.vex_shadow2 = priv->vex_shadow2;
279
280 VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
281 frame_size + VG_STACK_REDZONE_SZB );
282
283 if (VG_(clo_trace_signals))
284 VG_(message)(Vg_DebugMsg,
285 "vg_pop_signal_frame (thread %d): "
286 "isRT=%d valid magic; PC=%#llx\n",
287 tid, has_siginfo, tst->arch.vex.guest_PC);
288
289 /* tell the tools */
290 VG_TRACK( post_deliver_signal, tid, sigNo );
291 }
292
293 #endif // defined(VGP_arm_linux)
294
295 /*--------------------------------------------------------------------*/
296 /*--- end sigframe-arm64-linux.c ---*/
297 /*--------------------------------------------------------------------*/
298