[2/7] Fixes for aarch64-linux gdb core file support

Message ID 1401898871-2270-3-git-send-email-omair.javaid@linaro.org
State New
Headers show

Commit Message

Omair Javaid June 4, 2014, 4:21 p.m.
This patch fixes aarch64 linux core file support by adding/updating
aarch64-linux supply/collect methods for aarch64 register set.

gdb:

2014-06-04  Omair Javaid  <omair.javaid@linaro.org>

	* aarch64-linux-tdep.c (aarch64_linux_supply_gregset): Updated.
	(aarch64_linux_supply_fpregset): Updated.
	(supply_gregset_from_core): Removed.
	(aarch64_linux_collect_gregset): New function.
	(supply_fpregset_from_core): Removed.
	(aarch64_linux_collect_fpregset): New function.
	(struct regset aarch64_linux_gregset): Updated.
	(struct core_regset_section aarch64_linux_regset_sections[]): Declared.
	* aarch64-linux-tdep.h (aarch64_linux_supply_gregset): Updated extern.
	(aarch64_linux_supply_fpregset): New extern declaration.
	(aarch64_linux_collect_gregset): New extern declaration.
	(aarch64_linux_collect_fpregset): New extern declaration.
	* aarch64-linux-nat.c (aarch64_linux_supply_gregset): Updated.
	(aarch64_linux_supply_fpregset): Updated.

---
 gdb/aarch64-linux-nat.c  |  4 +--
 gdb/aarch64-linux-tdep.c | 91 +++++++++++++++++++++++++++++++++---------------
 gdb/aarch64-linux-tdep.h | 22 +++++++++---
 3 files changed, 83 insertions(+), 34 deletions(-)

Comments

Andreas Arnez June 4, 2014, 5:11 p.m. | #1
On Wed, Jun 04 2014, Omair Javaid wrote:

> This patch fixes aarch64 linux core file support by adding/updating
> aarch64-linux supply/collect methods for aarch64 register set.

Have you looked at that patch?

  https://sourceware.org/ml/gdb-patches/2014-05/msg00637.html

Apart from 'core_regset_sections', I believe it provides the same
functionality as this patch, right?
Will Newton June 5, 2014, 9:07 a.m. | #2
On 4 June 2014 17:21, Omair Javaid <omair.javaid@linaro.org> wrote:
> This patch fixes aarch64 linux core file support by adding/updating
> aarch64-linux supply/collect methods for aarch64 register set.
>
> gdb:
>
> 2014-06-04  Omair Javaid  <omair.javaid@linaro.org>
>
>         * aarch64-linux-tdep.c (aarch64_linux_supply_gregset): Updated.
>         (aarch64_linux_supply_fpregset): Updated.
>         (supply_gregset_from_core): Removed.
>         (aarch64_linux_collect_gregset): New function.
>         (supply_fpregset_from_core): Removed.
>         (aarch64_linux_collect_fpregset): New function.
>         (struct regset aarch64_linux_gregset): Updated.
>         (struct core_regset_section aarch64_linux_regset_sections[]): Declared.
>         * aarch64-linux-tdep.h (aarch64_linux_supply_gregset): Updated extern.
>         (aarch64_linux_supply_fpregset): New extern declaration.
>         (aarch64_linux_collect_gregset): New extern declaration.
>         (aarch64_linux_collect_fpregset): New extern declaration.
>         * aarch64-linux-nat.c (aarch64_linux_supply_gregset): Updated.
>         (aarch64_linux_supply_fpregset): Updated.
>
> ---
>  gdb/aarch64-linux-nat.c  |  4 +--
>  gdb/aarch64-linux-tdep.c | 91 +++++++++++++++++++++++++++++++++---------------
>  gdb/aarch64-linux-tdep.h | 22 +++++++++---
>  3 files changed, 83 insertions(+), 34 deletions(-)
>
> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index 877e702..f631d9e 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -632,7 +632,7 @@ fill_gregset (const struct regcache *regcache,
>  void
>  supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
>  {
> -  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) gregsetp);
> +  aarch64_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0);
>  }
>
>  /* Fill register REGNO (if it is a floating-point register) in
> @@ -667,7 +667,7 @@ fill_fpregset (const struct regcache *regcache,
>  void
>  supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
>  {
> -  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) fpregsetp);
> +  aarch64_linux_supply_fpregset (NULL, regcache, -1, fpregsetp, 0);
>  }
>
>  /* Called when resuming a thread.
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index 30ed73f..b285818 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -191,70 +191,93 @@ static const struct tramp_frame aarch64_linux_rt_sigframe =
>  };
>
>  /* Fill GDB's register array with the general-purpose register values
> -   in the buffer pointed by GREGS_BUF.  */
> +   in the buffer pointed by gregs_buf.  */

I believe upper casing parameter names in comments is actually correct
per the GNU coding style.
>
>  void
> -aarch64_linux_supply_gregset (struct regcache *regcache,
> -                             const gdb_byte *gregs_buf)
> +aarch64_linux_supply_gregset (const struct regset *regset,
> +                              struct regcache *regcache, int regnum,
> +                              const void *gregs_buf, size_t len)
>  {
> +  gdb_byte *gregs_bufp = (gdb_byte *) gregs_buf;
>    int regno;
>
>    for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
>      regcache_raw_supply (regcache, regno,
> -                        gregs_buf + X_REGISTER_SIZE
> +            gregs_bufp + X_REGISTER_SIZE
>                          * (regno - AARCH64_X0_REGNUM));
>  }
>
> -/* The "supply_regset" function for the general-purpose register set.  */
> +/* Fill registers in *gregs_buf with the values in GDB's register cache.  */
>
> -static void
> -supply_gregset_from_core (const struct regset *regset,
> -                         struct regcache *regcache,
> -                         int regnum, const void *regbuf, size_t len)
> +void
> +aarch64_linux_collect_gregset (const struct regset *regset,
> +                              const struct regcache *regcache, int regnum,
> +                              void *gregs_buf, size_t len)
>  {
> -  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
> +  gdb_byte *gregs_bufp = (gdb_byte *) gregs_buf;
> +  int regno;
> +
> +  for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      regcache_raw_collect (regcache, regno, gregs_bufp + X_REGISTER_SIZE *
> +                            (regno - AARCH64_X0_REGNUM));
>  }
>
>  /* Fill GDB's register array with the floating-point register values
> -   in the buffer pointed by FPREGS_BUF.  */
> +   in the buffer pointed by fpregs_buf.  */
>
>  void
> -aarch64_linux_supply_fpregset (struct regcache *regcache,
> -                              const gdb_byte *fpregs_buf)
> +aarch64_linux_supply_fpregset (const struct regset *regset,
> +                               struct regcache *regcache, int regnum,
> +                               const void *fpregs_buf, size_t len)
>  {
> +  gdb_byte *fpregs_bufp = (gdb_byte *) fpregs_buf;
>    int regno;
>
>    for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
> -    regcache_raw_supply (regcache, regno,
> -                        fpregs_buf + V_REGISTER_SIZE
> -                        * (regno - AARCH64_V0_REGNUM));
> +    regcache_raw_supply (regcache, regno, fpregs_bufp + V_REGISTER_SIZE *
> +                         (regno - AARCH64_V0_REGNUM));
>
> -  regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
> -                      fpregs_buf + V_REGISTER_SIZE * 32);
> -  regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
> -                      fpregs_buf + V_REGISTER_SIZE * 32 + 4);
> +  regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM, fpregs_bufp +
> +                       V_REGISTER_SIZE * 32);
> +  regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM, fpregs_bufp +
> +                       V_REGISTER_SIZE * 32 + 4);
>  }
>
> -/* The "supply_regset" function for the floating-point register set.  */
> +/* Fill registers in *fpregs_buf with the values in GDB's register cache.  */
>
> -static void
> -supply_fpregset_from_core (const struct regset *regset,
> -                          struct regcache *regcache,
> -                          int regnum, const void *regbuf, size_t len)
> +void
> +aarch64_linux_collect_fpregset (const struct regset *regset,
> +                                const struct regcache *regcache, int regnum,
> +                                void *fpregs_buf, size_t len)
>  {
> -  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
> +  gdb_byte *fpregs_bufp = (gdb_byte *) fpregs_buf;
> +  int regno;
> +
> +  for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      regcache_raw_collect (regcache, regno, fpregs_bufp + V_REGISTER_SIZE *
> +                            (regno - AARCH64_V0_REGNUM));
> +
> +  if (regnum == -1 || regnum == AARCH64_FPSR_REGNUM)
> +    regcache_raw_collect (regcache, AARCH64_FPSR_REGNUM, fpregs_bufp +
> +                          V_REGISTER_SIZE * 32);
> +
> +  if (regnum == -1 || regnum == AARCH64_FPCR_REGNUM)
> +    regcache_raw_collect (regcache, AARCH64_FPCR_REGNUM, fpregs_bufp +
> +                          V_REGISTER_SIZE * 32 + 4);
>  }
>
>  /* Register set definitions. */
>
>  static const struct regset aarch64_linux_gregset =
>    {
> -    NULL, supply_gregset_from_core, NULL
> +    NULL, aarch64_linux_supply_gregset, aarch64_linux_collect_gregset
>    };
>
>  static const struct regset aarch64_linux_fpregset =
>    {
> -    NULL, supply_fpregset_from_core, NULL
> +    NULL, aarch64_linux_supply_fpregset, aarch64_linux_collect_fpregset
>    };
>
>  /* Implement the "regset_from_core_section" gdbarch method.  */
> @@ -275,6 +298,15 @@ aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch,
>    return NULL;
>  }
>
> +/* Core file register set sections.  */
> +
> +static struct core_regset_section aarch64_linux_regset_sections[] =
> +{
> +  { ".reg", AARCH64_LINUX_SIZEOF_GREGSET, "general-purpose" },
> +  { ".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, "floating-point" },
> +  { NULL, 0}
> +};
> +
>  /* Implementation of `gdbarch_stap_is_single_operand', as defined in
>     gdbarch.h.  */
>
> @@ -420,6 +452,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>    /* Enable longjmp.  */
>    tdep->jb_pc = 11;
>
> +  /* Install supported register note sections.  */
> +  set_gdbarch_core_regset_sections (gdbarch, aarch64_linux_regset_sections);
> +
>    set_gdbarch_regset_from_core_section (gdbarch,
>                                         aarch64_linux_regset_from_core_section);
>
> diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
> index 48c7092..e3d7ed7 100644
> --- a/gdb/aarch64-linux-tdep.h
> +++ b/gdb/aarch64-linux-tdep.h
> @@ -20,7 +20,21 @@
>
>  struct regcache;
>
> -extern void aarch64_linux_supply_gregset (struct regcache *regcache,
> -                                         const gdb_byte *gregs_buf);
> -extern void aarch64_linux_supply_fpregset (struct regcache *regcache,
> -                                          const gdb_byte *fpregs_buf);
> +/* Function prototypes for function transferring the general-purpose
> +   registers between GDB, inferiors and core files.  */
> +
> +/* Fill GDB's register array with the general-purpose register values
> +   in *gregs_buf.  */
> +
> +extern void aarch64_linux_supply_gregset (const struct regset *regset,
> +                                  struct regcache *regcache, int regnum,
> +                                  const void *gregs_buf, size_t len);
> +extern void aarch64_linux_collect_gregset (const struct regset *regset,
> +                                   const struct regcache *regcache,
> +                                   int regnum, void *gregs_buf, size_t len);
> +extern void aarch64_linux_supply_fpregset (const struct regset *regset,
> +                                   struct regcache *regcache, int regnum,
> +                                   const void *fpregs_buf, size_t len);
> +extern void aarch64_linux_collect_fpregset (const struct regset *regset,
> +                                    const struct regcache *regcache,
> +                                    int regnum, void *fpregs_buf, size_t len);
> --
> 1.9.1
>
Omair Javaid June 5, 2014, 5:08 p.m. | #3
On 4 June 2014 22:11, Andreas Arnez <arnez@linux.vnet.ibm.com> wrote:
> On Wed, Jun 04 2014, Omair Javaid wrote:
>
>> This patch fixes aarch64 linux core file support by adding/updating
>> aarch64-linux supply/collect methods for aarch64 register set.
>
> Have you looked at that patch?
>
>   https://sourceware.org/ml/gdb-patches/2014-05/msg00637.html
>
> Apart from 'core_regset_sections', I believe it provides the same
> functionality as this patch, right?
>
Agreed!. I wrote this patch when I started work on aarch64 record
replay in april and corefile support wasnt working. I guess once
regset rework patches gets pushed then we may have to rework this
patch to extract corefile related changes only.

Thanks Andreas for bringing this up.

Patch

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 877e702..f631d9e 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -632,7 +632,7 @@  fill_gregset (const struct regcache *regcache,
 void
 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
 {
-  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) gregsetp);
+  aarch64_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0);
 }
 
 /* Fill register REGNO (if it is a floating-point register) in
@@ -667,7 +667,7 @@  fill_fpregset (const struct regcache *regcache,
 void
 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
 {
-  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) fpregsetp);
+  aarch64_linux_supply_fpregset (NULL, regcache, -1, fpregsetp, 0);
 }
 
 /* Called when resuming a thread.
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 30ed73f..b285818 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -191,70 +191,93 @@  static const struct tramp_frame aarch64_linux_rt_sigframe =
 };
 
 /* Fill GDB's register array with the general-purpose register values
-   in the buffer pointed by GREGS_BUF.  */
+   in the buffer pointed by gregs_buf.  */
 
 void
-aarch64_linux_supply_gregset (struct regcache *regcache,
-			      const gdb_byte *gregs_buf)
+aarch64_linux_supply_gregset (const struct regset *regset,
+                              struct regcache *regcache, int regnum,
+                              const void *gregs_buf, size_t len)
 {
+  gdb_byte *gregs_bufp = (gdb_byte *) gregs_buf;
   int regno;
 
   for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
     regcache_raw_supply (regcache, regno,
-			 gregs_buf + X_REGISTER_SIZE
+            gregs_bufp + X_REGISTER_SIZE
 			 * (regno - AARCH64_X0_REGNUM));
 }
 
-/* The "supply_regset" function for the general-purpose register set.  */
+/* Fill registers in *gregs_buf with the values in GDB's register cache.  */
 
-static void
-supply_gregset_from_core (const struct regset *regset,
-			  struct regcache *regcache,
-			  int regnum, const void *regbuf, size_t len)
+void
+aarch64_linux_collect_gregset (const struct regset *regset,
+                              const struct regcache *regcache, int regnum,
+                              void *gregs_buf, size_t len)
 {
-  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
+  gdb_byte *gregs_bufp = (gdb_byte *) gregs_buf;
+  int regno;
+
+  for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
+    if (regnum == -1 || regnum == regno)
+      regcache_raw_collect (regcache, regno, gregs_bufp + X_REGISTER_SIZE *
+                            (regno - AARCH64_X0_REGNUM));
 }
 
 /* Fill GDB's register array with the floating-point register values
-   in the buffer pointed by FPREGS_BUF.  */
+   in the buffer pointed by fpregs_buf.  */
 
 void
-aarch64_linux_supply_fpregset (struct regcache *regcache,
-			       const gdb_byte *fpregs_buf)
+aarch64_linux_supply_fpregset (const struct regset *regset,
+                               struct regcache *regcache, int regnum,
+                               const void *fpregs_buf, size_t len)
 {
+  gdb_byte *fpregs_bufp = (gdb_byte *) fpregs_buf;
   int regno;
 
   for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
-    regcache_raw_supply (regcache, regno,
-			 fpregs_buf + V_REGISTER_SIZE
-			 * (regno - AARCH64_V0_REGNUM));
+    regcache_raw_supply (regcache, regno, fpregs_bufp + V_REGISTER_SIZE *
+                         (regno - AARCH64_V0_REGNUM));
 
-  regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
-		       fpregs_buf + V_REGISTER_SIZE * 32);
-  regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
-		       fpregs_buf + V_REGISTER_SIZE * 32 + 4);
+  regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM, fpregs_bufp +
+                       V_REGISTER_SIZE * 32);
+  regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM, fpregs_bufp +
+                       V_REGISTER_SIZE * 32 + 4);
 }
 
-/* The "supply_regset" function for the floating-point register set.  */
+/* Fill registers in *fpregs_buf with the values in GDB's register cache.  */
 
-static void
-supply_fpregset_from_core (const struct regset *regset,
-			   struct regcache *regcache,
-			   int regnum, const void *regbuf, size_t len)
+void
+aarch64_linux_collect_fpregset (const struct regset *regset,
+                                const struct regcache *regcache, int regnum,
+                                void *fpregs_buf, size_t len)
 {
-  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
+  gdb_byte *fpregs_bufp = (gdb_byte *) fpregs_buf;
+  int regno;
+
+  for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
+    if (regnum == -1 || regnum == regno)
+      regcache_raw_collect (regcache, regno, fpregs_bufp + V_REGISTER_SIZE *
+                            (regno - AARCH64_V0_REGNUM));
+
+  if (regnum == -1 || regnum == AARCH64_FPSR_REGNUM)
+    regcache_raw_collect (regcache, AARCH64_FPSR_REGNUM, fpregs_bufp +
+                          V_REGISTER_SIZE * 32);
+
+  if (regnum == -1 || regnum == AARCH64_FPCR_REGNUM)
+    regcache_raw_collect (regcache, AARCH64_FPCR_REGNUM, fpregs_bufp +
+                          V_REGISTER_SIZE * 32 + 4);
 }
 
 /* Register set definitions. */
 
 static const struct regset aarch64_linux_gregset =
   {
-    NULL, supply_gregset_from_core, NULL
+    NULL, aarch64_linux_supply_gregset, aarch64_linux_collect_gregset
   };
 
 static const struct regset aarch64_linux_fpregset =
   {
-    NULL, supply_fpregset_from_core, NULL
+    NULL, aarch64_linux_supply_fpregset, aarch64_linux_collect_fpregset
   };
 
 /* Implement the "regset_from_core_section" gdbarch method.  */
@@ -275,6 +298,15 @@  aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch,
   return NULL;
 }
 
+/* Core file register set sections.  */
+
+static struct core_regset_section aarch64_linux_regset_sections[] =
+{
+  { ".reg", AARCH64_LINUX_SIZEOF_GREGSET, "general-purpose" },
+  { ".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, "floating-point" },
+  { NULL, 0}
+};
+
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
    gdbarch.h.  */
 
@@ -420,6 +452,9 @@  aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Enable longjmp.  */
   tdep->jb_pc = 11;
 
+  /* Install supported register note sections.  */
+  set_gdbarch_core_regset_sections (gdbarch, aarch64_linux_regset_sections);
+
   set_gdbarch_regset_from_core_section (gdbarch,
 					aarch64_linux_regset_from_core_section);
 
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index 48c7092..e3d7ed7 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -20,7 +20,21 @@ 
 
 struct regcache;
 
-extern void aarch64_linux_supply_gregset (struct regcache *regcache,
-					  const gdb_byte *gregs_buf);
-extern void aarch64_linux_supply_fpregset (struct regcache *regcache,
-					   const gdb_byte *fpregs_buf);
+/* Function prototypes for function transferring the general-purpose
+   registers between GDB, inferiors and core files.  */
+
+/* Fill GDB's register array with the general-purpose register values
+   in *gregs_buf.  */
+
+extern void aarch64_linux_supply_gregset (const struct regset *regset,
+                                  struct regcache *regcache, int regnum,
+                                  const void *gregs_buf, size_t len);
+extern void aarch64_linux_collect_gregset (const struct regset *regset,
+                                   const struct regcache *regcache,
+                                   int regnum, void *gregs_buf, size_t len);
+extern void aarch64_linux_supply_fpregset (const struct regset *regset,
+                                   struct regcache *regcache, int regnum,
+                                   const void *fpregs_buf, size_t len);
+extern void aarch64_linux_collect_fpregset (const struct regset *regset,
+                                    const struct regcache *regcache,
+                                    int regnum, void *fpregs_buf, size_t len);