static void stack_mcontext ( struct vki_mcontext *mc, ThreadState* tst, Bool use_rt_sigreturn, UInt fault_addr ) { VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", (Addr)mc, sizeof(struct vki_pt_regs) ); # define DO(gpr) mc->mc_gregs[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 mc->mc_gregs[VKI_PT_NIP] = tst->arch.vex.guest_CIA; mc->mc_gregs[VKI_PT_MSR] = 0xf032; /* pretty arbitrary */ mc->mc_gregs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3; mc->mc_gregs[VKI_PT_CTR] = tst->arch.vex.guest_CTR; mc->mc_gregs[VKI_PT_LNK] = tst->arch.vex.guest_LR; mc->mc_gregs[VKI_PT_XER] = LibVEX_GuestPPC32_get_XER(&tst->arch.vex); mc->mc_gregs[VKI_PT_CCR] = LibVEX_GuestPPC32_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; VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, (Addr)mc, sizeof(struct vki_pt_regs) ); /* 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. */ VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", (Addr)&mc->mc_pad, sizeof(mc->mc_pad)); mc->mc_pad[0] = 0; /* invalid */ mc->mc_pad[1] = 0; /* invalid */ VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&mc->mc_pad, sizeof(mc->mc_pad) ); /* invalidate any translation of this area */ VG_(discard_translations)( (Addr)&mc->mc_pad, sizeof(mc->mc_pad), "stack_mcontext" ); /* set the signal handler to return to the trampoline */ SET_SIGNAL_LR(tst, (Addr)(use_rt_sigreturn ? (Addr)&VG_(ppc32_linux_SUBST_FOR_rt_sigreturn) : (Addr)&VG_(ppc32_linux_SUBST_FOR_sigreturn) )); }
static void stack_mcontext ( struct vki_mcontext *mc, ThreadState* tst, Int ret, UInt fault_addr ) { VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", (Addr)mc, sizeof(struct vki_pt_regs) ); # define DO(gpr) mc->mc_gregs[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 mc->mc_gregs[VKI_PT_NIP] = tst->arch.vex.guest_CIA; mc->mc_gregs[VKI_PT_MSR] = 0xf032; /* pretty arbitrary */ mc->mc_gregs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3; mc->mc_gregs[VKI_PT_CTR] = tst->arch.vex.guest_CTR; mc->mc_gregs[VKI_PT_LNK] = tst->arch.vex.guest_LR; mc->mc_gregs[VKI_PT_XER] = LibVEX_GuestPPC32_get_XER(&tst->arch.vex); mc->mc_gregs[VKI_PT_CCR] = LibVEX_GuestPPC32_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; VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, (Addr)mc, sizeof(struct vki_pt_regs) ); /* XXX should do FP and vector regs */ /* set up signal return trampoline */ VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", (Addr)&mc->mc_pad, sizeof(mc->mc_pad)); mc->mc_pad[0] = 0x38000000U + ret; /* li 0,ret */ mc->mc_pad[1] = 0x44000002U; /* sc */ VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, (Addr)&mc->mc_pad, sizeof(mc->mc_pad) ); /* invalidate any translation of this area */ VG_(discard_translations)( (Addr64)(Addr)&mc->mc_pad, sizeof(mc->mc_pad), "stack_mcontext" ); /* set the signal handler to return to the trampoline */ SET_SIGNAL_LR(tst, (Addr) &mc->mc_pad[0]); }
/* 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); }