[PATCH] handle dprintf error more gracefully
Antoine Tremblay
antoine.tremblay@ericsson.com
Mon Feb 23 13:00:00 GMT 2015
ping...
On 02/10/2015 11:27 AM, Antoine Tremblay wrote:
> If a dprintf generates an error, handle it so that we leave
> the program as stopped at location as if a real breakpoint was hit.
> On the mi interface this sends a *stopped event and avoids
> breaking frontend functionality. On cli it prints as a breakpoint
> would.
>
> Here's an example of what is returned on the mi interface :
>
> &"No symbol \"invalidvar1\" in current context.\n"
> ~"\nBreakpoint "
> ~"5, invalid () at ../../../gdb/testsuite/gdb.mi/mi-dprintf.c:37\n"
> ~"37\t ++i; /* set dprintf 2 here */\n"
> *stopped,reason="breakpoint-hit",disp="keep",bkptno="5",frame={addr="0x0000000000400665",
> func="invalid",args=[],file="../../../gdb/testsuite/gdb.mi/mi-dprintf.c",
> fullname="/home/eantotr/src/binutils-gdb/gdb/testsuite/gdb.mi/mi-dprintf.c",line="37"},
> thread-id="1",stopped-threads="all",core="2"
>
> Here's an example for the cli :
>
> No symbol "asdf" in current context.
>
> Breakpoint 1, main () at testdprintf.c:8
> 8 printf("i is %d\n",i);
>
> Note we could also treat the error as a warning and continue
> the program's execution by leaving bs->stop at 0 and continuing.
>
> I sided with the stop on error for now since I though an error
> should be treated as soon as possible, but continuing also
> seems like a possiblity. I'm unsure between the behavior of
> stopping at error or dprintf not stopping...
>
> Feedback is welcome, on the best way to handle this...
>
> gdb/ChangeLog:
> PR breakpoints/16551
> * breakpoint.c (dprintf_after_condition_true): Handle dprintf error.
> (bpstat_what) : Enable dprintf to print on stop.
>
> gdb/testsuite/ChangeLog:
> PR breakpoints/16551
> * gdb.mi/mi-dprintf.c (invalid): New function to test invalid dprintf.
> * gdb.mi/mi-dprintf.exp: Add invalid dprintf test.
> ---
> gdb/breakpoint.c | 21 +++++++++++++++++++--
> gdb/testsuite/gdb.mi/mi-dprintf.c | 12 +++++++++++-
> gdb/testsuite/gdb.mi/mi-dprintf.exp | 15 +++++++++++++++
> 3 files changed, 45 insertions(+), 3 deletions(-)
>
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 2804453..b51d17c 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -5818,7 +5818,12 @@ bpstat_what (bpstat bs_head)
>
> case bp_dprintf:
> if (bs->stop)
> - this_action = BPSTAT_WHAT_STOP_SILENT;
> + {
> + if (bs->print)
> + this_action = BPSTAT_WHAT_STOP_NOISY;
> + else
> + this_action = BPSTAT_WHAT_STOP_SILENT;
> + }
> else
> this_action = BPSTAT_WHAT_SINGLE;
> break;
> @@ -13885,6 +13890,7 @@ dprintf_after_condition_true (struct bpstats *bs)
> struct cleanup *old_chain;
> struct bpstats tmp_bs = { NULL };
> struct bpstats *tmp_bs_p = &tmp_bs;
> + volatile struct gdb_exception e;
>
> /* dprintf's never cause a stop. This wasn't set in the
> check_status hook instead because that would make the dprintf's
> @@ -13900,7 +13906,18 @@ dprintf_after_condition_true (struct bpstats *bs)
> bs->commands = NULL;
> old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
>
> - bpstat_do_actions_1 (&tmp_bs_p);
> + TRY_CATCH (e, RETURN_MASK_ERROR)
> + {
> + bpstat_do_actions_1 (&tmp_bs_p);
> + }
> + if (e.reason < 0)
> + {
> + /* Do stop if we have an error executing a dprintf command. */
> + bs->stop = 1;
> + /* Print the breakpoint information. */
> + bs->print = 1;
> + exception_print (gdb_stderr, e);
> + }
>
> /* 'tmp_bs.commands' will usually be NULL by now, but
> bpstat_do_actions_1 may return early without processing the whole
> diff --git a/gdb/testsuite/gdb.mi/mi-dprintf.c b/gdb/testsuite/gdb.mi/mi-dprintf.c
> index 0b8fc82..ed7d87e 100644
> --- a/gdb/testsuite/gdb.mi/mi-dprintf.c
> +++ b/gdb/testsuite/gdb.mi/mi-dprintf.c
> @@ -29,6 +29,14 @@ foo (int arg)
> g /= 2.5; /* set breakpoint 1 here */
> }
>
> +/* Function to test invalid symbols used in dprinf. */
> +void
> +invalid (void)
> +{
> + int i = 0;
> + ++i; /* set dprintf 2 here */
> +}
> +
> int
> main (int argc, char *argv[])
> {
> @@ -40,7 +48,9 @@ main (int argc, char *argv[])
>
> foo (loc++);
> foo (loc++);
> - foo (loc++);
> +
> + invalid ();
> +
> return g;
> }
>
> diff --git a/gdb/testsuite/gdb.mi/mi-dprintf.exp b/gdb/testsuite/gdb.mi/mi-dprintf.exp
> index ea198bd..0cdf2b5 100644
> --- a/gdb/testsuite/gdb.mi/mi-dprintf.exp
> +++ b/gdb/testsuite/gdb.mi/mi-dprintf.exp
> @@ -33,6 +33,7 @@ mi_delete_breakpoints
>
> set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
> set dp_location1 [gdb_get_line_number "set dprintf 1 here"]
> +set dp_location2 [gdb_get_line_number "set dprintf 2 here"]
>
> mi_run_to_main
>
> @@ -60,12 +61,22 @@ set bps [mi_make_breakpoint -type dprintf -func foo \
> mi_gdb_test "[incr i]-dprintf-insert $dp_location1 \"arg=%d, g=%d\\n\" arg g" \
> "$i\\^done,$bps" "mi insert dprintf dp_location1"
>
> +set bps [mi_make_breakpoint -type dprintf -func invalid \
> + -file ".*mi-dprintf.c" -fullname ".*mi-dprintf.c" \
> + -line $dp_location2]
> +mi_gdb_test "[incr i]-dprintf-insert $dp_location2 \"g=%d\\n\" invalidvar1" \
> + "$i\\^done,$bps" "mi insert dprintf dp_location2"
> +
> set bps {}
> lappend bps [mi_make_breakpoint -number 3 -type dprintf -func foo \
> -file ".*mi-dprintf.c" -fullname ".*mi-dprintf.c"]
> lappend bps [mi_make_breakpoint -type dprintf -func foo \
> -file ".*mi-dprintf.c" -fullname ".*mi-dprintf.c" \
> -line $dp_location1]
> +lappend bps [mi_make_breakpoint -type dprintf -func invalid \
> + -file ".*mi-dprintf.c" -fullname ".*mi-dprintf.c" \
> + -line $dp_location2]
> +
> mi_gdb_test "[incr i]-break-info" \
> "$i\\^done,[mi_make_breakpoint_table $bps]" \
> "mi info dprintf"
> @@ -111,6 +122,10 @@ proc mi_continue_dprintf {args} {
> }
> }
> mi_expect_stop ".*" ".*" ".*" ".*" ".*" "" "$msg 2nd stop"
> +
> + set msg "mi 3nd dprintf"
> + mi_send_resuming_command "exec-continue" "$msg continue"
> + mi_expect_stop ".*" ".*" ".*" ".*" ".*" "" "$msg 3nd stop"
> }
> }
>
More information about the Gdb-patches
mailing list