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/rfa] VFP/NEON register set support for ARM core files


Hello,

the ARM kernel currently does not save VFP/NEON registers into core files.
However, the patch set available here:
http://lists.infradead.org/pipermail/linux-arm-kernel/2011-April/047222.html
will add support by providing a new NT_ARM_VFP core file note type,
analogously to how vector registers are handled e.g. on ppc or i386.

This patch adds corresponding support to BFD and GDB to read such notes,
and write them as well (for GDB's generate-core-file command).

Tested on armv7l-unknown-linux-gnuabi on a Linux 2.6.38 kernel with the
above patch set applied.  Fixes one gcore.exp test case failure.

Are the BFD parts OK?

I'm planning on committing the GDB parts once kernel support has been
accepted and BFD parts are approved.


ChangeLog:

include/elf/
	* common.h (NT_ARM_VFP): Define.

bfd/
	* elf-bfd.h (elfcore_write_arm_vfp): Add prototype.
	* elf.c (elfcore_grok_arm_vfp): New function.
	(elfcore_grok_note): Call it to handle NT_ARM_VFP notes.
	(elfcore_write_arm_vfp): New function.
	(elfcore_write_register_note): Call it to handle .reg-arm-vfp.

gdb/
	* arm-linux-tdep.c: Include "auxv.h".
	(AT_HWCAP): Define.
	(ARM_LINUX_SIZEOF_VFP): Define.
	(arm_linux_supply_vfp): New function.
	(arm_linux_collect_vfp): Likewise.
	(arm_linux_regset_from_core_section): Handle .reg-arm-vfp sections.
	(arm_linux_fpa_regset_sections): New variable.
	(arm_linux_vfp_regset_sections): Likewise.
	(arm_linux_core_read_description): New function.
	(arm_linux_init_abi): Install arm_linux_core_read_description and
	arm_linux_fpa_regset_sections or arm_linux_vfp_regset_sections as
	appropriate for the architecture.
	* arm-tdep.h (struct gdbarch_tdep): Add member "vfpregset".
	(tdesc_arm_with_m): Declare.
	(tdesc_arm_with_iwmmxt): Likewise.
	(tdesc_arm_with_vfpv2): Likewise.
	(tdesc_arm_with_vfpv3): Likewise.
	(tdesc_arm_with_neon): Likewise.
	* arm-linux-nat.c: Move features/*.c includes ...
	* arm-tdep.c: ... here.
	* arm-linux-nat.c (arm_linux_read_description): Move initializing
	target description data structures ...
	* arm-tdep.c (_initialize_arm_tdep): ... here.
	* arm-linux-nat.c (HWCAP_VFP, HWCAP_IWMMXT, HWCAP_NEON, HWCAP_VFPv3,
	HWCAP_VFPv3D16): Move definitions ...
	* arm-linux-tdep.h: ... here.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.315
diff -u -p -r1.315 elf-bfd.h
--- bfd/elf-bfd.h	14 Mar 2011 15:54:57 -0000	1.315
+++ bfd/elf-bfd.h	1 Apr 2011 19:19:42 -0000
@@ -2210,6 +2210,8 @@ extern char *elfcore_write_s390_ctrs
   (bfd *, char *, int *, const void *, int);
 extern char *elfcore_write_s390_prefix
   (bfd *, char *, int *, const void *, int);
+extern char *elfcore_write_arm_vfp
+  (bfd *, char *, int *, const void *, int);
 extern char *elfcore_write_lwpstatus
   (bfd *, char *, int *, long, int, const void *);
 extern char *elfcore_write_register_note
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.530
diff -u -p -r1.530 elf.c
--- bfd/elf.c	14 Mar 2011 15:54:58 -0000	1.530
+++ bfd/elf.c	1 Apr 2011 19:19:43 -0000
@@ -7950,6 +7950,12 @@ elfcore_grok_s390_prefix (bfd *abfd, Elf
   return elfcore_make_note_pseudosection (abfd, ".reg-s390-prefix", note);
 }
 
+static bfd_boolean
+elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note);
+}
+
 #if defined (HAVE_PRPSINFO_T)
 typedef prpsinfo_t   elfcore_psinfo_t;
 #if defined (HAVE_PRPSINFO32_T)		/* Sparc64 cross Sparc32 */
@@ -8363,6 +8369,13 @@ elfcore_grok_note (bfd *abfd, Elf_Intern
       else
         return TRUE;
 
+    case NT_ARM_VFP:
+      if (note->namesz == 6
+	  && strcmp (note->namedata, "LINUX") == 0)
+	return elfcore_grok_arm_vfp (abfd, note);
+      else
+	return TRUE;
+
     case NT_PRPSINFO:
     case NT_PSINFO:
       if (bed->elf_backend_grok_psinfo)
@@ -9088,6 +9101,18 @@ elfcore_write_s390_prefix (bfd *abfd,
 }
 
 char *
+elfcore_write_arm_vfp (bfd *abfd,
+		       char *buf,
+		       int *bufsiz,
+		       const void *arm_vfp,
+		       int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+			     note_name, NT_ARM_VFP, arm_vfp, size);
+}
+
+char *
 elfcore_write_register_note (bfd *abfd,
 			     char *buf,
 			     int *bufsiz,
@@ -9117,6 +9142,8 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_s390_ctrs (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-s390-prefix") == 0)
     return elfcore_write_s390_prefix (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-arm-vfp") == 0)
+    return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
   return NULL;
 }
 
Index: gdb/arm-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-linux-nat.c,v
retrieving revision 1.47
diff -u -p -r1.47 arm-linux-nat.c
--- gdb/arm-linux-nat.c	21 Feb 2011 15:03:37 -0000	1.47
+++ gdb/arm-linux-nat.c	1 Apr 2011 19:19:43 -0000
@@ -44,11 +44,6 @@
 /* Defines ps_err_e, struct ps_prochandle.  */
 #include "gdb_proc_service.h"
 
-#include "features/arm-with-iwmmxt.c"
-#include "features/arm-with-vfpv2.c"
-#include "features/arm-with-vfpv3.c"
-#include "features/arm-with-neon.c"
-
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 22
 #endif
@@ -68,13 +63,6 @@
 #define PTRACE_SETHBPREGS 30
 #endif
 
-/* These are in <asm/elf.h> in current kernels.  */
-#define HWCAP_VFP       64
-#define HWCAP_IWMMXT    512
-#define HWCAP_NEON      4096
-#define HWCAP_VFPv3     8192
-#define HWCAP_VFPv3D16  16384
-
 /* A flag for whether the WMMX registers are available.  */
 static int arm_linux_has_wmmx_registers;
 
@@ -696,8 +684,6 @@ arm_linux_read_description (struct targe
   if (arm_hwcap & HWCAP_IWMMXT)
     {
       arm_linux_has_wmmx_registers = 1;
-      if (tdesc_arm_with_iwmmxt == NULL)
-	initialize_tdesc_arm_with_iwmmxt ();
       return tdesc_arm_with_iwmmxt;
     }
 
@@ -712,22 +698,16 @@ arm_linux_read_description (struct targe
       if (arm_hwcap & HWCAP_NEON)
 	{
 	  arm_linux_vfp_register_count = 32;
-	  if (tdesc_arm_with_neon == NULL)
-	    initialize_tdesc_arm_with_neon ();
 	  result = tdesc_arm_with_neon;
 	}
       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
 	{
 	  arm_linux_vfp_register_count = 32;
-	  if (tdesc_arm_with_vfpv3 == NULL)
-	    initialize_tdesc_arm_with_vfpv3 ();
 	  result = tdesc_arm_with_vfpv3;
 	}
       else
 	{
 	  arm_linux_vfp_register_count = 16;
-	  if (tdesc_arm_with_vfpv2 == NULL)
-	    initialize_tdesc_arm_with_vfpv2 ();
 	  result = tdesc_arm_with_vfpv2;
 	}
 
Index: gdb/arm-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-linux-tdep.c,v
retrieving revision 1.85
diff -u -p -r1.85 arm-linux-tdep.c
--- gdb/arm-linux-tdep.c	1 Apr 2011 11:57:02 -0000	1.85
+++ gdb/arm-linux-tdep.c	1 Apr 2011 19:19:43 -0000
@@ -33,6 +33,7 @@
 #include "trad-frame.h"
 #include "tramp-frame.h"
 #include "breakpoint.h"
+#include "auxv.h"
 
 #include "arm-tdep.h"
 #include "arm-linux-tdep.h"
@@ -45,6 +46,9 @@
 
 #include "gdb_string.h"
 
+/* This is defined in <elf.h> on ARM GNU/Linux systems.  */
+#define AT_HWCAP        16
+
 extern int arm_apcs_32;
 
 /* Under ARM GNU/Linux the traditional way of performing a breakpoint
@@ -638,6 +642,44 @@ arm_linux_collect_nwfpe (const struct re
 			  regs + INT_REGISTER_SIZE * ARM_FPS_REGNUM);
 }
 
+/* Support VFP register format.  */
+
+#define ARM_LINUX_SIZEOF_VFP (32 * 8 + 4)
+
+static void
+arm_linux_supply_vfp (const struct regset *regset,
+		      struct regcache *regcache,
+		      int regnum, const void *regs_buf, size_t len)
+{
+  const gdb_byte *regs = regs_buf;
+  int regno;
+
+  if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
+    regcache_raw_supply (regcache, ARM_FPSCR_REGNUM, regs + 32 * 8);
+
+  for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
+    if (regnum == -1 || regnum == regno)
+      regcache_raw_supply (regcache, regno,
+			   regs + (regno - ARM_D0_REGNUM) * 8);
+}
+
+static void
+arm_linux_collect_vfp (const struct regset *regset,
+			 const struct regcache *regcache,
+			 int regnum, void *regs_buf, size_t len)
+{
+  gdb_byte *regs = regs_buf;
+  int regno;
+
+  if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
+    regcache_raw_collect (regcache, ARM_FPSCR_REGNUM, regs + 32 * 8);
+
+  for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
+    if (regnum == -1 || regnum == regno)
+      regcache_raw_collect (regcache, regno,
+			    regs + (regno - ARM_D0_REGNUM) * 8);
+}
+
 /* Return the appropriate register set for the core section identified
    by SECT_NAME and SECT_SIZE.  */
 
@@ -665,9 +707,62 @@ arm_linux_regset_from_core_section (stru
       return tdep->fpregset;
     }
 
+  if (strcmp (sect_name, ".reg-arm-vfp") == 0
+      && sect_size == ARM_LINUX_SIZEOF_VFP)
+    {
+      if (tdep->vfpregset == NULL)
+        tdep->vfpregset = regset_alloc (gdbarch, arm_linux_supply_vfp,
+					arm_linux_collect_vfp);
+      return tdep->vfpregset;
+    }
+
+  return NULL;
+}
+
+/* Core file register set sections.  */
+
+static struct core_regset_section arm_linux_fpa_regset_sections[] =
+{
+  { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" },
+  { ".reg2", ARM_LINUX_SIZEOF_NWFPE, "FPA floating-point" },
+  { NULL, 0}
+};
+
+static struct core_regset_section arm_linux_vfp_regset_sections[] =
+{
+  { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" },
+  { ".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, "VFP floating-point" },
+  { NULL, 0}
+};
+
+/* Determine target description from core file.  */
+
+static const struct target_desc *
+arm_linux_core_read_description (struct gdbarch *gdbarch,
+                                 struct target_ops *target,
+                                 bfd *abfd)
+{
+  CORE_ADDR arm_hwcap = 0;
+
+  if (target_auxv_search (target, AT_HWCAP, &arm_hwcap) != 1)
+    return NULL;
+
+  if (arm_hwcap & HWCAP_VFP)
+    {
+      /* NEON implies VFPv3-D32 or no-VFP unit.  Say that we only support
+         Neon with VFPv3-D32.  */
+      if (arm_hwcap & HWCAP_NEON)
+	return tdesc_arm_with_neon;
+      else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
+	return tdesc_arm_with_vfpv3;
+      else
+	return tdesc_arm_with_vfpv2;
+    }
+
   return NULL;
 }
 
+
 /* Copy the value of next pc of sigreturn and rt_sigrturn into PC,
    return 1.  In addition, set IS_THUMB depending on whether we
    will return to ARM or Thumb code.  Return 0 if it is not a
@@ -1041,6 +1136,12 @@ arm_linux_init_abi (struct gdbarch_info 
   /* Core file support.  */
   set_gdbarch_regset_from_core_section (gdbarch,
 					arm_linux_regset_from_core_section);
+  set_gdbarch_core_read_description (gdbarch, arm_linux_core_read_description);
+
+  if (tdep->have_vfp_registers)
+    set_gdbarch_core_regset_sections (gdbarch, arm_linux_vfp_regset_sections);
+  else if (tdep->have_fpa_registers)
+    set_gdbarch_core_regset_sections (gdbarch, arm_linux_fpa_regset_sections);
 
   set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 
Index: gdb/arm-linux-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/arm-linux-tdep.h,v
retrieving revision 1.9
diff -u -p -r1.9 arm-linux-tdep.h
--- gdb/arm-linux-tdep.h	1 Jan 2011 15:32:57 -0000	1.9
+++ gdb/arm-linux-tdep.h	1 Apr 2011 19:19:43 -0000
@@ -59,3 +59,12 @@ void arm_linux_supply_nwfpe (const struc
 void arm_linux_collect_nwfpe (const struct regset *regset,
 			      const struct regcache *regcache,
 			      int regnum, void *regs_buf, size_t len);
+
+/* ARM GNU/Linux HWCAP values.  These are in defined in
+   <asm/elf.h> in current kernels.  */
+#define HWCAP_VFP       64
+#define HWCAP_IWMMXT    512
+#define HWCAP_NEON      4096
+#define HWCAP_VFPv3     8192
+#define HWCAP_VFPv3D16  16384
+
Index: gdb/arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.340
diff -u -p -r1.340 arm-tdep.c
--- gdb/arm-tdep.c	1 Apr 2011 11:57:02 -0000	1.340
+++ gdb/arm-tdep.c	1 Apr 2011 19:19:45 -0000
@@ -56,6 +56,10 @@
 #include "vec.h"
 
 #include "features/arm-with-m.c"
+#include "features/arm-with-iwmmxt.c"
+#include "features/arm-with-vfpv2.c"
+#include "features/arm-with-vfpv3.c"
+#include "features/arm-with-neon.c"
 
 static int arm_debug;
 
@@ -8707,6 +8711,10 @@ _initialize_arm_tdep (void)
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_arm_with_m ();
+  initialize_tdesc_arm_with_iwmmxt ();
+  initialize_tdesc_arm_with_vfpv2 ();
+  initialize_tdesc_arm_with_vfpv3 ();
+  initialize_tdesc_arm_with_neon ();
 
   /* Get the number of possible sets of register names defined in opcodes.  */
   num_disassembly_options = get_arm_regname_num_options ();
Index: gdb/arm-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.h,v
retrieving revision 1.50
diff -u -p -r1.50 arm-tdep.h
--- gdb/arm-tdep.h	1 Apr 2011 11:57:03 -0000	1.50
+++ gdb/arm-tdep.h	1 Apr 2011 19:19:45 -0000
@@ -190,7 +190,7 @@ struct gdbarch_tdep
   enum struct_return struct_return;
 
   /* Cached core file helpers.  */
-  struct regset *gregset, *fpregset;
+  struct regset *gregset, *fpregset, *vfpregset;
 
   /* ISA-specific data types.  */
   struct type *arm_ext_type;
@@ -339,4 +339,11 @@ extern const struct regset *
   armbsd_regset_from_core_section (struct gdbarch *gdbarch,
 				   const char *sect_name, size_t sect_size);
 
+/* Target descriptions.  */
+extern struct target_desc *tdesc_arm_with_m;
+extern struct target_desc *tdesc_arm_with_iwmmxt;
+extern struct target_desc *tdesc_arm_with_vfpv2;
+extern struct target_desc *tdesc_arm_with_vfpv3;
+extern struct target_desc *tdesc_arm_with_neon;
+
 #endif /* arm-tdep.h */
Index: include/elf/common.h
===================================================================
RCS file: /cvs/src/src/include/elf/common.h,v
retrieving revision 1.126
diff -u -p -r1.126 common.h
--- include/elf/common.h	10 Mar 2011 10:23:37 -0000	1.126
+++ include/elf/common.h	1 Apr 2011 19:19:46 -0000
@@ -538,6 +538,8 @@
 					/*   note name must be "LINUX".  */
 #define NT_S390_PREFIX	0x305		/* S390 prefix register */
 					/*   note name must be "LINUX".  */
+#define NT_ARM_VFP	0x400		/* ARM VFP registers */
+					/*   note name must be "LINUX".  */
 
 /* Note segments for core files on dir-style procfs systems.  */
 
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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