Inline breakpoints
authorPedro Alves <palves@redhat.com>
Thu, 14 Jun 2018 11:23:56 +0000 (12:23 +0100)
committerPedro Alves <palves@redhat.com>
Thu, 14 Jun 2018 11:24:39 +0000 (12:24 +0100)
gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

* inline-frame.c (stopped_by_user_bp_inline_frame): Replace PC
parameter with a block parameter.  Compare location's block symbol
with the frame's block instead of addresses.
(skip_inline_frames): Pass the current block instead of the
frame's address.  Break out as soon as we determine the frame
should not be skipped.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

* gdb.opt/inline-break.c (func_callee, func_caller): New.
(main): Call func_caller.

gdb/inline-frame.c
gdb/testsuite/gdb.opt/inline-break.c
gdb/testsuite/gdb.opt/inline-break.exp

index 1ac5835438da4577fb45bea560b7e03296824d63..3edd5b2b20b1728288a7f36ec7eb718c26c57ebb 100644 (file)
@@ -286,11 +286,10 @@ 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.  THIS_PC is the current
-   frame's PC.  */
+   inlined frame because of a user breakpoint set at FRAME_BLOCK.  */
 
 static bool
-stopped_by_user_bp_inline_frame (CORE_ADDR this_pc, bpstat stop_chain)
+stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain)
 {
   for (bpstat s = stop_chain; s != NULL; s = s->next)
     {
@@ -301,9 +300,9 @@ stopped_by_user_bp_inline_frame (CORE_ADDR this_pc, bpstat stop_chain)
          bp_location *loc = s->bp_location_at;
          enum bp_loc_type t = loc->loc_type;
 
-         if (loc->address == this_pc
-             && (t == bp_loc_software_breakpoint
-                 || t == bp_loc_hardware_breakpoint))
+         if ((t == bp_loc_software_breakpoint
+              || t == bp_loc_hardware_breakpoint)
+             && frame_block == SYMBOL_BLOCK_VALUE (loc->symbol))
            return true;
        }
     }
@@ -340,12 +339,12 @@ skip_inline_frames (ptid_t ptid, bpstat stop_chain)
                {
                  /* Do not skip the inlined frame if execution
                     stopped in an inlined frame because of a user
-                    breakpoint.  */
-                 if (!stopped_by_user_bp_inline_frame (this_pc, stop_chain))
-                   {
-                     skip_count++;
-                     last_sym = BLOCK_FUNCTION (cur_block);
-                   }
+                    breakpoint for this inline function.  */
+                 if (stopped_by_user_bp_inline_frame (cur_block, stop_chain))
+                   break;
+
+                 skip_count++;
+                 last_sym = BLOCK_FUNCTION (cur_block);
                }
              else
                break;
index 922102debb696791f53e32d11c4a3e2d8ef5082b..351b983524ab3951c9f59ad61677446e61c0fcdd 100644 (file)
@@ -176,6 +176,25 @@ not_inline_func3 (int x)
   return y + inline_func3 (x);
 }
 
+/* A static inlined function that is called by another static inlined
+   function.  */
+
+static inline ATTR int
+func_callee (int x)
+{
+  return x * 23;
+}
+
+/* A static inlined function that calls another static inlined
+   function.  The body of the function is as simple as possible so
+   that both functions are inlined to the same PC address.  */
+
+static int
+func_caller (int x)
+{
+  return func_callee (x);
+}
+
 /* Entry point.  */
 
 int
@@ -205,5 +224,7 @@ main (int argc, char *argv[])
 
   x = not_inline_func3 (-21);
 
+  func_caller (1);
+
   return x;
 }
index 008ff1ac33ac0cf2d9601eff6b04126a8961466f..f1ab3d23715c477e40134d9dc09fa1e4e67eaa8a 100644 (file)
@@ -231,4 +231,21 @@ foreach_with_prefix cmd [list "break" "tbreak"] {
     }
 }
 
+# func_caller and func_callee are both inline functions, and one calls
+# the other.  Test that setting a breakpoint on the caller reports the
+# stop at the caller, and that setting a breakpoint at the callee
+# reports a stop at the callee.
+foreach_with_prefix func {"func_callee" "func_caller"} {
+    clean_restart $binfile
+
+    if {![runto main]} {
+       untested "could not run to main"
+       continue
+    }
+
+    gdb_breakpoint $func
+    gdb_test "continue" "Breakpoint .* $func .*at .*$srcfile.*" \
+       "continue to inline function"
+}
+
 unset -nocomplain results