CORE_ADDR fbsd_thread_get_local_address(struct target_ops *ops, ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset) { td_thrhandle_t th; void *address; int ret; if (IS_THREAD (ptid)) { if (!td_thr_tls_get_addr_p) error ("Cannot find thread-local interface in thread_db library."); ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th); /* get the address of the variable. */ ret = td_thr_tls_get_addr_p (&th, (void *)lm, offset, &address); if (ret != TD_OK) { error ("Cannot find thread-local storage for thread %ld\n%s", (long) GET_THREAD (ptid), thread_db_err_str (ret)); } /* Cast assuming host == target. */ return extract_data_ptr (&address); } return (0); }
CORE_ADDR fbsd_thread_get_local_address(ptid_t ptid, struct objfile *objfile, CORE_ADDR offset) { td_thrhandle_t th; void *address; CORE_ADDR lm; void *lm2; int ret, is_library = (objfile->flags & OBJF_SHARED); if (IS_THREAD (ptid)) { if (!td_thr_tls_get_addr_p) error ("Cannot find thread-local interface in thread_db library."); /* Get the address of the link map for this objfile. */ lm = svr4_fetch_objfile_link_map (objfile); /* Couldn't find link map. Bail out. */ if (!lm) { if (is_library) error ("Cannot find shared library `%s' link_map in dynamic" " linker's module list", objfile->name); else error ("Cannot find executable file `%s' link_map in dynamic" " linker's module list", objfile->name); } ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th); /* get the address of the variable. */ store_typed_address(&lm2, builtin_type_void_data_ptr, lm); ret = td_thr_tls_get_addr_p (&th, lm2, offset, &address); if (ret != TD_OK) { if (is_library) error ("Cannot find thread-local storage for thread %ld, " "shared library %s:\n%s", (long) GET_THREAD (ptid), objfile->name, thread_db_err_str (ret)); else error ("Cannot find thread-local storage for thread %ld, " "executable file %s:\n%s", (long) GET_THREAD (ptid), objfile->name, thread_db_err_str (ret)); } /* Cast assuming host == target. */ return extract_typed_address(&address, builtin_type_void_data_ptr); } return (0); }
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 fbsd_thread_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { prgregset_t gregset; prfpregset_t fpregset; td_thrhandle_t th; td_err_e err; #ifdef PT_GETXMMREGS char xmmregs[512]; #endif if (!IS_THREAD (inferior_ptid)) { fbsd_lwp_fetch_registers (ops, regcache, regnum); return; } err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); if (err != TD_OK) error ("Cannot find thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); err = td_thr_getgregs_p (&th, gregset); if (err != TD_OK) error ("Cannot fetch general-purpose registers for thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); #ifdef PT_GETXMMREGS err = td_thr_getxmmregs_p (&th, xmmregs); if (err == TD_OK) { i387_supply_fxsave (regcache, -1, xmmregs); } else { #endif err = td_thr_getfpregs_p (&th, &fpregset); if (err != TD_OK) error ("Cannot get floating-point registers for thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); supply_fpregset (regcache, &fpregset); #ifdef PT_GETXMMREGS } #endif supply_gregset (regcache, gregset); }
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 void fbsd_thread_store_registers (int regno) { prgregset_t gregset; prfpregset_t fpregset; td_thrhandle_t th; td_err_e err; #ifdef PT_GETXMMREGS char xmmregs[512]; #endif if (!IS_THREAD (inferior_ptid)) { fbsd_lwp_store_registers (regno); return; } err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); if (err != TD_OK) error ("Cannot find thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); if (regno != -1) { char old_value[MAX_REGISTER_SIZE]; regcache_collect (regno, old_value); err = td_thr_getgregs_p (&th, gregset); if (err != TD_OK) error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err)); #ifdef PT_GETXMMREGS err = td_thr_getxmmregs_p (&th, xmmregs); if (err != TD_OK) { #endif err = td_thr_getfpregs_p (&th, &fpregset); if (err != TD_OK) error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err)); #ifdef PT_GETXMMREGS } #endif supply_register (regno, old_value); } fill_gregset (gregset, regno); err = td_thr_setgregs_p (&th, gregset); if (err != TD_OK) error ("Cannot store general-purpose registers for thread %d: Thread ID=%d, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); #ifdef PT_GETXMMREGS i387_fill_fxsave (xmmregs, regno); err = td_thr_setxmmregs_p (&th, xmmregs); if (err == TD_OK) return; #endif fill_fpregset (&fpregset, regno); err = td_thr_setfpregs_p (&th, &fpregset); if (err != TD_OK) error ("Cannot store floating-point registers for thread %d: Thread ID=%d, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); }
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); } }