This is the mail archive of the rda@sources.redhat.com mailing list for the rda project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add attach functionality; use vfork() instead of fork()


I've just committed the following patch to the rda sources.  It adds
"attach" functionality to rda, allowing the user to use rda to attach
to and debug an existing process.  It also uses fork() instead of
vfork() in order to allow rda to be used on systems which do not
support fork().

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

Index: ptrace-target.c
===================================================================
RCS file: /cvs/src/src/rda/unix/ptrace-target.c,v
retrieving revision 1.4
diff -u -p -r1.4 ptrace-target.c
--- ptrace-target.c	7 Feb 2003 23:03:09 -0000	1.4
+++ ptrace-target.c	10 Mar 2004 17:52:52 -0000
@@ -68,10 +68,12 @@ close_open_files (void)
 
 /* 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: */
@@ -81,37 +83,51 @@ ptrace_create_child (struct child_proces
 {
   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;
Index: server.c
===================================================================
RCS file: /cvs/src/src/rda/unix/server.c,v
retrieving revision 1.2
diff -u -p -r1.2 server.c
--- server.c	7 Feb 2003 23:03:09 -0000	1.2
+++ server.c	10 Mar 2004 17:52:52 -0000
@@ -55,10 +55,12 @@ static void
 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"
@@ -68,8 +70,9 @@ usage (char *progname)
     "                   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);
 }
 
@@ -79,6 +82,7 @@ main (int argc, char **argv)
   int portno;
   char *endptr;
   int verbose = 0;
+  int attach = 0;
   int optidx;
   struct child_process *process;
 
@@ -89,6 +93,9 @@ main (int argc, char **argv)
 	{
 	  switch (argv[optidx][1])
 	    {
+	      case 'a':
+		attach = 1;
+		break;
 	      case 'h':
 		usage (argv[0]);
 		/* not reached */
@@ -116,8 +123,17 @@ main (int argc, char **argv)
 
   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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]