[PATCH 2/4] Support 'info proc' for FreeBSD process core dumps.

Simon Marchi simark@simark.ca
Wed Dec 27 01:56:00 GMT 2017


On 2017-12-22 05:05 PM, John Baldwin wrote:
> - Command line arguments are obtained from the pr_psargs[] array
>   saved in the NT_PRPSINFO note.
> - The 'cwd' and 'exe' values are obtained from the per-process file
>   descriptor table stored in the NT_PROCSTAT_FILES core note.
> - 'mappings' is implemented by walking the array of VM map entries
>   stored in the NT_PROCSTAT_VMMAP core note.
> - 'stat' and 'status' output is generated by outputting fields from
>   the first structure stored in the NT_PROCSTAT_PROC core note.
> 
> gdb/ChangeLog:
> 
> 	* fbsd-tdep.c (KVE_STRUCTSIZE, KVE_START, KVE_END, KVE_OFFSET)
> 	(KVE_FLAGS, KVE_PROTECTION, KVE_PATH, KINFO_VME_PROT_READ)
> 	(KINFO_VME_PROT_WRITE, KINFO_VME_PROT_EXEC, KINFO_VME_FLAG_COW)
> 	(KINFO_VME_FLAG_NEEDS_COPY, KINFO_VME_FLAG_NOCOREDUMP)
> 	(KINFO_VME_FLAG_SUPER, KINFO_VME_FLAG_GROWS_UP)
> 	(KINFO_VME_FLAG_GROWS_DOWN, KF_STRUCTSIZE, KF_TYPE, KF_FD)
> 	(KF_PATH, KINFO_FILE_TYPE_VNODE, KINFO_FILE_FD_TYPE_CWD)
> 	(KINFO_FILE_FD_TYPE_TEXT, struct kinfo_proc_layout)
> 	(kinfo_proc_layout_32, kinfo_proc_layout_i386)
> 	(kinfo_proc_layout_64, fbsd_vm_map_entry_flags)
> 	(fbsd_core_info_proc_mappings)
> 	(fbsd_core_vnode_path, fbsd_print_sigset)
> 	(fbsd_core_info_proc_status, fbsd_core_fetch_timeval)
> 	(fbsd_core_info_proc_stat, fbsd_core_info_proc): New.
> 	(fbsd_init_abi):  Install gdbarch "core_info_proc" method.
> 	* fbsd-tdep.h (fbsd_vm_map_entry_flags): New.
> ---
>  gdb/ChangeLog   |  19 ++
>  gdb/fbsd-tdep.c | 698 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  gdb/fbsd-tdep.h |   1 +
>  3 files changed, 718 insertions(+)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 1b4b13aba9..2311749de7 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,22 @@
> +2017-12-22  John Baldwin  <jhb@FreeBSD.org>
> +
> +	* fbsd-tdep.c (KVE_STRUCTSIZE, KVE_START, KVE_END, KVE_OFFSET)
> +	(KVE_FLAGS, KVE_PROTECTION, KVE_PATH, KINFO_VME_PROT_READ)
> +	(KINFO_VME_PROT_WRITE, KINFO_VME_PROT_EXEC, KINFO_VME_FLAG_COW)
> +	(KINFO_VME_FLAG_NEEDS_COPY, KINFO_VME_FLAG_NOCOREDUMP)
> +	(KINFO_VME_FLAG_SUPER, KINFO_VME_FLAG_GROWS_UP)
> +	(KINFO_VME_FLAG_GROWS_DOWN, KF_STRUCTSIZE, KF_TYPE, KF_FD)
> +	(KF_PATH, KINFO_FILE_TYPE_VNODE, KINFO_FILE_FD_TYPE_CWD)
> +	(KINFO_FILE_FD_TYPE_TEXT, struct kinfo_proc_layout)
> +	(kinfo_proc_layout_32, kinfo_proc_layout_i386)
> +	(kinfo_proc_layout_64, fbsd_vm_map_entry_flags)
> +	(fbsd_core_info_proc_mappings)
> +	(fbsd_core_vnode_path, fbsd_print_sigset)
> +	(fbsd_core_info_proc_status, fbsd_core_fetch_timeval)
> +	(fbsd_core_info_proc_stat, fbsd_core_info_proc): New.
> +	(fbsd_init_abi):  Install gdbarch "core_info_proc" method.
> +	* fbsd-tdep.h (fbsd_vm_map_entry_flags): New.
> +
>  2017-12-21  Simon Marchi  <simon.marchi@ericsson.com>
>  	    Sergio Durigan Junior  <sergiodj@redhat.com>
>  
> diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
> index f89b520c5f..454036dcac 100644
> --- a/gdb/fbsd-tdep.c
> +++ b/gdb/fbsd-tdep.c
> @@ -52,6 +52,223 @@
>  #define	SIZE64_SIGINFO_T	80
>  #define	SIZE32_SIGINFO_T	64
>  
> +/* Offsets in data structure used in NT_FREEBSD_PROCSTAT_VMMAP core
> +   dump notes.  See <sys/user.h> for the definition of struct
> +   kinfo_vmentry.  This data structure should have the same layout on
> +   all architectures.  */
> +
> +#define	KVE_STRUCTSIZE		0x0
> +#define	KVE_START		0x8
> +#define	KVE_END			0x10
> +#define	KVE_OFFSET		0x18
> +#define	KVE_FLAGS		0x2c
> +#define	KVE_PROTECTION		0x56
> +#define	KVE_PATH		0x88
> +
> +/* Flags in the 'kve_protection' field in struct kinfo_vmentry.  These
> +   match the KVME_PROT_* constants in <sys/user.h>.  */
> +
> +#define	KINFO_VME_PROT_READ	0x00000001
> +#define	KINFO_VME_PROT_WRITE	0x00000002
> +#define	KINFO_VME_PROT_EXEC	0x00000004
> +
> +/* Flags in the 'kve_flags' field in struct kinfo_vmentry.  These
> +   match the KVME_FLAG_* constants in <sys/user.h>.  */
> +
> +#define	KINFO_VME_FLAG_COW		0x00000001
> +#define	KINFO_VME_FLAG_NEEDS_COPY	0x00000002
> +#define	KINFO_VME_FLAG_NOCOREDUMP	0x00000004
> +#define	KINFO_VME_FLAG_SUPER		0x00000008
> +#define	KINFO_VME_FLAG_GROWS_UP		0x00000010
> +#define	KINFO_VME_FLAG_GROWS_DOWN	0x00000020
> +
> +/* Offsets in data structure used in NT_FREEBSD_PROCSTAT_FILES core
> +   dump notes.  See <sys/user.h> for the definition of struct
> +   kinfo_file.  This data structure should have the same layout on all
> +   architectures.  */
> +
> +#define	KF_STRUCTSIZE		0x0
> +#define	KF_TYPE			0x4
> +#define	KF_FD			0x8
> +#define	KF_PATH			0x170
> +
> +/* Constants for the 'kf_type' field in struct kinfo_file.  These
> +   match the KF_TYPE_* constants in <sys/user.h>.  */
> +
> +#define	KINFO_FILE_TYPE_VNODE	1
> +
> +/* Special values for the 'kf_fd' field in struct kinfo_file.  These
> +   match the KF_FD_TYPE_* constants in <sys/user.h>.  */
> +
> +#define	KINFO_FILE_FD_TYPE_CWD	-1
> +#define	KINFO_FILE_FD_TYPE_TEXT	-5
> +
> +/* Offsets in data structure used in NT_FREEBSD_PROCSTAT_PROC core
> +   dump notes.  See <sys/user.h> for the definition of struct
> +   kinfo_proc.  This data structure has different layouts on different
> +   architectures mostly due to ILP32 vs LP64.  However, FreeBSD/i386
> +   uses a 32-bit time_t while all other architectures use a 64-bit
> +   time_t.
> +
> +   The core dump note actually contains one kinfo_proc structure for
> +   each thread, but all of the process-wide data can be obtained from
> +   the first structure.  One result of this note's format is that some
> +   of the process-wide status available in the native target method
> +   from the kern.proc.pid.<pid> sysctl such as ki_stat and ki_siglist
> +   is not available from a core dump.  Instead, the per-thread data
> +   structures contain the value of these fields for individual
> +   threads.  */
> +
> +struct kinfo_proc_layout

struct definitions should not be indented, they should look like:

struct kinfo_proc_layout
{
  int ki_layout;
  ...
}

> +  {
> +    /* Offsets of struct kinfo_proc members.  */
> +    int ki_layout;
> +    int ki_pid;
> +    int ki_ppid;
> +    int ki_pgid;
> +    int ki_tpgid;
> +    int ki_sid;
> +    int ki_tdev_freebsd11;
> +    int ki_sigignore;
> +    int ki_sigcatch;
> +    int ki_uid;
> +    int ki_ruid;
> +    int ki_svuid;
> +    int ki_rgid;
> +    int ki_svgid;
> +    int ki_ngroups;
> +    int ki_groups;
> +    int ki_size;
> +    int ki_rssize;
> +    int ki_tsize;
> +    int ki_dsize;
> +    int ki_ssize;
> +    int ki_start;
> +    int ki_nice;
> +    int ki_comm;
> +    int ki_tdev;
> +    int ki_rusage;
> +    int ki_rusage_ch;
> +
> +    /* Offsets of struct rusage members.  */
> +    int ru_utime;
> +    int ru_stime;
> +    int ru_maxrss;
> +    int ru_minflt;
> +    int ru_majflt;
> +  };
> +
> +struct kinfo_proc_layout kinfo_proc_layout_32 =

I would suggest making these const.

> +  {
> +    .ki_layout = 0x4,
> +    .ki_pid = 0x28,
> +    .ki_ppid = 0x2c,
> +    .ki_pgid = 0x30,
> +    .ki_tpgid = 0x34,
> +    .ki_sid = 0x38,
> +    .ki_tdev_freebsd11 = 0x44,
> +    .ki_sigignore = 0x68,
> +    .ki_sigcatch = 0x78,
> +    .ki_uid = 0x88,
> +    .ki_ruid = 0x8c,
> +    .ki_svuid = 0x90,
> +    .ki_rgid = 0x94,
> +    .ki_svgid = 0x98,
> +    .ki_ngroups = 0x9c,
> +    .ki_groups = 0xa0,
> +    .ki_size = 0xe0,
> +    .ki_rssize = 0xe4,
> +    .ki_tsize = 0xec,
> +    .ki_dsize = 0xf0,
> +    .ki_ssize = 0xf4,
> +    .ki_start = 0x118,
> +    .ki_nice = 0x145,
> +    .ki_comm = 0x17f,
> +    .ki_tdev = 0x1f0,
> +    .ki_rusage = 0x220,
> +    .ki_rusage_ch = 0x278,
> +
> +    .ru_utime = 0x0,
> +    .ru_stime = 0x10,
> +    .ru_maxrss = 0x20,
> +    .ru_minflt = 0x30,
> +    .ru_majflt = 0x34,
> +  };
> +
> +struct kinfo_proc_layout kinfo_proc_layout_i386 =
> +  {
> +    .ki_layout = 0x4,
> +    .ki_pid = 0x28,
> +    .ki_ppid = 0x2c,
> +    .ki_pgid = 0x30,
> +    .ki_tpgid = 0x34,
> +    .ki_sid = 0x38,
> +    .ki_tdev_freebsd11 = 0x44,
> +    .ki_sigignore = 0x68,
> +    .ki_sigcatch = 0x78,
> +    .ki_uid = 0x88,
> +    .ki_ruid = 0x8c,
> +    .ki_svuid = 0x90,
> +    .ki_rgid = 0x94,
> +    .ki_svgid = 0x98,
> +    .ki_ngroups = 0x9c,
> +    .ki_groups = 0xa0,
> +    .ki_size = 0xe0,
> +    .ki_rssize = 0xe4,
> +    .ki_tsize = 0xec,
> +    .ki_dsize = 0xf0,
> +    .ki_ssize = 0xf4,
> +    .ki_start = 0x118,
> +    .ki_nice = 0x135,
> +    .ki_comm = 0x16f,
> +    .ki_tdev = 0x1e0,
> +    .ki_rusage = 0x210,
> +    .ki_rusage_ch = 0x258,
> +
> +    .ru_utime = 0x0,
> +    .ru_stime = 0x8,
> +    .ru_maxrss = 0x10,
> +    .ru_minflt = 0x20,
> +    .ru_majflt = 0x24,
> +  };
> +
> +struct kinfo_proc_layout kinfo_proc_layout_64 =
> +  {
> +    .ki_layout = 0x4,
> +    .ki_pid = 0x48,
> +    .ki_ppid = 0x4c,
> +    .ki_pgid = 0x50,
> +    .ki_tpgid = 0x54,
> +    .ki_sid = 0x58,
> +    .ki_tdev_freebsd11 = 0x64,
> +    .ki_sigignore = 0x88,
> +    .ki_sigcatch = 0x98,
> +    .ki_uid = 0xa8,
> +    .ki_ruid = 0xac,
> +    .ki_svuid = 0xb0,
> +    .ki_rgid = 0xb4,
> +    .ki_svgid = 0xb8,
> +    .ki_ngroups = 0xbc,
> +    .ki_groups = 0xc0,
> +    .ki_size = 0x100,
> +    .ki_rssize = 0x108,
> +    .ki_tsize = 0x118,
> +    .ki_dsize = 0x120,
> +    .ki_ssize = 0x128,
> +    .ki_start = 0x150,
> +    .ki_nice = 0x185,
> +    .ki_comm = 0x1bf,
> +    .ki_tdev = 0x230,
> +    .ki_rusage = 0x260,
> +    .ki_rusage_ch = 0x2f0,
> +
> +    .ru_utime = 0x0,
> +    .ru_stime = 0x10,
> +    .ru_maxrss = 0x20,
> +    .ru_minflt = 0x40,
> +    .ru_majflt = 0x48,
> +  };
> +
>  static struct gdbarch_data *fbsd_gdbarch_data_handle;
>  
>  struct fbsd_gdbarch_data
> @@ -367,6 +584,486 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
>    return note_data;
>  }
>  
> +/* Helper function to generate mappings flags for a single VM map entry.  */
> +
> +const char *
> +fbsd_vm_map_entry_flags (int kve_flags, int kve_protection)
> +{
> +  static char vm_flags[9];
> +
> +  vm_flags[0] = (kve_protection & KINFO_VME_PROT_READ) ? 'r' : '-';
> +  vm_flags[1] = (kve_protection & KINFO_VME_PROT_WRITE) ? 'w' : '-';
> +  vm_flags[2] = (kve_protection & KINFO_VME_PROT_EXEC) ? 'x' : '-';
> +  vm_flags[3] = ' ';
> +  vm_flags[4] = (kve_flags & KINFO_VME_FLAG_COW) ? 'C' : '-';
> +  vm_flags[5] = (kve_flags & KINFO_VME_FLAG_NEEDS_COPY) ? 'N' : '-';
> +  vm_flags[6] = (kve_flags & KINFO_VME_FLAG_SUPER) ? 'S' : '-';
> +  vm_flags[7] = (kve_flags & KINFO_VME_FLAG_GROWS_UP) ? 'U'
> +    : (kve_flags & KINFO_VME_FLAG_GROWS_DOWN) ? 'D' : '-';
> +  vm_flags[8] = '\0';
> +
> +  return vm_flags;
> +}
> +
> +/* Implement "info proc mappings" for a corefile.  */
> +
> +static void
> +fbsd_core_info_proc_mappings (struct gdbarch *gdbarch)
> +{
> +  asection *section;
> +  unsigned char *descdata, *descend;
> +  size_t note_size;
> +
> +  section = bfd_get_section_by_name (core_bfd, ".note.freebsdcore.vmmap");
> +  if (section == NULL)
> +    {
> +      warning (_("unable to find mappings in core file"));
> +      return;
> +    }
> +
> +  note_size = bfd_get_section_size (section);
> +  if (note_size < 4)
> +    error (_("malformed core note - too short for header"));
> +
> +  gdb::def_vector<unsigned char> contents (note_size);
> +  if (!bfd_get_section_contents (core_bfd, section, contents.data (),
> +				 0, note_size))
> +    error (_("could not get core note contents"));
> +
> +  descdata = contents.data ();
> +  descend = descdata + note_size;
> +
> +  /* Skip over the structure size.  */
> +  descdata += 4;
> +
> +  printf_filtered (_("Mapped address spaces:\n\n"));
> +  if (gdbarch_addr_bit (gdbarch) == 64)
> +    {
> +      printf_filtered ("  %18s %18s %10s %10s %9s %s\n",
> +		       "Start Addr",
> +		       "  End Addr",
> +		       "      Size", "    Offset", "Flags  ", "File");
> +    }
> +  else
> +    {
> +      printf_filtered ("\t%10s %10s %10s %10s %9s %s\n",
> +		       "Start Addr",
> +		       "  End Addr",
> +		       "      Size", "    Offset", "Flags  ", "File");
> +    }
> +
> +  while (descdata + KVE_PATH < descend)
> +    {
> +      ULONGEST start, end, offset, flags, prot, structsize;
> +
> +      structsize = bfd_get_32 (core_bfd, descdata + KVE_STRUCTSIZE);
> +      if (structsize < KVE_PATH)
> +	error (_("malformed core note - vmmap entry too small"));
> +
> +      start = bfd_get_64 (core_bfd, descdata + KVE_START);
> +      end = bfd_get_64 (core_bfd, descdata + KVE_END);
> +      offset = bfd_get_64 (core_bfd, descdata + KVE_OFFSET);
> +      flags = bfd_get_32 (core_bfd, descdata + KVE_FLAGS);
> +      prot = bfd_get_32 (core_bfd, descdata + KVE_PROTECTION);
> +      if (gdbarch_addr_bit (gdbarch) == 64)
> +	{
> +	  printf_filtered ("  %18s %18s %10s %10s %9s %s\n",
> +			   paddress (gdbarch, start),
> +			   paddress (gdbarch, end),
> +			   hex_string (end - start),
> +			   hex_string (offset),
> +			   fbsd_vm_map_entry_flags (flags, prot),
> +			   descdata + KVE_PATH);
> +	}
> +      else
> +	{
> +	  printf_filtered ("\t%10s %10s %10s %10s %9s %s\n",
> +			   paddress (gdbarch, start),
> +			   paddress (gdbarch, end),
> +			   hex_string (end - start),
> +			   hex_string (offset),
> +			   fbsd_vm_map_entry_flags (flags, prot),
> +			   descdata + KVE_PATH);
> +	}
> +
> +      descdata += structsize;
> +    }
> +}
> +
> +/* Fetch the pathname of a vnode for a single file descriptor from the
> +   file table core note.  */
> +
> +static gdb::unique_xmalloc_ptr<char>
> +fbsd_core_vnode_path (struct gdbarch *gdbarch, int fd)
> +{
> +  asection *section;
> +  unsigned char *descdata, *descend;
> +  size_t note_size;
> +
> +  section = bfd_get_section_by_name (core_bfd, ".note.freebsdcore.files");
> +  if (section == NULL)
> +    return nullptr;
> +
> +  note_size = bfd_get_section_size (section);
> +  if (note_size < 4)
> +    error (_("malformed core note - too short for header"));
> +
> +  gdb::def_vector<unsigned char> contents (note_size);
> +  if (!bfd_get_section_contents (core_bfd, section, contents.data (),
> +				 0, note_size))
> +    error (_("could not get core note contents"));
> +
> +  descdata = contents.data ();
> +  descend = descdata + note_size;
> +
> +  /* Skip over the structure size.  */
> +  descdata += 4;
> +
> +  while (descdata + KVE_PATH < descend)
> +    {
> +      ULONGEST structsize;
> +
> +      structsize = bfd_get_32 (core_bfd, descdata + KF_STRUCTSIZE);
> +      if (structsize < KVE_PATH)
> +	error (_("malformed core note - vmmap entry too small"));
> +
> +      if (bfd_get_32 (core_bfd, descdata + KF_TYPE) == KINFO_FILE_TYPE_VNODE
> +	  && bfd_get_signed_32 (core_bfd, descdata + KF_FD) == fd)
> +	{
> +	  char *path = (char *) descdata + KF_PATH;
> +	  return gdb::unique_xmalloc_ptr<char> (xstrdup (path));
> +	}
> +
> +      descdata += structsize;
> +    }
> +  return nullptr;
> +}
> +
> +/* Print out the contents of a signal set.  */
> +
> +static void
> +fbsd_print_sigset (const char *descr, unsigned char *sigset)
> +{
> +  printf_filtered ("%s:\t", descr);
> +  for (int i = 0; i < _SIG_WORDS; i++)

_SIG_WORDS seems to be FreeBSD-specific, so shouldn't be used in the tdep file,
unless we redefine it.

> +    printf_filtered ("%08x ",
> +		     (unsigned int) bfd_get_32 (core_bfd, sigset + i * 4));
> +  printf_filtered ("\n");
> +}
> +
> +/* Implement "info proc status" for a corefile.  */
> +
> +static void
> +fbsd_core_info_proc_status (struct gdbarch *gdbarch)
> +{
> +  struct kinfo_proc_layout *kp;
> +  asection *section;
> +  const char *state;
> +  unsigned char *descdata, *descend;
> +  int addr_bit, long_bit;
> +  size_t note_size;
> +  ULONGEST value;
> +
> +  section = bfd_get_section_by_name (core_bfd, ".note.freebsdcore.proc");
> +  if (section == NULL)
> +    {
> +      warning (_("unable to find process info in core file"));
> +      return;
> +    }
> +
> +  addr_bit = gdbarch_addr_bit (gdbarch);
> +  if (addr_bit == 64)
> +    kp = &kinfo_proc_layout_64;
> +  else if (bfd_get_arch (core_bfd) == bfd_arch_i386)
> +    kp = &kinfo_proc_layout_i386;
> +  else
> +    kp = &kinfo_proc_layout_32;
> +
> +  note_size = bfd_get_section_size (section);
> +  if (note_size < 4 + kp->ki_rusage_ch + kp->ru_majflt + addr_bit)
> +    error (_("malformed core note - too short"));
> +
> +  gdb::def_vector<unsigned char> contents (note_size);
> +  if (!bfd_get_section_contents (core_bfd, section, contents.data (),
> +				 0, note_size))
> +    error (_("could not get core note contents"));
> +
> +  descdata = contents.data ();
> +  descend = descdata + note_size;
> +
> +  /* Skip over the structure size.  */
> +  descdata += 4;
> +
> +  /* Verify 'ki_layout' is 0.  */
> +  if (bfd_get_32 (core_bfd, descdata + kp->ki_layout) != 0)
> +    {
> +      warning (_("unsupported process information in core file"));
> +      return;
> +    }
> +
> +  printf_filtered ("Name:\t%.19s\n", descdata + kp->ki_comm);
> +  printf_filtered ("Pid:\t%s\n",
> +		   pulongest(bfd_get_32 (core_bfd, descdata + kp->ki_pid)));

Missing a few spaces before parentheses here and there.

> +  printf_filtered ("PPid:\t%s\n",
> +		   pulongest(bfd_get_32 (core_bfd, descdata + kp->ki_ppid)));
> +  printf_filtered ("Uid:\t%s %s %s\n",
> +		   pulongest(bfd_get_32 (core_bfd, descdata + kp->ki_ruid)),
> +		   pulongest(bfd_get_32 (core_bfd, descdata + kp->ki_uid)),
> +		   pulongest(bfd_get_32 (core_bfd, descdata + kp->ki_svuid)));
> +  printf_filtered ("Gid:\t%s %s %s\n",
> +		   pulongest(bfd_get_32 (core_bfd, descdata + kp->ki_rgid)),
> +		   pulongest(bfd_get_32 (core_bfd, descdata + kp->ki_groups)),
> +		   pulongest(bfd_get_32 (core_bfd, descdata + kp->ki_svgid)));
> +  printf_filtered ("Groups:\t");
> +  uint16_t ngroups = bfd_get_16 (core_bfd, descdata + kp->ki_ngroups);
> +  for (int i = 0; i < ngroups; i++)
> +    printf_filtered ("%s ",
> +		     pulongest(bfd_get_32 (core_bfd,
> +					   descdata + kp->ki_groups + i * 4)));
> +  printf_filtered ("\n");
> +  value = bfd_get (addr_bit, core_bfd, descdata + kp->ki_size);
> +  printf_filtered ("VmSize:\t%8ju kB\n", (uintmax_t) value / 1024);
> +  value = bfd_get (addr_bit, core_bfd, descdata + kp->ki_rssize);
> +  printf_filtered ("VmRSS:\t%8ju pages\n", (uintmax_t) value);
> +  value = bfd_get (addr_bit, core_bfd, descdata + kp->ki_dsize);
> +  printf_filtered ("VmData:\t%8ju pages\n", (uintmax_t) value);
> +  value = bfd_get (addr_bit, core_bfd, descdata + kp->ki_ssize);
> +  printf_filtered ("VmStk:\t%8ju pages\n", (uintmax_t) value);
> +  value = bfd_get (addr_bit, core_bfd, descdata + kp->ki_tsize);
> +  printf_filtered ("VmExe:\t%8ju pages\n", (uintmax_t) value);
> +  fbsd_print_sigset ("SigIgn", descdata + kp->ki_sigignore);
> +  fbsd_print_sigset ("SigCgt", descdata + kp->ki_sigcatch);
> +}
> +
> +/* Helper function to read a struct timeval.  */
> +
> +static void
> +fbsd_core_fetch_timeval (struct gdbarch *gdbarch, unsigned char *data,
> +			 LONGEST &sec, ULONGEST &usec)
> +{
> +  if (gdbarch_addr_bit (gdbarch) == 64)
> +    {
> +      sec = bfd_get_signed_64 (core_bfd, data);
> +      usec = bfd_get_64 (core_bfd, data + 8);
> +    }
> +  else if (bfd_get_arch (core_bfd) == bfd_arch_i386)
> +    {
> +      sec = bfd_get_signed_32 (core_bfd, data);
> +      usec = bfd_get_32 (core_bfd, data + 4);
> +    }
> +  else
> +    {
> +      sec = bfd_get_signed_64 (core_bfd, data);
> +      usec = bfd_get_32 (core_bfd, data + 8);
> +    }
> +}
> +
> +/* Implement "info proc stat" for a corefile.  */
> +
> +static void
> +fbsd_core_info_proc_stat (struct gdbarch *gdbarch)
> +{
> +  struct kinfo_proc_layout *kp;
> +  asection *section;
> +  char state;
> +  unsigned char *descdata, *descend;
> +  int addr_bit;
> +  size_t note_size;
> +  ULONGEST value;
> +  LONGEST sec;
> +
> +  section = bfd_get_section_by_name (core_bfd, ".note.freebsdcore.proc");
> +  if (section == NULL)
> +    {
> +      warning (_("unable to find process info in core file"));
> +      return;
> +    }
> +
> +  addr_bit = gdbarch_addr_bit (gdbarch);
> +  if (addr_bit == 64)
> +    kp = &kinfo_proc_layout_64;
> +  else if (bfd_get_arch (core_bfd) == bfd_arch_i386)
> +    kp = &kinfo_proc_layout_i386;
> +  else
> +    kp = &kinfo_proc_layout_32;
> +
> +  note_size = bfd_get_section_size (section);
> +  if (note_size < 4 + kp->ki_rusage_ch + kp->ru_majflt + addr_bit)
> +    error (_("malformed core note - too short"));
> +
> +  gdb::def_vector<unsigned char> contents (note_size);
> +  if (!bfd_get_section_contents (core_bfd, section, contents.data (),
> +				 0, note_size))
> +    error (_("could not get core note contents"));
> +
> +  descdata = contents.data ();
> +  descend = descdata + note_size;
> +
> +  /* Skip over the structure size.  */
> +  descdata += 4;
> +
> +  /* Verify 'ki_layout' is 0.  */
> +  if (bfd_get_32 (core_bfd, descdata + kp->ki_layout) != 0)
> +    {
> +      warning (_("unsupported process information in core file"));
> +      return;
> +    }
> +
> +  printf_filtered ("Exec file: %.19s\n", descdata + kp->ki_comm);
> +  printf_filtered ("Parent process: %s\n",
> +		   pulongest (bfd_get_32 (core_bfd, descdata + kp->ki_ppid)));
> +  printf_filtered ("Process group: %s\n",
> +		   pulongest (bfd_get_32 (core_bfd, descdata + kp->ki_pgid)));
> +  printf_filtered ("Session id: %s\n",
> +		   pulongest (bfd_get_32 (core_bfd, descdata + kp->ki_sid)));
> +
> +  /* FreeBSD 12.0 and later store a 64-bit dev_t at 'ki_tdev'.  Older
> +     kernels store a 32-bit dev_t at 'ki_tdev_freebsd11'.  In older
> +     kernels the 64-bit 'ki_tdev' field is in a reserved section of
> +     the structure that is cleared to zero.  Assume that a zero value
> +     in ki_tdev indicates a core dump from an older kernel and use the
> +     value in 'ki_tdev_freebsd11' instead.  */
> +  value = bfd_get_64 (core_bfd, descdata + kp->ki_tdev);
> +  if (value == 0)
> +    value = bfd_get_32 (core_bfd, descdata + kp->ki_tdev_freebsd11);
> +  printf_filtered ("TTY: %s\n", pulongest (value));
> +  printf_filtered ("TTY owner process group: %s\n",
> +		   pulongest (bfd_get_32 (core_bfd, descdata + kp->ki_tpgid)));
> +  value = bfd_get (addr_bit, core_bfd,
> +		   descdata + kp->ki_rusage + kp->ru_minflt);
> +  printf_filtered ("Minor faults (no memory page): %s\n", pulongest (value));
> +  value = bfd_get (addr_bit, core_bfd,
> +		   descdata + kp->ki_rusage_ch + kp->ru_minflt);
> +  printf_filtered ("Minor faults, children: %s\n", pulongest (value));
> +  value = bfd_get (addr_bit, core_bfd,
> +		   descdata + kp->ki_rusage + kp->ru_majflt);
> +  printf_filtered ("Major faults (memory page faults): %s\n",
> +		   pulongest (value));
> +  value = bfd_get (addr_bit, core_bfd,
> +		   descdata + kp->ki_rusage_ch + kp->ru_majflt);
> +  printf_filtered ("Major faults, children: %s\n", pulongest (value));
> +  fbsd_core_fetch_timeval (gdbarch,
> +			   descdata + kp->ki_rusage + kp->ru_utime,
> +			   sec, value);
> +  printf_filtered ("utime: %s.%06d\n", plongest (sec), (int) value);
> +  fbsd_core_fetch_timeval (gdbarch,
> +			   descdata + kp->ki_rusage + kp->ru_stime,
> +			   sec, value);
> +  printf_filtered ("stime: %s.%06d\n", plongest (sec), (int) value);
> +  fbsd_core_fetch_timeval (gdbarch,
> +			   descdata + kp->ki_rusage_ch + kp->ru_utime,
> +			   sec, value);
> +  printf_filtered ("utime, children: %s.%06d\n", plongest (sec), (int) value);
> +  fbsd_core_fetch_timeval (gdbarch,
> +			   descdata + kp->ki_rusage_ch + kp->ru_stime,
> +			   sec, value);
> +  printf_filtered ("stime, children: %s.%06d\n", plongest (sec), (int) value);
> +  printf_filtered ("'nice' value: %d\n",
> +		   bfd_get_signed_8 (core_bfd, descdata + kp->ki_nice));
> +  fbsd_core_fetch_timeval (gdbarch, descdata + kp->ki_start, sec, value);
> +  printf_filtered ("start time: %s.%06d\n", plongest (sec), (int) value);
> +  printf_filtered ("Virtual memory size: %s kB\n",
> +		   pulongest (bfd_get (addr_bit, core_bfd,
> +				       descdata + kp->ki_start) / 1024));
> +  printf_filtered ("Resident set size: %s pages\n",
> +		   pulongest (bfd_get (addr_bit, core_bfd,
> +				       descdata + kp->ki_rssize)));
> +  value = bfd_get (addr_bit, core_bfd,
> +		   descdata + kp->ki_rusage + kp->ru_maxrss);
> +  printf_filtered ("rlim: %s kB\n", pulongest (value));
> +}
> +
> +/* Implement the "core_info_proc" gdbarch method.  */
> +
> +static void
> +fbsd_core_info_proc (struct gdbarch *gdbarch, const char *args,
> +		     enum info_proc_what what)
> +{
> +  bool do_cmdline = false;
> +  bool do_cwd = false;
> +  bool do_exe = false;
> +  bool do_mappings = false;
> +  bool do_status = false;
> +  bool do_stat = false;
> +  int pid;
> +
> +  switch (what)
> +    {
> +    case IP_MINIMAL:
> +      do_cmdline = true;
> +      do_cwd = true;
> +      do_exe = true;
> +      break;
> +    case IP_MAPPINGS:
> +      do_mappings = true;
> +      break;
> +    case IP_STATUS:
> +      do_status = true;
> +      break;
> +    case IP_STAT:
> +      do_stat = true;
> +      break;
> +    case IP_CMDLINE:
> +      do_cmdline = true;
> +      break;
> +    case IP_EXE:
> +      do_exe = true;
> +      break;
> +    case IP_CWD:
> +      do_cwd = true;
> +      break;
> +    case IP_ALL:
> +      do_cmdline = true;
> +      do_cwd = true;
> +      do_exe = true;
> +      do_mappings = true;
> +      do_status = true;
> +      do_stat = true;
> +      break;
> +    default:
> +      error (_("Not supported on this architecture."));

If you mean "not supported for FreeBSD", I'm not sure architecture
is the right word, since architecture usually refers to CPU architecture.

> +    }
> +
> +  pid = bfd_core_file_pid (core_bfd);
> +  if (pid != 0)
> +    printf_filtered (_("process %d\n"), pid);
> +
> +  if (do_cmdline)
> +    {
> +      const char *cmdline;
> +
> +      cmdline = bfd_core_file_failing_command (core_bfd);
> +      if (cmdline)
> +	printf_filtered ("cmdline = '%s'\n", cmdline);
> +      else
> +	warning (_("Command line unavailable"));
> +    }
> +  if (do_cwd)
> +    {
> +      gdb::unique_xmalloc_ptr<char> cwd =
> +	fbsd_core_vnode_path (gdbarch, KINFO_FILE_FD_TYPE_CWD);
> +      if (cwd)
> +	printf_filtered ("cwd = '%s'\n", cwd.get ());
> +      else
> +	warning (_("unable to read current working directory"));
> +    }
> +  if (do_exe)
> +    {
> +      gdb::unique_xmalloc_ptr<char> exe =
> +	fbsd_core_vnode_path (gdbarch, KINFO_FILE_FD_TYPE_TEXT);
> +      if (exe)
> +	printf_filtered ("exe = '%s'\n", exe.get ());
> +      else
> +	warning (_("unable to read executable path name"));
> +    }
> +  if (do_mappings)
> +    fbsd_core_info_proc_mappings (gdbarch);
> +  if (do_status)
> +    fbsd_core_info_proc_status (gdbarch);
> +  if (do_stat)
> +    fbsd_core_info_proc_stat (gdbarch);
> +}
> +
>  /* Print descriptions of FreeBSD-specific AUXV entries to FILE.  */
>  
>  static void
> @@ -519,6 +1216,7 @@ fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>    set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name);
>    set_gdbarch_core_xfer_siginfo (gdbarch, fbsd_core_xfer_siginfo);
>    set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
> +  set_gdbarch_core_info_proc (gdbarch, fbsd_core_info_proc);
>    set_gdbarch_print_auxv_entry (gdbarch, fbsd_print_auxv_entry);
>    set_gdbarch_get_siginfo_type (gdbarch, fbsd_get_siginfo_type);
>  
> diff --git a/gdb/fbsd-tdep.h b/gdb/fbsd-tdep.h
> index ff2e207aae..0029e03d41 100644
> --- a/gdb/fbsd-tdep.h
> +++ b/gdb/fbsd-tdep.h
> @@ -21,5 +21,6 @@
>  #define FBSD_TDEP_H
>  
>  extern void fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
> +extern const char *fbsd_vm_map_entry_flags (int kve_flags, int kve_protection);

Can you please add doc for this new function?

>  
>  #endif /* fbsd-tdep.h */
> 


Thanks,

Simon



More information about the Gdb-patches mailing list