static void nbsd_update_thread_list (struct target_ops *ops) { int retval; ptid_t ptid; if (nbsd_thread_active == 0) return; if (ptid_equal (inferior_ptid, minus_one_ptid)) { printf_filtered ("No process.\n"); return; } if (target_has_execution) { struct ptrace_lwpinfo pl; pl.pl_lwpid = 0; retval = ptrace (PT_LWPINFO, ptid_get_pid(inferior_ptid), (void *)&pl, sizeof(pl)); while ((retval != -1) && pl.pl_lwpid != 0) { ptid = ptid_build (ptid_get_pid (main_ptid), pl.pl_lwpid, 0); if (!in_thread_list (ptid)) add_thread (ptid); retval = ptrace (PT_LWPINFO, ptid_get_pid(inferior_ptid), (void *)&pl, sizeof(pl)); } } }
static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, const td_thrinfo_t *ti_p, int verbose) { td_err_e err; /* Add the thread to GDB's thread list. */ if (!in_thread_list (ptid)) { add_thread (ptid); if (verbose) printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid)); } if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) return; /* A zombie thread -- do not attach. */ if (! IS_THREAD(ptid)) return; if (fbsd_thread_core != 0) return; /* Enable thread event reporting for this thread. */ err = td_thr_event_enable_p (th_p, 1); if (err != TD_OK) error ("Cannot enable thread event reporting for %s: %s", target_pid_to_str (ptid), thread_db_err_str (err)); }
static void obsd_update_thread_list (struct target_ops *ops) { pid_t pid = ptid_get_pid (inferior_ptid); struct ptrace_thread_state pts; prune_threads (); if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1) perror_with_name (("ptrace")); while (pts.pts_tid != -1) { ptid_t ptid = ptid_build (pid, pts.pts_tid, 0); if (!in_thread_list (ptid)) { if (ptid_get_lwp (inferior_ptid) == 0) thread_change_ptid (inferior_ptid, ptid); else add_thread (ptid); } if (ptrace (PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1) perror_with_name (("ptrace")); } }
static void fbsd_add_threads (pid_t pid) { struct cleanup *cleanup; lwpid_t *lwps; int i, nlwps; gdb_assert (!in_thread_list (pid_to_ptid (pid))); nlwps = ptrace (PT_GETNUMLWPS, pid, NULL, 0); if (nlwps == -1) perror_with_name (("ptrace")); lwps = XCNEWVEC (lwpid_t, nlwps); cleanup = make_cleanup (xfree, lwps); nlwps = ptrace (PT_GETLWPLIST, pid, (caddr_t) lwps, nlwps); if (nlwps == -1) perror_with_name (("ptrace")); for (i = 0; i < nlwps; i++) { ptid_t ptid = ptid_build (pid, lwps[i], 0); if (!in_thread_list (ptid)) { #ifdef PT_LWP_EVENTS struct ptrace_lwpinfo pl; /* Don't add exited threads. Note that this is only called when attaching to a multi-threaded process. */ if (ptrace (PT_LWPINFO, lwps[i], (caddr_t) &pl, sizeof pl) == -1) perror_with_name (("ptrace")); if (pl.pl_flags & PL_FLAG_EXITED) continue; #endif if (debug_fbsd_lwp) fprintf_unfiltered (gdb_stdlog, "FLWP: adding thread for LWP %u\n", lwps[i]); add_thread (ptid); } } do_cleanups (cleanup); }
static ptid_t sol_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus) { ptid_t rtnval; ptid_t save_ptid; struct cleanup *old_chain; save_ptid = inferior_ptid; old_chain = save_inferior_ptid (); inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid)); if (PIDGET (inferior_ptid) == -1) inferior_ptid = procfs_first_available (); if (PIDGET (ptid) != -1) { ptid_t save_ptid = ptid; ptid = thread_to_lwp (ptid, -2); if (PIDGET (ptid) == -2) /* Inactive thread */ error ("This version of Solaris can't start inactive threads."); if (info_verbose && PIDGET (ptid) == -1) warning ("Specified thread %ld seems to have terminated", GET_THREAD (save_ptid)); } rtnval = procfs_ops.to_wait (ptid, ourstatus); if (ourstatus->kind != TARGET_WAITKIND_EXITED) { /* Map the LWP of interest back to the appropriate thread ID */ rtnval = lwp_to_thread (rtnval); if (PIDGET (rtnval) == -1) rtnval = save_ptid; /* See if we have a new thread */ if (is_thread (rtnval) && !ptid_equal (rtnval, save_ptid) && !in_thread_list (rtnval)) { printf_filtered ("[New %s]\n", target_pid_to_str (rtnval)); add_thread (rtnval); } } /* During process initialization, we may get here without the thread package being initialized, since that can only happen after we've found the shared libs. */ do_cleanups (old_chain); return rtnval; }
static void check_event (ptid_t ptid) { struct regcache *regcache = get_thread_regcache (ptid); struct gdbarch *gdbarch = get_regcache_arch (regcache); td_event_msg_t msg; td_thrinfo_t ti; td_err_e err; CORE_ADDR stop_pc; int loop = 0; /* Bail out early if we're not at a thread event breakpoint. */ stop_pc = regcache_read_pc (regcache) - gdbarch_decr_pc_after_break (gdbarch); if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr) return; loop = 1; do { err = td_ta_event_getmsg_p (thread_agent, &msg); if (err != TD_OK) { if (err == TD_NOMSG) return; error ("Cannot get thread event message: %s", thread_db_err_str (err)); } err = td_thr_get_info_p ((void *)(uintptr_t)msg.th_p, &ti); if (err != TD_OK) error ("Cannot get thread info: %s", thread_db_err_str (err)); ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid)); switch (msg.event) { case TD_CREATE: /* We may already know about this thread, for instance when the user has issued the `info threads' command before the SIGTRAP for hitting the thread creation breakpoint was reported. */ attach_thread (ptid, (void *)(uintptr_t)msg.th_p, &ti, 1); break; case TD_DEATH: if (!in_thread_list (ptid)) error ("Spurious thread death event."); detach_thread (ptid, 1); break; default: error ("Spurious thread event."); } } while (loop); }
static void get_current_thread () { td_thrhandle_t th; td_thrinfo_t ti; long lwp; ptid_t tmp, ptid; lwp = get_current_lwp (proc_handle.pid); tmp = BUILD_LWP (lwp, proc_handle.pid); ptid = thread_from_lwp (tmp, &th, &ti); if (!in_thread_list (ptid)) { attach_thread (ptid, &th, &ti, 1); } inferior_ptid = ptid; }
static int sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored) { td_err_e retval; td_thrinfo_t ti; ptid_t ptid; if ((retval = p_td_thr_get_info (th, &ti)) != TD_OK) { return -1; } ptid = BUILD_THREAD (ti.ti_tid, PIDGET (inferior_ptid)); if (!in_thread_list (ptid)) add_thread (ptid); return 0; }
static ptid_t fbsd_thread_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *ourstatus, int options) { struct target_ops *beneath = find_target_beneath (ops); ptid_t ret; long lwp; CORE_ADDR stop_pc; td_thrhandle_t th; td_thrinfo_t ti; ret = beneath->to_wait (beneath, ptid, ourstatus, options); if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED) { lwp = get_current_lwp (GET_PID(ret)); ret = thread_from_lwp (BUILD_LWP(lwp, GET_PID(ret)), &th, &ti); if (!in_thread_list(ret)) { /* * We have to enable event reporting for initial thread * which was not mapped before. */ attach_thread(ret, &th, &ti, 1); } if (ourstatus->value.sig == TARGET_SIGNAL_TRAP) check_event(ret); /* this is a hack, if an event won't cause gdb to stop, for example, SIGALRM, gdb resumes the process immediatly without setting inferior_ptid to the new thread returned here, this is a bug because inferior_ptid may already not exist there, and passing a non-existing thread to fbsd_thread_resume causes error. However, if the exiting thread is the currently selected thread, then that is handled later in handle_inferior_event(), and we must not delete the currently selected thread. */ if (!fbsd_thread_alive (ops, inferior_ptid) && !ptid_equal(inferior_ptid, ret)) { delete_thread (inferior_ptid); inferior_ptid = ret; } } return (ret); }
static void sol_thread_create_inferior (char *exec_file, char *allargs, char **env) { procfs_ops.to_create_inferior (exec_file, allargs, env); if (sol_thread_active && !ptid_equal (inferior_ptid, null_ptid)) { main_ph.ptid = inferior_ptid; /* Save for xfer_memory */ push_target (&sol_thread_ops); inferior_ptid = lwp_to_thread (inferior_ptid); if (PIDGET (inferior_ptid) == -1) inferior_ptid = main_ph.ptid; if (!in_thread_list (inferior_ptid)) add_thread (inferior_ptid); } }
static ptid_t nbsd_thread_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *ourstatus, int options) { ptid_t rtnval; struct target_ops *beneath = find_target_beneath (ops); rtnval = beneath->to_wait (beneath, ptid, ourstatus, options); nbsd_thread_unsuspend(); if (nbsd_thread_active && (ourstatus->kind != TARGET_WAITKIND_EXITED)) { rtnval = find_active_thread (); if (ptid_equal (rtnval, minus_one_ptid)) error ("No active thread!\n"); if (!in_thread_list (rtnval)) add_thread (rtnval); } return rtnval; }
static ptid_t fbsd_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus) { ptid_t ret; long lwp; CORE_ADDR stop_pc; td_thrhandle_t th; td_thrinfo_t ti; ret = child_ops.to_wait (ptid, ourstatus); if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED) { lwp = get_current_lwp (GET_PID(ret)); ret = thread_from_lwp (BUILD_LWP(lwp, GET_PID(ret)), &th, &ti); if (!in_thread_list(ret)) { /* * We have to enable event reporting for initial thread * which was not mapped before. */ attach_thread(ret, &th, &ti, 1); } if (ourstatus->value.sig == TARGET_SIGNAL_TRAP) check_event(ret); /* this is a hack, if an event won't cause gdb to stop, for example, SIGARLM, gdb resumes the process immediatly without setting inferior_ptid to the new thread returned here, this is a bug because inferior_ptid may already not exist there, and passing a none existing thread to fbsd_thread_resume causes error. */ if (!fbsd_thread_alive (inferior_ptid)) { delete_thread (inferior_ptid); inferior_ptid = ret; } } return (ret); }
ptid_t child_wait (ptid_t ptid, struct target_waitstatus *ourstatus) { int save_errno; int thread; union wait status; int pid; while (1) { int sig; set_sigint_trap (); /* Causes SIGINT to be passed on to the attached process. */ pid = wait (&status); save_errno = errno; clear_sigint_trap (); if (pid == -1) { if (save_errno == EINTR) continue; fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n", safe_strerror (save_errno)); /* Claim it exited with unknown signal. */ ourstatus->kind = TARGET_WAITKIND_SIGNALLED; ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; return -1; } if (pid != PIDGET (inferior_ptid)) /* Some other process?!? */ continue; thread = status.w_tid; /* Get thread id from status */ /* Initial thread value can only be acquired via wait, so we have to resort to this hack. */ if (TIDGET (inferior_ptid) == 0 && thread != 0) { inferior_ptid = MERGEPID (PIDGET (inferior_ptid), thread); add_thread (inferior_ptid); } ptid = BUILDPID (pid, thread); /* We've become a single threaded process again. */ if (thread == 0) inferior_ptid = ptid; /* Check for thread creation. */ if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && !in_thread_list (ptid)) { int realsig; realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0); if (realsig == SIGNEWTHREAD) { /* It's a new thread notification. We don't want to much with realsig -- the code in wait_for_inferior expects SIGTRAP. */ ourstatus->kind = TARGET_WAITKIND_SPURIOUS; ourstatus->value.sig = TARGET_SIGNAL_0; return ptid; } else error ("Signal for unknown thread was not SIGNEWTHREAD"); } /* Check for thread termination. */ else if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && in_thread_list (ptid)) { int realsig; realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0); if (realsig == SIGTHREADEXIT) { ptrace (PTRACE_CONT, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0); continue; } } #ifdef SPARC /* SPARC Lynx uses an byte reversed wait status; we must use the host macros to access it. These lines just a copy of store_waitstatus. We can't use CHILD_SPECIAL_WAITSTATUS because target.c can't include the Lynx <sys/wait.h>. */ if (WIFEXITED (status)) { ourstatus->kind = TARGET_WAITKIND_EXITED; ourstatus->value.integer = WEXITSTATUS (status); } else if (!WIFSTOPPED (status)) { ourstatus->kind = TARGET_WAITKIND_SIGNALLED; ourstatus->value.sig = target_signal_from_host (WTERMSIG (status)); } else { ourstatus->kind = TARGET_WAITKIND_STOPPED; ourstatus->value.sig = target_signal_from_host (WSTOPSIG (status)); } #else store_waitstatus (ourstatus, status.w_status); #endif return ptid; } }
static ptid_t obsd_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *ourstatus, int options) { pid_t pid; int status, save_errno; do { set_sigint_trap (); do { pid = waitpid (ptid_get_pid (ptid), &status, 0); save_errno = errno; } while (pid == -1 && errno == EINTR); clear_sigint_trap (); if (pid == -1) { fprintf_unfiltered (gdb_stderr, _("Child process unexpectedly missing: %s.\n"), safe_strerror (save_errno)); /* Claim it exited with unknown signal. */ ourstatus->kind = TARGET_WAITKIND_SIGNALLED; ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; return inferior_ptid; } /* Ignore terminated detached child processes. */ if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid)) pid = -1; } while (pid == -1); ptid = pid_to_ptid (pid); if (WIFSTOPPED (status)) { ptrace_state_t pe; pid_t fpid; if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&pe, sizeof pe) == -1) perror_with_name (("ptrace")); switch (pe.pe_report_event) { case PTRACE_FORK: ourstatus->kind = TARGET_WAITKIND_FORKED; ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid); /* Make sure the other end of the fork is stopped too. */ fpid = waitpid (pe.pe_other_pid, &status, 0); if (fpid == -1) perror_with_name (("waitpid")); if (ptrace (PT_GET_PROCESS_STATE, fpid, (caddr_t)&pe, sizeof pe) == -1) perror_with_name (("ptrace")); gdb_assert (pe.pe_report_event == PTRACE_FORK); gdb_assert (pe.pe_other_pid == pid); if (fpid == ptid_get_pid (inferior_ptid)) { ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid); return pid_to_ptid (fpid); } return pid_to_ptid (pid); } ptid = ptid_build (pid, pe.pe_tid, 0); if (!in_thread_list (ptid)) { if (ptid_get_lwp (inferior_ptid) == 0) thread_change_ptid (inferior_ptid, ptid); else add_thread (ptid); } } store_waitstatus (ourstatus, status); return ptid; }