* Makefile.in (SFILES): Add osabi.c.

(COMMON_OBS): Add osabi.o.
(osabi.o): New dependency list.
* osabi.c: New file.
* osabi.h: New file.
* doc/gdbint.texinfo: Document new generic OS ABI framework.

* Makefile.in (alpha_tdep_h): Define and use instead of
alpha-tdep.h.
* alpha-tdep.c (alpha_abi_names, process_note_abi_tag_sections,
get_elfosabi, alpha_abi_handler_list, alpha_gdbarch_register_os_abi):
Remove.
(alpha_gdbarch_init, alpha_dump_tdep): Use generic OS ABI framework.
* alpha-tdep.h: Include osabi.h.
(alpha_abi): Remove.
(gdbarch_tdep): Use generic OS ABI framework.
* alpha-linux-tdep.c (_initialize_alpha_linux_tdep): Use
gdbarch_register_osabi.
* alpha-osf1-tdep.c (_initialize_alpha_osf1_tdep): Likewise.
* alphafbsd-tdep.c (_initialize_alphafbsd_tdep): Likewise.
* alphanbsd-tdep.c (_initialize_alphanbsd_tdep): Likewise.

* Makefile.in (sh_tdep_h): Add osabi.h.
* sh-tdep.h (sh_osabi): Remove.
(gdbarch_tdep): Use generic OS ABI framework.
* sh-tdep.c (sh_osabi_names, process_note_abi_tag_sections,
sh_osabi_handler_list, sh_gdbarch_register_os_abi): Remove.
(sh_gdbarch_init, sh_dump_tdep): Use generic OS ABI framework.
* shnbsd-tdep.c (_initialize_shnbsd_tdep): Use gdbarch_register_osabi.

* Makefile.in (arm_tdep_h): Define and use instead of arm-tdep.h.
* arm-linux-tdep.c (_initialize_arm_linux_tdep): Use
gdbarch_register_osabi.
* arm-tdep.c (arm_abi_names, process_note_abi_tag_sections,
arm_abi_handler_list, arm_gdbarch_register_os_abi): Remove.
(get_elfosabi): Rename to...
(arm_elf_osabi_sniffer): ...this.  Adjust to use generic OS
ABI framework support routines.
(arm_gdbarch_init): Use generic OS ABI framework.
(arm_dump_tdep): Likewise.
(_initialize_arm_tdep): Likewise.
* arm-tdep.h: Include osabi.h.
(arm_abi): Remove.
(gdbarch_tdep): Remove arm_abi and abi_name members.  Add
osabi member.
(arm_gdbarch_register_os_abi): Remove prototype.
* armnbsd-tdep.c (arm_netbsd_aout_osabi_sniffer): New function.
(_initialize_arm_netbsd_tdep): Use gdbarch_register_osabi.

* Makefile.in (mips-tdep.o): Add osabi.h to dependency list.
* mips-tdep.c: Include osabi.h.
(gdbarch_tdep, mips_gdbarch_init, mips_dump_tdep): Use generic
OS ABI framework.
This commit is contained in:
Jason Thorpe 2002-05-21 15:36:03 +00:00
parent 658f25883a
commit 70f80edf7c
19 changed files with 875 additions and 828 deletions

View File

@ -1,3 +1,59 @@
2002-05-21 Jason Thorpe <thorpej@wasabisystems.com>
* Makefile.in (SFILES): Add osabi.c.
(COMMON_OBS): Add osabi.o.
(osabi.o): New dependency list.
* osabi.c: New file.
* osabi.h: New file.
* doc/gdbint.texinfo: Document new generic OS ABI framework.
* Makefile.in (alpha_tdep_h): Define and use instead of
alpha-tdep.h.
* alpha-tdep.c (alpha_abi_names, process_note_abi_tag_sections,
get_elfosabi, alpha_abi_handler_list, alpha_gdbarch_register_os_abi):
Remove.
(alpha_gdbarch_init, alpha_dump_tdep): Use generic OS ABI framework.
* alpha-tdep.h: Include osabi.h.
(alpha_abi): Remove.
(gdbarch_tdep): Use generic OS ABI framework.
* alpha-linux-tdep.c (_initialize_alpha_linux_tdep): Use
gdbarch_register_osabi.
* alpha-osf1-tdep.c (_initialize_alpha_osf1_tdep): Likewise.
* alphafbsd-tdep.c (_initialize_alphafbsd_tdep): Likewise.
* alphanbsd-tdep.c (_initialize_alphanbsd_tdep): Likewise.
* Makefile.in (sh_tdep_h): Add osabi.h.
* sh-tdep.h (sh_osabi): Remove.
(gdbarch_tdep): Use generic OS ABI framework.
* sh-tdep.c (sh_osabi_names, process_note_abi_tag_sections,
sh_osabi_handler_list, sh_gdbarch_register_os_abi): Remove.
(sh_gdbarch_init, sh_dump_tdep): Use generic OS ABI framework.
* shnbsd-tdep.c (_initialize_shnbsd_tdep): Use gdbarch_register_osabi.
* Makefile.in (arm_tdep_h): Define and use instead of arm-tdep.h.
* arm-linux-tdep.c (_initialize_arm_linux_tdep): Use
gdbarch_register_osabi.
* arm-tdep.c (arm_abi_names, process_note_abi_tag_sections,
arm_abi_handler_list, arm_gdbarch_register_os_abi): Remove.
(get_elfosabi): Rename to...
(arm_elf_osabi_sniffer): ...this. Adjust to use generic OS
ABI framework support routines.
(arm_gdbarch_init): Use generic OS ABI framework.
(arm_dump_tdep): Likewise.
(_initialize_arm_tdep): Likewise.
* arm-tdep.h: Include osabi.h.
(arm_abi): Remove.
(gdbarch_tdep): Remove arm_abi and abi_name members. Add
osabi member.
(arm_gdbarch_register_os_abi): Remove prototype.
* armnbsd-tdep.c (arm_netbsd_aout_osabi_sniffer): New function.
(_initialize_arm_netbsd_tdep): Use gdbarch_register_osabi.
* Makefile.in (mips-tdep.o): Add osabi.h to dependency list.
* mips-tdep.c: Include osabi.h.
(gdbarch_tdep, mips_gdbarch_init, mips_dump_tdep): Use generic
OS ABI framework.
2002-05-20 Kazu Hirata <kazu@cs.umass.edu>
* h8300-tdep.c: Fix formatting.

View File

@ -530,7 +530,7 @@ SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \
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 \
@ -593,8 +593,10 @@ xm_h = @xm_h@
tm_h = @tm_h@
nm_h = @nm_h@
alpha_tdep_h = alpha-tdep.h osabi.h
annotate_h = annotate.h $(symtab_h) $(gdbtypes_h)
arch_utils_h = arch-utils.h
arm_tdep_h = arm-tdep.h osabi.h
ax_h = ax.h $(doublest_h)
bcache_h = bcache.h
builtin_regs_h = builtin-regs.h
@ -649,7 +651,7 @@ remote_h = remote.h
remote_utils_h = remote-utils.h $(target_h)
ser_unix_h = ser-unix.h
serial_h = serial.h
sh_tdep_h = sh-tdep.h
sh_tdep_h = sh-tdep.h osabi.h
solist_h = solist.h
source_h = source.h
stabsread_h = stabsread.h
@ -724,7 +726,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
expprint.o environ.o stack.o thread.o \
macrotab.o macrocmd.o macroexp.o macroscope.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 \
@ -1256,44 +1258,44 @@ a68v-nat.o: a68v-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) \
$(regcache_h)
alpha-nat.o: alpha-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(target_h) \
$(regcache_h) alpha-tdep.h
$(regcache_h) $(alpha_tdep_h)
alphabsd-nat.o: alphabsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
alpha-tdep.h alphabsd-tdep.h
$(alpha_tdep_h) alphabsd-tdep.h
alpha-tdep.o: alpha-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
$(inferior_h) $(symtab_h) $(dis_asm_h) $(gdb_string_h) $(linespec_h) \
$(regcache_h) $(doublest_h) $(BFD_SRC)/elf-bfd.h alpha-tdep.h
$(regcache_h) $(doublest_h) $(BFD_SRC)/elf-bfd.h $(alpha_tdep_h)
alpha-linux-tdep.o: alpha-linux-tdep.c $(defs_h) $(value_h) alpha-tdep.h
alpha-linux-tdep.o: alpha-linux-tdep.c $(defs_h) $(value_h) $(alpha_tdep_h)
alpha-osf1-tdep.o: alpha-osf1-tdep.c $(defs_h) $(value_h) alpha-tdep.h
alpha-osf1-tdep.o: alpha-osf1-tdep.c $(defs_h) $(value_h) $(alpha_tdep_h)
alphabsd-tdep.o: alphabsd-tdep.c $(defs_h) $(regcache_h) alphabsd-tdep.h
alphafbsd-tdep.o: alphafbsd-tdep.c $(defs_h) $(value_h) alpha-tdep.h
alphafbsd-tdep.o: alphafbsd-tdep.c $(defs_h) $(value_h) $(alpha_tdep_h)
alphanbsd-tdep.o: alphanbsd-tdep.c $(defs_h) $(gdbcore_h) $(regcache_h) \
$(value_h) alpha-tdep.h alphabsd-tdep.h nbsd-tdep.h
$(value_h) $(alpha_tdep_h) alphabsd-tdep.h nbsd-tdep.h
annotate.o: annotate.c $(defs_h) $(annotate_h) $(value_h) $(target_h) $(gdbtypes_h)
arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
$(gdb_string_h) $(regcache_h) arm-tdep.h
$(gdb_string_h) $(regcache_h) $(arm_tdep_h)
arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \
$(gdbtypes_h) $(floatformat_h) $(regcache_h) $(doublest_h) arm-tdep.h
$(gdbtypes_h) $(floatformat_h) $(regcache_h) $(doublest_h) $(arm_tdep_h)
arm-tdep.o: arm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcmd_h) \
$(gdbcore_h) $(gdb_string_h) $(dis_asm_h) $(regcache_h) $(doublest_h) \
$(value_h) $(arch_utils_h) $(solib_svr4_h) arm-tdep.h \
$(value_h) $(arch_utils_h) $(solib_svr4_h) $(arm_tdep_h) \
$(BFD_SRC)/elf-bfd.h $(INCLUDE_DIR)/coff/internal.h \
$(INCLUDE_DIR)/elf/arm.h
armnbsd-nat.o: armnbsd-nat.c $(defs_h) arm-tdep.h $(inferior_h) $(regcache_h) \
$(gdbcore_h)
armnbsd-nat.o: armnbsd-nat.c $(defs_h) $(arm_tdep_h) $(inferior_h) \
$(regcache_h) $(gdbcore_h)
armnbsd-tdep.o: armnbsd-tdep.c $(defs_h) arm-tdep.h
armnbsd-tdep.o: armnbsd-tdep.c $(defs_h) $(arm_tdep_h)
avr-tdep.o: avr-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
$(symfile_h) $(regcache_h) $(arch_utils_h)
@ -1585,6 +1587,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) $(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)
@ -1811,7 +1815,8 @@ mips-nat.o: mips-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(regcache_h)
mips-tdep.o: mips-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
$(arch_utils_h) $(regcache_h) \
$(inferior_h) $(language_h) $(objfiles_h) $(symfile_h) $(gdb_string_h)
$(inferior_h) $(language_h) $(objfiles_h) $(symfile_h) \
$(gdb_string_h) osabi.h
mipsread.o: mipsread.c $(buildsym_h) $(complaints_h) $(bfd_h) $(defs_h) \
$(expression_h) $(gdb_stabs_h) $(gdbcore_h) $(gdbtypes_h) \
@ -1933,7 +1938,7 @@ remote-array.o: remote-array.c $(defs_h) $(gdbcore_h) $(target_h) \
$(version_h) $(regcache_h)
remote-rdi.o: remote-rdi.c $(defs_h) $(gdbcore_h) \
$(inferior_h) $(gdb_string_h) $(completer_h) arm-tdep.h
$(inferior_h) $(gdb_string_h) $(completer_h) $(arm_tdep_h)
rdi-share/libangsd.a: force
@dir=rdi-share; \
@ -1946,7 +1951,7 @@ rdi-share/libangsd.a: force
fi
remote-rdp.o: remote-rdp.c $(defs_h) $(gdbcore_h) \
$(inferior_h) $(gdb_string_h) arm-tdep.h
$(inferior_h) $(gdb_string_h) $(arm_tdep_h)
remote-bug.o: remote-bug.c $(defs_h) $(gdbcore_h) $(serial_h) \
$(inferior_h) $(target_h) $(terminal_h) $(remote_utils_h) \

View File

@ -116,5 +116,6 @@ alpha_linux_init_abi (struct gdbarch_info info,
void
_initialize_alpha_linux_tdep (void)
{
alpha_gdbarch_register_os_abi (ALPHA_ABI_LINUX, alpha_linux_init_abi);
gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_LINUX,
alpha_linux_init_abi);
}

View File

@ -69,5 +69,5 @@ alpha_osf1_init_abi (struct gdbarch_info info,
void
_initialize_alpha_osf1_tdep (void)
{
alpha_gdbarch_register_os_abi (ALPHA_ABI_OSF1, alpha_osf1_init_abi);
gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_OSF1, alpha_osf1_init_abi);
}

View File

@ -1766,186 +1766,6 @@ alpha_software_single_step (enum target_signal sig, int insert_breakpoints_p)
}
/* This table matches the indices assigned to enum alpha_abi. Keep
them in sync. */
static const char * const alpha_abi_names[] =
{
"<unknown>",
"OSF/1",
"GNU/Linux",
"FreeBSD",
"NetBSD",
NULL
};
static void
process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
{
enum alpha_abi *os_ident_ptr = obj;
const char *name;
unsigned int sectsize;
name = bfd_get_section_name (abfd, sect);
sectsize = bfd_section_size (abfd, sect);
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 == 1
&& strcmp (note + 12, "GNU") == 0)
{
int os_number = bfd_h_get_32 (abfd, note + 16);
/* The case numbers are from abi-tags in glibc. */
switch (os_number)
{
case 0 :
*os_ident_ptr = ALPHA_ABI_LINUX;
break;
case 1 :
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: Hurd objects not supported");
break;
case 2 :
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: Solaris objects not supported");
break;
default :
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: unknown OS number %d",
os_number);
break;
}
}
}
/* 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 = ALPHA_ABI_NETBSD;
}
}
static int
get_elfosabi (bfd *abfd)
{
int elfosabi;
enum alpha_abi alpha_abi = ALPHA_ABI_UNKNOWN;
elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
/* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate
what 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. */
if (elfosabi == 0)
{
bfd_map_over_sections (abfd,
process_note_abi_tag_sections,
&alpha_abi);
}
if (alpha_abi != ALPHA_ABI_UNKNOWN)
return alpha_abi;
switch (elfosabi)
{
case ELFOSABI_NONE:
/* Leave it as unknown. */
break;
case ELFOSABI_NETBSD:
return ALPHA_ABI_NETBSD;
case ELFOSABI_FREEBSD:
return ALPHA_ABI_FREEBSD;
case ELFOSABI_LINUX:
return ALPHA_ABI_LINUX;
}
return ALPHA_ABI_UNKNOWN;
}
struct alpha_abi_handler
{
struct alpha_abi_handler *next;
enum alpha_abi abi;
void (*init_abi)(struct gdbarch_info, struct gdbarch *);
};
struct alpha_abi_handler *alpha_abi_handler_list = NULL;
void
alpha_gdbarch_register_os_abi (enum alpha_abi abi,
void (*init_abi)(struct gdbarch_info,
struct gdbarch *))
{
struct alpha_abi_handler **handler_p;
for (handler_p = &alpha_abi_handler_list; *handler_p != NULL;
handler_p = &(*handler_p)->next)
{
if ((*handler_p)->abi == abi)
{
internal_error
(__FILE__, __LINE__,
"alpha_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;
}
}
(*handler_p)
= (struct alpha_abi_handler *) xmalloc (sizeof (struct alpha_abi_handler));
(*handler_p)->next = NULL;
(*handler_p)->abi = abi;
(*handler_p)->init_abi = init_abi;
}
/* Initialize the current architecture based on INFO. If possible, re-use an
architecture from ARCHES, which is a list of architectures already created
@ -1959,27 +1779,18 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch_tdep *tdep;
struct gdbarch *gdbarch;
enum alpha_abi alpha_abi = ALPHA_ABI_UNKNOWN;
struct alpha_abi_handler *abi_handler;
enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
/* Try to determine 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:
alpha_abi = get_elfosabi (info.abfd);
break;
case bfd_target_ecoff_flavour:
/* Assume it's OSF/1. */
alpha_abi = ALPHA_ABI_OSF1;
break;
default:
/* Not sure what to do here, leave the ABI as unknown. */
break;
/* If it's an ECOFF file, assume it's OSF/1. */
if (bfd_get_flavour (info.abfd) == bfd_target_ecoff_flavour)
osabi = GDB_OSABI_OSF1;
}
}
@ -1990,22 +1801,14 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
/* Make sure the ABI selection matches. */
tdep = gdbarch_tdep (arches->gdbarch);
if (tdep && tdep->alpha_abi == alpha_abi)
if (tdep && tdep->osabi == osabi)
return arches->gdbarch;
}
tdep = xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
tdep->alpha_abi = alpha_abi;
if (alpha_abi < ALPHA_ABI_INVALID)
tdep->abi_name = alpha_abi_names[alpha_abi];
else
{
internal_error (__FILE__, __LINE__, "Invalid setting of alpha_abi %d",
(int) alpha_abi);
tdep->abi_name = "<invalid>";
}
tdep->osabi = osabi;
/* Lowest text address. This is used by heuristic_proc_start() to
decide when to stop looking. */
@ -2122,38 +1925,7 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_frame_args_skip (gdbarch, 0);
/* Hook in ABI-specific overrides, if they have been registered. */
if (alpha_abi == ALPHA_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 Alpha settings");
}
else
{
for (abi_handler = alpha_abi_handler_list; abi_handler != NULL;
abi_handler = abi_handler->next)
if (abi_handler->abi == alpha_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 Alpha settings",
alpha_abi_names[alpha_abi]);
}
}
gdbarch_init_osabi (info, gdbarch, osabi);
/* Now that we have tuned the configuration, set a few final things
based on what the OS ABI has told us. */
@ -2172,12 +1944,8 @@ alpha_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
if (tdep == NULL)
return;
if (tdep->abi_name != NULL)
fprintf_unfiltered (file, "alpha_dump_tdep: ABI = %s\n", tdep->abi_name);
else
internal_error (__FILE__, __LINE__,
"alpha_dump_tdep: illegal setting of tdep->alpha_abi (%d)",
(int) tdep->alpha_abi);
fprintf_unfiltered (file, "alpha_dump_tdep: OS ABI = %s\n",
gdbarch_osabi_name (tdep->osabi));
fprintf_unfiltered (file,
"alpha_dump_tdep: vm_min_address = 0x%lx\n",

View File

@ -22,6 +22,8 @@
#ifndef ALPHA_TDEP_H
#define ALPHA_TDEP_H
#include "osabi.h"
/* Say how long (ordinary) registers are. This is a piece of bogosity
used in push_word and a few other places; REGISTER_RAW_SIZE is the
real way to know how big a register is. */
@ -76,24 +78,10 @@
pointer, the value of localoff is obtained from the PDR. */
#define ALPHA_NUM_ARG_REGS 6
/* ABI variants that we know about. If you add to this enum, please
update the table of names in alpha-tdep.c. */
enum alpha_abi
{
ALPHA_ABI_UNKNOWN = 0,
ALPHA_ABI_OSF1,
ALPHA_ABI_LINUX,
ALPHA_ABI_FREEBSD,
ALPHA_ABI_NETBSD,
ALPHA_ABI_INVALID /* Keep this last. */
};
/* Target-dependent structure in gdbarch. */
struct gdbarch_tdep
{
enum alpha_abi alpha_abi; /* OS/ABI of inferior. */
const char *abi_name; /* Name of the above. */
enum gdb_osabi osabi; /* OS/ABI of inferior. */
CORE_ADDR vm_min_address; /* used by heuristic_proc_start */
@ -118,8 +106,4 @@ struct gdbarch_tdep
void alpha_software_single_step (enum target_signal, int);
void alpha_gdbarch_register_os_abi (enum alpha_abi,
void (*init_abi)(struct gdbarch_info,
struct gdbarch *));
#endif /* ALPHA_TDEP_H */

View File

@ -78,5 +78,6 @@ alphafbsd_init_abi (struct gdbarch_info info,
void
_initialize_alphafbsd_tdep (void)
{
alpha_gdbarch_register_os_abi (ALPHA_ABI_FREEBSD, alphafbsd_init_abi);
gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_FREEBSD_ELF,
alphafbsd_init_abi);
}

View File

@ -203,7 +203,8 @@ alphanbsd_init_abi (struct gdbarch_info info,
void
_initialize_alphanbsd_tdep (void)
{
alpha_gdbarch_register_os_abi (ALPHA_ABI_NETBSD, alphanbsd_init_abi);
gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_NETBSD_ELF,
alphanbsd_init_abi);
add_core_fns (&alphanbsd_core_fns);
add_core_fns (&alphanbsd_elfcore_fns);

View File

@ -543,5 +543,5 @@ arm_linux_init_abi (struct gdbarch_info info,
void
_initialize_arm_linux_tdep (void)
{
arm_gdbarch_register_os_abi (ARM_ABI_LINUX, arm_linux_init_abi);
gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_LINUX, arm_linux_init_abi);
}

View File

@ -93,23 +93,6 @@
#define MSYMBOL_SIZE(msym) \
((long) MSYMBOL_INFO (msym) & 0x7fffffff)
/* This table matches the indices 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;
@ -2608,208 +2591,82 @@ arm_coff_make_msymbol_special(int val, struct minimal_symbol *msym)
}
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;
name = bfd_get_section_name (abfd, sect);
sectsize = bfd_section_size (abfd, sect);
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 == 1
&& strcmp (note + 12, "GNU") == 0)
{
int os_number = bfd_h_get_32 (abfd, note + 16);
/* The case numbers are from abi-tags in glibc. */
switch (os_number)
{
case 0 :
*os_ident_ptr = ARM_ABI_LINUX;
break;
case 1 :
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: Hurd objects not supported");
break;
case 2 :
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: Solaris objects not supported");
break;
default :
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: unknown OS number %d",
os_number);
break;
}
}
}
/* 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;
unsigned int elfosabi, eflags;
enum gdb_osabi osabi = GDB_OSABI_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.
GNU/ARM tools set the EI_OSABI field to ELFOSABI_ARM, so handle that
as well. */
if (elfosabi == 0 || elfosabi == ELFOSABI_ARM)
{
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))
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)
{
case EF_ARM_EABI_VER1:
return ARM_ABI_EABI_V1;
/* 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 EF_ARM_EABI_VER1:
osabi = GDB_OSABI_ARM_EABI_V1;
break;
case EF_ARM_EABI_VER2:
return ARM_ABI_EABI_V2;
case EF_ARM_EABI_VER2:
osabi = GDB_OSABI_ARM_EABI_V2;
break;
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));
case EF_ARM_EABI_UNKNOWN:
/* Assume GNU tools. */
osabi = GDB_OSABI_ARM_APCS;
break;
default:
internal_error (__FILE__, __LINE__,
"arm_elf_osabi_sniffer: Unknown ARM EABI "
"version 0x%x", eflags);
}
}
break;
case ELFOSABI_NETBSD:
return ARM_ABI_NETBSD_ELF;
case ELFOSABI_ARM:
/* GNU tools use this value. Check note sections in this case,
as well. */
bfd_map_over_sections (abfd,
generic_elf_osabi_sniff_abi_tag_sections,
&osabi);
if (osabi == GDB_OSABI_UNKNOWN)
{
/* Assume APCS ABI. */
osabi = GDB_OSABI_ARM_APCS;
}
break;
case ELFOSABI_FREEBSD:
return ARM_ABI_FREEBSD;
osabi = GDB_OSABI_FREEBSD_ELF;
break;
case ELFOSABI_NETBSD:
osabi = GDB_OSABI_NETBSD_ELF;
break;
case ELFOSABI_LINUX:
return ARM_ABI_LINUX;
case ELFOSABI_ARM:
/* Assume GNU tools with the old APCS abi. */
return ARM_ABI_APCS;
default:
osabi = GDB_OSABI_LINUX;
break;
}
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;
void
arm_gdbarch_register_os_abi (enum arm_abi abi,
void (*init_abi)(struct gdbarch_info,
struct gdbarch *))
{
struct arm_abi_handler **handler_p;
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;
}
}
(*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;
}
/* 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.
@ -2822,36 +2679,31 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
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;
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_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;
case bfd_target_coff_flavour:
/* Assume it's an old APCS-style ABI. */
/* XXX WinCE? */
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;
default:
/* Not sure what to do here, leave the ABI as unknown. */
break;
default:
/* Leave it as "unknown". */
}
}
}
@ -2862,22 +2714,14 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
/* 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;
@ -3047,38 +2891,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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. */
@ -3144,12 +2957,8 @@ arm_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
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);
@ -3191,10 +3000,18 @@ _initialize_arm_tdep (void)
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;

View File

@ -18,6 +18,8 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "osabi.h"
/* Register numbers of various important registers. Note that some of
these values are "real" register numbers, and correspond to the
general registers of the machine, and some are "phony" register
@ -104,23 +106,6 @@ enum gdb_regnum {
#define FLAG_C 0x20000000
#define FLAG_V 0x10000000
/* ABI variants that we know about. If you add to this enum, please
update the table of names in tm-arm.c. */
enum arm_abi
{
ARM_ABI_UNKNOWN = 0,
ARM_ABI_EABI_V1,
ARM_ABI_EABI_V2,
ARM_ABI_LINUX,
ARM_ABI_NETBSD_AOUT,
ARM_ABI_NETBSD_ELF,
ARM_ABI_APCS,
ARM_ABI_FREEBSD,
ARM_ABI_WINCE,
ARM_ABI_INVALID /* Keep this last. */
};
/* Type of floating-point code in use by inferior. There are really 3 models
that are traditionally supported (plus the endianness issue), but gcc can
only generate 2 of those. The third is APCS_FLOAT, where arguments to
@ -139,8 +124,7 @@ enum arm_float_model
/* Target-dependent structure in gdbarch. */
struct gdbarch_tdep
{
enum arm_abi arm_abi; /* OS/ABI of inferior. */
const char *abi_name; /* Name of the above. */
enum gdb_osabi osabi; /* OS/ABI of inferior. */
enum arm_float_model fp_model; /* Floating point calling conventions. */
@ -170,10 +154,3 @@ int arm_pc_is_thumb (CORE_ADDR);
CORE_ADDR thumb_get_next_pc (CORE_ADDR);
CORE_ADDR arm_get_next_pc (CORE_ADDR);
/* How a OS variant tells the ARM generic code that it can handle an ABI
type. */
void
arm_gdbarch_register_os_abi (enum arm_abi abi,
void (*init_abi)(struct gdbarch_info,
struct gdbarch *));

View File

@ -77,9 +77,23 @@ arm_netbsd_elf_init_abi (struct gdbarch_info info,
tdep->fp_model = ARM_FLOAT_SOFT_VFP;
}
static enum gdb_osabi
arm_netbsd_aout_osabi_sniffer (bfd *abfd)
{
if (strcmp (bfd_get_target (abfd), "a.out-arm-netbsd") == 0)
return GDB_OSABI_NETBSD_AOUT;
return GDB_OSABI_UNKNOWN;
}
void
_initialize_arm_netbsd_tdep (void)
{
arm_gdbarch_register_os_abi (ARM_ABI_NETBSD_AOUT, arm_netbsd_aout_init_abi);
arm_gdbarch_register_os_abi (ARM_ABI_NETBSD_ELF, arm_netbsd_elf_init_abi);
gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_aout_flavour,
arm_netbsd_aout_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_NETBSD_AOUT,
arm_netbsd_aout_init_abi);
gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_NETBSD_ELF,
arm_netbsd_elf_init_abi);
}

View File

@ -2312,6 +2312,127 @@ The target architecture object is implemented as the C structure
@code{struct gdbarch *}. The structure, and its methods, are generated
using the Bourne shell script @file{gdbarch.sh}.
@section Operating System ABI Variant Handling
@cindex OS ABI variants
@value{GDBN} provides a mechanism for handling variations in OS
ABIs. An OS ABI variant may have influence over any number of
variables in the target architecture definition. There are two major
components in the OS ABI mechanism: sniffers and handlers.
A @dfn{sniffer} examines a file matching a BFD architecture/flavour pair
(the architecture may be wildcarded) in an attempt to determine the
OS ABI of that file. Sniffers with a wildcarded architecture are considered
to be @dfn{generic}, while sniffers for a specific architecture are
considered to be @dfn{specific}. A match from a specific sniffer
overrides a match from a generic sniffer. Multiple sniffers for an
architecture/flavour may exist, in order to differentiate between two
different operating systems which use the same basic file format. The
OS ABI framework provides a generic sniffer for ELF-format files which
examines the @code{EI_OSABI} field of the ELF header, as well as note
sections known to be used by several operating systems.
@cindex fine-tuning @code{gdbarch} structure
A @dfn{handler} is used to fine-tune the @code{gdbarch} structure for the
selected OS ABI. There may be only one handler for a given OS ABI
for each BFD architecture.
The following OS ABI variants are defined in @file{osabi.h}:
@table @code
@findex GDB_OSABI_UNKNOWN
@item GDB_OSABI_UNKNOWN
The ABI of the inferior is unknown. The default @code{gdbarch}
settings for the architecture will be used.
@findex GDB_OSABI_SVR4
@item GDB_OSABI_SVR4
UNIX System V Release 4
@findex GDB_OSABI_HURD
@item GDB_OSABI_HURD
GNU using the Hurd kernel
@findex GDB_OSABI_SOLARIS
@item GDB_OSABI_SOLARIS
Sun Solaris
@findex GDB_OSABI_OSF1
@item GDB_OSABI_OSF1
OSF/1, including Digital UNIX and Compaq Tru64 UNIX
@findex GDB_OSABI_LINUX
@item GDB_OSABI_LINUX
GNU using the Linux kernel
@findex GDB_OSABI_FREEBSD_AOUT
@item GDB_OSABI_FREEBSD_AOUT
FreeBSD using the a.out executable format
@findex GDB_OSABI_FREEBSD_ELF
@item GDB_OSABI_FREEBSD_ELF
FreeBSD using the ELF executable format
@findex GDB_OSABI_NETBSD_AOUT
@item GDB_OSABI_NETBSD_AOUT
NetBSD using the a.out executable format
@findex GDB_OSABI_NETBSD_ELF
@item GDB_OSABI_NETBSD_ELF
NetBSD using the ELF executable format
@findex GDB_OSABI_WINCE
@item GDB_OSABI_WINCE
Windows CE
@findex GDB_OSABI_ARM_EABI_V1
@item GDB_OSABI_ARM_EABI_V1
ARM Embedded ABI version 1
@findex GDB_OSABI_ARM_EABI_V2
@item GDB_OSABI_ARM_EABI_V2
ARM Embedded ABI version 2
@findex GDB_OSABI_ARM_APCS
@item GDB_OSABI_ARM_APCS
Generic ARM Procedure Call Standard
@end table
Here are the functions that make up the OS ABI framework:
@deftypefun const char *gdbarch_osabi_name (enum gdb_osabi @var{osabi})
Return the name of the OS ABI corresponding to @var{osabi}.
@end deftypefun
@deftypefun void gdbarch_register_osabi (enum bfd_architecture @var{arch}, enum gdb_osabi @var{osabi}, void (*@var{init_osabi})(struct gdbarch_info @var{info}, struct gdbarch *@var{gdbarch}))
Register the OS ABI handler specified by @var{init_osabi} for the
architecture/OS ABI pair specified by @var{arch} and @var{osabi}.
@end deftypefun
@deftypefun void gdbarch_register_osabi_sniffer (enum bfd_architecture @var{arch}, enum bfd_flavour @var{flavour}, enum gdb_osabi (*@var{sniffer})(bfd *@var{abfd}))
Register the OS ABI file sniffer specified by @var{sniffer} for the
BFD architecture/flavour pair specified by @var{arch} and @var{flavour}.
If @var{arch} is @code{bfd_arch_unknown}, the sniffer is considered to
be generic, and is allowed to examine @var{flavour}-flavoured files for
any architecture.
@end deftypefun
@deftypefun enum gdb_osabi gdbarch_lookup_osabi (bfd *@var{abfd})
Examine the file described by @var{abfd} to determine its OS ABI.
The value @code{GDB_OSABI_UNKNOWN} is returned if the OS ABI cannot
be determined.
@end deftypefun
@deftypefun void gdbarch_init_osabi (struct gdbarch info @var{info}, struct gdbarch *@var{gdbarch}, enum gdb_osabi @var{osabi})
Invoke the OS ABI handler corresponding to @var{osabi} to fine-tune the
@code{gdbarch} structure specified by @var{gdbarch}. If a handler
corresponding to @var{osabi} has not been registered for @var{gdbarch}'s
architecture, a warning will be issued and the debugging session will continue
with the defaults already established for @var{gdbarch}.
@end deftypefun
@section Registers and Memory
@value{GDBN}'s model of the target machine is rather simple.

View File

@ -38,6 +38,7 @@
#include "target.h"
#include "arch-utils.h"
#include "regcache.h"
#include "osabi.h"
#include "opcode/mips.h"
#include "elf/mips.h"
@ -119,6 +120,7 @@ struct gdbarch_tdep
{
/* from the elf header */
int elf_flags;
/* mips options */
enum mips_abi mips_abi;
const char *mips_abi_string;
@ -131,6 +133,8 @@ struct gdbarch_tdep
int mips_default_stack_argsize;
int gdb_target_is_mips64;
int default_mask_address_p;
enum gdb_osabi osabi;
};
#if GDB_MULTI_ARCH
@ -4132,6 +4136,7 @@ mips_gdbarch_init (struct gdbarch_info info,
struct gdbarch_tdep *tdep;
int elf_flags;
enum mips_abi mips_abi;
enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
/* Reset the disassembly info, in case it was set to something
non-default. */
@ -4139,12 +4144,18 @@ mips_gdbarch_init (struct gdbarch_info info,
tm_print_insn_info.arch = bfd_arch_unknown;
tm_print_insn_info.mach = 0;
/* Extract the elf_flags if available */
if (info.abfd != NULL
&& bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
elf_flags = elf_elfheader (info.abfd)->e_flags;
else
elf_flags = 0;
elf_flags = 0;
if (info.abfd)
{
/* First of all, extract the elf_flags, if available. */
if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
elf_flags = elf_elfheader (info.abfd)->e_flags;
/* Try to determine the OS ABI of the object we are loading. If
we end up with `unknown', just leave it that way. */
osabi = gdbarch_lookup_osabi (info.abfd);
}
/* Check ELF_FLAGS to see if it specifies the ABI being used. */
switch ((elf_flags & EF_MIPS_ABI))
@ -4215,13 +4226,15 @@ mips_gdbarch_init (struct gdbarch_info info,
continue;
if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
continue;
return arches->gdbarch;
if (gdbarch_tdep (arches->gdbarch)->osabi == osabi)
return arches->gdbarch;
}
/* Need a new architecture. Fill in a target specific vector. */
tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
tdep->elf_flags = elf_flags;
tdep->osabi = osabi;
/* Initially set everything according to the default ABI/ISA. */
set_gdbarch_short_bit (gdbarch, 16);
@ -4433,6 +4446,10 @@ mips_gdbarch_init (struct gdbarch_info info,
set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
/* Hook in OS ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch, osabi);
return gdbarch;
}
@ -4841,6 +4858,10 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
fprintf_unfiltered (file,
"mips_dump_tdep: _PROC_MAGIC_ = %d\n",
_PROC_MAGIC_);
fprintf_unfiltered (file,
"mips_dump_tdep: OS ABI = %s\n",
gdbarch_osabi_name (tdep->osabi));
}
void

424
gdb/osabi.c Normal file
View File

@ -0,0 +1,424 @@
/* 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[] =
{
"<unknown>",
"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",
"<invalid>"
};
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[GDB_OSABI_INVALID];
}
/* 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;
/* 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_osabi_name (osabi),
bfd_printable_arch_mach (arch, 0));
return;
}
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 OS ABI \"%s\" "
"has already been registered for architecture %s",
gdbarch_osabi_name (osabi),
bfd_printable_arch_mach (arch, 0));
/* 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->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;
match = GDB_OSABI_UNKNOWN;
match_specific = 0;
for (sniffer = gdb_osabi_sniffer_list; sniffer != NULL;
sniffer = sniffer->next)
{
if ((sniffer->arch == bfd_arch_unknown /* wildcard */
|| 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)
{
/* A specific sniffer always overrides a generic sniffer.
Croak on multiple match if the two matches are of the
same class. If the user wishes to continue, we'll use
the first match. */
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;
}
void
gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch,
enum gdb_osabi osabi)
{
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 not knowing the OS ABI if we don't
have an inferior. */
if (info.abfd)
fprintf_filtered
(gdb_stderr, "GDB doesn't recognize the OS ABI of the inferior. "
"Attempting to continue with the default %s settings",
bfd_printable_arch_mach (arch_info->arch, arch_info->mach));
return;
}
for (handler = gdb_osabi_handler_list; handler != NULL;
handler = handler->next)
{
if (handler->arch == bfd_get_arch (abfd)
&& handler->osabi == osabi)
{
(*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));
}
/* 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;
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__,
"generic_elf_osabi_sniff_abi_tag_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)
{
unsigned 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), 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);
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)
{
if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID], "<invalid>") != 0)
internal_error
(__FILE__, __LINE__,
"_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);
}

78
gdb/osabi.h Normal file
View File

@ -0,0 +1,78 @@
/* 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. */
void 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);
/* Helper routine for ELF file sniffers. This looks at ABI tag note
sections to determine the OS ABI from the note. It should be called
via bfd_map_over_sections. */
void generic_elf_osabi_sniff_abi_tag_sections (bfd *, asection *, void *);
#endif /* OSABI_H */

View File

@ -4179,175 +4179,6 @@ sh_linux_svr4_fetch_link_map_offsets (void)
#endif /* SVR4_SHARED_LIBS */
/* This table matches the indices assigned to enum sh_osabi. Keep
them in sync. */
static const char * const sh_osabi_names[] =
{
"<unknown>",
"GNU/Linux",
"NetBSD ELF",
NULL
};
static void
process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
{
enum sh_osabi *os_ident_ptr = obj;
const char *name;
unsigned int sectsize;
name = bfd_get_section_name (abfd, sect);
sectsize = bfd_section_size (abfd, sect);
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);
/* The case numbers are from abi-tags in glibc. */
switch (os_number)
{
case GNU_ABI_TAG_LINUX:
*os_ident_ptr = SH_OSABI_LINUX;
break;
case GNU_ABI_TAG_HURD:
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: Hurd objects not supported");
break;
case GNU_ABI_TAG_SOLARIS:
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: Solaris objects not supported");
break;
default:
internal_error
(__FILE__, __LINE__,
"process_note_abi_sections: unknown OS number %d",
os_number);
}
}
}
/* 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 == NT_NETBSD_IDENT
&& strcmp (note + 12, "NetBSD") == 0)
/* XXX Should we check the version here?
Probably not necessary yet. */
*os_ident_ptr = SH_OSABI_NETBSD_ELF;
}
}
static int
get_elfosabi (bfd *abfd)
{
int elfosabi;
enum sh_osabi sh_osabi = SH_OSABI_UNKNOWN;
elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
switch (elfosabi)
{
case ELFOSABI_NONE:
/* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate
that we're on a SYSV 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,
&sh_osabi);
break;
case ELFOSABI_NETBSD:
sh_osabi = SH_OSABI_NETBSD_ELF;
break;
case ELFOSABI_LINUX:
sh_osabi = SH_OSABI_LINUX;
break;
}
return (sh_osabi);
}
struct sh_osabi_handler
{
struct sh_osabi_handler *next;
enum sh_osabi abi;
void (*init_osabi)(struct gdbarch_info, struct gdbarch *);
};
struct sh_osabi_handler *sh_osabi_handler_list = NULL;
void
sh_gdbarch_register_os_abi (enum sh_osabi abi,
void (*init_osabi)(struct gdbarch_info,
struct gdbarch *))
{
struct sh_osabi_handler **handler_p;
for (handler_p = &sh_osabi_handler_list; *handler_p != NULL;
handler_p = &(*handler_p)->next)
{
if ((*handler_p)->abi == abi)
{
internal_error
(__FILE__, __LINE__,
"sh_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_osabi = init_osabi;
return;
}
}
(*handler_p)
= (struct sh_osabi_handler *) xmalloc (sizeof (struct sh_osabi_handler));
(*handler_p)->next = NULL;
(*handler_p)->abi = abi;
(*handler_p)->init_osabi = init_osabi;
}
static gdbarch_init_ftype sh_gdbarch_init;
static struct gdbarch *
@ -4359,23 +4190,14 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
gdbarch_register_name_ftype *sh_register_name;
gdbarch_store_return_value_ftype *sh_store_return_value;
gdbarch_register_virtual_type_ftype *sh_register_virtual_type;
enum sh_osabi sh_osabi = SH_OSABI_UNKNOWN;
struct sh_osabi_handler *osabi_handler;
enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
/* Try to determine the ABI of the object we are loading. */
if (info.abfd != NULL)
{
switch (bfd_get_flavour (info.abfd))
{
case bfd_target_elf_flavour:
sh_osabi = get_elfosabi (info.abfd);
break;
default:
/* Just leave it as "unkown". */
break;
}
osabi = gdbarch_lookup_osabi (info.abfd);
/* If we get "unknown" back, just leave it that way. */
}
/* Find a candidate among the list of pre-declared architectures. */
@ -4385,7 +4207,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
/* Make sure the ABI selection matches. */
tdep = gdbarch_tdep (arches->gdbarch);
if (tdep && tdep->sh_osabi == sh_osabi)
if (tdep && tdep->osabi == osabi)
return arches->gdbarch;
}
@ -4394,15 +4216,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep = XMALLOC (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
tdep->sh_osabi = sh_osabi;
if (sh_osabi < SH_OSABI_INVALID)
tdep->osabi_name = sh_osabi_names[sh_osabi];
else
{
internal_error (__FILE__, __LINE__, "Invalid setting of sh_osabi %d",
(int) sh_osabi);
tdep->osabi_name = "<invalid>";
}
tdep->osabi = osabi;
/* Initialize the register numbers that are not common to all the
variants to -1, if necessary thse will be overwritten in the case
@ -4754,32 +4568,11 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
/* Hook in ABI-specific overrides, if they have been registered. If
the ABI is unknown, this is probably an embedded target, so we
should not warn about this situation. */
if (sh_osabi != SH_OSABI_UNKNOWN)
{
for (osabi_handler = sh_osabi_handler_list; osabi_handler != NULL;
osabi_handler = osabi_handler->next)
if (osabi_handler->abi == sh_osabi)
break;
/* Hook in ABI-specific overrides, if they have been registered.
if (osabi_handler)
osabi_handler->init_osabi (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 SuperH settings",
sh_osabi_names[sh_osabi]);
}
}
FIXME: if the ABI is unknown, this is probably an embedded target,
so we should not warn about this situation. */
gdbarch_init_osabi (info, gdbarch, osabi);
return gdbarch;
}
@ -4792,12 +4585,8 @@ sh_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
if (tdep == NULL)
return;
if (tdep->osabi_name != NULL)
fprintf_unfiltered (file, "sh_dump_tdep: OS ABI = %s\n", tdep->osabi_name);
else
internal_error (__FILE__, __LINE__,
"sh_dump_tdep: illegal setting of tdep->sh_osabi (%d)",
(int) tdep->sh_osabi);
fprintf_unfiltered (file, "sh_dump_tdep: OS ABI = %s\n",
gdbarch_osabi_name (tdep->osabi));
}
void

View File

@ -22,21 +22,12 @@
#ifndef SH_TDEP_H
#define SH_TDEP_H
#include "osabi.h"
/* Contributed by Steve Chamberlain sac@cygnus.com */
/* Information that is dependent on the processor variant. */
/* ABI variants that we know about. If you add to this enum, please
update the table of names in sh-tdep.c. */
enum sh_osabi
{
SH_OSABI_UNKNOWN = 0,
SH_OSABI_LINUX,
SH_OSABI_NETBSD_ELF,
SH_OSABI_INVALID /* Keep this last. */
};
enum sh_abi
{
SH_ABI_UNKNOWN,
@ -98,8 +89,7 @@ struct gdbarch_tdep
int ARGLAST_REGNUM;
int FLOAT_ARGLAST_REGNUM;
int RETURN_REGNUM;
enum sh_osabi sh_osabi; /* OS/ABI of the inferior */
const char *osabi_name; /* Name of the above */
enum gdb_osabi osabi; /* OS/ABI of the inferior */
enum sh_abi sh_abi;
};

View File

@ -177,5 +177,5 @@ _initialize_shnbsd_tdep (void)
add_core_fns (&shnbsd_core_fns);
add_core_fns (&shnbsd_elfcore_fns);
sh_gdbarch_register_os_abi (SH_OSABI_NETBSD_ELF, shnbsd_init_abi);
gdbarch_register_osabi (bfd_arch_sh, GDB_OSABI_NETBSD_ELF, shnbsd_init_abi);
}