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.
This commit is contained in:
Daniel Jacobowitz 2007-01-09 22:55:10 +00:00
parent 3e9cb5f4b2
commit 23181151a2
19 changed files with 850 additions and 13 deletions

View File

@ -1,3 +1,36 @@
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.

View File

@ -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) \

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -198,4 +198,10 @@ struct linux_target_ops the_low_target = {
NULL,
1,
i386_breakpoint_at,
NULL,
NULL,
NULL,
NULL,
0,
"i386"
};

View File

@ -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

View File

@ -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;

View File

@ -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",
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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, ... */
};

233
gdb/xml-tdesc.c Normal file
View File

@ -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;
}

36
gdb/xml-tdesc.h Normal file
View File

@ -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 *);