• 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 //ZZ #include "pub_core_vkiscnums.h"
37 #include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
38 #include "pub_core_threadstate.h"
39 #include "pub_core_aspacemgr.h"
40 #include "pub_core_libcbase.h"
41 #include "pub_core_libcassert.h"
42 #include "pub_core_libcprint.h"
43 #include "pub_core_machine.h"
44 #include "pub_core_options.h"
45 #include "pub_core_sigframe.h"
46 #include "pub_core_signals.h"
47 #include "pub_core_tooliface.h"
48 #include "pub_core_trampoline.h"
49 //ZZ #include "pub_core_transtab.h"      // VG_(discard_translations)
50 
51 
52 /* This uses the hack of dumping the vex guest state along with both
53    shadows in the frame, and restoring it afterwards from there,
54    rather than pulling it out of the ucontext.  That means that signal
55    handlers which modify the ucontext and then return, expecting their
56    modifications to take effect, will have those modifications
57    ignored.  This could be fixed properly with an hour or so more
58    effort. */
59 
60 /* This also always does the 'has siginfo' behaviour whether or
61    not it is requested. */
62 
63 struct vg_sig_private {
64    UInt magicPI;
65    UInt sigNo_private;
66    VexGuestARM64State vex;
67    VexGuestARM64State vex_shadow1;
68    VexGuestARM64State vex_shadow2;
69 };
70 
71 struct sigframe {
72    struct vki_ucontext uc;
73    unsigned long retcode[2];
74    struct vg_sig_private vp;
75 };
76 
77 struct rt_sigframe {
78    vki_siginfo_t info;
79    struct sigframe sig;
80 };
81 
extend(ThreadState * tst,Addr addr,SizeT size)82 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
83 {
84    ThreadId        tid = tst->tid;
85    NSegment const* stackseg = NULL;
86 
87    if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
88       stackseg = VG_(am_find_nsegment)(addr);
89       if (0 && stackseg)
90          VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
91                      addr, stackseg->start, stackseg->end);
92    }
93 
94    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
95       VG_(message)(
96          Vg_UserMsg,
97          "Can't extend stack to %#lx during signal delivery for thread %d:",
98          addr, tid);
99       if (stackseg == NULL)
100          VG_(message)(Vg_UserMsg, "  no stack segment");
101       else
102          VG_(message)(Vg_UserMsg, "  too small or bad protection modes");
103 
104       /* set SIGSEGV to default handler */
105       VG_(set_default_handler)(VKI_SIGSEGV);
106       VG_(synth_fault_mapping)(tid, addr);
107 
108       /* The whole process should be about to die, since the default
109          action of SIGSEGV to kill the whole process. */
110       return False;
111    }
112 
113    /* For tracking memory events, indicate the entire frame has been
114       allocated. */
115    VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
116              size + VG_STACK_REDZONE_SZB, tid );
117 
118    return True;
119 }
120 
synth_ucontext(ThreadId tid,const vki_siginfo_t * si,UWord trapno,UWord err,const vki_sigset_t * set,struct vki_ucontext * uc)121 static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
122                             UWord trapno, UWord err, const vki_sigset_t *set,
123                             struct vki_ucontext *uc)
124 {
125 
126    ThreadState *tst = VG_(get_ThreadState)(tid);
127    struct vki_sigcontext *sc = &uc->uc_mcontext;
128 
129    VG_(memset)(uc, 0, sizeof(*uc));
130 
131    uc->uc_flags = 0;
132    uc->uc_link = 0;
133    uc->uc_sigmask = *set;
134    uc->uc_stack = tst->altstack;
135 
136 #  define SC2(reg)  sc->regs[reg] = tst->arch.vex.guest_X##reg
137    SC2(0);   SC2(1);   SC2(2);   SC2(3);
138    SC2(4);   SC2(5);   SC2(6);   SC2(7);
139    SC2(8);   SC2(9);   SC2(10);  SC2(11);
140    SC2(12);  SC2(13);  SC2(14);  SC2(15);
141    SC2(16);  SC2(17);  SC2(18);  SC2(19);
142    SC2(20);  SC2(21);  SC2(22);  SC2(23);
143    SC2(24);  SC2(25);  SC2(26);  SC2(27);
144    SC2(28);  SC2(29);  SC2(30);
145 #  undef SC2
146    sc->sp = tst->arch.vex.guest_XSP;
147    sc->pc = tst->arch.vex.guest_PC;
148    sc->pstate = 0; /* slack .. could do better */
149 
150    //sc->trap_no = trapno;
151    //sc->error_code = err;
152    sc->fault_address = (ULong)si->_sifields._sigfault._addr;
153 }
154 
155 
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)156 static void build_sigframe(ThreadState *tst,
157                            struct sigframe *frame,
158                            const vki_siginfo_t *siginfo,
159                            const struct vki_ucontext *siguc,
160                            void *handler, UInt flags,
161                            const vki_sigset_t *mask,
162                            void *restorer)
163 {
164    UWord trapno;
165    UWord err;
166    Int   sigNo = siginfo->si_signo;
167    struct vg_sig_private *priv = &frame->vp;
168 
169    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
170              (Addr)frame, offsetof(struct sigframe, vp));
171 
172    if (siguc) {
173       trapno = 0; //siguc->uc_mcontext.trap_no;
174       err = 0; //siguc->uc_mcontext.error_code;
175    } else {
176       trapno = 0;
177       err = 0;
178    }
179 
180    synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
181 
182    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
183              (Addr)frame, offsetof(struct sigframe, vp));
184 
185    priv->magicPI = 0x31415927;
186    priv->sigNo_private = sigNo;
187    priv->vex         = tst->arch.vex;
188    priv->vex_shadow1 = tst->arch.vex_shadow1;
189    priv->vex_shadow2 = tst->arch.vex_shadow2;
190 }
191 
192 
193 /* EXPORTED */
VG_(sigframe_create)194 void VG_(sigframe_create)( ThreadId tid,
195                            Addr sp_top_of_frame,
196                            const vki_siginfo_t *siginfo,
197                            const struct vki_ucontext *siguc,
198                            void *handler,
199                            UInt flags,
200                            const vki_sigset_t *mask,
201                            void *restorer )
202 {
203    ThreadState *tst;
204    Addr sp    = sp_top_of_frame;
205    Int  sigNo = siginfo->si_signo;
206    UInt size;
207 
208    tst = VG_(get_ThreadState)(tid);
209 
210    size = sizeof(struct rt_sigframe);
211 
212    sp -= size;
213    sp = VG_ROUNDDN(sp, 16);
214 
215    if (!extend(tst, sp, size))
216       return; // Give up.  No idea if this is correct
217 
218    struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
219 
220    /* Track our writes to siginfo */
221    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
222              "signal handler siginfo", (Addr)rsf,
223              offsetof(struct rt_sigframe, sig));
224 
225    VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
226 
227    if (sigNo == VKI_SIGILL && siginfo->si_code > 0) {
228       rsf->info._sifields._sigfault._addr
229         = (Addr*)(tst)->arch.vex.guest_PC;
230    }
231    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
232          (Addr)rsf, offsetof(struct rt_sigframe, sig));
233 
234    build_sigframe(tst, &rsf->sig, siginfo, siguc,
235                        handler, flags, mask, restorer);
236    tst->arch.vex.guest_X1 = (Addr)&rsf->info;
237    tst->arch.vex.guest_X2 = (Addr)&rsf->sig.uc;
238 
239    VG_(set_SP)(tid, sp);
240    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
241              sizeof(Addr));
242    tst->arch.vex.guest_X0 = sigNo;
243 
244    if (flags & VKI_SA_RESTORER)
245        tst->arch.vex.guest_X30 = (Addr)restorer;
246    else
247        tst->arch.vex.guest_X30
248           = (Addr)&VG_(arm64_linux_SUBST_FOR_rt_sigreturn);
249 
250    tst->arch.vex.guest_PC = (Addr)handler;
251 }
252 
253 
254 /*------------------------------------------------------------*/
255 /*--- Destroying signal frames                             ---*/
256 /*------------------------------------------------------------*/
257 
258 /* EXPORTED */
VG_(sigframe_destroy)259 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
260 {
261    ThreadState *tst;
262    struct vg_sig_private *priv;
263    Addr sp;
264    UInt frame_size;
265 //ZZ    struct vki_sigcontext *mc;
266    Int sigNo;
267    Bool has_siginfo = isRT;
268 
269    vg_assert(VG_(is_valid_tid)(tid));
270    tst = VG_(get_ThreadState)(tid);
271    sp = tst->arch.vex.guest_XSP;
272 
273 //ZZ    if (has_siginfo) {
274       struct rt_sigframe *frame = (struct rt_sigframe *)sp;
275       frame_size = sizeof(*frame);
276       //mc = &frame->sig.uc.uc_mcontext;
277       priv = &frame->sig.vp;
278       vg_assert(priv->magicPI == 0x31415927);
279       tst->sig_mask = frame->sig.uc.uc_sigmask;
280 //ZZ    } else {
281 //ZZ       struct sigframe *frame = (struct sigframe *)sp;
282 //ZZ       frame_size = sizeof(*frame);
283 //ZZ       mc = &frame->uc.uc_mcontext;
284 //ZZ       priv = &frame->vp;
285 //ZZ       vg_assert(priv->magicPI == 0x31415927);
286 //ZZ       tst->sig_mask = frame->uc.uc_sigmask;
287 //ZZ       //VG_(printf)("Setting signmask to %08x%08x\n",
288 //ZZ       //            tst->sig_mask[0],tst->sig_mask[1]);
289 //ZZ    }
290    tst->tmp_sig_mask = tst->sig_mask;
291 
292    sigNo = priv->sigNo_private;
293 
294 //ZZ     //XXX: restore regs
295 //ZZ #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
296 //ZZ    REST(r0,R0);
297 //ZZ    REST(r1,R1);
298 //ZZ    REST(r2,R2);
299 //ZZ    REST(r3,R3);
300 //ZZ    REST(r4,R4);
301 //ZZ    REST(r5,R5);
302 //ZZ    REST(r6,R6);
303 //ZZ    REST(r7,R7);
304 //ZZ    REST(r8,R8);
305 //ZZ    REST(r9,R9);
306 //ZZ    REST(r10,R10);
307 //ZZ    REST(fp,R11);
308 //ZZ    REST(ip,R12);
309 //ZZ    REST(sp,R13);
310 //ZZ    REST(lr,R14);
311 //ZZ    REST(pc,R15T);
312 //ZZ #  undef REST
313 
314    /* Uh, the next line makes all the REST() above pointless. */
315    tst->arch.vex         = priv->vex;
316 
317    tst->arch.vex_shadow1 = priv->vex_shadow1;
318    tst->arch.vex_shadow2 = priv->vex_shadow2;
319 
320    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
321              frame_size + VG_STACK_REDZONE_SZB );
322 
323    if (VG_(clo_trace_signals))
324       VG_(message)(Vg_DebugMsg,
325                    "vg_pop_signal_frame (thread %d): "
326                    "isRT=%d valid magic; PC=%#llx\n",
327                    tid, has_siginfo, tst->arch.vex.guest_PC);
328 
329    /* tell the tools */
330    VG_TRACK( post_deliver_signal, tid, sigNo );
331 }
332 
333 #endif // defined(VGP_arm_linux)
334 
335 /*--------------------------------------------------------------------*/
336 /*--- end                                   sigframe-arm64-linux.c ---*/
337 /*--------------------------------------------------------------------*/
338