#define MSYMBOL_SIZE(msym) \
((long) MSYMBOL_INFO (msym) & 0x7fffffff)
-/* This table matches the indicees 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;
/* Print interesting information about the floating point processor
(if present) or emulator. */
static void
-arm_print_float_info (void)
+arm_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+ struct frame_info *frame)
{
register unsigned long status = read_register (ARM_FPS_REGNUM);
int type;
}
\f
-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;
}
+\f
/* 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.
{
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". */
+ }
}
}
{
/* 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;
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. */
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);
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;