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]

[binutils-gdb] Fix running to breakpoint set in inline function by lineno/address


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

commit 991ff2922affa0b3afb837d2246d01f0c1fdb364
Author: Pedro Alves <palves@redhat.com>
Date:   Fri Jun 29 19:31:49 2018 +0100

    Fix running to breakpoint set in inline function by lineno/address
    
    Commit 61b04dd04ac2 ("Change inline frame breakpoint skipping logic
    (fix gdb.gdb/selftest.exp)") caused a GDB crash when you set a
    breakpoint by line number in an inline function, and then run to the
    breakpoint:
    
        $ gdb -q test Reading symbols from test...done.
        (gdb) b inline-break.c:32
        Breakpoint 1 at 0x40062f: file inline-break.c, line 32.
        (gdb) run
        Starting program: /[...]/test
        [1]    75618 segmentation fault  /[...]/gdb -q test
    
    The problem occurs because we assume that a bp_location's symbol is
    not NULL, which is not true when we set the breakpoint with a linespec
    location:
    
        Program received signal SIGSEGV, Segmentation fault.
        0x00000000006f42bb in stopped_by_user_bp_inline_frame (
            stop_chain=<optimized out>, frame_block=<optimized out>)
            at gdb/inline-frame.c:305
        305		      && frame_block == SYMBOL_BLOCK_VALUE (loc->symbol))
        (gdb) p loc->symbol
        $1 = (const symbol *) 0x0
    
    The same thing happens if you run to a breakpoint set in an inline
    function by address:
    
      (gdb) b *0x40062f
      Breakpoint 3 at 0x40062f: file inline-break.c, line 32.
    
    To fix this, add a null pointer check, to avoid the crash, and make it
    so that if there's no symbol for the location, then we present the
    stop at the inline function.  This preserves the previous behavior
    when e.g., setting a breakpoint by address, with "b *ADDRESS".
    
    gdb/ChangeLog:
    2018-06-29  Pedro Alves  <palves@redhat.com>
    
    	* inline-frame.c (stopped_by_user_bp_inline_frame): Return
    	true if the the location has no symbol.
    
    gdb/testsuite/ChangeLog:
    2018-06-29  Pedro Alves  <palves@redhat.com>
    
    	* gdb.opt/inline-break.c (func1): Add "break here" marker.
    	* gdb.opt/inline-break.exp: Test setting breakpoints by line
    	number and address and running to them.

Diff:
---
 gdb/ChangeLog                          |  5 ++++
 gdb/inline-frame.c                     | 16 +++++++++----
 gdb/testsuite/ChangeLog                |  6 +++++
 gdb/testsuite/gdb.opt/inline-break.c   |  2 +-
 gdb/testsuite/gdb.opt/inline-break.exp | 42 ++++++++++++++++++++++++++++++++++
 5 files changed, 66 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4c04d0b..3ed5cf3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2018-06-29  Pedro Alves  <palves@redhat.com>
+
+	* inline-frame.c (stopped_by_user_bp_inline_frame): Return
+	true if the the location has no symbol.
+
 2018-06-28  Tom Tromey  <tom@tromey.com>
 
 	* NEWS: Mention --enable-codesign.
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index 896b000..c6caf9d 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -300,10 +300,18 @@ stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain)
 	  bp_location *loc = s->bp_location_at;
 	  enum bp_loc_type t = loc->loc_type;
 
-	  if ((t == bp_loc_software_breakpoint
-	       || t == bp_loc_hardware_breakpoint)
-	      && frame_block == SYMBOL_BLOCK_VALUE (loc->symbol))
-	    return true;
+	  if (t == bp_loc_software_breakpoint
+	      || t == bp_loc_hardware_breakpoint)
+	    {
+	      /* If the location has a function symbol, check whether
+		 the frame was for that inlined function.  If it has
+		 no function symbol, then assume it is.  I.e., default
+		 to presenting the stop at the innermost inline
+		 function.  */
+	      if (loc->symbol == nullptr
+		  || frame_block == SYMBOL_BLOCK_VALUE (loc->symbol))
+		return true;
+	    }
 	}
     }
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index d16f33a..3d93d32 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2018-06-29  Pedro Alves  <palves@redhat.com>
+
+	* gdb.opt/inline-break.c (func1): Add "break here" marker.
+	* gdb.opt/inline-break.exp: Test setting breakpoints by line
+	number and address and running to them.
+
 2018-06-29  Richard Bunt  <richard.bunt@arm.com>
 
 	* gdb.base/watchpoint-hw-attach.exp: Remove unstable output.
diff --git a/gdb/testsuite/gdb.opt/inline-break.c b/gdb/testsuite/gdb.opt/inline-break.c
index f64a81a..d477929 100644
--- a/gdb/testsuite/gdb.opt/inline-break.c
+++ b/gdb/testsuite/gdb.opt/inline-break.c
@@ -29,7 +29,7 @@
 static inline ATTR int
 func1 (int x)
 {
-  return x * 23;
+  return x * 23; /* break here */
 }
 
 /* A non-static inlined function that is called once.  */
diff --git a/gdb/testsuite/gdb.opt/inline-break.exp b/gdb/testsuite/gdb.opt/inline-break.exp
index bae7625..46ef6f1 100644
--- a/gdb/testsuite/gdb.opt/inline-break.exp
+++ b/gdb/testsuite/gdb.opt/inline-break.exp
@@ -256,4 +256,46 @@ foreach_with_prefix func {
 	"breakpoint hit presents stop at breakpointed function"
 }
 
+# Test setting a breakpoint in an inline function by line number and
+# by address, and that GDB presents the stop there.
+
+set line [gdb_get_line_number "break here"]
+
+with_test_prefix "line number" {
+    clean_restart $binfile
+
+    if {![runto main]} {
+	untested "could not run to main"
+	continue
+    }
+
+    # Set the breakpoint by line number, and check that GDB reports
+    # the breakpoint location being the inline function.
+    gdb_test "break $srcfile:$line" ".*Breakpoint .* at .*: file .*$srcfile, line $line."
+    gdb_test "continue" "Breakpoint .*, func1 \\(x=1\\) at .*$srcfile:$line.*break here.*" \
+	"breakpoint hit presents stop at inlined function"
+
+    # Save the PC for the following by-address test.
+    set address [get_hexadecimal_valueof "\$pc" "0"]
+}
+
+# Test setting a breakpoint in an inline function by address, and that
+# GDB presents the stop there.
+
+with_test_prefix "address" {
+
+    clean_restart $binfile
+
+    if {![runto main]} {
+	untested "could not run to main"
+	continue
+    }
+
+    # Set the breakpoint by address, and check that GDB reports the
+    # breakpoint location being the inline function.
+    gdb_test "break *$address" ".*Breakpoint .* at $address: file .*$srcfile, line $line."
+    gdb_test "continue" "Breakpoint .*, func1 \\(x=1\\) at .*$srcfile:$line.*break here.*" \
+	"breakpoint hit presents stop at inlined function"
+}
+
 unset -nocomplain results


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