[1/2] Fix advance/until and inline frames (PR gdb/26523)

Message ID 20200822203859.26622-2-pedro@palves.net
State New
Headers show
Series
  • Fix some advance/until issues
Related show

Commit Message

Pedro Alves Aug. 22, 2020, 8:38 p.m.
If you do "tbreak LINENO; c" to advance to an inlined function, GDB
presents the stop at the inline frame instead of at the non-artificial
stack frame:

 (gdb) list 21
 18      static inline __attribute__ ((always_inline)) int
 19      inline_func (int i)
 20      {
 21        return i + 1;
 22      }

 (gdb) tbreak 21
 Temporary breakpoint 3 at 0x55555555516f: advance.cc:21.
 (gdb) c
 Continuing.

 Temporary breakpoint 3, inline_func (i=0) at advance.cc:21
 21        return i + 1;

The logic for this is in stopped_by_user_bp_inline_frame:

 /* Loop over the stop chain and determine if execution stopped in an
    inlined frame because of a breakpoint with a user-specified
    location set at FRAME_BLOCK.  */

 static bool
 stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain)

If however, you do "advance LINENO" or "until LINENO" instead, GDB
presents the stop at the non-artificial frame:

 (gdb) advance 21
 main () at advance.cc:43
 43        i = inline_func (i);
 (gdb)

"advance" and "until" should really behave like user breakpoints here,
since their location is also user-specified.  As the comment in
gdb.base/advance.exp says, "advance <location>" is really just
syntactic sugar for "tbreak <location>; continue".

Fix this by making stopped_by_user_bp_inline_frame also consider
advance/until breakpoints.

A testcase covering this will be included in the next patch.

gdb/ChangeLog:

	PR gdb/26523
	* inline-frame.c (stopped_by_user_bp_inline_frame): Also consider
	bp_until breakpoints user-specified locations.  Update intro
	comment.
---
 gdb/inline-frame.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

-- 
2.14.5

Comments

Lancelot SIX via Gdb-patches Aug. 26, 2020, 8:12 p.m. | #1
On 2020-08-22 4:38 p.m., Pedro Alves wrote:
> If you do "tbreak LINENO; c" to advance to an inlined function, GDB

> presents the stop at the inline frame instead of at the non-artificial

> stack frame:

> 

>  (gdb) list 21

>  18      static inline __attribute__ ((always_inline)) int

>  19      inline_func (int i)

>  20      {

>  21        return i + 1;

>  22      }

> 

>  (gdb) tbreak 21

>  Temporary breakpoint 3 at 0x55555555516f: advance.cc:21.

>  (gdb) c

>  Continuing.

> 

>  Temporary breakpoint 3, inline_func (i=0) at advance.cc:21

>  21        return i + 1;

> 

> The logic for this is in stopped_by_user_bp_inline_frame:

> 

>  /* Loop over the stop chain and determine if execution stopped in an

>     inlined frame because of a breakpoint with a user-specified

>     location set at FRAME_BLOCK.  */

> 

>  static bool

>  stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain)

> 

> If however, you do "advance LINENO" or "until LINENO" instead, GDB

> presents the stop at the non-artificial frame:

> 

>  (gdb) advance 21

>  main () at advance.cc:43

>  43        i = inline_func (i);

>  (gdb)

> 

> "advance" and "until" should really behave like user breakpoints here,

> since their location is also user-specified.  As the comment in

> gdb.base/advance.exp says, "advance <location>" is really just

> syntactic sugar for "tbreak <location>; continue".

> 

> Fix this by making stopped_by_user_bp_inline_frame also consider

> advance/until breakpoints.

> 

> A testcase covering this will be included in the next patch.

> 

> gdb/ChangeLog:

> 

> 	PR gdb/26523

> 	* inline-frame.c (stopped_by_user_bp_inline_frame): Also consider

> 	bp_until breakpoints user-specified locations.  Update intro

> 	comment.

> ---

>  gdb/inline-frame.c | 6 ++++--

>  1 file changed, 4 insertions(+), 2 deletions(-)

> 

> diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c

> index c650195e570..35ceb27d9c1 100644

> --- a/gdb/inline-frame.c

> +++ b/gdb/inline-frame.c

> @@ -303,7 +303,8 @@ block_starting_point_at (CORE_ADDR pc, const struct block *block)

>  }

>  

>  /* Loop over the stop chain and determine if execution stopped in an

> -   inlined frame because of a user breakpoint set at FRAME_BLOCK.  */

> +   inlined frame because of a breakpoint with a user-specified location

> +   set at FRAME_BLOCK.  */

>  

>  static bool

>  stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain)

> @@ -312,7 +313,8 @@ stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain)

>      {

>        struct breakpoint *bpt = s->breakpoint_at;

>  

> -      if (bpt != NULL && user_breakpoint_p (bpt))

> +      if (bpt != NULL

> +	  && (user_breakpoint_p (bpt) || bpt->type == bp_until))

>  	{

>  	  bp_location *loc = s->bp_location_at;

>  	  enum bp_loc_type t = loc->loc_type;

> -- 

> 2.14.5

> 


This LGTM.

Simon

Patch

diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index c650195e570..35ceb27d9c1 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -303,7 +303,8 @@  block_starting_point_at (CORE_ADDR pc, const struct block *block)
 }
 
 /* Loop over the stop chain and determine if execution stopped in an
-   inlined frame because of a user breakpoint set at FRAME_BLOCK.  */
+   inlined frame because of a breakpoint with a user-specified location
+   set at FRAME_BLOCK.  */
 
 static bool
 stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain)
@@ -312,7 +313,8 @@  stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain)
     {
       struct breakpoint *bpt = s->breakpoint_at;
 
-      if (bpt != NULL && user_breakpoint_p (bpt))
+      if (bpt != NULL
+	  && (user_breakpoint_p (bpt) || bpt->type == bp_until))
 	{
 	  bp_location *loc = s->bp_location_at;
 	  enum bp_loc_type t = loc->loc_type;