From 8e8901c5c22072ecab98e3f3e121df2bf0aefc01 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Sat, 15 Mar 2008 13:53:25 +0000 Subject: [PATCH] Implement -thread-info. * gdbthread.h (print_thread_info): Declare. * thread.c (print_thread_info): New, extracted from info_threads_command and adjusted to work for CLI and MI. (info_threads_command): Use print_thread_info. * Makefile.in: Update dependencies. * mi/mi-cmds.c (mi_cmds): Specify a handler for -thread-info. * mi/mi-cmds.h (mi_cmd_thread_info): Declare. * mi/mi-main.c (mi_cmd_thread_info): New. (mi_cmd_list_features): Include 'thread-info'. --- gdb/ChangeLog | 17 ++++++++++ gdb/Makefile.in | 2 +- gdb/doc/ChangeLog | 5 +++ gdb/doc/gdb.texinfo | 37 +++++++++++---------- gdb/gdbthread.h | 4 +++ gdb/mi/mi-cmds.c | 3 +- gdb/mi/mi-cmds.h | 1 + gdb/mi/mi-main.c | 19 +++++++++++ gdb/thread.c | 80 ++++++++++++++++++++++++++++++++++++--------- 9 files changed, 131 insertions(+), 37 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1620d6492a..38fac7420e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2008-03-15 Vladimir Prus + + Implement -thread-info. + * gdbthread.h (print_thread_info): Declare. + + * thread.c (print_thread_info): New, extracted + from info_threads_command and adjusted to + work for CLI and MI. + (info_threads_command): Use print_thread_info. + * Makefile.in: Update dependencies. + + * mi/mi-cmds.c (mi_cmds): Specify a handler + for -thread-info. + * mi/mi-cmds.h (mi_cmd_thread_info): Declare. + * mi/mi-main.c (mi_cmd_thread_info): New. + (mi_cmd_list_features): Include 'thread-info'. + 2008-03-14 Kevin Buettner * mips-tdep.c (mips32_scan_prologue): Use the ABI register size diff --git a/gdb/Makefile.in b/gdb/Makefile.in index a3e73b914f..7942b77a13 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -792,7 +792,7 @@ gdb_stabs_h = gdb-stabs.h gdb_stat_h = gdb_stat.h gdb_string_h = gdb_string.h gdb_thread_db_h = gdb_thread_db.h -gdbthread_h = gdbthread.h $(breakpoint_h) $(frame_h) +gdbthread_h = gdbthread.h $(breakpoint_h) $(frame_h) $(ui_out_h) gdbtypes_h = gdbtypes.h $(hashtab_h) gdb_vfork_h = gdb_vfork.h gdb_wait_h = gdb_wait.h diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 60b83e92d3..d32caf6636 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2008-03-15 Vladimir Prus + + * gdb.texinfo (Thread Commands): Document + -thread-info. Remove -thread-list-all-threads. + 2008-03-14 Pedro Alves Sandra Loosemore diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 9b69ad6e54..2ed036ca4f 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -18924,34 +18924,33 @@ The corresponding @value{GDBN} command is @samp{pwd}. @subsubheading Synopsis @smallexample - -thread-info + -thread-info [ @var{thread-id} ] @end smallexample +Reports information about either a specific thread, if +the @var{thread-id} parameter is present, or about all +threads. When printing information about all threads, +also reports the current thread. + @subsubheading @value{GDBN} Command -No equivalent. +The @samp{info thread} command prints the same information +about all threads. @subsubheading Example -N.A. - - -@subheading The @code{-thread-list-all-threads} Command -@findex -thread-list-all-threads - -@subsubheading Synopsis @smallexample - -thread-list-all-threads +-thread-info +^done,threads=[ +@{id="2",target-id="Thread 0xb7e14b90 (LWP 21257)", + frame=@{level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]@}, +@{id="1",target-id="Thread 0xb7e156b0 (LWP 21254)", + frame=@{level="0",addr="0x0804891f",func="foo",args=[@{name="i",value="10"@}], + file="/tmp/a.c",fullname="/tmp/a.c",line="158"@}@}], +current-thread-id="1" +(gdb) @end smallexample -@subsubheading @value{GDBN} Command - -The equivalent @value{GDBN} command is @samp{info threads}. - -@subsubheading Example -N.A. - - @subheading The @code{-thread-list-ids} Command @findex -thread-list-ids @@ -21845,6 +21844,8 @@ The current list of features is: @item @samp{pending-breakpoints}---indicates presence of the @code{-f} option to the @code{-break-insert} command. +@item +@samp{thread-info}---indicates presence of the @code{-thread-info} command. @end itemize diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index dd4345aa28..5632af6816 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -32,6 +32,8 @@ struct symtab; /* For struct frame_id. */ #include "frame.h" +#include "ui-out.h" + struct thread_info { struct thread_info *next; @@ -150,4 +152,6 @@ extern struct cmd_list_element *thread_cmd_list; `set print thread-events'. */ extern int print_thread_events; +extern void print_thread_info (struct ui_out *uiout, int thread); + #endif /* GDBTHREAD_H */ diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index c651694b73..89c63769a4 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -130,8 +130,7 @@ struct mi_cmd mi_cmds[] = { "target-list-current-targets", { NULL, 0 }, NULL, NULL }, { "target-list-parameters", { NULL, 0 }, NULL, NULL }, { "target-select", { NULL, 0 }, mi_cmd_target_select}, - { "thread-info", { NULL, 0 }, NULL, NULL }, - { "thread-list-all-threads", { NULL, 0 }, NULL, NULL }, + { "thread-info", { NULL, 0 }, NULL, mi_cmd_thread_info }, { "thread-list-ids", { NULL, 0 }, 0, mi_cmd_thread_list_ids}, { "thread-select", { NULL, 0 }, 0, mi_cmd_thread_select}, { "trace-actions", { NULL, 0 }, NULL, NULL }, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 2d0393b20f..6a033e5e64 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -105,6 +105,7 @@ extern mi_cmd_argv_ftype mi_cmd_target_file_get; extern mi_cmd_argv_ftype mi_cmd_target_file_put; extern mi_cmd_argv_ftype mi_cmd_target_file_delete; extern mi_cmd_args_ftype mi_cmd_target_select; +extern mi_cmd_argv_ftype mi_cmd_thread_info; extern mi_cmd_argv_ftype mi_cmd_thread_list_ids; extern mi_cmd_argv_ftype mi_cmd_thread_select; extern mi_cmd_argv_ftype mi_cmd_var_assign; diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 41e12d2e4d..cea8503b1f 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -276,6 +276,24 @@ mi_cmd_thread_list_ids (char *command, char **argv, int argc) return MI_CMD_DONE; } +enum mi_cmd_result +mi_cmd_thread_info (char *command, char **argv, int argc) +{ + int thread = -1; + + if (argc != 0 && argc != 1) + { + mi_error_message = xstrprintf ("Invalid MI command"); + return MI_CMD_ERROR; + } + + if (argc == 1) + thread = atoi (argv[0]); + + print_thread_info (uiout, thread); + return MI_CMD_DONE; +} + enum mi_cmd_result mi_cmd_data_list_register_names (char *command, char **argv, int argc) { @@ -1055,6 +1073,7 @@ mi_cmd_list_features (char *command, char **argv, int argc) ui_out_field_string (uiout, NULL, "frozen-varobjs"); ui_out_field_string (uiout, NULL, "pending-breakpoints"); + ui_out_field_string (uiout, NULL, "thread-info"); do_cleanups (cleanup); diff --git a/gdb/thread.c b/gdb/thread.c index 97facd2e6b..1ce514a2d2 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -407,15 +407,14 @@ prune_threads (void) } } -/* Print information about currently known threads - - * Note: this has the drawback that it _really_ switches - * threads, which frees the frame cache. A no-side - * effects info-threads command would be nicer. - */ - -static void -info_threads_command (char *arg, int from_tty) +/* Prints the list of threads and their details on UIOUT. + This is a version of 'info_thread_command' suitable for + use from MI. + If REQESTED_THREAD is not -1, it's the GDB id of the thread + that should be printed. Otherwise, all threads are + printed. */ +void +print_thread_info (struct ui_out *uiout, int requested_thread) { struct thread_info *tp; ptid_t current_ptid; @@ -423,45 +422,94 @@ info_threads_command (char *arg, int from_tty) struct cleanup *old_chain; struct frame_id saved_frame_id; char *extra_info; + int current_thread = -1; /* Backup current thread and selected frame. */ saved_frame_id = get_frame_id (get_selected_frame (NULL)); old_chain = make_cleanup_restore_current_thread (inferior_ptid, saved_frame_id); + make_cleanup_ui_out_list_begin_end (uiout, "threads"); + prune_threads (); target_find_new_threads (); current_ptid = inferior_ptid; for (tp = thread_list; tp; tp = tp->next) { + struct cleanup *chain2; + + if (requested_thread != -1 && tp->num != requested_thread) + continue; + + chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + if (ptid_equal (tp->ptid, current_ptid)) - printf_filtered ("* "); + { + current_thread = tp->num; + ui_out_text (uiout, "* "); + } else - printf_filtered (" "); + ui_out_text (uiout, " "); - printf_filtered ("%d %s", tp->num, target_tid_to_str (tp->ptid)); + ui_out_field_int (uiout, "id", tp->num); + ui_out_text (uiout, " "); + ui_out_field_string (uiout, "target-id", target_tid_to_str (tp->ptid)); extra_info = target_extra_thread_info (tp); if (extra_info) - printf_filtered (" (%s)", extra_info); - puts_filtered (" "); + { + ui_out_text (uiout, " ("); + ui_out_field_string (uiout, "details", extra_info); + ui_out_text (uiout, ")"); + } + ui_out_text (uiout, " "); /* That switch put us at the top of the stack (leaf frame). */ switch_to_thread (tp->ptid); - print_stack_frame (get_selected_frame (NULL), 0, LOCATION); + print_stack_frame (get_selected_frame (NULL), + /* For MI output, print frame level. */ + ui_out_is_mi_like_p (uiout), + LOCATION); + + do_cleanups (chain2); } /* Restores the current thread and the frame selected before the "info threads" command. */ do_cleanups (old_chain); + if (requested_thread == -1) + { + gdb_assert (current_thread != -1); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_int (uiout, "current-thread-id", current_thread); + } + /* If case we were not able to find the original frame, print the new selected frame. */ if (frame_find_by_id (saved_frame_id) == NULL) { warning (_("Couldn't restore frame in current thread, at frame 0")); - print_stack_frame (get_selected_frame (NULL), 0, LOCATION); + /* For MI, we should probably have a notification about + current frame change. But this error is not very likely, so + don't bother for now. */ + if (!ui_out_is_mi_like_p (uiout)) + print_stack_frame (get_selected_frame (NULL), 0, LOCATION); } } + +/* Print information about currently known threads + + * Note: this has the drawback that it _really_ switches + * threads, which frees the frame cache. A no-side + * effects info-threads command would be nicer. + */ + +static void +info_threads_command (char *arg, int from_tty) +{ + print_thread_info (uiout, -1); +} + /* Switch from one thread to another. */ void -- 2.34.1