From patchwork Thu Jan 21 13:11:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 10503 Received: (qmail 111386 invoked by alias); 21 Jan 2016 13:11:36 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 111365 invoked by uid 89); 21 Jan 2016 13:11:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=616, 617, writer, 61, 7 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 21 Jan 2016 13:11:32 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 245E019F210; Thu, 21 Jan 2016 13:11:31 +0000 (UTC) Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u0LDBTmB021967; Thu, 21 Jan 2016 08:11:30 -0500 Message-ID: <56A0D901.7010709@redhat.com> Date: Thu, 21 Jan 2016 13:11:29 +0000 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Alan Modra , binutils@sourceware.org, gdb-patches@sourceware.org Subject: Re: Use elfcore_write_linux_prstatus in gdb References: <20160121092855.GJ17028@bubble.grove.modra.org> <56A0CE51.1090709@redhat.com> In-Reply-To: <56A0CE51.1090709@redhat.com> On 01/21/2016 12:25 PM, Pedro Alves wrote: > On 01/21/2016 09:28 AM, Alan Modra wrote: >> The gdb side. Nothing fancy here, and no support for targets that >> need gdbarch_elfcore_write_linux_prstatus, mips n32, sparc64 if >> writing any of pr_{u,s,cu,cs}time, and probably x86-64 x32. > > Thanks a lot for doing all this! I don't have spare cycles either to > drive this all the way to completion for all archs, I think we can still > move forward with it, by adding a stop-gap implementation those > archs, which just calls elfcore_write_prstatus. I'll send it along > in a bit. Like this. I've pushed this to the users/palves/core-prstatus-rework branch. I've tested on x86_64 with: make check RUNTESTFLAGS="--target_board unix/-m32" TESTS="*/*core*.exp" make check RUNTESTFLAGS="--target_board unix/-m64" TESTS="*/*core*.exp" and it seems to work fine. Also did the same after installing the stop-gap hook on x86-64, to make sure that works. From 341d977d0d79d2b07e5a4d41e5be2f6977033fb3 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 21 Jan 2016 19:58:55 +1030 Subject: [PATCH] Use elfcore_write_linux_prstatus in gdb The gdb side. Nothing fancy here, though it'd be easier to fill in more fields now. Targets that are known to need a custom gdbarch_elfcore_write_linux_prstatus but don't have one yet can install a stop-gap hook implementation that still calls into elfcore_write_prstatus. It is currently installed for MIPS n32 and Sparc64 (though we're not writting any of pr_{u,s,cu,cs}time yet). Might be needed for x86-64 x32 too. Signed-off-by: Pedro Alves --- gdb/gdbarch.c | 32 ++++++++++++++++++++++++++++++++ gdb/gdbarch.h | 15 +++++++++++---- gdb/gdbarch.sh | 10 ++++++---- gdb/linux-tdep.c | 43 ++++++++++++++++++++++++++++++++++++++++--- gdb/linux-tdep.h | 8 ++++++++ gdb/mips-linux-tdep.c | 5 +++++ gdb/sparc64-linux-tdep.c | 5 +++++ 7 files changed, 107 insertions(+), 11 deletions(-) diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 4143744..fe0acbc 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -265,6 +265,7 @@ struct gdbarch gdbarch_iterate_over_regset_sections_ftype *iterate_over_regset_sections; gdbarch_make_corefile_notes_ftype *make_corefile_notes; gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo; + gdbarch_elfcore_write_linux_prstatus_ftype *elfcore_write_linux_prstatus; gdbarch_find_memory_regions_ftype *find_memory_regions; gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries; gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix; @@ -609,6 +610,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of iterate_over_regset_sections, has predicate. */ /* Skip verify of make_corefile_notes, has predicate. */ /* Skip verify of elfcore_write_linux_prpsinfo, has predicate. */ + /* Skip verify of elfcore_write_linux_prstatus, has predicate. */ /* Skip verify of find_memory_regions, has predicate. */ /* Skip verify of core_xfer_shared_libraries, has predicate. */ /* Skip verify of core_xfer_shared_libraries_aix, has predicate. */ @@ -931,6 +933,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: elfcore_write_linux_prpsinfo = <%s>\n", host_address_to_string (gdbarch->elfcore_write_linux_prpsinfo)); fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_elfcore_write_linux_prstatus_p() = %d\n", + gdbarch_elfcore_write_linux_prstatus_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: elfcore_write_linux_prstatus = <%s>\n", + host_address_to_string (gdbarch->elfcore_write_linux_prstatus)); + fprintf_unfiltered (file, "gdbarch_dump: fast_tracepoint_valid_at = <%s>\n", host_address_to_string (gdbarch->fast_tracepoint_valid_at)); fprintf_unfiltered (file, @@ -3466,6 +3474,30 @@ set_gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch, } int +gdbarch_elfcore_write_linux_prstatus_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->elfcore_write_linux_prstatus != NULL; +} + +char * +gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prstatus *info) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->elfcore_write_linux_prstatus != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_elfcore_write_linux_prstatus called\n"); + return gdbarch->elfcore_write_linux_prstatus (obfd, note_data, note_size, info); +} + +void +set_gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, + gdbarch_elfcore_write_linux_prstatus_ftype elfcore_write_linux_prstatus) +{ + gdbarch->elfcore_write_linux_prstatus = elfcore_write_linux_prstatus; +} + +int gdbarch_find_memory_regions_p (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 3fadcd1..5e00b32 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -61,6 +61,7 @@ struct stap_parse_info; struct parser_state; struct ravenscar_arch_ops; struct elf_internal_linux_prpsinfo; +struct elf_internal_linux_prstatus; struct mem_range; struct syscalls_info; struct thread_info; @@ -818,10 +819,10 @@ typedef char * (gdbarch_make_corefile_notes_ftype) (struct gdbarch *gdbarch, bfd extern char * gdbarch_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size); extern void set_gdbarch_make_corefile_notes (struct gdbarch *gdbarch, gdbarch_make_corefile_notes_ftype *make_corefile_notes); -/* The elfcore writer hook to use to write Linux prpsinfo notes to core - files. Most Linux architectures use the same prpsinfo32 or - prpsinfo64 layouts, and so won't need to provide this hook, as we - call the Linux generic routines in bfd to write prpsinfo notes by +/* The elfcore writer hooks to use to write Linux notes to core files. + Most Linux architectures use the same prpsinfo{32,64} and + prstatus{32,64} layouts, and so won't need to provide these hooks, + as we call the Linux generic routines in bfd to write notes by default. */ extern int gdbarch_elfcore_write_linux_prpsinfo_p (struct gdbarch *gdbarch); @@ -830,6 +831,12 @@ typedef char * (gdbarch_elfcore_write_linux_prpsinfo_ftype) (bfd *obfd, char *no extern char * gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prpsinfo *info); extern void set_gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch, gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo); +extern int gdbarch_elfcore_write_linux_prstatus_p (struct gdbarch *gdbarch); + +typedef char * (gdbarch_elfcore_write_linux_prstatus_ftype) (bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prstatus *info); +extern char * gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prstatus *info); +extern void set_gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, gdbarch_elfcore_write_linux_prstatus_ftype *elfcore_write_linux_prstatus); + /* Find core file memory regions */ extern int gdbarch_find_memory_regions_p (struct gdbarch *gdbarch); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 4ac6b90..71e3e8c 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -697,12 +697,13 @@ M:void:iterate_over_regset_sections:iterate_over_regset_sections_cb *cb, void *c # Create core file notes M:char *:make_corefile_notes:bfd *obfd, int *note_size:obfd, note_size -# The elfcore writer hook to use to write Linux prpsinfo notes to core -# files. Most Linux architectures use the same prpsinfo32 or -# prpsinfo64 layouts, and so won't need to provide this hook, as we -# call the Linux generic routines in bfd to write prpsinfo notes by +# The elfcore writer hooks to use to write Linux notes to core files. +# Most Linux architectures use the same prpsinfo{32,64} and +# prstatus{32,64} layouts, and so won't need to provide these hooks, +# as we call the Linux generic routines in bfd to write notes by # default. F:char *:elfcore_write_linux_prpsinfo:bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prpsinfo *info:obfd, note_data, note_size, info +F:char *:elfcore_write_linux_prstatus:bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prstatus *info:obfd, note_data, note_size, info # Find core file memory regions M:int:find_memory_regions:find_memory_region_ftype func, void *data:func, data @@ -1248,6 +1249,7 @@ struct stap_parse_info; struct parser_state; struct ravenscar_arch_ops; struct elf_internal_linux_prpsinfo; +struct elf_internal_linux_prstatus; struct mem_range; struct syscalls_info; struct thread_info; diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 29f5f3c..d432c47 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -1526,6 +1526,21 @@ linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, return note_data; } +/* See linux-tdep.h. + + FIXME: This should be reimplemented on the BFD side along the lines + of elfcore_write_linux_prstatus{32,64}, instead of relying on + elfcore_write_prstatus. */ + +char * +gdb_deprecated_elfcore_write_linux_prstatus + (bfd *obfd, char *note_data, int *note_size, + const struct elf_internal_linux_prstatus *info) +{ + return elfcore_write_prstatus (obfd, note_data, note_size, info->pr_pid, + info->pr_cursig, info->pr_reg); +} + /* Structure for passing information from linux_collect_thread_registers via an iterator to linux_collect_regset_section_cb. */ @@ -1564,9 +1579,31 @@ linux_collect_regset_section_cb (const char *sect_name, int size, /* PRSTATUS still needs to be treated specially. */ if (strcmp (sect_name, ".reg") == 0) - data->note_data = (char *) elfcore_write_prstatus - (data->obfd, data->note_data, data->note_size, data->lwp, - gdb_signal_to_host (data->stop_signal), buf); + { + struct elf_internal_linux_prstatus prstatus; + + memset (&prstatus, 0, sizeof (prstatus)); + prstatus.pr_reg = buf; + prstatus.pr_reg_size = size; + prstatus.pr_pid = data->lwp; + prstatus.pr_cursig = gdb_signal_to_host (data->stop_signal); + if (gdbarch_elfcore_write_linux_prstatus_p (data->gdbarch)) + data->note_data = gdbarch_elfcore_write_linux_prstatus (data->gdbarch, + data->obfd, + data->note_data, + data->note_size, + &prstatus); + else if (gdbarch_ptr_bit (data->gdbarch) == 64) + data->note_data = elfcore_write_linux_prstatus64 (data->obfd, + data->note_data, + data->note_size, + &prstatus); + else + data->note_data = elfcore_write_linux_prstatus32 (data->obfd, + data->note_data, + data->note_size, + &prstatus); + } else data->note_data = (char *) elfcore_write_register_note (data->obfd, data->note_data, data->note_size, diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h index 328c7f0..ae50b14 100644 --- a/gdb/linux-tdep.h +++ b/gdb/linux-tdep.h @@ -44,4 +44,12 @@ extern void linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch); extern int linux_is_uclinux (void); +/* Stop-gap gdbarch_elfcore_write_linux_prstatus implementation for + architectures whose prstatus{32,64} layout differs from the + standard one, and for which BFD doesn't provide a custom writer + yet. */ +extern char *gdb_deprecated_elfcore_write_linux_prstatus + (bfd *obfd, char *note_data, int *note_size, + const struct elf_internal_linux_prstatus *info); + #endif /* linux-tdep.h */ diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index 8dc0566..b2fcf23 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -1683,6 +1683,11 @@ mips_linux_init_abi (struct gdbarch_info info, µmips_linux_n32_rt_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe); set_xml_syscall_file_name (gdbarch, "syscalls/mips-n32-linux.xml"); + + /* N32 uses a different prstatus compared to most other Linux + archs. */ + set_gdbarch_elfcore_write_linux_prstatus + (gdbarch, gdb_deprecated_elfcore_write_linux_prstatus); break; case MIPS_ABI_N64: set_gdbarch_get_longjmp_target (gdbarch, diff --git a/gdb/sparc64-linux-tdep.c b/gdb/sparc64-linux-tdep.c index 1336d73..3a50900 100644 --- a/gdb/sparc64-linux-tdep.c +++ b/gdb/sparc64-linux-tdep.c @@ -307,6 +307,11 @@ sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->fpregset = &sparc64_linux_fpregset; tdep->sizeof_fpregset = 280; + /* Sparc64 uses a different prstatus compared to most other Linux + archs. */ + set_gdbarch_elfcore_write_linux_prstatus + (gdbarch, gdb_deprecated_elfcore_write_linux_prstatus); + tramp_frame_prepend_unwinder (gdbarch, &sparc64_linux_rt_sigframe); /* Hook in the DWARF CFI frame unwinder. */