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]

[AArch64][6/6] Core file support for "pauth" feature


This patch add coredump support for the new "pauth" feature.  A few necessary
low level methods and descriptions are added accordingly.

2017-08-09  Jiong Wang  <jiong.wang@arm.com>
bfd/
	* elf-bfd.h (elfcore_write_aarch_pauth): New function declaration.
	* elf.c (elfcore_grok_aarch_pauth): New function.
	(elfcore_grok_note): Handle NT_ARM_PAUTH.
	(elfcore_write_aarch_pauth): New function.
	(elfcore_write_register_note): Handle ".reg-aarch-pauth" section.

gdb/
	* aarch64-linux-tdep.c: #include "auxv.h".
	#include "elf/common.h"
	(aarch64_collect_pauth_regset): New function.
	(aarch64_supply_pauth_regset): New function.
	(aarch64_linux_pauthregset): New regset.
	(aarch64_linux_iterate_over_regset_sections): Support
	".reg-aarch64-pauth" section.
	(aarch64_linux_core_read_description): New function.
	(aarch64_linux_init_abi): Register core_read_description method.
	* aarch64-linux-tdep.h (AARCH64_LINUX_SIZEOF_PAUTH): New define.
	(HWCAP_APIA): New define.
	(aarch64_linux_pauthregset): New variable declaration.

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 92a8e02..d9b61ba 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2539,6 +2539,8 @@ extern char *elfcore_write_s390_gs_bc
   (bfd *, char *, int *, const void *, int);
 extern char *elfcore_write_arm_vfp
   (bfd *, char *, int *, const void *, int);
+extern char *elfcore_write_aarch_pauth
+  (bfd *, char *, int *, const void *, int);
 extern char *elfcore_write_aarch_tls
   (bfd *, char *, int *, const void *, int);
 extern char *elfcore_write_aarch_hw_break
diff --git a/bfd/elf.c b/bfd/elf.c
index b99e297..30772cf 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -9207,6 +9207,12 @@ elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
 }
 
 static bfd_boolean
+elfcore_grok_aarch_pauth (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-aarch-pauth", note);
+}
+
+static bfd_boolean
 elfcore_grok_aarch_tls (bfd *abfd, Elf_Internal_Note *note)
 {
   return elfcore_make_note_pseudosection (abfd, ".reg-aarch-tls", note);
@@ -9699,6 +9705,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       else
 	return TRUE;
 
+    case NT_ARM_PAC_MASK:
+      if (note->namesz == 6
+	  && strcmp (note->namedata, "LINUX") == 0)
+	return elfcore_grok_aarch_pauth (abfd, note);
+      else
+	return TRUE;
+
     case NT_ARM_TLS:
       if (note->namesz == 6
 	  && strcmp (note->namedata, "LINUX") == 0)
@@ -10794,6 +10807,18 @@ elfcore_write_arm_vfp (bfd *abfd,
 }
 
 char *
+elfcore_write_aarch_pauth (bfd *abfd,
+			   char *buf,
+			   int *bufsiz,
+			   const void *aarch_pauth,
+			   int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+			     note_name, NT_ARM_PAC_MASK, aarch_pauth, size);
+}
+
+char *
 elfcore_write_aarch_tls (bfd *abfd,
 		       char *buf,
 		       int *bufsiz,
@@ -10875,6 +10900,8 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_s390_gs_bc (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-arm-vfp") == 0)
     return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-aarch-pauth") == 0)
+    return elfcore_write_aarch_pauth (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-aarch-tls") == 0)
     return elfcore_write_aarch_tls (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-aarch-hw-break") == 0)
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index ec6125a..56ca1ce 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -45,6 +45,8 @@
 
 #include "record-full.h"
 #include "linux-record.h"
+#include "auxv.h"
+#include "elf/common.h"
 
 /* Signal frame handling.
 
@@ -217,6 +219,65 @@ const struct regset aarch64_linux_fpregset =
     regcache_supply_regset, regcache_collect_regset
   };
 
+/* Collect register REGNUM from REGCACHE and store its contents in the buffer
+   PAUTH_REGS which is of SIZE.  REGSET is not used as for PAUTH regset the
+   register number inside GDB is dynamicly allocated so we are not using
+   register map in REGSET.  */
+
+static void
+aarch64_collect_pauth_regset (const struct regset *regset,
+			      const struct regcache *regcache,
+			      int regnum, void *pauth_regs, size_t size)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  gdb_assert (size == AARCH64_LINUX_SIZEOF_PAUTH);
+  gdb_assert (regnum == -1);
+  gdb_assert (aarch64_tdep_has_pauth_p (tdep));
+
+  int dmask = tdep->regnum.pauth_reg_base;
+  int cmask = tdep->regnum.pauth_reg_base + 1;
+
+  memset (pauth_regs, 0, AARCH64_LINUX_SIZEOF_PAUTH);
+  regcache_raw_collect (regcache, dmask, pauth_regs);
+  regcache_raw_collect (regcache, cmask,
+			(gdb_byte *) pauth_regs + X_REGISTER_SIZE);
+
+  return;
+}
+
+/* Supply register REGNUM from the buffer PAUTH_REGS which is of SIZE to
+   REGCACHE.  REGSET is not used as for PAUTH regset the register number inside
+   GDB is dynamicly allocated so we are not using register map in REGSET.  */
+
+static void
+aarch64_supply_pauth_regset (const struct regset *regset,
+			     struct regcache *regcache,
+			     int regnum, const void *pauth_regs, size_t size)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  gdb_assert (size == AARCH64_LINUX_SIZEOF_PAUTH);
+  gdb_assert (regnum == -1);
+  gdb_assert (aarch64_tdep_has_pauth_p (tdep));
+
+  int dmask = tdep->regnum.pauth_reg_base;
+  int cmask = tdep->regnum.pauth_reg_base + 1;
+
+  regcache_raw_supply (regcache, dmask, pauth_regs);
+  regcache_raw_supply (regcache, cmask,
+		       (gdb_byte *) pauth_regs + X_REGISTER_SIZE);
+
+  return;
+}
+
+const struct regset aarch64_linux_pauthregset =
+  {
+    NULL, aarch64_supply_pauth_regset, aarch64_collect_pauth_regset
+  };
+
 /* Implement the "regset_from_core_section" gdbarch method.  */
 
 static void
@@ -225,10 +286,16 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					    void *cb_data,
 					    const struct regcache *regcache)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, &aarch64_linux_gregset,
       NULL, cb_data);
   cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, &aarch64_linux_fpregset,
       NULL, cb_data);
+
+  if (aarch64_tdep_has_pauth_p (tdep))
+    cb (".reg-aarch-pauth", AARCH64_LINUX_SIZEOF_PAUTH,
+	&aarch64_linux_pauthregset, NULL, cb_data);
 }
 
 /* Determine target description from core file.  */
@@ -242,7 +309,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
   if (target_auxv_search (target, AT_HWCAP, &aarch64_hwcap) != 1)
     return NULL;
 
-  return tdesc_aarch64;
+  return aarch64_hwcap & HWCAP_APIA ? tdesc_aarch64_pauth : tdesc_aarch64;
 }
 
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index d0f9b12..580a8b8 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -29,6 +29,14 @@
    are 4 bytes wide each, and the whole structure is padded to 128 bit
    alignment.  */
 #define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
+#define AARCH64_LINUX_SIZEOF_PAUTH (2 * X_REGISTER_SIZE)
 
 extern const struct regset aarch64_linux_gregset;
 extern const struct regset aarch64_linux_fpregset;
+extern const struct regset aarch64_linux_pauthregset;
+
+#ifndef HWCAP_APIA
+/* AArch64 GNU/Linux HWCAP values.  These should be synced with kernel
+   definitions.  */
+#define HWCAP_APIA (1 << 16)
+#endif

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