From a423c9f39294b5cc6f658a145f3844d19f3f3cf1 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 28 Jan 2022 11:14:37 -0800 Subject: [PATCH] Use register maps for gp regsets on FreeBSD/x86 core dumps. 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(-) diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c index 647d9d744a1..f61ca74d88a 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 . */ -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 . */ int amd64fbsd_sc_reg_offset[] = @@ -193,8 +202,8 @@ amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, { i386_gdbarch_tdep *tdep = (i386_gdbarch_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 c3f02d1d227..6d720d8377f 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 . */ -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 . */ int i386fbsd_sc_reg_offset[] = { @@ -229,8 +254,8 @@ i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, { i386_gdbarch_tdep *tdep = (i386_gdbarch_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. */ -- 2.30.2