diff options
author | Jason Thorpe <thorpej@netbsd.org> | 2002-05-21 15:36:03 +0000 |
---|---|---|
committer | Jason Thorpe <thorpej@netbsd.org> | 2002-05-21 15:36:03 +0000 |
commit | 70f80edf7ccd4c18977394be8b91c852e119b7e3 (patch) | |
tree | 5d07db93b94757ae43f4100443e172a971d02eb6 /gdb/arm-tdep.c | |
parent | 658f25883ae46d547a9c3052c3d65a36b772d150 (diff) | |
download | gdb-70f80edf7ccd4c18977394be8b91c852e119b7e3.zip gdb-70f80edf7ccd4c18977394be8b91c852e119b7e3.tar.gz gdb-70f80edf7ccd4c18977394be8b91c852e119b7e3.tar.bz2 |
* 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.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r-- | gdb/arm-tdep.c | 347 |
1 files changed, 82 insertions, 265 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index e40d3ef..04fca2e 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; |