summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog26
-rw-r--r--gdb/amd64-nat.c144
-rw-r--r--gdb/amd64-nat.h51
-rw-r--r--gdb/amd64fbsd-nat.c104
-rw-r--r--gdb/config/i386/fbsd64.mh2
5 files changed, 278 insertions, 49 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e7d670d7bf6..4bd50aa8aac 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,31 @@
2003-08-29 Mark Kettenis <kettenis@gnu.org>
+ * amd64-nat.h: New file.
+ * amd64-nat.c: New file.
+ * amd64fbsd-nat.c: Include "amd64-nat.h".
+ (REG_ADDR, GETREGS_SUPPLIES): Remove macros.
+ (amd64fbsd32_r_reg_offset): New variable.
+ (supply_gregset): Simply call amd64_supply_native_gregset.
+ (fill_gregset): Rename `regno' to `regnum'. Simply call
+ amd64_collect_native_gregset.
+ (fill_fpregset): Rename `regno' to `regnum'.
+ (fetch_inferior_registers): Rename `regno' to `regnum'. Replace
+ usage of GETREGS_SUPPLIES with amd64_native_gregset_supplies_p.
+ Use `struct reg' and `struct fpreg' instead of `gregset_t' and
+ `fpregset_t'. Call amd64_supply_native_gregset instead of
+ supply_gregset. Call x86_64_supply_fxsave instead of
+ supply_fpregset.
+ (store_inferior_registers): Rename `regno' to `regnum'. Replace
+ usage of GETREGS_SUPPLIES with amd64_native_gregset_supplies_p.
+ Use `struct reg' and `struct fpreg' instead of `gregset_t' and
+ `fpregset_t'. Call amd64_collect_native_gregset instead of
+ fill_gregset. Call x86_64_collect_fxsave instead of
+ fill_fpregset.
+ (_initialize_am64fbsd_nat): Initialize
+ amd64_native_gregset32_reg_offset and
+ amd64_native_gregset64_reg_offset.
+ * config/i386/fbsd64.mh (NATDEPFILES): Add amd64-nat.o.
+
* regcache.c (regcache_raw_supply): Don't assert that BUF isn't a
null pointer. Fix typo in comment.
diff --git a/gdb/amd64-nat.c b/gdb/amd64-nat.c
new file mode 100644
index 00000000000..fb0efcf8dea
--- /dev/null
+++ b/gdb/amd64-nat.c
@@ -0,0 +1,144 @@
+/* Native-dependent code for AMD64.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbarch.h"
+#include "regcache.h"
+
+#include "gdb_assert.h"
+
+#include "i386-tdep.h"
+#include "x86-64-tdep.h"
+
+/* The following bits of code help with implementing debugging 32-bit
+ code natively on AMD64. The idea is to define two mappings between
+ the register number as used by GDB and the register set used by the
+ host to represent the general-purpose registers; one for 32-bit
+ code and one for 64-bit code. The mappings are specified by the
+ follwing variables and consist of an array of offsets within the
+ register set indexed by register number, and the number of
+ registers supported by the mapping. We don't need mappings for the
+ floating-point and SSE registers, since the difference between
+ 64-bit and 32-bit variants are negligable. The difference in the
+ number of SSE registers is already handled by the target code. */
+
+/* General-purpose register mapping for native 32-bit code. */
+int *amd64_native_gregset32_reg_offset;
+int amd64_native_gregset32_num_regs = I386_NUM_GREGS;
+
+/* General-purpose register mapping for native 64-bit code. */
+int *amd64_native_gregset64_reg_offset;
+int amd64_native_gregset64_num_regs = X86_64_NUM_GREGS;
+
+/* Return the offset of REGNUM within the appropriate native
+ general-purpose register set. */
+
+static int
+amd64_native_gregset_reg_offset (int regnum)
+{
+ int *reg_offset = amd64_native_gregset64_reg_offset;
+ int num_regs = amd64_native_gregset64_num_regs;
+
+ gdb_assert (regnum >= 0);
+
+ if (gdbarch_ptr_bit (current_gdbarch) == 32)
+ {
+ reg_offset = amd64_native_gregset32_reg_offset;
+ num_regs = amd64_native_gregset32_num_regs;
+ }
+
+ if (num_regs > NUM_REGS)
+ num_regs = NUM_REGS;
+
+ if (regnum < num_regs && regnum < NUM_REGS)
+ return reg_offset[regnum];
+
+ return -1;
+}
+
+/* Return whether the native general-purpose register set supplies
+ register REGNUM. */
+
+int
+amd64_native_gregset_supplies_p (int regnum)
+{
+ return (amd64_native_gregset_reg_offset (regnum) != -1);
+}
+
+
+/* Supply register REGNUM, whose contents are store in BUF, to
+ REGCACHE. If REGNUM is -1, supply all appropriate registers. */
+
+void
+amd64_supply_native_gregset (struct regcache *regcache,
+ const void *gregs, int regnum)
+{
+ const char *regs = gregs;
+ int num_regs = amd64_native_gregset64_num_regs;
+ int i;
+
+ if (gdbarch_ptr_bit (current_gdbarch) == 32)
+ num_regs = amd64_native_gregset32_num_regs;
+
+ if (num_regs > NUM_REGS)
+ num_regs = NUM_REGS;
+
+ for (i = 0; i < num_regs; i++)
+ {
+ if (regnum == -1 || regnum == i)
+ {
+ int offset = amd64_native_gregset_reg_offset (i);
+
+ if (offset != -1)
+ regcache_raw_supply (current_regcache, i, regs + offset);
+ }
+ }
+}
+
+/* Collect register REGNUM from REGCACHE and store its contents in
+ GREGS. If REGNUM is -1, collect and store all appropriate
+ registers. */
+
+void
+amd64_collect_native_gregset (const struct regcache *regcache,
+ void *gregs, int regnum)
+{
+ char *regs = gregs;
+ int num_regs = amd64_native_gregset64_num_regs;
+ int i;
+
+ if (gdbarch_ptr_bit (current_gdbarch) == 32)
+ num_regs = amd64_native_gregset32_num_regs;
+
+ if (num_regs > NUM_REGS)
+ num_regs = NUM_REGS;
+
+ for (i = 0; i < num_regs; i++)
+ {
+ if (regnum == -1 || regnum == i)
+ {
+ int offset = amd64_native_gregset_reg_offset (i);
+
+ if (offset != -1)
+ regcache_raw_collect (current_regcache, i, regs + offset);
+ }
+ }
+}
diff --git a/gdb/amd64-nat.h b/gdb/amd64-nat.h
new file mode 100644
index 00000000000..e2c9379f944
--- /dev/null
+++ b/gdb/amd64-nat.h
@@ -0,0 +1,51 @@
+/* Native-dependent code for AMD64.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef AMD64_NAT_H
+#define AMD64_NAT_H 1
+
+/* General-purpose register set description for native 32-bit code. */
+extern int *amd64_native_gregset32_reg_offset;
+extern int amd64_native_gregset32_num_regs;
+
+/* General-purpose register set description for native 64-bit code. */
+extern int *amd64_native_gregset64_reg_offset;
+extern int amd64_native_gregset64_num_regs;
+
+/* Return whether the native general-purpose register set supplies
+ register REGNUM. */
+
+extern int amd64_native_gregset_supplies_p (int regnum);
+
+/* Supply register REGNUM, whose contents are store in BUF, to
+ REGCACHE. If REGNUM is -1, supply all appropriate registers. */
+
+extern void amd64_supply_native_gregset (struct regcache *regcache,
+ const void *gregs, int regnum);
+
+/* Collect register REGNUM from REGCACHE and store its contents in
+ GREGS. If REGNUM is -1, collect and store all appropriate
+ registers. */
+
+extern void amd64_collect_native_gregset (const struct regcache *regcache,
+ void *gregs, int regnum);
+
+#endif /* amd64-nat.h */
diff --git a/gdb/amd64fbsd-nat.c b/gdb/amd64fbsd-nat.c
index e90d8fac061..dee2c8dea1a 100644
--- a/gdb/amd64fbsd-nat.c
+++ b/gdb/amd64fbsd-nat.c
@@ -1,4 +1,5 @@
/* Native-dependent code for FreeBSD/amd64.
+
Copyright 2003 Free Software Foundation, Inc.
This file is part of GDB.
@@ -44,13 +45,14 @@ typedef struct fpreg fpregset_t;
#include "gregset.h"
#include "x86-64-tdep.h"
+#include "amd64-nat.h"
/* Offset to the gregset_t location where REG is stored. */
#define REG_OFFSET(reg) offsetof (gregset_t, reg)
-/* At reg_offset[REGNO] you'll find the offset to the gregset_t
- location where the GDB register REGNO is stored. Unsupported
+/* 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[] =
{
@@ -77,12 +79,27 @@ static int reg_offset[] =
-1,
-1
};
+
+
+/* Mapping between the general-purpose registers in FreeBSD/amd64
+ `struct reg' format and GDB's register cache layout for
+ FreeBSD/i386.
-#define REG_ADDR(regset, regno) ((char *) (regset) + reg_offset[regno])
+ Note that most FreeBSD/amd64 registers are 64-bit, while the
+ FreeBSD/i386 registers are all 32-bit, but since we're
+ little-endian we get away with that. */
-/* Macro to determine if a register is fetched with PT_GETREGS. */
-#define GETREGS_SUPPLIES(regno) \
- ((0 <= (regno) && (regno) < X86_64_NUM_GREGS))
+/* From <machine/reg.h>. */
+static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] =
+{
+ 14 * 8, 13 * 8, /* %eax, %ecx */
+ 12 * 8, 11 * 8, /* %edx, %ebx */
+ 20 * 8, 10 * 8, /* %esp, %ebp */
+ 9 * 8, 8 * 8, /* %esi, %edi */
+ 17 * 8, 19 * 8, /* %eip, %eflags */
+ 18 * 8, 21 * 8, /* %cs, %ss */
+ -1, -1, -1, -1 /* %ds, %es, %fs, %gs */
+};
/* Transfering the registers between GDB, inferiors and core files. */
@@ -93,29 +110,17 @@ static int reg_offset[] =
void
supply_gregset (gregset_t *gregsetp)
{
- int i;
-
- for (i = 0; i < X86_64_NUM_GREGS; i++)
- {
- if (reg_offset[i] == -1)
- supply_register (i, NULL);
- else
- supply_register (i, REG_ADDR (gregsetp, i));
- }
+ amd64_supply_native_gregset (current_regcache, gregsetp, -1);
}
-/* Fill register REGNO (if it is a general-purpose register) in
- *GREGSETPS with the value in GDB's register array. If REGNO is -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 regno)
+fill_gregset (gregset_t *gregsetp, int regnum)
{
- int i;
-
- for (i = 0; i < X86_64_NUM_GREGS; i++)
- if ((regno == -1 || regno == i) && reg_offset[i] != -1)
- regcache_collect (i, REG_ADDR (gregsetp, i));
+ amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
}
/* Fill GDB's register array with the floating-point register values
@@ -127,80 +132,80 @@ supply_fpregset (fpregset_t *fpregsetp)
x86_64_supply_fxsave ((const char *) fpregsetp, -1);
}
-/* Fill register REGNO (if it is a floating-point register) in
- *FPREGSETP with the value in GDB's register array. If REGNO is -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 regno)
+fill_fpregset (fpregset_t *fpregsetp, int regnum)
{
- x86_64_fill_fxsave ((char *) fpregsetp, regno);
+ x86_64_fill_fxsave ((char *) fpregsetp, regnum);
}
-/* Fetch register REGNO from the inferior. If REGNO is -1, do this
+/* 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 regno)
+fetch_inferior_registers (int regnum)
{
- if (regno == -1 || GETREGS_SUPPLIES (regno))
+ if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
{
- gregset_t gregs;
+ struct reg regs;
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
+ (PTRACE_ARG3_TYPE) &regs, 0) == -1)
perror_with_name ("Couldn't get registers");
- supply_gregset (&gregs);
- if (regno != -1)
+ amd64_supply_native_gregset (current_regcache, &regs, -1);
+ if (regnum != -1)
return;
}
- if (regno == -1 || regno >= FP0_REGNUM)
+ if (regnum == -1 || regnum >= FP0_REGNUM)
{
- fpregset_t fpregs;
+ 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");
- supply_fpregset (&fpregs);
+ x86_64_supply_fxsave ((const char *) &fpregs, -1);
}
}
-/* Store register REGNO back into the inferior. If REGNO is -1, do
+/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers (including the floating point registers). */
void
-store_inferior_registers (int regno)
+store_inferior_registers (int regnum)
{
- if (regno == -1 || GETREGS_SUPPLIES (regno))
+ if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
{
- gregset_t gregs;
+ struct reg regs;
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
+ (PTRACE_ARG3_TYPE) &regs, 0) == -1)
perror_with_name ("Couldn't get registers");
- fill_gregset (&gregs, regno);
+ amd64_collect_native_gregset (current_regcache, &regs, regnum);
if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
+ (PTRACE_ARG3_TYPE) &regs, 0) == -1)
perror_with_name ("Couldn't write registers");
- if (regno != -1)
+ if (regnum != -1)
return;
}
- if (regno == -1 || regno >= FP0_REGNUM)
+ if (regnum == -1 || regnum >= FP0_REGNUM)
{
- fpregset_t fpregs;
+ 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");
- fill_fpregset (&fpregs, regno);
+ x86_64_fill_fxsave ((char *) &fpregs, regnum);
if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
@@ -217,6 +222,9 @@ _initialize_am64fbsd_nat (void)
{
int offset;
+ amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
+ amd64_native_gregset64_reg_offset = reg_offset;
+
/* To support the recognition of signal handlers, i386bsd-tdep.c
hardcodes some constants. Inclusion of this file means that we
are compiling a native debugger, which means that we can use the
diff --git a/gdb/config/i386/fbsd64.mh b/gdb/config/i386/fbsd64.mh
index a1a79a33499..7e42aaa2cd6 100644
--- a/gdb/config/i386/fbsd64.mh
+++ b/gdb/config/i386/fbsd64.mh
@@ -4,4 +4,4 @@ XM_FILE= xm-i386.h
NAT_FILE= nm-fbsd64.h
# NOTE: Do not spread NATDEPFILES over several lines - it hurts BSD make.
-NATDEPFILES= fork-child.o infptrace.o inftarg.o solib.o solib-svr4.o solib-legacy.o corelow.o core-regset.o amd64fbsd-nat.o gcore.o fbsd-proc.o
+NATDEPFILES= fork-child.o infptrace.o inftarg.o solib.o solib-svr4.o solib-legacy.o corelow.o core-regset.o amd64-nat.o amd64fbsd-nat.o gcore.o fbsd-proc.o