1
2/*--------------------------------------------------------------------*/
3/*--- Create/destroy signal delivery frames.                       ---*/
4/*---                                       sigframe-ppc32-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_ppc32_linux)
35
36#include "pub_core_basics.h"
37#include "pub_core_vki.h"
38#include "pub_core_vkiscnums.h"
39#include "pub_core_threadstate.h"
40#include "pub_core_aspacemgr.h"
41#include "pub_core_libcbase.h"
42#include "pub_core_libcassert.h"
43#include "pub_core_libcprint.h"
44#include "pub_core_machine.h"
45#include "pub_core_options.h"
46#include "pub_core_sigframe.h"
47#include "pub_core_signals.h"
48#include "pub_core_tooliface.h"
49#include "pub_core_trampoline.h"
50#include "pub_core_transtab.h"      // VG_(discard_translations)
51#include "priv_sigframe.h"
52
53/* This module creates and removes signal frames for signal deliveries
54   on ppc32-linux.
55
56   Note, this file contains kernel-specific knowledge in the form of
57   'struct sigframe' and 'struct rt_sigframe'.  How does that relate
58   to the vki kernel interface stuff?
59
60   Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
61   onto the client's stack.  This contains a subsidiary
62   vki_ucontext.  That holds the vcpu's state across the signal,
63   so that the sighandler can mess with the vcpu state if it
64   really wants.
65
66   FIXME: sigcontexting is basically broken for the moment.  When
67   delivering a signal, the integer registers and %eflags are
68   correctly written into the sigcontext, however the FP and SSE state
69   is not.  When returning from a signal, only the integer registers
70   are restored from the sigcontext; the rest of the CPU state is
71   restored to what it was before the signal.
72
73   This will be fixed.
74*/
75
76
77/*------------------------------------------------------------*/
78/*--- Signal frame layouts                                 ---*/
79/*------------------------------------------------------------*/
80
81// A structure in which to save the application's registers
82// during the execution of signal handlers.
83
84// Linux has 2 signal frame structures: one for normal signal
85// deliveries, and one for SA_SIGINFO deliveries (also known as RT
86// signals).
87//
88// In theory, so long as we get the arguments to the handler function
89// right, it doesn't matter what the exact layout of the rest of the
90// frame is.  Unfortunately, things like gcc's exception unwinding
91// make assumptions about the locations of various parts of the frame,
92// so we need to duplicate it exactly.
93
94/* Structure containing bits of information that we want to save
95   on signal delivery. */
96struct vg_sig_private {
97   UInt magicPI;
98   UInt sigNo_private;
99   VexGuestPPC32State vex_shadow1;
100   VexGuestPPC32State vex_shadow2;
101};
102
103/* Structure put on stack for signal handlers with SA_SIGINFO clear. */
104struct nonrt_sigframe {
105   UInt gap1[16];
106   struct vki_sigcontext sigcontext;
107   struct vki_mcontext mcontext;
108   struct vg_sig_private priv;
109   unsigned char abigap[224];    // unused
110};
111
112/* Structure put on stack for signal handlers with SA_SIGINFO set. */
113struct rt_sigframe {
114   UInt gap1[20];
115   vki_siginfo_t siginfo;
116   struct vki_ucontext ucontext;
117   struct vg_sig_private priv;
118   unsigned char abigap[224];    // unused
119};
120
121#define SET_SIGNAL_LR(zztst, zzval)                          \
122   do { tst->arch.vex.guest_LR = (zzval);                    \
123      VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
124                offsetof(VexGuestPPC32State,guest_LR),       \
125                sizeof(UWord) );                             \
126   } while (0)
127
128#define SET_SIGNAL_GPR(zztst, zzn, zzval)                    \
129   do { tst->arch.vex.guest_GPR##zzn = (zzval);              \
130      VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
131                offsetof(VexGuestPPC32State,guest_GPR##zzn), \
132                sizeof(UWord) );                             \
133   } while (0)
134
135
136static
137void stack_mcontext ( struct vki_mcontext *mc,
138                      ThreadState* tst,
139                      Bool use_rt_sigreturn,
140                      UInt fault_addr )
141{
142   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
143             (Addr)mc, sizeof(struct vki_pt_regs) );
144
145#  define DO(gpr)  mc->mc_gregs[VKI_PT_R0+gpr] = tst->arch.vex.guest_GPR##gpr
146   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
147   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
148   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
149   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
150#  undef DO
151
152   mc->mc_gregs[VKI_PT_NIP]     = tst->arch.vex.guest_CIA;
153   mc->mc_gregs[VKI_PT_MSR]     = 0xf032;   /* pretty arbitrary */
154   mc->mc_gregs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
155   mc->mc_gregs[VKI_PT_CTR]     = tst->arch.vex.guest_CTR;
156   mc->mc_gregs[VKI_PT_LNK]     = tst->arch.vex.guest_LR;
157   mc->mc_gregs[VKI_PT_XER]     = LibVEX_GuestPPC32_get_XER(&tst->arch.vex);
158   mc->mc_gregs[VKI_PT_CCR]     = LibVEX_GuestPPC32_get_CR(&tst->arch.vex);
159   mc->mc_gregs[VKI_PT_MQ]      = 0;
160   mc->mc_gregs[VKI_PT_TRAP]    = 0;
161   mc->mc_gregs[VKI_PT_DAR]     = fault_addr;
162   mc->mc_gregs[VKI_PT_DSISR]   = 0;
163   mc->mc_gregs[VKI_PT_RESULT]  = 0;
164   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
165             (Addr)mc, sizeof(struct vki_pt_regs) );
166
167   /* XXX should do FP and vector regs */
168
169   /* set up signal return trampoline */
170   /* NB.  5 Sept 07.  mc->mc_pad[0..1] used to contain a the code to
171      which the signal handler returns, and it just did sys_sigreturn
172      or sys_rt_sigreturn.  But this doesn't work if the stack is
173      non-executable, and it isn't consistent with the x86-linux and
174      amd64-linux scheme for removing the stack frame.  So instead be
175      consistent and use a stub in m_trampoline.  Then it doesn't
176      matter whether or not the (guest) stack is executable.  This
177      fixes #149519 and #145837. */
178   VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
179            (Addr)&mc->mc_pad, sizeof(mc->mc_pad));
180   mc->mc_pad[0] = 0; /* invalid */
181   mc->mc_pad[1] = 0; /* invalid */
182   VG_TRACK( post_mem_write,  Vg_CoreSignal, tst->tid,
183             (Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
184   /* invalidate any translation of this area */
185   VG_(discard_translations)( (Addr)&mc->mc_pad,
186                              sizeof(mc->mc_pad), "stack_mcontext" );
187
188   /* set the signal handler to return to the trampoline */
189   SET_SIGNAL_LR(tst, (Addr)(use_rt_sigreturn
190                               ? (Addr)&VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
191                               : (Addr)&VG_(ppc32_linux_SUBST_FOR_sigreturn)
192                      ));
193}
194
195//:: /* Valgrind-specific parts of the signal frame */
196//:: struct vg_sigframe
197//:: {
198//::    /* Sanity check word. */
199//::    UInt magicPI;
200//::
201//::    UInt handlerflags;	/* flags for signal handler */
202//::
203//::
204//::    /* Safely-saved version of sigNo, as described above. */
205//::    Int  sigNo_private;
206//::
207//::    /* XXX This is wrong.  Surely we should store the shadow values
208//::       into the shadow memory behind the actual values? */
209//::    VexGuestPPC32State vex_shadow;
210//::
211//::    /* HACK ALERT */
212//::    VexGuestPPC32State vex;
213//::    /* end HACK ALERT */
214//::
215//::    /* saved signal mask to be restored when handler returns */
216//::    vki_sigset_t	mask;
217//::
218//::    /* Sanity check word.  Is the highest-addressed word; do not
219//::       move!*/
220//::    UInt magicE;
221//:: };
222//::
223//:: struct sigframe
224//:: {
225//::    /* Sig handler's return address */
226//::    Addr retaddr;
227//::    Int  sigNo;
228//::
229//::    struct vki_sigcontext sigContext;
230//:: //..    struct _vki_fpstate fpstate;
231//::
232//::    struct vg_sigframe vg;
233//:: };
234//::
235//:: struct rt_sigframe
236//:: {
237//::    /* Sig handler's return address */
238//::    Addr retaddr;
239//::    Int  sigNo;
240//::
241//::    /* ptr to siginfo_t. */
242//::    Addr psigInfo;
243//::
244//::    /* ptr to ucontext */
245//::    Addr puContext;
246//::    /* pointed to by psigInfo */
247//::    vki_siginfo_t sigInfo;
248//::
249//::    /* pointed to by puContext */
250//::    struct vki_ucontext uContext;
251//:: //..    struct _vki_fpstate fpstate;
252//::
253//::    struct vg_sigframe vg;
254//:: };
255
256
257//:: /*------------------------------------------------------------*/
258//:: /*--- Signal operations                                    ---*/
259//:: /*------------------------------------------------------------*/
260//::
261//:: /*
262//::    Great gobs of FP state conversion taken wholesale from
263//::    linux/arch/i386/kernel/i387.c
264//::  */
265//::
266//:: /*
267//::  * FXSR floating point environment conversions.
268//::  */
269//:: #define X86_FXSR_MAGIC		0x0000
270//::
271//:: /*
272//::  * FPU tag word conversions.
273//::  */
274//::
275//:: static inline unsigned short twd_i387_to_fxsr( unsigned short twd )
276//:: {
277//::    unsigned int tmp; /* to avoid 16 bit prefixes in the code */
278//::
279//::    /* Transform each pair of bits into 01 (valid) or 00 (empty) */
280//::    tmp = ~twd;
281//::    tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
282//::    /* and move the valid bits to the lower byte. */
283//::    tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
284//::    tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
285//::    tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
286//::    return tmp;
287//:: }
288//::
289//:: static unsigned long twd_fxsr_to_i387( const struct i387_fxsave_struct *fxsave )
290//:: {
291//::    struct _vki_fpxreg *st = NULL;
292//::    unsigned long twd = (unsigned long) fxsave->twd;
293//::    unsigned long tag;
294//::    unsigned long ret = 0xffff0000u;
295//::    int i;
296//::
297//:: #define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16);
298//::
299//::    for ( i = 0 ; i < 8 ; i++ ) {
300//::       if ( twd & 0x1 ) {
301//:: 	 st = (struct _vki_fpxreg *) FPREG_ADDR( fxsave, i );
302//::
303//:: 	 switch ( st->exponent & 0x7fff ) {
304//:: 	 case 0x7fff:
305//:: 	    tag = 2;		/* Special */
306//:: 	    break;
307//:: 	 case 0x0000:
308//:: 	    if ( !st->significand[0] &&
309//:: 		 !st->significand[1] &&
310//:: 		 !st->significand[2] &&
311//:: 		 !st->significand[3] ) {
312//:: 	       tag = 1;	/* Zero */
313//:: 	    } else {
314//:: 	       tag = 2;	/* Special */
315//:: 	    }
316//:: 	    break;
317//:: 	 default:
318//:: 	    if ( st->significand[3] & 0x8000 ) {
319//:: 	       tag = 0;	/* Valid */
320//:: 	    } else {
321//:: 	       tag = 2;	/* Special */
322//:: 	    }
323//:: 	    break;
324//:: 	 }
325//::       } else {
326//:: 	 tag = 3;			/* Empty */
327//::       }
328//::       ret |= (tag << (2 * i));
329//::       twd = twd >> 1;
330//::    }
331//::    return ret;
332//:: }
333//::
334//:: static void convert_fxsr_to_user( struct _vki_fpstate *buf,
335//:: 				  const struct i387_fxsave_struct *fxsave )
336//:: {
337//::    unsigned long env[7];
338//::    struct _vki_fpreg *to;
339//::    struct _vki_fpxreg *from;
340//::    int i;
341//::
342//::    env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
343//::    env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
344//::    env[2] = twd_fxsr_to_i387(fxsave);
345//::    env[3] = fxsave->fip;
346//::    env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
347//::    env[5] = fxsave->foo;
348//::    env[6] = fxsave->fos;
349//::
350//::    VG_(memcpy)(buf, env, 7 * sizeof(unsigned long));
351//::
352//::    to = &buf->_st[0];
353//::    from = (struct _vki_fpxreg *) &fxsave->st_space[0];
354//::    for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
355//::       unsigned long __user *t = (unsigned long __user *)to;
356//::       unsigned long *f = (unsigned long *)from;
357//::
358//::       t[0] = f[0];
359//::       t[1] = f[1];
360//::       to->exponent = from->exponent;
361//::    }
362//:: }
363//::
364//:: static void convert_fxsr_from_user( struct i387_fxsave_struct *fxsave,
365//:: 				    const struct _vki_fpstate *buf )
366//:: {
367//::    unsigned long env[7];
368//::    struct _vki_fpxreg *to;
369//::    const struct _vki_fpreg *from;
370//::    int i;
371//::
372//::    VG_(memcpy)(env, buf, 7 * sizeof(long));
373//::
374//::    fxsave->cwd = (unsigned short)(env[0] & 0xffff);
375//::    fxsave->swd = (unsigned short)(env[1] & 0xffff);
376//::    fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
377//::    fxsave->fip = env[3];
378//::    fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
379//::    fxsave->fcs = (env[4] & 0xffff);
380//::    fxsave->foo = env[5];
381//::    fxsave->fos = env[6];
382//::
383//::    to = (struct _vki_fpxreg *) &fxsave->st_space[0];
384//::    from = &buf->_st[0];
385//::    for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
386//::       unsigned long *t = (unsigned long *)to;
387//::       unsigned long __user *f = (unsigned long __user *)from;
388//::
389//::       t[0] = f[0];
390//::       t[1] = f[1];
391//::       to->exponent = from->exponent;
392//::    }
393//:: }
394//::
395//:: static inline void save_i387_fsave( arch_thread_t *regs, struct _vki_fpstate *buf )
396//:: {
397//::    struct i387_fsave_struct *fs = &regs->m_sse.fsave;
398//::
399//::    fs->status = fs->swd;
400//::    VG_(memcpy)(buf, fs, sizeof(*fs));
401//:: }
402//::
403//:: static void save_i387_fxsave( arch_thread_t *regs, struct _vki_fpstate *buf )
404//:: {
405//::    const struct i387_fxsave_struct *fx = &regs->m_sse.fxsave;
406//::    convert_fxsr_to_user( buf, fx );
407//::
408//::    buf->status = fx->swd;
409//::    buf->magic = X86_FXSR_MAGIC;
410//::    VG_(memcpy)(buf->_fxsr_env, fx, sizeof(struct i387_fxsave_struct));
411//:: }
412//::
413//:: static void save_i387( arch_thread_t *regs, struct _vki_fpstate *buf )
414//:: {
415//::    if ( VG_(have_ssestate) )
416//::       save_i387_fxsave( regs, buf );
417//::    else
418//::       save_i387_fsave( regs, buf );
419//:: }
420//::
421//:: static inline void restore_i387_fsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
422//:: {
423//::    VG_(memcpy)( &regs->m_sse.fsave, buf, sizeof(struct i387_fsave_struct) );
424//:: }
425//::
426//:: static void restore_i387_fxsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
427//:: {
428//::    VG_(memcpy)(&regs->m_sse.fxsave, &buf->_fxsr_env[0],
429//:: 	       sizeof(struct i387_fxsave_struct) );
430//::    /* mxcsr reserved bits must be masked to zero for security reasons */
431//::    regs->m_sse.fxsave.mxcsr &= 0xffbf;
432//::    convert_fxsr_from_user( &regs->m_sse.fxsave, buf );
433//:: }
434//::
435//:: static void restore_i387( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
436//:: {
437//::    if ( VG_(have_ssestate) ) {
438//::       restore_i387_fxsave( regs, buf );
439//::    } else {
440//::       restore_i387_fsave( regs, buf );
441//::    }
442//:: }
443
444
445
446
447/*------------------------------------------------------------*/
448/*--- Creating signal frames                               ---*/
449/*------------------------------------------------------------*/
450
451//.. /* Create a plausible-looking sigcontext from the thread's
452//..    Vex guest state.  NOTE: does not fill in the FP or SSE
453//..    bits of sigcontext at the moment.
454//.. */
455//.. static
456//.. void synth_ucontext(ThreadId tid, const vki_siginfo_t *si,
457//..                     const vki_sigset_t *set, struct vki_ucontext *uc)
458//.. {
459//..    ThreadState *tst = VG_(get_ThreadState)(tid);
460//..    struct vki_sigcontext *sc = &uc->uc_mcontext;
461//..
462//..    VG_(memset)(uc, 0, sizeof(*uc));
463//..
464//..    uc->uc_flags = 0;
465//..    uc->uc_link = 0;
466//..    uc->uc_sigmask = *set;
467//..    uc->uc_stack = tst->altstack;
468//..    sc->fpstate = fpstate;
469//..
470//..    // FIXME: save_i387(&tst->arch, fpstate);
471//..
472//.. #  define SC2(reg,REG)  sc->reg = tst->arch.vex.guest_##REG
473//..    SC2(gs,GS);
474//..    SC2(fs,FS);
475//..    SC2(es,ES);
476//..    SC2(ds,DS);
477//..
478//..    SC2(edi,EDI);
479//..    SC2(esi,ESI);
480//..    SC2(ebp,EBP);
481//..    SC2(esp,ESP);
482//..    SC2(ebx,EBX);
483//..    SC2(edx,EDX);
484//..    SC2(ecx,ECX);
485//..    SC2(eax,EAX);
486//..
487//..    SC2(eip,EIP);
488//..    SC2(cs,CS);
489//..    sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex);
490//..    SC2(ss,SS);
491//..    /* XXX esp_at_signal */
492//..    /* XXX trapno */
493//..    /* XXX err */
494//.. #  undef SC2
495//..
496//..    sc->cr2 = (UInt)si->_sifields._sigfault._addr;
497//.. }
498/*
499//.. #define SET_SIGNAL_ESP(zztid, zzval) \
500//..    SET_THREAD_REG(zztid, zzval, STACK_PTR, post_reg_write, \
501//..                   Vg_CoreSignal, zztid, VG_O_STACK_PTR, sizeof(Addr))
502*/
503
504
505//.. /* Build the Valgrind-specific part of a signal frame. */
506//..
507//.. static void build_vg_sigframe(struct vg_sigframe *frame,
508//.. 			      ThreadState *tst,
509//.. 			      const vki_sigset_t *mask,
510//.. 			      UInt flags,
511//.. 			      Int sigNo)
512//.. {
513//..    frame->sigNo_private = sigNo;
514//..    frame->magicPI       = 0x31415927;
515//..    frame->vex_shadow    = tst->arch.vex_shadow;
516//..    /* HACK ALERT */
517//..    frame->vex           = tst->arch.vex;
518//..    /* end HACK ALERT */
519//..    frame->mask          = tst->sig_mask;
520//..    frame->handlerflags  = flags;
521//..    frame->magicE        = 0x27182818;
522//.. }
523
524
525//.. static Addr build_sigframe(ThreadState *tst,
526//.. 			   Addr esp_top_of_frame,
527//.. 			   const vki_siginfo_t *siginfo,
528//.. 			   void *handler, UInt flags,
529//.. 			   const vki_sigset_t *mask,
530//.. 			   void *restorer)
531//.. {
532//..    struct sigframe *frame;
533//..    Addr esp = esp_top_of_frame;
534//..    Int	sigNo = siginfo->si_signo;
535//..    struct vki_ucontext uc;
536//..
537//..    vg_assert((flags & VKI_SA_SIGINFO) == 0);
538//..
539//..    esp -= sizeof(*frame);
540//..    esp = ROUNDDN(esp, 16);
541//..    frame = (struct sigframe *)esp;
542//..
543//..    if (!extend(tst, esp, sizeof(*frame)))
544//..       return esp_top_of_frame;
545//..
546//..    /* retaddr, sigNo, siguContext fields are to be written */
547//..    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
548//.. 	     esp, offsetof(struct sigframe, vg) );
549//..
550//..    frame->sigNo = sigNo;
551//..
552//..    if (flags & VKI_SA_RESTORER)
553//..       frame->retaddr = (Addr)restorer;
554//..    else
555//..       frame->retaddr
556//..          = VG_(client_trampoline_code)+VG_(tramp_sigreturn_offset);
557//..
558//..    synth_ucontext(tst->tid, siginfo, mask, &uc, &frame->fpstate);
559//..
560//..    VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext,
561//.. 	       sizeof(struct vki_sigcontext));
562//..    frame->sigContext.oldmask = mask->sig[0];
563//..
564//..    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
565//..              esp, offsetof(struct sigframe, vg) );
566//..
567//..    build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo);
568//..
569//..    return esp;
570//.. }
571
572
573//.. static Addr build_rt_sigframe(ThreadState *tst,
574//.. 			      Addr esp_top_of_frame,
575//.. 			      const vki_siginfo_t *siginfo,
576//.. 			      void *handler, UInt flags,
577//.. 			      const vki_sigset_t *mask,
578//.. 			      void *restorer)
579//.. {
580//..    struct rt_sigframe *frame;
581//..    Addr esp = esp_top_of_frame;
582//..    Int	sigNo = siginfo->si_signo;
583//..
584//..    vg_assert((flags & VKI_SA_SIGINFO) != 0);
585//..
586//..    esp -= sizeof(*frame);
587//..    esp = ROUNDDN(esp, 16);
588//..    frame = (struct rt_sigframe *)esp;
589//..
590//..    if (!extend(tst, esp, sizeof(*frame)))
591//..       return esp_top_of_frame;
592//..
593//..    /* retaddr, sigNo, pSiginfo, puContext fields are to be written */
594//..    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "rt signal handler frame",
595//.. 	     esp, offsetof(struct rt_sigframe, vg) );
596//..
597//..    frame->sigNo = sigNo;
598//..
599//..    if (flags & VKI_SA_RESTORER)
600//..       frame->retaddr = (Addr)restorer;
601//..    else
602//..       frame->retaddr
603//..          = VG_(client_trampoline_code)+VG_(tramp_rt_sigreturn_offset);
604//..
605//..    frame->psigInfo = (Addr)&frame->sigInfo;
606//..    frame->puContext = (Addr)&frame->uContext;
607//..    VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
608//..
609//..    /* SIGILL defines addr to be the faulting address */
610//..    if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
611//..       frame->sigInfo._sifields._sigfault._addr
612//..          = (void*)tst->arch.vex.guest_CIA;
613//..
614//..    synth_ucontext(tst->tid, siginfo, mask, &frame->uContext, &frame->fpstate);
615//..
616//..    VG_TRACK( post_mem_write,  Vg_CoreSignal, tst->tid,
617//..              esp, offsetof(struct rt_sigframe, vg) );
618//..
619//..    build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo);
620//..
621//..    return esp;
622//.. }
623
624
625/* EXPORTED */
626void VG_(sigframe_create)( ThreadId tid,
627                           Addr sp_top_of_frame,
628                           const vki_siginfo_t *siginfo,
629                           const struct vki_ucontext *siguc,
630                           void *handler,
631                           UInt flags,
632                           const vki_sigset_t *mask,
633		           void *restorer )
634{
635   struct vg_sig_private *priv;
636   Addr sp;
637   ThreadState *tst;
638   Int sigNo = siginfo->si_signo;
639   Addr faultaddr;
640
641   /* Stack must be 16-byte aligned */
642   sp_top_of_frame &= ~0xf;
643
644   if (flags & VKI_SA_SIGINFO) {
645      sp = sp_top_of_frame - sizeof(struct rt_sigframe);
646   } else {
647      sp = sp_top_of_frame - sizeof(struct nonrt_sigframe);
648   }
649
650   tst = VG_(get_ThreadState)(tid);
651
652   if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
653      return;
654
655   vg_assert(VG_IS_16_ALIGNED(sp));
656
657   /* Set up the stack chain pointer */
658   VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
659             sp, sizeof(UWord) );
660   *(Addr *)sp = tst->arch.vex.guest_GPR1;
661   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
662             sp, sizeof(UWord) );
663
664   faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
665   if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
666      faultaddr = tst->arch.vex.guest_CIA;
667
668   if (flags & VKI_SA_SIGINFO) {
669      struct rt_sigframe *frame = (struct rt_sigframe *) sp;
670      struct vki_ucontext *ucp = &frame->ucontext;
671
672      VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
673                (Addr)&frame->siginfo, sizeof(frame->siginfo) );
674      VG_(memcpy)(&frame->siginfo, siginfo, sizeof(*siginfo));
675      VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
676                (Addr)&frame->siginfo, sizeof(frame->siginfo) );
677
678      VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
679                (Addr)ucp, offsetof(struct vki_ucontext, uc_pad) );
680      ucp->uc_flags = 0;
681      ucp->uc_link = 0;
682      ucp->uc_stack = tst->altstack;
683      VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
684                offsetof(struct vki_ucontext, uc_pad) );
685
686      VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
687                (Addr)&ucp->uc_regs,
688                sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
689      ucp->uc_regs = &ucp->uc_mcontext;
690      ucp->uc_sigmask = tst->sig_mask;
691      VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
692                (Addr)&ucp->uc_regs,
693                sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
694
695      stack_mcontext(&ucp->uc_mcontext, tst, True/*use_rt_sigreturn*/, faultaddr);
696      priv = &frame->priv;
697
698      SET_SIGNAL_GPR(tid, 4, (Addr) &frame->siginfo);
699      SET_SIGNAL_GPR(tid, 5, (Addr) ucp);
700      /* the kernel sets this, though it doesn't seem to be in the ABI */
701      SET_SIGNAL_GPR(tid, 6, (Addr) &frame->siginfo);
702
703   } else {
704      /* non-RT signal delivery */
705      struct nonrt_sigframe *frame = (struct nonrt_sigframe *) sp;
706      struct vki_sigcontext *scp = &frame->sigcontext;
707
708      VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame sigcontext",
709                (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) );
710      scp->signal = sigNo;
711      scp->handler = (Addr) handler;
712      scp->oldmask = tst->sig_mask.sig[0];
713      scp->_unused[3] = tst->sig_mask.sig[1];
714      VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
715                (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) );
716
717      stack_mcontext(&frame->mcontext, tst, False/*!use_rt_sigreturn*/, faultaddr);
718      priv = &frame->priv;
719
720      SET_SIGNAL_GPR(tid, 4, (Addr) scp);
721   }
722
723   priv->magicPI       = 0x31415927;
724   priv->sigNo_private = sigNo;
725   priv->vex_shadow1   = tst->arch.vex_shadow1;
726   priv->vex_shadow2   = tst->arch.vex_shadow2;
727
728   SET_SIGNAL_GPR(tid, 1, sp);
729   SET_SIGNAL_GPR(tid, 3, sigNo);
730   tst->arch.vex.guest_CIA = (Addr) handler;
731
732//..    Addr		esp;
733//..    ThreadState* tst = VG_(get_ThreadState)(tid);
734//..
735//..    if (flags & VKI_SA_SIGINFO)
736//..       esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo,
737//..                                    handler, flags, mask, restorer);
738//..    else
739//..       esp = build_sigframe(tst, esp_top_of_frame,
740//..                                 siginfo, handler, flags, mask, restorer);
741//..
742//..    /* Set the thread so it will next run the handler. */
743//..    /* tst->m_esp  = esp; */
744//..    SET_SIGNAL_ESP(tid, esp);
745//..
746//..    //VG_(printf)("handler = %p\n", handler);
747//..    tst->arch.vex.guest_CIA = (Addr) handler;
748//..    /* This thread needs to be marked runnable, but we leave that the
749//..       caller to do. */
750
751   if (0)
752      VG_(printf)("pushed signal frame; %%R1 now = %#lx, "
753                  "next %%CIA = %#x, status=%d\n",
754		  sp, tst->arch.vex.guest_CIA, tst->status);
755}
756
757
758/*------------------------------------------------------------*/
759/*--- Destroying signal frames                             ---*/
760/*------------------------------------------------------------*/
761
762//.. /* Return False and don't do anything, just set the client to take a
763//..    segfault, if it looks like the frame is corrupted. */
764//.. static
765//.. Bool restore_vg_sigframe ( ThreadState *tst,
766//..                            struct vg_sigframe *frame, Int *sigNo )
767//.. {
768//..    if (frame->magicPI != 0x31415927 ||
769//..        frame->magicE  != 0x27182818) {
770//..       VG_(message)(Vg_UserMsg, "Thread %d return signal frame "
771//..                                "corrupted.  Killing process.",
772//.. 		   tst->tid);
773//..       VG_(set_default_handler)(VKI_SIGSEGV);
774//..       VG_(synth_fault)(tst->tid);
775//..       *sigNo = VKI_SIGSEGV;
776//..       return False;
777//..    }
778//..    tst->sig_mask        = frame->mask;
779//..    tst->tmp_sig_mask    = frame->mask;
780//..    tst->arch.vex_shadow = frame->vex_shadow;
781//..    /* HACK ALERT */
782//..    tst->arch.vex        = frame->vex;
783//..    /* end HACK ALERT */
784//..    *sigNo               = frame->sigNo_private;
785//..    return True;
786//.. }
787
788//.. static
789//.. void restore_sigcontext( ThreadState *tst,
790//..                          struct vki_sigcontext *sc )
791//.. //..                          struct vki_sigcontext *sc, struct _vki_fpstate *fpstate )
792//.. {
793//..    tst->arch.vex.guest_EAX     = sc->eax;
794//..    tst->arch.vex.guest_ECX     = sc->ecx;
795//..    tst->arch.vex.guest_EDX     = sc->edx;
796//..    tst->arch.vex.guest_EBX     = sc->ebx;
797//..    tst->arch.vex.guest_EBP     = sc->ebp;
798//..    tst->arch.vex.guest_ESP     = sc->esp;
799//..    tst->arch.vex.guest_ESI     = sc->esi;
800//..    tst->arch.vex.guest_EDI     = sc->edi;
801//.. //::    tst->arch.vex.guest_eflags  = sc->eflags;
802//.. //::    tst->arch.vex.guest_EIP     = sc->eip;
803//..
804//..    tst->arch.vex.guest_CS      = sc->cs;
805//..    tst->arch.vex.guest_SS      = sc->ss;
806//..    tst->arch.vex.guest_DS      = sc->ds;
807//..    tst->arch.vex.guest_ES      = sc->es;
808//..    tst->arch.vex.guest_FS      = sc->fs;
809//..    tst->arch.vex.guest_GS      = sc->gs;
810//..
811//.. //::    restore_i387(&tst->arch, fpstate);
812//.. }
813
814
815//.. static
816//.. SizeT restore_sigframe ( ThreadState *tst,
817//..                          struct sigframe *frame, Int *sigNo )
818//.. {
819//..    if (restore_vg_sigframe(tst, &frame->vg, sigNo))
820//..       restore_sigcontext(tst, &frame->sigContext, &frame->fpstate);
821//..    return sizeof(*frame);
822//.. }
823
824//.. static
825//.. SizeT restore_rt_sigframe ( ThreadState *tst,
826//..                             struct rt_sigframe *frame, Int *sigNo )
827//.. {
828//..    if (restore_vg_sigframe(tst, &frame->vg, sigNo))
829//..       restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate);
830//..    return sizeof(*frame);
831//.. }
832
833
834/* EXPORTED */
835void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
836{
837   ThreadState *tst;
838   struct vg_sig_private *priv;
839   Addr sp;
840   UInt frame_size;
841   struct vki_mcontext *mc;
842   Int sigNo;
843   Bool has_siginfo = isRT;
844
845   vg_assert(VG_(is_valid_tid)(tid));
846   tst = VG_(get_ThreadState)(tid);
847
848   /* Check that the stack frame looks valid */
849   sp = tst->arch.vex.guest_GPR1;
850   vg_assert(VG_IS_16_ALIGNED(sp));
851   /* JRS 17 Nov 05: This code used to check that *sp -- which should
852      have been set by the stwu at the start of the handler -- points
853      to just above the frame (ie, the previous frame).  However, that
854      isn't valid when delivering signals on alt stacks.  So I removed
855      it.  The frame is still sanity-checked using the priv->magicPI
856      field. */
857
858   if (has_siginfo) {
859      struct rt_sigframe *frame = (struct rt_sigframe *)sp;
860      frame_size = sizeof(*frame);
861      mc = &frame->ucontext.uc_mcontext;
862      priv = &frame->priv;
863      vg_assert(priv->magicPI == 0x31415927);
864      tst->sig_mask = frame->ucontext.uc_sigmask;
865   } else {
866      struct nonrt_sigframe *frame = (struct nonrt_sigframe *)sp;
867      frame_size = sizeof(*frame);
868      mc = &frame->mcontext;
869      priv = &frame->priv;
870      vg_assert(priv->magicPI == 0x31415927);
871      tst->sig_mask.sig[0] = frame->sigcontext.oldmask;
872      tst->sig_mask.sig[1] = frame->sigcontext._unused[3];
873   }
874   tst->tmp_sig_mask = tst->sig_mask;
875
876   sigNo = priv->sigNo_private;
877
878#  define DO(gpr)  tst->arch.vex.guest_GPR##gpr = mc->mc_gregs[VKI_PT_R0+gpr]
879   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
880   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
881   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
882   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
883#  undef DO
884
885   tst->arch.vex.guest_CIA = mc->mc_gregs[VKI_PT_NIP];
886
887   // Umm ... ? (jrs 2005 July 8)
888   // tst->arch.m_orig_gpr3 = mc->mc_gregs[VKI_PT_ORIG_R3];
889
890   LibVEX_GuestPPC32_put_CR( mc->mc_gregs[VKI_PT_CCR], &tst->arch.vex );
891
892   tst->arch.vex.guest_LR  = mc->mc_gregs[VKI_PT_LNK];
893   tst->arch.vex.guest_CTR = mc->mc_gregs[VKI_PT_CTR];
894   LibVEX_GuestPPC32_put_XER( mc->mc_gregs[VKI_PT_XER], &tst->arch.vex );
895
896   tst->arch.vex_shadow1 = priv->vex_shadow1;
897   tst->arch.vex_shadow2 = priv->vex_shadow2;
898
899   VG_TRACK(die_mem_stack_signal, sp, frame_size);
900
901   if (VG_(clo_trace_signals))
902      VG_(message)(Vg_DebugMsg,
903                   "vg_pop_signal_frame (thread %d): "
904                   "isRT=%d valid magic; EIP=%#x\n",
905                   tid, has_siginfo, tst->arch.vex.guest_CIA);
906
907   /* tell the tools */
908   VG_TRACK( post_deliver_signal, tid, sigNo );
909
910//..    Addr          esp;
911//..    ThreadState*  tst;
912//..    SizeT	 size;
913//..    Int		 sigNo;
914//..
915//..    tst = VG_(get_ThreadState)(tid);
916//..
917//..    /* Correctly reestablish the frame base address. */
918//..    esp   = tst->arch.vex.guest_ESP;
919//..
920//..    if (!isRT)
921//..       size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo);
922//..    else
923//..       size = restore_rt_sigframe(tst, (struct rt_sigframe *)esp, &sigNo);
924//..
925//..    VG_TRACK( die_mem_stack_signal, esp, size );
926//..
927//..    if (VG_(clo_trace_signals))
928//..       VG_(message)(
929//..          Vg_DebugMsg,
930//..          "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%p",
931//..          tid, isRT, tst->arch.vex.guest_EIP);
932//..
933//..    /* tell the tools */
934//..    VG_TRACK( post_deliver_signal, tid, sigNo );
935}
936
937#endif // defined(VGP_ppc32_linux)
938
939/*--------------------------------------------------------------------*/
940/*--- end                                                          ---*/
941/*--------------------------------------------------------------------*/
942