public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 8/8] AArch64: Read pauth section from core files
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
                   ` (4 preceding siblings ...)
  2019-03-06 13:33 ` [PATCH v2 7/8] AArch64: Prologue scan unwinder support for signed return addresses Alan Hayward
@ 2019-03-06 13:33 ` Alan Hayward
  2019-03-06 13:33 ` [PATCH v2 1/8] AArch64: Add pointer authentication feature Alan Hayward
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* aarch64-linux-tdep.c
	(aarch64_linux_iterate_over_regset_sections): Check for pauth
	section.
	* aarch64-linux-tdep.h (AARCH64_LINUX_SIZEOF_PAUTH): New define.
---
 gdb/aarch64-linux-tdep.c | 20 ++++++++++++++++++++
 gdb/aarch64-linux-tdep.h |  3 +++
 2 files changed, 23 insertions(+)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 5eeafa456c..32c5eefa35 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -627,6 +627,26 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   else
     cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, AARCH64_LINUX_SIZEOF_FPREGSET,
 	&aarch64_linux_fpregset, NULL, cb_data);
+
+
+  if (tdep->has_pauth ())
+    {
+      /* Create this on the fly in order to handle the variable location.  */
+      const struct regcache_map_entry pauth_regmap[] =
+	{
+	  { 2, AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base), 8},
+	  { 0 }
+	};
+
+      const struct regset aarch64_linux_pauth_regset =
+	{
+	  pauth_regmap, regcache_supply_regset, regcache_collect_regset
+	};
+
+      cb (".reg-aarch-pauth", AARCH64_LINUX_SIZEOF_PAUTH,
+	  AARCH64_LINUX_SIZEOF_PAUTH, &aarch64_linux_pauth_regset,
+	  "pauth registers", cb_data);
+    }
 }
 
 /* Implement the "core_read_description" gdbarch method.  */
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index 244095cbca..a8c9443cbe 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -33,6 +33,9 @@
    alignment.  */
 #define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
 
+/* The pauth regset consists of 2 X sized registers.  */
+#define AARCH64_LINUX_SIZEOF_PAUTH (2 * X_REGISTER_SIZE)
+
 extern const struct regset aarch64_linux_gregset;
 extern const struct regset aarch64_linux_fpregset;
 
-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 2/8] AArch64: Use HWCAP to detect pauth feature
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
  2019-03-06 13:33 ` [PATCH v2 3/8] AArch64: Read pauth registers Alan Hayward
@ 2019-03-06 13:33 ` Alan Hayward
  2019-03-21 20:51   ` Simon Marchi
  2019-03-06 13:33 ` [PATCH v2 6/8] AArch64: DWARF unwinder support for signed return addresses Alan Hayward
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Add aarch64_get_hwcap functions for reading the HWCAP.
From this extract the PACA value and use this to enable pauth.

gdb/ChangeLog:

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* aarch64-linux-nat.c
	(aarch64_linux_nat_target::read_description): Read PACA hwcap.
	* aarch64-linux-tdep.c
	(aarch64_linux_core_read_description): Likewise.
	(aarch64_linux_get_hwcap): New function.
	* aarch64-linux-tdep.h (AARCH64_HWCAP_PACA): New define.
	(aarch64_linux_get_hwcap): New declaration.

gdb/gdbserver/ChangeLog:

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* linux-aarch64-low.c (AARCH64_HWCAP_PACA): New define.
	(aarch64_get_hwcap): New function.
	(aarch64_arch_setup): Read APIA hwcap.
---
 gdb/aarch64-linux-nat.c           |  7 +++++--
 gdb/aarch64-linux-tdep.c          | 16 +++++++++++----
 gdb/aarch64-linux-tdep.h          |  6 ++++++
 gdb/gdbserver/linux-aarch64-low.c | 33 +++++++++++++++++++++++++++++--
 4 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index f58a41e195..8a7006165e 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -606,8 +606,11 @@ aarch64_linux_nat_target::read_description ()
   if (ret == 0)
     return tdesc_arm_with_neon;
 
-  /* pauth not yet supported.  */
-  return aarch64_read_description (aarch64_sve_get_vq (tid), false);
+  CORE_ADDR hwcap = 0;
+  bool pauth_p = aarch64_linux_get_hwcap (&hwcap)
+		 && (hwcap & AARCH64_HWCAP_PACA);
+
+  return aarch64_read_description (aarch64_sve_get_vq (tid), pauth_p);
 }
 
 /* Convert a native/host siginfo object, into/from the siginfo in the
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 445019accc..5eeafa456c 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -637,12 +637,11 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
 {
   CORE_ADDR aarch64_hwcap = 0;
 
-  if (target_auxv_search (target, AT_HWCAP, &aarch64_hwcap) != 1)
-    return NULL;
+  if (!aarch64_linux_get_hwcap (&aarch64_hwcap))
+    return nullptr;
 
-  /* pauth not yet supported.  */
   return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd),
-				   false);
+				   aarch64_hwcap & AARCH64_HWCAP_PACA);
 }
 
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
@@ -1420,6 +1419,15 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
   return NULL;
 }
 
+/* See aarch64-linux-tdep.h.  */
+
+bool
+aarch64_linux_get_hwcap (CORE_ADDR *hwcap)
+{
+  *hwcap = 0;
+  return target_auxv_search (current_top_target (), AT_HWCAP, hwcap) == 1;
+}
+
 static void
 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index 814222ead0..244095cbca 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -36,4 +36,10 @@
 extern const struct regset aarch64_linux_gregset;
 extern const struct regset aarch64_linux_fpregset;
 
+/* Matches HWCAP_PACA in kernel header arch/arm64/include/uapi/asm/hwcap.h.  */
+#define AARCH64_HWCAP_PACA (1 << 30)
+
+/* Fetch the AT_HWCAP entry from the auxv vector.  */
+bool aarch64_linux_get_hwcap (CORE_ADDR *hwcap);
+
 #endif /* AARCH64_LINUX_TDEP_H */
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index db329da4dc..e2e25f0e27 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -485,6 +485,33 @@ aarch64_linux_new_fork (struct process_info *parent,
   *child->priv->arch_private = *parent->priv->arch_private;
 }
 
+/* Matches HWCAP_PACA in kernel header arch/arm64/include/uapi/asm/hwcap.h.  */
+#define AARCH64_HWCAP_PACA (1 << 30)
+
+/* Fetch the AT_HWCAP entry from the auxv vector.  */
+
+static bool
+aarch64_get_hwcap (unsigned long *valp)
+{
+  unsigned char *data = (unsigned char *) alloca (16);
+  int offset = 0;
+
+  while ((*the_target->read_auxv) (offset, data, 16) == 16)
+    {
+      unsigned long *data_p = (unsigned long *)data;
+      if (data_p[0] == AT_HWCAP)
+	{
+	  *valp = data_p[1];
+	  return true;
+	}
+
+      offset += 16;
+    }
+
+  *valp = 0;
+  return false;
+}
+
 /* Implementation of linux_target_ops method "arch_setup".  */
 
 static void
@@ -501,8 +528,10 @@ aarch64_arch_setup (void)
   if (is_elf64)
     {
       uint64_t vq = aarch64_sve_get_vq (tid);
-      /* pauth not yet supported.  */
-      current_process ()->tdesc = aarch64_linux_read_description (vq, false);
+      unsigned long hwcap = 0;
+      bool pauth_p = aarch64_get_hwcap (&hwcap) && (hwcap & AARCH64_HWCAP_PACA);
+
+      current_process ()->tdesc = aarch64_linux_read_description (vq, pauth_p);
     }
   else
     current_process ()->tdesc = tdesc_arm_with_neon;
-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 7/8] AArch64: Prologue scan unwinder support for signed return addresses
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
                   ` (3 preceding siblings ...)
  2019-03-06 13:33 ` [PATCH v2 4/8] AArch64: gdbserver: read pauth registers Alan Hayward
@ 2019-03-06 13:33 ` Alan Hayward
  2019-03-06 13:33 ` [PATCH v2 8/8] AArch64: Read pauth section from core files Alan Hayward
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Pauth address signing is enabled at binary compile time.  When enabled the
return addresses for functions may be mangled.  This patch adds functionality
to restore the original address for use in the prologue scan unwinder.

In the prologue analyzer, check for PACIASP/PACIBSP (enable address mangling)
and AUTIASP/AUTIBSP (disable address mangling).

When unwinding the PC from the prologue, unmask the register if required.

Add a test case to the prologue tests.

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* aarch64-tdep.c (aarch64_analyze_prologue): Check for pauth
	instructions.
	(aarch64_analyze_prologue_test): Add PACIASP test.
	(aarch64_prologue_prev_register): Unmask PC value.
---
 gdb/aarch64-tdep.c | 89 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 83 insertions(+), 6 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 07430c0f25..247d0ed4c6 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -476,6 +476,37 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 	  /* Stop analysis on branch.  */
 	  break;
 	}
+      else if (inst.opcode->iclass == ic_system)
+	{
+	  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+	  int ra_state_val = 0;
+
+	  if (insn == 0xd503233f /* paciasp.  */
+	      || insn == 0xd503237f  /* pacibsp.  */)
+	    {
+	      /* Return addresses are mangled.  */
+	      ra_state_val = 1;
+	    }
+	  else if (insn == 0xd50323bf /* autiasp.  */
+		   || insn == 0xd50323ff /* autibsp.  */)
+	    {
+	      /* Return addresses are not mangled.  */
+	      ra_state_val = 0;
+	    }
+	  else
+	    {
+	      if (aarch64_debug)
+		debug_printf ("aarch64: prologue analysis gave up addr=%s"
+			      " opcode=0x%x (iclass)\n",
+			      core_addr_to_string_nz (start), insn);
+	      break;
+	    }
+
+	  if (tdep->has_pauth () && cache != nullptr)
+	    trad_frame_set_value (cache->saved_regs,
+				  tdep->pauth_ra_state_regnum,
+				  ra_state_val);
+	}
       else
 	{
 	  if (aarch64_debug)
@@ -582,11 +613,13 @@ aarch64_analyze_prologue_test (void)
   struct gdbarch *gdbarch = gdbarch_find_by_info (info);
   SELF_CHECK (gdbarch != NULL);
 
+  struct aarch64_prologue_cache cache;
+  cache.saved_regs = trad_frame_alloc_saved_regs (gdbarch);
+
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   /* Test the simple prologue in which frame pointer is used.  */
   {
-    struct aarch64_prologue_cache cache;
-    cache.saved_regs = trad_frame_alloc_saved_regs (gdbarch);
-
     static const uint32_t insns[] = {
       0xa9af7bfd, /* stp     x29, x30, [sp,#-272]! */
       0x910003fd, /* mov     x29, sp */
@@ -622,9 +655,6 @@ aarch64_analyze_prologue_test (void)
   /* Test a prologue in which STR is used and frame pointer is not
      used.  */
   {
-    struct aarch64_prologue_cache cache;
-    cache.saved_regs = trad_frame_alloc_saved_regs (gdbarch);
-
     static const uint32_t insns[] = {
       0xf81d0ff3, /* str	x19, [sp, #-48]! */
       0xb9002fe0, /* str	w0, [sp, #44] */
@@ -664,6 +694,45 @@ aarch64_analyze_prologue_test (void)
 		      == -1);
       }
   }
+
+  /* Test a prologue in which there is a return address signing instruction.  */
+  if (tdep->has_pauth ())
+    {
+      static const uint32_t insns[] = {
+	0xd503233f, /* paciasp */
+	0xa9bd7bfd, /* stp	x29, x30, [sp, #-48]! */
+	0x910003fd, /* mov	x29, sp */
+	0xf801c3f3, /* str	x19, [sp, #28] */
+	0xb9401fa0, /* ldr	x19, [x29, #28] */
+      };
+      instruction_reader_test reader (insns);
+
+      CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128, &cache,
+						reader);
+
+      SELF_CHECK (end == 4 * 4);
+      SELF_CHECK (cache.framereg == AARCH64_FP_REGNUM);
+      SELF_CHECK (cache.framesize == 48);
+
+      for (int i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
+	{
+	  if (i == 19)
+	    SELF_CHECK (cache.saved_regs[i].addr == -20);
+	  else if (i == AARCH64_FP_REGNUM)
+	    SELF_CHECK (cache.saved_regs[i].addr == -48);
+	  else if (i == AARCH64_LR_REGNUM)
+	    SELF_CHECK (cache.saved_regs[i].addr == -40);
+	  else
+	    SELF_CHECK (cache.saved_regs[i].addr == -1);
+	}
+
+      if (tdep->has_pauth ())
+	{
+	  SELF_CHECK (trad_frame_value_p (cache.saved_regs,
+					  tdep->pauth_ra_state_regnum));
+	  SELF_CHECK (cache.saved_regs[tdep->pauth_ra_state_regnum].addr == 1);
+	}
+    }
 }
 } // namespace selftests
 #endif /* GDB_SELF_TEST */
@@ -873,8 +942,16 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
   if (prev_regnum == AARCH64_PC_REGNUM)
     {
       CORE_ADDR lr;
+      struct gdbarch *gdbarch = get_frame_arch (this_frame);
+      struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
       lr = frame_unwind_register_unsigned (this_frame, AARCH64_LR_REGNUM);
+
+      if (tdep->has_pauth ()
+	  && trad_frame_value_p (cache->saved_regs,
+				 tdep->pauth_ra_state_regnum))
+	lr = aarch64_frame_unmask_address (tdep, this_frame, lr);
+
       return frame_unwind_got_constant (this_frame, prev_regnum, lr);
     }
 
-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 5/8] AArch64: Add pauth DWARF registers
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
                   ` (6 preceding siblings ...)
  2019-03-06 13:33 ` [PATCH v2 1/8] AArch64: Add pointer authentication feature Alan Hayward
@ 2019-03-06 13:33 ` Alan Hayward
  2019-03-14 12:34 ` [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
  8 siblings, 0 replies; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Map the pauth registers to DWARF.

Add a new pseudo register ra_state and also map this to DWARF.  This register
is hidden from the user - prevent it from being read or written to.  It will
be used for the unmangling of addresses.

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* aarch64-tdep.c (aarch64_dwarf_reg_to_regnum): Check for pauth
	registers.
	(aarch64_pseudo_register_name): Likewise.
	(aarch64_pseudo_register_type): Likewise.
	(aarch64_pseudo_register_reggroup_p): Likewise.
	(aarch64_gdbarch_init): Add pauth registers.
	* aarch64-tdep.h (AARCH64_DWARF_PAUTH_RA_STATE): New define.
	(AARCH64_DWARF_PAUTH_DMASK): Likewise.
	(AARCH64_DWARF_PAUTH_CMASK): Likewise.
	(struct gdbarch_tdep): Add regnum for ra_state.
---
 gdb/aarch64-tdep.c | 94 ++++++++++++++++++++++++++++++----------------
 gdb/aarch64-tdep.h |  4 ++
 2 files changed, 65 insertions(+), 33 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 66fdd7bf05..01e98b7195 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -1839,6 +1839,8 @@ aarch64_vnv_type (struct gdbarch *gdbarch)
 static int
 aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   if (reg >= AARCH64_DWARF_X0 && reg <= AARCH64_DWARF_X0 + 30)
     return AARCH64_X0_REGNUM + reg - AARCH64_DWARF_X0;
 
@@ -1860,6 +1862,15 @@ aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
   if (reg >= AARCH64_DWARF_SVE_Z0 && reg <= AARCH64_DWARF_SVE_Z0 + 15)
     return AARCH64_SVE_Z0_REGNUM + reg - AARCH64_DWARF_SVE_Z0;
 
+  if (tdep->has_pauth ())
+    {
+      if (reg >= AARCH64_DWARF_PAUTH_DMASK && reg <= AARCH64_DWARF_PAUTH_CMASK)
+	return tdep->pauth_reg_base + reg - AARCH64_DWARF_PAUTH_DMASK;
+
+      if (reg == AARCH64_DWARF_PAUTH_RA_STATE)
+	return tdep->pauth_ra_state_regnum;
+    }
+
   return -1;
 }
 
@@ -2215,22 +2226,22 @@ aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
       "b28", "b29", "b30", "b31",
     };
 
-  regnum -= gdbarch_num_regs (gdbarch);
+  int p_regnum = regnum - gdbarch_num_regs (gdbarch);
 
-  if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32)
-    return q_name[regnum - AARCH64_Q0_REGNUM];
+  if (p_regnum >= AARCH64_Q0_REGNUM && p_regnum < AARCH64_Q0_REGNUM + 32)
+    return q_name[p_regnum - AARCH64_Q0_REGNUM];
 
-  if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32)
-    return d_name[regnum - AARCH64_D0_REGNUM];
+  if (p_regnum >= AARCH64_D0_REGNUM && p_regnum < AARCH64_D0_REGNUM + 32)
+    return d_name[p_regnum - AARCH64_D0_REGNUM];
 
-  if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32)
-    return s_name[regnum - AARCH64_S0_REGNUM];
+  if (p_regnum >= AARCH64_S0_REGNUM && p_regnum < AARCH64_S0_REGNUM + 32)
+    return s_name[p_regnum - AARCH64_S0_REGNUM];
 
-  if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32)
-    return h_name[regnum - AARCH64_H0_REGNUM];
+  if (p_regnum >= AARCH64_H0_REGNUM && p_regnum < AARCH64_H0_REGNUM + 32)
+    return h_name[p_regnum - AARCH64_H0_REGNUM];
 
-  if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32)
-    return b_name[regnum - AARCH64_B0_REGNUM];
+  if (p_regnum >= AARCH64_B0_REGNUM && p_regnum < AARCH64_B0_REGNUM + 32)
+    return b_name[p_regnum - AARCH64_B0_REGNUM];
 
   if (tdep->has_sve ())
     {
@@ -2246,14 +2257,20 @@ aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 	  "v28", "v29", "v30", "v31",
 	};
 
-      if (regnum >= AARCH64_SVE_V0_REGNUM
-	  && regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
-	return sve_v_name[regnum - AARCH64_SVE_V0_REGNUM];
+      if (p_regnum >= AARCH64_SVE_V0_REGNUM
+	  && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
+	return sve_v_name[p_regnum - AARCH64_SVE_V0_REGNUM];
     }
 
+  /* RA_STATE is used for unwinding only.  Do not assign it a name - this
+     prevents it from being read by methods such as
+     mi_cmd_trace_frame_collected.  */
+  if (tdep->has_pauth () && regnum == tdep->pauth_ra_state_regnum)
+    return "";
+
   internal_error (__FILE__, __LINE__,
 		  _("aarch64_pseudo_register_name: bad register number %d"),
-		  regnum);
+		  p_regnum);
 }
 
 /* Implement the "pseudo_register_type" tdesc_arch_data method.  */
@@ -2263,30 +2280,33 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  regnum -= gdbarch_num_regs (gdbarch);
+  int p_regnum = regnum - gdbarch_num_regs (gdbarch);
 
-  if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32)
+  if (p_regnum >= AARCH64_Q0_REGNUM && p_regnum < AARCH64_Q0_REGNUM + 32)
     return aarch64_vnq_type (gdbarch);
 
-  if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32)
+  if (p_regnum >= AARCH64_D0_REGNUM && p_regnum < AARCH64_D0_REGNUM + 32)
     return aarch64_vnd_type (gdbarch);
 
-  if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32)
+  if (p_regnum >= AARCH64_S0_REGNUM && p_regnum < AARCH64_S0_REGNUM + 32)
     return aarch64_vns_type (gdbarch);
 
-  if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32)
+  if (p_regnum >= AARCH64_H0_REGNUM && p_regnum < AARCH64_H0_REGNUM + 32)
     return aarch64_vnh_type (gdbarch);
 
-  if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32)
+  if (p_regnum >= AARCH64_B0_REGNUM && p_regnum < AARCH64_B0_REGNUM + 32)
     return aarch64_vnb_type (gdbarch);
 
-  if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM
-      && regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
+  if (tdep->has_sve () && p_regnum >= AARCH64_SVE_V0_REGNUM
+      && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
     return aarch64_vnv_type (gdbarch);
 
+  if (tdep->has_pauth () && regnum == tdep->pauth_ra_state_regnum)
+    return builtin_type (gdbarch)->builtin_uint64;
+
   internal_error (__FILE__, __LINE__,
 		  _("aarch64_pseudo_register_type: bad register number %d"),
-		  regnum);
+		  p_regnum);
 }
 
 /* Implement the "pseudo_register_reggroup_p" tdesc_arch_data method.  */
@@ -2297,23 +2317,26 @@ aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  regnum -= gdbarch_num_regs (gdbarch);
+  int p_regnum = regnum - gdbarch_num_regs (gdbarch);
 
-  if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32)
+  if (p_regnum >= AARCH64_Q0_REGNUM && p_regnum < AARCH64_Q0_REGNUM + 32)
     return group == all_reggroup || group == vector_reggroup;
-  else if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32)
+  else if (p_regnum >= AARCH64_D0_REGNUM && p_regnum < AARCH64_D0_REGNUM + 32)
     return (group == all_reggroup || group == vector_reggroup
 	    || group == float_reggroup);
-  else if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32)
+  else if (p_regnum >= AARCH64_S0_REGNUM && p_regnum < AARCH64_S0_REGNUM + 32)
     return (group == all_reggroup || group == vector_reggroup
 	    || group == float_reggroup);
-  else if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32)
+  else if (p_regnum >= AARCH64_H0_REGNUM && p_regnum < AARCH64_H0_REGNUM + 32)
     return group == all_reggroup || group == vector_reggroup;
-  else if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32)
+  else if (p_regnum >= AARCH64_B0_REGNUM && p_regnum < AARCH64_B0_REGNUM + 32)
     return group == all_reggroup || group == vector_reggroup;
-  else if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM
-	   && regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
+  else if (tdep->has_sve () && p_regnum >= AARCH64_SVE_V0_REGNUM
+	   && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
     return group == all_reggroup || group == vector_reggroup;
+  /* RA_STATE is used for unwinding only.  Do not assign it to any groups.  */
+  if (tdep->has_pauth () && regnum == tdep->pauth_ra_state_regnum)
+    return 0;
 
   return group == all_reggroup;
 }
@@ -2983,6 +3006,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int num_regs = 0;
   int num_pseudo_regs = 0;
   int first_pauth_regnum = -1;
+  int pauth_ra_state_offset = -1;
 
   /* Ensure we always have a target description.  */
   if (!tdesc_has_registers (tdesc))
@@ -3051,7 +3075,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (feature_pauth != NULL)
     {
       first_pauth_regnum = num_regs;
-
+      pauth_ra_state_offset = num_pseudo_regs;
       /* Validate the descriptor provides the mandatory PAUTH registers and
 	 allocate their numbers.  */
       for (i = 0; i < ARRAY_SIZE (aarch64_pauth_register_names); i++)
@@ -3060,6 +3084,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					    aarch64_pauth_register_names[i]);
 
       num_regs += i;
+      num_pseudo_regs += 1;	/* Count RA_STATE pseudo register.  */
     }
 
   if (!valid_p)
@@ -3096,6 +3121,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->jb_elt_size = 8;
   tdep->vq = aarch64_get_tdesc_vq (tdesc);
   tdep->pauth_reg_base = first_pauth_regnum;
+  tdep->pauth_ra_state_regnum = (feature_pauth == NULL) ? -1
+				: pauth_ra_state_offset + num_regs;
+
 
   set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
   set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index f9fc8965f0..f73392d59b 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -31,6 +31,9 @@ struct regset;
 /* AArch64 Dwarf register numbering.  */
 #define AARCH64_DWARF_X0   0
 #define AARCH64_DWARF_SP  31
+#define AARCH64_DWARF_PAUTH_RA_STATE  34
+#define AARCH64_DWARF_PAUTH_DMASK  35
+#define AARCH64_DWARF_PAUTH_CMASK  36
 #define AARCH64_DWARF_V0  64
 #define AARCH64_DWARF_SVE_VG   46
 #define AARCH64_DWARF_SVE_FFR  47
@@ -89,6 +92,7 @@ struct gdbarch_tdep
   }
 
   int pauth_reg_base;
+  int pauth_ra_state_regnum;
 
   /* Returns true if the target supports pauth.  */
   bool has_pauth () const
-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 0/8] Support for AArch64 Pointer Authentication
@ 2019-03-06 13:33 Alan Hayward
  2019-03-06 13:33 ` [PATCH v2 3/8] AArch64: Read pauth registers Alan Hayward
                   ` (8 more replies)
  0 siblings, 9 replies; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Pointer Authentication is a new feature in AArch64 v8.3-a. When enabled in
the compiler, function return addresses will be mangled by the kernel. This
set of patches adds support to add the new registers and umangle addresses
to allow the unwinder to work.

Linux Kernel support is in Linux 5.0, and was added here:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=04ca3204fa09f5f55c8f113b0072004a7b364ff4

Binutils support was added earlier this year:
https://www.sourceware.org/ml/binutils/2019-02/msg00069.html

GCC support is in GCC 7.1.1 and is enabled by default when building for
8.3-a, originally added here:
https://gcc.gnu.org/ml/gcc-patches/2017-01/msg00376.html
Additional support is in progress, see:
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00697.html


This patch series has been tested on an 8.3 Fast Model running head Linux,
using both head GCC and GCC patched with the additional support.

This series is a reworking of the series originally posted by Jiong:
https://sourceware.org/ml/gdb-patches/2017-08/msg00170.html

Patches 1-5 add the new feature, register support and feature detection.
Patches 6 and 7 add the address unmangling.
Patch 8 adds core file support.


Alan Hayward (8):
  AArch64: Add pointer authentication feature
  AArch64: Use HWCAP to detect pauth feature
  AArch64: Read pauth registers
  AArch64: gdbserver: read pauth registers
  AArch64: Add pauth DWARF registers
  AArch64: DWARF unwinder support for signed return addresses
  AArch64: Prologue scan unwinder support for signed return addresses
  AArch64: Read pauth section from core files

 gdb/aarch64-linux-nat.c                      |  41 ++-
 gdb/aarch64-linux-tdep.c                     |  36 +-
 gdb/aarch64-linux-tdep.h                     |   9 +
 gdb/aarch64-tdep.c                           | 325 ++++++++++++++++---
 gdb/aarch64-tdep.h                           |  14 +-
 gdb/arch/aarch64.c                           |   6 +-
 gdb/arch/aarch64.h                           |   9 +-
 gdb/doc/gdb.texinfo                          |   3 +
 gdb/features/Makefile                        |   1 +
 gdb/features/aarch64-pauth.c                 |  16 +
 gdb/features/aarch64-pauth.xml               |  13 +
 gdb/gdbserver/linux-aarch64-ipa.c            |   8 +-
 gdb/gdbserver/linux-aarch64-low.c            |  55 +++-
 gdb/gdbserver/linux-aarch64-tdesc-selftest.c |   2 +-
 gdb/gdbserver/linux-aarch64-tdesc.c          |  10 +-
 gdb/gdbserver/linux-aarch64-tdesc.h          |   2 +-
 gdb/gdbserver/linux-low.c                    |  14 +-
 gdb/gdbserver/linux-low.h                    |   1 +
 18 files changed, 491 insertions(+), 74 deletions(-)
 create mode 100644 gdb/features/aarch64-pauth.c
 create mode 100644 gdb/features/aarch64-pauth.xml

-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 6/8] AArch64: DWARF unwinder support for signed return addresses
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
  2019-03-06 13:33 ` [PATCH v2 3/8] AArch64: Read pauth registers Alan Hayward
  2019-03-06 13:33 ` [PATCH v2 2/8] AArch64: Use HWCAP to detect pauth feature Alan Hayward
@ 2019-03-06 13:33 ` Alan Hayward
  2019-03-06 13:33 ` [PATCH v2 4/8] AArch64: gdbserver: read pauth registers Alan Hayward
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Pauth address signing is enabled at binary compile time.  When enabled the
return addresses for functions may be mangled.  This patch adds functionality
to restore the original address for use in the DWARF unwinder.

DW_CFA_AARCH64_negate_ra_state in a binary indicates the toggling of address
signing between enabled and disabled.  Ensure the state is stored in the DWARF
register ra_state.

Ensure the pauth DWARF registers are initialised.

gdb/ChangeLog:

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* aarch64-tdep.c (aarch64_frame_unmask_address): New function.
	(aarch64_dwarf2_prev_register): Unmask PC value.
	(aarch64_dwarf2_frame_init_reg): Init pauth registers.
	(aarch64_execute_dwarf_cfa_vendor_op): Check for
	DW_CFA_AARCH64_negate_ra_state.
	(aarch64_gdbarch_init): Add aarch64_execute_dwarf_cfa_vendor_op.
---
 gdb/aarch64-tdep.c | 87 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 85 insertions(+), 2 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 01e98b7195..07430c0f25 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -34,6 +34,7 @@
 #include "frame-base.h"
 #include "trad-frame.h"
 #include "objfiles.h"
+#include "dwarf2.h"
 #include "dwarf2-frame.h"
 #include "gdbtypes.h"
 #include "prologue-value.h"
@@ -248,6 +249,26 @@ class instruction_reader : public abstract_instruction_reader
 
 } // namespace
 
+/* If address signing is enabled, mask off the signature bits from ADDR, using
+   the register values in THIS_FRAME.  */
+
+static CORE_ADDR
+aarch64_frame_unmask_address (struct gdbarch_tdep *tdep,
+			      struct frame_info *this_frame,
+			      CORE_ADDR addr)
+{
+  if (tdep->has_pauth ()
+      && frame_unwind_register_unsigned (this_frame,
+					 tdep->pauth_ra_state_regnum))
+    {
+      int cmask_num = AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base);
+      CORE_ADDR cmask = frame_unwind_register_unsigned (this_frame, cmask_num);
+      addr = addr & ~cmask;
+    }
+
+  return addr;
+}
+
 /* Analyze a prologue, looking for a recognizable stack frame
    and frame pointer.  Scan until we encounter a store that could
    clobber the stack frame unexpectedly, or an unknown instruction.  */
@@ -1013,12 +1034,14 @@ static struct value *
 aarch64_dwarf2_prev_register (struct frame_info *this_frame,
 			      void **this_cache, int regnum)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
   CORE_ADDR lr;
 
   switch (regnum)
     {
     case AARCH64_PC_REGNUM:
       lr = frame_unwind_register_unsigned (this_frame, AARCH64_LR_REGNUM);
+      lr = aarch64_frame_unmask_address (tdep, this_frame, lr);
       return frame_unwind_got_constant (this_frame, regnum, lr);
 
     default:
@@ -1027,6 +1050,9 @@ aarch64_dwarf2_prev_register (struct frame_info *this_frame,
     }
 }
 
+static const unsigned char op_lit0 = DW_OP_lit0;
+static const unsigned char op_lit1 = DW_OP_lit1;
+
 /* Implement the "init_reg" dwarf2_frame_ops method.  */
 
 static void
@@ -1034,18 +1060,72 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
 			       struct dwarf2_frame_state_reg *reg,
 			       struct frame_info *this_frame)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   switch (regnum)
     {
     case AARCH64_PC_REGNUM:
       reg->how = DWARF2_FRAME_REG_FN;
       reg->loc.fn = aarch64_dwarf2_prev_register;
-      break;
+      return;
+
     case AARCH64_SP_REGNUM:
       reg->how = DWARF2_FRAME_REG_CFA;
-      break;
+      return;
+    }
+
+  /* Init pauth registers.  */
+  if (tdep->has_pauth ())
+    {
+      if (regnum == tdep->pauth_ra_state_regnum)
+	{
+	  /* Initialize RA_STATE to zero.  */
+	  reg->how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
+	  reg->loc.exp.start = &op_lit0;
+	  reg->loc.exp.len = 1;
+	  return;
+	}
+      else if (regnum == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base)
+	       || regnum == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base))
+	{
+	  reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+	  return;
+	}
     }
 }
 
+/* Implement the execute_dwarf_cfa_vendor_op method.  */
+
+static bool
+aarch64_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op,
+				     struct dwarf2_frame_state *fs)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct dwarf2_frame_state_reg *ra_state;
+
+  if (tdep->has_pauth () && op == DW_CFA_AARCH64_negate_ra_state)
+    {
+      /* Allocate RA_STATE column if it's not allocated yet.  */
+      fs->regs.alloc_regs (AARCH64_DWARF_PAUTH_RA_STATE + 1);
+
+      /* Toggle the status of RA_STATE between 0 and 1.  */
+      ra_state = &(fs->regs.reg[AARCH64_DWARF_PAUTH_RA_STATE]);
+      ra_state->how = DWARF2_FRAME_REG_SAVED_VAL_EXP;
+
+      if (ra_state->loc.exp.start == nullptr
+	  || ra_state->loc.exp.start == &op_lit0)
+	ra_state->loc.exp.start = &op_lit1;
+      else
+	ra_state->loc.exp.start = &op_lit0;
+
+      ra_state->loc.exp.len = 1;
+
+      return true;
+    }
+
+  return false;
+}
+
 /* When arguments must be pushed onto the stack, they go on in reverse
    order.  The code below implements a FILO (stack) to do this.  */
 
@@ -3192,6 +3272,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   gdbarch_init_osabi (info, gdbarch);
 
   dwarf2_frame_set_init_reg (gdbarch, aarch64_dwarf2_frame_init_reg);
+  /* Register DWARF CFA vendor handler.  */
+  set_gdbarch_execute_dwarf_cfa_vendor_op (gdbarch,
+					   aarch64_execute_dwarf_cfa_vendor_op);
 
   /* Add some default predicates.  */
   frame_unwind_append_unwinder (gdbarch, &aarch64_stub_unwind);
-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 4/8] AArch64: gdbserver: read pauth registers
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
                   ` (2 preceding siblings ...)
  2019-03-06 13:33 ` [PATCH v2 6/8] AArch64: DWARF unwinder support for signed return addresses Alan Hayward
@ 2019-03-06 13:33 ` Alan Hayward
  2019-03-21 21:03   ` Simon Marchi
  2019-03-06 13:33 ` [PATCH v2 7/8] AArch64: Prologue scan unwinder support for signed return addresses Alan Hayward
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Add the pauth registers to the regset lists.

Add a new regset type OPTIONAL_REGS which allows for the regset read to fail.
Once the read fails, it will not be checked again.  This allows targets with
optional features to keep a single static regset_info structure.

gdb/ChangeLog:

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* arch/aarch64.h (AARCH64_PAUTH_REGS_SIZE): New define.

gdb/gdbserver/ChangeLog:

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* linux-aarch64-low.c (aarch64_store_pauthregset): New function.
	* linux-low.c (regsets_store_inferior_registers): Allow optional reads
	to fail.
	* linux-low.h (enum regset_type): Add OPTIONAL_REGS.
---
 gdb/arch/aarch64.h                |  1 +
 gdb/gdbserver/linux-aarch64-low.c | 23 +++++++++++++++++++++++
 gdb/gdbserver/linux-low.c         | 14 ++++++++------
 gdb/gdbserver/linux-low.h         |  1 +
 4 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index 8c80b7be62..309fe75273 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -68,6 +68,7 @@ enum aarch64_regnum
 
 #define AARCH64_PAUTH_DMASK_REGNUM(pauth_reg_base) (pauth_reg_base)
 #define AARCH64_PAUTH_CMASK_REGNUM(pauth_reg_base) (pauth_reg_base + 1)
+#define AARCH64_PAUTH_REGS_SIZE (16)
 
 #define AARCH64_X_REGS_NUM 31
 #define AARCH64_V_REGS_NUM 32
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index e2e25f0e27..20c75493b0 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -135,6 +135,23 @@ aarch64_store_fpregset (struct regcache *regcache, const void *buf)
   supply_register (regcache, AARCH64_FPCR_REGNUM, &regset->fpcr);
 }
 
+/* Store the pauth registers to regcache.  */
+
+static void
+aarch64_store_pauthregset (struct regcache *regcache, const void *buf)
+{
+  uint64_t *pauth_regset = (uint64_t *) buf;
+  int pauth_base = find_regno (regcache->tdesc, "pauth_dmask");
+
+  if (pauth_base == 0)
+    return;
+
+  supply_register (regcache, AARCH64_PAUTH_DMASK_REGNUM (pauth_base),
+		   &pauth_regset[0]);
+  supply_register (regcache, AARCH64_PAUTH_CMASK_REGNUM (pauth_base),
+		   &pauth_regset[1]);
+}
+
 /* Enable miscellaneous debugging output.  The name is historical - it
    was originally used to debug LinuxThreads support.  */
 extern int debug_threads;
@@ -564,6 +581,9 @@ static struct regset_info aarch64_regsets[] =
     sizeof (struct user_fpsimd_state), FP_REGS,
     aarch64_fill_fpregset, aarch64_store_fpregset
   },
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
+    AARCH64_PAUTH_REGS_SIZE, OPTIONAL_REGS,
+    NULL, aarch64_store_pauthregset },
   NULL_REGSET
 };
 
@@ -590,6 +610,9 @@ static struct regset_info aarch64_sve_regsets[] =
     SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE), EXTENDED_REGS,
     aarch64_sve_regs_copy_from_regcache, aarch64_sve_regs_copy_to_regcache
   },
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
+    AARCH64_PAUTH_REGS_SIZE, OPTIONAL_REGS,
+    NULL, aarch64_store_pauthregset },
   NULL_REGSET
 };
 
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 8c5a51f23c..e1cb7fcfbc 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -5359,10 +5359,11 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
 #endif
       if (res < 0)
 	{
-	  if (errno == EIO)
+	  if (errno == EIO
+	      || (errno == EINVAL && regset->type == OPTIONAL_REGS))
 	    {
-	      /* If we get EIO on a regset, do not try it again for
-		 this process mode.  */
+	      /* If we get EIO on a regset, or an EINVAL and the regset is
+		 optional, do not try it again for this process mode.  */
 	      disable_regset (regsets_info, regset);
 	    }
 	  else if (errno == ENODATA)
@@ -5457,10 +5458,11 @@ regsets_store_inferior_registers (struct regsets_info *regsets_info,
 
       if (res < 0)
 	{
-	  if (errno == EIO)
+	  if (errno == EIO
+	      || (errno == EINVAL && regset->type == OPTIONAL_REGS))
 	    {
-	      /* If we get EIO on a regset, do not try it again for
-		 this process mode.  */
+	      /* If we get EIO on a regset, or an EINVAL and the regset is
+		 optional, do not try it again for this process mode.  */
 	      disable_regset (regsets_info, regset);
 	    }
 	  else if (errno == ESRCH)
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index d09390dd99..1ade35d648 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -40,6 +40,7 @@ enum regset_type {
   GENERAL_REGS,
   FP_REGS,
   EXTENDED_REGS,
+  OPTIONAL_REGS, /* Do not error if the regset cannot be accessed.  */
 };
 
 /* The arch's regsets array initializer must be terminated with a NULL
-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 1/8] AArch64: Add pointer authentication feature
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
                   ` (5 preceding siblings ...)
  2019-03-06 13:33 ` [PATCH v2 8/8] AArch64: Read pauth section from core files Alan Hayward
@ 2019-03-06 13:33 ` Alan Hayward
  2019-03-06 15:36   ` Eli Zaretskii
  2019-03-06 13:33 ` [PATCH v2 5/8] AArch64: Add pauth DWARF registers Alan Hayward
  2019-03-14 12:34 ` [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
  8 siblings, 1 reply; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Pointer Authentication is a new feature in AArch64 v8.3-a. When enabled in
the compiler, function return addresses will be mangled by the kernel.

Add register description xml and wire up to aarch64_linux_read_description.
This description includes the two pauth user registers.

Nothing yet uses the feature - that is added in later patches.

gdb/ChangeLog:

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* aarch64-linux-nat.c
	(aarch64_linux_nat_target::read_description): Add pauth param.
	* aarch64-linux-tdep.c
	(aarch64_linux_core_read_description): Likewise.
	* aarch64-tdep.c (struct target_desc): Add in pauth.
	(aarch64_read_description): Add pauth param.
	(aarch64_gdbarch_init): Likewise.
	* aarch64-tdep.h (aarch64_read_description): Likewise.
	* arch/aarch64.c (aarch64_create_target_description): Likewise.
	* arch/aarch64.h (aarch64_create_target_description): Likewise.
	* features/Makefile: Add new files.
	* features/aarch64-pauth.c: New file.
	* features/aarch64-pauth.xml: New file.

gdb/doc/ChangeLog:

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* gdb.texinfo: Describe pauth feature.

gdb/gdbserver/ChangeLog:

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* linux-aarch64-ipa.c (get_ipa_tdesc): Add pauth param.
	(initialize_low_tracepoint): Likewise.
	* linux-aarch64-low.c (aarch64_arch_setup): Likewise.
	* linux-aarch64-tdesc-selftest.c (aarch64_tdesc_test): Likewise.
	* linux-aarch64-tdesc.c (struct target_desc): Likewise.
	(aarch64_linux_read_description): Likewise.
	* linux-aarch64-tdesc.h (aarch64_linux_read_description): Likewise.
---
 gdb/aarch64-linux-nat.c                      |  5 +++--
 gdb/aarch64-linux-tdep.c                     |  4 +++-
 gdb/aarch64-tdep.c                           | 14 +++++++-------
 gdb/aarch64-tdep.h                           |  2 +-
 gdb/arch/aarch64.c                           |  6 +++++-
 gdb/arch/aarch64.h                           |  5 +++--
 gdb/doc/gdb.texinfo                          |  3 +++
 gdb/features/Makefile                        |  1 +
 gdb/features/aarch64-pauth.c                 | 16 ++++++++++++++++
 gdb/features/aarch64-pauth.xml               | 13 +++++++++++++
 gdb/gdbserver/linux-aarch64-ipa.c            |  8 ++++----
 gdb/gdbserver/linux-aarch64-low.c            |  3 ++-
 gdb/gdbserver/linux-aarch64-tdesc-selftest.c |  2 +-
 gdb/gdbserver/linux-aarch64-tdesc.c          | 10 +++++-----
 gdb/gdbserver/linux-aarch64-tdesc.h          |  2 +-
 15 files changed, 68 insertions(+), 26 deletions(-)
 create mode 100644 gdb/features/aarch64-pauth.c
 create mode 100644 gdb/features/aarch64-pauth.xml

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 6f91e9568e..f58a41e195 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -605,8 +605,9 @@ aarch64_linux_nat_target::read_description ()
   ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_VFP, &iovec);
   if (ret == 0)
     return tdesc_arm_with_neon;
-  else
-    return aarch64_read_description (aarch64_sve_get_vq (tid));
+
+  /* pauth not yet supported.  */
+  return aarch64_read_description (aarch64_sve_get_vq (tid), false);
 }
 
 /* Convert a native/host siginfo object, into/from the siginfo in the
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 39e607658f..445019accc 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -640,7 +640,9 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
   if (target_auxv_search (target, AT_HWCAP, &aarch64_hwcap) != 1)
     return NULL;
 
-  return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd));
+  /* pauth not yet supported.  */
+  return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd),
+				   false);
 }
 
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index dd57ef9873..0518837a1f 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -69,7 +69,7 @@
 #define HA_MAX_NUM_FLDS		4
 
 /* All possible aarch64 target descriptors.  */
-struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1];
+struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/];
 
 /* The standard register names, and all the valid aliases for them.  */
 static const struct
@@ -2885,18 +2885,18 @@ aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
    (It is not possible to set VQ to zero on an SVE system).  */
 
 const target_desc *
-aarch64_read_description (uint64_t vq)
+aarch64_read_description (uint64_t vq, bool pauth_p)
 {
   if (vq > AARCH64_MAX_SVE_VQ)
     error (_("VQ is %" PRIu64 ", maximum supported value is %d"), vq,
 	   AARCH64_MAX_SVE_VQ);
 
-  struct target_desc *tdesc = tdesc_aarch64_list[vq];
+  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p];
 
   if (tdesc == NULL)
     {
-      tdesc = aarch64_create_target_description (vq);
-      tdesc_aarch64_list[vq] = tdesc;
+      tdesc = aarch64_create_target_description (vq, pauth_p);
+      tdesc_aarch64_list[vq][pauth_p] = tdesc;
     }
 
   return tdesc;
@@ -2961,7 +2961,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Ensure we always have a target description.  */
   if (!tdesc_has_registers (tdesc))
-    tdesc = aarch64_read_description (0);
+    tdesc = aarch64_read_description (0, false);
   gdb_assert (tdesc);
 
   feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.core");
@@ -3190,7 +3190,7 @@ When on, AArch64 specific debugging is enabled."),
   selftests::register_test ("aarch64-process-record",
 			    selftests::aarch64_process_record_test);
   selftests::record_xml_tdesc ("aarch64.xml",
-			       aarch64_create_target_description (0));
+			       aarch64_create_target_description (0, false));
 #endif
 }
 
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index 704eacb50c..3db6bee9f3 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -89,7 +89,7 @@ struct gdbarch_tdep
   }
 };
 
-const target_desc *aarch64_read_description (uint64_t vq);
+const target_desc *aarch64_read_description (uint64_t vq, bool pauth_p);
 
 extern int aarch64_process_record (struct gdbarch *gdbarch,
                                struct regcache *regcache, CORE_ADDR addr);
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index d36ed9d19e..11a15dd94c 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -22,11 +22,12 @@
 #include "../features/aarch64-core.c"
 #include "../features/aarch64-fpu.c"
 #include "../features/aarch64-sve.c"
+#include "../features/aarch64-pauth.c"
 
 /* See arch/aarch64.h.  */
 
 target_desc *
-aarch64_create_target_description (uint64_t vq)
+aarch64_create_target_description (uint64_t vq, bool pauth_p)
 {
   target_desc *tdesc = allocate_target_description ();
 
@@ -43,5 +44,8 @@ aarch64_create_target_description (uint64_t vq)
   else
     regnum = create_feature_aarch64_sve (tdesc, regnum, vq);
 
+  if (pauth_p)
+    regnum = create_feature_aarch64_pauth (tdesc, regnum);
+
   return tdesc;
 }
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index 807a4a6558..4fe6d02f6e 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -24,9 +24,10 @@
 
 /* Create the aarch64 target description.  A non zero VQ value indicates both
    the presence of SVE and the Vector Quotient - the number of 128bit chunks in
-   an SVE Z register.  */
+   an SVE Z register.  HAS_PAUTH_P indicates the presence of the PAUTH
+   feature.  */
 
-target_desc *aarch64_create_target_description (uint64_t vq);
+target_desc *aarch64_create_target_description (uint64_t vq, bool has_pauth_p);
 
 /* Register numbers of various important registers.
    Note that on SVE, the Z registers reuse the V register numbers and the V
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index f2028f86b0..e4d8e44cae 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -43076,6 +43076,9 @@ The @samp{org.gnu.gdb.aarch64.sve} feature is optional.  If present,
 it should contain registers @samp{z0} through @samp{z31}, @samp{p0}
 through @samp{p15}, @samp{ffr} and @samp{vg}.
 
+The @samp{org.gnu.gdb.aarch64.pauth} feature is optional.  If present,
+it should contain registers @samp{pauth_dmask} and @samp{pauth_cmask}.
+
 @node ARC Features
 @subsection ARC Features
 @cindex target descriptions, ARC Features
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 3d84ca09a1..d0cd4f851f 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -227,6 +227,7 @@ $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
 
 FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-fpu.xml \
+	aarch64-pauth.xml \
 	i386/32bit-core.xml \
 	i386/32bit-sse.xml \
 	i386/32bit-linux.xml \
diff --git a/gdb/features/aarch64-pauth.c b/gdb/features/aarch64-pauth.c
new file mode 100644
index 0000000000..e4b84ffb55
--- /dev/null
+++ b/gdb/features/aarch64-pauth.c
@@ -0,0 +1,16 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aarch64-pauth.xml */
+
+#include "common/tdesc.h"
+
+static int
+create_feature_aarch64_pauth (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.pauth");
+  tdesc_create_reg (feature, "pauth_dmask", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pauth_cmask", regnum++, 1, NULL, 64, "int");
+
+  return regnum;
+}
diff --git a/gdb/features/aarch64-pauth.xml b/gdb/features/aarch64-pauth.xml
new file mode 100644
index 0000000000..9c8987fca7
--- /dev/null
+++ b/gdb/features/aarch64-pauth.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.pauth">
+  <reg name="pauth_dmask" bitsize="64"/>
+  <reg name="pauth_cmask" bitsize="64"/>
+</feature>
+
diff --git a/gdb/gdbserver/linux-aarch64-ipa.c b/gdb/gdbserver/linux-aarch64-ipa.c
index 94db53f59a..3804b1e239 100644
--- a/gdb/gdbserver/linux-aarch64-ipa.c
+++ b/gdb/gdbserver/linux-aarch64-ipa.c
@@ -147,12 +147,12 @@ get_raw_reg (const unsigned char *raw_regs, int regnum)
 
 /* Return target_desc to use for IPA, given the tdesc index passed by
    gdbserver.  Index is ignored, since we have only one tdesc
-   at the moment.  SVE not yet supported.  */
+   at the moment.  SVE and pauth not yet supported.  */
 
 const struct target_desc *
 get_ipa_tdesc (int idx)
 {
-  return aarch64_linux_read_description (0);
+  return aarch64_linux_read_description (0, false);
 }
 
 /* Allocate buffer for the jump pads.  The branch instruction has a reach
@@ -204,6 +204,6 @@ alloc_jump_pad_buffer (size_t size)
 void
 initialize_low_tracepoint (void)
 {
-  /* SVE not yet supported.  */
-  aarch64_linux_read_description (0);
+  /* SVE and pauth not yet supported.  */
+  aarch64_linux_read_description (0, false);
 }
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index 0b2946ea22..db329da4dc 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -501,7 +501,8 @@ aarch64_arch_setup (void)
   if (is_elf64)
     {
       uint64_t vq = aarch64_sve_get_vq (tid);
-      current_process ()->tdesc = aarch64_linux_read_description (vq);
+      /* pauth not yet supported.  */
+      current_process ()->tdesc = aarch64_linux_read_description (vq, false);
     }
   else
     current_process ()->tdesc = tdesc_arm_with_neon;
diff --git a/gdb/gdbserver/linux-aarch64-tdesc-selftest.c b/gdb/gdbserver/linux-aarch64-tdesc-selftest.c
index 1b2453aa30..bf24a27c59 100644
--- a/gdb/gdbserver/linux-aarch64-tdesc-selftest.c
+++ b/gdb/gdbserver/linux-aarch64-tdesc-selftest.c
@@ -29,7 +29,7 @@ namespace tdesc {
 static void
 aarch64_tdesc_test ()
 {
-  const target_desc *tdesc = aarch64_linux_read_description (0);
+  const target_desc *tdesc = aarch64_linux_read_description (0, false);
   SELF_CHECK (*tdesc == *tdesc_aarch64);
 }
 }
diff --git a/gdb/gdbserver/linux-aarch64-tdesc.c b/gdb/gdbserver/linux-aarch64-tdesc.c
index 6ab473ea51..6f9b4f1efc 100644
--- a/gdb/gdbserver/linux-aarch64-tdesc.c
+++ b/gdb/gdbserver/linux-aarch64-tdesc.c
@@ -24,22 +24,22 @@
 #include <inttypes.h>
 
 /* All possible aarch64 target descriptors.  */
-struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1];
+struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/];
 
 /* Create the aarch64 target description.  */
 
 const target_desc *
-aarch64_linux_read_description (uint64_t vq)
+aarch64_linux_read_description (uint64_t vq, bool pauth_p)
 {
   if (vq > AARCH64_MAX_SVE_VQ)
     error (_("VQ is %" PRIu64 ", maximum supported value is %d"), vq,
 	   AARCH64_MAX_SVE_VQ);
 
-  struct target_desc *tdesc = tdesc_aarch64_list[vq];
+  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p];
 
   if (tdesc == NULL)
     {
-      tdesc = aarch64_create_target_description (vq);
+      tdesc = aarch64_create_target_description (vq, pauth_p);
 
       static const char *expedite_regs_aarch64[] = { "x29", "sp", "pc", NULL };
       static const char *expedite_regs_aarch64_sve[] = { "x29", "sp", "pc",
@@ -50,7 +50,7 @@ aarch64_linux_read_description (uint64_t vq)
       else
 	init_target_desc (tdesc, expedite_regs_aarch64_sve);
 
-      tdesc_aarch64_list[vq] = tdesc;
+      tdesc_aarch64_list[vq][pauth_p] = tdesc;
     }
 
   return tdesc;
diff --git a/gdb/gdbserver/linux-aarch64-tdesc.h b/gdb/gdbserver/linux-aarch64-tdesc.h
index 7ce8150663..06b3ec9b1e 100644
--- a/gdb/gdbserver/linux-aarch64-tdesc.h
+++ b/gdb/gdbserver/linux-aarch64-tdesc.h
@@ -20,7 +20,7 @@
 #ifndef GDBSERVER_LINUX_AARCH64_TDESC_H
 #define GDBSERVER_LINUX_AARCH64_TDESC_H
 
-const target_desc * aarch64_linux_read_description (uint64_t vq);
+const target_desc * aarch64_linux_read_description (uint64_t vq, bool pauth_p);
 
 #if GDB_SELF_TEST
 void initialize_low_tdesc ();
-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 3/8] AArch64: Read pauth registers
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
@ 2019-03-06 13:33 ` Alan Hayward
  2019-03-21 20:56   ` Simon Marchi
  2019-03-06 13:33 ` [PATCH v2 2/8] AArch64: Use HWCAP to detect pauth feature Alan Hayward
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Alan Hayward @ 2019-03-06 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Initialise the pauth registers when creating a target description, and store
the regnum of the first pauth register.

Use ptrace to read the registers in the pauth feature.

Do not allow the registers to be written.

2019-03-06  Alan Hayward  <alan.hayward@arm.com>
	    Jiong Wang  <jiong.wang@arm.com>

	* aarch64-linux-nat.c (fetch_pauth_masks_from_thread): New
	function.
	(aarch64_linux_nat_target::fetch_registers): Read pauth registers.
	* aarch64-tdep.c (aarch64_cannot_store_register): New function.
	(aarch64_gdbarch_init): Add puth registers.
	* aarch64-tdep.h (struct gdbarch_tdep): Add pauth features.
	* arch/aarch64.h (AARCH64_PAUTH_DMASK_REGNUM): New define.
	(AARCH64_PAUTH_CMASK_REGNUM): Likewise.
---
 gdb/aarch64-linux-nat.c | 33 +++++++++++++++++++++++++++++++
 gdb/aarch64-tdep.c      | 43 +++++++++++++++++++++++++++++++++++++++++
 gdb/aarch64-tdep.h      |  8 ++++++++
 gdb/arch/aarch64.h      |  3 +++
 4 files changed, 87 insertions(+)

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 8a7006165e..094d4e1d1c 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -423,6 +423,31 @@ store_sveregs_to_thread (struct regcache *regcache)
     perror_with_name (_("Unable to store sve registers"));
 }
 
+/* Fill GDB's register array with the pointer authentication mask values from
+   the current thread.  */
+
+static void
+fetch_pauth_masks_from_thread (struct regcache *regcache)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
+  int ret;
+  struct iovec iovec;
+  uint64_t pauth_regset[2] = {0, 0};
+  int tid = regcache->ptid ().lwp ();
+
+  iovec.iov_base = &pauth_regset;
+  iovec.iov_len = sizeof (pauth_regset);
+
+  ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_PAC_MASK, &iovec);
+  if (ret != 0)
+    perror_with_name (_("unable to fetch pauth registers."));
+
+  regcache->raw_supply (AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base),
+			&pauth_regset[0]);
+  regcache->raw_supply (AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base),
+			&pauth_regset[1]);
+}
+
 /* Implement the "fetch_registers" target_ops method.  */
 
 void
@@ -438,6 +463,9 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
 	fetch_sveregs_from_thread (regcache);
       else
 	fetch_fpregs_from_thread (regcache);
+
+      if (tdep->has_pauth ())
+	fetch_pauth_masks_from_thread (regcache);
     }
   else if (regno < AARCH64_V0_REGNUM)
     fetch_gregs_from_thread (regcache);
@@ -445,6 +473,11 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
     fetch_sveregs_from_thread (regcache);
   else
     fetch_fpregs_from_thread (regcache);
+
+  if (tdep->has_pauth ())
+    if (regno == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base)
+	|| regno == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base))
+      fetch_pauth_masks_from_thread (regcache);
 }
 
 /* Implement the "store_registers" target_ops method.  */
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 0518837a1f..66fdd7bf05 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -175,6 +175,14 @@ static const char *const aarch64_sve_register_names[] =
   "ffr", "vg"
 };
 
+static const char *const aarch64_pauth_register_names[] =
+{
+  /* Authentication mask for data pointer.  */
+  "pauth_dmask",
+  /* Authentication mask for code pointer.  */
+  "pauth_cmask"
+};
+
 /* AArch64 prologue cache structure.  */
 struct aarch64_prologue_cache
 {
@@ -2936,6 +2944,21 @@ aarch64_add_reggroups (struct gdbarch *gdbarch)
   reggroup_add (gdbarch, restore_reggroup);
 }
 
+/* Implement the "cannot_store_register" gdbarch method.  */
+
+static int
+aarch64_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->has_pauth ())
+    return 0;
+
+  /* Pointer authentication registers are read-only.  */
+  return (regnum == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base)
+	  || regnum == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base));
+}
+
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
    architectures already created during this debugging session.
@@ -2956,8 +2979,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   const struct tdesc_feature *feature_core;
   const struct tdesc_feature *feature_fpu;
   const struct tdesc_feature *feature_sve;
+  const struct tdesc_feature *feature_pauth;
   int num_regs = 0;
   int num_pseudo_regs = 0;
+  int first_pauth_regnum = -1;
 
   /* Ensure we always have a target description.  */
   if (!tdesc_has_registers (tdesc))
@@ -2967,6 +2992,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.core");
   feature_fpu = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpu");
   feature_sve = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sve");
+  feature_pauth = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.pauth");
 
   if (feature_core == NULL)
     return NULL;
@@ -3021,6 +3047,21 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       num_pseudo_regs += 32;	/* add the Bn scalar register pseudos */
     }
 
+  /* Add the pauth registers.  */
+  if (feature_pauth != NULL)
+    {
+      first_pauth_regnum = num_regs;
+
+      /* Validate the descriptor provides the mandatory PAUTH registers and
+	 allocate their numbers.  */
+      for (i = 0; i < ARRAY_SIZE (aarch64_pauth_register_names); i++)
+	valid_p &= tdesc_numbered_register (feature_pauth, tdesc_data,
+					    first_pauth_regnum + i,
+					    aarch64_pauth_register_names[i]);
+
+      num_regs += i;
+    }
+
   if (!valid_p)
     {
       tdesc_data_cleanup (tdesc_data);
@@ -3054,6 +3095,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->jb_pc = -1;		/* Longjump support not enabled by default.  */
   tdep->jb_elt_size = 8;
   tdep->vq = aarch64_get_tdesc_vq (tdesc);
+  tdep->pauth_reg_base = first_pauth_regnum;
 
   set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
   set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
@@ -3084,6 +3126,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_tdesc_pseudo_register_type (gdbarch, aarch64_pseudo_register_type);
   set_tdesc_pseudo_register_reggroup_p (gdbarch,
 					aarch64_pseudo_register_reggroup_p);
+  set_gdbarch_cannot_store_register (gdbarch, aarch64_cannot_store_register);
 
   /* ABI */
   set_gdbarch_short_bit (gdbarch, 16);
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index 3db6bee9f3..f9fc8965f0 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -87,6 +87,14 @@ struct gdbarch_tdep
   {
     return vq != 0;
   }
+
+  int pauth_reg_base;
+
+  /* Returns true if the target supports pauth.  */
+  bool has_pauth () const
+  {
+    return pauth_reg_base != -1;
+  }
 };
 
 const target_desc *aarch64_read_description (uint64_t vq, bool pauth_p);
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index 4fe6d02f6e..8c80b7be62 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -66,6 +66,9 @@ enum aarch64_regnum
 #define AARCH64_B0_REGNUM (AARCH64_H0_REGNUM + 32)
 #define AARCH64_SVE_V0_REGNUM (AARCH64_B0_REGNUM + 32)
 
+#define AARCH64_PAUTH_DMASK_REGNUM(pauth_reg_base) (pauth_reg_base)
+#define AARCH64_PAUTH_CMASK_REGNUM(pauth_reg_base) (pauth_reg_base + 1)
+
 #define AARCH64_X_REGS_NUM 31
 #define AARCH64_V_REGS_NUM 32
 #define AARCH64_SVE_Z_REGS_NUM AARCH64_V_REGS_NUM
-- 
2.17.2 (Apple Git-113)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 1/8] AArch64: Add pointer authentication feature
  2019-03-06 13:33 ` [PATCH v2 1/8] AArch64: Add pointer authentication feature Alan Hayward
@ 2019-03-06 15:36   ` Eli Zaretskii
  0 siblings, 0 replies; 16+ messages in thread
From: Eli Zaretskii @ 2019-03-06 15:36 UTC (permalink / raw)
  To: Alan Hayward; +Cc: gdb-patches, nd

> From: Alan Hayward <Alan.Hayward@arm.com>
> CC: nd <nd@arm.com>, Alan Hayward <Alan.Hayward@arm.com>
> Date: Wed, 6 Mar 2019 13:33:34 +0000
> 
> gdb/doc/ChangeLog:
> 
> 2019-03-06  Alan Hayward  <alan.hayward@arm.com>
> 	    Jiong Wang  <jiong.wang@arm.com>
> 
> 	* gdb.texinfo: Describe pauth feature.

This part is OK, but please mention the name of the node where you are
making the changes, as if it were a function.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 0/8] Support for AArch64 Pointer Authentication
  2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
                   ` (7 preceding siblings ...)
  2019-03-06 13:33 ` [PATCH v2 5/8] AArch64: Add pauth DWARF registers Alan Hayward
@ 2019-03-14 12:34 ` Alan Hayward
  2019-03-21 21:29   ` Simon Marchi
  8 siblings, 1 reply; 16+ messages in thread
From: Alan Hayward @ 2019-03-14 12:34 UTC (permalink / raw)
  To: GDB Patches; +Cc: nd

Ping for this.
Hopefully most of this is just standard boiler plate code, with detailed
bits in the two unwinder patches, and some common code changes in the
gdbserver patch.


Alan.


> On 6 Mar 2019, at 13:33, Alan Hayward <Alan.Hayward@arm.com> wrote:
> 
> Pointer Authentication is a new feature in AArch64 v8.3-a. When enabled in
> the compiler, function return addresses will be mangled by the kernel. This
> set of patches adds support to add the new registers and umangle addresses
> to allow the unwinder to work.
> 
> Linux Kernel support is in Linux 5.0, and was added here:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=04ca3204fa09f5f55c8f113b0072004a7b364ff4
> 
> Binutils support was added earlier this year:
> https://www.sourceware.org/ml/binutils/2019-02/msg00069.html
> 
> GCC support is in GCC 7.1.1 and is enabled by default when building for
> 8.3-a, originally added here:
> https://gcc.gnu.org/ml/gcc-patches/2017-01/msg00376.html
> Additional support is in progress, see:
> https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00697.html
> 
> 
> This patch series has been tested on an 8.3 Fast Model running head Linux,
> using both head GCC and GCC patched with the additional support.
> 
> This series is a reworking of the series originally posted by Jiong:
> https://sourceware.org/ml/gdb-patches/2017-08/msg00170.html
> 
> Patches 1-5 add the new feature, register support and feature detection.
> Patches 6 and 7 add the address unmangling.
> Patch 8 adds core file support.
> 
> 
> Alan Hayward (8):
>  AArch64: Add pointer authentication feature
>  AArch64: Use HWCAP to detect pauth feature
>  AArch64: Read pauth registers
>  AArch64: gdbserver: read pauth registers
>  AArch64: Add pauth DWARF registers
>  AArch64: DWARF unwinder support for signed return addresses
>  AArch64: Prologue scan unwinder support for signed return addresses
>  AArch64: Read pauth section from core files
> 
> gdb/aarch64-linux-nat.c                      |  41 ++-
> gdb/aarch64-linux-tdep.c                     |  36 +-
> gdb/aarch64-linux-tdep.h                     |   9 +
> gdb/aarch64-tdep.c                           | 325 ++++++++++++++++---
> gdb/aarch64-tdep.h                           |  14 +-
> gdb/arch/aarch64.c                           |   6 +-
> gdb/arch/aarch64.h                           |   9 +-
> gdb/doc/gdb.texinfo                          |   3 +
> gdb/features/Makefile                        |   1 +
> gdb/features/aarch64-pauth.c                 |  16 +
> gdb/features/aarch64-pauth.xml               |  13 +
> gdb/gdbserver/linux-aarch64-ipa.c            |   8 +-
> gdb/gdbserver/linux-aarch64-low.c            |  55 +++-
> gdb/gdbserver/linux-aarch64-tdesc-selftest.c |   2 +-
> gdb/gdbserver/linux-aarch64-tdesc.c          |  10 +-
> gdb/gdbserver/linux-aarch64-tdesc.h          |   2 +-
> gdb/gdbserver/linux-low.c                    |  14 +-
> gdb/gdbserver/linux-low.h                    |   1 +
> 18 files changed, 491 insertions(+), 74 deletions(-)
> create mode 100644 gdb/features/aarch64-pauth.c
> create mode 100644 gdb/features/aarch64-pauth.xml
> 
> -- 
> 2.17.2 (Apple Git-113)
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 2/8] AArch64: Use HWCAP to detect pauth feature
  2019-03-06 13:33 ` [PATCH v2 2/8] AArch64: Use HWCAP to detect pauth feature Alan Hayward
@ 2019-03-21 20:51   ` Simon Marchi
  2019-03-22 12:06     ` Alan Hayward
  0 siblings, 1 reply; 16+ messages in thread
From: Simon Marchi @ 2019-03-21 20:51 UTC (permalink / raw)
  To: Alan Hayward, gdb-patches; +Cc: nd

On 2019-03-06 8:33 a.m., Alan Hayward wrote:
> Add aarch64_get_hwcap functions for reading the HWCAP.
>  From this extract the PACA value and use this to enable pauth.
> 
> gdb/ChangeLog:
> 
> 2019-03-06  Alan Hayward  <alan.hayward@arm.com>
> 	    Jiong Wang  <jiong.wang@arm.com>
> 
> 	* aarch64-linux-nat.c
> 	(aarch64_linux_nat_target::read_description): Read PACA hwcap.
> 	* aarch64-linux-tdep.c
> 	(aarch64_linux_core_read_description): Likewise.
> 	(aarch64_linux_get_hwcap): New function.
> 	* aarch64-linux-tdep.h (AARCH64_HWCAP_PACA): New define.
> 	(aarch64_linux_get_hwcap): New declaration.
> 
> gdb/gdbserver/ChangeLog:
> 
> 2019-03-06  Alan Hayward  <alan.hayward@arm.com>
> 	    Jiong Wang  <jiong.wang@arm.com>
> 
> 	* linux-aarch64-low.c (AARCH64_HWCAP_PACA): New define.
> 	(aarch64_get_hwcap): New function.
> 	(aarch64_arch_setup): Read APIA hwcap.
> ---
>   gdb/aarch64-linux-nat.c           |  7 +++++--
>   gdb/aarch64-linux-tdep.c          | 16 +++++++++++----
>   gdb/aarch64-linux-tdep.h          |  6 ++++++
>   gdb/gdbserver/linux-aarch64-low.c | 33 +++++++++++++++++++++++++++++--
>   4 files changed, 54 insertions(+), 8 deletions(-)
> 
> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index f58a41e195..8a7006165e 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -606,8 +606,11 @@ aarch64_linux_nat_target::read_description ()
>     if (ret == 0)
>       return tdesc_arm_with_neon;
>   
> -  /* pauth not yet supported.  */
> -  return aarch64_read_description (aarch64_sve_get_vq (tid), false);
> +  CORE_ADDR hwcap = 0;
> +  bool pauth_p = aarch64_linux_get_hwcap (&hwcap)
> +		 && (hwcap & AARCH64_HWCAP_PACA);
> +
> +  return aarch64_read_description (aarch64_sve_get_vq (tid), pauth_p);
>   }
>   
>   /* Convert a native/host siginfo object, into/from the siginfo in the
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index 445019accc..5eeafa456c 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -637,12 +637,11 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
>   {
>     CORE_ADDR aarch64_hwcap = 0;
>   
> -  if (target_auxv_search (target, AT_HWCAP, &aarch64_hwcap) != 1)
> -    return NULL;
> +  if (!aarch64_linux_get_hwcap (&aarch64_hwcap))
> +    return nullptr;
>   
> -  /* pauth not yet supported.  */
>     return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd),
> -				   false);
> +				   aarch64_hwcap & AARCH64_HWCAP_PACA);
>   }
>   
>   /* Implementation of `gdbarch_stap_is_single_operand', as defined in
> @@ -1420,6 +1419,15 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
>     return NULL;
>   }
>   
> +/* See aarch64-linux-tdep.h.  */
> +
> +bool
> +aarch64_linux_get_hwcap (CORE_ADDR *hwcap)
> +{
> +  *hwcap = 0;
> +  return target_auxv_search (current_top_target (), AT_HWCAP, hwcap) == 1;
> +}
> +

I don't know if it actually matters, but when the target_aux_search call 
was in aarch64_linux_core_read_description, it used the TARGET 
parameter, rather than using current_top_target.  So, perhaps that new 
function should take a target_ops parameter and use it?  The other call 
in aarch64_linux_nat_target::read_description would pass "this".

And this function does nothing AArch64-specific, so I think it would be 
nice to have it in linux-tdep.{h,c} and update other arches to use it. 
But I would say, don't bother with that in this series, we can do it after.

Simon

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 3/8] AArch64: Read pauth registers
  2019-03-06 13:33 ` [PATCH v2 3/8] AArch64: Read pauth registers Alan Hayward
@ 2019-03-21 20:56   ` Simon Marchi
  0 siblings, 0 replies; 16+ messages in thread
From: Simon Marchi @ 2019-03-21 20:56 UTC (permalink / raw)
  To: Alan Hayward, gdb-patches; +Cc: nd

On 2019-03-06 8:33 a.m., Alan Hayward wrote:
> @@ -445,6 +473,11 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
>       fetch_sveregs_from_thread (regcache);
>     else
>       fetch_fpregs_from_thread (regcache);
> +
> +  if (tdep->has_pauth ())
> +    if (regno == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base)
> +	|| regno == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base))
> +      fetch_pauth_masks_from_thread (regcache);
>   }

Just this nit:

The "outer" if should have curly braces.

Ref: 
https://www.gnu.org/prep/standards/html_node/Syntactic-Conventions.html#Syntactic-Conventions

Simon

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 4/8] AArch64: gdbserver: read pauth registers
  2019-03-06 13:33 ` [PATCH v2 4/8] AArch64: gdbserver: read pauth registers Alan Hayward
@ 2019-03-21 21:03   ` Simon Marchi
  0 siblings, 0 replies; 16+ messages in thread
From: Simon Marchi @ 2019-03-21 21:03 UTC (permalink / raw)
  To: Alan Hayward, gdb-patches; +Cc: nd

On 2019-03-06 8:33 a.m., Alan Hayward wrote:
> Add the pauth registers to the regset lists.
> 
> Add a new regset type OPTIONAL_REGS which allows for the regset read to fail.
> Once the read fails, it will not be checked again.  This allows targets with
> optional features to keep a single static regset_info structure.

The change in the gdbserver common looks fine to me.

Simon

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 0/8] Support for AArch64 Pointer Authentication
  2019-03-14 12:34 ` [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
@ 2019-03-21 21:29   ` Simon Marchi
  0 siblings, 0 replies; 16+ messages in thread
From: Simon Marchi @ 2019-03-21 21:29 UTC (permalink / raw)
  To: Alan Hayward, GDB Patches; +Cc: nd

On 2019-03-14 8:34 a.m., Alan Hayward wrote:
> Ping for this.
> Hopefully most of this is just standard boiler plate code, with detailed
> bits in the two unwinder patches, and some common code changes in the
> gdbserver patch.

Hi Alan,

The common gdbserver part looks good to me.  I glanced over the rest, 
and it looks good to me as well, I sent some minor comments on a few 
patches.

Simon

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 2/8] AArch64: Use HWCAP to detect pauth feature
  2019-03-21 20:51   ` Simon Marchi
@ 2019-03-22 12:06     ` Alan Hayward
  0 siblings, 0 replies; 16+ messages in thread
From: Alan Hayward @ 2019-03-22 12:06 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches, nd



> On 21 Mar 2019, at 20:50, Simon Marchi <simark@simark.ca> wrote:
> 
> On 2019-03-06 8:33 a.m., Alan Hayward wrote:
>> Add aarch64_get_hwcap functions for reading the HWCAP.
>> From this extract the PACA value and use this to enable pauth.
>> gdb/ChangeLog:
>> 

<snip>

>> +
> 
> I don't know if it actually matters, but when the target_aux_search call was in aarch64_linux_core_read_description, it used the TARGET parameter, rather than using current_top_target.  So, perhaps that new function should take a target_ops parameter and use it?  The other call in aarch64_linux_nat_target::read_description would pass "this”.

For safety I’ve updated it to pass through the target.

> 
> And this function does nothing AArch64-specific, so I think it would be nice to have it in linux-tdep.{h,c} and update other arches to use it. But I would say, don't bother with that in this series, we can do it after.
> 
> Simon

Agreed. And the gdbserver version should probably be moved into common code too. I’ll get a new patch together for that.


Thanks for the reviews. Pushed the series. Updated version of this patch below.


diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index f58a41e195..9572055d9f 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -606,8 +606,11 @@ aarch64_linux_nat_target::read_description ()
   if (ret == 0)
     return tdesc_arm_with_neon;

-  /* pauth not yet supported.  */
-  return aarch64_read_description (aarch64_sve_get_vq (tid), false);
+  CORE_ADDR hwcap = 0;
+  bool pauth_p = aarch64_linux_get_hwcap (this, &hwcap)
+                && (hwcap & AARCH64_HWCAP_PACA);
+
+  return aarch64_read_description (aarch64_sve_get_vq (tid), pauth_p);
 }

 /* Convert a native/host siginfo object, into/from the siginfo in the
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 445019accc..d7db23ef38 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -637,12 +637,11 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
 {
   CORE_ADDR aarch64_hwcap = 0;

-  if (target_auxv_search (target, AT_HWCAP, &aarch64_hwcap) != 1)
-    return NULL;
+  if (!aarch64_linux_get_hwcap (target, &aarch64_hwcap))
+    return nullptr;

-  /* pauth not yet supported.  */
   return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd),
-                                  false);
+                                  aarch64_hwcap & AARCH64_HWCAP_PACA);
 }

 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
@@ -1420,6 +1419,15 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
   return NULL;
 }

+/* See aarch64-linux-tdep.h.  */
+
+bool
+aarch64_linux_get_hwcap (struct target_ops *target, CORE_ADDR *hwcap)
+{
+  *hwcap = 0;
+  return target_auxv_search (target, AT_HWCAP, hwcap) == 1;
+}
+
 static void
 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index 814222ead0..e9f7c9bccf 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -36,4 +36,10 @@
 extern const struct regset aarch64_linux_gregset;
 extern const struct regset aarch64_linux_fpregset;

+/* Matches HWCAP_PACA in kernel header arch/arm64/include/uapi/asm/hwcap.h.  */
+#define AARCH64_HWCAP_PACA (1 << 30)
+
+/* Fetch the AT_HWCAP entry from the auxv vector for the given TARGET.  */
+bool aarch64_linux_get_hwcap (struct target_ops *target, CORE_ADDR *hwcap);
+
 #endif /* AARCH64_LINUX_TDEP_H */
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index db329da4dc..e2e25f0e27 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -485,6 +485,33 @@ aarch64_linux_new_fork (struct process_info *parent,
   *child->priv->arch_private = *parent->priv->arch_private;
 }

+/* Matches HWCAP_PACA in kernel header arch/arm64/include/uapi/asm/hwcap.h.  */
+#define AARCH64_HWCAP_PACA (1 << 30)
+
+/* Fetch the AT_HWCAP entry from the auxv vector.  */
+
+static bool
+aarch64_get_hwcap (unsigned long *valp)
+{
+  unsigned char *data = (unsigned char *) alloca (16);
+  int offset = 0;
+
+  while ((*the_target->read_auxv) (offset, data, 16) == 16)
+    {
+      unsigned long *data_p = (unsigned long *)data;
+      if (data_p[0] == AT_HWCAP)
+       {
+         *valp = data_p[1];
+         return true;
+       }
+
+      offset += 16;
+    }
+
+  *valp = 0;
+  return false;
+}
+
 /* Implementation of linux_target_ops method "arch_setup".  */

 static void
@@ -501,8 +528,10 @@ aarch64_arch_setup (void)
   if (is_elf64)
     {
       uint64_t vq = aarch64_sve_get_vq (tid);
-      /* pauth not yet supported.  */
-      current_process ()->tdesc = aarch64_linux_read_description (vq, false);
+      unsigned long hwcap = 0;
+      bool pauth_p = aarch64_get_hwcap (&hwcap) && (hwcap & AARCH64_HWCAP_PACA);
+
+      current_process ()->tdesc = aarch64_linux_read_description (vq, pauth_p);
     }
   else
     current_process ()->tdesc = tdesc_arm_with_neon;

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2019-03-22 12:06 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-06 13:33 [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
2019-03-06 13:33 ` [PATCH v2 3/8] AArch64: Read pauth registers Alan Hayward
2019-03-21 20:56   ` Simon Marchi
2019-03-06 13:33 ` [PATCH v2 2/8] AArch64: Use HWCAP to detect pauth feature Alan Hayward
2019-03-21 20:51   ` Simon Marchi
2019-03-22 12:06     ` Alan Hayward
2019-03-06 13:33 ` [PATCH v2 6/8] AArch64: DWARF unwinder support for signed return addresses Alan Hayward
2019-03-06 13:33 ` [PATCH v2 4/8] AArch64: gdbserver: read pauth registers Alan Hayward
2019-03-21 21:03   ` Simon Marchi
2019-03-06 13:33 ` [PATCH v2 7/8] AArch64: Prologue scan unwinder support for signed return addresses Alan Hayward
2019-03-06 13:33 ` [PATCH v2 8/8] AArch64: Read pauth section from core files Alan Hayward
2019-03-06 13:33 ` [PATCH v2 1/8] AArch64: Add pointer authentication feature Alan Hayward
2019-03-06 15:36   ` Eli Zaretskii
2019-03-06 13:33 ` [PATCH v2 5/8] AArch64: Add pauth DWARF registers Alan Hayward
2019-03-14 12:34 ` [PATCH v2 0/8] Support for AArch64 Pointer Authentication Alan Hayward
2019-03-21 21:29   ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).