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'.
This commit is contained in:
parent
7d1e6fb863
commit
8e8901c5c2
@ -1,3 +1,20 @@
|
||||
2008-03-15 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
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 <kevinb@redhat.com>
|
||||
|
||||
* mips-tdep.c (mips32_scan_prologue): Use the ABI register size
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,8 @@
|
||||
2008-03-15 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Thread Commands): Document
|
||||
-thread-info. Remove -thread-list-all-threads.
|
||||
|
||||
2008-03-14 Pedro Alves <pedro@codesourcery.com>
|
||||
Sandra Loosemore <sandra@codesourcery.com>
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 },
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
134
gdb/thread.c
134
gdb/thread.c
@ -407,6 +407,96 @@ prune_threads (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
struct frame_info *cur_frame;
|
||||
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))
|
||||
{
|
||||
current_thread = tp->num;
|
||||
ui_out_text (uiout, "* ");
|
||||
}
|
||||
else
|
||||
ui_out_text (uiout, " ");
|
||||
|
||||
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)
|
||||
{
|
||||
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),
|
||||
/* 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"));
|
||||
/* 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
|
||||
@ -417,49 +507,7 @@ prune_threads (void)
|
||||
static void
|
||||
info_threads_command (char *arg, int from_tty)
|
||||
{
|
||||
struct thread_info *tp;
|
||||
ptid_t current_ptid;
|
||||
struct frame_info *cur_frame;
|
||||
struct cleanup *old_chain;
|
||||
struct frame_id saved_frame_id;
|
||||
char *extra_info;
|
||||
|
||||
/* 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);
|
||||
|
||||
prune_threads ();
|
||||
target_find_new_threads ();
|
||||
current_ptid = inferior_ptid;
|
||||
for (tp = thread_list; tp; tp = tp->next)
|
||||
{
|
||||
if (ptid_equal (tp->ptid, current_ptid))
|
||||
printf_filtered ("* ");
|
||||
else
|
||||
printf_filtered (" ");
|
||||
|
||||
printf_filtered ("%d %s", tp->num, target_tid_to_str (tp->ptid));
|
||||
|
||||
extra_info = target_extra_thread_info (tp);
|
||||
if (extra_info)
|
||||
printf_filtered (" (%s)", extra_info);
|
||||
puts_filtered (" ");
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Restores the current thread and the frame selected before
|
||||
the "info threads" command. */
|
||||
do_cleanups (old_chain);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
print_thread_info (uiout, -1);
|
||||
}
|
||||
|
||||
/* Switch from one thread to another. */
|
||||
|
Loading…
Reference in New Issue
Block a user