mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-10 13:40:25 +00:00
530 lines
18 KiB
C
530 lines
18 KiB
C
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- Create/destroy signal delivery frames. ---*/
|
|
/*--- sigframe-s390x-linux.c ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/*
|
|
This file is part of Valgrind, a dynamic binary instrumentation
|
|
framework.
|
|
|
|
Copyright IBM Corp. 2010-2015
|
|
|
|
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 Christian Borntraeger */
|
|
|
|
#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"
|
|
|
|
#if defined(VGA_s390x)
|
|
|
|
/* This module creates and removes signal frames for signal deliveries
|
|
on s390x-linux.
|
|
|
|
Note, this file contains kernel-specific knowledge in the form of
|
|
'struct sigframe' and 'struct rt_sigframe'.
|
|
|
|
Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
|
|
onto the client's stack. This contains a subsidiary
|
|
vki_ucontext. That holds the vcpu's state across the signal,
|
|
so that the sighandler can mess with the vcpu state if it
|
|
really wants.
|
|
*/
|
|
|
|
#define SET_SIGNAL_GPR(zztst, zzn, zzval) \
|
|
do { zztst->arch.vex.guest_r##zzn = (unsigned long)(zzval); \
|
|
VG_TRACK( post_reg_write, Vg_CoreSignal, zztst->tid, \
|
|
offsetof(VexGuestS390XState,guest_r##zzn), \
|
|
sizeof(UWord) ); \
|
|
} while (0)
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- Signal frame layouts ---*/
|
|
/*------------------------------------------------------------*/
|
|
|
|
// A structure in which to save the application's registers
|
|
// during the execution of signal handlers.
|
|
|
|
// Linux has 2 signal frame structures: one for normal signal
|
|
// deliveries, and one for SA_SIGINFO deliveries (also known as RT
|
|
// signals).
|
|
//
|
|
// In theory, so long as we get the arguments to the handler function
|
|
// right, it doesn't matter what the exact layout of the rest of the
|
|
// frame is. Unfortunately, things like gcc's exception unwinding
|
|
// make assumptions about the locations of various parts of the frame,
|
|
// so we need to duplicate it exactly.
|
|
|
|
/* Valgrind-specific parts of the signal frame */
|
|
struct vg_sigframe
|
|
{
|
|
/* Sanity check word. */
|
|
UInt magicPI;
|
|
|
|
UInt handlerflags; /* flags for signal handler */
|
|
|
|
|
|
/* Safely-saved version of sigNo, as described above. */
|
|
Int sigNo_private;
|
|
|
|
/* XXX This is wrong. Surely we should store the shadow values
|
|
into the shadow memory behind the actual values? */
|
|
VexGuestS390XState vex_shadow1;
|
|
VexGuestS390XState vex_shadow2;
|
|
|
|
/* HACK ALERT */
|
|
VexGuestS390XState vex;
|
|
/* end HACK ALERT */
|
|
|
|
/* saved signal mask to be restored when handler returns */
|
|
vki_sigset_t mask;
|
|
|
|
/* Sanity check word. Is the highest-addressed word; do not
|
|
move!*/
|
|
UInt magicE;
|
|
};
|
|
|
|
#define S390_SYSCALL_SIZE 2
|
|
|
|
struct sigframe
|
|
{
|
|
UChar callee_used_stack[__VKI_SIGNAL_FRAMESIZE];
|
|
struct vki_sigcontext sc;
|
|
_vki_sigregs sregs;
|
|
Int sigNo;
|
|
UChar retcode[S390_SYSCALL_SIZE];
|
|
|
|
struct vg_sigframe vg;
|
|
};
|
|
|
|
struct rt_sigframe
|
|
{
|
|
UChar callee_used_stack[__VKI_SIGNAL_FRAMESIZE];
|
|
UChar retcode[S390_SYSCALL_SIZE];
|
|
struct vki_siginfo info;
|
|
struct vki_ucontext uc;
|
|
|
|
struct vg_sigframe vg;
|
|
};
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- Creating signal frames ---*/
|
|
/*------------------------------------------------------------*/
|
|
|
|
/* Saves all user-controlled register into a _vki_sigregs structure */
|
|
static void save_sigregs(ThreadState *tst, _vki_sigregs *sigregs)
|
|
{
|
|
sigregs->regs.gprs[0] = tst->arch.vex.guest_r0;
|
|
sigregs->regs.gprs[1] = tst->arch.vex.guest_r1;
|
|
sigregs->regs.gprs[2] = tst->arch.vex.guest_r2;
|
|
sigregs->regs.gprs[3] = tst->arch.vex.guest_r3;
|
|
sigregs->regs.gprs[4] = tst->arch.vex.guest_r4;
|
|
sigregs->regs.gprs[5] = tst->arch.vex.guest_r5;
|
|
sigregs->regs.gprs[6] = tst->arch.vex.guest_r6;
|
|
sigregs->regs.gprs[7] = tst->arch.vex.guest_r7;
|
|
sigregs->regs.gprs[8] = tst->arch.vex.guest_r8;
|
|
sigregs->regs.gprs[9] = tst->arch.vex.guest_r9;
|
|
sigregs->regs.gprs[10] = tst->arch.vex.guest_r10;
|
|
sigregs->regs.gprs[11] = tst->arch.vex.guest_r11;
|
|
sigregs->regs.gprs[12] = tst->arch.vex.guest_r12;
|
|
sigregs->regs.gprs[13] = tst->arch.vex.guest_r13;
|
|
sigregs->regs.gprs[14] = tst->arch.vex.guest_r14;
|
|
sigregs->regs.gprs[15] = tst->arch.vex.guest_r15;
|
|
|
|
sigregs->regs.acrs[0] = tst->arch.vex.guest_a0;
|
|
sigregs->regs.acrs[1] = tst->arch.vex.guest_a1;
|
|
sigregs->regs.acrs[2] = tst->arch.vex.guest_a2;
|
|
sigregs->regs.acrs[3] = tst->arch.vex.guest_a3;
|
|
sigregs->regs.acrs[4] = tst->arch.vex.guest_a4;
|
|
sigregs->regs.acrs[5] = tst->arch.vex.guest_a5;
|
|
sigregs->regs.acrs[6] = tst->arch.vex.guest_a6;
|
|
sigregs->regs.acrs[7] = tst->arch.vex.guest_a7;
|
|
sigregs->regs.acrs[8] = tst->arch.vex.guest_a8;
|
|
sigregs->regs.acrs[9] = tst->arch.vex.guest_a9;
|
|
sigregs->regs.acrs[10] = tst->arch.vex.guest_a10;
|
|
sigregs->regs.acrs[11] = tst->arch.vex.guest_a11;
|
|
sigregs->regs.acrs[12] = tst->arch.vex.guest_a12;
|
|
sigregs->regs.acrs[13] = tst->arch.vex.guest_a13;
|
|
sigregs->regs.acrs[14] = tst->arch.vex.guest_a14;
|
|
sigregs->regs.acrs[15] = tst->arch.vex.guest_a15;
|
|
|
|
sigregs->fpregs.fprs[0] = tst->arch.vex.guest_f0;
|
|
sigregs->fpregs.fprs[1] = tst->arch.vex.guest_f1;
|
|
sigregs->fpregs.fprs[2] = tst->arch.vex.guest_f2;
|
|
sigregs->fpregs.fprs[3] = tst->arch.vex.guest_f3;
|
|
sigregs->fpregs.fprs[4] = tst->arch.vex.guest_f4;
|
|
sigregs->fpregs.fprs[5] = tst->arch.vex.guest_f5;
|
|
sigregs->fpregs.fprs[6] = tst->arch.vex.guest_f6;
|
|
sigregs->fpregs.fprs[7] = tst->arch.vex.guest_f7;
|
|
sigregs->fpregs.fprs[8] = tst->arch.vex.guest_f8;
|
|
sigregs->fpregs.fprs[9] = tst->arch.vex.guest_f9;
|
|
sigregs->fpregs.fprs[10] = tst->arch.vex.guest_f10;
|
|
sigregs->fpregs.fprs[11] = tst->arch.vex.guest_f11;
|
|
sigregs->fpregs.fprs[12] = tst->arch.vex.guest_f12;
|
|
sigregs->fpregs.fprs[13] = tst->arch.vex.guest_f13;
|
|
sigregs->fpregs.fprs[14] = tst->arch.vex.guest_f14;
|
|
sigregs->fpregs.fprs[15] = tst->arch.vex.guest_f15;
|
|
sigregs->fpregs.fpc = tst->arch.vex.guest_fpc;
|
|
|
|
sigregs->regs.psw.addr = tst->arch.vex.guest_IA;
|
|
/* save a sane dummy mask */
|
|
sigregs->regs.psw.mask = 0x0705000180000000UL;
|
|
}
|
|
|
|
static void restore_sigregs(ThreadState *tst, _vki_sigregs *sigregs)
|
|
{
|
|
tst->arch.vex.guest_r0 = sigregs->regs.gprs[0];
|
|
tst->arch.vex.guest_r1 = sigregs->regs.gprs[1];
|
|
tst->arch.vex.guest_r2 = sigregs->regs.gprs[2];
|
|
tst->arch.vex.guest_r3 = sigregs->regs.gprs[3];
|
|
tst->arch.vex.guest_r4 = sigregs->regs.gprs[4];
|
|
tst->arch.vex.guest_r5 = sigregs->regs.gprs[5];
|
|
tst->arch.vex.guest_r6 = sigregs->regs.gprs[6];
|
|
tst->arch.vex.guest_r7 = sigregs->regs.gprs[7];
|
|
tst->arch.vex.guest_r8 = sigregs->regs.gprs[8];
|
|
tst->arch.vex.guest_r9 = sigregs->regs.gprs[9];
|
|
tst->arch.vex.guest_r10 = sigregs->regs.gprs[10];
|
|
tst->arch.vex.guest_r11 = sigregs->regs.gprs[11];
|
|
tst->arch.vex.guest_r12 = sigregs->regs.gprs[12];
|
|
tst->arch.vex.guest_r13 = sigregs->regs.gprs[13];
|
|
tst->arch.vex.guest_r14 = sigregs->regs.gprs[14];
|
|
tst->arch.vex.guest_r15 = sigregs->regs.gprs[15];
|
|
|
|
tst->arch.vex.guest_a0 = sigregs->regs.acrs[0];
|
|
tst->arch.vex.guest_a1 = sigregs->regs.acrs[1];
|
|
tst->arch.vex.guest_a2 = sigregs->regs.acrs[2];
|
|
tst->arch.vex.guest_a3 = sigregs->regs.acrs[3];
|
|
tst->arch.vex.guest_a4 = sigregs->regs.acrs[4];
|
|
tst->arch.vex.guest_a5 = sigregs->regs.acrs[5];
|
|
tst->arch.vex.guest_a6 = sigregs->regs.acrs[6];
|
|
tst->arch.vex.guest_a7 = sigregs->regs.acrs[7];
|
|
tst->arch.vex.guest_a8 = sigregs->regs.acrs[8];
|
|
tst->arch.vex.guest_a9 = sigregs->regs.acrs[9];
|
|
tst->arch.vex.guest_a10 = sigregs->regs.acrs[10];
|
|
tst->arch.vex.guest_a11 = sigregs->regs.acrs[11];
|
|
tst->arch.vex.guest_a12 = sigregs->regs.acrs[12];
|
|
tst->arch.vex.guest_a13 = sigregs->regs.acrs[13];
|
|
tst->arch.vex.guest_a14 = sigregs->regs.acrs[14];
|
|
tst->arch.vex.guest_a15 = sigregs->regs.acrs[15];
|
|
|
|
tst->arch.vex.guest_f0 = sigregs->fpregs.fprs[0];
|
|
tst->arch.vex.guest_f1 = sigregs->fpregs.fprs[1];
|
|
tst->arch.vex.guest_f2 = sigregs->fpregs.fprs[2];
|
|
tst->arch.vex.guest_f3 = sigregs->fpregs.fprs[3];
|
|
tst->arch.vex.guest_f4 = sigregs->fpregs.fprs[4];
|
|
tst->arch.vex.guest_f5 = sigregs->fpregs.fprs[5];
|
|
tst->arch.vex.guest_f6 = sigregs->fpregs.fprs[6];
|
|
tst->arch.vex.guest_f7 = sigregs->fpregs.fprs[7];
|
|
tst->arch.vex.guest_f8 = sigregs->fpregs.fprs[8];
|
|
tst->arch.vex.guest_f9 = sigregs->fpregs.fprs[9];
|
|
tst->arch.vex.guest_f10 = sigregs->fpregs.fprs[10];
|
|
tst->arch.vex.guest_f11 = sigregs->fpregs.fprs[11];
|
|
tst->arch.vex.guest_f12 = sigregs->fpregs.fprs[12];
|
|
tst->arch.vex.guest_f13 = sigregs->fpregs.fprs[13];
|
|
tst->arch.vex.guest_f14 = sigregs->fpregs.fprs[14];
|
|
tst->arch.vex.guest_f15 = sigregs->fpregs.fprs[15];
|
|
tst->arch.vex.guest_fpc = sigregs->fpregs.fpc;
|
|
|
|
tst->arch.vex.guest_IA = sigregs->regs.psw.addr;
|
|
}
|
|
|
|
|
|
/* Build the Valgrind-specific part of a signal frame. */
|
|
|
|
static void build_vg_sigframe(struct vg_sigframe *frame,
|
|
ThreadState *tst,
|
|
UInt flags,
|
|
Int sigNo)
|
|
{
|
|
frame->sigNo_private = sigNo;
|
|
frame->magicPI = 0x31415927;
|
|
frame->vex_shadow1 = tst->arch.vex_shadow1;
|
|
frame->vex_shadow2 = tst->arch.vex_shadow2;
|
|
/* HACK ALERT */
|
|
frame->vex = tst->arch.vex;
|
|
/* end HACK ALERT */
|
|
frame->mask = tst->sig_mask;
|
|
frame->handlerflags = flags;
|
|
frame->magicE = 0x27182818;
|
|
}
|
|
|
|
|
|
static Addr build_sigframe(ThreadState *tst,
|
|
Addr sp_top_of_frame,
|
|
const vki_siginfo_t *siginfo,
|
|
const struct vki_ucontext *siguc,
|
|
UInt flags,
|
|
const vki_sigset_t *mask,
|
|
void *restorer)
|
|
{
|
|
struct sigframe *frame;
|
|
Addr sp = sp_top_of_frame;
|
|
|
|
vg_assert((flags & VKI_SA_SIGINFO) == 0);
|
|
vg_assert((sizeof(*frame) & 7) == 0);
|
|
vg_assert((sp & 7) == 0);
|
|
|
|
sp -= sizeof(*frame);
|
|
frame = (struct sigframe *)sp;
|
|
|
|
if (! ML_(sf_maybe_extend_stack)(tst, sp, sizeof(*frame), flags))
|
|
return sp_top_of_frame;
|
|
|
|
/* retcode, sigNo, sc, sregs fields are to be written */
|
|
VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
|
|
sp, offsetof(struct sigframe, vg) );
|
|
|
|
save_sigregs(tst, &frame->sregs);
|
|
|
|
frame->sigNo = siginfo->si_signo;
|
|
frame->sc.sregs = &frame->sregs;
|
|
VG_(memcpy)(frame->sc.oldmask, mask->sig, sizeof(frame->sc.oldmask));
|
|
|
|
if (flags & VKI_SA_RESTORER) {
|
|
SET_SIGNAL_GPR(tst, 14, restorer);
|
|
} else {
|
|
frame->retcode[0] = 0x0a;
|
|
frame->retcode[1] = __NR_sigreturn;
|
|
/* This normally should be &frame->recode. but since there
|
|
might be problems with non-exec stack and we must discard
|
|
the translation for the on-stack sigreturn we just use the
|
|
trampoline like x86,ppc. We still fill in the retcode, lets
|
|
just hope that nobody actually jumps here */
|
|
SET_SIGNAL_GPR(tst, 14, (Addr)&VG_(s390x_linux_SUBST_FOR_sigreturn));
|
|
}
|
|
|
|
SET_SIGNAL_GPR(tst, 2, siginfo->si_signo);
|
|
SET_SIGNAL_GPR(tst, 3, &frame->sc);
|
|
/* fixs390: we dont fill in trapno and prot_addr in r4 and r5*/
|
|
|
|
/* Set up backchain. */
|
|
*((Addr *) sp) = sp_top_of_frame;
|
|
|
|
VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
|
|
sp, offsetof(struct sigframe, vg) );
|
|
|
|
build_vg_sigframe(&frame->vg, tst, flags, siginfo->si_signo);
|
|
|
|
return sp;
|
|
}
|
|
|
|
static Addr build_rt_sigframe(ThreadState *tst,
|
|
Addr sp_top_of_frame,
|
|
const vki_siginfo_t *siginfo,
|
|
const struct vki_ucontext *siguc,
|
|
UInt flags,
|
|
const vki_sigset_t *mask,
|
|
void *restorer)
|
|
{
|
|
struct rt_sigframe *frame;
|
|
Addr sp = sp_top_of_frame;
|
|
Int sigNo = siginfo->si_signo;
|
|
|
|
vg_assert((flags & VKI_SA_SIGINFO) != 0);
|
|
vg_assert((sizeof(*frame) & 7) == 0);
|
|
vg_assert((sp & 7) == 0);
|
|
|
|
sp -= sizeof(*frame);
|
|
frame = (struct rt_sigframe *)sp;
|
|
|
|
if (! ML_(sf_maybe_extend_stack)(tst, sp, sizeof(*frame), flags))
|
|
return sp_top_of_frame;
|
|
|
|
/* retcode, sigNo, sc, sregs fields are to be written */
|
|
VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
|
|
sp, offsetof(struct rt_sigframe, vg) );
|
|
|
|
save_sigregs(tst, &frame->uc.uc_mcontext);
|
|
|
|
if (flags & VKI_SA_RESTORER) {
|
|
frame->retcode[0] = 0;
|
|
frame->retcode[1] = 0;
|
|
SET_SIGNAL_GPR(tst, 14, restorer);
|
|
} else {
|
|
frame->retcode[0] = 0x0a;
|
|
frame->retcode[1] = __NR_rt_sigreturn;
|
|
/* This normally should be &frame->recode. but since there
|
|
might be problems with non-exec stack and we must discard
|
|
the translation for the on-stack sigreturn we just use the
|
|
trampoline like x86,ppc. We still fill in the retcode, lets
|
|
just hope that nobody actually jumps here */
|
|
SET_SIGNAL_GPR(tst, 14, (Addr)&VG_(s390x_linux_SUBST_FOR_rt_sigreturn));
|
|
}
|
|
|
|
VG_(memcpy)(&frame->info, siginfo, sizeof(vki_siginfo_t));
|
|
frame->uc.uc_flags = 0;
|
|
frame->uc.uc_link = 0;
|
|
frame->uc.uc_sigmask = *mask;
|
|
frame->uc.uc_stack = tst->altstack;
|
|
|
|
SET_SIGNAL_GPR(tst, 2, siginfo->si_signo);
|
|
SET_SIGNAL_GPR(tst, 3, &frame->info);
|
|
SET_SIGNAL_GPR(tst, 4, &frame->uc);
|
|
|
|
/* Set up backchain. */
|
|
*((Addr *) sp) = sp_top_of_frame;
|
|
|
|
VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
|
|
sp, offsetof(struct rt_sigframe, vg) );
|
|
|
|
build_vg_sigframe(&frame->vg, tst, flags, sigNo);
|
|
return sp;
|
|
}
|
|
|
|
/* 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 = VG_(get_ThreadState)(tid);
|
|
|
|
if (flags & VKI_SA_SIGINFO)
|
|
sp = build_rt_sigframe(tst, sp_top_of_frame, siginfo, siguc,
|
|
flags, mask, restorer);
|
|
else
|
|
sp = build_sigframe(tst, sp_top_of_frame, siginfo, siguc,
|
|
flags, mask, restorer);
|
|
|
|
/* Set the thread so it will next run the handler. */
|
|
VG_(set_SP)(tid, sp);
|
|
VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
|
|
|
|
tst->arch.vex.guest_IA = (Addr) handler;
|
|
/* We might have interrupted a repeating instruction that uses the guest
|
|
counter. Since our VEX requires that a new instruction will see a
|
|
guest counter == 0, we have to set it here. The old value will be
|
|
restored by restore_vg_sigframe. */
|
|
tst->arch.vex.guest_counter = 0;
|
|
/* This thread needs to be marked runnable, but we leave that the
|
|
caller to do. */
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- Destroying signal frames ---*/
|
|
/*------------------------------------------------------------*/
|
|
|
|
/* Return False and don't do anything, just set the client to take a
|
|
segfault, if it looks like the frame is corrupted. */
|
|
static
|
|
Bool restore_vg_sigframe ( ThreadState *tst,
|
|
struct vg_sigframe *frame, Int *sigNo )
|
|
{
|
|
if (frame->magicPI != 0x31415927 ||
|
|
frame->magicE != 0x27182818) {
|
|
VG_(message)(Vg_UserMsg, "Thread %u return signal frame "
|
|
"corrupted. Killing process.\n",
|
|
tst->tid);
|
|
VG_(set_default_handler)(VKI_SIGSEGV);
|
|
VG_(synth_fault)(tst->tid);
|
|
*sigNo = VKI_SIGSEGV;
|
|
return False;
|
|
}
|
|
tst->sig_mask = frame->mask;
|
|
tst->tmp_sig_mask = frame->mask;
|
|
tst->arch.vex_shadow1 = frame->vex_shadow1;
|
|
tst->arch.vex_shadow2 = frame->vex_shadow2;
|
|
/* HACK ALERT */
|
|
tst->arch.vex = frame->vex;
|
|
/* end HACK ALERT */
|
|
*sigNo = frame->sigNo_private;
|
|
return True;
|
|
}
|
|
|
|
static
|
|
SizeT restore_sigframe ( ThreadState *tst,
|
|
struct sigframe *frame, Int *sigNo )
|
|
{
|
|
if (restore_vg_sigframe(tst, &frame->vg, sigNo))
|
|
restore_sigregs(tst, frame->sc.sregs);
|
|
|
|
return sizeof(*frame);
|
|
}
|
|
|
|
static
|
|
SizeT restore_rt_sigframe ( ThreadState *tst,
|
|
struct rt_sigframe *frame, Int *sigNo )
|
|
{
|
|
if (restore_vg_sigframe(tst, &frame->vg, sigNo)) {
|
|
restore_sigregs(tst, &frame->uc.uc_mcontext);
|
|
}
|
|
return sizeof(*frame);
|
|
}
|
|
|
|
|
|
/* EXPORTED */
|
|
void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
|
|
{
|
|
Addr sp;
|
|
ThreadState* tst;
|
|
SizeT size;
|
|
Int sigNo;
|
|
|
|
tst = VG_(get_ThreadState)(tid);
|
|
|
|
/* Correctly reestablish the frame base address. */
|
|
sp = tst->arch.vex.guest_SP;
|
|
|
|
if (!isRT)
|
|
size = restore_sigframe(tst, (struct sigframe *)sp, &sigNo);
|
|
else
|
|
size = restore_rt_sigframe(tst, (struct rt_sigframe *)sp, &sigNo);
|
|
|
|
/* same as for creation: we must announce the full memory (including
|
|
alignment), otherwise massif might fail on longjmp */
|
|
VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
|
|
size + VG_STACK_REDZONE_SZB );
|
|
|
|
if (VG_(clo_trace_signals))
|
|
VG_(message)(
|
|
Vg_DebugMsg,
|
|
"VG_(sigframe_destroy) (thread %u): isRT=%d valid magic; IP=%#llx\n",
|
|
tid, isRT, tst->arch.vex.guest_IA);
|
|
|
|
/* tell the tools */
|
|
VG_TRACK( post_deliver_signal, tid, sigNo );
|
|
}
|
|
|
|
#endif /* VGA_s390x */
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- end sigframe-s390x-linux.c ---*/
|
|
/*--------------------------------------------------------------------*/
|