blob: 3448ff8860c980fafa1b552deb626f9de9587c16 [file] [log] [blame]
/*--------------------------------------------------------------------*/
/*--- Create/destroy signal delivery frames. ---*/
/*--- sigframe-tilegx-linux.c ---*/
/*--------------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2010-2013 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,
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. */
if (0)
VG_(printf)("pushed signal frame; sp now = %lx, "
"next %pc = %lx, status=%d\n",
(Addr)frame, tst->arch.vex.guest_pc, tst->status);
}
/* 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)("destory signal frame; sp = %lx, "
" %pc = %lx, status=%d\n",
(Addr)frame, tst->arch.vex.guest_pc, 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 %d): 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 ---*/
/*--------------------------------------------------------------------*/