aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog37
-rw-r--r--gdb/NEWS6
-rw-r--r--gdb/config.in3
-rwxr-xr-xgdb/configure16
-rw-r--r--gdb/configure.ac7
-rw-r--r--gdb/doc/ChangeLog4
-rw-r--r--gdb/doc/gdb.texinfo5
-rw-r--r--gdb/fbsd-nat.c423
8 files changed, 469 insertions, 32 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0d9a7fb..2cdf2fa 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,42 @@
2016-01-19 John Baldwin <jhb@FreeBSD.org>
+ * configure.ac: Check for support for LWP names on FreeBSD.
+ * fbsd-nat.c [PT_LWPINFO] New variable debug_fbsd_lwp.
+ [TDP_RFPPWAIT || HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME]
+ (fbsd_fetch_kinfo_proc): Move function earlier.
+ [PT_LWPINFO] (fbsd_thread_alive): New function.
+ [PT_LWPINFO] (fbsd_pid_to_str): New function.
+ [HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME] (fbsd_thread_name): New function.
+ [PT_LWP_EVENTS] (fbsd_enable_lwp_events): New function.
+ [PT_LWPINFO] (fbsd_add_threads): New function.
+ [PT_LWPINFO] (fbsd_update_thread_list): New function.
+ [PT_LWPINFO] New variable super_resume.
+ [PT_LWPINFO] (resume_one_thread_cb): New function.
+ [PT_LWPINFO] (resume_all_threads_cb): New function.
+ [PT_LWPINFO] (fbsd_resume): New function.
+ (fbsd_remember_child): Save full ptid instead of plain pid.
+ (fbsd_is_child_pending): Return ptid of saved child process.
+ (fbsd_wait): Include lwp in returned ptid and switch to LWP ptid on
+ first stop.
+ [PT_LWP_EVENTS] Handle LWP events.
+ [TDP_RFPPWAIT] Include LWP in child ptid.
+ (fbsd_post_startup_inferior) [PT_LWP_EVENTS]: Enable LWP events.
+ (fbsd_post_attach) [PT_LWP_EVENTS]: Enable LWP events.
+ Add threads for existing processes.
+ (fbsd_nat_add_target) [PT_LWPINFO]: Set "to_thread_alive" to
+ "fbsd_thread_alive".
+ Set "to_pid_to_str" to "fbsd_pid_to_str".
+ [HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME]: Set "to_thread_name" to
+ "fbsd_thread_name".
+ [PT_LWPINFO]: Set "to_update_thread_list" to "fbsd_update_thread_list".
+ Set "to_has_thread_control" to "tc_schedlock".
+ Set "to_resume" to "fbsd_resume".
+ (_initialize_fbsd_nat): New function.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+
+2016-01-19 John Baldwin <jhb@FreeBSD.org>
+
* amd64bsd-nat.c (amd64bsd_fetch_inferior_registers): Use
get_ptrace_pid.
(amd64bsd_store_inferior_registers): Use get_ptrace_pid.
diff --git a/gdb/NEWS b/gdb/NEWS
index f4ba65d..4312117 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,8 @@
*** Changes since GDB 7.10
+* GDB now supports debugging kernel-based threads on FreeBSD.
+
* Per-inferior thread numbers
Thread numbers are now per inferior instead of global. If you're
@@ -100,6 +102,10 @@ set debug bfd-cache
show debug bfd-cache
Control display of debugging info regarding bfd caching.
+set debug fbsd-lwp
+show debug fbsd-lwp
+ Control display of debugging info regarding FreeBSD threads.
+
set remote multiprocess-extensions-packet
show remote multiprocess-extensions-packet
Set/show the use of the remote protocol multiprocess extensions.
diff --git a/gdb/config.in b/gdb/config.in
index 6196fa0..dc9da0a 100644
--- a/gdb/config.in
+++ b/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 a/gdb/configure b/gdb/configure
index 11f91e3..701cfcb 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -12965,6 +12965,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 a/gdb/configure.ac b/gdb/configure.ac
index 8f9486e..a7b7421 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1511,6 +1511,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 a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 59a8e0a..990f2ec 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-19 John Baldwin <jhb@FreeBSD.org>
+
+ * gdb.texinfo (Debugging Output): Document "set/show debug fbsd-lwp".
+
2016-01-18 Pedro Alves <palves@redhat.com>
* gdb.texinfo (Threads): Mention that GDB displays the ID and name
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index f996c8d..cd311db 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -23608,6 +23608,11 @@ expression parsing. The default is off.
@item show debug expression
Displays the current state of displaying debugging info about
@value{GDBN} expression parsing.
+@item set debug fbsd-lwp
+@cindex FreeBSD LWP debug messages
+Turns on or off debugging messages from the FreeBSD LWP debug support.
+@item show debug fbsd-lwp
+Show the current state of FreeBSD LWP debugging messages.
@item set debug frame
@cindex frame debugging info
Turns on or off display of @value{GDBN} frame debugging info. The
diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c
index 702e51d..d2ec527 100644
--- a/gdb/fbsd-nat.c
+++ b/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 = 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);
+}
+
+/* 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 = XCNEW (struct fbsd_fork_child_info);
@@ -265,45 +538,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
@@ -328,21 +585,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)
@@ -354,6 +673,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
@@ -361,6 +681,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;
}
@@ -370,7 +691,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
@@ -449,13 +770,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. */
@@ -463,9 +790,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
@@ -491,16 +823,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;
@@ -509,3 +850,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
+}