Bug 17000 - user breakpoint not inserted if software-single-step at same location
Summary: user breakpoint not inserted if software-single-step at same location
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: breakpoints (show other bugs)
Version: 7.7
: P2 normal
Target Milestone: 7.8
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-05-30 16:09 UTC by Pedro Alves
Modified: 2014-06-04 12:58 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pedro Alves 2014-05-30 16:09:02 UTC
This was first reported as a regression caused by the fix for 
bug 7143.  See discussion starting at:

 https://sourceware.org/bugzilla/show_bug.cgi?id=7143#c12

On software single-step targets, if another breakpoint happens to be inserted where a single-step breakpoint is also inserted, and gdb removes the single-step breakpoint, while intenting to leave the other breakpoint inserted, GDB actually really removes the breakpoint from the target, while it thinks it hasn't, leading to all sort of nasty issues related to the breakpoint being missed.
Comment 1 cvs-commit@gcc.gnu.org 2014-05-30 16:22:00 UTC
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  9ba6657a6b81a02dca9071ec14cbcef970f0ca07 (commit)
      from  522c09bf63a4b235e6fde07a5e389f2a533cfe0f (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=9ba6657a6b81a02dca9071ec14cbcef970f0ca07

commit 9ba6657a6b81a02dca9071ec14cbcef970f0ca07
Author: Pedro Alves <palves@redhat.com>
Date:   Fri May 30 17:21:02 2014 +0100

    PR breakpoints/17000: user breakpoint not inserted if software-single-step at same location - test
    
    GDB gets confused when removing a software single-step breakpoint that
    is at the same address as another breakpoint.  Add a kfailed test.
    
    gdb/testsuite/
    2014-05-30  Pedro Alves  <palves@redhat.com>
    
    	PR breakpoints/17000
    	* gdb.base/sss-bp-on-user-bp.c: New file.
    	* gdb.base/sss-bp-on-user-bp.exp: New file.

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

Summary of changes:
 gdb/testsuite/ChangeLog                      |    6 +++
 gdb/testsuite/gdb.base/sss-bp-on-user-bp.c   |   30 +++++++++++++++
 gdb/testsuite/gdb.base/sss-bp-on-user-bp.exp |   52 ++++++++++++++++++++++++++
 3 files changed, 88 insertions(+), 0 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/sss-bp-on-user-bp.c
 create mode 100644 gdb/testsuite/gdb.base/sss-bp-on-user-bp.exp
Comment 2 cvs-commit@gcc.gnu.org 2014-06-03 11:50:27 UTC
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  835c559fd59d4ebb3b04d046c1f9f36183db0fe6 (commit)
      from  06eb158633faa8746dd39f19ce784448bb7ece00 (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=835c559fd59d4ebb3b04d046c1f9f36183db0fe6

commit 835c559fd59d4ebb3b04d046c1f9f36183db0fe6
Author: Pedro Alves <palves@redhat.com>
Date:   Tue Jun 3 12:46:46 2014 +0100

    PR breakpoints/17000: user breakpoint not inserted if software-single-step at same location - test
    
    GDB gets confused when removing a software single-step breakpoint that
    is at the same address as another breakpoint.  Add another kfailed
    test.
    
    gdb/testsuite/
    2014-06-03  Pedro Alves  <palves@redhat.com>
    
    	PR breakpoints/17000
    	* gdb.base/sss-bp-on-user-bp-2.c: New file.
    	* gdb.base/sss-bp-on-user-bp-2.exp: New file.

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

Summary of changes:
 gdb/testsuite/ChangeLog                        |    6 ++
 gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.c   |   29 ++++++
 gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.exp |  109 ++++++++++++++++++++++++
 3 files changed, 144 insertions(+), 0 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.c
 create mode 100644 gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.exp
Comment 3 cvs-commit@gcc.gnu.org 2014-06-03 16:44:15 UTC
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  ef370185fcf955b1273c2c6bcbe0b406ec1cbd83 (commit)
      from  c32abae8456a2cb959862626b5ff9ebdd1543514 (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=ef370185fcf955b1273c2c6bcbe0b406ec1cbd83

commit ef370185fcf955b1273c2c6bcbe0b406ec1cbd83
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Tue Jun 3 17:42:19 2014 +0100

    User breakpoint ignored if software-single-step at same location
    
    with the following code...
    
        12    Nested;   -- break #1
        13    return I; -- break #2
        14  end;
    
    (line 12 is a call to function Nested)
    
    ... we have noticed the following errorneous behavior on ppc-aix,
    where, after having inserted a breakpoint at line 12 and line 13,
    and continuing from the breakpoint at line 12, the program never
    stops at line 13, running away until the program terminates:
    
        % gdb -q func
        (gdb) b func.adb:12
        Breakpoint 1 at 0x10000a24: file func.adb, line 12.
        (gdb) b func.adb:13
        Breakpoint 2 at 0x10000a28: file func.adb, line 13.
        (gdb) run
        Starting program: /[...]/func
    
        Breakpoint 1, func () at func.adb:12
        12        Nested;   -- break #1
        (gdb) c
        Continuing.
        [Inferior 1 (process 4128872) exited with code 02]
    
    When resuming from the first breakpoint, GDB first tries to step out
    of that first breakpoint.  We rely on software single-stepping on this
    platform, and it just so happens that the address of the first
    software single-step breakpoint is the same as the user's breakpoint
    #2 (0x10000a28).  So, with infrun and target traces turned on (but
    uninteresting traces snip'ed off), the "continue" operation looks like
    this:
    
        (gdb) c
        ### First, we insert the user breakpoints (the second one is an internal
        ### breakpoint on __pthread_init). The first user breakpoint is not
        ### inserted as we need to step out of it first.
        target_insert_breakpoint (0x0000000010000a28, xxx) = 0
        target_insert_breakpoint (0x00000000d03f3800, xxx) = 0
        ### Then we proceed with the step-out-of-breakpoint...
        infrun: resume (step=1, signal=GDB_SIGNAL_0), trap_expected=1, current thread [process 15335610] at 0x10000a24
        ### That's when we insert the SSS breakpoints...
        target_insert_breakpoint (0x0000000010000a28, xxx) = 0
        target_insert_breakpoint (0x00000000100009ac, xxx) = 0
        ### ... then let the inferior resume...
        target_resume (15335610, continue, 0)
        infrun: wait_for_inferior ()
        target_wait (-1, status, options={}) = 15335610,   status->kind = stopped, signal = GDB_SIGNAL_TRAP
        infrun: target_wait (-1, status) =
        infrun:   15335610 [process 15335610],
        infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
        infrun: infwait_normal_state
        infrun: TARGET_WAITKIND_STOPPED
        infrun: stop_pc = 0x100009ac
        ### At this point, we stopped at the second SSS breakpoint...
        target_stopped_by_watchpoint () = 0
        ### We remove the SSS breakpoints...
        target_remove_breakpoint (0x0000000010000a28, xxx) = 0
        target_remove_breakpoint (0x00000000100009ac, xxx) = 0
        target_stopped_by_watchpoint () = 0
        ### We find that we're not done, so we resume....
        infrun: no stepping, continue
        ### And thus insert the user breakpoints again, except we're not
        ### inserting the second breakpoint?!?
        target_insert_breakpoint (0x0000000010000a24, xxx) = 0
        infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 15335610] at 0x100009ac
        target_resume (-1, continue, 0)
        infrun: prepare_to_wait
        target_wait (-1, status, options={}) = 15335610,   status->kind = exited, status = 2
    
    What happens is that the removal of the software single-step
    breakpoints effectively removed the breakpoint instruction from
    inferior memory.  But because such breakpoints are inserted directly
    as raw breakpoints rather than through the normal chain of
    breakpoints, we fail to notice that one of the user breakpoints points
    to the same address and that this user breakpoint is therefore
    effectively un-inserted.  When resuming after the single-step, GDB
    thinks that the user breakpoint is still inserted and therefore does
    not need to insert it again.
    
    This patch teaches the insert and remove routines of both regular and
    raw breakpoints to be aware of each other.  Special care needs to be
    applied in case the target supports evaluation of breakpoint
    conditions or commands.
    
    gdb/ChangeLog:
    
    	PR breakpoints/17000
    	* breakpoint.c (find_non_raw_software_breakpoint_inserted_here):
    	New function, extracted from software_breakpoint_inserted_here_p.
    	(software_breakpoint_inserted_here_p): Replace factored out code
    	by call to find_non_raw_software_breakpoint_inserted_here.
    	(bp_target_info_copy_insertion_state): New function.
    	(bkpt_insert_location): Handle the case of a single-step
    	breakpoint already inserted at the same address.
    	(bkpt_remove_location): Handle the case of a single-step
    	breakpoint still inserted at the same address.
    	(deprecated_insert_raw_breakpoint): Handle the case of non-raw
    	breakpoint already inserted at the same address.
    	(deprecated_remove_raw_breakpoint): Handle the case of a
    	non-raw breakpoint still inserted at the same address.
    	(find_single_step_breakpoint): New function, extracted from
    	single_step_breakpoint_inserted_here_p.
    	(find_single_step_breakpoint): New function,
    	factored out from single_step_breakpoint_inserted_here_p.
    	(single_step_breakpoint_inserted_here_p): Reimplement.
    
    gdb/testsuite/ChangeLog:
    
    	PR breakpoints/17000
    	* gdb.base/sss-bp-on-user-bp.exp: Remove kfail.
    	* gdb.base/sss-bp-on-user-bp-2.exp: Remove kfail.
    
    Tested on ppc-aix with AdaCore's testsuite.  Tested on x86_64-linux,
    (native and gdbserver) with the official testsuite.  Also tested on
    x86_64-linux through Pedro's branch enabling software single-stepping
    on that platform (native and gdbserver).

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

Summary of changes:
 gdb/ChangeLog                                  |   23 ++++
 gdb/breakpoint.c                               |  141 +++++++++++++++++++++---
 gdb/testsuite/ChangeLog                        |    7 +
 gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.exp |    1 -
 gdb/testsuite/gdb.base/sss-bp-on-user-bp.exp   |    3 +-
 5 files changed, 155 insertions(+), 20 deletions(-)
Comment 4 Pedro Alves 2014-06-03 16:52:02 UTC
Fixed.
Comment 5 cvs-commit@gcc.gnu.org 2014-06-04 12:58:57 UTC
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  03388bb71c1a1d1c613bb963f3d9287cfd100138 (commit)
      from  ac21917f6bef764c73323c8117d293b5f6c70228 (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=03388bb71c1a1d1c613bb963f3d9287cfd100138

commit 03388bb71c1a1d1c613bb963f3d9287cfd100138
Author: Yao Qi <yao@codesourcery.com>
Date:   Wed Jun 4 13:03:19 2014 +0800

    Tweak sss-bp-on-user-bp.exp
    
    sss-bp-on-user-bp.c has an assumption that write to integer can be
    compiled to a single instruction, which isn't true on some arch, such
    as arm.  This test requires setting two breakpoints on two consecutive
    instructions, so this patch is to get the address of the next
    instruction via disassemble and set the 2nd breakpoint there.  This
    approach is portable.
    
    This patch fixes the fails in sss-bp-on-user-bp.exp on arm-none-abi
    target.  There is no change in x86 test results.  I also revert the
    patch to PR breakpoints/17000, and verified that the patched
    sss-bp-on-user-bp.exp still trigger the fail on
    x86-with-software-single-step.
    
    gdb/testsuite:
    
    2014-06-04  Yao Qi  <yao@codesourcery.com>
    
    	* gdb.base/sss-bp-on-user-bp.c (main): Remove comments.
    	* gdb.base/sss-bp-on-user-bp.exp: Don't set breakpoint on
    	"set bar break here".  Get the next instruction address and
    	set breakpoint there.  Remove "bar break" from the regexp
    	patterns.

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

Summary of changes:
 gdb/testsuite/gdb.base/sss-bp-on-user-bp.c   |    4 ++--
 gdb/testsuite/gdb.base/sss-bp-on-user-bp.exp |   20 +++++++++++++++++---
 2 files changed, 19 insertions(+), 5 deletions(-)