aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/inline-frame.c23
-rw-r--r--gdb/testsuite/ChangeLog8
-rw-r--r--gdb/testsuite/gdb.opt/inline-break.c34
-rw-r--r--gdb/testsuite/gdb.opt/inline-break.exp25
5 files changed, 87 insertions, 12 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7b108bf..93703fd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@
+2018-06-19 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.
+
2018-06-18 Tom Tromey <tom@tromey.com>
* solib-aix.c (solib_aix_get_section_offsets): Return
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index 1ac5835..3edd5b2 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -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;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 358474b..a8f99b8 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2018-06-19 Pedro Alves <palves@redhat.com>
+
+ * gdb.opt/inline-break.c (func_inline_callee, func_inline_caller)
+ (func_extern_caller): New.
+ (main): Call func_extern_caller.
+ * gdb.opt/inline-break.exp: Add tests for inline frame skipping
+ logic change.
+
2018-06-18 Weimin Pan <weimin.pan@oracle.com>
PR gdb/16841
diff --git a/gdb/testsuite/gdb.opt/inline-break.c b/gdb/testsuite/gdb.opt/inline-break.c
index 922102d..f64a81a 100644
--- a/gdb/testsuite/gdb.opt/inline-break.c
+++ b/gdb/testsuite/gdb.opt/inline-break.c
@@ -176,6 +176,38 @@ not_inline_func3 (int x)
return y + inline_func3 (x);
}
+/* The following three functions serve to exercise GDB's inline frame
+ skipping logic when setting a user breakpoint on an inline function
+ by name. */
+
+/* A static inlined function that is called by another static inlined
+ function. */
+
+static inline ATTR int
+func_inline_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 inline ATTR int
+func_inline_caller (int x)
+{
+ return func_inline_callee (x);
+}
+
+/* An extern not-inline function that calls a static inlined
+ function. */
+
+int
+func_extern_caller (int x)
+{
+ return func_inline_caller (x);
+}
+
/* Entry point. */
int
@@ -205,5 +237,7 @@ main (int argc, char *argv[])
x = not_inline_func3 (-21);
+ func_extern_caller (1);
+
return x;
}
diff --git a/gdb/testsuite/gdb.opt/inline-break.exp b/gdb/testsuite/gdb.opt/inline-break.exp
index 008ff1a..bae7625 100644
--- a/gdb/testsuite/gdb.opt/inline-break.exp
+++ b/gdb/testsuite/gdb.opt/inline-break.exp
@@ -231,4 +231,29 @@ foreach_with_prefix cmd [list "break" "tbreak"] {
}
}
+# func_extern_caller calls func_inline_caller which calls
+# func_inline_callee. The latter two are both inline functions. Test
+# that setting a breakpoint on each of the functions reports a stop at
+# that function. This exercises the inline frame skipping logic. If
+# we set a breakpoint at function A, we want to present the stop at A,
+# even if A's entry code is an inlined call to another inline function
+# B.
+
+foreach_with_prefix func {
+ "func_extern_caller"
+ "func_inline_caller"
+ "func_inline_callee"
+} {
+ clean_restart $binfile
+
+ if {![runto main]} {
+ untested "could not run to main"
+ continue
+ }
+
+ gdb_breakpoint $func
+ gdb_test "continue" "Breakpoint .* $func .*at .*$srcfile.*" \
+ "breakpoint hit presents stop at breakpointed function"
+}
+
unset -nocomplain results