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