From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16767 invoked by alias); 30 Mar 2005 20:30:53 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 16080 invoked from network); 30 Mar 2005 20:30:30 -0000 Received: from unknown (HELO nevyn.them.org) (66.93.172.17) by sourceware.org with SMTP; 30 Mar 2005 20:30:30 -0000 Received: from drow by nevyn.them.org with local (Exim 4.50 #1 (Debian)) id 1DGjqn-0002xS-LO; Wed, 30 Mar 2005 15:31:41 -0500 Date: Wed, 30 Mar 2005 20:30:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Cc: Richard Earnshaw Subject: RFA: Update ARM architecture selection, add set arm abi Message-ID: <20050330203140.GA10953@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com, Richard Earnshaw Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.6+20040907i X-SW-Source: 2005-03/txt/msg00393.txt.bz2 This patch redoes the way the ARM target handles the architecture's ABI and floating point model. Right now we adjust the gdbarch in place when the FP model changes; but gdbarches are supposed to be read-only after their creation. What we should do instead is use gdbarch_update_p for this purpose. This also separates the ABI from the OSABI, for consistency with other architectures; this fixes assorted problems, including the core dump consistency discussed on gdb@ this week, and the use of the default OSABI for untagged binaries. If you've ever had GDB set the wrong breakpoint instruction when debugging a GNU/Linux ld.so, this is why; the patch should fix it. When creating an architecture we need to honor settings in this order: - Global settings set by the user. - Settings inferred from the current binary. - Settings inherited from the last ARM architecture created. This is usually equivalent to the settings it inferred from the binary; when gdbarch_update_p is used the new architecture is created without a BFD. - Defaults chosen by the architecture, in absence of anything else. OK? I've tested this as much as I can by inspection, on both APCS and AAPCS binaries, but another pair of eyes would be appreciated. Revised versions of two of the csl-arm-branch patches will use this machinery. -- Daniel Jacobowitz CodeSourcery, LLC 2005-03-30 Daniel Jacobowitz * arm-tdep.c (fp_model_strings): Add terminating NULL. (arm_abi_strings, arm_abi_global, arm_abi_string): New variables. (arm_extract_return_value, arm_store_return_value): Don't use arm_get_fp_model. (arm_get_fp_model, arm_set_fp): Delete. (arm_update_current_architecture): New function. (set_fp_model_sfunc): Call arm_update_current_architecture. (show_fp_model): Update output messages. (arm_set_abi, arm_show_abi): New functions. (arm_elf_osabi_sniffer): Only handle ELFOSABI_ARM. (arm_gdbarch_init): Infer the object's ABI separately from its OSABI. Search for a matching architecture. Honor the global ABI and FPU settings. Set floating point format based on the architecture. (arm_init_abi_eabi_v1, arm_init_abi_eabi_v2, arm_init_abi_apcs): Delete. (_initialize_arm_tdep): Don't call gdbarch_register_osabi. Create "arm set abi" command. * arm-tdep.h (arm_get_fp_model): Delete prototype. (enum arm_abi_kind): New type. (struct gdbarch_tdep): Add arm_abi field. * arm-linux-tdep.c (arm_linux_init_abi): Only override tdep->fp_model if it is ARM_FLOAT_AUTO. * armnbsd-tdep.c (arm_netbsd_aout_init_abi): Likewise. (arm_netbsd_elf_init_abi): Likewise. * defs.h (enum gdb_osabi): Delete ARM-specific OSABIs. * osabi.c (gdb_osabi_name): Likewise. Index: arm-linux-tdep.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/arm-linux-tdep.c,v retrieving revision 1.45 diff -u -p -r1.45 arm-linux-tdep.c --- arm-linux-tdep.c 29 Mar 2005 16:57:30 -0000 1.45 +++ arm-linux-tdep.c 30 Mar 2005 19:05:14 -0000 @@ -480,7 +480,8 @@ arm_linux_init_abi (struct gdbarch_info tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint); tdep->thumb_breakpoint_size = sizeof (arm_linux_thumb_le_breakpoint); - tdep->fp_model = ARM_FLOAT_FPA; + if (tdep->fp_model == ARM_FLOAT_AUTO) + tdep->fp_model = ARM_FLOAT_FPA; tdep->jb_pc = ARM_LINUX_JB_PC; tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE; Index: arm-tdep.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/arm-tdep.c,v retrieving revision 1.196 diff -u -p -r1.196 arm-tdep.c --- arm-tdep.c 29 Mar 2005 16:56:40 -0000 1.196 +++ arm-tdep.c 30 Mar 2005 20:10:27 -0000 @@ -107,13 +107,27 @@ static const char *fp_model_strings[] = "softfpa", "fpa", "softvfp", - "vfp" + "vfp", + NULL }; /* A variable that can be configured by the user. */ static enum arm_float_model arm_fp_model = ARM_FLOAT_AUTO; static const char *current_fp_model = "auto"; +/* The ABI to use. Keep this in sync with arm_abi_kind. */ +static const char *arm_abi_strings[] = +{ + "auto", + "APCS", + "AAPCS", + NULL +}; + +/* A variable that can be configured by the user. */ +static enum arm_abi_kind arm_abi_global = ARM_ABI_AUTO; +static const char *arm_abi_string = "auto"; + /* Number of different reg name sets (options). */ static int num_disassembly_options; @@ -2007,7 +2021,7 @@ arm_extract_return_value (struct type *t if (TYPE_CODE_FLT == TYPE_CODE (type)) { - switch (arm_get_fp_model (current_gdbarch)) + switch (gdbarch_tdep (current_gdbarch)->fp_model) { case ARM_FLOAT_FPA: { @@ -2204,7 +2218,7 @@ arm_store_return_value (struct type *typ { char buf[MAX_REGISTER_SIZE]; - switch (arm_get_fp_model (current_gdbarch)) + switch (gdbarch_tdep (current_gdbarch)->fp_model) { case ARM_FLOAT_FPA: @@ -2361,34 +2375,20 @@ show_arm_command (char *args, int from_t cmd_show_list (showarmcmdlist, from_tty, ""); } -enum arm_float_model -arm_get_fp_model (struct gdbarch *gdbarch) +static void +arm_update_current_architecture (void) { - if (arm_fp_model == ARM_FLOAT_AUTO) - return gdbarch_tdep (gdbarch)->fp_model; + struct gdbarch_info info; - return arm_fp_model; -} + /* If the current architecture is not ARM, we have nothing to do. */ + if (gdbarch_bfd_arch_info (current_gdbarch)->arch != bfd_arch_arm) + return; -static void -arm_set_fp (struct gdbarch *gdbarch) -{ - enum arm_float_model fp_model = arm_get_fp_model (gdbarch); + /* Update the architecture. */ + gdbarch_info_init (&info); - if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE - && (fp_model == ARM_FLOAT_SOFT_FPA || fp_model == ARM_FLOAT_FPA)) - { - set_gdbarch_double_format (gdbarch, - &floatformat_ieee_double_littlebyte_bigword); - set_gdbarch_long_double_format - (gdbarch, &floatformat_ieee_double_littlebyte_bigword); - } - else - { - set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little); - set_gdbarch_long_double_format (gdbarch, - &floatformat_ieee_double_little); - } + if (!gdbarch_update_p (info)) + internal_error (__FILE__, __LINE__, "could not update architecture"); } static void @@ -2408,8 +2408,7 @@ set_fp_model_sfunc (char *args, int from internal_error (__FILE__, __LINE__, _("Invalid fp model accepted: %s."), current_fp_model); - if (gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm) - arm_set_fp (current_gdbarch); + arm_update_current_architecture (); } static void @@ -2418,12 +2417,51 @@ show_fp_model (struct ui_file *file, int { struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - deprecated_show_value_hack (file, from_tty, c, value); - if (arm_fp_model == ARM_FLOAT_AUTO + if (arm_fp_model == ARM_FLOAT_AUTO + && gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm) + fprintf_filtered (file, _("\ +The current ARM floating point model is \"auto\" (currently \"%s\").\n"), + fp_model_strings[tdep->fp_model]); + else + fprintf_filtered (file, _("\ +The current ARM floating point model is \"%s\".\n"), + fp_model_strings[arm_fp_model]); +} + +static void +arm_set_abi (char *args, int from_tty, + struct cmd_list_element *c) +{ + enum arm_abi_kind arm_abi; + + for (arm_abi = ARM_ABI_AUTO; arm_abi != ARM_ABI_LAST; arm_abi++) + if (strcmp (arm_abi_string, arm_abi_strings[arm_abi]) == 0) + { + arm_abi_global = arm_abi; + break; + } + + if (arm_abi == ARM_ABI_LAST) + internal_error (__FILE__, __LINE__, _("Invalid ABI accepted: %s."), + arm_abi_string); + + arm_update_current_architecture (); +} + +static void +arm_show_abi (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + + if (arm_abi_global == ARM_ABI_AUTO && gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm) - /* i18n: "the default [floating point model] for the current ABI..." */ - printf_filtered (_(" - the default for the current ABI is \"%s\".\n"), - fp_model_strings[tdep->fp_model]); + fprintf_filtered (file, _("\ +The current ARM ABI is \"auto\" (currently \"%s\").\n"), + arm_abi_strings[tdep->arm_abi]); + else + fprintf_filtered (file, _("The current ARM ABI is \"%s\".\n"), + arm_abi_string); } /* If the user changes the register disassembly style used for info @@ -2540,71 +2578,14 @@ arm_elf_osabi_sniffer (bfd *abfd) 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); - if (osabi == GDB_OSABI_UNKNOWN) - { - /* 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: - osabi = GDB_OSABI_ARM_EABI_V2; - break; - - 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_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: - osabi = GDB_OSABI_FREEBSD_ELF; - break; - - case ELFOSABI_NETBSD: - osabi = GDB_OSABI_NETBSD_ELF; - break; - - case ELFOSABI_LINUX: - osabi = GDB_OSABI_LINUX; - break; - } + if (elfosabi == 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); + /* Anything else will be handled by the generic ELF sniffer. */ return osabi; } @@ -2621,42 +2602,120 @@ arm_gdbarch_init (struct gdbarch_info in { struct gdbarch_tdep *tdep; struct gdbarch *gdbarch; + struct gdbarch_list *best_arch; + enum arm_abi_kind arm_abi = arm_abi_global; + enum arm_float_model fp_model = arm_fp_model; - /* Try to deterimine the ABI of the object we are loading. */ + /* If we have an object to base this architecture on, try to determine + its ABI. */ - if (info.abfd != NULL && info.osabi == GDB_OSABI_UNKNOWN) + if (arm_abi == ARM_ABI_AUTO && info.abfd != NULL) { + int ei_osabi; + switch (bfd_get_flavour (info.abfd)) { case bfd_target_aout_flavour: /* Assume it's an old APCS-style ABI. */ - info.osabi = GDB_OSABI_ARM_APCS; + arm_abi = ARM_ABI_APCS; break; case bfd_target_coff_flavour: /* Assume it's an old APCS-style ABI. */ /* XXX WinCE? */ - info.osabi = GDB_OSABI_ARM_APCS; + arm_abi = ARM_ABI_APCS; + break; + + case bfd_target_elf_flavour: + ei_osabi = elf_elfheader (info.abfd)->e_ident[EI_OSABI]; + if (ei_osabi == ELFOSABI_ARM) + { + /* GNU tools used to use this value, but do not for EABI + objects. There's nowhere to tag an EABI version anyway, + so assume APCS. */ + arm_abi = ARM_ABI_APCS; + } + else if (ei_osabi == ELFOSABI_NONE) + { + int e_flags, eabi_ver; + + e_flags = elf_elfheader (info.abfd)->e_flags; + eabi_ver = EF_ARM_EABI_VERSION (e_flags); + + switch (eabi_ver) + { + case EF_ARM_EABI_UNKNOWN: + /* Assume GNU tools. */ + arm_abi = ARM_ABI_APCS; + break; + + case EF_ARM_EABI_VER4: + arm_abi = ARM_ABI_AAPCS; + break; + + default: + warning (_("unknown ARM EABI version 0x%x"), eabi_ver); + arm_abi = ARM_ABI_APCS; + break; + } + } break; default: - /* Leave it as "unknown". */ + /* Leave it as "auto". */ break; } } - /* If there is already a candidate, use it. */ - arches = gdbarch_list_lookup_by_info (arches, &info); + /* Now that we have inferred any architecture settings that we + can, try to inherit from the last ARM ABI. */ if (arches != NULL) - return arches->gdbarch; + { + if (arm_abi == ARM_ABI_AUTO) + arm_abi = gdbarch_tdep (arches->gdbarch)->arm_abi; + + if (fp_model == ARM_FLOAT_AUTO) + fp_model = gdbarch_tdep (arches->gdbarch)->fp_model; + } + else + { + /* There was no prior ARM architecture; fill in default values. */ + + if (arm_abi == ARM_ABI_AUTO) + arm_abi = ARM_ABI_APCS; + + /* We used to default to FPA for generic ARM, but almost nobody + uses that now, and we now provide a way for the user to force + the model. So default to the most useful variant. */ + if (fp_model == ARM_FLOAT_AUTO) + fp_model = ARM_FLOAT_SOFT_FPA; + } - tdep = xmalloc (sizeof (struct gdbarch_tdep)); + /* If there is already a candidate, use it. */ + for (best_arch = gdbarch_list_lookup_by_info (arches, &info); + best_arch != NULL; + best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info)) + { + if (arm_abi != gdbarch_tdep (best_arch->gdbarch)->arm_abi) + continue; + + if (fp_model != gdbarch_tdep (best_arch->gdbarch)->fp_model) + continue; + + /* Found a match. */ + break; + } + + if (best_arch != NULL) + return best_arch->gdbarch; + + tdep = xcalloc (1, sizeof (struct gdbarch_tdep)); gdbarch = gdbarch_alloc (&info, tdep); - /* We used to default to FPA for generic ARM, but almost nobody uses that - now, and we now provide a way for the user to force the model. So - default to the most useful variant. */ - tdep->fp_model = ARM_FLOAT_SOFT_FPA; + /* Record additional information about the architecture we are defining. + These are gdbarch discriminators, like the OSABI. */ + tdep->arm_abi = arm_abi; + tdep->fp_model = fp_model; /* Breakpoints. */ switch (info.byte_order) @@ -2772,12 +2831,23 @@ arm_gdbarch_init (struct gdbarch_info in set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big); set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big); set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big); - break; case BFD_ENDIAN_LITTLE: set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little); - arm_set_fp (gdbarch); + if (fp_model == ARM_FLOAT_SOFT_FPA || fp_model == ARM_FLOAT_FPA) + { + set_gdbarch_double_format + (gdbarch, &floatformat_ieee_double_littlebyte_bigword); + set_gdbarch_long_double_format + (gdbarch, &floatformat_ieee_double_littlebyte_bigword); + } + else + { + set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little); + set_gdbarch_long_double_format (gdbarch, + &floatformat_ieee_double_little); + } break; default: @@ -2800,27 +2870,6 @@ arm_dump_tdep (struct gdbarch *current_g (unsigned long) tdep->lowest_pc); } -static void -arm_init_abi_eabi_v1 (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - /* Place-holder. */ -} - -static void -arm_init_abi_eabi_v2 (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - /* Place-holder. */ -} - -static void -arm_init_abi_apcs (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - /* Place-holder. */ -} - extern initialize_file_ftype _initialize_arm_tdep; /* -Wmissing-prototypes */ void @@ -2844,14 +2893,6 @@ _initialize_arm_tdep (void) bfd_target_elf_flavour, arm_elf_osabi_sniffer); - /* Register some ABI variants for embedded systems. */ - gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V1, - arm_init_abi_eabi_v1); - gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V2, - arm_init_abi_eabi_v2); - gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_APCS, - arm_init_abi_apcs); - /* Get the number of possible sets of register names defined in opcodes. */ num_disassembly_options = get_arm_regname_num_options (); @@ -2929,6 +2970,13 @@ vfp - VFP co-processor."), set_fp_model_sfunc, show_fp_model, &setarmcmdlist, &showarmcmdlist); + /* Add a command to allow the user to force the ABI. */ + add_setshow_enum_cmd ("abi", class_support, arm_abi_strings, &arm_abi_string, + _("Set the ABI."), + _("Show the ABI."), + NULL, arm_set_abi, arm_show_abi, + &setarmcmdlist, &showarmcmdlist); + /* Debugging flag. */ add_setshow_boolean_cmd ("arm", class_maintenance, &arm_debug, _("Set ARM debugging."), Index: arm-tdep.h =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/arm-tdep.h,v retrieving revision 1.12 diff -u -p -r1.12 arm-tdep.h --- arm-tdep.h 25 Mar 2004 16:52:42 -0000 1.12 +++ arm-tdep.h 30 Mar 2005 19:24:17 -0000 @@ -113,12 +113,22 @@ enum arm_float_model ARM_FLOAT_LAST /* Keep at end. */ }; -/* A method to the setting based on user's choice and ABI setting. */ -enum arm_float_model arm_get_fp_model (struct gdbarch *); +/* ABI used by the inferior. */ +enum arm_abi_kind +{ + ARM_ABI_AUTO, + ARM_ABI_APCS, + ARM_ABI_AAPCS, + ARM_ABI_LAST +}; /* Target-dependent structure in gdbarch. */ struct gdbarch_tdep { + /* The ABI for this architecture. It should never be set to + ARM_ABI_AUTO. */ + enum arm_abi_kind arm_abi; + enum arm_float_model fp_model; /* Floating point calling conventions. */ CORE_ADDR lowest_pc; /* Lowest address at which instructions Index: armnbsd-tdep.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/armnbsd-tdep.c,v retrieving revision 1.16 diff -u -p -r1.16 armnbsd-tdep.c --- armnbsd-tdep.c 5 Jan 2005 15:43:43 -0000 1.16 +++ armnbsd-tdep.c 30 Mar 2005 19:04:46 -0000 @@ -78,7 +78,8 @@ arm_netbsd_aout_init_abi (struct gdbarch struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); arm_netbsd_init_abi_common (info, gdbarch); - tdep->fp_model = ARM_FLOAT_SOFT_FPA; + if (tdep->fp_model == ARM_FLOAT_AUTO) + tdep->fp_model = ARM_FLOAT_SOFT_FPA; } static void @@ -92,7 +93,8 @@ arm_netbsd_elf_init_abi (struct gdbarch_ set_solib_svr4_fetch_link_map_offsets (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets); - tdep->fp_model = ARM_FLOAT_SOFT_VFP; + if (tdep->fp_model == ARM_FLOAT_AUTO) + tdep->fp_model = ARM_FLOAT_SOFT_VFP; } static enum gdb_osabi Index: defs.h =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/defs.h,v retrieving revision 1.182 diff -u -p -r1.182 defs.h --- defs.h 17 Mar 2005 22:11:09 -0000 1.182 +++ defs.h 30 Mar 2005 16:17:16 -0000 @@ -952,9 +952,6 @@ enum gdb_osabi GDB_OSABI_HPUX_ELF, GDB_OSABI_HPUX_SOM, - GDB_OSABI_ARM_EABI_V1, - GDB_OSABI_ARM_EABI_V2, - GDB_OSABI_ARM_APCS, GDB_OSABI_QNXNTO, GDB_OSABI_CYGWIN, Index: osabi.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/osabi.c,v retrieving revision 1.32 diff -u -p -r1.32 osabi.c --- osabi.c 21 Feb 2005 04:31:58 -0000 1.32 +++ osabi.c 30 Mar 2005 18:30:44 -0000 @@ -71,9 +71,6 @@ static const char * const gdb_osabi_name "HP/UX ELF", "HP/UX SOM", - "ARM EABI v1", - "ARM EABI v2", - "ARM APCS", "QNX Neutrino", "Cygwin",