git: 5dd228e81c1b - main - devel/gdb: kgdb: fixup aarch64 pcb/trapframe layout

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Tue, 05 Sep 2023 18:24:18 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/ports/commit/?id=5dd228e81c1bcb49e0a7c5eca3927df24a607a15

commit 5dd228e81c1bcb49e0a7c5eca3927df24a607a15
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2023-09-05 18:16:59 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2023-09-05 18:23:36 +0000

    devel/gdb: kgdb: fixup aarch64 pcb/trapframe layout
    
    base 1c1f31a5e5 and 2ecbbcc7cab altered the pcb and trapframe layouts in
    osreldate 1400084. This version of the patch is effectively extracted
    from work done by @jhb in CheriBSD's gdb fork, then ported forward to
    work with the gdb 13.x program_space_data equivalent. With
    this + D39951, I can again get a solid backtrace in recent main.
    
    While we're here, remove some special handling for kthreads not yet run,
    as the stack pointer is in-fact stored in pcb_sp in cpu_copy_thread and
    cpu_fork.  This silences the following exception:
    
    Python Exception <class 'gdb.error'>: Register 2 is not available
    
    but there's not really any effect on the end result, since the thread
    hasn't been scheduled yet.
    
    Reviewed by:    jhb
    Approved by:    jhb (maintainer)
    MFH:            2023Q3
    Differential Revision:  https://reviews.freebsd.org/D41684
---
 devel/gdb/Makefile                       |   2 +-
 devel/gdb/files/kgdb/aarch64-fbsd-kern.c | 123 ++++++++++++++++++++++++++-----
 2 files changed, 105 insertions(+), 20 deletions(-)

diff --git a/devel/gdb/Makefile b/devel/gdb/Makefile
index 378ed1e197ca..921a14b566de 100644
--- a/devel/gdb/Makefile
+++ b/devel/gdb/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	gdb
 DISTVERSION=	13.1
-PORTREVISION=	3
+PORTREVISION=	4
 CATEGORIES=	devel
 MASTER_SITES=	GNU
 
diff --git a/devel/gdb/files/kgdb/aarch64-fbsd-kern.c b/devel/gdb/files/kgdb/aarch64-fbsd-kern.c
index f2d8f6511ff7..4d813c786b52 100644
--- a/devel/gdb/files/kgdb/aarch64-fbsd-kern.c
+++ b/devel/gdb/files/kgdb/aarch64-fbsd-kern.c
@@ -41,11 +41,44 @@
 
 #include "kgdb.h"
 
+struct aarch64fbsd_info
+{
+  int osreldate;
+};
+
+/* Per-program-space data key.  */
+static const registry<program_space>::key<aarch64fbsd_info> aarch64fbsd_pspace_data;
+
+static void
+aarch64fbsd_pspace_data_cleanup (struct program_space *pspace, void *arg)
+{
+  struct aarch64fbsd_info *info = (struct aarch64fbsd_info *)arg;
+
+  xfree (info);
+}
+
+/* Get the current aarch64_fbsd data.  If none is found yet, add it
+   now.  This function always returns a valid object.  */
+
+static struct aarch64fbsd_info *
+get_aarch64fbsd_info (void)
+{
+  struct aarch64fbsd_info *info;
+
+  info = aarch64fbsd_pspace_data.get (current_program_space);
+  if (info != nullptr)
+    return info;
+
+  info = aarch64fbsd_pspace_data.emplace (current_program_space);
+
+  info->osreldate = parse_and_eval_long ("osreldate");
+  return info;
+}
+
 static const struct regcache_map_entry aarch64_fbsd_pcbmap[] =
   {
-    { 30, AARCH64_X0_REGNUM, 8 }, /* x0 ... x29 */
+    { 11, AARCH64_X0_REGNUM + 19, 8 }, /* x19 ... x29 */
     { 1, AARCH64_PC_REGNUM, 8 },
-    { 1, REGCACHE_MAP_SKIP, 8 },
     { 1, AARCH64_SP_REGNUM, 8 },
     { 0 }
   };
@@ -56,29 +89,92 @@ static const struct regset aarch64_fbsd_pcbregset =
     regcache_supply_regset, regcache_collect_regset
   };
 
+/* In kernels prior to __FreeBSD_version 1400084, struct pcb used an
+   alternate layout.  */
+
+static const struct regcache_map_entry aarch64_fbsd13_pcbmap[] =
+  {
+    { 30, AARCH64_X0_REGNUM, 8 }, /* x0 ... x29 */
+    { 1, AARCH64_PC_REGNUM, 8 },
+    { 1, REGCACHE_MAP_SKIP, 8 },
+    { 1, AARCH64_SP_REGNUM, 8 },
+    { 0 }
+  };
+
+static const struct regset aarch64_fbsd13_pcbregset =
+  {
+    aarch64_fbsd13_pcbmap,
+    regcache_supply_regset, regcache_collect_regset
+  };
+
 static void
 aarch64_fbsd_supply_pcb(struct regcache *regcache, CORE_ADDR pcb_addr)
 {
+  const struct regset *pcbregset;
+  struct aarch64fbsd_info *info = get_aarch64fbsd_info();
   gdb_byte buf[8 * 33];
 
+  if (info->osreldate >= 1400084)
+    pcbregset = &aarch64_fbsd_pcbregset;
+  else
+    pcbregset = &aarch64_fbsd13_pcbregset;
+
   if (target_read_memory (pcb_addr, buf, sizeof buf) == 0)
-    regcache_supply_regset (&aarch64_fbsd_pcbregset, regcache, -1, buf,
+    regcache_supply_regset (pcbregset, regcache, -1, buf,
 			    sizeof (buf));
 }
 
+static const struct regcache_map_entry aarch64_fbsd_trapframe_map[] =
+  {
+    { 1, AARCH64_SP_REGNUM, 0 },
+    { 1, AARCH64_LR_REGNUM, 0 },
+    { 1, AARCH64_PC_REGNUM, 0 },
+    { 1, AARCH64_CPSR_REGNUM, 0 },
+    { 1, REGCACHE_MAP_SKIP, 8 },	/* esr */
+    { 1, REGCACHE_MAP_SKIP, 8 },	/* far */
+    { 30, AARCH64_X0_REGNUM, 0 },	/* x0 ... x29 */
+    { 0 },
+  };
+
+/* In kernels prior to __FreeBSD_version 1400084, struct trapframe
+   used an alternate layout.  */
+
+static const struct regcache_map_entry aarch64_fbsd13_trapframe_map[] =
+  {
+    { 1, AARCH64_SP_REGNUM, 0 },
+    { 1, AARCH64_LR_REGNUM, 0 },
+    { 1, AARCH64_PC_REGNUM, 0 },
+    { 1, AARCH64_CPSR_REGNUM, 4 },
+    { 1, REGCACHE_MAP_SKIP, 4 },	/* esr */
+    { 30, AARCH64_X0_REGNUM, 0 },	/* x0 ... x29 */
+    { 0 },
+  };
+
 static struct trad_frame_cache *
 aarch64_fbsd_trapframe_cache (frame_info_ptr this_frame, void **this_cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct aarch64fbsd_info *info = get_aarch64fbsd_info();
   struct trad_frame_cache *cache;
   CORE_ADDR func, pc, sp;
   const char *name;
-  int i;
+  int i, tf_size;
 
   if (*this_cache != NULL)
     return ((struct trad_frame_cache *)*this_cache);
 
+  const struct regcache_map_entry *trapframe_map;
+
+  if (info->osreldate >= 1400084)
+    {
+      trapframe_map = aarch64_fbsd_trapframe_map;
+    }
+  else
+    {
+      trapframe_map = aarch64_fbsd13_trapframe_map;
+    }
+
   cache = trad_frame_cache_zalloc (this_frame);
   *this_cache = cache;
 
@@ -86,23 +182,12 @@ aarch64_fbsd_trapframe_cache (frame_info_ptr this_frame, void **this_cache)
   sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
 
   find_pc_partial_function (func, &name, NULL, NULL);
-  if (strcmp(name, "fork_trampoline") == 0 && get_frame_pc (this_frame) == func)
-    {
-      /* fork_exit hasn't been called (kthread has never run), so SP
-	 hasn't been initialized yet.  The stack pointer is stored in
-	 the X2 in the pcb.  */
-      sp = get_frame_register_unsigned (this_frame, AARCH64_X0_REGNUM + 2);
-    }
 
-  trad_frame_set_reg_addr (cache, AARCH64_SP_REGNUM, sp);
-  trad_frame_set_reg_addr (cache, AARCH64_LR_REGNUM, sp + 8);
-  trad_frame_set_reg_addr (cache, AARCH64_PC_REGNUM, sp + 16);
-  trad_frame_set_reg_addr (cache, AARCH64_CPSR_REGNUM, sp + 24);
-  for (i = 0; i < 30; i++)
-    trad_frame_set_reg_addr (cache, AARCH64_X0_REGNUM + i, sp + 32 + i * 8);
+  tf_size = regcache_map_entry_size (trapframe_map);
+  trad_frame_set_reg_regmap (cache, trapframe_map, sp, tf_size);
 
   /* Read $PC from trap frame.  */
-  pc = read_memory_unsigned_integer (sp + 16, 8, byte_order);
+  pc = read_memory_unsigned_integer (sp + 2 * 8, 8, byte_order);
 
   if (pc == 0 && strcmp(name, "fork_trampoline") == 0)
     {
@@ -112,7 +197,7 @@ aarch64_fbsd_trapframe_cache (frame_info_ptr this_frame, void **this_cache)
   else
     {
       /* Construct the frame ID using the function start.  */
-      trad_frame_set_id (cache, frame_id_build (sp + 8 * 34, func));
+      trad_frame_set_id (cache, frame_id_build (sp + tf_size, func));
     }
 
   return cache;