This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: Use elfcore_write_linux_prstatus in gdb
- From: Pedro Alves <palves at redhat dot com>
- To: Alan Modra <amodra at gmail dot com>, binutils at sourceware dot org, gdb-patches at sourceware dot org
- Date: Thu, 21 Jan 2016 13:11:29 +0000
- Subject: Re: Use elfcore_write_linux_prstatus in gdb
- Authentication-results: sourceware.org; auth=none
- References: <20160121092855 dot GJ17028 at bubble dot grove dot modra dot org> <56A0CE51 dot 1090709 at redhat dot 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 <amodra@gmail.com>
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 <palves@redhat.com>
---
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. */
--
1.9.3