git: 1c25ded0af45 - main - devel/gdb: Update to 12.1.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 10 May 2022 17:42:23 UTC
The branch main has been updated by jhb (doc, src committer):

URL: https://cgit.FreeBSD.org/ports/commit/?id=1c25ded0af45ac5dc5817b4004f99ee288a2ce7a

commit 1c25ded0af45ac5dc5817b4004f99ee288a2ce7a
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-05-10 17:41:13 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2022-05-10 17:41:13 +0000

    devel/gdb: Update to 12.1.
    
    One notable feature included in 12.1 is async target support
    permitting the use of commands like continue&.
    
    In addition, this commit backports various post-12 commits to add
    support for hardware breakpoints/watchpoints on aarch64, support for
    resolving TLS variables from core dumps on amd64 and i386 via the
    recently added NT_X86_SEGBASES core dump note, and support for
    resolving TLS variables on arm and aarch64 via the recently added
    NT_ARM_TLS register set.
    
    Reviewed by:    pizzamig
    Differential Revision:  https://reviews.freebsd.org/D35111
---
 devel/gdb/Makefile                        |   34 +-
 devel/gdb/distinfo                        |    6 +-
 devel/gdb/files/commit-041a4212d37        |   97 ++
 devel/gdb/files/commit-065a00b3a46        |  338 ++++++
 devel/gdb/files/commit-099fbce0acc        |  114 ++
 devel/gdb/files/commit-0a765c1a8e9        |   78 ++
 devel/gdb/files/commit-1570c37c340        |  892 +++++++++++++++
 devel/gdb/files/commit-2e686a74dc4        |   68 ++
 devel/gdb/files/commit-3181aed81c9        |   20 +
 devel/gdb/files/commit-40c23d88038        |  163 +++
 devel/gdb/files/commit-414d5848bb2        |  293 +++++
 devel/gdb/files/commit-4bd817e71ee        | 1726 +++++++++++++++++++++++++++++
 devel/gdb/files/commit-6719bc690e2        |   48 +
 devel/gdb/files/commit-684943d213b        |  102 ++
 devel/gdb/files/commit-711b0b6698f        |   55 +
 devel/gdb/files/commit-8e6afe4013f        |   38 +
 devel/gdb/files/commit-922c2fc18e4        |  132 +++
 devel/gdb/files/commit-92d48a1e4ea        |  288 +++++
 devel/gdb/files/commit-983b1119bc3        |   42 +
 devel/gdb/files/commit-a171378aa47        |   45 +
 devel/gdb/files/commit-a3627b54280        |   53 +
 devel/gdb/files/commit-a49ce729c80        |  157 +++
 devel/gdb/files/commit-b1babce7c31        |   50 +
 devel/gdb/files/commit-b5c2367c3ac        |   89 ++
 devel/gdb/files/commit-b7fe5463cf0        |  102 ++
 devel/gdb/files/commit-c13566fdd57        |   35 +
 devel/gdb/files/commit-c77282d8ba9        |   41 +
 devel/gdb/files/commit-e330d4c033e        |   55 +
 devel/gdb/files/commit-f3215e1526d        |  114 ++
 devel/gdb/files/commit-f9fbb7636a5        |   68 ++
 devel/gdb/files/extrapatch-kgdb           |  124 +--
 devel/gdb/files/kgdb/aarch64-fbsd-kern.c  |    2 +-
 devel/gdb/files/kgdb/arm-fbsd-kern.c      |    2 +-
 devel/gdb/files/kgdb/fbsd-kld.c           |    8 +-
 devel/gdb/files/kgdb/fbsd-kthr.c          |   20 +-
 devel/gdb/files/kgdb/fbsd-kvm.c           |    5 +-
 devel/gdb/files/kgdb/ppcfbsd-kern.c       |    6 +-
 devel/gdb/files/patch-fixes               |   10 -
 devel/gdb/files/patch-gdb_amd64-bsd-nat.c |   30 -
 devel/gdb/files/patch-gdb_i386-fbsd-nat.c |   22 +-
 devel/gdb/files/patch-include_libiberty.h |   11 -
 devel/gdb/files/patch-libiberty_configure |   12 -
 devel/gdb/pkg-plist                       |    2 +
 43 files changed, 5431 insertions(+), 166 deletions(-)

diff --git a/devel/gdb/Makefile b/devel/gdb/Makefile
index 66ae1ce8316a..ec71f616457f 100644
--- a/devel/gdb/Makefile
+++ b/devel/gdb/Makefile
@@ -1,7 +1,7 @@
 # Created by: Steven Kreuzer <skreuzer@FreeBSD.org>
 
 PORTNAME=	gdb
-DISTVERSION=	11.2
+DISTVERSION=	12.1
 PORTREVISION=	0
 CATEGORIES=	devel
 MASTER_SITES=	GNU
@@ -38,6 +38,34 @@ CFLAGS:=	${CFLAGS:C/ +$//}	# blanks at EOL creep in sometimes
 CFLAGS+=	-DRL_NO_COMPAT
 EXCLUDE=	dejagnu expect sim texinfo intl
 EXTRACT_AFTER_ARGS=	${EXCLUDE:S/^/--exclude /}
+EXTRA_PATCHES=	${FILESDIR}/commit-711b0b6698f \
+		${FILESDIR}/commit-922c2fc18e4 \
+		${FILESDIR}/commit-b1babce7c31 \
+		${FILESDIR}/commit-a49ce729c80 \
+		${FILESDIR}/commit-c77282d8ba9 \
+		${FILESDIR}/commit-041a4212d37 \
+		${FILESDIR}/commit-4bd817e71ee \
+		${FILESDIR}/commit-1570c37c340 \
+		${FILESDIR}/commit-6719bc690e2 \
+		${FILESDIR}/commit-983b1119bc3 \
+		${FILESDIR}/commit-a3627b54280 \
+		${FILESDIR}/commit-065a00b3a46 \
+		${FILESDIR}/commit-e330d4c033e \
+		${FILESDIR}/commit-a171378aa47 \
+		${FILESDIR}/commit-b5c2367c3ac \
+		${FILESDIR}/commit-f3215e1526d \
+		${FILESDIR}/commit-c13566fdd57 \
+		${FILESDIR}/commit-3181aed81c9 \
+		${FILESDIR}/commit-8e6afe4013f \
+		${FILESDIR}/commit-40c23d88038 \
+		${FILESDIR}/commit-92d48a1e4ea \
+		${FILESDIR}/commit-099fbce0acc \
+		${FILESDIR}/commit-2e686a74dc4 \
+		${FILESDIR}/commit-684943d213b \
+		${FILESDIR}/commit-414d5848bb2 \
+		${FILESDIR}/commit-0a765c1a8e9 \
+		${FILESDIR}/commit-f9fbb7636a5 \
+		${FILESDIR}/commit-b7fe5463cf0
 LIB_DEPENDS+=	libexpat.so:textproc/expat2
 
 VER=		${DISTVERSION:S/.//g}
@@ -123,10 +151,6 @@ EXCLUDE+=	zlib
 CONFIGURE_TARGET=	x86_64-portbld-freebsd${OSREL}
 .endif
 
-.if ${CHOSEN_COMPILER_TYPE} == clang
-CFLAGS+=	-Wno-extended-offsetof
-.endif
-
 post-patch:
 	@${REINPLACE_CMD} -e 's|$$| [GDB v${DISTVERSION} for FreeBSD]|' \
 		${WRKSRC}/gdb/version.in
diff --git a/devel/gdb/distinfo b/devel/gdb/distinfo
index 4004bd294123..41afd51e1aae 100644
--- a/devel/gdb/distinfo
+++ b/devel/gdb/distinfo
@@ -1,5 +1,5 @@
-TIMESTAMP = 1642410957
-SHA256 (gdb-11.2.tar.xz) = 1497c36a71881b8671a9a84a0ee40faab788ca30d7ba19d8463c3cc787152e32
-SIZE (gdb-11.2.tar.xz) = 22039420
+TIMESTAMP = 1651512279
+SHA256 (gdb-12.1.tar.xz) = 0e1793bf8f2b54d53f46dea84ccfd446f48f81b297b28c4f7fc017b818d69fed
+SIZE (gdb-12.1.tar.xz) = 22470332
 SHA256 (bsdjhb-libcxx-gdbpy-03d0d9b_GH0.tar.gz) = 2c1563f361d4fb59b54b1b39bff5cdf609d73962758eb05a8cdfe2c22551b259
 SIZE (bsdjhb-libcxx-gdbpy-03d0d9b_GH0.tar.gz) = 6052
diff --git a/devel/gdb/files/commit-041a4212d37 b/devel/gdb/files/commit-041a4212d37
new file mode 100644
index 000000000000..8df89ea0cc7c
--- /dev/null
+++ b/devel/gdb/files/commit-041a4212d37
@@ -0,0 +1,97 @@
+commit 7d06796cbc1e5f5a9ca03a5214934a849bd519b1
+Author: John Baldwin <jhb@FreeBSD.org>
+Date:   Tue Mar 22 12:05:43 2022 -0700
+
+    x86-fbsd-nat: Copy debug register state on fork.
+    
+    Use the FreeBSD native target low_new_fork hook to copy the
+    per-process debug state from the parent to the child on fork.
+    
+    (cherry picked from commit 041a4212d37de6172b3428613c9f9f52ab950c6c)
+
+diff --git a/gdb/configure.nat b/gdb/configure.nat
+index b45519fd116..92ad4a6522b 100644
+--- gdb/configure.nat
++++ gdb/configure.nat
+@@ -165,7 +165,7 @@ case ${gdb_host} in
+ 	    i386)
+ 		# Host: FreeBSD/i386
+ 		NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
+-		x86-bsd-nat.o i386-fbsd-nat.o bsd-kvm.o"
++		x86-bsd-nat.o x86-fbsd-nat.o i386-fbsd-nat.o bsd-kvm.o"
+ 		;;
+ 	    mips)
+ 		# Host: FreeBSD/mips
+@@ -194,7 +194,7 @@ case ${gdb_host} in
+ 		# Host: FreeBSD/amd64
+ 		NATDEPFILES="${NATDEPFILES} amd64-nat.o \
+ 		amd64-fbsd-nat.o bsd-kvm.o x86-nat.o nat/x86-dregs.o \
+-		x86-bsd-nat.o"
++		x86-bsd-nat.o x86-fbsd-nat.o"
+ 		;;
+ 	esac
+ 	;;
+diff --git a/gdb/x86-fbsd-nat.c b/gdb/x86-fbsd-nat.c
+new file mode 100644
+index 00000000000..ad8c693b68e
+--- /dev/null
++++ gdb/x86-fbsd-nat.c
+@@ -0,0 +1,45 @@
++/* Native-dependent code for FreeBSD x86.
++
++   Copyright (C) 2022 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/>.  */
++
++#include "defs.h"
++#include "x86-fbsd-nat.h"
++
++/* Implement the virtual fbsd_nat_target::low_new_fork method.  */
++
++void
++x86_fbsd_nat_target::low_new_fork (ptid_t parent, pid_t child)
++{
++  struct x86_debug_reg_state *parent_state, *child_state;
++
++  /* If there is no parent state, no watchpoints nor breakpoints have
++     been set, so there is nothing to do.  */
++  parent_state = x86_lookup_debug_reg_state (parent.pid ());
++  if (parent_state == nullptr)
++    return;
++
++  /* The kernel clears debug registers in the new child process after
++     fork, but GDB core assumes the child inherits the watchpoints/hw
++     breakpoints of the parent, and will remove them all from the
++     forked off process.  Copy the debug registers mirrors into the
++     new process so that all breakpoints and watchpoints can be
++     removed together.  */
++
++  child_state = x86_debug_reg_state (child);
++  *child_state = *parent_state;
++}
+diff --git a/gdb/x86-fbsd-nat.h b/gdb/x86-fbsd-nat.h
+index f9d3514aab4..cdb8cd36a4c 100644
+--- gdb/x86-fbsd-nat.h
++++ gdb/x86-fbsd-nat.h
+@@ -29,6 +29,8 @@ class x86_fbsd_nat_target : public x86bsd_nat_target<fbsd_nat_target>
+ {
+   bool supports_stopped_by_hw_breakpoint () override
+   { return true; }
++
++  void low_new_fork (ptid_t parent, pid_t child) override;
+ };
+ 
+ #endif /* x86-bsd-nat.h */
diff --git a/devel/gdb/files/commit-065a00b3a46 b/devel/gdb/files/commit-065a00b3a46
new file mode 100644
index 000000000000..a7725dc73827
--- /dev/null
+++ b/devel/gdb/files/commit-065a00b3a46
@@ -0,0 +1,338 @@
+commit 194342a42538301d9ef47d4be6efd74ddfb8fac2
+Author: John Baldwin <jhb@FreeBSD.org>
+Date:   Tue Mar 22 12:05:43 2022 -0700
+
+    Add support for hardware breakpoints/watchpoints on FreeBSD/Aarch64.
+    
+    This shares aarch64-nat.c and nat/aarch64-hw-point.c with the Linux
+    native target.  Since FreeBSD writes all of the debug registers in one
+    ptrace op, use an unordered_set<> to track the "dirty" state for
+    threads rather than bitmasks of modified registers.
+    
+    (cherry picked from commit 065a00b3a461463cca766ac6bb33e3be436397bd)
+
+diff --git a/gdb/NEWS b/gdb/NEWS
+index 501ace1872e..0320bf8ea1e 100644
+--- gdb/NEWS
++++ gdb/NEWS
+@@ -3,6 +3,8 @@
+ 
+ *** Changes in GDB 12
+ 
++* GDB now supports hardware watchpoints on FreeBSD/Aarch64.
++
+ * DBX mode is deprecated, and will be removed in GDB 13
+ 
+ * GDB 12 is the last release of GDB that will support building against
+diff --git a/gdb/aarch64-fbsd-nat.c b/gdb/aarch64-fbsd-nat.c
+index e6ca1196139..99e2bf35276 100644
+--- gdb/aarch64-fbsd-nat.c
++++ gdb/aarch64-fbsd-nat.c
+@@ -18,24 +18,60 @@
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+ 
+ #include "defs.h"
++#include "arch-utils.h"
++#include "inferior.h"
+ #include "regcache.h"
+ #include "target.h"
++#include "nat/aarch64-hw-point.h"
+ 
+-#include <sys/types.h>
++#include <sys/param.h>
+ #include <sys/ptrace.h>
++#include <machine/armreg.h>
+ #include <machine/reg.h>
+ 
+ #include "fbsd-nat.h"
+ #include "aarch64-fbsd-tdep.h"
++#include "aarch64-nat.h"
+ #include "inf-ptrace.h"
+ 
++#if __FreeBSD_version >= 1400005
++#define	HAVE_DBREG
++
++#include <unordered_set>
++#endif
++
++#ifdef HAVE_DBREG
++struct aarch64_fbsd_nat_target final
++  : public aarch64_nat_target<fbsd_nat_target>
++#else
+ struct aarch64_fbsd_nat_target final : public fbsd_nat_target
++#endif
+ {
+   void fetch_registers (struct regcache *, int) override;
+   void store_registers (struct regcache *, int) override;
++
++#ifdef HAVE_DBREG
++  /* Hardware breakpoints and watchpoints.  */
++  bool stopped_by_watchpoint () override;
++  bool stopped_data_address (CORE_ADDR *) override;
++  bool stopped_by_hw_breakpoint () override;
++  bool supports_stopped_by_hw_breakpoint () override;
++
++  void post_startup_inferior (ptid_t) override;
++  void post_attach (int pid) override;
++
++  void low_new_fork (ptid_t parent, pid_t child) override;
++  void low_delete_thread (thread_info *) override;
++  void low_prepare_to_resume (thread_info *) override;
++
++private:
++  void probe_debug_regs (int pid);
++  static bool debug_regs_probed;
++#endif
+ };
+ 
+ static aarch64_fbsd_nat_target the_aarch64_fbsd_nat_target;
++bool aarch64_fbsd_nat_target::debug_regs_probed;
+ 
+ /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
+    for all registers.  */
+@@ -63,9 +99,231 @@ aarch64_fbsd_nat_target::store_registers (struct regcache *regcache,
+ 				    PT_SETFPREGS, &aarch64_fbsd_fpregset);
+ }
+ 
++#ifdef HAVE_DBREG
++/* Set of threads which need to update debug registers on next resume.  */
++
++static std::unordered_set<lwpid_t> aarch64_debug_pending_threads;
++
++/* Implement the "stopped_data_address" target_ops method.  */
++
++bool
++aarch64_fbsd_nat_target::stopped_data_address (CORE_ADDR *addr_p)
++{
++  siginfo_t siginfo;
++  struct aarch64_debug_reg_state *state;
++
++  if (!fbsd_nat_get_siginfo (inferior_ptid, &siginfo))
++    return false;
++
++  /* This must be a hardware breakpoint.  */
++  if (siginfo.si_signo != SIGTRAP
++      || siginfo.si_code != TRAP_TRACE
++      || siginfo.si_trapno != EXCP_WATCHPT_EL0)
++    return false;
++
++  const CORE_ADDR addr_trap = (CORE_ADDR) siginfo.si_addr;
++
++  /* Check if the address matches any watched address.  */
++  state = aarch64_get_debug_reg_state (inferior_ptid.pid ());
++  return aarch64_stopped_data_address (state, addr_trap, addr_p);
++}
++
++/* Implement the "stopped_by_watchpoint" target_ops method.  */
++
++bool
++aarch64_fbsd_nat_target::stopped_by_watchpoint ()
++{
++  CORE_ADDR addr;
++
++  return stopped_data_address (&addr);
++}
++
++/* Implement the "stopped_by_hw_breakpoint" target_ops method.  */
++
++bool
++aarch64_fbsd_nat_target::stopped_by_hw_breakpoint ()
++{
++  siginfo_t siginfo;
++  struct aarch64_debug_reg_state *state;
++
++  if (!fbsd_nat_get_siginfo (inferior_ptid, &siginfo))
++    return false;
++
++  /* This must be a hardware breakpoint.  */
++  if (siginfo.si_signo != SIGTRAP
++      || siginfo.si_code != TRAP_TRACE
++      || siginfo.si_trapno != EXCP_WATCHPT_EL0)
++    return false;
++
++  return !stopped_by_watchpoint();
++}
++
++/* Implement the "supports_stopped_by_hw_breakpoint" target_ops method.  */
++
++bool
++aarch64_fbsd_nat_target::supports_stopped_by_hw_breakpoint ()
++{
++  return true;
++}
++
++/* Fetch the hardware debug register capability information.  */
++
++void
++aarch64_fbsd_nat_target::probe_debug_regs (int pid)
++{
++  if (!debug_regs_probed)
++    {
++      struct dbreg reg;
++
++      debug_regs_probed = true;
++      aarch64_num_bp_regs = 0;
++      aarch64_num_wp_regs = 0;
++
++      if (ptrace(PT_GETDBREGS, pid, (PTRACE_TYPE_ARG3) &reg, 0) == 0)
++	{
++	  switch (reg.db_debug_ver)
++	    {
++	    case AARCH64_DEBUG_ARCH_V8:
++	    case AARCH64_DEBUG_ARCH_V8_1:
++	    case AARCH64_DEBUG_ARCH_V8_2:
++	    case AARCH64_DEBUG_ARCH_V8_4:
++	      break;
++	    default:
++	      return;
++	    }
++
++	  aarch64_num_bp_regs = reg.db_nbkpts;
++	  if (aarch64_num_bp_regs > AARCH64_HBP_MAX_NUM)
++	    {
++	      warning (_("Unexpected number of hardware breakpoint registers"
++			 " reported by ptrace, got %d, expected %d."),
++		       aarch64_num_bp_regs, AARCH64_HBP_MAX_NUM);
++	      aarch64_num_bp_regs = AARCH64_HBP_MAX_NUM;
++	    }
++	  aarch64_num_wp_regs = reg.db_nwtpts;
++	  if (aarch64_num_wp_regs > AARCH64_HWP_MAX_NUM)
++	    {
++	      warning (_("Unexpected number of hardware watchpoint registers"
++			 " reported by ptrace, got %d, expected %d."),
++		       aarch64_num_wp_regs, AARCH64_HWP_MAX_NUM);
++	      aarch64_num_wp_regs = AARCH64_HWP_MAX_NUM;
++	    }
++	}
++    }
++}
++
++/* Implement the virtual inf_ptrace_target::post_startup_inferior method.  */
++
++void
++aarch64_fbsd_nat_target::post_startup_inferior (ptid_t ptid)
++{
++  aarch64_remove_debug_reg_state (ptid.pid ());
++  probe_debug_regs (ptid.pid ());
++  fbsd_nat_target::post_startup_inferior (ptid);
++}
++
++/* Implement the "post_attach" target_ops method.  */
++
++void
++aarch64_fbsd_nat_target::post_attach (int pid)
++{
++  aarch64_remove_debug_reg_state (pid);
++  probe_debug_regs (pid);
++  fbsd_nat_target::post_attach (pid);
++}
++
++/* Implement the virtual fbsd_nat_target::low_new_fork method.  */
++
++void
++aarch64_fbsd_nat_target::low_new_fork (ptid_t parent, pid_t child)
++{
++  struct aarch64_debug_reg_state *parent_state, *child_state;
++
++  /* If there is no parent state, no watchpoints nor breakpoints have
++     been set, so there is nothing to do.  */
++  parent_state = aarch64_lookup_debug_reg_state (parent.pid ());
++  if (parent_state == nullptr)
++    return;
++
++  /* The kernel clears debug registers in the new child process after
++     fork, but GDB core assumes the child inherits the watchpoints/hw
++     breakpoints of the parent, and will remove them all from the
++     forked off process.  Copy the debug registers mirrors into the
++     new process so that all breakpoints and watchpoints can be
++     removed together.  */
++
++  child_state = aarch64_get_debug_reg_state (child);
++  *child_state = *parent_state;
++}
++
++/* Mark debug register state "dirty" for all threads belonging to the
++   current inferior.  */
++
++void
++aarch64_notify_debug_reg_change (ptid_t ptid,
++				 int is_watchpoint, unsigned int idx)
++{
++  for (thread_info *tp : current_inferior ()->non_exited_threads ())
++    {
++      if (tp->ptid.lwp_p ())
++	aarch64_debug_pending_threads.emplace (tp->ptid.lwp ());
++    }
++}
++
++/* Implement the virtual fbsd_nat_target::low_delete_thread method.  */
++
++void
++aarch64_fbsd_nat_target::low_delete_thread (thread_info *tp)
++{
++  gdb_assert(tp->ptid.lwp_p ());
++  aarch64_debug_pending_threads.erase (tp->ptid.lwp ());
++}
++
++/* Implement the virtual fbsd_nat_target::low_prepare_to_resume method.  */
++
++void
++aarch64_fbsd_nat_target::low_prepare_to_resume (thread_info *tp)
++{
++  gdb_assert(tp->ptid.lwp_p ());
++
++  if (aarch64_debug_pending_threads.erase (tp->ptid.lwp ()) == 0)
++    return;
++
++  struct aarch64_debug_reg_state *state =
++    aarch64_lookup_debug_reg_state (tp->ptid.pid ());
++  gdb_assert(state != nullptr);
++
++  struct dbreg reg;
++  memset (&reg, 0, sizeof(reg));
++  for (int i = 0; i < aarch64_num_bp_regs; i++)
++    {
++      reg.db_breakregs[i].dbr_addr = state->dr_addr_bp[i];
++      reg.db_breakregs[i].dbr_ctrl = state->dr_ctrl_bp[i];
++    }
++  for (int i = 0; i < aarch64_num_wp_regs; i++)
++    {
++      reg.db_watchregs[i].dbw_addr = state->dr_addr_wp[i];
++      reg.db_watchregs[i].dbw_ctrl = state->dr_ctrl_wp[i];
++    }
++  if (ptrace(PT_SETDBREGS, tp->ptid.lwp (), (PTRACE_TYPE_ARG3) &reg, 0) != 0)
++    error (_("Failed to set hardware debug registers"));
++}
++#else
++/* A stub that should never be called.  */
++void
++aarch64_notify_debug_reg_change (ptid_t ptid,
++				 int is_watchpoint, unsigned int idx)
++{
++  gdb_assert (true);
++}
++#endif
++
+ void _initialize_aarch64_fbsd_nat ();
+ void
+ _initialize_aarch64_fbsd_nat ()
+ {
++#ifdef HAVE_DBREG
++  aarch64_initialize_hw_point ();
++#endif
+   add_inf_child_target (&the_aarch64_fbsd_nat_target);
+ }
+diff --git a/gdb/configure.nat b/gdb/configure.nat
+index 4f5850dd595..d219d6a960c 100644
+--- gdb/configure.nat
++++ gdb/configure.nat
+@@ -154,7 +154,8 @@ case ${gdb_host} in
+ 	case ${gdb_host_cpu} in
+ 	    aarch64)
+ 		# Host: FreeBSD/aarch64
+-		NATDEPFILES="${NATDEPFILES} aarch64-fbsd-nat.o"
++		NATDEPFILES="${NATDEPFILES} aarch64-nat.o \
++		nat/aarch64-hw-point.o aarch64-fbsd-nat.o"
+ 		LOADLIBES=
+ 		;;
+ 	    arm)
diff --git a/devel/gdb/files/commit-099fbce0acc b/devel/gdb/files/commit-099fbce0acc
new file mode 100644
index 000000000000..cdb75dee984d
--- /dev/null
+++ b/devel/gdb/files/commit-099fbce0acc
@@ -0,0 +1,114 @@
+commit 82d5c31c4fe5bb67386dc568893dc23c899ff303
+Author: John Baldwin <jhb@FreeBSD.org>
+Date:   Tue May 3 16:05:10 2022 -0700
+
+    Read the tpidruro register from NT_ARM_TLS core dump notes on FreeBSD/arm.
+    
+    (cherry picked from commit 099fbce0accf209677e041fd9dc10bcb4a5eb578)
+
+diff --git gdb/arm-fbsd-nat.c gdb/arm-fbsd-nat.c
+index 3106d73cc3a..c32924de735 100644
+--- gdb/arm-fbsd-nat.c
++++ 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 gdb/arm-fbsd-tdep.c gdb/arm-fbsd-tdep.c
+index 06745a36186..a27dfb2fb4a 100644
+--- gdb/arm-fbsd-tdep.c
++++ 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 gdb/arm-fbsd-tdep.h gdb/arm-fbsd-tdep.h
+index 633dafad75d..193eb76df3c 100644
+--- gdb/arm-fbsd-tdep.h
++++ 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 */
diff --git a/devel/gdb/files/commit-0a765c1a8e9 b/devel/gdb/files/commit-0a765c1a8e9
new file mode 100644
index 000000000000..9e90fbe417da
--- /dev/null
+++ b/devel/gdb/files/commit-0a765c1a8e9
@@ -0,0 +1,78 @@
+commit 25dc6de9343ae320e37a6b9daaf5c5fc398debae
+Author: John Baldwin <jhb@FreeBSD.org>
+Date:   Tue May 3 16:05:10 2022 -0700
+
+    Read the tpidr register from NT_ARM_TLS core dump notes on FreeBSD/Aarch64.
+    
+    (cherry picked from commit 0a765c1a8e9c59f4cd0cdaf986291f957fe6ee90)
+
+diff --git gdb/aarch64-fbsd-tdep.c gdb/aarch64-fbsd-tdep.c
+index 32f441892a8..ed1b84387f0 100644
+--- gdb/aarch64-fbsd-tdep.c
++++ 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 gdb/aarch64-fbsd-tdep.h gdb/aarch64-fbsd-tdep.h
+index fc8fbee8843..7419ea6be03 100644
+--- gdb/aarch64-fbsd-tdep.h
++++ 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;
+ 
diff --git a/devel/gdb/files/commit-1570c37c340 b/devel/gdb/files/commit-1570c37c340
new file mode 100644
index 000000000000..4457b360d751
--- /dev/null
+++ b/devel/gdb/files/commit-1570c37c340
@@ -0,0 +1,892 @@
+commit ae520e967e0ccde249b47b7cea1c557299afd7ab
+Author: John Baldwin <jhb@FreeBSD.org>
+Date:   Tue Mar 22 12:05:43 2022 -0700
+
+    aarch64: Add an aarch64_nat_target mixin class.
+    
+    This class includes platform-independent target methods for hardware
+    breakpoints and watchpoints using routines from
+    nat/aarch64-hw-point.c.
+    
+    stopped_data_address is not platform-independent since the FAR
+    register holding the address for a breakpoint hit must be fetched in a
+    platform-specific manner.  However, aarch64_stopped_data_address is
+    provided as a helper routine which performs platform-independent
+    validation given the value of the FAR register.
+    
+    For tracking the per-process debug register mirror state, use an
+    unordered_map indexed by pid as recently adopted in x86-nat.c rather
+    than a manual linked-list.
+    
+    (cherry picked from commit 1570c37c340bb9df2db2c30b437d6c30e1d75459)
+
+diff --git gdb/aarch64-linux-nat.c gdb/aarch64-linux-nat.c
+index dd072d9315e..7bb82d17cc8 100644
+--- gdb/aarch64-linux-nat.c
++++ gdb/aarch64-linux-nat.c
+@@ -27,6 +27,7 @@
+ #include "target-descriptions.h"
+ #include "auxv.h"
+ #include "gdbcmd.h"
++#include "aarch64-nat.h"
+ #include "aarch64-tdep.h"
+ #include "aarch64-linux-tdep.h"
+ #include "aarch32-linux-nat.h"
+@@ -58,7 +59,8 @@
+ #define TRAP_HWBKPT 0x0004
+ #endif
+ 
+-class aarch64_linux_nat_target final : public linux_nat_target
++class aarch64_linux_nat_target final
++  : public aarch64_nat_target<linux_nat_target>
+ {
+ public:
+   /* Add our register access methods.  */
+@@ -68,17 +70,8 @@ class aarch64_linux_nat_target final : public linux_nat_target
+   const struct target_desc *read_description () override;
+ 
+   /* Add our hardware breakpoint and watchpoint implementation.  */
+-  int can_use_hw_breakpoint (enum bptype, int, int) override;
+-  int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
+-  int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
+-  int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
+-  int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
+-			 struct expression *) override;
+-  int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
+-			 struct expression *) override;
+   bool stopped_by_watchpoint () override;
+   bool stopped_data_address (CORE_ADDR *) override;
+-  bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
+ 
+   int can_do_single_step () override;
+ 
+@@ -118,103 +111,13 @@ class aarch64_linux_nat_target final : public linux_nat_target
+ 
+ static aarch64_linux_nat_target the_aarch64_linux_nat_target;
+ 
+-/* Per-process data.  We don't bind this to a per-inferior registry
+-   because of targets like x86 GNU/Linux that need to keep track of
+-   processes that aren't bound to any inferior (e.g., fork children,
+-   checkpoints).  */
+-
+-struct aarch64_process_info
+-{
+-  /* Linked list.  */
+-  struct aarch64_process_info *next;
+-
+-  /* The process identifier.  */
+-  pid_t pid;
+-
+-  /* Copy of aarch64 hardware debug registers.  */
+-  struct aarch64_debug_reg_state state;
+-};
+-
+-static struct aarch64_process_info *aarch64_process_list = NULL;
+-
+-/* Find process data for process PID.  */
+-
+-static struct aarch64_process_info *
+-aarch64_find_process_pid (pid_t pid)
+-{
+-  struct aarch64_process_info *proc;
+-
+-  for (proc = aarch64_process_list; proc; proc = proc->next)
+-    if (proc->pid == pid)
+-      return proc;
+-
+-  return NULL;
+-}
+-
+-/* Add process data for process PID.  Returns newly allocated info
+-   object.  */
+-
+-static struct aarch64_process_info *
+-aarch64_add_process (pid_t pid)
+-{
+-  struct aarch64_process_info *proc;
+-
+-  proc = XCNEW (struct aarch64_process_info);
+-  proc->pid = pid;
+-
+-  proc->next = aarch64_process_list;
+-  aarch64_process_list = proc;
+-
+-  return proc;
+-}
+-
+-/* Get data specific info for process PID, creating it if necessary.
+-   Never returns NULL.  */
+-
+-static struct aarch64_process_info *
+-aarch64_process_info_get (pid_t pid)
+-{
+-  struct aarch64_process_info *proc;
+-
+-  proc = aarch64_find_process_pid (pid);
+-  if (proc == NULL)
+-    proc = aarch64_add_process (pid);
+-
+-  return proc;
+-}
+-
+ /* Called whenever GDB is no longer debugging process PID.  It deletes
+    data structures that keep track of debug register state.  */
+ 
+ void
+ aarch64_linux_nat_target::low_forget_process (pid_t pid)
+ {
+-  struct aarch64_process_info *proc, **proc_link;
+-
+-  proc = aarch64_process_list;
+-  proc_link = &aarch64_process_list;
+-
+-  while (proc != NULL)
+-    {
+-      if (proc->pid == pid)
+-	{
+-	  *proc_link = proc->next;
+-
+-	  xfree (proc);
+-	  return;
+-	}
+-
+-      proc_link = &proc->next;
+-      proc = *proc_link;
+-    }
+-}
+-
+-/* Get debug registers state for process PID.  */
+-
+-struct aarch64_debug_reg_state *
+-aarch64_get_debug_reg_state (pid_t pid)
+-{
+-  return &aarch64_process_info_get (pid)->state;
++  aarch64_remove_debug_reg_state (pid);
+ }
+ 
+ /* Fill GDB's register array with the general-purpose register values
+@@ -775,192 +678,12 @@ aarch64_linux_nat_target::low_siginfo_fixup (siginfo_t *native, gdb_byte *inf,
+   return false;
+ }
+ 
+-/* Returns the number of hardware watchpoints of type TYPE that we can
+-   set.  Value is positive if we can set CNT watchpoints, zero if
+-   setting watchpoints of type TYPE is not supported, and negative if
+-   CNT is more than the maximum number of watchpoints of type TYPE
+-   that we can support.  TYPE is one of bp_hardware_watchpoint,
+-   bp_read_watchpoint, bp_write_watchpoint, or bp_hardware_breakpoint.
+-   CNT is the number of such watchpoints used so far (including this
+-   one).  OTHERTYPE is non-zero if other types of watchpoints are
+-   currently enabled.  */
+-
+-int
+-aarch64_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
+-						 int cnt, int othertype)
+-{
+-  if (type == bp_hardware_watchpoint || type == bp_read_watchpoint
+-      || type == bp_access_watchpoint || type == bp_watchpoint)
+-    {
*** 5335 LINES SKIPPED ***