[5/8] Use register maps for gp regsets on FreeBSD/x86 core dumps.

Message ID 20210714140741.6460-6-jhb@FreeBSD.org
State New
Headers show
Series
  • Switch FreeBSD x86 to using register maps for GP registers
Related show

Commit Message

John Baldwin July 14, 2021, 2:07 p.m.
In particular, this permits reporting the value of the $ds, $es, $fs,
and $gs segment registers from amd64 core dumps since they are stored
as 16-bit values rather than the 32-bit size assumed by i386_gregset.
---
 gdb/amd64-fbsd-tdep.c | 89 +++++++++++++++++++++++--------------------
 gdb/i386-fbsd-tdep.c  | 58 +++++++++++++++++++---------
 2 files changed, 87 insertions(+), 60 deletions(-)

-- 
2.31.1

Patch

diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c
index e8ad246f61..b52fc6d431 100644
--- a/gdb/amd64-fbsd-tdep.c
+++ b/gdb/amd64-fbsd-tdep.c
@@ -32,6 +32,51 @@ 
 #include "solib-svr4.h"
 #include "inferior.h"
 
+/* The general-purpose regset consists of 22 64-bit slots, most of
+   which contain individual registers, but a few contain multiple
+   16-bit segment registers.  */
+#define AMD64_FBSD_SIZEOF_GREGSET	(22 * 8)
+
+/* Register maps.  */
+
+static const struct regcache_map_entry amd64_fbsd_gregmap[] =
+{
+  { 1, AMD64_R15_REGNUM, 0 },
+  { 1, AMD64_R14_REGNUM, 0 },
+  { 1, AMD64_R13_REGNUM, 0 },
+  { 1, AMD64_R12_REGNUM, 0 },
+  { 1, AMD64_R11_REGNUM, 0 },
+  { 1, AMD64_R10_REGNUM, 0 },
+  { 1, AMD64_R9_REGNUM, 0 },
+  { 1, AMD64_R8_REGNUM, 0 },
+  { 1, AMD64_RDI_REGNUM, 0 },
+  { 1, AMD64_RSI_REGNUM, 0 },
+  { 1, AMD64_RBP_REGNUM, 0 },
+  { 1, AMD64_RBX_REGNUM, 0 },
+  { 1, AMD64_RDX_REGNUM, 0 },
+  { 1, AMD64_RCX_REGNUM, 0 },
+  { 1, AMD64_RAX_REGNUM, 0 },
+  { 1, REGCACHE_MAP_SKIP, 4 },	/* trapno */
+  { 1, AMD64_FS_REGNUM, 2 },
+  { 1, AMD64_GS_REGNUM, 2 },
+  { 1, REGCACHE_MAP_SKIP, 4 },	/* err */
+  { 1, AMD64_ES_REGNUM, 2 },
+  { 1, AMD64_DS_REGNUM, 2 },
+  { 1, AMD64_RIP_REGNUM, 0 },
+  { 1, AMD64_CS_REGNUM, 8 },
+  { 1, AMD64_EFLAGS_REGNUM, 8 },
+  { 1, AMD64_RSP_REGNUM, 0 },
+  { 1, AMD64_SS_REGNUM, 8 },
+  { 0 }
+};
+
+/* Register set definitions.  */
+
+const struct regset amd64_fbsd_gregset =
+{
+  amd64_fbsd_gregmap, regcache_supply_regset, regcache_collect_regset
+};
+
 /* Support for signal handlers.  */
 
 /* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp
@@ -80,42 +125,6 @@  amd64fbsd_sigcontext_addr (struct frame_info *this_frame)
   return sp + 16;
 }
 
-/* FreeBSD 5.1-RELEASE or later.  */
-
-/* Mapping between the general-purpose registers in `struct reg'
-   format and GDB's register cache layout.
-
-   Note that some registers are 32-bit, but since we're little-endian
-   we get away with that.  */
-
-/* From <machine/reg.h>.  */
-static int amd64fbsd_r_reg_offset[] =
-{
-  14 * 8,			/* %rax */
-  11 * 8,			/* %rbx */
-  13 * 8,			/* %rcx */
-  12 * 8,			/* %rdx */
-  9 * 8,			/* %rsi */
-  8 * 8,			/* %rdi */
-  10 * 8,			/* %rbp */
-  20 * 8,			/* %rsp */
-  7 * 8,			/* %r8 ...  */
-  6 * 8,
-  5 * 8,
-  4 * 8,
-  3 * 8,
-  2 * 8,
-  1 * 8,
-  0 * 8,			/* ... %r15 */
-  17 * 8,			/* %rip */
-  19 * 8,			/* %eflags */
-  18 * 8,			/* %cs */
-  21 * 8,			/* %ss */
-  -1,				/* %ds */
-  -1,				/* %es */
-  -1,				/* %fs */
-  -1				/* %gs */
-};
 
 /* From <machine/signal.h>.  */
 int amd64fbsd_sc_reg_offset[] =
@@ -193,8 +202,8 @@  amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, &i386_gregset, NULL,
-      cb_data);
+  cb (".reg", AMD64_FBSD_SIZEOF_GREGSET, AMD64_FBSD_SIZEOF_GREGSET,
+      &amd64_fbsd_gregset, NULL, cb_data);
   cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, &amd64_fpregset,
       NULL, cb_data);
   cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
@@ -233,10 +242,6 @@  amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Obviously FreeBSD is BSD-based.  */
   i386bsd_init_abi (info, gdbarch);
 
-  tdep->gregset_reg_offset = amd64fbsd_r_reg_offset;
-  tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset);
-  tdep->sizeof_gregset = 22 * 8;
-
   amd64_init_abi (info, gdbarch,
 		  amd64_target_description (X86_XSTATE_SSE_MASK, true));
 
diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c
index 4d235541ea..2aeb51dbec 100644
--- a/gdb/i386-fbsd-tdep.c
+++ b/gdb/i386-fbsd-tdep.c
@@ -32,6 +32,42 @@ 
 #include "solib-svr4.h"
 #include "inferior.h"
 
+/* The general-purpose regset consists of 19 32-bit slots.  */
+#define I386_FBSD_SIZEOF_GREGSET	(19 * 4)
+
+/* Register maps.  */
+
+static const struct regcache_map_entry i386_fbsd_gregmap[] =
+{
+  { 1, I386_FS_REGNUM, 4 },
+  { 1, I386_ES_REGNUM, 4 },
+  { 1, I386_DS_REGNUM, 4 },
+  { 1, I386_EDI_REGNUM, 0 },
+  { 1, I386_ESI_REGNUM, 0 },
+  { 1, I386_EBP_REGNUM, 0 },
+  { 1, REGCACHE_MAP_SKIP, 4 },	/* isp */
+  { 1, I386_EBX_REGNUM, 0 },
+  { 1, I386_EDX_REGNUM, 0 },
+  { 1, I386_ECX_REGNUM, 0 },
+  { 1, I386_EAX_REGNUM, 0 },
+  { 1, REGCACHE_MAP_SKIP, 4 },	/* trapno */
+  { 1, REGCACHE_MAP_SKIP, 4 },	/* err */
+  { 1, I386_EIP_REGNUM, 0 },
+  { 1, I386_CS_REGNUM, 4 },
+  { 1, I386_EFLAGS_REGNUM, 0 },
+  { 1, I386_ESP_REGNUM, 0 },
+  { 1, I386_SS_REGNUM, 4 },
+  { 1, I386_GS_REGNUM, 4 },
+  { 0 }
+};
+
+/* Register set definitions.  */
+
+const struct regset i386_fbsd_gregset =
+{
+  i386_fbsd_gregmap, regcache_supply_regset, regcache_collect_regset
+};
+
 /* Support for signal handlers.  */
 
 /* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp
@@ -111,17 +147,6 @@  i386fbsd_sigtramp_p (struct frame_info *this_frame)
   return 1;
 }
 
-/* From <machine/reg.h>.  */
-static int i386fbsd_r_reg_offset[] =
-{
-  10 * 4, 9 * 4, 8 * 4, 7 * 4,	/* %eax, %ecx, %edx, %ebx */
-  16 * 4, 5 * 4,		/* %esp, %ebp */
-  4 * 4, 3 * 4,			/* %esi, %edi */
-  13 * 4, 15 * 4,		/* %eip, %eflags */
-  14 * 4, 17 * 4,		/* %cs, %ss */
-  2 * 4, 1 * 4, 0 * 4, 18 * 4	/* %ds, %es, %fs, %gs */
-};
-
 /* From <machine/signal.h>.  */
 int i386fbsd_sc_reg_offset[] =
 {
@@ -229,8 +254,8 @@  i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, &i386_gregset, NULL,
-      cb_data);
+  cb (".reg", I386_FBSD_SIZEOF_GREGSET, I386_FBSD_SIZEOF_GREGSET,
+      &i386_fbsd_gregset, NULL, cb_data);
   cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, &i386_fpregset,
       NULL, cb_data);
 
@@ -276,11 +301,8 @@  i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Obviously FreeBSD is BSD-based.  */
   i386bsd_init_abi (info, gdbarch);
 
-  /* FreeBSD has a different `struct reg', and reserves some space for
-     its FPU emulator in `struct fpreg'.  */
-  tdep->gregset_reg_offset = i386fbsd_r_reg_offset;
-  tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset);
-  tdep->sizeof_gregset = 19 * 4;
+  /* FreeBSD reserves some space for its FPU emulator in
+     `struct fpreg'.  */
   tdep->sizeof_fpregset = 176;
 
   /* FreeBSD uses -freg-struct-return by default.  */