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.
This commit is contained in:
parent
74ccf6db11
commit
d2176225dc
|
@ -1,3 +1,21 @@
|
|||
2018-01-09 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, 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-08 Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
|
||||
* gdb/gnu-nat.c: Include <elf.h> and <link.h>.
|
||||
|
|
650
gdb/fbsd-tdep.c
650
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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue