gdb/osabi.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "osabi.h"
- #include "arch-utils.h"
- #include "gdbcmd.h"
- #include "command.h"
- #include "elf-bfd.h"
- #ifndef GDB_OSABI_DEFAULT
- #define GDB_OSABI_DEFAULT GDB_OSABI_UNKNOWN
- #endif
- static enum { osabi_auto, osabi_default, osabi_user } user_osabi_state;
- static enum gdb_osabi user_selected_osabi;
- static const char *gdb_osabi_available_names[GDB_OSABI_INVALID + 3] = {
- "auto",
- "default",
- "none",
- NULL
- };
- static const char *set_osabi_string;
- struct osabi_names
- {
-
- const char *pretty;
-
- const char *regexp;
- };
- static const struct osabi_names gdb_osabi_names[] =
- {
- { "none", NULL },
- { "SVR4", NULL },
- { "GNU/Hurd", NULL },
- { "Solaris", NULL },
- { "GNU/Linux", "linux(-gnu)?" },
- { "FreeBSD a.out", NULL },
- { "FreeBSD ELF", NULL },
- { "NetBSD a.out", NULL },
- { "NetBSD ELF", NULL },
- { "OpenBSD ELF", NULL },
- { "Windows CE", NULL },
- { "DJGPP", NULL },
- { "Irix", NULL },
- { "HP/UX ELF", NULL },
- { "HP/UX SOM", NULL },
- { "QNX Neutrino", NULL },
- { "Cygwin", NULL },
- { "AIX", NULL },
- { "DICOS", NULL },
- { "Darwin", NULL },
- { "Symbian", NULL },
- { "OpenVMS", NULL },
- { "LynxOS178", NULL },
- { "Newlib", NULL },
- { "SDE", NULL },
- { "<invalid>", NULL }
- };
- const char *
- gdbarch_osabi_name (enum gdb_osabi osabi)
- {
- if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
- return gdb_osabi_names[osabi].pretty;
- return gdb_osabi_names[GDB_OSABI_INVALID].pretty;
- }
- const char *
- osabi_triplet_regexp (enum gdb_osabi osabi)
- {
- if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
- return gdb_osabi_names[osabi].regexp;
- return gdb_osabi_names[GDB_OSABI_INVALID].regexp;
- }
- enum gdb_osabi
- osabi_from_tdesc_string (const char *name)
- {
- int i;
- for (i = 0; i < ARRAY_SIZE (gdb_osabi_names); i++)
- if (strcmp (name, gdb_osabi_names[i].pretty) == 0)
- {
-
- enum gdb_osabi osabi = (enum gdb_osabi) i;
- if (osabi == GDB_OSABI_INVALID)
- return GDB_OSABI_UNKNOWN;
- else
- return osabi;
- }
- return GDB_OSABI_UNKNOWN;
- }
- struct gdb_osabi_handler
- {
- struct gdb_osabi_handler *next;
- const struct bfd_arch_info *arch_info;
- 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, unsigned long machine,
- enum gdb_osabi osabi,
- void (*init_osabi)(struct gdbarch_info,
- struct gdbarch *))
- {
- struct gdb_osabi_handler **handler_p;
- const struct bfd_arch_info *arch_info = bfd_lookup_arch (arch, machine);
- const char **name_ptr;
-
- 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, machine));
- return;
- }
- gdb_assert (arch_info);
- for (handler_p = &gdb_osabi_handler_list; *handler_p != NULL;
- handler_p = &(*handler_p)->next)
- {
- if ((*handler_p)->arch_info == arch_info
- && (*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),
- arch_info->printable_name);
-
- (*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_info = arch_info;
- (*handler_p)->osabi = osabi;
- (*handler_p)->init_osabi = init_osabi;
-
- for (name_ptr = gdb_osabi_available_names; *name_ptr; name_ptr ++)
- {
- if (*name_ptr == gdbarch_osabi_name (osabi))
- return;
- }
- *name_ptr++ = gdbarch_osabi_name (osabi);
- *name_ptr = NULL;
- }
- struct gdb_osabi_sniffer
- {
- struct gdb_osabi_sniffer *next;
- enum bfd_architecture arch;
- 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;
-
- if (user_osabi_state == osabi_user)
- return user_selected_osabi;
-
- if (abfd == NULL)
- return GDB_OSABI_UNKNOWN;
- match = GDB_OSABI_UNKNOWN;
- match_specific = 0;
- for (sniffer = gdb_osabi_sniffer_list; sniffer != NULL;
- sniffer = sniffer->next)
- {
- if ((sniffer->arch == bfd_arch_unknown
- || 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)
- {
-
- 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;
- }
- static int
- can_run_code_for (const struct bfd_arch_info *a, const struct bfd_arch_info *b)
- {
-
- return (a == b || a->compatible (a, b) == a);
- }
- void
- gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
- {
- struct gdb_osabi_handler *handler;
- if (info.osabi == GDB_OSABI_UNKNOWN)
- {
-
- return;
- }
- for (handler = gdb_osabi_handler_list; handler != NULL;
- handler = handler->next)
- {
- if (handler->osabi != info.osabi)
- continue;
-
-
- if (can_run_code_for (info.bfd_arch_info, handler->arch_info))
- {
- (*handler->init_osabi) (info, gdbarch);
- return;
- }
- }
- warning
- ("A handler for the OS ABI \"%s\" is not built into this configuration\n"
- "of GDB. Attempting to continue with the default %s settings.\n",
- gdbarch_osabi_name (info.osabi),
- info.bfd_arch_info->printable_name);
- }
- #define MAX_NOTESZ 128
- static int
- check_note (bfd *abfd, asection *sect, char *note, unsigned int *sectsize,
- const char *name, unsigned long descsz, unsigned long type)
- {
- unsigned long notesz;
- if (*sectsize)
- {
- if (!bfd_get_section_contents (abfd, sect, note, 0, *sectsize))
- return 0;
- *sectsize = 0;
- }
-
- notesz = strlen (name) + 1;
- notesz = ((notesz + 3) & ~3);
- notesz += descsz;
- notesz = ((notesz + 3) & ~3);
-
- gdb_assert (notesz <= MAX_NOTESZ);
-
- if (notesz > bfd_section_size (abfd, sect))
- return 0;
-
- if (bfd_h_get_32 (abfd, note) != (strlen (name) + 1)
- || strcmp (note + 12, name) != 0)
- return 0;
-
- if (bfd_h_get_32 (abfd, note + 4) != descsz)
- return 0;
-
- if (bfd_h_get_32 (abfd, note + 8) != type)
- return 0;
- return 1;
- }
- void
- generic_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
- {
- enum gdb_osabi *osabi = obj;
- const char *name;
- unsigned int sectsize;
- char *note;
- name = bfd_get_section_name (abfd, sect);
- sectsize = bfd_section_size (abfd, sect);
-
- if (sectsize > MAX_NOTESZ)
- sectsize = MAX_NOTESZ;
-
- note = alloca (sectsize);
-
- if (strcmp (name, ".note.ABI-tag") == 0)
- {
-
- if (check_note (abfd, sect, note, §size, "GNU", 16, NT_GNU_ABI_TAG))
- {
- unsigned int abi_tag = bfd_h_get_32 (abfd, note + 16);
- switch (abi_tag)
- {
- case GNU_ABI_TAG_LINUX:
- *osabi = GDB_OSABI_LINUX;
- break;
- case GNU_ABI_TAG_HURD:
- *osabi = GDB_OSABI_HURD;
- break;
- case GNU_ABI_TAG_SOLARIS:
- *osabi = GDB_OSABI_SOLARIS;
- break;
- case GNU_ABI_TAG_FREEBSD:
- *osabi = GDB_OSABI_FREEBSD_ELF;
- break;
- case GNU_ABI_TAG_NETBSD:
- *osabi = GDB_OSABI_NETBSD_ELF;
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("generic_elf_osabi_sniff_abi_tag_sections: "
- "unknown OS number %d"),
- abi_tag);
- }
- return;
- }
-
- if (check_note (abfd, sect, note, §size, "FreeBSD", 4,
- NT_FREEBSD_ABI_TAG))
- {
-
- *osabi = GDB_OSABI_FREEBSD_ELF;
- return;
- }
- return;
- }
-
- if (strcmp (name, ".note.netbsd.ident") == 0
- && check_note (abfd, sect, note, §size, "NetBSD", 4, NT_NETBSD_IDENT))
- {
-
- *osabi = GDB_OSABI_NETBSD_ELF;
- return;
- }
-
- if (strcmp (name, ".note.openbsd.ident") == 0
- && check_note (abfd, sect, note, §size, "OpenBSD", 4,
- NT_OPENBSD_IDENT))
- {
-
- *osabi = GDB_OSABI_OPENBSD_ELF;
- return;
- }
-
- if (strcmp (name, ".note.netbsdcore.procinfo") == 0)
- {
- *osabi = 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:
- case ELFOSABI_GNU:
-
- 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_SOLARIS:
- osabi = GDB_OSABI_SOLARIS;
- break;
- case ELFOSABI_HPUX:
-
- osabi = GDB_OSABI_HPUX_ELF;
- bfd_map_over_sections (abfd,
- generic_elf_osabi_sniff_abi_tag_sections,
- &osabi);
- break;
- case ELFOSABI_OPENVMS:
- osabi = GDB_OSABI_OPENVMS;
- break;
- }
- if (osabi == GDB_OSABI_UNKNOWN)
- {
-
- if (memcmp (&elf_elfheader (abfd)->e_ident[8],
- "FreeBSD", sizeof ("FreeBSD")) == 0)
- osabi = GDB_OSABI_FREEBSD_ELF;
- }
- return osabi;
- }
- static void
- set_osabi (char *args, int from_tty, struct cmd_list_element *c)
- {
- struct gdbarch_info info;
- if (strcmp (set_osabi_string, "auto") == 0)
- user_osabi_state = osabi_auto;
- else if (strcmp (set_osabi_string, "default") == 0)
- {
- user_selected_osabi = GDB_OSABI_DEFAULT;
- user_osabi_state = osabi_user;
- }
- else if (strcmp (set_osabi_string, "none") == 0)
- {
- user_selected_osabi = GDB_OSABI_UNKNOWN;
- user_osabi_state = osabi_user;
- }
- else
- {
- int i;
- for (i = 1; i < GDB_OSABI_INVALID; i++)
- if (strcmp (set_osabi_string, gdbarch_osabi_name (i)) == 0)
- {
- user_selected_osabi = i;
- user_osabi_state = osabi_user;
- break;
- }
- if (i == GDB_OSABI_INVALID)
- internal_error (__FILE__, __LINE__,
- _("Invalid OS ABI \"%s\" passed to command handler."),
- set_osabi_string);
- }
-
- gdbarch_info_init (&info);
- if (! gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__, _("Updating OS ABI failed."));
- }
- static void
- show_osabi (struct ui_file *file, int from_tty, struct cmd_list_element *c,
- const char *value)
- {
- if (user_osabi_state == osabi_auto)
- fprintf_filtered (file,
- _("The current OS ABI is \"auto\" "
- "(currently \"%s\").\n"),
- gdbarch_osabi_name (gdbarch_osabi (get_current_arch ())));
- else
- fprintf_filtered (file, _("The current OS ABI is \"%s\".\n"),
- gdbarch_osabi_name (user_selected_osabi));
- if (GDB_OSABI_DEFAULT != GDB_OSABI_UNKNOWN)
- fprintf_filtered (file, _("The default OS ABI is \"%s\".\n"),
- gdbarch_osabi_name (GDB_OSABI_DEFAULT));
- }
- extern initialize_file_ftype _initialize_gdb_osabi;
- void
- _initialize_gdb_osabi (void)
- {
- if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID].pretty, "<invalid>") != 0)
- internal_error
- (__FILE__, __LINE__,
- _("_initialize_gdb_osabi: gdb_osabi_names[] is inconsistent"));
-
- gdbarch_register_osabi_sniffer (bfd_arch_unknown,
- bfd_target_elf_flavour,
- generic_elf_osabi_sniffer);
-
- add_setshow_enum_cmd ("osabi", class_support, gdb_osabi_available_names,
- &set_osabi_string,
- _("Set OS ABI of target."),
- _("Show OS ABI of target."),
- NULL, set_osabi, show_osabi,
- &setlist, &showlist);
- user_osabi_state = osabi_auto;
- }