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; }
/* Create a signal frame for thread 'tid'. */ void VG_(sigframe_create) ( ThreadId tid, Addr sp_top_of_frame, const vki_siginfo_t *siginfo, void *handler, UInt flags, const vki_sigset_t *mask, void *restorer ) { ThreadState* tst; Addr sp; struct hacky_sigframe* frame; Int sigNo = siginfo->si_signo; Int __NR_FAKE_SIGRETURN = __NR_AIX5_FAKE_SIGRETURN; vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe))); sp_top_of_frame &= ~0xf; sp = sp_top_of_frame - sizeof(struct hacky_sigframe); tst = VG_(get_ThreadState)(tid); if (!extend(tst, sp, sp_top_of_frame - sp)) return; vg_assert(VG_IS_16_ALIGNED(sp)); frame = (struct hacky_sigframe *) sp; /* clear it (very conservatively) */ VG_(memset)(&frame->lower_guardzone, 0, 512); VG_(memset)(&frame->gst, 0, sizeof(VexGuestPPC32State)); VG_(memset)(&frame->gshadow, 0, sizeof(VexGuestPPC32State)); /* save stuff in frame */ frame->gst = tst->arch.vex; frame->gshadow = tst->arch.vex_shadow; frame->sigNo_private = sigNo; frame->magicPI = 0x31415927; /* Set up stack frame pointer */ sp += 256; vg_assert(sp == (Addr)&frame->lower_guardzone[256]); VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame", sp, sizeof(UWord) ); *(Addr*)sp = tst->arch.vex.guest_GPR1; VG_TRACK( post_mem_write, Vg_CoreSignal, tid, sp, sizeof(UWord) ); /* Set regs for the handler */ SET_SIGNAL_GPR(tid, 1, sp); SET_SIGNAL_GPR(tid, 2, ((UWord*)handler)[1]); SET_SIGNAL_GPR(tid, 3, sigNo); SET_SIGNAL_GPR(tid, 4, 0); /* XXX: the siginfo* */ SET_SIGNAL_GPR(tid, 5, 0); /* XXX: the ucontext* */ tst->arch.vex.guest_CIA = ((UWord*)handler)[0]; /* set up return trampoline */ vg_assert(__NR_FAKE_SIGRETURN >= 10000); vg_assert(__NR_FAKE_SIGRETURN <= 32767); frame->tramp[0] = 0x38400000U + __NR_FAKE_SIGRETURN; /* li 2,__NR_FAKE_SIGRETURN */ frame->tramp[1] = 0x44000002U; /* sc */ /* invalidate any translation of this area */ VG_(discard_translations)( (Addr64)(Addr)&frame->tramp[0], sizeof(frame->tramp), "sigframe tramp" ); /* set the signal handler to return to the trampoline */ SET_SIGNAL_LR(tst, (Addr) &frame->tramp[0]); VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&frame->tramp, sizeof(frame->tramp)); if (0) { VG_(printf)("pushed signal frame for sig %d; R1 now = %p, " "next %%CIA = %p, status=%d\n", sigNo, sp, tst->arch.vex.guest_CIA, tst->status); VG_(printf)("trampoline is at %p\n", &frame->tramp[0]); } }
/* 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 ) { struct vg_sig_private* priv; Addr sp; ThreadState* tst; Int sigNo = siginfo->si_signo; Addr faultaddr; struct rt_sigframe* frame; /* Stack must be 16-byte aligned */ vg_assert(VG_IS_16_ALIGNED(sizeof(struct vg_sig_private))); vg_assert(VG_IS_16_ALIGNED(sizeof(struct rt_sigframe))); sp_top_of_frame &= ~0xf; sp = sp_top_of_frame - sizeof(struct rt_sigframe); tst = VG_(get_ThreadState)(tid); if (!extend(tst, sp, sp_top_of_frame - sp)) return; vg_assert(VG_IS_16_ALIGNED(sp)); frame = (struct rt_sigframe *) sp; /* clear it (conservatively) */ VG_(memset)(frame, 0, sizeof(*frame)); ///////// frame->pinfo = &frame->info; frame->puc = &frame->uc; frame->uc.uc_flags = 0; frame->uc.uc_link = 0; ///////// /* Set up the stack chain pointer */ VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame", sp, sizeof(UWord) ); *(Addr *)sp = tst->arch.vex.guest_GPR1; VG_TRACK( post_mem_write, Vg_CoreSignal, tid, sp, sizeof(UWord) ); faultaddr = (Addr)siginfo->_sifields._sigfault._addr; if (sigNo == VKI_SIGILL && siginfo->si_code > 0) faultaddr = tst->arch.vex.guest_CIA; VG_(memcpy)(&frame->info, siginfo, sizeof(*siginfo)); VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)&frame->info, sizeof(frame->info) ); frame->uc.uc_flags = 0; frame->uc.uc_link = 0; frame->uc.uc_stack = tst->altstack; frame->uc.uc_sigmask = tst->sig_mask; VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)(&frame->uc), sizeof(frame->uc) ); # define DO(gpr) frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr] \ = tst->arch.vex.guest_GPR##gpr DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); # undef DO frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP] = tst->arch.vex.guest_CIA; frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR] = 0xf032; /* pretty arbitrary */ frame->uc.uc_mcontext.gp_regs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3; frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR] = tst->arch.vex.guest_CTR; frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK] = tst->arch.vex.guest_LR; frame->uc.uc_mcontext.gp_regs[VKI_PT_XER] = LibVEX_GuestPPC64_get_XER( &tst->arch.vex); frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR] = LibVEX_GuestPPC64_get_CR( &tst->arch.vex); //mc->mc_gregs[VKI_PT_MQ] = 0; //mc->mc_gregs[VKI_PT_TRAP] = 0; //mc->mc_gregs[VKI_PT_DAR] = fault_addr; //mc->mc_gregs[VKI_PT_DSISR] = 0; //mc->mc_gregs[VKI_PT_RESULT] = 0; /* XXX should do FP and vector regs */ /* set up signal return trampoline */ /* NB. 5 Sept 07. mc->mc_pad[0..1] used to contain a the code to which the signal handler returns, and it just did sys_sigreturn or sys_rt_sigreturn. But this doesn't work if the stack is non-executable, and it isn't consistent with the x86-linux and amd64-linux scheme for removing the stack frame. So instead be consistent and use a stub in m_trampoline. Then it doesn't matter whether or not the (guest) stack is executable. This fixes #149519 and #145837. */ frame->tramp[0] = 0; /* invalid */ frame->tramp[1] = 0; /* invalid */ VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&frame->tramp, sizeof(frame->tramp)); /* invalidate any translation of this area */ VG_(discard_translations)( (Addr64)&frame->tramp[0], sizeof(frame->tramp), "stack_mcontext" ); /* set the signal handler to return to the trampoline */ SET_SIGNAL_LR(tst, (Addr)&VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)); /* Stack pointer for the handler .. (note, back chain set earlier) */ SET_SIGNAL_GPR(tid, 1, sp); /* Args for the handler .. */ SET_SIGNAL_GPR(tid, 3, sigNo); SET_SIGNAL_GPR(tid, 4, (Addr) &frame->info); SET_SIGNAL_GPR(tid, 5, (Addr) &frame->uc); /* the kernel sets this, though it doesn't seem to be in the ABI */ SET_SIGNAL_GPR(tid, 6, (Addr) &frame->info); /* Handler is in fact a standard ppc64-linux function descriptor, so extract the function entry point and also the toc ptr to use. */ SET_SIGNAL_GPR(tid, 2, (Addr) ((ULong*)handler)[1]); tst->arch.vex.guest_CIA = (Addr) ((ULong*)handler)[0]; priv = &frame->priv; priv->magicPI = 0x31415927; priv->sigNo_private = sigNo; priv->vex_shadow1 = tst->arch.vex_shadow1; priv->vex_shadow2 = tst->arch.vex_shadow2; if (0) VG_(printf)("pushed signal frame; %%R1 now = %#lx, " "next %%CIA = %#llx, status=%d\n", sp, tst->arch.vex.guest_CIA, tst->status); }
/* 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 ) { struct vg_sig_private *priv; Addr sp; ThreadState *tst; Int sigNo = siginfo->si_signo; Addr faultaddr; /* Stack must be 16-byte aligned */ sp_top_of_frame &= ~0xf; if (flags & VKI_SA_SIGINFO) { sp = sp_top_of_frame - sizeof(struct rt_sigframe); } else { sp = sp_top_of_frame - sizeof(struct nonrt_sigframe); } tst = VG_(get_ThreadState)(tid); if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags)) return; vg_assert(VG_IS_16_ALIGNED(sp)); /* Set up the stack chain pointer */ VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame", sp, sizeof(UWord) ); *(Addr *)sp = tst->arch.vex.guest_GPR1; VG_TRACK( post_mem_write, Vg_CoreSignal, tid, sp, sizeof(UWord) ); faultaddr = (Addr)siginfo->_sifields._sigfault._addr; if (sigNo == VKI_SIGILL && siginfo->si_code > 0) faultaddr = tst->arch.vex.guest_CIA; if (flags & VKI_SA_SIGINFO) { struct rt_sigframe *frame = (struct rt_sigframe *) sp; struct vki_ucontext *ucp = &frame->ucontext; VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo", (Addr)&frame->siginfo, sizeof(frame->siginfo) ); VG_(memcpy)(&frame->siginfo, siginfo, sizeof(*siginfo)); VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)&frame->siginfo, sizeof(frame->siginfo) ); VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", (Addr)ucp, offsetof(struct vki_ucontext, uc_pad) ); 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_pad) ); VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", (Addr)&ucp->uc_regs, sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) ); ucp->uc_regs = &ucp->uc_mcontext; ucp->uc_sigmask = tst->sig_mask; VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)&ucp->uc_regs, sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) ); stack_mcontext(&ucp->uc_mcontext, tst, True/*use_rt_sigreturn*/, faultaddr); priv = &frame->priv; SET_SIGNAL_GPR(tid, 4, (Addr) &frame->siginfo); SET_SIGNAL_GPR(tid, 5, (Addr) ucp); /* the kernel sets this, though it doesn't seem to be in the ABI */ SET_SIGNAL_GPR(tid, 6, (Addr) &frame->siginfo); } else {