static int fbsd_thread_alive (ptid_t ptid) { td_thrhandle_t th; td_thrinfo_t ti; td_err_e err; gregset_t gregs; lwpid_t lwp; if (IS_THREAD (ptid)) { err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); if (err != TD_OK) return 0; err = td_thr_get_info_p (&th, &ti); if (err != TD_OK) return 0; /* A zombie thread. */ if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) return 0; return 1; } else if (GET_LWP (ptid) == 0) { /* we sometimes are called with lwp == 0 */ return 1; } if (fbsd_thread_active) { err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); /* * if the lwp was already mapped to user thread, don't use it * directly, please use user thread id instead. */ if (err == TD_OK) return 0; } if (!target_has_execution) { lwp = GET_LWP (ptid); bfd_map_over_sections (core_bfd, fbsd_core_check_lwp, &lwp); return (lwp == 0); } /* check lwp in kernel */ return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0; }
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 char * fbsd_thread_pid_to_str (ptid_t ptid) { static char buf[64 + MAXCOMLEN]; if (IS_THREAD (ptid)) { td_thrhandle_t th; td_thrinfo_t ti; td_err_e err; err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); if (err != TD_OK) error ("Cannot find thread, Thread ID=%ld, %s", GET_THREAD (ptid), thread_db_err_str (err)); err = td_thr_get_info_p (&th, &ti); if (err != TD_OK) error ("Cannot get thread info, Thread ID=%ld, %s", GET_THREAD (ptid), thread_db_err_str (err)); if (ti.ti_lid != 0) { snprintf (buf, sizeof (buf), "Thread %llx (LWP %d/%s)", (unsigned long long)th.th_thread, ti.ti_lid, fbsd_thread_get_name (ti.ti_lid)); } else { snprintf (buf, sizeof (buf), "Thread %llx (%s)", (unsigned long long)th.th_thread, thread_db_state_str (ti.ti_state)); } return buf; } else if (IS_LWP (ptid)) { snprintf (buf, sizeof (buf), "LWP %d", (int) GET_LWP (ptid)); return buf; } return normal_pid_to_str (ptid); }
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data) { td_thrinfo_t ti; td_err_e err; ptid_t ptid; err = td_thr_get_info_p (th_p, &ti); if (err != TD_OK) error ("Cannot get thread info: %s", thread_db_err_str (err)); /* Ignore zombie */ if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) return 0; ptid = BUILD_THREAD (ti.ti_tid, proc_handle.pid); attach_thread (ptid, th_p, &ti, 1); return 0; }
/* Convert LWP to user-level thread id. */ static ptid_t thread_from_lwp (ptid_t ptid, td_thrhandle_t *th, td_thrinfo_t *ti) { td_err_e err; gdb_assert (IS_LWP (ptid)); if (fbsd_thread_active) { err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), th); if (err == TD_OK) { err = td_thr_get_info_p (th, ti); if (err != TD_OK) error ("Cannot get thread info: %s", thread_db_err_str (err)); return BUILD_THREAD (ti->ti_tid, GET_PID (ptid)); } } /* the LWP is not mapped to user thread */ return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid)); }
static void fbsd_thread_resume (ptid_t ptid, int step, enum target_signal signo) { td_thrhandle_t th; td_thrinfo_t ti; ptid_t work_ptid; int resume_all, ret; long lwp, thvalid = 0; if (!fbsd_thread_active) { child_ops.to_resume (ptid, step, signo); return; } if (GET_PID(ptid) != -1 && step != 0) { resume_all = 0; work_ptid = ptid; } else { resume_all = 1; work_ptid = inferior_ptid; } lwp = GET_LWP (work_ptid); if (lwp == 0) { /* check user thread */ ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(work_ptid), &th); if (ret) error (thread_db_err_str (ret)); /* For M:N thread, we need to tell UTS to set/unset single step flag at context switch time, the flag will be written into thread mailbox. This becauses some architecture may not have machine single step flag in ucontext, so we put the flag in mailbox, when the thread switches back, kse_switchin restores the single step state. */ ret = td_thr_sstep_p (&th, step); if (ret) error (thread_db_err_str (ret)); ret = td_thr_get_info_p (&th, &ti); if (ret) error (thread_db_err_str (ret)); thvalid = 1; lwp = ti.ti_lid; } if (lwp) { int req = step ? PT_SETSTEP : PT_CLEARSTEP; if (ptrace (req, (pid_t) lwp, (caddr_t) 1, target_signal_to_host(signo))) perror_with_name ("PT_SETSTEP/PT_CLEARSTEP"); } if (!ptid_equal (last_single_step_thread, null_ptid)) { ret = td_ta_thr_iter_p (thread_agent, resume_thread_callback, NULL, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); if (ret != TD_OK) error ("resume error: %s", thread_db_err_str (ret)); } if (!resume_all) { ret = td_ta_thr_iter_p (thread_agent, suspend_thread_callback, NULL, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); if (ret != TD_OK) error ("suspend error: %s", thread_db_err_str (ret)); last_single_step_thread = work_ptid; } else last_single_step_thread = null_ptid; if (thvalid) { ret = td_thr_dbresume_p (&th); if (ret != TD_OK) error ("resume error: %s", thread_db_err_str (ret)); } else { /* it is not necessary, put it here for completness */ ret = ptrace(PT_RESUME, lwp, 0, 0); } /* now continue the process, suspended thread wont run */ if (ptrace (PT_CONTINUE, proc_handle.pid , (caddr_t)1, target_signal_to_host(signo))) perror_with_name ("PT_CONTINUE"); }
static void fbsd_thread_signal_cmd (char *exp, int from_tty) { td_thrhandle_t th; td_thrinfo_t ti; td_err_e err; const char *code; if (!fbsd_thread_active || !IS_THREAD(inferior_ptid)) return; err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); if (err != TD_OK) return; err = td_thr_get_info_p (&th, &ti); if (err != TD_OK) return; printf_filtered("signal mask:\n"); fbsd_print_sigset(&ti.ti_sigmask); printf_filtered("signal pending:\n"); fbsd_print_sigset(&ti.ti_pending); if (ti.ti_siginfo.si_signo != 0) { printf_filtered("si_signo %d si_errno %d", ti.ti_siginfo.si_signo, ti.ti_siginfo.si_errno); if (ti.ti_siginfo.si_errno != 0) printf_filtered(" (%s)", strerror(ti.ti_siginfo.si_errno)); printf_filtered("\n"); switch (ti.ti_siginfo.si_code) { case SI_NOINFO: code = "NOINFO"; break; case SI_USER: code = "USER"; break; case SI_QUEUE: code = "QUEUE"; break; case SI_TIMER: code = "TIMER"; break; case SI_ASYNCIO: code = "ASYNCIO"; break; case SI_MESGQ: code = "MESGQ"; break; case SI_KERNEL: code = "KERNEL"; break; default: code = "UNKNOWN"; break; } printf_filtered("si_code %s (%d) si_pid %d si_uid %d si_status %x " "si_addr %p\n", code, ti.ti_siginfo.si_code, ti.ti_siginfo.si_pid, ti.ti_siginfo.si_uid, ti.ti_siginfo.si_status, ti.ti_siginfo.si_addr); } }