示例#1
0
static void
lynx_add_threads_after_attach (int pid)
{
  /* Ugh!  There appears to be no way to get the list of threads
     in the program we just attached to.  So get the list by calling
     the "ps" command.  This is only needed now, as we will then
     keep the thread list up to date thanks to thread creation and
     exit notifications.  */
  FILE *f;
  char buf[256];
  int thread_pid, thread_tid;

  f = popen ("ps atx", "r");
  if (f == NULL)
    perror_with_name ("Cannot get thread list");

  while (fgets (buf, sizeof (buf), f) != NULL)
    if ((sscanf (buf, "%d %d", &thread_pid, &thread_tid) == 2
	 && thread_pid == pid))
    {
      ptid_t thread_ptid = lynx_ptid_build (pid, thread_tid);

      if (!find_thread_ptid (thread_ptid))
	{
	  lynx_debug ("New thread: (pid = %d, tid = %d)",
		      pid, thread_tid);
	  add_thread (thread_ptid, NULL);
	}
    }

  pclose (f);
}
示例#2
0
static int
lynx_detach (int pid)
{
  ptid_t ptid = lynx_ptid_build (pid, 0);
  struct process_info *process;

  process = find_process_pid (pid);
  if (process == NULL)
    return -1;

  lynx_ptrace (PTRACE_DETACH, ptid, 0, 0, 0);
  the_target->mourn (process);
  return 0;
}
示例#3
0
static int
lynx_attach (unsigned long pid)
{
  ptid_t ptid = lynx_ptid_build (pid, 0);

  if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0)
    error ("Cannot attach to process %lu: %s (%d)\n", pid,
	   strerror (errno), errno);

  lynx_add_process (pid, 1);
  lynx_add_threads_after_attach (pid);

  return 0;
}
示例#4
0
static int
lynx_attach (unsigned long pid)
{
  struct process_info *new_process;
  ptid_t ptid = lynx_ptid_build (pid, 0);

  if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0)
    error ("Cannot attach to process %lu: %s (%d)\n", pid,
	   strerror (errno), errno);

  new_process = add_process (pid, 1);
  add_thread (ptid, NULL);

  return 0;
}
示例#5
0
static int
lynx_kill (int pid)
{
  ptid_t ptid = lynx_ptid_build (pid, 0);
  struct target_waitstatus status;
  struct process_info *process;

  process = find_process_pid (pid);
  if (process == NULL)
    return -1;

  lynx_ptrace (PTRACE_KILL, ptid, 0, 0, 0);
  lynx_wait (ptid, &status, 0);
  the_target->mourn (process);
  return 0;
}
示例#6
0
static ptid_t
lynx_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options)
{
  int pid;
  int ret;
  int wstat;
  ptid_t new_ptid;

  if (ptid_equal (ptid, minus_one_ptid))
    pid = lynx_ptid_get_pid (thread_to_gdb_id (current_thread));
  else
    pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));

retry:

  ret = lynx_waitpid (pid, &wstat);
  new_ptid = lynx_ptid_build (ret, ((union wait *) &wstat)->w_tid);
  find_process_pid (ret)->priv->last_wait_event_ptid = new_ptid;

  /* If this is a new thread, then add it now.  The reason why we do
     this here instead of when handling new-thread events is because
     we need to add the thread associated to the "main" thread - even
     for non-threaded applications where the new-thread events are not
     generated.  */
  if (!find_thread_ptid (new_ptid))
    {
      lynx_debug ("New thread: (pid = %d, tid = %d)",
		  lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid));
      add_thread (new_ptid, NULL);
    }

  if (WIFSTOPPED (wstat))
    {
      status->kind = TARGET_WAITKIND_STOPPED;
      status->value.integer = gdb_signal_from_host (WSTOPSIG (wstat));
      lynx_debug ("process stopped with signal: %d",
                  status->value.integer);
    }
  else if (WIFEXITED (wstat))
    {
      status->kind = TARGET_WAITKIND_EXITED;
      status->value.integer = WEXITSTATUS (wstat);
      lynx_debug ("process exited with code: %d", status->value.integer);
    }
  else if (WIFSIGNALED (wstat))
    {
      status->kind = TARGET_WAITKIND_SIGNALLED;
      status->value.integer = gdb_signal_from_host (WTERMSIG (wstat));
      lynx_debug ("process terminated with code: %d",
                  status->value.integer);
    }
  else
    {
      /* Not sure what happened if we get here, or whether we can
	 in fact get here.  But if we do, handle the event the best
	 we can.  */
      status->kind = TARGET_WAITKIND_STOPPED;
      status->value.integer = gdb_signal_from_host (0);
      lynx_debug ("unknown event ????");
    }

  /* SIGTRAP events are generated for situations other than single-step/
     breakpoint events (Eg. new-thread events).  Handle those other types
     of events, and resume the execution if necessary.  */
  if (status->kind == TARGET_WAITKIND_STOPPED
      && status->value.integer == GDB_SIGNAL_TRAP)
    {
      const int realsig = lynx_ptrace (PTRACE_GETTRACESIG, new_ptid, 0, 0, 0);

      lynx_debug ("(realsig = %d)", realsig);
      switch (realsig)
	{
	  case SIGNEWTHREAD:
	    /* We just added the new thread above.  No need to do anything
	       further.  Just resume the execution again.  */
	    lynx_continue (new_ptid);
	    goto retry;

	  case SIGTHREADEXIT:
	    remove_thread (find_thread_ptid (new_ptid));
	    lynx_continue (new_ptid);
	    goto retry;
	}
    }

  return new_ptid;
}