char * solaris_pid_to_str (ptid_t ptid) { static char buf[100]; /* in case init failed to resolve the libthread_db library */ if (!procfs_suppress_run) return procfs_pid_to_str (ptid); if (is_thread (ptid)) { ptid_t lwp; lwp = thread_to_lwp (ptid, -2); if (PIDGET (lwp) == -1) sprintf (buf, "Thread %ld (defunct)", GET_THREAD (ptid)); else if (PIDGET (lwp) != -2) sprintf (buf, "Thread %ld (LWP %ld)", GET_THREAD (ptid), GET_LWP (lwp)); else sprintf (buf, "Thread %ld ", GET_THREAD (ptid)); } else if (GET_LWP (ptid) != 0) sprintf (buf, "LWP %ld ", GET_LWP (ptid)); else sprintf (buf, "process %d ", PIDGET (ptid)); return buf; }
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 const struct target_desc * arm_linux_read_description (struct target_ops *ops) { CORE_ADDR arm_hwcap = 0; arm_linux_has_wmmx_registers = 0; arm_linux_vfp_register_count = 0; if (target_auxv_search (ops, AT_HWCAP, &arm_hwcap) != 1) { return NULL; } if (arm_hwcap & HWCAP_IWMMXT) { arm_linux_has_wmmx_registers = 1; return tdesc_arm_with_iwmmxt; } if (arm_hwcap & HWCAP_VFP) { int pid; char *buf; const struct target_desc * result = NULL; /* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support Neon with VFPv3-D32. */ if (arm_hwcap & HWCAP_NEON) { arm_linux_vfp_register_count = 32; result = tdesc_arm_with_neon; } else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3) { arm_linux_vfp_register_count = 32; result = tdesc_arm_with_vfpv3; } else { arm_linux_vfp_register_count = 16; result = tdesc_arm_with_vfpv2; } /* Now make sure that the kernel supports reading these registers. Support was added in 2.6.30. */ pid = GET_LWP (inferior_ptid); errno = 0; buf = alloca (VFP_REGS_SIZE); if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0 && errno == EIO) result = NULL; return result; } return NULL; }
/* Attach to lwp PTID, doing whatever else is required to have this LWP under the debugger's control --- e.g., enabling event reporting. Returns true on success. */ int thread_db_attach_lwp (ptid_t ptid) { td_thrhandle_t th; td_thrinfo_t ti; td_err_e err; struct thread_db_info *info; info = get_thread_db_info (GET_PID (ptid)); if (info == NULL) return 0; /* This ptid comes from linux-nat.c, which should always fill in the LWP. */ gdb_assert (GET_LWP (ptid) != 0); /* Access an lwp we know is stopped. */ info->proc_handle.ptid = ptid; /* If we have only looked at the first thread before libpthread was initialized, we may not know its thread ID yet. Make sure we do before we add another thread to the list. */ if (!have_threads (ptid)) thread_db_find_new_threads_1 (ptid); err = info->td_ta_map_lwp2thr_p (info->thread_agent, GET_LWP (ptid), &th); if (err != TD_OK) /* Cannot find user-level thread. */ return 0; err = info->td_thr_get_info_p (&th, &ti); if (err != TD_OK) { warning (_("Cannot get thread info: %s"), thread_db_err_str (err)); return 0; } attach_thread (ptid, &th, &ti); return 1; }
static void fbsd_lwp_store_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { gregset_t gregs; fpregset_t fpregs; lwpid_t lwp; #ifdef PT_GETXMMREGS char xmmregs[512]; #endif /* FIXME, is it possible ? */ if (!IS_LWP (inferior_ptid)) { struct target_ops *beneath = find_target_beneath (ops); beneath->to_store_registers (ops, regcache, regnum); return ; } lwp = GET_LWP (inferior_ptid); if (regnum != -1) if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); fill_gregset (regcache, &gregs, regnum); if (ptrace (PT_SETREGS, lwp, (caddr_t) &gregs, 0) == -1) error ("Cannot set lwp %d registers: %s\n", lwp, safe_strerror (errno)); #ifdef PT_GETXMMREGS if (regnum != -1) if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == -1) goto noxmm; i387_collect_fxsave (regcache, regnum, xmmregs); if (ptrace (PT_SETXMMREGS, lwp, xmmregs, 0) == -1) goto noxmm; return; noxmm: #endif if (regnum != -1) if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) error ("Cannot get lwp %d float registers: %s\n", lwp, safe_strerror (errno)); fill_fpregset (regcache, &fpregs, regnum); if (ptrace (PT_SETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) error ("Cannot set lwp %d float registers: %s\n", lwp, safe_strerror (errno)); }
/* 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 ptid_t thread_from_lwp (ptid_t ptid) { td_thrhandle_t th; td_err_e err; ptid_t thread_ptid; struct thread_db_info *info; struct thread_get_info_inout io = {0}; /* This ptid comes from linux-nat.c, which should always fill in the LWP. */ gdb_assert (GET_LWP (ptid) != 0); info = get_thread_db_info (GET_PID (ptid)); /* Access an lwp we know is stopped. */ info->proc_handle.ptid = ptid; err = info->td_ta_map_lwp2thr_p (info->thread_agent, GET_LWP (ptid), &th); if (err != TD_OK) error (_("Cannot find user-level thread for LWP %ld: %s"), GET_LWP (ptid), thread_db_err_str (err)); /* Fetch the thread info. If we get back TD_THR_ZOMBIE, then the event thread has already died. If another gdb interface has called thread_alive() previously, the thread won't be found on the thread list anymore. In that case, we don't want to process this ptid anymore to avoid the possibility of later treating it as a newly discovered thread id that we should add to the list. Thus, we return a -1 ptid which is also how the thread list marks a dead thread. */ io.thread_db_info = info; io.thread_info = NULL; if (thread_get_info_callback (&th, &io) == TD_THR_ZOMBIE && io.thread_info == NULL) return minus_one_ptid; gdb_assert (ptid_get_tid (ptid) == 0); return ptid; }
static void fbsd_lwp_store_registers (int regno) { gregset_t gregs; fpregset_t fpregs; lwpid_t lwp; #ifdef PT_GETXMMREGS char xmmregs[512]; #endif /* FIXME, is it possible ? */ if (!IS_LWP (inferior_ptid)) { child_ops.to_store_registers (regno); return ; } lwp = GET_LWP (inferior_ptid); if (regno != -1) if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); fill_gregset (&gregs, regno); if (ptrace (PT_SETREGS, lwp, (caddr_t) &gregs, 0) == -1) error ("Cannot set lwp %d registers: %s\n", lwp, safe_strerror (errno)); #ifdef PT_GETXMMREGS if (regno != -1) if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == -1) goto noxmm; i387_fill_fxsave (xmmregs, regno); if (ptrace (PT_SETXMMREGS, lwp, xmmregs, 0) == -1) goto noxmm; return; noxmm: #endif if (regno != -1) if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) error ("Cannot get lwp %d float registers: %s\n", lwp, safe_strerror (errno)); fill_fpregset (&fpregs, regno); if (ptrace (PT_SETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) error ("Cannot set lwp %d float registers: %s\n", lwp, safe_strerror (errno)); }
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_lwp_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { gregset_t gregs; fpregset_t fpregs; lwpid_t lwp; #ifdef PT_GETXMMREGS char xmmregs[512]; #endif if (!target_has_execution) { struct target_ops *beneath = find_target_beneath (ops); beneath->to_fetch_registers (ops, regcache, regnum); return; } lwp = GET_LWP (inferior_ptid); if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); supply_gregset (regcache, &gregs); #ifdef PT_GETXMMREGS if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == 0) { i387_supply_fxsave (regcache, -1, xmmregs); } else { #endif if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) error ("Cannot get lwp %d registers: %s\n ", lwp, safe_strerror (errno)); supply_fpregset (regcache, &fpregs); #ifdef PT_GETXMMREGS } #endif }
static ptid_t lwp_to_thread (ptid_t lwp) { td_thrinfo_t ti; td_thrhandle_t th; td_err_e val; if (is_thread (lwp)) return lwp; /* It's already a thread id */ /* It's an lwp. Convert it to a thread id. */ if (!sol_thread_alive (lwp)) return pid_to_ptid (-1); /* defunct lwp */ val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th); if (val == TD_NOTHR) return pid_to_ptid (-1); /* thread must have terminated */ else if (val != TD_OK) error ("lwp_to_thread: td_ta_map_lwp2thr: %s.", td_err_string (val)); val = p_td_thr_validate (&th); if (val == TD_NOTHR) return lwp; /* libthread doesn't know about it; just return lwp */ else if (val != TD_OK) error ("lwp_to_thread: td_thr_validate: %s.", td_err_string (val)); val = p_td_thr_get_info (&th, &ti); if (val == TD_NOTHR) return pid_to_ptid (-1); /* thread must have terminated */ else if (val != TD_OK) error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val)); return BUILD_THREAD (ti.ti_tid, PIDGET (lwp)); }
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"); }