From 70f80edf7ccd4c18977394be8b91c852e119b7e3 Mon Sep 17 00:00:00 2001 From: Jason Thorpe Date: Tue, 21 May 2002 15:36:03 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 56 ++++++ gdb/Makefile.in | 43 +++-- gdb/alpha-linux-tdep.c | 3 +- gdb/alpha-osf1-tdep.c | 2 +- gdb/alpha-tdep.c | 254 ++---------------------- gdb/alpha-tdep.h | 22 +-- gdb/alphafbsd-tdep.c | 3 +- gdb/alphanbsd-tdep.c | 3 +- gdb/arm-linux-tdep.c | 2 +- gdb/arm-tdep.c | 347 ++++++++------------------------- gdb/arm-tdep.h | 29 +-- gdb/armnbsd-tdep.c | 18 +- gdb/doc/gdbint.texinfo | 121 ++++++++++++ gdb/mips-tdep.c | 35 +++- gdb/osabi.c | 424 +++++++++++++++++++++++++++++++++++++++++ gdb/osabi.h | 78 ++++++++ gdb/sh-tdep.c | 233 ++-------------------- gdb/sh-tdep.h | 16 +- gdb/shnbsd-tdep.c | 2 +- 19 files changed, 869 insertions(+), 822 deletions(-) create mode 100644 gdb/osabi.c create mode 100644 gdb/osabi.h 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 + + * 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 * 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[] = -{ - "", - "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 = ""; - } + 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[] = -{ - "", - "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 = ""; - } + 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 55442d44d4a..4f76f5fb524 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -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[] = +{ + "", + + "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", + + "" +}; + +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], "") != 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[] = -{ - "", - "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 = ""; - } + 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); } -- 2.30.2