/* Native-dependent code for FreeBSD/amd64.
- Copyright 2003 Free Software Foundation, Inc.
+ Copyright 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "inferior.h"
#include "regcache.h"
+#include "target.h"
#include "gdb_assert.h"
#include <signal.h>
#include <sys/sysctl.h>
#include <machine/reg.h>
-#ifdef HAVE_SYS_PROCFS_H
-#include <sys/procfs.h>
-#endif
-
-#ifndef HAVE_GREGSET_T
-typedef struct reg gregset_t;
-#endif
-
-#ifndef HAVE_FPREGSET_T
-typedef struct fpreg fpregset_t;
-#endif
-
-#include "gregset.h"
-#include "x86-64-tdep.h"
+#include "fbsd-nat.h"
+#include "amd64-tdep.h"
#include "amd64-nat.h"
\f
-/* Offset to the gregset_t location where REG is stored. */
-#define REG_OFFSET(reg) offsetof (gregset_t, reg)
+/* Offset in `struct reg' where MEMBER is stored. */
+#define REG_OFFSET(member) offsetof (struct reg, member)
-/* At reg_offset[REGNUM] you'll find the offset to the gregset_t
- location where the GDB register REGNUM is stored. Unsupported
- registers are marked with `-1'. */
-static int reg_offset[] =
+/* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in
+ `struct reg' location where the GDB register REGNUM is stored.
+ Unsupported registers are marked with `-1'. */
+static int amd64fbsd64_r_reg_offset[] =
{
REG_OFFSET (r_rax),
REG_OFFSET (r_rbx),
REG_OFFSET (r_r15),
REG_OFFSET (r_rip),
REG_OFFSET (r_rflags),
+ REG_OFFSET (r_cs),
+ REG_OFFSET (r_ss),
-1,
-1,
-1,
};
\f
-/* Transfering the registers between GDB, inferiors and core files. */
-
-/* Fill GDB's register array with the general-purpose register values
- in *GREGSETP. */
-
-void
-supply_gregset (gregset_t *gregsetp)
-{
- amd64_supply_native_gregset (current_regcache, gregsetp, -1);
-}
-
-/* Fill register REGNUM (if it is a general-purpose register) in
- *GREGSETPS with the value in GDB's register array. If REGNUM is -1,
- do this for all registers. */
-
-void
-fill_gregset (gregset_t *gregsetp, int regnum)
-{
- amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
-}
-
-/* Fill GDB's register array with the floating-point register values
- in *FPREGSETP. */
-
-void
-supply_fpregset (fpregset_t *fpregsetp)
-{
- x86_64_supply_fxsave ((const char *) fpregsetp, -1);
-}
-
-/* Fill register REGNUM (if it is a floating-point register) in
- *FPREGSETP with the value in GDB's register array. If REGNUM is -1,
- do this for all registers. */
-
-void
-fill_fpregset (fpregset_t *fpregsetp, int regnum)
-{
- x86_64_fill_fxsave ((char *) fpregsetp, regnum);
-}
-
-/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
- for all registers (including the floating point registers). */
-
-void
-fetch_inferior_registers (int regnum)
-{
- if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
- {
- struct reg regs;
-
- if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) ®s, 0) == -1)
- perror_with_name ("Couldn't get registers");
-
- amd64_supply_native_gregset (current_regcache, ®s, -1);
- if (regnum != -1)
- return;
- }
-
- if (regnum == -1 || regnum >= FP0_REGNUM)
- {
- struct fpreg fpregs;
+/* Support for debugging kernel virtual memory images. */
- if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
- perror_with_name ("Couldn't get floating point status");
-
- x86_64_supply_fxsave ((const char *) &fpregs, -1);
- }
-}
+#include <sys/types.h>
+#include <machine/pcb.h>
-/* Store register REGNUM back into the inferior. If REGNUM is -1, do
- this for all registers (including the floating point registers). */
+#include "bsd-kvm.h"
-void
-store_inferior_registers (int regnum)
+static int
+amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
{
- if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
- {
- struct reg regs;
-
- if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) ®s, 0) == -1)
- perror_with_name ("Couldn't get registers");
-
- amd64_collect_native_gregset (current_regcache, ®s, regnum);
-
- if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) ®s, 0) == -1)
- perror_with_name ("Couldn't write registers");
-
- if (regnum != -1)
- return;
- }
-
- if (regnum == -1 || regnum >= FP0_REGNUM)
- {
- struct fpreg fpregs;
-
- if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
- perror_with_name ("Couldn't get floating point status");
-
- x86_64_fill_fxsave ((char *) &fpregs, regnum);
-
- if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
- perror_with_name ("Couldn't write floating point status");
- }
+ /* The following is true for FreeBSD 5.2:
+
+ The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15,
+ %ds, %es, %fs and %gs. This accounts for all callee-saved
+ registers specified by the psABI and then some. Here %esp
+ contains the stack pointer at the point just after the call to
+ cpu_switch(). From this information we reconstruct the register
+ state as it would like when we just returned from cpu_switch(). */
+
+ /* The stack pointer shouldn't be zero. */
+ if (pcb->pcb_rsp == 0)
+ return 0;
+
+ pcb->pcb_rsp += 8;
+ regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip);
+ regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx);
+ regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp);
+ regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp);
+ regcache_raw_supply (regcache, 12, &pcb->pcb_r12);
+ regcache_raw_supply (regcache, 13, &pcb->pcb_r13);
+ regcache_raw_supply (regcache, 14, &pcb->pcb_r14);
+ regcache_raw_supply (regcache, 15, &pcb->pcb_r15);
+ regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds);
+ regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es);
+ regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs);
+ regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs);
+
+ return 1;
}
\f
void
_initialize_amd64fbsd_nat (void)
{
+ struct target_ops *t;
int offset;
amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
- amd64_native_gregset64_reg_offset = reg_offset;
+ amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset;
+
+ /* Add some extra features to the common *BSD/i386 target. */
+ t = amd64bsd_target ();
+ t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
+ t->to_find_memory_regions = fbsd_find_memory_regions;
+ t->to_make_corefile_notes = fbsd_make_corefile_notes;
+ add_target (t);
+
+ /* Support debugging kernel virtual memory images. */
+ bsd_kvm_add_target (amd64fbsd_supply_pcb);
/* To support the recognition of signal handlers, i386bsd-tdep.c
hardcodes some constants. Inclusion of this file means that we
pointer since these members of `struct sigcontext' are essential
for providing backtraces. */
-#define SC_RIP_OFFSET SC_REG_OFFSET[X86_64_RIP_REGNUM]
-#define SC_RSP_OFFSET SC_REG_OFFSET[X86_64_RSP_REGNUM]
-#define SC_RBP_OFFSET SC_REG_OFFSET[X86_64_RBP_REGNUM]
+#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. */
if (SC_RIP_OFFSET != offset)
{
- warning ("\
+ warning (_("\
offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
-Please report this to <bug-gdb@gnu.org>.",
+Please report this to <bug-gdb@gnu.org>."),
offset, SC_RIP_OFFSET);
}
if (SC_RSP_OFFSET != offset)
{
- warning ("\
+ warning (_("\
offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
-Please report this to <bug-gdb@gnu.org>.",
+Please report this to <bug-gdb@gnu.org>."),
offset, SC_RSP_OFFSET);
}
if (SC_RBP_OFFSET != offset)
{
- warning ("\
+ warning (_("\
offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
-Please report this to <bug-gdb@gnu.org>.",
+Please report this to <bug-gdb@gnu.org>."),
offset, SC_RBP_OFFSET);
}
len = sizeof (ps_strings);
if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
{
- amd64fbsd_sigtramp_start = ps_strings - 32;
- amd64fbsd_sigtramp_end = ps_strings;
+ amd64fbsd_sigtramp_start_addr = ps_strings - 32;
+ amd64fbsd_sigtramp_end_addr = ps_strings;
}
}
}