]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Use elfcore_write_linux_prstatus in gdb
authorAlan Modra <amodra@gmail.com>
Thu, 21 Jan 2016 09:28:55 +0000 (19:58 +1030)
committerPedro Alves <palves@redhat.com>
Thu, 21 Jan 2016 11:45:38 +0000 (11:45 +0000)
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), and
x86-64 x32 too.

Signed-off-by: Pedro Alves <palves@redhat.com>
gdb/amd64-linux-tdep.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/linux-tdep.c
gdb/linux-tdep.h
gdb/mips-linux-tdep.c
gdb/sparc64-linux-tdep.c

index b948ea77fad9f00226b97fdb279e98b144f3d425..c545cd02a5605b2b02bcab9a1881534d41a8f6a1 100644 (file)
@@ -2073,6 +2073,10 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
   tdep->sizeof_gregset = 27 * 8;
 
+  /* x32's layout is not compatible with the 32-bit layout.  */
+  set_gdbarch_elfcore_write_linux_prstatus
+    (gdbarch, gdb_deprecated_elfcore_write_linux_prstatus);
+
   amd64_x32_init_abi (info, gdbarch);
 
   /* Reserve a number for orig_rax.  */
index 41437447af7375d4dfa75b0534cfd3b74a05f71c..fe0acbc8640518795f8a6ac15fad3b8f8f36ac14 100644 (file)
@@ -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.  */
@@ -930,6 +932,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (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));
@@ -3465,6 +3473,30 @@ set_gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch,
   gdbarch->elfcore_write_linux_prpsinfo = elfcore_write_linux_prpsinfo;
 }
 
+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)
 {
index 3fadcd14ba01bbeada1b086a1d37247c6a2cdc1b..5e00b32c9f4b23b091f37845507648b1eabb428a 100644 (file)
@@ -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);
index 4ac6b90fd128214c42c0b0d24f1ef2f4b66d3dfc..71e3e8c580f176c1cab402952d2c54ac894e107d 100755 (executable)
@@ -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;
index 29f5f3c003ee024ac441b0e36ac15e948e0133e9..d432c471438580f5e6197783078976464ce74f56 100644 (file)
@@ -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,
index 328c7f09b04b54d4bff858909a4aa24b0469d1c2..ae50b14c35877408e7e79b1ee50fc61737bb23cd 100644 (file)
@@ -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 */
index 8dc0566dba5b72f1be701de62c708820293db311..b2fcf23597180826271dfe33d85675ce5243a354 100644 (file)
@@ -1683,6 +1683,11 @@ mips_linux_init_abi (struct gdbarch_info info,
                                      &micromips_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,
index 1336d73b3ac2c4bcadcc0f0247596a23fc4d2f8f..3a50900ecd03cf9a598e24452e78cd8065ce48cf 100644 (file)
@@ -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.  */