| |
| /*--------------------------------------------------------------------*/ |
| /*--- Create/destroy signal delivery frames. ---*/ |
| /*--- sigframe-tilegx-linux.c ---*/ |
| /*--------------------------------------------------------------------*/ |
| |
| /* |
| This file is part of Valgrind, a dynamic binary instrumentation |
| framework. |
| |
| Copyright (C) 2010-2015 Tilera Corp. |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License as |
| published by the Free Software Foundation; either version 2 of the |
| License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307, USA. |
| |
| The GNU General Public License is contained in the file COPYING. |
| */ |
| |
| /* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */ |
| |
| #if defined(VGP_tilegx_linux) |
| |
| #include "pub_core_basics.h" |
| #include "pub_core_vki.h" |
| #include "pub_core_vkiscnums.h" |
| #include "pub_core_threadstate.h" |
| #include "pub_core_aspacemgr.h" |
| #include "pub_core_libcbase.h" |
| #include "pub_core_libcassert.h" |
| #include "pub_core_libcprint.h" |
| #include "pub_core_machine.h" |
| #include "pub_core_options.h" |
| #include "pub_core_sigframe.h" |
| #include "pub_core_signals.h" |
| #include "pub_core_tooliface.h" |
| #include "pub_core_trampoline.h" |
| #include "priv_sigframe.h" |
| |
| struct vg_sig_private |
| { |
| UInt magicPI; |
| UInt sigNo_private; |
| VexGuestTILEGXState vex_shadow1; |
| VexGuestTILEGXState vex_shadow2; |
| }; |
| |
| #ifndef C_ABI_SAVE_AREA_SIZE |
| #define C_ABI_SAVE_AREA_SIZE 16 |
| #endif |
| struct rt_sigframe { |
| unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */ |
| vki_siginfo_t rs_info; |
| struct vki_ucontext rs_uc; |
| struct vg_sig_private priv; |
| }; |
| |
| |
| static |
| void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1, |
| const vki_siginfo_t *si ) |
| { |
| |
| struct vki_sigcontext *sc = *sc1; |
| |
| VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", |
| (Addr)sc, sizeof(unsigned long long)*34 ); |
| sc->gregs[0] = tst->arch.vex.guest_r0; |
| sc->gregs[1] = tst->arch.vex.guest_r1; |
| sc->gregs[2] = tst->arch.vex.guest_r2; |
| sc->gregs[3] = tst->arch.vex.guest_r3; |
| sc->gregs[4] = tst->arch.vex.guest_r4; |
| sc->gregs[5] = tst->arch.vex.guest_r5; |
| sc->gregs[6] = tst->arch.vex.guest_r6; |
| sc->gregs[7] = tst->arch.vex.guest_r7; |
| sc->gregs[8] = tst->arch.vex.guest_r8; |
| sc->gregs[9] = tst->arch.vex.guest_r9; |
| sc->gregs[10] = tst->arch.vex.guest_r10; |
| sc->gregs[11] = tst->arch.vex.guest_r11; |
| sc->gregs[12] = tst->arch.vex.guest_r12; |
| sc->gregs[13] = tst->arch.vex.guest_r13; |
| sc->gregs[14] = tst->arch.vex.guest_r14; |
| sc->gregs[15] = tst->arch.vex.guest_r15; |
| sc->gregs[16] = tst->arch.vex.guest_r16; |
| sc->gregs[17] = tst->arch.vex.guest_r17; |
| sc->gregs[18] = tst->arch.vex.guest_r18; |
| sc->gregs[19] = tst->arch.vex.guest_r19; |
| sc->gregs[20] = tst->arch.vex.guest_r20; |
| sc->gregs[21] = tst->arch.vex.guest_r21; |
| sc->gregs[22] = tst->arch.vex.guest_r22; |
| sc->gregs[23] = tst->arch.vex.guest_r23; |
| sc->gregs[24] = tst->arch.vex.guest_r24; |
| sc->gregs[25] = tst->arch.vex.guest_r25; |
| sc->gregs[26] = tst->arch.vex.guest_r26; |
| sc->gregs[27] = tst->arch.vex.guest_r27; |
| sc->gregs[28] = tst->arch.vex.guest_r28; |
| sc->gregs[29] = tst->arch.vex.guest_r29; |
| sc->gregs[30] = tst->arch.vex.guest_r30; |
| sc->gregs[31] = tst->arch.vex.guest_r31; |
| sc->gregs[32] = tst->arch.vex.guest_r32; |
| sc->gregs[33] = tst->arch.vex.guest_r33; |
| sc->gregs[34] = tst->arch.vex.guest_r34; |
| sc->gregs[35] = tst->arch.vex.guest_r35; |
| sc->gregs[36] = tst->arch.vex.guest_r36; |
| sc->gregs[37] = tst->arch.vex.guest_r37; |
| sc->gregs[38] = tst->arch.vex.guest_r38; |
| sc->gregs[39] = tst->arch.vex.guest_r39; |
| sc->gregs[40] = tst->arch.vex.guest_r40; |
| sc->gregs[41] = tst->arch.vex.guest_r41; |
| sc->gregs[42] = tst->arch.vex.guest_r42; |
| sc->gregs[43] = tst->arch.vex.guest_r43; |
| sc->gregs[44] = tst->arch.vex.guest_r44; |
| sc->gregs[45] = tst->arch.vex.guest_r45; |
| sc->gregs[46] = tst->arch.vex.guest_r46; |
| sc->gregs[47] = tst->arch.vex.guest_r47; |
| sc->gregs[48] = tst->arch.vex.guest_r48; |
| sc->gregs[49] = tst->arch.vex.guest_r49; |
| sc->gregs[50] = tst->arch.vex.guest_r50; |
| sc->gregs[51] = tst->arch.vex.guest_r51; |
| sc->gregs[52] = tst->arch.vex.guest_r52; |
| sc->tp = tst->arch.vex.guest_r53; |
| sc->sp = tst->arch.vex.guest_r54; |
| sc->lr = tst->arch.vex.guest_r55; |
| sc->pc = tst->arch.vex.guest_pc; |
| } |
| |
| /* EXPORTED */ |
| void VG_(sigframe_create)( ThreadId tid, |
| Bool on_altstack, |
| Addr sp_top_of_frame, |
| const vki_siginfo_t *siginfo, |
| const struct vki_ucontext *siguc, |
| void *handler, |
| UInt flags, |
| const vki_sigset_t *mask, |
| void *restorer ) |
| { |
| Addr sp; |
| ThreadState* tst; |
| Addr faultaddr; |
| Int sigNo = siginfo->si_signo; |
| struct vg_sig_private *priv; |
| |
| /* Stack must be 8-byte aligned */ |
| sp_top_of_frame &= ~0x7ULL; |
| |
| sp = sp_top_of_frame - sizeof(struct rt_sigframe); |
| |
| tst = VG_(get_ThreadState)(tid); |
| if (! ML_(sf_maybe_extend_stack)(tst, sp, sizeof(struct rt_sigframe), flags)) |
| return; |
| |
| vg_assert(VG_IS_8_ALIGNED(sp)); |
| |
| /* SIGILL defines addr to be the faulting address */ |
| |
| faultaddr = (Addr)siginfo->_sifields._sigfault._addr; |
| if (sigNo == VKI_SIGILL && siginfo->si_code > 0) |
| faultaddr = tst->arch.vex.guest_pc; |
| |
| |
| struct rt_sigframe *frame = (struct rt_sigframe *) sp; |
| struct vki_ucontext *ucp = &frame->rs_uc; |
| if (VG_(clo_trace_signals)) |
| VG_(printf)("rt_sigframe\n"); |
| /* Create siginfo. */ |
| VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo", |
| (Addr)&frame->rs_info, sizeof(frame->rs_info) ); |
| |
| VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo)); |
| |
| VG_TRACK( post_mem_write, Vg_CoreSignal, tid, |
| (Addr)&frame->rs_info, sizeof(frame->rs_info) ); |
| |
| /* Create the ucontext. */ |
| VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", |
| (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext) ); |
| |
| ucp->uc_flags = 0; |
| ucp->uc_link = 0; |
| ucp->uc_stack = tst->altstack; |
| |
| VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp, |
| offsetof(struct vki_ucontext, uc_mcontext) ); |
| |
| struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext); |
| setup_sigcontext2(tst, &(scp), siginfo); |
| |
| ucp->uc_sigmask = tst->sig_mask; |
| |
| priv = &frame->priv; |
| |
| /* |
| * Arguments to signal handler: |
| * |
| * r0 = signal number |
| * r1 = 0 (should be cause) |
| * r2 = pointer to ucontext |
| * |
| * r54 points to the struct rt_sigframe. |
| */ |
| |
| tst->arch.vex.guest_r0 = siginfo->si_signo; |
| tst->arch.vex.guest_r1 = (Addr) &frame->rs_info; |
| tst->arch.vex.guest_r2 = (Addr) &frame->rs_uc; |
| tst->arch.vex.guest_r54 = (Addr) frame; |
| |
| if (flags & VKI_SA_RESTORER) |
| { |
| tst->arch.vex.guest_r55 = (Addr) restorer; |
| } |
| else |
| { |
| tst->arch.vex.guest_r55 = (Addr)&VG_(tilegx_linux_SUBST_FOR_rt_sigreturn); |
| } |
| |
| priv->magicPI = 0x31415927; |
| priv->sigNo_private = sigNo; |
| priv->vex_shadow1 = tst->arch.vex_shadow1; |
| priv->vex_shadow2 = tst->arch.vex_shadow2; |
| /* Set the thread so it will next run the handler. */ |
| /* tst->m_sp = sp; also notify the tool we've updated SP */ |
| VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); |
| if (VG_(clo_trace_signals)) |
| VG_(printf)("handler = %p\n", handler); |
| tst->arch.vex.guest_pc = (Addr) handler; |
| /* This thread needs to be marked runnable, but we leave that the |
| caller to do. */ |
| } |
| |
| /* EXPORTED */ |
| void VG_(sigframe_destroy)( ThreadId tid, Bool isRT ) |
| { |
| ThreadState *tst; |
| struct vg_sig_private *priv1; |
| Addr sp; |
| UInt frame_size; |
| struct vki_sigcontext *mc; |
| Int sigNo; |
| Bool has_siginfo = isRT; |
| |
| vg_assert(VG_(is_valid_tid)(tid)); |
| tst = VG_(get_ThreadState)(tid); |
| sp = tst->arch.vex.guest_r54 + 8; |
| if (has_siginfo) |
| { |
| struct rt_sigframe *frame = (struct rt_sigframe *)sp; |
| struct vki_ucontext *ucp = &frame->rs_uc; |
| |
| if (0) |
| VG_(printf)("destroy signal frame; sp = %lx, " |
| " %pc = %lx, status=%d\n", |
| (Addr)frame, tst->arch.vex.guest_pc, (Int)tst->status); |
| |
| frame_size = sizeof(*frame); |
| mc = &ucp->uc_mcontext; |
| priv1 = &frame->priv; |
| vg_assert(priv1->magicPI == 0x31415927); |
| sigNo = priv1->sigNo_private; |
| } |
| else |
| { |
| vg_assert(0); |
| } |
| |
| //restore regs |
| tst->arch.vex.guest_r0 = mc->gregs[0]; |
| tst->arch.vex.guest_r1 = mc->gregs[1]; |
| tst->arch.vex.guest_r2 = mc->gregs[2]; |
| tst->arch.vex.guest_r3 = mc->gregs[3]; |
| tst->arch.vex.guest_r4 = mc->gregs[4]; |
| tst->arch.vex.guest_r5 = mc->gregs[5]; |
| tst->arch.vex.guest_r6 = mc->gregs[6]; |
| tst->arch.vex.guest_r7 = mc->gregs[7]; |
| tst->arch.vex.guest_r8 = mc->gregs[8]; |
| tst->arch.vex.guest_r9 = mc->gregs[9]; |
| tst->arch.vex.guest_r10 = mc->gregs[10]; |
| tst->arch.vex.guest_r11 = mc->gregs[11]; |
| tst->arch.vex.guest_r12 = mc->gregs[12]; |
| tst->arch.vex.guest_r13 = mc->gregs[13]; |
| tst->arch.vex.guest_r14 = mc->gregs[14]; |
| tst->arch.vex.guest_r15 = mc->gregs[15]; |
| tst->arch.vex.guest_r16 = mc->gregs[16]; |
| tst->arch.vex.guest_r17 = mc->gregs[17]; |
| tst->arch.vex.guest_r18 = mc->gregs[18]; |
| tst->arch.vex.guest_r19 = mc->gregs[19]; |
| tst->arch.vex.guest_r20 = mc->gregs[20]; |
| tst->arch.vex.guest_r21 = mc->gregs[21]; |
| tst->arch.vex.guest_r22 = mc->gregs[22]; |
| tst->arch.vex.guest_r23 = mc->gregs[23]; |
| tst->arch.vex.guest_r24 = mc->gregs[24]; |
| tst->arch.vex.guest_r25 = mc->gregs[25]; |
| tst->arch.vex.guest_r26 = mc->gregs[26]; |
| tst->arch.vex.guest_r27 = mc->gregs[27]; |
| tst->arch.vex.guest_r28 = mc->gregs[28]; |
| tst->arch.vex.guest_r29 = mc->gregs[29]; |
| tst->arch.vex.guest_r30 = mc->gregs[30]; |
| tst->arch.vex.guest_r31 = mc->gregs[31]; |
| tst->arch.vex.guest_r32 = mc->gregs[32]; |
| tst->arch.vex.guest_r33 = mc->gregs[33]; |
| tst->arch.vex.guest_r34 = mc->gregs[34]; |
| tst->arch.vex.guest_r35 = mc->gregs[35]; |
| tst->arch.vex.guest_r36 = mc->gregs[36]; |
| tst->arch.vex.guest_r37 = mc->gregs[37]; |
| tst->arch.vex.guest_r38 = mc->gregs[38]; |
| tst->arch.vex.guest_r39 = mc->gregs[39]; |
| tst->arch.vex.guest_r40 = mc->gregs[40]; |
| tst->arch.vex.guest_r41 = mc->gregs[41]; |
| tst->arch.vex.guest_r42 = mc->gregs[42]; |
| tst->arch.vex.guest_r43 = mc->gregs[43]; |
| tst->arch.vex.guest_r44 = mc->gregs[44]; |
| tst->arch.vex.guest_r45 = mc->gregs[45]; |
| tst->arch.vex.guest_r46 = mc->gregs[46]; |
| tst->arch.vex.guest_r47 = mc->gregs[47]; |
| tst->arch.vex.guest_r48 = mc->gregs[48]; |
| tst->arch.vex.guest_r49 = mc->gregs[49]; |
| tst->arch.vex.guest_r50 = mc->gregs[50]; |
| tst->arch.vex.guest_r51 = mc->gregs[51]; |
| tst->arch.vex.guest_r52 = mc->gregs[52]; |
| tst->arch.vex.guest_r53 = mc->tp; |
| tst->arch.vex.guest_r54 = mc->sp; |
| tst->arch.vex.guest_r55 = mc->lr; |
| tst->arch.vex.guest_pc = mc->pc; |
| |
| VG_TRACK(die_mem_stack_signal, sp, frame_size); |
| if (VG_(clo_trace_signals)) |
| VG_(message)( Vg_DebugMsg, |
| "VG_(signal_return) (thread %u): isRT=%d valid magic; EIP=%#x\n", |
| tid, isRT, tst->arch.vex.guest_pc); |
| /* tell the tools */ |
| VG_TRACK( post_deliver_signal, tid, sigNo ); |
| } |
| |
| #endif // defined(VGP_tilegx_linux) |
| |
| /*--------------------------------------------------------------------*/ |
| /*--- end sigframe-tilegx-linux.c ---*/ |
| /*--------------------------------------------------------------------*/ |