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/RFC]: Moving forward on the road to a truly multi-arched i386


Ok folks,

Here is the result of my work on the i386 target.  This patch
addresses several issues at ones, and the result is a mammoth patch.
I know, that's not how it should be done.  However, most of these
changes are hopelessly intertwined, or at least they appeared to be
when I was coding.  So I'd really like to ask your permission, to
check this in as it is now.  Splitting off the parts that are more or
less seperate would take a lot of time, and it would be rather
difficult to ensure that things don't get broken in the process.

To help you with reading the patch, here's something like a summary of
what it does:

* Multi-arch longjmp handling: i386_get_longjmp_target() deals with
  all i386 targets.  The details of `jmp_buf' are moved to `struct
  gdbarch_tdep', which contains the offset where one can find the PC.
  No need for JB_ELEMENT_SIZE.  A pointer is 32-bits on the i386.
  We'll need a separate function for x86_64.

* Signal handler handling: the default i386 target has the hooks for
  signal trampoline recognition and backtracing through them.  There
  are only a few targets that don't need the stuff, and those aren't
  severely penalized by this change.

* Struct convention handling: the patch introduces a new command
  "set/show struct-return".  There are three possible values, "reg"
  (corresponding to the -freg-struct-return GCC option), "pcc"
  (-fpcc-struct-return) and "default", which uses the right behaviour
  for the current target ("reg" for NetBSD a.out and FreeBSD, "pcc"
  for all others).

* Generic OS ABI handling: The patch converts the i386 target to use
  the generic OS ABI framework.

It's not really possible for me to test all possible i386
configurations, especially the native ones.  The targets that I've
threatened to obsolete probably won't work.  I'll deal with them after
I've checked this patch in.  I'm fairly confident that the following
targets will keep working:

i386-*-aout
i386-*-coff
i386-*-elf
i386-*-freebsd2
i386-*-freebsd4
i386-*-freebsdaout
i386-*-msdosdjgpp
i386-*-netbsd
i386-*-netbsdelf
i386-*-linux-gnu
i386-*-netware
i386-*-openbsd
i386-*-sysv4*

The following targets are broken in some respects

i386-*-freebsd3 [1]
i386-*-linux-gnuaout [2]
i386-*-solaris2 [3]

These won't be properly recognized.

[1] Treated as i386-*-freebsd4.  Signal handlers probably won't be
correctly recognized.

[2] Cannot (yet) be distinguished from SVR4.  Signal handlers probably
won't be recognized, SSE registers won't be there, longjmp handling
will be broken, etc.

[3] Cannot (yet) be distinguished from SVR4.  Signal handlers probably
won't be recognized.

The following targets will be definitely definitely broken:

i386-*-lynxos
i386-*-linux-gnuaout

Anyway, if I don't get any negative input in the comming week, I'll
check this in next weekend.

Mark

2002-06-09  Mark Kettenis  <kettenis@gnu.org>

	* config/i386/i386sol2.mt (TDEPFILES): Add i386-sol2-tdep.o and
	i386bsd-tdep.o.  Remove solib.o, solib-svr4.o and solib-legacy.o.
	Move these to ...
	* config/i386/i386sol2.mh: ... here.
	* config/i386/tm-i386sol2.h (STAB_REG_TO_REGNUM): Remove define.
	(sigtramp_saved_pc, I386V4_SIGTRAMP_SAVED_PC): Don't #undef.
	(SIGCONTEXT_PC_OFFSET): Remove define.
	(IN_SIGTRAMP): Remove define.
	* i386-sol2-tdep.c: New file.
	
	* config/i386/i386nw.mt (TM_FILE): Change to tm-i386.h.
	* config/i386/tm-i386nw.h: Removed.

	* config/i386/tm-fbsd.h (STAB_REG_TO_REGNUM,
	USE_STRUCT_CONVENTION): Remove defines.
	(JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines.
	(get_longjmp_target): Remove prototype.
	(IN_SIGTRAMP): Remove define.
	(i386bsd_in_sigtramp): Remove prototype.
	(i386bsd_sigtramp_start, i386bsd_sigtramp_end): Turn into a
	function.  Update comment accordingly
	(SIGTRAMP_START, SIGTRAMP): Adjust definition accordingly.
	(FRAME_SAVED_PC): Remove define.
	(i386bsd_frame_saved_pc): Remove prototype.
	* config/i386/tm-nbsd.h (JB_ELEMENT_SIZE, JB_PC,
	GET_LONGJMP_TARGET): Remove defines.
	(get_longjmp_target): Remove prototype.
	(IN_SIGTRAMP): Remove define.
	(i386bsd_in_sigtramp): Remove prototype.
	(i386bsd_sigtramp_start, i386bsd_sigtramp_end): Turn into a
	function.  Update comment accordingly
	(SIGTRAMP_START, SIGTRAMP): Adjust definition accordingly.
	(FRAME_SAVED_PC): Remove define.
	(i386bsd_frame_saved_pc): Remove prototype.
	* config/i386/tm-nbsdaout.h (i386nbsd_aout_use_struct_convention):
	Remove prototype.
	(USE_STRUCT_CONVENTION): Remove prototype.
	* i386bsd-nat.c (i386bsd_sigcontext_pc_offset): Remove
	declaration.
	(_initialize_i386bsd_nat): Revise logic to determine some
	constants at compile time when compiling a native GDB.  Warn if
	things don't match up with what we expect.
	* i386bsd-tdep.c (i386bsd_sigtramp_start, i386bsd_sigtramp_end):
	Remove variables.
	(i386bsd_in_sigtramp): Rename tp i386bsd_pc_in_sigtramp.  Rewrite
	to use date stored in `struct gdbarch_tdep'.
	(i386bsd_sigcontext_offset): Remove varaible.
	(i386bsd_sigtramp_saved_pc): Make public.  Rewrite to use data
	stored in `struct gdbarch_tdep'.
	(i386bsd_frame_saved_pc): Make static.
	(i386bsd_sigtramp_start, i386bsd_sigtramp_end): New functions.
	(i386bsd_sc_pc_offset, i386nbsd_sc_pc_offset,
	i386fbsd_sigtramp_start, i386fbsd_sigtramp_end,
	i386fbsd4_sc_pc_offset): New variables.
	(i386bsd_init_abi, i386nbsd_init_abi, i386nbsdelf_init_abi,
	i386fbsdaout_init_abi, i386fbsd_init_abi, i386fbsd4_init_abi): New
	functions.
	(i386bsd_aout_osabi_sniffer, _initialize_i386bsd_tdep): New
	functions.
	* i386fbsd-nat.c (_initialize_i386fbsd_nat): Fix type in comment.
	Modify the value of i386fbsd_sigtramp_start and
	i386fbsd_sigtramp_end instead of i386bsd_sigtramp_start and
	i386fbsd_sigtramp_end.
	* i386nbsd-tdep.c: (i386nbsd_aout_use_struct_convention): Remove
	function.

	* config/i386/tm-linux.h (I386_LINUX_ORIG_EAX_REGNUM): Move
	define to i386-linux-tdep.h.
	(NUM_REGS, MAX_NUM_REGS, REGISTER_BYTES, REGISTER_NAME,
	REGISTER_BYTE, REGISTER_RAW_SIZE, STAB_REG_TO_REGNUM): Remove
	defines.
	(i386_linux_register_name, i386_linux_register_byte,
	i386_linux_register_raw_size): Remove prototypes.
	(i386_linux_svr4_fetch_link_map_offsets): Remove prototype.
	(SVR4_FETCH_LINK_MAP_OFFSETS): Remove define.
	(IN_SIGTRAMP, FRAME_CHAIN, FRAME_SAVED_PC, SAVED_PC_AFTER_CALL,
	TARGET_WRITE_PC): Remove defines.
	(i386_linux_in_sigtramp, i386_linux_frame_chain,
	i386_linux_frame_saved_pc, i386_linux_saved_pc_after_call,
	i386_linux_write_pc): Remove prototypes.
	(JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines.
	(get_longjmp_target): Remove prototype.
	* i386-linux-tdep.h: New file.
	* i386-linux-nat.c: Include "i386-linux-tdep.h".
	* i386-linux-tdep.c: Include "i386-tdep.h" and
	"i386-linux-tdep.h".
	(i386_linux_register_name, i386_linux_register_byte,
	i386_linux_register_raw_size, i386_linux_in_sigtramp,
	i386_linux_write_pc, i386_linux_svr4_fetch_link_map_offsets):
	Make static.
	(i386_linux_init_abi): New function.
	(_initialize_i386_linux_tdep): New function.

	* config/i386/tm-i386.h (SAVED_PC_AFTER_CALL): Remove define.
	(i386_saved_pc_after_call): Remove prototype.
	(MAX_NUM_REGS): Increase to deal with Linux's orig_eax "register".
	(REGISTER_NAME, STAB_REG_TO_REGNUM, SDB_REG_TO_REGNUM,
	DWARF_REG_TO_REGNUM, DWARF2_REG_TO_REGNUM): Remove defines.
	(i386_register_name, i386_stab_reg_to_regnum,
	i386_dwarf_reg_to_regnum): Remove prototypes.
	(SIZEOF_GREGS, SIZEOF_FPU_REGS, SIZEOF_FPU_CTL_REGS,
	SIZEOF_SSE_REGS): Remove defines.
	(REGISTER_BYTES): Remove define.
	(REGISTER_BYTE, REGISTER_RAW_SIZE): Remove defines.
	(i386_register_byte, i386_register_raw_size): Remove prototypes.
	(FRAME_CHAIN, FRAME_SAVED_PC): Remove defines.
	(i386_frame_chain, i386_frame_saved_pc): Remove prototypes.
	* config/i386/tm-i386v4.h (FRAME_CHAIN_VALID): Remove define.
	(JB_ELEMENT_SIZE, JB_PC, JB_EBX, JB_ESI, JB_EDI, JB_EBP, JB_ESP,
	JB_EDX, GET_LONGJMP_TARGET): Remove defines.
	(get_longjmp_target): Remove prototype.
	(I386V4_SIGTRAMP_SAVED_PC, IN_SIGTRAMP): Remove defines.
	(sigtramp_saved_pc): Remove define.
	(i386v4_sigtramp_saved_pc): Remove prototype.
	* config/i386/tm-go32.h (FRAME_CHAIN,
	FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC): Remove defines.
	(i386go32_frame_saved_pc): Remove prototype.
	(JB_ELEMENT_SIZE, JB_PC, GET_LONGJMP_TARGET): Remove defines.
	(get_longjmp_target): Remove prototype.
	* i386-tdep.h: Include "osabi.h".
	(enum i386_abi): Removed.
	(enum struct_return): New enum.
	(struct gdbarch_tdep): Remove abi member, add osabi, jb_pc_offset,
	struct_return, sigtramp_saved_pc, sigtramp_start, sigtramp_end and
	sc_pc_offset members.
	(i386_gdbarch_register_os_abi): Remove prototype.
	(I386_NUM_GREGS, I386_NUM_FREGS, I386_NUM_XREGS,
	I386_SSE_NUM_REGS): New defines.
	(I386_SIZEOF_GREGS, I386_SIZEOF_FREGS, I386_SIZEOF_XREGS,
	I386_SSE_SIZEOF_REGS): New defines.
	(i386_register_name, i386_register_byte, i386_register_raw_size):
	New prototypes.
	(i386_elf_init_abi, i386_svr4_init_abi): New prototypes.
	(i386bsd_sigtramp_saved_pc): New prototype.
	* i386-tdep.c: Don't include "elf-bfd.h".
	(i386_stab_reg_to_regnum, i386_dwarf_reg_to_regnum,
	i386_frame_chain, i386_saved_pc_after_call): Make static.
	(i386_frame_saved_pc): Rewrite to call architecture dependent
	function to deal with signal handlers.  Make static.
	(i386go32_frame_saved_pc): Removed.
	[GET_LONGJMP_TARGET] (JB_PC, JB_ELEMENT_SIZE, get_longjmp_target):
	Removed.
	(i386_get_longjmp_target): New function.
	(default_struct_convention, pcc_struct_convention,
	reg_struct_convention, valid_conventions, struct_convention): New
	variables.
	(i386_use_struct_convention): New function.
	(i386v4_sigtramp_saved_pc): Renamed to
	i386_svr4_sigtramp_saved_pc.  Made static.  Moved.
	(i386_pc_in_sigtramp): New function.
	(i386_abi_names): Removed.
	(ABI_TAG_OS_GNU_LINUX, ABI_TAG_OS_GNU_HURD,
	ABI_TAG_OS_GNU_SOLARIS, ABI_TAG_OS_FREEBSD, ABI_TAG_OS_NETBSD):
	Removed.
	(process_note_sections, i386_elf_abi_from_note, i386_elf_abi,
	i386_gdbarch_register_os_abi): Removed.
	(struct i386_abi_handler): Removed.
	(i386_abi_handler_list): Removed.
	(i386_svr4_pc_in_sigtramp, i386_go32_pc_in_sigtramp): New
	functions.
	(i386_elf_init_abi, i386_svr4_init_abi, i386_go32_init_abi,
	i386_nw_init_abi): New functions.
	(i386_gdbarch_init): Rewritten to use generic OS ABI framework.
	Use set_gdbarch_xxx() calls instead of relying on macros for a
	number of calls.
	(i386_coff_osabi_sniffer, i386_nlm_osabi_sniffer): New functions.
	(_initialize_i386_tdep): Add new 'struct-convcention' command.
	Register the various architecture variants defined in this file.



Index: i386-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-linux-tdep.c,v
retrieving revision 1.12
diff -u -p -r1.12 i386-linux-tdep.c
--- i386-linux-tdep.c 24 Apr 2002 16:28:15 -0000 1.12
+++ i386-linux-tdep.c 9 Jun 2002 16:46:33 -0000
@@ -33,9 +33,12 @@
 
 #include "solib-svr4.h"		/* For struct link_map_offsets.  */
 
+#include "i386-tdep.h"
+#include "i386-linux-tdep.h"
+
 /* Return the name of register REG.  */
 
-char *
+static char *
 i386_linux_register_name (int reg)
 {
   /* Deal with the extra "orig_eax" pseudo register.  */
@@ -45,7 +48,7 @@ i386_linux_register_name (int reg)
   return i386_register_name (reg);
 }
 
-int
+static int
 i386_linux_register_byte (int reg)
 {
   /* Deal with the extra "orig_eax" pseudo register.  */
@@ -56,7 +59,7 @@ i386_linux_register_byte (int reg)
   return i386_register_byte (reg);
 }
 
-int
+static int
 i386_linux_register_raw_size (int reg)
 {
   /* Deal with the extra "orig_eax" pseudo register.  */
@@ -224,8 +227,8 @@ i386_linux_rt_sigtramp_start (CORE_ADDR 
 
 /* Return whether PC is in a GNU/Linux sigtramp routine.  */
 
-int
-i386_linux_in_sigtramp (CORE_ADDR pc, char *name)
+static int
+i386_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
 {
   if (name)
     return STREQ ("__restore", name) || STREQ ("__restore_rt", name);
@@ -379,7 +382,7 @@ i386_linux_saved_pc_after_call (struct f
 
 /* Set the program counter for process PTID to PC.  */
 
-void
+static void
 i386_linux_write_pc (CORE_ADDR pc, ptid_t ptid)
 {
   write_register_pid (PC_REGNUM, pc, ptid);
@@ -496,7 +499,7 @@ i386_linux_skip_solib_resolver (CORE_ADD
    from a GDB that was not built on an GNU/Linux x86 host (for cross
    debugging).  */
 
-struct link_map_offsets *
+static struct link_map_offsets *
 i386_linux_svr4_fetch_link_map_offsets (void)
 {
   static struct link_map_offsets lmo;
@@ -527,4 +530,54 @@ i386_linux_svr4_fetch_link_map_offsets (
     }
 
   return lmp;
+}
+
+
+static void
+i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* GNU/Linux uses ELF.  */
+  i386_elf_init_abi (info, gdbarch);
+
+  /* We support the SSE registers on GNU/Linux.  */
+  tdep->num_xmm_regs = I386_NUM_XREGS - 1;
+  /* set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS); */
+
+  /* Since we have the extra "orig_eax" register on GNU/Linux, we have
+     to adjust a few things.  */
+
+  set_gdbarch_write_pc (gdbarch, i386_linux_write_pc);
+  set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS + 1);
+  set_gdbarch_register_name (gdbarch, i386_linux_register_name);
+  set_gdbarch_register_bytes (gdbarch, I386_SSE_SIZEOF_REGS + 4);
+  set_gdbarch_register_byte (gdbarch, i386_linux_register_byte);
+  set_gdbarch_register_raw_size (gdbarch, i386_linux_register_raw_size);
+
+  tdep->jb_pc_offset = 20;	/* From <bits/setjmp.h>.  */
+
+  /* When the i386 Linux kernel calls a signal handler, the return
+     address points to a bit of code on the stack.  These definitions
+     are used to identify this bit of code as a signal trampoline in
+     order to support backtracing through calls to signal handlers.  */
+
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386_linux_pc_in_sigtramp);
+  set_gdbarch_frame_chain (gdbarch, i386_linux_frame_chain);
+  set_gdbarch_frame_saved_pc (gdbarch, i386_linux_frame_saved_pc);
+  set_gdbarch_saved_pc_after_call (gdbarch, i386_linux_saved_pc_after_call);
+  tdep->sigtramp_saved_pc = i386_linux_sigtramp_saved_pc;
+
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+				       i386_linux_svr4_fetch_link_map_offsets);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern void _initialize_i386_linux_tdep (void);
+
+void
+_initialize_i386_linux_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_LINUX,
+			  i386_linux_init_abi);
 }
Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.55
diff -u -p -r1.55 i386-tdep.c
--- i386-tdep.c 27 May 2002 09:17:24 -0000 1.55
+++ i386-tdep.c 9 Jun 2002 16:46:34 -0000
@@ -36,8 +36,6 @@
 #include "value.h"
 #include "gdb_assert.h"
 
-#include "elf-bfd.h"
-
 #include "i386-tdep.h"
 
 /* Names of the registers.  The first 10 registers match the register
@@ -119,7 +117,7 @@ i386_register_virtual_size (int reg)
 /* Convert stabs register number REG to the appropriate register
    number used by GDB.  */
 
-int
+static int
 i386_stab_reg_to_regnum (int reg)
 {
   /* This implements what GCC calls the "default" register map.  */
@@ -150,10 +148,10 @@ i386_stab_reg_to_regnum (int reg)
   return NUM_REGS + NUM_PSEUDO_REGS;
 }
 
-/* Convert Dwarf register number REG to the appropriate register
+/* Convert DWARF register number REG to the appropriate register
    number used by GDB.  */
 
-int
+static int
 i386_dwarf_reg_to_regnum (int reg)
 {
   /* The DWARF register numbering includes %eip and %eflags, and
@@ -466,7 +464,7 @@ i386_get_frame_setup (CORE_ADDR pc)
    frame's nominal address is the address of a 4-byte word containing
    the calling frame's address.  */
 
-CORE_ADDR
+static CORE_ADDR
 i386_frame_chain (struct frame_info *frame)
 {
   if (frame->signal_handler_caller)
@@ -493,30 +491,24 @@ i386_frameless_function_invocation (stru
 
 /* Return the saved program counter for FRAME.  */
 
-CORE_ADDR
+static CORE_ADDR
 i386_frame_saved_pc (struct frame_info *frame)
 {
-  /* FIXME: kettenis/2001-05-09: Conditionalizing the next bit of code
-     on SIGCONTEXT_PC_OFFSET and I386V4_SIGTRAMP_SAVED_PC should be
-     considered a temporary hack.  I plan to come up with something
-     better when we go multi-arch.  */
-#if defined (SIGCONTEXT_PC_OFFSET) || defined (I386V4_SIGTRAMP_SAVED_PC)
   if (frame->signal_handler_caller)
-    return sigtramp_saved_pc (frame);
-#endif
+    {
+      CORE_ADDR (*sigtramp_saved_pc) (struct frame_info *);
+      sigtramp_saved_pc = gdbarch_tdep (current_gdbarch)->sigtramp_saved_pc;
 
-  return read_memory_unsigned_integer (frame->frame + 4, 4);
-}
+      gdb_assert (sigtramp_saved_pc != NULL);
+      return sigtramp_saved_pc (frame);
+    }
 
-CORE_ADDR
-i386go32_frame_saved_pc (struct frame_info *frame)
-{
-  return read_memory_integer (frame->frame + 4, 4);
+  return read_memory_unsigned_integer (frame->frame + 4, 4);
 }
 
 /* Immediately after a function call, return the saved pc.  */
 
-CORE_ADDR
+static CORE_ADDR
 i386_saved_pc_after_call (struct frame_info *frame)
 {
   return read_memory_unsigned_integer (read_register (SP_REGNUM), 4);
@@ -834,49 +826,35 @@ i386_pop_frame (void)
 }
 
 
-#ifdef GET_LONGJMP_TARGET
-
-/* FIXME: Multi-arching does not set JB_PC and JB_ELEMENT_SIZE yet.  
-   Fill in with dummy value to enable compilation.  */
-#ifndef JB_PC
-#define JB_PC 0
-#endif /* JB_PC */
-
-#ifndef JB_ELEMENT_SIZE
-#define JB_ELEMENT_SIZE 4
-#endif /* JB_ELEMENT_SIZE */
-
 /* Figure out where the longjmp will land.  Slurp the args out of the
    stack.  We expect the first arg to be a pointer to the jmp_buf
-   structure from which we extract the pc (JB_PC) that we will land
-   at.  The pc is copied into PC.  This routine returns true on
+   structure from which we extract the address that we will land at.
+   This address is copied into PC.  This routine returns true on
    success.  */
 
-int
-get_longjmp_target (CORE_ADDR *pc)
+static int
+i386_get_longjmp_target (CORE_ADDR *pc)
 {
-  char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+  char buf[4];
   CORE_ADDR sp, jb_addr;
+  int jb_pc_offset = gdbarch_tdep (current_gdbarch)->jb_pc_offset;
 
-  sp = read_register (SP_REGNUM);
-
-  if (target_read_memory (sp + SP_ARG0,	/* Offset of first arg on stack.  */
-			  buf,
-			  TARGET_PTR_BIT / TARGET_CHAR_BIT))
+  /* If JB_PC_OFFSET is -1, we have no way to find out where the
+     longjmp will land.  */
+  if (jb_pc_offset == -1)
     return 0;
 
-  jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
-
-  if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
-			  TARGET_PTR_BIT / TARGET_CHAR_BIT))
+  sp = read_register (SP_REGNUM);
+  if (target_read_memory (sp + 4, buf, 4))
     return 0;
 
-  *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+  jb_addr = extract_address (buf, 4);
+  if (target_read_memory (jb_addr + jb_pc_offset, buf, 4))
+    return 0;
 
+  *pc = extract_address (buf, 4);
   return 1;
 }
-
-#endif /* GET_LONGJMP_TARGET */
 
 
 CORE_ADDR
@@ -1044,6 +1022,37 @@ i386_extract_struct_value_address (char 
 }
 
 
+/* This is the variable that is set with "set struct-convention", and
+   its legitimate values.  */
+static const char default_struct_convention[] = "default";
+static const char pcc_struct_convention[] = "pcc";
+static const char reg_struct_convention[] = "reg";
+static const char *valid_conventions[] =
+{
+  default_struct_convention,
+  pcc_struct_convention,
+  reg_struct_convention,
+  NULL
+};
+static const char *struct_convention = default_struct_convention;
+
+static int
+i386_use_struct_convention (int gcc_p, struct type *type)
+{
+  enum struct_return struct_return;
+
+  if (struct_convention == default_struct_convention)
+    struct_return = gdbarch_tdep (current_gdbarch)->struct_return;
+  else if (struct_convention == pcc_struct_convention)
+    struct_return = pcc_struct_return;
+  else
+    struct_return = reg_struct_return;
+
+  return generic_use_struct_convention (struct_return == reg_struct_return,
+					type);
+}
+
+
 /* Return the GDB type object for the "standard" data type of data in
    register REGNUM.  Perhaps %esi and %edi should go here, but
    potentially they could be used for things other than address.  */
@@ -1122,34 +1131,6 @@ i386_register_convert_to_raw (struct typ
 }
      
 
-#ifdef I386V4_SIGTRAMP_SAVED_PC
-/* Get saved user PC for sigtramp from the pushed ucontext on the
-   stack for all three variants of SVR4 sigtramps.  */
-
-CORE_ADDR
-i386v4_sigtramp_saved_pc (struct frame_info *frame)
-{
-  CORE_ADDR saved_pc_offset = 4;
-  char *name = NULL;
-
-  find_pc_partial_function (frame->pc, &name, NULL, NULL);
-  if (name)
-    {
-      if (STREQ (name, "_sigreturn"))
-	saved_pc_offset = 132 + 14 * 4;
-      else if (STREQ (name, "_sigacthandler"))
-	saved_pc_offset = 80 + 14 * 4;
-      else if (STREQ (name, "sigvechandler"))
-	saved_pc_offset = 120 + 14 * 4;
-    }
-
-  if (frame->next)
-    return read_memory_integer (frame->next->frame + saved_pc_offset, 4);
-  return read_memory_integer (read_register (SP_REGNUM) + saved_pc_offset, 4);
-}
-#endif /* I386V4_SIGTRAMP_SAVED_PC */
-
-
 #ifdef STATIC_TRANSFORM_NAME
 /* SunPRO encodes the static variables.  This is not related to C++
    mangling, it is done for C too.  */
@@ -1199,6 +1180,16 @@ skip_trampoline_code (CORE_ADDR pc, char
 }
 
 
+/* Return non-zero if PC and NAME show that we are in a signal
+   trampoline.  */
+
+static int
+i386_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  return (name && strcmp ("_sigtramp", name) == 0);
+}
+
+
 /* We have two flavours of disassembly.  The machinery on this page
    deals with switching between those.  */
 
@@ -1213,229 +1204,132 @@ gdb_print_insn_i386 (bfd_vma memaddr, di
      or intel_flavor.  */
   internal_error (__FILE__, __LINE__, "failed internal consistency check");
 }
-
 
-/* This table matches the indices assigned to enum i386_abi.  Keep
-   them in sync.  */
-static const char * const i386_abi_names[] =
-{
-  "<unknown>",
-  "SVR4",
-  "NetBSD",
-  "GNU/Linux",
-  "GNU/Hurd",
-  "Solaris",
-  "FreeBSD",
-  NULL
-};
 
+/* There are a few i386 architecture variants that differ only
+   slightly from the generic i386 target.  For now, we don't give them
+   their own source file, but include them here.  As a consequence,
+   they'll always be included.  */
 
-#define ABI_TAG_OS_GNU_LINUX	I386_ABI_LINUX
-#define ABI_TAG_OS_GNU_HURD	I386_ABI_HURD
-#define ABI_TAG_OS_GNU_SOLARIS	I386_ABI_INVALID
-#define ABI_TAG_OS_FREEBSD	I386_ABI_FREEBSD
-#define ABI_TAG_OS_NETBSD	I386_ABI_NETBSD
+/* System V Release 4 (SVR4).  */
 
-static void
-process_note_sections (bfd *abfd, asection *sect, void *obj)
+static int
+i386_svr4_pc_in_sigtramp (CORE_ADDR pc, char *name)
 {
-  int *abi = obj;
-  const char *name;
-  unsigned int sectsize;
-
-  name = bfd_get_section_name (abfd, sect);
-  sectsize = bfd_section_size (abfd, sect);
-
-  if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0)
-    {
-      unsigned int name_length, data_length, note_type;
-      char *note;
-
-      /* If the section is larger than this, it's probably not what we
-	 are looking for.  */
-      if (sectsize > 128)
-	sectsize = 128;
-
-      note = alloca (sectsize);
-
-      bfd_get_section_contents (abfd, sect, note,
-				(file_ptr) 0, (bfd_size_type) sectsize);
+  return (name && (strcmp ("_sigreturn", name) == 0
+		   || strcmp ("_sigacthandler", name) == 0
+		   || strcmp ("sigvechandler", name) == 0));
+}
 
-      name_length = bfd_h_get_32 (abfd, note);
-      data_length = bfd_h_get_32 (abfd, note + 4);
-      note_type = bfd_h_get_32 (abfd, note + 8);
+/* Get saved user PC for sigtramp from the pushed ucontext on the
+   stack for all three variants of SVR4 sigtramps.  */
 
-      if (name_length == 4 && data_length == 16
-	  && note_type == NT_GNU_ABI_TAG
-	  && strcmp (note + 12, "GNU") == 0)
-	{
-	  int abi_tag_os = bfd_h_get_32 (abfd, note + 16);
+CORE_ADDR
+i386_svr4_sigtramp_saved_pc (struct frame_info *frame)
+{
+  CORE_ADDR saved_pc_offset = 4;
+  char *name = NULL;
 
-	  /* The case numbers are from abi-tags in glibc.  */
-	  switch (abi_tag_os)
-	    {
-	    case GNU_ABI_TAG_LINUX:
-	      *abi = ABI_TAG_OS_GNU_LINUX;
-	      break;
-
-	    case GNU_ABI_TAG_HURD:
-	      *abi = ABI_TAG_OS_GNU_HURD;
-	      break;
-
-	    case GNU_ABI_TAG_SOLARIS:
-	      *abi = ABI_TAG_OS_GNU_SOLARIS;
-	      break;
-
-	    default:
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: unknown ABI OS tag %d",
-		 abi_tag_os);
-	      break;
-	    }
-	}
-      else if (name_length == 8 && data_length == 4
-	       && note_type == NT_FREEBSD_ABI_TAG
-	       && strcmp (note + 12, "FreeBSD") == 0)
-	*abi = ABI_TAG_OS_FREEBSD;
-    }
-  /* NetBSD uses a similar trick.  */
-  else if (strcmp (name, ".note.netbsd.ident") == 0 && sectsize > 0)
-    {
-      unsigned int name_length, desc_length, note_type;
-      char *note;
-
-      /* If the section is larger than this, it's probably not what we are
-         looking for.  */
-      if (sectsize > 128)
-	sectsize = 128;
-
-      note = alloca (sectsize);
-
-      bfd_get_section_contents (abfd, sect, note,
-				(file_ptr) 0, (bfd_size_type) sectsize);
-
-      name_length = bfd_h_get_32 (abfd, note);
-      desc_length = bfd_h_get_32 (abfd, note + 4);
-      note_type = bfd_h_get_32 (abfd, note + 8);
-
-      if (name_length == 7 && desc_length == 4
-	  && note_type == NT_NETBSD_IDENT
-	  && strcmp (note + 12, "NetBSD") == 0)
-	*abi = ABI_TAG_OS_NETBSD;
+  find_pc_partial_function (frame->pc, &name, NULL, NULL);
+  if (name)
+    {
+      if (strcmp (name, "_sigreturn") == 0)
+	saved_pc_offset = 132 + 14 * 4;
+      else if (strcmp (name, "_sigacthandler") == 0)
+	saved_pc_offset = 80 + 14 * 4;
+      else if (strcmp (name, "sigvechandler") == 0)
+	saved_pc_offset = 120 + 14 * 4;
     }
+
+  if (frame->next)
+    return read_memory_integer (frame->next->frame + saved_pc_offset, 4);
+  return read_memory_integer (read_register (SP_REGNUM) + saved_pc_offset, 4);
 }
+
+
+/* DJGPP.  */
 
 static int
-i386_elf_abi_from_note (bfd *abfd)
+i386_go32_pc_in_sigtramp (CORE_ADDR pc, char *name)
 {
-  enum i386_abi abi = I386_ABI_UNKNOWN;
-  
-  bfd_map_over_sections (abfd, process_note_sections, &abi);
-
-  return abi;
+  /* DJGPP doesn't have any special frames for signal handlers.  */
+  return 0;
 }
+
+
+/* Generic ELF.  */
 
-static enum i386_abi
-i386_elf_abi (bfd *abfd)
+void
+i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
-  int elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
+  /* We typically use stabs-in-ELF with the DWARF register numbering.  */
+  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+}
 
-  /* The fact that the EI_OSABI byte is set to ELFOSABI_NONE doesn't
-     necessarily mean that this is a System V ELF binary.  To further
-     distinguish between binaries for differens operating systems,
-     check for vendor-specific note elements.  */
-  if (elfosabi == ELFOSABI_NONE)
-    {
-      enum i386_abi abi = i386_elf_abi_from_note (abfd);
+/* System V Release 4 (SVR4).  */
 
-      if (abi != I386_ABI_UNKNOWN)
-	return abi;
+void
+i386_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-      /* FreeBSD folks are naughty; they stored the string "FreeBSD"
-	 in the padding of the e_ident field of the ELF header.  */
-      if (strcmp (&elf_elfheader (abfd)->e_ident[8], "FreeBSD") == 0)
-	return I386_ABI_FREEBSD;
-    }
+  /* System V Release 4 uses ELF.  */
+  i386_elf_init_abi (info, gdbarch);
 
-  switch (elfosabi)
-    {
-    case ELFOSABI_NONE:
-      return I386_ABI_SVR4;
-    case ELFOSABI_FREEBSD:
-      return I386_ABI_FREEBSD;
-    }
+  /* FIXME: kettenis/20020511: Why do we override this function here?  */
+  set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
 
-  return I386_ABI_UNKNOWN;
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386_svr4_pc_in_sigtramp);
+  tdep->sigtramp_saved_pc = i386_svr4_sigtramp_saved_pc;
+
+  tdep->jb_pc_offset = 20;
 }
 
-struct i386_abi_handler
+/* DJGPP.  */
+
+void
+i386_go32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
-  struct i386_abi_handler *next;
-  enum i386_abi abi;
-  void (*init_abi)(struct gdbarch_info, struct gdbarch *);
-};
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386_go32_pc_in_sigtramp);
 
-struct i386_abi_handler *i386_abi_handler_list = NULL;
+  tdep->jb_pc_offset = 36;
+}
+
+/* NetWare.  */
 
 void
-i386_gdbarch_register_os_abi (enum i386_abi abi,
-			      void (*init_abi)(struct gdbarch_info,
-					       struct gdbarch *))
+i386_nw_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
-  struct i386_abi_handler **handler_p;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  for (handler_p = &i386_abi_handler_list; *handler_p != NULL;
-       handler_p = &(*handler_p)->next)
-    {
-      if ((*handler_p)->abi == abi)
-	{
-	  internal_error
-	    (__FILE__, __LINE__,
-	     "i386_gdbarch_register_abi: A handler for this ABI variant "
-	     "(%d) has already been registered", (int) abi);
-	  /* If user wants to continue, override previous definition.  */
-	  (*handler_p)->init_abi = init_abi;
-	  return;
-	}
-    }
-  (*handler_p)
-    = (struct i386_abi_handler *) xmalloc (sizeof (struct i386_abi_handler));
-  (*handler_p)->next = NULL;
-  (*handler_p)->abi = abi;
-  (*handler_p)->init_abi = init_abi;
+  /* FIXME: kettenis/20020511: Why do we override this function here?  */
+  set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
+
+  tdep->jb_pc_offset = 24;
 }
+
 
 struct gdbarch *
 i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch_tdep *tdep;
   struct gdbarch *gdbarch;
-  enum i386_abi abi = I386_ABI_UNKNOWN;
-  struct i386_abi_handler *abi_handler;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
+  /* Try to determine the OS ABI of the object we're loading.  */
   if (info.abfd != NULL)
-    {
-      switch (bfd_get_flavour (info.abfd))
-	{
-	case bfd_target_elf_flavour:
-	  abi= i386_elf_abi (info.abfd);
-	  break;
-
-	default:
-	  /* Not sure what to do here, leave the ABI as unknown.  */
-	  break;
-	}
-    }
+    osabi = gdbarch_lookup_osabi (info.abfd);
 
   /* Find a candidate among extant architectures.  */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
        arches != NULL;
        arches = gdbarch_list_lookup_by_info (arches->next, &info))
     {
-      /* Make sure the ABI selection matches.  */
+      /* Make sure the OS ABI selection matches.  */
       tdep = gdbarch_tdep (arches->gdbarch);
-      if (tdep && tdep->abi == abi)
+      if (tdep && tdep->osabi == osabi)
         return arches->gdbarch;
     }
 
@@ -1443,11 +1337,21 @@ i386_gdbarch_init (struct gdbarch_info i
   tdep = XMALLOC (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  tdep->abi = abi;
+  tdep->osabi = osabi;
+
+  /* The i386 default settings don't include the SSE registers.
+     FIXME: kettenis/20020509: They do include the FPU registers for
+     now, which is not quite right.  */
+  tdep->num_xmm_regs = 0;
+
+  tdep->jb_pc_offset = -1;
+  tdep->struct_return = pcc_struct_return;
+  tdep->sigtramp_saved_pc = NULL;
+  tdep->sigtramp_start = 0;
+  tdep->sigtramp_end = 0;
+  tdep->sc_pc_offset = -1;
 
-  /* FIXME: kettenis/2001-11-24: Although not all IA-32 processors
-     have the SSE registers, it's easier to set the default to 8.  */
-  tdep->num_xmm_regs = 8;
+  set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
 
   set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
 
@@ -1463,50 +1367,61 @@ i386_gdbarch_init (struct gdbarch_info i
 
   set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
 
-  /* NOTE: tm-i386nw.h and tm-i386v4.h override this.  */
-  set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
+  set_gdbarch_use_struct_convention (gdbarch, i386_use_struct_convention);
 
-  /* NOTE: tm-i386aix.h, tm-i386bsd.h, tm-i386os9k.h, tm-linux.h,
-     tm-ptx.h, tm-symmetry.h currently override this.  Sigh.  */
-  set_gdbarch_num_regs (gdbarch, NUM_GREGS + NUM_FREGS + NUM_SSE_REGS);
+  /* The following redefines make backtracing through sigtramp work.
+     They manufacture a fake sigtramp frame and obtain the saved pc in
+     sigtramp from the sigcontext structure which is pushed by the
+     kernel on the user stack, along with a pointer to it.  */
+
+  set_gdbarch_frame_chain (gdbarch, i386_frame_chain);
+  set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
+  set_gdbarch_frame_saved_pc (gdbarch, i386_frame_saved_pc);
+  set_gdbarch_saved_pc_after_call (gdbarch, i386_saved_pc_after_call);
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp);
+
+  /* NOTE: tm-i386aix.h, tm-i386bsd.h, tm-i386os9k.h, tm-ptx.h,
+     tm-symmetry.h currently override this.  Sigh.  */
+  set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS);
+
+  /* Use the "default" register numbering scheme for stabs and COFF.  */
+  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
+  set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
+
+  /* Use the DWARF register numbering scheme for DWARF and DWARF 2.  */
+  set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+
+  /* We don't define ECOFF_REG_TO_REGNUM, since ECOFF doesn't seem to
+     be in use on any of the supported i386 targets.  */
+
+  set_gdbarch_register_bytes (gdbarch, I386_SIZEOF_GREGS + I386_SIZEOF_FREGS);
+  set_gdbarch_register_name (gdbarch, i386_register_name);
+  set_gdbarch_register_byte (gdbarch, i386_register_byte);
+  set_gdbarch_register_raw_size (gdbarch, i386_register_raw_size);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
-  if (abi == I386_ABI_UNKNOWN)
-    {
-      /* Don't complain about not knowing the ABI variant if we don't
-	 have an inferior.  */
-      if (info.abfd)
-	fprintf_filtered
-	  (gdb_stderr, "GDB doesn't recognize the ABI of the inferior.  "
-	   "Attempting to continue with the default i386 settings");
-    }
-  else
-    {
-      for (abi_handler = i386_abi_handler_list; abi_handler != NULL;
-	   abi_handler = abi_handler->next)
-	if (abi_handler->abi == abi)
-	  break;
+  gdbarch_init_osabi (info, gdbarch, osabi);
 
-      if (abi_handler)
-	abi_handler->init_abi (info, gdbarch);
-      else
-	{
-	  /* We assume that if GDB_MULTI_ARCH is less than
-	     GDB_MULTI_ARCH_TM that an ABI variant can be supported by
-	     overriding definitions in this file.  */
-	  if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL)
-	    fprintf_filtered
-	      (gdb_stderr,
-	       "A handler for the ABI variant \"%s\" is not built into this "
-	       "configuration of GDB.  "
-	       "Attempting to continue with the default i386 settings",
-	       i386_abi_names[abi]);
-	}
-    }
-  
   return gdbarch;
 }
 
+static enum gdb_osabi
+i386_coff_osabi_sniffer (bfd *abfd)
+{
+  if (strcmp (bfd_get_target (abfd), "coff-go32-exe") == 0)
+    return GDB_OSABI_GO32;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+static enum gdb_osabi
+i386_nlm_osabi_sniffer (bfd *abfd)
+{
+  return GDB_OSABI_NETWARE;
+}
+
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 void _initialize_i386_tdep (void);
 
@@ -1544,4 +1459,30 @@ and the default value is \"att\".",
 				&setlist);
     add_show_from_set (new_cmd, &showlist);
   }
+
+  /* Add the variable that controls the convention for returning
+     structs.  */
+  {
+    struct cmd_list_element *new_cmd;
+
+    new_cmd = add_set_enum_cmd ("struct-convention", no_class,
+				 valid_conventions,
+				&struct_convention, "\
+Set the convention for returning small structs, valid values \
+are \"default\", \"pcc\" and \"reg\", and the default value is \"default\".",
+                                &setlist);
+    add_show_from_set (new_cmd, &showlist);
+  }
+
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
+				  i386_coff_osabi_sniffer);
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_nlm_flavour,
+				  i386_nlm_osabi_sniffer);
+
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_SVR4,
+			  i386_svr4_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_GO32,
+			  i386_go32_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_NETWARE,
+			  i386_nw_init_abi);
 }
Index: i386-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.h,v
retrieving revision 1.6
diff -u -p -r1.6 i386-tdep.h
--- i386-tdep.h 9 May 2002 13:53:36 -0000 1.6
+++ i386-tdep.h 9 Jun 2002 16:46:34 -0000
@@ -1,5 +1,5 @@
 /* Target-dependent code for GDB, the GNU debugger.
-   Copyright 2001
+   Copyright 2001, 2002
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -22,6 +22,8 @@
 #ifndef I386_TDEP_H
 #define I386_TDEP_H
 
+#include "osabi.h"
+
 /* GDB's i386 target supports both the 32-bit Intel Architecture
    (IA-32) and the 64-bit AMD x86-64 architecture.  Internally it uses
    a similar register layout for both.
@@ -40,30 +42,38 @@
    differs and is determined by the num_xmm_regs member of `struct
    gdbarch_tdep'.  */
 
-/* ABI variants that we know about.  */
-enum i386_abi
-{
-  I386_ABI_UNKNOWN = 0,
-
-  /* ELF */
-  I386_ABI_SVR4,		/* This is the default.  */
-  I386_ABI_NETBSD,
-  I386_ABI_LINUX,
-  I386_ABI_HURD,
-  I386_ABI_SOLARIS,
-  I386_ABI_FREEBSD,
+/* Convention for returning structures.  */
 
-  I386_ABI_INVALID = -1
+enum struct_return
+{
+  pcc_struct_return,		/* Return "short" structures in memory.  */
+  reg_struct_return		/* Return "short" structures in registers.  */
 };
 
 /* i386 architecture specific information.  */
 struct gdbarch_tdep
 {
   /* ABI.  */
-  enum i386_abi abi;
+  enum gdb_osabi osabi;
 
   /* Number of SSE registers.  */
   int num_xmm_regs;
+
+  /* Offset of saved PC in jmp_buf.  */
+  int jb_pc_offset;
+
+  /* Convention for returning structures.  */
+  enum struct_return struct_return;
+
+  /* Get saved PC for sigtramp.  */
+  CORE_ADDR (*sigtramp_saved_pc) (struct frame_info *);
+
+  /* Address range where sigtramp lives.  */
+  CORE_ADDR sigtramp_start;
+  CORE_ADDR sigtramp_end;
+
+  /* Offset of saved PC in `struct sigcontext'.  */
+  int sc_pc_offset;
 };
 
 /* Floating-point registers.  */
@@ -129,8 +139,42 @@ struct gdbarch_tdep
 #define IS_FPU_CTRL_REGNUM(n) FPC_REGNUM_P (n)
 #define IS_SSE_REGNUM(n) SSE_REGNUM_P (n)
 
-void i386_gdbarch_register_os_abi (enum i386_abi,
-				   void (*init_abi)(struct gdbarch_info,
-						    struct gdbarch *));
+#define I386_NUM_GREGS	16
+#define I386_NUM_FREGS	16
+#define I386_NUM_XREGS  9
+
+#define I386_SSE_NUM_REGS	(I386_NUM_GREGS + I386_NUM_FREGS \
+				 + I386_NUM_XREGS)
+
+/* Sizes of individual register sets.  These cover the entire register
+   file, so summing up the sizes of those portions actually present
+   yields REGISTER_BYTES.  */
+#define I386_SIZEOF_GREGS	(I386_NUM_GREGS * 4)
+#define I386_SIZEOF_FREGS	(8 * 10 + 8 * 4)
+#define I386_SIZEOF_XREGS	(8 * 16 + 4)
+
+#define I386_SSE_SIZEOF_REGS	(I386_SIZEOF_GREGS + I386_SIZEOF_FREGS \
+				 + I386_SIZEOF_XREGS)
+
+/* Return the name of register REG.  */
+extern char *i386_register_name (int reg);
+
+/* Return the offset into the register array of the start of register
+   number REG.  */
+extern int i386_register_byte (int reg);
+
+/* Return the number of bytes of storage in GDB's register array
+   occupied by register REG.  */
+extern int i386_register_raw_size (int reg);
+
+/* Initialize a basic ELF architecture variant.  */
+extern void i386_elf_init_abi (struct gdbarch_info, struct gdbarch *);
+
+/* Initialize a SVR4 architecture variant.  */
+extern void i386_svr4_init_abi (struct gdbarch_info, struct gdbarch *);
+
+/* Functions exported from i386bsd-tdep.c.  */
+
+extern CORE_ADDR i386bsd_sigtramp_saved_pc (struct frame_info *frame);
 
 #endif /* i386-tdep.h */
Index: i386bsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386bsd-nat.c,v
retrieving revision 1.12
diff -u -p -r1.12 i386bsd-nat.c
--- i386bsd-nat.c 11 May 2002 17:22:26 -0000 1.12
+++ i386bsd-nat.c 9 Jun 2002 16:46:34 -0000
@@ -382,19 +382,39 @@ kernel_u_size (void)
   return (sizeof (struct user));
 }
 
-/* See i386bsd-tdep.c.  */
-extern int i386bsd_sigcontext_pc_offset;
-
 void
 _initialize_i386bsd_nat (void)
 {
+  int sc_pc_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
      system header files and sysctl(3) to get at the relevant
      information.  */
 
+#if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
+  extern int i386fbsd4_sc_pc_offset;
+#define SC_PC_OFFSET i386fbsd4_sc_pc_offset
+#elif defined (NetBSD) || defined (__NetBSD_Version__)
+  extern int i386nbsd_sc_pc_offset;
+#define SC_PC_OFFSET i386nbsd_sc_pc_offset
+#else
+  extern int i386bsd_sc_pc_offset;
+#define SC_PC_OFFSET i386bsd_sc_pc_offset
+#endif
+
   /* Override the default value for the offset of the program counter
      in the sigcontext structure.  */
-  i386bsd_sigcontext_pc_offset = offsetof (struct sigcontext, sc_pc);
+  sc_pc_offset = offsetof (struct sigcontext, sc_pc);
+
+  if (SC_PC_OFFSET != sc_pc_offset)
+    {
+      warning ("\
+offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
+Please report this to <bug-gdb@gnu.org>.",
+	       sc_pc_offset, SC_PC_OFFSET);
+    }
+
+  SC_PC_OFFSET = sc_pc_offset;
 }
Index: i386bsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386bsd-tdep.c,v
retrieving revision 1.1
diff -u -p -r1.1 i386bsd-tdep.c
--- i386bsd-tdep.c 13 Jul 2001 18:27:21 -0000 1.1
+++ i386bsd-tdep.c 9 Jun 2002 16:46:34 -0000
@@ -1,5 +1,5 @@
 /* Target-dependent code for i386 BSD's.
-   Copyright 2001 Free Software Foundation, Inc.
+   Copyright 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -23,26 +23,19 @@
 #include "gdbcore.h"
 #include "regcache.h"
 
-/* Support for signal handlers.  */
-
-/* Range in which to find the signaltramp routine, traditionally found
-   on the use stack, just below the user area.  Initialized to values
-   that work for NetBSD and FreeBSD.  */
+#include "i386-tdep.h"
 
-CORE_ADDR i386bsd_sigtramp_start = 0xbfbfdf20;
-CORE_ADDR i386bsd_sigtramp_end = 0xbfbfdff0;
+/* Support for signal handlers.  */
 
 /* Return whether PC is in a BSD sigtramp routine.  */
 
-int
-i386bsd_in_sigtramp (CORE_ADDR pc, char *name)
+static int
+i386bsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
 {
-  return (pc >= i386bsd_sigtramp_start && pc < i386bsd_sigtramp_end);
-}
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-/* Offset in the sigcontext structure of the program counter.
-   Initialized to the value from 4.4 BSD Lite.  */
-int i386bsd_sigcontext_pc_offset = 20;
+  return (pc >= tdep->sigtramp_start && pc < tdep->sigtramp_end);
+}
 
 /* Assuming FRAME is for a BSD sigtramp routine, return the address of
    the associated sigcontext structure.  */
@@ -62,23 +55,193 @@ i386bsd_sigcontext_addr (struct frame_in
 }
 
 /* Assuming FRAME is for a BSD sigtramp routine, return the saved
-   program counter.  */
+   program counter.
 
-static CORE_ADDR
+   Note: This function is used for Solaris 2 too, so don't make it
+   static.  */
+
+CORE_ADDR
 i386bsd_sigtramp_saved_pc (struct frame_info *frame)
 {
+  int sc_pc_offset = gdbarch_tdep (current_gdbarch)->sc_pc_offset;
   CORE_ADDR addr;
+
   addr = i386bsd_sigcontext_addr (frame);
-  return read_memory_unsigned_integer (addr + i386bsd_sigcontext_pc_offset, 4);
+  return read_memory_unsigned_integer (addr + sc_pc_offset, 4);
 }
 
 /* Return the saved program counter for FRAME.  */
 
-CORE_ADDR
+static CORE_ADDR
 i386bsd_frame_saved_pc (struct frame_info *frame)
 {
   if (frame->signal_handler_caller)
     return i386bsd_sigtramp_saved_pc (frame);
 
   return read_memory_unsigned_integer (frame->frame + 4, 4);
+}
+
+/* Return the start address of the sigtramp routine.  */
+
+CORE_ADDR
+i386bsd_sigtramp_start (CORE_ADDR pc)
+{
+  return gdbarch_tdep (current_gdbarch)->sigtramp_start;
+}
+
+/* Return the end address of the sigtramp routine.  */
+
+CORE_ADDR
+i386bsd_sigtramp_end (CORE_ADDR pc)
+{
+  return gdbarch_tdep (current_gdbarch)->sigtramp_end;
+}
+
+
+/* Traditional BSD (4.3 BSD, still used for BSDI and 386BSD).  */
+
+/* From <machine/signal.h>.  */
+int i386bsd_sc_pc_offset = 20;
+
+static void
+i386bsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386bsd_pc_in_sigtramp);
+
+  tdep->jb_pc_offset = 0;
+
+  tdep->sigtramp_saved_pc = i386bsd_sigtramp_saved_pc;
+  tdep->sigtramp_start = 0xfdbfdfc0;
+  tdep->sigtramp_end = 0xfdbfe000;
+  tdep->sc_pc_offset = i386bsd_sc_pc_offset;
+}
+
+/* NetBSD 1.0 or later.  */
+
+/* From <machine/signal.h>.  */
+int i386nbsd_sc_pc_offset = 44;
+
+static void
+i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* Obviously NetBSD is BSD-based.  */
+  i386bsd_init_abi (info, gdbarch);
+
+  /* NetBSD uses -freg-struct-return by default.  */
+  tdep->struct_return = reg_struct_return;
+
+  /* NetBSD uses a different memory layout.  */
+  tdep->sigtramp_start = 0xbfbfdf20;
+  tdep->sigtramp_end = 0xbfbfdff0;
+
+  /* NetBSD has a `struct sigcontext' that's different from the
+     origional 4.3 BSD.  */
+  tdep->sc_pc_offset = i386nbsd_sc_pc_offset;
+}
+
+/* NetBSD ELF.  */
+static void
+i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* It's still NetBSD.  */
+  i386nbsd_init_abi (info, gdbarch);
+
+  /* But ELF-based.  */
+  i386_elf_init_abi (info, gdbarch);
+
+  /* NetBSD ELF uses -fpcc-struct-return by default.  */
+  tdep->struct_return = pcc_struct_return;
+
+  /* We support the SSE registers on NetBSD ELF.  */
+  tdep->num_xmm_regs = I386_NUM_XREGS - 1;
+  set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS
+			+ I386_NUM_XREGS);
+}
+
+/* FreeBSD 3.0-RELEASE or later.  */
+
+CORE_ADDR i386fbsd_sigtramp_start = 0xbfbfdf20;
+CORE_ADDR i386fbsd_sigtramp_end = 0xbfbfdff0;
+
+static void
+i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* Obviously FreeBSD is BSD-based.  */
+  i386bsd_init_abi (info, gdbarch);
+
+  /* FreeBSD uses -freg-struct-return by default.  */
+  tdep->struct_return = reg_struct_return;
+
+  /* FreeBSD uses a different memory layout.  */
+  tdep->sigtramp_start = i386fbsd_sigtramp_start;
+  tdep->sigtramp_end = i386fbsd_sigtramp_end;
+}
+
+static void
+i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  /* It's almost identical to FreeBSD a.out.  */
+  i386fbsdaout_init_abi (info, gdbarch);
+
+  /* Except that it uses ELF.  */
+  i386_elf_init_abi (info, gdbarch);
+}
+
+/* FreeBSD 4.0-RELEASE or later.  */
+
+/* From <machine/signal.h>.  */
+int i386fbsd4_sc_pc_offset = 76;
+
+static void
+i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* Inherit stuff from older releases.  We assume that FreeBSD
+     4.0-RELEASE always uses ELF.  */
+  i386fbsd_init_abi (info, gdbarch);
+
+  /* FreeBSD 4.0 introduced a new `struct sigcontext'.  */
+  tdep->sc_pc_offset = i386fbsd4_sc_pc_offset;
+}
+
+
+static enum gdb_osabi
+i386bsd_aout_osabi_sniffer (bfd *abfd)
+{
+  if (strcmp (bfd_get_target (abfd), "a.out-i386-netbsd") == 0)
+    return GDB_OSABI_NETBSD_AOUT;
+
+  if (strcmp (bfd_get_target (abfd), "a.out-i386-freebsd") == 0)
+    return GDB_OSABI_FREEBSD_AOUT;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_i386bsd_tdep (void);
+
+void
+_initialize_i386bsd_tdep (void)
+{
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_aout_flavour,
+				  i386bsd_aout_osabi_sniffer);
+
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_NETBSD_AOUT,
+			  i386nbsd_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_NETBSD_ELF,
+ 			  i386nbsdelf_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_FREEBSD_AOUT,
+			  i386fbsdaout_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_FREEBSD_ELF,
+			  i386fbsd4_init_abi);
 }
Index: i386fbsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386fbsd-nat.c,v
retrieving revision 1.1
diff -u -p -r1.1 i386fbsd-nat.c
--- i386fbsd-nat.c 21 Jul 2001 20:16:44 -0000 1.1
+++ i386fbsd-nat.c 9 Jun 2002 16:46:34 -0000
@@ -1,5 +1,5 @@
 /* Native-dependent code for FreeBSD/i386.
-   Copyright 2001 Free Software Foundation, Inc.
+   Copyright 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -79,7 +79,7 @@ _initialize_i386fbsd_nat (void)
 {
   /* FreeBSD provides a kern.ps_strings sysctl that we can use to
      locate the sigtramp.  That way we can still recognize a sigtramp
-     if it's location is changed in a new kernel.  Of course this is
+     if its location is changed in a new kernel.  Of course this is
      still based on the assumption that the sigtramp is placed
      directly under the location where the program arguments and
      environment can be found.  */
@@ -89,13 +89,16 @@ _initialize_i386fbsd_nat (void)
     int ps_strings;
     size_t len;
 
+    extern CORE_ADDR i386fbsd_sigtramp_start;
+    extern CORE_ADDR i386fbsd_sigtramp_end;
+
     mib[0] = CTL_KERN;
     mib[1] = KERN_PS_STRINGS;
     len = sizeof (ps_strings);
     if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
       {
-	i386bsd_sigtramp_start = ps_strings - 128;
-	i386bsd_sigtramp_end = ps_strings;
+	i386fbsd_sigtramp_start = ps_strings - 128;
+	i386fbsd_sigtramp_end = ps_strings;
       }
   }
 #endif
Index: i386nbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386nbsd-tdep.c,v
retrieving revision 1.4
diff -u -p -r1.4 i386nbsd-tdep.c
--- i386nbsd-tdep.c 11 May 2002 21:22:51 -0000 1.4
+++ i386nbsd-tdep.c 9 Jun 2002 16:46:34 -0000
@@ -137,16 +137,6 @@ static struct core_fns i386nbsd_elfcore_
   NULL					/* next */
 };
 
-/* FIXME: should be multi-arch'd */
-int
-i386nbsd_aout_use_struct_convention (int gcc_p, struct type *type)
-{
-  return !(TYPE_LENGTH (type) == 1
-	   || TYPE_LENGTH (type) == 2
-	   || TYPE_LENGTH (type) == 4
-	   || TYPE_LENGTH (type) == 8);
-}
-
 void
 _initialize_i386nbsd_tdep (void)
 {
Index: config/i386/i386nw.mt
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/i386nw.mt,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 i386nw.mt
--- config/i386/i386nw.mt 16 Apr 1999 01:34:18 -0000 1.1.1.1
+++ config/i386/i386nw.mt 9 Jun 2002 16:46:35 -0000
@@ -1,3 +1,3 @@
 # Target: Intel 386 running NetWare
 TDEPFILES= i386-tdep.o i387-tdep.o
-TM_FILE= tm-i386nw.h
+TM_FILE= tm-i386.h
Index: config/i386/i386sol2.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/i386sol2.mh,v
retrieving revision 1.5
diff -u -p -r1.5 i386sol2.mh
--- config/i386/i386sol2.mh 11 May 2002 17:22:27 -0000 1.5
+++ config/i386/i386sol2.mh 9 Jun 2002 16:46:35 -0000
@@ -5,4 +5,5 @@ XM_CLIBS= -lsocket -lnsl
 
 NAT_FILE= nm-i386sol2.h
 NATDEPFILES= core-regset.o fork-child.o i386v4-nat.o corelow.o \
-	procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o gcore.o
+	procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o gcore.o \
+        solib.o solib-svr4.o solib-legacy.o
Index: config/i386/i386sol2.mt
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/i386sol2.mt,v
retrieving revision 1.3
diff -u -p -r1.3 i386sol2.mt
--- config/i386/i386sol2.mt 10 Mar 2001 06:17:21 -0000 1.3
+++ config/i386/i386sol2.mt 9 Jun 2002 16:46:35 -0000
@@ -1,3 +1,3 @@
-# Target: Intel 386 running SVR4
-TDEPFILES= i386-tdep.o i387-tdep.o solib.o solib-svr4.o solib-legacy.o
+# Target: Intel 386 running Solaris 2 (SVR4)
+TDEPFILES= i386-tdep.o i387-tdep.o i386-sol2-tdep.o i386bsd-tdep.o
 TM_FILE= tm-i386sol2.h
Index: config/i386/tm-fbsd.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-fbsd.h,v
retrieving revision 1.5
diff -u -p -r1.5 tm-fbsd.h
--- config/i386/tm-fbsd.h 28 Jul 2001 17:03:38 -0000 1.5
+++ config/i386/tm-fbsd.h 9 Jun 2002 16:46:35 -0000
@@ -24,56 +24,17 @@
 #define HAVE_I387_REGS
 #include "i386/tm-i386.h"
 
-/* FreeBSD/ELF uses stabs-in-ELF with the DWARF register numbering
-   scheme by default, so we must redefine STAB_REG_TO_REGNUM.  This
-   messes up the floating-point registers for a.out, but there is not
-   much we can do about that.  */
-
-#undef STAB_REG_TO_REGNUM
-#define STAB_REG_TO_REGNUM(reg) i386_dwarf_reg_to_regnum ((reg))
-
-/* FreeBSD uses the old gcc convention for struct returns.  */
-
-#define USE_STRUCT_CONVENTION(gcc_p, type) \
-  generic_use_struct_convention (1, type)
-
-
-/* Support for longjmp.  */
-
-/* Details about jmp_buf.  It's supposed to be an array of integers.  */
-
-#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.  */
-
-#define GET_LONGJMP_TARGET(addr) get_longjmp_target (addr)
-extern int get_longjmp_target (CORE_ADDR *addr);
-
-
-/* Support for signal handlers.  */
-
-#define IN_SIGTRAMP(pc, name) i386bsd_in_sigtramp (pc, name)
-extern int i386bsd_in_sigtramp (CORE_ADDR pc, char *name);
-
 /* These defines allow the recognition of sigtramps as a function name
    <sigtramp>.
 
-   FIXME: kettenis/2001-07-13: These should be added to the target
-   vector and turned into functions when we go "multi-arch".  */
-
-#define SIGTRAMP_START(pc) i386bsd_sigtramp_start
-#define SIGTRAMP_END(pc) i386bsd_sigtramp_end
-extern CORE_ADDR i386bsd_sigtramp_start;
-extern CORE_ADDR i386bsd_sigtramp_end;
-
-/* Override FRAME_SAVED_PC to enable the recognition of signal handlers.  */
-
-#undef FRAME_SAVED_PC
-#define FRAME_SAVED_PC(frame) i386bsd_frame_saved_pc (frame)
-extern CORE_ADDR i386bsd_frame_saved_pc (struct frame_info *frame);
-
+   FIXME: kettenis/2002-05-12: Of course these defines will have to go
+   if we go truly "multi-arch", but I don't know yet how to get rid of
+   them.  */
+
+#define SIGTRAMP_START(pc) i386bsd_sigtramp_start (pc)
+#define SIGTRAMP_END(pc) i386bsd_sigtramp_end (pc)
+extern CORE_ADDR i386bsd_sigtramp_start (CORE_ADDR pc);
+extern CORE_ADDR i386bsd_sigtramp_end (CORE_ADDR pc);
 
 /* Shared library support.  */
 
Index: config/i386/tm-go32.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-go32.h,v
retrieving revision 1.5
diff -u -p -r1.5 tm-go32.h
--- config/i386/tm-go32.h 2 Dec 2001 18:29:08 -0000 1.5
+++ config/i386/tm-go32.h 9 Jun 2002 16:46:35 -0000
@@ -26,43 +26,4 @@
 
 #include "i386/tm-i386.h"
 
-/* FRAME_CHAIN takes a frame's nominal address and produces the frame's
-   chain-pointer.
-   In the case of the i386, the frame's nominal address
-   is the address of a 4-byte word containing the calling frame's address.
-   DJGPP doesn't have any special frames for signal handlers, they are
-   just normal C functions. */
-#undef  FRAME_CHAIN
-#define FRAME_CHAIN(thisframe) \
-  (!inside_entry_file ((thisframe)->pc) ? \
-   read_memory_integer ((thisframe)->frame, 4) :\
-   0)
-
-/* A macro that tells us whether the function invocation represented
-   by FI does not have a frame on the stack associated with it.  If it
-   does not, FRAMELESS is set to 1, else 0.  */
-#undef  FRAMELESS_FUNCTION_INVOCATION
-#define FRAMELESS_FUNCTION_INVOCATION(FI) \
-     (frameless_look_for_prologue(FI))
-
-extern CORE_ADDR i386go32_frame_saved_pc (struct frame_info *frame);
-#undef  FRAME_SAVED_PC
-#define FRAME_SAVED_PC(FRAME) (i386go32_frame_saved_pc ((FRAME)))
-
-/* Support for longjmp.  */
-
-/* Details about jmp_buf.  It's supposed to be an array of integers.  */
-
-#define JB_ELEMENT_SIZE 4	/* Size of elements in jmp_buf.  */
-#define JB_PC		8	/* Array index of saved PC inside jmp_buf.  */
-
-/* Figure out where the longjmp will land.  Slurp the args out of the
-   stack.  We expect the first arg to be a pointer to the jmp_buf
-   structure from which we extract the pc (JB_PC) that we will land
-   at.  The pc is copied into ADDR.  This routine returns true on
-   success.  */
-
-#define GET_LONGJMP_TARGET(addr) get_longjmp_target (addr)
-extern int get_longjmp_target (CORE_ADDR *addr);
-
 #endif /* TM_GO32_H */
Index: config/i386/tm-i386.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-i386.h,v
retrieving revision 1.29
diff -u -p -r1.29 tm-i386.h
--- config/i386/tm-i386.h 29 Jan 2002 04:42:37 -0000 1.29
+++ config/i386/tm-i386.h 9 Jun 2002 16:46:35 -0000
@@ -63,11 +63,6 @@ struct type;
 
 extern int i386_skip_prologue (int);
 
-/* Immediately after a function call, return the saved pc.  */
-
-#define SAVED_PC_AFTER_CALL(frame) i386_saved_pc_after_call (frame)
-extern CORE_ADDR i386_saved_pc_after_call (struct frame_info *frame);
-
 /* Stack grows downward.  */
 
 #define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
@@ -118,7 +113,7 @@ extern CORE_ADDR i386_saved_pc_after_cal
 #endif
 
 /* Largest number of registers we could have in any configuration.  */
-#define MAX_NUM_REGS (16 + 16 + 9)
+#define MAX_NUM_REGS (16 + 16 + 9 + 1)
 
 /* Register numbers of various important registers.
    Note that some of these values are "real" register numbers,
@@ -139,60 +134,8 @@ extern CORE_ADDR i386_saved_pc_after_cal
 #else
 #define FP0_REGNUM 0
 #endif
-
-/* Return the name of register REG.  */
-
-#define REGISTER_NAME(reg) i386_register_name ((reg))
-extern char *i386_register_name (int reg);
-
-/* Use the "default" register numbering scheme for stabs and COFF.  */
-
-#define STAB_REG_TO_REGNUM(reg) i386_stab_reg_to_regnum ((reg))
-#define SDB_REG_TO_REGNUM(reg) i386_stab_reg_to_regnum ((reg))
-extern int i386_stab_reg_to_regnum (int reg);
-
-/* Use the DWARF register numbering scheme for DWARF and DWARF 2.  */
-
-#define DWARF_REG_TO_REGNUM(reg) i386_dwarf_reg_to_regnum ((reg))
-#define DWARF2_REG_TO_REGNUM(reg) i386_dwarf_reg_to_regnum ((reg))
-extern int i386_dwarf_reg_to_regnum (int reg);
-
-/* We don't define ECOFF_REG_TO_REGNUM, since ECOFF doesn't seem to be
-   in use on any of the supported i386 targets.  */
 
 
-/* Sizes of individual register sets.  These cover the entire register
-   file, so summing up the sizes of those portions actually present
-   yields REGISTER_BYTES.  */
-#define SIZEOF_GREGS (NUM_GREGS * 4)
-#define SIZEOF_FPU_REGS (8 * 10)
-#define SIZEOF_FPU_CTRL_REGS (8 * 4)
-#define SIZEOF_SSE_REGS (8 * 16 + 4)
-
-
-/* Total amount of space needed to store our copies of the machine's register
-   state, the array `registers'. */
-#ifdef HAVE_SSE_REGS
-#define REGISTER_BYTES \
-  (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS)
-#else
-#ifdef HAVE_I387_REGS
-#define REGISTER_BYTES (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS)
-#else
-#define REGISTER_BYTES (SIZEOF_GREGS)
-#endif
-#endif
-
-/* Return the offset into the register array of the start of register
-   number REG.  */
-#define REGISTER_BYTE(reg) i386_register_byte ((reg))
-extern int i386_register_byte (int reg);
-
-/* Return the number of bytes of storage in GDB's register array
-   occupied by register REG.  */
-#define REGISTER_RAW_SIZE(reg) i386_register_raw_size ((reg))
-extern int i386_register_raw_size (int reg);
-
 /* Largest value REGISTER_RAW_SIZE can have.  */
 #define MAX_REGISTER_RAW_SIZE 16
 
@@ -275,18 +218,6 @@ extern void i386_store_return_value (str
   i386_extract_struct_value_address ((regbuf))
 extern CORE_ADDR i386_extract_struct_value_address (char *regbuf);
 
-/* The following redefines make backtracing through sigtramp work.
-   They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
-   from the sigcontext structure which is pushed by the kernel on the
-   user stack, along with a pointer to it.  */
-
-/* Return the chain-pointer for FRAME.  In the case of the i386, the
-   frame's nominal address is the address of a 4-byte word containing
-   the calling frame's address.  */
-
-#define FRAME_CHAIN(frame) i386_frame_chain ((frame))
-extern CORE_ADDR i386_frame_chain (struct frame_info *frame);
-
 /* Determine whether the function invocation represented by FRAME does
    not have a from on the stack associated with it.  If it does not,
    return non-zero, otherwise return zero.  */
@@ -294,11 +225,6 @@ extern CORE_ADDR i386_frame_chain (struc
 #define FRAMELESS_FUNCTION_INVOCATION(frame) \
   i386_frameless_function_invocation (frame)
 extern int i386_frameless_function_invocation (struct frame_info *frame);
-
-/* Return the saved program counter for FRAME.  */
-
-#define FRAME_SAVED_PC(frame) i386_frame_saved_pc (frame)
-extern CORE_ADDR i386_frame_saved_pc (struct frame_info *frame);
 
 #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
 
Index: config/i386/tm-i386sol2.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-i386sol2.h,v
retrieving revision 1.10
diff -u -p -r1.10 tm-i386sol2.h
--- config/i386/tm-i386sol2.h 30 Jul 2001 21:45:26 -0000 1.10
+++ config/i386/tm-i386sol2.h 9 Jun 2002 16:46:35 -0000
@@ -24,11 +24,6 @@
 #define HAVE_I387_REGS
 #include "i386/tm-i386v4.h"
 
-/* We use stabs-in-ELF with the DWARF register numbering scheme.  */
-
-#undef STAB_REG_TO_REGNUM
-#define STAB_REG_TO_REGNUM(reg) i386_dwarf_reg_to_regnum ((reg))
-
 /* If the current gcc for for this target does not produce correct
    debugging information for float parameters, both prototyped and
    unprototyped, then define this macro.  This forces gdb to always
@@ -36,15 +31,6 @@
    callee. */
 
 #define COERCE_FLOAT_TO_DOUBLE(formal, actual) (1)
-
-/* Signal handler frames under Solaris 2 are recognized by a return address
-   of 0xFFFFFFFF, the third parameter on the signal handler stack is
-   a pointer to an ucontext.  */
-#undef sigtramp_saved_pc
-#undef I386V4_SIGTRAMP_SAVED_PC
-#define SIGCONTEXT_PC_OFFSET (36 + 14 * 4)
-#undef IN_SIGTRAMP
-#define IN_SIGTRAMP(pc, name) (pc == 0xFFFFFFFF)
 
 /* The SunPRO compiler puts out 0 instead of the address in N_SO symbols,
    and for SunPRO 3.0, N_FUN symbols too.  */
Index: config/i386/tm-i386v4.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-i386v4.h,v
retrieving revision 1.5
diff -u -p -r1.5 tm-i386v4.h
--- config/i386/tm-i386v4.h 5 Jun 2002 19:18:19 -0000 1.5
+++ config/i386/tm-i386v4.h 9 Jun 2002 16:46:35 -0000
@@ -31,49 +31,4 @@
 
 #include "config/tm-sysv4.h"
 
-/* Use the alternate method of determining valid frame chains. */
-
-#define FRAME_CHAIN_VALID(fp,fi) func_frame_chain_valid (fp, fi)
-
-/* Offsets (in target ints) into jmp_buf.  Not defined in any system header
-   file, so we have to step through setjmp/longjmp with a debugger and figure
-   them out.  Note that <setjmp> defines _JBLEN as 10, which is the default
-   if no specific machine is selected, even though we only use 6 slots. */
-
-#define JB_ELEMENT_SIZE sizeof(int)	/* jmp_buf[_JBLEN] is array of ints */
-
-#define JB_EBX	0
-#define JB_ESI	1
-#define JB_EDI	2
-#define JB_EBP	3
-#define JB_ESP	4
-#define JB_EDX	5
-
-#define JB_PC	JB_EDX		/* Setjmp()'s return PC saved in EDX */
-
-/* Figure out where the longjmp will land.  Slurp the args out of the stack.
-   We expect the first arg to be a pointer to the jmp_buf structure from which
-   we extract the pc (JB_PC) that we will land at.  The pc is copied into ADDR.
-   This routine returns true on success */
-
-extern int get_longjmp_target (CORE_ADDR *);
-
-#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
-
-/* The following redefines make backtracing through sigtramp work.
-   They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
-   from the ucontext structure which is pushed by the kernel on the
-   user stack. Unfortunately there are three variants of sigtramp handlers.  */
-
-#define I386V4_SIGTRAMP_SAVED_PC
-#define IN_SIGTRAMP(pc, name) ((name)					\
-			       && (STREQ ("_sigreturn", name)		\
-				   || STREQ ("_sigacthandler", name)	\
-				   || STREQ ("sigvechandler", name)))
-
-/* Saved Pc.  Get it from ucontext if within sigtramp.  */
-
-#define sigtramp_saved_pc i386v4_sigtramp_saved_pc
-extern CORE_ADDR i386v4_sigtramp_saved_pc (struct frame_info *);
-
 #endif /* ifndef TM_I386V4_H */
Index: config/i386/tm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-linux.h,v
retrieving revision 1.19
diff -u -p -r1.19 tm-linux.h
--- config/i386/tm-linux.h 5 Jun 2002 19:18:19 -0000 1.19
+++ config/i386/tm-linux.h 9 Jun 2002 16:46:35 -0000
@@ -33,72 +33,9 @@
 #include "i386/tm-i386.h"
 #include "config/tm-linux.h"
 
-/* Register number for the "orig_eax" pseudo-register.  If this
-   pseudo-register contains a value >= 0 it is interpreted as the
-   system call number that the kernel is supposed to restart.  */
-#define I386_LINUX_ORIG_EAX_REGNUM (NUM_GREGS + NUM_FREGS + NUM_SSE_REGS)
-
-/* Adjust a few macros to deal with this extra register.  */
-
-#undef NUM_REGS
-#define NUM_REGS (NUM_GREGS + NUM_FREGS + NUM_SSE_REGS + 1)
-
-#undef MAX_NUM_REGS
-#define MAX_NUM_REGS (16 + 16 + 9 + 1)
-
-#undef REGISTER_BYTES
-#define REGISTER_BYTES \
-  (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS + 4)
-
-#undef REGISTER_NAME
-#define REGISTER_NAME(reg) i386_linux_register_name ((reg))
-extern char *i386_linux_register_name (int reg);
-
-#undef REGISTER_BYTE
-#define REGISTER_BYTE(reg) i386_linux_register_byte ((reg))
-extern int i386_linux_register_byte (int reg);
-
-#undef REGISTER_RAW_SIZE
-#define REGISTER_RAW_SIZE(reg) i386_linux_register_raw_size ((reg))
-extern int i386_linux_register_raw_size (int reg);
-
-/* GNU/Linux ELF uses stabs-in-ELF with the DWARF register numbering
-   scheme by default, so we must redefine STAB_REG_TO_REGNUM.  This
-   messes up the floating-point registers for a.out, but there is not
-   much we can do about that.  */
-#undef STAB_REG_TO_REGNUM
-#define STAB_REG_TO_REGNUM(reg) i386_dwarf_reg_to_regnum ((reg))
-
-/* Use target_specific function to define link map offsets.  */
-extern struct link_map_offsets *i386_linux_svr4_fetch_link_map_offsets (void);
-#define SVR4_FETCH_LINK_MAP_OFFSETS() i386_linux_svr4_fetch_link_map_offsets ()
-
 /* The following works around a problem with /usr/include/sys/procfs.h  */
 #define sys_quotactl 1
 
-/* When the i386 Linux kernel calls a signal handler, the return
-   address points to a bit of code on the stack.  These definitions
-   are used to identify this bit of code as a signal trampoline in
-   order to support backtracing through calls to signal handlers.  */
-
-#define IN_SIGTRAMP(pc, name) i386_linux_in_sigtramp (pc, name)
-extern int i386_linux_in_sigtramp (CORE_ADDR, char *);
-
-#undef FRAME_CHAIN
-#define FRAME_CHAIN(frame) i386_linux_frame_chain (frame)
-extern CORE_ADDR i386_linux_frame_chain (struct frame_info *frame);
-
-#undef FRAME_SAVED_PC
-#define FRAME_SAVED_PC(frame) i386_linux_frame_saved_pc (frame)
-extern CORE_ADDR i386_linux_frame_saved_pc (struct frame_info *frame);
-
-#undef SAVED_PC_AFTER_CALL
-#define SAVED_PC_AFTER_CALL(frame) i386_linux_saved_pc_after_call (frame)
-extern CORE_ADDR i386_linux_saved_pc_after_call (struct frame_info *);
-
-#define TARGET_WRITE_PC(pc, ptid) i386_linux_write_pc (pc, ptid)
-extern void i386_linux_write_pc (CORE_ADDR pc, ptid_t ptid);
-
 /* When we call a function in a shared library, and the PLT sends us
    into the dynamic linker to find the function's real address, we
    need to skip over the dynamic linker call.  This function decides
@@ -110,22 +47,5 @@ extern CORE_ADDR i386_linux_skip_solib_r
 /* N_FUN symbols in shared libaries have 0 for their values and need
    to be relocated. */
 #define SOFUN_ADDRESS_MAYBE_MISSING
-
-
-/* Support for longjmp.  */
-
-/* Details about jmp_buf.  It's supposed to be an array of integers.  */
-
-#define JB_ELEMENT_SIZE 4	/* Size of elements in jmp_buf.  */
-#define JB_PC		5	/* Array index of saved PC.  */
-
-/* Figure out where the longjmp will land.  Slurp the args out of the
-   stack.  We expect the first arg to be a pointer to the jmp_buf
-   structure from which we extract the pc (JB_PC) that we will land
-   at.  The pc is copied into ADDR.  This routine returns true on
-   success.  */
-
-#define GET_LONGJMP_TARGET(addr) get_longjmp_target (addr)
-extern int get_longjmp_target (CORE_ADDR *addr);
 
 #endif /* #ifndef TM_LINUX_H */
Index: config/i386/tm-nbsd.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-nbsd.h,v
retrieving revision 1.10
diff -u -p -r1.10 tm-nbsd.h
--- config/i386/tm-nbsd.h 22 May 2002 03:59:54 -0000 1.10
+++ config/i386/tm-nbsd.h 9 Jun 2002 16:46:35 -0000
@@ -26,39 +26,16 @@
 
 #include "i386/tm-i386.h"
 
-#define JB_ELEMENT_SIZE sizeof(int)	/* jmp_buf[_JBLEN] is array of ints */
-#define JB_PC	0		/* Setjmp()'s return PC saved here */
-
-/* Figure out where the longjmp will land.  Slurp the args out of the stack.
-   We expect the first arg to be a pointer to the jmp_buf structure from which
-   we extract the pc (JB_PC) that we will land at.  The pc is copied into ADDR.
-   This routine returns true on success */
-
-extern int get_longjmp_target (CORE_ADDR *);
-
-#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
-
-
-/* Support for signal handlers.  */
-
-#define IN_SIGTRAMP(pc, name) i386bsd_in_sigtramp (pc, name)
-extern int i386bsd_in_sigtramp (CORE_ADDR pc, char *name);
-
 /* These defines allow the recognition of sigtramps as a function name
    <sigtramp>.
 
-   FIXME: kettenis/2001-07-13: These should be added to the target
-   vector and turned into functions when we go "multi-arch".  */
-
-#define SIGTRAMP_START(pc) i386bsd_sigtramp_start
-#define SIGTRAMP_END(pc) i386bsd_sigtramp_end
-extern CORE_ADDR i386bsd_sigtramp_start;
-extern CORE_ADDR i386bsd_sigtramp_end;
-
-/* Override FRAME_SAVED_PC to enable the recognition of signal handlers.  */
-
-#undef FRAME_SAVED_PC
-#define FRAME_SAVED_PC(frame) i386bsd_frame_saved_pc (frame)
-extern CORE_ADDR i386bsd_frame_saved_pc (struct frame_info *frame);
+   FIXME: kettenis/2002-05-12: Of course these defines will have to go
+   if we go truly "multi-arch", but I don't know yet how to get rid of
+   them.  */
+
+#define SIGTRAMP_START(pc) i386bsd_sigtramp_start (pc)
+#define SIGTRAMP_END(pc) i386bsd_sigtramp_end (pc)
+extern CORE_ADDR i386bsd_sigtramp_start (CORE_ADDR pc);
+extern CORE_ADDR i386bsd_sigtramp_end (CORE_ADDR pc);
 
 #endif /* TM_NBSD_H */
Index: config/i386/tm-nbsdaout.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-nbsdaout.h,v
retrieving revision 1.1
diff -u -p -r1.1 tm-nbsdaout.h
--- config/i386/tm-nbsdaout.h 22 May 2002 03:59:54 -0000 1.1
+++ config/i386/tm-nbsdaout.h 9 Jun 2002 16:46:35 -0000
@@ -27,8 +27,4 @@
 #define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \
   (name && !strcmp(name, "_DYNAMIC"))
 
-extern use_struct_convention_fn i386nbsd_aout_use_struct_convention;
-#define USE_STRUCT_CONVENTION(gcc_p, type) \
-        i386nbsd_aout_use_struct_convention(gcc_p, type)
-
 #endif /* TM_NBSDAOUT_H */
Index: config/i386/tm-i386nw.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-i386nw.h,v
retrieving revision 1.3
diff -u -p -r1.3 tm-i386nw.h
--- config/i386/tm-i386nw.h 6 Mar 2001 08:21:29 -0000 1.3
+++ config/i386/tm-i386nw.h 9 Jun 2002 16:46:35 -0000
@@ -1,5 +1,5 @@
 /* Macro definitions for i386 running NetWare.
-   Copyright 1993, 1994, 1995, 1998, 1999, 2000
+   Copyright 1993, 1994, 1995, 1998, 1999, 2000, 2002
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -23,27 +23,5 @@
 #define TM_I386NW_H 1
 
 #include "i386/tm-i386.h"
-
-/* Stop backtracing when we wander into main.  */
-
-#define FRAME_CHAIN_VALID(fp,fi) func_frame_chain_valid (fp, fi)
-
-
-/* Offsets (in target ints) into jmp_buf.  Not defined in any system header
-   file, so we have to step through setjmp/longjmp with a debugger and figure
-   them out.  */
-
-#define JB_ELEMENT_SIZE 4	/* jmp_buf[] is array of ints */
-
-#define JB_PC	6		/* Setjmp()'s return PC saved here */
-
-/* Figure out where the longjmp will land.  Slurp the args out of the stack.
-   We expect the first arg to be a pointer to the jmp_buf structure from which
-   we extract the pc (JB_PC) that we will land at.  The pc is copied into ADDR.
-   This routine returns true on success */
-
-extern int get_longjmp_target (CORE_ADDR *);
-
-#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
 
 #endif /* ifndef TM_I386NW_H */
--- /dev/null	Sun Jun  9 18:50:34 2002
+++ i386-linux-tdep.h	Sun Jun  9 16:08:22 2002
@@ -0,0 +1,36 @@
+/* Target-dependent code for Linux/x86.
+   Copyright 2002
+   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 I386_LINUX_TDEP_H
+#define I386_LINUX_TDEP_H
+
+/* The Linux kernel pretends there is an additional "orig_eax"
+   register.  Since GDB needs access to that register to be able to
+   properly restart system calls when necessary (see
+   i386-linux-tdep.c) we need our own versions of a number of
+   functions that deal with GDB's register cache.  */
+
+/* Register number for the "orig_eax" pseudo-register.  If this
+   pseudo-register contains a value >= 0 it is interpreted as the
+   system call number that the kernel is supposed to restart.  */
+#define I386_LINUX_ORIG_EAX_REGNUM I386_SSE_NUM_REGS
+
+#endif /* i386-linux-tdep.h */
--- /dev/null	Sun Jun  9 18:50:34 2002
+++ i386-sol2-tdep.c	Sun Jun  9 16:56:43 2002
@@ -0,0 +1,59 @@
+/* Target-dependent code for Solaris x86.
+   Copyright 2002 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 "i386-tdep.h"
+
+static int
+i386_sol2_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  /* Signal handler frames under Solaris 2 are recognized by a return
+     address of 0xffffffff.  */
+  return (pc == 0xffffffff);
+}
+
+/* Solaris 2.  */
+
+static void
+i386_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* Solaris is SVR4-based.  */
+  i386_svr4_init_abi (info, gdbarch);
+
+  /* Signal trampolines are different from SVR4, in fact they're
+     rather similar to BSD.  */
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386_sol2_pc_in_sigtramp);
+  tdep->sigtramp_saved_pc = i386bsd_sigtramp_saved_pc;
+  tdep->sc_pc_offset = 36 + 14 * 4;
+}
+
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_i386_sol2_tdep (void);
+
+void
+_initialize_i386_sol2_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_SOLARIS,
+			  i386_sol2_init_abi);
+}


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