summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog56
-rw-r--r--gdb/Makefile.in43
-rw-r--r--gdb/alpha-linux-tdep.c3
-rw-r--r--gdb/alpha-osf1-tdep.c2
-rw-r--r--gdb/alpha-tdep.c254
-rw-r--r--gdb/alpha-tdep.h22
-rw-r--r--gdb/alphafbsd-tdep.c3
-rw-r--r--gdb/alphanbsd-tdep.c3
-rw-r--r--gdb/arm-linux-tdep.c2
-rw-r--r--gdb/arm-tdep.c347
-rw-r--r--gdb/arm-tdep.h29
-rw-r--r--gdb/armnbsd-tdep.c18
-rw-r--r--gdb/doc/gdbint.texinfo123
-rw-r--r--gdb/mips-tdep.c35
-rw-r--r--gdb/osabi.c424
-rw-r--r--gdb/osabi.h78
-rw-r--r--gdb/sh-tdep.c233
-rw-r--r--gdb/sh-tdep.h16
-rw-r--r--gdb/shnbsd-tdep.c2
19 files changed, 870 insertions, 823 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ade53234cdd..57a965ff598 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,59 @@
+2002-05-21 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * 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.
+
2002-05-20 Kazu Hirata <kazu@cs.umass.edu>
* h8300-tdep.c: Fix formatting.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index abe4d06a56c..02e6344f6ae 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -530,7 +530,7 @@ SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \
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 @@ xm_h = @xm_h@
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_h = remote.h
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 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
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 @@ a68v-nat.o: a68v-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) \
$(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.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)
@@ -1811,7 +1815,8 @@ mips-nat.o: mips-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(regcache_h)
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 @@ remote-array.o: remote-array.c $(defs_h) $(gdbcore_h) $(target_h) \
$(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 @@ rdi-share/libangsd.a: force
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) \
diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c
index d467840e920..4596d37e327 100644
--- a/gdb/alpha-linux-tdep.c
+++ b/gdb/alpha-linux-tdep.c
@@ -116,5 +116,6 @@ alpha_linux_init_abi (struct gdbarch_info info,
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);
}
diff --git a/gdb/alpha-osf1-tdep.c b/gdb/alpha-osf1-tdep.c
index 67c56cf9d36..12320519ae8 100644
--- a/gdb/alpha-osf1-tdep.c
+++ b/gdb/alpha-osf1-tdep.c
@@ -69,5 +69,5 @@ alpha_osf1_init_abi (struct gdbarch_info info,
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);
}
diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c
index f354036dda4..efafcc90078 100644
--- a/gdb/alpha-tdep.c
+++ b/gdb/alpha-tdep.c
@@ -1766,186 +1766,6 @@ alpha_software_single_step (enum target_signal sig, int insert_breakpoints_p)
}
-/* 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 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
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 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
/* 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 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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 @@ alpha_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
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",
diff --git a/gdb/alpha-tdep.h b/gdb/alpha-tdep.h
index c3ee007c6ac..cea232b502c 100644
--- a/gdb/alpha-tdep.h
+++ b/gdb/alpha-tdep.h
@@ -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 */
@@ -118,8 +106,4 @@ struct gdbarch_tdep
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 */
diff --git a/gdb/alphafbsd-tdep.c b/gdb/alphafbsd-tdep.c
index 3c1e64da3e8..f8f515d3cc8 100644
--- a/gdb/alphafbsd-tdep.c
+++ b/gdb/alphafbsd-tdep.c
@@ -78,5 +78,6 @@ alphafbsd_init_abi (struct gdbarch_info info,
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);
}
diff --git a/gdb/alphanbsd-tdep.c b/gdb/alphanbsd-tdep.c
index d10a3cab159..ba705aa4015 100644
--- a/gdb/alphanbsd-tdep.c
+++ b/gdb/alphanbsd-tdep.c
@@ -203,7 +203,8 @@ alphanbsd_init_abi (struct gdbarch_info info,
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);
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 29f11ae91bf..920d27ba95f 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -543,5 +543,5 @@ arm_linux_init_abi (struct gdbarch_info info,
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);
}
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index e40d3ef5713..04fca2e44c6 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -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 @@ arm_coff_make_msymbol_special(int val, struct minimal_symbol *msym)
}
-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)
+ 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)
{
- int os_number = bfd_h_get_32 (abfd, note + 16);
-
- /* The case numbers are from abi-tags in glibc. */
- switch (os_number)
+ /* 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];
-
- /* 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.
+ break;
- 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 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
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 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
/* 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_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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 @@ arm_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
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 @@ _initialize_arm_tdep (void)
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;
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index e7c56515a95..a8f15148364 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -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 @@ enum gdb_regnum {
#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 @@ enum arm_float_model
/* 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 @@ int arm_pc_is_thumb (CORE_ADDR);
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 *));
diff --git a/gdb/armnbsd-tdep.c b/gdb/armnbsd-tdep.c
index 7f6e63992e2..7c9e425bc6a 100644
--- a/gdb/armnbsd-tdep.c
+++ b/gdb/armnbsd-tdep.c
@@ -77,9 +77,23 @@ arm_netbsd_elf_init_abi (struct gdbarch_info info,
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);
}
diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo
index f6e50ef088c..a48e3aa6820 100644
--- a/gdb/doc/gdbint.texinfo
+++ b/gdb/doc/gdbint.texinfo
@@ -41,7 +41,7 @@ Software Foundation raise funds for GNU development.''
@page
@tex
\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
-\xdef\manvers{\$Revision: 1.84 $} % For use in headers, footers too
+\xdef\manvers{\$Revision: 1.85 $} % For use in headers, footers too
{\parskip=0pt
\hfill Cygnus Solutions\par
\hfill \manvers\par
@@ -2312,6 +2312,127 @@ The target architecture object is implemented as the C structure
@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.
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 16ebaca7eb7..67409f6d18a 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -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 @@ struct gdbarch_tdep
{
/* from the elf header */
int elf_flags;
+
/* mips options */
enum mips_abi mips_abi;
const char *mips_abi_string;
@@ -131,6 +133,8 @@ struct gdbarch_tdep
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 @@ mips_gdbarch_init (struct gdbarch_info info,
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 @@ mips_gdbarch_init (struct gdbarch_info info,
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 @@ mips_gdbarch_init (struct gdbarch_info info,
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 @@ mips_gdbarch_init (struct gdbarch_info info,
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 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
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
diff --git a/gdb/osabi.c b/gdb/osabi.c
new file mode 100644
index 00000000000..4186cbd5245
--- /dev/null
+++ b/gdb/osabi.c
@@ -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);
+}
diff --git a/gdb/osabi.h b/gdb/osabi.h
new file mode 100644
index 00000000000..23e7025d9d5
--- /dev/null
+++ b/gdb/osabi.h
@@ -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 */
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 55909e20dd7..924b675a276 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -4179,175 +4179,6 @@ sh_linux_svr4_fetch_link_map_offsets (void)
#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 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
/* 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 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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 @@ sh_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
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
diff --git a/gdb/sh-tdep.h b/gdb/sh-tdep.h
index 81bb39d25a6..cd7f35a8324 100644
--- a/gdb/sh-tdep.h
+++ b/gdb/sh-tdep.h
@@ -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 @@ struct gdbarch_tdep
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;
};
diff --git a/gdb/shnbsd-tdep.c b/gdb/shnbsd-tdep.c
index 7ac04892bc2..1a58d3c1f1f 100644
--- a/gdb/shnbsd-tdep.c
+++ b/gdb/shnbsd-tdep.c
@@ -177,5 +177,5 @@ _initialize_shnbsd_tdep (void)
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);
}