* [patch] Fix internal error on breaking at a multi-locations caller
@ 2009-03-09 22:17 Jan Kratochvil
2009-04-24 1:01 ` Tom Tromey
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kratochvil @ 2009-03-09 22:17 UTC (permalink / raw)
To: gdb-patches
Hi,
patch deals with break after `up' into the caller where the caller line has
multiple locations (instances). Discussion is contained in the code.
Original bugreport at: https://bugzilla.redhat.com/show_bug.cgi?id=488572
No regressions on x86_64-unknown-linux-gnu.
Thanks,
Jan
gdb/
2009-03-09 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix internal error on breaking at a multi-locations caller source line.
* breakpoint.c (expand_line_sal_maybe): Remove the variable `found'.
(expand_line_sal_maybe <original_pc && expanded.nelts >= 2>): New
initialized variable `best'. Set `expanded.sals[best].pc'. New
comment.
gdb/testsuite/
2009-03-09 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.cp/expand-sals.exp, gdb.cp/expand-sals.cc: New.
--- gdb/breakpoint.c 6 Mar 2009 18:51:05 -0000 1.382
+++ gdb/breakpoint.c 9 Mar 2009 21:55:50 -0000
@@ -5189,7 +5189,6 @@ expand_line_sal_maybe (struct symtab_and
struct symtabs_and_lines expanded;
CORE_ADDR original_pc = sal.pc;
char *original_function = NULL;
- int found;
int i;
/* If we have explicit pc, don't expand.
@@ -5265,14 +5264,42 @@ expand_line_sal_maybe (struct symtab_and
if (original_pc)
{
- found = 0;
+ /* Find all the other PCs for a line of code with multiple instances
+ (locations). If the instruction is in the middle of an instruction
+ block for source line GDB cannot safely find the same instruction in
+ the other compiled instances of the same source line because the other
+ instances may have been compiled completely differently.
+
+ The testcase gdb.cp/expand-sals.exp shows that breaking at the return
+ address in a caller of the current frame works for the current
+ instance but the breakpoint cannot catch the point (instruction) where
+ the callee returns in the other compiled instances of this source line.
+
+ The current implementation will place the breakpoint at the expected
+ returning address of the current instance of the caller. But the
+ other instances will get the breakpoint at the first instruction of
+ the source line - therefore before the call would be made. Another
+ possibility would be to place the breakpoint in the other instances at
+ the start of the next source line.
+
+ A possible heuristics would compare the instructions length of each of
+ the instances of the current source line and if it matches it would
+ place the breakpoint at the same offset. Unfortunately a mistaken
+ guess would possibly crash the inferior. */
+
+ CORE_ADDR best = -1;
+
+ /* Find the nearest preceding PC and set it to ORIGINAL_PC. */
for (i = 0; i < expanded.nelts; ++i)
- if (expanded.sals[i].pc == original_pc)
- {
- found = 1;
- break;
- }
- gdb_assert (found);
+ if (expanded.sals[i].pc <= original_pc
+ && (best == -1 || expanded.sals[best].pc < expanded.sals[i].pc))
+ best = i;
+
+ if (best == -1)
+ error (_("Cannot find the best address for %s out of the %d locations"),
+ paddr (original_pc), expanded.nelts);
+
+ expanded.sals[best].pc = original_pc;
}
return expanded;
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.cp/expand-sals.cc 9 Mar 2009 21:55:51 -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 9 Mar 2009 21:55:51 -0000
@@ -0,0 +1,100 @@
+# 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. Still sanity multiple locations
+# were found at this code place as otherwise this test would not test anything.
+set test "break"
+gdb_test_multiple $test $test {
+ -re "Breakpoint \[0-9\]+ at .*, line \[0-9\]+\\. \\(\[2-9\] locations\\)\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re "Breakpoint \[0-9\]+ at .*, line \[0-9\]+\\.\r\n$gdb_prompt $" {
+ # It just could not be decided if GDB is OK by this testcase.
+ setup_xfail *-*-*
+ fail $test
+ return 0
+ }
+}
+
+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 instance" ".*caller-line.*"
+
+# Test that GDB caught now already A through B::B() in the other instance.
+# As discussed in GDB expand_line_sal_maybe it would more match the original
+# instance behavior to catch here the `func' breakpoint and catch the
+# multiple-locations breakpoint only during the call return. This is not the
+# case, expecting here to catch the breakpoint before the call happens.
+
+gdb_test "bt" \
+ "#0 \[^\r\n\]* A \[^\r\n\]*\r\n#1 \[^\r\n\]* B \[^\r\n\]*\r\n#2 \[^\r\n\]* main \[^\r\n\]*" \
+ "bt from B before the call"
+
+gdb_continue_to_breakpoint "next caller func" ".*func-line.*"
+
+# Verify GDB really could not catch the originally intended point of the return
+# from func.
+
+gdb_continue_to_breakpoint "uncaught return" ".*exit-line.*"
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-03-09 22:17 [patch] Fix internal error on breaking at a multi-locations caller Jan Kratochvil
@ 2009-04-24 1:01 ` Tom Tromey
2009-04-28 20:32 ` Joel Brobecker
0 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2009-04-24 1:01 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches
>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
Jan> patch deals with break after `up' into the caller where the caller line has
Jan> multiple locations (instances). Discussion is contained in the code.
Jan> Original bugreport at: https://bugzilla.redhat.com/show_bug.cgi?id=488572
Thanks.
Jan> + /* Find all the other PCs for a line of code with multiple instances
Jan> + (locations). If the instruction is in the middle of an instruction
Jan> + block for source line GDB cannot safely find the same instruction in
Jan> + the other compiled instances of the same source line because the other
Jan> + instances may have been compiled completely differently.
[...]
Jan> + The current implementation will place the breakpoint at the expected
Jan> + returning address of the current instance of the caller. But the
Jan> + other instances will get the breakpoint at the first instruction of
Jan> + the source line - therefore before the call would be made. Another
Jan> + possibility would be to place the breakpoint in the other instances at
Jan> + the start of the next source line.
Based on the documentation of `break', and also my mental model of
debugging with gdb, I think that the best behavior here would be to
simply set a single breakpoint here -- the one corresponding to the
instance that is currently being executed. Then we don't have to
worry about the other instances, and we won't set odd breakpoints
elsewhere.
What do you (or anybody) think of that?
Tom
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-04-24 1:01 ` Tom Tromey
@ 2009-04-28 20:32 ` Joel Brobecker
2009-05-01 9:20 ` Jan Kratochvil
0 siblings, 1 reply; 10+ messages in thread
From: Joel Brobecker @ 2009-04-28 20:32 UTC (permalink / raw)
To: Tom Tromey; +Cc: Jan Kratochvil, gdb-patches
> Based on the documentation of `break', and also my mental model of
> debugging with gdb, I think that the best behavior here would be to
> simply set a single breakpoint here -- the one corresponding to the
> instance that is currently being executed. Then we don't have to
> worry about the other instances, and we won't set odd breakpoints
> elsewhere.
>
> What do you (or anybody) think of that?
That's a good point. I actually had a different interpretation
of the "break" command without arguments, but the documentation
is very specific about it. I agree with you.
--
Joel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-04-28 20:32 ` Joel Brobecker
@ 2009-05-01 9:20 ` Jan Kratochvil
2009-05-01 15:48 ` Joel Brobecker
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kratochvil @ 2009-05-01 9:20 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches
> On Fri, 24 Apr 2009 03:00:50 +0200, Tom Tromey wrote:
> > Based on the documentation of `break', and also my mental model of
> > debugging with gdb, I think that the best behavior here would be to
> > simply set a single breakpoint here -- the one corresponding to the
> > instance that is currently being executed.
info '(gdb)Set Breaks'
`break'
When called without any arguments, `break' sets a breakpoint at
the next instruction to be executed in the selected stack frame
[...]
Do you refer here to the "selected stack frame" part of the doc?
On Tue, 28 Apr 2009 22:32:35 +0200, Joel Brobecker wrote:
> That's a good point. I actually had a different interpretation
> of the "break" command without arguments, but the documentation
> is very specific about it. I agree with you.
Attaching here such a patch variant; it at least prints a warning in such case.
Regression tested on x86_64-unknown-linux-gnu.
Thanks,
Jan
gdb/
2009-05-01 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix internal error on breaking at a multi-locations caller source line.
* breakpoint.c (expand_line_sal_maybe): Remove the variable `found'.
(expand_line_sal_maybe <original_pc && expanded.nelts >= 2>): New
initialized variable `best'. Trim `expanded.sals' for the caller lines.
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 08:54:09 -0000
@@ -5336,7 +5336,6 @@ expand_line_sal_maybe (struct symtab_and
struct symtabs_and_lines expanded;
CORE_ADDR original_pc = sal.pc;
char *original_function = NULL;
- int found;
int i;
/* If we have explicit pc, don't expand.
@@ -5412,14 +5411,56 @@ expand_line_sal_maybe (struct symtab_and
if (original_pc)
{
- found = 0;
+ /* There are multiple PCs for this line of code with multiple instances
+ (locations). If the instruction is in the middle of an instruction
+ block for source line GDB cannot safely find the same instruction in
+ the other compiled instances of the same source line because the other
+ instances may have been compiled completely differently.
+
+ The testcase gdb.cp/expand-sals.exp shows that breaking at the return
+ address in a caller of the current frame works for the current
+ instance but the breakpoint cannot catch the point (instruction) where
+ the callee returns in the other compiled instances of this source line.
+
+ The current implementation will place the breakpoint at the expected
+ returning address of the current instance of the caller. But the
+ other instances get no breakpoint at all.
+
+ One possibility would be to put the breakpoint at first instruction of
+ the same source line - therefore before the call would be made.
+ Another possibility would be to place the breakpoint in the other
+ instances at the start of the next source line.
+
+ A possible heuristics would compare the instructions length of each of
+ the instances of the current source line and if it matches it would
+ place the breakpoint at the same offset. Unfortunately a mistaken
+ guess would possibly crash the inferior. */
+
+ CORE_ADDR best = -1;
+
+ /* Find the nearest preceding PC and set it to ORIGINAL_PC. */
for (i = 0; i < expanded.nelts; ++i)
- if (expanded.sals[i].pc == original_pc)
- {
- found = 1;
- break;
- }
- gdb_assert (found);
+ if (expanded.sals[i].pc <= original_pc
+ && (best == -1 || expanded.sals[best].pc < expanded.sals[i].pc))
+ best = i;
+
+ if (best == -1)
+ error (_("Cannot find the best address for %s out of the %d locations"),
+ paddr (original_pc), expanded.nelts);
+
+ /* ORIGINAL_PC is set even for regular `break LINENO' commands which
+ should cover all the locations. Catch specifically the
+ `up'-into-caller case where SAL.PC does not match the first
+ instruction of the line but still SAL.EXPLICIT_PC is not set. */
+
+ if (expanded.sals[best].pc != original_pc)
+ {
+ warning (_("Breakpoint has been set only in the current location "
+ "out of %d existing ones for this line."), expanded.nelts);
+ expanded.sals[best].pc = original_pc;
+ expanded.sals[0] = expanded.sals[best];
+ expanded.nelts = 1;
+ }
}
return expanded;
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.cp/expand-sals.cc 1 May 2009 08:54:10 -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 08:54:10 -0000
@@ -0,0 +1,86 @@
+# 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 "warning: Breakpoint has been set only in the current location out of 2 existing ones for this line\\.\r\nBreakpoint \[0-9\]+ at .*, line \[0-9\]+\\.\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re "Breakpoint \[0-9\]+ at .*, line \[0-9\]+\\.\r\n$gdb_prompt $" {
+ fail $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.*"
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-05-01 9:20 ` Jan Kratochvil
@ 2009-05-01 15:48 ` Joel Brobecker
2009-05-01 17:32 ` Jan Kratochvil
0 siblings, 1 reply; 10+ messages in thread
From: Joel Brobecker @ 2009-05-01 15:48 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: Tom Tromey, gdb-patches
Hello Jan,
I think Tom must be pretty busy right now :), so here is my take on this.
> info '(gdb)Set Breaks'
> `break'
> When called without any arguments, `break' sets a breakpoint at
> the next instruction to be executed in the selected stack frame
> [...]
>
> Do you refer here to the "selected stack frame" part of the doc?
More importantly: "next instruction"; but yes, the selected stack
frame is also important.
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. That should
make sure that expand_line_sal_maybe does not, in fact, do any expansion.
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. But I think that such a warning
would quickly become more annoying than anything if the user knows
precisely the meaning of his command. What do others think?
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. Does this sound
reasonable to you?
--
Joel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-05-01 15:48 ` Joel Brobecker
@ 2009-05-01 17:32 ` Jan Kratochvil
2009-05-06 16:51 ` Joel Brobecker
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kratochvil @ 2009-05-01 17:32 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches
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.*"
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-05-01 17:32 ` Jan Kratochvil
@ 2009-05-06 16:51 ` Joel Brobecker
2009-05-10 18:33 ` Jan Kratochvil
0 siblings, 1 reply; 10+ messages in thread
From: Joel Brobecker @ 2009-05-06 16:51 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: Tom Tromey, gdb-patches
Hi 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.
The code part is OK, but I was a little confused by the comment.
I think this is because you're talking about your specific scenario
whereas I'm ready to bet that the issue can appear without doing
an "up" before. My suggestion is to keep it general, but saying
something like: "break" without arguments is equivalent to "break *PC"
where PC is the default_breakpoint_address. So make sure to set
sal.explicit_pc to prevent GDB from trying to expand the list of
sals to include all other instances with the same symtab and 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
> +}
I don't think this is right - the fail here is conditional on the code
generated by the compiler on the given platform. If the return address
points at the beginning of the next line of code, then our testcase
won't allow us to test the issue. But there's no real failure
demonstrated at this point.
My feeling on this is that we should just do the testing you do after
without worrying whether the break address is at the beginning of
a line or not. So I'd just ditch the above, and keep the rest of
the testcase as is.
--
Joel
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-05-06 16:51 ` Joel Brobecker
@ 2009-05-10 18:33 ` Jan Kratochvil
2009-05-11 9:11 ` Joel Brobecker
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kratochvil @ 2009-05-10 18:33 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches
Hi Joel,
still requesting approval now just for the ChangeLog entry.
On Wed, 06 May 2009 18:51:43 +0200, Joel Brobecker wrote:
> The code part is OK, but I was a little confused by the comment.
I agree my comment was misleading, used now yours.
> > +# 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
> > +}
>
> I don't think this is right - the fail here is conditional on the code
> generated by the compiler on the given platform. If the return address
> points at the beginning of the next line of code, then our testcase
> won't allow us to test the issue. But there's no real failure
> demonstrated at this point.
I agree just chose it as the least worse way out: FAIL did mean a bug in the
testcase itself as it did not force the system compiler to produce code
acceptable for the testing. Some UNRESOLVED/XFAIL would be probably the right
result code but one may not give enough priority for such regression.
> My feeling on this is that we should just do the testing you do after
> without worrying whether the break address is at the beginning of
> a line or not. So I'd just ditch the above, and keep the rest of
> the testcase as is.
OK, removed this part of code as it should never happen. Put there now:
+# PC should not be now at the boundary of source lines to make the original bug
+# exploitable. The GLOBAL_X variable exists in the source for this purpose.
Thanks,
Jan
gdb/
2009-05-10 Joel Brobecker <brobecker@adacore.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-10 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.cp/expand-sals.exp, gdb.cp/expand-sals.cc: New.
--- gdb/breakpoint.c 5 May 2009 13:24:48 -0000 1.393
+++ gdb/breakpoint.c 10 May 2009 18:22:47 -0000
@@ -5494,6 +5494,14 @@ parse_breakpoint_sals (char **address,
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
sal.section = find_pc_overlay (sal.pc);
+
+ /* "break" without arguments is equivalent to "break *PC" where PC is
+ the default_breakpoint_address. So make sure to set
+ sal.explicit_pc to prevent GDB from trying to expand the list of
+ sals to include all other instances with the same symtab and 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 10 May 2009 18:22:47 -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 10 May 2009 18:22:47 -0000
@@ -0,0 +1,58 @@
+# 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 now at the boundary of source lines to make the original bug
+# exploitable. The GLOBAL_X variable exists in the source for this purpose.
+
+# 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.*"
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-05-10 18:33 ` Jan Kratochvil
@ 2009-05-11 9:11 ` Joel Brobecker
2009-05-11 15:07 ` Jan Kratochvil
0 siblings, 1 reply; 10+ messages in thread
From: Joel Brobecker @ 2009-05-11 9:11 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: Tom Tromey, gdb-patches
> gdb/
> 2009-05-10 Joel Brobecker <brobecker@adacore.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-10 Jan Kratochvil <jan.kratochvil@redhat.com>
>
> * gdb.cp/expand-sals.exp, gdb.cp/expand-sals.cc: New.
It all looks great to me.
Thanks!
--
Joel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] Fix internal error on breaking at a multi-locations caller
2009-05-11 9:11 ` Joel Brobecker
@ 2009-05-11 15:07 ` Jan Kratochvil
0 siblings, 0 replies; 10+ messages in thread
From: Jan Kratochvil @ 2009-05-11 15:07 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches
On Mon, 11 May 2009 11:11:28 +0200, Joel Brobecker wrote:
> > gdb/
> > 2009-05-10 Joel Brobecker <brobecker@adacore.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-10 Jan Kratochvil <jan.kratochvil@redhat.com>
> >
> > * gdb.cp/expand-sals.exp, gdb.cp/expand-sals.cc: New.
>
> It all looks great to me.
Checked in.
http://sourceware.org/ml/gdb-cvs/2009-05/msg00063.html
Thanks,
Jan
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-05-11 15:07 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-09 22:17 [patch] Fix internal error on breaking at a multi-locations caller Jan Kratochvil
2009-04-24 1:01 ` Tom Tromey
2009-04-28 20:32 ` Joel Brobecker
2009-05-01 9:20 ` Jan Kratochvil
2009-05-01 15:48 ` Joel Brobecker
2009-05-01 17:32 ` Jan Kratochvil
2009-05-06 16:51 ` Joel Brobecker
2009-05-10 18:33 ` Jan Kratochvil
2009-05-11 9:11 ` Joel Brobecker
2009-05-11 15:07 ` Jan Kratochvil
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox