This is the mail archive of the gdb-cvs@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]

gdb and binutils branch master updated. b18e90f549f21f6a8cff7039d932754c4cfe2b46


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gdb and binutils".

The branch, master has been updated
       via  b18e90f549f21f6a8cff7039d932754c4cfe2b46 (commit)
      from  908794a91538a6a758b60847f33411efea0cb2fe (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b18e90f549f21f6a8cff7039d932754c4cfe2b46

commit b18e90f549f21f6a8cff7039d932754c4cfe2b46
Author: Pedro Alves <palves@redhat.com>
Date:   Thu Oct 31 21:00:23 2013 +0000

    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 signals.
    
    There's more.  Take this bit of handle_inferior_event, where we
    determine whether a real signal (TARGET_WAITKIND_STOPPED) was random
    or not:
    
      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
        ecs->random_signal
          = !((bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
    				   GDB_SIGNAL_TRAP)
    	   != BPSTAT_SIGNAL_NO)
    	  || stopped_by_watchpoint
    	  || ecs->event_thread->control.trap_expected
    	  || (ecs->event_thread->control.step_range_end
    	      && (ecs->event_thread->control.step_resume_breakpoint
    		  == NULL)));
      else
        {
          enum bpstat_signal_value sval;
    
          sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
    				     ecs->event_thread->suspend.stop_signal);
          ecs->random_signal = (sval == BPSTAT_SIGNAL_NO);
    
          if (sval == BPSTAT_SIGNAL_HIDE)
    	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
        }
    
    Note that the
    
          if (sval == BPSTAT_SIGNAL_HIDE)
    	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP;
    
    bit is only reacheable for signals != GDB_SIGNAL_TRAP.  AFAICS, sval
    can only be BPSTAT_SIGNAL_HIDE if nothing in the bpstat returns
    BPSTAT_SIGNAL_PASS.  So that excludes a "catch signal" for the signal
    in question in the bpstat.  All other catchpoints that aren't based on
    breakpoints behind the scenes call process_event_stop_test directly
    (don't pass through here) (well, almost all: TARGET_WAITKIND_LOADED
    does have a fall through, but only for STOP_QUIETLY or
    STOP_QUIETLY_NO_SIGSTOP, which still return before this code is
    reached).  Catchpoints that are implemented as breakpoints behind the
    scenes can only appear in the bpstat if the signal was GDB_SIGNAL_TRAP
    (bkpt_breakpoint_hit returns false otherwise).  So that leaves a
    target reporting a hardware watchpoint hit with a signal other than
    GDB_SIGNAL_TRAP.  And even then it looks quite wrong to me to
    magically convert the signal into a GDB_SIGNAL_TRAP here too -- if the
    user has set SIGTRAP to "handle pass", the program will see a trap
    that gdb invented, not one the program would ever see without gdb in
    the picture.
    
    Tested on x86_64 Fedora 17.
    
    gdb/
    2013-10-31  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.

-----------------------------------------------------------------------

Summary of changes:
 gdb/ChangeLog |   11 +++++++++++
 gdb/infrun.c  |   13 ++++---------
 2 files changed, 15 insertions(+), 9 deletions(-)


hooks/post-receive
-- 
gdb and binutils


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