1
2/*--------------------------------------------------------------------*/
3/*--- Create/destroy signal delivery frames.                       ---*/
4/*---                                       sigframe-ppc64-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
16   This program is free software; you can redistribute it and/or
17   modify it under the terms of the GNU General Public License as
18   published by the Free Software Foundation; either version 2 of the
19   License, or (at your option) any later version.
20
21   This program is distributed in the hope that it will be useful, but
22   WITHOUT ANY WARRANTY; without even the implied warranty of
23   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24   General Public License for more details.
25
26   You should have received a copy of the GNU General Public License
27   along with this program; if not, write to the Free Software
28   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29   02111-1307, USA.
30
31   The GNU General Public License is contained in the file COPYING.
32*/
33
34#if defined(VGP_ppc64_linux)
35
36#include "pub_core_basics.h"
37#include "pub_core_vki.h"
38#include "pub_core_vkiscnums.h"
39#include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
40#include "pub_core_threadstate.h"
41#include "pub_core_aspacemgr.h"
42#include "pub_core_libcbase.h"
43#include "pub_core_libcassert.h"
44#include "pub_core_libcprint.h"
45#include "pub_core_machine.h"
46#include "pub_core_options.h"
47#include "pub_core_sigframe.h"
48#include "pub_core_signals.h"
49#include "pub_core_tooliface.h"
50#include "pub_core_trampoline.h"
51#include "pub_core_transtab.h"      // VG_(discard_translations)
52
53
54/* This module creates and removes signal frames for signal deliveries
55   on ppc64-linux.
56
57   Note, this file contains kernel-specific knowledge in the form of
58   'struct sigframe' and 'struct rt_sigframe'.  How does that relate
59   to the vki kernel interface stuff?
60
61   Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
62   onto the client's stack.  This contains a subsidiary
63   vki_ucontext.  That holds the vcpu's state across the signal,
64   so that the sighandler can mess with the vcpu state if it
65   really wants.
66
67   FIXME: sigcontexting is basically broken for the moment.  When
68   delivering a signal, the integer registers and %eflags are
69   correctly written into the sigcontext, however the FP and SSE state
70   is not.  When returning from a signal, only the integer registers
71   are restored from the sigcontext; the rest of the CPU state is
72   restored to what it was before the signal.
73
74   This will be fixed.
75*/
76
77
78/*------------------------------------------------------------*/
79/*--- Signal frame layouts                                 ---*/
80/*------------------------------------------------------------*/
81
82// A structure in which to save the application's registers
83// during the execution of signal handlers.
84
85// On ppc64-linux, rt_sigframe is used for all signals.
86
87// In theory, so long as we get the arguments to the handler function
88// right, it doesn't matter what the exact layout of the rest of the
89// frame is.  Unfortunately, things like gcc's exception unwinding
90// make assumptions about the locations of various parts of the frame,
91// so we need to duplicate it exactly.
92
93/* Many of these byzantine details derived from
94   linux-2.6.13/arch/ppc64/kernel/signal.c */
95
96#define TRAMP_SIZE 6 /* who knows why - it only needs to be 2. */
97
98/* Structure containing bits of information that we want to save
99   on signal delivery. */
100struct vg_sig_private {
101   UInt  magicPI;
102   UInt  sigNo_private;
103   ULong _unused; /* makes the struct size be zero % 16 */
104   VexGuestPPC64State vex_shadow1;
105   VexGuestPPC64State vex_shadow2;
106};
107
108/* Structure put on stack for all signal handlers. */
109struct rt_sigframe {
110   struct vki_ucontext   uc;
111   ULong                 _unused[2];
112   UInt                  tramp[TRAMP_SIZE];
113   struct vki_siginfo*   pinfo;
114   void*                 puc;
115   vki_siginfo_t         info;
116   struct vg_sig_private priv;
117   UChar                 abigap[288];
118};
119
120#define SET_SIGNAL_LR(zztst, zzval)                          \
121   do { tst->arch.vex.guest_LR = (zzval);                    \
122      VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
123                offsetof(VexGuestPPC64State,guest_LR),       \
124                sizeof(UWord) );                             \
125   } while (0)
126
127#define SET_SIGNAL_GPR(zztst, zzn, zzval)                    \
128   do { tst->arch.vex.guest_GPR##zzn = (zzval);              \
129      VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
130                offsetof(VexGuestPPC64State,guest_GPR##zzn), \
131                sizeof(UWord) );                             \
132   } while (0)
133
134
135/* Extend the stack segment downwards if needed so as to ensure the
136   new signal frames are mapped to something.  Return a Bool
137   indicating whether or not the operation was successful.
138*/
139static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
140{
141   ThreadId        tid = tst->tid;
142   NSegment const* stackseg = NULL;
143
144   if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
145      stackseg = VG_(am_find_nsegment)(addr);
146      if (0 && stackseg)
147	 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
148		     addr, stackseg->start, stackseg->end);
149   }
150
151   if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
152      VG_(message)(
153         Vg_UserMsg,
154         "Can't extend stack to %#lx during signal delivery for thread %d:\n",
155         addr, tid);
156      if (stackseg == NULL)
157         VG_(message)(Vg_UserMsg, "  no stack segment\n");
158      else
159         VG_(message)(Vg_UserMsg, "  too small or bad protection modes\n");
160
161      /* set SIGSEGV to default handler */
162      VG_(set_default_handler)(VKI_SIGSEGV);
163      VG_(synth_fault_mapping)(tid, addr);
164
165      /* The whole process should be about to die, since the default
166	 action of SIGSEGV to kill the whole process. */
167      return False;
168   }
169
170   /* For tracking memory events, indicate the entire frame has been
171      allocated. */
172   VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
173             size + VG_STACK_REDZONE_SZB, tid );
174
175   return True;
176}
177
178
179/* EXPORTED */
180void VG_(sigframe_create)( ThreadId tid,
181                           Addr sp_top_of_frame,
182                           const vki_siginfo_t *siginfo,
183                           const struct vki_ucontext *siguc,
184                           void *handler,
185                           UInt flags,
186                           const vki_sigset_t *mask,
187		           void *restorer )
188{
189   struct vg_sig_private* priv;
190   Addr sp;
191   ThreadState* tst;
192   Int sigNo = siginfo->si_signo;
193   /* Addr faultaddr; */ /* UNUSED */
194   struct rt_sigframe* frame;
195
196   /* Stack must be 16-byte aligned */
197   vg_assert(VG_IS_16_ALIGNED(sizeof(struct vg_sig_private)));
198   vg_assert(VG_IS_16_ALIGNED(sizeof(struct rt_sigframe)));
199
200   sp_top_of_frame &= ~0xf;
201   sp = sp_top_of_frame - sizeof(struct rt_sigframe);
202
203   tst = VG_(get_ThreadState)(tid);
204   if (!extend(tst, sp, sp_top_of_frame - sp))
205      return;
206
207   vg_assert(VG_IS_16_ALIGNED(sp));
208
209   frame = (struct rt_sigframe *) sp;
210
211   /* clear it (conservatively) */
212   VG_(memset)(frame, 0, sizeof(*frame));
213
214   /////////
215   frame->pinfo = &frame->info;
216   frame->puc = &frame->uc;
217
218   frame->uc.uc_flags = 0;
219   frame->uc.uc_link = 0;
220   /////////
221
222   /* Set up the stack chain pointer */
223   VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
224             sp, sizeof(UWord) );
225   *(Addr *)sp = tst->arch.vex.guest_GPR1;
226   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
227             sp, sizeof(UWord) );
228
229   /* UNUSED:
230   faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
231   if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
232      faultaddr = tst->arch.vex.guest_CIA;
233   */
234
235   VG_(memcpy)(&frame->info, siginfo, sizeof(*siginfo));
236   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
237             (Addr)&frame->info, sizeof(frame->info) );
238
239   frame->uc.uc_flags = 0;
240   frame->uc.uc_link  = 0;
241   frame->uc.uc_stack = tst->altstack;
242   frame->uc.uc_sigmask = tst->sig_mask;
243   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
244             (Addr)(&frame->uc), sizeof(frame->uc) );
245
246#  define DO(gpr)  frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr] \
247                      = tst->arch.vex.guest_GPR##gpr
248   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
249   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
250   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
251   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
252#  undef DO
253
254   frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP]     = tst->arch.vex.guest_CIA;
255   frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR]     = 0xf032;   /* pretty arbitrary */
256   frame->uc.uc_mcontext.gp_regs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
257   frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR]     = tst->arch.vex.guest_CTR;
258   frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK]     = tst->arch.vex.guest_LR;
259   frame->uc.uc_mcontext.gp_regs[VKI_PT_XER]     = LibVEX_GuestPPC64_get_XER(
260                                                      &tst->arch.vex);
261   frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR]     = LibVEX_GuestPPC64_get_CR(
262                                                      &tst->arch.vex);
263   //mc->mc_gregs[VKI_PT_MQ]      = 0;
264   //mc->mc_gregs[VKI_PT_TRAP]    = 0;
265   //mc->mc_gregs[VKI_PT_DAR]     = fault_addr;
266   //mc->mc_gregs[VKI_PT_DSISR]   = 0;
267   //mc->mc_gregs[VKI_PT_RESULT]  = 0;
268
269   /* XXX should do FP and vector regs */
270
271   /* set up signal return trampoline */
272   /* NB.  5 Sept 07.  mc->mc_pad[0..1] used to contain a the code to
273      which the signal handler returns, and it just did sys_sigreturn
274      or sys_rt_sigreturn.  But this doesn't work if the stack is
275      non-executable, and it isn't consistent with the x86-linux and
276      amd64-linux scheme for removing the stack frame.  So instead be
277      consistent and use a stub in m_trampoline.  Then it doesn't
278      matter whether or not the (guest) stack is executable.  This
279      fixes #149519 and #145837. */
280   frame->tramp[0] = 0; /* invalid */
281   frame->tramp[1] = 0; /* invalid */
282   VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid,
283            (Addr)&frame->tramp, sizeof(frame->tramp));
284
285   /* invalidate any translation of this area */
286   VG_(discard_translations)( (Addr64)&frame->tramp[0],
287                              sizeof(frame->tramp), "stack_mcontext" );
288
289   /* set the signal handler to return to the trampoline */
290   SET_SIGNAL_LR(tst, (Addr)&VG_(ppc64_linux_SUBST_FOR_rt_sigreturn));
291
292   /* Stack pointer for the handler .. (note, back chain set
293      earlier) */
294   SET_SIGNAL_GPR(tid, 1, sp);
295
296   /* Args for the handler .. */
297   SET_SIGNAL_GPR(tid, 3, sigNo);
298   SET_SIGNAL_GPR(tid, 4, (Addr) &frame->info);
299   SET_SIGNAL_GPR(tid, 5, (Addr) &frame->uc);
300   /* the kernel sets this, though it doesn't seem to be in the ABI */
301   SET_SIGNAL_GPR(tid, 6, (Addr) &frame->info);
302
303   /* Handler is in fact a standard ppc64-linux function descriptor,
304      so extract the function entry point and also the toc ptr to use. */
305   SET_SIGNAL_GPR(tid, 2, (Addr) ((ULong*)handler)[1]);
306   tst->arch.vex.guest_CIA = (Addr) ((ULong*)handler)[0];
307
308   priv = &frame->priv;
309   priv->magicPI       = 0x31415927;
310   priv->sigNo_private = sigNo;
311   priv->vex_shadow1   = tst->arch.vex_shadow1;
312   priv->vex_shadow2   = tst->arch.vex_shadow2;
313
314   if (0)
315      VG_(printf)("pushed signal frame; %%R1 now = %#lx, "
316                  "next %%CIA = %#llx, status=%d\n",
317		  sp, tst->arch.vex.guest_CIA, tst->status);
318}
319
320
321/*------------------------------------------------------------*/
322/*--- Destroying signal frames                             ---*/
323/*------------------------------------------------------------*/
324
325/* EXPORTED */
326void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
327{
328   ThreadState *tst;
329   struct vg_sig_private *priv;
330   Addr sp;
331   UInt frame_size;
332   struct rt_sigframe *frame;
333   Int sigNo;
334   Bool has_siginfo = isRT;
335
336   vg_assert(VG_(is_valid_tid)(tid));
337   tst = VG_(get_ThreadState)(tid);
338
339   /* Check that the stack frame looks valid */
340   sp = tst->arch.vex.guest_GPR1;
341   vg_assert(VG_IS_16_ALIGNED(sp));
342   /* JRS 17 Nov 05: This code used to check that *sp -- which should
343      have been set by the stwu at the start of the handler -- points
344      to just above the frame (ie, the previous frame).  However, that
345      isn't valid when delivering signals on alt stacks.  So I removed
346      it.  The frame is still sanity-checked using the priv->magicPI
347      field. */
348
349   frame = (struct rt_sigframe *)sp;
350   frame_size = sizeof(*frame);
351   priv = &frame->priv;
352   vg_assert(priv->magicPI == 0x31415927);
353   tst->sig_mask = frame->uc.uc_sigmask;
354   tst->tmp_sig_mask = tst->sig_mask;
355
356   sigNo = priv->sigNo_private;
357
358#  define DO(gpr)  tst->arch.vex.guest_GPR##gpr \
359                      = frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr]
360   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
361   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
362   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
363   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
364#  undef DO
365
366   tst->arch.vex.guest_CIA = frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP];
367
368   LibVEX_GuestPPC64_put_CR( frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR],
369                             &tst->arch.vex );
370
371   tst->arch.vex.guest_LR  = frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK];
372   tst->arch.vex.guest_CTR = frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR];
373   LibVEX_GuestPPC64_put_XER( frame->uc.uc_mcontext.gp_regs[VKI_PT_XER],
374                              &tst->arch.vex );
375
376   tst->arch.vex_shadow1 = priv->vex_shadow1;
377   tst->arch.vex_shadow2 = priv->vex_shadow2;
378
379   VG_TRACK(die_mem_stack_signal, sp, frame_size);
380
381   if (VG_(clo_trace_signals))
382      VG_(message)(Vg_DebugMsg,
383                   "vg_pop_signal_frame (thread %d): isRT=%d "
384                   "valid magic; EIP=%#llx\n",
385                   tid, has_siginfo, tst->arch.vex.guest_CIA);
386
387   /* tell the tools */
388   VG_TRACK( post_deliver_signal, tid, sigNo );
389}
390
391#endif // defined(VGP_ppc64_linux)
392
393/*--------------------------------------------------------------------*/
394/*--- end                                                          ---*/
395/*--------------------------------------------------------------------*/
396