diff options
author | Daniel Jacobowitz <drow@false.org> | 2007-01-09 22:55:10 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2007-01-09 22:55:10 +0000 |
commit | 23181151a2399f4ecbc272cda73172a078d1b435 (patch) | |
tree | ea2a6e528a8ea59c2af185ebd8e1d1c7c08d7a55 /gdb/arch-utils.c | |
parent | 3e9cb5f4b2410bf5b0e0659dbeb532f08c2963de (diff) | |
download | gdb-23181151a2399f4ecbc272cda73172a078d1b435.zip gdb-23181151a2399f4ecbc272cda73172a078d1b435.tar.gz gdb-23181151a2399f4ecbc272cda73172a078d1b435.tar.bz2 |
XML feature description support.
* NEWS: Mention target descriptions, "set tdesc filename",
"unset tdesc filename", "show tdesc filename", and
qXfer:features:read.
* arch-utils.c (choose_architecture_for_target): New function.
(gdbarch_info_fill): Call it.
* target-descriptions.c (struct property): Make members non-const.
(struct target_desc): Add arch member.
(target_description_filename): New variable.
(target_find_description): Try via XML first.
(tdesc_architecture): New.
(free_target_description, make_cleanup_free_target_description): New.
(set_tdesc_property): Call xstrdup.
(set_tdesc_architecture, tdesc_set_cmdlist, tdesc_show_cmdlist)
(tdesc_unset_cmdlist, unset_tdesc_cmd, unset_tdesc_filename_cmd)
(set_tdesc_cmd, show_tdesc_cmd, set_tdesc_filename_cmd)
(show_tdesc_filename_cmd, _initialize_target_descriptions): New.
* target-descriptions.h (tdesc_architecture)
(make_cleanup_free_target_description, set_tdesc_architecture): New
prototypes.
* Makefile.in (SFILES): Add xml-tdesc.c.
(COMMON_OBS): Add xml-tdesc.o.
(target-descriptions.o): Update.
(xml-tdesc.o): New rule.
* xml-tdesc.c, xml-tdesc.h: New files.
* remote.c (PACKET_qXfer_features): New enum.
(remote_protocol_features): Add qXfer:features:read.
(remote_xfer_partial): Handle TARGET_OBJECT_AVAILABLE_FEATURES.
(_initialize_remote): Register qXfer:features:read.
* target.h (enum target_object): Add TARGET_OBJECT_AVAILABLE_FEATURES.
* features/gdb-target.dtd: New file.
* linux-i386-low.c (the_low_target): Set arch_string.
* linux-x86-64-low.c (the_low_target): Likewise.
* linux-low.c (linux_arch_string): New.
(linux_target_ops): Add it.
* linux-low.h (struct linux_target_ops): Add arch_string.
* server.c (write_qxfer_response): Use const void * for DATA.
(get_features_xml): New.
(handle_query): Handle qXfer:features:read. Report it for qSupported.
* target.h (struct target_ops): Add arch_string method.
* gdb.texinfo (Target Descriptions): New section.
(General Query Packets): Add QPassSignals anchor. Mention
qXfer:features:read under qSupported. Expand mentions of
qXfer:memory-map:read and QPassSignals. Document
qXfer:features:read.
Diffstat (limited to 'gdb/arch-utils.c')
-rw-r--r-- | gdb/arch-utils.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 78768a6..3635955 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -409,6 +409,75 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c) show_endian (gdb_stdout, from_tty, NULL, NULL); } +/* Given SELECTED, a currently selected BFD architecture, and + FROM_TARGET, a BFD architecture reported by the target description, + return what architecture to use. Either may be NULL; if both are + specified, we use the more specific. If the two are obviously + incompatible, warn the user. */ + +static const struct bfd_arch_info * +choose_architecture_for_target (const struct bfd_arch_info *selected, + const struct bfd_arch_info *from_target) +{ + const struct bfd_arch_info *compat1, *compat2; + + if (selected == NULL) + return from_target; + + if (from_target == NULL) + return selected; + + /* struct bfd_arch_info objects are singletons: that is, there's + supposed to be exactly one instance for a given machine. So you + can tell whether two are equivalent by comparing pointers. */ + if (from_target == selected) + return selected; + + /* BFD's 'A->compatible (A, B)' functions return zero if A and B are + incompatible. But if they are compatible, it returns the 'more + featureful' of the two arches. That is, if A can run code + written for B, but B can't run code written for A, then it'll + return A. + + Some targets (e.g. MIPS as of 2006-12-04) don't fully + implement this, instead always returning NULL or the first + argument. We detect that case by checking both directions. */ + + compat1 = selected->compatible (selected, from_target); + compat2 = from_target->compatible (from_target, selected); + + if (compat1 == NULL && compat2 == NULL) + { + warning (_("Selected architecture %s is not compatible " + "with reported target architecture %s"), + selected->printable_name, from_target->printable_name); + return selected; + } + + if (compat1 == NULL) + return compat2; + if (compat2 == NULL) + return compat1; + if (compat1 == compat2) + return compat1; + + /* If the two didn't match, but one of them was a default architecture, + assume the more specific one is correct. This handles the case + where an executable or target description just says "mips", but + the other knows which MIPS variant. */ + if (compat1->the_default) + return compat2; + if (compat2->the_default) + return compat1; + + /* We have no idea which one is better. This is a bug, but not + a critical problem; warn the user. */ + warning (_("Selected architecture %s is ambiguous with " + "reported target architecture %s"), + selected->printable_name, from_target->printable_name); + return selected; +} + /* Functions to manipulate the architecture of the target */ enum set_arch { set_arch_auto, set_arch_manual }; @@ -703,6 +772,10 @@ gdbarch_info_fill (struct gdbarch_info *info) && bfd_get_arch (info->abfd) != bfd_arch_unknown && bfd_get_arch (info->abfd) != bfd_arch_obscure) info->bfd_arch_info = bfd_get_arch_info (info->abfd); + /* From the target. */ + if (info->target_desc != NULL) + info->bfd_arch_info = choose_architecture_for_target + (info->bfd_arch_info, tdesc_architecture (info->target_desc)); /* From the default. */ if (info->bfd_arch_info == NULL) info->bfd_arch_info = default_bfd_arch; |