Use containing function when reporting breakpoint location.
Commit Message
print_breakpoint_location currently uses find_pc_sect_function, which always
returns the linkage symbol. This essentially means that it skips over any
inline frames. Thus, when a breakpoint is set in an inlined function,
"info break" may report the calling function as the location of the
breakpoint.
While pedantically true, it is a little misleading to users:
(gdb) b inline_func
Breakpoint 1 at 0x400434: file test.c, line 5.
(gdb) inf br
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400434 in main at test.c:5
With this patch, print_breakpoint_location now calls a new variation of
find_pc_sect_function, find_pc_sect_containing_function, which does not
skip over inlined functions, and the breakpoint location is now reported
"correctly":
(gdb) inf br
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400434 in inline_func at test.c:5
gdb/ChangeLog
* blockframe.c (find_pc_sect_containing_function): New function.
* breakpoint.c (print_breakpoint_location): Use
find_pc_sect_containing_function to avoid skipping inline frames.
* symtab.h (find_pc_sect_containing_function): Declare.
gdb/testsuite/ChangeLog
* gdb.opt/inline-break.exp (break_info_1): New procedure.
Use break_info_1 to test "info break" for all breakpoints.
---
gdb/ChangeLog | 7 ++++
gdb/blockframe.c | 12 ++++++
gdb/breakpoint.c | 2 +-
gdb/symtab.h | 7 ++++
gdb/testsuite/ChangeLog | 5 +++
gdb/testsuite/gdb.opt/inline-break.exp | 75 ++++++++++++++++++++++++++++++++++
6 files changed, 107 insertions(+), 1 deletion(-)
@@ -1,3 +1,10 @@
+2017-MM-DD Keith Seitz <keiths@redhat.com>
+
+ * blockframe.c (find_pc_sect_containing_function): New function.
+ * breakpoint.c (print_breakpoint_location): Use
+ find_pc_sect_containing_function to avoid skipping inline frames.
+ * symtab.h (find_pc_sect_containing_function): Declare.
+
2017-03-10 Keith Seitz <keiths@redhat.com>
PR c++/8218
@@ -142,6 +142,18 @@ find_pc_sect_function (CORE_ADDR pc, struct obj_section *section)
return block_linkage_function (b);
}
+/* See description in symtab.h. */
+
+struct symbol *
+find_pc_sect_containing_function (CORE_ADDR pc, struct obj_section *section)
+{
+ const struct block *b = block_for_pc_sect (pc, section);
+
+ if (b == NULL)
+ return NULL;
+ return block_containing_function (b);
+}
+
/* Return the function containing pc value PC.
Returns 0 if function is not known.
Backward compatibility, no section */
@@ -6154,7 +6154,7 @@ print_breakpoint_location (struct breakpoint *b,
else if (loc && loc->symtab)
{
struct symbol *sym
- = find_pc_sect_function (loc->address, loc->section);
+ = find_pc_sect_containing_function (loc->address, loc->section);
if (sym)
{
uiout->text ("in ");
@@ -1336,6 +1336,13 @@ extern struct symbol *find_pc_function (CORE_ADDR);
extern struct symbol *find_pc_sect_function (CORE_ADDR, struct obj_section *);
+/* Return the function containing pc value PC in section SECTION.
+ Returns NULL if function is not known. Unlike find_pc_sect_function,
+ this function does not skip inline frames. */
+
+extern struct symbol *find_pc_sect_containing_function (CORE_ADDR,
+ struct obj_section *);
+
extern int find_pc_partial_function_gnu_ifunc (CORE_ADDR pc, const char **name,
CORE_ADDR *address,
CORE_ADDR *endaddr,
@@ -1,3 +1,8 @@
+2017-MM-DD Keith Seitz <keiths@redhat.com>
+
+ * gdb.opt/inline-break.exp (break_info_1): New procedure.
+ Use break_info_1 to test "info break" for all breakpoints.
+
2017-03-10 Keith Seitz <keiths@redhat.com>
PR c++/8128
@@ -24,6 +24,61 @@ if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
return -1
}
+# Return a string that may be used to match the output of "info break NUM".
+#
+# Optional arguments:
+#
+# source - the name of the source file
+# func - the name of the function
+# disp - the breakpoint disposition
+# enabled - breakpoint enable state
+# locs - number of locations
+# line - source line number (ignored without -source)
+
+proc break_info_1 {num args} {
+ global decimal
+
+ # Column delimiter
+ set c {[\t ]+}
+
+ # Row delimiter
+ set end {[\r\n \t]+}
+
+ # Table header
+ set header "[join [list Num Type Disp Enb Address What] ${c}]"
+
+ # Get/configure any optional parameters.
+ parse_args [list {source ""} {func ".*"} {disp "keep"} \
+ {enabled "y"} {locs 1} [list line $decimal]]
+
+ if {$source != ""} {
+ set source "/$source:$line"
+ }
+
+ # Result starts with the standard header.
+ set result "$header${end}"
+
+ # Set up for multi-location breakpoint marker.
+ if {$locs == 1} {
+ set multi ".*"
+ } else {
+ set multi "<MULTIPLE>${end}"
+ }
+ append result "[join [list $num breakpoint $disp $enabled $multi] $c]"
+
+ # Add sub-location info.
+ if {$locs > 1} {
+ for {set i 1} {$i <= $locs} {incr i} {
+ append result "[join [list $num.$i $enabled] $c].*"
+ }
+ }
+
+ # Add function/source file info.
+ append result "in $func at .*$source${end}"
+
+ return $result
+}
+
#
# func1 is a static inlined function that is called once.
# The result should be a single-location breakpoint.
@@ -111,3 +166,23 @@ gdb_test "print func1" \
#
gdb_test "print func2" \
"\\\$.* = {int \\(int\\)} .* <func2>"
+
+# Test that "info break" reports the location of the breakpoints "inside"
+# the inlined functions
+
+set i 0
+set results([incr i]) [break_info_1 1 -source $srcfile -func "func1"]
+set results([incr i]) [break_info_1 2 -locs 2 -source $srcfile -func "func2"]
+set results([incr i]) [break_info_1 3 -source $srcfile -func "func3b"]
+set results([incr i]) [break_info_1 4 -locs 2 -source $srcfile -func "func4b"]
+set results([incr i]) [break_info_1 5 -locs 2 -source $srcfile -func "func5b"]
+set results([incr i]) [break_info_1 6 -locs 3 -source $srcfile -func "func6b"]
+set results([incr i]) [break_info_1 7 -locs 2 -source $srcfile -func "func7b"]
+set results([incr i]) [break_info_1 8 -locs 3 -source $srcfile -func "func8b"]
+
+for {set i 1} {$i <= [llength [array names results]]} {incr i} {
+ send_log "Expecting: $results($i)\n"
+ gdb_test "info break $i" $results($i)
+}
+
+unset -nocomplain results