From: Kamil Rytarowski Date: Wed, 25 Mar 2020 19:29:44 +0000 (+0100) Subject: Implement basic threading support in the NetBSD target X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=05f00e223d56927bfb03e3272a4827276ed67372;p=binutils-gdb.git Implement basic threading support in the NetBSD target Use sysctl(3) as the portable interface to prompt NetBSD threads on all supported NetBSD versions. In future newer versions could switch to PT_LWPSTATUS ptrace(2) API that will be supported on NetBSD 10.0 and newer. Implement as part of nbsd_nat_target: - thread_name() - read descriptive thread name - thread_alive() - check whether a thread is alive - post_attach() - updates the list of threads after attach - update_thread_list() - updates the list of threads - pid_to_str() - translates ptid to a descriptive string There are two local static functions: - nbsd_thread_lister() - generic LWP lister for a specified pid - nbsd_add_threads() - utility to update the list of threads Now, GDB on NetBSD can attach to a multithreaded process, spawn a multithreaded process, list threads, print their LWP+PID numbers and descriptive thread names. gdb/ChangeLog: * nbsd-nat.h (struct thread_info): Add forward declaration. (nbsd_nat_target::thread_alive): Add. (nbsd_nat_target::thread_name): Likewise. (nbsd_nat_target::update_thread_list): Likewise. (update_thread_list::post_attach): Likewise. (post_attach::pid_to_str): Likewise. * nbsd-nat.c: Include "gdbthread.h" and "inferior.h". (nbsd_thread_lister): Add. (nbsd_nat_target::thread_alive): Likewise. (nbsd_nat_target::thread_name): Likewise. (nbsd_add_threads): Likewise. (update_thread_list::post_attach): Likewise. (nbsd_nat_target::update_thread_list): Likewise. (post_attach::pid_to_str): Likewise. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 94fbdbde2f2..bd1a0f4df18 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2020-04-06 Kamil Rytarowski + + * nbsd-nat.h (struct thread_info): Add forward declaration. + (nbsd_nat_target::thread_alive): Add. + (nbsd_nat_target::thread_name): Likewise. + (nbsd_nat_target::update_thread_list): Likewise. + (update_thread_list::post_attach): Likewise. + (post_attach::pid_to_str): Likewise. + * nbsd-nat.c: Include "gdbthread.h" and "inferior.h". + (nbsd_thread_lister): Add. + (nbsd_nat_target::thread_alive): Likewise. + (nbsd_nat_target::thread_name): Likewise. + (nbsd_add_threads): Likewise. + (update_thread_list::post_attach): Likewise. + (nbsd_nat_target::update_thread_list): Likewise. + (post_attach::pid_to_str): Likewise. + 2020-04-06 Tom Tromey * ada-valprint.c (print_variant_part): Extract the variant field. diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c index 326bbe3aec3..4423e19428d 100644 --- a/gdb/nbsd-nat.c +++ b/gdb/nbsd-nat.c @@ -20,6 +20,8 @@ #include "defs.h" #include "nbsd-nat.h" +#include "gdbthread.h" +#include "inferior.h" #include #include @@ -39,3 +41,161 @@ nbsd_nat_target::pid_to_exec_file (int pid) return NULL; return buf; } + +/* Generic thread (LWP) lister within a specified process. The callback + parameters is a C++ function that is called for each detected thread. */ + +static bool +nbsd_thread_lister (const pid_t pid, + gdb::function_view + callback) +{ + int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0}; + size_t size; + + if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) + perror_with_name (("sysctl")); + + mib[4] = size / sizeof (size_t); + + gdb::unique_xmalloc_ptr kl + ((struct kinfo_lwp *) xcalloc (size, 1)); + + if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1 + || size == 0) + perror_with_name (("sysctl")); + + for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++) + { + struct kinfo_lwp *l = &kl[i]; + + /* Return true if the specified thread is alive. */ + auto lwp_alive + = [] (struct kinfo_lwp *lwp) + { + switch (lwp->l_stat) + { + case LSSLEEP: + case LSRUN: + case LSONPROC: + case LSSTOP: + case LSSUSPENDED: + return true; + default: + return false; + } + }; + + /* Ignore embryonic or demised threads. */ + if (!lwp_alive (l)) + continue; + + if (callback (l)) + return true; + } + + return false; +} + +/* Return true if PTID is still active in the inferior. */ + +bool +nbsd_nat_target::thread_alive (ptid_t ptid) +{ + pid_t pid = ptid.pid (); + int lwp = ptid.lwp (); + + auto fn + = [&lwp] (const struct kinfo_lwp *kl) + { + return kl->l_lid == lwp; + }; + + return nbsd_thread_lister (pid, fn); +} + +/* Return the name assigned to a thread by an application. Returns + the string in a static buffer. */ + +const char * +nbsd_nat_target::thread_name (struct thread_info *thr) +{ + ptid_t ptid = thr->ptid; + pid_t pid = ptid.pid (); + int lwp = ptid.lwp (); + + static char buf[KI_LNAMELEN] = {}; + + auto fn + = [&lwp] (const struct kinfo_lwp *kl) + { + if (kl->l_lid == lwp) + { + xsnprintf (buf, sizeof buf, "%s", kl->l_name); + return true; + } + return false; + }; + + if (nbsd_thread_lister (pid, fn)) + return buf; + else + return NULL; +} + +/* Implement the "post_attach" target_ops method. */ + +static void +nbsd_add_threads (nbsd_nat_target *target, pid_t pid) +{ + auto fn + = [&target, &pid] (const struct kinfo_lwp *kl) + { + ptid_t ptid = ptid_t (pid, kl->l_lid, 0); + if (!in_thread_list (target, ptid)) + { + if (inferior_ptid.lwp () == 0) + thread_change_ptid (target, inferior_ptid, ptid); + else + add_thread (target, ptid); + } + return false; + }; + + nbsd_thread_lister (pid, fn); +} + +/* Implement the "post_attach" target_ops method. */ + +void +nbsd_nat_target::post_attach (int pid) +{ + nbsd_add_threads (this, pid); +} + +/* Implement the "update_thread_list" target_ops method. */ + +void +nbsd_nat_target::update_thread_list () +{ + prune_threads (); + + nbsd_add_threads (this, inferior_ptid.pid ()); +} + +/* Convert PTID to a string. */ + +std::string +nbsd_nat_target::pid_to_str (ptid_t ptid) +{ + int lwp = ptid.lwp (); + + if (lwp != 0) + { + pid_t pid = ptid.pid (); + + return string_printf ("LWP %d of process %d", lwp, pid); + } + + return normal_pid_to_str (ptid); +} diff --git a/gdb/nbsd-nat.h b/gdb/nbsd-nat.h index a752fbe572d..3606048cd07 100644 --- a/gdb/nbsd-nat.h +++ b/gdb/nbsd-nat.h @@ -22,11 +22,19 @@ #include "inf-ptrace.h" +struct thread_info; + /* A prototype NetBSD target. */ struct nbsd_nat_target : public inf_ptrace_target { char *pid_to_exec_file (int pid) override; + + bool thread_alive (ptid_t ptid) override; + const char *thread_name (struct thread_info *thr) override; + void post_attach (int pid) override; + void update_thread_list () override; + std::string pid_to_str (ptid_t ptid) override; }; #endif /* nbsd-nat.h */