diff options
author | Daniel Jacobowitz <dan@debian.org> | 2006-03-23 16:52:21 +0000 |
---|---|---|
committer | Daniel Jacobowitz <dan@debian.org> | 2006-03-23 16:52:21 +0000 |
commit | 314ef690a58129613cfb892bd569ee281ddb8e71 (patch) | |
tree | ec63ff593372abe44dfc941a2e67763ca30bedb0 | |
parent | 561ef9b5b1415fb437a7b228b5cca1610137a22d (diff) | |
download | gdb-314ef690a58129613cfb892bd569ee281ddb8e71.tar.gz |
Require targets to provide all their registers if an XML description
is used; fix various bugs this uncovered. Allow ARM descriptions without
FPA.
-rw-r--r-- | gdb/Makefile.in | 18 | ||||
-rw-r--r-- | gdb/arm-tdep.c | 86 | ||||
-rw-r--r-- | gdb/arm-tdep.h | 2 | ||||
-rw-r--r-- | gdb/available.c | 98 | ||||
-rw-r--r-- | gdb/available.h | 15 | ||||
-rw-r--r-- | gdb/features/feature_to_c.sh | 78 | ||||
-rw-r--r-- | gdb/gdbarch.c | 16 | ||||
-rw-r--r-- | gdb/gdbarch.h | 6 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 14 | ||||
-rw-r--r-- | gdb/parse-avail.c | 1 |
10 files changed, 243 insertions, 91 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 3b13c5cfe69..323e00c85f9 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1686,21 +1686,7 @@ po/$(PACKAGE).pot: force xml-builtin.c: stamp-xml; @true stamp-xml: $(srcdir)/features/feature_to_c.sh Makefile $(XMLFILES) rm -f xml-builtin.tmp - for f in dummy $(XMLFILES); do \ - if test $$f != dummy; then \ - $(SHELL) $(srcdir)/features/feature_to_c.sh "$$f" xml-builtin.tmp; \ - fi; \ - done - echo "const char *const xml_builtin[][2] = {" >> xml-builtin.tmp - for f in dummy $(XMLFILES); do \ - if test $$f != dummy; then \ - basename=`echo $$f | sed 's,.*/,,'`; \ - arrayname=xml_feature_`echo $$basename | sed 's/[-.]/_/g'`; \ - echo " { \"$$basename\", $$arrayname }," >> xml-builtin.tmp; \ - fi; \ - done - echo " { 0, 0 }" >> xml-builtin.tmp - echo "};" >> xml-builtin.tmp + $(SHELL) $(srcdir)/features/feature_to_c.sh xml-builtin.tmp $(XMLFILES) $(SHELL) $(srcdir)/../move-if-change xml-builtin.tmp xml-builtin.c echo stamp > stamp-xml @@ -1825,7 +1811,7 @@ auxv.o: auxv.c $(defs_h) $(target_h) $(gdbtypes_h) $(command_h) \ $(inferior_h) $(valprint_h) $(gdb_assert_h) $(auxv_h) \ $(elf_common_h) available.o: available.c $(defs_h) $(symfile_h) $(target_h) $(available_h) \ - $(arch_utils_h) $(gdbtypes_h) $(sha1_h) \ + $(arch_utils_h) $(exceptions_h) $(gdbtypes_h) $(sha1_h) \ $(gdb_string) $(gdb_assert) $(gdb_obstack_h) $(gdb_stdint_h) avr-tdep.o: avr-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \ $(frame_base_h) $(trad_frame_h) $(gdbcmd_h) $(gdbcore_h) \ diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index a831b653fe5..8a086907233 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -805,13 +805,15 @@ arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cac imm = (imm >> rot) | (imm << (32 - rot)); sp_offset -= imm; } - else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */ + else if ((insn & 0xffff7fff) == 0xed6d0103 /* stfe f?, [sp, -#c]! */ + && gdbarch_tdep (current_gdbarch)->have_fpa_registers) { sp_offset -= 12; regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07); cache->saved_regs[regno].addr = sp_offset; } - else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */ + else if ((insn & 0xffbf0fff) == 0xec2d0200 /* sfmfd f0, 4, [sp!] */ + && gdbarch_tdep (current_gdbarch)->have_fpa_registers) { int n_saved_fp_regs; unsigned int fp_start_reg, fp_bound_reg; @@ -1352,6 +1354,9 @@ arm_register_type (struct gdbarch *gdbarch, int regnum) if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS) { + if (!gdbarch_tdep (gdbarch)->have_fpa_registers) + return builtin_type_void; + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) return builtin_type_arm_ext_big; else @@ -2458,11 +2463,20 @@ arm_register_name (int i) { const char *avail_name; - avail_name = available_register_name (current_gdbarch, i); - if (avail_name) - return avail_name; + /* Allow arm_register_names to override the names for standard + registers from the target, for "set arm disassembler". */ + if (i <= ARM_PC_REGNUM || i == ARM_PS_REGNUM) + return arm_register_names[i]; + if (i <= ARM_FPS_REGNUM) + { + if (gdbarch_tdep (current_gdbarch)->have_fpa_registers) + return arm_register_names[i]; + else + return ""; + } - return arm_register_names[i]; + /* Check for target-supplied register numbers. */ + return available_register_name (current_gdbarch, i); } static void @@ -2571,6 +2585,51 @@ arm_elf_osabi_sniffer (bfd *abfd) return osabi; } +static void +arm_require_register (struct gdb_feature_set *feature_set, + const char *name, int regnum) +{ + if (!available_find_named_register (feature_set, name, regnum)) + error (_("target does not provide required register \"%s\""), name); +} + +static void +arm_check_feature_set (struct gdbarch *gdbarch, + struct gdb_feature_set *feature_set) +{ + static const char *const arm_standard_names[] = + { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "fps", + "cpsr" + }; + int i; + + if (!available_find_named_feature (feature_set, "org.gnu.gdb.arm.core")) + error (_("target does not provide ARM core registers")); + + for (i = 0; i < 16; i++) + arm_require_register (feature_set, arm_standard_names[i], i); + + arm_require_register (feature_set, arm_standard_names[ARM_PS_REGNUM], + ARM_PS_REGNUM); + + /* If we have an FPA unit, require the FPA registers and assign them + fixed numbers. If we don't have FPA, these register numbers will + remain unused, since various ARM subtargets hardcode the + numbering. */ + + if (available_find_named_feature (feature_set, "org.gnu.gdb.arm.fpa")) + { + for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++) + arm_require_register (feature_set, arm_standard_names[i], i); + gdbarch_tdep (gdbarch)->have_fpa_registers = 1; + } + else + gdbarch_tdep (gdbarch)->have_fpa_registers = 0; +} + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of @@ -2761,7 +2820,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_breakpoint_from_pc (gdbarch, arm_breakpoint_from_pc); /* Information about registers, etc. */ - set_gdbarch_print_float_info (gdbarch, arm_print_float_info); set_gdbarch_deprecated_fp_regnum (gdbarch, ARM_FP_REGNUM); /* ??? */ set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM); set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM); @@ -2771,7 +2829,19 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_type (gdbarch, arm_register_type); if (info.feature_set) - record_available_features (gdbarch, info.feature_set); + { + arm_check_feature_set (gdbarch, info.feature_set); + record_available_features (gdbarch, info.feature_set); + } + else + /* The legacy layout of the remote "g" packet assumes we have + the FPA registers, as do some native targets. */ + gdbarch_tdep (gdbarch)->have_fpa_registers = 1; + + /* This "info float" is FPA-specific. Use the generic version if we + do not have FPA. */ + if (gdbarch_tdep (gdbarch)->have_fpa_registers) + set_gdbarch_print_float_info (gdbarch, arm_print_float_info); /* Internal <-> external register number maps. */ set_gdbarch_register_sim_regno (gdbarch, arm_register_sim_regno); diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h index 314105254cc..f02eeb1eeed 100644 --- a/gdb/arm-tdep.h +++ b/gdb/arm-tdep.h @@ -131,6 +131,8 @@ struct gdbarch_tdep enum arm_float_model fp_model; /* Floating point calling conventions. */ + int have_fpa_registers; /* Does the target report the FPA registers? */ + CORE_ADDR lowest_pc; /* Lowest address at which instructions will appear. */ diff --git a/gdb/available.c b/gdb/available.c index ed6f2804b43..0fa69a5dbf2 100644 --- a/gdb/available.c +++ b/gdb/available.c @@ -24,6 +24,7 @@ #include "defs.h" #include "arch-utils.h" +#include "exceptions.h" #include "gdbtypes.h" #include "symfile.h" #include "target.h" @@ -405,8 +406,6 @@ int features_same_p (const struct gdb_feature_set *lhs, const struct gdb_feature_set *rhs) { - const struct gdb_available_feature *lhs_p, *rhs_p; - /* Two feature sets are the same if and only if they are described by the same XML. */ @@ -419,14 +418,23 @@ features_same_p (const struct gdb_feature_set *lhs, /* Switch the architecture (gdbarch) to one which supports FEATURES. */ void -arch_set_available_features (const struct gdb_feature_set *features) +arch_set_available_features (struct gdb_feature_set *features) { + volatile struct gdb_exception e; struct gdbarch_info info; - gdbarch_info_init (&info); - info.feature_set = features; - if (!gdbarch_update_p (info)) - internal_error (__FILE__, __LINE__, "could not update architecture"); + TRY_CATCH (e, RETURN_MASK_ERROR) + { + gdbarch_info_init (&info); + info.feature_set = features; + + if (!gdbarch_update_p (info)) + internal_error (__FILE__, __LINE__, "could not update architecture"); + } + + if (e.reason == RETURN_ERROR) + exception_fprintf (gdb_stderr, e, + _("warning: could not use supplied target description: ")); } static struct gdb_feature_set * @@ -491,20 +499,20 @@ copy_features_to_obstack (struct obstack *obstack, /* Set an architecture's feature set. Store BASE_FEATURES in GDBARCH, and on the correct obstack. - This function will update num_regs. It is the architecture's - responsibility to handle this if it has pseudo registers. - - FIXME: This interface may need to go away; what if we want to add - a single additional feature to that provided by the target? */ + This function will update GDBARCH's num_regs. It is the + architecture's responsibility to handle this if it has pseudo + registers. Before calling this function, num_regs should be + the number of fixed registers handled by the target code; all + unassigned registers will be given numbers above that point. */ void record_available_features (struct gdbarch *gdbarch, - const struct gdb_feature_set *base_features) + struct gdb_feature_set *base_features) { struct gdb_available_feature *feature; struct gdb_available_register *reg; struct gdb_feature_set *features; - int gdb_regnum, protocol_number; + int gdb_regnum; features = copy_features_to_obstack (gdbarch_obstack (gdbarch), base_features); @@ -513,21 +521,16 @@ record_available_features (struct gdbarch *gdbarch, gdb_regnum = gdbarch_num_regs (gdbarch); for (feature = features->features; feature; feature = feature->next) - { - protocol_number = feature->protocol_number; - for (reg = feature->registers; reg; reg = reg->next) - { - reg->gdb_regnum = gdb_regnum++; - reg->protocol_number = protocol_number++; - } - } + for (reg = feature->registers; reg; reg = reg->next) + if (reg->gdb_regnum == -1) + reg->gdb_regnum = gdb_regnum++; set_gdbarch_num_regs (gdbarch, gdb_regnum); } /* Search FEATURES for a register with GDB register number REGNUM. */ -struct gdb_available_register * +static struct gdb_available_register * find_register (const struct gdb_feature_set *features, int regnum) { struct gdb_available_feature *feature; @@ -544,6 +547,55 @@ find_register (const struct gdb_feature_set *features, int regnum) return NULL; } +/* Search FEATURES for a register with target-specified name NAME, + and set its GDB register number to REGNUM. Return 1 if the + register was found, and 0 if it was not. This function should + only be used while initializing a gdbarch. */ + +int +available_find_named_register (struct gdb_feature_set *features, + const char *name, int regnum) +{ + struct gdb_available_feature *feature; + struct gdb_available_register *reg; + + if (features == NULL) + return 0; + + for (feature = features->features; feature; feature = feature->next) + for (reg = feature->registers; reg; reg = reg->next) + if (strcmp (reg->name, name) == 0) + { + reg->gdb_regnum = regnum; + return 1; + } + + /* FIXME: Should we sanity check the target-supplied data here for + duplicate register names? Right now GDB can't handle duplicated + register names at all, but in the future it may. */ + + return 0; +} + +/* Search FEATURES for a feature with the well-known name NAME, + which GDB may have special support for. */ + +int +available_find_named_feature (struct gdb_feature_set *features, + const char *name) +{ + struct gdb_available_feature *feature; + + if (features == NULL) + return 0; + + for (feature = features->features; feature; feature = feature->next) + if (strcmp (feature->name, name) == 0) + return 1; + + return 0; +} + /* Return the type of target-described register REGNUM, if the feature set for GDBARCH describes that register. Otherwise return NULL. */ diff --git a/gdb/available.h b/gdb/available.h index c657a749bad..7b35e40d8b2 100644 --- a/gdb/available.h +++ b/gdb/available.h @@ -139,7 +139,7 @@ struct gdb_feature_set *available_features_from_target_object /* Standard method to update an architecture based on detected available features. */ -void arch_set_available_features (const struct gdb_feature_set *); +void arch_set_available_features (struct gdb_feature_set *); /* Compare two sets of available features. */ @@ -149,7 +149,18 @@ int features_same_p (const struct gdb_feature_set *, /* Set an architecture's feature set. */ void record_available_features (struct gdbarch *, - const struct gdb_feature_set *); + struct gdb_feature_set *); + +/* Find a register with the given name, and set its internal register + number. */ + +int available_find_named_register (struct gdb_feature_set *, + const char *, int); + +/* Find a feature with the given name. */ + +int available_find_named_feature (struct gdb_feature_set *, + const char *); /* Find the type of a target-described register. */ diff --git a/gdb/features/feature_to_c.sh b/gdb/features/feature_to_c.sh index 0617b05dd50..764297725ee 100644 --- a/gdb/features/feature_to_c.sh +++ b/gdb/features/feature_to_c.sh @@ -1,37 +1,55 @@ #!/bin/sh -input=$1 -output=$2 +output=$1 +shift -if test -z "$input" || test -z "$output"; then - echo "Usage: $0 INPUTFILE OUTPUTFILE" +if test -z "$output" || test -z "$1"; then + echo "Usage: $0 OUTPUTFILE INPUTFILE..." exit 1 fi -arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'` +for input in dummy "$@"; do + if test $input != dummy; then + arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'` -gawk 'BEGIN { n = 0 - print "static const char '$arrayname'[] = {" - for (i = 0; i < 255; i++) - _ord_[sprintf("%c", i)] = i -} { - split($0, line, ""); - printf " " - for (i = 1; i <= length(line); i++) { - c = line[i] - if (c == "'\''") { - printf "'\''\\'\'''\'', " - } else if (c == "\\") { - printf "'\''\\\\'\'', " - } else if (match (c, "[[:print:]]") != 0) { - printf "'\''" c "'\'', " - } else { - printf "'\''\\%03o'\'', ", _ord_[c] - } - if (i % 10 == 0) - printf "\n " - } - printf "'\''\\n'\'', \n" -} END { - print " 0 };" -}' < $input > $output + gawk 'BEGIN { n = 0 + print "static const char '$arrayname'[] = {" + for (i = 0; i < 255; i++) + _ord_[sprintf("%c", i)] = i + } { + split($0, line, ""); + printf " " + for (i = 1; i <= length(line); i++) { + c = line[i] + if (c == "'\''") { + printf "'\''\\'\'''\'', " + } else if (c == "\\") { + printf "'\''\\\\'\'', " + } else if (match (c, "[[:print:]]") != 0) { + printf "'\''" c "'\'', " + } else { + printf "'\''\\%03o'\'', ", _ord_[c] + } + if (i % 10 == 0) + printf "\n " + } + printf "'\''\\n'\'', \n" + } END { + print " 0 };" + }' < $input >> $output + fi +done + +echo >> $output +echo "const char *const xml_builtin[][2] = {" >> $output + +for input in dummy "$@"; do + if test $input != dummy; then + basename=`echo $input | sed 's,.*/,,'` + arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'` + echo " { \"$basename\", $arrayname }," >> $output + fi +done + +echo " { 0, 0 }" >> $output +echo "};" >> $output diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index d5490845a87..80aebec3af0 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -238,7 +238,7 @@ struct gdbarch gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument; gdbarch_regset_from_core_section_ftype *regset_from_core_section; int available_features_support; - const struct gdb_feature_set * feature_set; + struct gdb_feature_set * feature_set; }; @@ -3750,7 +3750,7 @@ set_gdbarch_available_features_support (struct gdbarch *gdbarch, gdbarch->available_features_support = available_features_support; } -const struct gdb_feature_set * +struct gdb_feature_set * gdbarch_feature_set (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); @@ -3761,7 +3761,7 @@ gdbarch_feature_set (struct gdbarch *gdbarch) void set_gdbarch_feature_set (struct gdbarch *gdbarch, - const struct gdb_feature_set * feature_set) + struct gdb_feature_set * feature_set) { gdbarch->feature_set = feature_set; } @@ -3978,8 +3978,9 @@ current_gdbarch_swap_out_hack (void) } static void -current_gdbarch_swap_in_hack (struct gdbarch *new_gdbarch) +current_gdbarch_swap_in_hack (void *argument) { + struct gdbarch *new_gdbarch = argument; struct gdbarch_swap *curr; gdb_assert (current_gdbarch == NULL); @@ -4264,13 +4265,18 @@ gdbarch_find_by_info (struct gdbarch_info info) architecture of the same family is found at the head of the rego->arches list. */ struct gdbarch *old_gdbarch = current_gdbarch_swap_out_hack (); + struct cleanup *back_to; + + /* Make sure we restore current_gdbarch on our way out if an error + occurs. */ + back_to = make_cleanup (current_gdbarch_swap_in_hack, old_gdbarch); /* Find the specified architecture. */ struct gdbarch *new_gdbarch = find_arch_by_info (old_gdbarch, info); /* Restore the existing architecture. */ gdb_assert (current_gdbarch == NULL); - current_gdbarch_swap_in_hack (old_gdbarch); + do_cleanups (back_to); return new_gdbarch; } diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 1d11fb70b06..6a4d6885ab1 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1421,8 +1421,8 @@ extern void set_gdbarch_available_features_support (struct gdbarch *gdbarch, int /* The architecture's currently associated feature set. */ -extern const struct gdb_feature_set * gdbarch_feature_set (struct gdbarch *gdbarch); -extern void set_gdbarch_feature_set (struct gdbarch *gdbarch, const struct gdb_feature_set * feature_set); +extern struct gdb_feature_set * gdbarch_feature_set (struct gdbarch *gdbarch); +extern void set_gdbarch_feature_set (struct gdbarch *gdbarch, struct gdb_feature_set * feature_set); extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch); @@ -1511,7 +1511,7 @@ struct gdbarch_info enum gdb_osabi osabi; /* Use default: NULL. */ - const struct gdb_feature_set *feature_set; + struct gdb_feature_set *feature_set; }; typedef struct gdbarch *(gdbarch_init_ftype) (struct gdbarch_info info, struct gdbarch_list *arches); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index fb26e901d76..6b022d49d84 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -672,7 +672,7 @@ M::const struct regset *:regset_from_core_section:const char *sect_name, size_t v::int:available_features_support # The architecture's currently associated feature set. -v::const struct gdb_feature_set *:feature_set:::::::paddr_nz ((long) current_gdbarch->feature_set) +v::struct gdb_feature_set *:feature_set:::::::paddr_nz ((long) current_gdbarch->feature_set) EOF } @@ -1001,7 +1001,7 @@ struct gdbarch_info enum gdb_osabi osabi; /* Use default: NULL. */ - const struct gdb_feature_set *feature_set; + struct gdb_feature_set *feature_set; }; typedef struct gdbarch *(gdbarch_init_ftype) (struct gdbarch_info info, struct gdbarch_list *arches); @@ -1938,8 +1938,9 @@ current_gdbarch_swap_out_hack (void) } static void -current_gdbarch_swap_in_hack (struct gdbarch *new_gdbarch) +current_gdbarch_swap_in_hack (void *argument) { + struct gdbarch *new_gdbarch = argument; struct gdbarch_swap *curr; gdb_assert (current_gdbarch == NULL); @@ -2224,13 +2225,18 @@ gdbarch_find_by_info (struct gdbarch_info info) architecture of the same family is found at the head of the rego->arches list. */ struct gdbarch *old_gdbarch = current_gdbarch_swap_out_hack (); + struct cleanup *back_to; + + /* Make sure we restore current_gdbarch on our way out if an error + occurs. */ + back_to = make_cleanup (current_gdbarch_swap_in_hack, old_gdbarch); /* Find the specified architecture. */ struct gdbarch *new_gdbarch = find_arch_by_info (old_gdbarch, info); /* Restore the existing architecture. */ gdb_assert (current_gdbarch == NULL); - current_gdbarch_swap_in_hack (old_gdbarch); + do_cleanups (back_to); return new_gdbarch; } diff --git a/gdb/parse-avail.c b/gdb/parse-avail.c index f49fa020297..b20e3ae0e36 100644 --- a/gdb/parse-avail.c +++ b/gdb/parse-avail.c @@ -264,6 +264,7 @@ xml_start_reg (struct xml_feature_parse_data *data, sizeof (struct gdb_available_register)); memset (reg, 0, sizeof (struct gdb_available_register)); + reg->gdb_regnum = -1; reg->protocol_number = -1; reg->bitsize = -1; reg->readonly = -1; |