Re: [patch] PR gdb/1665 pending catch/throw catchpoints

Aleksandar Ristovski
2008-05-02T17:43:40Z

[-- Attachment #1: Type: text/plain, Size: 1361 bytes --]

Daniel Jacobowitz wrote:
>
> This won't work if the C++ library is linked in, e.g. -static or a
> bare metal toolchain; it won't be pending.

Made test accept both <PENDING> and address.

>
>> +gdb_test "tbreak main" "Temporary breakpoint 3.*" \
>> + "Set temporary breakpoint at main"
>> +
>> +gdb_test "run" "Temporary breakpoint 3,.*" "Run to main"
>
> There's runto_main, use that instead; it handles remote targets and so
> forth.

Yeah, but it wouldn't work in my case as it deletes breakpoints automagically. I introduced new runto_main_new that accepts options like temporary-break and keep-breakpoints.

>
> If you'll try to update this, I can test it on arm-none-eabi or
> another bare metal platform. Running it with
> "RUNTESTFLAGS=--target_board unix/-static" should be enough to test
> the <PENDING> problem.
>

Please do with the attached patch.

Thanks,
Aleksandar

ChangeLog:

* gdb.cp/exception.exp: Made test functional.
* lib/gdb.exp (runto): New option: keep-breakpoints to make procedure
more useful. If the option is not specified, it deletes breakpoints
like before. Made matching regexp accept both temporary and regular
breakpoint.
(runto_main_new): New procedure, to avoid breakage of the existing
stuff. This procedure works like runto_main, except it can take
arguments: temporary-break and keep-breakpoints.

[-- Attachment #2: exception.exp.diff --]
[-- Type: text/plain, Size: 9900 bytes --]

Index: gdb/testsuite/gdb.cp/exception.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/exception.exp,v
retrieving revision 1.12
diff -u -p -r1.12 exception.exp
--- gdb/testsuite/gdb.cp/exception.exp 1 Jan 2008 22:53:19 -0000 1.12
+++ gdb/testsuite/gdb.cp/exception.exp 2 May 2008 17:40:35 -0000
@@ -27,10 +27,6 @@
# Static-linked executables use a different mechanism to get the
# address of the notification hook in the C++ support library.

-# TODO: this file is not ready for production yet. If you are working
-# on C++ exception support for gdb, you can take out the "continue"
-# statement and try your luck. -- chastain 2004-01-09
-
# TODO: this file has many absolute line numbers.
# Replace them with gdb_get_line_number.

@@ -67,56 +63,58 @@ gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}

-if ![runto_main] then {
- perror "couldn't run to breakpoint"
- continue
-}
-
-# As I said before, this test script is not ready yet!
-
-continue
-
# Set a catch catchpoint

-gdb_test "catch catch" "Catchpoint \[0-9\]+ \\(catch\\)"
+gdb_test "catch catch" "Catchpoint \[0-9\]+ \\(catch\\)" \
+ "catch catch (before inferior run)"

# Set a throw catchpoint

gdb_test "catch throw" "Catchpoint \[0-9\]+ \\(throw\\)" \
- "catch throw (static executable)"
+ "catch throw (before inferior run)"

-# The catchpoints should be listed in the list of breakpoints.

+# The catchpoints should be listed in the list of breakpoints.
+# In case of a statically linked test, we won't have a pending breakpoint.
+# Hence we allow for both an address or "<PENDING>". If we ever become able
+# to tell whether the target is linked statically or not, we can be more
+# precise and require exact output.
+set addr "\(<PENDING>|$hex\)"
set re_head "Num${ws}Type${ws}Disp${ws}Enb${ws}Address${ws}What"
-set re_1_main "1${ws}breakpoint${ws}keep${ws}y${ws}$hex${ws}in main.*breakpoint already hit.*"
-set re_2_catch "2${ws}catch catch${ws}keep${ws}y${ws}$hex${ws}exception catch"
-set re_3_catch "3${ws}catch throw${ws}keep${ws}y${ws}$hex${ws}exception throw"
-set re_2_bp "2${ws}breakpoint${ws}keep${ws}y${ws}$hex${ws}exception catch"
-set re_3_bp "3${ws}breakpoint${ws}keep${ws}y${ws}$hex${ws}exception throw"
+set re_2_bp "1${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception catch"
+set re_3_bp "2${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception throw"

-set name "info breakpoints"
+set name "info breakpoints (before inferior run)"
gdb_test_multiple "info breakpoints" $name {
- -re "$re_head${ws}$re_1_main${ws}$re_2_catch${ws}$re_3_catch\r\n$gdb_prompt $" {
+ -re "$re_head${ws}$re_2_bp${ws}$re_3_bp\r\n$gdb_prompt $" {
pass $name
}
- -re "$re_head${ws}$re_1_main${ws}$re_2_bp${ws}$re_3_bp\r\n$gdb_prompt $" {
- # TODO: gdb HEAD 2004-01-08 does this. Is this okay?
- unresolved $name
- }
+ -re ".*$gdb_prompt $"
+ {
+ fail $name
+ }
+}
+
+if ![runto_main_new { temporary-break keep-breakpoints }] {
+ perror "Couldn't run to main"
+ continue
}

-# Some targets support "info catch".
-# Some do not.
+set addr "$hex"
+set re_head "Num${ws}Type${ws}Disp${ws}Enb${ws}Address${ws}What"
+set re_2_bp "1${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception catch"
+set re_3_bp "2${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception throw"

-set name "info catch"
-gdb_test_multiple "info catch" $name {
- -re "Info catch not supported with this target/compiler combination.\r\n$gdb_prompt $" {
- unsupported $name
- }
- -re "No catches.\r\n$gdb_prompt $" {
- # TODO: gdb HEAD 2004-01-08 does this. Is this okay?
- unresolved $name
+set name "info breakpoints (after inferior run)"
+gdb_test_multiple "info breakpoints" $name {
+ -re "$re_head${ws}$re_2_bp${ws}$re_3_bp\r\n$gdb_prompt $" {
+ pass $name
}
+ -re ".*$gdb_prompt $"
+ {
+ send_user "\n---\n$expect_out(buffer)\n---\n"
+ fail $name
+ }
}

# Get the first exception thrown
@@ -127,8 +125,7 @@ gdb_test_multiple "continue" $name {
pass $name
}
-re "Continuing.${ws}Catchpoint \[0-9\]+ \\(exception thrown\\)\r\n.*\r\n$gdb_prompt $" {
- # TODO: gdb HEAD 2004-01-08 does this. Is this okay?
- unresolved $name
+ pass $name
}
}

@@ -137,7 +134,7 @@ gdb_test_multiple "continue" $name {

set name "backtrace after first throw"
gdb_test_multiple "backtrace" $name {
- -re ".*#\[0-9\]+${ws}$hex in foo \\(i=20\\) at .*${srcfile}:30\r\n#\[0-9\]+${ws}$hex in main \\((void|)\\) at .*${srcfile}:48\r\n$gdb_prompt $" {
+ -re ".*#\[0-9\]+${ws}$hex in __cxa_throw.*#\[0-9\]+${ws}$hex in foo \\(i=20\\) at .*${srcfile}:\[0-9\]+\r\n#\[0-9\]+${ws}$hex in main \\(.*\\) at .*${srcfile}:\[0-9\]+\r\n$gdb_prompt $" {
pass $name
}
}
@@ -150,8 +147,7 @@ gdb_test_multiple "continue" $name {
pass $name
}
-re "Continuing.${ws}Catchpoint \[0-9\]+ \\(exception caught\\)\r\n.*\r\n$gdb_prompt $" {
- # TODO: gdb HEAD 2004-01-08 does this. Is this okay?
- unresolved $name
+ pass $name
}
}

@@ -160,7 +156,7 @@ gdb_test_multiple "continue" $name {

set name "backtrace after first catch"
gdb_test_multiple "backtrace" $name {
- -re ".*#\[0-9\]+${ws}$hex in main \\((void|)\\) at .*$srcfile:50\r\n$gdb_prompt $" {
+ -re ".*#\[0-9\]+${ws}$hex in __cxa_begin_catch.*#\[0-9\]+${ws}$hex in main \\(.*\\) at .*$srcfile:\[0-9\]+\r\n$gdb_prompt $" {
pass $name
}
}
@@ -173,8 +169,7 @@ gdb_test_multiple "continue" $name {
pass $name
}
-re "Continuing.${ws}Got an except 13${ws}Catchpoint \[0-9\]+ \\(exception thrown\\)\r\n.*\r\n$gdb_prompt $" {
- # TODO: gdb HEAD 2004-01-08 does this. Is this okay?
- unresolved $name
+ pass $name
}
}

@@ -183,7 +178,7 @@ gdb_test_multiple "continue" $name {

set name "backtrace after second throw"
gdb_test_multiple "backtrace" $name {
- -re ".*#\[0-9\]+${ws}$hex in foo \\(i=20\\) at .*${srcfile}:30\r\n#\[0-9\]+${ws}$hex in main \\((void|)\\) at .*${srcfile}:56\r\n$gdb_prompt $" {
+ -re ".*#\[0-9\]+${ws}$hex in __cxa_throw.*#\[0-9\]+${ws}$hex in foo \\(i=20\\) at .*${srcfile}:\[0-9\]+\r\n#\[0-9\]+${ws}$hex in main \\(.*\\) at .*${srcfile}:\[0-9\]+\r\n$gdb_prompt $" {
pass $name
}
}
@@ -196,8 +191,7 @@ gdb_test_multiple "continue" $name {
pass $name
}
-re "Continuing.${ws}Catchpoint \[0-9\]+ \\(exception caught\\)\r\n.*\r\n$gdb_prompt $" {
- # TODO: gdb HEAD 2004-01-08 does this. Is this okay?
- unresolved $name
+ pass $name
}
}

@@ -206,7 +200,7 @@ gdb_test_multiple "continue" $name {

set name "backtrace after second catch"
gdb_test_multiple "backtrace" $name {
- -re ".*#\[0-9\]+${ws}$hex in main \\((void|)\\) at .*$srcfile:58\r\n$gdb_prompt $" {
+ -re ".*#\[0-9\]+${ws}$hex in __cxa_begin_catch.*#\[0-9\]+${ws}$hex in main \\(.*\\) at .*$srcfile:\[0-9\]+\r\n$gdb_prompt $" {
pass $name
}
}
Index: gdb/testsuite/lib/gdb.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/lib/gdb.exp,v
retrieving revision 1.101
diff -u -p -r1.101 gdb.exp
--- gdb/testsuite/lib/gdb.exp 24 Apr 2008 10:21:45 -0000 1.101
+++ gdb/testsuite/lib/gdb.exp 2 May 2008 17:40:35 -0000
@@ -371,29 +371,42 @@ proc gdb_breakpoint { function args } {
# just compare to "function" because it might be a fully qualified,
# single quoted C++ function specifier. If there's an additional argument,
# pass it to gdb_breakpoint.
+# If one of the formal arguments is named 'keep-breakpoints', do not
+# delete breakpoints.

proc runto { function args } {
global gdb_prompt
global decimal
+ set do_delete_breakpoints 1

- delete_breakpoints
+ if {[lsearch -exact [lindex $args 0] keep-breakpoints] != -1} {
+ set do_delete_breakpoints 0
+ }
+
+ if { $do_delete_breakpoints == 1 } {
+ delete_breakpoints
+ }

if ![gdb_breakpoint $function [lindex $args 0]] {
return 0;
}

gdb_run_cmd
-
+
+ set breakpointmsg "\(Temporary breakpoint|Breakpoint\)"
+
# the "at foo.c:36" output we get with -g.
# the "in func" output we get without -g.
gdb_expect 30 {
- -re "Break.* at .*:$decimal.*$gdb_prompt $" {
+ -re "${breakpointmsg} \[0-9\]+, .* at .*:$decimal.*$gdb_prompt $" {
return 1
}
- -re "Breakpoint \[0-9\]*, \[0-9xa-f\]* in .*$gdb_prompt $" {
+ -re "${breakpointmsg} \[0-9\]+, \[0-9xa-f\]* in .*$gdb_prompt $" {
+ send_user "Matched: \n---\n$expect_out(buffer)\n---\n"
return 1
}
- -re "$gdb_prompt $" {
+ -re "$gdb_prompt $" {
+ send_user "\n***\n$expect_out(buffer)\n***\n"
fail "running to $function in runto"
return 0
}
@@ -426,6 +439,43 @@ proc runto_main { } {
return 1
}

+#
+# runto_main_new -- ask gdb to run until we hit a breakpoint at main.
+# The case where the target uses stubs has to be handled
+# specially--if it uses stubs, assuming we hit
+# breakpoint() and just step out of the function.
+# opts - arguments. Possible values:
+# 'temporary-break' - use tbreak main
+# 'keep-breakpoints' - do not delete breakpoints
+# if opts is empty list, it behaves as runto_main.
+#
+proc runto_main_new { opts } {
+ global gdb_prompt
+ global decimal
+ set do_delete_breakpoints 1
+
+ if {[lsearch -exact [lindex $opts 0] temporary-break ] != -1} {
+# gdb_breakpoint understands 'temporary'.
+ lappend opts temporary
+ }
+
+ if ![target_info exists gdb_stub] {
+ return [runto main $opts ]
+ }
+
+ if {[lsearch -exact [lindex $opts 0] keep-breakpoints ] != -1} {
+ set do_delete_breakpoints 0
+ send_user "Keeping breakpoints\n"
+ }
+
+ if { $do_delete_breakpoints == 1 } {
+ delete_breakpoints
+ }
+
+ gdb_step_for_stub;
+
+ return 1
+}

### Continue, and expect to hit a breakpoint.
### Report a pass or fail, depending on whether it seems to have