All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] make single-step into signal delivery stop in handler
@ 2004-08-31  4:44 Roland McGrath
  2004-08-31 15:59 ` Andrew Cagney
  0 siblings, 1 reply; 2+ messages in thread
From: Roland McGrath @ 2004-08-31  4:44 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: Andrew Cagney, Linux Kernel Mailing List

On x86 and x86-64, setting up to run a signal handler clears the
single-step bit (TF) in the processor flags before starting the handler.
This makes sense when a process is handling its own SIGTRAPs.

But when TF is set because PTRACE_SINGLESTEP was used, and that call
specified a handled signal so the handler setup is happening, it doesn't
make so much sense.  When the debugger stops to show you a signal about to
be delivered, and that signal should be handled, and then you do step or
stepi, you expect to see the signal handler code.  In fact, the signal
handler runs to completion and then you see the single-step trap at the
resumed code instead of seeing the handler.  

This patch changes signal handler setup so that when TF is set and the
thread is under ptrace control, it synthesizes a single-step trap after
setting up the PC and registers to start the handler.  This makes that
PTRACE_SINGLESTEP not strictly a "step", since it actually runs no user
instructions at all.  But it is definitely what a debugger user wants, so
that single-stepping always stops and shows each and every instruction
before it gets executed.



Thanks,
Roland

Signed-off-by: Roland McGrath <roland@redhat.com>

--- vanilla-linux-2.6/arch/i386/kernel/signal.c	2004-08-30 20:48:24.132472094 -0700
+++ linux-2.6-ptracefix/arch/i386/kernel/signal.c	2004-08-30 20:47:30.000000000 -0700
@@ -19,6 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/personality.h>
 #include <linux/suspend.h>
+#include <linux/ptrace.h>
 #include <linux/elf.h>
 #include <asm/processor.h>
 #include <asm/ucontext.h>
@@ -401,7 +402,13 @@ static void setup_frame(int sig, struct 
 	regs->xes = __USER_DS;
 	regs->xss = __USER_DS;
 	regs->xcs = __USER_CS;
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -480,7 +487,13 @@ static void setup_rt_frame(int sig, stru
 	regs->xes = __USER_DS;
 	regs->xss = __USER_DS;
 	regs->xcs = __USER_CS;
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
--- vanilla-linux-2.6/arch/x86_64/ia32/ia32_signal.c	2004-08-30 20:48:24.160468505 -0700
+++ linux-2.6-ptracefix/arch/x86_64/ia32/ia32_signal.c	2004-08-30 20:47:46.000000000 -0700
@@ -489,7 +491,13 @@ void ia32_setup_frame(int sig, struct k_
 	regs->ss = __USER32_DS; 
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -583,7 +591,13 @@ void ia32_setup_rt_frame(int sig, struct
 	regs->ss = __USER32_DS; 
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
--- vanilla-linux-2.6/arch/x86_64/kernel/signal.c	2004-08-30 20:48:24.186465171 -0700
+++ linux-2.6-ptracefix/arch/x86_64/kernel/signal.c	2004-08-30 20:47:58.000000000 -0700
@@ -319,7 +319,13 @@ static void setup_rt_frame(int sig, stru
 	regs->rsp = (unsigned long)frame;
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #ifdef DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] make single-step into signal delivery stop in handler
  2004-08-31  4:44 [PATCH] make single-step into signal delivery stop in handler Roland McGrath
@ 2004-08-31 15:59 ` Andrew Cagney
  0 siblings, 0 replies; 2+ messages in thread
From: Andrew Cagney @ 2004-08-31 15:59 UTC (permalink / raw)
  To: Roland McGrath, Linus Torvalds, Andrew Morton
  Cc: Andrew Cagney, Linux Kernel Mailing List

[wonder if I can e-mail to linux-kernel]
Just FYI, GDB's testsuite has been extended to cover this case.  The 
sigstep.exp tests pass on a kernel with this and Roland's earlier 
changes.  Ya!

Andrew


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-08-31 16:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-31  4:44 [PATCH] make single-step into signal delivery stop in handler Roland McGrath
2004-08-31 15:59 ` Andrew Cagney

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.