* 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>
+
+ * 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.
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;
}
struct target_ops *
inf_ptrace_target (void)
{
- struct target_ops *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;
+ static struct target_ops *t;
+
+ 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;
}
\f
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;
}
#include "gdb_string.h"
#include "linux-fork.h"
#include "linux-nat.h"
+#include "checkpoint.h"
#include <sys/ptrace.h>
#include "gdb_wait.h"
{
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
/* 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)
{
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)
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)
{
}
/* Switch inferior process (checkpoint) context, by checkpoint id. */
+
static void
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. */
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. */
Detach from a checkpoint (experimental)."),
&detachlist);
- /* Info checkpoints command: list all forks/checkpoints
- currently under gdb's control. */
-
- add_info ("checkpoints", info_checkpoints_command,
- _("IDs of currently known checkpoints."));
+ /* 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;
+
+ /* 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.
+ */
}
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;
}