Home | History | Annotate | Download | only in m_sigframe
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Create/destroy signal delivery frames.                       ---*/
      4 /*---                                  sigframe-mips64-linux.c     ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2010-2013 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_mips64_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    UInt magicPI;
     53    UInt sigNo_private;
     54    VexGuestMIPS64State vex_shadow1;
     55    VexGuestMIPS64State vex_shadow2;
     56 };
     57 
     58 struct sigframe {
     59    UInt sf_ass[4];  /* argument save space for o32 */
     60    UInt sf_pad[2];  /* Was: signal trampoline */
     61    struct vki_sigcontext sf_sc;
     62    vki_sigset_t sf_mask;
     63    struct vg_sig_private priv;
     64 };
     65 
     66 struct rt_sigframe {
     67    UInt rs_ass[4];  /* argument save space for o32 */
     68    UInt rs_pad[2];  /* Was: signal trampoline */
     69    vki_siginfo_t rs_info;
     70    struct vki_ucontext rs_uc;
     71    struct vg_sig_private priv;
     72 };
     73 
     74 /* Extend the stack segment downwards if needed so as to ensure the new signal
     75    frames are mapped to something. Return a Bool indicating whether or not the
     76    operation was successful.
     77 */
     78 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
     79 {
     80    ThreadId tid = tst->tid;
     81    NSegment const* stackseg = NULL;
     82 
     83    if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
     84       stackseg = VG_(am_find_nsegment)(addr);
     85    }
     86 
     87    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
     88       VG_(message)(Vg_UserMsg,
     89          "Can't extend stack to %#lx during signal delivery for thread %d:\n",
     90          addr, tid);
     91       if (stackseg == NULL)
     92          VG_(message)(Vg_UserMsg, " no stack segment\n");
     93       else
     94          VG_(message)(Vg_UserMsg, " too small or bad protection modes\n");
     95 
     96       /* set SIGSEGV to default handler */
     97       VG_(set_default_handler)(VKI_SIGSEGV);
     98       VG_(synth_fault_mapping)(tid, addr);
     99 
    100       /* The whole process should be about to die, since the default
    101          action of SIGSEGV to kill the whole process. */
    102       return False;
    103    }
    104 
    105    /* For tracking memory events, indicate the entire frame has been
    106       allocated. */
    107    VG_TRACK(new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
    108             size + VG_STACK_REDZONE_SZB, tid);
    109 
    110    return True;
    111 }
    112 
    113 static void setup_sigcontext ( ThreadState* tst, struct vki_sigcontext **sc1,
    114                                const vki_siginfo_t *si)
    115 {
    116    struct vki_sigcontext *sc = *sc1;
    117 
    118    VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
    119             (Addr)sc, sizeof(unsigned long long)*34);
    120    sc->sc_regs[1] = tst->arch.vex.guest_r1;
    121    sc->sc_regs[2] = tst->arch.vex.guest_r2;
    122    sc->sc_regs[3] = tst->arch.vex.guest_r3;
    123    sc->sc_regs[4] = tst->arch.vex.guest_r4;
    124    sc->sc_regs[5] = tst->arch.vex.guest_r5;
    125    sc->sc_regs[6] = tst->arch.vex.guest_r6;
    126    sc->sc_regs[7] = tst->arch.vex.guest_r7;
    127    sc->sc_regs[8] = tst->arch.vex.guest_r8;
    128    sc->sc_regs[9] = tst->arch.vex.guest_r9;
    129    sc->sc_regs[10] = tst->arch.vex.guest_r10;
    130    sc->sc_regs[11] = tst->arch.vex.guest_r11;
    131    sc->sc_regs[12] = tst->arch.vex.guest_r12;
    132    sc->sc_regs[13] = tst->arch.vex.guest_r13;
    133    sc->sc_regs[14] = tst->arch.vex.guest_r14;
    134    sc->sc_regs[15] = tst->arch.vex.guest_r15;
    135    sc->sc_regs[16] = tst->arch.vex.guest_r16;
    136    sc->sc_regs[17] = tst->arch.vex.guest_r17;
    137    sc->sc_regs[18] = tst->arch.vex.guest_r18;
    138    sc->sc_regs[19] = tst->arch.vex.guest_r19;
    139    sc->sc_regs[20] = tst->arch.vex.guest_r20;
    140    sc->sc_regs[21] = tst->arch.vex.guest_r21;
    141    sc->sc_regs[22] = tst->arch.vex.guest_r22;
    142    sc->sc_regs[23] = tst->arch.vex.guest_r23;
    143    sc->sc_regs[24] = tst->arch.vex.guest_r24;
    144    sc->sc_regs[25] = tst->arch.vex.guest_r25;
    145    sc->sc_regs[26] = tst->arch.vex.guest_r26;
    146    sc->sc_regs[27] = tst->arch.vex.guest_r27;
    147    sc->sc_regs[28] = tst->arch.vex.guest_r28;
    148    sc->sc_regs[29] = tst->arch.vex.guest_r29;
    149    sc->sc_regs[30] = tst->arch.vex.guest_r30;
    150    sc->sc_regs[31] = tst->arch.vex.guest_r31;
    151    sc->sc_pc = tst->arch.vex.guest_PC;
    152    sc->sc_mdhi = tst->arch.vex.guest_HI;
    153    sc->sc_mdlo = tst->arch.vex.guest_LO;
    154 }
    155 
    156 /* EXPORTED */
    157 void VG_(sigframe_create) ( ThreadId tid,
    158                             Addr sp_top_of_frame,
    159                             const vki_siginfo_t *siginfo,
    160                             const struct vki_ucontext *siguc,
    161                             void *handler,
    162                             UInt flags,
    163                             const vki_sigset_t *mask,
    164                             void *restorer )
    165 {
    166    Addr sp;
    167    ThreadState* tst = VG_(get_ThreadState)(tid);
    168    Int sigNo = siginfo->si_signo;
    169    struct vg_sig_private *priv;
    170    /* Stack must be 16-byte aligned */
    171    sp_top_of_frame &= ~0xf;
    172 
    173    sp = sp_top_of_frame - sizeof(struct rt_sigframe);
    174 
    175    tst = VG_(get_ThreadState)(tid);
    176    if (!extend(tst, sp, sp_top_of_frame - sp))
    177       return;
    178 
    179    sp = VG_ROUNDDN(sp, 16);
    180 
    181    struct rt_sigframe *frame = (struct rt_sigframe *)sp;
    182    struct vki_ucontext *ucp = &frame->rs_uc;
    183    if (VG_(clo_trace_signals))
    184       VG_(printf)("rt_sigframe\n");
    185    /* Create siginfo. */
    186    VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
    187             (Addr)&frame->rs_info, sizeof(frame->rs_info));
    188 
    189    VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo));
    190 
    191    VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
    192             (Addr)&frame->rs_info, sizeof(frame->rs_info));
    193 
    194    /* Create the ucontext. */
    195    VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
    196             (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext));
    197 
    198    ucp->uc_flags = 0;
    199    ucp->uc_link = 0;
    200    ucp->uc_stack = tst->altstack;
    201 
    202    VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
    203             offsetof(struct vki_ucontext, uc_mcontext));
    204 
    205    struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext);
    206    setup_sigcontext(tst, &(scp), siginfo);
    207    ucp->uc_sigmask = tst->sig_mask;
    208    priv = &frame->priv;
    209 
    210    /* Arguments to signal handler:
    211 
    212       a0 = signal number
    213       a1 = 0 (should be cause)
    214       a2 = pointer to ucontext
    215 
    216       $25 and c0_epc point to the signal handler, $29 points to
    217       the struct rt_sigframe. */
    218 
    219    tst->arch.vex.guest_r4 = siginfo->si_signo;
    220    tst->arch.vex.guest_r5 = (Addr) &frame->rs_info;
    221    tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc;
    222    tst->arch.vex.guest_r29 = (Addr) frame;
    223    tst->arch.vex.guest_r25 = (Addr) handler;
    224 
    225    if (flags & VKI_SA_RESTORER)
    226       tst->arch.vex.guest_r31 = (Addr) restorer;
    227    else
    228       tst->arch.vex.guest_r31 = (Addr)&VG_(mips64_linux_SUBST_FOR_rt_sigreturn);
    229 
    230    priv->magicPI       = 0x31415927;
    231    priv->sigNo_private = sigNo;
    232    priv->vex_shadow1   = tst->arch.vex_shadow1;
    233    priv->vex_shadow2   = tst->arch.vex_shadow2;
    234    /* Set the thread so it will next run the handler. */
    235    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
    236    if (VG_(clo_trace_signals))
    237       VG_(printf)("handler = %p\n", handler);
    238    tst->arch.vex.guest_PC = (Addr) handler;
    239    /* This thread needs to be marked runnable, but we leave that
    240       the caller to do. */
    241 }
    242 
    243 /* EXPORTED */
    244 void VG_(sigframe_destroy) ( ThreadId tid, Bool isRT )
    245 {
    246    ThreadState *tst;
    247    struct vg_sig_private *priv1;
    248    Addr sp;
    249    UInt frame_size;
    250    struct vki_sigcontext *mc;
    251    Int sigNo;
    252 
    253    vg_assert(VG_(is_valid_tid)(tid));
    254    tst = VG_(get_ThreadState)(tid);
    255    sp   = tst->arch.vex.guest_r29;
    256    struct rt_sigframe *frame = (struct rt_sigframe *)sp;
    257    struct vki_ucontext *ucp = &frame->rs_uc;
    258    frame_size = sizeof(*frame);
    259    mc = &ucp->uc_mcontext;
    260    tst->sig_mask = ucp->uc_sigmask;
    261    tst->tmp_sig_mask = ucp->uc_sigmask;
    262    priv1 = &frame->priv;
    263    sigNo = priv1->sigNo_private;
    264    vg_assert(priv1->magicPI == 0x31415927);
    265    /* restore regs */
    266    tst->arch.vex.guest_r1 = mc->sc_regs[1];
    267    tst->arch.vex.guest_r2 = mc->sc_regs[2];
    268    tst->arch.vex.guest_r3 = mc->sc_regs[3];
    269    tst->arch.vex.guest_r4 = mc->sc_regs[4];
    270    tst->arch.vex.guest_r5 = mc->sc_regs[5];
    271    tst->arch.vex.guest_r6 = mc->sc_regs[6];
    272    tst->arch.vex.guest_r7 = mc->sc_regs[7];
    273    tst->arch.vex.guest_r8 = mc->sc_regs[8];
    274    tst->arch.vex.guest_r9 = mc->sc_regs[9];
    275    tst->arch.vex.guest_r10 = mc->sc_regs[10];
    276    tst->arch.vex.guest_r11 = mc->sc_regs[11];
    277    tst->arch.vex.guest_r12 = mc->sc_regs[12];
    278    tst->arch.vex.guest_r13= mc->sc_regs[13];
    279    tst->arch.vex.guest_r14 = mc->sc_regs[14];
    280    tst->arch.vex.guest_r15 = mc->sc_regs[15];
    281    tst->arch.vex.guest_r16 = mc->sc_regs[16];
    282    tst->arch.vex.guest_r17 = mc->sc_regs[17];
    283    tst->arch.vex.guest_r18 = mc->sc_regs[18];
    284    tst->arch.vex.guest_r19 = mc->sc_regs[19];
    285    tst->arch.vex.guest_r20 = mc->sc_regs[20];
    286    tst->arch.vex.guest_r21 = mc->sc_regs[21];
    287    tst->arch.vex.guest_r22 = mc->sc_regs[22];
    288    tst->arch.vex.guest_r23 = mc->sc_regs[23];
    289    tst->arch.vex.guest_r24 = mc->sc_regs[24];
    290    tst->arch.vex.guest_r25 = mc->sc_regs[25];
    291    tst->arch.vex.guest_r26 = mc->sc_regs[26];
    292    tst->arch.vex.guest_r27 = mc->sc_regs[27];
    293    tst->arch.vex.guest_r28 = mc->sc_regs[28];
    294    tst->arch.vex.guest_r30 = mc->sc_regs[30];
    295    tst->arch.vex.guest_PC = mc->sc_pc;
    296    tst->arch.vex.guest_r31 = mc->sc_regs[31];
    297    tst->arch.vex.guest_r29 = mc->sc_regs[29];
    298 
    299    tst->arch.vex.guest_HI = mc->sc_mdhi;
    300    tst->arch.vex.guest_LO = mc->sc_mdlo;
    301    tst->arch.vex_shadow1 = priv1->vex_shadow1;
    302    tst->arch.vex_shadow2 = priv1->vex_shadow2;
    303 
    304    VG_TRACK(die_mem_stack_signal, sp, frame_size);
    305    if (VG_(clo_trace_signals))
    306       VG_(message)(Vg_DebugMsg,
    307          "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#llx\n",
    308          tid, isRT, tst->arch.vex.guest_PC);
    309    /* tell the tools */
    310    VG_TRACK( post_deliver_signal, tid, sigNo );
    311 }
    312 
    313 #endif /* defined(VGP_mips64_linux) */
    314 
    315 /*--------------------------------------------------------------------*/
    316 /*--- end                                  sigframe-mips64-linux.c ---*/
    317 /*--------------------------------------------------------------------*/
    318