Home | History | Annotate | Download | only in m_sigframe
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Create/destroy signal delivery frames.                       ---*/
      4 /*---                                         sigframe-arm-linux.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2000-2012 Nicholas Nethercote
     12       njn (at) valgrind.org
     13    Copyright (C) 2004-2012 Paul Mackerras
     14       paulus (at) samba.org
     15    Copyright (C) 2008-2012 Evan Geller
     16       gaze (at) bea.ms
     17 
     18    This program is free software; you can redistribute it and/or
     19    modify it under the terms of the GNU General Public License as
     20    published by the Free Software Foundation; either version 2 of the
     21    License, or (at your option) any later version.
     22 
     23    This program is distributed in the hope that it will be useful, but
     24    WITHOUT ANY WARRANTY; without even the implied warranty of
     25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     26    General Public License for more details.
     27 
     28    You should have received a copy of the GNU General Public License
     29    along with this program; if not, write to the Free Software
     30    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     31    02111-1307, USA.
     32 
     33    The GNU General Public License is contained in the file COPYING.
     34 */
     35 
     36 #if defined(VGP_arm_linux)
     37 
     38 #include "pub_core_basics.h"
     39 #include "pub_core_vki.h"
     40 #include "pub_core_vkiscnums.h"
     41 #include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
     42 #include "pub_core_threadstate.h"
     43 #include "pub_core_aspacemgr.h"
     44 #include "pub_core_libcbase.h"
     45 #include "pub_core_libcassert.h"
     46 #include "pub_core_libcprint.h"
     47 #include "pub_core_machine.h"
     48 #include "pub_core_options.h"
     49 #include "pub_core_sigframe.h"
     50 #include "pub_core_signals.h"
     51 #include "pub_core_tooliface.h"
     52 #include "pub_core_trampoline.h"
     53 #include "pub_core_transtab.h"      // VG_(discard_translations)
     54 
     55 
     56 /* This uses the hack of dumping the vex guest state along with both
     57    shadows in the frame, and restoring it afterwards from there,
     58    rather than pulling it out of the ucontext.  That means that signal
     59    handlers which modify the ucontext and then return, expecting their
     60    modifications to take effect, will have those modifications
     61    ignored.  This could be fixed properly with an hour or so more
     62    effort. */
     63 
     64 
     65 struct vg_sig_private {
     66    UInt magicPI;
     67    UInt sigNo_private;
     68    VexGuestARMState vex;
     69    VexGuestARMState vex_shadow1;
     70    VexGuestARMState vex_shadow2;
     71 };
     72 
     73 struct sigframe {
     74    struct vki_ucontext uc;
     75    unsigned long retcode[2];
     76    struct vg_sig_private vp;
     77 };
     78 
     79 struct rt_sigframe {
     80    vki_siginfo_t info;
     81    struct sigframe sig;
     82 };
     83 
     84 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
     85 {
     86    ThreadId        tid = tst->tid;
     87    NSegment const* stackseg = NULL;
     88 
     89    if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
     90       stackseg = VG_(am_find_nsegment)(addr);
     91       if (0 && stackseg)
     92     VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
     93            addr, stackseg->start, stackseg->end);
     94    }
     95 
     96    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
     97       VG_(message)(
     98          Vg_UserMsg,
     99          "Can't extend stack to %#lx during signal delivery for thread %d:",
    100          addr, tid);
    101       if (stackseg == NULL)
    102          VG_(message)(Vg_UserMsg, "  no stack segment");
    103       else
    104          VG_(message)(Vg_UserMsg, "  too small or bad protection modes");
    105 
    106       /* set SIGSEGV to default handler */
    107       VG_(set_default_handler)(VKI_SIGSEGV);
    108       VG_(synth_fault_mapping)(tid, addr);
    109 
    110       /* The whole process should be about to die, since the default
    111     action of SIGSEGV to kill the whole process. */
    112       return False;
    113    }
    114 
    115    /* For tracking memory events, indicate the entire frame has been
    116       allocated. */
    117    VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
    118              size + VG_STACK_REDZONE_SZB, tid );
    119 
    120    return True;
    121 }
    122 
    123 static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
    124                     UWord trapno, UWord err, const vki_sigset_t *set,
    125                     struct vki_ucontext *uc){
    126 
    127    ThreadState *tst = VG_(get_ThreadState)(tid);
    128    struct vki_sigcontext *sc = &uc->uc_mcontext;
    129 
    130    VG_(memset)(uc, 0, sizeof(*uc));
    131 
    132    uc->uc_flags = 0;
    133    uc->uc_link = 0;
    134    uc->uc_sigmask = *set;
    135    uc->uc_stack = tst->altstack;
    136 
    137 #  define SC2(reg,REG)  sc->arm_##reg = tst->arch.vex.guest_##REG
    138    SC2(r0,R0);
    139    SC2(r1,R1);
    140    SC2(r2,R2);
    141    SC2(r3,R3);
    142    SC2(r4,R4);
    143    SC2(r5,R5);
    144    SC2(r6,R6);
    145    SC2(r7,R7);
    146    SC2(r8,R8);
    147    SC2(r9,R9);
    148    SC2(r10,R10);
    149    SC2(fp,R11);
    150    SC2(ip,R12);
    151    SC2(sp,R13);
    152    SC2(lr,R14);
    153    SC2(pc,R15T);
    154 #  undef SC2
    155 
    156    sc->trap_no = trapno;
    157    sc->error_code = err;
    158    sc->fault_address = (UInt)si->_sifields._sigfault._addr;
    159 }
    160 
    161 
    162 static void build_sigframe(ThreadState *tst,
    163             struct sigframe *frame,
    164             const vki_siginfo_t *siginfo,
    165             const struct vki_ucontext *siguc,
    166             void *handler, UInt flags,
    167             const vki_sigset_t *mask,
    168             void *restorer){
    169 
    170    UWord trapno;
    171    UWord err;
    172    Int  sigNo = siginfo->si_signo;
    173    struct vg_sig_private *priv = &frame->vp;
    174 
    175    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
    176          (Addr)frame, offsetof(struct sigframe, vp));
    177 
    178    if(siguc) {
    179       trapno = siguc->uc_mcontext.trap_no;
    180       err = siguc->uc_mcontext.error_code;
    181    } else {
    182       trapno = 0;
    183       err = 0;
    184    }
    185 
    186    synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
    187 
    188    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
    189          (Addr)frame, offsetof(struct sigframe, vp));
    190 
    191    priv->magicPI = 0x31415927;
    192    priv->sigNo_private = sigNo;
    193    priv->vex         = tst->arch.vex;
    194    priv->vex_shadow1 = tst->arch.vex_shadow1;
    195    priv->vex_shadow2 = tst->arch.vex_shadow2;
    196 
    197 }
    198 
    199 
    200 
    201 /* EXPORTED */
    202 void VG_(sigframe_create)( ThreadId tid,
    203                            Addr sp_top_of_frame,
    204                            const vki_siginfo_t *siginfo,
    205                            const struct vki_ucontext *siguc,
    206                            void *handler,
    207                            UInt flags,
    208                            const vki_sigset_t *mask,
    209                            void *restorer )
    210 {
    211 //   struct vg_sig_private *priv;
    212    Addr sp = sp_top_of_frame;
    213    ThreadState *tst;
    214    Int sigNo = siginfo->si_signo;
    215 //   Addr faultaddr;
    216    UInt size;
    217 
    218    tst = VG_(get_ThreadState)(tid);
    219 
    220    size = flags & VKI_SA_SIGINFO ? sizeof(struct rt_sigframe) :
    221       sizeof(struct sigframe);
    222 
    223    sp -= size;
    224    sp = VG_ROUNDDN(sp, 16);
    225 
    226    if(!extend(tst, sp, size))
    227       I_die_here; // XXX Incorrect behavior
    228 
    229 
    230    if (flags & VKI_SA_SIGINFO){
    231       struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
    232 
    233       /* Track our writes to siginfo */
    234       VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
    235             "signal handler siginfo", (Addr)rsf,
    236             offsetof(struct rt_sigframe, sig));
    237 
    238       VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
    239 
    240       if(sigNo == VKI_SIGILL && siginfo->si_code > 0) {
    241          rsf->info._sifields._sigfault._addr = (Addr *) (tst)->arch.vex.guest_R12; /* IP */
    242       }
    243       VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
    244             (Addr)rsf, offsetof(struct rt_sigframe, sig));
    245 
    246       build_sigframe(tst, &rsf->sig, siginfo, siguc,
    247                              handler, flags, mask, restorer);
    248       tst->arch.vex.guest_R1 = (Addr)&rsf->info;
    249       tst->arch.vex.guest_R2 = (Addr)&rsf->sig.uc;
    250    }
    251    else {
    252       build_sigframe(tst, (struct sigframe *)sp, siginfo, siguc,
    253                              handler, flags, mask, restorer);
    254    }
    255 
    256    VG_(set_SP)(tid, sp);
    257    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
    258          sizeof(Addr));
    259    tst->arch.vex.guest_R0  = sigNo;
    260 
    261    if (flags & VKI_SA_RESTORER)
    262        tst->arch.vex.guest_R14 = (Addr)restorer;
    263    else
    264        tst->arch.vex.guest_R14
    265           = (flags & VKI_SA_SIGINFO)
    266             ? (Addr)&VG_(arm_linux_SUBST_FOR_rt_sigreturn)
    267             : (Addr)&VG_(arm_linux_SUBST_FOR_sigreturn);
    268 
    269    tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
    270 }
    271 
    272 
    273 /*------------------------------------------------------------*/
    274 /*--- Destroying signal frames                             ---*/
    275 /*------------------------------------------------------------*/
    276 
    277 /* EXPORTED */
    278 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
    279 {
    280    ThreadState *tst;
    281    struct vg_sig_private *priv;
    282    Addr sp;
    283    UInt frame_size;
    284    struct vki_sigcontext *mc;
    285    Int sigNo;
    286    Bool has_siginfo = isRT;
    287 
    288    vg_assert(VG_(is_valid_tid)(tid));
    289    tst = VG_(get_ThreadState)(tid);
    290    sp = tst->arch.vex.guest_R13;
    291 
    292    if (has_siginfo) {
    293       struct rt_sigframe *frame = (struct rt_sigframe *)sp;
    294       frame_size = sizeof(*frame);
    295       mc = &frame->sig.uc.uc_mcontext;
    296       priv = &frame->sig.vp;
    297       vg_assert(priv->magicPI == 0x31415927);
    298       tst->sig_mask = frame->sig.uc.uc_sigmask;
    299    } else {
    300       struct sigframe *frame = (struct sigframe *)sp;
    301       frame_size = sizeof(*frame);
    302       mc = &frame->uc.uc_mcontext;
    303       priv = &frame->vp;
    304       vg_assert(priv->magicPI == 0x31415927);
    305       tst->sig_mask = frame->uc.uc_sigmask;
    306       /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
    307       tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
    308       VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
    309 */
    310    }
    311    tst->tmp_sig_mask = tst->sig_mask;
    312 
    313    sigNo = priv->sigNo_private;
    314 
    315     //XXX: restore regs
    316 #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
    317    REST(r0,R0);
    318    REST(r1,R1);
    319    REST(r2,R2);
    320    REST(r3,R3);
    321    REST(r4,R4);
    322    REST(r5,R5);
    323    REST(r6,R6);
    324    REST(r7,R7);
    325    REST(r8,R8);
    326    REST(r9,R9);
    327    REST(r10,R10);
    328    REST(fp,R11);
    329    REST(ip,R12);
    330    REST(sp,R13);
    331    REST(lr,R14);
    332    REST(pc,R15T);
    333 #  undef REST
    334 
    335    /* Uh, the next line makes all the REST() above pointless. */
    336    tst->arch.vex         = priv->vex;
    337 
    338    tst->arch.vex_shadow1 = priv->vex_shadow1;
    339    tst->arch.vex_shadow2 = priv->vex_shadow2;
    340 
    341    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
    342              frame_size + VG_STACK_REDZONE_SZB );
    343 
    344    if (VG_(clo_trace_signals))
    345       VG_(message)(Vg_DebugMsg,
    346                    "vg_pop_signal_frame (thread %d): "
    347                    "isRT=%d valid magic; PC=%#x\n",
    348                    tid, has_siginfo, tst->arch.vex.guest_R15T);
    349 
    350    /* tell the tools */
    351    VG_TRACK( post_deliver_signal, tid, sigNo );
    352 }
    353 
    354 #endif // defined(VGP_arm_linux)
    355 
    356 /*--------------------------------------------------------------------*/
    357 /*--- end                                     sigframe-arm-linux.c ---*/
    358 /*--------------------------------------------------------------------*/
    359