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-2015 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                            Bool on_altstack,
156                            Addr sp_top_of_frame,
157                            const vki_siginfo_t *siginfo,
158                            const struct vki_ucontext *siguc,
159                            void *handler,
160                            UInt flags,
161                            const vki_sigset_t *mask,
162                            void *restorer )
163 {
164    ThreadState *tst;
165    Addr sp    = sp_top_of_frame;
166    Int  sigNo = siginfo->si_signo;
167    UInt size;
168 
169    tst = VG_(get_ThreadState)(tid);
170 
171    size = sizeof(struct rt_sigframe);
172 
173    sp -= size;
174    sp = VG_ROUNDDN(sp, 16);
175 
176    if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
177       return; // Give up.  No idea if this is correct
178 
179    struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
180 
181    /* Track our writes to siginfo */
182    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
183              "signal handler siginfo", (Addr)rsf,
184              offsetof(struct rt_sigframe, sig));
185 
186    VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
187 
188    if (sigNo == VKI_SIGILL && siginfo->si_code > 0) {
189       rsf->info._sifields._sigfault._addr
190         = (Addr*)(tst)->arch.vex.guest_PC;
191    }
192    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
193          (Addr)rsf, offsetof(struct rt_sigframe, sig));
194 
195    build_sigframe(tst, &rsf->sig, siginfo, siguc,
196                        handler, flags, mask, restorer);
197    tst->arch.vex.guest_X1 = (Addr)&rsf->info;
198    tst->arch.vex.guest_X2 = (Addr)&rsf->sig.uc;
199 
200    VG_(set_SP)(tid, sp);
201    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
202              sizeof(Addr));
203    tst->arch.vex.guest_X0 = sigNo;
204 
205    if (flags & VKI_SA_RESTORER)
206        tst->arch.vex.guest_X30 = (Addr)restorer;
207    else
208        tst->arch.vex.guest_X30
209           = (Addr)&VG_(arm64_linux_SUBST_FOR_rt_sigreturn);
210 
211    tst->arch.vex.guest_PC = (Addr)handler;
212 }
213 
214 
215 /*------------------------------------------------------------*/
216 /*--- Destroying signal frames                             ---*/
217 /*------------------------------------------------------------*/
218 
219 /* EXPORTED */
VG_(sigframe_destroy)220 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
221 {
222    ThreadState *tst;
223    struct vg_sig_private *priv;
224    Addr sp;
225    UInt frame_size;
226 //ZZ    struct vki_sigcontext *mc;
227    Int sigNo;
228    Bool has_siginfo = isRT;
229 
230    vg_assert(VG_(is_valid_tid)(tid));
231    tst = VG_(get_ThreadState)(tid);
232    sp = tst->arch.vex.guest_XSP;
233 
234 //ZZ    if (has_siginfo) {
235       struct rt_sigframe *frame = (struct rt_sigframe *)sp;
236       frame_size = sizeof(*frame);
237       //mc = &frame->sig.uc.uc_mcontext;
238       priv = &frame->sig.vp;
239       vg_assert(priv->magicPI == 0x31415927);
240       tst->sig_mask = frame->sig.uc.uc_sigmask;
241 //ZZ    } else {
242 //ZZ       struct sigframe *frame = (struct sigframe *)sp;
243 //ZZ       frame_size = sizeof(*frame);
244 //ZZ       mc = &frame->uc.uc_mcontext;
245 //ZZ       priv = &frame->vp;
246 //ZZ       vg_assert(priv->magicPI == 0x31415927);
247 //ZZ       tst->sig_mask = frame->uc.uc_sigmask;
248 //ZZ       //VG_(printf)("Setting signmask to %08x%08x\n",
249 //ZZ       //            tst->sig_mask[0],tst->sig_mask[1]);
250 //ZZ    }
251    tst->tmp_sig_mask = tst->sig_mask;
252 
253    sigNo = priv->sigNo_private;
254 
255 //ZZ     //XXX: restore regs
256 //ZZ #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
257 //ZZ    REST(r0,R0);
258 //ZZ    REST(r1,R1);
259 //ZZ    REST(r2,R2);
260 //ZZ    REST(r3,R3);
261 //ZZ    REST(r4,R4);
262 //ZZ    REST(r5,R5);
263 //ZZ    REST(r6,R6);
264 //ZZ    REST(r7,R7);
265 //ZZ    REST(r8,R8);
266 //ZZ    REST(r9,R9);
267 //ZZ    REST(r10,R10);
268 //ZZ    REST(fp,R11);
269 //ZZ    REST(ip,R12);
270 //ZZ    REST(sp,R13);
271 //ZZ    REST(lr,R14);
272 //ZZ    REST(pc,R15T);
273 //ZZ #  undef REST
274 
275    /* Uh, the next line makes all the REST() above pointless. */
276    tst->arch.vex         = priv->vex;
277 
278    tst->arch.vex_shadow1 = priv->vex_shadow1;
279    tst->arch.vex_shadow2 = priv->vex_shadow2;
280 
281    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
282              frame_size + VG_STACK_REDZONE_SZB );
283 
284    if (VG_(clo_trace_signals))
285       VG_(message)(Vg_DebugMsg,
286                    "vg_pop_signal_frame (thread %u): "
287                    "isRT=%d valid magic; PC=%#llx\n",
288                    tid, has_siginfo, tst->arch.vex.guest_PC);
289 
290    /* tell the tools */
291    VG_TRACK( post_deliver_signal, tid, sigNo );
292 }
293 
294 #endif // defined(VGP_arm_linux)
295 
296 /*--------------------------------------------------------------------*/
297 /*--- end                                   sigframe-arm64-linux.c ---*/
298 /*--------------------------------------------------------------------*/
299