Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature
@ 2026-06-26 18:08 srinath.parvathaneni
  2026-06-26 18:08 ` [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni
                   ` (7 more replies)
  0 siblings, 8 replies; 21+ messages in thread
From: srinath.parvathaneni @ 2026-06-26 18:08 UTC (permalink / raw)
  To: gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, guinevere, Ezra.Sitorus,
	Matthieu.Longo, Srinath Parvathaneni

From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

Thanks Matthieu, Ezra and Luis for the reviews.

Changes v1 -> v2:

* Rebased the SIGSEGV diagnostic support on Matthieu Longo's generic
  "siginfo_t" changes, using the new "_._addr_pkey.si_pkey" layout
  instead of introducing a target-specific "siginfo_t" extension.

* Split the original series into smaller, subsystem-specific patches:
  * GDB register support
  * POR_EL0 pretty printing
  * SIGSEGV diagnostics
  * gdbserver support
  * BFD/readelf core file support
  * GDB core file support
  * Testsuite

* Separated BFD/readelf and GDB core file support into independent
  patches.

* Retained FEAT_S1POE expansion as "Permission Overlay Extension" after internal discussion.

* Removed the POR_EL0 permission decoding string (e.g. `por_el0[pkey=<value>] = rwx`) from
  SIGSEGV diagnostics, as displaying permissions without also showing base and effective
  permissions can be misleading to users.

* Rebased the series onto current upstream master + Matthieu's patch
  "gdb: align siginfo_t with the Linux kernel definition"

----------------
Hi,

This series adds support for the AArch64 Permission Overlay Extension
(FEAT_S1POE) in GDB, gdbserver, BFD and the testsuite.

The series introduces support for the POR_EL0 register, allowing GDB to
read and write the register using the Linux "NT_ARM_POE" regset. It also
improves SIGSEGV diagnostics for Permission Overlay violations and
extends gdbserver and core file handling to preserve POR_EL0 during
remote debugging and core file analysis.

The series consists of the following patches:

[1/7] gdb/aarch64: Add POR_EL0 register support
Add POR_EL0 to the AArch64 register set and support reading and
writing the register using the Linux "NT_ARM_POE" regset.

[2/7] gdb/aarch64: Add custom printing for POR_EL0
Add custom printing support for the POR_EL0 register.

[3/7] gdb: Improve SIGSEGV diagnostics for POE faults
Report the faulting address together with the associated
protection key for Permission Overlay violations.

[4/7] gdbserver/aarch64: Add POR_EL0 register support
Transfer POR_EL0 through the Linux "NT_ARM_POE" regset during
remote debugging.

[5/7] bfd/readelf: Add core file support for FEAT_S1POE
Add support for the "NT_ARM_POE" core file note.

[6/7] gdb/aarch64: Add core file support for FEAT_S1POE
Restore POR_EL0 from core files.

[7/7] gdb/testsuite: Add FEAT_S1POE testcases
Add tests covering register access, SIGSEGV diagnostics,
fix-and-continue, and core file support.

The series has been tested natively and using gdbserver with
remote GDB on an FVP built using shrinkwrap with a Linux kernel
configured with "CONFIG_ARM64_POE=y" and a glibc version
providing userspace POE support.

Regression tested on aarch64-none-linux-gnu with no regressions.

Ok for Binutils-GDB ?

Regards,
Srinath

Srinath Parvathaneni (7):
  gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
  gdb/aarch64: Add custom printing for POR_EL0
  gdb: Improve SIGSEGV diagnostics for POE faults
  gdbserver/aarch64: Add POR_EL0 register support
  bfd/readelf: Add core file support for FEAT_S1POE
  gdb/aarch64: Add core file support for FEAT_S1POE
  gdb/testsuite: Add FEAT_S1POE testcases

 bfd/elf.c                                     |  25 +++++
 binutils/readelf.c                            |   2 +
 gdb/Makefile.in                               |   2 +
 gdb/aarch64-linux-nat.c                       |  66 +++++++++++
 gdb/aarch64-linux-tdep.c                      |  72 +++++++++++-
 gdb/aarch64-tdep.c                            | 104 ++++++++++++++++++
 gdb/aarch64-tdep.h                            |  11 +-
 gdb/arch/aarch64-poe-linux.h                  |  29 +++++
 gdb/arch/aarch64.c                            |   4 +
 gdb/arch/aarch64.h                            |   7 +-
 gdb/features/Makefile                         |   1 +
 gdb/features/aarch64-poe.c                    |  14 +++
 gdb/features/aarch64-poe.xml                  |  12 ++
 gdb/nat/aarch64-poe-linux.h                   |  28 +++++
 gdb/testsuite/gdb.arch/aarch64-poe-core.exp   | 102 +++++++++++++++++
 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c  |  52 +++++++++
 .../gdb.arch/aarch64-poe-sigsegv.exp          |  60 ++++++++++
 gdb/testsuite/gdb.arch/aarch64-poe.c          |  29 +++++
 gdb/testsuite/gdb.arch/aarch64-poe.exp        |  44 ++++++++
 gdb/testsuite/lib/gdb.exp                     |  55 +++++++++
 gdbserver/linux-aarch64-low.cc                |  30 +++++
 include/elf/common.h                          |   2 +
 22 files changed, 746 insertions(+), 5 deletions(-)
 create mode 100644 gdb/arch/aarch64-poe-linux.h
 create mode 100644 gdb/features/aarch64-poe.c
 create mode 100644 gdb/features/aarch64-poe.xml
 create mode 100644 gdb/nat/aarch64-poe-linux.h
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-core.exp
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.c
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.exp

-- 
2.43.0


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

* [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
  2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
@ 2026-06-26 18:08 ` srinath.parvathaneni
  2026-06-27  6:06   ` Thiago Jung Bauermann
  2026-06-26 18:08 ` [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0 srinath.parvathaneni
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: srinath.parvathaneni @ 2026-06-26 18:08 UTC (permalink / raw)
  To: gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, guinevere, Ezra.Sitorus,
	Matthieu.Longo, Srinath Parvathaneni

From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

Add support for the FEAT_S1POE POR_EL0 register on AArch64.

This patch adds POR_EL0 to the AArch64 register set and reads/writes it
using the NT_ARM_POE ptrace regset.

With this change, POR_EL0 is available through:
*  info registers
*  info registers por_el0
*  p $por_el0
*  p/x $por_el0
*  set $por_el0 = <value>
---
 gdb/Makefile.in              |  2 ++
 gdb/aarch64-linux-nat.c      | 66 ++++++++++++++++++++++++++++++++++++
 gdb/aarch64-linux-tdep.c     |  1 +
 gdb/aarch64-tdep.c           | 18 ++++++++++
 gdb/aarch64-tdep.h           | 11 +++++-
 gdb/arch/aarch64-poe-linux.h | 29 ++++++++++++++++
 gdb/arch/aarch64.c           |  4 +++
 gdb/arch/aarch64.h           |  7 +++-
 gdb/features/Makefile        |  1 +
 gdb/features/aarch64-poe.c   | 14 ++++++++
 gdb/features/aarch64-poe.xml | 12 +++++++
 gdb/nat/aarch64-poe-linux.h  | 28 +++++++++++++++
 include/elf/common.h         |  2 ++
 13 files changed, 193 insertions(+), 2 deletions(-)
 create mode 100644 gdb/arch/aarch64-poe-linux.h
 create mode 100644 gdb/features/aarch64-poe.c
 create mode 100644 gdb/features/aarch64-poe.xml
 create mode 100644 gdb/nat/aarch64-poe-linux.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 57f384170ab..3dc9cd07dcb 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1292,6 +1292,7 @@ HFILES_NO_SRCDIR = \
 	arch/aarch32.h \
 	arch/aarch64-fpmr-linux.h \
 	arch/aarch64-gcs-linux.h \
+	arch/aarch64-poe-linux.h \
 	arch/aarch64.h \
 	arch/aarch64-insn.h \
 	arch/aarch64-mte.h \
@@ -1540,6 +1541,7 @@ HFILES_NO_SRCDIR = \
 	namespace.h \
 	nat/aarch64-fpmr-linux.h \
 	nat/aarch64-gcs-linux.h \
+	nat/aarch64-poe-linux.h \
 	nat/aarch64-hw-point.h \
 	nat/aarch64-linux.h \
 	nat/aarch64-linux-hw-point.h \
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 52ace4aab41..54265920d69 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -34,6 +34,7 @@
 #include "arch/arm.h"
 #include "nat/aarch64-fpmr-linux.h"
 #include "nat/aarch64-gcs-linux.h"
+#include "nat/aarch64-poe-linux.h"
 #include "nat/aarch64-linux.h"
 #include "nat/aarch64-linux-hw-point.h"
 #include "nat/aarch64-mte-linux-ptrace.h"
@@ -569,6 +570,54 @@ fetch_gcsregs_from_thread (regcache *regcache)
 			&user_gcs.features_locked);
 }
 
+/* Fill GDB's register array with the POE register value from the current
+   thread.  */
+
+static void
+fetch_poeregs_from_thread (regcache *regcache)
+{
+  aarch64_gdbarch_tdep *tdep
+    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+  gdb_assert (tdep->has_poe ());
+
+  uint64_t user_poe;
+  iovec iovec;
+
+  iovec.iov_base = &user_poe;
+  iovec.iov_len = sizeof (user_poe);
+
+  int tid = get_ptrace_pid (regcache->ptid ());
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_POE, &iovec) != 0)
+    perror_with_name (_("Unable to fetch POE register"));
+
+  regcache->raw_supply (tdep->poe_regnum, &user_poe);
+}
+
+/* Store the NT_ARM_POE register contents from GDB's REGCACHE to the
+    thread associated with REGCACHE.  */
+
+static void
+store_poeregs_to_thread (struct regcache *regcache)
+{
+  aarch64_gdbarch_tdep *tdep
+    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+  gdb_assert (tdep->has_poe ());
+
+  int tid = regcache->ptid ().lwp ();
+
+  iovec iovec;
+  uint64_t user_poe;
+  iovec.iov_base = &user_poe;
+  iovec.iov_len = sizeof (user_poe);
+
+  regcache->raw_collect (tdep->poe_regnum, &user_poe);
+
+  if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_POE, &iovec) != 0)
+    perror_with_name (_("Unable to store POE register"));
+}
+
 /* Store to the current thread the valid GCS register set in the GDB's
    register array.  */
 
@@ -683,6 +732,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
       if (tdep->has_gcs_linux ())
 	fetch_gcsregs_from_thread (regcache);
 
+      if (tdep->has_poe ())
+	fetch_poeregs_from_thread (regcache);
+
       if (tdep->has_fpmr ())
 	fetch_fpmr_from_thread (regcache);
     }
@@ -722,6 +774,10 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
 	   && (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base
 	       || regno == tdep->gcs_linux_reg_base + 1))
     fetch_gcsregs_from_thread (regcache);
+  /* POE register?  */
+  else if (tdep->has_poe () && (regno == tdep->poe_regnum))
+    fetch_poeregs_from_thread (regcache);
+
   /* FPMR?  */
   else if (tdep->has_fpmr () && (regno == tdep->fpmr_regnum))
     fetch_fpmr_from_thread (regcache);
@@ -802,6 +858,9 @@ aarch64_store_registers (struct regcache *regcache, int regno)
 
       if (tdep->has_fpmr ())
 	store_fpmr_to_thread (regcache);
+
+      if (tdep->has_poe ())
+	store_poeregs_to_thread (regcache);
     }
   /* General purpose register?  */
   else if (regno < AARCH64_V0_REGNUM)
@@ -837,6 +896,10 @@ aarch64_store_registers (struct regcache *regcache, int regno)
   else if (tdep->has_fpmr () && regno == tdep->fpmr_regnum)
     store_fpmr_to_thread (regcache);
 
+  /* POE register?  */
+  else if (tdep->has_poe () && regno == tdep->poe_regnum)
+    store_poeregs_to_thread (regcache);
+
   /* PAuth registers are read-only.  */
 }
 
@@ -1024,6 +1087,9 @@ aarch64_linux_nat_target::read_description ()
   /* Check for FPMR.  */
   features.fpmr = hwcap2 & HWCAP2_FPMR;
 
+  /* Check for POE support.  */
+  features.poe = hwcap2 & HWCAP2_POE;
+
   return aarch64_read_description (features);
 }
 
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index f11eccc1bc1..4a6bc3158c8 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -53,6 +53,7 @@
 
 #include "arch/aarch64-fpmr-linux.h"
 #include "arch/aarch64-gcs-linux.h"
+#include "arch/aarch64-poe-linux.h"
 #include "arch/aarch64-mte.h"
 #include "arch/aarch64-mte-linux.h"
 #include "arch/aarch64-pauth-linux.h"
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 886e7ce1e7b..f1e1a9c7a19 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -164,6 +164,11 @@ static const char *const aarch64_gcs_register_names[] = {
   "gcspr"
 };
 
+static const char *const aarch64_poe_register_names[] = {
+  /* Permission Overlay Extension Register.  */
+  "por_el0"
+};
+
 static const char *const aarch64_gcs_linux_register_names[] = {
   /* Field in struct user_gcs.  */
   "gcs_features_enabled",
@@ -4556,6 +4561,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 					  fpmr_regnum, "fpmr");
     }
 
+  int poe_regnum = -1;
+  const struct tdesc_feature *feature_poe
+      = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe");
+  if (feature_poe != nullptr)
+    {
+      poe_regnum = num_regs;
+      for (i = 0; i < ARRAY_SIZE (aarch64_poe_register_names); i++)
+	valid_p &= tdesc_numbered_register (feature_poe, tdesc_data.get (),
+					    poe_regnum + i,
+					    aarch64_poe_register_names[i]);
+      num_regs++;
+    }
+
   int first_sme_regnum = -1;
   int first_sme2_regnum = -1;
   int first_sme_pseudo_regnum = -1;
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index dff05a08f84..8029725b145 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -208,6 +208,16 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base
     return gcs_linux_reg_base != -1;
   }
 
+  /* POE register.  This is -1 if no POE feature is available.  */
+  int poe_regnum = -1;
+
+  /* Returns true if the target supports the Linux POE feature.  */
+  bool
+  has_poe () const
+  {
+    return poe_regnum != -1;
+  }
+
   /* First FPMR register.  This is -1 if FPMR is not supported.  */
   int fpmr_regnum = -1;
 
@@ -224,7 +234,6 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc);
 
 extern int aarch64_process_record (struct gdbarch *gdbarch,
 			       struct regcache *regcache, CORE_ADDR addr);
-
 displaced_step_copy_insn_closure_up
   aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
 				    CORE_ADDR from, CORE_ADDR to,
diff --git a/gdb/arch/aarch64-poe-linux.h b/gdb/arch/aarch64-poe-linux.h
new file mode 100644
index 00000000000..d6e4a001cbf
--- /dev/null
+++ b/gdb/arch/aarch64-poe-linux.h
@@ -0,0 +1,29 @@
+/* Common Linux target-dependent definitions for AArch64 POE
+
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_ARCH_AARCH64_POE_LINUX_H
+#define GDB_ARCH_AARCH64_POE_LINUX_H
+
+/* Feature check for Permission Overlay Extension.  */
+#define AARCH64_HWCAP2_POE (1ULL << 63)
+
+/* Data or instruction abort caused by Protection Key Violation.  */
+#define AARCH64_SEGV_PKUERR 4
+
+#endif /* GDB_ARCH_AARCH64_POE_LINUX_H */
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index 2401a325b7b..a567938d06d 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -28,6 +28,7 @@
 #include "../features/aarch64-sme2.c"
 #include "../features/aarch64-tls.c"
 #include "../features/aarch64-gcs.c"
+#include "../features/aarch64-poe.c"
 #include "../features/aarch64-gcs-linux.c"
 
 /* See arch/aarch64.h.  */
@@ -77,6 +78,9 @@ aarch64_create_target_description (const aarch64_features &features)
   if (features.fpmr)
     regnum = create_feature_aarch64_fpmr (tdesc.get (), regnum);
 
+  if (features.poe)
+    regnum = create_feature_aarch64_poe (tdesc.get (), regnum);
+
   return tdesc;
 }
 
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index cf7318cbe74..4e4b50f729e 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -35,6 +35,7 @@ struct aarch64_features
   bool pauth = false;
   bool mte = false;
   bool fpmr = false;
+  bool poe = false;
 
   /* A positive TLS value indicates the number of TLS registers available.  */
   uint8_t tls = 0;
@@ -70,7 +71,8 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs)
     && lhs.sme2 == rhs.sme2
     && lhs.gcs == rhs.gcs
     && lhs.gcs_linux == rhs.gcs_linux
-    && lhs.fpmr == rhs.fpmr;
+    && lhs.fpmr == rhs.fpmr
+    && lhs.poe == rhs.poe;
 }
 
 namespace std
@@ -103,6 +105,9 @@ namespace std
 
       /* FPMR feature.  */
       h = h << 1 | features.fpmr;
+
+      /* POE feature.  */
+      h = h << 1 | features.poe;
       return h;
     }
   };
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 161a7453d66..cc77e5bb652 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -207,6 +207,7 @@ FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-pauth.xml \
 	aarch64-mte.xml \
 	aarch64-gcs.xml \
+	aarch64-poe.xml \
 	aarch64-gcs-linux.xml \
 	arc/v1-core.xml \
 	arc/v1-aux.xml \
diff --git a/gdb/features/aarch64-poe.c b/gdb/features/aarch64-poe.c
new file mode 100644
index 00000000000..e964a625173
--- /dev/null
+++ b/gdb/features/aarch64-poe.c
@@ -0,0 +1,14 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aarch64-poe.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_aarch64_poe (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.poe");
+  tdesc_create_reg (feature, "por_el0", regnum++, 1, "system", 64, "uint64");
+  return regnum;
+}
diff --git a/gdb/features/aarch64-poe.xml b/gdb/features/aarch64-poe.xml
new file mode 100644
index 00000000000..43ee09e01d6
--- /dev/null
+++ b/gdb/features/aarch64-poe.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2026 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.poe">
+
+  <reg name="por_el0" bitsize="64" type="uint64" group="system"/>
+</feature>
diff --git a/gdb/nat/aarch64-poe-linux.h b/gdb/nat/aarch64-poe-linux.h
new file mode 100644
index 00000000000..3d858d3ff92
--- /dev/null
+++ b/gdb/nat/aarch64-poe-linux.h
@@ -0,0 +1,28 @@
+/* Common native Linux definitions for AArch64 Permission Overlay Extension.
+
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_NAT_AARCH64_POE_LINUX_H
+#define GDB_NAT_AARCH64_POE_LINUX_H
+
+/* Feature check for Permission Overlay Extension.  */
+#ifndef HWCAP2_POE
+#define HWCAP2_POE (1ULL << 63)
+#endif /* HWCAP2_POE */
+
+#endif /* GDB_NAT_AARCH64_POE_LINUX_H */
diff --git a/include/elf/common.h b/include/elf/common.h
index 1ae68221a89..f811b8daeb5 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -760,6 +760,8 @@
 					/*   Note: name must be "LINUX".  */
 #define NT_ARM_FPMR     0x40e           /* AArch64 FPMR.  */
 					/*   Note: name must be "LINUX".  */
+#define NT_ARM_POE	0x40f		/* AArch64 POE register.  */
+					/*   Note: name must be "LINUX".  */
 #define NT_ARM_GCS	0x410		/* AArch64 Guarded Control Stack
 					   registers.  */
 					/*   Note  name must be "LINUX".  */
-- 
2.43.0


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

* [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0
  2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
  2026-06-26 18:08 ` [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni
@ 2026-06-26 18:08 ` srinath.parvathaneni
  2026-06-27  7:03   ` Thiago Jung Bauermann
  2026-06-26 18:08 ` [PATCH v2 3/7] gdb: Improve SIGSEGV diagnostics for POE faults srinath.parvathaneni
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: srinath.parvathaneni @ 2026-06-26 18:08 UTC (permalink / raw)
  To: gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, guinevere, Ezra.Sitorus,
	Matthieu.Longo, Srinath Parvathaneni

From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

Add custom printing support for the POR_EL0 register when displayed
using `info registers` or `info all-registers`.

The register value is decoded into a human-readable "rwx"
representation for each nibble in the POR_EL0 register, making the
POE permissions easier to interpret.

Example:
(gdb) set $por_el0=0xffffffff77777777
(gdb) info register por_el0
por_el0        0xffffffff77777777  [P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ]
---
 gdb/aarch64-tdep.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index f1e1a9c7a19..3ef4e696c7c 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -3135,6 +3135,86 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 		  p_regnum);
 }
 
+/* Convert a POR_EL0 Perm<m> overlay permission encoding into rwx-style string.
+   For example:
+     0b0011 -> "r-x" (3)
+     0b0101 -> "rw-" (5)
+     0b0111 -> "rwx" (7)
+     0b0000 -> "---" (0)
+   Reserved encodings (0b1xxx) are returned as "???".  */
+
+static const char*
+aarch64_perm_overlay_decode (unsigned int perm)
+{
+  switch (perm)
+   {
+     case 0: return "---";
+     case 1: return "r--";
+     case 2: return "--x";
+     case 3: return "r-x";
+     case 4: return "-w-";
+     case 5: return "rw-";
+     case 6: return "-wx";
+     case 7: return "rwx";
+     default: return "???";
+   }
+}
+
+/* Display POE reigster POR_EL0 in the following format for the 'info registers'
+   and 'info all-registers' commands:
+   <register-name> <hex-value> [<decoded per-protection-key permissions>]  */
+
+static void
+aarch64_print_poe_register_info (struct ui_file *file,
+				 int regnum,
+				 const char *name,
+				 const frame_info_ptr &frame)
+{
+  value *val = value_of_register (regnum, get_next_frame_sentinel_okay (frame));
+  ULONGEST por_el0 = (ULONGEST) value_as_long (val);
+  gdb_printf (file, "%-14s 0x%s  [", name, phex_nz (por_el0, 8));
+
+  for (int i = 15; i >= 0; --i)
+    {
+      unsigned int perm = (por_el0 >> (i * 4)) & 0xf;
+      gdb_printf (file, "P%d=%s ", i, aarch64_perm_overlay_decode (perm));
+    }
+
+  gdb_puts ("]\n", file);
+}
+
+/* For 'info registers' and 'info all-registers', print POR_EL0 using the
+   custom POE register printer and all other registers using the default
+   register printer.  */
+
+static void
+aarch64_print_registers_info (struct gdbarch *gdbarch,
+			      struct ui_file *file,
+			      const frame_info_ptr &frame,
+			      int regnum,
+			      bool print_all)
+{
+  const int numregs = gdbarch_num_cooked_regs (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+
+  if (regnum == -1)
+    {
+      for (int i = 0; i < numregs; i++)
+	{
+	  if (i == tdep->poe_regnum)
+	    {
+	      aarch64_print_poe_register_info (file, i, "por_el0", frame);
+	      continue;
+	    }
+	  default_print_registers_info (gdbarch, file, frame,  i, print_all);
+	}
+    }
+  else if (regnum == tdep->poe_regnum)
+    aarch64_print_poe_register_info (file, regnum, "por_el0", frame);
+  else
+    default_print_registers_info (gdbarch, file, frame, regnum, print_all);
+}
+
 /* Implement the "pseudo_register_reggroup_p" tdesc_arch_data method.  */
 
 static bool
@@ -4141,6 +4221,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc)
   features.fpmr = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr")
 		   != nullptr);
 
+  /* Check for POE feature.  */
+  features.poe = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe")
+		  != nullptr);
+
   return features;
 }
 
@@ -4774,6 +4858,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->gcs_reg_base = first_gcs_regnum;
   tdep->gcs_linux_reg_base = first_gcs_linux_regnum;
   tdep->fpmr_regnum = fpmr_regnum;
+  tdep->poe_regnum = poe_regnum;
 
   /* Set the SME register set details.  The pseudo-registers will be adjusted
      later.  */
@@ -4816,6 +4901,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_tdesc_pseudo_register_reggroup_p (gdbarch,
 					aarch64_pseudo_register_reggroup_p);
   set_gdbarch_cannot_store_register (gdbarch, aarch64_cannot_store_register);
+  set_gdbarch_print_registers_info (gdbarch, aarch64_print_registers_info);
 
   /* Set the allocation tag granule size to 16 bytes.  */
   set_gdbarch_memtag_granule_size (gdbarch, AARCH64_MTE_GRANULE_SIZE);
-- 
2.43.0


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

* [PATCH v2 3/7] gdb: Improve SIGSEGV diagnostics for POE faults
  2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
  2026-06-26 18:08 ` [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni
  2026-06-26 18:08 ` [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0 srinath.parvathaneni
@ 2026-06-26 18:08 ` srinath.parvathaneni
  2026-06-29  2:42   ` Thiago Jung Bauermann
  2026-06-26 18:08 ` [PATCH v2 4/7] gdbserver/aarch64: Add POR_EL0 register support srinath.parvathaneni
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: srinath.parvathaneni @ 2026-06-26 18:08 UTC (permalink / raw)
  To: gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, guinevere, Ezra.Sitorus,
	Matthieu.Longo, Srinath Parvathaneni

From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

When a SIGSEGV is caused by a Permission Overlay violation, include
additional information in GDB's error message to help identify the
failing address along with the responsible protection key causing
this fault.

Example:
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault
Protection Key Violation while accessing address 0x0000fffff7ff3000 with Protection Key = 1.
0x0000aaaaaaaa0a3c in main () at poe_sigsegv.c:26
---
 gdb/aarch64-linux-tdep.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 4a6bc3158c8..b8a02ab9972 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -2676,11 +2676,12 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
 {
   aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
-  if (!(tdep->has_mte () || tdep->has_gcs ()) || siggnal != GDB_SIGNAL_SEGV)
+  if (!(tdep->has_mte () || tdep->has_gcs () || tdep->has_poe ())
+      || siggnal != GDB_SIGNAL_SEGV)
     return;
 
   CORE_ADDR fault_addr = 0;
-  long si_code = 0, si_errno = 0;
+  long si_code = 0, si_errno = 0, si_pkey = -1;
 
   try
     {
@@ -2688,6 +2689,9 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
 	 violation.  */
       si_code = parse_and_eval_long ("$_siginfo.si_code");
       si_errno = parse_and_eval_long ("$_siginfo.si_errno");
+      if (tdep->has_poe ())
+	si_pkey = parse_and_eval_long
+	  ("$_siginfo._sifields._sigfault._._addr_pkey.si_pkey");
 
       fault_addr
 	= parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr");
@@ -2704,6 +2708,8 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
     meaning = _("Memory tag violation");
   else if (si_code == AARCH64_SEGV_CPERR && si_errno == 0)
     meaning = _("Guarded Control Stack error");
+  else if (si_code == AARCH64_SEGV_PKUERR)
+    meaning = _("Protection Key Violation");
   else
     return;
 
@@ -2735,6 +2741,14 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
 	  uiout->field_string ("logical-tag", hex_string (ltag));
 	}
     }
+  /* For POE SEGSEGV, show additional information.  */
+  else if (si_code == AARCH64_SEGV_PKUERR)
+    {
+      uiout->text (_(" while accessing address "));
+      uiout->field_core_addr ("fault-addr", gdbarch, fault_addr);
+      uiout->text (" with Protection Key = ");
+      uiout->field_signed ("protection-key", si_pkey);
+    }
   else if (si_code != AARCH64_SEGV_CPERR)
     {
       uiout->text ("\n");
@@ -3055,7 +3069,7 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 					 aarch64_linux_decode_memtag_section);
     }
 
-  if (tdep->has_mte () || tdep->has_gcs ())
+  if (tdep->has_mte () || tdep->has_gcs () || tdep->has_poe ())
     set_gdbarch_report_signal_info (gdbarch, aarch64_linux_report_signal_info);
 
   /* Initialize the aarch64_linux_record_tdep.  */
-- 
2.43.0


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

* [PATCH v2 4/7] gdbserver/aarch64: Add POR_EL0 register support
  2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
                   ` (2 preceding siblings ...)
  2026-06-26 18:08 ` [PATCH v2 3/7] gdb: Improve SIGSEGV diagnostics for POE faults srinath.parvathaneni
@ 2026-06-26 18:08 ` srinath.parvathaneni
  2026-06-29  2:43   ` Thiago Jung Bauermann
  2026-06-26 18:08 ` [PATCH v2 5/7] bfd/readelf: Add core file support for FEAT_S1POE srinath.parvathaneni
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: srinath.parvathaneni @ 2026-06-26 18:08 UTC (permalink / raw)
  To: gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, guinevere, Ezra.Sitorus,
	Matthieu.Longo, Srinath Parvathaneni

From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

Add support for transferring the POR_EL0 register between the Linux
kernel and GDB during remote debugging.

This patch implements the necessary `fill` and `store` operations using
the `NT_ARM_POE` regset, allowing GDB to read and write the POR_EL0
register when debugging a remote target that supports FEAT_S1POE.
---
 gdbserver/linux-aarch64-low.cc | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
index a2588a6e2a9..d326341e63a 100644
--- a/gdbserver/linux-aarch64-low.cc
+++ b/gdbserver/linux-aarch64-low.cc
@@ -45,6 +45,7 @@
 #include "linux-aarch32-tdesc.h"
 #include "linux-aarch64-tdesc.h"
 #include "nat/aarch64-fpmr-linux.h"
+#include "nat/aarch64-poe-linux.h"
 #include "nat/aarch64-gcs-linux.h"
 #include "nat/aarch64-mte-linux-ptrace.h"
 #include "nat/aarch64-scalable-linux-ptrace.h"
@@ -250,6 +251,26 @@ aarch64_store_fpregset (struct regcache *regcache, const void *buf)
   supply_register (regcache, AARCH64_FPCR_REGNUM, &regset->fpcr);
 }
 
+/* Fill BUF with the POE (POR_EL0) register set from the regcache.  */
+
+static void
+aarch64_fill_por_el0_regset (struct regcache *regcache, void *buf)
+{
+  uint64_t *poe = (uint64_t *) buf;
+  int poe_regnum = find_regno (regcache->tdesc, "por_el0");
+  collect_register (regcache, poe_regnum, poe);
+}
+
+/* Store the POE (POR_EL0) register set to regcache.  */
+
+static void
+aarch64_store_por_el0_regset (struct regcache *regcache, const void *buf)
+{
+  uint64_t *poe = (uint64_t *) buf;
+  int poe_regnum = find_regno (regcache->tdesc, "por_el0");
+  supply_register (regcache, poe_regnum, poe);
+}
+
 /* Fill BUF with the FPMR register set from the regcache.  */
 
 static void
@@ -901,6 +922,10 @@ static struct regset_info aarch64_regsets[] =
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_FPMR,
     0, OPTIONAL_REGS,
     aarch64_fill_fpmr_regset, aarch64_store_fpmr_regset },
+  /* POE register (POR_EL0).  */
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_POE,
+    0, OPTIONAL_REGS,
+    aarch64_fill_por_el0_regset, aarch64_store_por_el0_regset },
   /* TLS register.  */
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TLS,
     0, OPTIONAL_REGS,
@@ -980,6 +1005,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
 	  if (features.fpmr)
 	    regset->size = sizeof (uint64_t);
 	  break;
+	case NT_ARM_POE:
+	  if (features.poe)
+	    regset->size = sizeof (uint64_t);
+	  break;
 	default:
 	  gdb_assert_not_reached ("Unknown register set found.");
 	}
@@ -1010,6 +1039,7 @@ aarch64_target::low_arch_setup ()
       features.tls = aarch64_tls_register_count (tid);
       features.gcs = features.gcs_linux = linux_get_hwcap (pid, 8) & HWCAP_GCS;
       features.fpmr = linux_get_hwcap2 (pid, 8) & HWCAP2_FPMR;
+      features.poe = linux_get_hwcap2 (pid, 8) & HWCAP2_POE;
 
       /* Scalable Matrix Extension feature and size check.  */
       if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME)
-- 
2.43.0


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

* [PATCH v2 5/7] bfd/readelf: Add core file support for FEAT_S1POE
  2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
                   ` (3 preceding siblings ...)
  2026-06-26 18:08 ` [PATCH v2 4/7] gdbserver/aarch64: Add POR_EL0 register support srinath.parvathaneni
@ 2026-06-26 18:08 ` srinath.parvathaneni
  2026-06-29  2:43   ` Thiago Jung Bauermann
  2026-06-26 18:08 ` [PATCH v2 6/7] gdb/aarch64: " srinath.parvathaneni
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: srinath.parvathaneni @ 2026-06-26 18:08 UTC (permalink / raw)
  To: gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, guinevere, Ezra.Sitorus,
	Matthieu.Longo, Srinath Parvathaneni

From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

Add support for `NT_ARM_POE` dumps/reads for core files.
---
 bfd/elf.c          | 25 +++++++++++++++++++++++++
 binutils/readelf.c |  2 ++
 2 files changed, 27 insertions(+)

diff --git a/bfd/elf.c b/bfd/elf.c
index c9a68404e9d..c7f557b8be6 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -64,6 +64,7 @@ SECTION
 /* Names of a pseudo-section which represent core notes.  */
 #define NOTE_PSEUDO_SECTION_AARCH_FPMR		".reg-aarch-fpmr"
 #define NOTE_PSEUDO_SECTION_AARCH_GCS		".reg-aarch-gcs"
+#define NOTE_PSEUDO_SECTION_AARCH_POE		".reg-aarch-poe"
 #define NOTE_PSEUDO_SECTION_AARCH_HW_BREAK	".reg-aarch-hw-break"
 #define NOTE_PSEUDO_SECTION_AARCH_HW_WATCH	".reg-aarch-hw-watch"
 #define NOTE_PSEUDO_SECTION_AARCH_MTE		".reg-aarch-mte"
@@ -10735,6 +10736,15 @@ elfcore_grok_aarch_gcs (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, NOTE_PSEUDO_SECTION_AARCH_GCS, note);
 }
 
+/* Convert NOTE into a bfd_section called ".reg-aarch-poe".  Return TRUE if
+   successful, otherwise return FALSE.  */
+
+static bool
+elfcore_grok_aarch_poe (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, NOTE_PSEUDO_SECTION_AARCH_POE, note);
+}
+
 /* Convert NOTE into the appropriate note pseudo-section for the AArch64 FPMR.
  * Return TRUE if successful, otherwise return FALSE.  */
 
@@ -11179,6 +11189,7 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 	case NT_ARC_V2:		return elfcore_grok_arc_v2 (abfd, note);
 	case NT_ARM_FPMR:	return elfcore_grok_aarch_fpmr (abfd, note);
 	case NT_ARM_GCS:	return elfcore_grok_aarch_gcs (abfd, note);
+	case NT_ARM_POE:	return elfcore_grok_aarch_poe (abfd, note);
 	case NT_ARM_HW_BREAK:	return elfcore_grok_aarch_hw_break (abfd, note);
 	case NT_ARM_HW_WATCH:	return elfcore_grok_aarch_hw_watch (abfd, note);
 	case NT_ARM_PAC_MASK:	return elfcore_grok_aarch_pauth (abfd, note);
@@ -12900,6 +12911,19 @@ elfcore_write_aarch_gcs (bfd *abfd, char *buf, int *bufsiz,
 			     aarch_gcs, size);
 }
 
+/* Write the buffer of POE register values in AARCH_POE (length SIZE) into
+   the note buffer BUF and update *BUFSIZ.  ABFD is the bfd the note is being
+   written into.  Return a pointer to the new start of the note buffer, to
+   replace BUF which may no longer be valid.  */
+
+static char *
+elfcore_write_aarch_poe (bfd *abfd, char *buf, int *bufsiz,
+			 const void *aarch_poe, int size)
+{
+  return elfcore_write_note (abfd, buf, bufsiz, NOTE_NAME_LINUX, NT_ARM_POE,
+			     aarch_poe, size);
+}
+
 /* Write the buffer of FPMR value in AARCH_FPMR (length SIZE) into
    the note buffer BUF and update *BUFSIZ.  ABFD is the bfd the note is being
    written into.  Return a pointer to the new start of the note buffer, to
@@ -13024,6 +13048,7 @@ elfcore_write_register_note (bfd *abfd,
     {
       { NOTE_PSEUDO_SECTION_AARCH_FPMR,       elfcore_write_aarch_fpmr},
       { NOTE_PSEUDO_SECTION_AARCH_GCS,        elfcore_write_aarch_gcs},
+      { NOTE_PSEUDO_SECTION_AARCH_POE,        elfcore_write_aarch_poe},
       { NOTE_PSEUDO_SECTION_AARCH_HW_BREAK,   elfcore_write_aarch_hw_break},
       { NOTE_PSEUDO_SECTION_AARCH_HW_WATCH,   elfcore_write_aarch_hw_watch},
       { NOTE_PSEUDO_SECTION_AARCH_MTE,        elfcore_write_aarch_mte},
diff --git a/binutils/readelf.c b/binutils/readelf.c
index bf27f9eec23..61354d7ab11 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -21915,6 +21915,8 @@ get_note_type (Filedata * filedata, unsigned e_type)
 	return _("NT_ARM_PAC_ENABLED_KEYS (AArch64 pointer authentication enabled keys)");
       case NT_ARM_FPMR:
 	return _("NT_ARM_FPMR (AArch64 Floating Point Mode Register)");
+      case NT_ARM_POE:
+	return _("NT_ARM_POE (AArch64 Permission Overlay Extension Register)");
       case NT_ARC_V2:
 	return _("NT_ARC_V2 (ARC HS accumulator/extra registers)");
       case NT_RISCV_CSR:
-- 
2.43.0


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

* [PATCH v2 6/7] gdb/aarch64: Add core file support for FEAT_S1POE
  2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
                   ` (4 preceding siblings ...)
  2026-06-26 18:08 ` [PATCH v2 5/7] bfd/readelf: Add core file support for FEAT_S1POE srinath.parvathaneni
@ 2026-06-26 18:08 ` srinath.parvathaneni
  2026-06-29  2:44   ` Thiago Jung Bauermann
  2026-06-26 18:08 ` [PATCH v2 7/7] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni
  2026-06-29 12:18 ` [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature Guinevere Larsen
  7 siblings, 1 reply; 21+ messages in thread
From: srinath.parvathaneni @ 2026-06-26 18:08 UTC (permalink / raw)
  To: gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, guinevere, Ezra.Sitorus,
	Matthieu.Longo, Srinath Parvathaneni

From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

Add support for POR_EL0 dumps/reads for core files.
---
 gdb/aarch64-linux-tdep.c | 51 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index b8a02ab9972..1d6d4c94b84 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -171,6 +171,7 @@
 #define AARCH64_ZT_MAGIC			0x5a544e01
 #define AARCH64_GCS_MAGIC			0x47435300
 #define AARCH64_FPMR_MAGIC			0x46504d52
+#define AARCH64_POE_MAGIC			0x504f4530
 
 /* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC.  */
 #define AARCH64_EXTRA_DATAP_OFFSET		8
@@ -220,6 +221,9 @@
 /* FPMR constants.  */
 #define AARCH64_FPMR_OFFSET			8
 
+/* POE constants.  */
+#define AARCH64_POE_OFFSET			8
+
 /* Holds information about the signal frame.  */
 struct aarch64_linux_sigframe
 {
@@ -273,6 +277,11 @@ struct aarch64_linux_sigframe
   /* FPMR value.  */
   CORE_ADDR fpmr = 0;
 
+  /* True if we have an POE entry in the signal context, false otherwise.  */
+  bool poe_available = false;
+  /* FPMR value.  */
+  CORE_ADDR poe = 0;
+
 };
 
 /* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the
@@ -605,6 +614,22 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame,
 	    section += size;
 	    break;
 	  }
+	case AARCH64_POE_MAGIC:
+	  {
+	    gdb_byte buf[8];
+	    if (target_read_memory (section + AARCH64_POE_OFFSET,
+				    buf, 8) != 0)
+	      {
+		warning (_("Failed to read the POE section address from the"
+			   " signal frame context."));
+		section += size;
+		break;
+	      }
+	    signal_frame.poe = extract_unsigned_integer (buf, 8, byte_order);
+	    signal_frame.poe_available = true;
+	    section += size;
+	    break;
+	  }
 	case AARCH64_EXTRA_MAGIC:
 	  {
 	    /* Extra is always the last valid section in reserved and points to
@@ -775,6 +800,13 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
 			      signal_frame.fpmr);
   }
 
+  /* Handle POE register.  */
+  if (tdep->has_poe () && signal_frame.poe_available != 0)
+  {
+    trad_frame_set_reg_value (this_cache, tdep->poe_regnum,
+			      signal_frame.poe);
+  }
+
   /* Restore the tpidr2 register, if the target supports it and if there is
      an entry for it.  */
   if (signal_frame.tpidr2_section != 0 && tdep->has_tls ()
@@ -828,6 +860,7 @@ aarch64_linux_sigframe_prev_arch (const frame_info_ptr &this_frame,
   features.vq = sve_vq_from_vl (signal_frame.vl);
   features.svq = (uint8_t) sve_vq_from_vl (signal_frame.svl);
   features.fpmr = signal_frame.fpmr_available;
+  features.poe = signal_frame.poe_available;
 
   struct gdbarch_info info;
   info.bfd_arch_info = bfd_lookup_arch (bfd_arch_aarch64, bfd_mach_aarch64);
@@ -1655,6 +1688,23 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 	  &aarch64_linux_fpmr_regset, "FPMR", cb_data);
     }
 
+  if (tdep->has_poe ())
+    {
+      const struct regcache_map_entry poe_regmap[] =
+	{
+	  { 1, tdep->poe_regnum, sizeof (uint64_t) },
+	  { 0 }
+	};
+
+      const struct regset aarch64_linux_poe_regset =
+	{
+	  poe_regmap, regcache_supply_regset, regcache_collect_regset
+	};
+
+      cb (".reg-aarch-poe", sizeof (uint64_t), sizeof (uint64_t),
+	  &aarch64_linux_poe_regset, "POE register", cb_data);
+    }
+
   if (tdep->has_pauth ())
     {
       /* Create this on the fly in order to handle the variable location.  */
@@ -1768,6 +1818,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
   features.gcs = features.gcs_linux = hwcap & AARCH64_HWCAP_GCS;
   features.mte = hwcap2 & AARCH64_HWCAP2_MTE;
   features.fpmr = hwcap2 & AARCH64_HWCAP2_FPMR;
+  features.poe = hwcap2 & AARCH64_HWCAP2_POE;
 
   /* Handle the TLS section.  */
   asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls");
-- 
2.43.0


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

* [PATCH v2 7/7] gdb/testsuite: Add FEAT_S1POE testcases
  2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
                   ` (5 preceding siblings ...)
  2026-06-26 18:08 ` [PATCH v2 6/7] gdb/aarch64: " srinath.parvathaneni
@ 2026-06-26 18:08 ` srinath.parvathaneni
  2026-07-01  5:12   ` Thiago Jung Bauermann
  2026-06-29 12:18 ` [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature Guinevere Larsen
  7 siblings, 1 reply; 21+ messages in thread
From: srinath.parvathaneni @ 2026-06-26 18:08 UTC (permalink / raw)
  To: gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, guinevere, Ezra.Sitorus,
	Matthieu.Longo, Srinath Parvathaneni

From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

Add testcases for POR_EL0 register access, SIGSEGV diagnostics, fix-and-continue
support (updating $por_el0 after SIGSEGV and continuing with signal 0), and core
file support.
---
 gdb/testsuite/gdb.arch/aarch64-poe-core.exp   | 102 ++++++++++++++++++
 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c  |  52 +++++++++
 .../gdb.arch/aarch64-poe-sigsegv.exp          |  60 +++++++++++
 gdb/testsuite/gdb.arch/aarch64-poe.c          |  29 +++++
 gdb/testsuite/gdb.arch/aarch64-poe.exp        |  44 ++++++++
 gdb/testsuite/lib/gdb.exp                     |  55 ++++++++++
 6 files changed, 342 insertions(+)
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-core.exp
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.c
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.exp

diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-core.exp b/gdb/testsuite/gdb.arch/aarch64-poe-core.exp
new file mode 100644
index 00000000000..ab998781f10
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-poe-core.exp
@@ -0,0 +1,102 @@
+# Copyright (C) 2026 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# Test generating and reading a core file with POR_EL0.
+
+proc check_poe_core_file {core_filename} {
+    # Load the core file.
+    if {
+        [gdb_test "core $core_filename" \
+            [multi_line \
+                "Core was generated by .*" \
+                "Program terminated with signal SIGSEGV, Segmentation fault\\." \
+                "Protection Key Violation while accessing address ${::hex} with Protection Key = ${::decimal}\\." \
+                "#0  ${::hex} in main \\(.*\\) at .*" \
+                ".*buf\\\[0\\\] = 42;.*"] \
+            "load core file"]
+    } {
+        untested "failed to load core file"
+        return -1
+    }
+
+    # Check the value of POR_EL0 in the core file.
+    gdb_test "print/x \$por_el0" " = 0x55" \
+        "por_el0 contents from core file"
+}
+
+require is_aarch64_target
+require allow_aarch64_poe_tests
+
+standard_testfile aarch64-poe-sigsegv.c
+
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
+    return
+}
+
+set binfile [standard_output_file ${testfile}]
+
+if {![runto_main]} {
+    return
+}
+
+set poe_crash_re [multi_line \
+    "Program received signal SIGSEGV, Segmentation fault\\." \
+    "Protection Key Violation while accessing address ${::hex} with Protection Key = ${::decimal}\\." \
+    ".*buf\\\[0\\\] = 42;.*"]
+
+gdb_test_multiple "continue" "run to POE crash" {
+    -re "$poe_crash_re.*$gdb_prompt $" {
+        pass $gdb_test_name
+    }
+
+    -re ".*exited with code 01.*$gdb_prompt $" {
+        unsupported "POE userspace support unavailable"
+        return
+    }
+}
+
+# Generate the gcore core file.
+set gcore_filename [standard_output_file "${testfile}.gcore"]
+set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"]
+
+# Generate a native core file.
+set core_filename [core_find ${binfile}]
+set core_generated [expr {$core_filename != ""}]
+
+# At this point we have a couple core files, the gcore one generated by GDB
+# and the native one generated by the Linux Kernel.  Make sure GDB can read
+# both correctly.
+
+if {$gcore_generated} {
+    clean_restart
+    gdb_load ${binfile}
+    with_test_prefix "gcore corefile" {
+        check_poe_core_file $gcore_filename
+    }
+} else {
+    fail "gcore corefile not generated"
+}
+
+if {$core_generated} {
+    clean_restart
+    gdb_load ${binfile}
+    with_test_prefix "native corefile" {
+        check_poe_core_file $core_filename
+    }
+} else {
+    untested "native corefile not generated"
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
new file mode 100644
index 00000000000..6b0c07e782f
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
@@ -0,0 +1,52 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2026 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Exercise AArch64's POE Extension.  */
+
+/* This test is based on the Linux kernel documentation for Memory
+   Protection Keys, including the arm64 Permission Overlay Extension
+   (FEAT_S1POE) support described in
+   Documentation/core-api/protection-keys.rst.  */
+
+#define _GNU_SOURCE
+#include <sys/mman.h>
+#include <unistd.h>
+
+int
+main (void)
+{
+  long pagesize = sysconf (_SC_PAGESIZE);
+
+  int *buf = mmap (NULL, pagesize, PROT_READ | PROT_WRITE,
+		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (buf == MAP_FAILED)
+    return 1;
+
+  int pkey = pkey_alloc (0, 0);
+  if (pkey == -1)
+    return 1;
+
+  if (pkey_mprotect (buf, pagesize, PROT_READ | PROT_WRITE, pkey) == -1)
+    return 1;
+
+  if (pkey_set (pkey, PKEY_DISABLE_WRITE) == -1)
+    return 1;
+
+  buf[0] = 42;  /* Expect SIGSEGV POE violation.  */
+
+  return 1;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
new file mode 100644
index 00000000000..b22814f9ab9
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
@@ -0,0 +1,60 @@
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test a binary that supports FEAT_S1POE and exposes POR_EL0 register.
+
+global hex
+global decimal
+
+require is_aarch64_target
+
+if {![allow_aarch64_poe_tests]} {
+    unsupported "AArch64 POE not supported"
+    return
+}
+
+standard_testfile
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+    return
+}
+
+if {![runto_main]} {
+    return
+}
+
+# Display POE violation SIGSEGV error message.
+set poe_sigsegv_re [multi_line \
+    "Program received signal SIGSEGV, Segmentation fault\\." \
+    "Protection Key Violation while accessing address ${hex} with Protection Key = ${decimal}"]
+
+gdb_test_multiple "continue" "display POE violation information" {
+    -re "$poe_sigsegv_re.*$gdb_prompt $" {
+	pass $gdb_test_name
+    }
+    -re ".*exited with code 01.*$gdb_prompt $" {
+	unsupported "POE userspace support unavailable"
+	return
+    }
+}
+
+# Fix the POE permissions (set $por_el0) and continue without delivering SIGSEGV.
+gdb_test "set \$por_el0 = 0x47" "" \
+    "allow write access by updating POR_EL0"
+
+gdb_test_multiple "signal 0" "continue after fixing POE fault" {
+    -re ".*exited normally.*$gdb_prompt $" {
+	pass $gdb_test_name
+    }
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-poe.c b/gdb/testsuite/gdb.arch/aarch64-poe.c
new file mode 100644
index 00000000000..2c95dc2a99b
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-poe.c
@@ -0,0 +1,29 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2026 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Exercise AArch64's POE Extension.  */
+
+/* This test is based on the Linux kernel documentation for Memory
+   Protection Keys, including the arm64 Permission Overlay Extension
+   (FEAT_S1POE) support described in
+   Documentation/core-api/protection-keys.rst.  */
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-poe.exp b/gdb/testsuite/gdb.arch/aarch64-poe.exp
new file mode 100644
index 00000000000..ae2663a7dbc
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-poe.exp
@@ -0,0 +1,44 @@
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test a binary that uses POE and exposed POR_EL0 register.
+
+global hex
+global decimal
+
+require is_aarch64_target
+
+if {![allow_aarch64_poe_tests]} {
+    unsupported "AArch64 POE not supported"
+    return
+}
+
+standard_testfile
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+    return
+}
+
+if {![runto_main]} {
+    return
+}
+
+# Validate the presence of the POE register.
+    gdb_test "info registers por_el0" \
+	     "por_el0\[ \t\]+$hex.*" \
+	     "register por_el0 available"
+
+    gdb_test "p/x \$por_el0" \
+	     "\\$\[0-9\]+ = ${hex}" \
+	     "print por_el0"
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index d8619ded236..40a8124955a 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -5654,6 +5654,61 @@ gdb_caching_proc allow_aarch64_gcs_tests {} {
     return $allow_gcs_tests
 }
 
+# Run a test on the target to see if it supports AArch64 POE extensions.
+# Return 1 if so, 0 if it does not.  Note this causes a restart of GDB.
+
+gdb_caching_proc allow_aarch64_poe_tests {} {
+    global srcdir subdir gdb_prompt inferior_exited_re
+
+    set me "allow_aarch64_poe_tests"
+
+    if { ![is_aarch64_target]} {
+	return 0
+    }
+
+    # Compile a program that tests the POE feature.
+    set src {
+	#include <stdbool.h>
+	#include <sys/auxv.h>
+
+	/* Feature check for POE feature.  */
+	#ifndef HWCAP2_POE
+	#define HWCAP2_POE (1ULL << 63)
+	#endif
+
+	int main (void) {
+	    bool poe_supported = getauxval (AT_HWCAP2) & HWCAP2_POE;
+
+	    /* Return success if POE is supported.  */
+	    return !poe_supported;
+	}
+    }
+
+    if {![gdb_simple_compile $me $src executable]} {
+	return 0
+    }
+
+    # Compilation succeeded so now run it via gdb.
+    set allow_poe_tests 0
+    clean_restart
+    gdb_load $obj
+    gdb_run_cmd
+    gdb_expect {
+	-re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
+	    verbose -log "\n$me: poe support detected"
+	    set allow_poe_tests 1
+	}
+	-re ".*$inferior_exited_re with code 01.*${gdb_prompt} $" {
+	    verbose -log "\n$me: poe support not detected"
+	}
+    }
+    gdb_exit
+    remote_file build delete $obj
+
+    verbose "$me:  returning $allow_poe_tests" 2
+    return $allow_poe_tests
+}
+
 # A helper that compiles a test case to see if __int128 is supported.
 proc gdb_int128_helper {lang} {
     return [gdb_can_simple_compile "i128-for-$lang" {
-- 
2.43.0


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

* Re: [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
  2026-06-26 18:08 ` [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni
@ 2026-06-27  6:06   ` Thiago Jung Bauermann
  2026-06-29 10:44     ` Srinath Parvathaneni
  0 siblings, 1 reply; 21+ messages in thread
From: Thiago Jung Bauermann @ 2026-06-27  6:06 UTC (permalink / raw)
  To: srinath.parvathaneni
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra.Sitorus, Matthieu.Longo

Hello Srinath,

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Add support for the FEAT_S1POE POR_EL0 register on AArch64.
>
> This patch adds POR_EL0 to the AArch64 register set and reads/writes it
> using the NT_ARM_POE ptrace regset.
>
> With this change, POR_EL0 is available through:
> *  info registers
> *  info registers por_el0
> *  p $por_el0
> *  p/x $por_el0
> *  set $por_el0 = <value>

One question, more about general policy on the AArch64 GDB port:

Should the register name have the _el0 suffix? It's more than half of
the register name (though tab completion helps).

We don't currently have that suffix in the name of any register. And in
the case of Guarded Control Stack, I didn't add it. For native
debugging, it will always be the register at EL0. For remote debugging,
I assumed the target would send the register corresponding to the
current exception level in the inferior.

Can there be a situation where it would be possible to see both the EL0
and EL1 (for example) registers at the same time? Or a situation where
the inferior is at EL1 but one wants to see the register at EL0, or
vice-versa?

> ---
>  gdb/Makefile.in              |  2 ++
>  gdb/aarch64-linux-nat.c      | 66 ++++++++++++++++++++++++++++++++++++
>  gdb/aarch64-linux-tdep.c     |  1 +
>  gdb/aarch64-tdep.c           | 18 ++++++++++
>  gdb/aarch64-tdep.h           | 11 +++++-
>  gdb/arch/aarch64-poe-linux.h | 29 ++++++++++++++++
>  gdb/arch/aarch64.c           |  4 +++
>  gdb/arch/aarch64.h           |  7 +++-
>  gdb/features/Makefile        |  1 +
>  gdb/features/aarch64-poe.c   | 14 ++++++++
>  gdb/features/aarch64-poe.xml | 12 +++++++
>  gdb/nat/aarch64-poe-linux.h  | 28 +++++++++++++++
>  include/elf/common.h         |  2 ++
>  13 files changed, 193 insertions(+), 2 deletions(-)
>  create mode 100644 gdb/arch/aarch64-poe-linux.h
>  create mode 100644 gdb/features/aarch64-poe.c
>  create mode 100644 gdb/features/aarch64-poe.xml
>  create mode 100644 gdb/nat/aarch64-poe-linux.h
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 57f384170ab..3dc9cd07dcb 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -1292,6 +1292,7 @@ HFILES_NO_SRCDIR = \
>  	arch/aarch32.h \
>  	arch/aarch64-fpmr-linux.h \
>  	arch/aarch64-gcs-linux.h \
> +	arch/aarch64-poe-linux.h \
>  	arch/aarch64.h \
>  	arch/aarch64-insn.h \
>  	arch/aarch64-mte.h \
> @@ -1540,6 +1541,7 @@ HFILES_NO_SRCDIR = \
>  	namespace.h \
>  	nat/aarch64-fpmr-linux.h \
>  	nat/aarch64-gcs-linux.h \
> +	nat/aarch64-poe-linux.h \
>  	nat/aarch64-hw-point.h \
>  	nat/aarch64-linux.h \
>  	nat/aarch64-linux-hw-point.h \
> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index 52ace4aab41..54265920d69 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -34,6 +34,7 @@
>  #include "arch/arm.h"
>  #include "nat/aarch64-fpmr-linux.h"
>  #include "nat/aarch64-gcs-linux.h"
> +#include "nat/aarch64-poe-linux.h"
>  #include "nat/aarch64-linux.h"
>  #include "nat/aarch64-linux-hw-point.h"
>  #include "nat/aarch64-mte-linux-ptrace.h"
> @@ -569,6 +570,54 @@ fetch_gcsregs_from_thread (regcache *regcache)
>  			&user_gcs.features_locked);
>  }
>  
> +/* Fill GDB's register array with the POE register value from the current
> +   thread.  */
> +
> +static void
> +fetch_poeregs_from_thread (regcache *regcache)
> +{
> +  aarch64_gdbarch_tdep *tdep
> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
> +
> +  gdb_assert (tdep->has_poe ());
> +
> +  uint64_t user_poe;
> +  iovec iovec;
> +
> +  iovec.iov_base = &user_poe;
> +  iovec.iov_len = sizeof (user_poe);
> +
> +  int tid = get_ptrace_pid (regcache->ptid ());
> +  if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_POE, &iovec) != 0)
> +    perror_with_name (_("Unable to fetch POE register"));
> +
> +  regcache->raw_supply (tdep->poe_regnum, &user_poe);
> +}
> +
> +/* Store the NT_ARM_POE register contents from GDB's REGCACHE to the
> +    thread associated with REGCACHE.  */
> +
> +static void
> +store_poeregs_to_thread (struct regcache *regcache)
> +{
> +  aarch64_gdbarch_tdep *tdep
> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
> +
> +  gdb_assert (tdep->has_poe ());
> +
> +  int tid = regcache->ptid ().lwp ();
> +
> +  iovec iovec;
> +  uint64_t user_poe;
> +  iovec.iov_base = &user_poe;
> +  iovec.iov_len = sizeof (user_poe);
> +
> +  regcache->raw_collect (tdep->poe_regnum, &user_poe);
> +
> +  if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_POE, &iovec) != 0)
> +    perror_with_name (_("Unable to store POE register"));
> +}
> +
>  /* Store to the current thread the valid GCS register set in the GDB's
>     register array.  */

These functions are fine, but they were added between
fetch_gcsregs_from_thread and store_gcsregs_to_thread. For better
organization of the file, they should be either before or after the GCS
ones.

> @@ -683,6 +732,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
>        if (tdep->has_gcs_linux ())
>  	fetch_gcsregs_from_thread (regcache);
>  
> +      if (tdep->has_poe ())
> +	fetch_poeregs_from_thread (regcache);
> +
>        if (tdep->has_fpmr ())
>  	fetch_fpmr_from_thread (regcache);
>      }
> @@ -722,6 +774,10 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
>  	   && (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base
>  	       || regno == tdep->gcs_linux_reg_base + 1))
>      fetch_gcsregs_from_thread (regcache);
> +  /* POE register?  */
> +  else if (tdep->has_poe () && (regno == tdep->poe_regnum))
> +    fetch_poeregs_from_thread (regcache);
> +

Please remove the extra blank line here.

>    /* FPMR?  */
>    else if (tdep->has_fpmr () && (regno == tdep->fpmr_regnum))
>      fetch_fpmr_from_thread (regcache);
> @@ -802,6 +858,9 @@ aarch64_store_registers (struct regcache *regcache, int regno)
>  
>        if (tdep->has_fpmr ())
>  	store_fpmr_to_thread (regcache);
> +
> +      if (tdep->has_poe ())
> +	store_poeregs_to_thread (regcache);
>      }
>    /* General purpose register?  */
>    else if (regno < AARCH64_V0_REGNUM)
> @@ -837,6 +896,10 @@ aarch64_store_registers (struct regcache *regcache, int regno)
>    else if (tdep->has_fpmr () && regno == tdep->fpmr_regnum)
>      store_fpmr_to_thread (regcache);
>  

Please remove the extra blank line here. The else ifs should be joined.

> +  /* POE register?  */
> +  else if (tdep->has_poe () && regno == tdep->poe_regnum)
> +    store_poeregs_to_thread (regcache);
> +
>    /* PAuth registers are read-only.  */
>  }
>  
> @@ -1024,6 +1087,9 @@ aarch64_linux_nat_target::read_description ()
>    /* Check for FPMR.  */
>    features.fpmr = hwcap2 & HWCAP2_FPMR;
>  
> +  /* Check for POE support.  */
> +  features.poe = hwcap2 & HWCAP2_POE;
> +
>    return aarch64_read_description (features);
>  }
>  
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index f11eccc1bc1..4a6bc3158c8 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -53,6 +53,7 @@
>  
>  #include "arch/aarch64-fpmr-linux.h"
>  #include "arch/aarch64-gcs-linux.h"
> +#include "arch/aarch64-poe-linux.h"
>  #include "arch/aarch64-mte.h"
>  #include "arch/aarch64-mte-linux.h"
>  #include "arch/aarch64-pauth-linux.h"

This should be moved to the patch that makes use of the new header.

> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index 886e7ce1e7b..f1e1a9c7a19 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -164,6 +164,11 @@ static const char *const aarch64_gcs_register_names[] = {
>    "gcspr"
>  };
>  
> +static const char *const aarch64_poe_register_names[] = {
> +  /* Permission Overlay Extension Register.  */
> +  "por_el0"
> +};
> +
>  static const char *const aarch64_gcs_linux_register_names[] = {
>    /* Field in struct user_gcs.  */
>    "gcs_features_enabled",
> @@ -4556,6 +4561,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>  					  fpmr_regnum, "fpmr");
>      }
>  
> +  int poe_regnum = -1;
> +  const struct tdesc_feature *feature_poe
> +      = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe");
> +  if (feature_poe != nullptr)
> +    {
> +      poe_regnum = num_regs;
> +      for (i = 0; i < ARRAY_SIZE (aarch64_poe_register_names); i++)
> +	valid_p &= tdesc_numbered_register (feature_poe, tdesc_data.get (),
> +					    poe_regnum + i,
> +					    aarch64_poe_register_names[i]);
> +      num_regs++;
> +    }
> +
>    int first_sme_regnum = -1;
>    int first_sme2_regnum = -1;
>    int first_sme_pseudo_regnum = -1;
> diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
> index dff05a08f84..8029725b145 100644
> --- a/gdb/aarch64-tdep.h
> +++ b/gdb/aarch64-tdep.h
> @@ -208,6 +208,16 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base
>      return gcs_linux_reg_base != -1;
>    }
>  
> +  /* POE register.  This is -1 if no POE feature is available.  */
> +  int poe_regnum = -1;
> +
> +  /* Returns true if the target supports the Linux POE feature.  */

Remove the "Linux" word, since the feature isn't specific to it, and
also because this header file isn't OS-specific.

> +  bool
> +  has_poe () const
> +  {
> +    return poe_regnum != -1;
> +  }
> +
>    /* First FPMR register.  This is -1 if FPMR is not supported.  */
>    int fpmr_regnum = -1;
>  
> @@ -224,7 +234,6 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc);
>  
>  extern int aarch64_process_record (struct gdbarch *gdbarch,
>  			       struct regcache *regcache, CORE_ADDR addr);
> -
>  displaced_step_copy_insn_closure_up
>    aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
>  				    CORE_ADDR from, CORE_ADDR to,

This change is unrelated to this patch.

> diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
> index 2401a325b7b..a567938d06d 100644
> --- a/gdb/arch/aarch64.c
> +++ b/gdb/arch/aarch64.c
> @@ -28,6 +28,7 @@
>  #include "../features/aarch64-sme2.c"
>  #include "../features/aarch64-tls.c"
>  #include "../features/aarch64-gcs.c"
> +#include "../features/aarch64-poe.c"
>  #include "../features/aarch64-gcs-linux.c"
>  
>  /* See arch/aarch64.h.  */
> @@ -77,6 +78,9 @@ aarch64_create_target_description (const aarch64_features &features)
>    if (features.fpmr)
>      regnum = create_feature_aarch64_fpmr (tdesc.get (), regnum);
>  
> +  if (features.poe)
> +    regnum = create_feature_aarch64_poe (tdesc.get (), regnum);
> +
>    return tdesc;
>  }
>  
> diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
> index cf7318cbe74..4e4b50f729e 100644
> --- a/gdb/arch/aarch64.h
> +++ b/gdb/arch/aarch64.h
> @@ -35,6 +35,7 @@ struct aarch64_features
>    bool pauth = false;
>    bool mte = false;
>    bool fpmr = false;
> +  bool poe = false;

You should add a comment for this boolean, as mentioned by Matthieu and
Luis. Luis gave a good suggestion for the comment.

> diff --git a/gdb/features/aarch64-poe.xml b/gdb/features/aarch64-poe.xml
> new file mode 100644
> index 00000000000..43ee09e01d6
> --- /dev/null
> +++ b/gdb/features/aarch64-poe.xml
> @@ -0,0 +1,12 @@
> +<?xml version="1.0"?>
> +<!-- Copyright (C) 2026 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.poe">
> +

Please remove the extra blank line here.

> +  <reg name="por_el0" bitsize="64" type="uint64" group="system"/>
> +</feature>
> diff --git a/gdb/nat/aarch64-poe-linux.h b/gdb/nat/aarch64-poe-linux.h
> new file mode 100644
> index 00000000000..3d858d3ff92
> --- /dev/null
> +++ b/gdb/nat/aarch64-poe-linux.h
> @@ -0,0 +1,28 @@
> +/* Common native Linux definitions for AArch64 Permission Overlay Extension.
> +
> +   Copyright (C) 2026 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef GDB_NAT_AARCH64_POE_LINUX_H
> +#define GDB_NAT_AARCH64_POE_LINUX_H
> +

This file should include <asm/hwcap.h> so that the system definition is
used if available.

> +/* Feature check for Permission Overlay Extension.  */
> +#ifndef HWCAP2_POE
> +#define HWCAP2_POE (1ULL << 63)
> +#endif /* HWCAP2_POE */
> +
> +#endif /* GDB_NAT_AARCH64_POE_LINUX_H */
> diff --git a/include/elf/common.h b/include/elf/common.h
> index 1ae68221a89..f811b8daeb5 100644
> --- a/include/elf/common.h
> +++ b/include/elf/common.h
> @@ -760,6 +760,8 @@
>  					/*   Note: name must be "LINUX".  */
>  #define NT_ARM_FPMR     0x40e           /* AArch64 FPMR.  */
>  					/*   Note: name must be "LINUX".  */
> +#define NT_ARM_POE	0x40f		/* AArch64 POE register.  */
> +					/*   Note: name must be "LINUX".  */
>  #define NT_ARM_GCS	0x410		/* AArch64 Guarded Control Stack
>  					   registers.  */
>  					/*   Note  name must be "LINUX".  */

This file is under binutils' "jurisdiction", so you should move this
change to the bfd/readelf patch. And consequently also move that patch
to become the first of the series, since this patch needs the definition
above.

Finally, the bfd/readelf patch should be cc'd to the binutils mailing
list. Or alternatively sent there separately from this series.

-- 
Thiago
(he/him)

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

* Re: [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0
  2026-06-26 18:08 ` [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0 srinath.parvathaneni
@ 2026-06-27  7:03   ` Thiago Jung Bauermann
  2026-06-29  7:02     ` Srinath Parvathaneni
  0 siblings, 1 reply; 21+ messages in thread
From: Thiago Jung Bauermann @ 2026-06-27  7:03 UTC (permalink / raw)
  To: srinath.parvathaneni
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra.Sitorus, Matthieu.Longo

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Add custom printing support for the POR_EL0 register when displayed
> using `info registers` or `info all-registers`.
>
> The register value is decoded into a human-readable "rwx"
> representation for each nibble in the POR_EL0 register, making the
> POE permissions easier to interpret.
>
> Example:
> (gdb) set $por_el0=0xffffffff77777777
> (gdb) info register por_el0
> por_el0        0xffffffff77777777  [P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ]

Nice.

> ---
>  gdb/aarch64-tdep.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 86 insertions(+)
>
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index f1e1a9c7a19..3ef4e696c7c 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -3135,6 +3135,86 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
>  		  p_regnum);
>  }
>  
> +/* Convert a POR_EL0 Perm<m> overlay permission encoding into rwx-style string.
> +   For example:
> +     0b0011 -> "r-x" (3)
> +     0b0101 -> "rw-" (5)
> +     0b0111 -> "rwx" (7)
> +     0b0000 -> "---" (0)
> +   Reserved encodings (0b1xxx) are returned as "???".  */
> +
> +static const char*
> +aarch64_perm_overlay_decode (unsigned int perm)
> +{
> +  switch (perm)
> +   {
> +     case 0: return "---";
> +     case 1: return "r--";
> +     case 2: return "--x";
> +     case 3: return "r-x";
> +     case 4: return "-w-";
> +     case 5: return "rw-";
> +     case 6: return "-wx";
> +     case 7: return "rwx";
> +     default: return "???";
> +   }
> +}
> +
> +/* Display POE reigster POR_EL0 in the following format for the 'info registers'

Typo: reigster

> +   and 'info all-registers' commands:
> +   <register-name> <hex-value> [<decoded per-protection-key permissions>]  */
> +
> +static void
> +aarch64_print_poe_register_info (struct ui_file *file,
> +				 int regnum,
> +				 const char *name,
> +				 const frame_info_ptr &frame)
> +{
> +  value *val = value_of_register (regnum, get_next_frame_sentinel_okay (frame));
> +  ULONGEST por_el0 = (ULONGEST) value_as_long (val);
> +  gdb_printf (file, "%-14s 0x%s  [", name, phex_nz (por_el0, 8));
> +
> +  for (int i = 15; i >= 0; --i)
> +    {
> +      unsigned int perm = (por_el0 >> (i * 4)) & 0xf;
> +      gdb_printf (file, "P%d=%s ", i, aarch64_perm_overlay_decode (perm));
> +    }
> +
> +  gdb_puts ("]\n", file);
> +}
> +
> +/* For 'info registers' and 'info all-registers', print POR_EL0 using the
> +   custom POE register printer and all other registers using the default
> +   register printer.  */
> +
> +static void
> +aarch64_print_registers_info (struct gdbarch *gdbarch,
> +			      struct ui_file *file,
> +			      const frame_info_ptr &frame,
> +			      int regnum,
> +			      bool print_all)
> +{
> +  const int numregs = gdbarch_num_cooked_regs (gdbarch);
> +  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
> +
> +  if (regnum == -1)
> +    {
> +      for (int i = 0; i < numregs; i++)
> +	{
> +	  if (i == tdep->poe_regnum)
> +	    {
> +	      aarch64_print_poe_register_info (file, i, "por_el0", frame);
> +	      continue;
> +	    }
> +	  default_print_registers_info (gdbarch, file, frame,  i, print_all);
> +	}
> +    }
> +  else if (regnum == tdep->poe_regnum)
> +    aarch64_print_poe_register_info (file, regnum, "por_el0", frame);
> +  else
> +    default_print_registers_info (gdbarch, file, frame, regnum, print_all);
> +}
> +
>  /* Implement the "pseudo_register_reggroup_p" tdesc_arch_data method.  */
>  
>  static bool

Instead of adding this gdbarch hook, have you considered using enum
target types¹ in the feature XML instead? E.g:

<feature name="org.gnu.gdb.aarch64.poe">
  <enum id="perms_enum" size="4">
    <evalue name="---" value="0"/>
    <evalue name="r--" value="1"/>
    <evalue name="r-x" value="2"/>
    <evalue name="r-x" value="3"/>
    <evalue name="-w-" value="4"/>
    <evalue name="rw-" value="5"/>
    <evalue name="-wx" value="6"/>
    <evalue name="rwx" value="7"/>
    <!-- Maybe add the other 8 values as "???"? -->
  </enum>
  <flags id="por_flags" size="8">
    <field name="P0" start="0" end="3" type="perms_enum"/>
    <field name="P1" start="4" end="7" type="perms_enum"/>
    <field name="P2" start="8" end="11" type="perms_enum"/>
    <field name="P3" start="12" end="15" type="perms_enum"/>
    <!-- And so on until P15. -->
  </flags>

  <reg name="por_el0" bitsize="64" type="por_flags" group="system"/>
</feature>

Note that I haven't tested the above and I'm not sure it would actually
work (or work well).

I see two advantages:

- It works in the "print $por_el0" case too, not only "info register
  $por_el0". Or does this patch also work with "print $por_el0" as well?

- It's less code.

> @@ -4141,6 +4221,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc)
>    features.fpmr = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr")
>  		   != nullptr);
>  
> +  /* Check for POE feature.  */
> +  features.poe = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe")
> +		  != nullptr);
> +
>    return features;
>  }
>  
> @@ -4774,6 +4858,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    tdep->gcs_reg_base = first_gcs_regnum;
>    tdep->gcs_linux_reg_base = first_gcs_linux_regnum;
>    tdep->fpmr_regnum = fpmr_regnum;
> +  tdep->poe_regnum = poe_regnum;
>  
>    /* Set the SME register set details.  The pseudo-registers will be adjusted
>       later.  */

This change and the one above it in aarch64_features_from_target_desc
should be in the previous patch instead.

-- 
Thiago
(he/him)

¹ https://sourceware.org/gdb/current/onlinedocs/gdb.html/Enum-Target-Types.html#Enum-Target-Types

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

* Re: [PATCH v2 3/7] gdb: Improve SIGSEGV diagnostics for POE faults
  2026-06-26 18:08 ` [PATCH v2 3/7] gdb: Improve SIGSEGV diagnostics for POE faults srinath.parvathaneni
@ 2026-06-29  2:42   ` Thiago Jung Bauermann
  0 siblings, 0 replies; 21+ messages in thread
From: Thiago Jung Bauermann @ 2026-06-29  2:42 UTC (permalink / raw)
  To: srinath.parvathaneni
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra.Sitorus, Matthieu.Longo

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> When a SIGSEGV is caused by a Permission Overlay violation, include
> additional information in GDB's error message to help identify the
> failing address along with the responsible protection key causing
> this fault.
>
> Example:
> (gdb) c
> Continuing.
>
> Program received signal SIGSEGV, Segmentation fault
> Protection Key Violation while accessing address 0x0000fffff7ff3000 with Protection Key = 1.
> 0x0000aaaaaaaa0a3c in main () at poe_sigsegv.c:26
> ---
>  gdb/aarch64-linux-tdep.c | 20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)

This one looks good, thanks!

Of course, it needs to wait until the other patches in the series are
ready, but:

Approved-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

-- 
Thiago
(he/him)

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

* Re: [PATCH v2 4/7] gdbserver/aarch64: Add POR_EL0 register support
  2026-06-26 18:08 ` [PATCH v2 4/7] gdbserver/aarch64: Add POR_EL0 register support srinath.parvathaneni
@ 2026-06-29  2:43   ` Thiago Jung Bauermann
  0 siblings, 0 replies; 21+ messages in thread
From: Thiago Jung Bauermann @ 2026-06-29  2:43 UTC (permalink / raw)
  To: srinath.parvathaneni
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra.Sitorus, Matthieu.Longo

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Add support for transferring the POR_EL0 register between the Linux
> kernel and GDB during remote debugging.
>
> This patch implements the necessary `fill` and `store` operations using
> the `NT_ARM_POE` regset, allowing GDB to read and write the POR_EL0
> register when debugging a remote target that supports FEAT_S1POE.
> ---
>  gdbserver/linux-aarch64-low.cc | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)

Great, thanks!

Approved-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>


-- 
Thiago
(he/him)

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

* Re: [PATCH v2 5/7] bfd/readelf: Add core file support for FEAT_S1POE
  2026-06-26 18:08 ` [PATCH v2 5/7] bfd/readelf: Add core file support for FEAT_S1POE srinath.parvathaneni
@ 2026-06-29  2:43   ` Thiago Jung Bauermann
  0 siblings, 0 replies; 21+ messages in thread
From: Thiago Jung Bauermann @ 2026-06-29  2:43 UTC (permalink / raw)
  To: srinath.parvathaneni
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra.Sitorus, Matthieu.Longo

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Add support for `NT_ARM_POE` dumps/reads for core files.
> ---
>  bfd/elf.c          | 25 +++++++++++++++++++++++++
>  binutils/readelf.c |  2 ++
>  2 files changed, 27 insertions(+)

Assuming that the definition of NT_ARM_POE in include/elf/common.h is
moved to this patch, as I mentioned earlier:

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

-- 
Thiago
(he/him)

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

* Re: [PATCH v2 6/7] gdb/aarch64: Add core file support for FEAT_S1POE
  2026-06-26 18:08 ` [PATCH v2 6/7] gdb/aarch64: " srinath.parvathaneni
@ 2026-06-29  2:44   ` Thiago Jung Bauermann
  0 siblings, 0 replies; 21+ messages in thread
From: Thiago Jung Bauermann @ 2026-06-29  2:44 UTC (permalink / raw)
  To: srinath.parvathaneni
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra.Sitorus, Matthieu.Longo

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Add support for POR_EL0 dumps/reads for core files.

This descriptions is incomplete. The patch is also about adding support
for reading the POE value in the signal frame.

> ---
>  gdb/aarch64-linux-tdep.c | 51 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
>
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index b8a02ab9972..1d6d4c94b84 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -171,6 +171,7 @@
>  #define AARCH64_ZT_MAGIC			0x5a544e01
>  #define AARCH64_GCS_MAGIC			0x47435300
>  #define AARCH64_FPMR_MAGIC			0x46504d52
> +#define AARCH64_POE_MAGIC			0x504f4530
>  
>  /* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC.  */
>  #define AARCH64_EXTRA_DATAP_OFFSET		8
> @@ -220,6 +221,9 @@
>  /* FPMR constants.  */
>  #define AARCH64_FPMR_OFFSET			8
>  
> +/* POE constants.  */
> +#define AARCH64_POE_OFFSET			8
> +
>  /* Holds information about the signal frame.  */
>  struct aarch64_linux_sigframe
>  {
> @@ -273,6 +277,11 @@ struct aarch64_linux_sigframe
>    /* FPMR value.  */
>    CORE_ADDR fpmr = 0;
>  
> +  /* True if we have an POE entry in the signal context, false otherwise.  */
> +  bool poe_available = false;
> +  /* FPMR value.  */
> +  CORE_ADDR poe = 0;
> +

Extraneous empty line.

>  };
>  
>  /* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the
> @@ -605,6 +614,22 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame,
>  	    section += size;
>  	    break;
>  	  }
> +	case AARCH64_POE_MAGIC:
> +	  {
> +	    gdb_byte buf[8];
> +	    if (target_read_memory (section + AARCH64_POE_OFFSET,
> +				    buf, 8) != 0)
> +	      {
> +		warning (_("Failed to read the POE section address from the"
> +			   " signal frame context."));
> +		section += size;
> +		break;
> +	      }
> +	    signal_frame.poe = extract_unsigned_integer (buf, 8, byte_order);
> +	    signal_frame.poe_available = true;
> +	    section += size;
> +	    break;
> +	  }
>  	case AARCH64_EXTRA_MAGIC:
>  	  {
>  	    /* Extra is always the last valid section in reserved and points to
> @@ -775,6 +800,13 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
>  			      signal_frame.fpmr);
>    }
>  
> +  /* Handle POE register.  */
> +  if (tdep->has_poe () && signal_frame.poe_available != 0)

poe_available is a boolean, so you can just use "&&
signal_frame.poe_available".

> +  {
> +    trad_frame_set_reg_value (this_cache, tdep->poe_regnum,
> +			      signal_frame.poe);
> +  }
> +
>    /* Restore the tpidr2 register, if the target supports it and if there is
>       an entry for it.  */
>    if (signal_frame.tpidr2_section != 0 && tdep->has_tls ()

-- 
Thiago
(he/him)

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

* Re: [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0
  2026-06-27  7:03   ` Thiago Jung Bauermann
@ 2026-06-29  7:02     ` Srinath Parvathaneni
  2026-06-29 15:58       ` Ezra Sitorus
  0 siblings, 1 reply; 21+ messages in thread
From: Srinath Parvathaneni @ 2026-06-29  7:02 UTC (permalink / raw)
  To: Thiago Jung Bauermann
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra Sitorus, Matthieu Longo

[-- Attachment #1: Type: text/plain, Size: 9110 bytes --]

Hi,

>
>Instead of adding this gdbarch hook, have you considered using enum
>target types¹ in the feature XML instead? E.g:
>
><feature name="org.gnu.gdb.aarch64.poe">
>  <enum id="perms_enum" size="4">
>    <evalue name="---" value="0"/>
>    <evalue name="r--" value="1"/>
>    <evalue name="r-x" value="2"/>
>    <evalue name="r-x" value="3"/>
>    <evalue name="-w-" value="4"/>
>    <evalue name="rw-" value="5"/>
>    <evalue name="-wx" value="6"/>
>    <evalue name="rwx" value="7"/>
>    <!-- Maybe add the other 8 values as "???"? -->
>  </enum>
>  <flags id="por_flags" size="8">
>    <field name="P0" start="0" end="3" type="perms_enum"/>
>    <field name="P1" start="4" end="7" type="perms_enum"/>
>    <field name="P2" start="8" end="11" type="perms_enum"/>
>    <field name="P3" start="12" end="15" type="perms_enum"/>
>    <!-- And so on until P15. -->
>  </flags>
>
>  <reg name="por_el0" bitsize="64" type="por_flags" group="system"/>
></feature>
>
>Note that I haven't tested the above and I'm not sure it would actually
>work (or work well).
>
>I see two advantages:
>
>- It works in the "print $por_el0" case too, not only "info register
>  $por_el0". Or does this patch also work with "print $por_el0" as well?
>
>- It's less code.
>

Thanks Thiago for the review. I'll address the other review comments and
post a new version of the patches.

The approach you suggested above is actually what I used in v1
(https://sourceware.org/pipermail/gdb-patches/2026-June/228082.html).
With that approach, I was able to display the custom string for
info registers, info all-registers, and print $por_el0.

However, the problem I faced was when the register type was por_flags.
In that case, "set $por_el0 = <value>" failed with an "Invalid case" error.
Because of this, I had to drop support for writing to por_el0 in the initial
version of the patch.

When I tried to resolve this, the only approach I found was to use
type="uint64_t" so that set works and I have implement the custom string
handling specifically for info register $por_el0. The downside is that this does
not affect print $por_el0.

If you have any suggestions for avoiding the "Invalid case" issue with
set $por_el0 = <value>, I'd be happy to switch back to the original XML
approach from v1.

Regards
Srinath.

________________________________
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Sent: 27 June 2026 08:03
To: Srinath Parvathaneni <Srinath.Parvathaneni@arm.com>
Cc: gdb-patches@sourceware.org <gdb-patches@sourceware.org>; luis.machado.foss@gmail.com <luis.machado.foss@gmail.com>; guinevere@redhat.com <guinevere@redhat.com>; Ezra Sitorus <Ezra.Sitorus@arm.com>; Matthieu Longo <Matthieu.Longo@arm.com>
Subject: Re: [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Add custom printing support for the POR_EL0 register when displayed
> using `info registers` or `info all-registers`.
>
> The register value is decoded into a human-readable "rwx"
> representation for each nibble in the POR_EL0 register, making the
> POE permissions easier to interpret.
>
> Example:
> (gdb) set $por_el0=0xffffffff77777777
> (gdb) info register por_el0
> por_el0        0xffffffff77777777  [P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ]

Nice.

> ---
>  gdb/aarch64-tdep.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 86 insertions(+)
>
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index f1e1a9c7a19..3ef4e696c7c 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -3135,6 +3135,86 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
>                  p_regnum);
>  }
>
> +/* Convert a POR_EL0 Perm<m> overlay permission encoding into rwx-style string.
> +   For example:
> +     0b0011 -> "r-x" (3)
> +     0b0101 -> "rw-" (5)
> +     0b0111 -> "rwx" (7)
> +     0b0000 -> "---" (0)
> +   Reserved encodings (0b1xxx) are returned as "???".  */
> +
> +static const char*
> +aarch64_perm_overlay_decode (unsigned int perm)
> +{
> +  switch (perm)
> +   {
> +     case 0: return "---";
> +     case 1: return "r--";
> +     case 2: return "--x";
> +     case 3: return "r-x";
> +     case 4: return "-w-";
> +     case 5: return "rw-";
> +     case 6: return "-wx";
> +     case 7: return "rwx";
> +     default: return "???";
> +   }
> +}
> +
> +/* Display POE reigster POR_EL0 in the following format for the 'info registers'

Typo: reigster

> +   and 'info all-registers' commands:
> +   <register-name> <hex-value> [<decoded per-protection-key permissions>]  */
> +
> +static void
> +aarch64_print_poe_register_info (struct ui_file *file,
> +                              int regnum,
> +                              const char *name,
> +                              const frame_info_ptr &frame)
> +{
> +  value *val = value_of_register (regnum, get_next_frame_sentinel_okay (frame));
> +  ULONGEST por_el0 = (ULONGEST) value_as_long (val);
> +  gdb_printf (file, "%-14s 0x%s  [", name, phex_nz (por_el0, 8));
> +
> +  for (int i = 15; i >= 0; --i)
> +    {
> +      unsigned int perm = (por_el0 >> (i * 4)) & 0xf;
> +      gdb_printf (file, "P%d=%s ", i, aarch64_perm_overlay_decode (perm));
> +    }
> +
> +  gdb_puts ("]\n", file);
> +}
> +
> +/* For 'info registers' and 'info all-registers', print POR_EL0 using the
> +   custom POE register printer and all other registers using the default
> +   register printer.  */
> +
> +static void
> +aarch64_print_registers_info (struct gdbarch *gdbarch,
> +                           struct ui_file *file,
> +                           const frame_info_ptr &frame,
> +                           int regnum,
> +                           bool print_all)
> +{
> +  const int numregs = gdbarch_num_cooked_regs (gdbarch);
> +  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
> +
> +  if (regnum == -1)
> +    {
> +      for (int i = 0; i < numregs; i++)
> +     {
> +       if (i == tdep->poe_regnum)
> +         {
> +           aarch64_print_poe_register_info (file, i, "por_el0", frame);
> +           continue;
> +         }
> +       default_print_registers_info (gdbarch, file, frame,  i, print_all);
> +     }
> +    }
> +  else if (regnum == tdep->poe_regnum)
> +    aarch64_print_poe_register_info (file, regnum, "por_el0", frame);
> +  else
> +    default_print_registers_info (gdbarch, file, frame, regnum, print_all);
> +}
> +
>  /* Implement the "pseudo_register_reggroup_p" tdesc_arch_data method.  */
>
>  static bool

Instead of adding this gdbarch hook, have you considered using enum
target types¹ in the feature XML instead? E.g:

<feature name="org.gnu.gdb.aarch64.poe">
  <enum id="perms_enum" size="4">
    <evalue name="---" value="0"/>
    <evalue name="r--" value="1"/>
    <evalue name="r-x" value="2"/>
    <evalue name="r-x" value="3"/>
    <evalue name="-w-" value="4"/>
    <evalue name="rw-" value="5"/>
    <evalue name="-wx" value="6"/>
    <evalue name="rwx" value="7"/>
    <!-- Maybe add the other 8 values as "???"? -->
  </enum>
  <flags id="por_flags" size="8">
    <field name="P0" start="0" end="3" type="perms_enum"/>
    <field name="P1" start="4" end="7" type="perms_enum"/>
    <field name="P2" start="8" end="11" type="perms_enum"/>
    <field name="P3" start="12" end="15" type="perms_enum"/>
    <!-- And so on until P15. -->
  </flags>

  <reg name="por_el0" bitsize="64" type="por_flags" group="system"/>
</feature>

Note that I haven't tested the above and I'm not sure it would actually
work (or work well).

I see two advantages:

- It works in the "print $por_el0" case too, not only "info register
  $por_el0". Or does this patch also work with "print $por_el0" as well?

- It's less code.

> @@ -4141,6 +4221,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc)
>    features.fpmr = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr")
>                   != nullptr);
>
> +  /* Check for POE feature.  */
> +  features.poe = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe")
> +               != nullptr);
> +
>    return features;
>  }
>
> @@ -4774,6 +4858,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    tdep->gcs_reg_base = first_gcs_regnum;
>    tdep->gcs_linux_reg_base = first_gcs_linux_regnum;
>    tdep->fpmr_regnum = fpmr_regnum;
> +  tdep->poe_regnum = poe_regnum;
>
>    /* Set the SME register set details.  The pseudo-registers will be adjusted
>       later.  */

This change and the one above it in aarch64_features_from_target_desc
should be in the previous patch instead.

--
Thiago
(he/him)

¹ https://sourceware.org/gdb/current/onlinedocs/gdb.html/Enum-Target-Types.html#Enum-Target-Types

[-- Attachment #2: Type: text/html, Size: 26740 bytes --]

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

* Re: [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
  2026-06-27  6:06   ` Thiago Jung Bauermann
@ 2026-06-29 10:44     ` Srinath Parvathaneni
  2026-07-01  5:16       ` Thiago Jung Bauermann
  0 siblings, 1 reply; 21+ messages in thread
From: Srinath Parvathaneni @ 2026-06-29 10:44 UTC (permalink / raw)
  To: Thiago Jung Bauermann
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra Sitorus,
	Matthieu Longo, Mark Rutland, maz

[-- Attachment #1: Type: text/plain, Size: 16827 bytes --]

Hi,

>> *  info registers por_el0
>> *  p $por_el0
>> *  p/x $por_el0
>> *  set $por_el0 = <value>
>
>One question, more about general policy on the AArch64 GDB port:
>
>Should the register name have the _el0 suffix? It's more than half of
>the register name (though tab completion helps).
>
>We don't currently have that suffix in the name of any register. And in
>the case of Guarded Control Stack, I didn't add it. For native
>debugging, it will always be the register at EL0. For remote debugging,
>I assumed the target would send the register corresponding to the
>current exception level in the inferior.
>
>Can there be a situation where it would be possible to see both the EL0
>and EL1 (for example) registers at the same time? Or a situation where
>the inferior is at EL1 but one wants to see the register at EL0, or
>vice-versa?
>

Thanks Thiago for the review. I'll address the other review comments and
post a new version of the patches.

I'm happy to follow the existing AArch64 GDB convention and expose the register
as `POR` for consistency.

That said, after discussing this with kernel/KVM developers, there are valid
debugging scenarios (e.g. KGDB or guest debugging via KVM/QEMU) where exposing
`POR_EL0`, `POR_EL1`, and `POR_EL2` simultaneously would be useful. This seems
like a broader GDB register naming issue rather than something specific to
FEAT_S1POE.

CC'ing Mark Rutland and Marc Zyngier, who can provide more context on
those use cases.

Regards,
Srinath
________________________________
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Sent: 27 June 2026 07:06
To: Srinath Parvathaneni <Srinath.Parvathaneni@arm.com>
Cc: gdb-patches@sourceware.org <gdb-patches@sourceware.org>; luis.machado.foss@gmail.com <luis.machado.foss@gmail.com>; guinevere@redhat.com <guinevere@redhat.com>; Ezra Sitorus <Ezra.Sitorus@arm.com>; Matthieu Longo <Matthieu.Longo@arm.com>
Subject: Re: [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE

Hello Srinath,

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Add support for the FEAT_S1POE POR_EL0 register on AArch64.
>
> This patch adds POR_EL0 to the AArch64 register set and reads/writes it
> using the NT_ARM_POE ptrace regset.
>
> With this change, POR_EL0 is available through:
> *  info registers
> *  info registers por_el0
> *  p $por_el0
> *  p/x $por_el0
> *  set $por_el0 = <value>

One question, more about general policy on the AArch64 GDB port:

Should the register name have the _el0 suffix? It's more than half of
the register name (though tab completion helps).

We don't currently have that suffix in the name of any register. And in
the case of Guarded Control Stack, I didn't add it. For native
debugging, it will always be the register at EL0. For remote debugging,
I assumed the target would send the register corresponding to the
current exception level in the inferior.

Can there be a situation where it would be possible to see both the EL0
and EL1 (for example) registers at the same time? Or a situation where
the inferior is at EL1 but one wants to see the register at EL0, or
vice-versa?

> ---
>  gdb/Makefile.in              |  2 ++
>  gdb/aarch64-linux-nat.c      | 66 ++++++++++++++++++++++++++++++++++++
>  gdb/aarch64-linux-tdep.c     |  1 +
>  gdb/aarch64-tdep.c           | 18 ++++++++++
>  gdb/aarch64-tdep.h           | 11 +++++-
>  gdb/arch/aarch64-poe-linux.h | 29 ++++++++++++++++
>  gdb/arch/aarch64.c           |  4 +++
>  gdb/arch/aarch64.h           |  7 +++-
>  gdb/features/Makefile        |  1 +
>  gdb/features/aarch64-poe.c   | 14 ++++++++
>  gdb/features/aarch64-poe.xml | 12 +++++++
>  gdb/nat/aarch64-poe-linux.h  | 28 +++++++++++++++
>  include/elf/common.h         |  2 ++
>  13 files changed, 193 insertions(+), 2 deletions(-)
>  create mode 100644 gdb/arch/aarch64-poe-linux.h
>  create mode 100644 gdb/features/aarch64-poe.c
>  create mode 100644 gdb/features/aarch64-poe.xml
>  create mode 100644 gdb/nat/aarch64-poe-linux.h
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 57f384170ab..3dc9cd07dcb 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -1292,6 +1292,7 @@ HFILES_NO_SRCDIR = \
>        arch/aarch32.h \
>        arch/aarch64-fpmr-linux.h \
>        arch/aarch64-gcs-linux.h \
> +     arch/aarch64-poe-linux.h \
>        arch/aarch64.h \
>        arch/aarch64-insn.h \
>        arch/aarch64-mte.h \
> @@ -1540,6 +1541,7 @@ HFILES_NO_SRCDIR = \
>        namespace.h \
>        nat/aarch64-fpmr-linux.h \
>        nat/aarch64-gcs-linux.h \
> +     nat/aarch64-poe-linux.h \
>        nat/aarch64-hw-point.h \
>        nat/aarch64-linux.h \
>        nat/aarch64-linux-hw-point.h \
> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index 52ace4aab41..54265920d69 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -34,6 +34,7 @@
>  #include "arch/arm.h"
>  #include "nat/aarch64-fpmr-linux.h"
>  #include "nat/aarch64-gcs-linux.h"
> +#include "nat/aarch64-poe-linux.h"
>  #include "nat/aarch64-linux.h"
>  #include "nat/aarch64-linux-hw-point.h"
>  #include "nat/aarch64-mte-linux-ptrace.h"
> @@ -569,6 +570,54 @@ fetch_gcsregs_from_thread (regcache *regcache)
>                        &user_gcs.features_locked);
>  }
>
> +/* Fill GDB's register array with the POE register value from the current
> +   thread.  */
> +
> +static void
> +fetch_poeregs_from_thread (regcache *regcache)
> +{
> +  aarch64_gdbarch_tdep *tdep
> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
> +
> +  gdb_assert (tdep->has_poe ());
> +
> +  uint64_t user_poe;
> +  iovec iovec;
> +
> +  iovec.iov_base = &user_poe;
> +  iovec.iov_len = sizeof (user_poe);
> +
> +  int tid = get_ptrace_pid (regcache->ptid ());
> +  if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_POE, &iovec) != 0)
> +    perror_with_name (_("Unable to fetch POE register"));
> +
> +  regcache->raw_supply (tdep->poe_regnum, &user_poe);
> +}
> +
> +/* Store the NT_ARM_POE register contents from GDB's REGCACHE to the
> +    thread associated with REGCACHE.  */
> +
> +static void
> +store_poeregs_to_thread (struct regcache *regcache)
> +{
> +  aarch64_gdbarch_tdep *tdep
> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
> +
> +  gdb_assert (tdep->has_poe ());
> +
> +  int tid = regcache->ptid ().lwp ();
> +
> +  iovec iovec;
> +  uint64_t user_poe;
> +  iovec.iov_base = &user_poe;
> +  iovec.iov_len = sizeof (user_poe);
> +
> +  regcache->raw_collect (tdep->poe_regnum, &user_poe);
> +
> +  if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_POE, &iovec) != 0)
> +    perror_with_name (_("Unable to store POE register"));
> +}
> +
>  /* Store to the current thread the valid GCS register set in the GDB's
>     register array.  */

These functions are fine, but they were added between
fetch_gcsregs_from_thread and store_gcsregs_to_thread. For better
organization of the file, they should be either before or after the GCS
ones.

> @@ -683,6 +732,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
>        if (tdep->has_gcs_linux ())
>        fetch_gcsregs_from_thread (regcache);
>
> +      if (tdep->has_poe ())
> +     fetch_poeregs_from_thread (regcache);
> +
>        if (tdep->has_fpmr ())
>        fetch_fpmr_from_thread (regcache);
>      }
> @@ -722,6 +774,10 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
>           && (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base
>               || regno == tdep->gcs_linux_reg_base + 1))
>      fetch_gcsregs_from_thread (regcache);
> +  /* POE register?  */
> +  else if (tdep->has_poe () && (regno == tdep->poe_regnum))
> +    fetch_poeregs_from_thread (regcache);
> +

Please remove the extra blank line here.

>    /* FPMR?  */
>    else if (tdep->has_fpmr () && (regno == tdep->fpmr_regnum))
>      fetch_fpmr_from_thread (regcache);
> @@ -802,6 +858,9 @@ aarch64_store_registers (struct regcache *regcache, int regno)
>
>        if (tdep->has_fpmr ())
>        store_fpmr_to_thread (regcache);
> +
> +      if (tdep->has_poe ())
> +     store_poeregs_to_thread (regcache);
>      }
>    /* General purpose register?  */
>    else if (regno < AARCH64_V0_REGNUM)
> @@ -837,6 +896,10 @@ aarch64_store_registers (struct regcache *regcache, int regno)
>    else if (tdep->has_fpmr () && regno == tdep->fpmr_regnum)
>      store_fpmr_to_thread (regcache);
>

Please remove the extra blank line here. The else ifs should be joined.

> +  /* POE register?  */
> +  else if (tdep->has_poe () && regno == tdep->poe_regnum)
> +    store_poeregs_to_thread (regcache);
> +
>    /* PAuth registers are read-only.  */
>  }
>
> @@ -1024,6 +1087,9 @@ aarch64_linux_nat_target::read_description ()
>    /* Check for FPMR.  */
>    features.fpmr = hwcap2 & HWCAP2_FPMR;
>
> +  /* Check for POE support.  */
> +  features.poe = hwcap2 & HWCAP2_POE;
> +
>    return aarch64_read_description (features);
>  }
>
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index f11eccc1bc1..4a6bc3158c8 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -53,6 +53,7 @@
>
>  #include "arch/aarch64-fpmr-linux.h"
>  #include "arch/aarch64-gcs-linux.h"
> +#include "arch/aarch64-poe-linux.h"
>  #include "arch/aarch64-mte.h"
>  #include "arch/aarch64-mte-linux.h"
>  #include "arch/aarch64-pauth-linux.h"

This should be moved to the patch that makes use of the new header.

> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index 886e7ce1e7b..f1e1a9c7a19 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -164,6 +164,11 @@ static const char *const aarch64_gcs_register_names[] = {
>    "gcspr"
>  };
>
> +static const char *const aarch64_poe_register_names[] = {
> +  /* Permission Overlay Extension Register.  */
> +  "por_el0"
> +};
> +
>  static const char *const aarch64_gcs_linux_register_names[] = {
>    /* Field in struct user_gcs.  */
>    "gcs_features_enabled",
> @@ -4556,6 +4561,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>                                          fpmr_regnum, "fpmr");
>      }
>
> +  int poe_regnum = -1;
> +  const struct tdesc_feature *feature_poe
> +      = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe");
> +  if (feature_poe != nullptr)
> +    {
> +      poe_regnum = num_regs;
> +      for (i = 0; i < ARRAY_SIZE (aarch64_poe_register_names); i++)
> +     valid_p &= tdesc_numbered_register (feature_poe, tdesc_data.get (),
> +                                         poe_regnum + i,
> +                                         aarch64_poe_register_names[i]);
> +      num_regs++;
> +    }
> +
>    int first_sme_regnum = -1;
>    int first_sme2_regnum = -1;
>    int first_sme_pseudo_regnum = -1;
> diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
> index dff05a08f84..8029725b145 100644
> --- a/gdb/aarch64-tdep.h
> +++ b/gdb/aarch64-tdep.h
> @@ -208,6 +208,16 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base
>      return gcs_linux_reg_base != -1;
>    }
>
> +  /* POE register.  This is -1 if no POE feature is available.  */
> +  int poe_regnum = -1;
> +
> +  /* Returns true if the target supports the Linux POE feature.  */

Remove the "Linux" word, since the feature isn't specific to it, and
also because this header file isn't OS-specific.

> +  bool
> +  has_poe () const
> +  {
> +    return poe_regnum != -1;
> +  }
> +
>    /* First FPMR register.  This is -1 if FPMR is not supported.  */
>    int fpmr_regnum = -1;
>
> @@ -224,7 +234,6 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc);
>
>  extern int aarch64_process_record (struct gdbarch *gdbarch,
>                               struct regcache *regcache, CORE_ADDR addr);
> -
>  displaced_step_copy_insn_closure_up
>    aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
>                                    CORE_ADDR from, CORE_ADDR to,

This change is unrelated to this patch.

> diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
> index 2401a325b7b..a567938d06d 100644
> --- a/gdb/arch/aarch64.c
> +++ b/gdb/arch/aarch64.c
> @@ -28,6 +28,7 @@
>  #include "../features/aarch64-sme2.c"
>  #include "../features/aarch64-tls.c"
>  #include "../features/aarch64-gcs.c"
> +#include "../features/aarch64-poe.c"
>  #include "../features/aarch64-gcs-linux.c"
>
>  /* See arch/aarch64.h.  */
> @@ -77,6 +78,9 @@ aarch64_create_target_description (const aarch64_features &features)
>    if (features.fpmr)
>      regnum = create_feature_aarch64_fpmr (tdesc.get (), regnum);
>
> +  if (features.poe)
> +    regnum = create_feature_aarch64_poe (tdesc.get (), regnum);
> +
>    return tdesc;
>  }
>
> diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
> index cf7318cbe74..4e4b50f729e 100644
> --- a/gdb/arch/aarch64.h
> +++ b/gdb/arch/aarch64.h
> @@ -35,6 +35,7 @@ struct aarch64_features
>    bool pauth = false;
>    bool mte = false;
>    bool fpmr = false;
> +  bool poe = false;

You should add a comment for this boolean, as mentioned by Matthieu and
Luis. Luis gave a good suggestion for the comment.

> diff --git a/gdb/features/aarch64-poe.xml b/gdb/features/aarch64-poe.xml
> new file mode 100644
> index 00000000000..43ee09e01d6
> --- /dev/null
> +++ b/gdb/features/aarch64-poe.xml
> @@ -0,0 +1,12 @@
> +<?xml version="1.0"?>
> +<!-- Copyright (C) 2026 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.poe">
> +

Please remove the extra blank line here.

> +  <reg name="por_el0" bitsize="64" type="uint64" group="system"/>
> +</feature>
> diff --git a/gdb/nat/aarch64-poe-linux.h b/gdb/nat/aarch64-poe-linux.h
> new file mode 100644
> index 00000000000..3d858d3ff92
> --- /dev/null
> +++ b/gdb/nat/aarch64-poe-linux.h
> @@ -0,0 +1,28 @@
> +/* Common native Linux definitions for AArch64 Permission Overlay Extension.
> +
> +   Copyright (C) 2026 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef GDB_NAT_AARCH64_POE_LINUX_H
> +#define GDB_NAT_AARCH64_POE_LINUX_H
> +

This file should include <asm/hwcap.h> so that the system definition is
used if available.

> +/* Feature check for Permission Overlay Extension.  */
> +#ifndef HWCAP2_POE
> +#define HWCAP2_POE (1ULL << 63)
> +#endif /* HWCAP2_POE */
> +
> +#endif /* GDB_NAT_AARCH64_POE_LINUX_H */
> diff --git a/include/elf/common.h b/include/elf/common.h
> index 1ae68221a89..f811b8daeb5 100644
> --- a/include/elf/common.h
> +++ b/include/elf/common.h
> @@ -760,6 +760,8 @@
>                                        /*   Note: name must be "LINUX".  */
>  #define NT_ARM_FPMR     0x40e           /* AArch64 FPMR.  */
>                                        /*   Note: name must be "LINUX".  */
> +#define NT_ARM_POE   0x40f           /* AArch64 POE register.  */
> +                                     /*   Note: name must be "LINUX".  */
>  #define NT_ARM_GCS   0x410           /* AArch64 Guarded Control Stack
>                                           registers.  */
>                                        /*   Note  name must be "LINUX".  */

This file is under binutils' "jurisdiction", so you should move this
change to the bfd/readelf patch. And consequently also move that patch
to become the first of the series, since this patch needs the definition
above.

Finally, the bfd/readelf patch should be cc'd to the binutils mailing
list. Or alternatively sent there separately from this series.

--
Thiago
(he/him)

[-- Attachment #2: Type: text/html, Size: 33427 bytes --]

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

* Re: [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature
  2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
                   ` (6 preceding siblings ...)
  2026-06-26 18:08 ` [PATCH v2 7/7] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni
@ 2026-06-29 12:18 ` Guinevere Larsen
  7 siblings, 0 replies; 21+ messages in thread
From: Guinevere Larsen @ 2026-06-29 12:18 UTC (permalink / raw)
  To: srinath.parvathaneni, gdb-patches
  Cc: thiago.bauermann, luis.machado.foss, Ezra.Sitorus, Matthieu.Longo

On 6/26/26 3:08 PM, srinath.parvathaneni@arm.com wrote:
> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Thanks Matthieu, Ezra and Luis for the reviews.
>
> Changes v1 -> v2:
>
> * Rebased the SIGSEGV diagnostic support on Matthieu Longo's generic
>    "siginfo_t" changes, using the new "_._addr_pkey.si_pkey" layout
>    instead of introducing a target-specific "siginfo_t" extension.
>
> * Split the original series into smaller, subsystem-specific patches:
>    * GDB register support
>    * POR_EL0 pretty printing
>    * SIGSEGV diagnostics
>    * gdbserver support
>    * BFD/readelf core file support
>    * GDB core file support
>    * Testsuite
>
> * Separated BFD/readelf and GDB core file support into independent
>    patches.
>
> * Retained FEAT_S1POE expansion as "Permission Overlay Extension" after internal discussion.
>
> * Removed the POR_EL0 permission decoding string (e.g. `por_el0[pkey=<value>] = rwx`) from
>    SIGSEGV diagnostics, as displaying permissions without also showing base and effective
>    permissions can be misleading to users.
>
> * Rebased the series onto current upstream master + Matthieu's patch
>    "gdb: align siginfo_t with the Linux kernel definition"
>
> ----------------
> Hi,
>
> This series adds support for the AArch64 Permission Overlay Extension
> (FEAT_S1POE) in GDB, gdbserver, BFD and the testsuite.

Hi Srinath!

I don't know much about the arm architecture or this extension in 
specific, but it seems that it at least adds new registers so this seems 
like a valid question: Do these impact recording of ARM instructions 
with the record-full subsystem at all?

It would be nice to have a gdb.reverse test that exercises some (ideally 
all) new instructions if there are any, and some other instructions that 
manipulate those new registers, if needed.

This isn't required to get this series merged, of course, but it would 
be very nice to have it.

-- 
Cheers,
Guinevere Larsen
it/its
she/her (deprecated)

>
> The series introduces support for the POR_EL0 register, allowing GDB to
> read and write the register using the Linux "NT_ARM_POE" regset. It also
> improves SIGSEGV diagnostics for Permission Overlay violations and
> extends gdbserver and core file handling to preserve POR_EL0 during
> remote debugging and core file analysis.
>
> The series consists of the following patches:
>
> [1/7] gdb/aarch64: Add POR_EL0 register support
> Add POR_EL0 to the AArch64 register set and support reading and
> writing the register using the Linux "NT_ARM_POE" regset.
>
> [2/7] gdb/aarch64: Add custom printing for POR_EL0
> Add custom printing support for the POR_EL0 register.
>
> [3/7] gdb: Improve SIGSEGV diagnostics for POE faults
> Report the faulting address together with the associated
> protection key for Permission Overlay violations.
>
> [4/7] gdbserver/aarch64: Add POR_EL0 register support
> Transfer POR_EL0 through the Linux "NT_ARM_POE" regset during
> remote debugging.
>
> [5/7] bfd/readelf: Add core file support for FEAT_S1POE
> Add support for the "NT_ARM_POE" core file note.
>
> [6/7] gdb/aarch64: Add core file support for FEAT_S1POE
> Restore POR_EL0 from core files.
>
> [7/7] gdb/testsuite: Add FEAT_S1POE testcases
> Add tests covering register access, SIGSEGV diagnostics,
> fix-and-continue, and core file support.
>
> The series has been tested natively and using gdbserver with
> remote GDB on an FVP built using shrinkwrap with a Linux kernel
> configured with "CONFIG_ARM64_POE=y" and a glibc version
> providing userspace POE support.
>
> Regression tested on aarch64-none-linux-gnu with no regressions.
>
> Ok for Binutils-GDB ?
>
> Regards,
> Srinath
>
> Srinath Parvathaneni (7):
>    gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
>    gdb/aarch64: Add custom printing for POR_EL0
>    gdb: Improve SIGSEGV diagnostics for POE faults
>    gdbserver/aarch64: Add POR_EL0 register support
>    bfd/readelf: Add core file support for FEAT_S1POE
>    gdb/aarch64: Add core file support for FEAT_S1POE
>    gdb/testsuite: Add FEAT_S1POE testcases
>
>   bfd/elf.c                                     |  25 +++++
>   binutils/readelf.c                            |   2 +
>   gdb/Makefile.in                               |   2 +
>   gdb/aarch64-linux-nat.c                       |  66 +++++++++++
>   gdb/aarch64-linux-tdep.c                      |  72 +++++++++++-
>   gdb/aarch64-tdep.c                            | 104 ++++++++++++++++++
>   gdb/aarch64-tdep.h                            |  11 +-
>   gdb/arch/aarch64-poe-linux.h                  |  29 +++++
>   gdb/arch/aarch64.c                            |   4 +
>   gdb/arch/aarch64.h                            |   7 +-
>   gdb/features/Makefile                         |   1 +
>   gdb/features/aarch64-poe.c                    |  14 +++
>   gdb/features/aarch64-poe.xml                  |  12 ++
>   gdb/nat/aarch64-poe-linux.h                   |  28 +++++
>   gdb/testsuite/gdb.arch/aarch64-poe-core.exp   | 102 +++++++++++++++++
>   gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c  |  52 +++++++++
>   .../gdb.arch/aarch64-poe-sigsegv.exp          |  60 ++++++++++
>   gdb/testsuite/gdb.arch/aarch64-poe.c          |  29 +++++
>   gdb/testsuite/gdb.arch/aarch64-poe.exp        |  44 ++++++++
>   gdb/testsuite/lib/gdb.exp                     |  55 +++++++++
>   gdbserver/linux-aarch64-low.cc                |  30 +++++
>   include/elf/common.h                          |   2 +
>   22 files changed, 746 insertions(+), 5 deletions(-)
>   create mode 100644 gdb/arch/aarch64-poe-linux.h
>   create mode 100644 gdb/features/aarch64-poe.c
>   create mode 100644 gdb/features/aarch64-poe.xml
>   create mode 100644 gdb/nat/aarch64-poe-linux.h
>   create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-core.exp
>   create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
>   create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
>   create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.c
>   create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.exp
>


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

* Re: [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0
  2026-06-29  7:02     ` Srinath Parvathaneni
@ 2026-06-29 15:58       ` Ezra Sitorus
  0 siblings, 0 replies; 21+ messages in thread
From: Ezra Sitorus @ 2026-06-29 15:58 UTC (permalink / raw)
  To: Srinath Parvathaneni
  Cc: Thiago Jung Bauermann, gdb-patches, luis.machado.foss, guinevere,
	Matthieu Longo

> The approach you suggested above is actually what I used in v1
> (https://sourceware.org/pipermail/gdb-patches/2026-June/228082.html).
> With that approach, I was able to display the custom string for
> info registers, info all-registers, and print $por_el0.
> 
> However, the problem I faced was when the register type was por_flags.
> In that case, "set $por_el0 = <value>" failed with an "Invalid case" error.
> Because of this, I had to drop support for writing to por_el0 in the initial
> version of the patch.
> 
> When I tried to resolve this, the only approach I found was to use
> type="uint64_t" so that set works and I have implement the custom string
> handling specifically for info register $por_el0. The downside is that this does
> not affect print $por_el0.

Your v1 version/Thiago's suggestion seems to be what I did for fpmr.  I'm not
sure how it's different than the fpmr case - there's even a test case where I
check writing to fpmr as well: gdb/testsuite/gdb.arch/aarch64-fpmr.exp. This
seems just like the test you have in the patch no. 7 tests.

I'll try to test out your new patch series with the XML version. The previous
version didn't have store_poeregs_to_thread.

Ezra

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

* Re: [PATCH v2 7/7] gdb/testsuite: Add FEAT_S1POE testcases
  2026-06-26 18:08 ` [PATCH v2 7/7] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni
@ 2026-07-01  5:12   ` Thiago Jung Bauermann
  0 siblings, 0 replies; 21+ messages in thread
From: Thiago Jung Bauermann @ 2026-07-01  5:12 UTC (permalink / raw)
  To: srinath.parvathaneni
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra.Sitorus, Matthieu.Longo

Hello Srinath,

Today I ran the testcases on FVP and was able to complete the review of
this patch. Sorry for the delay.

<srinath.parvathaneni@arm.com> writes:

> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Add testcases for POR_EL0 register access, SIGSEGV diagnostics, fix-and-continue
> support (updating $por_el0 after SIGSEGV and continuing with signal 0), and core
> file support.

A good selection of test scenarios, thanks!

> ---
>  gdb/testsuite/gdb.arch/aarch64-poe-core.exp   | 102 ++++++++++++++++++
>  gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c  |  52 +++++++++
>  .../gdb.arch/aarch64-poe-sigsegv.exp          |  60 +++++++++++
>  gdb/testsuite/gdb.arch/aarch64-poe.c          |  29 +++++
>  gdb/testsuite/gdb.arch/aarch64-poe.exp        |  44 ++++++++
>  gdb/testsuite/lib/gdb.exp                     |  55 ++++++++++
>  6 files changed, 342 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-core.exp
>  create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
>  create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
>  create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.c
>  create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.exp
>
> diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-core.exp b/gdb/testsuite/gdb.arch/aarch64-poe-core.exp
> new file mode 100644
> index 00000000000..ab998781f10
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-poe-core.exp
> @@ -0,0 +1,102 @@
> +# Copyright (C) 2026 Free Software Foundation, Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# This file is part of the gdb testsuite.
> +
> +# Test generating and reading a core file with POR_EL0.
> +
> +proc check_poe_core_file {core_filename} {
> +    # Load the core file.
> +    if {
> +        [gdb_test "core $core_filename" \

This file is indented only with spaces, when the GDB style is to use
tabs and spaces. Please adjust.

I recently mentioned the .editorconfig file which we use to help
configure editors to automatically use the right settings, perhaps it
can be useful:

https://inbox.sourceware.org/gdb-patches/87zf0jwr23.fsf@linaro.org/

> +            [multi_line \
> +                "Core was generated by .*" \
> +                "Program terminated with signal SIGSEGV, Segmentation fault\\." \

This regexp isn't matching in my test run because GDB doesn't print the
last dot:

Core was generated by `/home/bauermann/.cache/builds/gdb-native/gdb/testsuite/outputs/gdb.arch/aarch64-poe-core/aarch64-poe-core'.^M
Program terminated with signal SIGSEGV, Segmentation fault^M
Protection Key Violation while accessing address 0x0000fffff7ff3000 with Protection Key = 1.^M
#0  0x0000aaaaaaaa09a4 in main () at /home/bauermann/src/binutils-gdb/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c:49^M
49	  buf[0] = 42;  /* Expect SIGSEGV POE violation.  */^M
(gdb) FAIL: gdb.arch/aarch64-poe-core.exp: gcore corefile: load core file
UNTESTED: gdb.arch/aarch64-poe-core.exp: gcore corefile: failed to load core file

> +                "Protection Key Violation while accessing address ${::hex} with Protection Key = ${::decimal}\\." \
> +                "#0  ${::hex} in main \\(.*\\) at .*" \
> +                ".*buf\\\[0\\\] = 42;.*"] \
> +            "load core file"]
> +    } {
> +        untested "failed to load core file"
> +        return -1
> +    }
> +
> +    # Check the value of POR_EL0 in the core file.
> +    gdb_test "print/x \$por_el0" " = 0x55" \
> +        "por_el0 contents from core file"

When I remove the dot from the pattern above, this test fails:

print/x $por_el0^M
$1 = 0x37^M
(gdb) FAIL: gdb.arch/aarch64-poe-core.exp: gcore corefile: por_el0 contents from core file

I get the output above both for the gcore and the native corefile.

> +}
> +
> +require is_aarch64_target

This require is redundant, since allow_aarch64_poe_tests already calls
is_aarch64_target.

> +require allow_aarch64_poe_tests
> +
> +standard_testfile aarch64-poe-sigsegv.c
> +
> +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
> +    return
> +}
> +
> +set binfile [standard_output_file ${testfile}]
> +
> +if {![runto_main]} {
> +    return
> +}
> +
> +set poe_crash_re [multi_line \
> +    "Program received signal SIGSEGV, Segmentation fault\\." \

I also had to remove the dot here to make the RE match.

> +    "Protection Key Violation while accessing address ${::hex} with Protection Key = ${::decimal}\\." \
> +    ".*buf\\\[0\\\] = 42;.*"]
> +
> +gdb_test_multiple "continue" "run to POE crash" {
> +    -re "$poe_crash_re.*$gdb_prompt $" {

$poe_crash_re already has .* at the end, so either remove .* there or
here.

> +        pass $gdb_test_name
> +    }
> +
> +    -re ".*exited with code 01.*$gdb_prompt $" {
> +        unsupported "POE userspace support unavailable"
> +        return
> +    }
> +}
> +
> +# Generate the gcore core file.
> +set gcore_filename [standard_output_file "${testfile}.gcore"]
> +set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"]
> +
> +# Generate a native core file.
> +set core_filename [core_find ${binfile}]
> +set core_generated [expr {$core_filename != ""}]
> +
> +# At this point we have a couple core files, the gcore one generated by GDB
> +# and the native one generated by the Linux Kernel.  Make sure GDB can read
> +# both correctly.
> +
> +if {$gcore_generated} {
> +    clean_restart
> +    gdb_load ${binfile}
> +    with_test_prefix "gcore corefile" {
> +        check_poe_core_file $gcore_filename
> +    }
> +} else {
> +    fail "gcore corefile not generated"
> +}
> +
> +if {$core_generated} {
> +    clean_restart
> +    gdb_load ${binfile}
> +    with_test_prefix "native corefile" {
> +        check_poe_core_file $core_filename
> +    }
> +} else {
> +    untested "native corefile not generated"
> +}
> diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
> new file mode 100644
> index 00000000000..6b0c07e782f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
> @@ -0,0 +1,52 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2026 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +/* Exercise AArch64's POE Extension.  */
> +
> +/* This test is based on the Linux kernel documentation for Memory
> +   Protection Keys, including the arm64 Permission Overlay Extension
> +   (FEAT_S1POE) support described in
> +   Documentation/core-api/protection-keys.rst.  */
> +
> +#define _GNU_SOURCE
> +#include <sys/mman.h>
> +#include <unistd.h>
> +
> +int
> +main (void)
> +{
> +  long pagesize = sysconf (_SC_PAGESIZE);
> +
> +  int *buf = mmap (NULL, pagesize, PROT_READ | PROT_WRITE,
> +		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> +  if (buf == MAP_FAILED)
> +    return 1;
> +
> +  int pkey = pkey_alloc (0, 0);
> +  if (pkey == -1)
> +    return 1;
> +
> +  if (pkey_mprotect (buf, pagesize, PROT_READ | PROT_WRITE, pkey) == -1)
> +    return 1;
> +
> +  if (pkey_set (pkey, PKEY_DISABLE_WRITE) == -1)
> +    return 1;
> +
> +  buf[0] = 42;  /* Expect SIGSEGV POE violation.  */
> +
> +  return 1;

This needs to be "return 0" for aarch64-poe-sigsegv.exp to pass.

> +}
> diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
> new file mode 100644
> index 00000000000..b22814f9ab9
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
> @@ -0,0 +1,60 @@
> +# Copyright (C) 2026 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# Test a binary that supports FEAT_S1POE and exposes POR_EL0 register.
> +
> +global hex
> +global decimal
> +
> +require is_aarch64_target
> +
> +if {![allow_aarch64_poe_tests]} {
> +    unsupported "AArch64 POE not supported"
> +    return
> +}

Like in the previous testcase, is_aarch64_target is redundant, and the
if block above should just be "require allow_aarch64_poe_tests".

> +
> +standard_testfile
> +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
> +    return
> +}
> +
> +if {![runto_main]} {
> +    return
> +}
> +
> +# Display POE violation SIGSEGV error message.
> +set poe_sigsegv_re [multi_line \
> +    "Program received signal SIGSEGV, Segmentation fault\\." \
> +    "Protection Key Violation while accessing address ${hex} with Protection Key = ${decimal}"]
> +
> +gdb_test_multiple "continue" "display POE violation information" {
> +    -re "$poe_sigsegv_re.*$gdb_prompt $" {
> +	pass $gdb_test_name
> +    }
> +    -re ".*exited with code 01.*$gdb_prompt $" {
> +	unsupported "POE userspace support unavailable"
> +	return
> +    }
> +}
> +
> +# Fix the POE permissions (set $por_el0) and continue without delivering SIGSEGV.
> +gdb_test "set \$por_el0 = 0x47" "" \
> +    "allow write access by updating POR_EL0"

It's clearer to use gdb_test_no_output here.

> +
> +gdb_test_multiple "signal 0" "continue after fixing POE fault" {
> +    -re ".*exited normally.*$gdb_prompt $" {

Here is where the change of the last return statement in
aarch64-poe-sigsegv.c is needed, otherwise I get:

signal 0^M
Continuing with no signal.^M
[Inferior 1 (process 1513) exited with code 01]^M
(gdb) FAIL: gdb.arch/aarch64-poe-sigsegv.exp: continue after fixing POE fault (the program exited)

> +	pass $gdb_test_name
> +    }
> +}
> diff --git a/gdb/testsuite/gdb.arch/aarch64-poe.exp b/gdb/testsuite/gdb.arch/aarch64-poe.exp
> new file mode 100644
> index 00000000000..ae2663a7dbc
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-poe.exp
> @@ -0,0 +1,44 @@
> +# Copyright (C) 2026 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# Test a binary that uses POE and exposed POR_EL0 register.
> +
> +global hex
> +global decimal
> +
> +require is_aarch64_target
> +
> +if {![allow_aarch64_poe_tests]} {
> +    unsupported "AArch64 POE not supported"
> +    return
> +}

Same here: is_aarch64_target is redundant, and the if block above should
just be "require allow_aarch64_poe_tests".

> +
> +standard_testfile
> +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
> +    return
> +}
> +
> +if {![runto_main]} {
> +    return
> +}
> +
> +# Validate the presence of the POE register.
> +    gdb_test "info registers por_el0" \
> +	     "por_el0\[ \t\]+$hex.*" \
> +	     "register por_el0 available"
> +
> +    gdb_test "p/x \$por_el0" \
> +	     "\\$\[0-9\]+ = ${hex}" \
> +	     "print por_el0"

The gdb_test statements above should start at the first column.

> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index d8619ded236..40a8124955a 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -5654,6 +5654,61 @@ gdb_caching_proc allow_aarch64_gcs_tests {} {
>      return $allow_gcs_tests
>  }
>  
> +# Run a test on the target to see if it supports AArch64 POE extensions.
> +# Return 1 if so, 0 if it does not.  Note this causes a restart of GDB.
> +
> +gdb_caching_proc allow_aarch64_poe_tests {} {
> +    global srcdir subdir gdb_prompt inferior_exited_re
> +
> +    set me "allow_aarch64_poe_tests"
> +
> +    if { ![is_aarch64_target]} {

Extraneous space after the { above.

> +	return 0
> +    }
> +
> +    # Compile a program that tests the POE feature.
> +    set src {
> +	#include <stdbool.h>
> +	#include <sys/auxv.h>
> +
> +	/* Feature check for POE feature.  */
> +	#ifndef HWCAP2_POE
> +	#define HWCAP2_POE (1ULL << 63)
> +	#endif
> +
> +	int main (void) {
> +	    bool poe_supported = getauxval (AT_HWCAP2) & HWCAP2_POE;
> +
> +	    /* Return success if POE is supported.  */
> +	    return !poe_supported;
> +	}
> +    }
> +
> +    if {![gdb_simple_compile $me $src executable]} {
> +	return 0
> +    }
> +
> +    # Compilation succeeded so now run it via gdb.
> +    set allow_poe_tests 0
> +    clean_restart
> +    gdb_load $obj
> +    gdb_run_cmd
> +    gdb_expect {
> +	-re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
> +	    verbose -log "\n$me: poe support detected"
> +	    set allow_poe_tests 1
> +	}
> +	-re ".*$inferior_exited_re with code 01.*${gdb_prompt} $" {
> +	    verbose -log "\n$me: poe support not detected"
> +	}
> +    }
> +    gdb_exit
> +    remote_file build delete $obj
> +
> +    verbose "$me:  returning $allow_poe_tests" 2

Extraneous space after the : above.

> +    return $allow_poe_tests
> +}
> +
>  # A helper that compiles a test case to see if __int128 is supported.
>  proc gdb_int128_helper {lang} {
>      return [gdb_can_simple_compile "i128-for-$lang" {

-- 
Thiago
(he/him)

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

* Re: [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
  2026-06-29 10:44     ` Srinath Parvathaneni
@ 2026-07-01  5:16       ` Thiago Jung Bauermann
  2026-07-01 14:45         ` Marc Zyngier
  0 siblings, 1 reply; 21+ messages in thread
From: Thiago Jung Bauermann @ 2026-07-01  5:16 UTC (permalink / raw)
  To: Srinath Parvathaneni
  Cc: gdb-patches, luis.machado.foss, guinevere, Ezra Sitorus,
	Matthieu Longo, Mark Rutland, maz

Hello Srinath,

Srinath Parvathaneni <Srinath.Parvathaneni@arm.com> writes:

>>> *  info registers por_el0
>>> *  p $por_el0
>>> *  p/x $por_el0
>>> *  set $por_el0 = <value>
>>
>>One question, more about general policy on the AArch64 GDB port:
>>
>>Should the register name have the _el0 suffix? It's more than half of
>>the register name (though tab completion helps).
>>
>>We don't currently have that suffix in the name of any register. And in
>>the case of Guarded Control Stack, I didn't add it. For native
>>debugging, it will always be the register at EL0. For remote debugging,
>>I assumed the target would send the register corresponding to the
>>current exception level in the inferior.
>>
>>Can there be a situation where it would be possible to see both the EL0
>>and EL1 (for example) registers at the same time? Or a situation where
>>the inferior is at EL1 but one wants to see the register at EL0, or
>>vice-versa?
>>
>
> Thanks Thiago for the review. I'll address the other review comments and
> post a new version of the patches.
>
> I'm happy to follow the existing AArch64 GDB convention and expose the register
> as `POR` for consistency.
>
> That said, after discussing this with kernel/KVM developers, there are valid
> debugging scenarios (e.g. KGDB or guest debugging via KVM/QEMU) where exposing
> `POR_EL0`, `POR_EL1`, and `POR_EL2` simultaneously would be useful.

Thanks for checking! Considering it's indeed useful then it's better to
use $por_el0 in this patch series as you have done.

> This seems like a broader GDB register naming issue rather than
> something specific to FEAT_S1POE.

I agree. This just seemed like a good moment to consider this question.

-- 
Thiago
(he/him)

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

* Re: [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
  2026-07-01  5:16       ` Thiago Jung Bauermann
@ 2026-07-01 14:45         ` Marc Zyngier
  0 siblings, 0 replies; 21+ messages in thread
From: Marc Zyngier @ 2026-07-01 14:45 UTC (permalink / raw)
  To: Thiago Jung Bauermann
  Cc: Srinath Parvathaneni, gdb-patches, luis.machado.foss, guinevere,
	Ezra Sitorus, Matthieu Longo, Mark Rutland

On Wed, 01 Jul 2026 06:16:21 +0100,
Thiago Jung Bauermann <thiago.bauermann@linaro.org> wrote:
> 
> Hello Srinath,
> 
> Srinath Parvathaneni <Srinath.Parvathaneni@arm.com> writes:
> 
> >>> *  info registers por_el0
> >>> *  p $por_el0
> >>> *  p/x $por_el0
> >>> *  set $por_el0 = <value>
> >>
> >>One question, more about general policy on the AArch64 GDB port:
> >>
> >>Should the register name have the _el0 suffix? It's more than half of
> >>the register name (though tab completion helps).
> >>
> >>We don't currently have that suffix in the name of any register. And in
> >>the case of Guarded Control Stack, I didn't add it. For native
> >>debugging, it will always be the register at EL0. For remote debugging,
> >>I assumed the target would send the register corresponding to the
> >>current exception level in the inferior.
> >>
> >>Can there be a situation where it would be possible to see both the EL0
> >>and EL1 (for example) registers at the same time? Or a situation where
> >>the inferior is at EL1 but one wants to see the register at EL0, or
> >>vice-versa?
> >>
> >
> > Thanks Thiago for the review. I'll address the other review comments and
> > post a new version of the patches.
> >
> > I'm happy to follow the existing AArch64 GDB convention and expose the register
> > as `POR` for consistency.
> >
> > That said, after discussing this with kernel/KVM developers, there are valid
> > debugging scenarios (e.g. KGDB or guest debugging via KVM/QEMU) where exposing
> > `POR_EL0`, `POR_EL1`, and `POR_EL2` simultaneously would be useful.
> 
> Thanks for checking! Considering it's indeed useful then it's better to
> use $por_el0 in this patch series as you have done.
> 
> > This seems like a broader GDB register naming issue rather than
> > something specific to FEAT_S1POE.
> 
> I agree. This just seemed like a good moment to consider this question.

It would certainly make our life easier if GDB was in general adopting
the architecture nomenclature.

It is probably fine to have a "shorthand" such as POR for POR_EL0, but
I'd like to make sure that it is possible to unambiguously target the
correct register for the cases where we have to debug a full guest
(which is something people actively do using the QEMU GDB stubs).

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

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

end of thread, other threads:[~2026-07-01 14:46 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-26 18:08 [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature srinath.parvathaneni
2026-06-26 18:08 ` [PATCH v2 1/7] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni
2026-06-27  6:06   ` Thiago Jung Bauermann
2026-06-29 10:44     ` Srinath Parvathaneni
2026-07-01  5:16       ` Thiago Jung Bauermann
2026-07-01 14:45         ` Marc Zyngier
2026-06-26 18:08 ` [PATCH v2 2/7] gdb/aarch64: Add custom printing for POR_EL0 srinath.parvathaneni
2026-06-27  7:03   ` Thiago Jung Bauermann
2026-06-29  7:02     ` Srinath Parvathaneni
2026-06-29 15:58       ` Ezra Sitorus
2026-06-26 18:08 ` [PATCH v2 3/7] gdb: Improve SIGSEGV diagnostics for POE faults srinath.parvathaneni
2026-06-29  2:42   ` Thiago Jung Bauermann
2026-06-26 18:08 ` [PATCH v2 4/7] gdbserver/aarch64: Add POR_EL0 register support srinath.parvathaneni
2026-06-29  2:43   ` Thiago Jung Bauermann
2026-06-26 18:08 ` [PATCH v2 5/7] bfd/readelf: Add core file support for FEAT_S1POE srinath.parvathaneni
2026-06-29  2:43   ` Thiago Jung Bauermann
2026-06-26 18:08 ` [PATCH v2 6/7] gdb/aarch64: " srinath.parvathaneni
2026-06-29  2:44   ` Thiago Jung Bauermann
2026-06-26 18:08 ` [PATCH v2 7/7] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni
2026-07-01  5:12   ` Thiago Jung Bauermann
2026-06-29 12:18 ` [PATCH v2 0/7] gdb/aarch64: Add support for FEAT_S1POE feature Guinevere Larsen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox