This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [PATCH/RFA] Add OS/ABI infrastructure to SuperH target
- From: Elena Zannoni <ezannoni at redhat dot com>
- To: thorpej at wasabisystems dot com
- Cc: gdb-patches at sources dot redhat dot com
- Date: Tue, 7 May 2002 11:18:01 -0400
- Subject: Re: [PATCH/RFA] Add OS/ABI infrastructure to SuperH target
- References: <20020507014529.I503@dr-evil.shagadelic.org>
Jason R Thorpe writes:
> The following adds OS/ABI handling a'la the ARM and Alpha targets
> to the SuperH target.
>
> Once this is in, I'll be able to commit my NetBSD/sh variant.
>
> OK to commit?
>
> * sh-tdep.c (sh_abi_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_abi): Declare.
> (gdbarch_tdep): Add sh_abi and abi_name members.
>
Ah, great! But hmmm...it would be ok, except that I am afraid there
may be some conflict with the sh5 work. In there I defined:
enum sh_abi
{
SH_ABI_UNKNOWN,
SH_ABI_32,
SH_ABI_64
};
The ABI is unknown for all the architectures except for sh5 where it
is set to either 32 or 64 depending on the bfd. I am not saying this
is completely correct, note.
Is there any chance you could take a look at the sh5 patch I posted a
while back, and see if/how your patch integrates (in principle, at least)?
The patch is here:
http://sources.redhat.com/ml/gdb-patches/2002-02/msg00218.html
About your patch, I would prefer if the switch on the os_number used
names instead of 0,1,2, is this possible? Same for this line:
+ if (elfosabi == 0)
thanks
Elena
> --
> -- Jason R. Thorpe <thorpej@wasabisystems.com>
> Index: sh-tdep.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/sh-tdep.c,v
> retrieving revision 1.52
> diff -u -r1.52 sh-tdep.c
> --- sh-tdep.c 12 Apr 2002 18:18:57 -0000 1.52
> +++ sh-tdep.c 7 May 2002 08:21:59 -0000
> @@ -41,6 +41,8 @@
> #include "regcache.h"
> #include "doublest.h"
>
> +#include "elf-bfd.h"
> +
> #include "solib-svr4.h"
>
> void (*sh_show_regs) (void);
> @@ -1895,6 +1897,182 @@
> }
> #endif /* SVR4_SHARED_LIBS */
>
> +
> +/* This table matches the indices assigned to enum sh_abi. Keep
> + them in sync. */
> +static const char * const sh_abi_names[] =
> +{
> + "<unknown>",
> + "GNU/Linux",
> + "NetBSD ELF",
> + NULL
> +};
> +
> +static void
> +process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
> +{
> + enum sh_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 = SH_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);
> + }
> + }
> + }
> + /* 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 = SH_ABI_NETBSD_ELF;
> + }
> +}
> +
> +static int
> +get_elfosabi (bfd *abfd)
> +{
> + int elfosabi;
> + enum sh_abi sh_abi = SH_ABI_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. */
> + if (elfosabi == 0)
> + {
> + bfd_map_over_sections (abfd,
> + process_note_abi_tag_sections,
> + &sh_abi);
> + }
> +
> + if (sh_abi != SH_ABI_UNKNOWN)
> + return sh_abi;
> +
> + switch (elfosabi)
> + {
> + case ELFOSABI_NONE:
> + /* Leave it as unknown. */
> + break;
> +
> + case ELFOSABI_NETBSD:
> + return SH_ABI_NETBSD_ELF;
> +
> + case ELFOSABI_LINUX:
> + return SH_ABI_LINUX;
> + }
> +
> + return SH_ABI_UNKNOWN;
> +}
> +
> +struct sh_abi_handler
> +{
> + struct sh_abi_handler *next;
> + enum sh_abi abi;
> + void (*init_abi)(struct gdbarch_info, struct gdbarch *);
> +};
> +
> +struct sh_abi_handler *sh_abi_handler_list = NULL;
> +
> +void
> +sh_gdbarch_register_os_abi (enum sh_abi abi,
> + void (*init_abi)(struct gdbarch_info,
> + struct gdbarch *))
> +{
> + struct sh_abi_handler **handler_p;
> +
> + for (handler_p = &sh_abi_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_abi = init_abi;
> + return;
> + }
> + }
> +
> + (*handler_p)
> + = (struct sh_abi_handler *) xmalloc (sizeof (struct sh_abi_handler));
> + (*handler_p)->next = NULL;
> + (*handler_p)->abi = abi;
> + (*handler_p)->init_abi = init_abi;
> +}
> +
> static gdbarch_init_ftype sh_gdbarch_init;
>
> static struct gdbarch *
> @@ -1906,17 +2084,51 @@
> 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_abi sh_abi = SH_ABI_UNKNOWN;
> + struct sh_abi_handler *abi_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_abi = get_elfosabi (info.abfd);
> + break;
> +
> + default:
> + /* Just leave it as "unkown". */
> + break;
> + }
> + }
>
> /* Find a candidate among the list of pre-declared architectures. */
> - arches = gdbarch_list_lookup_by_info (arches, &info);
> - if (arches != NULL)
> - return arches->gdbarch;
> + for (arches = gdbarch_list_lookup_by_info (arches, &info);
> + 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_abi == sh_abi)
> + return arches->gdbarch;
> + }
>
> /* None found, create a new architecture from the information
> provided. */
> tdep = XMALLOC (struct gdbarch_tdep);
> gdbarch = gdbarch_alloc (&info, tdep);
>
> + tdep->sh_abi = sh_abi;
> + if (sh_abi < SH_ABI_INVALID)
> + tdep->abi_name = sh_abi_names[sh_abi];
> + else
> + {
> + internal_error (__FILE__, __LINE__, "Invalid setting of sh_abi %d",
> + (int) sh_abi);
> + tdep->abi_name = "<invalid>";
> + }
> +
> /* Initialize the register numbers that are not common to all the
> variants to -1, if necessary thse will be overwritten in the case
> statement below. */
> @@ -2167,15 +2379,58 @@
> 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_abi != SH_ABI_UNKNOWN)
> + {
> + for (abi_handler = sh_abi_handler_list; abi_handler != NULL;
> + abi_handler = abi_handler->next)
> + if (abi_handler->abi == sh_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 SuperH settings",
> + sh_abi_names[sh_abi]);
> + }
> + }
> +
> 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->abi_name != NULL)
> + fprintf_unfiltered (file, "sh_dump_tdep: ABI = %s\n", tdep->abi_name);
> + else
> + internal_error (__FILE__, __LINE__,
> + "sh_dump_tdep: illegal setting of tdep->sh_abi (%d)",
> + (int) tdep->sh_abi);
> +}
> +
> void
> _initialize_sh_tdep (void)
> {
> 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");
> }
> Index: config/sh/tm-sh.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/config/sh/tm-sh.h,v
> retrieving revision 1.16
> diff -u -r1.16 tm-sh.h
> --- config/sh/tm-sh.h 12 Jul 2001 02:29:33 -0000 1.16
> +++ config/sh/tm-sh.h 7 May 2002 08:22:00 -0000
> @@ -23,6 +23,17 @@
>
> #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_abi
> +{
> + SH_ABI_UNKNOWN = 0,
> + SH_ABI_LINUX,
> + SH_ABI_NETBSD_ELF,
> +
> + SH_ABI_INVALID /* Keep this last. */
> +};
> +
> /* Information that is dependent on the processor variant. */
>
> struct gdbarch_tdep
> @@ -56,6 +67,9 @@
> int ARGLAST_REGNUM;
> int FLOAT_ARGLAST_REGNUM;
> int RETURN_REGNUM;
> +
> + enum sh_abi sh_abi; /* OS/ABI of the inferior */
> + const char *abi_name; /* Name of the above */
> };
>
> /* Registers common to all the SH variants. */
> @@ -81,4 +95,3 @@
> #define LITTLE_REMOTE_BREAKPOINT { 0x20, 0xc3 } /* Used in remote.c */
>
> /*#define NOP {0x20, 0x0b}*/ /* Who uses this???*/
> -