[PATCH] Final: Generic OS ABI handling

Jason R Thorpe thorpej@wasabisystems.com
Tue May 21 08:35:00 GMT 2002


Ok, I've gotten an OK from all of the affected target maintainers,
so this is the final patch I'm checking in.

Thanks, everybody, for your input!

        * Makefile.in (SFILES): Add osabi.c.
        (COMMON_OBS): Add osabi.o.
        (osabi.o): New dependency list.
        * osabi.c: New file.
        * osabi.h: New file.
        * doc/gdbint.texinfo: Document new generic OS ABI framework.

        * Makefile.in (alpha_tdep_h): Define and use instead of
        alpha-tdep.h.
        * alpha-tdep.c (alpha_abi_names, process_note_abi_tag_sections,
        get_elfosabi, alpha_abi_handler_list, alpha_gdbarch_register_os_abi):
        Remove.
        (alpha_gdbarch_init, alpha_dump_tdep): Use generic OS ABI framework.
        * alpha-tdep.h: Include osabi.h.
        (alpha_abi): Remove.
        (gdbarch_tdep): Use generic OS ABI framework.
        * alpha-linux-tdep.c (_initialize_alpha_linux_tdep): Use
        gdbarch_register_osabi.
        * alpha-osf1-tdep.c (_initialize_alpha_osf1_tdep): Likewise.
        * alphafbsd-tdep.c (_initialize_alphafbsd_tdep): Likewise.
        * alphanbsd-tdep.c (_initialize_alphanbsd_tdep): Likewise.

        * Makefile.in (sh_tdep_h): Add osabi.h.
        * sh-tdep.h (sh_osabi): Remove.
        (gdbarch_tdep): Use generic OS ABI framework.
        * sh-tdep.c (sh_osabi_names, process_note_abi_tag_sections,
        sh_osabi_handler_list, sh_gdbarch_register_os_abi): Remove.
        (sh_gdbarch_init, sh_dump_tdep): Use generic OS ABI framework.
        * shnbsd-tdep.c (_initialize_shnbsd_tdep): Use gdbarch_register_osabi.

        * Makefile.in (arm_tdep_h): Define and use instead of arm-tdep.h.
        * arm-linux-tdep.c (_initialize_arm_linux_tdep): Use
        gdbarch_register_osabi.
        * arm-tdep.c (arm_abi_names, process_note_abi_tag_sections,
        arm_abi_handler_list, arm_gdbarch_register_os_abi): Remove.
        (get_elfosabi): Rename to...
        (arm_elf_osabi_sniffer): ...this.  Adjust to use generic OS
        ABI framework support routines.
        (arm_gdbarch_init): Use generic OS ABI framework. 
        (arm_dump_tdep): Likewise.
        (_initialize_arm_tdep): Likewise.
        * arm-tdep.h: Include osabi.h.
        (arm_abi): Remove.
        (gdbarch_tdep): Remove arm_abi and abi_name members.  Add
        osabi member.
        (arm_gdbarch_register_os_abi): Remove prototype.
        * armnbsd-tdep.c (arm_netbsd_aout_osabi_sniffer): New function.
        (_initialize_arm_netbsd_tdep): Use gdbarch_register_osabi.

        * Makefile.in (mips-tdep.o): Add osabi.h to dependency list.
        * mips-tdep.c: Include osabi.h.
        (gdbarch_tdep, mips_gdbarch_init, mips_dump_tdep): Use generic
        OS ABI framework.

-- 
        -- Jason R. Thorpe <thorpej@wasabisystems.com>
-------------- next part --------------
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.194
diff -u -r1.194 Makefile.in
--- Makefile.in	17 May 2002 17:57:48 -0000	1.194
+++ Makefile.in	21 May 2002 15:15:33 -0000
@@ -530,7 +530,7 @@
 	demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \
 	event-loop.c event-top.c \
 	expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \
-	findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c \
+	findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c osabi.c \
 	inf-loop.c infcmd.c inflow.c infrun.c language.c \
 	kod.c kod-cisco.c \
 	ui-out.c cli-out.c \
@@ -593,8 +593,10 @@
 tm_h =		@tm_h@
 nm_h =		@nm_h@
 
+alpha_tdep_h =	alpha-tdep.h osabi.h
 annotate_h =	annotate.h $(symtab_h) $(gdbtypes_h)
 arch_utils_h =	arch-utils.h
+arm_tdep_h =	arm-tdep.h osabi.h
 ax_h = 		ax.h $(doublest_h)
 bcache_h =	bcache.h
 builtin_regs_h = builtin-regs.h
@@ -649,7 +651,7 @@
 remote_utils_h =  remote-utils.h $(target_h)
 ser_unix_h =	ser-unix.h
 serial_h =	serial.h
-sh_tdep_h =	sh-tdep.h
+sh_tdep_h =	sh-tdep.h osabi.h
 solist_h =	solist.h
 source_h =	source.h
 stabsread_h =	stabsread.h
@@ -724,7 +726,7 @@
 	expprint.o environ.o stack.o thread.o \
 	macrotab.o macrocmd.o macroexp.o macroscope.o \
 	event-loop.o event-top.o inf-loop.o completer.o \
-	gdbarch.o arch-utils.o gdbtypes.o copying.o $(DEPFILES) \
+	gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o $(DEPFILES) \
 	memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \
 	builtin-regs.o std-regs.o \
 	signals.o \
@@ -1256,44 +1258,44 @@
 	$(regcache_h)
 
 alpha-nat.o: alpha-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(target_h) \
-	$(regcache_h) alpha-tdep.h
+	$(regcache_h) $(alpha_tdep_h)
 
 alphabsd-nat.o: alphabsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
-	alpha-tdep.h alphabsd-tdep.h
+	$(alpha_tdep_h) alphabsd-tdep.h
 
 alpha-tdep.o: alpha-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
 	$(inferior_h) $(symtab_h) $(dis_asm_h) $(gdb_string_h) $(linespec_h) \
-	$(regcache_h) $(doublest_h) $(BFD_SRC)/elf-bfd.h alpha-tdep.h
+	$(regcache_h) $(doublest_h) $(BFD_SRC)/elf-bfd.h $(alpha_tdep_h)
 
-alpha-linux-tdep.o: alpha-linux-tdep.c $(defs_h) $(value_h) alpha-tdep.h
+alpha-linux-tdep.o: alpha-linux-tdep.c $(defs_h) $(value_h) $(alpha_tdep_h)
 
-alpha-osf1-tdep.o: alpha-osf1-tdep.c $(defs_h) $(value_h) alpha-tdep.h
+alpha-osf1-tdep.o: alpha-osf1-tdep.c $(defs_h) $(value_h) $(alpha_tdep_h)
 
 alphabsd-tdep.o: alphabsd-tdep.c $(defs_h) $(regcache_h) alphabsd-tdep.h
 
-alphafbsd-tdep.o: alphafbsd-tdep.c $(defs_h) $(value_h) alpha-tdep.h
+alphafbsd-tdep.o: alphafbsd-tdep.c $(defs_h) $(value_h) $(alpha_tdep_h)
 
 alphanbsd-tdep.o: alphanbsd-tdep.c $(defs_h) $(gdbcore_h) $(regcache_h) \
-	$(value_h) alpha-tdep.h alphabsd-tdep.h nbsd-tdep.h
+	$(value_h) $(alpha_tdep_h) alphabsd-tdep.h nbsd-tdep.h
 
 annotate.o: annotate.c $(defs_h) $(annotate_h) $(value_h) $(target_h) $(gdbtypes_h)
 
 arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
-	$(gdb_string_h) $(regcache_h) arm-tdep.h
+	$(gdb_string_h) $(regcache_h) $(arm_tdep_h)
 
 arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \
-	$(gdbtypes_h) $(floatformat_h) $(regcache_h) $(doublest_h) arm-tdep.h
+	$(gdbtypes_h) $(floatformat_h) $(regcache_h) $(doublest_h) $(arm_tdep_h)
 
 arm-tdep.o: arm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcmd_h) \
 	$(gdbcore_h) $(gdb_string_h) $(dis_asm_h) $(regcache_h) $(doublest_h) \
-	$(value_h) $(arch_utils_h) $(solib_svr4_h) arm-tdep.h \
+	$(value_h) $(arch_utils_h) $(solib_svr4_h) $(arm_tdep_h) \
 	$(BFD_SRC)/elf-bfd.h $(INCLUDE_DIR)/coff/internal.h \
 	$(INCLUDE_DIR)/elf/arm.h 
 
-armnbsd-nat.o: armnbsd-nat.c $(defs_h) arm-tdep.h $(inferior_h) $(regcache_h) \
-	$(gdbcore_h)
+armnbsd-nat.o: armnbsd-nat.c $(defs_h) $(arm_tdep_h) $(inferior_h) \
+	$(regcache_h) $(gdbcore_h)
 
-armnbsd-tdep.o: armnbsd-tdep.c $(defs_h) arm-tdep.h
+armnbsd-tdep.o: armnbsd-tdep.c $(defs_h) $(arm_tdep_h)
 
 avr-tdep.o: avr-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
 	$(symfile_h) $(regcache_h) $(arch_utils_h)
@@ -1585,6 +1587,8 @@
 	$(gdbtypes_h) $(language_h) $(objfiles_h) $(symfile_h) $(symtab_h) \
 	$(target_h) $(value_h) $(gdb_string_h) $(wrapper_h) $(cp_abi_h)
 
+osabi.o: osabi.c $(defs_h) $(BFD_SRC)/elf-bfd.h
+
 go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) $(gdb_wait_h) $(gdbcore_h) \
 	$(command_h) $(floatformat_h) $(target_h) i387-tdep.h $(regcache_h)
 
@@ -1811,7 +1815,8 @@
 
 mips-tdep.o: mips-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
 	$(arch_utils_h) $(regcache_h) \
-	$(inferior_h) $(language_h) $(objfiles_h) $(symfile_h) $(gdb_string_h)
+	$(inferior_h) $(language_h) $(objfiles_h) $(symfile_h) \
+	$(gdb_string_h) osabi.h
 
 mipsread.o: mipsread.c $(buildsym_h) $(complaints_h) $(bfd_h) $(defs_h) \
 	$(expression_h) $(gdb_stabs_h) $(gdbcore_h) $(gdbtypes_h) \
@@ -1933,7 +1938,7 @@
 	$(version_h) $(regcache_h)
 
 remote-rdi.o: remote-rdi.c $(defs_h) $(gdbcore_h) \
-	$(inferior_h) $(gdb_string_h) $(completer_h) arm-tdep.h
+	$(inferior_h) $(gdb_string_h) $(completer_h) $(arm_tdep_h)
 
 rdi-share/libangsd.a:	force
 	@dir=rdi-share; \
@@ -1946,7 +1951,7 @@
 	fi
 
 remote-rdp.o: remote-rdp.c $(defs_h) $(gdbcore_h) \
-	$(inferior_h) $(gdb_string_h) arm-tdep.h
+	$(inferior_h) $(gdb_string_h) $(arm_tdep_h)
 
 remote-bug.o: remote-bug.c $(defs_h) $(gdbcore_h) $(serial_h) \
 	$(inferior_h) $(target_h) $(terminal_h) $(remote_utils_h) \
Index: alpha-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alpha-linux-tdep.c,v
retrieving revision 1.5
diff -u -r1.5 alpha-linux-tdep.c
--- alpha-linux-tdep.c	26 Apr 2002 07:05:34 -0000	1.5
+++ alpha-linux-tdep.c	21 May 2002 15:15:34 -0000
@@ -116,5 +116,6 @@
 void
 _initialize_alpha_linux_tdep (void)
 {
-  alpha_gdbarch_register_os_abi (ALPHA_ABI_LINUX, alpha_linux_init_abi);
+  gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_LINUX,
+                          alpha_linux_init_abi);
 }
Index: alpha-osf1-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alpha-osf1-tdep.c,v
retrieving revision 1.4
diff -u -r1.4 alpha-osf1-tdep.c
--- alpha-osf1-tdep.c	26 Apr 2002 07:05:34 -0000	1.4
+++ alpha-osf1-tdep.c	21 May 2002 15:15:34 -0000
@@ -69,5 +69,5 @@
 void
 _initialize_alpha_osf1_tdep (void)
 {
-  alpha_gdbarch_register_os_abi (ALPHA_ABI_OSF1, alpha_osf1_init_abi);
+  gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_OSF1, alpha_osf1_init_abi);
 }
Index: alpha-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alpha-tdep.c,v
retrieving revision 1.33
diff -u -r1.33 alpha-tdep.c
--- alpha-tdep.c	5 May 2002 18:49:57 -0000	1.33
+++ alpha-tdep.c	21 May 2002 15:15:35 -0000
@@ -1766,186 +1766,6 @@
 }
 
 
-/* This table matches the indices assigned to enum alpha_abi.  Keep
-   them in sync.  */
-static const char * const alpha_abi_names[] =
-{
-  "<unknown>",
-  "OSF/1",
-  "GNU/Linux",
-  "FreeBSD",
-  "NetBSD",
-  NULL
-};
-
-static void
-process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
-{
-  enum alpha_abi *os_ident_ptr = 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);
-
-      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);
-
-      if (name_length == 4 && data_length == 16 && note_type == 1
-	  && strcmp (note + 12, "GNU") == 0)
-	{
-	  int os_number = bfd_h_get_32 (abfd, note + 16);
-
-	  /* The case numbers are from abi-tags in glibc.  */
-	  switch (os_number)
-	    {
-	    case 0 :
-	      *os_ident_ptr = ALPHA_ABI_LINUX;
-	      break;
-
-	    case 1 :
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: Hurd objects not supported");
-	      break;
-
-	    case 2 :
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: Solaris objects not supported");
-	      break;
-
-	    default :
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: unknown OS number %d",
-		 os_number);
-	      break;
-	    }
-	}
-    }
-  /* 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 == 1
-	  && strcmp (note + 12, "NetBSD") == 0)
-	/* XXX Should we check the version here?
-	   Probably not necessary yet.  */
-	*os_ident_ptr = ALPHA_ABI_NETBSD;
-    }
-}
-
-static int
-get_elfosabi (bfd *abfd)
-{
-  int elfosabi;
-  enum alpha_abi alpha_abi = ALPHA_ABI_UNKNOWN;
-
-  elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
-
-  /* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate
-     what we're on a SYSV system.  However, GNU/Linux uses a note section
-     to record OS/ABI info, but leaves e_ident[EI_OSABI] zero.  So we
-     have to check the note sections too.  */
-  if (elfosabi == 0)
-    {
-      bfd_map_over_sections (abfd,
-			     process_note_abi_tag_sections,
-			     &alpha_abi);
-    }
-
-  if (alpha_abi != ALPHA_ABI_UNKNOWN)
-    return alpha_abi;
-
-  switch (elfosabi)
-    {
-    case ELFOSABI_NONE:
-      /* Leave it as unknown.  */
-      break;
-
-    case ELFOSABI_NETBSD:
-      return ALPHA_ABI_NETBSD;
-
-    case ELFOSABI_FREEBSD:
-      return ALPHA_ABI_FREEBSD;
-
-    case ELFOSABI_LINUX:
-      return ALPHA_ABI_LINUX;
-    }
-
-  return ALPHA_ABI_UNKNOWN;
-}
-
-struct alpha_abi_handler
-{
-  struct alpha_abi_handler *next;
-  enum alpha_abi abi;
-  void (*init_abi)(struct gdbarch_info, struct gdbarch *);
-};
-
-struct alpha_abi_handler *alpha_abi_handler_list = NULL;
-
-void
-alpha_gdbarch_register_os_abi (enum alpha_abi abi,
-                               void (*init_abi)(struct gdbarch_info,
-						struct gdbarch *))
-{
-  struct alpha_abi_handler **handler_p;
-
-  for (handler_p = &alpha_abi_handler_list; *handler_p != NULL;
-       handler_p = &(*handler_p)->next)
-    {
-      if ((*handler_p)->abi == abi)
-	{
-	  internal_error
-	    (__FILE__, __LINE__,
-	     "alpha_gdbarch_register_os_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 alpha_abi_handler *) xmalloc (sizeof (struct alpha_abi_handler));
-  (*handler_p)->next = NULL;
-  (*handler_p)->abi = abi;
-  (*handler_p)->init_abi = init_abi;
-}
 
 /* Initialize the current architecture based on INFO.  If possible, re-use an
    architecture from ARCHES, which is a list of architectures already created
@@ -1959,27 +1779,18 @@
 {
   struct gdbarch_tdep *tdep;
   struct gdbarch *gdbarch;
-  enum alpha_abi alpha_abi = ALPHA_ABI_UNKNOWN;
-  struct alpha_abi_handler *abi_handler;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
   /* Try to determine the ABI of the object we are loading.  */
 
   if (info.abfd != NULL)
     {
-      switch (bfd_get_flavour (info.abfd))
+      osabi = gdbarch_lookup_osabi (info.abfd);
+      if (osabi == GDB_OSABI_UNKNOWN)
 	{
-	case bfd_target_elf_flavour:
-	  alpha_abi = get_elfosabi (info.abfd);
-	  break;
-
-	case bfd_target_ecoff_flavour:
-	  /* Assume it's OSF/1.  */
-	  alpha_abi = ALPHA_ABI_OSF1;
-          break;
-
-	default:
-	  /* Not sure what to do here, leave the ABI as unknown.  */
-	  break;
+	  /* If it's an ECOFF file, assume it's OSF/1.  */
+	  if (bfd_get_flavour (info.abfd) == bfd_target_ecoff_flavour)
+	    osabi = GDB_OSABI_OSF1;
 	}
     }
 
@@ -1990,22 +1801,14 @@
     {
       /* Make sure the ABI selection matches.  */
       tdep = gdbarch_tdep (arches->gdbarch);
-      if (tdep && tdep->alpha_abi == alpha_abi)
+      if (tdep && tdep->osabi == osabi)
 	return arches->gdbarch;
     }
 
   tdep = xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  tdep->alpha_abi = alpha_abi;
-  if (alpha_abi < ALPHA_ABI_INVALID)
-    tdep->abi_name = alpha_abi_names[alpha_abi];
-  else
-    {
-      internal_error (__FILE__, __LINE__, "Invalid setting of alpha_abi %d",
-		      (int) alpha_abi);
-      tdep->abi_name = "<invalid>";
-    }
+  tdep->osabi = osabi;
 
   /* Lowest text address.  This is used by heuristic_proc_start() to
      decide when to stop looking.  */
@@ -2122,38 +1925,7 @@
   set_gdbarch_frame_args_skip (gdbarch, 0);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
-  if (alpha_abi == ALPHA_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 Alpha settings");
-    }
-  else
-    {
-      for (abi_handler = alpha_abi_handler_list; abi_handler != NULL;
-	   abi_handler = abi_handler->next)
-	if (abi_handler->abi == alpha_abi)
-	  break;
-
-      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 Alpha settings",
-	       alpha_abi_names[alpha_abi]);
-	}
-    }
+  gdbarch_init_osabi (info, gdbarch, osabi);
 
   /* Now that we have tuned the configuration, set a few final things
      based on what the OS ABI has told us.  */
@@ -2172,12 +1944,8 @@
   if (tdep == NULL)
     return;
 
-  if (tdep->abi_name != NULL)
-    fprintf_unfiltered (file, "alpha_dump_tdep: ABI = %s\n", tdep->abi_name);
-  else
-    internal_error (__FILE__, __LINE__,
-		    "alpha_dump_tdep: illegal setting of tdep->alpha_abi (%d)",
-		    (int) tdep->alpha_abi);
+  fprintf_unfiltered (file, "alpha_dump_tdep: OS ABI = %s\n",
+		      gdbarch_osabi_name (tdep->osabi));
 
   fprintf_unfiltered (file,
                       "alpha_dump_tdep: vm_min_address = 0x%lx\n",
Index: alpha-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/alpha-tdep.h,v
retrieving revision 1.7
diff -u -r1.7 alpha-tdep.h
--- alpha-tdep.h	26 Apr 2002 07:05:34 -0000	1.7
+++ alpha-tdep.h	21 May 2002 15:15:36 -0000
@@ -22,6 +22,8 @@
 #ifndef ALPHA_TDEP_H
 #define ALPHA_TDEP_H
 
+#include "osabi.h"
+
 /* Say how long (ordinary) registers are.  This is a piece of bogosity
    used in push_word and a few other places;  REGISTER_RAW_SIZE is the
    real way to know how big a register is.  */
@@ -76,24 +78,10 @@
    pointer, the value of localoff is obtained from the PDR.  */
 #define ALPHA_NUM_ARG_REGS   6
 
-/* ABI variants that we know about.  If you add to this enum, please
-   update the table of names in alpha-tdep.c.  */
-enum alpha_abi
-{
-  ALPHA_ABI_UNKNOWN = 0,
-  ALPHA_ABI_OSF1,
-  ALPHA_ABI_LINUX,
-  ALPHA_ABI_FREEBSD,
-  ALPHA_ABI_NETBSD,
-
-  ALPHA_ABI_INVALID	/* Keep this last. */
-};
-
 /* Target-dependent structure in gdbarch.  */
 struct gdbarch_tdep
 {
-  enum alpha_abi alpha_abi;	/* OS/ABI of inferior.  */
-  const char *abi_name;		/* Name of the above.  */
+  enum gdb_osabi osabi;		/* OS/ABI of inferior.  */
 
   CORE_ADDR vm_min_address;	/* used by heuristic_proc_start */
 
@@ -117,9 +105,5 @@
 };
 
 void alpha_software_single_step (enum target_signal, int);
-
-void alpha_gdbarch_register_os_abi (enum alpha_abi,
-                                    void (*init_abi)(struct gdbarch_info,
-						     struct gdbarch *));
 
 #endif /* ALPHA_TDEP_H */
Index: alphafbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alphafbsd-tdep.c,v
retrieving revision 1.4
diff -u -r1.4 alphafbsd-tdep.c
--- alphafbsd-tdep.c	26 Apr 2002 01:08:19 -0000	1.4
+++ alphafbsd-tdep.c	21 May 2002 15:15:36 -0000
@@ -78,5 +78,6 @@
 void
 _initialize_alphafbsd_tdep (void)
 {
-  alpha_gdbarch_register_os_abi (ALPHA_ABI_FREEBSD, alphafbsd_init_abi);
+  gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_FREEBSD_ELF,
+                          alphafbsd_init_abi);
 }
Index: alphanbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alphanbsd-tdep.c,v
retrieving revision 1.5
diff -u -r1.5 alphanbsd-tdep.c
--- alphanbsd-tdep.c	11 May 2002 22:14:19 -0000	1.5
+++ alphanbsd-tdep.c	21 May 2002 15:15:36 -0000
@@ -203,7 +203,8 @@
 void
 _initialize_alphanbsd_tdep (void)
 {
-  alpha_gdbarch_register_os_abi (ALPHA_ABI_NETBSD, alphanbsd_init_abi);
+  gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_NETBSD_ELF,
+                          alphanbsd_init_abi);
 
   add_core_fns (&alphanbsd_core_fns);
   add_core_fns (&alphanbsd_elfcore_fns);
Index: arm-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-linux-tdep.c,v
retrieving revision 1.21
diff -u -r1.21 arm-linux-tdep.c
--- arm-linux-tdep.c	15 May 2002 12:29:41 -0000	1.21
+++ arm-linux-tdep.c	21 May 2002 15:15:36 -0000
@@ -543,5 +543,5 @@
 void
 _initialize_arm_linux_tdep (void)
 {
-  arm_gdbarch_register_os_abi (ARM_ABI_LINUX, arm_linux_init_abi);
+  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_LINUX, arm_linux_init_abi);
 }
Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.61
diff -u -r1.61 arm-tdep.c
--- arm-tdep.c	17 May 2002 00:05:24 -0000	1.61
+++ arm-tdep.c	21 May 2002 15:15:39 -0000
@@ -93,23 +93,6 @@
 #define MSYMBOL_SIZE(msym)				\
 	((long) MSYMBOL_INFO (msym) & 0x7fffffff)
 
-/* This table matches the indices assigned to enum arm_abi. 
-   Keep them in sync.  */
-
-static const char * const arm_abi_names[] =
-{
-  "<unknown>",
-  "ARM EABI (version 1)",
-  "ARM EABI (version 2)",
-  "GNU/Linux",
-  "NetBSD (a.out)",
-  "NetBSD (ELF)",
-  "APCS",
-  "FreeBSD",
-  "Windows CE",
-  NULL
-};
-
 /* Number of different reg name sets (options).  */
 static int num_flavor_options;
 
@@ -2608,208 +2591,82 @@
 }
 
 
-static void
-process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
+static enum gdb_osabi
+arm_elf_osabi_sniffer (bfd *abfd)
 {
-  enum arm_abi *os_ident_ptr = obj;
-  const char *name;
-  unsigned int sectsize;
+  unsigned int elfosabi, eflags;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
-  name = bfd_get_section_name (abfd, sect);
-  sectsize = bfd_section_size (abfd, sect);
+  elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
 
-  if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0)
+  switch (elfosabi)
     {
-      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);
-
-      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);
-
-      if (name_length == 4 && data_length == 16 && note_type == 1
-          && strcmp (note + 12, "GNU") == 0)
-	{
-	  int os_number = bfd_h_get_32 (abfd, note + 16);
-
-	  /* The case numbers are from abi-tags in glibc.  */
-	  switch (os_number)
+    case ELFOSABI_NONE:  
+      /* When elfosabi is ELFOSABI_NONE (0), then the ELF structures in the
+	 file are conforming to the base specification for that machine 
+	 (there are no OS-specific extensions).  In order to determine the 
+	 real OS in use we must look for OS notes that have been added.  */
+      bfd_map_over_sections (abfd,
+			     generic_elf_osabi_sniff_abi_tag_sections,  
+			     &osabi);
+      if (osabi == GDB_OSABI_UNKNOWN)
+	{
+	  /* Existing ARM tools don't set this field, so look at the EI_FLAGS
+	     field for more information.  */
+	  eflags = EF_ARM_EABI_VERSION(elf_elfheader(abfd)->e_flags);
+	  switch (eflags)
 	    {
-	    case 0 :
-	      *os_ident_ptr = ARM_ABI_LINUX;
+	    case EF_ARM_EABI_VER1:
+	      osabi = GDB_OSABI_ARM_EABI_V1;
 	      break;
 
-	    case 1 :
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: Hurd objects not supported");
+	    case EF_ARM_EABI_VER2:
+	      osabi = GDB_OSABI_ARM_EABI_V2;
 	      break;
 
-	    case 2 :
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: Solaris objects not supported");
+	    case EF_ARM_EABI_UNKNOWN:
+	      /* Assume GNU tools.  */
+	      osabi = GDB_OSABI_ARM_APCS;
 	      break;
 
-	    default :
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: unknown OS number %d",
-		 os_number);
-	      break;
+	    default:
+	      internal_error (__FILE__, __LINE__,
+			      "arm_elf_osabi_sniffer: Unknown ARM EABI "
+			      "version 0x%x", eflags);
 	    }
 	}
-    }
-  /* 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 == 1
-          && strcmp (note + 12, "NetBSD") == 0)
-	/* XXX Should we check the version here?
-	   Probably not necessary yet.  */
-	*os_ident_ptr = ARM_ABI_NETBSD_ELF;
-    }
-}
-
-/* Return one of the ELFOSABI_ constants for BFDs representing ELF
-   executables.  If it's not an ELF executable or if the OS/ABI couldn't
-   be determined, simply return -1.  */
-
-static int
-get_elfosabi (bfd *abfd)
-{
-  int elfosabi;
-  enum arm_abi arm_abi = ARM_ABI_UNKNOWN;
-
-  elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
+      break;
 
-  /* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate
-     that we're on a SYSV system.  However, GNU/Linux uses a note section
-     to record OS/ABI info, but leaves e_ident[EI_OSABI] zero.  So we
-     have to check the note sections too.
-
-     GNU/ARM tools set the EI_OSABI field to ELFOSABI_ARM, so handle that
-     as well.  */
-  if (elfosabi == 0 || elfosabi == ELFOSABI_ARM)
-    {
+    case ELFOSABI_ARM:
+      /* GNU tools use this value.  Check note sections in this case,
+	 as well.  */
       bfd_map_over_sections (abfd,
-			     process_note_abi_tag_sections,
-			     &arm_abi);
-    }
-
-  if (arm_abi != ARM_ABI_UNKNOWN)
-    return arm_abi;
-
-  switch (elfosabi)
-    {
-    case ELFOSABI_NONE:
-      /* Existing ARM Tools don't set this field, so look at the EI_FLAGS
-	 field for more information.  */
-
-      switch (EF_ARM_EABI_VERSION(elf_elfheader(abfd)->e_flags))
+			     generic_elf_osabi_sniff_abi_tag_sections, 
+			     &osabi);
+      if (osabi == GDB_OSABI_UNKNOWN)
 	{
-	case EF_ARM_EABI_VER1:
-	  return ARM_ABI_EABI_V1;
-
-	case EF_ARM_EABI_VER2:
-	  return ARM_ABI_EABI_V2;
-
-	case EF_ARM_EABI_UNKNOWN:
-	  /* Assume GNU tools.  */
-	  return ARM_ABI_APCS;
-
-	default:
-	  internal_error (__FILE__, __LINE__,
-			  "get_elfosabi: Unknown ARM EABI version 0x%lx",
-			  EF_ARM_EABI_VERSION(elf_elfheader(abfd)->e_flags));
-
+	  /* Assume APCS ABI.  */
+	  osabi = GDB_OSABI_ARM_APCS;
 	}
       break;
 
-    case ELFOSABI_NETBSD:
-      return ARM_ABI_NETBSD_ELF;
-
     case ELFOSABI_FREEBSD:
-      return ARM_ABI_FREEBSD;
-
-    case ELFOSABI_LINUX:
-      return ARM_ABI_LINUX;
-
-    case ELFOSABI_ARM:
-      /* Assume GNU tools with the old APCS abi.  */
-      return ARM_ABI_APCS;
-
-    default:
-    }
-
-  return ARM_ABI_UNKNOWN;
-}
-
-struct arm_abi_handler
-{
-  struct arm_abi_handler *next;
-  enum arm_abi abi;
-  void (*init_abi)(struct gdbarch_info, struct gdbarch *);
-};
-
-struct arm_abi_handler *arm_abi_handler_list = NULL;
+      osabi = GDB_OSABI_FREEBSD_ELF;
+      break;
 
-void
-arm_gdbarch_register_os_abi (enum arm_abi abi,
-			     void (*init_abi)(struct gdbarch_info,
-					      struct gdbarch *))
-{
-  struct arm_abi_handler **handler_p;
+    case ELFOSABI_NETBSD:
+      osabi = GDB_OSABI_NETBSD_ELF;
+      break;
 
-  for (handler_p = &arm_abi_handler_list; *handler_p != NULL;
-       handler_p = &(*handler_p)->next)
-    {
-      if ((*handler_p)->abi == abi)
-	{
-	  internal_error
-	    (__FILE__, __LINE__,
-	     "arm_gdbarch_register_os_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;
-	}
+    case ELFOSABI_LINUX:
+      osabi = GDB_OSABI_LINUX;
+      break;
     }
 
-  (*handler_p)
-    = (struct arm_abi_handler *) xmalloc (sizeof (struct arm_abi_handler));
-  (*handler_p)->next = NULL;
-  (*handler_p)->abi = abi;
-  (*handler_p)->init_abi = init_abi;
+  return osabi;
 }
 
+
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
    architectures already created during this debugging session.
@@ -2822,36 +2679,31 @@
 {
   struct gdbarch_tdep *tdep;
   struct gdbarch *gdbarch;
-  enum arm_abi arm_abi = ARM_ABI_UNKNOWN;
-  struct arm_abi_handler *abi_handler;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
   /* Try to deterimine the ABI of the object we are loading.  */
 
   if (info.abfd != NULL)
     {
-      switch (bfd_get_flavour (info.abfd))
+      osabi = gdbarch_lookup_osabi (info.abfd);
+      if (osabi == GDB_OSABI_UNKNOWN)
 	{
-	case bfd_target_elf_flavour:
-	  arm_abi = get_elfosabi (info.abfd);
-	  break;
-
-	case bfd_target_aout_flavour:
-	  if (strcmp (bfd_get_target(info.abfd), "a.out-arm-netbsd") == 0)
-	    arm_abi = ARM_ABI_NETBSD_AOUT;
-	  else
-	    /* Assume it's an old APCS-style ABI.  */
-	    arm_abi = ARM_ABI_APCS;
-	  break;
+	  switch (bfd_get_flavour (info.abfd))
+	    {
+	    case bfd_target_aout_flavour:
+	      /* Assume it's an old APCS-style ABI.  */
+	      osabi = GDB_OSABI_ARM_APCS;
+	      break;
 
-	case bfd_target_coff_flavour:
-	  /* Assume it's an old APCS-style ABI.  */
-	  /* XXX WinCE?  */
-	  arm_abi = ARM_ABI_APCS;
-	  break;
+	    case bfd_target_coff_flavour:
+	      /* Assume it's an old APCS-style ABI.  */
+	      /* XXX WinCE?  */
+	      osabi = GDB_OSABI_ARM_APCS;
+	      break;
 
-	default:
-	  /* Not sure what to do here, leave the ABI as unknown.  */
-	  break;
+	    default:
+	      /* Leave it as "unknown".  */
+	    }
 	}
     }
 
@@ -2862,22 +2714,14 @@
     {
       /* Make sure the ABI selection matches.  */
       tdep = gdbarch_tdep (arches->gdbarch);
-      if (tdep && tdep->arm_abi == arm_abi)
+      if (tdep && tdep->osabi == osabi)
 	return arches->gdbarch;
     }
 
   tdep = xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  tdep->arm_abi = arm_abi;
-  if (arm_abi < ARM_ABI_INVALID)
-    tdep->abi_name = arm_abi_names[arm_abi];
-  else
-    {
-      internal_error (__FILE__, __LINE__, "Invalid setting of arm_abi %d",
-		      (int) arm_abi);
-      tdep->abi_name = "<invalid>";
-    }
+  tdep->osabi = osabi;
 
   /* This is the way it has always defaulted.  */
   tdep->fp_model = ARM_FLOAT_FPA;
@@ -3047,38 +2891,7 @@
 					 arm_coff_make_msymbol_special);
 
   /* Hook in the ABI-specific overrides, if they have been registered.  */
-  if (arm_abi == ARM_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 ARM settings");
-    }
-  else
-    {
-      for (abi_handler = arm_abi_handler_list; abi_handler != NULL;
-	   abi_handler = abi_handler->next)
-	if (abi_handler->abi == arm_abi)
-	  break;
-
-      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 ARM settings",
-	       arm_abi_names[arm_abi]);
-	}
-    }
+  gdbarch_init_osabi (info, gdbarch, osabi);
 
   /* Now we have tuned the configuration, set a few final things,
      based on what the OS ABI has told us.  */
@@ -3144,12 +2957,8 @@
   if (tdep == NULL)
     return;
 
-  if (tdep->abi_name != NULL)
-    fprintf_unfiltered (file, "arm_dump_tdep: ABI = %s\n", tdep->abi_name);
-  else
-    internal_error (__FILE__, __LINE__,
-		    "arm_dump_tdep: illegal setting of tdep->arm_abi (%d)",
-		    (int) tdep->arm_abi);
+  fprintf_unfiltered (file, "arm_dump_tdep: OS ABI = %s\n",
+		      gdbarch_osabi_name (tdep->osabi));
 
   fprintf_unfiltered (file, "arm_dump_tdep: Lowest pc = 0x%lx",
 		      (unsigned long) tdep->lowest_pc);
@@ -3191,10 +3000,18 @@
   if (GDB_MULTI_ARCH)
     gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
 
+  /* Register an ELF OS ABI sniffer for ARM binaries.  */
+  gdbarch_register_osabi_sniffer (bfd_arch_arm,
+				  bfd_target_elf_flavour,
+				  arm_elf_osabi_sniffer);
+
   /* Register some ABI variants for embedded systems.  */
-  arm_gdbarch_register_os_abi (ARM_ABI_EABI_V1, arm_init_abi_eabi_v1);
-  arm_gdbarch_register_os_abi (ARM_ABI_EABI_V2, arm_init_abi_eabi_v2);
-  arm_gdbarch_register_os_abi (ARM_ABI_APCS, arm_init_abi_apcs);
+  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_EABI_V1,
+                          arm_init_abi_eabi_v1);
+  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_EABI_V2,
+                          arm_init_abi_eabi_v2);
+  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_APCS,
+                          arm_init_abi_apcs);
 
   tm_print_insn = gdb_print_insn_arm;
 
Index: arm-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.h,v
retrieving revision 1.8
diff -u -r1.8 arm-tdep.h
--- arm-tdep.h	7 May 2002 12:58:51 -0000	1.8
+++ arm-tdep.h	21 May 2002 15:15:39 -0000
@@ -18,6 +18,8 @@
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include "osabi.h"
+
 /* Register numbers of various important registers.  Note that some of
    these values are "real" register numbers, and correspond to the
    general registers of the machine, and some are "phony" register
@@ -104,23 +106,6 @@
 #define FLAG_C		0x20000000
 #define FLAG_V		0x10000000
 
-/* ABI variants that we know about.  If you add to this enum, please 
-   update the table of names in tm-arm.c.  */
-enum arm_abi
-{
-  ARM_ABI_UNKNOWN = 0,
-  ARM_ABI_EABI_V1,
-  ARM_ABI_EABI_V2,
-  ARM_ABI_LINUX,
-  ARM_ABI_NETBSD_AOUT,
-  ARM_ABI_NETBSD_ELF,
-  ARM_ABI_APCS,
-  ARM_ABI_FREEBSD,
-  ARM_ABI_WINCE,
-
-  ARM_ABI_INVALID	/* Keep this last.  */
-};
-
 /* Type of floating-point code in use by inferior.  There are really 3 models
    that are traditionally supported (plus the endianness issue), but gcc can
    only generate 2 of those.  The third is APCS_FLOAT, where arguments to
@@ -139,8 +124,7 @@
 /* Target-dependent structure in gdbarch.  */
 struct gdbarch_tdep
 {
-  enum arm_abi arm_abi;		/* OS/ABI of inferior.  */
-  const char *abi_name;		/* Name of the above.  */
+  enum gdb_osabi osabi;		/* OS/ABI of inferior.  */
 
   enum arm_float_model fp_model; /* Floating point calling conventions.  */
 
@@ -170,10 +154,3 @@
 CORE_ADDR thumb_get_next_pc (CORE_ADDR);
 
 CORE_ADDR arm_get_next_pc (CORE_ADDR);
-
-/* How a OS variant tells the ARM generic code that it can handle an ABI
-   type. */
-void
-arm_gdbarch_register_os_abi (enum arm_abi abi,
-			     void (*init_abi)(struct gdbarch_info,
-					      struct gdbarch *));
Index: armnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/armnbsd-tdep.c,v
retrieving revision 1.4
diff -u -r1.4 armnbsd-tdep.c
--- armnbsd-tdep.c	19 Feb 2002 19:20:31 -0000	1.4
+++ armnbsd-tdep.c	21 May 2002 15:15:39 -0000
@@ -77,9 +77,23 @@
   tdep->fp_model = ARM_FLOAT_SOFT_VFP;
 }
 
+static enum gdb_osabi
+arm_netbsd_aout_osabi_sniffer (bfd *abfd)
+{
+  if (strcmp (bfd_get_target (abfd), "a.out-arm-netbsd") == 0)
+    return GDB_OSABI_NETBSD_AOUT;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
 void
 _initialize_arm_netbsd_tdep (void)
 {
-  arm_gdbarch_register_os_abi (ARM_ABI_NETBSD_AOUT, arm_netbsd_aout_init_abi);
-  arm_gdbarch_register_os_abi (ARM_ABI_NETBSD_ELF, arm_netbsd_elf_init_abi);
+  gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_aout_flavour,
+				  arm_netbsd_aout_osabi_sniffer);
+
+  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_NETBSD_AOUT,
+                          arm_netbsd_aout_init_abi);
+  gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_NETBSD_ELF,
+                          arm_netbsd_elf_init_abi);
 }
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.73
diff -u -r1.73 mips-tdep.c
--- mips-tdep.c	11 May 2002 14:18:15 -0000	1.73
+++ mips-tdep.c	21 May 2002 15:15:46 -0000
@@ -38,6 +38,7 @@
 #include "target.h"
 #include "arch-utils.h"
 #include "regcache.h"
+#include "osabi.h"
 
 #include "opcode/mips.h"
 #include "elf/mips.h"
@@ -119,6 +120,7 @@
   {
     /* from the elf header */
     int elf_flags;
+
     /* mips options */
     enum mips_abi mips_abi;
     const char *mips_abi_string;
@@ -131,6 +133,8 @@
     int mips_default_stack_argsize;
     int gdb_target_is_mips64;
     int default_mask_address_p;
+
+    enum gdb_osabi osabi;
   };
 
 #if GDB_MULTI_ARCH
@@ -4132,6 +4136,7 @@
   struct gdbarch_tdep *tdep;
   int elf_flags;
   enum mips_abi mips_abi;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
   /* Reset the disassembly info, in case it was set to something
      non-default.  */
@@ -4139,12 +4144,18 @@
   tm_print_insn_info.arch = bfd_arch_unknown;
   tm_print_insn_info.mach = 0;
 
-  /* Extract the elf_flags if available */
-  if (info.abfd != NULL
-      && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
-    elf_flags = elf_elfheader (info.abfd)->e_flags;
-  else
-    elf_flags = 0;
+  elf_flags = 0;
+
+  if (info.abfd)
+    {
+      /* First of all, extract the elf_flags, if available.  */
+      if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+	elf_flags = elf_elfheader (info.abfd)->e_flags;
+
+      /* Try to determine the OS ABI of the object we are loading.  If
+	 we end up with `unknown', just leave it that way.  */
+      osabi = gdbarch_lookup_osabi (info.abfd);
+    }
 
   /* Check ELF_FLAGS to see if it specifies the ABI being used. */
   switch ((elf_flags & EF_MIPS_ABI))
@@ -4215,13 +4226,15 @@
 	continue;
       if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
 	continue;
-      return arches->gdbarch;
+      if (gdbarch_tdep (arches->gdbarch)->osabi == osabi)
+        return arches->gdbarch;
     }
 
   /* Need a new architecture. Fill in a target specific vector. */
   tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
   tdep->elf_flags = elf_flags;
+  tdep->osabi = osabi;
 
   /* Initially set everything according to the default ABI/ISA. */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -4433,6 +4446,10 @@
   set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
   set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
   set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
+
+  /* Hook in OS ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch, osabi);
+
   return gdbarch;
 }
 
@@ -4841,6 +4858,10 @@
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: _PROC_MAGIC_ = %d\n",
 		      _PROC_MAGIC_);
+
+  fprintf_unfiltered (file,
+		      "mips_dump_tdep: OS ABI = %s\n",
+		      gdbarch_osabi_name (tdep->osabi));
 }
 
 void
Index: osabi.c
===================================================================
RCS file: osabi.c
diff -N osabi.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ osabi.c	21 May 2002 15:15:47 -0000
@@ -0,0 +1,424 @@
+/* OS ABI variant handling for GDB.
+   Copyright 2001, 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 "osabi.h"
+
+#include "elf-bfd.h"
+
+
+/* This table matches the indices assigned to enum gdb_osabi.  Keep
+   them in sync.  */
+static const char * const gdb_osabi_names[] =
+{
+  "<unknown>",
+
+  "SVR4",
+  "GNU/Hurd",
+  "Solaris",
+  "OSF/1",
+  "GNU/Linux",
+  "FreeBSD a.out",
+  "FreeBSD ELF",
+  "NetBSD a.out",
+  "NetBSD ELF",
+  "Windows CE",
+
+  "ARM EABI v1",
+  "ARM EABI v2",
+  "ARM APCS",
+
+  "<invalid>"
+};
+
+const char *
+gdbarch_osabi_name (enum gdb_osabi osabi)
+{
+  if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
+    return gdb_osabi_names[osabi];
+
+  return gdb_osabi_names[GDB_OSABI_INVALID];
+}
+
+/* Handler for a given architecture/OS ABI pair.  There should be only
+   one handler for a given OS ABI each architecture family.  */
+struct gdb_osabi_handler  
+{
+  struct gdb_osabi_handler *next;
+  enum bfd_architecture arch;
+  enum gdb_osabi osabi;
+  void (*init_osabi)(struct gdbarch_info, struct gdbarch *);
+};
+
+static struct gdb_osabi_handler *gdb_osabi_handler_list;
+
+void
+gdbarch_register_osabi (enum bfd_architecture arch, enum gdb_osabi osabi,
+                        void (*init_osabi)(struct gdbarch_info,
+					   struct gdbarch *))
+{
+  struct gdb_osabi_handler **handler_p;
+
+  /* Registering an OS ABI handler for "unknown" is not allowed.  */
+  if (osabi == GDB_OSABI_UNKNOWN)
+    {
+      internal_error
+	(__FILE__, __LINE__,
+	 "gdbarch_register_osabi: An attempt to register a handler for "
+         "OS ABI \"%s\" for architecture %s was made.  The handler will "
+	 "not be registered",
+	 gdbarch_osabi_name (osabi),
+	 bfd_printable_arch_mach (arch, 0));
+      return;
+    }
+
+  for (handler_p = &gdb_osabi_handler_list; *handler_p != NULL;
+       handler_p = &(*handler_p)->next)
+    {
+      if ((*handler_p)->arch == arch
+	  && (*handler_p)->osabi == osabi)
+	{
+	  internal_error
+	    (__FILE__, __LINE__,
+	     "gdbarch_register_osabi: A handler for OS ABI \"%s\" "
+	     "has already been registered for architecture %s",
+	     gdbarch_osabi_name (osabi),
+	     bfd_printable_arch_mach (arch, 0));
+	  /* If user wants to continue, override previous definition.  */
+	  (*handler_p)->init_osabi = init_osabi;
+	  return;
+	}
+    }
+
+  (*handler_p)
+    = (struct gdb_osabi_handler *) xmalloc (sizeof (struct gdb_osabi_handler));
+  (*handler_p)->next = NULL;
+  (*handler_p)->arch = arch;
+  (*handler_p)->osabi = osabi;
+  (*handler_p)->init_osabi = init_osabi;
+}
+
+
+/* Sniffer to find the OS ABI for a given file's architecture and flavour. 
+   It is legal to have multiple sniffers for each arch/flavour pair, to
+   disambiguate one OS's a.out from another, for example.  The first sniffer
+   to return something other than GDB_OSABI_UNKNOWN wins, so a sniffer should
+   be careful to claim a file only if it knows for sure what it is.  */
+struct gdb_osabi_sniffer
+{
+  struct gdb_osabi_sniffer *next;
+  enum bfd_architecture arch;   /* bfd_arch_unknown == wildcard */
+  enum bfd_flavour flavour;
+  enum gdb_osabi (*sniffer)(bfd *);
+};
+
+static struct gdb_osabi_sniffer *gdb_osabi_sniffer_list;
+
+void
+gdbarch_register_osabi_sniffer (enum bfd_architecture arch,
+                                enum bfd_flavour flavour,
+				enum gdb_osabi (*sniffer_fn)(bfd *))
+{
+  struct gdb_osabi_sniffer *sniffer;
+
+  sniffer =
+    (struct gdb_osabi_sniffer *) xmalloc (sizeof (struct gdb_osabi_sniffer));
+  sniffer->arch = arch;
+  sniffer->flavour = flavour;
+  sniffer->sniffer = sniffer_fn;
+
+  sniffer->next = gdb_osabi_sniffer_list;
+  gdb_osabi_sniffer_list = sniffer;
+}
+
+
+enum gdb_osabi
+gdbarch_lookup_osabi (bfd *abfd)
+{
+  struct gdb_osabi_sniffer *sniffer;
+  enum gdb_osabi osabi, match;
+  int match_specific;
+
+  match = GDB_OSABI_UNKNOWN;
+  match_specific = 0;
+
+  for (sniffer = gdb_osabi_sniffer_list; sniffer != NULL;
+       sniffer = sniffer->next)
+    {
+      if ((sniffer->arch == bfd_arch_unknown /* wildcard */
+	   || sniffer->arch == bfd_get_arch (abfd))
+	  && sniffer->flavour == bfd_get_flavour (abfd))
+	{
+	  osabi = (*sniffer->sniffer) (abfd);
+	  if (osabi < GDB_OSABI_UNKNOWN || osabi >= GDB_OSABI_INVALID)
+	    {
+	      internal_error
+		(__FILE__, __LINE__,
+		 "gdbarch_lookup_osabi: invalid OS ABI (%d) from sniffer "
+		 "for architecture %s flavour %d",
+		 (int) osabi,
+		 bfd_printable_arch_mach (bfd_get_arch (abfd), 0),
+		 (int) bfd_get_flavour (abfd));
+	    }
+	  else if (osabi != GDB_OSABI_UNKNOWN)
+	    {
+	      /* A specific sniffer always overrides a generic sniffer.
+		 Croak on multiple match if the two matches are of the
+		 same class.  If the user wishes to continue, we'll use
+		 the first match.  */
+	      if (match != GDB_OSABI_UNKNOWN)
+		{
+		  if ((match_specific && sniffer->arch != bfd_arch_unknown)
+		   || (!match_specific && sniffer->arch == bfd_arch_unknown))
+		    {
+		      internal_error
+		        (__FILE__, __LINE__,
+		         "gdbarch_lookup_osabi: multiple %sspecific OS ABI "
+			 "match for architecture %s flavour %d: first "
+			 "match \"%s\", second match \"%s\"",
+			 match_specific ? "" : "non-",
+		         bfd_printable_arch_mach (bfd_get_arch (abfd), 0),
+		         (int) bfd_get_flavour (abfd),
+		         gdbarch_osabi_name (match),
+		         gdbarch_osabi_name (osabi));
+		    }
+		  else if (sniffer->arch != bfd_arch_unknown)
+		    {
+		      match = osabi;
+		      match_specific = 1;
+		    }
+		}
+	      else
+		{
+		  match = osabi;
+		  if (sniffer->arch != bfd_arch_unknown)
+		    match_specific = 1;
+		}
+	    }
+	}
+    }
+
+  return match;
+}
+
+void
+gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch,
+                    enum gdb_osabi osabi)
+{
+  struct gdb_osabi_handler *handler;
+  bfd *abfd = info.abfd;
+  const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
+
+  if (osabi == GDB_OSABI_UNKNOWN)
+    {
+      /* Don't complain about not knowing the OS ABI if we don't
+	 have an inferior.  */
+      if (info.abfd)
+	fprintf_filtered
+	  (gdb_stderr, "GDB doesn't recognize the OS ABI of the inferior.  "
+	   "Attempting to continue with the default %s settings",
+	   bfd_printable_arch_mach (arch_info->arch, arch_info->mach));
+      return;
+    }
+
+  for (handler = gdb_osabi_handler_list; handler != NULL;
+       handler = handler->next)
+    {
+      if (handler->arch == bfd_get_arch (abfd)
+	  && handler->osabi == osabi)
+	{
+	  (*handler->init_osabi) (info, gdbarch);
+	  return;
+	}
+    }
+
+  /* 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
+     the tm-file.  */
+  if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL)
+    fprintf_filtered
+      (gdb_stderr,
+       "A handler for the OS ABI \"%s\" is not built into this "
+       "configuration of GDB.  "
+       "Attempting to continue with the default %s settings",
+       gdbarch_osabi_name (osabi),
+       bfd_printable_arch_mach (arch_info->arch, arch_info->mach));
+}
+
+
+/* Generic sniffer for ELF flavoured files.  */
+
+void
+generic_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
+{
+  enum gdb_osabi *os_ident_ptr = obj;
+  const char *name;
+  unsigned int sectsize;
+
+  name = bfd_get_section_name (abfd, sect);
+  sectsize = bfd_section_size (abfd, sect);
+
+  /* .note.ABI-tag notes, used by GNU/Linux and FreeBSD.  */
+  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);
+
+      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);
+
+      if (name_length == 4 && data_length == 16 && note_type == NT_GNU_ABI_TAG
+	  && strcmp (note + 12, "GNU") == 0)
+	{
+	  int os_number = bfd_h_get_32 (abfd, note + 16);
+
+	  switch (os_number)
+	    {
+	    case GNU_ABI_TAG_LINUX:
+	      *os_ident_ptr = GDB_OSABI_LINUX;
+	      break;
+
+	    case GNU_ABI_TAG_HURD:
+	      *os_ident_ptr = GDB_OSABI_HURD;
+	      break;
+
+	    case GNU_ABI_TAG_SOLARIS:
+	      *os_ident_ptr = GDB_OSABI_SOLARIS;
+	      break;
+
+	    default:
+	      internal_error
+		(__FILE__, __LINE__,
+		 "generic_elf_osabi_sniff_abi_tag_sections: unknown OS number %d",
+		 os_number);
+	    }
+	  return;
+	}
+      else if (name_length == 8 && data_length == 4
+	       && note_type == NT_FREEBSD_ABI_TAG
+	       && strcmp (note + 12, "FreeBSD") == 0)
+	{
+	  /* XXX Should we check the version here?  Probably not
+	     necessary yet.  */
+	  *os_ident_ptr = GDB_OSABI_FREEBSD_ELF;
+	}
+      return;
+    }
+
+  /* .note.netbsd.ident notes, used by NetBSD.  */
+  if (strcmp (name, ".note.netbsd.ident") == 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);
+      
+      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);
+
+      if (name_length == 7 && data_length == 4 && note_type == NT_NETBSD_IDENT
+	  && strcmp (note + 12, "NetBSD") == 0)
+	{
+	  /* XXX Should we check the version here?  Probably not
+	     necessary yet.  */
+	  *os_ident_ptr = GDB_OSABI_NETBSD_ELF;
+	}
+      return;
+    }
+}
+
+static enum gdb_osabi
+generic_elf_osabi_sniffer (bfd *abfd)
+{
+  unsigned int elfosabi;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
+
+  elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
+
+  switch (elfosabi)
+    {
+    case ELFOSABI_NONE:
+      /* When elfosabi is ELFOSABI_NONE (0), then the ELF structures in the
+         file are conforming to the base specification for that machine
+	 (there are no OS-specific extensions).  In order to determine the
+	 real OS in use we must look for OS notes that have been added.  */
+      bfd_map_over_sections (abfd,
+			     generic_elf_osabi_sniff_abi_tag_sections,
+			     &osabi);
+      break;
+
+    case ELFOSABI_FREEBSD:
+      osabi = GDB_OSABI_FREEBSD_ELF;
+      break;
+
+    case ELFOSABI_NETBSD:
+      osabi = GDB_OSABI_NETBSD_ELF;
+      break;
+
+    case ELFOSABI_LINUX:
+      osabi = GDB_OSABI_LINUX;
+      break;
+
+    case ELFOSABI_HURD:
+      osabi = GDB_OSABI_HURD;
+      break;
+
+    case ELFOSABI_SOLARIS:
+      osabi = GDB_OSABI_SOLARIS;
+      break;
+    }
+
+  return osabi;
+}
+
+
+void
+_initialize_gdb_osabi (void)
+{
+  if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID], "<invalid>") != 0)
+    internal_error
+      (__FILE__, __LINE__,
+       "_initialize_gdb_osabi: gdb_osabi_names[] is inconsistent");
+
+  /* Register a generic sniffer for ELF flavoured files.  */
+  gdbarch_register_osabi_sniffer (bfd_arch_unknown,
+				  bfd_target_elf_flavour,
+				  generic_elf_osabi_sniffer);
+}
Index: osabi.h
===================================================================
RCS file: osabi.h
diff -N osabi.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ osabi.h	21 May 2002 15:15:47 -0000
@@ -0,0 +1,78 @@
+/* OS ABI variant handling for GDB.
+   Copyright 2001, 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 OSABI_H
+#define OSABI_H
+
+/* List of known OS ABIs.  If you change this, make sure to update the
+   table in osabi.c.  */
+enum gdb_osabi
+{
+  GDB_OSABI_UNKNOWN = 0,	/* keep this first */
+
+  GDB_OSABI_SVR4,
+  GDB_OSABI_HURD,
+  GDB_OSABI_SOLARIS,
+  GDB_OSABI_OSF1,
+  GDB_OSABI_LINUX,
+  GDB_OSABI_FREEBSD_AOUT,
+  GDB_OSABI_FREEBSD_ELF,
+  GDB_OSABI_NETBSD_AOUT,
+  GDB_OSABI_NETBSD_ELF,
+  GDB_OSABI_WINCE,
+
+  GDB_OSABI_ARM_EABI_V1,
+  GDB_OSABI_ARM_EABI_V2,
+  GDB_OSABI_ARM_APCS,
+
+  GDB_OSABI_INVALID		/* keep this last */
+};
+
+/* Register an OS ABI sniffer.  Each arch/flavour may have more than
+   one sniffer.  This is used to e.g. differentiate one OS's a.out from
+   another.  The first sniffer to return something other than
+   GDB_OSABI_UNKNOWN wins, so a sniffer should be careful to claim a file
+   only if it knows for sure what it is.  */
+void gdbarch_register_osabi_sniffer (enum bfd_architecture,
+				     enum bfd_flavour,
+				     enum gdb_osabi (*)(bfd *));
+
+/* Register a handler for an OS ABI variant for a given architecture.  There
+   should be only one handler for a given OS ABI each architecture family.  */
+void gdbarch_register_osabi (enum bfd_architecture, enum gdb_osabi,
+                             void (*)(struct gdbarch_info,
+				      struct gdbarch *));
+
+/* Lookup the OS ABI corresponding to the specified BFD.  */
+enum gdb_osabi gdbarch_lookup_osabi (bfd *);
+
+/* Initialize the gdbarch for the specified OS ABI variant.  */
+void gdbarch_init_osabi (struct gdbarch_info, struct gdbarch *,
+                         enum gdb_osabi);
+
+/* Return the name of the specified OS ABI.  */
+const char *gdbarch_osabi_name (enum gdb_osabi);
+
+/* Helper routine for ELF file sniffers.  This looks at ABI tag note
+   sections to determine the OS ABI from the note.  It should be called
+   via bfd_map_over_sections.  */
+void generic_elf_osabi_sniff_abi_tag_sections (bfd *, asection *, void *);
+
+#endif /* OSABI_H */
Index: sh-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sh-tdep.c,v
retrieving revision 1.60
diff -u -r1.60 sh-tdep.c
--- sh-tdep.c	17 May 2002 14:36:44 -0000	1.60
+++ sh-tdep.c	21 May 2002 15:15:51 -0000
@@ -4179,175 +4179,6 @@
 #endif /* SVR4_SHARED_LIBS */
 
 
-/* This table matches the indices assigned to enum sh_osabi.  Keep
-   them in sync.  */
-static const char * const sh_osabi_names[] =
-{
-  "<unknown>",
-  "GNU/Linux",
-  "NetBSD ELF",
-  NULL
-};
-
-static void
-process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
-{
-  enum sh_osabi *os_ident_ptr = 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);
-
-      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);
-
-      if (name_length == 4 && data_length == 16 && note_type == NT_GNU_ABI_TAG
-	  && strcmp (note + 12, "GNU") == 0)
-	{
-	  int os_number = bfd_h_get_32 (abfd, note + 16);
-
-	  /* The case numbers are from abi-tags in glibc.  */
-	  switch (os_number)
-	    {
-	    case GNU_ABI_TAG_LINUX:
-	      *os_ident_ptr = SH_OSABI_LINUX;
-	      break;
-
-	    case GNU_ABI_TAG_HURD:
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: Hurd objects not supported");
-	      break;
-
-	    case GNU_ABI_TAG_SOLARIS:
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: Solaris objects not supported");
-	      break;
-
-	    default:
-	      internal_error
-		(__FILE__, __LINE__,
-		 "process_note_abi_sections: unknown OS number %d",
-		 os_number);
-	    }
-	}
-    }
-  /* 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)
-	/* XXX Should we check the version here?
-	   Probably not necessary yet.  */
-	*os_ident_ptr = SH_OSABI_NETBSD_ELF;
-    }
-}
-
-static int
-get_elfosabi (bfd *abfd)
-{
-  int elfosabi;
-  enum sh_osabi sh_osabi = SH_OSABI_UNKNOWN;
-
-  elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
-
-  switch (elfosabi)
-    {
-    case ELFOSABI_NONE:
-      /* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate
-	 that we're on a SYSV system.  However, some systems use note sections
-	 to record OS/ABI info, but leave e_ident[EI_OSABI] zero.  So we
-	 have to check the note sections too.  */
-      bfd_map_over_sections (abfd,
-			     process_note_abi_tag_sections,
-			     &sh_osabi);
-      break;
-
-    case ELFOSABI_NETBSD:
-      sh_osabi = SH_OSABI_NETBSD_ELF;
-      break;
-
-    case ELFOSABI_LINUX:
-      sh_osabi = SH_OSABI_LINUX;
-      break;
-    }
-
-  return (sh_osabi);
-}
-
-struct sh_osabi_handler
-{
-  struct sh_osabi_handler *next;
-  enum sh_osabi abi;
-  void (*init_osabi)(struct gdbarch_info, struct gdbarch *);
-};
-
-struct sh_osabi_handler *sh_osabi_handler_list = NULL;
-
-void
-sh_gdbarch_register_os_abi (enum sh_osabi abi,
-                            void (*init_osabi)(struct gdbarch_info,
-					       struct gdbarch *))
-{
-  struct sh_osabi_handler **handler_p;
-
-  for (handler_p = &sh_osabi_handler_list; *handler_p != NULL;
-       handler_p = &(*handler_p)->next)
-    {
-      if ((*handler_p)->abi == abi)
-	{
-	  internal_error
-	    (__FILE__, __LINE__,
-	     "sh_gdbarch_register_os_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_osabi = init_osabi;
-	  return;
-	}
-    }
-
-  (*handler_p)
-    = (struct sh_osabi_handler *) xmalloc (sizeof (struct sh_osabi_handler));
-  (*handler_p)->next = NULL;
-  (*handler_p)->abi = abi;
-  (*handler_p)->init_osabi = init_osabi;
-}
-
 static gdbarch_init_ftype sh_gdbarch_init;
 
 static struct gdbarch *
@@ -4359,23 +4190,14 @@
   gdbarch_register_name_ftype *sh_register_name;
   gdbarch_store_return_value_ftype *sh_store_return_value;
   gdbarch_register_virtual_type_ftype *sh_register_virtual_type;
-  enum sh_osabi sh_osabi = SH_OSABI_UNKNOWN;
-  struct sh_osabi_handler *osabi_handler;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
   /* Try to determine the ABI of the object we are loading.  */
 
   if (info.abfd != NULL)
     {
-      switch (bfd_get_flavour (info.abfd))
-	{
-	case bfd_target_elf_flavour:
-	  sh_osabi = get_elfosabi (info.abfd);
-	  break;
-
-	default:
-	  /* Just leave it as "unkown".  */
-	  break;
-	}
+      osabi = gdbarch_lookup_osabi (info.abfd);
+      /* If we get "unknown" back, just leave it that way.  */
     }
 
   /* Find a candidate among the list of pre-declared architectures. */
@@ -4385,7 +4207,7 @@
     {
       /* Make sure the ABI selection matches.  */
       tdep = gdbarch_tdep (arches->gdbarch);
-      if (tdep && tdep->sh_osabi == sh_osabi)
+      if (tdep && tdep->osabi == osabi)
 	return arches->gdbarch;
     }
 
@@ -4394,15 +4216,7 @@
   tdep = XMALLOC (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  tdep->sh_osabi = sh_osabi;
-  if (sh_osabi < SH_OSABI_INVALID)
-    tdep->osabi_name = sh_osabi_names[sh_osabi];
-  else
-    {
-      internal_error (__FILE__, __LINE__, "Invalid setting of sh_osabi %d",
-		      (int) sh_osabi);
-      tdep->osabi_name = "<invalid>";
-    }
+  tdep->osabi = osabi;
 
   /* Initialize the register numbers that are not common to all the
      variants to -1, if necessary thse will be overwritten in the case
@@ -4754,32 +4568,11 @@
   set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
   set_gdbarch_believe_pcc_promotion (gdbarch, 1);
 
-  /* Hook in ABI-specific overrides, if they have been registered.  If
-     the ABI is unknown, this is probably an embedded target, so we
-     should not warn about this situation.  */
-  if (sh_osabi != SH_OSABI_UNKNOWN)
-    {
-      for (osabi_handler = sh_osabi_handler_list; osabi_handler != NULL;
-	   osabi_handler = osabi_handler->next)
-	if (osabi_handler->abi == sh_osabi)
-	  break;
+  /* Hook in ABI-specific overrides, if they have been registered.
 
-      if (osabi_handler)
-        osabi_handler->init_osabi (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 SuperH settings",
-	       sh_osabi_names[sh_osabi]);
-        }
-    }
+     FIXME: if the ABI is unknown, this is probably an embedded target,
+     so we should not warn about this situation.  */
+  gdbarch_init_osabi (info, gdbarch, osabi);
 
   return gdbarch;
 }
@@ -4792,12 +4585,8 @@
   if (tdep == NULL)
     return;
 
-  if (tdep->osabi_name != NULL)
-    fprintf_unfiltered (file, "sh_dump_tdep: OS ABI = %s\n", tdep->osabi_name);
-  else
-    internal_error (__FILE__, __LINE__,
-		    "sh_dump_tdep: illegal setting of tdep->sh_osabi (%d)",
-		    (int) tdep->sh_osabi);
+  fprintf_unfiltered (file, "sh_dump_tdep: OS ABI = %s\n",
+                      gdbarch_osabi_name (tdep->osabi));
 }
 
 void
Index: sh-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/sh-tdep.h,v
retrieving revision 1.1
diff -u -r1.1 sh-tdep.h
--- sh-tdep.h	17 May 2002 06:55:48 -0000	1.1
+++ sh-tdep.h	21 May 2002 15:15:51 -0000
@@ -22,21 +22,12 @@
 #ifndef SH_TDEP_H
 #define SH_TDEP_H
 
+#include "osabi.h"
+
 /* Contributed by Steve Chamberlain sac@cygnus.com */
 
 /* Information that is dependent on the processor variant. */
 
-/* ABI variants that we know about.  If you add to this enum, please
-   update the table of names in sh-tdep.c.  */
-enum sh_osabi
-{
-  SH_OSABI_UNKNOWN = 0,
-  SH_OSABI_LINUX,
-  SH_OSABI_NETBSD_ELF,
-
-  SH_OSABI_INVALID     /* Keep this last.  */
-};
-
 enum sh_abi
   {
     SH_ABI_UNKNOWN,
@@ -98,8 +89,7 @@
     int ARGLAST_REGNUM;
     int FLOAT_ARGLAST_REGNUM;
     int RETURN_REGNUM;
-    enum sh_osabi sh_osabi;    /* OS/ABI of the inferior */
-    const char *osabi_name;    /* Name of the above */
+    enum gdb_osabi osabi;	/* OS/ABI of the inferior */
     enum sh_abi sh_abi;
   };
 
Index: shnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/shnbsd-tdep.c,v
retrieving revision 1.4
diff -u -r1.4 shnbsd-tdep.c
--- shnbsd-tdep.c	17 May 2002 06:55:48 -0000	1.4
+++ shnbsd-tdep.c	21 May 2002 15:15:51 -0000
@@ -177,5 +177,5 @@
   add_core_fns (&shnbsd_core_fns);
   add_core_fns (&shnbsd_elfcore_fns);
 
-  sh_gdbarch_register_os_abi (SH_OSABI_NETBSD_ELF, shnbsd_init_abi);
+  gdbarch_register_osabi (bfd_arch_sh, GDB_OSABI_NETBSD_ELF, shnbsd_init_abi);
 }
Index: doc/gdbint.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
retrieving revision 1.84
diff -u -r1.84 gdbint.texinfo
--- doc/gdbint.texinfo	13 May 2002 17:20:59 -0000	1.84
+++ doc/gdbint.texinfo	21 May 2002 15:15:58 -0000
@@ -2312,6 +2312,127 @@
 @code{struct gdbarch *}.  The structure, and its methods, are generated
 using the Bourne shell script @file{gdbarch.sh}.
 
+@section Operating System ABI Variant Handling
+@cindex OS ABI variants
+
+@value{GDBN} provides a mechanism for handling variations in OS
+ABIs.  An OS ABI variant may have influence over any number of
+variables in the target architecture definition.  There are two major
+components in the OS ABI mechanism: sniffers and handlers.
+
+A @dfn{sniffer} examines a file matching a BFD architecture/flavour pair
+(the architecture may be wildcarded) in an attempt to determine the
+OS ABI of that file.  Sniffers with a wildcarded architecture are considered
+to be @dfn{generic}, while sniffers for a specific architecture are
+considered to be @dfn{specific}.  A match from a specific sniffer
+overrides a match from a generic sniffer.  Multiple sniffers for an
+architecture/flavour may exist, in order to differentiate between two
+different operating systems which use the same basic file format.  The
+OS ABI framework provides a generic sniffer for ELF-format files which
+examines the @code{EI_OSABI} field of the ELF header, as well as note
+sections known to be used by several operating systems.
+
+@cindex fine-tuning @code{gdbarch} structure
+A @dfn{handler} is used to fine-tune the @code{gdbarch} structure for the
+selected OS ABI.  There may be only one handler for a given OS ABI
+for each BFD architecture.
+
+The following OS ABI variants are defined in @file{osabi.h}:
+
+@table @code
+
+@findex GDB_OSABI_UNKNOWN
+@item GDB_OSABI_UNKNOWN
+The ABI of the inferior is unknown.  The default @code{gdbarch}
+settings for the architecture will be used.
+
+@findex GDB_OSABI_SVR4
+@item GDB_OSABI_SVR4
+UNIX System V Release 4
+
+@findex GDB_OSABI_HURD
+@item GDB_OSABI_HURD
+GNU using the Hurd kernel
+
+@findex GDB_OSABI_SOLARIS
+@item GDB_OSABI_SOLARIS
+Sun Solaris
+
+@findex GDB_OSABI_OSF1
+@item GDB_OSABI_OSF1
+OSF/1, including Digital UNIX and Compaq Tru64 UNIX
+
+@findex GDB_OSABI_LINUX
+@item GDB_OSABI_LINUX
+GNU using the Linux kernel
+
+@findex GDB_OSABI_FREEBSD_AOUT
+@item GDB_OSABI_FREEBSD_AOUT
+FreeBSD using the a.out executable format
+
+@findex GDB_OSABI_FREEBSD_ELF
+@item GDB_OSABI_FREEBSD_ELF
+FreeBSD using the ELF executable format
+
+@findex GDB_OSABI_NETBSD_AOUT
+@item GDB_OSABI_NETBSD_AOUT
+NetBSD using the a.out executable format
+
+@findex GDB_OSABI_NETBSD_ELF
+@item GDB_OSABI_NETBSD_ELF
+NetBSD using the ELF executable format
+
+@findex GDB_OSABI_WINCE
+@item GDB_OSABI_WINCE
+Windows CE
+
+@findex GDB_OSABI_ARM_EABI_V1
+@item GDB_OSABI_ARM_EABI_V1
+ARM Embedded ABI version 1
+
+@findex GDB_OSABI_ARM_EABI_V2
+@item GDB_OSABI_ARM_EABI_V2
+ARM Embedded ABI version 2
+
+@findex GDB_OSABI_ARM_APCS
+@item GDB_OSABI_ARM_APCS
+Generic ARM Procedure Call Standard
+
+@end table
+
+Here are the functions that make up the OS ABI framework:
+
+@deftypefun const char *gdbarch_osabi_name (enum gdb_osabi @var{osabi})
+Return the name of the OS ABI corresponding to @var{osabi}.
+@end deftypefun
+
+@deftypefun void gdbarch_register_osabi (enum bfd_architecture @var{arch}, enum gdb_osabi @var{osabi}, void (*@var{init_osabi})(struct gdbarch_info @var{info}, struct gdbarch *@var{gdbarch}))
+Register the OS ABI handler specified by @var{init_osabi} for the
+architecture/OS ABI pair specified by @var{arch} and @var{osabi}.
+@end deftypefun
+
+@deftypefun void gdbarch_register_osabi_sniffer (enum bfd_architecture @var{arch}, enum bfd_flavour @var{flavour}, enum gdb_osabi (*@var{sniffer})(bfd *@var{abfd}))
+Register the OS ABI file sniffer specified by @var{sniffer} for the
+BFD architecture/flavour pair specified by @var{arch} and @var{flavour}.
+If @var{arch} is @code{bfd_arch_unknown}, the sniffer is considered to
+be generic, and is allowed to examine @var{flavour}-flavoured files for
+any architecture.
+@end deftypefun
+
+@deftypefun enum gdb_osabi gdbarch_lookup_osabi (bfd *@var{abfd})
+Examine the file described by @var{abfd} to determine its OS ABI.
+The value @code{GDB_OSABI_UNKNOWN} is returned if the OS ABI cannot
+be determined.
+@end deftypefun
+
+@deftypefun void gdbarch_init_osabi (struct gdbarch info @var{info}, struct gdbarch *@var{gdbarch}, enum gdb_osabi @var{osabi})
+Invoke the OS ABI handler corresponding to @var{osabi} to fine-tune the
+@code{gdbarch} structure specified by @var{gdbarch}.  If a handler
+corresponding to @var{osabi} has not been registered for @var{gdbarch}'s
+architecture, a warning will be issued and the debugging session will continue
+with the defaults already established for @var{gdbarch}.
+@end deftypefun
+
 @section Registers and Memory
 
 @value{GDBN}'s model of the target machine is rather simple.


More information about the Gdb-patches mailing list