public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures.
@ 2022-04-27 15:14 John Baldwin
  2022-04-27 15:14 ` [PATCH v3 01/13] fbsd-nat: Add helper routines for register sets using PT_[G]SETREGSET John Baldwin
                   ` (12 more replies)
  0 siblings, 13 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

Changes since V2:

- Both arm and Aarch64 use a dynamically allocated register number
  whose value is stored in the arch-specific tdep structure as
  requested by Luis.

- I dropped the XXX comments about missing tests for NT_ARM_TLS on
  Linux on the assumption that it is ok to just assume they are
  always present given it was added to the kernel in 2012.

- I went ahead and pushed the binutils change to handle NT_ARM_TLS
  notes on FreeBSD as it was approved previously.

The NEWS blurb has been approved previously.

I have tested this on FreeBSD/armv7, FreeBSD/aarch64, and Linux Aarch64.

John Baldwin (13):
  fbsd-nat: Add helper routines for register sets using PT_[G]SETREGSET.
  Add an arm-tls feature which includes the tpidruro register from CP15.
  Read the tpidruro register from NT_ARM_TLS core dump notes on
    FreeBSD/arm.
  Support TLS variables on FreeBSD/arm.
  Fetch the NT_ARM_TLS register set for native FreeBSD/arm processes.
  Add an aarch64-tls feature which includes the tpidr register.
  Read the tpidr register from NT_ARM_TLS core dump notes on
    FreeBSD/Aarch64.
  Support TLS variables on FreeBSD/Aarch64.
  Fetch the NT_ARM_TLS register set for native FreeBSD/Aarch64
    processes.
  Read the tpidr register from NT_ARM_TLS core dump notes on Linux
    Aarch64.
  gdbserver: Read the tpidr register from NT_ARM_TLS on Linux.
  Read the tpidr register from NT_ARM_TLS on Linux.
  NEWS: Add a note for TLS support on FreeBSD/arm and FreeBSD/Aarch64.

 gdb/NEWS                         |  3 ++
 gdb/aarch64-fbsd-nat.c           | 54 +++++++++++++++++++++++
 gdb/aarch64-fbsd-tdep.c          | 67 ++++++++++++++++++++++++++++
 gdb/aarch64-fbsd-tdep.h          |  3 ++
 gdb/aarch64-linux-nat.c          | 69 ++++++++++++++++++++++++++++-
 gdb/aarch64-linux-tdep.c         | 21 ++++++++-
 gdb/aarch64-linux-tdep.h         |  3 ++
 gdb/aarch64-tdep.c               | 33 ++++++++++----
 gdb/aarch64-tdep.h               | 10 ++++-
 gdb/arch/aarch32.c               |  2 +
 gdb/arch/aarch64.c               |  7 ++-
 gdb/arch/aarch64.h               |  8 +++-
 gdb/arch/arm.c                   |  6 ++-
 gdb/arch/arm.h                   |  2 +-
 gdb/arm-fbsd-nat.c               | 52 +++++++++++++++++++++-
 gdb/arm-fbsd-tdep.c              | 65 ++++++++++++++++++++++++---
 gdb/arm-fbsd-tdep.h              |  5 ++-
 gdb/arm-linux-nat.c              |  6 +--
 gdb/arm-linux-tdep.c             |  4 +-
 gdb/arm-netbsd-nat.c             |  4 +-
 gdb/arm-tdep.c                   | 25 ++++++++---
 gdb/arm-tdep.h                   |  4 +-
 gdb/fbsd-nat.c                   | 75 ++++++++++++++++++++++++++++++++
 gdb/fbsd-nat.h                   | 38 ++++++++++++++++
 gdb/features/Makefile            |  2 +
 gdb/features/aarch64-tls.c       | 14 ++++++
 gdb/features/aarch64-tls.xml     | 11 +++++
 gdb/features/arm/arm-tls.c       | 14 ++++++
 gdb/features/arm/arm-tls.xml     | 11 +++++
 gdbserver/linux-aarch64-ipa.cc   |  8 ++--
 gdbserver/linux-aarch64-low.cc   | 32 +++++++++++++-
 gdbserver/linux-aarch64-tdesc.cc | 11 ++---
 gdbserver/linux-aarch64-tdesc.h  |  2 +-
 gdbserver/netbsd-aarch64-low.cc  |  2 +-
 34 files changed, 624 insertions(+), 49 deletions(-)
 create mode 100644 gdb/features/aarch64-tls.c
 create mode 100644 gdb/features/aarch64-tls.xml
 create mode 100644 gdb/features/arm/arm-tls.c
 create mode 100644 gdb/features/arm/arm-tls.xml

-- 
2.34.1


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

* [PATCH v3 01/13] fbsd-nat: Add helper routines for register sets using PT_[G]SETREGSET.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 02/13] Add an arm-tls feature which includes the tpidruro register from CP15 John Baldwin
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

FreeBSD's kernel has recently added PT_GETREGSET and PT_SETREGSET
operations to fetch a register set named by an ELF note type.  These
helper routines provide helpers to check for a register set's
existence, fetch registers for a register set, and store registers to
a register set.
---
 gdb/fbsd-nat.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/fbsd-nat.h | 38 +++++++++++++++++++++++++
 2 files changed, 113 insertions(+)

diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c
index 8e5107c26f8..a501d9212c0 100644
--- a/gdb/fbsd-nat.c
+++ b/gdb/fbsd-nat.c
@@ -49,6 +49,11 @@
 
 #include <list>
 
+#ifndef PT_GETREGSET
+#define	PT_GETREGSET	42	/* Get a target register set */
+#define	PT_SETREGSET	43	/* Set a target register set */
+#endif
+
 /* Return the name of a file that can be opened to get the symbols for
    the child process identified by PID.  */
 
@@ -1774,6 +1779,76 @@ fbsd_nat_target::store_register_set (struct regcache *regcache, int regnum,
 
 /* See fbsd-nat.h.  */
 
+bool
+fbsd_nat_target::have_regset (ptid_t ptid, int note)
+{
+  pid_t pid = get_ptrace_pid (ptid);
+  struct iovec iov;
+
+  iov.iov_base = nullptr;
+  iov.iov_len = 0;
+  if (ptrace (PT_GETREGSET, pid, (PTRACE_TYPE_ARG3) &iov, note) == -1)
+    return 0;
+  return iov.iov_len;
+}
+
+/* See fbsd-nat.h.  */
+
+bool
+fbsd_nat_target::fetch_regset (struct regcache *regcache, int regnum, int note,
+			       const struct regset *regset, void *regs,
+			       size_t size)
+{
+  const struct regcache_map_entry *map
+    = (const struct regcache_map_entry *) regset->regmap;
+  pid_t pid = get_ptrace_pid (regcache->ptid ());
+
+  if (regnum == -1 || regcache_map_supplies (map, regnum, regcache->arch(),
+					     size))
+    {
+      struct iovec iov;
+
+      iov.iov_base = regs;
+      iov.iov_len = size;
+      if (ptrace (PT_GETREGSET, pid, (PTRACE_TYPE_ARG3) &iov, note) == -1)
+	perror_with_name (_("Couldn't get registers"));
+
+      regcache->supply_regset (regset, regnum, regs, size);
+      return true;
+    }
+  return false;
+}
+
+bool
+fbsd_nat_target::store_regset (struct regcache *regcache, int regnum, int note,
+			       const struct regset *regset, void *regs,
+			       size_t size)
+{
+  const struct regcache_map_entry *map
+    = (const struct regcache_map_entry *) regset->regmap;
+  pid_t pid = get_ptrace_pid (regcache->ptid ());
+
+  if (regnum == -1 || regcache_map_supplies (map, regnum, regcache->arch(),
+					     size))
+    {
+      struct iovec iov;
+
+      iov.iov_base = regs;
+      iov.iov_len = size;
+      if (ptrace (PT_GETREGSET, pid, (PTRACE_TYPE_ARG3) &iov, note) == -1)
+	perror_with_name (_("Couldn't get registers"));
+
+      regcache->collect_regset (regset, regnum, regs, size);
+
+      if (ptrace (PT_SETREGSET, pid, (PTRACE_TYPE_ARG3) &iov, note) == -1)
+	perror_with_name (_("Couldn't write registers"));
+      return true;
+    }
+  return false;
+}
+
+/* See fbsd-nat.h.  */
+
 bool
 fbsd_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo)
 {
diff --git a/gdb/fbsd-nat.h b/gdb/fbsd-nat.h
index 82f7ee47949..ba359c62314 100644
--- a/gdb/fbsd-nat.h
+++ b/gdb/fbsd-nat.h
@@ -151,6 +151,17 @@ class fbsd_nat_target : public inf_ptrace_target
   bool store_register_set (struct regcache *regcache, int regnum, int fetch_op,
 			   int store_op, const struct regset *regset,
 			   void *regs, size_t size);
+
+  /* Helper routines which use PT_GETREGSET and PT_SETREGSET for the
+     specified NOTE instead of regset-specific fetch and store
+     ops.  */
+
+  bool fetch_regset (struct regcache *regcache, int regnum, int note,
+		     const struct regset *regset, void *regs, size_t size);
+
+  bool store_regset (struct regcache *regcache, int regnum, int note,
+		     const struct regset *regset, void *regs, size_t size);
+
 protected:
   /* Wrapper versions of the above helpers which accept a register set
      type such as 'struct reg' or 'struct fpreg'.  */
@@ -172,6 +183,33 @@ class fbsd_nat_target : public inf_ptrace_target
     return store_register_set (regcache, regnum, fetch_op, store_op, regset,
 			       &regs, sizeof (regs));
   }
+
+  /* Helper routine for use in read_description in subclasses.  This
+     routine checks if the register set for the specified NOTE is
+     present for a given PTID.  If the register set is present, the
+     the size of the register set is returned.  If the register set is
+     not present, zero is returned.  */
+
+  bool have_regset (ptid_t ptid, int note);
+
+  /* Wrapper versions of the PT_GETREGSET and PT_REGSET helpers which
+     accept a register set type.  */
+
+  template <class Regset>
+  bool fetch_regset (struct regcache *regcache, int regnum, int note,
+		     const struct regset *regset)
+  {
+    Regset regs;
+    return fetch_regset (regcache, regnum, note, regset, &regs, sizeof (regs));
+  }
+
+  template <class Regset>
+  bool store_regset (struct regcache *regcache, int regnum, int note,
+		     const struct regset *regset)
+  {
+    Regset regs;
+    return store_regset (regcache, regnum, note, regset, &regs, sizeof (regs));
+  }
 };
 
 /* Fetch the signal information for PTID and store it in *SIGINFO.
-- 
2.34.1


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

* [PATCH v3 02/13] Add an arm-tls feature which includes the tpidruro register from CP15.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
  2022-04-27 15:14 ` [PATCH v3 01/13] fbsd-nat: Add helper routines for register sets using PT_[G]SETREGSET John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 03/13] Read the tpidruro register from NT_ARM_TLS core dump notes on FreeBSD/arm John Baldwin
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

---
 gdb/arch/aarch32.c           |  2 ++
 gdb/arch/arm.c               |  6 +++++-
 gdb/arch/arm.h               |  2 +-
 gdb/arm-fbsd-tdep.c          |  4 ++--
 gdb/arm-linux-nat.c          |  6 +++---
 gdb/arm-linux-tdep.c         |  4 ++--
 gdb/arm-netbsd-nat.c         |  4 ++--
 gdb/arm-tdep.c               | 25 ++++++++++++++++++++-----
 gdb/arm-tdep.h               |  4 +++-
 gdb/features/Makefile        |  1 +
 gdb/features/arm/arm-tls.c   | 14 ++++++++++++++
 gdb/features/arm/arm-tls.xml | 11 +++++++++++
 12 files changed, 66 insertions(+), 17 deletions(-)
 create mode 100644 gdb/features/arm/arm-tls.c
 create mode 100644 gdb/features/arm/arm-tls.xml

diff --git a/gdb/arch/aarch32.c b/gdb/arch/aarch32.c
index 0c544d381f1..4d6ffb44a15 100644
--- a/gdb/arch/aarch32.c
+++ b/gdb/arch/aarch32.c
@@ -19,6 +19,7 @@
 #include "aarch32.h"
 
 #include "../features/arm/arm-core.c"
+#include "../features/arm/arm-tls.c"
 #include "../features/arm/arm-vfpv3.c"
 
 /* See aarch32.h.  */
@@ -38,6 +39,7 @@ aarch32_create_target_description ()
   /* Create a vfpv3 feature, then a blank NEON feature.  */
   regnum = create_feature_arm_arm_vfpv3 (tdesc.get (), regnum);
   tdesc_create_feature (tdesc.get (), "org.gnu.gdb.arm.neon");
+  regnum = create_feature_arm_arm_tls (tdesc.get (), regnum);
 
   return tdesc.release ();
 }
diff --git a/gdb/arch/arm.c b/gdb/arch/arm.c
index bc6e5ce3f09..14f0a7a7f6c 100644
--- a/gdb/arch/arm.c
+++ b/gdb/arch/arm.c
@@ -22,6 +22,7 @@
 #include "arm.h"
 
 #include "../features/arm/arm-core.c"
+#include "../features/arm/arm-tls.c"
 #include "../features/arm/arm-vfpv2.c"
 #include "../features/arm/arm-vfpv3.c"
 #include "../features/arm/xscale-iwmmxt.c"
@@ -374,7 +375,7 @@ shifted_reg_val (struct regcache *regcache, unsigned long inst,
 /* See arch/arm.h.  */
 
 target_desc *
-arm_create_target_description (arm_fp_type fp_type)
+arm_create_target_description (arm_fp_type fp_type, bool tls)
 {
   target_desc_up tdesc = allocate_target_description ();
 
@@ -410,6 +411,9 @@ arm_create_target_description (arm_fp_type fp_type)
       error (_("Invalid Arm FP type: %d"), fp_type);
     }
 
+  if (tls)
+    regnum = create_feature_arm_arm_tls (tdesc.get (), regnum);
+
   return tdesc.release ();
 }
 
diff --git a/gdb/arch/arm.h b/gdb/arch/arm.h
index 0728bea1501..4ad329f6f1f 100644
--- a/gdb/arch/arm.h
+++ b/gdb/arch/arm.h
@@ -207,7 +207,7 @@ unsigned long shifted_reg_val (struct regcache *regcache,
 
 /* Create an Arm target description with the given FP hardware type.  */
 
-target_desc *arm_create_target_description (arm_fp_type fp_type);
+target_desc *arm_create_target_description (arm_fp_type fp_type, bool tls);
 
 /* Create an Arm M-profile target description with the given hardware type.  */
 
diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
index bf337b13f98..06745a36186 100644
--- a/gdb/arm-fbsd-tdep.c
+++ b/gdb/arm-fbsd-tdep.c
@@ -188,9 +188,9 @@ arm_fbsd_read_description_auxv (struct target_ops *target)
 	return aarch32_read_description ();
       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32))
 	       == (HWCAP_VFPv3 | HWCAP_VFPD32))
-	return arm_read_description (ARM_FP_TYPE_VFPV3);
+	return arm_read_description (ARM_FP_TYPE_VFPV3, false);
       else
-	return arm_read_description (ARM_FP_TYPE_VFPV2);
+	return arm_read_description (ARM_FP_TYPE_VFPV2, false);
     }
 
   return nullptr;
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
index f0f09acf2f9..2abaf5a675d 100644
--- a/gdb/arm-linux-nat.c
+++ b/gdb/arm-linux-nat.c
@@ -550,7 +550,7 @@ arm_linux_nat_target::read_description ()
     }
 
   if (arm_hwcap & HWCAP_IWMMXT)
-    return arm_read_description (ARM_FP_TYPE_IWMMXT);
+    return arm_read_description (ARM_FP_TYPE_IWMMXT, false);
 
   if (arm_hwcap & HWCAP_VFP)
     {
@@ -567,9 +567,9 @@ arm_linux_nat_target::read_description ()
       if (arm_hwcap & HWCAP_NEON)
 	return aarch32_read_description ();
       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
-	return arm_read_description (ARM_FP_TYPE_VFPV3);
+	return arm_read_description (ARM_FP_TYPE_VFPV3, false);
 
-      return arm_read_description (ARM_FP_TYPE_VFPV2);
+      return arm_read_description (ARM_FP_TYPE_VFPV2, false);
     }
 
   return this->beneath ()->read_description ();
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index c8e882ab096..f299e9665d5 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -741,9 +741,9 @@ arm_linux_core_read_description (struct gdbarch *gdbarch,
       if (arm_hwcap & HWCAP_NEON)
 	return aarch32_read_description ();
       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
-	return arm_read_description (ARM_FP_TYPE_VFPV3);
+	return arm_read_description (ARM_FP_TYPE_VFPV3, false);
 
-      return arm_read_description (ARM_FP_TYPE_VFPV2);
+      return arm_read_description (ARM_FP_TYPE_VFPV2, false);
     }
 
   return nullptr;
diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c
index 591a0ab1d54..764bbe8cd3d 100644
--- a/gdb/arm-netbsd-nat.c
+++ b/gdb/arm-netbsd-nat.c
@@ -346,13 +346,13 @@ arm_netbsd_nat_target::read_description ()
 
   if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0
       || !flag)
-    return arm_read_description (ARM_FP_TYPE_NONE);
+    return arm_read_description (ARM_FP_TYPE_NONE, false);
 
   len = sizeof(flag);
   if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
     return aarch32_read_description ();
 
-  return arm_read_description (ARM_FP_TYPE_VFPV3);
+  return arm_read_description (ARM_FP_TYPE_VFPV3, false);
 }
 
 void _initialize_arm_netbsd_nat ();
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 7274752c2b9..cb7589af83a 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -240,7 +240,7 @@ static const char **valid_disassembly_styles;
 static const char *disassembly_style;
 
 /* All possible arm target descriptors.  */
-static struct target_desc *tdesc_arm_list[ARM_FP_TYPE_INVALID];
+static struct target_desc *tdesc_arm_list[ARM_FP_TYPE_INVALID][2];
 static struct target_desc *tdesc_arm_mprofile_list[ARM_M_TYPE_INVALID];
 
 /* This is used to keep the bfd arch_info in sync with the disassembly
@@ -9606,6 +9606,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int m_profile_psp_ns_regnum = -1;
   int m_profile_msp_s_regnum = -1;
   int m_profile_psp_s_regnum = -1;
+  int tls_regnum = 0;
 
   /* If we have an object to base this architecture on, try to determine
      its ABI.  */
@@ -9973,6 +9974,19 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	    }
 	}
 
+      /* Check for the TLS register feature.  */
+      feature = tdesc_find_feature (tdesc, "org.gnu.gdb.arm.tls");
+      if (feature != nullptr)
+	{
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+					      register_count, "tpidruro");
+	  if (!valid_p)
+	    return nullptr;
+
+	  tls_regnum = register_count;
+	  register_count++;
+	}
+
       /* Check for MVE after all the checks for GPR's, VFP and Neon.
 	 MVE (Helium) is an M-profile extension.  */
       if (is_m)
@@ -10128,6 +10142,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->have_s_pseudos = have_s_pseudos;
   tdep->have_q_pseudos = have_q_pseudos;
   tdep->have_neon = have_neon;
+  tdep->tls_regnum = tls_regnum;
 
   /* Adjust the MVE feature settings.  */
   if (have_mve)
@@ -14416,14 +14431,14 @@ arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
 /* See arm-tdep.h.  */
 
 const target_desc *
-arm_read_description (arm_fp_type fp_type)
+arm_read_description (arm_fp_type fp_type, bool tls)
 {
-  struct target_desc *tdesc = tdesc_arm_list[fp_type];
+  struct target_desc *tdesc = tdesc_arm_list[fp_type][tls];
 
   if (tdesc == nullptr)
     {
-      tdesc = arm_create_target_description (fp_type);
-      tdesc_arm_list[fp_type] = tdesc;
+      tdesc = arm_create_target_description (fp_type, tls);
+      tdesc_arm_list[fp_type][tls] = tdesc;
     }
 
   return tdesc;
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index 864406e98d2..0fc4774a20c 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -134,6 +134,8 @@ struct arm_gdbarch_tdep : gdbarch_tdep
   int m_profile_msp_s_regnum = ARM_SP_REGNUM;	/* M-profile MSP_S register number.  */
   int m_profile_psp_s_regnum = ARM_SP_REGNUM;	/* M-profile PSP_S register number.  */
 
+  int tls_regnum = 0;		/* Number of the tpidruro register.  */
+
   bool is_m = false;		/* Does the target follow the "M" profile.  */
   bool have_sec_ext = false;	/* Do we have security extensions?  */
   CORE_ADDR lowest_pc = 0;	/* Lowest address at which instructions
@@ -317,7 +319,7 @@ extern void
 				       const struct regcache *regcache);
 
 /* Get the correct Arm target description with given FP hardware type.  */
-const target_desc *arm_read_description (arm_fp_type fp_type);
+const target_desc *arm_read_description (arm_fp_type fp_type, bool tls);
 
 /* Get the correct Arm M-Profile target description with given hardware
    type.  */
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 737d9cbd3db..5f1826baa6f 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -208,6 +208,7 @@ FEATURE_XMLFILES = aarch64-core.xml \
 	arm/arm-m-profile-mve.xml \
 	arm/arm-m-system.xml \
 	arm/arm-m-profile-with-fpa.xml \
+	arm/arm-tls.xml \
 	arm/arm-vfpv2.xml \
 	arm/arm-vfpv3.xml \
 	arm/xscale-iwmmxt.xml \
diff --git a/gdb/features/arm/arm-tls.c b/gdb/features/arm/arm-tls.c
new file mode 100644
index 00000000000..d1214dda8ec
--- /dev/null
+++ b/gdb/features/arm/arm-tls.c
@@ -0,0 +1,14 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: arm-tls.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arm_arm_tls (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.tls");
+  tdesc_create_reg (feature, "tpidruro", regnum++, 1, NULL, 32, "data_ptr");
+  return regnum;
+}
diff --git a/gdb/features/arm/arm-tls.xml b/gdb/features/arm/arm-tls.xml
new file mode 100644
index 00000000000..3cdf73e776f
--- /dev/null
+++ b/gdb/features/arm/arm-tls.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2022 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.arm.tls">
+  <reg name="tpidruro" bitsize="32" type="data_ptr"/>
+</feature>
-- 
2.34.1


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

* [PATCH v3 03/13] Read the tpidruro register from NT_ARM_TLS core dump notes on FreeBSD/arm.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
  2022-04-27 15:14 ` [PATCH v3 01/13] fbsd-nat: Add helper routines for register sets using PT_[G]SETREGSET John Baldwin
  2022-04-27 15:14 ` [PATCH v3 02/13] Add an arm-tls feature which includes the tpidruro register from CP15 John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 04/13] Support TLS variables " John Baldwin
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

---
 gdb/arm-fbsd-nat.c  |  2 +-
 gdb/arm-fbsd-tdep.c | 32 ++++++++++++++++++++++++++------
 gdb/arm-fbsd-tdep.h |  5 ++++-
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/gdb/arm-fbsd-nat.c b/gdb/arm-fbsd-nat.c
index 3106d73cc3a..c32924de735 100644
--- a/gdb/arm-fbsd-nat.c
+++ b/gdb/arm-fbsd-nat.c
@@ -72,7 +72,7 @@ arm_fbsd_nat_target::read_description ()
 {
   const struct target_desc *desc;
 
-  desc = arm_fbsd_read_description_auxv (this);
+  desc = arm_fbsd_read_description_auxv (this, false);
   if (desc == NULL)
     desc = this->beneath ()->read_description ();
   return desc;
diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
index 06745a36186..a27dfb2fb4a 100644
--- a/gdb/arm-fbsd-tdep.c
+++ b/gdb/arm-fbsd-tdep.c
@@ -163,6 +163,24 @@ arm_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
   cb (".reg", ARM_FBSD_SIZEOF_GREGSET, ARM_FBSD_SIZEOF_GREGSET,
       &arm_fbsd_gregset, NULL, cb_data);
 
+  if (tdep->tls_regnum > 0)
+    {
+      const struct regcache_map_entry arm_fbsd_tlsregmap[] =
+	{
+	  { 1, tdep->tls_regnum, 4 },
+	  { 0 }
+	};
+
+      const struct regset arm_fbsd_tlsregset =
+	{
+	  arm_fbsd_tlsregmap,
+	  regcache_supply_regset, regcache_collect_regset
+	};
+
+      cb (".reg-aarch-tls", ARM_FBSD_SIZEOF_TLSREGSET, ARM_FBSD_SIZEOF_TLSREGSET,
+	  &arm_fbsd_tlsregset, NULL, cb_data);
+    }
+
   /* While FreeBSD/arm cores do contain a NT_FPREGSET / ".reg2"
      register set, it is not populated with register values by the
      kernel but just contains all zeroes.  */
@@ -175,12 +193,12 @@ arm_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
    vector.  */
 
 const struct target_desc *
-arm_fbsd_read_description_auxv (struct target_ops *target)
+arm_fbsd_read_description_auxv (struct target_ops *target, bool tls)
 {
   CORE_ADDR arm_hwcap = 0;
 
   if (target_auxv_search (target, AT_FREEBSD_HWCAP, &arm_hwcap) != 1)
-    return nullptr;
+    return arm_read_description (ARM_FP_TYPE_NONE, tls);
 
   if (arm_hwcap & HWCAP_VFP)
     {
@@ -188,12 +206,12 @@ arm_fbsd_read_description_auxv (struct target_ops *target)
 	return aarch32_read_description ();
       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32))
 	       == (HWCAP_VFPv3 | HWCAP_VFPD32))
-	return arm_read_description (ARM_FP_TYPE_VFPV3, false);
+	return arm_read_description (ARM_FP_TYPE_VFPV3, tls);
       else
-	return arm_read_description (ARM_FP_TYPE_VFPV2, false);
+	return arm_read_description (ARM_FP_TYPE_VFPV2, tls);
     }
 
-  return nullptr;
+  return arm_read_description (ARM_FP_TYPE_NONE, tls);
 }
 
 /* Implement the "core_read_description" gdbarch method.  */
@@ -203,7 +221,9 @@ arm_fbsd_core_read_description (struct gdbarch *gdbarch,
 				struct target_ops *target,
 				bfd *abfd)
 {
-  return arm_fbsd_read_description_auxv (target);
+  asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls");
+
+  return arm_fbsd_read_description_auxv (target, tls != nullptr);
 }
 
 /* Implement the 'init_osabi' method of struct gdb_osabi_handler.  */
diff --git a/gdb/arm-fbsd-tdep.h b/gdb/arm-fbsd-tdep.h
index 633dafad75d..193eb76df3c 100644
--- a/gdb/arm-fbsd-tdep.h
+++ b/gdb/arm-fbsd-tdep.h
@@ -26,6 +26,9 @@
    PC, and CPSR registers.  */
 #define ARM_FBSD_SIZEOF_GREGSET  (17 * 4)
 
+/* The TLS regset consists of a single register.  */
+#define	ARM_FBSD_SIZEOF_TLSREGSET	(4)
+
 /* The VFP regset consists of 32 D registers plus FPSCR, and the whole
    structure is padded to 64-bit alignment.  */
 #define	ARM_FBSD_SIZEOF_VFPREGSET	(33 * 8)
@@ -40,6 +43,6 @@ extern const struct regset arm_fbsd_vfpregset;
 #define	HWCAP_VFPD32		0x00080000
 
 extern const struct target_desc *
-arm_fbsd_read_description_auxv (struct target_ops *target);
+arm_fbsd_read_description_auxv (struct target_ops *target, bool tls);
 
 #endif /* ARM_FBSD_TDEP_H */
-- 
2.34.1


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

* [PATCH v3 04/13] Support TLS variables on FreeBSD/arm.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (2 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 03/13] Read the tpidruro register from NT_ARM_TLS core dump notes on FreeBSD/arm John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 05/13] Fetch the NT_ARM_TLS register set for native FreeBSD/arm processes John Baldwin
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

Derive the pointer to the DTV array from the tpidruro register.
---
 gdb/arm-fbsd-tdep.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
index a27dfb2fb4a..483820c1092 100644
--- a/gdb/arm-fbsd-tdep.c
+++ b/gdb/arm-fbsd-tdep.c
@@ -27,6 +27,7 @@
 #include "auxv.h"
 #include "fbsd-tdep.h"
 #include "gdbcore.h"
+#include "inferior.h"
 #include "osabi.h"
 #include "solib-svr4.h"
 #include "trad-frame.h"
@@ -226,6 +227,30 @@ arm_fbsd_core_read_description (struct gdbarch *gdbarch,
   return arm_fbsd_read_description_auxv (target, tls != nullptr);
 }
 
+/* Implement the get_thread_local_address gdbarch method.  */
+
+static CORE_ADDR
+arm_fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
+				   CORE_ADDR lm_addr, CORE_ADDR offset)
+{
+  arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  struct regcache *regcache;
+
+  regcache = get_thread_arch_regcache (current_inferior ()->process_target (),
+				       ptid, gdbarch);
+
+  target_fetch_registers (regcache, tdep->tls_regnum);
+
+  ULONGEST tpidruro;
+  if (regcache->cooked_read (tdep->tls_regnum, &tpidruro) != REG_VALID)
+    error (_("Unable to fetch %%tpidruro"));
+
+  /* %tpidruro points to the TCB whose first member is the dtv
+      pointer.  */
+  CORE_ADDR dtv_addr = tpidruro;
+  return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset);
+}
+
 /* Implement the 'init_osabi' method of struct gdb_osabi_handler.  */
 
 static void
@@ -251,6 +276,14 @@ arm_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
     (gdbarch, arm_fbsd_iterate_over_regset_sections);
   set_gdbarch_core_read_description (gdbarch, arm_fbsd_core_read_description);
 
+  if (tdep->tls_regnum > 0)
+    {
+      set_gdbarch_fetch_tls_load_module_address (gdbarch,
+						 svr4_fetch_objfile_link_map);
+      set_gdbarch_get_thread_local_address (gdbarch,
+					    arm_fbsd_get_thread_local_address);
+    }
+
   /* Single stepping.  */
   set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
 }
-- 
2.34.1


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

* [PATCH v3 05/13] Fetch the NT_ARM_TLS register set for native FreeBSD/arm processes.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (3 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 04/13] Support TLS variables " John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 06/13] Add an aarch64-tls feature which includes the tpidr register John Baldwin
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

This permits resolving TLS variables.
---
 gdb/arm-fbsd-nat.c | 52 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/gdb/arm-fbsd-nat.c b/gdb/arm-fbsd-nat.c
index c32924de735..a306e1e2ee0 100644
--- a/gdb/arm-fbsd-nat.c
+++ b/gdb/arm-fbsd-nat.c
@@ -18,13 +18,17 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "inferior.h"
 #include "target.h"
 
+#include "elf/common.h"
+
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <machine/reg.h>
 
 #include "fbsd-nat.h"
+#include "arm-tdep.h"
 #include "arm-fbsd-tdep.h"
 #include "inf-ptrace.h"
 
@@ -49,6 +53,27 @@ arm_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
   fetch_register_set<struct vfpreg> (regcache, regnum, PT_GETVFPREGS,
 				     &arm_fbsd_vfpregset);
 #endif
+#ifdef PT_GETREGSET
+  gdbarch *gdbarch = regcache->arch ();
+  arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+  if (tdep->tls_regnum > 0)
+    {
+      const struct regcache_map_entry arm_fbsd_tlsregmap[] =
+	{
+	  { 1, tdep->tls_regnum, 4 },
+	  { 0 }
+	};
+
+      const struct regset arm_fbsd_tlsregset =
+	{
+	  arm_fbsd_tlsregmap,
+	  regcache_supply_regset, regcache_collect_regset
+	};
+
+      fetch_regset<uint32_t> (regcache, regnum, NT_ARM_TLS, &arm_fbsd_tlsregset);
+    }
+#endif
 }
 
 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
@@ -63,6 +88,27 @@ arm_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
   store_register_set<struct vfpreg> (regcache, regnum, PT_GETVFPREGS,
 				     PT_SETVFPREGS, &arm_fbsd_vfpregset);
 #endif
+#ifdef PT_GETREGSET
+  gdbarch *gdbarch = regcache->arch ();
+  arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+  if (tdep->tls_regnum > 0)
+    {
+      const struct regcache_map_entry arm_fbsd_tlsregmap[] =
+	{
+	  { 1, tdep->tls_regnum, 4 },
+	  { 0 }
+	};
+
+      const struct regset arm_fbsd_tlsregset =
+	{
+	  arm_fbsd_tlsregmap,
+	  regcache_supply_regset, regcache_collect_regset
+	};
+
+      store_regset<uint32_t> (regcache, regnum, NT_ARM_TLS, &arm_fbsd_tlsregset);
+    }
+#endif
 }
 
 /* Implement the to_read_description method.  */
@@ -71,8 +117,12 @@ const struct target_desc *
 arm_fbsd_nat_target::read_description ()
 {
   const struct target_desc *desc;
+  bool tls = false;
 
-  desc = arm_fbsd_read_description_auxv (this, false);
+#ifdef PT_GETREGSET
+  tls = have_regset (inferior_ptid, NT_ARM_TLS) != 0;
+#endif
+  desc = arm_fbsd_read_description_auxv (this, tls);
   if (desc == NULL)
     desc = this->beneath ()->read_description ();
   return desc;
-- 
2.34.1


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

* [PATCH v3 06/13] Add an aarch64-tls feature which includes the tpidr register.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (4 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 05/13] Fetch the NT_ARM_TLS register set for native FreeBSD/arm processes John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 07/13] Read the tpidr register from NT_ARM_TLS core dump notes on FreeBSD/Aarch64 John Baldwin
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

---
 gdb/aarch64-linux-nat.c          |  3 ++-
 gdb/aarch64-linux-tdep.c         |  2 +-
 gdb/aarch64-tdep.c               | 33 ++++++++++++++++++++++++--------
 gdb/aarch64-tdep.h               | 10 +++++++++-
 gdb/arch/aarch64.c               |  7 ++++++-
 gdb/arch/aarch64.h               |  8 ++++++--
 gdb/features/Makefile            |  1 +
 gdb/features/aarch64-tls.c       | 14 ++++++++++++++
 gdb/features/aarch64-tls.xml     | 11 +++++++++++
 gdbserver/linux-aarch64-tdesc.cc |  2 +-
 gdbserver/netbsd-aarch64-low.cc  |  2 +-
 11 files changed, 77 insertions(+), 16 deletions(-)
 create mode 100644 gdb/features/aarch64-tls.c
 create mode 100644 gdb/features/aarch64-tls.xml

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 7bb82d17cc8..4da274c285a 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -646,7 +646,8 @@ aarch64_linux_nat_target::read_description ()
   bool pauth_p = hwcap & AARCH64_HWCAP_PACA;
   bool mte_p = hwcap2 & HWCAP2_MTE;
 
-  return aarch64_read_description (aarch64_sve_get_vq (tid), pauth_p, mte_p);
+  return aarch64_read_description (aarch64_sve_get_vq (tid), pauth_p, mte_p,
+				   false);
 }
 
 /* Convert a native/host siginfo object, into/from the siginfo in the
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 55094b3d88b..8cfb64d9f4a 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -763,7 +763,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
   bool pauth_p = hwcap & AARCH64_HWCAP_PACA;
   bool mte_p = hwcap2 & HWCAP2_MTE;
   return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd),
-				   pauth_p, mte_p);
+				   pauth_p, mte_p, false);
 }
 
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 98eaeaf8ca4..9d06ebfe27c 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -58,7 +58,7 @@
 #define HA_MAX_NUM_FLDS		4
 
 /* All possible aarch64 target descriptors.  */
-static target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/][2 /* mte */];
+static target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/][2 /* mte */][2 /* tls */];
 
 /* The standard register names, and all the valid aliases for them.  */
 static const struct
@@ -3327,21 +3327,23 @@ aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
    If VQ is zero then it is assumed SVE is not supported.
    (It is not possible to set VQ to zero on an SVE system).
 
-   MTE_P indicates the presence of the Memory Tagging Extension feature. */
+   MTE_P indicates the presence of the Memory Tagging Extension feature.
+
+   TLS_P indicates the presence of the Thread Local Storage feature.  */
 
 const target_desc *
-aarch64_read_description (uint64_t vq, bool pauth_p, bool mte_p)
+aarch64_read_description (uint64_t vq, bool pauth_p, bool mte_p, bool tls_p)
 {
   if (vq > AARCH64_MAX_SVE_VQ)
     error (_("VQ is %" PRIu64 ", maximum supported value is %d"), vq,
 	   AARCH64_MAX_SVE_VQ);
 
-  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p][mte_p];
+  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p][mte_p][tls_p];
 
   if (tdesc == NULL)
     {
-      tdesc = aarch64_create_target_description (vq, pauth_p, mte_p);
-      tdesc_aarch64_list[vq][pauth_p][mte_p] = tdesc;
+      tdesc = aarch64_create_target_description (vq, pauth_p, mte_p, tls_p);
+      tdesc_aarch64_list[vq][pauth_p][mte_p][tls_p] = tdesc;
     }
 
   return tdesc;
@@ -3416,7 +3418,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   bool valid_p = true;
   int i, num_regs = 0, num_pseudo_regs = 0;
   int first_pauth_regnum = -1, pauth_ra_state_offset = -1;
-  int first_mte_regnum = -1;
+  int first_mte_regnum = -1, tls_regnum = -1;
 
   /* Use the vector length passed via the target info.  Here -1 is used for no
      SVE, and 0 is unset.  If unset then use the vector length from the existing
@@ -3448,7 +3450,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      value.  */
   const struct target_desc *tdesc = info.target_desc;
   if (!tdesc_has_registers (tdesc) || vq != aarch64_get_tdesc_vq (tdesc))
-    tdesc = aarch64_read_description (vq, false, false);
+    tdesc = aarch64_read_description (vq, false, false, false);
   gdb_assert (tdesc);
 
   feature_core = tdesc_find_feature (tdesc,"org.gnu.gdb.aarch64.core");
@@ -3457,6 +3459,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   feature_pauth = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.pauth");
   const struct tdesc_feature *feature_mte
     = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.mte");
+  const struct tdesc_feature *feature_tls
+    = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.tls");
 
   if (feature_core == nullptr)
     return nullptr;
@@ -3511,6 +3515,18 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       num_pseudo_regs += 32;	/* add the Bn scalar register pseudos */
     }
 
+  /* Add the TLS register.  */
+  if (feature_tls != nullptr)
+    {
+      tls_regnum = num_regs;
+      /* Validate the descriptor provides the mandatory TLS register
+	 and allocate its number.  */
+      valid_p = tdesc_numbered_register (feature_tls, tdesc_data.get (),
+					 tls_regnum, "tpidr");
+
+      num_regs++;
+    }
+
   /* Add the pauth registers.  */
   if (feature_pauth != NULL)
     {
@@ -3559,6 +3575,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->pauth_ra_state_regnum = (feature_pauth == NULL) ? -1
 				: pauth_ra_state_offset + num_regs;
   tdep->mte_reg_base = first_mte_regnum;
+  tdep->tls_regnum = tls_regnum;
 
   set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
   set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index 60a9d5a29c2..e4cdebb6311 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -111,10 +111,18 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep
   {
     return mte_reg_base != -1;
   }
+
+  /* TLS register.  This is -1 if the TLS register is not available.  */
+  int tls_regnum = 0;
+
+  bool has_tls() const
+  {
+    return tls_regnum != -1;
+  }
 };
 
 const target_desc *aarch64_read_description (uint64_t vq, bool pauth_p,
-					     bool mte_p);
+					     bool mte_p, bool tls_p);
 
 extern int aarch64_process_record (struct gdbarch *gdbarch,
 			       struct regcache *regcache, CORE_ADDR addr);
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index 485d667ccde..733a3fd6d2a 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -24,11 +24,13 @@
 #include "../features/aarch64-sve.c"
 #include "../features/aarch64-pauth.c"
 #include "../features/aarch64-mte.c"
+#include "../features/aarch64-tls.c"
 
 /* See arch/aarch64.h.  */
 
 target_desc *
-aarch64_create_target_description (uint64_t vq, bool pauth_p, bool mte_p)
+aarch64_create_target_description (uint64_t vq, bool pauth_p, bool mte_p,
+				   bool tls_p)
 {
   target_desc_up tdesc = allocate_target_description ();
 
@@ -52,5 +54,8 @@ aarch64_create_target_description (uint64_t vq, bool pauth_p, bool mte_p)
   if (mte_p)
     regnum = create_feature_aarch64_mte (tdesc.get (), regnum);
 
+  if (tls_p)
+    regnum = create_feature_aarch64_tls (tdesc.get (), regnum);
+
   return tdesc.release ();
 }
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index e416e346e9a..8496a0341f7 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -29,6 +29,7 @@ struct aarch64_features
   bool sve = false;
   bool pauth = false;
   bool mte = false;
+  bool tls = false;
 };
 
 /* Create the aarch64 target description.  A non zero VQ value indicates both
@@ -36,10 +37,12 @@ struct aarch64_features
    an SVE Z register.  HAS_PAUTH_P indicates the presence of the PAUTH
    feature.
 
-   MTE_P indicates the presence of the Memory Tagging Extension feature.  */
+   MTE_P indicates the presence of the Memory Tagging Extension feature.
+
+   TLS_P indicates the presence of the Thread Local Storage feature.  */
 
 target_desc *aarch64_create_target_description (uint64_t vq, bool has_pauth_p,
-						bool mte_p);
+						bool mte_p, bool tls_p);
 
 /* Register numbers of various important registers.
    Note that on SVE, the Z registers reuse the V register numbers and the V
@@ -91,6 +94,7 @@ enum aarch64_regnum
 #define AARCH64_NUM_REGS AARCH64_FPCR_REGNUM + 1
 #define AARCH64_SVE_NUM_REGS AARCH64_SVE_VG_REGNUM + 1
 
+#define	AARCH64_TLS_REGS_SIZE (8)
 
 /* There are a number of ways of expressing the current SVE vector size:
 
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 5f1826baa6f..15d623c2681 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -198,6 +198,7 @@ FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-fpu.xml \
 	aarch64-pauth.xml \
 	aarch64-mte.xml \
+	aarch64-tls.xml \
 	arc/v1-core.xml \
 	arc/v1-aux.xml \
 	arc/v2-core.xml \
diff --git a/gdb/features/aarch64-tls.c b/gdb/features/aarch64-tls.c
new file mode 100644
index 00000000000..30d730dffba
--- /dev/null
+++ b/gdb/features/aarch64-tls.c
@@ -0,0 +1,14 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aarch64-tls.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_aarch64_tls (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.tls");
+  tdesc_create_reg (feature, "tpidr", regnum++, 1, NULL, 64, "data_ptr");
+  return regnum;
+}
diff --git a/gdb/features/aarch64-tls.xml b/gdb/features/aarch64-tls.xml
new file mode 100644
index 00000000000..f6437785f71
--- /dev/null
+++ b/gdb/features/aarch64-tls.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2022 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.tls">
+  <reg name="tpidr" bitsize="64" type="data_ptr"/>
+</feature>
diff --git a/gdbserver/linux-aarch64-tdesc.cc b/gdbserver/linux-aarch64-tdesc.cc
index e982ab85067..14d6a4f80eb 100644
--- a/gdbserver/linux-aarch64-tdesc.cc
+++ b/gdbserver/linux-aarch64-tdesc.cc
@@ -42,7 +42,7 @@ aarch64_linux_read_description (uint64_t vq, bool pauth_p, bool mte_p)
 
   if (tdesc == NULL)
     {
-      tdesc = aarch64_create_target_description (vq, pauth_p, mte_p);
+      tdesc = aarch64_create_target_description (vq, pauth_p, mte_p, false);
 
       static const char *expedite_regs_aarch64[] = { "x29", "sp", "pc", NULL };
       static const char *expedite_regs_aarch64_sve[] = { "x29", "sp", "pc",
diff --git a/gdbserver/netbsd-aarch64-low.cc b/gdbserver/netbsd-aarch64-low.cc
index 202bf1cdac6..b371e599232 100644
--- a/gdbserver/netbsd-aarch64-low.cc
+++ b/gdbserver/netbsd-aarch64-low.cc
@@ -96,7 +96,7 @@ void
 netbsd_aarch64_target::low_arch_setup ()
 {
   target_desc *tdesc
-    = aarch64_create_target_description (0, false);
+    = aarch64_create_target_description (0, false, false, false);
 
   static const char *expedite_regs_aarch64[] = { "x29", "sp", "pc", NULL };
   init_target_desc (tdesc, expedite_regs_aarch64);
-- 
2.34.1


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

* [PATCH v3 07/13] Read the tpidr register from NT_ARM_TLS core dump notes on FreeBSD/Aarch64.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (5 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 06/13] Add an aarch64-tls feature which includes the tpidr register John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 08/13] Support TLS variables " John Baldwin
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

---
 gdb/aarch64-fbsd-tdep.c | 34 ++++++++++++++++++++++++++++++++++
 gdb/aarch64-fbsd-tdep.h |  3 +++
 2 files changed, 37 insertions(+)

diff --git a/gdb/aarch64-fbsd-tdep.c b/gdb/aarch64-fbsd-tdep.c
index 32f441892a8..ed1b84387f0 100644
--- a/gdb/aarch64-fbsd-tdep.c
+++ b/gdb/aarch64-fbsd-tdep.c
@@ -142,10 +142,42 @@ aarch64_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					   void *cb_data,
 					   const struct regcache *regcache)
 {
+  aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
   cb (".reg", AARCH64_FBSD_SIZEOF_GREGSET, AARCH64_FBSD_SIZEOF_GREGSET,
       &aarch64_fbsd_gregset, NULL, cb_data);
   cb (".reg2", AARCH64_FBSD_SIZEOF_FPREGSET, AARCH64_FBSD_SIZEOF_FPREGSET,
       &aarch64_fbsd_fpregset, NULL, cb_data);
+
+  if (tdep->has_tls ())
+    {
+      const struct regcache_map_entry aarch64_fbsd_tls_regmap[] =
+	{
+	  { 1, tdep->tls_regnum, 8 },
+	  { 0 }
+	};
+
+      const struct regset aarch64_fbsd_tls_regset =
+	{
+	  aarch64_fbsd_tls_regmap,
+	  regcache_supply_regset, regcache_collect_regset
+	};
+
+      cb (".reg-aarch-tls", AARCH64_FBSD_SIZEOF_TLSREGSET,
+	  AARCH64_FBSD_SIZEOF_TLSREGSET, &aarch64_fbsd_tls_regset,
+	  "TLS register", cb_data);
+    }
+}
+
+/* Implement the "core_read_description" gdbarch method.  */
+
+static const struct target_desc *
+aarch64_fbsd_core_read_description (struct gdbarch *gdbarch,
+				    struct target_ops *target, bfd *abfd)
+{
+  asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls");
+
+  return aarch64_read_description (0, false, false, tls != nullptr);
 }
 
 /* Implement the 'init_osabi' method of struct gdb_osabi_handler.  */
@@ -168,6 +200,8 @@ aarch64_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_iterate_over_regset_sections
     (gdbarch, aarch64_fbsd_iterate_over_regset_sections);
+  set_gdbarch_core_read_description (gdbarch,
+				     aarch64_fbsd_core_read_description);
 }
 
 void _initialize_aarch64_fbsd_tdep ();
diff --git a/gdb/aarch64-fbsd-tdep.h b/gdb/aarch64-fbsd-tdep.h
index fc8fbee8843..7419ea6be03 100644
--- a/gdb/aarch64-fbsd-tdep.h
+++ b/gdb/aarch64-fbsd-tdep.h
@@ -32,6 +32,9 @@
    alignment.  */
 #define AARCH64_FBSD_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
 
+/* The TLS regset consists of a single register.  */
+#define	AARCH64_FBSD_SIZEOF_TLSREGSET (X_REGISTER_SIZE)
+
 extern const struct regset aarch64_fbsd_gregset;
 extern const struct regset aarch64_fbsd_fpregset;
 
-- 
2.34.1


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

* [PATCH v3 08/13] Support TLS variables on FreeBSD/Aarch64.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (6 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 07/13] Read the tpidr register from NT_ARM_TLS core dump notes on FreeBSD/Aarch64 John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 09/13] Fetch the NT_ARM_TLS register set for native FreeBSD/Aarch64 processes John Baldwin
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

Derive the pointer to the DTV array from the tpidr register.
---
 gdb/aarch64-fbsd-tdep.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/gdb/aarch64-fbsd-tdep.c b/gdb/aarch64-fbsd-tdep.c
index ed1b84387f0..fdf0795b9bf 100644
--- a/gdb/aarch64-fbsd-tdep.c
+++ b/gdb/aarch64-fbsd-tdep.c
@@ -23,6 +23,7 @@
 #include "fbsd-tdep.h"
 #include "aarch64-tdep.h"
 #include "aarch64-fbsd-tdep.h"
+#include "inferior.h"
 #include "osabi.h"
 #include "solib-svr4.h"
 #include "target.h"
@@ -180,6 +181,30 @@ aarch64_fbsd_core_read_description (struct gdbarch *gdbarch,
   return aarch64_read_description (0, false, false, tls != nullptr);
 }
 
+/* Implement the get_thread_local_address gdbarch method.  */
+
+static CORE_ADDR
+aarch64_fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
+				       CORE_ADDR lm_addr, CORE_ADDR offset)
+{
+  aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  struct regcache *regcache;
+
+  regcache = get_thread_arch_regcache (current_inferior ()->process_target (),
+				       ptid, gdbarch);
+
+  target_fetch_registers (regcache, tdep->tls_regnum);
+
+  ULONGEST tpidr;
+  if (regcache->cooked_read (tdep->tls_regnum, &tpidr) != REG_VALID)
+    error (_("Unable to fetch %%tpidr"));
+
+  /* %tpidr points to the TCB whose first member is the dtv
+      pointer.  */
+  CORE_ADDR dtv_addr = tpidr;
+  return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset);
+}
+
 /* Implement the 'init_osabi' method of struct gdb_osabi_handler.  */
 
 static void
@@ -202,6 +227,14 @@ aarch64_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
     (gdbarch, aarch64_fbsd_iterate_over_regset_sections);
   set_gdbarch_core_read_description (gdbarch,
 				     aarch64_fbsd_core_read_description);
+
+  if (tdep->has_tls ())
+    {
+      set_gdbarch_fetch_tls_load_module_address (gdbarch,
+						 svr4_fetch_objfile_link_map);
+      set_gdbarch_get_thread_local_address
+	(gdbarch, aarch64_fbsd_get_thread_local_address);
+    }
 }
 
 void _initialize_aarch64_fbsd_tdep ();
-- 
2.34.1


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

* [PATCH v3 09/13] Fetch the NT_ARM_TLS register set for native FreeBSD/Aarch64 processes.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (7 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 08/13] Support TLS variables " John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 10/13] Read the tpidr register from NT_ARM_TLS core dump notes on Linux Aarch64 John Baldwin
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

This permits resolving TLS variables.
---
 gdb/aarch64-fbsd-nat.c | 54 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/gdb/aarch64-fbsd-nat.c b/gdb/aarch64-fbsd-nat.c
index 99e2bf35276..910bf5bb190 100644
--- a/gdb/aarch64-fbsd-nat.c
+++ b/gdb/aarch64-fbsd-nat.c
@@ -24,12 +24,15 @@
 #include "target.h"
 #include "nat/aarch64-hw-point.h"
 
+#include "elf/common.h"
+
 #include <sys/param.h>
 #include <sys/ptrace.h>
 #include <machine/armreg.h>
 #include <machine/reg.h>
 
 #include "fbsd-nat.h"
+#include "aarch64-tdep.h"
 #include "aarch64-fbsd-tdep.h"
 #include "aarch64-nat.h"
 #include "inf-ptrace.h"
@@ -50,6 +53,8 @@ struct aarch64_fbsd_nat_target final : public fbsd_nat_target
   void fetch_registers (struct regcache *, int) override;
   void store_registers (struct regcache *, int) override;
 
+  const struct target_desc *read_description () override;
+
 #ifdef HAVE_DBREG
   /* Hardware breakpoints and watchpoints.  */
   bool stopped_by_watchpoint () override;
@@ -84,6 +89,26 @@ aarch64_fbsd_nat_target::fetch_registers (struct regcache *regcache,
 				  &aarch64_fbsd_gregset);
   fetch_register_set<struct fpreg> (regcache, regnum, PT_GETFPREGS,
 				    &aarch64_fbsd_fpregset);
+
+  gdbarch *gdbarch = regcache->arch ();
+  aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  if (tdep->has_tls ())
+    {
+      const struct regcache_map_entry aarch64_fbsd_tls_regmap[] =
+	{
+	  { 1, tdep->tls_regnum, 8 },
+	  { 0 }
+	};
+
+      const struct regset aarch64_fbsd_tls_regset =
+	{
+	  aarch64_fbsd_tls_regmap,
+	  regcache_supply_regset, regcache_collect_regset
+	};
+
+      fetch_regset<uint64_t> (regcache, regnum, NT_ARM_TLS,
+			      &aarch64_fbsd_tls_regset);
+    }
 }
 
 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
@@ -97,6 +122,35 @@ aarch64_fbsd_nat_target::store_registers (struct regcache *regcache,
 				  &aarch64_fbsd_gregset);
   store_register_set<struct fpreg> (regcache, regnum, PT_GETFPREGS,
 				    PT_SETFPREGS, &aarch64_fbsd_fpregset);
+
+  gdbarch *gdbarch = regcache->arch ();
+  aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  if (tdep->has_tls ())
+    {
+      const struct regcache_map_entry aarch64_fbsd_tls_regmap[] =
+	{
+	  { 1, tdep->tls_regnum, 8 },
+	  { 0 }
+	};
+
+      const struct regset aarch64_fbsd_tls_regset =
+	{
+	  aarch64_fbsd_tls_regmap,
+	  regcache_supply_regset, regcache_collect_regset
+	};
+
+      store_regset<uint64_t> (regcache, regnum, NT_ARM_TLS,
+			      &aarch64_fbsd_tls_regset);
+    }
+}
+
+/* Implement the target read_description method.  */
+
+const struct target_desc *
+aarch64_fbsd_nat_target::read_description ()
+{
+  bool tls = have_regset (inferior_ptid, NT_ARM_TLS) != 0;
+  return aarch64_read_description (0, false, false, tls);
 }
 
 #ifdef HAVE_DBREG
-- 
2.34.1


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

* [PATCH v3 10/13] Read the tpidr register from NT_ARM_TLS core dump notes on Linux Aarch64.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (8 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 09/13] Fetch the NT_ARM_TLS register set for native FreeBSD/Aarch64 processes John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 11/13] gdbserver: Read the tpidr register from NT_ARM_TLS on Linux John Baldwin
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

---
 gdb/aarch64-linux-tdep.c | 21 ++++++++++++++++++++-
 gdb/aarch64-linux-tdep.h |  3 +++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 8cfb64d9f4a..dbebcd4f0e0 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -749,6 +749,24 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 	  AARCH64_LINUX_SIZEOF_MTE_REGSET, &aarch64_linux_mte_regset,
 	  "MTE registers", cb_data);
     }
+
+  if (tdep->has_tls ())
+    {
+      const struct regcache_map_entry tls_regmap[] =
+	{
+	  { 1, tdep->tls_regnum, 8 },
+	  { 0 }
+	};
+
+      const struct regset aarch64_linux_tls_regset =
+	{
+	  tls_regmap, regcache_supply_regset, regcache_collect_regset
+	};
+
+      cb (".reg-aarch-tls", AARCH64_LINUX_SIZEOF_TLSREGSET,
+	  AARCH64_LINUX_SIZEOF_TLSREGSET, &aarch64_linux_tls_regset,
+	  "TLS register", cb_data);
+    }
 }
 
 /* Implement the "core_read_description" gdbarch method.  */
@@ -757,13 +775,14 @@ static const struct target_desc *
 aarch64_linux_core_read_description (struct gdbarch *gdbarch,
 				     struct target_ops *target, bfd *abfd)
 {
+  asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls");
   CORE_ADDR hwcap = linux_get_hwcap (target);
   CORE_ADDR hwcap2 = linux_get_hwcap2 (target);
 
   bool pauth_p = hwcap & AARCH64_HWCAP_PACA;
   bool mte_p = hwcap2 & HWCAP2_MTE;
   return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd),
-				   pauth_p, mte_p, false);
+				   pauth_p, mte_p, tls != nullptr);
 }
 
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index 8ae33efc605..9a7e4339dba 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -39,6 +39,9 @@
 /* The MTE regset consists of a 64-bit register.  */
 #define AARCH64_LINUX_SIZEOF_MTE_REGSET (8)
 
+/* The TLS regset consists of a single register.  */
+#define AARCH64_LINUX_SIZEOF_TLSREGSET (X_REGISTER_SIZE)
+
 extern const struct regset aarch64_linux_gregset;
 extern const struct regset aarch64_linux_fpregset;
 
-- 
2.34.1


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

* [PATCH v3 11/13] gdbserver: Read the tpidr register from NT_ARM_TLS on Linux.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (9 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 10/13] Read the tpidr register from NT_ARM_TLS core dump notes on Linux Aarch64 John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 12/13] " John Baldwin
  2022-04-27 15:14 ` [PATCH v3 13/13] NEWS: Add a note for TLS support on FreeBSD/arm and FreeBSD/Aarch64 John Baldwin
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

---
 gdbserver/linux-aarch64-ipa.cc   |  8 ++++----
 gdbserver/linux-aarch64-low.cc   | 32 +++++++++++++++++++++++++++++++-
 gdbserver/linux-aarch64-tdesc.cc | 11 ++++++-----
 gdbserver/linux-aarch64-tdesc.h  |  2 +-
 4 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/gdbserver/linux-aarch64-ipa.cc b/gdbserver/linux-aarch64-ipa.cc
index 296c63534d8..dc907d3ff88 100644
--- a/gdbserver/linux-aarch64-ipa.cc
+++ b/gdbserver/linux-aarch64-ipa.cc
@@ -147,12 +147,12 @@ get_raw_reg (const unsigned char *raw_regs, int regnum)
 
 /* Return target_desc to use for IPA, given the tdesc index passed by
    gdbserver.  Index is ignored, since we have only one tdesc
-   at the moment.  SVE, pauth and MTE not yet supported.  */
+   at the moment.  SVE, pauth, MTE and TLS not yet supported.  */
 
 const struct target_desc *
 get_ipa_tdesc (int idx)
 {
-  return aarch64_linux_read_description (0, false, false);
+  return aarch64_linux_read_description (0, false, false, false);
 }
 
 /* Allocate buffer for the jump pads.  The branch instruction has a reach
@@ -204,6 +204,6 @@ alloc_jump_pad_buffer (size_t size)
 void
 initialize_low_tracepoint (void)
 {
-  /* SVE, pauth and MTE not yet supported.  */
-  aarch64_linux_read_description (0, false, false);
+  /* SVE, pauth, MTE and TLS not yet supported.  */
+  aarch64_linux_read_description (0, false, false, false);
 }
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
index 0091f998c63..c924821c25c 100644
--- a/gdbserver/linux-aarch64-low.cc
+++ b/gdbserver/linux-aarch64-low.cc
@@ -287,6 +287,26 @@ aarch64_store_mteregset (struct regcache *regcache, const void *buf)
   supply_register (regcache, mte_base, mte_regset);
 }
 
+/* Fill BUF with TLS register from the regcache.  */
+
+static void
+aarch64_fill_tlsregset (struct regcache *regcache, void *buf)
+{
+  int tls_regnum  = find_regno (regcache->tdesc, "tpidr");
+
+  collect_register (regcache, tls_regnum, buf);
+}
+
+/* Store TLS register to regcache.  */
+
+static void
+aarch64_store_tlsregset (struct regcache *regcache, const void *buf)
+{
+  int tls_regnum  = find_regno (regcache->tdesc, "tpidr");
+
+  supply_register (regcache, tls_regnum, buf);
+}
+
 bool
 aarch64_target::low_supports_breakpoints ()
 {
@@ -719,6 +739,10 @@ static struct regset_info aarch64_regsets[] =
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TAGGED_ADDR_CTRL,
     0, OPTIONAL_REGS,
     aarch64_fill_mteregset, aarch64_store_mteregset },
+  /* TLS register.  */
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TLS,
+    0, OPTIONAL_REGS,
+    aarch64_fill_tlsregset, aarch64_store_tlsregset },
   NULL_REGSET
 };
 
@@ -770,6 +794,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
 	  if (features.mte)
 	    regset->size = AARCH64_LINUX_SIZEOF_MTE;
 	  break;
+	case NT_ARM_TLS:
+	  if (features.tls)
+	    regset->size = AARCH64_TLS_REGS_SIZE;
+	  break;
 	default:
 	  gdb_assert_not_reached ("Unknown register set found.");
 	}
@@ -802,9 +830,11 @@ aarch64_target::low_arch_setup ()
       features.pauth = linux_get_hwcap (8) & AARCH64_HWCAP_PACA;
       /* A-profile MTE is 64-bit only.  */
       features.mte = linux_get_hwcap2 (8) & HWCAP2_MTE;
+      features.tls = true;
 
       current_process ()->tdesc
-	= aarch64_linux_read_description (vq, features.pauth, features.mte);
+	= aarch64_linux_read_description (vq, features.pauth, features.mte,
+					  features.tls);
 
       /* Adjust the register sets we should use for this particular set of
 	 features.  */
diff --git a/gdbserver/linux-aarch64-tdesc.cc b/gdbserver/linux-aarch64-tdesc.cc
index 14d6a4f80eb..be96612d571 100644
--- a/gdbserver/linux-aarch64-tdesc.cc
+++ b/gdbserver/linux-aarch64-tdesc.cc
@@ -27,22 +27,23 @@
 #include <inttypes.h>
 
 /* All possible aarch64 target descriptors.  */
-struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/][2 /* mte */];
+struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/][2 /* mte */][2 /* tls */];
 
 /* Create the aarch64 target description.  */
 
 const target_desc *
-aarch64_linux_read_description (uint64_t vq, bool pauth_p, bool mte_p)
+aarch64_linux_read_description (uint64_t vq, bool pauth_p, bool mte_p,
+				bool tls_p)
 {
   if (vq > AARCH64_MAX_SVE_VQ)
     error (_("VQ is %" PRIu64 ", maximum supported value is %d"), vq,
 	   AARCH64_MAX_SVE_VQ);
 
-  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p][mte_p];
+  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p][mte_p][tls_p];
 
   if (tdesc == NULL)
     {
-      tdesc = aarch64_create_target_description (vq, pauth_p, mte_p, false);
+      tdesc = aarch64_create_target_description (vq, pauth_p, mte_p, tls_p);
 
       static const char *expedite_regs_aarch64[] = { "x29", "sp", "pc", NULL };
       static const char *expedite_regs_aarch64_sve[] = { "x29", "sp", "pc",
@@ -53,7 +54,7 @@ aarch64_linux_read_description (uint64_t vq, bool pauth_p, bool mte_p)
       else
 	init_target_desc (tdesc, expedite_regs_aarch64_sve);
 
-      tdesc_aarch64_list[vq][pauth_p][mte_p] = tdesc;
+      tdesc_aarch64_list[vq][pauth_p][mte_p][tls_p] = tdesc;
     }
 
   return tdesc;
diff --git a/gdbserver/linux-aarch64-tdesc.h b/gdbserver/linux-aarch64-tdesc.h
index 66d6fa32f16..4ab658447a2 100644
--- a/gdbserver/linux-aarch64-tdesc.h
+++ b/gdbserver/linux-aarch64-tdesc.h
@@ -21,6 +21,6 @@
 #define GDBSERVER_LINUX_AARCH64_TDESC_H
 
 const target_desc * aarch64_linux_read_description (uint64_t vq, bool pauth_p,
-						    bool mte_p);
+						    bool mte_p, bool tls_p);
 
 #endif /* GDBSERVER_LINUX_AARCH64_TDESC_H */
-- 
2.34.1


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

* [PATCH v3 12/13] Read the tpidr register from NT_ARM_TLS on Linux.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (10 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 11/13] gdbserver: Read the tpidr register from NT_ARM_TLS on Linux John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:14 ` [PATCH v3 13/13] NEWS: Add a note for TLS support on FreeBSD/arm and FreeBSD/Aarch64 John Baldwin
  12 siblings, 0 replies; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

---
 gdb/aarch64-linux-nat.c | 68 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 4da274c285a..10b0ca10984 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -431,6 +431,60 @@ store_mteregs_to_thread (struct regcache *regcache)
     perror_with_name (_("unable to store MTE registers."));
 }
 
+/* Fill GDB's register array with the TLS register values from
+   the current thread.  */
+
+static void
+fetch_tlsregs_from_thread (struct regcache *regcache)
+{
+  aarch64_gdbarch_tdep *tdep
+    = (aarch64_gdbarch_tdep *) gdbarch_tdep (regcache->arch ());
+  int regno = tdep->tls_regnum;
+
+  gdb_assert (regno != -1);
+
+  uint64_t tpidr = 0;
+  struct iovec iovec;
+
+  iovec.iov_base = &tpidr;
+  iovec.iov_len = sizeof (tpidr);
+
+  int tid = get_ptrace_pid (regcache->ptid ());
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_TLS, &iovec) != 0)
+      perror_with_name (_("unable to fetch TLS register."));
+
+  regcache->raw_supply (regno, &tpidr);
+}
+
+/* Store to the current thread the valid TLS register set in GDB's
+   register array.  */
+
+static void
+store_tlsregs_to_thread (struct regcache *regcache)
+{
+  aarch64_gdbarch_tdep *tdep
+    = (aarch64_gdbarch_tdep *) gdbarch_tdep (regcache->arch ());
+  int regno = tdep->tls_regnum;
+
+  gdb_assert (regno != -1);
+
+  uint64_t tpidr = 0;
+
+  if (REG_VALID != regcache->get_register_status (regno))
+    return;
+
+  regcache->raw_collect (regno, (char *) &tpidr);
+
+  struct iovec iovec;
+
+  iovec.iov_base = &tpidr;
+  iovec.iov_len = sizeof (tpidr);
+
+  int tid = get_ptrace_pid (regcache->ptid ());
+  if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_TLS, &iovec) != 0)
+    perror_with_name (_("unable to store TLS register."));
+}
+
 /* Implement the "fetch_registers" target_ops method.  */
 
 void
@@ -453,6 +507,9 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
 
       if (tdep->has_mte ())
 	fetch_mteregs_from_thread (regcache);
+
+      if (tdep->has_tls ())
+	fetch_tlsregs_from_thread (regcache);
     }
   else if (regno < AARCH64_V0_REGNUM)
     fetch_gregs_from_thread (regcache);
@@ -472,6 +529,9 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
   if (tdep->has_mte ()
       && (regno == tdep->mte_reg_base))
     fetch_mteregs_from_thread (regcache);
+
+  if (tdep->has_tls () && regno == tdep->tls_regnum)
+    fetch_tlsregs_from_thread (regcache);
 }
 
 /* Implement the "store_registers" target_ops method.  */
@@ -493,6 +553,9 @@ aarch64_linux_nat_target::store_registers (struct regcache *regcache,
 
       if (tdep->has_mte ())
 	store_mteregs_to_thread (regcache);
+
+      if (tdep->has_tls ())
+	store_tlsregs_to_thread (regcache);
     }
   else if (regno < AARCH64_V0_REGNUM)
     store_gregs_to_thread (regcache);
@@ -505,6 +568,9 @@ aarch64_linux_nat_target::store_registers (struct regcache *regcache,
   if (tdep->has_mte ()
       && (regno == tdep->mte_reg_base))
     store_mteregs_to_thread (regcache);
+
+  if (tdep->has_tls () && regno == tdep->tls_regnum)
+    store_tlsregs_to_thread (regcache);
 }
 
 /* Fill register REGNO (if it is a general-purpose register) in
@@ -647,7 +713,7 @@ aarch64_linux_nat_target::read_description ()
   bool mte_p = hwcap2 & HWCAP2_MTE;
 
   return aarch64_read_description (aarch64_sve_get_vq (tid), pauth_p, mte_p,
-				   false);
+				   true);
 }
 
 /* Convert a native/host siginfo object, into/from the siginfo in the
-- 
2.34.1


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

* [PATCH v3 13/13] NEWS: Add a note for TLS support on FreeBSD/arm and FreeBSD/Aarch64.
  2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
                   ` (11 preceding siblings ...)
  2022-04-27 15:14 ` [PATCH v3 12/13] " John Baldwin
@ 2022-04-27 15:14 ` John Baldwin
  2022-04-27 15:46   ` Eli Zaretskii
  12 siblings, 1 reply; 15+ messages in thread
From: John Baldwin @ 2022-04-27 15:14 UTC (permalink / raw)
  To: gdb-patches

---
 gdb/NEWS | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index 982f4a1a18c..a72fee81550 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,9 @@
 
 *** Changes since GDB 12
 
+* Support for Thread Local Storage (TLS) variables on FreeBSD arm and
+  aarch64 architectures.
+
 * GDB now supports hardware watchpoints on FreeBSD/Aarch64.
 
 * Remove support for building against Python 2, it is now only possible to
-- 
2.34.1


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

* Re: [PATCH v3 13/13] NEWS: Add a note for TLS support on FreeBSD/arm and FreeBSD/Aarch64.
  2022-04-27 15:14 ` [PATCH v3 13/13] NEWS: Add a note for TLS support on FreeBSD/arm and FreeBSD/Aarch64 John Baldwin
@ 2022-04-27 15:46   ` Eli Zaretskii
  0 siblings, 0 replies; 15+ messages in thread
From: Eli Zaretskii @ 2022-04-27 15:46 UTC (permalink / raw)
  To: John Baldwin; +Cc: gdb-patches

> From: John Baldwin <jhb@FreeBSD.org>
> Date: Wed, 27 Apr 2022 08:14:16 -0700
> 
> ---
>  gdb/NEWS | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 982f4a1a18c..a72fee81550 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -3,6 +3,9 @@
>  
>  *** Changes since GDB 12
>  
> +* Support for Thread Local Storage (TLS) variables on FreeBSD arm and
> +  aarch64 architectures.
> +
>  * GDB now supports hardware watchpoints on FreeBSD/Aarch64.
>  
>  * Remove support for building against Python 2, it is now only possible to

This part is OK, thanks.

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

end of thread, other threads:[~2022-04-27 15:46 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27 15:14 [PATCH v3 00/13] Support for Thread Local Storage (TLS) variables on FreeBSD arm and aarch64 architectures John Baldwin
2022-04-27 15:14 ` [PATCH v3 01/13] fbsd-nat: Add helper routines for register sets using PT_[G]SETREGSET John Baldwin
2022-04-27 15:14 ` [PATCH v3 02/13] Add an arm-tls feature which includes the tpidruro register from CP15 John Baldwin
2022-04-27 15:14 ` [PATCH v3 03/13] Read the tpidruro register from NT_ARM_TLS core dump notes on FreeBSD/arm John Baldwin
2022-04-27 15:14 ` [PATCH v3 04/13] Support TLS variables " John Baldwin
2022-04-27 15:14 ` [PATCH v3 05/13] Fetch the NT_ARM_TLS register set for native FreeBSD/arm processes John Baldwin
2022-04-27 15:14 ` [PATCH v3 06/13] Add an aarch64-tls feature which includes the tpidr register John Baldwin
2022-04-27 15:14 ` [PATCH v3 07/13] Read the tpidr register from NT_ARM_TLS core dump notes on FreeBSD/Aarch64 John Baldwin
2022-04-27 15:14 ` [PATCH v3 08/13] Support TLS variables " John Baldwin
2022-04-27 15:14 ` [PATCH v3 09/13] Fetch the NT_ARM_TLS register set for native FreeBSD/Aarch64 processes John Baldwin
2022-04-27 15:14 ` [PATCH v3 10/13] Read the tpidr register from NT_ARM_TLS core dump notes on Linux Aarch64 John Baldwin
2022-04-27 15:14 ` [PATCH v3 11/13] gdbserver: Read the tpidr register from NT_ARM_TLS on Linux John Baldwin
2022-04-27 15:14 ` [PATCH v3 12/13] " John Baldwin
2022-04-27 15:14 ` [PATCH v3 13/13] NEWS: Add a note for TLS support on FreeBSD/arm and FreeBSD/Aarch64 John Baldwin
2022-04-27 15:46   ` Eli Zaretskii

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