forked from Imagelibrary/binutils-gdb
2009-07-25 Michael Snyder <msnyder@vmware.com>
* inf-child.c (inf_child_target): Initialize target_ops only once. * inf-ptrace.c (inf_ptrace_target): Ditto. (inf_ptrace_trad_target): Ditto. * linux-nat.c (linux_target): Ditto. (linux_trad_target): Ditto. * linux-fork.c (_initialize_linux_fork): Rather than calling add_cmd to add checkpoint commands, use 'linux_target' to get the target vector, add the checkpoint functions to it, and call checkpoint_init to activate the user commands. (linux_fork_killall): Add optional verbose output.
This commit is contained in:
@@ -1,3 +1,17 @@
|
||||
2009-07-25 Michael Snyder <msnyder@vmware.com>
|
||||
|
||||
* inf-child.c (inf_child_target): Initialize target_ops only once.
|
||||
* inf-ptrace.c (inf_ptrace_target): Ditto.
|
||||
(inf_ptrace_trad_target): Ditto.
|
||||
* linux-nat.c (linux_target): Ditto.
|
||||
(linux_trad_target): Ditto.
|
||||
|
||||
* linux-fork.c (_initialize_linux_fork): Rather than calling
|
||||
add_cmd to add checkpoint commands, use 'linux_target' to
|
||||
get the target vector, add the checkpoint functions to it,
|
||||
and call checkpoint_init to activate the user commands.
|
||||
(linux_fork_killall): Add optional verbose output.
|
||||
|
||||
2009-07-25 Michael Snyder <msnyder@vmware.com>
|
||||
|
||||
* checkpoint.c: New file, target-agnostic checkpoints.
|
||||
|
||||
@@ -164,40 +164,46 @@ inf_child_pid_to_exec_file (int pid)
|
||||
struct target_ops *
|
||||
inf_child_target (void)
|
||||
{
|
||||
struct target_ops *t = XZALLOC (struct target_ops);
|
||||
t->to_shortname = "child";
|
||||
t->to_longname = "Unix child process";
|
||||
t->to_doc = "Unix child process (started by the \"run\" command).";
|
||||
t->to_open = inf_child_open;
|
||||
t->to_post_attach = inf_child_post_attach;
|
||||
t->to_fetch_registers = inf_child_fetch_inferior_registers;
|
||||
t->to_store_registers = inf_child_store_inferior_registers;
|
||||
t->to_prepare_to_store = inf_child_prepare_to_store;
|
||||
t->to_insert_breakpoint = memory_insert_breakpoint;
|
||||
t->to_remove_breakpoint = memory_remove_breakpoint;
|
||||
t->to_terminal_init = terminal_init_inferior;
|
||||
t->to_terminal_inferior = terminal_inferior;
|
||||
t->to_terminal_ours_for_output = terminal_ours_for_output;
|
||||
t->to_terminal_save_ours = terminal_save_ours;
|
||||
t->to_terminal_ours = terminal_ours;
|
||||
t->to_terminal_info = child_terminal_info;
|
||||
t->to_post_startup_inferior = inf_child_post_startup_inferior;
|
||||
t->to_acknowledge_created_inferior = inf_child_acknowledge_created_inferior;
|
||||
t->to_insert_fork_catchpoint = inf_child_insert_fork_catchpoint;
|
||||
t->to_remove_fork_catchpoint = inf_child_remove_fork_catchpoint;
|
||||
t->to_insert_vfork_catchpoint = inf_child_insert_vfork_catchpoint;
|
||||
t->to_remove_vfork_catchpoint = inf_child_remove_vfork_catchpoint;
|
||||
t->to_follow_fork = inf_child_follow_fork;
|
||||
t->to_insert_exec_catchpoint = inf_child_insert_exec_catchpoint;
|
||||
t->to_remove_exec_catchpoint = inf_child_remove_exec_catchpoint;
|
||||
t->to_can_run = inf_child_can_run;
|
||||
t->to_pid_to_exec_file = inf_child_pid_to_exec_file;
|
||||
t->to_stratum = process_stratum;
|
||||
t->to_has_all_memory = default_child_has_all_memory;
|
||||
t->to_has_memory = default_child_has_memory;
|
||||
t->to_has_stack = default_child_has_stack;
|
||||
t->to_has_registers = default_child_has_registers;
|
||||
t->to_has_execution = default_child_has_execution;
|
||||
t->to_magic = OPS_MAGIC;
|
||||
static struct target_ops *t;
|
||||
|
||||
if (t == NULL) /* Actually init only once. */
|
||||
{
|
||||
t = XZALLOC (struct target_ops);
|
||||
t->to_shortname = "child";
|
||||
t->to_longname = "Unix child process";
|
||||
t->to_doc = "Unix child process (started by the \"run\" command).";
|
||||
t->to_open = inf_child_open;
|
||||
t->to_post_attach = inf_child_post_attach;
|
||||
t->to_fetch_registers = inf_child_fetch_inferior_registers;
|
||||
t->to_store_registers = inf_child_store_inferior_registers;
|
||||
t->to_prepare_to_store = inf_child_prepare_to_store;
|
||||
t->to_insert_breakpoint = memory_insert_breakpoint;
|
||||
t->to_remove_breakpoint = memory_remove_breakpoint;
|
||||
t->to_terminal_init = terminal_init_inferior;
|
||||
t->to_terminal_inferior = terminal_inferior;
|
||||
t->to_terminal_ours_for_output = terminal_ours_for_output;
|
||||
t->to_terminal_save_ours = terminal_save_ours;
|
||||
t->to_terminal_ours = terminal_ours;
|
||||
t->to_terminal_info = child_terminal_info;
|
||||
t->to_post_startup_inferior = inf_child_post_startup_inferior;
|
||||
t->to_acknowledge_created_inferior
|
||||
= inf_child_acknowledge_created_inferior;
|
||||
t->to_insert_fork_catchpoint = inf_child_insert_fork_catchpoint;
|
||||
t->to_remove_fork_catchpoint = inf_child_remove_fork_catchpoint;
|
||||
t->to_insert_vfork_catchpoint = inf_child_insert_vfork_catchpoint;
|
||||
t->to_remove_vfork_catchpoint = inf_child_remove_vfork_catchpoint;
|
||||
t->to_follow_fork = inf_child_follow_fork;
|
||||
t->to_insert_exec_catchpoint = inf_child_insert_exec_catchpoint;
|
||||
t->to_remove_exec_catchpoint = inf_child_remove_exec_catchpoint;
|
||||
t->to_can_run = inf_child_can_run;
|
||||
t->to_pid_to_exec_file = inf_child_pid_to_exec_file;
|
||||
t->to_stratum = process_stratum;
|
||||
t->to_has_all_memory = default_child_has_all_memory;
|
||||
t->to_has_memory = default_child_has_memory;
|
||||
t->to_has_stack = default_child_has_stack;
|
||||
t->to_has_registers = default_child_has_registers;
|
||||
t->to_has_execution = default_child_has_execution;
|
||||
t->to_magic = OPS_MAGIC;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -606,26 +606,30 @@ inf_ptrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
|
||||
struct target_ops *
|
||||
inf_ptrace_target (void)
|
||||
{
|
||||
struct target_ops *t = inf_child_target ();
|
||||
static struct target_ops *t;
|
||||
|
||||
t->to_attach = inf_ptrace_attach;
|
||||
t->to_detach = inf_ptrace_detach;
|
||||
t->to_resume = inf_ptrace_resume;
|
||||
t->to_wait = inf_ptrace_wait;
|
||||
t->to_files_info = inf_ptrace_files_info;
|
||||
t->to_kill = inf_ptrace_kill;
|
||||
t->to_create_inferior = inf_ptrace_create_inferior;
|
||||
if (t == NULL) /* Actually init only once. */
|
||||
{
|
||||
t = inf_child_target ();
|
||||
|
||||
t->to_attach = inf_ptrace_attach;
|
||||
t->to_detach = inf_ptrace_detach;
|
||||
t->to_resume = inf_ptrace_resume;
|
||||
t->to_wait = inf_ptrace_wait;
|
||||
t->to_files_info = inf_ptrace_files_info;
|
||||
t->to_kill = inf_ptrace_kill;
|
||||
t->to_create_inferior = inf_ptrace_create_inferior;
|
||||
#ifdef PT_GET_PROCESS_STATE
|
||||
t->to_follow_fork = inf_ptrace_follow_fork;
|
||||
t->to_post_startup_inferior = inf_ptrace_post_startup_inferior;
|
||||
t->to_post_attach = inf_ptrace_post_attach;
|
||||
t->to_follow_fork = inf_ptrace_follow_fork;
|
||||
t->to_post_startup_inferior = inf_ptrace_post_startup_inferior;
|
||||
t->to_post_attach = inf_ptrace_post_attach;
|
||||
#endif
|
||||
t->to_mourn_inferior = inf_ptrace_mourn_inferior;
|
||||
t->to_thread_alive = inf_ptrace_thread_alive;
|
||||
t->to_pid_to_str = inf_ptrace_pid_to_str;
|
||||
t->to_stop = inf_ptrace_stop;
|
||||
t->to_xfer_partial = inf_ptrace_xfer_partial;
|
||||
|
||||
t->to_mourn_inferior = inf_ptrace_mourn_inferior;
|
||||
t->to_thread_alive = inf_ptrace_thread_alive;
|
||||
t->to_pid_to_str = inf_ptrace_pid_to_str;
|
||||
t->to_stop = inf_ptrace_stop;
|
||||
t->to_xfer_partial = inf_ptrace_xfer_partial;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -759,14 +763,17 @@ inf_ptrace_store_registers (struct target_ops *ops,
|
||||
|
||||
struct target_ops *
|
||||
inf_ptrace_trad_target (CORE_ADDR (*register_u_offset)
|
||||
(struct gdbarch *, int, int))
|
||||
(struct gdbarch *, int, int))
|
||||
{
|
||||
struct target_ops *t = inf_ptrace_target();
|
||||
|
||||
gdb_assert (register_u_offset);
|
||||
inf_ptrace_register_u_offset = register_u_offset;
|
||||
t->to_fetch_registers = inf_ptrace_fetch_registers;
|
||||
t->to_store_registers = inf_ptrace_store_registers;
|
||||
static struct target_ops *t;
|
||||
|
||||
if (t == NULL)
|
||||
{
|
||||
t = inf_ptrace_target();
|
||||
gdb_assert (register_u_offset);
|
||||
inf_ptrace_register_u_offset = register_u_offset;
|
||||
t->to_fetch_registers = inf_ptrace_fetch_registers;
|
||||
t->to_store_registers = inf_ptrace_store_registers;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "gdb_string.h"
|
||||
#include "linux-fork.h"
|
||||
#include "linux-nat.h"
|
||||
#include "checkpoint.h"
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include "gdb_wait.h"
|
||||
@@ -334,8 +335,10 @@ linux_fork_killall (void)
|
||||
{
|
||||
pid = PIDGET (fp->ptid);
|
||||
do {
|
||||
/* Use SIGKILL instead of PTRACE_KILL because the former works even
|
||||
if the thread is running, while the later doesn't. */
|
||||
/* Use SIGKILL instead of PTRACE_KILL because the former works
|
||||
even if the thread is running, while the later doesn't. */
|
||||
if (info_verbose)
|
||||
printf_filtered (_("Killing checkpoint/fork %d.\n"), pid);
|
||||
kill (pid, SIGKILL);
|
||||
ret = waitpid (pid, &status, 0);
|
||||
/* We might get a SIGCHLD instead of an exit status. This is
|
||||
@@ -414,6 +417,9 @@ linux_fork_detach (char *args, int from_tty)
|
||||
|
||||
/* Fork list <-> user interface. */
|
||||
|
||||
/* Delete checkpoint command: kill the process and remove it from
|
||||
the fork list. */
|
||||
|
||||
static void
|
||||
delete_checkpoint_command (char *args, int from_tty)
|
||||
{
|
||||
@@ -464,7 +470,8 @@ Please switch to another checkpoint before detaching the current one"));
|
||||
delete_fork (ptid);
|
||||
}
|
||||
|
||||
/* Print information about currently known checkpoints. */
|
||||
/* Info checkpoints command: list all forks/checkpoints
|
||||
currently under gdb's control. */
|
||||
|
||||
static void
|
||||
info_checkpoints_command (char *arg, int from_tty)
|
||||
@@ -545,6 +552,9 @@ linux_fork_checkpointing_p (int pid)
|
||||
return (checkpointing_pid == pid);
|
||||
}
|
||||
|
||||
/* checkpoint_command: create a fork of the inferior process
|
||||
and set it aside for later debugging. */
|
||||
|
||||
static void
|
||||
checkpoint_command (char *args, int from_tty)
|
||||
{
|
||||
@@ -629,6 +639,7 @@ linux_fork_context (struct fork_info *newfp, int from_tty)
|
||||
}
|
||||
|
||||
/* Switch inferior process (checkpoint) context, by checkpoint id. */
|
||||
|
||||
static void
|
||||
restart_command (char *args, int from_tty)
|
||||
{
|
||||
@@ -646,6 +657,8 @@ restart_command (char *args, int from_tty)
|
||||
void
|
||||
_initialize_linux_fork (void)
|
||||
{
|
||||
struct target_ops *t;
|
||||
|
||||
init_fork_list ();
|
||||
|
||||
/* Set/show detach-on-fork: user-settable mode. */
|
||||
@@ -656,26 +669,6 @@ Show whether gdb will detach the child of a fork."), _("\
|
||||
Tells gdb whether to detach the child of a fork."),
|
||||
NULL, NULL, &setlist, &showlist);
|
||||
|
||||
/* Checkpoint command: create a fork of the inferior process
|
||||
and set it aside for later debugging. */
|
||||
|
||||
add_com ("checkpoint", class_obscure, checkpoint_command, _("\
|
||||
Fork a duplicate process (experimental)."));
|
||||
|
||||
/* Restart command: restore the context of a specified checkpoint
|
||||
process. */
|
||||
|
||||
add_com ("restart", class_obscure, restart_command, _("\
|
||||
restart <n>: restore program context from a checkpoint.\n\
|
||||
Argument 'n' is checkpoint ID, as displayed by 'info checkpoints'."));
|
||||
|
||||
/* Delete checkpoint command: kill the process and remove it from
|
||||
the fork list. */
|
||||
|
||||
add_cmd ("checkpoint", class_obscure, delete_checkpoint_command, _("\
|
||||
Delete a checkpoint (experimental)."),
|
||||
&deletelist);
|
||||
|
||||
/* Detach checkpoint command: release the process to run independently,
|
||||
and remove it from the fork list. */
|
||||
|
||||
@@ -683,9 +676,28 @@ Delete a checkpoint (experimental)."),
|
||||
Detach from a checkpoint (experimental)."),
|
||||
&detachlist);
|
||||
|
||||
/* Info checkpoints command: list all forks/checkpoints
|
||||
currently under gdb's control. */
|
||||
/* Get the linux target vector. */
|
||||
t = linux_target ();
|
||||
/* Add checkpoint target methods. */
|
||||
t->to_set_checkpoint = checkpoint_command;
|
||||
t->to_unset_checkpoint = delete_checkpoint_command;
|
||||
t->to_restore_checkpoint = restart_command;
|
||||
t->to_info_checkpoints = info_checkpoints_command;
|
||||
|
||||
add_info ("checkpoints", info_checkpoints_command,
|
||||
_("IDs of currently known checkpoints."));
|
||||
/* Activate the checkpoint module. */
|
||||
checkpoint_init ();
|
||||
|
||||
/* XXX mvs call linux_target and add checkpoint methods.
|
||||
to_set_checkpoint
|
||||
to_unset_checkpoint
|
||||
to_info_checkpoints (maybe this could be common? Maybe not?
|
||||
to_detach_checkpoint (esoteric?)
|
||||
to_restore_checkpoint.
|
||||
|
||||
Make a new module called checkpoint.c, include it always, but
|
||||
don't make it auto-initialize like most modules. Instead,
|
||||
give it a global entry point checkpoint_init, which has to be
|
||||
called explicitly by targets that want to activate the
|
||||
checkpoint commands.
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -4306,22 +4306,26 @@ linux_target_install_ops (struct target_ops *t)
|
||||
struct target_ops *
|
||||
linux_target (void)
|
||||
{
|
||||
struct target_ops *t;
|
||||
|
||||
t = inf_ptrace_target ();
|
||||
linux_target_install_ops (t);
|
||||
static struct target_ops *t;
|
||||
|
||||
if (t == NULL)
|
||||
{
|
||||
t = inf_ptrace_target ();
|
||||
linux_target_install_ops (t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
struct target_ops *
|
||||
linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
|
||||
{
|
||||
struct target_ops *t;
|
||||
|
||||
t = inf_ptrace_trad_target (register_u_offset);
|
||||
linux_target_install_ops (t);
|
||||
static struct target_ops *t;
|
||||
|
||||
if (t == NULL)
|
||||
{
|
||||
t = inf_ptrace_trad_target (register_u_offset);
|
||||
linux_target_install_ops (t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user