blob: 1a3c0b4f4d7a04b5383baebbc17433508c88a1a3 [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
Elliott Hughesed398002017-06-21 14:41:24 -070011 Copyright (C) 2000-2017 Nicholas Nethercote
sewardje1c444e2005-07-08 18:28:40 +000012 njn@valgrind.org
Elliott Hughesed398002017-06-21 14:41:24 -070013 Copyright (C) 2004-2017 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"
cerion85665ca2005-06-20 15:51:07 +000039#include "pub_core_threadstate.h"
cerion85665ca2005-06-20 15:51:07 +000040#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"
sewardje1c444e2005-07-08 18:28:40 +000050#include "pub_core_transtab.h" // VG_(discard_translations)
florian01fcf6a2015-04-18 10:33:54 +000051#include "priv_sigframe.h"
cerion85665ca2005-06-20 15:51:07 +000052
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
sewardje1c444e2005-07-08 18:28:40 +000094/* Structure containing bits of information that we want to save
95 on signal delivery. */
96struct vg_sig_private {
cerion85665ca2005-06-20 15:51:07 +000097 UInt magicPI;
sewardje1c444e2005-07-08 18:28:40 +000098 UInt sigNo_private;
sewardj7cf4e6b2008-05-01 20:24:26 +000099 VexGuestPPC32State vex_shadow1;
100 VexGuestPPC32State vex_shadow2;
cerion85665ca2005-06-20 15:51:07 +0000101};
102
sewardje1c444e2005-07-08 18:28:40 +0000103/* 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;
florian7b7d5942014-12-19 20:29:22 +0000109 unsigned char abigap[224]; // unused
sewardje1c444e2005-07-08 18:28:40 +0000110};
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;
florian7b7d5942014-12-19 20:29:22 +0000118 unsigned char abigap[224]; // unused
sewardje1c444e2005-07-08 18:28:40 +0000119};
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,
sewardja5940262007-09-10 16:28:38 +0000139 Bool use_rt_sigreturn,
sewardje1c444e2005-07-08 18:28:40 +0000140 UInt fault_addr )
cerion85665ca2005-06-20 15:51:07 +0000141{
sewardje1c444e2005-07-08 18:28:40 +0000142 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
143 (Addr)mc, sizeof(struct vki_pt_regs) );
cerion85665ca2005-06-20 15:51:07 +0000144
sewardje1c444e2005-07-08 18:28:40 +0000145# 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
cerion85665ca2005-06-20 15:51:07 +0000151
sewardje1c444e2005-07-08 18:28:40 +0000152 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;
sewardj463b3d92005-07-18 11:41:15 +0000157 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);
sewardje1c444e2005-07-08 18:28:40 +0000159 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) );
cerion85665ca2005-06-20 15:51:07 +0000166
sewardje1c444e2005-07-08 18:28:40 +0000167 /* XXX should do FP and vector regs */
cerion85665ca2005-06-20 15:51:07 +0000168
sewardje1c444e2005-07-08 18:28:40 +0000169 /* set up signal return trampoline */
sewardja5940262007-09-10 16:28:38 +0000170 /* 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. */
sewardje1c444e2005-07-08 18:28:40 +0000178 VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
179 (Addr)&mc->mc_pad, sizeof(mc->mc_pad));
sewardja5940262007-09-10 16:28:38 +0000180 mc->mc_pad[0] = 0; /* invalid */
181 mc->mc_pad[1] = 0; /* invalid */
sewardje1c444e2005-07-08 18:28:40 +0000182 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 */
florianddd61ff2015-01-04 17:20:45 +0000185 VG_(discard_translations)( (Addr)&mc->mc_pad,
sewardja48a4932005-09-29 11:09:56 +0000186 sizeof(mc->mc_pad), "stack_mcontext" );
cerion85665ca2005-06-20 15:51:07 +0000187
sewardje1c444e2005-07-08 18:28:40 +0000188 /* set the signal handler to return to the trampoline */
sewardja5940262007-09-10 16:28:38 +0000189 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 ));
sewardje1c444e2005-07-08 18:28:40 +0000193}
cerion85665ca2005-06-20 15:51:07 +0000194
sewardje1c444e2005-07-08 18:28:40 +0000195//:: /* 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//:: };
cerion85665ca2005-06-20 15:51:07 +0000255
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, \
njnaf839f52005-06-23 03:27:57 +0000501//.. Vg_CoreSignal, zztid, VG_O_STACK_PTR, sizeof(Addr))
cerion85665ca2005-06-20 15:51:07 +0000502*/
cerion85665ca2005-06-20 15:51:07 +0000503
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,
sewardj8eb8bab2015-07-21 14:44:28 +0000627 Bool on_altstack,
cerion85665ca2005-06-20 15:51:07 +0000628 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",
florian97f1d332015-08-06 09:00:48 +0000755 sp, tst->arch.vex.guest_CIA, (Int)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,
florian97f1d332015-08-06 09:00:48 +0000904 "vg_pop_signal_frame (thread %u): "
sewardj738856f2009-07-15 14:48:32 +0000905 "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,
florian97f1d332015-08-06 09:00:48 +0000931//.. "VG_(signal_return) (thread %u): 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/*--------------------------------------------------------------------*/