This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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 (&current_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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]