This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [PATCH/RFA] Generic OS ABI handling
- From: Elena Zannoni <ezannoni at redhat dot com>
- To: thorpej at wasabisystems dot com
- Cc: gdb-patches at sources dot redhat dot com
- Date: Thu, 16 May 2002 17:57:01 -0400
- Subject: Re: [PATCH/RFA] Generic OS ABI handling
- References: <20020513120839.X3435@dr-evil.shagadelic.org>
Jason R Thorpe writes:
> Ok, I think it's reached the point where I'd like to ask for formal
> approval.
I completely missed the fact that the sh-tdep.c changes were included
here, sorry.
The sh* part is approved. A question, should be osabi.h be included
in defs.h? I see that in one file you add both include osabi.h
and defs.h. Another question, have you thought about whether this new
generic mechanism applies to the rs6000-tdep.c file as well? If so, I
can make the required changes.
Elena
>
> Included in this patch are some additional internal consistency checking
> points, and documentation updates. I also moved the inclusion of osabi.h
> into defs.h, since this stuff is somewhat tightly coupled to the whole
> gdbarch framework.
>
> * Makefile.in (SFILES): Add osabi.c.
> (defs_h): Add osabi.h.
> (COMMON_OBS): Add osabi.o.
> (osabi.o): New dependency list.
> * defs.h: Include osabi.h.
> * osabi.c: New file.
> * osabi.h: New file.
> * doc/gdbint.texinfo: Document new generic OS ABI framework.
>
> * 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 (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.
>
> * config/sh/tm-sh.h (sh_osabi): Remove.
> (sh_abi, gdbarch_tdep, register enum): Move to...
> * sh-tdep.h: ...here.
> (gdbarch_tdep): Use generic OS ABI framework.
> * sh-tdep.c: Include sh-tdep.h.
> (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.
> * sh3-rom.c: Include sh-tdep.h.
> * shnbsd-tdep.c: Include sh-tdep.h.
> (_initialize_shnbsd_tdep): Use gdbarch_register_osabi.
>
> --
> -- Jason R. Thorpe <thorpej@wasabisystems.com>
> Index: Makefile.in
> ===================================================================
> RCS file: /cvs/src/src/gdb/Makefile.in,v
> retrieving revision 1.184
> diff -u -r1.184 Makefile.in
> --- Makefile.in 11 May 2002 22:14:19 -0000 1.184
> +++ Makefile.in 13 May 2002 18:41:37 -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 \
> @@ -612,7 +612,7 @@
> cp_abi_h = cp-abi.h
> dcache_h = dcache.h
> defs_h = defs.h $(xm_h) $(tm_h) $(nm_h) config.status config.h \
> - gdbarch.h ui-file.h $(INCLUDE_DIR)/gdb/signals.h
> + gdbarch.h osabi.h ui-file.h $(INCLUDE_DIR)/gdb/signals.h
> doublest_h = doublest.h $(floatformat_h)
> dwarf2cfi_h = dwarf2cfi.h
> event_loop_h = event-loop.h
> @@ -712,7 +712,7 @@
> symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \
> expprint.o environ.o stack.o thread.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 \
> @@ -1556,6 +1556,8 @@
> gdbtypes.o: gdbtypes.c $(bfd_h) $(complaints_h) $(defs_h) $(expression_h) \
> $(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)
> 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 13 May 2002 18:41:37 -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 13 May 2002 18:41:37 -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 13 May 2002 18:41:42 -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 13 May 2002 18:41:42 -0000
> @@ -76,24 +76,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 +103,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 13 May 2002 18:41:43 -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 13 May 2002 18:41:43 -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: defs.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/defs.h,v
> retrieving revision 1.88
> diff -u -r1.88 defs.h
> --- defs.h 18 Apr 2002 18:08:59 -0000 1.88
> +++ defs.h 13 May 2002 18:41:50 -0000
> @@ -1029,6 +1029,10 @@
> #include "arch-utils.h"
> #endif
>
> +/* Operating system ABI variant handling for dynamic
> + target-system-dependent parameters. */
> +#include "osabi.h"
> +
> /* Static target-system-dependent parameters for GDB. */
>
> /* Number of bits in a char or unsigned char for the target machine.
> Index: osabi.c
> ===================================================================
> RCS file: osabi.c
> diff -N osabi.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ osabi.c 13 May 2002 18:41:56 -0000
> @@ -0,0 +1,404 @@
> +/* 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;
> +
> + match = GDB_OSABI_UNKNOWN;
> +
> + 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)
> + {
> + /* Croak on multiple match. If the user wishes to
> + continue, we'll use the first match. */
> + if (match != GDB_OSABI_UNKNOWN)
> + internal_error
> + (__FILE__, __LINE__,
> + "gdbarch_lookup_osabi: multiple OS ABI match for "
> + "architecture %s flavour %d: first match \"%s\", second "
> + "match \"%s\"",
> + bfd_printable_arch_mach (bfd_get_arch (abfd), 0),
> + (int) bfd_get_flavour (abfd),
> + gdbarch_osabi_name (match),
> + gdbarch_osabi_name (osabi));
> + else
> + match = osabi;
> + }
> + }
> + }
> +
> + 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. */
> +
> +static void
> +process_note_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__,
> + "process_note_abi_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)
> +{
> + 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), this is supposed to indicate
> + that we're on a SVR4 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,
> + &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 13 May 2002 18:41:56 -0000
> @@ -0,0 +1,73 @@
> +/* 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);
> +
> +#endif /* OSABI_H */
> Index: sh-tdep.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/sh-tdep.c,v
> retrieving revision 1.58
> diff -u -r1.58 sh-tdep.c
> --- sh-tdep.c 10 May 2002 23:59:09 -0000 1.58
> +++ sh-tdep.c 13 May 2002 18:42:23 -0000
> @@ -41,6 +41,8 @@
> #include "regcache.h"
> #include "doublest.h"
>
> +#include "sh-tdep.h"
> +
> #include "elf-bfd.h"
> #include "solib-svr4.h"
>
> @@ -4198,175 +4200,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 *
> @@ -4378,23 +4211,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. */
> @@ -4404,7 +4228,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;
> }
>
> @@ -4413,15 +4237,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
> @@ -4774,32 +4590,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;
> }
> @@ -4812,12 +4607,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: sh-tdep.h
> diff -N sh-tdep.h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ sh-tdep.h 13 May 2002 18:42:23 -0000
> @@ -0,0 +1,109 @@
> +/* Target-specific definition for a Hitachi Super-H.
> + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 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 SH_TDEP_H
> +#define SH_TDEP_H
> +
> +/* Contributed by Steve Chamberlain sac@cygnus.com */
> +
> +/* Information that is dependent on the processor variant. */
> +
> +enum sh_abi
> + {
> + SH_ABI_UNKNOWN,
> + SH_ABI_32,
> + SH_ABI_64
> + };
> +
> +struct gdbarch_tdep
> + {
> + int PR_REGNUM;
> + int FPUL_REGNUM; /* sh3e, sh4 */
> + int FPSCR_REGNUM; /* sh3e, sh4 */
> + int SR_REGNUM; /* sh-dsp, sh3, sh3-dsp, sh3e, sh4 */
> + int DSR_REGNUM; /* sh-dsp, sh3-dsp */
> + int FP_LAST_REGNUM; /* sh3e, sh4 */
> + int A0G_REGNUM; /* sh-dsp, sh3-dsp */
> + int A0_REGNUM; /* sh-dsp, sh3-dsp */
> + int A1G_REGNUM; /* sh-dsp, sh3-dsp */
> + int A1_REGNUM; /* sh-dsp, sh3-dsp */
> + int M0_REGNUM; /* sh-dsp, sh3-dsp */
> + int M1_REGNUM; /* sh-dsp, sh3-dsp */
> + int X0_REGNUM; /* sh-dsp, sh3-dsp */
> + int X1_REGNUM; /* sh-dsp, sh3-dsp */
> + int Y0_REGNUM; /* sh-dsp, sh3-dsp */
> + int Y1_REGNUM; /* sh-dsp, sh3-dsp */
> + int MOD_REGNUM; /* sh-dsp, sh3-dsp */
> + int SSR_REGNUM; /* sh3, sh3-dsp, sh3e, sh4 */
> + int SPC_REGNUM; /* sh3, sh3-dsp, sh3e, sh4 */
> + int RS_REGNUM; /* sh-dsp, sh3-dsp */
> + int RE_REGNUM; /* sh-dsp, sh3-dsp */
> + int DR0_REGNUM; /* sh4 */
> + int DR_LAST_REGNUM; /* sh4 */
> + int FV0_REGNUM; /* sh4 */
> + int FV_LAST_REGNUM; /* sh4 */
> + /* FPP stands for Floating Point Pair, to avoid confusion with
> + GDB's FP0_REGNUM, which is the number of the first Floating
> + point register. Unfortunately on the sh5, the floating point
> + registers are called FR, and the floating point pairs are called FP. */
> + int TR7_REGNUM; /* sh5-media*/
> + int FPP0_REGNUM; /* sh5-media*/
> + int FPP_LAST_REGNUM; /* sh5-media*/
> + int R0_C_REGNUM; /* sh5-compact*/
> + int R_LAST_C_REGNUM; /* sh5-compact*/
> + int PC_C_REGNUM; /* sh5-compact*/
> + int GBR_C_REGNUM; /* sh5-compact*/
> + int MACH_C_REGNUM; /* sh5-compact*/
> + int MACL_C_REGNUM; /* sh5-compact*/
> + int PR_C_REGNUM; /* sh5-compact*/
> + int T_C_REGNUM; /* sh5-compact*/
> + int FPSCR_C_REGNUM; /* sh5-compact*/
> + int FPUL_C_REGNUM; /* sh5-compact*/
> + int FP0_C_REGNUM; /* sh5-compact*/
> + int FP_LAST_C_REGNUM; /* sh5-compact*/
> + int DR0_C_REGNUM; /* sh5-compact*/
> + int DR_LAST_C_REGNUM; /* sh5-compact*/
> + int FV0_C_REGNUM; /* sh5-compact*/
> + int FV_LAST_C_REGNUM; /* sh5-compact*/
> + int ARG0_REGNUM;
> + int ARGLAST_REGNUM;
> + int FLOAT_ARGLAST_REGNUM;
> + int RETURN_REGNUM;
> + enum gdb_osabi osabi; /* OS/ABI of the inferior */
> + enum sh_abi sh_abi;
> + };
> +
> +/* Registers common to all the SH variants. */
> +enum
> + {
> + R0_REGNUM = 0,
> + STRUCT_RETURN_REGNUM = 2,
> + ARG0_REGNUM = 4, /* Used in h8300-tdep.c */
> + ARGLAST_REGNUM = 7, /* Used in h8300-tdep.c */
> + PR_REGNUM = 17, /* used in sh3-rom.c */
> + GBR_REGNUM = 18,
> + VBR_REGNUM = 19,
> + MACH_REGNUM = 20,
> + MACL_REGNUM = 21,
> + SR_REGNUM = 22
> + };
> +
> +#endif /* SH_TDEP_H */
> Index: sh3-rom.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/sh3-rom.c,v
> retrieving revision 1.11
> diff -u -r1.11 sh3-rom.c
> --- sh3-rom.c 15 Jul 2001 20:34:14 -0000 1.11
> +++ sh3-rom.c 13 May 2002 18:42:25 -0000
> @@ -28,6 +28,8 @@
> #include "arch-utils.h"
> #include "regcache.h"
>
> +#include "sh-tdep.h"
> +
> static struct serial *parallel;
> static int parallel_in_use;
>
> Index: shnbsd-tdep.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/shnbsd-tdep.c,v
> retrieving revision 1.3
> diff -u -r1.3 shnbsd-tdep.c
> --- shnbsd-tdep.c 11 May 2002 22:14:19 -0000 1.3
> +++ shnbsd-tdep.c 13 May 2002 18:42:25 -0000
> @@ -25,6 +25,7 @@
> #include "value.h"
>
> #include "nbsd-tdep.h"
> +#include "sh-tdep.h"
> #include "shnbsd-tdep.h"
>
> /* Convert an r0-r15 register number into an offset into a ptrace
> @@ -176,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: config/sh/tm-sh.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/config/sh/tm-sh.h,v
> retrieving revision 1.18
> diff -u -r1.18 tm-sh.h
> --- config/sh/tm-sh.h 10 May 2002 23:00:23 -0000 1.18
> +++ config/sh/tm-sh.h 13 May 2002 18:42:26 -0000
> @@ -23,100 +23,6 @@
>
> #define GDB_MULTI_ARCH 1
>
> -/* 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,
> - SH_ABI_32,
> - SH_ABI_64
> - };
> -
> -struct gdbarch_tdep
> - {
> - int PR_REGNUM;
> - int FPUL_REGNUM; /* sh3e, sh4 */
> - int FPSCR_REGNUM; /* sh3e, sh4 */
> - int SR_REGNUM; /* sh-dsp, sh3, sh3-dsp, sh3e, sh4 */
> - int DSR_REGNUM; /* sh-dsp, sh3-dsp */
> - int FP_LAST_REGNUM; /* sh3e, sh4 */
> - int A0G_REGNUM; /* sh-dsp, sh3-dsp */
> - int A0_REGNUM; /* sh-dsp, sh3-dsp */
> - int A1G_REGNUM; /* sh-dsp, sh3-dsp */
> - int A1_REGNUM; /* sh-dsp, sh3-dsp */
> - int M0_REGNUM; /* sh-dsp, sh3-dsp */
> - int M1_REGNUM; /* sh-dsp, sh3-dsp */
> - int X0_REGNUM; /* sh-dsp, sh3-dsp */
> - int X1_REGNUM; /* sh-dsp, sh3-dsp */
> - int Y0_REGNUM; /* sh-dsp, sh3-dsp */
> - int Y1_REGNUM; /* sh-dsp, sh3-dsp */
> - int MOD_REGNUM; /* sh-dsp, sh3-dsp */
> - int SSR_REGNUM; /* sh3, sh3-dsp, sh3e, sh4 */
> - int SPC_REGNUM; /* sh3, sh3-dsp, sh3e, sh4 */
> - int RS_REGNUM; /* sh-dsp, sh3-dsp */
> - int RE_REGNUM; /* sh-dsp, sh3-dsp */
> - int DR0_REGNUM; /* sh4 */
> - int DR_LAST_REGNUM; /* sh4 */
> - int FV0_REGNUM; /* sh4 */
> - int FV_LAST_REGNUM; /* sh4 */
> - /* FPP stands for Floating Point Pair, to avoid confusion with
> - GDB's FP0_REGNUM, which is the number of the first Floating
> - point register. Unfortunately on the sh5, the floating point
> - registers are called FR, and the floating point pairs are called FP. */
> - int TR7_REGNUM; /* sh5-media*/
> - int FPP0_REGNUM; /* sh5-media*/
> - int FPP_LAST_REGNUM; /* sh5-media*/
> - int R0_C_REGNUM; /* sh5-compact*/
> - int R_LAST_C_REGNUM; /* sh5-compact*/
> - int PC_C_REGNUM; /* sh5-compact*/
> - int GBR_C_REGNUM; /* sh5-compact*/
> - int MACH_C_REGNUM; /* sh5-compact*/
> - int MACL_C_REGNUM; /* sh5-compact*/
> - int PR_C_REGNUM; /* sh5-compact*/
> - int T_C_REGNUM; /* sh5-compact*/
> - int FPSCR_C_REGNUM; /* sh5-compact*/
> - int FPUL_C_REGNUM; /* sh5-compact*/
> - int FP0_C_REGNUM; /* sh5-compact*/
> - int FP_LAST_C_REGNUM; /* sh5-compact*/
> - int DR0_C_REGNUM; /* sh5-compact*/
> - int DR_LAST_C_REGNUM; /* sh5-compact*/
> - int FV0_C_REGNUM; /* sh5-compact*/
> - int FV_LAST_C_REGNUM; /* sh5-compact*/
> - int ARG0_REGNUM;
> - 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 sh_abi sh_abi;
> - };
> -
> -/* Registers common to all the SH variants. */
> -enum
> - {
> - R0_REGNUM = 0,
> - STRUCT_RETURN_REGNUM = 2,
> - ARG0_REGNUM = 4, /* Used in h8300-tdep.c */
> - ARGLAST_REGNUM = 7, /* Used in h8300-tdep.c */
> - PR_REGNUM = 17, /* used in sh3-rom.c */
> - GBR_REGNUM = 18,
> - VBR_REGNUM = 19,
> - MACH_REGNUM = 20,
> - MACL_REGNUM = 21,
> - SR_REGNUM = 22
> - };
> -
> #define NUM_REALREGS 59 /* used in remote-e7000.c which is not multiarched. */
>
> #define REGISTER_TYPE long /* used in standalone.c */
> Index: doc/gdbint.texinfo
> ===================================================================
> RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
> retrieving revision 1.81
> diff -u -r1.81 gdbint.texinfo
> --- doc/gdbint.texinfo 4 May 2002 19:57:22 -0000 1.81
> +++ doc/gdbint.texinfo 13 May 2002 18:42:57 -0000
> @@ -2312,6 +2312,58 @@
> @code{struct gdbarch *}. The structure, and its methods, are generated
> using the Bourne shell script @file{gdbarch.sh}.
>
> +@section Operating System ABI Variant Handling
> +
> +@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 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. 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.
> +
> +A 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.
> +
> +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 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 or @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.