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