Changeset View
Changeset View
Standalone View
Standalone View
head/devel/gdb/files/commit-4b654465bf
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 4b654465bfc3034c969d2d942c14b2cedfd3e3b6 | |||||
Author: John Baldwin <jhb@FreeBSD.org> | |||||
Date: Wed Jun 28 12:50:56 2017 -0700 | |||||
Read signal information from FreeBSD core dumps. | |||||
FreeBSD recently added a new ELF core note which dumps the entire LWP | |||||
info structure (the same structure returned by the ptrace PT_LWPINFO | |||||
operation) for each thread. The plan is for this note to eventually | |||||
supplant the older "thrmisc" ELF core note as it contains more | |||||
information and it permits new information to be exported via both | |||||
ptrace() and core dumps using the same structure. | |||||
For signal information, the implementation is similar to the native | |||||
implementation for FreeBSD processes. The PL_FLAG_SI flag must be | |||||
checked to determine if the embedded siginfo_t structure is valid, and | |||||
if so it is transferred into the caller's buffer. | |||||
gdb/ChangeLog: | |||||
* fbsd-tdep.c (LWPINFO_OFFSET, LWPINFO_PL_FLAGS) | |||||
(LWPINFO64_PL_SIGINFO, LWPINFO32_PL_SIGINFO, PL_FLAG_SI) | |||||
(SIZE64_SIGINFO_T, SIZE32_SIGINFO_T, fbsd_core_xfer_siginfo): New. | |||||
(fbsd_init_abi): Install gdbarch "core_xfer_siginfo" method. | |||||
diff --git gdb/fbsd-tdep.c gdb/fbsd-tdep.c | |||||
index 32df104208..6f30197a83 100644 | |||||
--- gdb/fbsd-tdep.c | |||||
+++ gdb/fbsd-tdep.c | |||||
@@ -30,6 +30,28 @@ | |||||
#include "fbsd-tdep.h" | |||||
+/* FreeBSD kernels 12.0 and later include a copy of the | |||||
+ 'ptrace_lwpinfo' structure returned by the PT_LWPINFO ptrace | |||||
+ operation in an ELF core note (NT_FREEBSD_PTLWPINFO) for each LWP. | |||||
+ The constants below define the offset of field members and flags in | |||||
+ this structure used by methods in this file. Note that the | |||||
+ 'ptrace_lwpinfo' struct in the note is preceded by a 4 byte integer | |||||
+ containing the size of the structure. */ | |||||
+ | |||||
+#define LWPINFO_OFFSET 0x4 | |||||
+ | |||||
+/* Offsets in ptrace_lwpinfo. */ | |||||
+#define LWPINFO_PL_FLAGS 0x8 | |||||
+#define LWPINFO64_PL_SIGINFO 0x30 | |||||
+#define LWPINFO32_PL_SIGINFO 0x2c | |||||
+ | |||||
+/* Flags in pl_flags. */ | |||||
+#define PL_FLAG_SI 0x20 /* siginfo is valid */ | |||||
+ | |||||
+/* Sizes of siginfo_t. */ | |||||
+#define SIZE64_SIGINFO_T 80 | |||||
+#define SIZE32_SIGINFO_T 64 | |||||
+ | |||||
static struct gdbarch_data *fbsd_gdbarch_data_handle; | |||||
struct fbsd_gdbarch_data | |||||
@@ -113,6 +135,51 @@ fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr) | |||||
return NULL; | |||||
} | |||||
+/* Implement the "core_xfer_siginfo" gdbarch method. */ | |||||
+ | |||||
+static LONGEST | |||||
+fbsd_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf, | |||||
+ ULONGEST offset, ULONGEST len) | |||||
+{ | |||||
+ size_t siginfo_size; | |||||
+ | |||||
+ if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32) | |||||
+ siginfo_size = SIZE32_SIGINFO_T; | |||||
+ else | |||||
+ siginfo_size = SIZE64_SIGINFO_T; | |||||
+ if (offset > siginfo_size) | |||||
+ return -1; | |||||
+ | |||||
+ thread_section_name section_name (".note.freebsdcore.lwpinfo", inferior_ptid); | |||||
+ asection *section = bfd_get_section_by_name (core_bfd, section_name.c_str ()); | |||||
+ if (section == NULL) | |||||
+ return -1; | |||||
+ | |||||
+ gdb_byte buf[4]; | |||||
+ if (!bfd_get_section_contents (core_bfd, section, buf, | |||||
+ LWPINFO_OFFSET + LWPINFO_PL_FLAGS, 4)) | |||||
+ return -1; | |||||
+ | |||||
+ int pl_flags = extract_signed_integer (buf, 4, gdbarch_byte_order (gdbarch)); | |||||
+ if (!(pl_flags & PL_FLAG_SI)) | |||||
+ return -1; | |||||
+ | |||||
+ if (offset + len > siginfo_size) | |||||
+ len = siginfo_size - offset; | |||||
+ | |||||
+ ULONGEST siginfo_offset; | |||||
+ if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32) | |||||
+ siginfo_offset = LWPINFO_OFFSET + LWPINFO32_PL_SIGINFO; | |||||
+ else | |||||
+ siginfo_offset = LWPINFO_OFFSET + LWPINFO64_PL_SIGINFO; | |||||
+ | |||||
+ if (!bfd_get_section_contents (core_bfd, section, readbuf, | |||||
+ siginfo_offset + offset, len)) | |||||
+ return -1; | |||||
+ | |||||
+ return len; | |||||
+} | |||||
+ | |||||
static int | |||||
find_signalled_thread (struct thread_info *info, void *data) | |||||
{ | |||||
@@ -447,6 +514,7 @@ fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |||||
{ | |||||
set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str); | |||||
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_print_auxv_entry (gdbarch, fbsd_print_auxv_entry); | |||||
set_gdbarch_get_siginfo_type (gdbarch, fbsd_get_siginfo_type); |