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