mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-13 20:10:02 +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:
@ -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>
|
2007-01-09 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* copyright.sh: Clarify error.
|
* copyright.sh: Clarify error.
|
||||||
|
@ -563,7 +563,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c \
|
|||||||
user-regs.c \
|
user-regs.c \
|
||||||
valarith.c valops.c valprint.c value.c varobj.c vec.c \
|
valarith.c valops.c valprint.c value.c varobj.c vec.c \
|
||||||
wrapper.c \
|
wrapper.c \
|
||||||
xml-support.c
|
xml-tdesc.c xml-support.c
|
||||||
|
|
||||||
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
|
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
|
||||||
|
|
||||||
@ -972,7 +972,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
|
|||||||
tramp-frame.o \
|
tramp-frame.o \
|
||||||
solib.o solib-null.o \
|
solib.o solib-null.o \
|
||||||
prologue-value.o memory-map.o xml-support.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
|
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) \
|
$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
|
||||||
$(exceptions_h) $(target_descriptions_h)
|
$(exceptions_h) $(target_descriptions_h)
|
||||||
target-descriptions.o: target-descriptions.c $(defs_h) $(arch_utils_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) \
|
target-memory.o: target-memory.c $(defs_h) $(vec_h) $(target_h) \
|
||||||
$(memory_map_h) $(gdb_assert_h)
|
$(memory_map_h) $(gdb_assert_h)
|
||||||
thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_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)
|
$(complaints_h) $(gdb_stabs_h) $(aout_stab_gnu_h)
|
||||||
xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
|
xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
|
||||||
$(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_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) \
|
xml-support.o: xml-support.c $(defs_h) $(xml_support_h) $(exceptions_h) \
|
||||||
$(gdbcmd_h) $(gdb_string_h) $(gdb_expat_h) $(safe_ctype_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) \
|
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.
|
* 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
|
* New commands
|
||||||
|
|
||||||
set mem inaccessible-by-default
|
set mem inaccessible-by-default
|
||||||
@ -47,6 +51,12 @@ show sysroot
|
|||||||
|
|
||||||
OpenBSD/sh sh*-*openbsd*
|
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
|
* New targets
|
||||||
|
|
||||||
OpenBSD/sh sh*-*-openbsd*
|
OpenBSD/sh sh*-*-openbsd*
|
||||||
@ -58,6 +68,9 @@ QPassSignals:
|
|||||||
Ignore the specified signals; pass them directly to the debugged program
|
Ignore the specified signals; pass them directly to the debugged program
|
||||||
without stopping other threads or reporting them to GDB.
|
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
|
*** 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);
|
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 */
|
/* Functions to manipulate the architecture of the target */
|
||||||
|
|
||||||
enum set_arch { set_arch_auto, set_arch_manual };
|
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_unknown
|
||||||
&& bfd_get_arch (info->abfd) != bfd_arch_obscure)
|
&& bfd_get_arch (info->abfd) != bfd_arch_obscure)
|
||||||
info->bfd_arch_info = bfd_get_arch_info (info->abfd);
|
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. */
|
/* From the default. */
|
||||||
if (info->bfd_arch_info == NULL)
|
if (info->bfd_arch_info == NULL)
|
||||||
info->bfd_arch_info = default_bfd_arch;
|
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>
|
2007-01-08 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* gdb.texinfo (Commands to specify files): Describe
|
* gdb.texinfo (Commands to specify files): Describe
|
||||||
|
@ -159,6 +159,8 @@ Copyright (C) 1988-2006 Free Software Foundation, Inc.
|
|||||||
* Maintenance Commands:: Maintenance Commands
|
* Maintenance Commands:: Maintenance Commands
|
||||||
* Remote Protocol:: GDB Remote Serial Protocol
|
* Remote Protocol:: GDB Remote Serial Protocol
|
||||||
* Agent Expressions:: The GDB Agent Expression Mechanism
|
* Agent Expressions:: The GDB Agent Expression Mechanism
|
||||||
|
* Target Descriptions:: How targets can describe themselves to
|
||||||
|
@value{GDBN}
|
||||||
* Copying:: GNU General Public License says
|
* Copying:: GNU General Public License says
|
||||||
how you can copy and share GDB
|
how you can copy and share GDB
|
||||||
* GNU Free Documentation License:: The license for this documentation
|
* 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{}
|
@item QPassSignals: @var{signal} @r{[};@var{signal}@r{]}@dots{}
|
||||||
@cindex pass signals to inferior, remote request
|
@cindex pass signals to inferior, remote request
|
||||||
@cindex @samp{QPassSignals} packet
|
@cindex @samp{QPassSignals} packet
|
||||||
|
@anchor{QPassSignals}
|
||||||
Each listed @var{signal} should be passed directly to the inferior process.
|
Each listed @var{signal} should be passed directly to the inferior process.
|
||||||
Signals are numbered identically to continue packets and stop replies
|
Signals are numbered identically to continue packets and stop replies
|
||||||
(@pxref{Stop Reply Packets}). Each @var{signal} list item should be
|
(@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 @samp{-}
|
||||||
@tab Yes
|
@tab Yes
|
||||||
|
|
||||||
|
@item @samp{qXfer:features:read}
|
||||||
|
@tab No
|
||||||
|
@tab @samp{-}
|
||||||
|
@tab Yes
|
||||||
|
|
||||||
@item @samp{qXfer:memory-map:read}
|
@item @samp{qXfer:memory-map:read}
|
||||||
@tab No
|
@tab No
|
||||||
@tab @samp{-}
|
@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
|
The remote stub understands the @samp{qXfer:auxv:read} packet
|
||||||
(@pxref{qXfer auxiliary vector read}).
|
(@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
|
@end table
|
||||||
|
|
||||||
@item qSymbol::
|
@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,
|
This packet is not probed by default; the remote stub must request it,
|
||||||
by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
|
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}
|
@item qXfer:memory-map:read::@var{offset},@var{length}
|
||||||
@anchor{qXfer memory map read}
|
@anchor{qXfer memory map read}
|
||||||
Access the target's @dfn{memory-map}. @xref{Memory map format}. The
|
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
|
@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
|
@include gpl.texi
|
||||||
|
|
||||||
@raisesections
|
@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>
|
2007-01-03 Denis Pilat <denis.pilat@st.com>
|
||||||
Daniel Jacobowitz <dan@codesourcery.com>
|
Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
@ -198,4 +198,10 @@ struct linux_target_ops the_low_target = {
|
|||||||
NULL,
|
NULL,
|
||||||
1,
|
1,
|
||||||
i386_breakpoint_at,
|
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
|
#endif
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
linux_arch_string (void)
|
||||||
|
{
|
||||||
|
return the_low_target.arch_string;
|
||||||
|
}
|
||||||
|
|
||||||
static struct target_ops linux_target_ops = {
|
static struct target_ops linux_target_ops = {
|
||||||
linux_create_inferior,
|
linux_create_inferior,
|
||||||
linux_attach,
|
linux_attach,
|
||||||
@ -1670,6 +1676,7 @@ static struct target_ops linux_target_ops = {
|
|||||||
#else
|
#else
|
||||||
NULL,
|
NULL,
|
||||||
#endif
|
#endif
|
||||||
|
linux_arch_string,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -71,6 +71,10 @@ struct linux_target_ops
|
|||||||
/* Whether to left-pad registers for PEEKUSR/POKEUSR if they are smaller
|
/* Whether to left-pad registers for PEEKUSR/POKEUSR if they are smaller
|
||||||
than an xfer unit. */
|
than an xfer unit. */
|
||||||
int left_pad_xfer;
|
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;
|
extern struct linux_target_ops the_low_target;
|
||||||
|
@ -172,4 +172,10 @@ struct linux_target_ops the_low_target = {
|
|||||||
NULL,
|
NULL,
|
||||||
1,
|
1,
|
||||||
x86_64_breakpoint_at,
|
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
|
to as much of DATA/LEN as we could fit. IS_MORE controls
|
||||||
the first character of the response. */
|
the first character of the response. */
|
||||||
static int
|
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;
|
int out_len;
|
||||||
|
|
||||||
@ -192,6 +192,31 @@ handle_general_set (char *own_buf)
|
|||||||
own_buf[0] = 0;
|
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. */
|
/* Handle all of the extended 'q' packets. */
|
||||||
void
|
void
|
||||||
handle_query (char *own_buf, int *new_packet_len_p)
|
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;
|
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. */
|
/* Protocol features query. */
|
||||||
if (strncmp ("qSupported", own_buf, 10) == 0
|
if (strncmp ("qSupported", own_buf, 10) == 0
|
||||||
&& (own_buf[10] == ':' || 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)
|
if (the_target->read_auxv != NULL)
|
||||||
strcat (own_buf, ";qXfer:auxv:read+");
|
strcat (own_buf, ";qXfer:auxv:read+");
|
||||||
|
|
||||||
|
if (get_features_xml () != NULL)
|
||||||
|
strcat (own_buf, ";qXfer:features:read+");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +171,10 @@ struct target_ops
|
|||||||
|
|
||||||
int (*get_tls_address) (struct thread_info *thread, CORE_ADDR offset,
|
int (*get_tls_address) (struct thread_info *thread, CORE_ADDR offset,
|
||||||
CORE_ADDR load_module, CORE_ADDR *address);
|
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;
|
extern struct target_ops *the_target;
|
||||||
|
11
gdb/remote.c
11
gdb/remote.c
@ -893,6 +893,7 @@ enum {
|
|||||||
PACKET_Z3,
|
PACKET_Z3,
|
||||||
PACKET_Z4,
|
PACKET_Z4,
|
||||||
PACKET_qXfer_auxv,
|
PACKET_qXfer_auxv,
|
||||||
|
PACKET_qXfer_features,
|
||||||
PACKET_qXfer_memory_map,
|
PACKET_qXfer_memory_map,
|
||||||
PACKET_qGetTLSAddr,
|
PACKET_qGetTLSAddr,
|
||||||
PACKET_qSupported,
|
PACKET_qSupported,
|
||||||
@ -2294,6 +2295,8 @@ static struct protocol_feature remote_protocol_features[] = {
|
|||||||
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
|
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
|
||||||
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
|
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
|
||||||
PACKET_qXfer_auxv },
|
PACKET_qXfer_auxv },
|
||||||
|
{ "qXfer:features:read", PACKET_DISABLE, remote_supported_packet,
|
||||||
|
PACKET_qXfer_features },
|
||||||
{ "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
|
{ "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
|
||||||
PACKET_qXfer_memory_map },
|
PACKET_qXfer_memory_map },
|
||||||
{ "QPassSignals", PACKET_DISABLE, remote_supported_packet,
|
{ "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,
|
return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
|
||||||
&remote_protocol_packets[PACKET_qXfer_auxv]);
|
&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:
|
case TARGET_OBJECT_MEMORY_MAP:
|
||||||
gdb_assert (annex == NULL);
|
gdb_assert (annex == NULL);
|
||||||
return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
|
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],
|
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_auxv],
|
||||||
"qXfer:auxv:read", "read-aux-vector", 0);
|
"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],
|
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
|
||||||
"qXfer:memory-map:read", "memory-map", 0);
|
"qXfer:memory-map:read", "memory-map", 0);
|
||||||
|
|
||||||
|
@ -23,9 +23,11 @@
|
|||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "arch-utils.h"
|
#include "arch-utils.h"
|
||||||
|
#include "gdbcmd.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "target-descriptions.h"
|
#include "target-descriptions.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
|
#include "xml-tdesc.h"
|
||||||
|
|
||||||
#include "gdb_assert.h"
|
#include "gdb_assert.h"
|
||||||
|
|
||||||
@ -33,13 +35,16 @@
|
|||||||
|
|
||||||
typedef struct property
|
typedef struct property
|
||||||
{
|
{
|
||||||
const char *key;
|
char *key;
|
||||||
const char *value;
|
char *value;
|
||||||
} property_s;
|
} property_s;
|
||||||
DEF_VEC_O(property_s);
|
DEF_VEC_O(property_s);
|
||||||
|
|
||||||
struct target_desc
|
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. */
|
/* Any architecture-specific properties specified by the target. */
|
||||||
VEC(property_s) *properties;
|
VEC(property_s) *properties;
|
||||||
};
|
};
|
||||||
@ -61,6 +66,12 @@ static int target_desc_fetched;
|
|||||||
|
|
||||||
static const struct target_desc *current_target_desc;
|
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
|
/* Fetch the current target's description, and switch the current
|
||||||
architecture to one which incorporates that description. */
|
architecture to one which incorporates that description. */
|
||||||
|
|
||||||
@ -79,6 +90,21 @@ target_find_description (void)
|
|||||||
disconnected from the previous target. */
|
disconnected from the previous target. */
|
||||||
gdb_assert (gdbarch_target_desc (current_gdbarch) == NULL);
|
gdb_assert (gdbarch_target_desc (current_gdbarch) == NULL);
|
||||||
|
|
||||||
|
/* 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);
|
current_target_desc = target_read_description (¤t_target);
|
||||||
|
|
||||||
/* If a non-NULL description was returned, then update the current
|
/* If a non-NULL description was returned, then update the current
|
||||||
@ -130,6 +156,9 @@ target_current_description (void)
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Direct accessors for feature sets. */
|
||||||
|
|
||||||
/* Return the string value of a property named KEY, or NULL if the
|
/* Return the string value of a property named KEY, or NULL if the
|
||||||
property was not specified. */
|
property was not specified. */
|
||||||
@ -148,6 +177,16 @@ tdesc_property (const struct target_desc *target_desc, const char *key)
|
|||||||
return NULL;
|
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. */
|
/* Methods for constructing a target description. */
|
||||||
|
|
||||||
struct target_desc *
|
struct target_desc *
|
||||||
@ -156,6 +195,31 @@ allocate_target_description (void)
|
|||||||
return XZALLOC (struct target_desc);
|
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
|
void
|
||||||
set_tdesc_property (struct target_desc *target_desc,
|
set_tdesc_property (struct target_desc *target_desc,
|
||||||
const char *key, const char *value)
|
const char *key, const char *value)
|
||||||
@ -171,7 +235,102 @@ set_tdesc_property (struct target_desc *target_desc,
|
|||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
_("Attempted to add duplicate property \"%s\""), key);
|
_("Attempted to add duplicate property \"%s\""), key);
|
||||||
|
|
||||||
new_prop.key = key;
|
new_prop.key = xstrdup (key);
|
||||||
new_prop.value = value;
|
new_prop.value = xstrdup (value);
|
||||||
VEC_safe_push (property_s, target_desc->properties, &new_prop);
|
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. */
|
/* 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
|
/* Return the string value of a property named KEY, or NULL if the
|
||||||
property was not specified. */
|
property was not specified. */
|
||||||
|
|
||||||
@ -53,6 +59,9 @@ const char *tdesc_property (const struct target_desc *,
|
|||||||
/* Methods for constructing a target description. */
|
/* Methods for constructing a target description. */
|
||||||
|
|
||||||
struct target_desc *allocate_target_description (void);
|
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 *,
|
void set_tdesc_property (struct target_desc *,
|
||||||
const char *key, const char *value);
|
const char *key, const char *value);
|
||||||
|
@ -206,8 +206,10 @@ enum target_object
|
|||||||
a previously erased flash memory. Using it without erasing
|
a previously erased flash memory. Using it without erasing
|
||||||
flash can have unexpected results. Addresses are physical
|
flash can have unexpected results. Addresses are physical
|
||||||
address on target, and not relative to flash start. */
|
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, ... */
|
/* 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 *);
|
Reference in New Issue
Block a user