summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog33
-rw-r--r--gdb/Makefile.in9
-rw-r--r--gdb/NEWS13
-rw-r--r--gdb/arch-utils.c73
-rw-r--r--gdb/doc/ChangeLog8
-rw-r--r--gdb/doc/gdb.texinfo155
-rw-r--r--gdb/gdbserver/ChangeLog12
-rw-r--r--gdb/gdbserver/linux-i386-low.c6
-rw-r--r--gdb/gdbserver/linux-low.c7
-rw-r--r--gdb/gdbserver/linux-low.h4
-rw-r--r--gdb/gdbserver/linux-x86-64-low.c6
-rw-r--r--gdb/gdbserver/server.c69
-rw-r--r--gdb/gdbserver/target.h4
-rw-r--r--gdb/remote.c11
-rw-r--r--gdb/target-descriptions.c169
-rw-r--r--gdb/target-descriptions.h9
-rw-r--r--gdb/target.h6
-rw-r--r--gdb/xml-tdesc.c233
-rw-r--r--gdb/xml-tdesc.h36
19 files changed, 850 insertions, 13 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3060ed7b1df..3c2b27aa03d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,38 @@
2007-01-09 Daniel Jacobowitz <dan@codesourcery.com>
+ * 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.
+
+2007-01-09 Daniel Jacobowitz <dan@codesourcery.com>
+
* copyright.sh: Clarify error.
2007-01-09 Jan Kratochvil <jan.kratochvil@redhat.com>
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 1de5f4c26fd..9567fac4580 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -563,7 +563,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c \
user-regs.c \
valarith.c valops.c valprint.c value.c varobj.c vec.c \
wrapper.c \
- xml-support.c
+ xml-tdesc.c xml-support.c
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -972,7 +972,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o
+ target-descriptions.o target-memory.o xml-tdesc.o
TSOBS = inflow.o
@@ -2776,7 +2776,8 @@ target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
$(exceptions_h) $(target_descriptions_h)
target-descriptions.o: target-descriptions.c $(defs_h) $(arch_utils_h) \
- $(target_h) $(target_descriptions_h) $(vec_h) $(gdb_assert_h)
+ $(target_h) $(target_descriptions_h) $(vec_h) $(xml_tdesc_h) \
+ $(gdbcmd_h) $(gdb_assert_h)
target-memory.o: target-memory.c $(defs_h) $(vec_h) $(target_h) \
$(memory_map_h) $(gdb_assert_h)
thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_h) \
@@ -2874,6 +2875,8 @@ xcoffread.o: xcoffread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(gdb_stat_h) \
$(complaints_h) $(gdb_stabs_h) $(aout_stab_gnu_h)
xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
$(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_h)
+xml-tdesc.o: xml-tdesc.c $(defs_h) $(target_h) $(target_descriptions_h) \
+ $(xml_tdesc_h) $(xml_support_h) $(gdb_assert_h)
xml-support.o: xml-support.c $(defs_h) $(xml_support_h) $(exceptions_h) \
$(gdbcmd_h) $(gdb_string_h) $(gdb_expat_h) $(safe_ctype_h)
xstormy16-tdep.o: xstormy16-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
diff --git a/gdb/NEWS b/gdb/NEWS
index 708df779972..a40e94f32c7 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -11,6 +11,10 @@ frequency signals (e.g. SIGALRM) via the QPassSignals packet.
* Support for C++ member pointers has been improved.
+* GDB now understands XML target descriptions, which specify the
+target's overall architecture. GDB can read a description from
+a local file or over the remote serial protocol.
+
* New commands
set mem inaccessible-by-default
@@ -47,6 +51,12 @@ show sysroot
OpenBSD/sh sh*-*openbsd*
+set tdesc filename
+unset tdesc filename
+show tdesc filename
+ Use the specified local file as an XML target description, and do
+ not query the target for its built-in description.
+
* New targets
OpenBSD/sh sh*-*-openbsd*
@@ -58,6 +68,9 @@ QPassSignals:
Ignore the specified signals; pass them directly to the debugged program
without stopping other threads or reporting them to GDB.
+qXfer:features:read:
+ Read an XML target description from the target, which describes its
+ features.
*** Changes in GDB 6.6
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index 78768a61a91..36359553441 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;
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index a20f9aaffb9..d1b27da2733 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,11 @@
+2007-01-09 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * 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.
+
2007-01-08 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Commands to specify files): Describe
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b3167b1eb2b..446e061612b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -159,6 +159,8 @@ Copyright (C) 1988-2006 Free Software Foundation, Inc.
* Maintenance Commands:: Maintenance Commands
* Remote Protocol:: GDB Remote Serial Protocol
* Agent Expressions:: The GDB Agent Expression Mechanism
+* Target Descriptions:: How targets can describe themselves to
+ @value{GDBN}
* Copying:: GNU General Public License says
how you can copy and share GDB
* GNU Free Documentation License:: The license for this documentation
@@ -23702,6 +23704,7 @@ Reply: see @code{remote.c:remote_unpack_thread_info_response()}.
@item QPassSignals: @var{signal} @r{[};@var{signal}@r{]}@dots{}
@cindex pass signals to inferior, remote request
@cindex @samp{QPassSignals} packet
+@anchor{QPassSignals}
Each listed @var{signal} should be passed directly to the inferior process.
Signals are numbered identically to continue packets and stop replies
(@pxref{Stop Reply Packets}). Each @var{signal} list item should be
@@ -23868,6 +23871,11 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab Yes
+@item @samp{qXfer:features:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
@item @samp{qXfer:memory-map:read}
@tab No
@tab @samp{-}
@@ -23898,6 +23906,18 @@ byte in its buffer for the NUL. If this stub feature is not supported,
The remote stub understands the @samp{qXfer:auxv:read} packet
(@pxref{qXfer auxiliary vector read}).
+@item qXfer:features:read
+The remote stub understands the @samp{qXfer:features:read} packet
+(@pxref{qXfer target description read}).
+
+@item qXfer:memory-map:read
+The remote stub understands the @samp{qXfer:memory-map:read} packet
+(@pxref{qXfer memory map read}).
+
+@item QPassSignals
+The remote stub understands the @samp{QPassSignals} packet
+(@pxref{QPassSignals}).
+
@end table
@item qSymbol::
@@ -23994,9 +24014,16 @@ auxiliary vector}. Note @var{annex} must be empty.
This packet is not probed by default; the remote stub must request it,
by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
-@end table
-@table @samp
+@item qXfer:features:read:@var{annex}:@var{offset},@var{length}
+@anchor{qXfer target description read}
+Access the @dfn{target description}. @xref{Target Descriptions}. The
+annex specifies which XML document to access. The main description is
+always loaded from the @samp{target.xml} annex.
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
@item qXfer:memory-map:read::@var{offset},@var{length}
@anchor{qXfer memory map read}
Access the target's @dfn{memory-map}. @xref{Memory map format}. The
@@ -25571,6 +25598,130 @@ The formal DTD for memory map format is given below:
@include agentexpr.texi
+@node Target Descriptions
+@appendix Target Descriptions
+@cindex target descriptions
+
+@strong{Warning:} target descriptions are still under active development,
+and the contents and format may change between @value{GDBN} releases.
+The format is expected to stabilize in the future.
+
+One of the challenges of using @value{GDBN} to debug embedded systems
+is that there are so many minor variants of each processor
+architecture in use. It is common practice for vendors to start with
+a standard processor core --- ARM, PowerPC, or MIPS, for example ---
+and then make changes to adapt it to a particular market niche. Some
+architectures have hundreds of variants, available from dozens of
+vendors. This leads to a number of problems:
+
+@itemize @bullet
+@item
+With so many different customized processors, it is difficult for
+the @value{GDBN} maintainers to keep up with the changes.
+@item
+Since individual variants may have short lifetimes or limited
+audiences, it may not be worthwhile to carry information about every
+variant in the @value{GDBN} source tree.
+@item
+When @value{GDBN} does support the architecture of the embedded system
+at hand, the task of finding the correct architecture name to give the
+@command{set architecture} command can be error-prone.
+@end itemize
+
+To address these problems, the @value{GDBN} remote protocol allows a
+target system to not only identify itself to @value{GDBN}, but to
+actually describe its own features. This lets @value{GDBN} support
+processor variants it has never seen before --- to the extent that the
+descriptions are accurate, and that @value{GDBN} understands them.
+
+@menu
+* Retrieving Descriptions:: How descriptions are fetched from a target.
+* Target Description Format:: The contents of a target description.
+@end menu
+
+@node Retrieving Descriptions
+@section Retrieving Descriptions
+
+Target descriptions can be read from the target automatically, or
+specified by the user manually. The default behavior is to read the
+description from the target. @value{GDBN} retrieves it via the remote
+protocol using @samp{qXfer} requests (@pxref{General Query Packets,
+qXfer}). The @var{annex} in the @samp{qXfer} packet will be
+@samp{target.xml}. The contents of the @samp{target.xml} annex are an
+XML document, of the form described in @ref{Target Description
+Format}.
+
+Alternatively, you can specify a file to read for the target description.
+If a file is set, the target will not be queried. The commands to
+specify a file are:
+
+@table @code
+@cindex set tdesc filename
+@item set tdesc filename @var{path}
+Read the target description from @var{path}.
+
+@cindex unset tdesc filename
+@item unset tdesc filename
+Do not read the XML target description from a file. @value{GDBN}
+will use the description supplied by the current target.
+
+@cindex show tdesc filename
+@item show tdesc filename
+Show the filename to read for a target description, if any.
+@end table
+
+
+@node Target Description Format
+@section Target Description Format
+@cindex target descriptions, XML format
+
+A target description annex is an @uref{http://www.w3.org/XML/, XML}
+document which complies with the Document Type Definition provided in
+the @value{GDBN} sources in @file{gdb/features/gdb-target.dtd}. This
+means you can use generally available tools like @command{xmllint} to
+check that your feature descriptions are well-formed and valid.
+However, to help people unfamiliar with XML write descriptions for
+their targets, we also describe the grammar here.
+
+At the moment, target descriptions can only provide minimal information
+about the architecture of the remote target. @value{GDBN} can use this
+information to autoconfigure, or to warn you if you connect to an
+unsupported target.
+
+Here is a simple target description:
+
+@example
+<target>
+ <architecture>i386:x86-64</architecture>
+</target>
+@end example
+
+@noindent
+This minimal description only says that the target uses
+the x86-64 architecture.
+
+A target description has the overall form:
+
+@example
+<?xml version="1.0"?>
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>@var{arch name}</architecture>
+</target>
+@end example
+
+@noindent
+The description is generally insensitive to whitespace and line
+breaks, under the usual common-sense rules. The XML version
+declaration and document type declaration can generally be omitted
+(@value{GDBN} does not require them), but specifying them may be
+useful for XML validation tools.
+
+The content of the @samp{<architecture>} element is an architecture
+name, from the same selection accepted by @code{set architecture}
+(@pxref{Targets, ,Specifying a Debugging Target}).
+
+
@include gpl.texi
@raisesections
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 2035473d5d7..8336ecabaf8 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,15 @@
+2007-01-09 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * 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.
+
2007-01-03 Denis Pilat <denis.pilat@st.com>
Daniel Jacobowitz <dan@codesourcery.com>
diff --git a/gdb/gdbserver/linux-i386-low.c b/gdb/gdbserver/linux-i386-low.c
index 4710773b77e..10c0ef0f458 100644
--- a/gdb/gdbserver/linux-i386-low.c
+++ b/gdb/gdbserver/linux-i386-low.c
@@ -198,4 +198,10 @@ struct linux_target_ops the_low_target = {
NULL,
1,
i386_breakpoint_at,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ "i386"
};
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index eb8ef4835bb..1d495936305 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -1641,6 +1641,12 @@ linux_read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p)
}
#endif
+static const char *
+linux_arch_string (void)
+{
+ return the_low_target.arch_string;
+}
+
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_attach,
@@ -1670,6 +1676,7 @@ static struct target_ops linux_target_ops = {
#else
NULL,
#endif
+ linux_arch_string,
};
static void
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index aa0102b7327..aa3bfe1268e 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -71,6 +71,10 @@ struct linux_target_ops
/* Whether to left-pad registers for PEEKUSR/POKEUSR if they are smaller
than an xfer unit. */
int left_pad_xfer;
+
+ /* What string to report to GDB when it asks for the architecture,
+ or NULL not to answer. */
+ const char *arch_string;
};
extern struct linux_target_ops the_low_target;
diff --git a/gdb/gdbserver/linux-x86-64-low.c b/gdb/gdbserver/linux-x86-64-low.c
index 81c92feeb53..5951104d421 100644
--- a/gdb/gdbserver/linux-x86-64-low.c
+++ b/gdb/gdbserver/linux-x86-64-low.c
@@ -172,4 +172,10 @@ struct linux_target_ops the_low_target = {
NULL,
1,
x86_64_breakpoint_at,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ "i386:x86-64",
};
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 1f78cce6920..20d47c92716 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -145,7 +145,7 @@ decode_xfer_read (char *buf, char **annex, CORE_ADDR *ofs, unsigned int *len)
to as much of DATA/LEN as we could fit. IS_MORE controls
the first character of the response. */
static int
-write_qxfer_response (char *buf, unsigned char *data, int len, int is_more)
+write_qxfer_response (char *buf, const void *data, int len, int is_more)
{
int out_len;
@@ -192,6 +192,31 @@ handle_general_set (char *own_buf)
own_buf[0] = 0;
}
+static const char *
+get_features_xml (void)
+{
+ static int features_supported = -1;
+ static char *document;
+
+ if (features_supported == -1)
+ {
+ const char *arch = (*the_target->arch_string) ();
+
+ if (arch == NULL)
+ features_supported = 0;
+ else
+ {
+ features_supported = 1;
+ document = malloc (64 + strlen (arch));
+ snprintf (document, 64 + strlen (arch),
+ "<target><architecture>%s</architecture></target>",
+ arch);
+ }
+ }
+
+ return document;
+}
+
/* Handle all of the extended 'q' packets. */
void
handle_query (char *own_buf, int *new_packet_len_p)
@@ -279,6 +304,45 @@ handle_query (char *own_buf, int *new_packet_len_p)
return;
}
+ if (strncmp ("qXfer:features:read:", own_buf, 20) == 0)
+ {
+ CORE_ADDR ofs;
+ unsigned int len, total_len;
+ const char *document;
+ char *annex;
+
+ document = get_features_xml ();
+ if (document == NULL)
+ {
+ own_buf[0] = '\0';
+ return;
+ }
+
+ /* Reject any annex other than target.xml; grab the offset and
+ length. */
+ if (decode_xfer_read (own_buf + 20, &annex, &ofs, &len) < 0
+ || strcmp (annex, "target.xml") != 0)
+ {
+ strcpy (own_buf, "E00");
+ return;
+ }
+
+ total_len = strlen (document);
+ if (len > PBUFSIZ - 2)
+ len = PBUFSIZ - 2;
+
+ if (ofs > total_len)
+ write_enn (own_buf);
+ else if (len < total_len - ofs)
+ *new_packet_len_p = write_qxfer_response (own_buf, document + ofs,
+ len, 1);
+ else
+ *new_packet_len_p = write_qxfer_response (own_buf, document + ofs,
+ total_len - ofs, 0);
+
+ return;
+ }
+
/* Protocol features query. */
if (strncmp ("qSupported", own_buf, 10) == 0
&& (own_buf[10] == ':' || own_buf[10] == '\0'))
@@ -288,6 +352,9 @@ handle_query (char *own_buf, int *new_packet_len_p)
if (the_target->read_auxv != NULL)
strcat (own_buf, ";qXfer:auxv:read+");
+ if (get_features_xml () != NULL)
+ strcat (own_buf, ";qXfer:features:read+");
+
return;
}
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index 17137dcb23e..d6e2655bf94 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -171,6 +171,10 @@ struct target_ops
int (*get_tls_address) (struct thread_info *thread, CORE_ADDR offset,
CORE_ADDR load_module, CORE_ADDR *address);
+
+ /* Return a string identifying the current architecture, or NULL if
+ this operation is not supported. */
+ const char *(*arch_string) (void);
};
extern struct target_ops *the_target;
diff --git a/gdb/remote.c b/gdb/remote.c
index c229bffab22..48be84479ec 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -893,6 +893,7 @@ enum {
PACKET_Z3,
PACKET_Z4,
PACKET_qXfer_auxv,
+ PACKET_qXfer_features,
PACKET_qXfer_memory_map,
PACKET_qGetTLSAddr,
PACKET_qSupported,
@@ -2294,6 +2295,8 @@ static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_auxv },
+ { "qXfer:features:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_features },
{ "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_memory_map },
{ "QPassSignals", PACKET_DISABLE, remote_supported_packet,
@@ -5716,6 +5719,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
&remote_protocol_packets[PACKET_qXfer_auxv]);
+ case TARGET_OBJECT_AVAILABLE_FEATURES:
+ return remote_read_qxfer
+ (ops, "features", annex, readbuf, offset, len,
+ &remote_protocol_packets[PACKET_qXfer_features]);
+
case TARGET_OBJECT_MEMORY_MAP:
gdb_assert (annex == NULL);
return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
@@ -6589,6 +6597,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_auxv],
"qXfer:auxv:read", "read-aux-vector", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_features],
+ "qXfer:features:read", "target-features", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
"qXfer:memory-map:read", "memory-map", 0);
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 9699b7d47c9..1100f5ebaf3 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -23,9 +23,11 @@
#include "defs.h"
#include "arch-utils.h"
+#include "gdbcmd.h"
#include "target.h"
#include "target-descriptions.h"
#include "vec.h"
+#include "xml-tdesc.h"
#include "gdb_assert.h"
@@ -33,13 +35,16 @@
typedef struct property
{
- const char *key;
- const char *value;
+ char *key;
+ char *value;
} property_s;
DEF_VEC_O(property_s);
struct target_desc
{
+ /* The architecture reported by the target, if any. */
+ const struct bfd_arch_info *arch;
+
/* Any architecture-specific properties specified by the target. */
VEC(property_s) *properties;
};
@@ -61,6 +66,12 @@ static int target_desc_fetched;
static const struct target_desc *current_target_desc;
+/* Other global variables. */
+
+/* The filename to read a target description from. */
+
+static char *target_description_filename;
+
/* Fetch the current target's description, and switch the current
architecture to one which incorporates that description. */
@@ -79,7 +90,22 @@ target_find_description (void)
disconnected from the previous target. */
gdb_assert (gdbarch_target_desc (current_gdbarch) == NULL);
- current_target_desc = target_read_description (&current_target);
+ /* First try to fetch an XML description from the user-specified
+ file. */
+ current_target_desc = NULL;
+ if (target_description_filename != NULL
+ && *target_description_filename != '\0')
+ current_target_desc
+ = file_read_description_xml (target_description_filename);
+
+ /* Next try to read the description from the current target using
+ target objects. */
+ if (current_target_desc == NULL)
+ current_target_desc = target_read_description_xml (&current_target);
+
+ /* If that failed try a target-specific hook. */
+ if (current_target_desc == NULL)
+ current_target_desc = target_read_description (&current_target);
/* If a non-NULL description was returned, then update the current
architecture. */
@@ -130,6 +156,9 @@ target_current_description (void)
return NULL;
}
+
+
+/* Direct accessors for feature sets. */
/* Return the string value of a property named KEY, or NULL if the
property was not specified. */
@@ -148,6 +177,16 @@ tdesc_property (const struct target_desc *target_desc, const char *key)
return NULL;
}
+/* Return the BFD architecture associated with this target
+ description, or NULL if no architecture was specified. */
+
+const struct bfd_arch_info *
+tdesc_architecture (const struct target_desc *target_desc)
+{
+ return target_desc->arch;
+}
+
+
/* Methods for constructing a target description. */
struct target_desc *
@@ -156,6 +195,31 @@ allocate_target_description (void)
return XZALLOC (struct target_desc);
}
+static void
+free_target_description (void *arg)
+{
+ struct target_desc *target_desc = arg;
+ struct property *prop;
+ int ix;
+
+ for (ix = 0;
+ VEC_iterate (property_s, target_desc->properties, ix, prop);
+ ix++)
+ {
+ xfree (prop->key);
+ xfree (prop->value);
+ }
+ VEC_free (property_s, target_desc->properties);
+
+ xfree (target_desc);
+}
+
+struct cleanup *
+make_cleanup_free_target_description (struct target_desc *target_desc)
+{
+ return make_cleanup (free_target_description, target_desc);
+}
+
void
set_tdesc_property (struct target_desc *target_desc,
const char *key, const char *value)
@@ -171,7 +235,102 @@ set_tdesc_property (struct target_desc *target_desc,
internal_error (__FILE__, __LINE__,
_("Attempted to add duplicate property \"%s\""), key);
- new_prop.key = key;
- new_prop.value = value;
+ new_prop.key = xstrdup (key);
+ new_prop.value = xstrdup (value);
VEC_safe_push (property_s, target_desc->properties, &new_prop);
}
+
+void
+set_tdesc_architecture (struct target_desc *target_desc,
+ const struct bfd_arch_info *arch)
+{
+ target_desc->arch = arch;
+}
+
+
+static struct cmd_list_element *tdesc_set_cmdlist, *tdesc_show_cmdlist;
+static struct cmd_list_element *tdesc_unset_cmdlist;
+
+/* Helper functions for the CLI commands. */
+
+static void
+set_tdesc_cmd (char *args, int from_tty)
+{
+ help_list (tdesc_set_cmdlist, "set tdesc ", -1, gdb_stdout);
+}
+
+static void
+show_tdesc_cmd (char *args, int from_tty)
+{
+ cmd_show_list (tdesc_show_cmdlist, from_tty, "");
+}
+
+static void
+unset_tdesc_cmd (char *args, int from_tty)
+{
+ help_list (tdesc_unset_cmdlist, "unset tdesc ", -1, gdb_stdout);
+}
+
+static void
+set_tdesc_filename_cmd (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ target_clear_description ();
+ target_find_description ();
+}
+
+static void
+show_tdesc_filename_cmd (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ if (value != NULL && *value != '\0')
+ printf_filtered (_("\
+The target description will be read from \"%s\".\n"),
+ value);
+ else
+ printf_filtered (_("\
+The target description will be read from the target.\n"));
+}
+
+static void
+unset_tdesc_filename_cmd (char *args, int from_tty)
+{
+ xfree (target_description_filename);
+ target_description_filename = NULL;
+ target_clear_description ();
+ target_find_description ();
+}
+
+void
+_initialize_target_descriptions (void)
+{
+ add_prefix_cmd ("tdesc", class_maintenance, set_tdesc_cmd, _("\
+Set target description specific variables."),
+ &tdesc_set_cmdlist, "set tdesc ",
+ 0 /* allow-unknown */, &setlist);
+ add_prefix_cmd ("tdesc", class_maintenance, show_tdesc_cmd, _("\
+Show target description specific variables."),
+ &tdesc_show_cmdlist, "show tdesc ",
+ 0 /* allow-unknown */, &showlist);
+ add_prefix_cmd ("tdesc", class_maintenance, unset_tdesc_cmd, _("\
+Unset target description specific variables."),
+ &tdesc_unset_cmdlist, "unset tdesc ",
+ 0 /* allow-unknown */, &unsetlist);
+
+ add_setshow_filename_cmd ("filename", class_obscure,
+ &target_description_filename,
+ _("\
+Set the file to read for an XML target description"), _("\
+Show the file to read for an XML target description"), _("\
+When set, GDB will read the target description from a local\n\
+file instead of querying the remote target."),
+ set_tdesc_filename_cmd,
+ show_tdesc_filename_cmd,
+ &tdesc_set_cmdlist, &tdesc_show_cmdlist);
+
+ add_cmd ("filename", class_obscure, unset_tdesc_filename_cmd, _("\
+Unset the file to read for an XML target description. When unset,\n\
+GDB will read the description from the target."),
+ &tdesc_unset_cmdlist);
+}
diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h
index cca90b155c2..f45e53be23c 100644
--- a/gdb/target-descriptions.h
+++ b/gdb/target-descriptions.h
@@ -44,6 +44,12 @@ const struct target_desc *target_current_description (void);
/* Accessors for target descriptions. */
+/* Return the BFD architecture associated with this target
+ description, or NULL if no architecture was specified. */
+
+const struct bfd_arch_info *tdesc_architecture
+ (const struct target_desc *);
+
/* Return the string value of a property named KEY, or NULL if the
property was not specified. */
@@ -53,6 +59,9 @@ const char *tdesc_property (const struct target_desc *,
/* Methods for constructing a target description. */
struct target_desc *allocate_target_description (void);
+struct cleanup *make_cleanup_free_target_description (struct target_desc *);
+void set_tdesc_architecture (struct target_desc *,
+ const struct bfd_arch_info *);
void set_tdesc_property (struct target_desc *,
const char *key, const char *value);
diff --git a/gdb/target.h b/gdb/target.h
index c8e2cc637c4..7a5f084888b 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -206,8 +206,10 @@ enum target_object
a previously erased flash memory. Using it without erasing
flash can have unexpected results. Addresses are physical
address on target, and not relative to flash start. */
- TARGET_OBJECT_FLASH
-
+ TARGET_OBJECT_FLASH,
+ /* Available target-specific features, e.g. registers and coprocessors.
+ See "target-descriptions.c". ANNEX should never be empty. */
+ TARGET_OBJECT_AVAILABLE_FEATURES
/* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */
};
diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c
new file mode 100644
index 00000000000..f47e3687b81
--- /dev/null
+++ b/gdb/xml-tdesc.c
@@ -0,0 +1,233 @@
+/* XML target description support for GDB.
+
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+ Contributed by CodeSourcery.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#include "defs.h"
+#include "target.h"
+#include "target-descriptions.h"
+#include "xml-support.h"
+#include "xml-tdesc.h"
+
+#include "gdb_assert.h"
+
+#if !defined(HAVE_LIBEXPAT)
+
+/* Parse DOCUMENT into a target description. Or don't, since we don't have
+ an XML parser. */
+
+static struct target_desc *
+tdesc_parse_xml (const char *document)
+{
+ static int have_warned;
+
+ if (!have_warned)
+ {
+ have_warned = 1;
+ warning (_("Can not parse XML target description; XML support was "
+ "disabled at compile time"));
+ }
+
+ return NULL;
+}
+
+#else /* HAVE_LIBEXPAT */
+
+/* Callback data for target description parsing. */
+
+struct tdesc_parsing_data
+{
+ /* The target description we are building. */
+ struct target_desc *tdesc;
+};
+
+/* Handle the end of an <architecture> element and its value. */
+
+static void
+tdesc_end_arch (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, const char *body_text)
+{
+ struct tdesc_parsing_data *data = user_data;
+ const struct bfd_arch_info *arch;
+
+ arch = bfd_scan_arch (body_text);
+ if (arch == NULL)
+ gdb_xml_error (parser, _("Target description specified unknown "
+ "architecture \"%s\""), body_text);
+ set_tdesc_architecture (data->tdesc, arch);
+}
+
+/* The elements and attributes of an XML target description. */
+
+const struct gdb_xml_element target_children[] = {
+ { "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
+ NULL, tdesc_end_arch },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element tdesc_elements[] = {
+ { "target", NULL, target_children, GDB_XML_EF_NONE,
+ NULL, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* Parse DOCUMENT into a target description and return it. */
+
+static struct target_desc *
+tdesc_parse_xml (const char *document)
+{
+ struct cleanup *back_to, *result_cleanup;
+ struct gdb_xml_parser *parser;
+ struct tdesc_parsing_data data;
+
+ memset (&data, 0, sizeof (struct tdesc_parsing_data));
+
+ back_to = make_cleanup (null_cleanup, NULL);
+ parser = gdb_xml_create_parser_and_cleanup (_("target description"),
+ tdesc_elements, &data);
+
+ data.tdesc = allocate_target_description ();
+ result_cleanup = make_cleanup_free_target_description (data.tdesc);
+
+ if (gdb_xml_parse (parser, document) == 0)
+ {
+ /* Parsed successfully. */
+ discard_cleanups (result_cleanup);
+ do_cleanups (back_to);
+ return data.tdesc;
+ }
+ else
+ {
+ warning (_("Could not load XML target description; ignoring"));
+ do_cleanups (back_to);
+ return NULL;
+ }
+}
+
+#endif /* HAVE_LIBEXPAT */
+
+
+/* Close FILE. */
+
+static void
+do_cleanup_fclose (void *file)
+{
+ fclose (file);
+}
+
+/* Open FILENAME, read all its text into memory, close it, and return
+ the text. If something goes wrong, return NULL and warn. */
+
+static char *
+fetch_xml_from_file (const char *filename)
+{
+ FILE *file;
+ struct cleanup *back_to;
+ char *text;
+ size_t len, offset;
+
+ file = fopen (filename, FOPEN_RT);
+ if (file == NULL)
+ {
+ warning (_("Could not open \"%s\""), filename);
+ return NULL;
+ }
+ back_to = make_cleanup (do_cleanup_fclose, file);
+
+ /* Read in the whole file, one chunk at a time. */
+ len = 4096;
+ offset = 0;
+ text = xmalloc (len);
+ make_cleanup (free_current_contents, &text);
+ while (1)
+ {
+ size_t bytes_read;
+
+ /* Continue reading where the last read left off. Leave at least
+ one byte so that we can NUL-terminate the result. */
+ bytes_read = fread (text + offset, 1, len - offset - 1, file);
+ if (ferror (file))
+ {
+ warning (_("Read error from \"%s\""), filename);
+ do_cleanups (back_to);
+ return NULL;
+ }
+
+ offset += bytes_read;
+
+ if (feof (file))
+ break;
+
+ len = len * 2;
+ text = xrealloc (text, len);
+ }
+
+ fclose (file);
+ discard_cleanups (back_to);
+
+ text[offset] = '\0';
+ return text;
+}
+
+/* Read an XML target description from FILENAME. Parse it, and return
+ the parsed description. */
+
+const struct target_desc *
+file_read_description_xml (const char *filename)
+{
+ struct target_desc *tdesc;
+ char *tdesc_str;
+ struct cleanup *back_to;
+
+ tdesc_str = fetch_xml_from_file (filename);
+ if (tdesc_str == NULL)
+ return NULL;
+
+ back_to = make_cleanup (xfree, tdesc_str);
+ tdesc = tdesc_parse_xml (tdesc_str);
+ do_cleanups (back_to);
+
+ return tdesc;
+}
+
+/* Read an XML target description using OPS. Parse it, and return the
+ parsed description. */
+
+const struct target_desc *
+target_read_description_xml (struct target_ops *ops)
+{
+ struct target_desc *tdesc;
+ char *tdesc_str;
+ struct cleanup *back_to;
+
+ tdesc_str = target_read_stralloc (ops, TARGET_OBJECT_AVAILABLE_FEATURES,
+ "target.xml");
+ if (tdesc_str == NULL)
+ return NULL;
+
+ back_to = make_cleanup (xfree, tdesc_str);
+ tdesc = tdesc_parse_xml (tdesc_str);
+ do_cleanups (back_to);
+
+ return tdesc;
+}
diff --git a/gdb/xml-tdesc.h b/gdb/xml-tdesc.h
new file mode 100644
index 00000000000..0f2a9d8379a
--- /dev/null
+++ b/gdb/xml-tdesc.h
@@ -0,0 +1,36 @@
+/* XML target description support for GDB.
+
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+ Contributed by CodeSourcery.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+struct target_ops;
+struct target_desc;
+
+/* Read an XML target description from FILENAME. Parse it, and return
+ the parsed description. */
+
+const struct target_desc *file_read_description_xml (const char *filename);
+
+/* Read an XML target description using OPS. Parse it, and return the
+ parsed description. */
+
+const struct target_desc *target_read_description_xml (struct target_ops *);