X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fosabi.c;h=22130f00fc81e6a305d684527bcd3e09d671c621;hb=c709acd150761fffe3536bf9e6a0b32870f41ca3;hp=097a45a0d01333786af0473aeacde2c3f2d2b375;hpb=d33b9831c7678a1e7a27b9f6195e59a095d28297;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/osabi.c b/gdb/osabi.c index 097a45a0d0..22130f00fc 100644 --- a/gdb/osabi.c +++ b/gdb/osabi.c @@ -1,22 +1,22 @@ /* OS ABI variant handling for GDB. - Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + Copyright (C) 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 + 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" @@ -63,19 +63,16 @@ static const char * const gdb_osabi_names[] = "OpenBSD ELF", "Windows CE", "DJGPP", - "NetWare", "Irix", - "LynxOS", "Interix", "HP/UX ELF", "HP/UX SOM", - - "ARM EABI v1", - "ARM EABI v2", - "ARM APCS", "QNX Neutrino", - "Cygwin", + "AIX", + "DICOS", + "Darwin", + "Symbian", "" }; @@ -89,6 +86,30 @@ gdbarch_osabi_name (enum gdb_osabi osabi) return gdb_osabi_names[GDB_OSABI_INVALID]; } +/* 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]) == 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 @@ -116,9 +137,9 @@ gdbarch_register_osabi (enum bfd_architecture arch, unsigned long machine, { internal_error (__FILE__, __LINE__, - "gdbarch_register_osabi: An attempt to register a handler for " + _("gdbarch_register_osabi: An attempt to register a handler for " "OS ABI \"%s\" for architecture %s was made. The handler will " - "not be registered", + "not be registered"), gdbarch_osabi_name (osabi), bfd_printable_arch_mach (arch, machine)); return; @@ -134,8 +155,8 @@ gdbarch_register_osabi (enum bfd_architecture arch, unsigned long machine, { 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), arch_info->printable_name); /* If user wants to continue, override previous definition. */ @@ -163,7 +184,7 @@ gdbarch_register_osabi (enum bfd_architecture arch, unsigned long machine, } -/* 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 @@ -207,15 +228,11 @@ gdbarch_lookup_osabi (bfd *abfd) if (user_osabi_state == osabi_user) return user_selected_osabi; - /* If we don't have a binary, return the default OS ABI (if set) or - an inconclusive result (otherwise). */ + /* 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) - { - if (GDB_OSABI_DEFAULT != GDB_OSABI_UNKNOWN) - return GDB_OSABI_DEFAULT; - else - return GDB_OSABI_UNINITIALIZED; - } + return GDB_OSABI_UNKNOWN; match = GDB_OSABI_UNKNOWN; match_specific = 0; @@ -232,8 +249,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)); @@ -251,9 +268,9 @@ gdbarch_lookup_osabi (bfd *abfd) { internal_error (__FILE__, __LINE__, - "gdbarch_lookup_osabi: multiple %sspecific OS ABI " + _("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), @@ -276,12 +293,7 @@ gdbarch_lookup_osabi (bfd *abfd) } } - /* If we didn't find a match, but a default was specified at configure - time, return the default. */ - if (GDB_OSABI_DEFAULT != GDB_OSABI_UNKNOWN && match == GDB_OSABI_UNKNOWN) - return GDB_OSABI_DEFAULT; - else - return match; + return match; } @@ -355,119 +367,138 @@ gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch) 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. */ + +static int +check_note (bfd *abfd, asection *sect, const char *note, + const char *name, unsigned long descsz, unsigned long type) +{ + unsigned long notesz; + + /* 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 comtain the complete note. */ + if (notesz > bfd_section_size (abfd, 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 = 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; + /* Limit the amount of data to read. */ + if (sectsize > MAX_NOTESZ) + sectsize = MAX_NOTESZ; - note = alloca (sectsize); + note = alloca (sectsize); + bfd_get_section_contents (abfd, sect, note, 0, 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 == 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, "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: - *os_ident_ptr = GDB_OSABI_FREEBSD_ELF; + *osabi = GDB_OSABI_FREEBSD_ELF; break; - + case GNU_ABI_TAG_NETBSD: - *os_ident_ptr = GDB_OSABI_NETBSD_ELF; + *osabi = GDB_OSABI_NETBSD_ELF; break; - + default: - internal_error - (__FILE__, __LINE__, - "generic_elf_osabi_sniff_abi_tag_sections: unknown OS number %d", - os_number); + internal_error (__FILE__, __LINE__, + _("generic_elf_osabi_sniff_abi_tag_sections: " + "unknown OS number %d"), + abi_tag); } 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, "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_ELF; + 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, "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); - - 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); + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_NETBSD_ELF; + 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.openbsd.ident notes, used by OpenBSD. */ + if (strcmp (name, ".note.openbsd.ident") == 0 + && check_note (abfd, sect, note, "OpenBSD", 4, NT_OPENBSD_IDENT)) + { + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_OPENBSD_ELF; return; } /* .note.netbsdcore.procinfo notes, used by NetBSD. */ - if (strcmp (name, ".note.netbsdcore.procinfo") == 0 && sectsize > 0) + if (strcmp (name, ".note.netbsdcore.procinfo") == 0) { - *os_ident_ptr = GDB_OSABI_NETBSD_ELF; + *osabi = GDB_OSABI_NETBSD_ELF; return; } } @@ -483,10 +514,15 @@ 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: + /* 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. */ bfd_map_over_sections (abfd, generic_elf_osabi_sniff_abi_tag_sections, &osabi); @@ -500,20 +536,19 @@ generic_elf_osabi_sniffer (bfd *abfd) osabi = GDB_OSABI_NETBSD_ELF; break; - case ELFOSABI_LINUX: - osabi = GDB_OSABI_LINUX; - break; - - case ELFOSABI_HURD: - osabi = GDB_OSABI_HURD; - break; - case ELFOSABI_SOLARIS: osabi = GDB_OSABI_SOLARIS; break; case 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). We use HP-UX ELF as the default, but let any + OS-specific notes override this. */ osabi = GDB_OSABI_HPUX_ELF; + bfd_map_over_sections (abfd, + generic_elf_osabi_sniff_abi_tag_sections, + &osabi); break; } @@ -522,7 +557,8 @@ generic_elf_osabi_sniffer (bfd *abfd) /* 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) + if (memcmp (&elf_elfheader (abfd)->e_ident[8], + "FreeBSD", sizeof ("FreeBSD")) == 0) osabi = GDB_OSABI_FREEBSD_ELF; } @@ -549,6 +585,7 @@ set_osabi (char *args, int from_tty, struct cmd_list_element *c) else { int i; + for (i = 1; i < GDB_OSABI_INVALID; i++) if (strcmp (set_osabi_string, gdbarch_osabi_name (i)) == 0) { @@ -558,7 +595,7 @@ set_osabi (char *args, int from_tty, struct cmd_list_element *c) } if (i == GDB_OSABI_INVALID) internal_error (__FILE__, __LINE__, - "Invalid OS ABI \"%s\" passed to command handler.", + _("Invalid OS ABI \"%s\" passed to command handler."), set_osabi_string); } @@ -566,22 +603,25 @@ set_osabi (char *args, int from_tty, struct cmd_list_element *c) graceful here. */ gdbarch_info_init (&info); if (! gdbarch_update_p (info)) - internal_error (__FILE__, __LINE__, "Updating OS ABI failed."); + internal_error (__FILE__, __LINE__, _("Updating OS ABI failed.")); } static void -show_osabi (char *args, int from_tty) +show_osabi (struct ui_file *file, int from_tty, struct cmd_list_element *c, + const char *value) { if (user_osabi_state == osabi_auto) - printf_filtered ("The current OS ABI is \"auto\" (currently \"%s\").\n", - gdbarch_osabi_name (gdbarch_osabi (current_gdbarch))); + fprintf_filtered (file, + _("The current OS ABI is \"auto\" " + "(currently \"%s\").\n"), + gdbarch_osabi_name (gdbarch_osabi (get_current_arch ()))); else - printf_filtered ("The current OS ABI is \"%s\".\n", - gdbarch_osabi_name (user_selected_osabi)); + fprintf_filtered (file, _("The current OS ABI is \"%s\".\n"), + gdbarch_osabi_name (user_selected_osabi)); if (GDB_OSABI_DEFAULT != GDB_OSABI_UNKNOWN) - printf_filtered ("The default OS ABI is \"%s\".\n", - gdbarch_osabi_name (GDB_OSABI_DEFAULT)); + fprintf_filtered (file, _("The default OS ABI is \"%s\".\n"), + gdbarch_osabi_name (GDB_OSABI_DEFAULT)); } extern initialize_file_ftype _initialize_gdb_osabi; /* -Wmissing-prototype */ @@ -589,12 +629,10 @@ extern initialize_file_ftype _initialize_gdb_osabi; /* -Wmissing-prototype */ void _initialize_gdb_osabi (void) { - struct cmd_list_element *c; - if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID], "") != 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, @@ -602,11 +640,11 @@ _initialize_gdb_osabi (void) generic_elf_osabi_sniffer); /* Register the "set osabi" command. */ - c = add_set_enum_cmd ("osabi", class_support, gdb_osabi_available_names, - &set_osabi_string, "Set OS ABI of target.", &setlist); - - set_cmd_sfunc (c, set_osabi); - add_cmd ("osabi", class_support, show_osabi, "Show OS/ABI of target.", - &showlist); + 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; }