public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores.
  2016-01-13 21:46 [PATCH v2 0/6] Support kernel-backed user threads on FreeBSD John Baldwin
  2016-01-13 21:46 ` [PATCH v2 6/6] Dump register notes for each thread when generating a FreeBSD core John Baldwin
@ 2016-01-13 21:46 ` John Baldwin
  2016-01-14 15:03   ` Pedro Alves
  2016-01-13 21:46 ` [PATCH v2 1/6] Add support to readelf for reading FreeBSD ELF core notes John Baldwin
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-13 21:46 UTC (permalink / raw)
  To: gdb-patches, binutils

Display the LWP ID of each thread in a FreeBSD core.  Extract thread names
from the per-thread THRMISC note.

gdb/ChangeLog:

	* fbsd_tdep.c (fbsd_core_pid_to_str): New function.
	(fbsd_init_abi): Add "core_pid_to_str" gdbarch method.
---
 gdb/ChangeLog   |  5 +++++
 gdb/fbsd-tdep.c | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 471d02b..93760ba 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-09  John Baldwin  <jhb@FreeBSD.org>
+
+	* fbsd_tdep.c (fbsd_core_pid_to_str): New function.
+	(fbsd_init_abi): Add "core_pid_to_str" gdbarch method.
+
 2016-01-08  Yao Qi  <yao.qi@linaro.org>
 
 	* extension.c: Include target.h.
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index 0ef94d6..6851cc1 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -28,6 +28,46 @@
 #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], name[64];
+  struct bfd_section *section;
+  bfd_size_type size;
+  char sectionstr[32];
+
+  if (ptid_get_lwp (ptid) != 0)
+    {
+      snprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld",
+		ptid_get_lwp (ptid));
+      section = bfd_get_section_by_name (core_bfd, sectionstr);
+      if (section != NULL)
+	{
+	  char *name;
+
+	  size = bfd_section_size (core_bfd, section);
+	  name = alloca (size + 1);
+	  if (bfd_get_section_contents (core_bfd, section, name, (file_ptr) 0,
+					size) && name[0] != '\0')
+	    {
+	      name[size] = '\0';
+	      if (strcmp(name, elf_tdata (core_bfd)->core->program) != 0)
+		{
+		  snprintf (buf, sizeof buf, "LWP %ld \"%s\"",
+			    ptid_get_lwp (ptid), name);
+		  return buf;
+		}
+	    }
+	}
+      snprintf (buf, sizeof buf, "LWP %ld", ptid_get_lwp (ptid));
+      return buf;
+    }
+
+  return normal_pid_to_str (ptid);
+}
+
 static int
 find_signalled_thread (struct thread_info *info, void *data)
 {
@@ -132,5 +172,6 @@ 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_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
 }
-- 
2.7.0

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 6/6] Dump register notes for each thread when generating a FreeBSD core.
  2016-01-13 21:46 [PATCH v2 0/6] Support kernel-backed user threads on FreeBSD John Baldwin
@ 2016-01-13 21:46 ` John Baldwin
  2016-01-14 15:34   ` Pedro Alves
  2016-01-13 21:46 ` [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores John Baldwin
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-13 21:46 UTC (permalink / raw)
  To: gdb-patches, binutils

gdb/ChangeLog:

	* fbsd-tdep.c (find_stop_signal): Remove.
	(struct fbsd_collect_regset_section_cb) <lwp>: New field.
	<stop_signal>: New field.
	<abort_iteration>: New field.
	(fbsd_collect_regset_section_cb): Use new fields.
	(fbsd_collect_thread_registers): New function.
	(struct fbsd_corefile_thread_data): New structure.
	(fbsd_corefile_thread): New function.
	(fbsd_make_corefile_notes): Use new function to dump notes for each
	non-exited thread in a process.
---
 gdb/ChangeLog   |  13 +++++
 gdb/fbsd-tdep.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 131 insertions(+), 26 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fdf35b0..178046d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,18 @@
 2016-01-10  John Baldwin  <jhb@FreeBSD.org>
 
+	* fbsd-tdep.c (find_stop_signal): Remove.
+	(struct fbsd_collect_regset_section_cb) <lwp>: New field.
+	<stop_signal>: New field.
+	<abort_iteration>: New field.
+	(fbsd_collect_regset_section_cb): Use new fields.
+	(fbsd_collect_thread_registers): New function.
+	(struct fbsd_corefile_thread_data): New structure.
+	(fbsd_corefile_thread): New function.
+	(fbsd_make_corefile_notes): Use new function to dump notes for each
+	non-exited thread in a process.
+
+2016-01-10  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]
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index 6851cc1..be3350e 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -78,17 +78,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
 {
@@ -96,6 +88,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
@@ -107,6 +102,9 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size,
   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);
 
   buf = (char *) xmalloc (size);
@@ -115,13 +113,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
@@ -130,10 +188,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);
@@ -141,16 +199,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));
@@ -164,6 +212,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;
 }
 
-- 
2.7.0

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 1/6] Add support to readelf for reading FreeBSD ELF core notes.
  2016-01-13 21:46 [PATCH v2 0/6] Support kernel-backed user threads on FreeBSD John Baldwin
  2016-01-13 21:46 ` [PATCH v2 6/6] Dump register notes for each thread when generating a FreeBSD core John Baldwin
  2016-01-13 21:46 ` [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores John Baldwin
@ 2016-01-13 21:46 ` John Baldwin
  2016-01-14  5:30   ` Alan Modra
  2016-01-13 21:46 ` [PATCH v2 2/6] Add a psuedosection for the NT_FREEBSD_THRMISC note John Baldwin
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-13 21:46 UTC (permalink / raw)
  To: gdb-patches, binutils

binutils/ChangeLog:

	* readelf.c (get_freebsd_elfcore_note_type): New
	(process_note): Add support for FreeBSD core notes.

include/elf/ChangeLog:

	* common.h (NT_FREEBSD_THRMISC): Define.
	(NT_FREEBSD_PROCSTAT_PROC): Define.
	(NT_FREEBSD_PROCSTAT_FILES): Define.
	(NT_FREEBSD_PROCSTAT_VMMAP): Define.
	(NT_FREEBSD_PROCSTAT_GROUPS): Define.
	(NT_FREEBSD_PROCSTAT_UMASK): Define.
	(NT_FREEBSD_PROCSTAT_RLIMIT): Define.
	(NT_FREEBSD_PROCSTAT_OSREL): Define.
	(NT_FREEBSD_PROCSTAT_PSSTRINGS): Define.
	(NT_FREEBSD_PROCSTAT_AUXV): Define.
---
 binutils/ChangeLog    |  5 +++++
 binutils/readelf.c    | 35 +++++++++++++++++++++++++++++++++++
 include/elf/ChangeLog | 27 +++++++++++++++++++++++++++
 include/elf/common.h  | 14 ++++++++++++++
 4 files changed, 81 insertions(+)
 create mode 100644 include/elf/ChangeLog

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 21dcb2c..47773c9 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-09  John Baldwin  <jhb@FreeBSD.org>
+
+	* readelf.c (get_freebsd_elfcore_note_type): New
+	(process_note): Add support for FreeBSD core notes.
+
 2016-01-01  Alan Modra  <amodra@gmail.com>
 
 	Update year range in copyright notice of all files.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 47ac1ad..fa9cda1 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -15388,6 +15388,37 @@ process_netbsd_elf_note (Elf_Internal_Note * pnote)
 }
 
 static const char *
+get_freebsd_elfcore_note_type (unsigned e_type)
+{
+  static char buff[64];
+
+  switch (e_type)
+    {
+    case NT_FREEBSD_THRMISC:
+      return _("NT_THRMISC (thrmisc structure)");
+    case NT_FREEBSD_PROCSTAT_PROC:
+      return _("NT_PROCSTAT_PROC (proc data)");
+    case NT_FREEBSD_PROCSTAT_FILES:
+      return _("NT_PROCSTAT_FILES (files data)");
+    case NT_FREEBSD_PROCSTAT_VMMAP:
+      return _("NT_PROCSTAT_VMMAP (vmmap data)");
+    case NT_FREEBSD_PROCSTAT_GROUPS:
+      return _("NT_PROCSTAT_GROUPS (groups data)");
+    case NT_FREEBSD_PROCSTAT_UMASK:
+      return _("NT_PROCSTAT_UMASK (umask data)");
+    case NT_FREEBSD_PROCSTAT_RLIMIT:
+      return _("NT_PROCSTAT_RLIMIT (rlimit data)");
+    case NT_FREEBSD_PROCSTAT_OSREL:
+      return _("NT_PROCSTAT_OSREL (osreldate data)");
+    case NT_FREEBSD_PROCSTAT_PSSTRINGS:
+      return _("NT_PROCSTAT_PSSTRINGS (ps_strings data)");
+    case NT_FREEBSD_PROCSTAT_AUXV:
+      return _("NT_PROCSTAT_AUXV (auxv data)");
+    }
+  return get_note_type (e_type);
+}
+
+static const char *
 get_netbsd_elfcore_note_type (unsigned e_type)
 {
   static char buff[64];
@@ -15636,6 +15667,10 @@ process_note (Elf_Internal_Note * pnote)
     /* GNU-specific object file notes.  */
     nt = get_gnu_elf_note_type (pnote->type);
 
+  else if (const_strneq (pnote->namedata, "FreeBSD"))
+    /* FreeBSD-specific core file notes.  */
+    nt = get_freebsd_elfcore_note_type (pnote->type);
+
   else if (const_strneq (pnote->namedata, "NetBSD-CORE"))
     /* NetBSD-specific core file notes.  */
     nt = get_netbsd_elfcore_note_type (pnote->type);
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
new file mode 100644
index 0000000..821a8bc
--- /dev/null
+++ b/include/elf/ChangeLog
@@ -0,0 +1,27 @@
+2016-01-09  John Baldwin  <jhb@FreeBSD.org>
+
+	* common.h (NT_FREEBSD_THRMISC): Define.
+	(NT_FREEBSD_PROCSTAT_PROC): Define.
+	(NT_FREEBSD_PROCSTAT_FILES): Define.
+	(NT_FREEBSD_PROCSTAT_VMMAP): Define.
+	(NT_FREEBSD_PROCSTAT_GROUPS): Define.
+	(NT_FREEBSD_PROCSTAT_UMASK): Define.
+	(NT_FREEBSD_PROCSTAT_RLIMIT): Define.
+	(NT_FREEBSD_PROCSTAT_OSREL): Define.
+	(NT_FREEBSD_PROCSTAT_PSSTRINGS): Define.
+	(NT_FREEBSD_PROCSTAT_AUXV): Define.
+
+For older changes see ChangeLog-0415
+\f
+Copyright (C) 2016 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
+
+Local Variables:
+mode: change-log
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/include/elf/common.h b/include/elf/common.h
index ce506fc..767ad3e 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -595,6 +595,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".  */
 
-- 
2.7.0

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 2/6] Add a psuedosection for the NT_FREEBSD_THRMISC note.
  2016-01-13 21:46 [PATCH v2 0/6] Support kernel-backed user threads on FreeBSD John Baldwin
                   ` (2 preceding siblings ...)
  2016-01-13 21:46 ` [PATCH v2 1/6] Add support to readelf for reading FreeBSD ELF core notes John Baldwin
@ 2016-01-13 21:46 ` John Baldwin
  2016-01-14  5:30   ` Alan Modra
  2016-01-13 21:52 ` [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD John Baldwin
  2016-01-13 21:52 ` [PATCH v2 5/6] Add support for LWP-based threads " John Baldwin
  5 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-13 21:46 UTC (permalink / raw)
  To: gdb-patches, binutils

bfd/ChangeLog:

	* elf.c (elfcore_grok_note): Recognize NT_FREEBSD_THRMISC notes.
---
 bfd/ChangeLog | 4 ++++
 bfd/elf.c     | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index d1c5a3b..fb9bb61 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-09  John Baldwin  <jhb@FreeBSD.org>
+
+	* elf.c (elfcore_grok_note): Recognize NT_FREEBSD_THRMISC notes.
+
 2016-01-08  Richard Sandiford  <richard.sandiford@arm.com>
 	    Jiong Wang  <jiong.wang@arm.com>
 
diff --git a/bfd/elf.c b/bfd/elf.c
index a1f857a..b2a50bf 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -9287,6 +9287,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;
     }
 }
 
-- 
2.7.0

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 0/6] Support kernel-backed user threads on FreeBSD
@ 2016-01-13 21:46 John Baldwin
  2016-01-13 21:46 ` [PATCH v2 6/6] Dump register notes for each thread when generating a FreeBSD core John Baldwin
                   ` (5 more replies)
  0 siblings, 6 replies; 25+ messages in thread
From: John Baldwin @ 2016-01-13 21:46 UTC (permalink / raw)
  To: gdb-patches, binutils

This set of patches adds support for examining kernel-backed user threads on
FreeBSD.  There is more history in a comment in fbsd-nat.c, but this target
uses ptrace directly (instead of libthread_db) to support the current
threading library (libthr) on FreeBSD which uses a kernel thread for each
user thread.  Support for thread names in both core dumps (via FreeBSD's
OS-specific NT_THRMISC core note) and live is supported as is scheduler
locking.  gcore generates register notes for each thread as well.

The first two patches are to binutils to support FreeBSD-specific core
notes.  The last four are to GDB.

Changes since the first version are that ptids for fbsd-nat always include
an LWP.  The default ptid for an inferior is changed to include the lwp
via thread_change_ptid() on the first stop in fbsd_wait().

I also changed the fork tracing to include the LWP of the new child process
in the ptid for the child from the start.  I did not let the new child
"auto-discover" its LWP due to the following race:

The first stop of a new child process is not reported directly to the main
loop (it is reported instead via the 'related_pid' of the parent process
fork event).  As such, there is no 'thread' in gdb yet whose ptid can be
updated to include the LWP when that first stop is reported.  If the next
stop from the child process reports the birth of a new LWP, the existing
logic would have use that LWP to replace the sole thread and would not
include the "main" thread in the thread list.  Rather than rescanning all
threads in that case, it seems simpler and more straightforward to simulate
the effect of thread_change_ptid() on the first child stop by reporting the
full ptid (including LWP) of the new child process in 'related_pid'.

John Baldwin (6):
  Add support to readelf for reading FreeBSD ELF core notes.
  Add a psuedosection for the NT_FREEBSD_THRMISC note.
  Display per-thread information for threads in FreeBSD cores.
  Use LWP IDs with ptrace register requests on FreeBSD.
  Add support for LWP-based threads on FreeBSD.
  Dump register notes for each thread when generating a FreeBSD core.

 bfd/ChangeLog         |   4 +
 bfd/elf.c             |   7 +
 binutils/ChangeLog    |   5 +
 binutils/readelf.c    |  35 +++++
 gdb/ChangeLog         |  71 +++++++++
 gdb/amd64bsd-nat.c    |  35 +++--
 gdb/config.in         |   3 +
 gdb/configure         |  16 ++
 gdb/configure.ac      |   7 +
 gdb/fbsd-nat.c        | 414 ++++++++++++++++++++++++++++++++++++++++++++++----
 gdb/fbsd-tdep.c       | 185 ++++++++++++++++++----
 gdb/i386bsd-nat.c     |  41 +++--
 gdb/ppcfbsd-nat.c     |  23 ++-
 include/elf/ChangeLog |  27 ++++
 include/elf/common.h  |  14 ++
 15 files changed, 797 insertions(+), 90 deletions(-)
 create mode 100644 include/elf/ChangeLog

-- 
2.7.0

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 5/6] Add support for LWP-based threads on FreeBSD.
  2016-01-13 21:46 [PATCH v2 0/6] Support kernel-backed user threads on FreeBSD John Baldwin
                   ` (4 preceding siblings ...)
  2016-01-13 21:52 ` [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD John Baldwin
@ 2016-01-13 21:52 ` John Baldwin
  2016-01-14 15:29   ` Pedro Alves
  5 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-13 21:52 UTC (permalink / raw)
  To: gdb-patches, binutils

Older versions of FreeBSD supported userland threading via a pure
user-space threading library (N threads scheduled on 1 process) and
a N:M model (N threads scheduled on M LWPs).  However, modern FreeBSD
versions only support a M:M threading model where each user thread is
backed by a dedicated LWP.  This thread target only supports this
threading model.  It also uses ptrace to query and alter LWP state
directly rather than using libthread_db to simplify the implementation.

FreeBSD recently gained support for reporting LWP events (birth and death
of LWPs).  GDB will use LWP events when present.  For older systems it
fetches the list of LWPs in the to_update_thread_list target op to update
the list of threads on each stop.

This target supports scheduler locking by using ptrace to suspend
individual LWPs as necessary before resuming a process.

gdb/ChangeLog:

	* 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.
---
 gdb/ChangeLog    |  38 +++++
 gdb/config.in    |   3 +
 gdb/configure    |  16 +++
 gdb/configure.ac |   7 +
 gdb/fbsd-nat.c   | 414 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 5 files changed, 447 insertions(+), 31 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0accac9..fdf35b0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,4 +1,42 @@
 2016-01-10  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-10  John Baldwin  <jhb@FreeBSD.org>
+
 	* amd64bsd-nat.c (get_ptrace_pid): New function.
 	(amd64bsd_fetch_inferior_registers): Use new function.
 	(amd64bsd_store_inferior_registers): Use new function.
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 15383d6..2dc1c9d 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -12964,6 +12964,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 d102640..ad62310 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1510,6 +1510,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/fbsd-nat.c b/gdb/fbsd-nat.c
index 702e51d..ee53f82 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,276 @@ 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);
 
+#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[64];
+
+  /* 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), (caddr_t)0, 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), (caddr_t)0, 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 +512,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 +521,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 +531,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
 
@@ -331,18 +581,80 @@ fbsd_wait (struct target_ops *ops,
 	  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, (PTRACE_TYPE_ARG3)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 +666,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 +674,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 +684,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 +763,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 +783,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 +816,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 +843,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,
+			   NULL,
+			   &setdebuglist, &showdebuglist);
+#endif
+}
-- 
2.7.0

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD.
  2016-01-13 21:46 [PATCH v2 0/6] Support kernel-backed user threads on FreeBSD John Baldwin
                   ` (3 preceding siblings ...)
  2016-01-13 21:46 ` [PATCH v2 2/6] Add a psuedosection for the NT_FREEBSD_THRMISC note John Baldwin
@ 2016-01-13 21:52 ` John Baldwin
  2016-01-14 15:07   ` Pedro Alves
  2016-01-13 21:52 ` [PATCH v2 5/6] Add support for LWP-based threads " John Baldwin
  5 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-13 21:52 UTC (permalink / raw)
  To: gdb-patches, binutils

This allows gdb to fetch per-thread registers for multi-threaded FreeBSD
processes.  NetBSD and OpenBSD also accept LWP IDs for ptrace requests
to fetch per-thread state.

gdb/ChangeLog:

	* amd64bsd-nat.c (get_ptrace_pid): New function.
	(amd64bsd_fetch_inferior_registers): Use new function.
	(amd64bsd_store_inferior_registers): Use new function.
	(amd64bsd_dr_get): Use new function.
	(amd64bsd_dr_set): Use new function.
	* i386bsd-nat.c (get_ptrace_pid): New function.
	(i386bsd_fetch_inferior_registers): Use new function.
	(i386bsd_store_inferior_registers): Use new function.
	(i386bsd_dr_get): Use new function.
	(i386bsd_dr_set): Use new function.
	* ppcfbsd-nat.c (get_ptrace_pid): New function.
	(ppcfbsd_fetch_inferior_registers): Use new function.
	(ppcfbsd_store_inferior_registers): Use new function.
---
 gdb/ChangeLog      | 15 +++++++++++++++
 gdb/amd64bsd-nat.c | 35 +++++++++++++++++++++++------------
 gdb/i386bsd-nat.c  | 41 ++++++++++++++++++++++++++---------------
 gdb/ppcfbsd-nat.c  | 23 +++++++++++++++++------
 4 files changed, 81 insertions(+), 33 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 93760ba..0accac9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,18 @@
+2016-01-10  John Baldwin  <jhb@FreeBSD.org>
+	* amd64bsd-nat.c (get_ptrace_pid): New function.
+	(amd64bsd_fetch_inferior_registers): Use new function.
+	(amd64bsd_store_inferior_registers): Use new function.
+	(amd64bsd_dr_get): Use new function.
+	(amd64bsd_dr_set): Use new function.
+	* i386bsd-nat.c (get_ptrace_pid): New function.
+	(i386bsd_fetch_inferior_registers): Use new function.
+	(i386bsd_store_inferior_registers): Use new function.
+	(i386bsd_dr_get): Use new function.
+	(i386bsd_dr_set): Use new function.
+	* ppcfbsd-nat.c (get_ptrace_pid): New function.
+	(ppcfbsd_fetch_inferior_registers): Use new function.
+	(ppcfbsd_store_inferior_registers): Use new function.
+
 2016-01-09  John Baldwin  <jhb@FreeBSD.org>
 
 	* fbsd_tdep.c (fbsd_core_pid_to_str): New function.
diff --git a/gdb/amd64bsd-nat.c b/gdb/amd64bsd-nat.c
index aa79c13..7e4adc8 100644
--- a/gdb/amd64bsd-nat.c
+++ b/gdb/amd64bsd-nat.c
@@ -39,6 +39,17 @@
 size_t amd64bsd_xsave_len;
 #endif
 
+static pid_t
+get_ptrace_pid (ptid_t ptid)
+{
+  pid_t pid;
+
+  pid = ptid_get_lwp (ptid);
+  if (pid == 0)
+    pid = ptid_get_pid (ptid);
+  return pid;
+}
+  
 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
    for all registers (including the floating-point registers).  */
 
@@ -52,7 +63,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) &regs, 0) == -1)
 	perror_with_name (_("Couldn't get registers"));
 
@@ -70,7 +81,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 +90,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"));
 
@@ -100,13 +111,13 @@ amd64bsd_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) &regs, 0) == -1)
         perror_with_name (_("Couldn't get registers"));
 
       amd64_collect_native_gregset (regcache, &regs, regnum);
 
-      if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid),
+      if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid),
 	          (PTRACE_TYPE_ARG3) &regs, 0) == -1)
         perror_with_name (_("Couldn't write registers"));
 
@@ -123,26 +134,26 @@ amd64bsd_store_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"));
 
 	  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"));
     }
@@ -172,7 +183,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"));
 
@@ -184,7 +195,7 @@ amd64bsd_dr_set (int regnum, unsigned long 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"));
 
@@ -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 a/gdb/i386bsd-nat.c b/gdb/i386bsd-nat.c
index 71f962c..df112c3 100644
--- a/gdb/i386bsd-nat.c
+++ b/gdb/i386bsd-nat.c
@@ -87,6 +87,17 @@ size_t i386bsd_xsave_len;
 #endif
 \f
 
+static pid_t
+get_ptrace_pid (ptid_t ptid)
+{
+  pid_t pid;
+
+  pid = ptid_get_lwp (ptid);
+  if (pid == 0)
+    pid = ptid_get_pid (ptid);
+  return pid;
+}
+  
 /* Supply the general-purpose registers in GREGS, to REGCACHE.  */
 
 static void
@@ -138,7 +149,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) &regs, 0) == -1)
 	perror_with_name (_("Couldn't get registers"));
 
@@ -160,7 +171,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 +182,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 +192,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 +214,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) &regs, 0) == -1)
         perror_with_name (_("Couldn't get registers"));
 
       i386bsd_collect_gregset (regcache, &regs, regnum);
 
-      if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid),
+      if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid),
 	          (PTRACE_TYPE_ARG3) &regs, 0) == -1)
         perror_with_name (_("Couldn't write registers"));
 
@@ -230,13 +241,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 +256,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 +271,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 +316,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 +328,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 +339,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 a/gdb/ppcfbsd-nat.c b/gdb/ppcfbsd-nat.c
index b41ed70..e4240c8 100644
--- a/gdb/ppcfbsd-nat.c
+++ b/gdb/ppcfbsd-nat.c
@@ -37,6 +37,17 @@
 #include "inf-ptrace.h"
 #include "bsd-kvm.h"
 
+static pid_t
+get_ptrace_pid (ptid_t ptid)
+{
+  pid_t pid;
+
+  pid = ptid_get_lwp (ptid);
+  if (pid == 0)
+    pid = ptid_get_pid (ptid);
+  return pid;
+}
+  
 /* Fill GDB's register array with the general-purpose register values
    in *GREGSETP.  */
 
@@ -121,7 +132,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, get_ptrace_pid (inferior_ptid),
 	      (PTRACE_TYPE_ARG3) &regs, 0) == -1)
     perror_with_name (_("Couldn't get registers"));
 
@@ -132,7 +143,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, get_ptrace_pid (inferior_ptid),
 		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
 	perror_with_name (_("Couldn't get FP registers"));
 
@@ -149,13 +160,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, get_ptrace_pid (inferior_ptid),
 	      (PTRACE_TYPE_ARG3) &regs, 0) == -1)
     perror_with_name (_("Couldn't get registers"));
 
   fill_gregset (regcache, &regs, regno);
 
-  if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid),
+  if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid),
 	      (PTRACE_TYPE_ARG3) &regs, 0) == -1)
     perror_with_name (_("Couldn't write registers"));
 
@@ -163,13 +174,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, get_ptrace_pid (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, get_ptrace_pid (inferior_ptid),
 		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
 	perror_with_name (_("Couldn't set FP registers"));
     }
-- 
2.7.0

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/6] Add a psuedosection for the NT_FREEBSD_THRMISC note.
  2016-01-13 21:46 ` [PATCH v2 2/6] Add a psuedosection for the NT_FREEBSD_THRMISC note John Baldwin
@ 2016-01-14  5:30   ` Alan Modra
  0 siblings, 0 replies; 25+ messages in thread
From: Alan Modra @ 2016-01-14  5:30 UTC (permalink / raw)
  To: John Baldwin; +Cc: gdb-patches, binutils

On Wed, Jan 13, 2016 at 01:45:47PM -0800, John Baldwin wrote:
> bfd/ChangeLog:
> 
> 	* elf.c (elfcore_grok_note): Recognize NT_FREEBSD_THRMISC notes.

OK.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/6] Add support to readelf for reading FreeBSD ELF core notes.
  2016-01-13 21:46 ` [PATCH v2 1/6] Add support to readelf for reading FreeBSD ELF core notes John Baldwin
@ 2016-01-14  5:30   ` Alan Modra
  2016-01-14  5:40     ` John Baldwin
  0 siblings, 1 reply; 25+ messages in thread
From: Alan Modra @ 2016-01-14  5:30 UTC (permalink / raw)
  To: John Baldwin; +Cc: gdb-patches, binutils

On Wed, Jan 13, 2016 at 01:45:46PM -0800, John Baldwin wrote:
> binutils/ChangeLog:
> 
> 	* readelf.c (get_freebsd_elfcore_note_type): New
> 	(process_note): Add support for FreeBSD core notes.
> 
> include/elf/ChangeLog:
> 
> 	* common.h (NT_FREEBSD_THRMISC): Define.
> 	(NT_FREEBSD_PROCSTAT_PROC): Define.
> 	(NT_FREEBSD_PROCSTAT_FILES): Define.
> 	(NT_FREEBSD_PROCSTAT_VMMAP): Define.
> 	(NT_FREEBSD_PROCSTAT_GROUPS): Define.
> 	(NT_FREEBSD_PROCSTAT_UMASK): Define.
> 	(NT_FREEBSD_PROCSTAT_RLIMIT): Define.
> 	(NT_FREEBSD_PROCSTAT_OSREL): Define.
> 	(NT_FREEBSD_PROCSTAT_PSSTRINGS): Define.
> 	(NT_FREEBSD_PROCSTAT_AUXV): Define.

OK, but I deleted include/elf/ChangeLog deliberately, so the entry goes in
include/ChangeLog and looks like

	* elf/common.h (NT_FREEBSD_THRMISC): Define.
	...

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/6] Add support to readelf for reading FreeBSD ELF core notes.
  2016-01-14  5:30   ` Alan Modra
@ 2016-01-14  5:40     ` John Baldwin
  0 siblings, 0 replies; 25+ messages in thread
From: John Baldwin @ 2016-01-14  5:40 UTC (permalink / raw)
  To: gdb-patches; +Cc: Alan Modra, binutils

On Thursday, January 14, 2016 03:58:23 PM Alan Modra wrote:
> On Wed, Jan 13, 2016 at 01:45:46PM -0800, John Baldwin wrote:
> > binutils/ChangeLog:
> > 
> > 	* readelf.c (get_freebsd_elfcore_note_type): New
> > 	(process_note): Add support for FreeBSD core notes.
> > 
> > include/elf/ChangeLog:
> > 
> > 	* common.h (NT_FREEBSD_THRMISC): Define.
> > 	(NT_FREEBSD_PROCSTAT_PROC): Define.
> > 	(NT_FREEBSD_PROCSTAT_FILES): Define.
> > 	(NT_FREEBSD_PROCSTAT_VMMAP): Define.
> > 	(NT_FREEBSD_PROCSTAT_GROUPS): Define.
> > 	(NT_FREEBSD_PROCSTAT_UMASK): Define.
> > 	(NT_FREEBSD_PROCSTAT_RLIMIT): Define.
> > 	(NT_FREEBSD_PROCSTAT_OSREL): Define.
> > 	(NT_FREEBSD_PROCSTAT_PSSTRINGS): Define.
> > 	(NT_FREEBSD_PROCSTAT_AUXV): Define.
> 
> OK, but I deleted include/elf/ChangeLog deliberately, so the entry goes in
> include/ChangeLog and looks like
> 
> 	* elf/common.h (NT_FREEBSD_THRMISC): Define.
> 	...

Ok, will fix thanks!

-- 
John Baldwin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores.
  2016-01-13 21:46 ` [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores John Baldwin
@ 2016-01-14 15:03   ` Pedro Alves
  2016-01-15 20:23     ` John Baldwin
  0 siblings, 1 reply; 25+ messages in thread
From: Pedro Alves @ 2016-01-14 15:03 UTC (permalink / raw)
  To: John Baldwin, gdb-patches, binutils

On 01/13/2016 09:45 PM, John Baldwin wrote:
> Display the LWP ID of each thread in a FreeBSD core.  Extract thread names
> from the per-thread THRMISC note.
> 
> gdb/ChangeLog:
> 
> 	* fbsd_tdep.c (fbsd_core_pid_to_str): New function.
> 	(fbsd_init_abi): Add "core_pid_to_str" gdbarch method.
> ---
>  gdb/ChangeLog   |  5 +++++
>  gdb/fbsd-tdep.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 46 insertions(+)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 471d02b..93760ba 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,8 @@
> +2016-01-09  John Baldwin  <jhb@FreeBSD.org>
> +
> +	* fbsd_tdep.c (fbsd_core_pid_to_str): New function.
> +	(fbsd_init_abi): Add "core_pid_to_str" gdbarch method.
> +
>  2016-01-08  Yao Qi  <yao.qi@linaro.org>
>  
>  	* extension.c: Include target.h.
> diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
> index 0ef94d6..6851cc1 100644
> --- a/gdb/fbsd-tdep.c
> +++ b/gdb/fbsd-tdep.c
> @@ -28,6 +28,46 @@
>  #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], name[64];

This static "name" buffer appears unused, and then masked
by the "name" pointer below.

> +  struct bfd_section *section;
> +  bfd_size_type size;
> +  char sectionstr[32];
> +
> +  if (ptid_get_lwp (ptid) != 0)
> +    {
> +      snprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld",
> +		ptid_get_lwp (ptid));

xsnprintf.

> +      section = bfd_get_section_by_name (core_bfd, sectionstr);
> +      if (section != NULL)
> +	{
> +	  char *name;
> +
> +	  size = bfd_section_size (core_bfd, section);
> +	  name = alloca (size + 1);
> +	  if (bfd_get_section_contents (core_bfd, section, name, (file_ptr) 0,
> +					size) && name[0] != '\0')

This indentation / line break reads unusual to me.  I think breaking
before the && would be clearer:

	  if (bfd_get_section_contents (core_bfd, section, name,
                                        (file_ptr) 0, size)
	      && name[0] != '\0')

Guess this should check size > 0 as well, otherwise name[0] contains
garbage.


> +	    {
> +	      name[size] = '\0';
> +	      if (strcmp(name, elf_tdata (core_bfd)->core->program) != 0)

Missing space after strcmp.

Is this ".thrmisc" section documented somewhere?  Could you add a
small comment on what this entry you're skipping means?

> +		{
> +		  snprintf (buf, sizeof buf, "LWP %ld \"%s\"",
> +			    ptid_get_lwp (ptid), name);

xsnprintf.

> +		  return buf;
> +		}
> +	    }
> +	}
> +      snprintf (buf, sizeof buf, "LWP %ld", ptid_get_lwp (ptid));

xsnprintf.

> +      return buf;
> +    }
> +
> +  return normal_pid_to_str (ptid);
> +}
> +
>  static int
>  find_signalled_thread (struct thread_info *info, void *data)
>  {
> @@ -132,5 +172,6 @@ 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_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
>  }
> 


Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD.
  2016-01-13 21:52 ` [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD John Baldwin
@ 2016-01-14 15:07   ` Pedro Alves
  2016-01-15 20:23     ` John Baldwin
  0 siblings, 1 reply; 25+ messages in thread
From: Pedro Alves @ 2016-01-14 15:07 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

[Dropping binutils.]

On 01/13/2016 09:45 PM, John Baldwin wrote:
> This allows gdb to fetch per-thread registers for multi-threaded FreeBSD
> processes.  NetBSD and OpenBSD also accept LWP IDs for ptrace requests
> to fetch per-thread state.

I'd prefer to make inf-ptrace.c:get_ptrace_pid extern and use
it, instead of duplicating it multiple times.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 5/6] Add support for LWP-based threads on FreeBSD.
  2016-01-13 21:52 ` [PATCH v2 5/6] Add support for LWP-based threads " John Baldwin
@ 2016-01-14 15:29   ` Pedro Alves
  2016-01-15 23:54     ` John Baldwin
  0 siblings, 1 reply; 25+ messages in thread
From: Pedro Alves @ 2016-01-14 15:29 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

[Dropping binutils.]

Hi John,

This deserves a NEWS entry.

New commands ("set debug fbsd-lwp") need to documented in
the manual, even debug ones.

This generally looks good to me.  A few minor comments inline below.

On 01/13/2016 09:45 PM, John Baldwin wrote:

> +
> +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)

Space after cast.

> +	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.  */
> +



> +#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[64];

Is this the kernel-side size limit?  Worth it of a define/comment.
Mainly looking at the xsnprintf below and wondering whether
a we could see a longer name and thus cause gdb to internal error.

> +
> +  /* 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"));

Space after cast.

> +  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"));

Space after cast.

> +}
> +#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)

Space after cast.

> +	    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);
> +}
> +



> +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)

Space after _cb.

> +{
> +  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), (caddr_t)0, 0) == -1)

Space after cast.

> +    perror_with_name (("ptrace"));
> +  return 0;
> +}
> +
> +static int
> +resume_all_threads_cb(struct thread_info *tp, void *data)

Missing space.


> +{
> +  ptid_t *filter = data;
> +
> +  if (!ptid_match (tp->ptid, *filter))
> +    return 0;
> +
> +  if (ptrace (PT_RESUME, ptid_get_lwp (tp->ptid), (caddr_t)0, 0) == -1)

Missing space.


> +    perror_with_name (("ptrace"));
> +  return 0;
> +}
> +



> @@ -331,18 +581,80 @@ fbsd_wait (struct target_ops *ops,
>  	  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, (PTRACE_TYPE_ARG3)1, 0) == -1)

Missing space.

> +		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 +666,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);

Missing space.

>  		}
>  
>  	      /* For vfork, the child process will have the P_PPWAIT
> @@ -361,6 +674,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 +684,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 +763,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
>  


> +/* 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,
> +			   NULL,

Please implement a show callback, for i18n.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 6/6] Dump register notes for each thread when generating a FreeBSD core.
  2016-01-13 21:46 ` [PATCH v2 6/6] Dump register notes for each thread when generating a FreeBSD core John Baldwin
@ 2016-01-14 15:34   ` Pedro Alves
  0 siblings, 0 replies; 25+ messages in thread
From: Pedro Alves @ 2016-01-14 15:34 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

[Dropping binutils.]

On 01/13/2016 09:45 PM, John Baldwin wrote:
> gdb/ChangeLog:
> 
> 	* fbsd-tdep.c (find_stop_signal): Remove.
> 	(struct fbsd_collect_regset_section_cb) <lwp>: New field.
> 	<stop_signal>: New field.
> 	<abort_iteration>: New field.
> 	(fbsd_collect_regset_section_cb): Use new fields.
> 	(fbsd_collect_thread_registers): New function.
> 	(struct fbsd_corefile_thread_data): New structure.
> 	(fbsd_corefile_thread): New function.
> 	(fbsd_make_corefile_notes): Use new function to dump notes for each
> 	non-exited thread in a process.

LGTM.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores.
  2016-01-14 15:03   ` Pedro Alves
@ 2016-01-15 20:23     ` John Baldwin
  2016-01-18 12:27       ` Pedro Alves
  0 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-15 20:23 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, binutils

On Thursday, January 14, 2016 03:03:50 PM Pedro Alves wrote:
> On 01/13/2016 09:45 PM, John Baldwin wrote:
> >  
> >  
> > +/* 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], name[64];
> 
> This static "name" buffer appears unused, and then masked
> by the "name" pointer below.

Yes, it was from an earlier rev of the patch before I switched to
alloca().  Removed.
> 
> > +  struct bfd_section *section;
> > +  bfd_size_type size;
> > +  char sectionstr[32];
> > +
> > +  if (ptid_get_lwp (ptid) != 0)
> > +    {
> > +      snprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld",
> > +		ptid_get_lwp (ptid));
> 
> xsnprintf.

Fixed here and throughout.

> > +      section = bfd_get_section_by_name (core_bfd, sectionstr);
> > +      if (section != NULL)
> > +	{
> > +	  char *name;
> > +
> > +	  size = bfd_section_size (core_bfd, section);
> > +	  name = alloca (size + 1);
> > +	  if (bfd_get_section_contents (core_bfd, section, name, (file_ptr) 0,
> > +					size) && name[0] != '\0')
> 
> This indentation / line break reads unusual to me.  I think breaking
> before the && would be clearer:
> 
> 	  if (bfd_get_section_contents (core_bfd, section, name,
>                                         (file_ptr) 0, size)
> 	      && name[0] != '\0')
> 
> Guess this should check size > 0 as well, otherwise name[0] contains
> garbage.

Ok.  I decided to check the size in the earlier if statement to avoid
the alloca(), etc. when the size is zero.

> > +	    {
> > +	      name[size] = '\0';
> > +	      if (strcmp(name, elf_tdata (core_bfd)->core->program) != 0)
> 
> Missing space after strcmp.

Fixed.

> Is this ".thrmisc" section documented somewhere?  Could you add a
> small comment on what this entry you're skipping means?

It is not documented aside from the code unfortunately. :(  If I had my
way we would be dumping the full ptrace_lwpinfo structure that contains
per-LWP info used by the 'nat' target instead (it has other potentially
useful information such as the siginfo_t for each thread).  At the moment
I don't generate a NT_THRMISC note in 'gcore' because 'struct thrmisc' is
currently only present in FreeBSD's headers.

A somewhat related question: would it be reasonable to dump additional
notes in 'gcore' only when native?  For example, FreeBSD kernels dump
several additional notes including things like auxv, open files, etc.
The "gross" way I can think of for doing that is to simply place that
additional logic under #ifdef __FreeBSD__ in fbsd-tdep.c, but that seems
quite hackish given the otherwise clean split between tdep.c and nat.c.

-- 
John Baldwin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD.
  2016-01-14 15:07   ` Pedro Alves
@ 2016-01-15 20:23     ` John Baldwin
  2016-01-15 21:41       ` Pedro Alves
  0 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-15 20:23 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Thursday, January 14, 2016 03:07:28 PM Pedro Alves wrote:
> [Dropping binutils.]
> 
> On 01/13/2016 09:45 PM, John Baldwin wrote:
> > This allows gdb to fetch per-thread registers for multi-threaded FreeBSD
> > processes.  NetBSD and OpenBSD also accept LWP IDs for ptrace requests
> > to fetch per-thread state.
> 
> I'd prefer to make inf-ptrace.c:get_ptrace_pid extern and use
> it, instead of duplicating it multiple times.

This sounds good to me.  Do you want me to use it in other places as well?
sparc-nat.c at least duplicates the same logic inline.  amd64linux-nat.c
does as well.  If so, would you rather that be a seperate patch (expose
get_ptrace_pid() and use it in existing targets) from this patch?

-- 
John Baldwin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD.
  2016-01-15 20:23     ` John Baldwin
@ 2016-01-15 21:41       ` Pedro Alves
  2016-01-15 23:54         ` John Baldwin
  0 siblings, 1 reply; 25+ messages in thread
From: Pedro Alves @ 2016-01-15 21:41 UTC (permalink / raw)
  To: John Baldwin; +Cc: gdb-patches

On 01/15/2016 08:18 PM, John Baldwin wrote:
> On Thursday, January 14, 2016 03:07:28 PM Pedro Alves wrote:
>> [Dropping binutils.]
>>
>> On 01/13/2016 09:45 PM, John Baldwin wrote:
>>> This allows gdb to fetch per-thread registers for multi-threaded FreeBSD
>>> processes.  NetBSD and OpenBSD also accept LWP IDs for ptrace requests
>>> to fetch per-thread state.
>>
>> I'd prefer to make inf-ptrace.c:get_ptrace_pid extern and use
>> it, instead of duplicating it multiple times.
> 
> This sounds good to me.  Do you want me to use it in other places as well?
> sparc-nat.c at least duplicates the same logic inline.  amd64linux-nat.c
> does as well.  If so, would you rather that be a seperate patch (expose
> get_ptrace_pid() and use it in existing targets) from this patch?

I won't impose that as requirement, but that'd be nice.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 5/6] Add support for LWP-based threads on FreeBSD.
  2016-01-14 15:29   ` Pedro Alves
@ 2016-01-15 23:54     ` John Baldwin
  2016-01-16 14:47       ` Pedro Alves
  0 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-15 23:54 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Thursday, January 14, 2016 03:29:39 PM Pedro Alves wrote:
> On 01/13/2016 09:45 PM, John Baldwin wrote:
> 
> > +
> > +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)
> 
> Space after cast.

Fixed here and throughout.  My previous changes to add fork following
include some of these as well.  I can clean those up in a separate
followup change after this series.

> > +#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[64];
> 
> Is this the kernel-side size limit?  Worth it of a define/comment.
> Mainly looking at the xsnprintf below and wondering whether
> a we could see a longer name and thus cause gdb to internal error.

Ah, I had not realized that was the reason for xsnprintf() vs snprintf().
The kernel returns a fixed-sized buffer, so I have updated the code to use
'static char buf[sizeof pl.pl_tdname + 1];' which should always be large
enough.

> > +/* 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,
> > +			   NULL,
> 
> Please implement a show callback, for i18n.

Done.

I've also added entries to NEWS.

-- 
John Baldwin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD.
  2016-01-15 21:41       ` Pedro Alves
@ 2016-01-15 23:54         ` John Baldwin
  2016-01-16 14:39           ` Pedro Alves
  0 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-15 23:54 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Friday, January 15, 2016 09:41:19 PM Pedro Alves wrote:
> On 01/15/2016 08:18 PM, John Baldwin wrote:
> > On Thursday, January 14, 2016 03:07:28 PM Pedro Alves wrote:
> >> [Dropping binutils.]
> >>
> >> On 01/13/2016 09:45 PM, John Baldwin wrote:
> >>> This allows gdb to fetch per-thread registers for multi-threaded FreeBSD
> >>> processes.  NetBSD and OpenBSD also accept LWP IDs for ptrace requests
> >>> to fetch per-thread state.
> >>
> >> I'd prefer to make inf-ptrace.c:get_ptrace_pid extern and use
> >> it, instead of duplicating it multiple times.
> > 
> > This sounds good to me.  Do you want me to use it in other places as well?
> > sparc-nat.c at least duplicates the same logic inline.  amd64linux-nat.c
> > does as well.  If so, would you rather that be a seperate patch (expose
> > get_ptrace_pid() and use it in existing targets) from this patch?
> 
> I won't impose that as requirement, but that'd be nice.

Ok.  I made a pass and fixed the ones that I thought were relevant (i.e.
generating a pid to pass to ptrace()).   However, the vast majority of the
files changed were various foo-linux-nat.c files which I am not setup to
test.  Is there a way to push a branch and have the build bots build it to
do a test build?  (Even then I think those would not cover 'nat' files for
s390, hppa, etc.)  I'm still happy to include this, just want to ensure I
don't break the build.  I'm also not sure if changing these files would
break gdbserver (if gdbserver doesn't include inf-ptrace.o).

-- 
John Baldwin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD.
  2016-01-15 23:54         ` John Baldwin
@ 2016-01-16 14:39           ` Pedro Alves
  2016-01-16 19:17             ` John Baldwin
  0 siblings, 1 reply; 25+ messages in thread
From: Pedro Alves @ 2016-01-16 14:39 UTC (permalink / raw)
  To: John Baldwin; +Cc: gdb-patches

On 01/15/2016 11:22 PM, John Baldwin wrote:

> Ok.  I made a pass and fixed the ones that I thought were relevant (i.e.
> generating a pid to pass to ptrace()).   However, the vast majority of the
> files changed were various foo-linux-nat.c files which I am not setup to
> test.  

Hmm, actually, sorry about that, but I remembered that the ptid_get_lwp()==0
paths in Linux code are dead code (90ad5e1d4f).  I see now that d89fa914ad6f
cleaned most of the linux code, but left out the cases that were open coded.

So I think it's best to just leave those be.  Someone can always clean
those up to use ptid_get_lwp directly afterwards.

I now think that to move forward with your patch, it's simpler/better to
export get_ptrace_pid, and just use it in the cases you cared about,
and leave other targets as is.

If you're changing the FreeBSD to always store an lwp, do you still
need get_ptrace_pid, or would something like this instead work?

-      if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
+      if (ptrace (PT_GETREGS, get_ptrace_lwp (inferior_ptid),

etc.  Or would you still need it because the foo-nat.c files you're
touching are used by other BSDs as well?

> Is there a way to push a branch and have the build bots build it to
> do a test build?  

No, sorry.

> (Even then I think those would not cover 'nat' files for
> s390, hppa, etc.)  I'm still happy to include this, just want to ensure I
> don't break the build.

>  I'm also not sure if changing these files would
> break gdbserver (if gdbserver doesn't include inf-ptrace.o).

gdbserver does not include inf-ptrace.o, but it doesn't use the
gdb/*-nat.c files either.  It has its own backends and shares
the gdb/nat/, gdb/common/ and gdb/arch/ files with gdb.

We'd actually like to merge the existing gdbserver/gdb backends
though:

  https://sourceware.org/gdb/wiki/Common

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 5/6] Add support for LWP-based threads on FreeBSD.
  2016-01-15 23:54     ` John Baldwin
@ 2016-01-16 14:47       ` Pedro Alves
  0 siblings, 0 replies; 25+ messages in thread
From: Pedro Alves @ 2016-01-16 14:47 UTC (permalink / raw)
  To: John Baldwin; +Cc: gdb-patches

On 01/15/2016 11:51 PM, John Baldwin wrote:

> I've also added entries to NEWS.
> 

Thanks.

FAOD, I should have mentioned that the command
should be mentioned in NEWS entry as well.

 https://sourceware.org/gdb/wiki/ContributionChecklist#Documentation

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD.
  2016-01-16 14:39           ` Pedro Alves
@ 2016-01-16 19:17             ` John Baldwin
  0 siblings, 0 replies; 25+ messages in thread
From: John Baldwin @ 2016-01-16 19:17 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Saturday, January 16, 2016 02:39:34 PM Pedro Alves wrote:
> On 01/15/2016 11:22 PM, John Baldwin wrote:
> 
> > Ok.  I made a pass and fixed the ones that I thought were relevant (i.e.
> > generating a pid to pass to ptrace()).   However, the vast majority of the
> > files changed were various foo-linux-nat.c files which I am not setup to
> > test.  
> 
> Hmm, actually, sorry about that, but I remembered that the ptid_get_lwp()==0
> paths in Linux code are dead code (90ad5e1d4f).  I see now that d89fa914ad6f
> cleaned most of the linux code, but left out the cases that were open coded.
> 
> So I think it's best to just leave those be.  Someone can always clean
> those up to use ptid_get_lwp directly afterwards.
> 
> I now think that to move forward with your patch, it's simpler/better to
> export get_ptrace_pid, and just use it in the cases you cared about,
> and leave other targets as is.

Ok.

> If you're changing the FreeBSD to always store an lwp, do you still
> need get_ptrace_pid, or would something like this instead work?
> 
> -      if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
> +      if (ptrace (PT_GETREGS, get_ptrace_lwp (inferior_ptid),
> 
> etc.  Or would you still need it because the foo-nat.c files you're
> touching are used by other BSDs as well?

Most of them are pan-BSD so they would need the helper, but ppcfbsd-nat.c
is FreeBSD-only, so it can use ptid_get_lwp() directly.

-- 
John Baldwin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores.
  2016-01-15 20:23     ` John Baldwin
@ 2016-01-18 12:27       ` Pedro Alves
  2016-01-18 17:06         ` John Baldwin
  0 siblings, 1 reply; 25+ messages in thread
From: Pedro Alves @ 2016-01-18 12:27 UTC (permalink / raw)
  To: John Baldwin; +Cc: gdb-patches, binutils

On 01/15/2016 08:13 PM, John Baldwin wrote:
> On Thursday, January 14, 2016 03:03:50 PM Pedro Alves wrote:
>> On 01/13/2016 09:45 PM, John Baldwin wrote:
>>>  
>>>  
>>> +/* 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], name[64];
>>
>> This static "name" buffer appears unused, and then masked
>> by the "name" pointer below.
> 
> Yes, it was from an earlier rev of the patch before I switched to
> alloca().  Removed.
>>
>>> +  struct bfd_section *section;
>>> +  bfd_size_type size;
>>> +  char sectionstr[32];
>>> +
>>> +  if (ptid_get_lwp (ptid) != 0)
>>> +    {
>>> +      snprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld",
>>> +		ptid_get_lwp (ptid));
>>
>> xsnprintf.
> 
> Fixed here and throughout.
> 
>>> +      section = bfd_get_section_by_name (core_bfd, sectionstr);
>>> +      if (section != NULL)
>>> +	{
>>> +	  char *name;
>>> +
>>> +	  size = bfd_section_size (core_bfd, section);
>>> +	  name = alloca (size + 1);
>>> +	  if (bfd_get_section_contents (core_bfd, section, name, (file_ptr) 0,
>>> +					size) && name[0] != '\0')
>>
>> This indentation / line break reads unusual to me.  I think breaking
>> before the && would be clearer:
>>
>> 	  if (bfd_get_section_contents (core_bfd, section, name,
>>                                         (file_ptr) 0, size)
>> 	      && name[0] != '\0')
>>
>> Guess this should check size > 0 as well, otherwise name[0] contains
>> garbage.
> 
> Ok.  I decided to check the size in the earlier if statement to avoid
> the alloca(), etc. when the size is zero.
> 
>>> +	    {
>>> +	      name[size] = '\0';
>>> +	      if (strcmp(name, elf_tdata (core_bfd)->core->program) != 0)
>>
>> Missing space after strcmp.
> 
> Fixed.
> 
>> Is this ".thrmisc" section documented somewhere?  Could you add a
>> small comment on what this entry you're skipping means?
> 
> It is not documented aside from the code unfortunately. :(  If I had my
> way we would be dumping the full ptrace_lwpinfo structure that contains
> per-LWP info used by the 'nat' target instead (it has other potentially
> useful information such as the siginfo_t for each thread).  At the moment
> I don't generate a NT_THRMISC note in 'gcore' because 'struct thrmisc' is
> currently only present in FreeBSD's headers.

I think just having a comment mentioning that this note contains
the "struct thrmisc" structure, which contains the thread name, would
be helpful.

But, if this is about the thread name, is there a reason you're hacking it
through fbsd_core_pid_to_str, rather than hooking this up
through "thread name" ?

> 
> A somewhat related question: would it be reasonable to dump additional
> notes in 'gcore' only when native?  

That's OK, as long as you go through the target vector, through some target
method or by reading some target object.

If there was a FreeBSD gdbserver port I'd push you into defining whatever
packets are missing to make it work in gdbserver too, though...

> For example, FreeBSD kernels dump
> several additional notes including things like auxv, open files, etc.

See the TARGET_OBJECT_AUXV dumping in linux-tdep.c.  When native, that goes
to linux-nat.c.  When cross/remote, it goes through remote.c/qXfer:auxv:read.

> The "gross" way I can think of for doing that is to simply place that
> additional logic under #ifdef __FreeBSD__ in fbsd-tdep.c, but that seems
> quite hackish given the otherwise clean split between tdep.c and nat.c.

Yeah, I'd rather not.  Best go through the target vector instead.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores.
  2016-01-18 12:27       ` Pedro Alves
@ 2016-01-18 17:06         ` John Baldwin
  2016-01-18 17:13           ` Pedro Alves
  0 siblings, 1 reply; 25+ messages in thread
From: John Baldwin @ 2016-01-18 17:06 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, binutils

On Monday, January 18, 2016 12:27:21 PM Pedro Alves wrote:
> On 01/15/2016 08:13 PM, John Baldwin wrote:
> > On Thursday, January 14, 2016 03:03:50 PM Pedro Alves wrote:
> >> Is this ".thrmisc" section documented somewhere?  Could you add a
> >> small comment on what this entry you're skipping means?
> > 
> > It is not documented aside from the code unfortunately. :(  If I had my
> > way we would be dumping the full ptrace_lwpinfo structure that contains
> > per-LWP info used by the 'nat' target instead (it has other potentially
> > useful information such as the siginfo_t for each thread).  At the moment
> > I don't generate a NT_THRMISC note in 'gcore' because 'struct thrmisc' is
> > currently only present in FreeBSD's headers.
> 
> I think just having a comment mentioning that this note contains
> the "struct thrmisc" structure, which contains the thread name, would
> be helpful.

Ok.

> But, if this is about the thread name, is there a reason you're hacking it
> through fbsd_core_pid_to_str, rather than hooking this up
> through "thread name" ?

Hmm, would this work for cross-debugging a core file?  fbsd_thread_name is
currently only defined for native debugging, whereas core_pid_to_str is a
gdbarch method on the ABI so it can be used to extract thread names from
non-native cores.

Alternatively, would it be best if the core target defined a to_thread_name
method that invoked a new gdbarch method (gdbarch_core_thread_name or the
like) to fetch the thread name?

-- 
John Baldwin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores.
  2016-01-18 17:06         ` John Baldwin
@ 2016-01-18 17:13           ` Pedro Alves
  0 siblings, 0 replies; 25+ messages in thread
From: Pedro Alves @ 2016-01-18 17:13 UTC (permalink / raw)
  To: John Baldwin; +Cc: gdb-patches, binutils

On 01/18/2016 05:05 PM, John Baldwin wrote:

> Alternatively, would it be best if the core target defined a to_thread_name
> method that invoked a new gdbarch method (gdbarch_core_thread_name or the
> like) to fetch the thread name?

Yes, that's the right way to go.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2016-01-18 17:13 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-13 21:46 [PATCH v2 0/6] Support kernel-backed user threads on FreeBSD John Baldwin
2016-01-13 21:46 ` [PATCH v2 6/6] Dump register notes for each thread when generating a FreeBSD core John Baldwin
2016-01-14 15:34   ` Pedro Alves
2016-01-13 21:46 ` [PATCH v2 3/6] Display per-thread information for threads in FreeBSD cores John Baldwin
2016-01-14 15:03   ` Pedro Alves
2016-01-15 20:23     ` John Baldwin
2016-01-18 12:27       ` Pedro Alves
2016-01-18 17:06         ` John Baldwin
2016-01-18 17:13           ` Pedro Alves
2016-01-13 21:46 ` [PATCH v2 1/6] Add support to readelf for reading FreeBSD ELF core notes John Baldwin
2016-01-14  5:30   ` Alan Modra
2016-01-14  5:40     ` John Baldwin
2016-01-13 21:46 ` [PATCH v2 2/6] Add a psuedosection for the NT_FREEBSD_THRMISC note John Baldwin
2016-01-14  5:30   ` Alan Modra
2016-01-13 21:52 ` [PATCH v2 4/6] Use LWP IDs with ptrace register requests on FreeBSD John Baldwin
2016-01-14 15:07   ` Pedro Alves
2016-01-15 20:23     ` John Baldwin
2016-01-15 21:41       ` Pedro Alves
2016-01-15 23:54         ` John Baldwin
2016-01-16 14:39           ` Pedro Alves
2016-01-16 19:17             ` John Baldwin
2016-01-13 21:52 ` [PATCH v2 5/6] Add support for LWP-based threads " John Baldwin
2016-01-14 15:29   ` Pedro Alves
2016-01-15 23:54     ` John Baldwin
2016-01-16 14:47       ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).