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:
Michael Snyder
2009-07-26 01:44:32 +00:00
parent ec6f1d7fc6
commit 74ed219893
5 changed files with 137 additions and 94 deletions

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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.
*/
}

View File

@@ -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;
}