aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2022-01-28 11:14:37 -0800
committerJohn Baldwin <jhb@FreeBSD.org>2022-01-28 11:14:37 -0800
commit7384826ebff8a91a3f9b632e9e3982760fab966e (patch)
treec1a7e3eff5562eeec53ac44686864a8873fbfb4a
parenta423c9f39294b5cc6f658a145f3844d19f3f3cf1 (diff)
downloadgdb-7384826ebff8a91a3f9b632e9e3982760fab966e.zip
gdb-7384826ebff8a91a3f9b632e9e3982760fab966e.tar.gz
gdb-7384826ebff8a91a3f9b632e9e3982760fab966e.tar.bz2
FreeBSD x86: Use tramp-frame for signal frames.
Use a register map to describe the registers in mcontext_t as part of the signal frame as is done on several other FreeBSD arches. This permits fetching the fsbase and gsbase register values from the signal frame for both amd64 and i386 and permits fetching additional segment registers stored as 16-bit values on amd64. While signal frames on FreeBSD do contain floating point/XSAVE state, these unwinders do not attempt to supply those registers. The existing x86 signal frame uwinders do not support these registers, and the only existing functions which handle FSAVE/FXSAVE/XSAVE state all work with regcaches. In the future these unwinders could create a tempory regcache, collect floating point registers, and then supply values out of the regcache into the trad-frame.
-rw-r--r--gdb/amd64-fbsd-nat.c58
-rw-r--r--gdb/amd64-fbsd-tdep.c185
-rw-r--r--gdb/amd64-tdep.h3
-rw-r--r--gdb/i386-bsd-nat.c4
-rw-r--r--gdb/i386-fbsd-tdep.c243
-rw-r--r--gdb/i386-tdep.h1
6 files changed, 266 insertions, 228 deletions
diff --git a/gdb/amd64-fbsd-nat.c b/gdb/amd64-fbsd-nat.c
index 3c79a40..f9bd45d 100644
--- a/gdb/amd64-fbsd-nat.c
+++ b/gdb/amd64-fbsd-nat.c
@@ -213,8 +213,6 @@ void _initialize_amd64fbsd_nat ();
void
_initialize_amd64fbsd_nat ()
{
- int offset;
-
amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset;
@@ -222,60 +220,4 @@ _initialize_amd64fbsd_nat ()
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (amd64fbsd_supply_pcb);
-
- /* To support the recognition of signal handlers, i386-bsd-tdep.c
- hardcodes some constants. Inclusion of this file means that we
- are compiling a native debugger, which means that we can use the
- system header files and sysctl(3) to get at the relevant
- information. */
-
-#define SC_REG_OFFSET amd64fbsd_sc_reg_offset
-
- /* We only check the program counter, stack pointer and frame
- pointer since these members of `struct sigcontext' are essential
- for providing backtraces. */
-
-#define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM]
-#define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM]
-#define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM]
-
- /* Override the default value for the offset of the program counter
- in the sigcontext structure. */
- offset = offsetof (struct sigcontext, sc_rip);
-
- if (SC_RIP_OFFSET != offset)
- {
- warning (_("\
-offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
-Please report this to <bug-gdb@gnu.org>."),
- offset, SC_RIP_OFFSET);
- }
-
- SC_RIP_OFFSET = offset;
-
- /* Likewise for the stack pointer. */
- offset = offsetof (struct sigcontext, sc_rsp);
-
- if (SC_RSP_OFFSET != offset)
- {
- warning (_("\
-offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
-Please report this to <bug-gdb@gnu.org>."),
- offset, SC_RSP_OFFSET);
- }
-
- SC_RSP_OFFSET = offset;
-
- /* And the frame pointer. */
- offset = offsetof (struct sigcontext, sc_rbp);
-
- if (SC_RBP_OFFSET != offset)
- {
- warning (_("\
-offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
-Please report this to <bug-gdb@gnu.org>."),
- offset, SC_RBP_OFFSET);
- }
-
- SC_RBP_OFFSET = offset;
}
diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c
index f61ca74..fa36377 100644
--- a/gdb/amd64-fbsd-tdep.c
+++ b/gdb/amd64-fbsd-tdep.c
@@ -18,12 +18,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-#include "arch-utils.h"
-#include "frame.h"
-#include "gdbcore.h"
-#include "regcache.h"
#include "osabi.h"
#include "regset.h"
+#include "target.h"
+#include "trad-frame.h"
+#include "tramp-frame.h"
#include "i386-fbsd-tdep.h"
#include "gdbsupport/x86-xstate.h"
@@ -70,6 +69,49 @@ static const struct regcache_map_entry amd64_fbsd_gregmap[] =
{ 0 }
};
+/* This layout including fsbase and gsbase was adopted in FreeBSD
+ 8.0. */
+
+static const struct regcache_map_entry amd64_fbsd_mcregmap[] =
+{
+ { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_onstack */
+ { 1, AMD64_RDI_REGNUM, 0 },
+ { 1, AMD64_RSI_REGNUM, 0 },
+ { 1, AMD64_RDX_REGNUM, 0 },
+ { 1, AMD64_RCX_REGNUM, 0 },
+ { 1, AMD64_R8_REGNUM, 0 },
+ { 1, AMD64_R9_REGNUM, 0 },
+ { 1, AMD64_RAX_REGNUM, 0 },
+ { 1, AMD64_RBX_REGNUM, 0 },
+ { 1, AMD64_RBP_REGNUM, 0 },
+ { 1, AMD64_R10_REGNUM, 0 },
+ { 1, AMD64_R11_REGNUM, 0 },
+ { 1, AMD64_R12_REGNUM, 0 },
+ { 1, AMD64_R13_REGNUM, 0 },
+ { 1, AMD64_R14_REGNUM, 0 },
+ { 1, AMD64_R15_REGNUM, 0 },
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_trapno */
+ { 1, AMD64_FS_REGNUM, 2 },
+ { 1, AMD64_GS_REGNUM, 2 },
+ { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_addr */
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_flags */
+ { 1, AMD64_ES_REGNUM, 2 },
+ { 1, AMD64_DS_REGNUM, 2 },
+ { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_err */
+ { 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 },
+ { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_len */
+ { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_fpformat */
+ { 1, REGCACHE_MAP_SKIP, 8 }, /* mc_ownedfp */
+ { 64, REGCACHE_MAP_SKIP, 8 }, /* mc_fpstate */
+ { 1, AMD64_FSBASE_REGNUM, 0 },
+ { 1, AMD64_GSBASE_REGNUM, 0 },
+ { 0 }
+};
+
/* Register set definitions. */
const struct regset amd64_fbsd_gregset =
@@ -79,80 +121,86 @@ const struct regset amd64_fbsd_gregset =
/* Support for signal handlers. */
-/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp
- routine. */
+/* In a signal frame, rsp points to a 'struct sigframe' which is
+ defined as:
-static const gdb_byte amd64fbsd_sigtramp_code[] =
-{
- 0x48, 0x8d, 0x7c, 0x24, 0x10, /* lea SIGF_UC(%rsp),%rdi */
- 0x6a, 0x00, /* pushq $0 */
- 0x48, 0xc7, 0xc0, 0xa1, 0x01, 0x00, 0x00,
- /* movq $SYS_sigreturn,%rax */
- 0x0f, 0x05 /* syscall */
-};
+ struct sigframe {
+ union {
+ __siginfohandler_t *sf_action;
+ __sighandler_t *sf_handler;
+ } sf_ahu;
+ ucontext_t sf_uc;
+ ...
+ }
-static int
-amd64fbsd_sigtramp_p (struct frame_info *this_frame)
-{
- CORE_ADDR pc = get_frame_pc (this_frame);
- gdb_byte buf[sizeof amd64fbsd_sigtramp_code];
+ ucontext_t is defined as:
- if (!safe_frame_unwind_memory (this_frame, pc, buf))
- return 0;
- if (memcmp (buf, amd64fbsd_sigtramp_code, sizeof amd64fbsd_sigtramp_code)
- != 0)
- return 0;
+ struct __ucontext {
+ sigset_t uc_sigmask;
+ mcontext_t uc_mcontext;
+ ...
+ };
- return 1;
-}
+ The mcontext_t contains the general purpose register set as well
+ as the floating point or XSAVE state. */
-/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the
- address of the associated sigcontext structure. */
+/* NB: There is an 8 byte padding hole between sf_ahu and sf_uc. */
+#define AMD64_SIGFRAME_UCONTEXT_OFFSET 16
+#define AMD64_UCONTEXT_MCONTEXT_OFFSET 16
+#define AMD64_SIZEOF_MCONTEXT_T 800
-static CORE_ADDR
-amd64fbsd_sigcontext_addr (struct frame_info *this_frame)
+/* Implement the "init" method of struct tramp_frame. */
+
+static void
+amd64_fbsd_sigframe_init (const struct tramp_frame *self,
+ struct frame_info *this_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR func)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR sp;
- gdb_byte buf[8];
-
- /* The `struct sigcontext' (which really is an `ucontext_t' on
- FreeBSD/amd64) lives at a fixed offset in the signal frame. See
- <machine/sigframe.h>. */
- get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
- sp = extract_unsigned_integer (buf, 8, byte_order);
- return sp + 16;
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM);
+ CORE_ADDR mcontext_addr
+ = (sp
+ + AMD64_SIGFRAME_UCONTEXT_OFFSET
+ + AMD64_UCONTEXT_MCONTEXT_OFFSET);
+
+ trad_frame_set_reg_regmap (this_cache, amd64_fbsd_mcregmap, mcontext_addr,
+ AMD64_SIZEOF_MCONTEXT_T);
+
+ /* Don't bother with floating point or XSAVE state for now. The
+ current helper routines for parsing FXSAVE and XSAVE state only
+ work with regcaches. This could perhaps create a temporary
+ regcache, collect the register values from mc_fpstate and
+ mc_xfpustate, and then set register values in the trad_frame. */
+
+ trad_frame_set_id (this_cache, frame_id_build (sp, func));
}
-
-/* From <machine/signal.h>. */
-int amd64fbsd_sc_reg_offset[] =
+static const struct tramp_frame amd64_fbsd_sigframe =
{
- 24 + 6 * 8, /* %rax */
- 24 + 7 * 8, /* %rbx */
- 24 + 3 * 8, /* %rcx */
- 24 + 2 * 8, /* %rdx */
- 24 + 1 * 8, /* %rsi */
- 24 + 0 * 8, /* %rdi */
- 24 + 8 * 8, /* %rbp */
- 24 + 22 * 8, /* %rsp */
- 24 + 4 * 8, /* %r8 ... */
- 24 + 5 * 8,
- 24 + 9 * 8,
- 24 + 10 * 8,
- 24 + 11 * 8,
- 24 + 12 * 8,
- 24 + 13 * 8,
- 24 + 14 * 8, /* ... %r15 */
- 24 + 19 * 8, /* %rip */
- 24 + 21 * 8, /* %eflags */
- 24 + 20 * 8, /* %cs */
- 24 + 23 * 8, /* %ss */
- -1, /* %ds */
- -1, /* %es */
- -1, /* %fs */
- -1 /* %gs */
+ SIGTRAMP_FRAME,
+ 1,
+ {
+ {0x48, ULONGEST_MAX}, /* lea SIGF_UC(%rsp),%rdi */
+ {0x8d, ULONGEST_MAX},
+ {0x7c, ULONGEST_MAX},
+ {0x24, ULONGEST_MAX},
+ {0x10, ULONGEST_MAX},
+ {0x6a, ULONGEST_MAX}, /* pushq $0 */
+ {0x00, ULONGEST_MAX},
+ {0x48, ULONGEST_MAX}, /* movq $SYS_sigreturn,%rax */
+ {0xc7, ULONGEST_MAX},
+ {0xc0, ULONGEST_MAX},
+ {0xa1, ULONGEST_MAX},
+ {0x01, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x0f, ULONGEST_MAX}, /* syscall */
+ {0x05, ULONGEST_MAX},
+ {TRAMP_SENTINEL_INSN, ULONGEST_MAX}
+ },
+ amd64_fbsd_sigframe_init
};
/* Implement the core_read_description gdbarch method. */
@@ -245,10 +293,7 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
amd64_init_abi (info, gdbarch,
amd64_target_description (X86_XSTATE_SSE_MASK, true));
- tdep->sigtramp_p = amd64fbsd_sigtramp_p;
- tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
- tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
- tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
+ tramp_frame_prepend_unwinder (gdbarch, &amd64_fbsd_sigframe);
tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h
index cdc1d6f..c18766e 100644
--- a/gdb/amd64-tdep.h
+++ b/gdb/amd64-tdep.h
@@ -144,7 +144,4 @@ extern int amd64nbsd_r_reg_offset[];
/* Variables exported from amd64-obsd-tdep.c. */
extern int amd64obsd_r_reg_offset[];
-/* Variables exported from amd64-fbsd-tdep.c. */
-extern int amd64fbsd_sc_reg_offset[];
-
#endif /* amd64-tdep.h */
diff --git a/gdb/i386-bsd-nat.c b/gdb/i386-bsd-nat.c
index a04478a..c112b02 100644
--- a/gdb/i386-bsd-nat.c
+++ b/gdb/i386-bsd-nat.c
@@ -350,9 +350,7 @@ _initialize_i386bsd_nat ()
system header files and sysctl(3) to get at the relevant
information. */
-#if defined (__FreeBSD_version)
-#define SC_REG_OFFSET i386fbsd_sc_reg_offset
-#elif defined (OpenBSD)
+#if defined (OpenBSD)
#define SC_REG_OFFSET i386obsd_sc_reg_offset
#endif
diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c
index 6d720d8..6a656dd 100644
--- a/gdb/i386-fbsd-tdep.c
+++ b/gdb/i386-fbsd-tdep.c
@@ -18,11 +18,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-#include "arch-utils.h"
-#include "gdbcore.h"
#include "osabi.h"
#include "regcache.h"
#include "regset.h"
+#include "trad-frame.h"
+#include "tramp-frame.h"
#include "i386-fbsd-tdep.h"
#include "gdbsupport/x86-xstate.h"
@@ -61,6 +61,41 @@ static const struct regcache_map_entry i386_fbsd_gregmap[] =
{ 0 }
};
+/* This layout including fsbase and gsbase was adopted in FreeBSD
+ 8.0. */
+
+static const struct regcache_map_entry i386_fbsd_mcregmap[] =
+{
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_onstack */
+ { 1, I386_GS_REGNUM, 4 },
+ { 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 }, /* mc_trapno */
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_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, REGCACHE_MAP_SKIP, 4 }, /* mc_len */
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_fpformat */
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_ownedfp */
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* mc_flags */
+ { 128, REGCACHE_MAP_SKIP, 4 },/* mc_fpstate */
+ { 1, I386_FSBASE_REGNUM, 0 },
+ { 1, I386_GSBASE_REGNUM, 0 },
+ { 0 }
+};
+
/* Register set definitions. */
const struct regset i386_fbsd_gregset =
@@ -70,102 +105,127 @@ const struct regset i386_fbsd_gregset =
/* Support for signal handlers. */
-/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp
- routine. */
+/* In a signal frame, esp points to a 'struct sigframe' which is
+ defined as:
-/* FreeBSD/i386 binaries running under an amd64 kernel use a different
- trampoline This trampoline differs from the i386 kernel trampoline
- in that it omits a middle section that conditionally restores
- %gs. */
+ struct sigframe {
+ register_t sf_signum;
+ register_t sf_siginfo;
+ register_t sf_ucontext;
+ register_t sf_addr;
+ union {
+ __siginfohandler_t *sf_action;
+ __sighandler_t *sf_handler;
+ } sf_ahu;
+ ucontext_t sf_uc;
+ ...
+ }
-static const gdb_byte i386fbsd_sigtramp_start[] =
-{
- 0x8d, 0x44, 0x24, 0x20, /* lea SIGF_UC(%esp),%eax */
- 0x50 /* pushl %eax */
-};
+ ucontext_t is defined as:
-static const gdb_byte i386fbsd_sigtramp_middle[] =
-{
- 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00,
- /* testl $PSL_VM,UC_EFLAGS(%eax) */
- 0x75, 0x03, /* jne +3 */
- 0x8e, 0x68, 0x14 /* mov UC_GS(%eax),%gs */
-};
+ struct __ucontext {
+ sigset_t uc_sigmask;
+ mcontext_t uc_mcontext;
+ ...
+ };
-static const gdb_byte i386fbsd_sigtramp_end[] =
-{
- 0xb8, 0xa1, 0x01, 0x00, 0x00, /* movl $SYS_sigreturn,%eax */
- 0x50, /* pushl %eax */
- 0xcd, 0x80 /* int $0x80 */
-};
+ The mcontext_t contains the general purpose register set as well
+ as the floating point or XSAVE state. */
-/* We assume that the middle is the largest chunk below. */
-gdb_static_assert (sizeof i386fbsd_sigtramp_middle
- > sizeof i386fbsd_sigtramp_start);
-gdb_static_assert (sizeof i386fbsd_sigtramp_middle
- > sizeof i386fbsd_sigtramp_end);
+/* NB: There is a 12 byte padding hole between sf_ahu and sf_uc. */
+#define I386_SIGFRAME_UCONTEXT_OFFSET 32
+#define I386_UCONTEXT_MCONTEXT_OFFSET 16
+#define I386_SIZEOF_MCONTEXT_T 640
-static int
-i386fbsd_sigtramp_p (struct frame_info *this_frame)
+/* Implement the "init" method of struct tramp_frame. */
+
+static void
+i386_fbsd_sigframe_init (const struct tramp_frame *self,
+ struct frame_info *this_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR func)
{
- CORE_ADDR pc = get_frame_pc (this_frame);
- gdb_byte buf[sizeof i386fbsd_sigtramp_middle];
-
- /* Look for a matching start. */
- if (!safe_frame_unwind_memory (this_frame, pc,
- {buf, sizeof i386fbsd_sigtramp_start}))
- return 0;
- if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start)
- != 0)
- return 0;
-
- /* Since the end is shorter than the middle, check for a matching end
- next. */
- pc += sizeof i386fbsd_sigtramp_start;
- if (!safe_frame_unwind_memory (this_frame, pc,
- {buf, sizeof i386fbsd_sigtramp_end}))
- return 0;
- if (memcmp (buf, i386fbsd_sigtramp_end, sizeof i386fbsd_sigtramp_end) == 0)
- return 1;
-
- /* If the end didn't match, check for a matching middle. */
- if (!safe_frame_unwind_memory (this_frame, pc,
- {buf, sizeof i386fbsd_sigtramp_middle}))
- return 0;
- if (memcmp (buf, i386fbsd_sigtramp_middle, sizeof i386fbsd_sigtramp_middle)
- != 0)
- return 0;
-
- /* The middle matched, check for a matching end. */
- pc += sizeof i386fbsd_sigtramp_middle;
- if (!safe_frame_unwind_memory (this_frame, pc,
- {buf, sizeof i386fbsd_sigtramp_end}))
- return 0;
- if (memcmp (buf, i386fbsd_sigtramp_end, sizeof i386fbsd_sigtramp_end) != 0)
- return 0;
-
- return 1;
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
+ CORE_ADDR mcontext_addr
+ = (sp
+ + I386_SIGFRAME_UCONTEXT_OFFSET
+ + I386_UCONTEXT_MCONTEXT_OFFSET);
+
+ trad_frame_set_reg_regmap (this_cache, i386_fbsd_mcregmap, mcontext_addr,
+ I386_SIZEOF_MCONTEXT_T);
+
+ /* Don't bother with floating point or XSAVE state for now. The
+ current helper routines for parsing FXSAVE and XSAVE state only
+ work with regcaches. This could perhaps create a temporary
+ regcache, collect the register values from mc_fpstate and
+ mc_xfpustate, and then set register values in the trad_frame. */
+
+ trad_frame_set_id (this_cache, frame_id_build (sp, func));
}
-/* From <machine/signal.h>. */
-int i386fbsd_sc_reg_offset[] =
+static const struct tramp_frame i386_fbsd_sigframe =
{
- 20 + 11 * 4, /* %eax */
- 20 + 10 * 4, /* %ecx */
- 20 + 9 * 4, /* %edx */
- 20 + 8 * 4, /* %ebx */
- 20 + 17 * 4, /* %esp */
- 20 + 6 * 4, /* %ebp */
- 20 + 5 * 4, /* %esi */
- 20 + 4 * 4, /* %edi */
- 20 + 14 * 4, /* %eip */
- 20 + 16 * 4, /* %eflags */
- 20 + 15 * 4, /* %cs */
- 20 + 18 * 4, /* %ss */
- 20 + 3 * 4, /* %ds */
- 20 + 2 * 4, /* %es */
- 20 + 1 * 4, /* %fs */
- 20 + 0 * 4 /* %gs */
+ SIGTRAMP_FRAME,
+ 1,
+ {
+ {0x8d, ULONGEST_MAX}, /* lea SIGF_UC(%esp),%eax */
+ {0x44, ULONGEST_MAX},
+ {0x24, ULONGEST_MAX},
+ {0x20, ULONGEST_MAX},
+ {0x50, ULONGEST_MAX}, /* pushl %eax */
+ {0xf7, ULONGEST_MAX}, /* testl $PSL_VM,UC_EFLAGS(%eax) */
+ {0x40, ULONGEST_MAX},
+ {0x54, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x02, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x75, ULONGEST_MAX}, /* jne +3 */
+ {0x03, ULONGEST_MAX},
+ {0x8e, ULONGEST_MAX}, /* mov UC_GS(%eax),%gs */
+ {0x68, ULONGEST_MAX},
+ {0x14, ULONGEST_MAX},
+ {0xb8, ULONGEST_MAX}, /* movl $SYS_sigreturn,%eax */
+ {0xa1, ULONGEST_MAX},
+ {0x01, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x50, ULONGEST_MAX}, /* pushl %eax */
+ {0xcd, ULONGEST_MAX}, /* int $0x80 */
+ {0x80, ULONGEST_MAX},
+ {TRAMP_SENTINEL_INSN, ULONGEST_MAX}
+ },
+ i386_fbsd_sigframe_init
+};
+
+/* FreeBSD/i386 binaries running under an amd64 kernel use a different
+ trampoline. This trampoline differs from the i386 kernel trampoline
+ in that it omits a middle section that conditionally restores
+ %gs. */
+
+static const struct tramp_frame i386_fbsd64_sigframe =
+{
+ SIGTRAMP_FRAME,
+ 1,
+ {
+ {0x8d, ULONGEST_MAX}, /* lea SIGF_UC(%esp),%eax */
+ {0x44, ULONGEST_MAX},
+ {0x24, ULONGEST_MAX},
+ {0x20, ULONGEST_MAX},
+ {0x50, ULONGEST_MAX}, /* pushl %eax */
+ {0xb8, ULONGEST_MAX}, /* movl $SYS_sigreturn,%eax */
+ {0xa1, ULONGEST_MAX},
+ {0x01, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x00, ULONGEST_MAX},
+ {0x50, ULONGEST_MAX}, /* pushl %eax */
+ {0xcd, ULONGEST_MAX}, /* int $0x80 */
+ {0x80, ULONGEST_MAX},
+ {TRAMP_SENTINEL_INSN, ULONGEST_MAX}
+ },
+ i386_fbsd_sigframe_init
};
/* Get XSAVE extended state xcr0 from core dump. */
@@ -308,11 +368,8 @@ i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* FreeBSD uses -freg-struct-return by default. */
tdep->struct_return = reg_struct_return;
- tdep->sigtramp_p = i386fbsd_sigtramp_p;
-
- /* FreeBSD has a more complete `struct sigcontext'. */
- tdep->sc_reg_offset = i386fbsd_sc_reg_offset;
- tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset);
+ tramp_frame_prepend_unwinder (gdbarch, &i386_fbsd_sigframe);
+ tramp_frame_prepend_unwinder (gdbarch, &i386_fbsd64_sigframe);
i386_elf_init_abi (info, gdbarch);
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 62d94da..eb58dd6 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -474,7 +474,6 @@ extern int i386_mpx_enabled (void);
extern void i386bsd_init_abi (struct gdbarch_info, struct gdbarch *);
extern CORE_ADDR i386obsd_sigtramp_start_addr;
extern CORE_ADDR i386obsd_sigtramp_end_addr;
-extern int i386fbsd_sc_reg_offset[];
extern int i386obsd_sc_reg_offset[];
extern int i386bsd_sc_reg_offset[];