diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7b108bf5b5..93703fdcb3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2018-06-19 Pedro Alves + + * 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 * solib-aix.c (solib_aix_get_section_offsets): Return diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c index 1ac5835438..3edd5b2b20 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 358474b1e3..a8f99b8c70 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2018-06-19 Pedro Alves + + * 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 PR gdb/16841 diff --git a/gdb/testsuite/gdb.opt/inline-break.c b/gdb/testsuite/gdb.opt/inline-break.c index 922102debb..f64a81af93 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 008ff1ac33..bae7625490 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