There are two basic BSD interfaces to retrieve kernel processes associated to a process: FreeBSD: PT_GETNUMLWPS This request returns the number of kernel threads associated with the traced process. PT_GETLWPLIST This request can be used to get the current thread list. A pointer to an array of type lwpid_t should be passed in addr, with the array size specified by data. The return value from ptrace() is the count of array entries filled in. OpenBSD: PT_GET_THREAD_FIRST This request reads the thread ID of the traced process' first thread into the “struct ptrace_thread_state” pointed to by addr. The data argument should be set to sizeof(struct ptrace_thread_state). PT_GET_THREAD_NEXT This request is just like PT_GET_THREAD_FIRST, except it returns the thread ID of the subsequent thread. The “struct ptrace_thread_state” pointed to by addr must be initialized by a previous PT_GET_THREAD_FIRST or PT_GET_THREAD_NEXT request. I need an equivalent interface for LLDB. Which one is preferred for NetBSD? In the OpenBSD one, as there is no timing window (likely harmless) between GETNUMLWPS and GETLWPLIST. The OpenBSD one can also omit allocations of intermediate arrays. On the other hand FreeBSD might need just two ptrace(2) calls for higher number of LWPs and it might scale better. Both functions construct equivalent algorithms. The following examples come from GDB: - FreeBSD 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); } https://github.com/jsonn/src/blob/trunk/external/gpl3/gdb/dist/gdb/fbsd-nat.c - OpenBSD 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")); } } https://github.com/jsonn/src/blob/trunk/external/gpl3/gdb/dist/gdb/obsd-nat.c
Attachment:
signature.asc
Description: OpenPGP digital signature