Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.184 diff -u -r1.184 Makefile.in --- Makefile.in 11 May 2002 22:14:19 -0000 1.184 +++ Makefile.in 12 May 2002 04:03:40 -0000 @@ -530,7 +530,7 @@ demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \ event-loop.c event-top.c \ expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \ - findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c \ + findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c osabi.c \ inf-loop.c infcmd.c inflow.c infrun.c language.c \ kod.c kod-cisco.c \ ui-out.c cli-out.c \ @@ -634,6 +634,7 @@ memattr_h = memattr.h monitor_h = monitor.h objfiles_h = objfiles.h +osabi_h = osabi.h parser_defs_h = parser-defs.h $(doublest_h) regcache_h = regcache.h remote_h = remote.h @@ -712,7 +713,7 @@ symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \ expprint.o environ.o stack.o thread.o \ event-loop.o event-top.o inf-loop.o completer.o \ - gdbarch.o arch-utils.o gdbtypes.o copying.o $(DEPFILES) \ + gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o $(DEPFILES) \ memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \ builtin-regs.o std-regs.o \ signals.o \ @@ -1556,6 +1557,8 @@ gdbtypes.o: gdbtypes.c $(bfd_h) $(complaints_h) $(defs_h) $(expression_h) \ $(gdbtypes_h) $(language_h) $(objfiles_h) $(symfile_h) $(symtab_h) \ $(target_h) $(value_h) $(gdb_string_h) $(wrapper_h) $(cp_abi_h) + +osabi.o: osabi.c $(defs_h) $(osabi_h) $(BFD_SRC)/elf-bfd.h go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) gdb_wait.h $(gdbcore_h) \ $(command_h) $(floatformat_h) $(target_h) i387-tdep.h $(regcache_h) Index: osabi.c =================================================================== RCS file: osabi.c diff -N osabi.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ osabi.c 12 May 2002 04:03:41 -0000 @@ -0,0 +1,334 @@ +/* OS ABI variant handling for GDB. + Copyright 2001, 2002 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 + (at your option) any later version. + + 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. */ + +#include "defs.h" +#include "osabi.h" +#include "elf-bfd.h" + + +/* This table matches the indices assigned to enum gdb_osabi. Keep + them in sync. */ +static const char * const gdb_osabi_names[] = +{ + "", + + "SVR4", + "GNU Hurd", + "Solaris", + "OSF/1", + "GNU/Linux", + "FreeBSD a.out", + "FreeBSD ELF", + "NetBSD a.out", + "NetBSD ELF", + "Windows CE", + + "ARM EABI v1" + "ARM EABI v2" + "ARM APCS", + + 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 ""; +} + +/* 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 *next; + enum bfd_architecture arch; + 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, enum gdb_osabi osabi, + void (*init_osabi)(struct gdbarch_info, + struct gdbarch *)) +{ + struct gdb_osabi_handler **handler_p; + + for (handler_p = &gdb_osabi_handler_list; *handler_p != NULL; + handler_p = &(*handler_p)->next) + { + if ((*handler_p)->arch == arch + && (*handler_p)->osabi == osabi) + { + internal_error + (__FILE__, __LINE__, + "gdbarch_register_osabi: A handler for this OS ABI variant " + "(%d) has already been registered for this architecture (%d)", + (int) osabi, (int) arch); + /* 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)->next = NULL; + (*handler_p)->arch = arch; + (*handler_p)->osabi = osabi; + (*handler_p)->init_osabi = init_osabi; +} + + +/* 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 + be careful to claim a file only if it knows for sure what it is. */ +struct gdb_osabi_sniffer +{ + struct gdb_osabi_sniffer *next; + enum bfd_architecture arch; /* bfd_arch_unknown == wildcard */ + 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->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; + + for (sniffer = gdb_osabi_sniffer_list; sniffer != NULL; + sniffer = sniffer->next) + { + if ((sniffer->arch == bfd_arch_unknown /* wildcard */ + || sniffer->arch == abfd->arch_info->arch) + && sniffer->flavour == abfd->xvec->flavour) + { + osabi = (*sniffer->sniffer) (abfd); + if (osabi != GDB_OSABI_UNKNOWN) + return osabi; + } + } + + return GDB_OSABI_UNKNOWN; +} + +int +gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch, + enum gdb_osabi osabi) +{ + struct gdb_osabi_handler *handler; + bfd *abfd = info.abfd; + + for (handler = gdb_osabi_handler_list; handler != NULL; + handler = handler->next) + { + if (handler->arch == abfd->arch_info->arch + && handler->osabi == osabi) + { + (*handler->init_osabi) (info, gdbarch); + return 0; + } + } + + /* Let the caller decide how much to complain. */ + return 1; +} + + +/* Generic sniffer for ELF flavoured files. */ + +static void +process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj) +{ + enum gdb_osabi *os_ident_ptr = obj; + const char *name; + unsigned int sectsize; + + 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); + + 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) + { + int os_number = bfd_h_get_32 (abfd, note + 16); + + switch (os_number) + { + case GNU_ABI_TAG_LINUX: + *os_ident_ptr = GDB_OSABI_LINUX; + break; + + case GNU_ABI_TAG_HURD: + *os_ident_ptr = GDB_OSABI_HURD; + break; + + case GNU_ABI_TAG_SOLARIS: + *os_ident_ptr = GDB_OSABI_SOLARIS; + break; + + default: + internal_error + (__FILE__, __LINE__, + "process_note_abi_sections: unknown OS number %d", + os_number); + } + return; + } + else if (name_length == 8 && data_length == 4 + && note_type == NT_FREEBSD_ABI_TAG + && strcmp (note + 12, "FreeBSD") == 0) + { + /* XXX Should we check the version here? Probably not + necessary yet. */ + *os_ident_ptr = GDB_OSABI_FREEBSD_ELF; + } + return; + } + + /* .note.netbsd.ident notes, used by NetBSD. */ + if (strcmp (name, ".note.netbsd.ident") == 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); + + 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 == 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; + } + return; + } +} + +static enum gdb_osabi +generic_elf_osabi_sniffer (bfd *abfd) +{ + int elfosabi; + enum gdb_osabi osabi = GDB_OSABI_UNKNOWN; + + elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI]; + + switch (elfosabi) + { + case ELFOSABI_NONE: + /* When elfosabi is ELFOSABI_NONE (0), this is supposed to indicate + that we're on a SVR4 system. However, some systems use note sections + to record OS/ABI info, but leave e_ident[EI_OSABI] zero. So we + have to check the note sections, too. */ + bfd_map_over_sections (abfd, + process_note_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_LINUX: + osabi = GDB_OSABI_LINUX; + break; + + case ELFOSABI_HURD: + osabi = GDB_OSABI_HURD; + break; + + case ELFOSABI_SOLARIS: + osabi = GDB_OSABI_SOLARIS; + break; + } + + return osabi; +} + + +void +_initialize_gdb_osabi (void) +{ + /* Register a generic sniffer for ELF flavoured files. */ + gdbarch_register_osabi_sniffer (bfd_arch_unknown, + bfd_target_elf_flavour, + generic_elf_osabi_sniffer); +} Index: osabi.h =================================================================== RCS file: osabi.h diff -N osabi.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ osabi.h 12 May 2002 04:03:41 -0000 @@ -0,0 +1,72 @@ +/* OS ABI variant handling for GDB. + Copyright 2001, 2002 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 + (at your option) any later version. + + 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. */ + +#ifndef OSABI_H +#define OSABI_H + +/* List of known OS ABIs. If you change this, make sure to update the + table in osabi.c. */ +enum gdb_osabi +{ + GDB_OSABI_UNKNOWN = 0, /* keep this first */ + + GDB_OSABI_SVR4, + GDB_OSABI_HURD, + GDB_OSABI_SOLARIS, + GDB_OSABI_OSF1, + GDB_OSABI_LINUX, + GDB_OSABI_FREEBSD_AOUT, + GDB_OSABI_FREEBSD_ELF, + GDB_OSABI_NETBSD_AOUT, + GDB_OSABI_NETBSD_ELF, + GDB_OSABI_WINCE, + + GDB_OSABI_ARM_EABI_V1, + GDB_OSABI_ARM_EABI_V2, + GDB_OSABI_ARM_APCS, + + GDB_OSABI_INVALID /* keep this last */ +}; + +/* Register an OS ABI sniffer. Each arch/flavour may have more than + one sniffer. This is used to e.g. differentiate one OS's a.out from + another. The first sniffer to return something other than + GDB_OSABI_UNKNOWN wins, so a sniffer should be careful to claim a file + only if it knows for sure what it is. */ +void gdbarch_register_osabi_sniffer (enum bfd_architecture, + enum bfd_flavour, + enum gdb_osabi (*)(bfd *)); + +/* Register a handler for an OS ABI variant for a given architecture. There + should be only one handler for a given OS ABI each architecture family. */ +void gdbarch_register_osabi (enum bfd_architecture, enum gdb_osabi, + void (*)(struct gdbarch_info, + struct gdbarch *)); + +/* Lookup the OS ABI corresponding to the specified BFD. */ +enum gdb_osabi gdbarch_lookup_osabi (bfd *); + +/* Initialize the gdbarch for the specified OS ABI variant. */ +int gdbarch_init_osabi (struct gdbarch_info, struct gdbarch *, enum gdb_osabi); + +/* Return the name of the specified OS ABI. */ +const char *gdbarch_osabi_name (enum gdb_osabi); + +#endif /* OSABI_H */