This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] infrun.c: use GDB_SIGNAL_0 when hidding signals, not GDB_SIGNAL_TRAP.


IMO, it doesn't make sense to map random syscall, fork, etc. events to
GDB_SIGNAL_TRAP, and possible have the debuggee see that trap.  This
just seems conceptually wrong to me - these aren't real signals a
debuggee would ever see.  In fact, when stopped for those events, on
Linux, the debuggee isn't in a signal-stop -- there's no way to
resume-and-deliver-signal at that point, for example.  E.g., when
stopped at a fork event:

 (gdb) catch fork
 Catchpoint 2 (fork)
 (gdb) c
 Continuing.

 Catchpoint 2 (forked process 4570), 0x000000323d4ba7c4 in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:131
 131       pid = ARCH_FORK ();
 (gdb) set debug infrun 1
 (gdb) signal SIGTRAP
 Continuing with signal SIGTRAP.
 infrun: clear_proceed_status_thread (process 4566)
 infrun: proceed (addr=0xffffffffffffffff, signal=5, step=0)
 infrun: resume (step=0, signal=5), trap_expected=0, current thread [process 4566] at 0x323d4ba7c4
 infrun: wait_for_inferior ()
 infrun: target_wait (-1, status) =
 infrun:   4566 [process 4566],
 infrun:   status->kind = exited, status = 0
 infrun: infwait_normal_state
 infrun: TARGET_WAITKIND_EXITED
 [Inferior 1 (process 4566) exited normally]
 infrun: stop_stepping
 (gdb)

Note the signal went nowhere.  It was swallowed.

Resuming with a SIGTRAP from a syscall event does queue the signal,
but doesn't deliver it immediately, like "signal SIGTRAP" from a real
signal would.  It's still an artificial SIGTRAP:

 (gdb) catch syscall
 Catchpoint 2 (any syscall)
 (gdb) c
 Continuing.

 Catchpoint 2 (call to syscall clone), 0x000000323d4ba7c4 in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:131
 131       pid = ARCH_FORK ();
 (gdb) set debug infrun 1
 (gdb) signal SIGTRAP
 Continuing with signal SIGTRAP.
 infrun: clear_proceed_status_thread (process 4622)
 infrun: proceed (addr=0xffffffffffffffff, signal=5, step=0)
 infrun: resume (step=0, signal=5), trap_expected=0, current thread [process 4622] at 0x323d4ba7c4
 infrun: wait_for_inferior ()
 infrun: target_wait (-1, status) =
 infrun:   4622 [process 4622],
 infrun:   status->kind = exited syscall
 infrun: infwait_normal_state
 infrun: TARGET_WAITKIND_SYSCALL_RETURN
 infrun: syscall number = '56'
 infrun: BPSTAT_WHAT_STOP_NOISY
 infrun: stop_stepping

 Catchpoint 2 (returned from syscall clone), 0x000000323d4ba7c4 in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:131
 131       pid = ARCH_FORK ();
 (gdb) c
 Continuing.
 infrun: clear_proceed_status_thread (process 4622)
 infrun: proceed (addr=0xffffffffffffffff, signal=144, step=0)
 infrun: resume (step=0, signal=0), trap_expected=0, current thread [process 4622] at 0x323d4ba7c4
 infrun: wait_for_inferior ()
 infrun: target_wait (-1, status) =
 infrun:   4622 [process 4622],
 infrun:   status->kind = stopped, signal = SIGTRAP
 infrun: infwait_normal_state
 infrun: TARGET_WAITKIND_STOPPED
 infrun: stop_pc = 0x323d4ba7c4
 infrun: random signal 5

 Program received signal SIGTRAP, Trace/breakpoint trap.
 infrun: stop_stepping
 0x000000323d4ba7c4 in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:131
 131       pid = ARCH_FORK ();
 (gdb)

In all the above, I used 'signal SIGTRAP' to emulate 'handle SIGTRAP
pass'.  As described in "keep_going", 'handle SIGTRAP pass' does have
its place:

      /* Do not deliver GDB_SIGNAL_TRAP (except when the user
	 explicitly specifies that such a signal should be delivered
	 to the target program).  Typically, that would occur when a
	 user is debugging a target monitor on a simulator: the target
	 monitor sets a breakpoint; the simulator encounters this
	 breakpoint and halts the simulation handing control to GDB;
	 GDB, noting that the stop address doesn't map to any known
	 breakpoint, returns control back to the simulator; the
	 simulator then delivers the hardware equivalent of a
	 GDB_SIGNAL_TRAP to the program being debugged.	 */

... and I've made use of that myself when implementing/debugging
stubs/monitors.  But in these cases, treating these events as SIGTRAP
possibly injects signals in the debuggee they'd never see otherwise,
because you need to use ptrace to enable these special events, which
aren't real signal.

Tested on x86_64 Fedora 17.

Comments?

gdb/
2013-10-22  Pedro Alves  <palves@redhat.com>

	* infrun.c (handle_syscall_event): Don't set or clear stop_signal.
	(handle_inferior_event) <TARGET_WAITKIND_FORKED,
	TARGET_WAITKIND_VFORKED>: Don't set stop_signal to
	GDB_SIGNAL_TRAP, or clear it.  Pass GDB_SIGNAL_0 to
	bpstat_explains signal, instead of GDB_SIGNAL_TRAP.
	<bpstat handling>: If the bpstat chain wants the signal to be
	hidden, then set stop_signal to GDB_SIGNAL_0 instead of
	GDB_SIGNAL_TRAP.
---
 gdb/infrun.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index b1d2dc5..dfc1ef6 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3101,19 +3101,17 @@ handle_syscall_event (struct execution_control_state *ecs)
 			      stop_pc, ecs->ptid, &ecs->ws);
 
       sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
-				     GDB_SIGNAL_TRAP);
+				     GDB_SIGNAL_0);
       ecs->random_signal = sval == BPSTAT_SIGNAL_NO;
 
       if (!ecs->random_signal)
 	{
 	  /* Catchpoint hit.  */
-	  ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
 	  return 0;
 	}
     }
 
   /* If no catchpoint triggered for this, then keep going.  */
-  ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
   keep_going (ecs);
   return 1;
 }
@@ -3352,13 +3350,12 @@ handle_inferior_event (struct execution_control_state *ecs)
 
 	  sval
 	    = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
-				      GDB_SIGNAL_TRAP);
+				      GDB_SIGNAL_0);
 	  ecs->random_signal = sval == BPSTAT_SIGNAL_NO;
 
 	  if (!ecs->random_signal)
 	    {
 	      /* A catchpoint triggered.  */
-	      ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
 	      goto process_event_stop_test;
 	    }
 
@@ -3636,7 +3633,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
 	    stop_stepping (ecs);
 	  return;
 	}
-      ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
       goto process_event_stop_test;
 
     case TARGET_WAITKIND_VFORK_DONE:
@@ -3682,7 +3678,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
 			      stop_pc, ecs->ptid, &ecs->ws);
       ecs->random_signal
 	= (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
-				   GDB_SIGNAL_TRAP)
+				   GDB_SIGNAL_0)
 	   == BPSTAT_SIGNAL_NO);
 
       /* Note that this may be referenced from inside
@@ -3697,7 +3693,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
 	  keep_going (ecs);
 	  return;
 	}
-      ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
       goto process_event_stop_test;
 
       /* Be careful not to try to gather much state about a thread
@@ -4304,7 +4299,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
       ecs->random_signal = (sval == BPSTAT_SIGNAL_NO);
 
       if (sval == BPSTAT_SIGNAL_HIDE)
-	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
+	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
     }
 
 process_event_stop_test:
-- 
1.7.11.7


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]