FreeBSD Bugzilla – Attachment 165834 Details for
Bug 201207
devel/gdb: Duplicate thread listing when attaching to running multithreaded program
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
gdb_port_ptrace_threads.patch
gdb_port_ptrace_threads.patch (text/plain), 48.41 KB, created by
John Baldwin
on 2016-01-19 18:29:11 UTC
(
hide
)
Description:
gdb_port_ptrace_threads.patch
Filename:
MIME Type:
Creator:
John Baldwin
Created:
2016-01-19 18:29:11 UTC
Size:
48.41 KB
patch
obsolete
>Index: devel/gdb/Makefile >=================================================================== >--- devel/gdb/Makefile (revision 406064) >+++ devel/gdb/Makefile (working copy) >@@ -36,18 +36,22 @@ > > ONLY_FOR_ARCHS= i386 amd64 powerpc powerpc64 # untested elsewhere, might work > >-OPTIONS_DEFINE= DEBUG EXPAT GDB_LINK GUILE KGDB PYTHON THREADS TUI >+OPTIONS_DEFINE= DEBUG EXPAT GDB_LINK GUILE KGDB PYTHON TUI > >-OPTIONS_DEFAULT= GDB_LINK KGDB THREADS TUI PORT_READLINE >+OPTIONS_DEFAULT= GDB_LINK KGDB THREAD_DB_THREAD TUI PORT_READLINE > >-OPTIONS_SINGLE= READLINE >+OPTIONS_SINGLE= READLINE THREADS > OPTIONS_SINGLE_READLINE= BASE_READLINE BUNDLED_READLINE PORT_READLINE >+OPTIONS_SINGLE_THREADS= THREAD_DB_THREAD PTRACE_THREAD NONE_THREAD > > GDB_LINK_DESC= Create ${PREFIX}/bin/gdb symlink > KGDB_DESC= Kernel Debugging Support > BASE_READLINE_DESC= from base system (experimental) > BUNDLED_READLINE_DESC= from gdb distfile >+NONE_THREAD_DESC= No thread debugging support > PORT_READLINE_DESC= from devel/readline port >+PTRACE_THREAD_DESC= Use ptrace() for thread debugging (experimental) >+THREAD_DB_THREAD_DESC= Use libthread_db for thread debugging > TUI_DESC= Text User Interface enabled > > OPTIONS_SUB= yes >@@ -80,14 +84,17 @@ > post-patch: > @${REINPLACE_CMD} -e 's|$$| [GDB v${PORTVERSION} for FreeBSD]|' \ > ${WRKSRC}/gdb/version.in >-.if ${PORT_OPTIONS:MTHREADS} >+.if ${PORT_OPTIONS:MTHREAD_DB_THREAD} > @${CP} ${FILESDIR}/fbsd-threads.c ${WRKSRC}/gdb/ > @${PATCH} ${PATCH_ARGS} < ${FILESDIR}/extrapatch-threads > .endif >+.if ${PORT_OPTIONS:MPTRACE_THREAD} >+ @${PATCH} ${PATCH_ARGS} < ${FILESDIR}/extrapatch-threads-ptrace >+.endif > .if ${PORT_OPTIONS:MKGDB} > @${CP} -r ${FILESDIR}/kgdb/*.[ch] ${WRKSRC}/gdb/ > @${PATCH} ${PATCH_ARGS} < ${FILESDIR}/extrapatch-kgdb >-.if ${PORT_OPTIONS:MTHREADS} >+.if ${PORT_OPTIONS:MTHREAD_DB_THREAD} > @${PATCH} ${PATCH_ARGS} < \ > ${FILESDIR}/extrapatch-kgdb-configure.tgt-threads > .else >Index: devel/gdb/files/extrapatch-threads-ptrace >=================================================================== >--- devel/gdb/files/extrapatch-threads-ptrace (nonexistent) >+++ devel/gdb/files/extrapatch-threads-ptrace (working copy) >@@ -0,0 +1,1396 @@ >+diff --git bfd/elf.c bfd/elf.c >+index 9846046..6ccdb8f 100644 >+--- bfd/elf.c >++++ bfd/elf.c >+@@ -9126,6 +9126,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) >+ case NT_SIGINFO: >+ return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo", >+ note); >++ >++ case NT_FREEBSD_THRMISC: >++ if (note->namesz == 8 >++ && strcmp (note->namedata, "FreeBSD") == 0) >++ return elfcore_make_note_pseudosection (abfd, ".thrmisc", note); >++ else >++ return TRUE; >+ } >+ } >+ >+diff --git gdb/amd64bsd-nat.c gdb/amd64bsd-nat.c >+index 66d4289..c3d8e0e 100644 >+--- gdb/amd64bsd-nat.c >++++ gdb/amd64bsd-nat.c >+@@ -52,7 +52,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, >+ { >+ struct reg regs; >+ >+- if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't get registers")); >+ >+@@ -70,7 +70,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, >+ if (amd64bsd_xsave_len != 0) >+ { >+ xstateregs = alloca (amd64bsd_xsave_len); >+- if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) >+ perror_with_name (_("Couldn't get extended state status")); >+ >+@@ -79,7 +79,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, >+ } >+ #endif >+ >+- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't get floating point status")); >+ >+@@ -103,11 +114,11 @@ amd64bsd_store_inferior_registers (struc >+ >+ memset( ®s, 0, sizeof(struct reg)); >+ memset( &oldregs, 0, sizeof(struct reg)); >+- if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't get registers")); >+ >+- ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), >++ ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &oldregs, 0); >+ amd64_collect_native_gregset (regcache, ®s, regnum); >+ >+@@ -117,7 +128,7 @@ amd64bsd_store_inferior_registers (struc >+ regs.r_rflags ^= (regs.r_rflags ^ oldregs.r_rflags ) & ~PSL_USERCHANGE; >+ //printf(" allowed regs.r_rflags = 0x%8.8X\n", regs.r_rflags ); >+ } >+- if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't write registers")); >+ >+@@ -134,26 +145,26 @@ amd64bsd_store_inferior_registers (struc >+ if (amd64bsd_xsave_len != 0) >+ { >+ xstateregs = alloca (amd64bsd_xsave_len); >+- if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) >+ perror_with_name (_("Couldn't get extended state status")); >+ >+ amd64_collect_xsave (regcache, regnum, xstateregs, 0); >+ >+- if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETXSTATE, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xstateregs, amd64bsd_xsave_len) == -1) >+ perror_with_name (_("Couldn't write extended state status")); >+ return; >+ } >+ #endif >+ >+- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't get floating point status")); >+ >+ amd64_collect_fxsave (regcache, regnum, &fpregs); >+ >+- if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETFPREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't write floating point status")); >+ } >+@@ -183,7 +194,7 @@ amd64bsd_dr_get (ptid_t ptid, int regnum >+ { >+ struct dbreg dbregs; >+ >+- if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) >+ perror_with_name (_("Couldn't read debug registers")); >+ >+@@ -195,7 +206,7 @@ amd64bsd_dr_set (int regnum, unsigned lo >+ { >+ struct dbreg dbregs; >+ >+- if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) >+ perror_with_name (_("Couldn't get debug registers")); >+ >+@@ -195,7 +206,7 @@ amd64bsd_dr_set (int regnum, unsigned long value) >+ >+ DBREG_DRX ((&dbregs), regnum) = value; >+ >+- if (ptrace (PT_SETDBREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETDBREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) >+ perror_with_name (_("Couldn't write debug registers")); >+ } >+diff --git gdb/config.in gdb/config.in >+index 9ef53b3..0e3166b 100644 >+--- gdb/config.in >++++ gdb/config.in >+@@ -450,6 +450,9 @@ >+ /* Define to 1 if your system has struct lwp. */ >+ #undef HAVE_STRUCT_LWP >+ >++/* Define to 1 if `struct ptrace_lwpinfo' is a member of `pl_tdname'. */ >++#undef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME >++ >+ /* Define to 1 if your system has struct reg in <machine/reg.h>. */ >+ #undef HAVE_STRUCT_REG >+ >+diff --git gdb/configure gdb/configure >+index e8979f0..62f8886 100755 >+--- gdb/configure >++++ gdb/configure >+@@ -12502,6 +12502,22 @@ $as_echo "#define HAVE_PT_GETXMMREGS 1" >>confdefs.h >+ >+ fi >+ >++# See if <sys/ptrace.h> supports LWP names on FreeBSD >++# Older FreeBSD versions don't have the pl_tdname member of >++# `struct ptrace_lwpinfo'. >++ac_fn_c_check_member "$LINENO" "struct ptrace_lwpinfo" "pl_tdname" "ac_cv_member_struct_ptrace_lwpinfo_pl_tdname" "#include <sys/ptrace.h> >++" >++if test "x$ac_cv_member_struct_ptrace_lwpinfo_pl_tdname" = x""yes; then : >++ >++cat >>confdefs.h <<_ACEOF >++#define HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME 1 >++_ACEOF >++ >++ >++fi >++ >++ >++ >+ # Detect which type of /proc is in use, such as for Solaris. >+ >+ if test "${target}" = "${host}"; then >+diff --git gdb/configure.ac gdb/configure.ac >+index a40860a..6664355 100644 >+--- gdb/configure.ac >++++ gdb/configure.ac >+@@ -1564,6 +1564,13 @@ if test $gdb_cv_have_pt_getxmmregs = yes; then >+ [Define if sys/ptrace.h defines the PT_GETXMMREGS request.]) >+ fi >+ >++# See if <sys/ptrace.h> supports LWP names on FreeBSD >++# Older FreeBSD versions don't have the pl_tdname member of >++# `struct ptrace_lwpinfo'. >++AC_CHECK_MEMBERS([struct ptrace_lwpinfo.pl_tdname], [], [], >++ [#include <sys/ptrace.h>]) >++ >++ >+ # Detect which type of /proc is in use, such as for Solaris. >+ >+ if test "${target}" = "${host}"; then >+diff --git gdb/corelow.c gdb/corelow.c >+index 9218003..48dfc87 100644 >+--- gdb/corelow.c >++++ gdb/corelow.c >+@@ -986,6 +986,15 @@ core_pid_to_str (struct target_ops *ops, ptid_t ptid) >+ return buf; >+ } >+ >++static const char * >++core_thread_name (struct target_ops *self, struct thread_info *thr) >++{ >++ if (core_gdbarch >++ && gdbarch_core_thread_name_p (core_gdbarch)) >++ return gdbarch_core_thread_name (core_gdbarch, thr); >++ return NULL; >++} >++ >+ static int >+ core_has_memory (struct target_ops *ops) >+ { >+@@ -1038,6 +1047,7 @@ init_core_ops (void) >+ core_ops.to_thread_alive = core_thread_alive; >+ core_ops.to_read_description = core_read_description; >+ core_ops.to_pid_to_str = core_pid_to_str; >++ core_ops.to_thread_name = core_thread_name; >+ core_ops.to_stratum = process_stratum; >+ core_ops.to_has_memory = core_has_memory; >+ core_ops.to_has_stack = core_has_stack; >+diff --git gdb/fbsd-nat.c gdb/fbsd-nat.c >+index 9705d45..cf54039 100644 >+--- gdb/fbsd-nat.c >++++ gdb/fbsd-nat.c >+@@ -22,6 +22,7 @@ >+ #include "inferior.h" >+ #include "regcache.h" >+ #include "regset.h" >++#include "gdbcmd.h" >+ #include "gdbthread.h" >+ #include "gdb_wait.h" >+ #include <sys/types.h> >+@@ -204,11 +205,283 @@ fbsd_find_memory_regions (struct target_ops *self, >+ #endif >+ >+ #ifdef PT_LWPINFO >++static int debug_fbsd_lwp; >++ >+ static ptid_t (*super_wait) (struct target_ops *, >+ ptid_t, >+ struct target_waitstatus *, >+ int); >+ >++static void >++show_fbsd_lwp_debug (struct ui_file *file, int from_tty, >++ struct cmd_list_element *c, const char *value) >++{ >++ fprintf_filtered (file, _("Debugging of FreeBSD lwp module is %s.\n"), value); >++} >++ >++#if defined(TDP_RFPPWAIT) || defined(HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME) >++/* Fetch the external variant of the kernel's internal process >++ structure for the process PID into KP. */ >++ >++static void >++fbsd_fetch_kinfo_proc (pid_t pid, struct kinfo_proc *kp) >++{ >++ size_t len; >++ int mib[4]; >++ >++ len = sizeof *kp; >++ mib[0] = CTL_KERN; >++ mib[1] = KERN_PROC; >++ mib[2] = KERN_PROC_PID; >++ mib[3] = pid; >++ if (sysctl (mib, 4, kp, &len, NULL, 0) == -1) >++ perror_with_name (("sysctl")); >++} >++#endif >++ >++/* >++ FreeBSD's first thread support was via a "reentrant" version of libc >++ (libc_r) that first shipped in 2.2.7. This library multiplexed all >++ of the threads in a process onto a single kernel thread. This >++ library is supported via the bsd-uthread target. >++ >++ FreeBSD 5.1 introduced two new threading libraries that made use of >++ multiple kernel threads. The first (libkse) scheduled M user >++ threads onto N (<= M) kernel threads (LWPs). The second (libthr) >++ bound each user thread to a dedicated kernel thread. libkse shipped >++ as the default threading library (libpthread). >++ >++ FreeBSD 5.3 added a libthread_db to abstract the interface across >++ the various thread libraries (libc_r, libkse, and libthr). >++ >++ FreeBSD 7.0 switched the default threading library from from libkse >++ to libpthread and removed libc_r. >++ >++ FreeBSD 8.0 removed libkse and the in-kernel support for it. The >++ only threading library supported by 8.0 and later is libthr which >++ ties each user thread directly to an LWP. To simplify the >++ implementation, this target only supports LWP-backed threads using >++ ptrace directly rather than libthread_db. >++ >++ FreeBSD 11.0 introduced LWP event reporting via PT_LWP_EVENTS. >++*/ >++ >++/* Return true if PTID is still active in the inferior. */ >++ >++static int >++fbsd_thread_alive (struct target_ops *ops, ptid_t ptid) >++{ >++ if (ptid_lwp_p (ptid)) >++ { >++ struct ptrace_lwpinfo pl; >++ >++ if (ptrace (PT_LWPINFO, ptid_get_lwp (ptid), (caddr_t) &pl, sizeof pl) >++ == -1) >++ return 0; >++#ifdef PL_FLAG_EXITED >++ if (pl.pl_flags & PL_FLAG_EXITED) >++ return 0; >++#endif >++ } >++ >++ return 1; >++} >++ >++/* Convert PTID to a string. Returns the string in a static >++ buffer. */ >++ >++static char * >++fbsd_pid_to_str (struct target_ops *ops, ptid_t ptid) >++{ >++ lwpid_t lwp; >++ >++ lwp = ptid_get_lwp (ptid); >++ if (lwp != 0) >++ { >++ static char buf[64]; >++ int pid = ptid_get_pid (ptid); >++ >++ xsnprintf (buf, sizeof buf, "process %d, LWP %d", pid, lwp); >++ return buf; >++ } >++ >++ return normal_pid_to_str (ptid); >++} >++ >++#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME >++/* Return the name assigned to a thread by an application. Returns >++ the string in a static buffer. */ >++ >++static const char * >++fbsd_thread_name (struct target_ops *self, struct thread_info *thr) >++{ >++ struct ptrace_lwpinfo pl; >++ struct kinfo_proc kp; >++ int pid = ptid_get_pid (thr->ptid); >++ long lwp = ptid_get_lwp (thr->ptid); >++ static char buf[sizeof pl.pl_tdname + 1]; >++ >++ /* Note that ptrace_lwpinfo returns the process command in pl_tdname >++ if a name has not been set explicitly. Return a NULL name in >++ that case. */ >++ fbsd_fetch_kinfo_proc (pid, &kp); >++ if (ptrace (PT_LWPINFO, lwp, (caddr_t) &pl, sizeof pl) == -1) >++ perror_with_name (("ptrace")); >++ if (strcmp (kp.ki_comm, pl.pl_tdname) == 0) >++ return NULL; >++ xsnprintf (buf, sizeof buf, "%s", pl.pl_tdname); >++ return buf; >++} >++#endif >++ >++#ifdef PT_LWP_EVENTS >++/* Enable LWP events for a specific process. >++ >++ To catch LWP events, PT_LWP_EVENTS is set on every traced process. >++ This enables stops on the birth for new LWPs (excluding the "main" LWP) >++ and the death of LWPs (excluding the last LWP in a process). Note >++ that unlike fork events, the LWP that creates a new LWP does not >++ report an event. */ >++ >++static void >++fbsd_enable_lwp_events (pid_t pid) >++{ >++ if (ptrace (PT_LWP_EVENTS, pid, (PTRACE_TYPE_ARG3)0, 1) == -1) >++ perror_with_name (("ptrace")); >++} >++#endif >++ >++/* Add threads for any new LWPs in a process. >++ >++ When LWP events are used, this function is only used to detect existing >++ threads when attaching to a process. On older systems, this function is >++ called to discover new threads each time the thread list is updated. */ >++ >++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 = xcalloc (nlwps, sizeof *lwps); >++ 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); >++} >++ >++/* Implement the "to_update_thread_list" target_ops method. */ >++ >++static void >++fbsd_update_thread_list (struct target_ops *ops) >++{ >++#ifdef PT_LWP_EVENTS >++ /* With support for thread events, threads are added/deleted from the >++ list as events are reported, so just try deleting exited threads. */ >++ delete_exited_threads (); >++#else >++ prune_threads (); >++ >++ fbsd_add_threads (ptid_get_pid (inferior_ptid)); >++#endif >++} >++ >++static void (*super_resume) (struct target_ops *, >++ ptid_t, >++ int, >++ enum gdb_signal); >++ >++static int >++resume_one_thread_cb (struct thread_info *tp, void *data) >++{ >++ ptid_t *ptid = data; >++ int request; >++ >++ if (ptid_get_pid (tp->ptid) != ptid_get_pid (*ptid)) >++ return 0; >++ >++ if (ptid_get_lwp (tp->ptid) == ptid_get_lwp (*ptid)) >++ request = PT_RESUME; >++ else >++ request = PT_SUSPEND; >++ >++ if (ptrace (request, ptid_get_lwp (tp->ptid), NULL, 0) == -1) >++ perror_with_name (("ptrace")); >++ return 0; >++} >++ >++static int >++resume_all_threads_cb (struct thread_info *tp, void *data) >++{ >++ ptid_t *filter = data; >++ >++ if (!ptid_match (tp->ptid, *filter)) >++ return 0; >++ >++ if (ptrace (PT_RESUME, ptid_get_lwp (tp->ptid), NULL, 0) == -1) >++ perror_with_name (("ptrace")); >++ return 0; >++} >++ >++/* Implement the "to_resume" target_ops method. */ >++ >++static void >++fbsd_resume (struct target_ops *ops, >++ ptid_t ptid, int step, enum gdb_signal signo) >++{ >++ >++ if (debug_fbsd_lwp) >++ fprintf_unfiltered (gdb_stdlog, >++ "FLWP: fbsd_resume for ptid (%d, %ld, %ld)\n", >++ ptid_get_pid (ptid), ptid_get_lwp (ptid), >++ ptid_get_tid (ptid)); >++ if (ptid_lwp_p (ptid)) >++ { >++ /* If ptid is a specific LWP, suspend all other LWPs in the process. */ >++ iterate_over_threads (resume_one_thread_cb, &ptid); >++ } >++ else >++ { >++ /* If ptid is a wildcard, resume all matching threads (they won't run >++ until the process is continued however). */ >++ iterate_over_threads (resume_all_threads_cb, &ptid); >++ ptid = inferior_ptid; >++ } >++ super_resume (ops, ptid, step, signo); >++} >++ >+ #ifdef TDP_RFPPWAIT >+ /* >+ To catch fork events, PT_FOLLOW_FORK is set on every traced process >+@@ -246,7 +519,7 @@ static ptid_t (*super_wait) (struct target_ops *, >+ struct fbsd_fork_child_info >+ { >+ struct fbsd_fork_child_info *next; >+- pid_t child; /* Pid of new child. */ >++ ptid_t child; /* Pid of new child. */ >+ }; >+ >+ static struct fbsd_fork_child_info *fbsd_pending_children; >+@@ -255,7 +528,7 @@ static struct fbsd_fork_child_info *fbsd_pending_children; >+ corresponding fork event in the parent. */ >+ >+ static void >+-fbsd_remember_child (pid_t pid) >++fbsd_remember_child (ptid_t pid) >+ { >+ struct fbsd_fork_child_info *info; >+ >+@@ -267,45 +540,29 @@ fbsd_remember_child (pid_t pid) >+ } >+ >+ /* Check for a previously-recorded new child process event for PID. >+- If one is found, remove it from the list. */ >++ If one is found, remove it from the list and return the PTID. */ >+ >+-static int >++static ptid_t >+ fbsd_is_child_pending (pid_t pid) >+ { >+ struct fbsd_fork_child_info *info, *prev; >++ ptid_t ptid; >+ >+ prev = NULL; >+ for (info = fbsd_pending_children; info; prev = info, info = info->next) >+ { >+- if (info->child == pid) >++ if (ptid_get_pid (info->child) == pid) >+ { >+ if (prev == NULL) >+ fbsd_pending_children = info->next; >+ else >+ prev->next = info->next; >++ ptid = info->child; >+ xfree (info); >+- return 1; >++ return ptid; >+ } >+ } >+- return 0; >+-} >+- >+-/* Fetch the external variant of the kernel's internal process >+- structure for the process PID into KP. */ >+- >+-static void >+-fbsd_fetch_kinfo_proc (pid_t pid, struct kinfo_proc *kp) >+-{ >+- size_t len; >+- int mib[4]; >+- >+- len = sizeof *kp; >+- mib[0] = CTL_KERN; >+- mib[1] = KERN_PROC; >+- mib[2] = KERN_PROC_PID; >+- mib[3] = pid; >+- if (sysctl (mib, 4, kp, &len, NULL, 0) == -1) >+- perror_with_name (("sysctl")); >++ return null_ptid; >+ } >+ #endif >+ >+@@ -330,21 +587,83 @@ fbsd_wait (struct target_ops *ops, >+ int status; >+ >+ pid = ptid_get_pid (wptid); >+- if (ptrace (PT_LWPINFO, pid, (caddr_t)&pl, sizeof pl) == -1) >++ if (ptrace (PT_LWPINFO, pid, (caddr_t) &pl, sizeof pl) == -1) >+ perror_with_name (("ptrace")); >+ >++ wptid = ptid_build (pid, pl.pl_lwpid, 0); >++ >++#ifdef PT_LWP_EVENTS >++ if (pl.pl_flags & PL_FLAG_EXITED) >++ { >++ /* If GDB attaches to a multi-threaded process, exiting >++ threads might be skipped during fbsd_post_attach that >++ have not yet reported their PL_FLAG_EXITED event. >++ Ignore EXITED events for an unknown LWP. */ >++ if (in_thread_list (wptid)) >++ { >++ if (debug_fbsd_lwp) >++ fprintf_unfiltered (gdb_stdlog, >++ "FLWP: deleting thread for LWP %u\n", >++ pl.pl_lwpid); >++ if (print_thread_events) >++ printf_unfiltered (_("[%s exited]\n"), target_pid_to_str >++ (wptid)); >++ delete_thread (wptid); >++ } >++ if (ptrace (PT_CONTINUE, pid, (caddr_t) 1, 0) == -1) >++ perror_with_name (("ptrace")); >++ continue; >++ } >++#endif >++ >++ /* Switch to an LWP PTID on the first stop in a new process. >++ This is done after handling PL_FLAG_EXITED to avoid >++ switching to an exited LWP. It is done before checking >++ PL_FLAG_BORN in case the first stop reported after >++ attaching to an existing process is a PL_FLAG_BORN >++ event. */ >++ if (in_thread_list (pid_to_ptid (pid))) >++ { >++ if (debug_fbsd_lwp) >++ fprintf_unfiltered (gdb_stdlog, >++ "FLWP: using LWP %u for first thread\n", >++ pl.pl_lwpid); >++ thread_change_ptid (pid_to_ptid (pid), wptid); >++ } >++ >++#ifdef PT_LWP_EVENTS >++ if (pl.pl_flags & PL_FLAG_BORN) >++ { >++ /* If GDB attaches to a multi-threaded process, newborn >++ threads might be added by fbsd_add_threads that have >++ not yet reported their PL_FLAG_BORN event. Ignore >++ BORN events for an already-known LWP. */ >++ if (!in_thread_list (wptid)) >++ { >++ if (debug_fbsd_lwp) >++ fprintf_unfiltered (gdb_stdlog, >++ "FLWP: adding thread for LWP %u\n", >++ pl.pl_lwpid); >++ add_thread (wptid); >++ } >++ ourstatus->kind = TARGET_WAITKIND_SPURIOUS; >++ return wptid; >++ } >++#endif >++ >+ #ifdef TDP_RFPPWAIT >+ if (pl.pl_flags & PL_FLAG_FORKED) >+ { >+ struct kinfo_proc kp; >++ ptid_t child_ptid; >+ pid_t child; >+ >+ child = pl.pl_child_pid; >+ ourstatus->kind = TARGET_WAITKIND_FORKED; >+- ourstatus->value.related_pid = pid_to_ptid (child); >+ >+ /* Make sure the other end of the fork is stopped too. */ >+- if (!fbsd_is_child_pending (child)) >++ child_ptid = fbsd_is_child_pending (child); >++ if (ptid_equal (child_ptid, null_ptid)) >+ { >+ pid = waitpid (child, &status, 0); >+ if (pid == -1) >+@@ -356,6 +675,7 @@ fbsd_wait (struct target_ops *ops, >+ perror_with_name (("ptrace")); >+ >+ gdb_assert (pl.pl_flags & PL_FLAG_CHILD); >++ child_ptid = ptid_build (child, pl.pl_lwpid, 0); >+ } >+ >+ /* For vfork, the child process will have the P_PPWAIT >+@@ -363,6 +683,7 @@ fbsd_wait (struct target_ops *ops, >+ fbsd_fetch_kinfo_proc (child, &kp); >+ if (kp.ki_flag & P_PPWAIT) >+ ourstatus->kind = TARGET_WAITKIND_VFORKED; >++ ourstatus->value.related_pid = child_ptid; >+ >+ return wptid; >+ } >+@@ -372,7 +693,7 @@ fbsd_wait (struct target_ops *ops, >+ /* Remember that this child forked, but do not report it >+ until the parent reports its corresponding fork >+ event. */ >+- fbsd_remember_child (ptid_get_pid (wptid)); >++ fbsd_remember_child (wptid); >+ continue; >+ } >+ #endif >+@@ -451,13 +772,19 @@ fbsd_enable_follow_fork (pid_t pid) >+ if (ptrace (PT_FOLLOW_FORK, pid, (PTRACE_TYPE_ARG3)0, 1) == -1) >+ perror_with_name (("ptrace")); >+ } >++#endif >+ >+ /* Implement the "to_post_startup_inferior" target_ops method. */ >+ >+ static void >+ fbsd_post_startup_inferior (struct target_ops *self, ptid_t pid) >+ { >++#ifdef TDP_RFPPWAIT >+ fbsd_enable_follow_fork (ptid_get_pid (pid)); >++#endif >++#ifdef PT_LWP_EVENTS >++ fbsd_enable_lwp_events (ptid_get_pid (pid)); >++#endif >+ } >+ >+ /* Implement the "to_post_attach" target_ops method. */ >+@@ -465,9 +792,14 @@ fbsd_post_startup_inferior (struct target_ops *self, ptid_t pid) >+ static void >+ fbsd_post_attach (struct target_ops *self, int pid) >+ { >++#ifdef TDP_RFPPWAIT >+ fbsd_enable_follow_fork (pid); >+-} >+ #endif >++#ifdef PT_LWP_EVENTS >++ fbsd_enable_lwp_events (pid); >++#endif >++ fbsd_add_threads (pid); >++} >+ >+ #ifdef PL_FLAG_EXEC >+ /* If the FreeBSD kernel supports PL_FLAG_EXEC, then traced processes >+@@ -493,16 +825,25 @@ fbsd_nat_add_target (struct target_ops *t) >+ t->to_pid_to_exec_file = fbsd_pid_to_exec_file; >+ t->to_find_memory_regions = fbsd_find_memory_regions; >+ #ifdef PT_LWPINFO >++ t->to_thread_alive = fbsd_thread_alive; >++ t->to_pid_to_str = fbsd_pid_to_str; >++#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME >++ t->to_thread_name = fbsd_thread_name; >++#endif >++ t->to_update_thread_list = fbsd_update_thread_list; >++ t->to_has_thread_control = tc_schedlock; >++ super_resume = t->to_resume; >++ t->to_resume = fbsd_resume; >+ super_wait = t->to_wait; >+ t->to_wait = fbsd_wait; >++ t->to_post_startup_inferior = fbsd_post_startup_inferior; >++ t->to_post_attach = fbsd_post_attach; >+ #ifdef TDP_RFPPWAIT >+ t->to_follow_fork = fbsd_follow_fork; >+ t->to_insert_fork_catchpoint = fbsd_insert_fork_catchpoint; >+ t->to_remove_fork_catchpoint = fbsd_remove_fork_catchpoint; >+ t->to_insert_vfork_catchpoint = fbsd_insert_vfork_catchpoint; >+ t->to_remove_vfork_catchpoint = fbsd_remove_vfork_catchpoint; >+- t->to_post_startup_inferior = fbsd_post_startup_inferior; >+- t->to_post_attach = fbsd_post_attach; >+ #endif >+ #ifdef PL_FLAG_EXEC >+ t->to_insert_exec_catchpoint = fbsd_insert_exec_catchpoint; >+@@ -511,3 +852,21 @@ fbsd_nat_add_target (struct target_ops *t) >+ #endif >+ add_target (t); >+ } >++ >++/* Provide a prototype to silence -Wmissing-prototypes. */ >++extern initialize_file_ftype _initialize_fbsd_nat; >++ >++void >++_initialize_fbsd_nat (void) >++{ >++#ifdef PT_LWPINFO >++ add_setshow_boolean_cmd ("fbsd-lwp", class_maintenance, >++ &debug_fbsd_lwp, _("\ >++Set debugging of FreeBSD lwp module."), _("\ >++Show debugging of FreeBSD lwp module."), _("\ >++Enables printf debugging output."), >++ NULL, >++ &show_fbsd_lwp_debug, >++ &setdebuglist, &showdebuglist); >++#endif >++} >+diff --git gdb/fbsd-tdep.c gdb/fbsd-tdep.c >+index 9609cd8..5aa24c6 100644 >+--- gdb/fbsd-tdep.c >++++ gdb/fbsd-tdep.c >+@@ -28,6 +28,70 @@ >+ #include "fbsd-tdep.h" >+ >+ >++/* This is how we want PTIDs from core files to be printed. */ >++ >++static char * >++fbsd_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid) >++{ >++ static char buf[80]; >++ >++ if (ptid_get_lwp (ptid) != 0) >++ { >++ xsnprintf (buf, sizeof buf, "LWP %ld", ptid_get_lwp (ptid)); >++ return buf; >++ } >++ >++ return normal_pid_to_str (ptid); >++} >++ >++/* Extract the name assigned to a thread from a core. Returns the >++ string in a static buffer. */ >++ >++static const char * >++fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr) >++{ >++ static char buf[80]; >++ struct bfd_section *section; >++ bfd_size_type size; >++ char sectionstr[32]; >++ >++ if (ptid_get_lwp (thr->ptid) != 0) >++ { >++ /* FreeBSD includes a NT_FREEBSD_THRMISC note for each thread >++ whose contents are defined by a "struct thrmisc" declared in >++ <sys/procfs.h> on FreeBSD. The per-thread name is stored as >++ a null-terminated string as the first member of the >++ structure. Rather than define the full structure here, just >++ extract the null-terminated name from the start of the >++ note. */ >++ xsnprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld", >++ ptid_get_lwp (thr->ptid)); >++ section = bfd_get_section_by_name (core_bfd, sectionstr); >++ if (section != NULL && bfd_section_size (core_bfd, section) > 0) >++ { >++ /* Truncate the name if it is longer than "buf". */ >++ size = bfd_section_size (core_bfd, section); >++ if (size > sizeof buf - 1) >++ size = sizeof buf - 1; >++ if (bfd_get_section_contents (core_bfd, section, buf, (file_ptr) 0, >++ size) >++ && buf[0] != '\0') >++ { >++ buf[size] = '\0'; >++ >++ /* Note that each thread will report the process command >++ as its thread name instead of an empty name if a name >++ has not been set explicitly. Return a NULL name in >++ that case. */ >++ if (strcmp (buf, elf_tdata (core_bfd)->core->program) != 0) >++ return buf; >++ } >++ } >++ } >++ >++ return NULL; >++} >++ >+ static int >+ find_signalled_thread (struct thread_info *info, void *data) >+ { >+@@ -38,17 +102,9 @@ find_signalled_thread (struct thread_info *info, void *data) >+ return 0; >+ } >+ >+-static enum gdb_signal >+-find_stop_signal (void) >+-{ >+- struct thread_info *info = >+- iterate_over_threads (find_signalled_thread, NULL); >+- >+- if (info) >+- return info->suspend.stop_signal; >+- else >+- return GDB_SIGNAL_0; >+-} >++/* Structure for passing information from >++ fbsd_collect_thread_registers via an iterator to >++ fbsd_collect_regset_section_cb. */ >+ >+ struct fbsd_collect_regset_section_cb_data >+ { >+@@ -56,6 +112,9 @@ struct fbsd_collect_regset_section_cb_data >+ bfd *obfd; >+ char *note_data; >+ int *note_size; >++ unsigned long lwp; >++ enum gdb_signal stop_signal; >++ int abort_iteration; >+ }; >+ >+ static void >+@@ -64,7 +123,11 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size, >+ const char *human_name, void *cb_data) >+ { >+ char *buf; >+- struct fbsd_collect_regset_section_cb_data *data = cb_data; >++ struct fbsd_collect_regset_section_cb_data *data >++ = (struct fbsd_collect_regset_section_cb_data *) cb_data; >++ >++ if (data->abort_iteration) >++ return; >+ >+ gdb_assert (regset->collect_regset); >+ >+@@ -74,13 +137,73 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size, >+ /* PRSTATUS still needs to be treated specially. */ >+ if (strcmp (sect_name, ".reg") == 0) >+ data->note_data = (char *) elfcore_write_prstatus >+- (data->obfd, data->note_data, data->note_size, >+- ptid_get_pid (inferior_ptid), find_stop_signal (), buf); >++ (data->obfd, data->note_data, data->note_size, data->lwp, >++ gdb_signal_to_host (data->stop_signal), buf); >+ else >+ data->note_data = (char *) elfcore_write_register_note >+ (data->obfd, data->note_data, data->note_size, >+ sect_name, buf, size); >+ xfree (buf); >++ >++ if (data->note_data == NULL) >++ data->abort_iteration = 1; >++} >++ >++/* Records the thread's register state for the corefile note >++ section. */ >++ >++static char * >++fbsd_collect_thread_registers (const struct regcache *regcache, >++ ptid_t ptid, bfd *obfd, >++ char *note_data, int *note_size, >++ enum gdb_signal stop_signal) >++{ >++ struct gdbarch *gdbarch = get_regcache_arch (regcache); >++ struct fbsd_collect_regset_section_cb_data data; >++ >++ data.regcache = regcache; >++ data.obfd = obfd; >++ data.note_data = note_data; >++ data.note_size = note_size; >++ data.stop_signal = stop_signal; >++ data.abort_iteration = 0; >++ data.lwp = ptid_get_lwp (ptid); >++ >++ gdbarch_iterate_over_regset_sections (gdbarch, >++ fbsd_collect_regset_section_cb, >++ &data, regcache); >++ return data.note_data; >++} >++ >++struct fbsd_corefile_thread_data >++{ >++ struct gdbarch *gdbarch; >++ bfd *obfd; >++ char *note_data; >++ int *note_size; >++ enum gdb_signal stop_signal; >++}; >++ >++/* Records the thread's register state for the corefile note >++ section. */ >++ >++static void >++fbsd_corefile_thread (struct thread_info *info, >++ struct fbsd_corefile_thread_data *args) >++{ >++ struct cleanup *old_chain; >++ struct regcache *regcache; >++ >++ regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); >++ >++ old_chain = save_inferior_ptid (); >++ inferior_ptid = info->ptid; >++ target_fetch_registers (regcache, -1); >++ do_cleanups (old_chain); >++ >++ args->note_data = fbsd_collect_thread_registers >++ (regcache, info->ptid, args->obfd, args->note_data, >++ args->note_size, args->stop_signal); >+ } >+ >+ /* Create appropriate note sections for a corefile, returning them in >+@@ -89,10 +212,10 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size, >+ static char * >+ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) >+ { >+- struct regcache *regcache = get_current_regcache (); >+- char *note_data; >++ struct fbsd_corefile_thread_data thread_args; >++ char *note_data = NULL; >+ Elf_Internal_Ehdr *i_ehdrp; >+- struct fbsd_collect_regset_section_cb_data data; >++ struct thread_info *curr_thr, *signalled_thr, *thr; >+ >+ /* Put a "FreeBSD" label in the ELF header. */ >+ i_ehdrp = elf_elfheader (obfd); >+@@ -100,16 +223,6 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) >+ >+ gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch)); >+ >+- data.regcache = regcache; >+- data.obfd = obfd; >+- data.note_data = NULL; >+- data.note_size = note_size; >+- target_fetch_registers (regcache, -1); >+- gdbarch_iterate_over_regset_sections (gdbarch, >+- fbsd_collect_regset_section_cb, >+- &data, regcache); >+- note_data = data.note_data; >+- >+ if (get_exec_file (0)) >+ { >+ const char *fname = lbasename (get_exec_file (0)); >+@@ -123,6 +236,50 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) >+ fname, psargs); >+ } >+ >++ /* Thread register information. */ >++ TRY >++ { >++ update_thread_list (); >++ } >++ CATCH (e, RETURN_MASK_ERROR) >++ { >++ exception_print (gdb_stderr, e); >++ } >++ END_CATCH >++ >++ /* Like the kernel, prefer dumping the signalled thread first. >++ "First thread" is what tools use to infer the signalled thread. >++ In case there's more than one signalled thread, prefer the >++ current thread, if it is signalled. */ >++ curr_thr = inferior_thread (); >++ if (curr_thr->suspend.stop_signal != GDB_SIGNAL_0) >++ signalled_thr = curr_thr; >++ else >++ { >++ signalled_thr = iterate_over_threads (find_signalled_thread, NULL); >++ if (signalled_thr == NULL) >++ signalled_thr = curr_thr; >++ } >++ >++ thread_args.gdbarch = gdbarch; >++ thread_args.obfd = obfd; >++ thread_args.note_data = note_data; >++ thread_args.note_size = note_size; >++ thread_args.stop_signal = signalled_thr->suspend.stop_signal; >++ >++ fbsd_corefile_thread (signalled_thr, &thread_args); >++ ALL_NON_EXITED_THREADS (thr) >++ { >++ if (thr == signalled_thr) >++ continue; >++ if (ptid_get_pid (thr->ptid) != ptid_get_pid (inferior_ptid)) >++ continue; >++ >++ fbsd_corefile_thread (thr, &thread_args); >++ } >++ >++ note_data = thread_args.note_data; >++ >+ return note_data; >+ } >+ >+@@ -131,5 +288,7 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) >+ void >+ fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) >+ { >++ set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str); >++ set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name); >+ set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes); >+ } >+diff --git gdb/gdbarch.c gdb/gdbarch.c >+index c289334..c8e2512 100644 >+--- gdb/gdbarch.c >++++ gdb/gdbarch.c >+@@ -269,6 +269,7 @@ struct gdbarch >+ gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries; >+ gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix; >+ gdbarch_core_pid_to_str_ftype *core_pid_to_str; >++ gdbarch_core_thread_name_ftype *core_thread_name; >+ const char * gcore_bfd_target; >+ int vtable_function_descriptors; >+ int vbit_in_delta; >+@@ -604,6 +605,7 @@ verify_gdbarch (struct gdbarch *gdbarch) >+ /* Skip verify of core_xfer_shared_libraries, has predicate. */ >+ /* Skip verify of core_xfer_shared_libraries_aix, has predicate. */ >+ /* Skip verify of core_pid_to_str, has predicate. */ >++ /* Skip verify of core_thread_name, has predicate. */ >+ /* Skip verify of gcore_bfd_target, has predicate. */ >+ /* Skip verify of vtable_function_descriptors, invalid_p == 0 */ >+ /* Skip verify of vbit_in_delta, invalid_p == 0 */ >+@@ -816,6 +818,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) >+ "gdbarch_dump: core_read_description = <%s>\n", >+ host_address_to_string (gdbarch->core_read_description)); >+ fprintf_unfiltered (file, >++ "gdbarch_dump: gdbarch_core_thread_name_p() = %d\n", >++ gdbarch_core_thread_name_p (gdbarch)); >++ fprintf_unfiltered (file, >++ "gdbarch_dump: core_thread_name = <%s>\n", >++ host_address_to_string (gdbarch->core_thread_name)); >++ fprintf_unfiltered (file, >+ "gdbarch_dump: gdbarch_core_xfer_shared_libraries_p() = %d\n", >+ gdbarch_core_xfer_shared_libraries_p (gdbarch)); >+ fprintf_unfiltered (file, >+@@ -3546,6 +3554,30 @@ set_gdbarch_core_pid_to_str (struct gdbarch *gdbarch, >+ } >+ >+ int >++gdbarch_core_thread_name_p (struct gdbarch *gdbarch) >++{ >++ gdb_assert (gdbarch != NULL); >++ return gdbarch->core_thread_name != NULL; >++} >++ >++const char * >++gdbarch_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr) >++{ >++ gdb_assert (gdbarch != NULL); >++ gdb_assert (gdbarch->core_thread_name != NULL); >++ if (gdbarch_debug >= 2) >++ fprintf_unfiltered (gdb_stdlog, "gdbarch_core_thread_name called\n"); >++ return gdbarch->core_thread_name (gdbarch, thr); >++} >++ >++void >++set_gdbarch_core_thread_name (struct gdbarch *gdbarch, >++ gdbarch_core_thread_name_ftype core_thread_name) >++{ >++ gdbarch->core_thread_name = core_thread_name; >++} >++ >++int >+ gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch) >+ { >+ gdb_assert (gdbarch != NULL); >+diff --git gdb/gdbarch.h gdb/gdbarch.h >+index 7d6a0cf..4dab0f7 100644 >+--- gdb/gdbarch.h >++++ gdb/gdbarch.h >+@@ -64,6 +64,7 @@ struct ravenscar_arch_ops; >+ struct elf_internal_linux_prpsinfo; >+ struct mem_range; >+ struct syscalls_info; >++struct thread_info; >+ >+ #include "regcache.h" >+ >+@@ -866,6 +867,14 @@ typedef char * (gdbarch_core_pid_to_str_ftype) (struct gdbarch *gdbarch, ptid_t >+ extern char * gdbarch_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid); >+ extern void set_gdbarch_core_pid_to_str (struct gdbarch *gdbarch, gdbarch_core_pid_to_str_ftype *core_pid_to_str); >+ >++/* How the core target extracts the name of a thread from a core file. */ >++ >++extern int gdbarch_core_thread_name_p (struct gdbarch *gdbarch); >++ >++typedef const char * (gdbarch_core_thread_name_ftype) (struct gdbarch *gdbarch, struct thread_info *thr); >++extern const char * gdbarch_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr); >++extern void set_gdbarch_core_thread_name (struct gdbarch *gdbarch, gdbarch_core_thread_name_ftype *core_thread_name); >++ >+ /* BFD target to use when generating a core file. */ >+ >+ extern int gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch); >+diff --git gdb/i386bsd-nat.c gdb/i386bsd-nat.c >+index ac8a19b..922c0e7 100644 >+--- gdb/i386bsd-nat.c >++++ gdb/i386bsd-nat.c >+@@ -138,7 +138,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, >+ { >+ struct reg regs; >+ >+- if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't get registers")); >+ >+@@ -160,7 +160,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, >+ char *xstateregs; >+ >+ xstateregs = alloca (i386bsd_xsave_len); >+- if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) >+ perror_with_name (_("Couldn't get extended state status")); >+ >+@@ -171,7 +171,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, >+ >+ #ifdef HAVE_PT_GETXMMREGS >+ if (have_ptrace_xmmregs != 0 >+- && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), >++ && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) >+ { >+ have_ptrace_xmmregs = 1; >+@@ -181,7 +181,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, >+ { >+ have_ptrace_xmmregs = 0; >+ #endif >+- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't get floating point status")); >+ >+@@ -203,13 +203,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, >+ { >+ struct reg regs; >+ >+- if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't get registers")); >+ >+ i386bsd_collect_gregset (regcache, ®s, regnum); >+ >+- if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't write registers")); >+ >+@@ -230,13 +230,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, >+ char *xstateregs; >+ >+ xstateregs = alloca (i386bsd_xsave_len); >+- if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) >+ perror_with_name (_("Couldn't get extended state status")); >+ >+ i387_collect_xsave (regcache, -1, xstateregs, 0); >+ >+- if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETXSTATE, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xstateregs, i386bsd_xsave_len) == -1) >+ perror_with_name (_("Couldn't write extended state status")); >+ return; >+@@ -245,14 +245,14 @@ i386bsd_store_inferior_registers (struct target_ops *ops, >+ >+ #ifdef HAVE_PT_GETXMMREGS >+ if (have_ptrace_xmmregs != 0 >+- && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), >++ && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) >+ { >+ have_ptrace_xmmregs = 1; >+ >+ i387_collect_fxsave (regcache, regnum, xmmregs); >+ >+- if (ptrace (PT_SETXMMREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETXMMREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) xmmregs, 0) == -1) >+ perror_with_name (_("Couldn't write XMM registers")); >+ } >+@@ -260,13 +260,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, >+ { >+ have_ptrace_xmmregs = 0; >+ #endif >+- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't get floating point status")); >+ >+ i387_collect_fsave (regcache, regnum, &fpregs); >+ >+- if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETFPREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't write floating point status")); >+ #ifdef HAVE_PT_GETXMMREGS >+@@ -305,7 +305,7 @@ i386bsd_dr_get (ptid_t ptid, int regnum) >+ { >+ struct dbreg dbregs; >+ >+- if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) >+ perror_with_name (_("Couldn't read debug registers")); >+ >+@@ -317,7 +317,7 @@ i386bsd_dr_set (int regnum, unsigned int value) >+ { >+ struct dbreg dbregs; >+ >+- if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) >+ perror_with_name (_("Couldn't get debug registers")); >+ >+@@ -328,7 +328,7 @@ i386bsd_dr_set (int regnum, unsigned int value) >+ >+ DBREG_DRX ((&dbregs), regnum) = value; >+ >+- if (ptrace (PT_SETDBREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETDBREGS, get_ptrace_pid (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) >+ perror_with_name (_("Couldn't write debug registers")); >+ } >+diff --git gdb/inf-ptrace.c gdb/inf-ptrace.c >+index cd58dfb..06c4e4f 100644 >+--- gdb/inf-ptrace.c >++++ gdb/inf-ptrace.c >+@@ -304,7 +304,7 @@ inf_ptrace_stop (struct target_ops *self, ptid_t ptid) >+ /* Return which PID to pass to ptrace in order to observe/control the >+ tracee identified by PTID. */ >+ >+-static pid_t >++pid_t >+ get_ptrace_pid (ptid_t ptid) >+ { >+ pid_t pid; >+diff --git gdb/inf-ptrace.h gdb/inf-ptrace.h >+index e74ec84..504821b 100644 >+--- gdb/inf-ptrace.h >++++ gdb/inf-ptrace.h >+@@ -33,4 +33,9 @@ extern struct target_ops * >+ inf_ptrace_trad_target (CORE_ADDR (*register_u_offset) >+ (struct gdbarch *, int, int)); >+ >++/* Return which PID to pass to ptrace in order to observe/control the >++ tracee identified by PTID. */ >++ >++extern pid_t get_ptrace_pid (ptid_t); >++ >+ #endif >+diff --git gdb/ppcfbsd-nat.c gdb/ppcfbsd-nat.c >+index 778e19a..df89c2d 100644 >+--- gdb/ppcfbsd-nat.c >++++ gdb/ppcfbsd-nat.c >+@@ -121,7 +121,7 @@ ppcfbsd_fetch_inferior_registers (struct target_ops *ops, >+ { >+ gdb_gregset_t regs; >+ >+- if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETREGS, ptid_get_lwp (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't get registers")); >+ >+@@ -132,7 +132,7 @@ ppcfbsd_fetch_inferior_registers (struct target_ops *ops, >+ const struct regset *fpregset = ppc_fbsd_fpregset (); >+ gdb_fpregset_t fpregs; >+ >+- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETFPREGS, ptid_get_lwp (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't get FP registers")); >+ >+@@ -149,13 +149,13 @@ ppcfbsd_store_inferior_registers (struct target_ops *ops, >+ { >+ gdb_gregset_t regs; >+ >+- if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETREGS, ptid_get_lwp (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't get registers")); >+ >+ fill_gregset (regcache, ®s, regno); >+ >+- if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETREGS, ptid_get_lwp (inferior_ptid), >+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) >+ perror_with_name (_("Couldn't write registers")); >+ >+@@ -163,13 +163,13 @@ ppcfbsd_store_inferior_registers (struct target_ops *ops, >+ { >+ gdb_fpregset_t fpregs; >+ >+- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_GETFPREGS, ptid_get_lwp (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't get FP registers")); >+ >+ fill_fpregset (regcache, &fpregs, regno); >+ >+- if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), >++ if (ptrace (PT_SETFPREGS, ptid_get_lwp (inferior_ptid), >+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) >+ perror_with_name (_("Couldn't set FP registers")); >+ } >+diff --git include/elf/common.h include/elf/common.h >+index e6d8c14..39582df 100644 >+--- include/elf/common.h >++++ include/elf/common.h >+@@ -594,6 +594,20 @@ >+ /* Note segment for SystemTap probes. */ >+ #define NT_STAPSDT 3 >+ >++/* Note segments for core files on FreeBSD systems. Note name is >++ "FreeBSD". */ >++ >++#define NT_FREEBSD_THRMISC 7 /* Thread miscellaneous info. */ >++#define NT_FREEBSD_PROCSTAT_PROC 8 /* Procstat proc data. */ >++#define NT_FREEBSD_PROCSTAT_FILES 9 /* Procstat files data. */ >++#define NT_FREEBSD_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */ >++#define NT_FREEBSD_PROCSTAT_GROUPS 11 /* Procstat groups data. */ >++#define NT_FREEBSD_PROCSTAT_UMASK 12 /* Procstat umask data. */ >++#define NT_FREEBSD_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */ >++#define NT_FREEBSD_PROCSTAT_OSREL 14 /* Procstat osreldate data. */ >++#define NT_FREEBSD_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */ >++#define NT_FREEBSD_PROCSTAT_AUXV 16 /* Procstat auxv data. */ >++ >+ /* Note segments for core files on NetBSD systems. Note name >+ must start with "NetBSD-CORE". */ >+ > >Property changes on: devel/gdb/files/extrapatch-threads-ptrace >___________________________________________________________________ >Added: fbsd:nokeywords >## -0,0 +1 ## >+yes >\ No newline at end of property >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Added: svn:mime-type >## -0,0 +1 ## >+text/plain >\ No newline at end of property
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 201207
:
158169
|
163019
|
165188
|
165447
| 165834 |
165924
|
165926
|
166037