This is the mail archive of the gdb-patches@sourceware.cygnus.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]

[PATCH] GDB runs on Linux 2.0 again!


Hi,

I just committed the appended patch.  GDB now runs on Linux 2.0 again.
I wasn't able to run the testsuite though.  Somehow dejagnu didn't
like my Linux 2.0.32 kernel :-(.  GDB seems to work fine though.  No
regressions on Linux 2.2.14 though so I felt confident enough to check
this in.

However, I'm interested in the testsuite results on Linux 2.0.x.
Expect the following tests to fail:

FAIL: gdb.base/callfuncs.exp: call inferior func with struct - returns float
FAIL: gdb.base/callfuncs.exp: call inferior func with struct - returns double
...
FAIL: gdb.base/callfwmall.exp: call inferior func with struct - returns float
FAIL: gdb.base/callfwmall.exp: call inferior func with struct - returns double
...
FAIL: gdb.base/varargs.exp: print find_max_double(5,1.0,17.0,2.0,3.0,4.0)

The tests check the return value of these functions.  In these
particular case the return value is a floating-point value, which is
returned in one of the floating-point registers.  Since on Linux
2.0.x we cannot look at the floating-point registers, these tests
fail.

I'm also interested to see if people can still compile GDB on a system
that uses libc5.

Mark


2000-03-05  Mark Kettenis  <kettenis@gnu.org>

	Allow GDB to run on Linux 2.0 again.
	* config.in: Add HAVE_PTRACE_GETREGS.
	* configure.in: Check if <sys/ptrace.h> defines PTRACE_GETREGS.
	* configure: Regenerated.
	* config/i386/nm-linux.h (CANNOT_FETCH_REGISTER,
	CANNOT_STORE_REGISTER): New defines.
	* i386-linux-nat.c (have_ptrace_getregs): New variable.
	(PTRACE_XFER_TYPE, CANNOT_FETCH_REGISTER, fetch_register,
	old_fetch_inferior_registers, CANNOT_STORE_REGISTER,
	store_register, old_store_inferior_registers): Copied over from
	`inptrace.c' as a temporary measure.
	(fetch_regs, store_regs, fetch_fpregs, store_fpregs):
	Conditionalize on HAVE_PTRACE_GETREGS.  Define stubs if
	HAVE_PTRACE_GETREGS isn't defined.
	(fetch_regs): Reset `have_ptrace_getregs' if ptrace call fails
	with EIO.
	(fetch_inferior_registers, store_inferior_registers): Fall back on
	the method use in `infptrace.c' (by calling
	old_fetch_inferior_registers and old_store_inferior_registers) if
	`have_ptrace_getregs' isn't set.


Index: config.in
===================================================================
RCS file: /cvs/src/src/gdb/config.in,v
retrieving revision 1.2
diff -u -p -r1.2 config.in
--- config.in	2000/02/16 13:43:05	1.2
+++ config.in	2000/03/05 22:56:08
@@ -117,6 +117,9 @@
 /* Set to true if the save_state_t structure has the ss_wide member */
 #undef HAVE_STRUCT_MEMBER_SS_WIDE
 
+/* Define if <sys/ptrace.h> defines the PTRACE_GETREGS request.  */
+#undef HAVE_PTRACE_GETREGS
+
 /* Define if <sys/ptrace.h> defines the PTRACE_GETXFPREGS request.  */
 #undef HAVE_PTRACE_GETXFPREGS
 
Index: configure.in
===================================================================
RCS file: /cvs/src/src/gdb/configure.in,v
retrieving revision 1.10
diff -u -p -r1.10 configure.in
--- configure.in	2000/03/03 05:44:39	1.10
+++ configure.in	2000/03/05 22:56:09
@@ -101,6 +101,18 @@ AC_C_CONST
 AC_CHECK_FUNCS(setpgid sbrk sigaction isascii bzero bcopy btowc poll sigprocmask)
 AC_FUNC_ALLOCA
 
+dnl See if ptrace.h provides the PTRACE_GETREGS request.
+AC_MSG_CHECKING(for PTRACE_GETREGS)
+AC_CACHE_VAL(gdb_cv_have_ptrace_getregs,
+[AC_TRY_COMPILE([#include <sys/ptrace.h>],
+		[PTRACE_GETREGS;],
+		[gdb_cv_have_ptrace_getregs=yes],
+		[gdb_cv_have_ptrace_getregs=no])])
+AC_MSG_RESULT($gdb_cv_have_ptrace_getregs)
+if test $gdb_cv_have_ptrace_getregs = yes; then
+  AC_DEFINE(HAVE_PTRACE_GETREGS)
+fi
+
 dnl See if ptrace.h provides the PTRACE_GETXFPREGS request.
 dnl PTRACE_GETXFPREGS is a Cygnus invention, since we wrote our own
 dnl Linux kernel patch for SSE support.  That patch may or may not
Index: i386-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-linux-nat.c,v
retrieving revision 1.2
diff -u -p -r1.2 i386-linux-nat.c
--- i386-linux-nat.c	2000/03/05 16:39:11	1.2
+++ i386-linux-nat.c	2000/03/05 22:56:09
@@ -79,6 +79,15 @@ static int regmap[] = 
 #define GETXFPREGS_SUPPLIES(regno) \
   (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
 
+/* Does the current host support the GETREGS request?  */
+int have_ptrace_getregs =
+#ifdef HAVE_PTRACE_GETREGS
+  1
+#else
+  0
+#endif
+;
+
 /* Does the current host support the GETXFPREGS request?  The header
    file may or may not define it, and even if it is defined, the
    kernel will return EIO if it's running on a pre-SSE processor.
@@ -103,6 +112,157 @@ int have_ptrace_getxfpregs =
 ;
 
 
+/* FIXME: kettenis/2000-03-05: This duplicates code from `inptrace.c'.
+   The problem is that we define FETCH_INFERIOR_REGISTERS since we
+   want to use our own versions of {fetch,store}_inferior_registers
+   that use the GETREGS request.  This means that the code in
+   `infptrace.c' is #ifdef'd out.  But we need to fall back on that
+   code when GDB is running on top of a kernel that doesn't support
+   the GETREGS request.  I want to avoid changing `infptrace.c' right
+   now.  */
+
+/* Default the type of the ptrace transfer to int.  */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE int
+#endif
+
+/* Registers we shouldn't try to fetch.  */
+#if !defined (CANNOT_FETCH_REGISTER)
+#define CANNOT_FETCH_REGISTER(regno) 0
+#endif
+
+/* Fetch one register.  */
+
+static void
+fetch_register (regno)
+     int regno;
+{
+  /* This isn't really an address.  But ptrace thinks of it as one.  */
+  CORE_ADDR regaddr;
+  char mess[128];		/* For messages */
+  register int i;
+  unsigned int offset;		/* Offset of registers within the u area.  */
+  char buf[MAX_REGISTER_RAW_SIZE];
+  int tid;
+
+  if (CANNOT_FETCH_REGISTER (regno))
+    {
+      memset (buf, '\0', REGISTER_RAW_SIZE (regno));	/* Supply zeroes */
+      supply_register (regno, buf);
+      return;
+    }
+
+  /* Overload thread id onto process id */
+  if ((tid = TIDGET (inferior_pid)) == 0)
+    tid = inferior_pid;		/* no thread id, just use process id */
+
+  offset = U_REGS_OFFSET;
+
+  regaddr = register_addr (regno, offset);
+  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+    {
+      errno = 0;
+      *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
+					       (PTRACE_ARG3_TYPE) regaddr, 0);
+      regaddr += sizeof (PTRACE_XFER_TYPE);
+      if (errno != 0)
+	{
+	  sprintf (mess, "reading register %s (#%d)", 
+		   REGISTER_NAME (regno), regno);
+	  perror_with_name (mess);
+	}
+    }
+  supply_register (regno, buf);
+}
+
+/* Fetch register values from the inferior.
+   If REGNO is negative, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+old_fetch_inferior_registers (regno)
+     int regno;
+{
+  if (regno >= 0)
+    {
+      fetch_register (regno);
+    }
+  else
+    {
+      for (regno = 0; regno < ARCH_NUM_REGS; regno++)
+	{
+	  fetch_register (regno);
+	}
+    }
+}
+
+/* Registers we shouldn't try to store.  */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* Store one register. */
+
+static void
+store_register (regno)
+     int regno;
+{
+  /* This isn't really an address.  But ptrace thinks of it as one.  */
+  CORE_ADDR regaddr;
+  char mess[128];		/* For messages */
+  register int i;
+  unsigned int offset;		/* Offset of registers within the u area.  */
+  int tid;
+
+  if (CANNOT_STORE_REGISTER (regno))
+    {
+      return;
+    }
+
+  /* Overload thread id onto process id */
+  if ((tid = TIDGET (inferior_pid)) == 0)
+    tid = inferior_pid;		/* no thread id, just use process id */
+
+  offset = U_REGS_OFFSET;
+
+  regaddr = register_addr (regno, offset);
+  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+    {
+      errno = 0;
+      ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+	      *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]);
+      regaddr += sizeof (PTRACE_XFER_TYPE);
+      if (errno != 0)
+	{
+	  sprintf (mess, "writing register %s (#%d)", 
+		   REGISTER_NAME (regno), regno);
+	  perror_with_name (mess);
+	}
+    }
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is negative, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+void
+old_store_inferior_registers (regno)
+     int regno;
+{
+  if (regno >= 0)
+    {
+      store_register (regno);
+    }
+  else
+    {
+      for (regno = 0; regno < ARCH_NUM_REGS; regno++)
+	{
+	  store_register (regno);
+	}
+    }
+}
+
+
 /* Transfering the general-purpose registers between GDB, inferiors
    and core files.  */
 
@@ -158,6 +318,8 @@ fill_gregset (elf_gregset_t *gregsetp, i
     }
 }
 
+#ifdef HAVE_PTRACE_GETREGS
+
 /* Fetch all general-purpose registers from process/thread TID and
    store their values in GDB's register array.  */
 
@@ -170,6 +332,14 @@ fetch_regs (int tid)
   ret = ptrace (PTRACE_GETREGS, tid, 0, (int) &regs);
   if (ret < 0)
     {
+      if (errno == EIO)
+	{
+	  /* The kernel we're running on doesn't support the GETREGS
+             request.  Reset `have_ptrace_getregs'.  */
+	  have_ptrace_getregs = 0;
+	  return;
+	}
+
       warning ("Couldn't get registers.");
       return;
     }
@@ -203,6 +373,13 @@ store_regs (int tid)
     }
 }
 
+#else
+
+static void fetch_regs (int tid) {}
+static void store_regs (int tid) {}
+
+#endif
+
 
 /* Transfering floating-point registers between GDB, inferiors and cores.  */
 
@@ -307,6 +484,8 @@ fill_fpregset (elf_fpregset_t *fpregsetp
     }
 }
 
+#ifdef HAVE_PTRACE_GETREGS
+
 /* Fetch all floating-point registers from process/thread TID and store
    thier values in GDB's register array.  */
 
@@ -352,6 +531,13 @@ store_fpregs (int tid)
     }
 }
 
+#else
+
+static void fetch_fpregs (int tid) {}
+static void store_fpregs (int tid) {}
+
+#endif
+
 
 /* Transfering floating-point and SSE registers to and from GDB.  */
 
@@ -561,6 +747,14 @@ fetch_inferior_registers (int regno)
 {
   int tid;
 
+  /* Use the old method of peeking around in `struct user' if the
+     GETREGS request isn't available.  */
+  if (! have_ptrace_getregs)
+    {
+      old_fetch_inferior_registers (regno);
+      return;
+    }
+
   /* Linux LWP ID's are process ID's.  */
   if ((tid = TIDGET (inferior_pid)) == 0)
     tid = inferior_pid;		/* Not a threaded program.  */
@@ -572,6 +766,14 @@ fetch_inferior_registers (int regno)
   if (regno == -1)
     {
       fetch_regs (tid);
+
+      /* The call above might reset `have_ptrace_getregs'.  */
+      if (! have_ptrace_getregs)
+	{
+	  old_fetch_inferior_registers (-1);
+	  return;
+	}
+
       if (fetch_xfpregs (tid))
 	return;
       fetch_fpregs (tid);
@@ -611,6 +813,14 @@ void
 store_inferior_registers (int regno)
 {
   int tid;
+
+  /* Use the old method of poking around in `struct user' if the
+     SETREGS request isn't available.  */
+  if (! have_ptrace_getregs)
+    {
+      old_store_inferior_registers (regno);
+      return;
+    }
 
   /* Linux LWP ID's are process ID's.  */
   if ((tid = TIDGET (inferior_pid)) == 0)
Index: config/i386/nm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/nm-linux.h,v
retrieving revision 1.1.1.5
diff -u -p -r1.1.1.5 nm-linux.h
--- config/i386/nm-linux.h	1999/12/07 03:56:10	1.1.1.5
+++ config/i386/nm-linux.h	2000/03/05 22:56:09
@@ -1,5 +1,5 @@
 /* Native support for GNU/Linux, for GDB, the GNU debugger.
-   Copyright (C) 1986, 1987, 1989, 1992, 1996, 1998
+   Copyright (C) 1986, 1987, 1989, 1992, 1996, 1998, 2000
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -62,8 +62,15 @@ extern int kernel_u_size PARAMS ((void))
 #include "solib.h"		/* Support for shared libraries. */
 #endif
 
-/* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
+/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'.  */
 #define FETCH_INFERIOR_REGISTERS
+
+/* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we fall
+   back on the code `infptrace.c' (well a copy of that code in
+   `i386-linux-nat.c' for now) and we can access only the
+   general-purpose registers in that way.  */
+#define CANNOT_FETCH_REGISTER(regno) ((regno) >= NUM_GREGS)
+#define CANNOT_STORE_REGISTER(regno) CANNOT_FETCH_REGISTER (regno)
 
 extern CORE_ADDR
   i386_stopped_by_watchpoint PARAMS ((int));


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