2009-05-16  Zheng Da  <zhengda1936@gmail.com>

	* rpctrace.c (print_contents): Set the task port and thread port
	when seeing thread_create() and task_create() replies.
	(trace_and_forward): Check exec_startup_get_info to find the main
	thread of the traced task.
	
diff --git a/utils/rpctrace.c b/utils/rpctrace.c
index d80f41d..595cf11 100644
--- a/utils/rpctrace.c
+++ b/utils/rpctrace.c
@@ -82,6 +82,8 @@ msgid_ihash_cleanup (void *element, void *arg)
 static struct hurd_ihash msgid_ihash
   = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP);
 
+task_t traced_task;
+
 /* Parse a file of RPC names and message IDs as output by mig's -list
    option: "subsystem base-id routine n request-id reply-id".  Put each
    request-id value into `msgid_ihash' with the routine name as its value.  */
@@ -549,6 +551,7 @@ print_contents (mach_msg_header_t *inp,
 	  poly = 0;
 	  for (i = 0; i < nelt; ++i)
 	    {
+	      mach_port_t orig_port = portnames[i];
 	      newtypes[i] = name;
 
 	      if (inp->msgh_id == 3215) /* mach_port_insert_right */
@@ -563,6 +566,41 @@ print_contents (mach_msg_header_t *inp,
 
 	      ti = rewrite_right (&portnames[i], &newtypes[i]);
 
+	      if (inp->msgh_id == 2161 /* the reply message for thread_create */
+		  || inp->msgh_id == 2107 /* for task_create */)
+		{
+		  err = mach_port_insert_right (mach_task_self (),
+						portnames[i], portnames[i],
+						MACH_MSG_TYPE_MAKE_SEND);
+		  if (err)
+		    error (0, err, "mach_port_insert_right");
+
+		  if (inp->msgh_id == 2161) /* thread_create reply */
+		    {
+		      err = thread_set_kernel_port (orig_port, portnames[i]);
+		      if (err)
+			error (0, err, "thread_set_kernel_port");
+		      if (ti->name == NULL)
+			asprintf (&ti->name, "thread(port %d)", (int) orig_port);
+		    }
+		  else /* task_create reply */
+		    {
+		      pid_t pid;
+		      err = task_set_kernel_port (orig_port, portnames[i]);
+		      if (err)
+			error (0, err, "thread_set_kernel_port");
+		      if (ti->name == NULL)
+			{
+			  pid = task2pid (orig_port);
+			  if (pid < 0)
+			    error (0, errno, "task2pid");
+			  asprintf (&ti->name, "task%d", (int) pid);
+			}
+		    }
+
+		  mach_port_deallocate (mach_task_self (), portnames[i]);
+		}
+
 	      putc ((i == 0 && nelt > 1) ? '{' : ' ', ostream);
 
 	      if (portnames[i] == MACH_PORT_NULL)
@@ -706,6 +744,44 @@ trace_and_forward (mach_msg_header_t *inp, mach_msg_header_t *outp)
 
   msgid = msgid_info (inp->msgh_id);
 
+  /* If it's the request of exec_startup_get_info,
+   * it means that the traced process starts running.  */
+  if (inp->msgh_id == 30500)
+    {
+      struct traced_info *info;
+      thread_t *threads = NULL;
+      size_t nthreads = 0;
+      err = task_threads (traced_task, &threads, &nthreads);
+      if (err)
+	error (1, err, "task_threads");
+
+      for (int i = 0; i < nthreads; i++)
+	{
+	  /* If we haven't seen the port already.  */
+	  info = hurd_ihash_find (&traced_names, threads[i]);
+	  if (info == NULL)
+	    {
+	      mach_port_t new_thread_port;
+	      info = new_send_wrapper (threads[i], &new_thread_port);
+	      if (info->name == NULL)
+		asprintf (&info->name, "thread(port %d)", (int) threads[i]);
+	      
+	      err = mach_port_insert_right (mach_task_self (),
+					    new_thread_port, new_thread_port,
+					    MACH_MSG_TYPE_MAKE_SEND);
+	      if (err)
+		error (0, err, "mach_port_insert_right");
+
+	      err = thread_set_kernel_port (threads[i], new_thread_port);
+	      if (err)
+		error (0, err, "thread_set_kernel_port");
+
+	      mach_port_deallocate (mach_task_self (), new_thread_port);
+	    }
+	}
+      munmap (threads, nthreads * sizeof (thread_t));
+    }
+
   /* Swap the header data like a crossover cable. */
   {
     mach_msg_type_name_t this_type = MACH_MSGH_BITS_LOCAL (inp->msgh_bits);
@@ -1014,8 +1092,6 @@ print_data (mach_msg_type_name_t type,
 
 /*** Main program and child startup ***/
 
-task_t traced_task;
-
 
 /* Run a child and have it do more or else `execvpe (argv, envp);'.  */
 pid_t
