From: Tom Tromey Date: Tue, 22 Nov 2011 21:25:19 +0000 (+0000) Subject: gdb X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=36dfb11c8b13be20baf34ea4ba772255c605e0ed;p=binutils-gdb.git gdb PR mi/8444: * mi/mi-common.h (EXEC_ASYNC_SOLIB_EVENT, EXEC_ASYNC_FORK) (EXEC_ASYNC_VFORK, EXEC_ASYNC_SYSCALL_ENTRY) (EXEC_ASYNC_SYSCALL_RETURN, EXEC_ASYNC_EXEC): New constants. * mi/mi-common.c (async_reason_string_lookup): Add new reasons. * breakpoint.c (print_it_catch_fork, print_it_catch_vfork) (print_it_catch_syscall, print_it_catch_exec) (internal_bkpt_print_it): Use ui_out. Emit stop reason. (bpstat_print): Add 'kind' argument. Handle TARGET_WAITKIND_LOADED. * infrun.c (normal_stop): Update for bpstat_print change. Don't handle TARGET_WAITKIND_LOADED here. * breakpoint.h (bpstat_print): Update. gdb/testsuite * lib/mi-support.exp (mi_run_cmd_full): Rename from mi_run_cmd. Add "use_mi_command" argument. (mi_run_cmd, mi_run_with_cli): New procs. * gdb.mi/solib-lib.c: New file. * gdb.mi/solib-main.c: New file. * gdb.mi/mi-solib.exp: New file. gdb/doc * gdb.texinfo (GDB/MI Async Records): Document new *stopped reasons. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2707c5137f1..b168d837825 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2011-11-22 Tom Tromey + + PR mi/8444: + * mi/mi-common.h (EXEC_ASYNC_SOLIB_EVENT, EXEC_ASYNC_FORK) + (EXEC_ASYNC_VFORK, EXEC_ASYNC_SYSCALL_ENTRY) + (EXEC_ASYNC_SYSCALL_RETURN, EXEC_ASYNC_EXEC): New constants. + * mi/mi-common.c (async_reason_string_lookup): Add new reasons. + * breakpoint.c (print_it_catch_fork, print_it_catch_vfork) + (print_it_catch_syscall, print_it_catch_exec) + (internal_bkpt_print_it): Use ui_out. Emit stop reason. + (bpstat_print): Add 'kind' argument. Handle + TARGET_WAITKIND_LOADED. + * infrun.c (normal_stop): Update for bpstat_print change. Don't + handle TARGET_WAITKIND_LOADED here. + * breakpoint.h (bpstat_print): Update. + 2011-11-22 Tom Tromey * mi/mi-interp.c (mi_on_normal_stop): Call bpstat_print. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index ab0d4020ac6..fa800188593 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -3446,7 +3446,8 @@ print_bp_stop_message (bpstat bs) /* Print a message indicating what happened. This is called from normal_stop(). The input to this routine is the head of the bpstat - list - a list of the eventpoints that caused this stop. This + list - a list of the eventpoints that caused this stop. KIND is + the target_waitkind for the stopping event. This routine calls the generic print routine for printing a message about reasons for stopping. This will print (for example) the "Breakpoint n," part of the output. The return value of this @@ -3465,7 +3466,7 @@ print_bp_stop_message (bpstat bs) further info to be printed. */ enum print_stop_action -bpstat_print (bpstat bs) +bpstat_print (bpstat bs, int kind) { int val; @@ -3482,6 +3483,18 @@ bpstat_print (bpstat bs) return val; } + /* If we had hit a shared library event breakpoint, + print_bp_stop_message would print out this message. If we hit an + OS-level shared library event, do the same thing. */ + if (kind == TARGET_WAITKIND_LOADED) + { + ui_out_text (current_uiout, _("Stopped due to shared library event\n")); + if (ui_out_is_mi_like_p (current_uiout)) + ui_out_field_string (current_uiout, "reason", + async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT)); + return PRINT_NOTHING; + } + /* We reached the end of the chain, or we got a null BS to start with and nothing was printed. */ return PRINT_UNKNOWN; @@ -6190,12 +6203,25 @@ breakpoint_hit_catch_fork (const struct bp_location *bl, static enum print_stop_action print_it_catch_fork (bpstat bs) { + struct ui_out *uiout = current_uiout; struct breakpoint *b = bs->breakpoint_at; struct fork_catchpoint *c = (struct fork_catchpoint *) bs->breakpoint_at; annotate_catchpoint (b->number); - printf_filtered (_("\nCatchpoint %d (forked process %d), "), - b->number, ptid_get_pid (c->forked_inferior_pid)); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary catchpoint "); + else + ui_out_text (uiout, "\nCatchpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_FORK)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, " (forked process "); + ui_out_field_int (uiout, "newpid", ptid_get_pid (c->forked_inferior_pid)); + ui_out_text (uiout, "), "); return PRINT_SRC_AND_LOC; } @@ -6286,12 +6312,25 @@ breakpoint_hit_catch_vfork (const struct bp_location *bl, static enum print_stop_action print_it_catch_vfork (bpstat bs) { + struct ui_out *uiout = current_uiout; struct breakpoint *b = bs->breakpoint_at; struct fork_catchpoint *c = (struct fork_catchpoint *) b; annotate_catchpoint (b->number); - printf_filtered (_("\nCatchpoint %d (vforked process %d), "), - b->number, ptid_get_pid (c->forked_inferior_pid)); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary catchpoint "); + else + ui_out_text (uiout, "\nCatchpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_VFORK)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, " (vforked process "); + ui_out_field_int (uiout, "newpid", ptid_get_pid (c->forked_inferior_pid)); + ui_out_text (uiout, "), "); return PRINT_SRC_AND_LOC; } @@ -6500,6 +6539,7 @@ breakpoint_hit_catch_syscall (const struct bp_location *bl, static enum print_stop_action print_it_catch_syscall (bpstat bs) { + struct ui_out *uiout = current_uiout; struct breakpoint *b = bs->breakpoint_at; /* These are needed because we want to know in which state a syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY @@ -6508,7 +6548,6 @@ print_it_catch_syscall (bpstat bs) ptid_t ptid; struct target_waitstatus last; struct syscall s; - struct cleanup *old_chain; char *syscall_id; get_last_target_status (&ptid, &last); @@ -6517,21 +6556,31 @@ print_it_catch_syscall (bpstat bs) annotate_catchpoint (b->number); - if (s.name == NULL) - syscall_id = xstrprintf ("%d", last.value.syscall_number); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary catchpoint "); else - syscall_id = xstrprintf ("'%s'", s.name); - - old_chain = make_cleanup (xfree, syscall_id); + ui_out_text (uiout, "\nCatchpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY + ? EXEC_ASYNC_SYSCALL_ENTRY + : EXEC_ASYNC_SYSCALL_RETURN)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY) - printf_filtered (_("\nCatchpoint %d (call to syscall %s), "), - b->number, syscall_id); - else if (last.kind == TARGET_WAITKIND_SYSCALL_RETURN) - printf_filtered (_("\nCatchpoint %d (returned from syscall %s), "), - b->number, syscall_id); + ui_out_text (uiout, " (call to syscall "); + else + ui_out_text (uiout, " (returned from syscall "); - do_cleanups (old_chain); + if (s.name == NULL || ui_out_is_mi_like_p (uiout)) + ui_out_field_int (uiout, "syscall-number", last.value.syscall_number); + if (s.name != NULL) + ui_out_field_string (uiout, "syscall-name", s.name); + + ui_out_text (uiout, "), "); return PRINT_SRC_AND_LOC; } @@ -6776,12 +6825,26 @@ breakpoint_hit_catch_exec (const struct bp_location *bl, static enum print_stop_action print_it_catch_exec (bpstat bs) { + struct ui_out *uiout = current_uiout; struct breakpoint *b = bs->breakpoint_at; struct exec_catchpoint *c = (struct exec_catchpoint *) b; annotate_catchpoint (b->number); - printf_filtered (_("\nCatchpoint %d (exec'd %s), "), b->number, - c->exec_pathname); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary catchpoint "); + else + ui_out_text (uiout, "\nCatchpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_EXEC)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, " (exec'd "); + ui_out_field_string (uiout, "new-exec", c->exec_pathname); + ui_out_text (uiout, "), "); + return PRINT_SRC_AND_LOC; } @@ -11153,6 +11216,7 @@ internal_bkpt_check_status (bpstat bs) static enum print_stop_action internal_bkpt_print_it (bpstat bs) { + struct ui_out *uiout = current_uiout; struct breakpoint *b; b = bs->breakpoint_at; @@ -11163,7 +11227,10 @@ internal_bkpt_print_it (bpstat bs) /* Did we stop because the user set the stop_on_solib_events variable? (If so, we report this as a generic, "Stopped due to shlib event" message.) */ - printf_filtered (_("Stopped due to shared library event\n")); + ui_out_text (uiout, _("Stopped due to shared library event\n")); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT)); break; case bp_thread_event: diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 96cc96aa5a0..438f347fae9 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -884,7 +884,7 @@ extern int bpstat_should_step (void); /* Print a message indicating what happened. Returns nonzero to say that only the source line should be printed after this (zero return means print the frame as well as the source line). */ -extern enum print_stop_action bpstat_print (bpstat); +extern enum print_stop_action bpstat_print (bpstat, int); /* Put in *NUM the breakpoint number of the first breakpoint we are stopped at. *BSP upon return is a bpstat which points to the diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 4b3a99fbb58..82eefc33225 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2011-11-22 Tom Tromey + + * gdb.texinfo (GDB/MI Async Records): Document new *stopped + reasons. + 2011-11-20 Stan Shebs * gdb.texinfo (Starting and Stopping Trace Experiments): Document diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index f4f68a344d7..3321a77380e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -26172,6 +26172,25 @@ The inferior exited. The inferior exited normally. @item signal-received A signal was received by the inferior. +@item solib-event +The inferior has stopped due to a library being loaded or unloaded. +This can only happen when @code{stop-on-solib-events} (@pxref{Files}) +is set. +@item fork +The inferior has forked. This is reported when @code{catch fork} +(@pxref{Set Catchpoints}) has been used. +@item vfork +The inferior has vforked. This is reported in when @code{catch vfork} +(@pxref{Set Catchpoints}) has been used. +@item syscall-entry +The inferior entered a system call. This is reported when @code{catch +syscall} (@pxref{Set Catchpoints}) has been used. +@item syscall-entry +The inferior returned from a system call. This is reported when +@code{catch syscall} (@pxref{Set Catchpoints}) has been used. +@item exec +The inferior called @code{exec}. This is reported when @code{catch exec} +(@pxref{Set Catchpoints}) has been used. @end table The @var{id} field identifies the thread that directly caused the stop diff --git a/gdb/infrun.c b/gdb/infrun.c index 33619268795..5a0f1d23dd0 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -5971,22 +5971,10 @@ normal_stop (void) int do_frame_printing = 1; struct thread_info *tp = inferior_thread (); - bpstat_ret = bpstat_print (tp->control.stop_bpstat); + bpstat_ret = bpstat_print (tp->control.stop_bpstat, last.kind); switch (bpstat_ret) { case PRINT_UNKNOWN: - /* If we had hit a shared library event breakpoint, - bpstat_print would print out this message. If we hit - an OS-level shared library event, do the same - thing. */ - if (last.kind == TARGET_WAITKIND_LOADED) - { - printf_filtered (_("Stopped due to shared library event\n")); - source_flag = SRC_LINE; /* something bogus */ - do_frame_printing = 0; - break; - } - /* FIXME: cagney/2002-12-01: Given that a frame ID does (or should) carry around the function and does (or should) use that when doing a frame comparison. */ diff --git a/gdb/mi/mi-common.c b/gdb/mi/mi-common.c index e7dd3c46c81..8fb9799ddc1 100644 --- a/gdb/mi/mi-common.c +++ b/gdb/mi/mi-common.c @@ -35,6 +35,12 @@ static const char * const async_reason_string_lookup[] = "exited", "exited-normally", "signal-received", + "solib-event", + "fork", + "vfork", + "syscall-entry", + "syscall-return", + "exec", NULL }; diff --git a/gdb/mi/mi-common.h b/gdb/mi/mi-common.h index dc5fc8e1704..9ecc5a1f087 100644 --- a/gdb/mi/mi-common.h +++ b/gdb/mi/mi-common.h @@ -37,6 +37,12 @@ enum async_reply_reason EXEC_ASYNC_EXITED, EXEC_ASYNC_EXITED_NORMALLY, EXEC_ASYNC_SIGNAL_RECEIVED, + EXEC_ASYNC_SOLIB_EVENT, + EXEC_ASYNC_FORK, + EXEC_ASYNC_VFORK, + EXEC_ASYNC_SYSCALL_ENTRY, + EXEC_ASYNC_SYSCALL_RETURN, + EXEC_ASYNC_EXEC, /* This is here only to represent the number of enums. */ EXEC_ASYNC_LAST }; diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 2aec1c717d3..b075e33c16f 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -427,9 +427,14 @@ mi_on_normal_stop (struct bpstats *bs, int print_frame) the frame again. In practice, this can only happen when running a CLI command in MI. */ struct ui_out *saved_uiout = current_uiout; + struct target_waitstatus last; + ptid_t last_ptid; current_uiout = mi_uiout; - bpstat_print (bs); + + get_last_target_status (&last_ptid, &last); + bpstat_print (bs, last.kind); + print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC); current_uiout = saved_uiout; } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 16838e10f0d..d84b323e1c7 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2011-11-22 Tom Tromey + + * lib/mi-support.exp (mi_run_cmd_full): Rename from mi_run_cmd. + Add "use_mi_command" argument. + (mi_run_cmd, mi_run_with_cli): New procs. + * gdb.mi/solib-lib.c: New file. + * gdb.mi/solib-main.c: New file. + * gdb.mi/mi-solib.exp: New file. + 2011-11-21 Doug Evans * gdb.cp/nextoverthrow.exp: Skip test if debug info for diff --git a/gdb/testsuite/gdb.mi/mi-solib.exp b/gdb/testsuite/gdb.mi/mi-solib.exp new file mode 100644 index 00000000000..4344f96fc5b --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-solib.exp @@ -0,0 +1,62 @@ +# Copyright 2011 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 . + +load_lib mi-support.exp +set MIFLAGS "-i=mi2" + +if {[skip_shlib_tests]} { + untested mi-solib.exp + return -1 +} + +gdb_exit +if [mi_gdb_start] { + continue +} + +set libname "solib-lib" +set srcfile_lib ${srcdir}/${subdir}/${libname}.c +set binfile_lib ${objdir}/${subdir}/${libname}.so +set lib_flags [list debug] + +set testfile "solib-main" +set srcfile ${srcdir}/${subdir}/${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set bin_flags [list debug shlib=${binfile_lib}] + +if [get_compiler_info ${binfile}] { + return -1 +} + +if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != "" + || [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } { + untested "Could not compile $binfile_lib or $binfile." + return -1 +} + +mi_delete_breakpoints +mi_gdb_reinitialize_dir $srcdir/$subdir +mi_gdb_reinitialize_dir $srcdir/$subdir +mi_gdb_load ${binfile} + +gdb_load_shlibs $binfile_lib + +mi_gdb_test "777-gdb-set stop-on-solib-events 1" "777\\^done" \ + "set stop-on-solib-events" + +# We use "run" rather than "-exec-run" here in order to test that CLI +# commands still cause the correct MI output to be generated. +mi_run_with_cli +mi_expect_stop solib-event .* .* .* .* .* "check for solib event" diff --git a/gdb/testsuite/gdb.mi/solib-lib.c b/gdb/testsuite/gdb.mi/solib-lib.c new file mode 100644 index 00000000000..e30ce8335cd --- /dev/null +++ b/gdb/testsuite/gdb.mi/solib-lib.c @@ -0,0 +1,19 @@ +/* Copyright 2011 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 . +*/ + +void solibfunction(void) +{ +} diff --git a/gdb/testsuite/gdb.mi/solib-main.c b/gdb/testsuite/gdb.mi/solib-main.c new file mode 100644 index 00000000000..eff210f201a --- /dev/null +++ b/gdb/testsuite/gdb.mi/solib-main.c @@ -0,0 +1,23 @@ +/* Copyright 2011 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 . +*/ + +extern void solibfunction(void); + +int main () +{ + solibfunction (); + return 0; +} diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index 63097cb80ca..dc1717bfc88 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -788,7 +788,7 @@ proc mi_gdb_test { args } { # In patterns, the newline sequence ``\r\n'' is matched explicitly as # ``.*$'' could swallow up output that we attempt to match elsewhere. -proc mi_run_cmd {args} { +proc mi_run_cmd_full {use_mi_command args} { global suppress_flag if { $suppress_flag } { return -1 @@ -797,6 +797,14 @@ proc mi_run_cmd {args} { global thread_selected_re global library_loaded_re + if {$use_mi_command} { + set run_prefix "220-exec-" + set run_match "220" + } else { + set run_prefix "" + set run_match "" + } + if [target_info exists gdb_init_command] { send_gdb "[target_info gdb_init_command]\n"; gdb_expect 30 { @@ -814,9 +822,9 @@ proc mi_run_cmd {args} { if [target_info exists use_gdb_stub] { if [target_info exists gdb,do_reload_on_run] { - send_gdb "220-exec-continue\n"; + send_gdb "${run_prefix}continue\n"; gdb_expect 60 { - -re "220\\^running\[\r\n\]+\\*running,thread-id=\"\[^\"\]+\"\r\n$mi_gdb_prompt" {} + -re "${run_match}\\^running\[\r\n\]+\\*running,thread-id=\"\[^\"\]+\"\r\n$mi_gdb_prompt" {} default {} } return 0; @@ -835,9 +843,9 @@ proc mi_run_cmd {args} { return 0 } - send_gdb "220-exec-run $args\n" + send_gdb "${run_prefix}run $args\n" gdb_expect { - -re "220\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n|=thread-created,id=\"1\",group-id=\"\[0-9\]+\"\r\n)*(${library_loaded_re})*(${thread_selected_re})?${mi_gdb_prompt}" { + -re "${run_match}\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n|=thread-created,id=\"1\",group-id=\"\[0-9\]+\"\r\n)*(${library_loaded_re})*(${thread_selected_re})?${mi_gdb_prompt}" { } -re "\\^error,msg=\"The target does not support running in non-stop mode.\"" { unsupported "Non-stop mode not supported" @@ -853,6 +861,20 @@ proc mi_run_cmd {args} { return 0 } +# A wrapper for mi_run_cmd_full which uses -exec-run and +# -exec-continue, as appropriate. ARGS are passed verbatim to +# mi_run_cmd_full. +proc mi_run_cmd {args} { + return [eval mi_run_cmd_full 1 $args] +} + +# A wrapper for mi_run_cmd_full which uses the CLI commands 'run' and +# 'continue', as appropriate. ARGS are passed verbatim to +# mi_run_cmd_full. +proc mi_run_with_cli {args} { + return [eval mi_run_cmd_full 0 $args] +} + # # Just like run-to-main but works with the MI interface #