aboutsummaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
authorJason Thorpe <thorpej@netbsd.org>2002-05-21 15:36:03 +0000
committerJason Thorpe <thorpej@netbsd.org>2002-05-21 15:36:03 +0000
commit70f80edf7ccd4c18977394be8b91c852e119b7e3 (patch)
tree5d07db93b94757ae43f4100443e172a971d02eb6 /gdb/arm-tdep.c
parent658f25883ae46d547a9c3052c3d65a36b772d150 (diff)
downloadgdb-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.c347
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;