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-2011 Nicholas Nethercote
     12       njn (at) valgrind.org
     13    Copyright (C) 2004-2011 Paul Mackerras
     14       paulus (at) samba.org
     15    Copyright (C) 2008-2011 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 
    264    tst->arch.vex.guest_R15T = (Addr) handler; /* R15 == PC */
    265 }
    266 
    267 
    268 /*------------------------------------------------------------*/
    269 /*--- Destroying signal frames                             ---*/
    270 /*------------------------------------------------------------*/
    271 
    272 /* EXPORTED */
    273 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
    274 {
    275    ThreadState *tst;
    276    struct vg_sig_private *priv;
    277    Addr sp;
    278    UInt frame_size;
    279    struct vki_sigcontext *mc;
    280    Int sigNo;
    281    Bool has_siginfo = isRT;
    282 
    283    vg_assert(VG_(is_valid_tid)(tid));
    284    tst = VG_(get_ThreadState)(tid);
    285    sp = tst->arch.vex.guest_R13;
    286 
    287    if (has_siginfo) {
    288       struct rt_sigframe *frame = (struct rt_sigframe *)sp;
    289       frame_size = sizeof(*frame);
    290       mc = &frame->sig.uc.uc_mcontext;
    291       priv = &frame->sig.vp;
    292       vg_assert(priv->magicPI == 0x31415927);
    293       tst->sig_mask = frame->sig.uc.uc_sigmask;
    294    } else {
    295       struct sigframe *frame = (struct sigframe *)sp;
    296       frame_size = sizeof(*frame);
    297       mc = &frame->uc.uc_mcontext;
    298       priv = &frame->vp;
    299       vg_assert(priv->magicPI == 0x31415927);
    300       tst->sig_mask = frame->uc.uc_sigmask;
    301       /*tst->sig_mask.sig[0] = frame->uc.uc_mcontext.oldmask;
    302       tst->sig_mask.sig[1] = frame->uc.uc_mcontext._unused[3];
    303       VG_(printf)("Setting signmask to %08x%08x\n",tst->sig_mask[0],tst->sig_mask[1]);
    304 */
    305    }
    306    tst->tmp_sig_mask = tst->sig_mask;
    307 
    308    sigNo = priv->sigNo_private;
    309 
    310     //XXX: restore regs
    311 #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
    312    REST(r0,R0);
    313    REST(r1,R1);
    314    REST(r2,R2);
    315    REST(r3,R3);
    316    REST(r4,R4);
    317    REST(r5,R5);
    318    REST(r6,R6);
    319    REST(r7,R7);
    320    REST(r8,R8);
    321    REST(r9,R9);
    322    REST(r10,R10);
    323    REST(fp,R11);
    324    REST(ip,R12);
    325    REST(sp,R13);
    326    REST(lr,R14);
    327    REST(pc,R15T);
    328 #  undef REST
    329 
    330    /* Uh, the next line makes all the REST() above pointless. */
    331    tst->arch.vex         = priv->vex;
    332 
    333    tst->arch.vex_shadow1 = priv->vex_shadow1;
    334    tst->arch.vex_shadow2 = priv->vex_shadow2;
    335 
    336    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
    337              frame_size + VG_STACK_REDZONE_SZB );
    338 
    339    if (VG_(clo_trace_signals))
    340       VG_(message)(Vg_DebugMsg,
    341                    "vg_pop_signal_frame (thread %d): "
    342                    "isRT=%d valid magic; PC=%#x\n",
    343                    tid, has_siginfo, tst->arch.vex.guest_R15T);
    344 
    345    /* tell the tools */
    346    VG_TRACK( post_deliver_signal, tid, sigNo );
    347 }
    348 
    349 #endif // defined(VGP_arm_linux)
    350 
    351 /*--------------------------------------------------------------------*/
    352 /*--- end                                     sigframe-arm-linux.c ---*/
    353 /*--------------------------------------------------------------------*/
    354