From: Tom Hughes Date: Fri, 21 Dec 2007 10:24:24 +0000 (+0000) Subject: Propagate the ucontext information with a received signal to the X-Git-Tag: svn/VALGRIND_3_4_0~1123 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=690019c33790299a9571b9dcb5672dfa275fab37;p=thirdparty%2Fvalgrind.git Propagate the ucontext information with a received signal to the signal frame constructors and use it (on x86 and amd64) to fill in the trap number in the signal context information. Needed for wine which likes to look at the trap number... git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7305 --- diff --git a/coregrind/m_sigframe/sigframe-amd64-linux.c b/coregrind/m_sigframe/sigframe-amd64-linux.c index 9bb1194497..89327b76c2 100644 --- a/coregrind/m_sigframe/sigframe-amd64-linux.c +++ b/coregrind/m_sigframe/sigframe-amd64-linux.c @@ -320,7 +320,7 @@ struct rt_sigframe bits of sigcontext at the moment. */ static -void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, +void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, Int trapno, const vki_sigset_t *set, struct vki_ucontext *uc, struct _vki_fpstate *fpstate) { @@ -361,7 +361,7 @@ void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, // FIXME: SC2(gs,GS); // FIXME: SC2(fs,FS); /* XXX err */ - /* XXX trapno */ + sc->trapno = trapno; # undef SC2 sc->cr2 = (UWord)si->_sifields._sigfault._addr; @@ -435,6 +435,7 @@ static void build_vg_sigframe(struct vg_sigframe *frame, static Addr build_rt_sigframe(ThreadState *tst, Addr rsp_top_of_frame, const vki_siginfo_t *siginfo, + const struct vki_ucontext *siguc, void *handler, UInt flags, const vki_sigset_t *mask, void *restorer) @@ -442,6 +443,7 @@ static Addr build_rt_sigframe(ThreadState *tst, struct rt_sigframe *frame; Addr rsp = rsp_top_of_frame; Int sigNo = siginfo->si_signo; + Int trapno; rsp -= sizeof(*frame); rsp = VG_ROUNDDN(rsp, 16); @@ -459,6 +461,11 @@ static Addr build_rt_sigframe(ThreadState *tst, else frame->retaddr = (Addr)&VG_(amd64_linux_SUBST_FOR_rt_sigreturn); + if (siguc) + trapno = siguc->uc_mcontext.trapno; + else + trapno = 0; + VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t)); /* SIGILL defines addr to be the faulting address */ @@ -466,7 +473,7 @@ static Addr build_rt_sigframe(ThreadState *tst, frame->sigInfo._sifields._sigfault._addr = (void*)tst->arch.vex.guest_RIP; - synth_ucontext(tst->tid, siginfo, mask, &frame->uContext, &frame->fpstate); + synth_ucontext(tst->tid, siginfo, trapno, mask, &frame->uContext, &frame->fpstate); VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, rsp, offsetof(struct rt_sigframe, vg) ); @@ -480,6 +487,7 @@ static Addr build_rt_sigframe(ThreadState *tst, void VG_(sigframe_create)( ThreadId tid, Addr rsp_top_of_frame, const vki_siginfo_t *siginfo, + const struct vki_ucontext *siguc, void *handler, UInt flags, const vki_sigset_t *mask, @@ -489,7 +497,7 @@ void VG_(sigframe_create)( ThreadId tid, struct rt_sigframe *frame; ThreadState* tst = VG_(get_ThreadState)(tid); - rsp = build_rt_sigframe(tst, rsp_top_of_frame, siginfo, + rsp = build_rt_sigframe(tst, rsp_top_of_frame, siginfo, siguc, handler, flags, mask, restorer); frame = (struct rt_sigframe *)rsp; diff --git a/coregrind/m_sigframe/sigframe-ppc32-aix5.c b/coregrind/m_sigframe/sigframe-ppc32-aix5.c index bbb72f8210..4f732ad59e 100644 --- a/coregrind/m_sigframe/sigframe-ppc32-aix5.c +++ b/coregrind/m_sigframe/sigframe-ppc32-aix5.c @@ -103,6 +103,7 @@ static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 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, diff --git a/coregrind/m_sigframe/sigframe-ppc32-linux.c b/coregrind/m_sigframe/sigframe-ppc32-linux.c index aa364269a5..1dedae41e7 100644 --- a/coregrind/m_sigframe/sigframe-ppc32-linux.c +++ b/coregrind/m_sigframe/sigframe-ppc32-linux.c @@ -665,6 +665,7 @@ static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 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, diff --git a/coregrind/m_sigframe/sigframe-ppc64-aix5.c b/coregrind/m_sigframe/sigframe-ppc64-aix5.c index 50ecad90a7..4346e51a20 100644 --- a/coregrind/m_sigframe/sigframe-ppc64-aix5.c +++ b/coregrind/m_sigframe/sigframe-ppc64-aix5.c @@ -103,6 +103,7 @@ static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 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, diff --git a/coregrind/m_sigframe/sigframe-ppc64-linux.c b/coregrind/m_sigframe/sigframe-ppc64-linux.c index 437b3e7c93..24f370d86b 100644 --- a/coregrind/m_sigframe/sigframe-ppc64-linux.c +++ b/coregrind/m_sigframe/sigframe-ppc64-linux.c @@ -175,6 +175,7 @@ static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 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, diff --git a/coregrind/m_sigframe/sigframe-x86-linux.c b/coregrind/m_sigframe/sigframe-x86-linux.c index bb665987bf..d341766dda 100644 --- a/coregrind/m_sigframe/sigframe-x86-linux.c +++ b/coregrind/m_sigframe/sigframe-x86-linux.c @@ -344,7 +344,7 @@ struct rt_sigframe bits of sigcontext at the moment. */ static -void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, +void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, Int trapno, const vki_sigset_t *set, struct vki_ucontext *uc, struct _vki_fpstate *fpstate) { @@ -381,7 +381,7 @@ void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex); SC2(ss,SS); /* XXX esp_at_signal */ - /* XXX trapno */ + sc->trapno = trapno; /* XXX err */ # undef SC2 @@ -456,6 +456,7 @@ static void build_vg_sigframe(struct vg_sigframe *frame, static Addr build_sigframe(ThreadState *tst, Addr esp_top_of_frame, const vki_siginfo_t *siginfo, + const struct vki_ucontext *siguc, void *handler, UInt flags, const vki_sigset_t *mask, void *restorer) @@ -463,6 +464,7 @@ static Addr build_sigframe(ThreadState *tst, struct sigframe *frame; Addr esp = esp_top_of_frame; Int sigNo = siginfo->si_signo; + Int trapno; struct vki_ucontext uc; vg_assert((flags & VKI_SA_SIGINFO) == 0); @@ -485,7 +487,12 @@ static Addr build_sigframe(ThreadState *tst, else frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_sigreturn); - synth_ucontext(tst->tid, siginfo, mask, &uc, &frame->fpstate); + if (siguc) + trapno = siguc->uc_mcontext.trapno; + else + trapno = 0; + + synth_ucontext(tst->tid, siginfo, trapno, mask, &uc, &frame->fpstate); VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext, sizeof(struct vki_sigcontext)); @@ -503,6 +510,7 @@ static Addr build_sigframe(ThreadState *tst, static Addr build_rt_sigframe(ThreadState *tst, Addr esp_top_of_frame, const vki_siginfo_t *siginfo, + const struct vki_ucontext *siguc, void *handler, UInt flags, const vki_sigset_t *mask, void *restorer) @@ -510,6 +518,7 @@ static Addr build_rt_sigframe(ThreadState *tst, struct rt_sigframe *frame; Addr esp = esp_top_of_frame; Int sigNo = siginfo->si_signo; + Int trapno; vg_assert((flags & VKI_SA_SIGINFO) != 0); @@ -531,6 +540,11 @@ static Addr build_rt_sigframe(ThreadState *tst, else frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_rt_sigreturn); + if (siguc) + trapno = siguc->uc_mcontext.trapno; + else + trapno = 0; + frame->psigInfo = (Addr)&frame->sigInfo; frame->puContext = (Addr)&frame->uContext; VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t)); @@ -540,7 +554,7 @@ static Addr build_rt_sigframe(ThreadState *tst, frame->sigInfo._sifields._sigfault._addr = (void*)tst->arch.vex.guest_EIP; - synth_ucontext(tst->tid, siginfo, mask, &frame->uContext, &frame->fpstate); + synth_ucontext(tst->tid, siginfo, trapno, mask, &frame->uContext, &frame->fpstate); VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, esp, offsetof(struct rt_sigframe, vg) ); @@ -555,6 +569,7 @@ static Addr build_rt_sigframe(ThreadState *tst, void VG_(sigframe_create)( ThreadId tid, Addr esp_top_of_frame, const vki_siginfo_t *siginfo, + const struct vki_ucontext *siguc, void *handler, UInt flags, const vki_sigset_t *mask, @@ -564,11 +579,11 @@ void VG_(sigframe_create)( ThreadId tid, ThreadState* tst = VG_(get_ThreadState)(tid); if (flags & VKI_SA_SIGINFO) - esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo, + esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo, siguc, handler, flags, mask, restorer); else - esp = build_sigframe(tst, esp_top_of_frame, - siginfo, handler, flags, mask, restorer); + esp = build_sigframe(tst, esp_top_of_frame, siginfo, siguc, + handler, flags, mask, restorer); /* Set the thread so it will next run the handler. */ /* tst->m_esp = esp; also notify the tool we've updated ESP */ diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index 9745d2c721..6ab5f270de 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -1002,7 +1002,7 @@ void VG_(clear_out_queued_signals)( ThreadId tid, vki_sigset_t* saved_mask ) /* Set up a stack frame (VgSigContext) for the client's signal handler. */ static -void push_signal_frame ( ThreadId tid, const vki_siginfo_t *siginfo ) +void push_signal_frame ( ThreadId tid, const vki_siginfo_t *siginfo, const struct vki_ucontext *uc ) { Addr esp_top_of_frame; ThreadState* tst; @@ -1051,7 +1051,7 @@ void push_signal_frame ( ThreadId tid, const vki_siginfo_t *siginfo ) /* This may fail if the client stack is busted; if that happens, the whole process will exit rather than simply calling the signal handler. */ - VG_(sigframe_create) (tid, esp_top_of_frame, siginfo, + VG_(sigframe_create) (tid, esp_top_of_frame, siginfo, uc, scss.scss_per_sig[sigNo].scss_handler, scss.scss_per_sig[sigNo].scss_flags, &tst->sig_mask, @@ -1346,7 +1346,7 @@ static void default_action(const vki_siginfo_t *info, ThreadId tid) This updates the thread state, but it does not set it to be Runnable. */ -static void deliver_signal ( ThreadId tid, const vki_siginfo_t *info ) +static void deliver_signal ( ThreadId tid, const vki_siginfo_t *info, const struct vki_ucontext *uc ) { Int sigNo = info->si_signo; SCSS_Per_Signal *handler = &scss.scss_per_sig[sigNo]; @@ -1393,7 +1393,7 @@ static void deliver_signal ( ThreadId tid, const vki_siginfo_t *info ) */ vg_assert(VG_(is_valid_tid)(tid)); - push_signal_frame ( tid, info ); + push_signal_frame ( tid, info, uc ); if (handler->scss_flags & VKI_SA_ONESHOT) { /* Do the ONESHOT thing. */ @@ -1448,7 +1448,7 @@ static void synth_fault_common(ThreadId tid, Addr addr, Int si_code) if (VG_(sigismember)(&VG_(threads)[tid].sig_mask, VKI_SIGSEGV)) VG_(set_default_handler)(VKI_SIGSEGV); - deliver_signal(tid, &info); + deliver_signal(tid, &info, NULL); } // Synthesize a fault where the address is OK, but the page @@ -1482,21 +1482,26 @@ void VG_(synth_sigill)(ThreadId tid, Addr addr) info.VKI_SIGINFO_si_addr = (void*)addr; resume_scheduler(tid); - deliver_signal(tid, &info); + deliver_signal(tid, &info, NULL); } // Synthesise a SIGTRAP. void VG_(synth_sigtrap)(ThreadId tid) { vki_siginfo_t info; + struct vki_ucontext uc; vg_assert(VG_(threads)[tid].status == VgTs_Runnable); info.si_signo = VKI_SIGTRAP; - info.si_code = VKI_TRAP_TRACE; /* jrs: no idea what this should be */ + info.si_code = VKI_TRAP_BRKPT; /* tjh: only ever called for a brkpt ins */ +#if defined(VGA_x86) || defined(VGA_amd64) + uc.uc_mcontext.trapno = 3; /* tjh: this is the x86 trap number + for a breakpoint trap... */ +#endif resume_scheduler(tid); - deliver_signal(tid, &info); + deliver_signal(tid, &info, &uc); } /* Make a signal pending for a thread, for later delivery. @@ -1627,7 +1632,7 @@ void async_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext * /* Set up the thread's state to deliver a signal */ if (!is_sig_ign(info->si_signo)) - deliver_signal(tid, info); + deliver_signal(tid, info, uc); /* longjmp back to the thread's main loop to start executing the handler. */ @@ -1784,7 +1789,7 @@ void sync_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext *u /* It's a fatal signal, so we force the default handler. */ VG_(set_default_handler)(sigNo); - deliver_signal(tid, info); + deliver_signal(tid, info, uc); resume_scheduler(tid); VG_(exit)(99); /* If we can't resume, then just exit */ } @@ -1893,7 +1898,7 @@ void sync_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext *u if (VG_(in_generated_code)) { /* Can't continue; must longjmp back to the scheduler and thus enter the sighandler immediately. */ - deliver_signal(tid, info); + deliver_signal(tid, info, uc); resume_scheduler(tid); } @@ -2041,7 +2046,7 @@ void VG_(poll_signals)(ThreadId tid) VG_(message)(Vg_DebugMsg, "Polling found signal %d for tid %d", sip->si_signo, tid); if (!is_sig_ign(sip->si_signo)) - deliver_signal(tid, sip); + deliver_signal(tid, sip, NULL); else if (VG_(clo_trace_signals)) VG_(message)(Vg_DebugMsg, " signal %d ignored", sip->si_signo); diff --git a/coregrind/pub_core_sigframe.h b/coregrind/pub_core_sigframe.h index defc8fa5e5..72057d8d20 100644 --- a/coregrind/pub_core_sigframe.h +++ b/coregrind/pub_core_sigframe.h @@ -47,6 +47,7 @@ extern void VG_(sigframe_create) ( ThreadId tid, Addr sp_top_of_frame, const vki_siginfo_t *siginfo, + const struct vki_ucontext *uc, void *handler, UInt flags, const vki_sigset_t *mask,