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_threadstate.h"
     38 #include "pub_core_aspacemgr.h"
     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_sigframe.h"
     45 #include "pub_core_signals.h"
     46 #include "pub_core_tooliface.h"
     47 #include "pub_core_trampoline.h"
     48 #include "priv_sigframe.h"
     49 
     50 struct vg_sig_private {
     51    UInt magicPI;
     52    UInt sigNo_private;
     53    VexGuestMIPS64State vex_shadow1;
     54    VexGuestMIPS64State vex_shadow2;
     55 };
     56 
     57 struct sigframe {
     58    UInt sf_ass[4];  /* argument save space for o32 */
     59    UInt sf_pad[2];  /* Was: signal trampoline */
     60    struct vki_sigcontext sf_sc;
     61    vki_sigset_t sf_mask;
     62    struct vg_sig_private priv;
     63 };
     64 
     65 struct rt_sigframe {
     66    UInt rs_ass[4];  /* argument save space for o32 */
     67    UInt rs_pad[2];  /* Was: signal trampoline */
     68    vki_siginfo_t rs_info;
     69    struct vki_ucontext rs_uc;
     70    struct vg_sig_private priv;
     71 };
     72 
     73 
     74 static void setup_sigcontext ( ThreadState* tst, struct vki_sigcontext **sc1,
     75                                const vki_siginfo_t *si)
     76 {
     77    struct vki_sigcontext *sc = *sc1;
     78 
     79    VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
     80             (Addr)sc, sizeof(unsigned long long)*34);
     81    sc->sc_regs[1] = tst->arch.vex.guest_r1;
     82    sc->sc_regs[2] = tst->arch.vex.guest_r2;
     83    sc->sc_regs[3] = tst->arch.vex.guest_r3;
     84    sc->sc_regs[4] = tst->arch.vex.guest_r4;
     85    sc->sc_regs[5] = tst->arch.vex.guest_r5;
     86    sc->sc_regs[6] = tst->arch.vex.guest_r6;
     87    sc->sc_regs[7] = tst->arch.vex.guest_r7;
     88    sc->sc_regs[8] = tst->arch.vex.guest_r8;
     89    sc->sc_regs[9] = tst->arch.vex.guest_r9;
     90    sc->sc_regs[10] = tst->arch.vex.guest_r10;
     91    sc->sc_regs[11] = tst->arch.vex.guest_r11;
     92    sc->sc_regs[12] = tst->arch.vex.guest_r12;
     93    sc->sc_regs[13] = tst->arch.vex.guest_r13;
     94    sc->sc_regs[14] = tst->arch.vex.guest_r14;
     95    sc->sc_regs[15] = tst->arch.vex.guest_r15;
     96    sc->sc_regs[16] = tst->arch.vex.guest_r16;
     97    sc->sc_regs[17] = tst->arch.vex.guest_r17;
     98    sc->sc_regs[18] = tst->arch.vex.guest_r18;
     99    sc->sc_regs[19] = tst->arch.vex.guest_r19;
    100    sc->sc_regs[20] = tst->arch.vex.guest_r20;
    101    sc->sc_regs[21] = tst->arch.vex.guest_r21;
    102    sc->sc_regs[22] = tst->arch.vex.guest_r22;
    103    sc->sc_regs[23] = tst->arch.vex.guest_r23;
    104    sc->sc_regs[24] = tst->arch.vex.guest_r24;
    105    sc->sc_regs[25] = tst->arch.vex.guest_r25;
    106    sc->sc_regs[26] = tst->arch.vex.guest_r26;
    107    sc->sc_regs[27] = tst->arch.vex.guest_r27;
    108    sc->sc_regs[28] = tst->arch.vex.guest_r28;
    109    sc->sc_regs[29] = tst->arch.vex.guest_r29;
    110    sc->sc_regs[30] = tst->arch.vex.guest_r30;
    111    sc->sc_regs[31] = tst->arch.vex.guest_r31;
    112    sc->sc_pc = tst->arch.vex.guest_PC;
    113    sc->sc_mdhi = tst->arch.vex.guest_HI;
    114    sc->sc_mdlo = tst->arch.vex.guest_LO;
    115 }
    116 
    117 /* EXPORTED */
    118 void VG_(sigframe_create) ( ThreadId tid,
    119                             Addr sp_top_of_frame,
    120                             const vki_siginfo_t *siginfo,
    121                             const struct vki_ucontext *siguc,
    122                             void *handler,
    123                             UInt flags,
    124                             const vki_sigset_t *mask,
    125                             void *restorer )
    126 {
    127    Addr sp;
    128    ThreadState* tst = VG_(get_ThreadState)(tid);
    129    Int sigNo = siginfo->si_signo;
    130    struct vg_sig_private *priv;
    131    /* Stack must be 16-byte aligned */
    132    sp_top_of_frame &= ~0xf;
    133 
    134    sp = sp_top_of_frame - sizeof(struct rt_sigframe);
    135 
    136    tst = VG_(get_ThreadState)(tid);
    137    if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
    138       return;
    139 
    140    sp = VG_ROUNDDN(sp, 16);
    141 
    142    struct rt_sigframe *frame = (struct rt_sigframe *)sp;
    143    struct vki_ucontext *ucp = &frame->rs_uc;
    144    if (VG_(clo_trace_signals))
    145       VG_(printf)("rt_sigframe\n");
    146    /* Create siginfo. */
    147    VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
    148             (Addr)&frame->rs_info, sizeof(frame->rs_info));
    149 
    150    VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo));
    151 
    152    VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
    153             (Addr)&frame->rs_info, sizeof(frame->rs_info));
    154 
    155    /* Create the ucontext. */
    156    VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
    157             (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext));
    158 
    159    ucp->uc_flags = 0;
    160    ucp->uc_link = 0;
    161    ucp->uc_stack = tst->altstack;
    162 
    163    VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
    164             offsetof(struct vki_ucontext, uc_mcontext));
    165 
    166    struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext);
    167    setup_sigcontext(tst, &(scp), siginfo);
    168    ucp->uc_sigmask = tst->sig_mask;
    169    priv = &frame->priv;
    170 
    171    /* Arguments to signal handler:
    172 
    173       a0 = signal number
    174       a1 = 0 (should be cause)
    175       a2 = pointer to ucontext
    176 
    177       $25 and c0_epc point to the signal handler, $29 points to
    178       the struct rt_sigframe. */
    179 
    180    tst->arch.vex.guest_r4 = siginfo->si_signo;
    181    tst->arch.vex.guest_r5 = (Addr) &frame->rs_info;
    182    tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc;
    183    tst->arch.vex.guest_r29 = (Addr) frame;
    184    tst->arch.vex.guest_r25 = (Addr) handler;
    185 
    186    if (flags & VKI_SA_RESTORER)
    187       tst->arch.vex.guest_r31 = (Addr) restorer;
    188    else
    189       tst->arch.vex.guest_r31 = (Addr)&VG_(mips64_linux_SUBST_FOR_rt_sigreturn);
    190 
    191    priv->magicPI       = 0x31415927;
    192    priv->sigNo_private = sigNo;
    193    priv->vex_shadow1   = tst->arch.vex_shadow1;
    194    priv->vex_shadow2   = tst->arch.vex_shadow2;
    195    /* Set the thread so it will next run the handler. */
    196    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
    197    if (VG_(clo_trace_signals))
    198       VG_(printf)("handler = %p\n", handler);
    199    tst->arch.vex.guest_PC = (Addr) handler;
    200    /* This thread needs to be marked runnable, but we leave that
    201       the caller to do. */
    202 }
    203 
    204 /* EXPORTED */
    205 void VG_(sigframe_destroy) ( ThreadId tid, Bool isRT )
    206 {
    207    ThreadState *tst;
    208    struct vg_sig_private *priv1;
    209    Addr sp;
    210    UInt frame_size;
    211    struct vki_sigcontext *mc;
    212    Int sigNo;
    213 
    214    vg_assert(VG_(is_valid_tid)(tid));
    215    tst = VG_(get_ThreadState)(tid);
    216    sp   = tst->arch.vex.guest_r29;
    217    struct rt_sigframe *frame = (struct rt_sigframe *)sp;
    218    struct vki_ucontext *ucp = &frame->rs_uc;
    219    frame_size = sizeof(*frame);
    220    mc = &ucp->uc_mcontext;
    221    tst->sig_mask = ucp->uc_sigmask;
    222    tst->tmp_sig_mask = ucp->uc_sigmask;
    223    priv1 = &frame->priv;
    224    sigNo = priv1->sigNo_private;
    225    vg_assert(priv1->magicPI == 0x31415927);
    226    /* restore regs */
    227    tst->arch.vex.guest_r1 = mc->sc_regs[1];
    228    tst->arch.vex.guest_r2 = mc->sc_regs[2];
    229    tst->arch.vex.guest_r3 = mc->sc_regs[3];
    230    tst->arch.vex.guest_r4 = mc->sc_regs[4];
    231    tst->arch.vex.guest_r5 = mc->sc_regs[5];
    232    tst->arch.vex.guest_r6 = mc->sc_regs[6];
    233    tst->arch.vex.guest_r7 = mc->sc_regs[7];
    234    tst->arch.vex.guest_r8 = mc->sc_regs[8];
    235    tst->arch.vex.guest_r9 = mc->sc_regs[9];
    236    tst->arch.vex.guest_r10 = mc->sc_regs[10];
    237    tst->arch.vex.guest_r11 = mc->sc_regs[11];
    238    tst->arch.vex.guest_r12 = mc->sc_regs[12];
    239    tst->arch.vex.guest_r13= mc->sc_regs[13];
    240    tst->arch.vex.guest_r14 = mc->sc_regs[14];
    241    tst->arch.vex.guest_r15 = mc->sc_regs[15];
    242    tst->arch.vex.guest_r16 = mc->sc_regs[16];
    243    tst->arch.vex.guest_r17 = mc->sc_regs[17];
    244    tst->arch.vex.guest_r18 = mc->sc_regs[18];
    245    tst->arch.vex.guest_r19 = mc->sc_regs[19];
    246    tst->arch.vex.guest_r20 = mc->sc_regs[20];
    247    tst->arch.vex.guest_r21 = mc->sc_regs[21];
    248    tst->arch.vex.guest_r22 = mc->sc_regs[22];
    249    tst->arch.vex.guest_r23 = mc->sc_regs[23];
    250    tst->arch.vex.guest_r24 = mc->sc_regs[24];
    251    tst->arch.vex.guest_r25 = mc->sc_regs[25];
    252    tst->arch.vex.guest_r26 = mc->sc_regs[26];
    253    tst->arch.vex.guest_r27 = mc->sc_regs[27];
    254    tst->arch.vex.guest_r28 = mc->sc_regs[28];
    255    tst->arch.vex.guest_r30 = mc->sc_regs[30];
    256    tst->arch.vex.guest_PC = mc->sc_pc;
    257    tst->arch.vex.guest_r31 = mc->sc_regs[31];
    258    tst->arch.vex.guest_r29 = mc->sc_regs[29];
    259 
    260    tst->arch.vex.guest_HI = mc->sc_mdhi;
    261    tst->arch.vex.guest_LO = mc->sc_mdlo;
    262    tst->arch.vex_shadow1 = priv1->vex_shadow1;
    263    tst->arch.vex_shadow2 = priv1->vex_shadow2;
    264 
    265    VG_TRACK(die_mem_stack_signal, sp, frame_size);
    266    if (VG_(clo_trace_signals))
    267       VG_(message)(Vg_DebugMsg,
    268          "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#llx\n",
    269          tid, isRT, tst->arch.vex.guest_PC);
    270    /* tell the tools */
    271    VG_TRACK( post_deliver_signal, tid, sigNo );
    272 }
    273 
    274 #endif /* defined(VGP_mips64_linux) */
    275 
    276 /*--------------------------------------------------------------------*/
    277 /*--- end                                  sigframe-mips64-linux.c ---*/
    278 /*--------------------------------------------------------------------*/
    279