]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Propagate the ucontext information with a received signal to the
authorTom Hughes <tom@compton.nu>
Fri, 21 Dec 2007 10:24:24 +0000 (10:24 +0000)
committerTom Hughes <tom@compton.nu>
Fri, 21 Dec 2007 10:24:24 +0000 (10:24 +0000)
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

coregrind/m_sigframe/sigframe-amd64-linux.c
coregrind/m_sigframe/sigframe-ppc32-aix5.c
coregrind/m_sigframe/sigframe-ppc32-linux.c
coregrind/m_sigframe/sigframe-ppc64-aix5.c
coregrind/m_sigframe/sigframe-ppc64-linux.c
coregrind/m_sigframe/sigframe-x86-linux.c
coregrind/m_signals.c
coregrind/pub_core_sigframe.h

index 9bb119449723eedd7ff3959aa4a766d7d3f4f8a0..89327b76c25220e3b4f304a63a3c79f7d1dc53a6 100644 (file)
@@ -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;
 
index bbb72f82101e434e9ca1d6c68cac30bc8aa4dc59..4f732ad59e7c266ee31ecb4fcbbed72fe88ea250 100644 (file)
@@ -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,
index aa364269a50bbb7bfc67fc1f10dfe895374ff7a7..1dedae41e7b0c560694fbb60c6ae0f00da4577ce 100644 (file)
@@ -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,
index 50ecad90a7d83a77f9751076347b15e0c3520ac6..4346e51a2084d2167298ff48aad244ac4d4838ae 100644 (file)
@@ -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,
index 437b3e7c930d55876661743218ee061251c8d821..24f370d86b3deeec5209f7cfe3818e5cc282901a 100644 (file)
@@ -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,
index bb665987bf1384f0b97eb7ea3e4e0bae2a8c2e8e..d341766dda77790a6df5177318ef813b1cab7b67 100644 (file)
@@ -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 */
index 9745d2c72120e18174ffc1c21aa7fcb8dd5f12ea..6ab5f270def1a236c72d500ac362bb96ea098d20 100644 (file)
@@ -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);
         
index defc8fa5e5a64fbb058109a5795d5e5a0f5f3d49..72057d8d2091dc7e94f66972f7ec29a5647b7d50 100644 (file)
@@ -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,