From patchwork Fri Jan 5 19:21:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Baldwin X-Patchwork-Id: 25238 Received: (qmail 123126 invoked by alias); 5 Jan 2018 19:43:56 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 122750 invoked by uid 89); 5 Jan 2018 19:43:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, SPF_SOFTFAIL autolearn=ham version=3.3.2 spammy=18653 X-HELO: mail.baldwin.cx Received: from bigwig.baldwin.cx (HELO mail.baldwin.cx) (96.47.65.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 05 Jan 2018 19:43:49 +0000 Received: from ralph.baldwin.cx (astound-66-234-202-155.ca.astound.net [66.234.202.155]) by mail.baldwin.cx (Postfix) with ESMTPSA id 43A1510A87D; Fri, 5 Jan 2018 14:43:47 -0500 (EST) From: John Baldwin To: Simon Marchi Cc: gdb-patches@sourceware.org Subject: Re: [PATCH v2 1/5] Support 'info proc' for FreeBSD process core dumps. Date: Fri, 05 Jan 2018 11:21:47 -0800 Message-ID: <1752022.FNtOcQG6Rg@ralph.baldwin.cx> User-Agent: KMail/4.14.10 (FreeBSD/11.1-STABLE; KDE/4.14.30; amd64; ; ) In-Reply-To: <8ce6ffcf-cf4c-9855-5d37-4d8db4e33803@simark.ca> References: <20180104014923.11899-1-jhb@FreeBSD.org> <20180104014923.11899-2-jhb@FreeBSD.org> <8ce6ffcf-cf4c-9855-5d37-4d8db4e33803@simark.ca> MIME-Version: 1.0 X-IsSubscribed: yes On Thursday, January 04, 2018 09:53:47 PM Simon Marchi wrote: > Hi John, > > I have two little comments, but otherwise it LGTM. > > On 2018-01-03 08:49 PM, John Baldwin wrote: > > +/* 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, *descend; > > I get this: > > /home/simark/src/binutils-gdb/gdb/fbsd-tdep.c: In function ‘void fbsd_core_info_proc_status(gdbarch*)’: > /home/simark/src/binutils-gdb/gdb/fbsd-tdep.c:791:29: error: variable ‘descend’ set but not used [-Werror=unused-but-set-variable] > unsigned char *descdata, *descend; > ^~~~~~~ Oops, too much copy and paste (and I've only been building with clang so far). > > + 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; > > + > > + note_size = bfd_get_section_size (section); > > + if (note_size < 4 + kp->ki_rusage_ch + kp->ru_majflt + addr_bit) > > What's the rationale behind that computation? The field ru_majflt in kp->ki_rusage_ch > is the furthest field we'll actually need in this function? And addr_bit is the size of > that field? And 4 is because there's a field at the beginning containing the size of > the structure that comes after? Correct. This is the bounds check to avoid overflowing the note buffer, but it does warrany a comment to explain what it is doing. And actually, writing that comment made me realize a bug. It should be 'addr_bit / TARGET_CHAR_BIT', not addr_bit directly. Also, I noticed that the 'long_bit' variable at the start of the quoted section above also isn't used, but it's probably cleaner to be explicit and assign it to gdbarch_long_bit() and use it in place of addr_bit for structure members that are of type long rather than assuming addr_bit == long_bit (even though that is true on all of the architectures FreeBSD supports or is likely to support). Ends up like this: commit b64825d47b446c6a160a2bf28b62641492d07d82 Author: John Baldwin Date: Fri Jan 5 11:19:02 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 a/gdb/ChangeLog b/gdb/ChangeLog index 24ccfe6882..dfdf4336ff 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,21 @@ +2018-01-05 John Baldwin + + * 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. + 2018-01-05 Pedro Alves PR gdb/18653 diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c index ce17c672d9..8aa0243d54 100644 --- a/gdb/fbsd-tdep.c +++ b/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 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 . */ + +#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 . */ + +#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 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 . */ + +#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 . */ + +#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 + 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 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. 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 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 +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 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 (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 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 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 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 a/gdb/fbsd-tdep.h b/gdb/fbsd-tdep.h index 9769903dec..0b293e5a25 100644 --- a/gdb/fbsd-tdep.h +++ b/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 */