Re: [patch] Fix internal error on breaking at a multi-locations caller

Jan Kratochvil
2009-05-01T17:32:49Z

On Fri, 01 May 2009 17:47:59 +0200, Joel Brobecker wrote:
> I think Tom must be pretty busy right now :),

I have no news on that issue. :-)

> Based on that, "break" in my opinion should be equivalent to "break *PC"
> where PC is the current frame's PC. So, I think that the correct way
> to fix this is to set the "explicit_pc" flag in the sal.

Attached. If you do not agree with the fix credit I am willing to fully
accept it as I agree with this change.

> I also understand the reason why you think a warning might help,
> especially since I had a different intuitive perception of what
> the argument-less command was doing.

As I was surprised of the change requested by Tom Tromey I share the feeling
there is no agreement on the intuitive expectation on side-effects of the
parameter-less `break' command.

> But I think that such a warning would quickly become more annoying than
> anything if the user knows precisely the meaning of his command.

Just my general opinion on this matter: In such cases there should be a GDB
variable to turn it off in the power user's `~/.gdbinit' file. Reading the
GDB manual should not be a prerequisite for starting GDB.

> Nonetheless, I think we can treat the two issues separately. We can
> fix the problem first with a one-liner, and then we can discuss the
> idea of a warning if you think it might be useful.

As I found out in this discussion it is not clear what the side-effects should
be and as I do not think newbie GDB users are aware the parameter-less `break'
command feature exists at all I no longer have any objections.

Regression tested on x86_64-unknown-linux-gnu.

Thanks,
Jan

gdb/
2009-05-01 Joel Brobecker <brobecker@adacore.com>
Jan Kratochvil <jan.kratochvil@redhat.com>

Fix internal error on breaking at a multi-locations caller source line.
* breakpoint.c (parse_breakpoint_sals): Set EXPLICIT_PC for the `break'
command with no parameters.

gdb/testsuite/
2009-05-01 Jan Kratochvil <jan.kratochvil@redhat.com>

* gdb.cp/expand-sals.exp, gdb.cp/expand-sals.cc: New.

--- gdb/breakpoint.c 29 Apr 2009 19:31:58 -0000 1.392
+++ gdb/breakpoint.c 1 May 2009 16:45:49 -0000
@@ -5488,6 +5475,13 @@ parse_breakpoint_sals (char **address,
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
sal.section = find_pc_overlay (sal.pc);
+
+ /* In the case of breaking at the caller line (right after the
+ calling instruction) GDB should use neither the first instruction
+ of the source line (before the calling instruction) nor any other
+ existing locations (function instances) for that source line. */
+ sal.explicit_pc = 1;
+
sals->sals[0] = sal;
sals->nelts = 1;
}
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.cp/expand-sals.cc 1 May 2009 16:45:50 -0000
@@ -0,0 +1,53 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+func ()
+{
+ return 42; /* func-line */
+}
+
+volatile int global_x;
+
+class A
+{
+public:
+ A ()
+ {
+ global_x = func (); /* caller-line */
+ }
+};
+
+/* class B is here just to make the `func' calling line above having multiple
+ instances - multiple locations. Template cannot be used as its instances
+ would have different function names which get discarded by GDB
+ expand_line_sal_maybe. */
+
+class B : public A
+{
+};
+
+int
+main (void)
+{
+ A a;
+ B b;
+
+ return 0; /* exit-line */
+}
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.cp/expand-sals.exp 1 May 2009 16:45:50 -0000
@@ -0,0 +1,83 @@
+# Copyright 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+if { [skip_cplus_tests] } { continue }
+
+set srcfile expand-sals.cc
+if { [prepare_for_testing expand-sals.exp expand-sals $srcfile {debug c++}] } {
+ return -1
+}
+if ![runto_main] {
+ return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "exit-line"]
+
+gdb_breakpoint [gdb_get_line_number "func-line"]
+gdb_continue_to_breakpoint "func" ".*func-line.*"
+
+gdb_test "up" "caller-line.*"
+
+# PC should not be at the boundary of source lines to make the original bug
+# exploitable.
+
+set test "p/x \$pc"
+set pc {}
+gdb_test_multiple $test $test {
+ -re "\\$\[0-9\]+ = (0x\[0-9a-f\]+)\r\n$gdb_prompt $" {
+ set pc $expect_out(1,string)
+ pass $test
+ }
+}
+
+set test "info line"
+set end {}
+gdb_test_multiple $test $test {
+ -re "Line \[0-9\]+ of .* starts at address 0x\[0-9a-f\]+.* and ends at (0x\[0-9a-f\]+).*\\.\r\n$gdb_prompt $" {
+ set end $expect_out(1,string)
+ pass $test
+ }
+}
+
+set test "caller line has trailing code"
+if {$pc != $end} {
+ pass $test
+} else {
+ fail $test
+}
+
+# Original problem was an internal error here.
+set test "break"
+gdb_test_multiple $test $test {
+ -re "Breakpoint \[0-9\]+ at .*, line \[0-9\]+\\. \\(\[2-9\] locations\\)\r\n$gdb_prompt $" {
+ fail $test
+ }
+ -re "Breakpoint \[0-9\]+ at .*, line \[0-9\]+\\.\r\n$gdb_prompt $" {
+ pass $test
+ }
+}
+
+gdb_continue_to_breakpoint "caller" ".*caller-line.*"
+
+# Test GDB caught this return call and not the next one through B::B()
+gdb_test "bt" \
+ "#0 \[^\r\n\]* A \[^\r\n\]*\r\n#1 \[^\r\n\]* main \[^\r\n\]*" \
+ "bt from A"
+
+gdb_continue_to_breakpoint "next caller func" ".*func-line.*"
+
+# Verify GDB really could not catch any other breakpoint location.
+
+gdb_continue_to_breakpoint "uncaught return" ".*exit-line.*"