From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20441 invoked by alias); 30 Oct 2012 17:18:16 -0000 Received: (qmail 20421 invoked by uid 22791); 30 Oct 2012 17:18:14 -0000 X-SWARE-Spam-Status: No, hits=-7.0 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,RP_MATCHES_RCVD,SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 30 Oct 2012 17:18:09 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9UHI9RL002013 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 30 Oct 2012 13:18:09 -0400 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q9UHI7Hu018122 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Tue, 30 Oct 2012 13:18:08 -0400 From: Tom Tromey To: gdb-patches@sourceware.org Subject: RFC: handle new NT_SIGINFO note in gdb CC: Binutils Development Date: Tue, 30 Oct 2012 17:18:00 -0000 Message-ID: <878vanyj3k.fsf@fleche.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-10/txt/msg00545.txt.bz2 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 * elf.c (elfcore_grok_note) : New case; make pseudosection. 2012-10-30 Tom Tromey * 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) : New case. 2012-10-30 Tom Tromey * 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