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-2010 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_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 
     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 */
     91 struct 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 
    119 struct 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 
    131 struct 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 */
    349 static
    350 void 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 /* Extend the stack segment downwards if needed so as to ensure the
    396    new signal frames are mapped to something.  Return a Bool
    397    indicating whether or not the operation was successful.
    398 */
    399 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
    400 {
    401    ThreadId        tid = tst->tid;
    402    NSegment const* stackseg = NULL;
    403 
    404    if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
    405       stackseg = VG_(am_find_nsegment)(addr);
    406       if (0 && stackseg)
    407 	 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
    408 		     addr, stackseg->start, stackseg->end);
    409    }
    410 
    411    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
    412       VG_(message)(
    413          Vg_UserMsg,
    414          "Can't extend stack to %#lx during signal delivery for thread %d:\n",
    415          addr, tid);
    416       if (stackseg == NULL)
    417          VG_(message)(Vg_UserMsg, "  no stack segment\n");
    418       else
    419          VG_(message)(Vg_UserMsg, "  too small or bad protection modes\n");
    420 
    421       /* set SIGSEGV to default handler */
    422       VG_(set_default_handler)(VKI_SIGSEGV);
    423       VG_(synth_fault_mapping)(tid, addr);
    424 
    425       /* The whole process should be about to die, since the default
    426 	 action of SIGSEGV to kill the whole process. */
    427       return False;
    428    }
    429 
    430    /* For tracking memory events, indicate the entire frame has been
    431       allocated. */
    432    VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
    433              size + VG_STACK_REDZONE_SZB, tid );
    434 
    435    return True;
    436 }
    437 
    438 
    439 /* Build the Valgrind-specific part of a signal frame. */
    440 
    441 static void build_vg_sigframe(struct vg_sigframe *frame,
    442 			      ThreadState *tst,
    443 			      UInt flags,
    444 			      Int sigNo)
    445 {
    446    frame->sigNo_private = sigNo;
    447    frame->magicPI       = 0x31415927;
    448    frame->vex_shadow1   = tst->arch.vex_shadow1;
    449    frame->vex_shadow2   = tst->arch.vex_shadow2;
    450    /* HACK ALERT */
    451    frame->vex           = tst->arch.vex;
    452    /* end HACK ALERT */
    453    frame->mask          = tst->sig_mask;
    454    frame->handlerflags  = flags;
    455    frame->magicE        = 0x27182818;
    456 }
    457 
    458 
    459 static Addr build_sigframe(ThreadState *tst,
    460 			   Addr esp_top_of_frame,
    461 			   const vki_siginfo_t *siginfo,
    462                            const struct vki_ucontext *siguc,
    463 			   UInt flags,
    464 			   const vki_sigset_t *mask,
    465 			   void *restorer)
    466 {
    467    struct sigframe *frame;
    468    Addr esp = esp_top_of_frame;
    469    Int	sigNo = siginfo->si_signo;
    470    UWord trapno;
    471    UWord err;
    472    struct vki_ucontext uc;
    473 
    474    vg_assert((flags & VKI_SA_SIGINFO) == 0);
    475 
    476    esp -= sizeof(*frame);
    477    esp = VG_ROUNDDN(esp, 16);
    478    frame = (struct sigframe *)esp;
    479 
    480    if (!extend(tst, esp, sizeof(*frame)))
    481       return esp_top_of_frame;
    482 
    483    /* retaddr, sigNo, siguContext fields are to be written */
    484    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
    485 	     esp, offsetof(struct sigframe, vg) );
    486 
    487    frame->sigNo = sigNo;
    488 
    489    if (flags & VKI_SA_RESTORER)
    490       frame->retaddr = (Addr)restorer;
    491    else
    492       frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_sigreturn);
    493 
    494    if (siguc) {
    495       trapno = siguc->uc_mcontext.trapno;
    496       err = siguc->uc_mcontext.err;
    497    } else {
    498       trapno = 0;
    499       err = 0;
    500    }
    501 
    502    synth_ucontext(tst->tid, siginfo, trapno, err, mask, &uc, &frame->fpstate);
    503 
    504    VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext,
    505 	       sizeof(struct vki_sigcontext));
    506    frame->sigContext.oldmask = mask->sig[0];
    507 
    508    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
    509              esp, offsetof(struct sigframe, vg) );
    510 
    511    build_vg_sigframe(&frame->vg, tst, flags, sigNo);
    512 
    513    return esp;
    514 }
    515 
    516 
    517 static Addr build_rt_sigframe(ThreadState *tst,
    518 			      Addr esp_top_of_frame,
    519 			      const vki_siginfo_t *siginfo,
    520                               const struct vki_ucontext *siguc,
    521 			      UInt flags,
    522 			      const vki_sigset_t *mask,
    523 			      void *restorer)
    524 {
    525    struct rt_sigframe *frame;
    526    Addr esp = esp_top_of_frame;
    527    Int	sigNo = siginfo->si_signo;
    528    UWord trapno;
    529    UWord err;
    530 
    531    vg_assert((flags & VKI_SA_SIGINFO) != 0);
    532 
    533    esp -= sizeof(*frame);
    534    esp = VG_ROUNDDN(esp, 16);
    535    frame = (struct rt_sigframe *)esp;
    536 
    537    if (!extend(tst, esp, sizeof(*frame)))
    538       return esp_top_of_frame;
    539 
    540    /* retaddr, sigNo, pSiginfo, puContext fields are to be written */
    541    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "rt signal handler frame",
    542 	     esp, offsetof(struct rt_sigframe, vg) );
    543 
    544    frame->sigNo = sigNo;
    545 
    546    if (flags & VKI_SA_RESTORER)
    547       frame->retaddr = (Addr)restorer;
    548    else
    549       frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_rt_sigreturn);
    550 
    551    if (siguc) {
    552       trapno = siguc->uc_mcontext.trapno;
    553       err = siguc->uc_mcontext.err;
    554    } else {
    555       trapno = 0;
    556       err = 0;
    557    }
    558 
    559    frame->psigInfo = (Addr)&frame->sigInfo;
    560    frame->puContext = (Addr)&frame->uContext;
    561    VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
    562 
    563    /* SIGILL defines addr to be the faulting address */
    564    if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
    565       frame->sigInfo._sifields._sigfault._addr
    566          = (void*)tst->arch.vex.guest_EIP;
    567 
    568    synth_ucontext(tst->tid, siginfo, trapno, err, mask,
    569                   &frame->uContext, &frame->fpstate);
    570 
    571    VG_TRACK( post_mem_write,  Vg_CoreSignal, tst->tid,
    572              esp, offsetof(struct rt_sigframe, vg) );
    573 
    574    build_vg_sigframe(&frame->vg, tst, flags, sigNo);
    575 
    576    return esp;
    577 }
    578 
    579 
    580 /* EXPORTED */
    581 void VG_(sigframe_create)( ThreadId tid,
    582                            Addr esp_top_of_frame,
    583                            const vki_siginfo_t *siginfo,
    584                            const struct vki_ucontext *siguc,
    585                            void *handler,
    586                            UInt flags,
    587                            const vki_sigset_t *mask,
    588 		           void *restorer )
    589 {
    590    Addr		esp;
    591    ThreadState* tst = VG_(get_ThreadState)(tid);
    592 
    593    if (flags & VKI_SA_SIGINFO)
    594       esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo, siguc,
    595                                    flags, mask, restorer);
    596    else
    597       esp = build_sigframe(tst, esp_top_of_frame, siginfo, siguc,
    598                                 flags, mask, restorer);
    599 
    600    /* Set the thread so it will next run the handler. */
    601    /* tst->m_esp  = esp;  also notify the tool we've updated ESP */
    602    VG_(set_SP)(tid, esp);
    603    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
    604 
    605    //VG_(printf)("handler = %p\n", handler);
    606    tst->arch.vex.guest_EIP = (Addr) handler;
    607    /* This thread needs to be marked runnable, but we leave that the
    608       caller to do. */
    609 
    610    if (0)
    611       VG_(printf)("pushed signal frame; %%ESP now = %#lx, "
    612                   "next %%EIP = %#x, status=%d\n",
    613 		  esp, tst->arch.vex.guest_EIP, tst->status);
    614 }
    615 
    616 
    617 /*------------------------------------------------------------*/
    618 /*--- Destroying signal frames                             ---*/
    619 /*------------------------------------------------------------*/
    620 
    621 /* Return False and don't do anything, just set the client to take a
    622    segfault, if it looks like the frame is corrupted. */
    623 static
    624 Bool restore_vg_sigframe ( ThreadState *tst,
    625                            struct vg_sigframe *frame, Int *sigNo )
    626 {
    627    if (frame->magicPI != 0x31415927 ||
    628        frame->magicE  != 0x27182818) {
    629       VG_(message)(Vg_UserMsg, "Thread %d return signal frame "
    630                                "corrupted.  Killing process.\n",
    631 		   tst->tid);
    632       VG_(set_default_handler)(VKI_SIGSEGV);
    633       VG_(synth_fault)(tst->tid);
    634       *sigNo = VKI_SIGSEGV;
    635       return False;
    636    }
    637    tst->sig_mask         = frame->mask;
    638    tst->tmp_sig_mask     = frame->mask;
    639    tst->arch.vex_shadow1 = frame->vex_shadow1;
    640    tst->arch.vex_shadow2 = frame->vex_shadow2;
    641    /* HACK ALERT */
    642    tst->arch.vex         = frame->vex;
    643    /* end HACK ALERT */
    644    *sigNo                = frame->sigNo_private;
    645    return True;
    646 }
    647 
    648 static
    649 void restore_sigcontext( ThreadState *tst,
    650                          struct vki_sigcontext *sc,
    651                          struct _vki_fpstate *fpstate )
    652 {
    653    tst->arch.vex.guest_EAX     = sc->eax;
    654    tst->arch.vex.guest_ECX     = sc->ecx;
    655    tst->arch.vex.guest_EDX     = sc->edx;
    656    tst->arch.vex.guest_EBX     = sc->ebx;
    657    tst->arch.vex.guest_EBP     = sc->ebp;
    658    tst->arch.vex.guest_ESP     = sc->esp;
    659    tst->arch.vex.guest_ESI     = sc->esi;
    660    tst->arch.vex.guest_EDI     = sc->edi;
    661 //::    tst->arch.vex.guest_eflags  = sc->eflags;
    662    tst->arch.vex.guest_EIP     = sc->eip;
    663    tst->arch.vex.guest_CS      = sc->cs;
    664    tst->arch.vex.guest_SS      = sc->ss;
    665    tst->arch.vex.guest_DS      = sc->ds;
    666    tst->arch.vex.guest_ES      = sc->es;
    667    tst->arch.vex.guest_FS      = sc->fs;
    668    tst->arch.vex.guest_GS      = sc->gs;
    669 
    670 //::    restore_i387(&tst->arch, fpstate);
    671 }
    672 
    673 
    674 static
    675 SizeT restore_sigframe ( ThreadState *tst,
    676                          struct sigframe *frame, Int *sigNo )
    677 {
    678    if (restore_vg_sigframe(tst, &frame->vg, sigNo))
    679       restore_sigcontext(tst, &frame->sigContext, &frame->fpstate);
    680 
    681    return sizeof(*frame);
    682 }
    683 
    684 static
    685 SizeT restore_rt_sigframe ( ThreadState *tst,
    686                             struct rt_sigframe *frame, Int *sigNo )
    687 {
    688    if (restore_vg_sigframe(tst, &frame->vg, sigNo))
    689       restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate);
    690 
    691    return sizeof(*frame);
    692 }
    693 
    694 
    695 /* EXPORTED */
    696 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
    697 {
    698    Addr          esp;
    699    ThreadState*  tst;
    700    SizeT	 size;
    701    Int		 sigNo;
    702 
    703    tst = VG_(get_ThreadState)(tid);
    704 
    705    /* Correctly reestablish the frame base address. */
    706    esp   = tst->arch.vex.guest_ESP;
    707 
    708    if (!isRT)
    709       size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo);
    710    else
    711       size = restore_rt_sigframe(tst, (struct rt_sigframe *)esp, &sigNo);
    712 
    713    VG_TRACK( die_mem_stack_signal, esp - VG_STACK_REDZONE_SZB,
    714              size + VG_STACK_REDZONE_SZB );
    715 
    716    if (VG_(clo_trace_signals))
    717       VG_(message)(
    718          Vg_DebugMsg,
    719          "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#x\n",
    720          tid, isRT, tst->arch.vex.guest_EIP);
    721 
    722    /* tell the tools */
    723    VG_TRACK( post_deliver_signal, tid, sigNo );
    724 }
    725 
    726 #endif // defined(VGP_x86_linux)
    727 
    728 /*--------------------------------------------------------------------*/
    729 /*--- end                                                          ---*/
    730 /*--------------------------------------------------------------------*/
    731