Changeset View
Changeset View
Standalone View
Standalone View
devel/gdb/files/commit-d2176225dc
- This file was added.
Property | Old Value | New Value |
---|---|---|
fbsd:nokeywords | null | yes \ No newline at end of property |
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
commit d2176225dc982c22640215a0e611e997e8eeb030 | |||||
Author: John Baldwin <jhb@FreeBSD.org> | |||||
Date: Tue Jan 9 13:35:17 2018 -0800 | |||||
Support 'info proc' for FreeBSD process core dumps. | |||||
- 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. | |||||
- 'status' output is generated by outputting fields from | |||||
the first structure stored in the NT_PROCSTAT_PROC core note. | |||||
- 'stat' is aliased to 'status'. | |||||
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, SIG_WORDS, 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_core_fetch_timeval, fbsd_print_sigset) | |||||
(fbsd_core_info_proc_status, fbsd_core_info_proc): New. | |||||
(fbsd_init_abi): Install gdbarch "core_info_proc" method. | |||||
* fbsd-tdep.h (fbsd_vm_map_entry_flags): New. | |||||
diff --git gdb/fbsd-tdep.c gdb/fbsd-tdep.c | |||||
index ce17c672d9..8aa0243d54 100644 | |||||
--- gdb/fbsd-tdep.c | |||||
+++ gdb/fbsd-tdep.c | |||||
@@ -52,6 +52,228 @@ | |||||
#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 | |||||
+ | |||||
+/* Number of 32-bit words in a signal set. This matches _SIG_WORDS in | |||||
+ <sys/_sigset.h> and is the same value on all architectures. */ | |||||
+ | |||||
+#define SIG_WORDS 4 | |||||
+ | |||||
+/* 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 | |||||
+{ | |||||
+ /* 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; | |||||
+}; | |||||
+ | |||||
+const struct kinfo_proc_layout kinfo_proc_layout_32 = | |||||
+ { | |||||
+ .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, | |||||
+ }; | |||||
+ | |||||
+const 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, | |||||
+ }; | |||||
+ | |||||
+const 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 +589,433 @@ 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 in 'info proc mappings'. */ | |||||
+ | |||||
+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; | |||||
+} | |||||
+ | |||||
+/* 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); | |||||
+ } | |||||
+} | |||||
+ | |||||
+/* Print out the contents of a signal set. */ | |||||
+ | |||||
+static void | |||||
+fbsd_print_sigset (const char *descr, unsigned char *sigset) | |||||
+{ | |||||
+ printf_filtered ("%s: ", descr); | |||||
+ for (int i = 0; i < SIG_WORDS; i++) | |||||
+ 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) | |||||
+{ | |||||
+ const struct kinfo_proc_layout *kp; | |||||
+ asection *section; | |||||
+ const char *state; | |||||
+ unsigned char *descdata; | |||||
+ int addr_bit, long_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; | |||||
+ long_bit = gdbarch_long_bit (gdbarch); | |||||
+ | |||||
+ /* | |||||
+ * Ensure that the note is large enough for all of the fields fetched | |||||
+ * by this function. In particular, the note must contain the 32-bit | |||||
+ * structure size, then it must be long enough to access the last | |||||
+ * field used (ki_rusage_ch.ru_majflt) which is the size of a long. | |||||
+ */ | |||||
+ note_size = bfd_get_section_size (section); | |||||
+ if (note_size < (4 + kp->ki_rusage_ch + kp->ru_majflt | |||||
+ + long_bit / TARGET_CHAR_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 (); | |||||
+ | |||||
+ /* 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: %.19s\n", descdata + kp->ki_comm); | |||||
+ printf_filtered ("Process ID: %s\n", | |||||
+ pulongest (bfd_get_32 (core_bfd, descdata + kp->ki_pid))); | |||||
+ 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))); | |||||
+ printf_filtered ("User IDs (real, effective, saved): %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 ("Group IDs (real, effective, saved): %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: "); | |||||
+ 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 (long_bit, core_bfd, | |||||
+ descdata + kp->ki_rusage + kp->ru_minflt); | |||||
+ printf_filtered ("Minor faults (no memory page): %s\n", pulongest (value)); | |||||
+ value = bfd_get (long_bit, core_bfd, | |||||
+ descdata + kp->ki_rusage_ch + kp->ru_minflt); | |||||
+ printf_filtered ("Minor faults, children: %s\n", pulongest (value)); | |||||
+ value = bfd_get (long_bit, core_bfd, | |||||
+ descdata + kp->ki_rusage + kp->ru_majflt); | |||||
+ printf_filtered ("Major faults (memory page faults): %s\n", | |||||
+ pulongest (value)); | |||||
+ value = bfd_get (long_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_size) / 1024)); | |||||
+ printf_filtered ("Data size: %s pages\n", | |||||
+ pulongest (bfd_get (addr_bit, core_bfd, | |||||
+ descdata + kp->ki_dsize))); | |||||
+ printf_filtered ("Stack size: %s pages\n", | |||||
+ pulongest (bfd_get (addr_bit, core_bfd, | |||||
+ descdata + kp->ki_ssize))); | |||||
+ printf_filtered ("Text size: %s pages\n", | |||||
+ pulongest (bfd_get (addr_bit, core_bfd, | |||||
+ descdata + kp->ki_tsize))); | |||||
+ printf_filtered ("Resident set size: %s pages\n", | |||||
+ pulongest (bfd_get (addr_bit, core_bfd, | |||||
+ descdata + kp->ki_rssize))); | |||||
+ printf_filtered ("Maximum RSS: %s pages\n", | |||||
+ pulongest (bfd_get (long_bit, core_bfd, | |||||
+ descdata + kp->ki_rusage | |||||
+ + kp->ru_maxrss))); | |||||
+ fbsd_print_sigset ("Ignored Signals", descdata + kp->ki_sigignore); | |||||
+ fbsd_print_sigset ("Caught Signals", descdata + kp->ki_sigcatch); | |||||
+} | |||||
+ | |||||
+/* 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; | |||||
+ 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: | |||||
+ case IP_STAT: | |||||
+ do_status = 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; | |||||
+ break; | |||||
+ default: | |||||
+ return; | |||||
+ } | |||||
+ | |||||
+ 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); | |||||
+} | |||||
+ | |||||
/* Print descriptions of FreeBSD-specific AUXV entries to FILE. */ | |||||
static void | |||||
@@ -519,6 +1168,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 gdb/fbsd-tdep.h gdb/fbsd-tdep.h | |||||
index 9769903dec..0b293e5a25 100644 | |||||
--- gdb/fbsd-tdep.h | |||||
+++ gdb/fbsd-tdep.h | |||||
@@ -22,4 +22,11 @@ | |||||
extern void fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch); | |||||
+/* Helper function to generate mappings flags for a single VM map | |||||
+ entry in 'info proc mappings'. The KVE_FLAGS and KVE_PROTECTION | |||||
+ parameters should contain the values of the corresponding fields in | |||||
+ a 'struct kinfo_vmentry'. */ | |||||
+ | |||||
+extern const char *fbsd_vm_map_entry_flags (int kve_flags, int kve_protection); | |||||
+ | |||||
#endif /* fbsd-tdep.h */ |