This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add support for debugging 32-bit code on FreeBSD/amd64


The attached patch implements support for debugging 32-bit code on
FreeBSD/amd64.  The re-usable components are in a new file
amd64-nat.c, which comes with an accompanying header file.  Later
today I'll add support for Linux x86-64 that uses these re-usable
components.

Checked in.

Mark

Index: ChangeLog
from  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.

 
Index: amd64-nat.c
===================================================================
RCS file: amd64-nat.c
diff -N amd64-nat.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ amd64-nat.c 29 Aug 2003 13:52:28 -0000
@@ -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);
+	}
+    }
+}
Index: amd64-nat.h
===================================================================
RCS file: amd64-nat.h
diff -N amd64-nat.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ amd64-nat.h 29 Aug 2003 13:52:28 -0000
@@ -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 */
Index: amd64fbsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/amd64fbsd-nat.c,v
retrieving revision 1.3
diff -u -p -r1.3 amd64fbsd-nat.c
--- amd64fbsd-nat.c 23 Aug 2003 13:58:18 -0000 1.3
+++ amd64fbsd-nat.c 29 Aug 2003 13:52:28 -0000
@@ -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
 };
+
 
-#define REG_ADDR(regset, regno) ((char *) (regset) + reg_offset[regno])
-
-/* Macro to determine if a register is fetched with PT_GETREGS.  */
-#define GETREGS_SUPPLIES(regno) \
-  ((0 <= (regno) && (regno) < X86_64_NUM_GREGS))
+/* Mapping between the general-purpose registers in FreeBSD/amd64
+   `struct reg' format and GDB's register cache layout for
+   FreeBSD/i386.
+
+   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.  */
+
+/* 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)
@@ -216,6 +221,9 @@ void
 _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
Index: config/i386/fbsd64.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/fbsd64.mh,v
retrieving revision 1.1
diff -u -p -r1.1 fbsd64.mh
--- config/i386/fbsd64.mh 13 Jul 2003 16:15:59 -0000 1.1
+++ config/i386/fbsd64.mh 29 Aug 2003 13:52:29 -0000
@@ -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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]