Home | History | Annotate | Download | only in m_sigframe
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Create/destroy signal delivery frames.                       ---*/
      4 /*---                                      sigframe-amd64-darwin.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2006-2015 OpenWorks Ltd
     12       info (at) open-works.co.uk
     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_amd64_darwin)
     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_signals.h"
     45 #include "pub_core_tooliface.h"
     46 #include "pub_core_trampoline.h"
     47 #include "pub_core_sigframe.h"      /* self */
     48 #include "priv_sigframe.h"
     49 
     50 
     51 /* Originally copied from ppc32-aix5 code.
     52    Produce a frame with layout entirely of our own choosing.
     53 
     54    This module creates and removes signal frames for signal deliveries
     55    on amd64-darwin.  The machine state is saved in a ucontext and retrieved
     56    from it later, so the handler can modify it and return.
     57 
     58    Frame should have a 16-aligned size, just in case that turns out to
     59    be important for Darwin.  (be conservative)
     60 */
     61 struct hacky_sigframe {
     62    /* first word looks like a call to a 3-arg amd64-ELF function */
     63    ULong               returnAddr;
     64    UChar               lower_guardzone[512];  // put nothing here
     65    VexGuestAMD64State  vex;
     66    VexGuestAMD64State  vex_shadow1;
     67    VexGuestAMD64State  vex_shadow2;
     68    vki_siginfo_t       fake_siginfo;
     69    struct vki_ucontext fake_ucontext;
     70    UInt                magicPI;
     71    UInt                sigNo_private;
     72    vki_sigset_t        mask; // saved sigmask; restore when hdlr returns
     73    UChar               upper_guardzone[512]; // put nothing here
     74    // and don't zero it, since that might overwrite the client's
     75    // stack redzone, at least on archs which have one
     76 };
     77 
     78 /* Create a plausible-looking sigcontext from the thread's
     79    Vex guest state.  NOTE: does not fill in the FP or SSE
     80    bits of sigcontext at the moment.
     81  */
     82 static void synthesize_ucontext(ThreadState *tst,
     83 				struct vki_ucontext *uc,
     84 				const struct vki_ucontext *siguc)
     85 {
     86    VG_(memset)(uc, 0, sizeof(*uc));
     87 
     88    if (siguc) uc->uc_sigmask = siguc->uc_sigmask;
     89    uc->uc_stack = tst->altstack;
     90    uc->uc_mcontext = &uc->__mcontext_data;
     91 
     92 #  define SC2(reg,REG)  uc->__mcontext_data.__ss.reg = tst->arch.vex.guest_##REG
     93    SC2(__r8,R8);
     94    SC2(__r9,R9);
     95    SC2(__r10,R10);
     96    SC2(__r11,R11);
     97    SC2(__r12,R12);
     98    SC2(__r13,R13);
     99    SC2(__r14,R14);
    100    SC2(__r15,R15);
    101    SC2(__rdi,RDI);
    102    SC2(__rsi,RSI);
    103    SC2(__rbp,RBP);
    104    SC2(__rbx,RBX);
    105    SC2(__rdx,RDX);
    106    SC2(__rax,RAX);
    107    SC2(__rcx,RCX);
    108    SC2(__rsp,RSP);
    109    SC2(__rip,RIP);
    110    uc->__mcontext_data.__ss.__rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
    111 
    112    if (siguc)
    113       uc->__mcontext_data.__es = siguc->__mcontext_data.__es;
    114 #  undef SC2
    115 }
    116 
    117 static void restore_from_ucontext(ThreadState *tst,
    118 				  const struct vki_ucontext *uc)
    119 {
    120 #  define SC2(REG,reg)  tst->arch.vex.guest_##REG = uc->__mcontext_data.__ss.reg
    121    SC2(R8,__r8);
    122    SC2(R9,__r9);
    123    SC2(R10,__r10);
    124    SC2(R11,__r11);
    125    SC2(R12,__r12);
    126    SC2(R13,__r13);
    127    SC2(R14,__r14);
    128    SC2(R15,__r15);
    129    SC2(RDI,__rdi);
    130    SC2(RSI,__rsi);
    131    SC2(RBP,__rbp);
    132    SC2(RBX,__rbx);
    133    SC2(RDX,__rdx);
    134    SC2(RAX,__rax);
    135    SC2(RCX,__rcx);
    136    SC2(RSP,__rsp);
    137    SC2(RIP,__rip);
    138    /* There doesn't seem to be an easy way to restore rflags */
    139 #  undef SC2
    140 }
    141 
    142 /* Create a signal frame for thread 'tid'.  Make a 3-arg frame
    143    regardless of whether the client originally requested a 1-arg
    144    version (no SA_SIGINFO) or a 3-arg one (SA_SIGINFO) since in the
    145    former case, the amd64 calling conventions will simply cause the
    146    extra 2 args to be ignored (inside the handler).  (We hope!) */
    147 void VG_(sigframe_create) ( ThreadId tid,
    148                             Bool on_altstack,
    149                             Addr sp_top_of_frame,
    150                             const vki_siginfo_t *siginfo,
    151                             const struct vki_ucontext *siguc,
    152                             void *handler,
    153                             UInt flags,
    154                             const vki_sigset_t *mask,
    155                             void *restorer )
    156 {
    157    ThreadState* tst;
    158    Addr rsp;
    159    struct hacky_sigframe* frame;
    160    Int sigNo = siginfo->si_signo;
    161 
    162    vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe)));
    163 
    164    sp_top_of_frame &= ~0xfUL;
    165    rsp = sp_top_of_frame - sizeof(struct hacky_sigframe);
    166    rsp -= 8; /* ELF ABI says that rsp+8 must be 16 aligned on
    167                 entry to a function. */
    168 
    169    tst = VG_(get_ThreadState)(tid);
    170    if (! ML_(sf_maybe_extend_stack)(tst, rsp, sp_top_of_frame - rsp, flags))
    171       return;
    172 
    173    vg_assert(VG_IS_16_ALIGNED(rsp+8));
    174 
    175    frame = (struct hacky_sigframe *) rsp;
    176 
    177    /* clear it (very conservatively) */
    178    VG_(memset)(&frame->lower_guardzone, 0, sizeof frame->lower_guardzone);
    179    VG_(memset)(&frame->vex,      0, sizeof(VexGuestAMD64State));
    180    VG_(memset)(&frame->vex_shadow1, 0, sizeof(VexGuestAMD64State));
    181    VG_(memset)(&frame->vex_shadow2, 0, sizeof(VexGuestAMD64State));
    182    VG_(memset)(&frame->fake_siginfo,  0, sizeof(frame->fake_siginfo));
    183    VG_(memset)(&frame->fake_ucontext, 0, sizeof(frame->fake_ucontext));
    184 
    185    /* save stuff in frame */
    186    frame->vex           = tst->arch.vex;
    187    frame->vex_shadow1   = tst->arch.vex_shadow1;
    188    frame->vex_shadow2   = tst->arch.vex_shadow2;
    189    frame->sigNo_private = sigNo;
    190    frame->mask          = tst->sig_mask;
    191    frame->magicPI       = 0x31415927;
    192 
    193    /* Fill in the siginfo and ucontext.  */
    194    synthesize_ucontext(tst, &frame->fake_ucontext, siguc);
    195    frame->fake_siginfo = *siginfo;
    196 
    197    /* Set up stack pointer */
    198    vg_assert(rsp == (Addr)&frame->returnAddr);
    199    VG_(set_SP)(tid, rsp);
    200    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(ULong));
    201 
    202    /* Set up program counter */
    203    VG_(set_IP)(tid, (ULong)handler);
    204    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_INSTR_PTR, sizeof(ULong));
    205 
    206    /* Set up RA and args for the frame */
    207    VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
    208              (Addr)frame, 1*sizeof(ULong) );
    209    frame->returnAddr  = (ULong)&VG_(amd64_darwin_SUBST_FOR_sigreturn);
    210 
    211    /* XXX should tell the tool that these regs got written */
    212    tst->arch.vex.guest_RDI = (ULong) sigNo;
    213    tst->arch.vex.guest_RSI = (Addr)  &frame->fake_siginfo;
    214    tst->arch.vex.guest_RDX = (Addr)  &frame->fake_ucontext;
    215 
    216    VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
    217              (Addr)frame, 1*sizeof(ULong) );
    218    VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
    219              (Addr)&frame->fake_siginfo, sizeof(frame->fake_siginfo));
    220    VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
    221              (Addr)&frame->fake_ucontext, sizeof(frame->fake_ucontext));
    222 
    223    if (VG_(clo_trace_signals))
    224       VG_(message)(Vg_DebugMsg,
    225                    "sigframe_create (thread %u): "
    226                    "next RIP=%#lx, next RSP=%#lx\n",
    227                    tid, (Addr)handler, (Addr)frame );
    228 }
    229 
    230 
    231 /* Remove a signal frame from thread 'tid's stack, and restore the CPU
    232    state from it.  Note, isRT is irrelevant here. */
    233 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
    234 {
    235    ThreadState *tst;
    236    Addr rsp;
    237    Int sigNo;
    238    struct hacky_sigframe* frame;
    239 
    240    vg_assert(VG_(is_valid_tid)(tid));
    241    tst = VG_(get_ThreadState)(tid);
    242 
    243    /* Check that the stack frame looks valid */
    244    rsp = VG_(get_SP)(tid);
    245 
    246    /* why -8 ? because the signal handler's return will have popped
    247       the return address off the stack; and the return address is the
    248       lowest-addressed element of hacky_sigframe. */
    249    frame = (struct hacky_sigframe*)(rsp - 8);
    250    vg_assert(frame->magicPI == 0x31415927);
    251 
    252    /* This +8 is because of the -8 referred to in the ELF ABI comment
    253       in VG_(sigframe_create) just above. */
    254    vg_assert(VG_IS_16_ALIGNED((Addr)frame + 8));
    255 
    256    /* restore the entire guest state, and shadows, from the frame. */
    257    tst->arch.vex            = frame->vex;
    258    tst->arch.vex_shadow1    = frame->vex_shadow1;
    259    tst->arch.vex_shadow2    = frame->vex_shadow2;
    260    restore_from_ucontext(tst, &frame->fake_ucontext);
    261 
    262    tst->sig_mask            = frame->mask;
    263    tst->tmp_sig_mask        = frame->mask;
    264    sigNo                    = frame->sigNo_private;
    265 
    266    if (VG_(clo_trace_signals))
    267       VG_(message)(Vg_DebugMsg,
    268                    "sigframe_destroy (thread %d): "
    269                    "valid magic; next RIP=%#llx\n",
    270                    tid, tst->arch.vex.guest_RIP);
    271 
    272    VG_TRACK( die_mem_stack_signal,
    273              (Addr)frame - VG_STACK_REDZONE_SZB,
    274              sizeof(struct hacky_sigframe) );
    275 
    276    /* tell the tools */
    277    VG_TRACK( post_deliver_signal, tid, sigNo );
    278 }
    279 
    280 #endif // defined(VGP_amd64_darwin)
    281 
    282 /*--------------------------------------------------------------------*/
    283 /*--- end                                  sigframe-amd64-darwin.c ---*/
    284 /*--------------------------------------------------------------------*/
    285