From 739ab2e92e1840c9285f3cfce1f1236c0fa68730 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 6 Sep 2018 15:03:19 -0700 Subject: [PATCH] Generate NT_PROCSTAT_{AUXV,VMMAP,PS_STRINGS} in FreeBSD coredumps gcore generates NT_AUXV and NT_FILE notes for Linux targets. On FreeBSD auxv is stored in a NT_PROCSTAT_AUXV section, virtual memory mappings are stored in a NT_PROCSTAT_VMMAP, and both are prefixed with the struct size. In addition, store a NT_PROCSTAT_PS_STRINGS note saving the initial location of the argv[] and environment[] arrays. gdb/ChangeLog: PR gdb/23105 * fbsd-nat.c (fbsd_nat_target::xfer_partial): Add support for TARGET_OBJECT_FREEBSD_VMMAP and TARGET_OBJECT_FREEBSD_PS_STRINGS. * fbsd-tdep.c (fbsd_make_note_desc): New. (fbsd_make_corefile_notes): Write NT_PROCSTAT_AUXV, NT_PROCSTAT_VMMAP and NT_PROCSTAT_PS_STRINGS notes. * target.h (enum target_object) Add FreeBSD-specific TARGET_OBJECT_FREEBSD_VMMAP and TARGET_OBJECT_FREEBSD_PS_STRINGS. --- gdb/ChangeLog | 11 +++++++++++ gdb/fbsd-nat.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/fbsd-tdep.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/target.h | 4 ++++ 4 files changed, 126 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 410fbef..e6f44a3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2018-09-06 Simon Ser + + PR gdb/23105 + * fbsd-nat.c (fbsd_nat_target::xfer_partial): Add support for + TARGET_OBJECT_FREEBSD_VMMAP and TARGET_OBJECT_FREEBSD_PS_STRINGS. + * fbsd-tdep.c (fbsd_make_note_desc): New. + (fbsd_make_corefile_notes): Write NT_PROCSTAT_AUXV, + NT_PROCSTAT_VMMAP and NT_PROCSTAT_PS_STRINGS notes. + * target.h (enum target_object) Add FreeBSD-specific + TARGET_OBJECT_FREEBSD_VMMAP and TARGET_OBJECT_FREEBSD_PS_STRINGS. + 2018-09-06 Simon Marchi * compile/compile-c.h (generate_c_for_variable_locations): diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c index 115deac..a255318 100644 --- a/gdb/fbsd-nat.c +++ b/gdb/fbsd-nat.c @@ -751,6 +751,61 @@ fbsd_nat_target::xfer_partial (enum target_object object, } return TARGET_XFER_E_IO; } + case TARGET_OBJECT_FREEBSD_VMMAP: + case TARGET_OBJECT_FREEBSD_PS_STRINGS: + { + gdb::byte_vector buf_storage; + gdb_byte *buf; + size_t buflen; + int mib[4]; + + int proc_target; + uint32_t struct_size; + switch (object) + { + case TARGET_OBJECT_FREEBSD_VMMAP: + proc_target = KERN_PROC_VMMAP; + struct_size = sizeof (struct kinfo_vmentry); + break; + case TARGET_OBJECT_FREEBSD_PS_STRINGS: + proc_target = KERN_PROC_PS_STRINGS; + struct_size = sizeof (void *); + break; + } + + if (writebuf != NULL) + return TARGET_XFER_E_IO; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = proc_target; + mib[3] = pid; + + if (sysctl (mib, 4, NULL, &buflen, NULL, 0) != 0) + return TARGET_XFER_E_IO; + buflen += sizeof (struct_size); + + if (offset >= buflen) + { + *xfered_len = 0; + return TARGET_XFER_EOF; + } + + buf_storage.resize (buflen); + buf = buf_storage.data (); + + memcpy (buf, &struct_size, sizeof (struct_size)); + buflen -= sizeof (struct_size); + if (sysctl (mib, 4, buf + sizeof (struct_size), &buflen, NULL, 0) != 0) + return TARGET_XFER_E_IO; + buflen += sizeof (struct_size); + + if (buflen - offset < len) + len = buflen - offset; + memcpy (readbuf, buf + offset, len); + *xfered_len = len; + return TARGET_XFER_OK; + } default: return inf_ptrace_target::xfer_partial (object, annex, readbuf, writebuf, offset, diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c index 78d0c3d..ed43087 100644 --- a/gdb/fbsd-tdep.c +++ b/gdb/fbsd-tdep.c @@ -512,6 +512,28 @@ fbsd_corefile_thread (struct thread_info *info, args->note_size, args->stop_signal); } +/* Return a byte_vector containing the contents of a core dump note + for the target object of type OBJECT. If STRUCTSIZE is non-zero, + the data is prefixed with a 32-bit integer size to match the format + used in FreeBSD NT_PROCSTAT_* notes. */ + +static gdb::optional +fbsd_make_note_desc (enum target_object object, uint32_t structsize) +{ + gdb::optional buf = + target_read_alloc (current_top_target (), object, NULL); + if (!buf || buf->empty ()) + return {}; + + if (structsize == 0) + return buf; + + gdb::byte_vector desc (sizeof (structsize) + buf->size ()); + memcpy (desc.data (), &structsize, sizeof (structsize)); + memcpy (desc.data () + sizeof (structsize), buf->data (), buf->size ()); + return desc; +} + /* Create appropriate note sections for a corefile, returning them in allocated memory. */ @@ -586,6 +608,40 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) note_data = thread_args.note_data; + /* Auxiliary vector. */ + uint32_t structsize = gdbarch_ptr_bit (gdbarch) / 4; /* Elf_Auxinfo */ + gdb::optional note_desc = + fbsd_make_note_desc (TARGET_OBJECT_AUXV, structsize); + if (note_desc && !note_desc->empty ()) + { + note_data = elfcore_write_note (obfd, note_data, note_size, "FreeBSD", + NT_FREEBSD_PROCSTAT_AUXV, + note_desc->data (), note_desc->size ()); + if (!note_data) + return NULL; + } + + /* Virtual memory mappings. */ + note_desc = fbsd_make_note_desc (TARGET_OBJECT_FREEBSD_VMMAP, 0); + if (note_desc && !note_desc->empty ()) + { + note_data = elfcore_write_note (obfd, note_data, note_size, "FreeBSD", + NT_FREEBSD_PROCSTAT_VMMAP, + note_desc->data (), note_desc->size ()); + if (!note_data) + return NULL; + } + + note_desc = fbsd_make_note_desc (TARGET_OBJECT_FREEBSD_PS_STRINGS, 0); + if (note_desc && !note_desc->empty ()) + { + note_data = elfcore_write_note (obfd, note_data, note_size, "FreeBSD", + NT_FREEBSD_PROCSTAT_PSSTRINGS, + note_desc->data (), note_desc->size ()); + if (!note_data) + return NULL; + } + return note_data; } diff --git a/gdb/target.h b/gdb/target.h index 229b5d0..a3000c8 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -202,6 +202,10 @@ enum target_object of the process ID of the process in question, in hexadecimal format. */ TARGET_OBJECT_EXEC_FILE, + /* FreeBSD virtual memory mappings. */ + TARGET_OBJECT_FREEBSD_VMMAP, + /* FreeBSD process strings. */ + TARGET_OBJECT_FREEBSD_PS_STRINGS, /* Possible future objects: TARGET_OBJECT_FILE, ... */ }; -- 2.7.4