1
2/*--------------------------------------------------------------------*/
3/*--- Create/destroy signal delivery frames.                       ---*/
4/*---                                         sigframe-x86-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
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27   02111-1307, USA.
28
29   The GNU General Public License is contained in the file COPYING.
30*/
31
32#if defined(VGP_x86_linux)
33
34#include "pub_core_basics.h"
35#include "pub_core_vki.h"
36#include "pub_core_threadstate.h"
37#include "pub_core_aspacemgr.h" /* find_segment */
38#include "pub_core_libcbase.h"
39#include "pub_core_libcassert.h"
40#include "pub_core_libcprint.h"
41#include "pub_core_machine.h"
42#include "pub_core_options.h"
43#include "pub_core_signals.h"
44#include "pub_core_tooliface.h"
45#include "pub_core_trampoline.h"
46#include "pub_core_sigframe.h"   /* self */
47#include "priv_sigframe.h"
48
49/* This module creates and removes signal frames for signal deliveries
50   on x86-linux.
51
52   Note, this file contains kernel-specific knowledge in the form of
53   'struct sigframe' and 'struct rt_sigframe'.  How does that relate
54   to the vki kernel interface stuff?
55
56   Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
57   onto the client's stack.  This contains a subsidiary
58   vki_ucontext.  That holds the vcpu's state across the signal,
59   so that the sighandler can mess with the vcpu state if it
60   really wants.
61
62   FIXME: sigcontexting is basically broken for the moment.  When
63   delivering a signal, the integer registers and %eflags are
64   correctly written into the sigcontext, however the FP and SSE state
65   is not.  When returning from a signal, only the integer registers
66   are restored from the sigcontext; the rest of the CPU state is
67   restored to what it was before the signal.
68
69   This will be fixed.
70*/
71
72
73/*------------------------------------------------------------*/
74/*--- Signal frame layouts                                 ---*/
75/*------------------------------------------------------------*/
76
77// A structure in which to save the application's registers
78// during the execution of signal handlers.
79
80// Linux has 2 signal frame structures: one for normal signal
81// deliveries, and one for SA_SIGINFO deliveries (also known as RT
82// signals).
83//
84// In theory, so long as we get the arguments to the handler function
85// right, it doesn't matter what the exact layout of the rest of the
86// frame is.  Unfortunately, things like gcc's exception unwinding
87// make assumptions about the locations of various parts of the frame,
88// so we need to duplicate it exactly.
89
90/* Valgrind-specific parts of the signal frame */
91struct vg_sigframe
92{
93   /* Sanity check word. */
94   UInt magicPI;
95
96   UInt handlerflags;	/* flags for signal handler */
97
98
99   /* Safely-saved version of sigNo, as described above. */
100   Int  sigNo_private;
101
102   /* XXX This is wrong.  Surely we should store the shadow values
103      into the shadow memory behind the actual values? */
104   VexGuestX86State vex_shadow1;
105   VexGuestX86State vex_shadow2;
106
107   /* HACK ALERT */
108   VexGuestX86State vex;
109   /* end HACK ALERT */
110
111   /* saved signal mask to be restored when handler returns */
112   vki_sigset_t	mask;
113
114   /* Sanity check word.  Is the highest-addressed word; do not
115      move!*/
116   UInt magicE;
117};
118
119struct sigframe
120{
121   /* Sig handler's return address */
122   Addr retaddr;
123   Int  sigNo;
124
125   struct vki_sigcontext sigContext;
126   struct _vki_fpstate fpstate;
127
128   struct vg_sigframe vg;
129};
130
131struct rt_sigframe
132{
133   /* Sig handler's return address */
134   Addr retaddr;
135   Int  sigNo;
136
137   /* ptr to siginfo_t. */
138   Addr psigInfo;
139
140   /* ptr to ucontext */
141   Addr puContext;
142   /* pointed to by psigInfo */
143   vki_siginfo_t sigInfo;
144
145   /* pointed to by puContext */
146   struct vki_ucontext uContext;
147   struct _vki_fpstate fpstate;
148
149   struct vg_sigframe vg;
150};
151
152
153//:: /*------------------------------------------------------------*/
154//:: /*--- Signal operations                                    ---*/
155//:: /*------------------------------------------------------------*/
156//::
157//:: /*
158//::    Great gobs of FP state conversion taken wholesale from
159//::    linux/arch/i386/kernel/i387.c
160//::  */
161//::
162//:: /*
163//::  * FXSR floating point environment conversions.
164//::  */
165//:: #define X86_FXSR_MAGIC		0x0000
166//::
167//:: /*
168//::  * FPU tag word conversions.
169//::  */
170//::
171//:: static inline unsigned short twd_i387_to_fxsr( unsigned short twd )
172//:: {
173//::    unsigned int tmp; /* to avoid 16 bit prefixes in the code */
174//::
175//::    /* Transform each pair of bits into 01 (valid) or 00 (empty) */
176//::    tmp = ~twd;
177//::    tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
178//::    /* and move the valid bits to the lower byte. */
179//::    tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
180//::    tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
181//::    tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
182//::    return tmp;
183//:: }
184//::
185//:: static unsigned long twd_fxsr_to_i387( const struct i387_fxsave_struct *fxsave )
186//:: {
187//::    struct _vki_fpxreg *st = NULL;
188//::    unsigned long twd = (unsigned long) fxsave->twd;
189//::    unsigned long tag;
190//::    unsigned long ret = 0xffff0000u;
191//::    int i;
192//::
193//:: #define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16);
194//::
195//::    for ( i = 0 ; i < 8 ; i++ ) {
196//::       if ( twd & 0x1 ) {
197//:: 	 st = (struct _vki_fpxreg *) FPREG_ADDR( fxsave, i );
198//::
199//:: 	 switch ( st->exponent & 0x7fff ) {
200//:: 	 case 0x7fff:
201//:: 	    tag = 2;		/* Special */
202//:: 	    break;
203//:: 	 case 0x0000:
204//:: 	    if ( !st->significand[0] &&
205//:: 		 !st->significand[1] &&
206//:: 		 !st->significand[2] &&
207//:: 		 !st->significand[3] ) {
208//:: 	       tag = 1;	/* Zero */
209//:: 	    } else {
210//:: 	       tag = 2;	/* Special */
211//:: 	    }
212//:: 	    break;
213//:: 	 default:
214//:: 	    if ( st->significand[3] & 0x8000 ) {
215//:: 	       tag = 0;	/* Valid */
216//:: 	    } else {
217//:: 	       tag = 2;	/* Special */
218//:: 	    }
219//:: 	    break;
220//:: 	 }
221//::       } else {
222//:: 	 tag = 3;			/* Empty */
223//::       }
224//::       ret |= (tag << (2 * i));
225//::       twd = twd >> 1;
226//::    }
227//::    return ret;
228//:: }
229//::
230//:: static void convert_fxsr_to_user( struct _vki_fpstate *buf,
231//:: 				  const struct i387_fxsave_struct *fxsave )
232//:: {
233//::    unsigned long env[7];
234//::    struct _vki_fpreg *to;
235//::    struct _vki_fpxreg *from;
236//::    int i;
237//::
238//::    env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
239//::    env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
240//::    env[2] = twd_fxsr_to_i387(fxsave);
241//::    env[3] = fxsave->fip;
242//::    env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
243//::    env[5] = fxsave->foo;
244//::    env[6] = fxsave->fos;
245//::
246//::    VG_(memcpy)(buf, env, 7 * sizeof(unsigned long));
247//::
248//::    to = &buf->_st[0];
249//::    from = (struct _vki_fpxreg *) &fxsave->st_space[0];
250//::    for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
251//::       unsigned long __user *t = (unsigned long __user *)to;
252//::       unsigned long *f = (unsigned long *)from;
253//::
254//::       t[0] = f[0];
255//::       t[1] = f[1];
256//::       to->exponent = from->exponent;
257//::    }
258//:: }
259//::
260//:: static void convert_fxsr_from_user( struct i387_fxsave_struct *fxsave,
261//:: 				    const struct _vki_fpstate *buf )
262//:: {
263//::    unsigned long env[7];
264//::    struct _vki_fpxreg *to;
265//::    const struct _vki_fpreg *from;
266//::    int i;
267//::
268//::    VG_(memcpy)(env, buf, 7 * sizeof(long));
269//::
270//::    fxsave->cwd = (unsigned short)(env[0] & 0xffff);
271//::    fxsave->swd = (unsigned short)(env[1] & 0xffff);
272//::    fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
273//::    fxsave->fip = env[3];
274//::    fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
275//::    fxsave->fcs = (env[4] & 0xffff);
276//::    fxsave->foo = env[5];
277//::    fxsave->fos = env[6];
278//::
279//::    to = (struct _vki_fpxreg *) &fxsave->st_space[0];
280//::    from = &buf->_st[0];
281//::    for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
282//::       unsigned long *t = (unsigned long *)to;
283//::       unsigned long __user *f = (unsigned long __user *)from;
284//::
285//::       t[0] = f[0];
286//::       t[1] = f[1];
287//::       to->exponent = from->exponent;
288//::    }
289//:: }
290//::
291//:: static inline void save_i387_fsave( arch_thread_t *regs, struct _vki_fpstate *buf )
292//:: {
293//::    struct i387_fsave_struct *fs = &regs->m_sse.fsave;
294//::
295//::    fs->status = fs->swd;
296//::    VG_(memcpy)(buf, fs, sizeof(*fs));
297//:: }
298//::
299//:: static void save_i387_fxsave( arch_thread_t *regs, struct _vki_fpstate *buf )
300//:: {
301//::    const struct i387_fxsave_struct *fx = &regs->m_sse.fxsave;
302//::    convert_fxsr_to_user( buf, fx );
303//::
304//::    buf->status = fx->swd;
305//::    buf->magic = X86_FXSR_MAGIC;
306//::    VG_(memcpy)(buf->_fxsr_env, fx, sizeof(struct i387_fxsave_struct));
307//:: }
308//::
309//:: static void save_i387( arch_thread_t *regs, struct _vki_fpstate *buf )
310//:: {
311//::    if ( VG_(have_ssestate) )
312//::       save_i387_fxsave( regs, buf );
313//::    else
314//::       save_i387_fsave( regs, buf );
315//:: }
316//::
317//:: static inline void restore_i387_fsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
318//:: {
319//::    VG_(memcpy)( &regs->m_sse.fsave, buf, sizeof(struct i387_fsave_struct) );
320//:: }
321//::
322//:: static void restore_i387_fxsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
323//:: {
324//::    VG_(memcpy)(&regs->m_sse.fxsave, &buf->_fxsr_env[0],
325//:: 	       sizeof(struct i387_fxsave_struct) );
326//::    /* mxcsr reserved bits must be masked to zero for security reasons */
327//::    regs->m_sse.fxsave.mxcsr &= 0xffbf;
328//::    convert_fxsr_from_user( &regs->m_sse.fxsave, buf );
329//:: }
330//::
331//:: static void restore_i387( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
332//:: {
333//::    if ( VG_(have_ssestate) ) {
334//::       restore_i387_fxsave( regs, buf );
335//::    } else {
336//::       restore_i387_fsave( regs, buf );
337//::    }
338//:: }
339
340
341/*------------------------------------------------------------*/
342/*--- Creating signal frames                               ---*/
343/*------------------------------------------------------------*/
344
345/* Create a plausible-looking sigcontext from the thread's
346   Vex guest state.  NOTE: does not fill in the FP or SSE
347   bits of sigcontext at the moment.
348*/
349static
350void synth_ucontext(ThreadId tid, const vki_siginfo_t *si,
351                    UWord trapno, UWord err, const vki_sigset_t *set,
352                    struct vki_ucontext *uc, struct _vki_fpstate *fpstate)
353{
354   ThreadState *tst = VG_(get_ThreadState)(tid);
355   struct vki_sigcontext *sc = &uc->uc_mcontext;
356
357   VG_(memset)(uc, 0, sizeof(*uc));
358
359   uc->uc_flags = 0;
360   uc->uc_link = 0;
361   uc->uc_sigmask = *set;
362   uc->uc_stack = tst->altstack;
363   sc->fpstate = fpstate;
364
365   // FIXME: save_i387(&tst->arch, fpstate);
366
367#  define SC2(reg,REG)  sc->reg = tst->arch.vex.guest_##REG
368   SC2(gs,GS);
369   SC2(fs,FS);
370   SC2(es,ES);
371   SC2(ds,DS);
372
373   SC2(edi,EDI);
374   SC2(esi,ESI);
375   SC2(ebp,EBP);
376   SC2(esp,ESP);
377   SC2(ebx,EBX);
378   SC2(edx,EDX);
379   SC2(ecx,ECX);
380   SC2(eax,EAX);
381
382   SC2(eip,EIP);
383   SC2(cs,CS);
384   sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex);
385   SC2(ss,SS);
386   /* XXX esp_at_signal */
387   sc->trapno = trapno;
388   sc->err = err;
389#  undef SC2
390
391   sc->cr2 = (UInt)si->_sifields._sigfault._addr;
392}
393
394
395/* Build the Valgrind-specific part of a signal frame. */
396
397static void build_vg_sigframe(struct vg_sigframe *frame,
398			      ThreadState *tst,
399			      UInt flags,
400			      Int sigNo)
401{
402   frame->sigNo_private = sigNo;
403   frame->magicPI       = 0x31415927;
404   frame->vex_shadow1   = tst->arch.vex_shadow1;
405   frame->vex_shadow2   = tst->arch.vex_shadow2;
406   /* HACK ALERT */
407   frame->vex           = tst->arch.vex;
408   /* end HACK ALERT */
409   frame->mask          = tst->sig_mask;
410   frame->handlerflags  = flags;
411   frame->magicE        = 0x27182818;
412}
413
414
415static Addr build_sigframe(ThreadState *tst,
416			   Addr esp_top_of_frame,
417			   const vki_siginfo_t *siginfo,
418                           const struct vki_ucontext *siguc,
419			   UInt flags,
420			   const vki_sigset_t *mask,
421			   void *restorer)
422{
423   struct sigframe *frame;
424   Addr esp = esp_top_of_frame;
425   Int	sigNo = siginfo->si_signo;
426   UWord trapno;
427   UWord err;
428   struct vki_ucontext uc;
429
430   vg_assert((flags & VKI_SA_SIGINFO) == 0);
431
432   esp -= sizeof(*frame);
433   esp = VG_ROUNDDN(esp, 16);
434   frame = (struct sigframe *)esp;
435
436   if (! ML_(sf_maybe_extend_stack)(tst, esp, sizeof(*frame), flags))
437      return esp_top_of_frame;
438
439   /* retaddr, sigNo, siguContext fields are to be written */
440   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
441	     esp, offsetof(struct sigframe, vg) );
442
443   frame->sigNo = sigNo;
444
445   if (flags & VKI_SA_RESTORER)
446      frame->retaddr = (Addr)restorer;
447   else
448      frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_sigreturn);
449
450   if (siguc) {
451      trapno = siguc->uc_mcontext.trapno;
452      err = siguc->uc_mcontext.err;
453   } else {
454      trapno = 0;
455      err = 0;
456   }
457
458   synth_ucontext(tst->tid, siginfo, trapno, err, mask, &uc, &frame->fpstate);
459
460   VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext,
461	       sizeof(struct vki_sigcontext));
462   frame->sigContext.oldmask = mask->sig[0];
463
464   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
465             esp, offsetof(struct sigframe, vg) );
466
467   build_vg_sigframe(&frame->vg, tst, flags, sigNo);
468
469   return esp;
470}
471
472
473static Addr build_rt_sigframe(ThreadState *tst,
474			      Addr esp_top_of_frame,
475			      const vki_siginfo_t *siginfo,
476                              const struct vki_ucontext *siguc,
477			      UInt flags,
478			      const vki_sigset_t *mask,
479			      void *restorer)
480{
481   struct rt_sigframe *frame;
482   Addr esp = esp_top_of_frame;
483   Int	sigNo = siginfo->si_signo;
484   UWord trapno;
485   UWord err;
486
487   vg_assert((flags & VKI_SA_SIGINFO) != 0);
488
489   esp -= sizeof(*frame);
490   esp = VG_ROUNDDN(esp, 16);
491   frame = (struct rt_sigframe *)esp;
492
493   if (! ML_(sf_maybe_extend_stack)(tst, esp, sizeof(*frame), flags))
494      return esp_top_of_frame;
495
496   /* retaddr, sigNo, pSiginfo, puContext fields are to be written */
497   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "rt signal handler frame",
498	     esp, offsetof(struct rt_sigframe, vg) );
499
500   frame->sigNo = sigNo;
501
502   if (flags & VKI_SA_RESTORER)
503      frame->retaddr = (Addr)restorer;
504   else
505      frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_rt_sigreturn);
506
507   if (siguc) {
508      trapno = siguc->uc_mcontext.trapno;
509      err = siguc->uc_mcontext.err;
510   } else {
511      trapno = 0;
512      err = 0;
513   }
514
515   frame->psigInfo = (Addr)&frame->sigInfo;
516   frame->puContext = (Addr)&frame->uContext;
517   VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
518
519   /* SIGILL defines addr to be the faulting address */
520   if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
521      frame->sigInfo._sifields._sigfault._addr
522         = (void*)tst->arch.vex.guest_EIP;
523
524   synth_ucontext(tst->tid, siginfo, trapno, err, mask,
525                  &frame->uContext, &frame->fpstate);
526
527   VG_TRACK( post_mem_write,  Vg_CoreSignal, tst->tid,
528             esp, offsetof(struct rt_sigframe, vg) );
529
530   build_vg_sigframe(&frame->vg, tst, flags, sigNo);
531
532   return esp;
533}
534
535
536/* EXPORTED */
537void VG_(sigframe_create)( ThreadId tid,
538                           Addr esp_top_of_frame,
539                           const vki_siginfo_t *siginfo,
540                           const struct vki_ucontext *siguc,
541                           void *handler,
542                           UInt flags,
543                           const vki_sigset_t *mask,
544		           void *restorer )
545{
546   Addr		esp;
547   ThreadState* tst = VG_(get_ThreadState)(tid);
548
549   if (flags & VKI_SA_SIGINFO)
550      esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo, siguc,
551                                   flags, mask, restorer);
552   else
553      esp = build_sigframe(tst, esp_top_of_frame, siginfo, siguc,
554                                flags, mask, restorer);
555
556   /* Set the thread so it will next run the handler. */
557   /* tst->m_esp  = esp;  also notify the tool we've updated ESP */
558   VG_(set_SP)(tid, esp);
559   VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
560
561   //VG_(printf)("handler = %p\n", handler);
562   tst->arch.vex.guest_EIP = (Addr) handler;
563   /* This thread needs to be marked runnable, but we leave that the
564      caller to do. */
565
566   if (0)
567      VG_(printf)("pushed signal frame; %%ESP now = %#lx, "
568                  "next %%EIP = %#x, status=%d\n",
569		  esp, tst->arch.vex.guest_EIP, tst->status);
570}
571
572
573/*------------------------------------------------------------*/
574/*--- Destroying signal frames                             ---*/
575/*------------------------------------------------------------*/
576
577/* Return False and don't do anything, just set the client to take a
578   segfault, if it looks like the frame is corrupted. */
579static
580Bool restore_vg_sigframe ( ThreadState *tst,
581                           struct vg_sigframe *frame, Int *sigNo )
582{
583   if (frame->magicPI != 0x31415927 ||
584       frame->magicE  != 0x27182818) {
585      VG_(message)(Vg_UserMsg, "Thread %d return signal frame "
586                               "corrupted.  Killing process.\n",
587		   tst->tid);
588      VG_(set_default_handler)(VKI_SIGSEGV);
589      VG_(synth_fault)(tst->tid);
590      *sigNo = VKI_SIGSEGV;
591      return False;
592   }
593   tst->sig_mask         = frame->mask;
594   tst->tmp_sig_mask     = frame->mask;
595   tst->arch.vex_shadow1 = frame->vex_shadow1;
596   tst->arch.vex_shadow2 = frame->vex_shadow2;
597   /* HACK ALERT */
598   tst->arch.vex         = frame->vex;
599   /* end HACK ALERT */
600   *sigNo                = frame->sigNo_private;
601   return True;
602}
603
604static
605void restore_sigcontext( ThreadState *tst,
606                         struct vki_sigcontext *sc,
607                         struct _vki_fpstate *fpstate )
608{
609   tst->arch.vex.guest_EAX     = sc->eax;
610   tst->arch.vex.guest_ECX     = sc->ecx;
611   tst->arch.vex.guest_EDX     = sc->edx;
612   tst->arch.vex.guest_EBX     = sc->ebx;
613   tst->arch.vex.guest_EBP     = sc->ebp;
614   tst->arch.vex.guest_ESP     = sc->esp;
615   tst->arch.vex.guest_ESI     = sc->esi;
616   tst->arch.vex.guest_EDI     = sc->edi;
617//::    tst->arch.vex.guest_eflags  = sc->eflags;
618   tst->arch.vex.guest_EIP     = sc->eip;
619   tst->arch.vex.guest_CS      = sc->cs;
620   tst->arch.vex.guest_SS      = sc->ss;
621   tst->arch.vex.guest_DS      = sc->ds;
622   tst->arch.vex.guest_ES      = sc->es;
623   tst->arch.vex.guest_FS      = sc->fs;
624   tst->arch.vex.guest_GS      = sc->gs;
625
626//::    restore_i387(&tst->arch, fpstate);
627}
628
629
630static
631SizeT restore_sigframe ( ThreadState *tst,
632                         struct sigframe *frame, Int *sigNo )
633{
634   if (restore_vg_sigframe(tst, &frame->vg, sigNo))
635      restore_sigcontext(tst, &frame->sigContext, &frame->fpstate);
636
637   return sizeof(*frame);
638}
639
640static
641SizeT restore_rt_sigframe ( ThreadState *tst,
642                            struct rt_sigframe *frame, Int *sigNo )
643{
644   if (restore_vg_sigframe(tst, &frame->vg, sigNo))
645      restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate);
646
647   return sizeof(*frame);
648}
649
650
651/* EXPORTED */
652void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
653{
654   Addr          esp;
655   ThreadState*  tst;
656   SizeT	 size;
657   Int		 sigNo;
658
659   tst = VG_(get_ThreadState)(tid);
660
661   /* Correctly reestablish the frame base address. */
662   esp   = tst->arch.vex.guest_ESP;
663
664   if (!isRT)
665      size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo);
666   else
667      size = restore_rt_sigframe(tst, (struct rt_sigframe *)esp, &sigNo);
668
669   VG_TRACK( die_mem_stack_signal, esp - VG_STACK_REDZONE_SZB,
670             size + VG_STACK_REDZONE_SZB );
671
672   if (VG_(clo_trace_signals))
673      VG_(message)(
674         Vg_DebugMsg,
675         "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#x\n",
676         tid, isRT, tst->arch.vex.guest_EIP);
677
678   /* tell the tools */
679   VG_TRACK( post_deliver_signal, tid, sigNo );
680}
681
682#endif // defined(VGP_x86_linux)
683
684/*--------------------------------------------------------------------*/
685/*--- end                                                          ---*/
686/*--------------------------------------------------------------------*/
687