This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RFC: handle new NT_SIGINFO note in gdb
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Cc: Binutils Development <binutils at sourceware dot org>
- Date: Tue, 30 Oct 2012 11:18:07 -0600
- Subject: RFC: handle new NT_SIGINFO note in gdb
This patch adds support for the new Linux NT_SIGINFO core note to gdb.
First, I've CCd the binutils list because this includes a BFD change.
In particular, in order to access the note data, I changed BFD to make a
pseudosection for this new note's data. This seemed ok based on
surrounding code; but if some other method is preferred, just let me
know and I will implement that instead.
On the gdb side the support is relatively straightforward.
I chose to implement the support directly in corelow, since adding a new
hook just for this functionality seemed like overkill.
A new test case is included. It uses "gcore" and then re-reads the
siginfo data from the generated core.
Built and regtested on x86-64 Fedora 16.
On the binutils side, I remembered this time to run the test suite in
binutils, gas, and ld.
Tom
2012-10-30 Tom Tromey <tromey@redhat.com>
* elf.c (elfcore_grok_note) <NT_SIGINFO>: New case; make
pseudosection.
2012-10-30 Tom Tromey <tromey@redhat.com>
* linux-tdep.c (linux_make_siginfo_note): New function.
(linux_make_corefile_notes): Use it.
* corelow.c (get_core_siginfo): New function.
(core_xfer_partial) <TARGET_OBJECT_SIGNAL_INFO>: New case.
2012-10-30 Tom Tromey <tromey@redhat.com>
* gdb.base/siginfo-obj.exp: Create core file. Test siginfo from
core files, if possible.
---
bfd/ChangeLog | 5 ++++
bfd/elf.c | 4 +++
gdb/ChangeLog | 7 ++++++
gdb/corelow.c | 25 +++++++++++++++++++++
gdb/linux-tdep.c | 38 ++++++++++++++++++++++++++++++++
gdb/testsuite/ChangeLog | 5 ++++
gdb/testsuite/gdb.base/siginfo-obj.exp | 17 ++++++++++++++
7 files changed, 101 insertions(+), 0 deletions(-)
diff --git a/bfd/elf.c b/bfd/elf.c
index cab1cc7..4465f48 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -8604,6 +8604,10 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
return TRUE;
}
+
+ case NT_SIGINFO:
+ return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo",
+ note);
}
}
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 340b149..d2f87cb 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -662,6 +662,26 @@ add_to_spuid_list (bfd *abfd, asection *asect, void *list_p)
list->pos += 4;
}
+/* Read siginfo data from the core, if possible. Returns -1 on
+ failure. Otherwise, returns the number of bytes read. ABFD is the
+ core file's BFD; READBUF, OFFSET, and LEN are all as specified by
+ the to_xfer_partial interface. */
+
+static LONGEST
+get_core_siginfo (bfd *abfd, gdb_byte *readbuf, ULONGEST offset, LONGEST len)
+{
+ asection *section;
+
+ section = bfd_get_section_by_name (abfd, ".note.linuxcore.siginfo");
+ if (section == NULL)
+ return -1;
+
+ if (!bfd_get_section_contents (abfd, section, readbuf, offset, len))
+ return -1;
+
+ return len;
+}
+
static LONGEST
core_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
@@ -800,6 +820,11 @@ core_xfer_partial (struct target_ops *ops, enum target_object object,
}
return -1;
+ case TARGET_OBJECT_SIGNAL_INFO:
+ if (readbuf)
+ return get_core_siginfo (core_bfd, readbuf, offset, len);
+ return -1;
+
default:
if (ops->beneath != NULL)
return ops->beneath->to_xfer_partial (ops->beneath, object,
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 65f5f97..f6408b6 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -712,6 +712,41 @@ linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
return note_data;
}
+/* Write the core note for siginfo data, if it exists.
+ GDBARCH is the architecture to use.
+ OBFD is the output BFD.
+ NOTE_DATA is the current note data.
+ NOTE_SIZE is an in-out parameter holding the current note size.
+ This returns the new note data pointer. */
+
+static char *
+linux_make_siginfo_note (struct gdbarch *gdbarch, bfd *obfd,
+ char *note_data, int *note_size)
+{
+ struct type *siginfo_type;
+ gdb_byte *buf;
+ LONGEST bytes_read;
+ struct cleanup *cleanups;
+
+ if (!gdbarch_get_siginfo_type_p (gdbarch))
+ return note_data;
+
+ siginfo_type = gdbarch_get_siginfo_type (gdbarch);
+
+ buf = xmalloc (TYPE_LENGTH (siginfo_type));
+ cleanups = make_cleanup (xfree, buf);
+
+ bytes_read = target_read (¤t_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+ buf, 0, TYPE_LENGTH (siginfo_type));
+ if (bytes_read == TYPE_LENGTH (siginfo_type))
+ note_data = elfcore_write_note (obfd, note_data, note_size,
+ "CORE", NT_SIGINFO,
+ buf, bytes_read);
+
+ do_cleanups (cleanups);
+ return note_data;
+}
+
/* Records the thread's register state for the corefile note
section. */
@@ -867,6 +902,9 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size,
if (!note_data)
return NULL;
+ /* Siginfo. */
+ note_data = linux_make_siginfo_note (gdbarch, obfd, note_data, note_size);
+
make_cleanup (xfree, note_data);
return note_data;
}
diff --git a/gdb/testsuite/gdb.base/siginfo-obj.exp b/gdb/testsuite/gdb.base/siginfo-obj.exp
index 9ca649d..75e76ff 100644
--- a/gdb/testsuite/gdb.base/siginfo-obj.exp
+++ b/gdb/testsuite/gdb.base/siginfo-obj.exp
@@ -56,6 +56,10 @@ if { ![runto_main] } then {
# Run to the signal.
gdb_test "continue" ".*Program received signal SIGSEGV.*" "continue to signal"
+# Try to generate a core file, for a later test.
+set gcorefile [standard_output_file $testfile.gcore]
+set gcore_created [gdb_gcore_cmd $gcorefile "save a core file"]
+
set ssi_addr ""
set test "Extract si_addr"
gdb_test_multiple "p \$_siginfo" "$test" {
@@ -123,3 +127,16 @@ gdb_test "p ssi_addr" " = \\(void \\*\\) 0x666"
gdb_test "p ssi_errno" " = 666"
gdb_test "p ssi_code" " = 999"
gdb_test "p ssi_signo" " = 11"
+
+# Test siginfo preservation in core files.
+if {$gcore_created} {
+ clean_restart $binfile
+
+ gdb_test "core $gcorefile" "Core was generated by.*"
+
+ gdb_test "p \$_siginfo.si_signo" " = $ssi_signo"
+ gdb_test "p \$_siginfo.si_errno" " = $ssi_errno"
+ gdb_test "p \$_siginfo.si_code" " = $ssi_code"
+ gdb_test "p \$_siginfo._sifields._sigfault.si_addr" \
+ " = \\(void \\*\\) $ssi_addr"
+}
--
1.7.7.6