[PATCH] FreeBSD/i386 ELF support.

Mark Kettenis kettenis@wins.uva.nl
Wed May 24 15:47:00 GMT 2000


FYI, I checked in the FreeBSD/i386 ELF support.  This should work on
FreeBSD 2.2 and up.  On systems where ELF is the default (e.g. 3.0 and
up) support for ELF shared libraries is included by default (and a.out
shared libraries aren't supported).  On a.out systems the old shared
library code is used (and ELF shared libraries aren't supported), but
I haven't tested this.  Defining FREEBSD_AOUT on an ELF system should
give you a GDB with support for a.out shared libraries (but again this
isn't tested).  GDB also supports ELF core dumps now.  I'll add some
blurp to the NEWS file for this.

GDB won't compile on FreeBSD releases before 2.2 now.  I'll try to fix
this if I can.  I'll add something to the TODO file if I can't find
the time to do it within the next week.

I did my work on FreeBSD 3.4, so I'm not entirely sure if it works
correctly on other releases.  Testing on other systems would be
welcome.  Running the testsuite with the system compiler on FreeBSD
3.4 (which is gcc 2.7.2.3) gives a lot of warnings, but apparently
most of these are related to compiler bugs.  Using gcc 2.8.1 from the
ports collection gives only 25 unexpected failures right now.

Mark


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

	Add support for FreeBSD/i386 ELF.
	* i386bsd-nat.c: New file.
	* config/i386/tm-fbsd.h (HAVE_I387_REGS): Define.
	Include "i386/tm-i386.h" instead of "i386/tm-i386b.h".
	(NUM_REGS): Remove redefinition.
	(USE_STRUCT_CONVENTION): Define.
	(i386_float_info): Remove prototype.
	(FLOAT_INFO): Remove define.
	(JB_ELEMENT_SIZE): Define to 4.
	(JB_PC): Define to 0.
	(GET_LONGJMP_TARGET): Define.
	(SIGTRAMP_START, SIGTRAMP_END): Define.
	(SIGCONTEXT_PC_OFFSET): Define.
	(IN_SOLIB_CALL_TRAMPOLINE): Only define if !SVR4_SHARED_LIBS
	* config/i386/nm-fbsd.h (PTRACE_ARG3_TYPE): Define to caddr_t.
	(FETCH_INFERIOR_REGISTERS): Define.
	(ATTACH_DETACH): Define.
	(kernel_u_size): Remove PARAMS.
	(register_u_addr): Use CORE_ADDR in prototype where appropriate.
	Remove PARAMS.
	(SVR4_SHARED_LIBS) [FREEBSD_ELF || __ELF__ && !FREEBSD_AOUT]:
	Define.
	[SVR4_SHARED_LIBS]: Include "elf/common.h".
	Only define aliases for struct members from <link.h> if
	!SVR4_SHARED_LIBS.
	* config/i386/xm-fbsd.h: New file.
	* config/i386/fbsd.mt (TDEPFILES): Remove solib.o.
	* config/i386/fbsd.mh (NATDEPFILES): Remove i386b-nat.o.  Add
	core-regset.o i387-nat.o i386bsd-nat.o.



--- /dev/null	Thu Feb 19 16:30:24 1998
+++ i386bsd-nat.c	Mon May 22 22:04:22 2000
@@ -0,0 +1,238 @@
+/* Native-dependent code for modern i386 BSD's.
+   Copyright (C) 2000 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 "inferior.h"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.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
+
+/* In older BSD versions we cannot get at some of the segment
+   registers.  FreeBSD for example didn't support the %fs and %gs
+   registers until the 3.0 release.  We have autoconf checks for their
+   presence, and deal gracefully with their absence.  */
+
+/* Registers we shouldn't try to fetch.  */
+#if !defined (CANNOT_FETCH_REGISTER)
+#define CANNOT_FETCH_REGISTER(regno) cannot_fetch_register (regno)
+#endif
+
+/* Registers we shouldn't try to store.  */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) CANNOT_FETCH_REGISTER (regno)
+#endif
+
+/* 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
+   registers are marked with `-1'.  */
+static int reg_offset[] =
+{
+  REG_OFFSET (r_eax),
+  REG_OFFSET (r_ecx),
+  REG_OFFSET (r_edx),
+  REG_OFFSET (r_edx),
+  REG_OFFSET (r_esp),
+  REG_OFFSET (r_ebp),
+  REG_OFFSET (r_esi),
+  REG_OFFSET (r_edi),
+  REG_OFFSET (r_eip),
+  REG_OFFSET (r_eflags),
+  REG_OFFSET (r_cs),
+  REG_OFFSET (r_ss),
+  REG_OFFSET (r_ds),
+  REG_OFFSET (r_es),
+#ifdef HAVE_R_FS
+  REG_OFFSET (r_fs),
+#else
+  -1,
+#endif
+#ifdef HAVE_R_GS
+  REG_OFFSET (r_gs)
+#else
+  -1
+#endif
+};
+
+#define REG_ADDR(regset, regno) ((char *) (regset) + reg_offset[regno])
+
+/* Return nonzero if we shouldn't try to fetch register REGNO.  */
+
+static int
+cannot_fetch_register (int regno)
+{
+  return (reg_offset[regno] == -1);
+}
+
+
+/* Transfering the registers between GDB, inferiors and core files.  */
+
+/* Fill GDB's register array with the genereal-purpose register values
+   in *GREGSETP.  */
+
+void
+supply_gregset (gregset_t *gregsetp)
+{
+  char buf[MAX_REGISTER_RAW_SIZE];
+  int i;
+
+  for (i = 0; i < NUM_GREGS; i++)
+    {
+      if (CANNOT_FETCH_REGISTER (i))
+	{
+	  memset (buf, 0, REGISTER_RAW_SIZE (i));
+	  supply_register (i, buf);
+	}
+      else
+	supply_register (i, REG_ADDR (gregsetp, i));
+    }
+}
+
+/* Fill register REGNO (if it is a general-purpose register) in
+   *GREGSETPS with the value in GDB's register array.  If REGNO is -1,
+   do this for all registers.  */
+
+void
+fill_gregset (gregset_t *gregsetp, int regno)
+{
+  int i;
+
+  for (i = 0; i < NUM_GREGS; i++)
+    if ((regno == -1 || regno == i) && ! CANNOT_STORE_REGISTER (i))
+      memcpy (REG_ADDR (gregsetp, i), &registers[REGISTER_BYTE (regno)],
+	      REGISTER_RAW_SIZE (i));
+}
+
+#include "i387-nat.h"
+
+/* Fill GDB's register array with the floating-point register values
+   in *FPREGSETP.  */
+
+void
+supply_fpregset (fpregset_t *fpregsetp)
+{
+  i387_supply_fsave ((char *) fpregsetp);
+}
+
+/* Fill register REGNO (if it is a floating-point register) in
+   *FPREGSETP with the value in GDB's register array.  If REGNO is -1,
+   do this for all registers.  */
+
+void
+fill_fpregset (fpregset_t *fpregsetp, int regno)
+{
+  i387_fill_fsave ((char *) fpregsetp, regno);
+}
+
+/* Fetch register REGNO from the inferior.  If REGNO is -1, do this
+   for all registers (including the floating point registers).  */
+
+void
+fetch_inferior_registers (int regno)
+{
+  gregset_t gregs;
+
+  if (ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
+    perror_with_name ("Couldn't get registers");
+
+  supply_gregset (&gregs);
+
+  if (regno == -1 || regno >= FP0_REGNUM)
+    {
+      fpregset_t fpregs;
+
+      if (ptrace (PT_GETFPREGS, inferior_pid,
+		  (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+	perror_with_name ("Couldn't get floating point status");
+
+      supply_fpregset (&fpregs);
+    }
+}  
+
+/* Store register REGNO back into the inferior.  If REGNO is -1, do
+   this for all registers (including the floating point registers).  */
+
+void
+store_inferior_registers (int regno)
+{
+  gregset_t gregs;
+
+  if (ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
+    perror_with_name ("Couldn't get registers");
+
+  fill_gregset (&gregs, regno);
+
+  if (ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
+    perror_with_name ("Couldn't write registers");
+
+  if (regno == -1 || regno >= FP0_REGNUM)
+    {
+      fpregset_t fpregs;
+
+      if (ptrace (PT_GETFPREGS, inferior_pid,
+		  (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+	perror_with_name ("Couldn't get floating point status");
+
+      fill_fpregset (&fpregs, regno);
+  
+      if (ptrace (PT_SETFPREGS, inferior_pid,
+		  (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+	perror_with_name ("Couldn't write floating point status");
+    }
+}
+
+
+/* Support for the user struct.  */
+
+/* Return the address register REGNO.  BLOCKEND is the value of
+   u.u_ar0, which should point to the registers.  */
+
+CORE_ADDR
+register_u_addr (CORE_ADDR blockend, int regno)
+{
+  return (CORE_ADDR) REG_ADDR (blockend, regno);
+}
+
+#include <sys/param.h>
+#include <sys/user.h>
+
+/* Return the size of the user struct.  */
+
+int
+kernel_u_size (void)
+{
+  return (sizeof (struct user));
+}
--- /dev/null	Thu Feb 19 16:30:24 1998
+++ config/i386/xm-fbsd.h	Mon May 22 01:10:10 2000
@@ -0,0 +1,28 @@
+/* Host-dependent definitions for FreeBSD/i386.
+   Copyright (C) 2000 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 XM_FBSD_H
+#define XM_FBSD_H
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#define HOST_LONG_DOUBLE_FORMAT &floatformat_i387_ext
+
+#endif /* XM_FBSD_H */
Index: config/i386/fbsd.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/fbsd.mh,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 fbsd.mh
--- config/i386/fbsd.mh	1999/04/16 01:34:17	1.1.1.1
+++ config/i386/fbsd.mh	2000/05/24 22:29:02
@@ -1,5 +1,6 @@
 # Host: Intel 386 running FreeBSD
 XDEPFILES= ser-tcp.o
-NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o core-aout.o i386b-nat.o
-XM_FILE= xm-i386bsd.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o solib.o \
+	corelow.o core-aout.o core-regset.o i387-nat.o i386bsd-nat.o
+XM_FILE= xm-fbsd.h
 NAT_FILE= nm-fbsd.h
Index: config/i386/fbsd.mt
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/fbsd.mt,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 fbsd.mt
--- config/i386/fbsd.mt	1999/04/16 01:34:17	1.1.1.1
+++ config/i386/fbsd.mt	2000/05/24 22:29:02
@@ -1,3 +1,3 @@
 # Target: Intel 386 running FreeBSD
-TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TDEPFILES= i386-tdep.o i387-tdep.o
 TM_FILE= tm-fbsd.h
Index: config/i386/nm-fbsd.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/nm-fbsd.h,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 nm-fbsd.h
--- config/i386/nm-fbsd.h	1999/07/07 20:12:33	1.1.1.2
+++ config/i386/nm-fbsd.h	2000/05/24 22:29:02
@@ -1,5 +1,5 @@
-/* Native-dependent definitions for Intel 386 running BSD Unix, for GDB.
-   Copyright 1986, 1987, 1989, 1992, 1996 Free Software Foundation, Inc.
+/* Native-dependent definitions for FreeBSD/i386.
+   Copyright (C) 1986, 87, 89, 92, 96, 2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -18,12 +18,26 @@
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#ifndef NM_FREEBSD_H
-#define NM_FREEBSD_H
+#ifndef NM_FBSD_H
+#define NM_FBSD_H
 
-/* Be shared lib aware */
-#include "solib.h"
+/* Type of the third argument to the `ptrace' system call.  */
+#define PTRACE_ARG3_TYPE caddr_t
 
+/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'.  */
+#define FETCH_INFERIOR_REGISTERS
+
+/* We can attach and detach.  */
+#define ATTACH_DETACH
+
+
+/* Support for the user struct.  */
+
+/* Return the size of the user struct.  */
+
+#define KERNEL_U_SIZE kernel_u_size ()
+extern int kernel_u_size (void);
+
 /* This is the amount to subtract from u.u_ar0
    to get the offset in the core file of the register values.  */
 
@@ -31,14 +45,27 @@
 #define KERNEL_U_ADDR USRSTACK
 
 #define REGISTER_U_ADDR(addr, blockend, regno) \
-	(addr) = i386_register_u_addr ((blockend),(regno));
+  (addr) = register_u_addr ((blockend), (regno))
+extern CORE_ADDR register_u_addr (CORE_ADDR blockend, int regno);
+
+
+/* Shared library support.  */
+
+/* The FreeBSD <link.h> uses the same condition to distinguish ELF
+   from a.out.  ELF implies SVR4 shared libraries.  */
+#if (defined (FREEBSD_ELF) || defined (__ELF__)) && !defined (FREEBSD_AOUT)
+#define SVR4_SHARED_LIBS
+#endif
+
+#include "solib.h"		/* Support for shared libraries. */
+#ifdef SVR4_SHARED_LIBS
+#include "elf/common.h"		/* Additional ELF shared library info. */
+#endif
 
-extern int
-i386_register_u_addr PARAMS ((int, int));
+#ifndef SVR4_SHARED_LIBS
 
-#define PTRACE_ARG3_TYPE char*
+/* Make structure definitions match up with those expected in `solib.c'.  */
 
-/* make structure definitions match up with those expected in solib.c */
 #define link_object	sod
 #define lo_name		sod_name
 #define lo_library	sod_library
@@ -90,10 +117,7 @@ i386_register_u_addr PARAMS ((int, int))
 #define ldd		d_debug
 #define ld_un		d_un
 #define ld_2		d_sdt
-
-/* Return sizeof user struct to callers in less machine dependent routines */
 
-#define KERNEL_U_SIZE kernel_u_size()
-extern int kernel_u_size PARAMS ((void));
+#endif /* !SVR4_SHARED_LIBS */
 
-#endif /* NM_FREEBSD_H */
+#endif /* NM_FBSD_H */
Index: config/i386/tm-fbsd.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-fbsd.h,v
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.3 tm-fbsd.h
--- config/i386/tm-fbsd.h	1999/07/07 20:13:00	1.1.1.3
+++ config/i386/tm-fbsd.h	2000/05/24 22:29:02
@@ -1,5 +1,5 @@
-/* Target macro definitions for i386 running FreeBSD
-   Copyright (C) 1997 Free Software Foundation, Inc.
+/* Target-dependent definitions for FreeBSD/i386.
+   Copyright (C) 1997, 2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -18,16 +18,54 @@
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include "i386/tm-i386bsd.h"
+#ifndef TM_FBSD_H
+#define TM_FBSD_H
 
+#define HAVE_I387_REGS
+#include "i386/tm-i386.h"
 
-#undef NUM_REGS
-#define NUM_REGS 14
+/* FreeBSD uses the old gcc convention for struct returns.  */
 
+#define USE_STRUCT_CONVENTION(gcc_p, type) \
+  generic_use_struct_convention (1, type)
+
 
-#undef IN_SOLIB_CALL_TRAMPOLINE
-#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) STREQ (name, "_DYNAMIC")
+/* Support for longjmp.  */
 
+/* Details about jmp_buf.  It's supposed to be an array of integers.  */
 
-extern i386_float_info ();
-#define FLOAT_INFO  i386_float_info ()
+#define JB_ELEMENT_SIZE 4	/* Size of elements in jmp_buf.  */
+#define JB_PC		0	/* Array index of saved PC.  */
+
+/* Figure out where the longjmp will land.  Store the address that
+   longjmp will jump to in *ADDR, and return non-zero if successful.  */
+
+extern int get_longjmp_target (CORE_ADDR *addr);
+#define GET_LONGJMP_TARGET(addr) get_longjmp_target (addr)
+
+
+/* Support for signal handlers.  */
+
+/* The sigtramp is above the user stack and immediately below
+   the user area.  Using constants here allows for cross debugging.
+   These are tested for FreeBSD 3.4.  */
+
+#define SIGTRAMP_START(pc)	0xbfbfdf20
+#define SIGTRAMP_END(pc)	0xbfbfdff0
+
+/* Offset to saved PC in sigcontext, from <sys/signal.h>.  */
+#define SIGCONTEXT_PC_OFFSET 20
+
+
+/* Shared library support.  */
+
+#ifndef SVR4_SHARED_LIBS
+
+/* Return non-zero if we are in a shared library trampoline code stub.  */
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \
+  (name && !strcmp(name, "_DYNAMIC"))
+
+#endif /* !SVR4_SHARED_LIBS */
+
+#endif /* TM_FBSD_H */


More information about the Gdb-patches mailing list