forked from Imagelibrary/binutils-gdb
* sh-tdep.c (sh_osabi_names): Declare.
(process_note_abi_tag_sections): New function. (get_elfosabi): Ditto. (sh_gdbarch_register_os_abi): Ditto. (sh_dump_tdep): Ditto. _initialize_sh_tdep): Use gdbarch_register to register sh_gdbarch_init and sh_dump_tdep. * config/sh/tm-sh.h (sh_osabi): Declare. (gdbarch_tdep): Add sh_osabi and osabi_name members.
This commit is contained in:
@@ -1,3 +1,15 @@
|
|||||||
|
2002-05-08 Jason Thorpe <thorpej@wasabisystems.com>
|
||||||
|
|
||||||
|
* sh-tdep.c (sh_osabi_names): Declare.
|
||||||
|
(process_note_abi_tag_sections): New function.
|
||||||
|
(get_elfosabi): Ditto.
|
||||||
|
(sh_gdbarch_register_os_abi): Ditto.
|
||||||
|
(sh_dump_tdep): Ditto.
|
||||||
|
_initialize_sh_tdep): Use gdbarch_register to register
|
||||||
|
sh_gdbarch_init and sh_dump_tdep.
|
||||||
|
* config/sh/tm-sh.h (sh_osabi): Declare.
|
||||||
|
(gdbarch_tdep): Add sh_osabi and osabi_name members.
|
||||||
|
|
||||||
2002-05-07 Andrew Cagney <ac131313@redhat.com>
|
2002-05-07 Andrew Cagney <ac131313@redhat.com>
|
||||||
|
|
||||||
* arm-tdep.c (arm_skip_prologue): Handle generic dummy frames.
|
* arm-tdep.c (arm_skip_prologue): Handle generic dummy frames.
|
||||||
|
|||||||
@@ -23,6 +23,17 @@
|
|||||||
|
|
||||||
#define GDB_MULTI_ARCH 1
|
#define GDB_MULTI_ARCH 1
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
};
|
||||||
|
|
||||||
/* Information that is dependent on the processor variant. */
|
/* Information that is dependent on the processor variant. */
|
||||||
|
|
||||||
struct gdbarch_tdep
|
struct gdbarch_tdep
|
||||||
@@ -56,6 +67,9 @@ struct gdbarch_tdep
|
|||||||
int ARGLAST_REGNUM;
|
int ARGLAST_REGNUM;
|
||||||
int FLOAT_ARGLAST_REGNUM;
|
int FLOAT_ARGLAST_REGNUM;
|
||||||
int RETURN_REGNUM;
|
int RETURN_REGNUM;
|
||||||
|
|
||||||
|
enum sh_osabi sh_osabi; /* OS/ABI of the inferior */
|
||||||
|
const char *osabi_name; /* Name of the above */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Registers common to all the SH variants. */
|
/* Registers common to all the SH variants. */
|
||||||
@@ -81,4 +95,3 @@ enum
|
|||||||
#define LITTLE_REMOTE_BREAKPOINT { 0x20, 0xc3 } /* Used in remote.c */
|
#define LITTLE_REMOTE_BREAKPOINT { 0x20, 0xc3 } /* Used in remote.c */
|
||||||
|
|
||||||
/*#define NOP {0x20, 0x0b}*/ /* Who uses this???*/
|
/*#define NOP {0x20, 0x0b}*/ /* Who uses this???*/
|
||||||
|
|
||||||
|
|||||||
255
gdb/sh-tdep.c
255
gdb/sh-tdep.c
@@ -41,6 +41,8 @@
|
|||||||
#include "regcache.h"
|
#include "regcache.h"
|
||||||
#include "doublest.h"
|
#include "doublest.h"
|
||||||
|
|
||||||
|
#include "elf-bfd.h"
|
||||||
|
|
||||||
#include "solib-svr4.h"
|
#include "solib-svr4.h"
|
||||||
|
|
||||||
void (*sh_show_regs) (void);
|
void (*sh_show_regs) (void);
|
||||||
@@ -1895,6 +1897,176 @@ sh_linux_svr4_fetch_link_map_offsets (void)
|
|||||||
}
|
}
|
||||||
#endif /* SVR4_SHARED_LIBS */
|
#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 gdbarch_init_ftype sh_gdbarch_init;
|
||||||
|
|
||||||
static struct gdbarch *
|
static struct gdbarch *
|
||||||
@@ -1906,17 +2078,51 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
gdbarch_register_name_ftype *sh_register_name;
|
gdbarch_register_name_ftype *sh_register_name;
|
||||||
gdbarch_store_return_value_ftype *sh_store_return_value;
|
gdbarch_store_return_value_ftype *sh_store_return_value;
|
||||||
gdbarch_register_virtual_type_ftype *sh_register_virtual_type;
|
gdbarch_register_virtual_type_ftype *sh_register_virtual_type;
|
||||||
|
enum sh_osabi sh_osabi = SH_OSABI_UNKNOWN;
|
||||||
|
struct sh_osabi_handler *osabi_handler;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find a candidate among the list of pre-declared architectures. */
|
/* Find a candidate among the list of pre-declared architectures. */
|
||||||
arches = gdbarch_list_lookup_by_info (arches, &info);
|
for (arches = gdbarch_list_lookup_by_info (arches, &info);
|
||||||
if (arches != NULL)
|
arches != NULL;
|
||||||
|
arches = gdbarch_list_lookup_by_info (arches->next, &info))
|
||||||
|
{
|
||||||
|
/* Make sure the ABI selection matches. */
|
||||||
|
tdep = gdbarch_tdep (arches->gdbarch);
|
||||||
|
if (tdep && tdep->sh_osabi == sh_osabi)
|
||||||
return arches->gdbarch;
|
return arches->gdbarch;
|
||||||
|
}
|
||||||
|
|
||||||
/* None found, create a new architecture from the information
|
/* None found, create a new architecture from the information
|
||||||
provided. */
|
provided. */
|
||||||
tdep = XMALLOC (struct gdbarch_tdep);
|
tdep = XMALLOC (struct gdbarch_tdep);
|
||||||
gdbarch = gdbarch_alloc (&info, 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>";
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize the register numbers that are not common to all the
|
/* Initialize the register numbers that are not common to all the
|
||||||
variants to -1, if necessary thse will be overwritten in the case
|
variants to -1, if necessary thse will be overwritten in the case
|
||||||
statement below. */
|
statement below. */
|
||||||
@@ -2167,15 +2373,58 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
|
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
|
||||||
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
|
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;
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return gdbarch;
|
return gdbarch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sh_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
|
||||||
|
{
|
||||||
|
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_sh_tdep (void)
|
_initialize_sh_tdep (void)
|
||||||
{
|
{
|
||||||
struct cmd_list_element *c;
|
struct cmd_list_element *c;
|
||||||
|
|
||||||
register_gdbarch_init (bfd_arch_sh, sh_gdbarch_init);
|
gdbarch_register (bfd_arch_sh, sh_gdbarch_init, sh_dump_tdep);
|
||||||
|
|
||||||
add_com ("regs", class_vars, sh_show_regs_command, "Print all registers");
|
add_com ("regs", class_vars, sh_show_regs_command, "Print all registers");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user