mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-11 13:02:10 +08:00
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:
parent
3e9cb5f4b2
commit
23181151a2
@ -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.
|
||||
|
@ -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) \
|
||||
|
13
gdb/NEWS
13
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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -198,4 +198,10 @@ struct linux_target_ops the_low_target = {
|
||||
NULL,
|
||||
1,
|
||||
i386_breakpoint_at,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
"i386"
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
11
gdb/remote.c
11
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);
|
||||
|
||||
|
@ -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 (¤t_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 (¤t_target);
|
||||
|
||||
/* If that failed try a target-specific hook. */
|
||||
if (current_target_desc == NULL)
|
||||
current_target_desc = target_read_description (¤t_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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
233
gdb/xml-tdesc.c
Normal 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
36
gdb/xml-tdesc.h
Normal 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 *);
|
Loading…
Reference in New Issue
Block a user