Home | History | Annotate | Download | only in m_sigframe
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Create/destroy signal delivery frames.                       ---*/
      4 /*---                                  sigframe-mips32-linux.c     ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2010-2012 RT-RK
     12       mips-valgrind (at) rt-rk.com
     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_mips32_linux)
     33 
     34 #include "pub_core_basics.h"
     35 #include "pub_core_vki.h"
     36 #include "pub_core_vkiscnums.h"
     37 #include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
     38 #include "pub_core_threadstate.h"
     39 #include "pub_core_aspacemgr.h"
     40 #include "pub_core_libcbase.h"
     41 #include "pub_core_libcassert.h"
     42 #include "pub_core_libcprint.h"
     43 #include "pub_core_machine.h"
     44 #include "pub_core_options.h"
     45 #include "pub_core_sigframe.h"
     46 #include "pub_core_signals.h"
     47 #include "pub_core_tooliface.h"
     48 #include "pub_core_trampoline.h"
     49 #include "pub_core_transtab.h"      // VG_(discard_translations)
     50 
     51 struct vg_sig_private
     52 {
     53   UInt magicPI;
     54   UInt sigNo_private;
     55   VexGuestMIPS32State vex_shadow1;
     56   VexGuestMIPS32State vex_shadow2;
     57 };
     58 
     59 struct sigframe
     60 {
     61   UInt sf_ass[4];       /* argument save space for o32 */
     62   UInt sf_pad[2];       /* Was: signal trampoline */
     63   struct vki_sigcontext sf_sc;
     64   vki_sigset_t sf_mask;
     65   struct vg_sig_private priv;
     66 };
     67 
     68 struct rt_sigframe
     69 {
     70   UInt rs_ass[4];		/* argument save space for o32 */
     71   UInt rs_pad[2];		/* Was: signal trampoline */
     72   vki_siginfo_t rs_info;
     73   struct vki_ucontext rs_uc;
     74   struct vg_sig_private priv;
     75 };
     76 
     77 /* Extend the stack segment downwards if needed so as to ensure the
     78    new signal frames are mapped to something.  Return a Bool
     79    indicating whether or not the operation was successful.
     80 */
     81 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
     82 {
     83   ThreadId        tid = tst->tid;
     84   NSegment const* stackseg = NULL;
     85 
     86   if (VG_(extend_stack)(addr, tst->client_stack_szB))
     87     {
     88       stackseg = VG_(am_find_nsegment)(addr);
     89    }
     90 
     91    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW)
     92      {
     93        VG_(message)(Vg_UserMsg,
     94          "Can't extend stack to %#lx during signal delivery for thread %d:\n",
     95          addr, tid );
     96        if (stackseg == NULL)
     97          VG_(message)( Vg_UserMsg, "  no stack segment\n" );
     98        else
     99          VG_(message)( Vg_UserMsg, "  too small or bad protection modes\n" );
    100 
    101        /* set SIGSEGV to default handler */
    102        VG_(set_default_handler)( VKI_SIGSEGV );
    103        VG_(synth_fault_mapping)( tid, addr );
    104 
    105        /* The whole process should be about to die, since the default
    106           action of SIGSEGV to kill the whole process. */
    107       return False;
    108     }
    109 
    110     /* For tracking memory events, indicate the entire frame has been
    111        allocated. */
    112     VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
    113               size + VG_STACK_REDZONE_SZB, tid );
    114 
    115     return True;
    116 }
    117 
    118 static
    119 void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1, const vki_siginfo_t *si)
    120 {
    121 
    122   struct vki_sigcontext *sc = *sc1;
    123 
    124   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
    125            (Addr)sc, sizeof(unsigned long long)*34 );
    126   sc->sc_regs[1] = tst->arch.vex.guest_r1;
    127   sc->sc_regs[2] = tst->arch.vex.guest_r2;
    128   sc->sc_regs[3] = tst->arch.vex.guest_r3;
    129   sc->sc_regs[4] = tst->arch.vex.guest_r4;
    130   sc->sc_regs[5] = tst->arch.vex.guest_r5;
    131   sc->sc_regs[6] = tst->arch.vex.guest_r6;
    132   sc->sc_regs[7] = tst->arch.vex.guest_r7;
    133   sc->sc_regs[8] = tst->arch.vex.guest_r8;
    134   sc->sc_regs[9] = tst->arch.vex.guest_r9;
    135   sc->sc_regs[10] = tst->arch.vex.guest_r10;
    136   sc->sc_regs[11] = tst->arch.vex.guest_r11;
    137   sc->sc_regs[12] = tst->arch.vex.guest_r12;
    138   sc->sc_regs[13] = tst->arch.vex.guest_r13;
    139   sc->sc_regs[14] = tst->arch.vex.guest_r14;
    140   sc->sc_regs[15] = tst->arch.vex.guest_r15;
    141   sc->sc_regs[16] = tst->arch.vex.guest_r16;
    142   sc->sc_regs[17] = tst->arch.vex.guest_r17;
    143   sc->sc_regs[18] = tst->arch.vex.guest_r18;
    144   sc->sc_regs[19] = tst->arch.vex.guest_r19;
    145   sc->sc_regs[20] = tst->arch.vex.guest_r20;
    146   sc->sc_regs[21] = tst->arch.vex.guest_r21;
    147   sc->sc_regs[22] = tst->arch.vex.guest_r22;
    148   sc->sc_regs[23] = tst->arch.vex.guest_r23;
    149   sc->sc_regs[24] = tst->arch.vex.guest_r24;
    150   sc->sc_regs[25] = tst->arch.vex.guest_r25;
    151   sc->sc_regs[26] = tst->arch.vex.guest_r26;
    152   sc->sc_regs[27] = tst->arch.vex.guest_r27;
    153   sc->sc_regs[28] = tst->arch.vex.guest_r28;
    154   sc->sc_regs[29] = tst->arch.vex.guest_r29;
    155   sc->sc_regs[30] = tst->arch.vex.guest_r30;
    156   sc->sc_regs[31] = tst->arch.vex.guest_r31;
    157   sc->sc_pc = tst->arch.vex.guest_PC;
    158   sc->sc_mdhi = tst->arch.vex.guest_HI;
    159   sc->sc_mdlo = tst->arch.vex.guest_LO;
    160 }
    161 
    162 /* EXPORTED */
    163 void VG_(sigframe_create)( ThreadId tid,
    164                            Addr sp_top_of_frame,
    165                            const vki_siginfo_t *siginfo,
    166                            const struct vki_ucontext *siguc,
    167                            void *handler,
    168                            UInt flags,
    169                            const vki_sigset_t *mask,
    170                            void *restorer )
    171 {
    172   Addr sp;
    173   ThreadState* tst = VG_(get_ThreadState)(tid);
    174   Addr faultaddr;
    175   Int sigNo = siginfo->si_signo;
    176   struct vg_sig_private *priv;
    177 
    178   /* Stack must be 8-byte aligned */
    179   sp_top_of_frame &= ~0xf;
    180 
    181   if (flags & VKI_SA_SIGINFO)
    182     {
    183       sp = sp_top_of_frame - sizeof(struct rt_sigframe);
    184     }
    185   else
    186     {
    187       sp = sp_top_of_frame - sizeof(struct sigframe);
    188     }
    189 
    190   tst = VG_(get_ThreadState)(tid);
    191   if (!extend(tst, sp, sp_top_of_frame - sp))
    192     return;
    193 
    194   vg_assert(VG_IS_8_ALIGNED(sp));
    195 
    196   /* SIGILL defines addr to be the faulting address */
    197 
    198   faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
    199   if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
    200     faultaddr = tst->arch.vex.guest_PC;
    201 
    202   if (flags & VKI_SA_SIGINFO)
    203     {
    204       struct rt_sigframe *frame = (struct rt_sigframe *) sp;
    205       struct vki_ucontext *ucp = &frame->rs_uc;
    206       if (VG_(clo_trace_signals))
    207         VG_(printf)("rt_sigframe\n");
    208       /* Create siginfo.  */
    209       VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
    210                (Addr)&frame->rs_info, sizeof(frame->rs_info) );
    211 
    212       VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo));
    213 
    214       VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
    215                (Addr)&frame->rs_info, sizeof(frame->rs_info) );
    216 
    217       /* Create the ucontext.  */
    218       VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
    219                (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext) );
    220 
    221       ucp->uc_flags = 0;
    222       ucp->uc_link = 0;
    223       ucp->uc_stack = tst->altstack;
    224 
    225       VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
    226                offsetof(struct vki_ucontext, uc_mcontext) );
    227 
    228       struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext);
    229       setup_sigcontext2(tst, &(scp), siginfo);
    230 
    231       ucp->uc_sigmask = tst->sig_mask;
    232 
    233       priv = &frame->priv;
    234 
    235       /*
    236        * Arguments to signal handler:
    237        *
    238        *   a0 = signal number
    239        *   a1 = 0 (should be cause)
    240        *   a2 = pointer to ucontext
    241        *
    242        * $25 and c0_epc point to the signal handler, $29 points to
    243        * the struct rt_sigframe.
    244        */
    245 
    246       tst->arch.vex.guest_r4 = siginfo->si_signo;
    247       tst->arch.vex.guest_r5 = (Addr) &frame->rs_info;
    248       tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc;
    249       tst->arch.vex.guest_r29 = (Addr) frame;
    250       tst->arch.vex.guest_r25 = (Addr) handler;
    251 
    252       if (flags & VKI_SA_RESTORER)
    253         {
    254           tst->arch.vex.guest_r31 = (Addr) restorer;
    255         }
    256       else
    257         {
    258           tst->arch.vex.guest_r31 = (Addr)&VG_(mips32_linux_SUBST_FOR_rt_sigreturn);
    259         }
    260 
    261     }
    262   else
    263     {
    264       if (VG_(clo_trace_signals))
    265         VG_(printf)("sigframe\n");
    266       struct sigframe *frame = (struct sigframe *) sp;
    267       struct vki_sigcontext *scp = &(frame->sf_sc);
    268       setup_sigcontext2(tst, &(scp), siginfo);
    269       frame->sf_mask = tst->sig_mask;
    270       priv = &frame->priv;
    271       /*
    272        * Arguments to signal handler:
    273        *
    274        *   a0 = signal number
    275        *   a1 = 0 (should be cause)
    276        *   a2 = pointer to struct sigcontext
    277        *
    278        * $25 and c0_epc point to the signal handler, $29 points to the
    279        * struct sigframe.
    280        */
    281       tst->arch.vex.guest_r4 = siginfo->si_signo;
    282       tst->arch.vex.guest_r5 = 0;
    283       tst->arch.vex.guest_r6 = (Addr) &frame->sf_sc;
    284       tst->arch.vex.guest_r29 = (Addr) frame;
    285       tst->arch.vex.guest_r25 = (Addr) handler;
    286 
    287       if (flags & VKI_SA_RESTORER)
    288         {
    289           tst->arch.vex.guest_r31 = (Addr) restorer;
    290         }
    291       else
    292         {
    293           tst->arch.vex.guest_r31 = (Addr)&VG_(mips32_linux_SUBST_FOR_sigreturn);
    294         }
    295     }
    296 
    297   priv->magicPI       = 0x31415927;
    298   priv->sigNo_private = sigNo;
    299   priv->vex_shadow1   = tst->arch.vex_shadow1;
    300   priv->vex_shadow2   = tst->arch.vex_shadow2;
    301   /* Set the thread so it will next run the handler. */
    302   /* tst->m_sp  = sp;  also notify the tool we've updated SP */
    303   VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
    304   if (VG_(clo_trace_signals))
    305     VG_(printf)("handler = %p\n", handler);
    306   tst->arch.vex.guest_PC = (Addr) handler;
    307   /* This thread needs to be marked runnable, but we leave that the
    308      caller to do. */
    309 }
    310 
    311 /* EXPORTED */
    312 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
    313 {
    314   ThreadState *tst;
    315   struct vg_sig_private *priv1;
    316   Addr sp;
    317   UInt frame_size;
    318   struct vki_sigcontext *mc;
    319   Int sigNo;
    320   Bool has_siginfo = isRT;
    321 
    322   vg_assert(VG_(is_valid_tid)(tid));
    323   tst = VG_(get_ThreadState)(tid);
    324   sp   = tst->arch.vex.guest_r29;
    325   if (has_siginfo)
    326     {
    327       struct rt_sigframe *frame = (struct rt_sigframe *)sp;
    328       struct vki_ucontext *ucp = &frame->rs_uc;
    329       frame_size = sizeof(*frame);
    330       mc = &ucp->uc_mcontext;
    331       priv1 = &frame->priv;
    332       vg_assert(priv1->magicPI == 0x31415927);
    333       sigNo = priv1->sigNo_private;
    334     }
    335   else
    336     {
    337       struct sigframe *frame = (struct sigframe *)sp;
    338       frame_size = sizeof(*frame);
    339       mc = &(frame->sf_sc);
    340       priv1 = &frame->priv;
    341       vg_assert(priv1->magicPI == 0x31415927);
    342       tst->sig_mask = frame->sf_mask;
    343       tst->tmp_sig_mask = tst->sig_mask;
    344       sigNo = priv1->sigNo_private;
    345     }
    346   //restore regs
    347   tst->arch.vex.guest_r1 = mc->sc_regs[1];
    348   tst->arch.vex.guest_r2 = mc->sc_regs[2];
    349   tst->arch.vex.guest_r3 = mc->sc_regs[3];
    350   tst->arch.vex.guest_r4 = mc->sc_regs[4];
    351   tst->arch.vex.guest_r5 = mc->sc_regs[5];
    352   tst->arch.vex.guest_r6 = mc->sc_regs[6];
    353   tst->arch.vex.guest_r7 = mc->sc_regs[7];
    354   tst->arch.vex.guest_r8 = mc->sc_regs[8];
    355   tst->arch.vex.guest_r9 = mc->sc_regs[9];
    356   tst->arch.vex.guest_r10 = mc->sc_regs[10];
    357   tst->arch.vex.guest_r11 = mc->sc_regs[11];
    358   tst->arch.vex.guest_r12 = mc->sc_regs[12];
    359   tst->arch.vex.guest_r13= mc->sc_regs[13];
    360   tst->arch.vex.guest_r14 = mc->sc_regs[14];
    361   tst->arch.vex.guest_r15 = mc->sc_regs[15];
    362   tst->arch.vex.guest_r16 = mc->sc_regs[16];
    363   tst->arch.vex.guest_r17 = mc->sc_regs[17];
    364   tst->arch.vex.guest_r18 = mc->sc_regs[18];
    365   tst->arch.vex.guest_r19 = mc->sc_regs[19];
    366   tst->arch.vex.guest_r20 = mc->sc_regs[20];
    367   tst->arch.vex.guest_r21 = mc->sc_regs[21];
    368   tst->arch.vex.guest_r22 = mc->sc_regs[22];
    369   tst->arch.vex.guest_r23 = mc->sc_regs[23];
    370   tst->arch.vex.guest_r24 = mc->sc_regs[24];
    371   tst->arch.vex.guest_r25 = mc->sc_regs[25];
    372   tst->arch.vex.guest_r26 = mc->sc_regs[26];
    373   tst->arch.vex.guest_r27 = mc->sc_regs[27];
    374   tst->arch.vex.guest_r28 = mc->sc_regs[28];
    375   tst->arch.vex.guest_r30 = mc->sc_regs[30];
    376   tst->arch.vex.guest_PC = mc->sc_pc;
    377   tst->arch.vex.guest_r31 = mc->sc_regs[31];
    378   tst->arch.vex.guest_r29 = mc->sc_regs[29];
    379 
    380   tst->arch.vex.guest_HI = mc->sc_mdhi;
    381   tst->arch.vex.guest_LO = mc->sc_mdlo;
    382   tst->arch.vex_shadow1 = priv1->vex_shadow1;
    383   tst->arch.vex_shadow2 = priv1->vex_shadow2;
    384 
    385   VG_TRACK(die_mem_stack_signal, sp, frame_size);
    386   if (VG_(clo_trace_signals))
    387     VG_(message)( Vg_DebugMsg,
    388          "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#x\n",
    389          tid, isRT, tst->arch.vex.guest_PC);
    390   /* tell the tools */
    391   VG_TRACK( post_deliver_signal, tid, sigNo );
    392 }
    393 
    394 #endif // defined(VGP_mips32_linux)
    395 
    396 /*--------------------------------------------------------------------*/
    397 /*--- end                                  sigframe-mips32-linux.c ---*/
    398 /*--------------------------------------------------------------------*/
    399