X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fosabi.c;h=627b9d98151513d1af0126ae8474139c3a515350;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=83eb767c0b731aa49739c3b0822b471b5cde472d;hpb=2ee563b53258d390d7446e90a67f465d504ae44c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/osabi.c b/gdb/osabi.c index 83eb767c0b..627b9d9815 100644 --- a/gdb/osabi.c +++ b/gdb/osabi.c @@ -1,72 +1,141 @@ /* OS ABI variant handling for GDB. - Copyright 2001, 2002 Free Software Foundation, Inc. + + Copyright (C) 2001-2020 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + 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. */ + along with this program. If not, see . */ #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 + +/* State for the "set osabi" command. */ +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; + +/* Names associated with each osabi. */ + +struct osabi_names +{ + /* The "pretty" name. */ + + const char *pretty; + + /* The triplet regexp, or NULL if not known. */ + + const char *regexp; +}; /* This table matches the indices assigned to enum gdb_osabi. Keep them in sync. */ -static const char * const gdb_osabi_names[] = +static const struct osabi_names gdb_osabi_names[] = { - "", - - "SVR4", - "GNU/Hurd", - "Solaris", - "OSF/1", - "GNU/Linux", - "FreeBSD a.out", - "FreeBSD ELF", - "NetBSD a.out", - "NetBSD ELF", - "Windows CE", - "DJGPP", - "NetWare", - "Irix", - "LynxOS", - - "ARM EABI v1", - "ARM EABI v2", - "ARM APCS", - - "" + { "unknown", NULL }, + { "none", NULL }, + + { "SVR4", NULL }, + { "GNU/Hurd", NULL }, + { "Solaris", NULL }, + { "GNU/Linux", "linux(-gnu[^-]*)?" }, + { "FreeBSD", NULL }, + { "NetBSD", NULL }, + { "OpenBSD", NULL }, + { "WindowsCE", NULL }, + { "DJGPP", NULL }, + { "QNX-Neutrino", NULL }, + { "Cygwin", NULL }, + { "Windows", NULL }, + { "AIX", NULL }, + { "DICOS", NULL }, + { "Darwin", NULL }, + { "Symbian", NULL }, + { "OpenVMS", NULL }, + { "LynxOS178", NULL }, + { "Newlib", NULL }, + { "SDE", NULL }, + { "PikeOS", NULL }, + + { "", NULL } }; 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[osabi].pretty; - return gdb_osabi_names[GDB_OSABI_INVALID]; + return gdb_osabi_names[GDB_OSABI_INVALID].pretty; +} + +/* See osabi.h. */ + +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; +} + +/* Lookup the OS ABI corresponding to the specified target description + string. */ + +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) + { + /* See note above: the name table matches the indices assigned + to enum gdb_osabi. */ + enum gdb_osabi osabi = (enum gdb_osabi) i; + + if (osabi == GDB_OSABI_INVALID) + return GDB_OSABI_UNKNOWN; + else + return osabi; + } + + return GDB_OSABI_UNKNOWN; } /* 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 { struct gdb_osabi_handler *next; - enum bfd_architecture arch; + const struct bfd_arch_info *arch_info; enum gdb_osabi osabi; void (*init_osabi)(struct gdbarch_info, struct gdbarch *); }; @@ -74,53 +143,67 @@ struct gdb_osabi_handler 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, +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; /* 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_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)); + 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 == arch + 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_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)); + arch_info->printable_name); /* 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) = XNEW (struct gdb_osabi_handler); (*handler_p)->next = NULL; - (*handler_p)->arch = arch; + (*handler_p)->arch_info = arch_info; (*handler_p)->osabi = osabi; (*handler_p)->init_osabi = init_osabi; + + /* Add this OS ABI to the list of enum values for "set osabi", if it isn't + already there. */ + 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; } -/* Sniffer to find the OS ABI for a given file's architecture and flavour. +/* 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 @@ -137,13 +220,12 @@ static struct gdb_osabi_sniffer *gdb_osabi_sniffer_list; void gdbarch_register_osabi_sniffer (enum bfd_architecture arch, - enum bfd_flavour flavour, + 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 = XNEW (struct gdb_osabi_sniffer); sniffer->arch = arch; sniffer->flavour = flavour; sniffer->sniffer = sniffer_fn; @@ -160,6 +242,16 @@ gdbarch_lookup_osabi (bfd *abfd) enum gdb_osabi osabi, match; int match_specific; + /* If we aren't in "auto" mode, return the specified OS ABI. */ + if (user_osabi_state == osabi_user) + return user_selected_osabi; + + /* If we don't have a binary, just return unknown. The caller may + have other sources the OSABI can be extracted from, e.g., the + target description. */ + if (abfd == NULL) + return GDB_OSABI_UNKNOWN; + match = GDB_OSABI_UNKNOWN; match_specific = 0; @@ -175,8 +267,8 @@ gdbarch_lookup_osabi (bfd *abfd) { internal_error (__FILE__, __LINE__, - "gdbarch_lookup_osabi: invalid OS ABI (%d) from sniffer " - "for architecture %s flavour %d", + _("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)); @@ -193,15 +285,15 @@ gdbarch_lookup_osabi (bfd *abfd) || (!match_specific && sniffer->arch == bfd_arch_unknown)) { internal_error - (__FILE__, __LINE__, - "gdbarch_lookup_osabi: multiple %sspecific OS ABI " + (__FILE__, __LINE__, + _("gdbarch_lookup_osabi: multiple %sspecific OS ABI " "match for architecture %s flavour %d: first " - "match \"%s\", second match \"%s\"", + "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)); + 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) { @@ -222,143 +314,224 @@ gdbarch_lookup_osabi (bfd *abfd) return match; } + +/* Return non-zero if architecture A can run code written for + architecture B. */ +static int +can_run_code_for (const struct bfd_arch_info *a, const struct bfd_arch_info *b) +{ + /* BFD's 'A->compatible (A, B)' functions return zero if A and B are + incompatible. But if they are compatible, it returns the 'more + featureful' of the two arches. That is, if A can run code + written for B, but B can't run code written for A, then it'll + return A. + + struct bfd_arch_info objects are singletons: that is, there's + supposed to be exactly one instance for a given machine. So you + can tell whether two are equivalent by comparing pointers. */ + return (a == b || a->compatible (a, b) == a); +} + + void -gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch, - enum gdb_osabi osabi) +gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch) { 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 an unknown OSABI. Assume the user knows - what they are doing. */ - return; - } + gdb_assert (info.osabi != GDB_OSABI_UNKNOWN); for (handler = gdb_osabi_handler_list; handler != NULL; handler = handler->next) { - if (handler->arch == bfd_get_arch (abfd) - && handler->osabi == osabi) + if (handler->osabi != info.osabi) + continue; + + /* If the architecture described by ARCH_INFO can run code for + the architecture we registered the handler for, then the + handler is applicable. Note, though, that if the handler is + for an architecture that is a superset of ARCH_INFO, we can't + use that --- it would be perfectly correct for it to install + gdbarch methods that refer to registers / instructions / + other facilities ARCH_INFO doesn't have. + + NOTE: kettenis/20021027: There may be more than one machine + type that is compatible with the desired machine type. Right + now we simply return the first match, which is fine for now. + However, we might want to do something smarter in the future. */ + /* NOTE: cagney/2003-10-23: The code for "a can_run_code_for b" + is implemented using BFD's compatible method (a->compatible + (b) == a -- the lowest common denominator between a and b is + a). That method's definition of compatible may not be as you + expect. For instance the test "amd64 can run code for i386" + (or more generally "64-bit ISA can run code for the 32-bit + ISA"). BFD doesn't normally consider 32-bit and 64-bit + "compatible" so it doesn't succeed. */ + if (can_run_code_for (info.bfd_arch_info, handler->arch_info)) { (*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)); + if (info.osabi == GDB_OSABI_NONE) + { + /* Don't complain about no OSABI. Assume the user knows + what they are doing. */ + 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); } +/* Limit on the amount of data to be read. */ +#define MAX_NOTESZ 128 + +/* Return non-zero if NOTE matches NAME, DESCSZ and TYPE. If + *SECTSIZE is non-zero, then this reads that many bytes from + the start of the section and clears *SECTSIZE. */ + +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; + } + + /* Calculate the size of this note. */ + notesz = strlen (name) + 1; + notesz = ((notesz + 3) & ~3); + notesz += descsz; + notesz = ((notesz + 3) & ~3); + + /* If this assertion triggers, increase MAX_NOTESZ. */ + gdb_assert (notesz <= MAX_NOTESZ); + + /* Check whether SECT is big enough to contain the complete note. */ + if (notesz > bfd_section_size (sect)) + return 0; + + /* Check the note name. */ + if (bfd_h_get_32 (abfd, note) != (strlen (name) + 1) + || strcmp (note + 12, name) != 0) + return 0; + + /* Check the descriptor size. */ + if (bfd_h_get_32 (abfd, note + 4) != descsz) + return 0; + + /* Check the note type. */ + if (bfd_h_get_32 (abfd, note + 8) != type) + return 0; + + return 1; +} /* 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; + enum gdb_osabi *osabi = (enum gdb_osabi *) obj; const char *name; unsigned int sectsize; + char *note; - 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); + name = bfd_section_name (sect); + sectsize = bfd_section_size (sect); - bfd_get_section_contents (abfd, sect, note, - (file_ptr) 0, (bfd_size_type) sectsize); + /* Limit the amount of data to read. */ + if (sectsize > MAX_NOTESZ) + sectsize = MAX_NOTESZ; - 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); + /* We lazily read the section data here. Since we use + BFD_DECOMPRESS, we can't use bfd_get_section_contents on a + compressed section. But, since note sections are not compressed, + deferring the reading until we recognize the section avoids any + error. */ + note = (char *) alloca (sectsize); - if (name_length == 4 && data_length == 16 && note_type == NT_GNU_ABI_TAG - && strcmp (note + 12, "GNU") == 0) + /* .note.ABI-tag notes, used by GNU/Linux and FreeBSD. */ + if (strcmp (name, ".note.ABI-tag") == 0) + { + /* GNU. */ + if (check_note (abfd, sect, note, §size, "GNU", 16, NT_GNU_ABI_TAG)) { - int os_number = bfd_h_get_32 (abfd, note + 16); + unsigned int abi_tag = bfd_h_get_32 (abfd, note + 16); - switch (os_number) + switch (abi_tag) { case GNU_ABI_TAG_LINUX: - *os_ident_ptr = GDB_OSABI_LINUX; + *osabi = GDB_OSABI_LINUX; break; case GNU_ABI_TAG_HURD: - *os_ident_ptr = GDB_OSABI_HURD; + *osabi = GDB_OSABI_HURD; break; case GNU_ABI_TAG_SOLARIS: - *os_ident_ptr = GDB_OSABI_SOLARIS; + *osabi = GDB_OSABI_SOLARIS; + break; + + case GNU_ABI_TAG_FREEBSD: + *osabi = GDB_OSABI_FREEBSD; + break; + + case GNU_ABI_TAG_NETBSD: + *osabi = GDB_OSABI_NETBSD; break; default: - internal_error - (__FILE__, __LINE__, - "generic_elf_osabi_sniff_abi_tag_sections: unknown OS number %d", - os_number); + warning (_("GNU ABI tag value %u unrecognized."), abi_tag); + break; } return; } - else if (name_length == 8 && data_length == 4 - && note_type == NT_FREEBSD_ABI_TAG - && strcmp (note + 12, "FreeBSD") == 0) + + /* FreeBSD. */ + if (check_note (abfd, sect, note, §size, "FreeBSD", 4, + NT_FREEBSD_ABI_TAG)) { - /* XXX Should we check the version here? Probably not - necessary yet. */ - *os_ident_ptr = GDB_OSABI_FREEBSD_ELF; + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_FREEBSD; + return; } + return; } /* .note.netbsd.ident notes, used by NetBSD. */ - if (strcmp (name, ".note.netbsd.ident") == 0 && sectsize > 0) + if (strcmp (name, ".note.netbsd.ident") == 0 + && check_note (abfd, sect, note, §size, "NetBSD", 4, NT_NETBSD_IDENT)) { - 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); + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_NETBSD; + return; + } - 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); + /* .note.openbsd.ident notes, used by OpenBSD. */ + if (strcmp (name, ".note.openbsd.ident") == 0 + && check_note (abfd, sect, note, §size, "OpenBSD", 4, + NT_OPENBSD_IDENT)) + { + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_OPENBSD; + return; + } - 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; - } + /* .note.netbsdcore.procinfo notes, used by NetBSD. */ + if (strcmp (name, ".note.netbsdcore.procinfo") == 0) + { + *osabi = GDB_OSABI_NETBSD; return; } } @@ -374,59 +547,133 @@ generic_elf_osabi_sniffer (bfd *abfd) 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. */ + case ELFOSABI_GNU: + case ELFOSABI_HPUX: + /* When the EI_OSABI field in the ELF header 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-specific notes. + + The same applies for ELFOSABI_GNU: this can mean GNU/Hurd, + GNU/Linux, and possibly more. */ + + /* And likewise ELFOSABI_HPUX. For some reason the default + value for the EI_OSABI field is ELFOSABI_HPUX for all PA-RISC + targets (with the exception of GNU/Linux). */ bfd_map_over_sections (abfd, generic_elf_osabi_sniff_abi_tag_sections, &osabi); break; case ELFOSABI_FREEBSD: - osabi = GDB_OSABI_FREEBSD_ELF; + osabi = GDB_OSABI_FREEBSD; 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; + osabi = GDB_OSABI_NETBSD; break; case ELFOSABI_SOLARIS: osabi = GDB_OSABI_SOLARIS; break; + + case ELFOSABI_OPENVMS: + osabi = GDB_OSABI_OPENVMS; + break; } if (osabi == GDB_OSABI_UNKNOWN) { /* The FreeBSD folks have been naughty; they stored the string - "FreeBSD" in the padding of the e_ident field of the ELF - header to "brand" their ELF binaries in FreeBSD 3.x. */ - if (strcmp (&elf_elfheader (abfd)->e_ident[8], "FreeBSD") == 0) - osabi = GDB_OSABI_FREEBSD_ELF; + "FreeBSD" in the padding of the e_ident field of the ELF + header to "brand" their ELF binaries in FreeBSD 3.x. */ + if (memcmp (&elf_elfheader (abfd)->e_ident[8], + "FreeBSD", sizeof ("FreeBSD")) == 0) + osabi = GDB_OSABI_FREEBSD; } return osabi; } +static void +set_osabi (const 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 + { + int i; + for (i = 1; i < GDB_OSABI_INVALID; i++) + { + enum gdb_osabi osabi = (enum gdb_osabi) i; + + if (strcmp (set_osabi_string, gdbarch_osabi_name (osabi)) == 0) + { + user_selected_osabi = osabi; + 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); + } + + /* NOTE: At some point (true multiple architectures) we'll need to be more + graceful here. */ + 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)); +} + +void _initialize_gdb_osabi (); void -_initialize_gdb_osabi (void) +_initialize_gdb_osabi () { - if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID], "") != 0) + if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID].pretty, "") != 0) internal_error (__FILE__, __LINE__, - "_initialize_gdb_osabi: gdb_osabi_names[] is inconsistent"); + _("_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); + + /* Register the "set osabi" command. */ + 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; }