+2004-03-10 Kevin Buettner <kevinb@redhat.com>
+
+ * ptrace-target.c (ptrace_create_child): Use vfork() instead of
+ fork(). Use PTRACE_ATTACH to attach to an existing process.
+ * server.c (usage): Update to include text about "-a".
+ (main): Allow use of -a switch to attach to an existing process.
+
2003-11-14 Kevin Buettner <kevinb@redhat.com>
* config.in (FRV_LINUX_TARGET): Add.
/* ptrace_create_child:
- Fork the child process and capture it via ptrace.
+ Either attach to an existing process or fork a child and capture
+ it via PTRACE_TRACEME.
+
+ The single argument PROCESS is a struct containing either the
+ process id to attach to or the file name and arguments to execute.
- Args: char *exec_path; \* path to executable file *\
- char **all_args; \* argv array for child. *\
*/
/* Local Functions: */
{
int pid;
- pid = fork ();
- if (pid < 0)
+ if (process->pid > 0)
{
- /*perror_with_name ("fork");*/
- fprintf (stderr, "PTRACE: fork failed!\n");
- return 0;
- }
+ pid = process->pid;
- if (pid == 0)
- {
- close_open_files ();
- if (process->debug_backend)
- fprintf (stderr, "PTRACE_TRACEME\n");
errno = 0;
- ptrace (PTRACE_TRACEME, 0L, 0L, 0L);
+ ptrace (PTRACE_ATTACH, pid, 0L, 0L);
if (errno != 0)
{
- fprintf (stderr, "PTRACE: child cannot be traced!\n");
- goto fail;
+ fprintf (stderr, "Could not attach to process id %d\n", pid);
+ exit (1);
+ }
+ }
+ else
+ {
+ pid = vfork ();
+ if (pid < 0)
+ {
+ fprintf (stderr, "PTRACE: vfork failed!\n");
+ return 0;
+ }
+
+ if (pid == 0)
+ {
+ close_open_files ();
+ if (process->debug_backend)
+ fprintf (stderr, "PTRACE_TRACEME\n");
+ errno = 0;
+ ptrace (PTRACE_TRACEME, 0L, 0L, 0L);
+ if (errno != 0)
+ {
+ fprintf (stderr, "PTRACE: child cannot be traced!\n");
+ goto fail;
+ }
+ if (process->executable != NULL && process->argv != NULL)
+ execv (process->executable, process->argv);
+ else
+ sleep (-1); /* FIXME ??? */
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", process->executable,
+ errno > 0 && errno < sys_nerr ?
+ strerror (errno) : "unknown error");
+ fail:
+ fflush (stderr);
+ _exit (0177);
}
- if (process->executable != NULL && process->argv != NULL)
- execv (process->executable, process->argv);
- else
- sleep (-1); /* FIXME ??? */
-
- fprintf (stderr, "Cannot exec %s: %s.\n", process->executable,
- errno > 0 && errno < sys_nerr ?
- strerror (errno) : "unknown error");
- fail:
- fflush (stderr);
- _exit (0177);
}
return pid;
usage (char *progname)
{
fprintf (stderr,
- "Usage: %s [-h] [-v] tcp-port-num executable-file [arguments ...]\n\n"
+ "Usage: %s [-h] [-v] tcp-port-num executable-file [arguments ...]\n"
+ " or: %s -a [-v] tcp-port-num process-id\n\n"
"Start the Red Hat debug agent listening on port ``tcp-port-num'' for\n"
"debugging``executable-file'' with optional arguments.\n\n"
"Options and arguments:\n"
+ " -a Attach to already running process.\n"
" -h Print this usage message.\n"
" -v Increase verbosity. One -v flag enables informational\n"
" messages. Two -v flags turn on internal debugging\n"
" remote protocol.\n"
" executable-file Name of program to debug.\n"
" arguments ... Command line arguments with which to start program\n"
- " being debugged.\n",
- progname);
+ " being debugged.\n"
+ " process-id Process ID (PID) of process to attach to.\n",
+ progname, progname);
exit (1);
}
int portno;
char *endptr;
int verbose = 0;
+ int attach = 0;
int optidx;
struct child_process *process;
{
switch (argv[optidx][1])
{
+ case 'a':
+ attach = 1;
+ break;
case 'h':
usage (argv[0]);
/* not reached */
process = malloc (sizeof (struct child_process));
memset (process, 0, sizeof (struct child_process));
- process->argv = &argv[optidx + 1];
- process->executable = argv[optidx + 1];
+ if (attach)
+ {
+ process->pid = strtol (argv[optidx + 1], &endptr, 10);
+ if (errno != 0 || endptr == argv[optidx] || process->pid <= 0)
+ usage (argv[0]);
+ }
+ else
+ {
+ process->argv = &argv[optidx + 1];
+ process->executable = argv[optidx + 1];
+ }
if (verbose > 1)
process->debug_backend = 1;