Home | History | Annotate | Download | only in m_sigframe
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Create/destroy signal delivery frames.                       ---*/
      4 /*---                                       sigframe-ppc64-linux.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2000-2015 Nicholas Nethercote
     12       njn (at) valgrind.org
     13    Copyright (C) 2004-2015 Paul Mackerras
     14       paulus (at) samba.org
     15 
     16    This program is free software; you can redistribute it and/or
     17    modify it under the terms of the GNU General Public License as
     18    published by the Free Software Foundation; either version 2 of the
     19    License, or (at your option) any later version.
     20 
     21    This program is distributed in the hope that it will be useful, but
     22    WITHOUT ANY WARRANTY; without even the implied warranty of
     23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     24    General Public License for more details.
     25 
     26    You should have received a copy of the GNU General Public License
     27    along with this program; if not, write to the Free Software
     28    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     29    02111-1307, USA.
     30 
     31    The GNU General Public License is contained in the file COPYING.
     32 */
     33 
     34 #if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
     35 
     36 #include "pub_core_basics.h"
     37 #include "pub_core_vki.h"
     38 #include "pub_core_vkiscnums.h"
     39 #include "pub_core_threadstate.h"
     40 #include "pub_core_aspacemgr.h"
     41 #include "pub_core_libcbase.h"
     42 #include "pub_core_libcassert.h"
     43 #include "pub_core_libcprint.h"
     44 #include "pub_core_machine.h"
     45 #include "pub_core_options.h"
     46 #include "pub_core_sigframe.h"
     47 #include "pub_core_signals.h"
     48 #include "pub_core_tooliface.h"
     49 #include "pub_core_trampoline.h"
     50 #include "pub_core_transtab.h"      // VG_(discard_translations)
     51 #include "priv_sigframe.h"
     52 
     53 /* This module creates and removes signal frames for signal deliveries
     54    on ppc64-linux.
     55 
     56    Note, this file contains kernel-specific knowledge in the form of
     57    'struct sigframe' and 'struct rt_sigframe'.  How does that relate
     58    to the vki kernel interface stuff?
     59 
     60    Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
     61    onto the client's stack.  This contains a subsidiary
     62    vki_ucontext.  That holds the vcpu's state across the signal,
     63    so that the sighandler can mess with the vcpu state if it
     64    really wants.
     65 
     66    FIXME: sigcontexting is basically broken for the moment.  When
     67    delivering a signal, the integer registers and %eflags are
     68    correctly written into the sigcontext, however the FP and SSE state
     69    is not.  When returning from a signal, only the integer registers
     70    are restored from the sigcontext; the rest of the CPU state is
     71    restored to what it was before the signal.
     72 
     73    This will be fixed.
     74 */
     75 
     76 
     77 /*------------------------------------------------------------*/
     78 /*--- Signal frame layouts                                 ---*/
     79 /*------------------------------------------------------------*/
     80 
     81 // A structure in which to save the application's registers
     82 // during the execution of signal handlers.
     83 
     84 // On ppc64-linux, rt_sigframe is used for all signals.
     85 
     86 // In theory, so long as we get the arguments to the handler function
     87 // right, it doesn't matter what the exact layout of the rest of the
     88 // frame is.  Unfortunately, things like gcc's exception unwinding
     89 // make assumptions about the locations of various parts of the frame,
     90 // so we need to duplicate it exactly.
     91 
     92 /* Many of these byzantine details derived from
     93    linux-2.6.13/arch/ppc64/kernel/signal.c */
     94 
     95 #define TRAMP_SIZE 6 /* who knows why - it only needs to be 2. */
     96 
     97 /* Structure containing bits of information that we want to save
     98    on signal delivery. */
     99 struct vg_sig_private {
    100    UInt  magicPI;
    101    UInt  sigNo_private;
    102    ULong _unused; /* makes the struct size be zero % 16 */
    103    VexGuestPPC64State vex_shadow1;
    104    VexGuestPPC64State vex_shadow2;
    105 };
    106 
    107 /* Structure put on stack for all signal handlers. */
    108 struct rt_sigframe {
    109    struct vki_ucontext   uc;
    110    ULong                 _unused[2];
    111    UInt                  tramp[TRAMP_SIZE];
    112    struct vki_siginfo*   pinfo;
    113    void*                 puc;
    114    vki_siginfo_t         info;
    115    struct vg_sig_private priv;
    116    UChar                 abigap[288];   // unused
    117 };
    118 
    119 #define SET_SIGNAL_LR(zztst, zzval)                          \
    120    do { tst->arch.vex.guest_LR = (zzval);                    \
    121       VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
    122                 offsetof(VexGuestPPC64State,guest_LR),       \
    123                 sizeof(UWord) );                             \
    124    } while (0)
    125 
    126 #define SET_SIGNAL_GPR(zztst, zzn, zzval)                    \
    127    do { tst->arch.vex.guest_GPR##zzn = (zzval);              \
    128       VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,     \
    129                 offsetof(VexGuestPPC64State,guest_GPR##zzn), \
    130                 sizeof(UWord) );                             \
    131    } while (0)
    132 
    133 
    134 
    135 /* EXPORTED */
    136 void VG_(sigframe_create)( ThreadId tid,
    137                            Bool on_altstack,
    138                            Addr sp_top_of_frame,
    139                            const vki_siginfo_t *siginfo,
    140                            const struct vki_ucontext *siguc,
    141                            void *handler,
    142                            UInt flags,
    143                            const vki_sigset_t *mask,
    144 		           void *restorer )
    145 {
    146    struct vg_sig_private* priv;
    147    Addr sp;
    148    ThreadState* tst;
    149    Int sigNo = siginfo->si_signo;
    150    /* Addr faultaddr; */ /* UNUSED */
    151    struct rt_sigframe* frame;
    152 
    153    /* Stack must be 16-byte aligned */
    154    vg_assert(VG_IS_16_ALIGNED(sizeof(struct vg_sig_private)));
    155    vg_assert(VG_IS_16_ALIGNED(sizeof(struct rt_sigframe)));
    156 
    157    sp_top_of_frame &= ~0xf;
    158    sp = sp_top_of_frame - sizeof(struct rt_sigframe);
    159 
    160    tst = VG_(get_ThreadState)(tid);
    161    if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
    162       return;
    163 
    164    vg_assert(VG_IS_16_ALIGNED(sp));
    165 
    166    frame = (struct rt_sigframe *) sp;
    167 
    168    /* clear it (conservatively) */
    169    VG_(memset)(frame, 0, sizeof(*frame));
    170 
    171    /////////
    172    frame->pinfo = &frame->info;
    173    frame->puc = &frame->uc;
    174 
    175    frame->uc.uc_flags = 0;
    176    frame->uc.uc_link = 0;
    177    /////////
    178 
    179    /* Set up the stack chain pointer */
    180    VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
    181              sp, sizeof(UWord) );
    182    *(Addr *)sp = tst->arch.vex.guest_GPR1;
    183    VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
    184              sp, sizeof(UWord) );
    185 
    186    /* UNUSED:
    187    faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
    188    if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
    189       faultaddr = tst->arch.vex.guest_CIA;
    190    */
    191 
    192    VG_(memcpy)(&frame->info, siginfo, sizeof(*siginfo));
    193    VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
    194              (Addr)&frame->info, sizeof(frame->info) );
    195 
    196    frame->uc.uc_flags = 0;
    197    frame->uc.uc_link  = 0;
    198    frame->uc.uc_stack = tst->altstack;
    199    frame->uc.uc_sigmask = tst->sig_mask;
    200    VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
    201              (Addr)(&frame->uc), sizeof(frame->uc) );
    202 
    203 #  define DO(gpr)  frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr] \
    204                       = tst->arch.vex.guest_GPR##gpr
    205    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
    206    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
    207    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
    208    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
    209 #  undef DO
    210 
    211    frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP]     = tst->arch.vex.guest_CIA;
    212 #ifdef VGP_ppc64le_linux
    213    frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR]     = 0xf033;  /* pretty arbitrary */
    214 #else
    215    frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR]     = 0xf032;  /* pretty arbitrary */
    216 #endif
    217    frame->uc.uc_mcontext.gp_regs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
    218    frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR]     = tst->arch.vex.guest_CTR;
    219    frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK]     = tst->arch.vex.guest_LR;
    220    frame->uc.uc_mcontext.gp_regs[VKI_PT_XER]     = LibVEX_GuestPPC64_get_XER(
    221                                                       &tst->arch.vex);
    222    frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR]     = LibVEX_GuestPPC64_get_CR(
    223                                                       &tst->arch.vex);
    224    //mc->mc_gregs[VKI_PT_MQ]      = 0;
    225    //mc->mc_gregs[VKI_PT_TRAP]    = 0;
    226    //mc->mc_gregs[VKI_PT_DAR]     = fault_addr;
    227    //mc->mc_gregs[VKI_PT_DSISR]   = 0;
    228    //mc->mc_gregs[VKI_PT_RESULT]  = 0;
    229 
    230    /* XXX should do FP and vector regs */
    231 
    232    /* set up signal return trampoline */
    233    /* NB.  5 Sept 07.  mc->mc_pad[0..1] used to contain a the code to
    234       which the signal handler returns, and it just did sys_sigreturn
    235       or sys_rt_sigreturn.  But this doesn't work if the stack is
    236       non-executable, and it isn't consistent with the x86-linux and
    237       amd64-linux scheme for removing the stack frame.  So instead be
    238       consistent and use a stub in m_trampoline.  Then it doesn't
    239       matter whether or not the (guest) stack is executable.  This
    240       fixes #149519 and #145837. */
    241    frame->tramp[0] = 0; /* invalid */
    242    frame->tramp[1] = 0; /* invalid */
    243    VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid,
    244             (Addr)&frame->tramp, sizeof(frame->tramp));
    245 
    246    /* invalidate any translation of this area */
    247    VG_(discard_translations)( (Addr)&frame->tramp[0],
    248                               sizeof(frame->tramp), "stack_mcontext" );
    249 
    250    /* set the signal handler to return to the trampoline */
    251    SET_SIGNAL_LR(tst, (Addr)&VG_(ppc64_linux_SUBST_FOR_rt_sigreturn));
    252 
    253    /* Stack pointer for the handler .. (note, back chain set
    254       earlier) */
    255    SET_SIGNAL_GPR(tid, 1, sp);
    256 
    257    /* Args for the handler .. */
    258    SET_SIGNAL_GPR(tid, 3, sigNo);
    259    SET_SIGNAL_GPR(tid, 4, (Addr) &frame->info);
    260    SET_SIGNAL_GPR(tid, 5, (Addr) &frame->uc);
    261    /* the kernel sets this, though it doesn't seem to be in the ABI */
    262    SET_SIGNAL_GPR(tid, 6, (Addr) &frame->info);
    263 
    264    /* Handler is in fact a standard ppc64-linux function descriptor,
    265       so extract the function entry point and also the toc ptr to use. */
    266 #if defined(VGP_ppc64be_linux)
    267    SET_SIGNAL_GPR(tid, 2, (Addr) ((ULong*)handler)[1]);
    268    tst->arch.vex.guest_CIA = (Addr) ((ULong*)handler)[0];
    269 #else
    270    SET_SIGNAL_GPR(tid, 12, (Addr) handler);
    271    tst->arch.vex.guest_CIA = (Addr) handler;
    272 #endif
    273    priv = &frame->priv;
    274    priv->magicPI       = 0x31415927;
    275    priv->sigNo_private = sigNo;
    276    priv->vex_shadow1   = tst->arch.vex_shadow1;
    277    priv->vex_shadow2   = tst->arch.vex_shadow2;
    278 
    279    if (0)
    280       VG_(printf)("pushed signal frame; %%R1 now = %#lx, "
    281                   "next %%CIA = %#llx, status=%d\n",
    282 		  sp, tst->arch.vex.guest_CIA, (Int)tst->status);
    283 }
    284 
    285 
    286 /*------------------------------------------------------------*/
    287 /*--- Destroying signal frames                             ---*/
    288 /*------------------------------------------------------------*/
    289 
    290 /* EXPORTED */
    291 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
    292 {
    293    ThreadState *tst;
    294    struct vg_sig_private *priv;
    295    Addr sp;
    296    UInt frame_size;
    297    struct rt_sigframe *frame;
    298    Int sigNo;
    299    Bool has_siginfo = isRT;
    300 
    301    vg_assert(VG_(is_valid_tid)(tid));
    302    tst = VG_(get_ThreadState)(tid);
    303 
    304    /* Check that the stack frame looks valid */
    305    sp = tst->arch.vex.guest_GPR1;
    306    vg_assert(VG_IS_16_ALIGNED(sp));
    307    /* JRS 17 Nov 05: This code used to check that *sp -- which should
    308       have been set by the stwu at the start of the handler -- points
    309       to just above the frame (ie, the previous frame).  However, that
    310       isn't valid when delivering signals on alt stacks.  So I removed
    311       it.  The frame is still sanity-checked using the priv->magicPI
    312       field. */
    313 
    314    frame = (struct rt_sigframe *)sp;
    315    frame_size = sizeof(*frame);
    316    priv = &frame->priv;
    317    vg_assert(priv->magicPI == 0x31415927);
    318    tst->sig_mask = frame->uc.uc_sigmask;
    319    tst->tmp_sig_mask = tst->sig_mask;
    320 
    321    sigNo = priv->sigNo_private;
    322 
    323 #  define DO(gpr)  tst->arch.vex.guest_GPR##gpr \
    324                       = frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr]
    325    DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
    326    DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
    327    DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
    328    DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
    329 #  undef DO
    330 
    331    tst->arch.vex.guest_CIA = frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP];
    332 
    333    LibVEX_GuestPPC64_put_CR( frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR],
    334                              &tst->arch.vex );
    335 
    336    tst->arch.vex.guest_LR  = frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK];
    337    tst->arch.vex.guest_CTR = frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR];
    338    LibVEX_GuestPPC64_put_XER( frame->uc.uc_mcontext.gp_regs[VKI_PT_XER],
    339                               &tst->arch.vex );
    340 
    341    tst->arch.vex_shadow1 = priv->vex_shadow1;
    342    tst->arch.vex_shadow2 = priv->vex_shadow2;
    343 
    344    VG_TRACK(die_mem_stack_signal, sp, frame_size);
    345 
    346    if (VG_(clo_trace_signals))
    347       VG_(message)(Vg_DebugMsg,
    348                    "vg_pop_signal_frame (thread %u): isRT=%d "
    349                    "valid magic; EIP=%#llx\n",
    350                    tid, has_siginfo, tst->arch.vex.guest_CIA);
    351 
    352    /* tell the tools */
    353    VG_TRACK( post_deliver_signal, tid, sigNo );
    354 }
    355 
    356 #endif // defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
    357 
    358 /*--------------------------------------------------------------------*/
    359 /*--- end                                                          ---*/
    360 /*--------------------------------------------------------------------*/
    361