• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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