Home | History | Annotate | Download | only in m_sigframe
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Create/destroy signal delivery frames.                       ---*/
      4 /*---                                       sigframe-arm64-linux.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2013-2013 OpenWorks
     12       info (at) open-works.net
     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_arm64_linux)
     33 
     34 #include "pub_core_basics.h"
     35 #include "pub_core_vki.h"
     36 //ZZ #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 //ZZ #include "pub_core_transtab.h"      // VG_(discard_translations)
     50 
     51 
     52 /* This uses the hack of dumping the vex guest state along with both
     53    shadows in the frame, and restoring it afterwards from there,
     54    rather than pulling it out of the ucontext.  That means that signal
     55    handlers which modify the ucontext and then return, expecting their
     56    modifications to take effect, will have those modifications
     57    ignored.  This could be fixed properly with an hour or so more
     58    effort. */
     59 
     60 /* This also always does the 'has siginfo' behaviour whether or
     61    not it is requested. */
     62 
     63 struct vg_sig_private {
     64    UInt magicPI;
     65    UInt sigNo_private;
     66    VexGuestARM64State vex;
     67    VexGuestARM64State vex_shadow1;
     68    VexGuestARM64State vex_shadow2;
     69 };
     70 
     71 struct sigframe {
     72    struct vki_ucontext uc;
     73    unsigned long retcode[2];
     74    struct vg_sig_private vp;
     75 };
     76 
     77 struct rt_sigframe {
     78    vki_siginfo_t info;
     79    struct sigframe sig;
     80 };
     81 
     82 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
     83 {
     84    ThreadId        tid = tst->tid;
     85    NSegment const* stackseg = NULL;
     86 
     87    if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
     88       stackseg = VG_(am_find_nsegment)(addr);
     89       if (0 && stackseg)
     90          VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
     91                      addr, stackseg->start, stackseg->end);
     92    }
     93 
     94    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
     95       VG_(message)(
     96          Vg_UserMsg,
     97          "Can't extend stack to %#lx during signal delivery for thread %d:",
     98          addr, tid);
     99       if (stackseg == NULL)
    100          VG_(message)(Vg_UserMsg, "  no stack segment");
    101       else
    102          VG_(message)(Vg_UserMsg, "  too small or bad protection modes");
    103 
    104       /* set SIGSEGV to default handler */
    105       VG_(set_default_handler)(VKI_SIGSEGV);
    106       VG_(synth_fault_mapping)(tid, addr);
    107 
    108       /* The whole process should be about to die, since the default
    109          action of SIGSEGV to kill the whole process. */
    110       return False;
    111    }
    112 
    113    /* For tracking memory events, indicate the entire frame has been
    114       allocated. */
    115    VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
    116              size + VG_STACK_REDZONE_SZB, tid );
    117 
    118    return True;
    119 }
    120 
    121 static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si,
    122                             UWord trapno, UWord err, const vki_sigset_t *set,
    123                             struct vki_ucontext *uc)
    124 {
    125 
    126    ThreadState *tst = VG_(get_ThreadState)(tid);
    127    struct vki_sigcontext *sc = &uc->uc_mcontext;
    128 
    129    VG_(memset)(uc, 0, sizeof(*uc));
    130 
    131    uc->uc_flags = 0;
    132    uc->uc_link = 0;
    133    uc->uc_sigmask = *set;
    134    uc->uc_stack = tst->altstack;
    135 
    136 #  define SC2(reg)  sc->regs[reg] = tst->arch.vex.guest_X##reg
    137    SC2(0);   SC2(1);   SC2(2);   SC2(3);
    138    SC2(4);   SC2(5);   SC2(6);   SC2(7);
    139    SC2(8);   SC2(9);   SC2(10);  SC2(11);
    140    SC2(12);  SC2(13);  SC2(14);  SC2(15);
    141    SC2(16);  SC2(17);  SC2(18);  SC2(19);
    142    SC2(20);  SC2(21);  SC2(22);  SC2(23);
    143    SC2(24);  SC2(25);  SC2(26);  SC2(27);
    144    SC2(28);  SC2(29);  SC2(30);
    145 #  undef SC2
    146    sc->sp = tst->arch.vex.guest_XSP;
    147    sc->pc = tst->arch.vex.guest_PC;
    148    sc->pstate = 0; /* slack .. could do better */
    149 
    150    //sc->trap_no = trapno;
    151    //sc->error_code = err;
    152    sc->fault_address = (ULong)si->_sifields._sigfault._addr;
    153 }
    154 
    155 
    156 static void build_sigframe(ThreadState *tst,
    157                            struct sigframe *frame,
    158                            const vki_siginfo_t *siginfo,
    159                            const struct vki_ucontext *siguc,
    160                            void *handler, UInt flags,
    161                            const vki_sigset_t *mask,
    162                            void *restorer)
    163 {
    164    UWord trapno;
    165    UWord err;
    166    Int   sigNo = siginfo->si_signo;
    167    struct vg_sig_private *priv = &frame->vp;
    168 
    169    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
    170              (Addr)frame, offsetof(struct sigframe, vp));
    171 
    172    if (siguc) {
    173       trapno = 0; //siguc->uc_mcontext.trap_no;
    174       err = 0; //siguc->uc_mcontext.error_code;
    175    } else {
    176       trapno = 0;
    177       err = 0;
    178    }
    179 
    180    synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc);
    181 
    182    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
    183              (Addr)frame, offsetof(struct sigframe, vp));
    184 
    185    priv->magicPI = 0x31415927;
    186    priv->sigNo_private = sigNo;
    187    priv->vex         = tst->arch.vex;
    188    priv->vex_shadow1 = tst->arch.vex_shadow1;
    189    priv->vex_shadow2 = tst->arch.vex_shadow2;
    190 }
    191 
    192 
    193 /* EXPORTED */
    194 void VG_(sigframe_create)( ThreadId tid,
    195                            Addr sp_top_of_frame,
    196                            const vki_siginfo_t *siginfo,
    197                            const struct vki_ucontext *siguc,
    198                            void *handler,
    199                            UInt flags,
    200                            const vki_sigset_t *mask,
    201                            void *restorer )
    202 {
    203    ThreadState *tst;
    204    Addr sp    = sp_top_of_frame;
    205    Int  sigNo = siginfo->si_signo;
    206    UInt size;
    207 
    208    tst = VG_(get_ThreadState)(tid);
    209 
    210    size = sizeof(struct rt_sigframe);
    211 
    212    sp -= size;
    213    sp = VG_ROUNDDN(sp, 16);
    214 
    215    if (!extend(tst, sp, size))
    216       return; // Give up.  No idea if this is correct
    217 
    218    struct rt_sigframe *rsf = (struct rt_sigframe *)sp;
    219 
    220    /* Track our writes to siginfo */
    221    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid,  /* VVVVV */
    222              "signal handler siginfo", (Addr)rsf,
    223              offsetof(struct rt_sigframe, sig));
    224 
    225    VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t));
    226 
    227    if (sigNo == VKI_SIGILL && siginfo->si_code > 0) {
    228       rsf->info._sifields._sigfault._addr
    229         = (Addr*)(tst)->arch.vex.guest_PC;
    230    }
    231    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */
    232          (Addr)rsf, offsetof(struct rt_sigframe, sig));
    233 
    234    build_sigframe(tst, &rsf->sig, siginfo, siguc,
    235                        handler, flags, mask, restorer);
    236    tst->arch.vex.guest_X1 = (Addr)&rsf->info;
    237    tst->arch.vex.guest_X2 = (Addr)&rsf->sig.uc;
    238 
    239    VG_(set_SP)(tid, sp);
    240    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR,
    241              sizeof(Addr));
    242    tst->arch.vex.guest_X0 = sigNo;
    243 
    244    if (flags & VKI_SA_RESTORER)
    245        tst->arch.vex.guest_X30 = (Addr)restorer;
    246    else
    247        tst->arch.vex.guest_X30
    248           = (Addr)&VG_(arm64_linux_SUBST_FOR_rt_sigreturn);
    249 
    250    tst->arch.vex.guest_PC = (Addr)handler;
    251 }
    252 
    253 
    254 /*------------------------------------------------------------*/
    255 /*--- Destroying signal frames                             ---*/
    256 /*------------------------------------------------------------*/
    257 
    258 /* EXPORTED */
    259 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
    260 {
    261    ThreadState *tst;
    262    struct vg_sig_private *priv;
    263    Addr sp;
    264    UInt frame_size;
    265 //ZZ    struct vki_sigcontext *mc;
    266    Int sigNo;
    267    Bool has_siginfo = isRT;
    268 
    269    vg_assert(VG_(is_valid_tid)(tid));
    270    tst = VG_(get_ThreadState)(tid);
    271    sp = tst->arch.vex.guest_XSP;
    272 
    273 //ZZ    if (has_siginfo) {
    274       struct rt_sigframe *frame = (struct rt_sigframe *)sp;
    275       frame_size = sizeof(*frame);
    276       //mc = &frame->sig.uc.uc_mcontext;
    277       priv = &frame->sig.vp;
    278       vg_assert(priv->magicPI == 0x31415927);
    279       tst->sig_mask = frame->sig.uc.uc_sigmask;
    280 //ZZ    } else {
    281 //ZZ       struct sigframe *frame = (struct sigframe *)sp;
    282 //ZZ       frame_size = sizeof(*frame);
    283 //ZZ       mc = &frame->uc.uc_mcontext;
    284 //ZZ       priv = &frame->vp;
    285 //ZZ       vg_assert(priv->magicPI == 0x31415927);
    286 //ZZ       tst->sig_mask = frame->uc.uc_sigmask;
    287 //ZZ       //VG_(printf)("Setting signmask to %08x%08x\n",
    288 //ZZ       //            tst->sig_mask[0],tst->sig_mask[1]);
    289 //ZZ    }
    290    tst->tmp_sig_mask = tst->sig_mask;
    291 
    292    sigNo = priv->sigNo_private;
    293 
    294 //ZZ     //XXX: restore regs
    295 //ZZ #  define REST(reg,REG)  tst->arch.vex.guest_##REG = mc->arm_##reg;
    296 //ZZ    REST(r0,R0);
    297 //ZZ    REST(r1,R1);
    298 //ZZ    REST(r2,R2);
    299 //ZZ    REST(r3,R3);
    300 //ZZ    REST(r4,R4);
    301 //ZZ    REST(r5,R5);
    302 //ZZ    REST(r6,R6);
    303 //ZZ    REST(r7,R7);
    304 //ZZ    REST(r8,R8);
    305 //ZZ    REST(r9,R9);
    306 //ZZ    REST(r10,R10);
    307 //ZZ    REST(fp,R11);
    308 //ZZ    REST(ip,R12);
    309 //ZZ    REST(sp,R13);
    310 //ZZ    REST(lr,R14);
    311 //ZZ    REST(pc,R15T);
    312 //ZZ #  undef REST
    313 
    314    /* Uh, the next line makes all the REST() above pointless. */
    315    tst->arch.vex         = priv->vex;
    316 
    317    tst->arch.vex_shadow1 = priv->vex_shadow1;
    318    tst->arch.vex_shadow2 = priv->vex_shadow2;
    319 
    320    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
    321              frame_size + VG_STACK_REDZONE_SZB );
    322 
    323    if (VG_(clo_trace_signals))
    324       VG_(message)(Vg_DebugMsg,
    325                    "vg_pop_signal_frame (thread %d): "
    326                    "isRT=%d valid magic; PC=%#llx\n",
    327                    tid, has_siginfo, tst->arch.vex.guest_PC);
    328 
    329    /* tell the tools */
    330    VG_TRACK( post_deliver_signal, tid, sigNo );
    331 }
    332 
    333 #endif // defined(VGP_arm_linux)
    334 
    335 /*--------------------------------------------------------------------*/
    336 /*--- end                                   sigframe-arm64-linux.c ---*/
    337 /*--------------------------------------------------------------------*/
    338