* Makefile.in (XMLFILES): Add library-list.dtd.
(ALLDEPFILES): Add solib-target.o. (solib-target.o): New rule. * remote.c (PACKET_qXfer_libraries): New constant. (remote_protocol_features): Add qXfer:libraries:read. (remote_wait): Recognize library stop replies. (remote_async_wait): Likewise. Fix typo. (remote_xfer_partial): Handle TARGET_OBJECT_LIBRARIES. (init_remote_async_ops): Fix typo. (_initialize_remote): Register "set remote library-info-packet". * solib-som.c (som_current_sos): Set addr_low and addr_high. * solib-target.c: New file. * solib.c (solib_map_sections): Use addr_low and addr_high instead of textsection. (info_sharedlibrary_command): Likewise. (solib_add_library, solib_remove_library): New. * solist.h (struct so_list): Replace textsection with addr_low and addr_high. * target.h (enum target_object): Add TARGET_OBJECT_LIBRARIES. * NEWS: Describe new qXfer:libraries:read and shared library event support. * features/library-list.dtd: New. * gdb.texinfo (Remote Configuration): Document library-info-packet. Add other missing entries. Adjust the table size to fit. (Stop Reply Packets): Use @itemize instead of @enumerate. Document stop reasons including the new "library" event. (General Query Packets): Adjust table widths for qSupported. Mention qXfer:libraries:read reply to qSupported and document the new packet. (Library List Format): New section.
This commit is contained in:
parent
b0f4b84b5c
commit
cfa9d6d991
@ -1,3 +1,28 @@
|
||||
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* Makefile.in (XMLFILES): Add library-list.dtd.
|
||||
(ALLDEPFILES): Add solib-target.o.
|
||||
(solib-target.o): New rule.
|
||||
* remote.c (PACKET_qXfer_libraries): New constant.
|
||||
(remote_protocol_features): Add qXfer:libraries:read.
|
||||
(remote_wait): Recognize library stop replies.
|
||||
(remote_async_wait): Likewise. Fix typo.
|
||||
(remote_xfer_partial): Handle TARGET_OBJECT_LIBRARIES.
|
||||
(init_remote_async_ops): Fix typo.
|
||||
(_initialize_remote): Register "set remote library-info-packet".
|
||||
* solib-som.c (som_current_sos): Set addr_low and addr_high.
|
||||
* solib-target.c: New file.
|
||||
* solib.c (solib_map_sections): Use addr_low and addr_high instead
|
||||
of textsection.
|
||||
(info_sharedlibrary_command): Likewise.
|
||||
(solib_add_library, solib_remove_library): New.
|
||||
* solist.h (struct so_list): Replace textsection with addr_low and
|
||||
addr_high.
|
||||
* target.h (enum target_object): Add TARGET_OBJECT_LIBRARIES.
|
||||
* NEWS: Describe new qXfer:libraries:read and shared library
|
||||
event support.
|
||||
* features/library-list.dtd: New.
|
||||
|
||||
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* infrun.c (inferior_ignoring_startup_exec_events): Delete.
|
||||
|
@ -403,6 +403,7 @@ RUNTESTFLAGS=
|
||||
|
||||
# XML files to build in to GDB.
|
||||
XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
|
||||
$(srcdir)/features/library-list.dtd \
|
||||
$(TDEP_XML)
|
||||
|
||||
# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
|
||||
@ -1471,6 +1472,7 @@ ALLDEPFILES = \
|
||||
mips64obsd-nat.c mips64obsd-tdep.c \
|
||||
nbsd-nat.c nbsd-tdep.c obsd-tdep.c \
|
||||
solib-osf.c \
|
||||
solib-target.c \
|
||||
somread.c solib-som.c \
|
||||
posix-hdep.c \
|
||||
ppc-sysv-tdep.c ppc-linux-nat.c ppc-linux-tdep.c \
|
||||
@ -2596,6 +2598,9 @@ solib-svr4.o: solib-svr4.c $(defs_h) $(elf_external_h) $(elf_common_h) \
|
||||
$(gdbcore_h) $(target_h) $(inferior_h) $(gdb_assert_h) \
|
||||
$(solist_h) $(solib_h) $(solib_svr4_h) $(bfd_target_h) $(elf_bfd_h) \
|
||||
$(exec_h)
|
||||
solib-target.o: solib-target.c $(defs_h) $(objfiles_h) $(solist_h) \
|
||||
$(symtab_h) $(symfile_h) $(target_h) $(vec_h) $(xml_support_h) \
|
||||
$(gdb_string_h)
|
||||
sol-thread.o: sol-thread.c $(defs_h) $(gdbthread_h) $(target_h) \
|
||||
$(inferior_h) $(gdb_stat_h) $(gdbcmd_h) $(gdbcore_h) $(regcache_h) \
|
||||
$(solib_h) $(symfile_h) $(observer_h) $(gdb_string_h) $(gregset_h)
|
||||
|
12
gdb/NEWS
12
gdb/NEWS
@ -44,6 +44,12 @@ segment base addresses (rather than offsets) are available.
|
||||
* The /i format now outputs any trailing branch delay slot instructions
|
||||
immediately following the last instruction within the count specified.
|
||||
|
||||
* The GDB remote protocol "T" stop reply packet now supports a
|
||||
"library" response. Combined with the new "qXfer:libraries:read"
|
||||
packet, this response allows GDB to debug shared libraries on targets
|
||||
where the operating system manages the list of loaded libraries (e.g.
|
||||
Windows and SymbianOS).
|
||||
|
||||
* New commands
|
||||
|
||||
set remoteflow
|
||||
@ -117,6 +123,12 @@ qXfer:spu:write:
|
||||
Read or write contents of an spufs file on the target system. These
|
||||
packets are available only on the Cell/B.E. SPU architecture.
|
||||
|
||||
qXfer:libraries:read:
|
||||
Report the loaded shared libraries. Combined with new "T" packet
|
||||
response, this packet allows GDB to debug shared libraries on
|
||||
targets where the operating system manages the list of loaded
|
||||
libraries (e.g. Windows and SymbianOS).
|
||||
|
||||
* Removed targets
|
||||
|
||||
Support for these obsolete configurations has been removed.
|
||||
|
@ -1,3 +1,13 @@
|
||||
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Remote Configuration): Document library-info-packet.
|
||||
Add other missing entries. Adjust the table size to fit.
|
||||
(Stop Reply Packets): Use @itemize instead of @enumerate. Document
|
||||
stop reasons including the new "library" event.
|
||||
(General Query Packets): Adjust table widths for qSupported. Mention
|
||||
qXfer:libraries:read reply to qSupported and document the new packet.
|
||||
(Library List Format): New section.
|
||||
|
||||
2007-07-01 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.texinfo (Attach): Fixed GDB exit inferior detachment.
|
||||
|
@ -12859,58 +12859,80 @@ If you do, that may be a bug in your remote debugging stub, or a bug
|
||||
in @value{GDBN}. You may want to report the problem to the
|
||||
@value{GDBN} developers.
|
||||
|
||||
The available settings are:
|
||||
For each packet @var{name}, the command to enable or disable the
|
||||
packet is @code{set remote @var{name}-packet}. The available settings
|
||||
are:
|
||||
|
||||
@multitable @columnfractions 0.3 0.2 0.35
|
||||
@multitable @columnfractions 0.28 0.32 0.25
|
||||
@item Command Name
|
||||
@tab Remote Packet
|
||||
@tab Related Features
|
||||
|
||||
@item @code{fetch-register-packet}
|
||||
@item @code{fetch-register}
|
||||
@tab @code{p}
|
||||
@tab @code{info registers}
|
||||
|
||||
@item @code{set-register-packet}
|
||||
@item @code{set-register}
|
||||
@tab @code{P}
|
||||
@tab @code{set}
|
||||
|
||||
@item @code{binary-download-packet}
|
||||
@item @code{binary-download}
|
||||
@tab @code{X}
|
||||
@tab @code{load}, @code{set}
|
||||
|
||||
@item @code{read-aux-vector-packet}
|
||||
@item @code{read-aux-vector}
|
||||
@tab @code{qXfer:auxv:read}
|
||||
@tab @code{info auxv}
|
||||
|
||||
@item @code{symbol-lookup-packet}
|
||||
@item @code{symbol-lookup}
|
||||
@tab @code{qSymbol}
|
||||
@tab Detecting multiple threads
|
||||
|
||||
@item @code{verbose-resume-packet}
|
||||
@item @code{verbose-resume}
|
||||
@tab @code{vCont}
|
||||
@tab Stepping or resuming multiple threads
|
||||
|
||||
@item @code{software-breakpoint-packet}
|
||||
@item @code{software-breakpoint}
|
||||
@tab @code{Z0}
|
||||
@tab @code{break}
|
||||
|
||||
@item @code{hardware-breakpoint-packet}
|
||||
@item @code{hardware-breakpoint}
|
||||
@tab @code{Z1}
|
||||
@tab @code{hbreak}
|
||||
|
||||
@item @code{write-watchpoint-packet}
|
||||
@item @code{write-watchpoint}
|
||||
@tab @code{Z2}
|
||||
@tab @code{watch}
|
||||
|
||||
@item @code{read-watchpoint-packet}
|
||||
@item @code{read-watchpoint}
|
||||
@tab @code{Z3}
|
||||
@tab @code{rwatch}
|
||||
|
||||
@item @code{access-watchpoint-packet}
|
||||
@item @code{access-watchpoint}
|
||||
@tab @code{Z4}
|
||||
@tab @code{awatch}
|
||||
|
||||
@item @code{get-thread-local-storage-address-packet}
|
||||
@item @code{target-features}
|
||||
@tab @code{qXfer:features:read}
|
||||
@tab @code{set architecture}
|
||||
|
||||
@item @code{library-info}
|
||||
@tab @code{qXfer:libraries:read}
|
||||
@tab @code{info sharedlibrary}
|
||||
|
||||
@item @code{memory-map}
|
||||
@tab @code{qXfer:memory-map:read}
|
||||
@tab @code{info mem}
|
||||
|
||||
@item @code{read-spu-object}
|
||||
@tab @code{qXfer:spu:read}
|
||||
@tab @code{info spu}
|
||||
|
||||
@item @code{write-spu-object}
|
||||
@tab @code{qXfer:spu:write}
|
||||
@tab @code{info spu}
|
||||
|
||||
@item @code{get-thread-local-@*storage-address}
|
||||
@tab @code{qGetTLSAddr}
|
||||
@tab Displaying @code{__thread} variables
|
||||
|
||||
@ -12918,7 +12940,7 @@ The available settings are:
|
||||
@tab @code{qSupported}
|
||||
@tab Remote communications parameters
|
||||
|
||||
@item @code{pass-signals-packet}
|
||||
@item @code{pass-signals}
|
||||
@tab @code{QPassSignals}
|
||||
@tab @code{handle @var{signal}}
|
||||
|
||||
@ -22506,6 +22528,7 @@ Show the current setting of the target wait timeout.
|
||||
* Interrupts::
|
||||
* Examples::
|
||||
* File-I/O Remote Protocol Extension::
|
||||
* Library List Format::
|
||||
* Memory Map Format::
|
||||
@end menu
|
||||
|
||||
@ -23223,24 +23246,45 @@ number). This is equivalent to an @samp{S} response, except that the
|
||||
and other information directly in the stop reply packet, reducing
|
||||
round-trip latency. Single-step and breakpoint traps are reported
|
||||
this way. Each @samp{@var{n}:@var{r}} pair is interpreted as follows:
|
||||
@enumerate
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
If @var{n} is a hexadecimal number, it is a register number, and the
|
||||
corresponding @var{r} gives that register's value. @var{r} is a
|
||||
series of bytes in target byte order, with each byte given by a
|
||||
two-digit hex number.
|
||||
|
||||
@item
|
||||
If @var{n} is @samp{thread}, then @var{r} is the thread process ID, in
|
||||
hex.
|
||||
|
||||
@item
|
||||
If @var{n} is @samp{watch}, @samp{rwatch}, or @samp{awatch}, then the
|
||||
packet indicates a watchpoint hit, and @var{r} is the data address, in
|
||||
hex.
|
||||
If @var{n} is a recognized @dfn{stop reason}, it describes a more
|
||||
specific event that stopped the target. The currently defined stop
|
||||
reasons are listed below. @var{aa} should be @samp{05}, the trap
|
||||
signal. At most one stop reason should be present.
|
||||
|
||||
@item
|
||||
Otherwise, @value{GDBN} should ignore this @samp{@var{n}:@var{r}} pair
|
||||
and go on to the next; this allows us to extend the protocol in the
|
||||
future.
|
||||
@end enumerate
|
||||
@end itemize
|
||||
|
||||
The currently defined stop reasons are:
|
||||
|
||||
@table @samp
|
||||
@item watch
|
||||
@itemx rwatch
|
||||
@itemx awatch
|
||||
The packet indicates a watchpoint hit, and @var{r} is the data address, in
|
||||
hex.
|
||||
|
||||
@cindex shared library events, remote reply
|
||||
@item library
|
||||
The packet indicates that the loaded libraries have changed.
|
||||
@value{GDBN} should use @samp{qXfer:libraries:read} to fetch a new
|
||||
list of loaded libraries. @var{r} is ignored.
|
||||
@end table
|
||||
|
||||
@item W @var{AA}
|
||||
The process exited, and @var{AA} is the exit status. This is only
|
||||
@ -23626,7 +23670,7 @@ stubs which may be configured for multiple targets.
|
||||
|
||||
These are the currently defined stub features and their properties:
|
||||
|
||||
@multitable @columnfractions 0.25 0.2 0.2 0.2
|
||||
@multitable @columnfractions 0.35 0.2 0.12 0.2
|
||||
@c NOTE: The first row should be @headitem, but we do not yet require
|
||||
@c a new enough version of Texinfo (4.7) to use @headitem.
|
||||
@item Feature Name
|
||||
@ -23649,6 +23693,11 @@ These are the currently defined stub features and their properties:
|
||||
@tab @samp{-}
|
||||
@tab Yes
|
||||
|
||||
@item @samp{qXfer:libraries:read}
|
||||
@tab No
|
||||
@tab @samp{-}
|
||||
@tab Yes
|
||||
|
||||
@item @samp{qXfer:memory-map:read}
|
||||
@tab No
|
||||
@tab @samp{-}
|
||||
@ -23693,6 +23742,10 @@ The remote stub understands the @samp{qXfer:auxv:read} packet
|
||||
The remote stub understands the @samp{qXfer:features:read} packet
|
||||
(@pxref{qXfer target description read}).
|
||||
|
||||
@item qXfer:libraries:read
|
||||
The remote stub understands the @samp{qXfer:libraries:read} packet
|
||||
(@pxref{qXfer library list read}).
|
||||
|
||||
@item qXfer:memory-map:read
|
||||
The remote stub understands the @samp{qXfer:memory-map:read} packet
|
||||
(@pxref{qXfer memory map read}).
|
||||
@ -23815,6 +23868,19 @@ 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:libraries:read:@var{annex}:@var{offset},@var{length}
|
||||
@anchor{qXfer library list read}
|
||||
Access the target's list of loaded libraries. @xref{Library List Format}.
|
||||
The annex part of the generic @samp{qXfer} packet must be empty
|
||||
(@pxref{qXfer read}).
|
||||
|
||||
Targets which maintain a list of libraries in the program's memory do
|
||||
not need to implement this packet; it is designed for platforms where
|
||||
the operating system manages the list of loaded libraries.
|
||||
|
||||
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
|
||||
@ -25331,6 +25397,51 @@ host is called:
|
||||
<- @code{T02}
|
||||
@end smallexample
|
||||
|
||||
@node Library List Format
|
||||
@section Library List Format
|
||||
@cindex library list format, remote protocol
|
||||
|
||||
On some platforms, a dynamic loader (e.g.@: @file{ld.so}) runs in the
|
||||
same process as your application to manage libraries. In this case,
|
||||
@value{GDBN} can use the loader's symbol table and normal memory
|
||||
operations to maintain a list of shared libraries. On other
|
||||
platforms, the operating system manages loaded libraries.
|
||||
@value{GDBN} can not retrieve the list of currently loaded libraries
|
||||
through memory operations, so it uses the @samp{qXfer:libraries:read}
|
||||
packet (@pxref{qXfer library list read}) instead. The remote stub
|
||||
queries the target's operating system and reports which libraries
|
||||
are loaded.
|
||||
|
||||
The @samp{qXfer:libraries:read} packet returns an XML document which
|
||||
lists loaded libraries and their offsets. Each library has an
|
||||
associated name and one or more segment base addresses, which report
|
||||
where the library was loaded in memory. The segment bases are start
|
||||
addresses, not relocation offsets; they do not depend on the library's
|
||||
link-time base addresses.
|
||||
|
||||
A simple memory map, with one loaded library relocated by a single
|
||||
offset, looks like this:
|
||||
|
||||
@smallexample
|
||||
<library-list>
|
||||
<library name="/lib/libc.so.6">
|
||||
<segment address="0x10000000"/>
|
||||
</library>
|
||||
</library-list>
|
||||
@end smallexample
|
||||
|
||||
The format of a library list is described by this DTD:
|
||||
|
||||
@smallexample
|
||||
<!-- library-list: Root element with versioning -->
|
||||
<!ELEMENT library-list (library)*>
|
||||
<!ATTLIST library-list version CDATA #FIXED "1.0">
|
||||
<!ELEMENT library (segment)*>
|
||||
<!ATTLIST library name CDATA #REQUIRED>
|
||||
<!ELEMENT segment EMPTY>
|
||||
<!ATTLIST segment address CDATA #REQUIRED>
|
||||
@end smallexample
|
||||
|
||||
@node Memory Map Format
|
||||
@section Memory Map Format
|
||||
@cindex memory map format
|
||||
|
15
gdb/features/library-list.dtd
Normal file
15
gdb/features/library-list.dtd
Normal file
@ -0,0 +1,15 @@
|
||||
<!-- Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!-- library-list: Root element with versioning -->
|
||||
<!ELEMENT library-list (library)*>
|
||||
<!ATTLIST library-list version CDATA #FIXED "1.0">
|
||||
|
||||
<!ELEMENT library (segment)*>
|
||||
<!ATTLIST library name CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT segment EMPTY>
|
||||
<!ATTLIST segment address CDATA #REQUIRED>
|
59
gdb/remote.c
59
gdb/remote.c
@ -905,6 +905,7 @@ enum {
|
||||
PACKET_Z4,
|
||||
PACKET_qXfer_auxv,
|
||||
PACKET_qXfer_features,
|
||||
PACKET_qXfer_libraries,
|
||||
PACKET_qXfer_memory_map,
|
||||
PACKET_qXfer_spu_read,
|
||||
PACKET_qXfer_spu_write,
|
||||
@ -2376,6 +2377,8 @@ static struct protocol_feature remote_protocol_features[] = {
|
||||
PACKET_qXfer_auxv },
|
||||
{ "qXfer:features:read", PACKET_DISABLE, remote_supported_packet,
|
||||
PACKET_qXfer_features },
|
||||
{ "qXfer:libraries:read", PACKET_DISABLE, remote_supported_packet,
|
||||
PACKET_qXfer_libraries },
|
||||
{ "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
|
||||
PACKET_qXfer_memory_map },
|
||||
{ "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet,
|
||||
@ -3181,6 +3184,7 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status)
|
||||
struct remote_arch_state *rsa = get_remote_arch_state ();
|
||||
ULONGEST thread_num = -1;
|
||||
ULONGEST addr;
|
||||
int solibs_changed = 0;
|
||||
|
||||
status->kind = TARGET_WAITKIND_EXITED;
|
||||
status->value.integer = 0;
|
||||
@ -3266,6 +3270,16 @@ Packet: '%s'\n"),
|
||||
p = unpack_varlen_hex (++p1, &addr);
|
||||
remote_watch_data_address = (CORE_ADDR)addr;
|
||||
}
|
||||
else if (strncmp (p, "library", p1 - p) == 0)
|
||||
{
|
||||
p1++;
|
||||
p_temp = p1;
|
||||
while (*p_temp && *p_temp != ';')
|
||||
p_temp++;
|
||||
|
||||
solibs_changed = 1;
|
||||
p = p_temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Silently skip unknown optional info. */
|
||||
@ -3307,9 +3321,14 @@ Packet: '%s'\n"),
|
||||
}
|
||||
/* fall through */
|
||||
case 'S': /* Old style status, just signal only. */
|
||||
status->kind = TARGET_WAITKIND_STOPPED;
|
||||
status->value.sig = (enum target_signal)
|
||||
(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
|
||||
if (solibs_changed)
|
||||
status->kind = TARGET_WAITKIND_LOADED;
|
||||
else
|
||||
{
|
||||
status->kind = TARGET_WAITKIND_STOPPED;
|
||||
status->value.sig = (enum target_signal)
|
||||
(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
|
||||
}
|
||||
|
||||
if (buf[3] == 'p')
|
||||
{
|
||||
@ -3372,6 +3391,7 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status)
|
||||
struct remote_arch_state *rsa = get_remote_arch_state ();
|
||||
ULONGEST thread_num = -1;
|
||||
ULONGEST addr;
|
||||
int solibs_changed = 0;
|
||||
|
||||
status->kind = TARGET_WAITKIND_EXITED;
|
||||
status->value.integer = 0;
|
||||
@ -3433,7 +3453,7 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status)
|
||||
/* If this packet is an awatch packet, don't parse the 'a'
|
||||
as a register number. */
|
||||
|
||||
if (!strncmp (p, "awatch", strlen ("awatch")) != 0)
|
||||
if (strncmp (p, "awatch", strlen("awatch")) != 0)
|
||||
{
|
||||
/* Read the register number. */
|
||||
pnum = strtol (p, &p_temp, 16);
|
||||
@ -3463,6 +3483,16 @@ Packet: '%s'\n"),
|
||||
p = unpack_varlen_hex (++p1, &addr);
|
||||
remote_watch_data_address = (CORE_ADDR)addr;
|
||||
}
|
||||
else if (strncmp (p, "library", p1 - p) == 0)
|
||||
{
|
||||
p1++;
|
||||
p_temp = p1;
|
||||
while (*p_temp && *p_temp != ';')
|
||||
p_temp++;
|
||||
|
||||
solibs_changed = 1;
|
||||
p = p_temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Silently skip unknown optional info. */
|
||||
@ -3504,9 +3534,14 @@ Packet: '%s'\n"),
|
||||
}
|
||||
/* fall through */
|
||||
case 'S': /* Old style status, just signal only. */
|
||||
status->kind = TARGET_WAITKIND_STOPPED;
|
||||
status->value.sig = (enum target_signal)
|
||||
(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
|
||||
if (solibs_changed)
|
||||
status->kind = TARGET_WAITKIND_LOADED;
|
||||
else
|
||||
{
|
||||
status->kind = TARGET_WAITKIND_STOPPED;
|
||||
status->value.sig = (enum target_signal)
|
||||
(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
|
||||
}
|
||||
|
||||
if (buf[3] == 'p')
|
||||
{
|
||||
@ -5799,6 +5834,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
|
||||
(ops, "features", annex, readbuf, offset, len,
|
||||
&remote_protocol_packets[PACKET_qXfer_features]);
|
||||
|
||||
case TARGET_OBJECT_LIBRARIES:
|
||||
return remote_read_qxfer
|
||||
(ops, "libraries", annex, readbuf, offset, len,
|
||||
&remote_protocol_packets[PACKET_qXfer_libraries]);
|
||||
|
||||
case TARGET_OBJECT_MEMORY_MAP:
|
||||
gdb_assert (annex == NULL);
|
||||
return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
|
||||
@ -6416,7 +6456,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
remote_async_ops.to_memory_map = remote_memory_map;
|
||||
remote_async_ops.to_flash_erase = remote_flash_erase;
|
||||
remote_async_ops.to_flash_done = remote_flash_done;
|
||||
remote_ops.to_read_description = remote_read_description;
|
||||
remote_async_ops.to_read_description = remote_read_description;
|
||||
}
|
||||
|
||||
/* Set up the async extended remote vector by making a copy of the standard
|
||||
@ -6656,6 +6696,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
|
||||
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_libraries],
|
||||
"qXfer:libraries:read", "library-info", 0);
|
||||
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
|
||||
"qXfer:memory-map:read", "memory-map", 0);
|
||||
|
||||
|
@ -623,6 +623,9 @@ som_current_sos (void)
|
||||
paddr_nz (new->lm_info->tsd_start_addr));
|
||||
#endif
|
||||
|
||||
new->addr_low = lmi->text_addr;
|
||||
new->addr_high = lmi->text_end;
|
||||
|
||||
/* Link the new object onto the list. */
|
||||
new->next = NULL;
|
||||
*link_ptr = new;
|
||||
|
384
gdb/solib-target.c
Normal file
384
gdb/solib-target.c
Normal file
@ -0,0 +1,384 @@
|
||||
/* Definitions for targets which report shared library events.
|
||||
|
||||
Copyright (C) 2007
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
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 "objfiles.h"
|
||||
#include "solist.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "target.h"
|
||||
#include "vec.h"
|
||||
|
||||
#include "gdb_string.h"
|
||||
|
||||
DEF_VEC_O(CORE_ADDR);
|
||||
|
||||
/* Private data for each loaded library. */
|
||||
struct lm_info
|
||||
{
|
||||
/* The library's name. The name is normally kept in the struct
|
||||
so_list; it is only here during XML parsing. */
|
||||
char *name;
|
||||
|
||||
/* The base addresses for each independently relocatable segment of
|
||||
this shared library. */
|
||||
VEC(CORE_ADDR) *segment_bases;
|
||||
|
||||
/* The cached offsets for each section of this shared library,
|
||||
determined from SEGMENT_BASES. */
|
||||
struct section_offsets *offsets;
|
||||
};
|
||||
|
||||
typedef struct lm_info *lm_info_p;
|
||||
DEF_VEC_P(lm_info_p);
|
||||
|
||||
#if !defined(HAVE_LIBEXPAT)
|
||||
|
||||
static VEC(lm_info_p)
|
||||
solib_target_parse_libraries (const char *library)
|
||||
{
|
||||
static int have_warned;
|
||||
|
||||
if (!have_warned)
|
||||
{
|
||||
have_warned = 1;
|
||||
warning (_("Can not parse XML library list; XML support was disabled "
|
||||
"at compile time"));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else /* HAVE_LIBEXPAT */
|
||||
|
||||
#include "xml-support.h"
|
||||
|
||||
/* Handle the start of a <segment> element. */
|
||||
|
||||
static void
|
||||
library_list_start_segment (struct gdb_xml_parser *parser,
|
||||
const struct gdb_xml_element *element,
|
||||
void *user_data, VEC(gdb_xml_value_s) *attributes)
|
||||
{
|
||||
VEC(lm_info_p) **list = user_data;
|
||||
struct lm_info *last = VEC_last (lm_info_p, *list);
|
||||
ULONGEST *address_p = VEC_index (gdb_xml_value_s, attributes, 0)->value;
|
||||
|
||||
VEC_safe_push (CORE_ADDR, last->segment_bases, address_p);
|
||||
}
|
||||
|
||||
/* Handle the start of a <library> element. */
|
||||
|
||||
static void
|
||||
library_list_start_library (struct gdb_xml_parser *parser,
|
||||
const struct gdb_xml_element *element,
|
||||
void *user_data, VEC(gdb_xml_value_s) *attributes)
|
||||
{
|
||||
VEC(lm_info_p) **list = user_data;
|
||||
struct lm_info *item = XZALLOC (struct lm_info);
|
||||
const char *name = VEC_index (gdb_xml_value_s, attributes, 0)->value;
|
||||
|
||||
item->name = xstrdup (name);
|
||||
VEC_safe_push (lm_info_p, *list, item);
|
||||
}
|
||||
|
||||
/* Handle the start of a <library-list> element. */
|
||||
|
||||
static void
|
||||
library_list_start_list (struct gdb_xml_parser *parser,
|
||||
const struct gdb_xml_element *element,
|
||||
void *user_data, VEC(gdb_xml_value_s) *attributes)
|
||||
{
|
||||
char *version = VEC_index (gdb_xml_value_s, attributes, 0)->value;
|
||||
|
||||
if (strcmp (version, "1.0") != 0)
|
||||
gdb_xml_error (parser,
|
||||
_("Library list has unsupported version \"%s\""),
|
||||
version);
|
||||
}
|
||||
|
||||
/* Discard the constructed library list. */
|
||||
|
||||
static void
|
||||
solib_target_free_library_list (void *p)
|
||||
{
|
||||
VEC(lm_info_p) **result = p;
|
||||
struct lm_info *info;
|
||||
int ix;
|
||||
|
||||
for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
|
||||
{
|
||||
xfree (info->name);
|
||||
VEC_free (CORE_ADDR, info->segment_bases);
|
||||
xfree (info);
|
||||
}
|
||||
VEC_free (lm_info_p, *result);
|
||||
*result = NULL;
|
||||
}
|
||||
|
||||
/* The allowed elements and attributes for an XML library list.
|
||||
The root element is a <library-list>. */
|
||||
|
||||
const struct gdb_xml_attribute segment_attributes[] = {
|
||||
{ "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
|
||||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
const struct gdb_xml_element library_children[] = {
|
||||
{ "segment", segment_attributes, NULL, GDB_XML_EF_REPEATABLE,
|
||||
library_list_start_segment, NULL },
|
||||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
const struct gdb_xml_attribute library_attributes[] = {
|
||||
{ "name", GDB_XML_AF_NONE, NULL, NULL },
|
||||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
const struct gdb_xml_element library_list_children[] = {
|
||||
{ "library", library_attributes, library_children,
|
||||
GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
|
||||
library_list_start_library, NULL },
|
||||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
const struct gdb_xml_attribute library_list_attributes[] = {
|
||||
{ "version", GDB_XML_AF_NONE, NULL, NULL },
|
||||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
const struct gdb_xml_element library_list_elements[] = {
|
||||
{ "library-list", library_list_attributes, library_list_children,
|
||||
GDB_XML_EF_NONE, library_list_start_list, NULL },
|
||||
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
static VEC(lm_info_p) *
|
||||
solib_target_parse_libraries (const char *library)
|
||||
{
|
||||
struct gdb_xml_parser *parser;
|
||||
VEC(lm_info_p) *result = NULL;
|
||||
struct cleanup *before_deleting_result, *back_to;
|
||||
|
||||
back_to = make_cleanup (null_cleanup, NULL);
|
||||
parser = gdb_xml_create_parser_and_cleanup (_("target library list"),
|
||||
library_list_elements, &result);
|
||||
gdb_xml_use_dtd (parser, "library-list.dtd");
|
||||
|
||||
before_deleting_result = make_cleanup (solib_target_free_library_list,
|
||||
&result);
|
||||
|
||||
if (gdb_xml_parse (parser, library) == 0)
|
||||
/* Parsed successfully, don't need to delete the result. */
|
||||
discard_cleanups (before_deleting_result);
|
||||
|
||||
do_cleanups (back_to);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct so_list *
|
||||
solib_target_current_sos (void)
|
||||
{
|
||||
struct so_list *new_solib, *start = NULL, *last = NULL;
|
||||
const char *library_document;
|
||||
VEC(lm_info_p) *library_list;
|
||||
struct lm_info *info;
|
||||
int ix;
|
||||
|
||||
/* Fetch the list of shared libraries. */
|
||||
library_document = target_read_stralloc (¤t_target,
|
||||
TARGET_OBJECT_LIBRARIES,
|
||||
NULL);
|
||||
if (library_document == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Parse the list. */
|
||||
library_list = solib_target_parse_libraries (library_document);
|
||||
if (library_list == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Build a struct so_list for each entry on the list. */
|
||||
for (ix = 0; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
|
||||
{
|
||||
new_solib = XZALLOC (struct so_list);
|
||||
strncpy (new_solib->so_name, info->name, SO_NAME_MAX_PATH_SIZE - 1);
|
||||
new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
|
||||
strncpy (new_solib->so_original_name, info->name,
|
||||
SO_NAME_MAX_PATH_SIZE - 1);
|
||||
new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
|
||||
new_solib->lm_info = info;
|
||||
|
||||
/* We no longer need this copy of the name. */
|
||||
xfree (info->name);
|
||||
info->name = NULL;
|
||||
|
||||
/* Add it to the list. */
|
||||
if (!start)
|
||||
last = start = new_solib;
|
||||
else
|
||||
{
|
||||
last->next = new_solib;
|
||||
last = new_solib;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the library list, but not its members. */
|
||||
VEC_free (lm_info_p, library_list);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
static void
|
||||
solib_target_special_symbol_handling (void)
|
||||
{
|
||||
/* Nothing needed. */
|
||||
}
|
||||
|
||||
static void
|
||||
solib_target_solib_create_inferior_hook (void)
|
||||
{
|
||||
/* Nothing needed. */
|
||||
}
|
||||
|
||||
static void
|
||||
solib_target_clear_solib (void)
|
||||
{
|
||||
/* Nothing needed. */
|
||||
}
|
||||
|
||||
static void
|
||||
solib_target_free_so (struct so_list *so)
|
||||
{
|
||||
gdb_assert (so->lm_info->name == NULL);
|
||||
xfree (so->lm_info->offsets);
|
||||
VEC_free (CORE_ADDR, so->lm_info->segment_bases);
|
||||
xfree (so->lm_info);
|
||||
}
|
||||
|
||||
static void
|
||||
solib_target_relocate_section_addresses (struct so_list *so,
|
||||
struct section_table *sec)
|
||||
{
|
||||
int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section);
|
||||
CORE_ADDR offset;
|
||||
|
||||
/* Build the offset table only once per object file. We can not do
|
||||
it any earlier, since we need to open the file first. */
|
||||
if (so->lm_info->offsets == NULL)
|
||||
{
|
||||
struct symfile_segment_data *data;
|
||||
int num_sections = bfd_count_sections (so->abfd);
|
||||
|
||||
so->lm_info->offsets = xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections));
|
||||
|
||||
data = get_symfile_segment_data (so->abfd);
|
||||
if (data == NULL)
|
||||
warning (_("Could not relocate shared library \"%s\": no segments"),
|
||||
so->so_name);
|
||||
else
|
||||
{
|
||||
ULONGEST orig_delta;
|
||||
int i;
|
||||
int num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
|
||||
CORE_ADDR *segment_bases = VEC_address (CORE_ADDR,
|
||||
so->lm_info->segment_bases);
|
||||
|
||||
if (!symfile_map_offsets_to_segments (so->abfd, data,
|
||||
so->lm_info->offsets,
|
||||
num_bases, segment_bases))
|
||||
warning (_("Could not relocate shared library \"%s\": bad offsets"),
|
||||
so->so_name);
|
||||
|
||||
/* Find the range of addresses to report for this library in
|
||||
"info sharedlibrary". Report any consecutive segments
|
||||
which were relocated as a single unit. */
|
||||
gdb_assert (num_bases > 0);
|
||||
orig_delta = segment_bases[0] - data->segment_bases[0];
|
||||
|
||||
for (i = 1; i < data->num_segments; i++)
|
||||
{
|
||||
/* If we have run out of offsets, assume all remaining segments
|
||||
have the same offset. */
|
||||
if (i >= num_bases)
|
||||
continue;
|
||||
|
||||
/* If this segment does not have the same offset, do not include
|
||||
it in the library's range. */
|
||||
if (segment_bases[i] - data->segment_bases[i] != orig_delta)
|
||||
break;
|
||||
}
|
||||
|
||||
so->addr_low = segment_bases[0];
|
||||
so->addr_high = (data->segment_bases[i - 1]
|
||||
+ data->segment_sizes[i - 1]
|
||||
/* FIXME this must be needed! + orig_delta */);
|
||||
|
||||
free_symfile_segment_data (data);
|
||||
}
|
||||
}
|
||||
|
||||
offset = so->lm_info->offsets->offsets[sec->the_bfd_section->index];
|
||||
sec->addr += offset;
|
||||
sec->endaddr += offset;
|
||||
}
|
||||
|
||||
static int
|
||||
solib_target_open_symbol_file_object (void *from_ttyp)
|
||||
{
|
||||
/* We can't locate the main symbol file based on the target's
|
||||
knowledge; the user has to specify it. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
|
||||
{
|
||||
/* We don't have a range of addresses for the dynamic linker; there
|
||||
may not be one in the program's address space. So only report
|
||||
PLT entries (which may be import stubs). */
|
||||
return in_plt_section (pc, NULL);
|
||||
}
|
||||
|
||||
static struct target_so_ops solib_target_so_ops;
|
||||
|
||||
extern initialize_file_ftype _initialize_solib_target; /* -Wmissing-prototypes */
|
||||
|
||||
void
|
||||
_initialize_solib_target (void)
|
||||
{
|
||||
solib_target_so_ops.relocate_section_addresses
|
||||
= solib_target_relocate_section_addresses;
|
||||
solib_target_so_ops.free_so = solib_target_free_so;
|
||||
solib_target_so_ops.clear_solib = solib_target_clear_solib;
|
||||
solib_target_so_ops.solib_create_inferior_hook
|
||||
= solib_target_solib_create_inferior_hook;
|
||||
solib_target_so_ops.special_symbol_handling
|
||||
= solib_target_special_symbol_handling;
|
||||
solib_target_so_ops.current_sos = solib_target_current_sos;
|
||||
solib_target_so_ops.open_symbol_file_object
|
||||
= solib_target_open_symbol_file_object;
|
||||
solib_target_so_ops.in_dynsym_resolve_code
|
||||
= solib_target_in_dynsym_resolve_code;
|
||||
|
||||
current_target_so_ops = &solib_target_so_ops;
|
||||
}
|
18
gdb/solib.c
18
gdb/solib.c
@ -316,9 +316,15 @@ solib_map_sections (void *arg)
|
||||
object's file by the base address to which the object was actually
|
||||
mapped. */
|
||||
ops->relocate_section_addresses (so, p);
|
||||
if (strcmp (p->the_bfd_section->name, ".text") == 0)
|
||||
|
||||
/* If the target didn't provide information about the address
|
||||
range of the shared object, assume we want the location of
|
||||
the .text section. */
|
||||
if (so->addr_low == 0 && so->addr_high == 0
|
||||
&& strcmp (p->the_bfd_section->name, ".text") == 0)
|
||||
{
|
||||
so->textsection = p;
|
||||
so->addr_low = p->addr;
|
||||
so->addr_high = p->endaddr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -742,15 +748,15 @@ info_sharedlibrary_command (char *ignore, int from_tty)
|
||||
}
|
||||
|
||||
printf_unfiltered ("%-*s", addr_width,
|
||||
so->textsection != NULL
|
||||
so->addr_high != 0
|
||||
? hex_string_custom (
|
||||
(LONGEST) so->textsection->addr,
|
||||
(LONGEST) so->addr_low,
|
||||
addr_width - 4)
|
||||
: "");
|
||||
printf_unfiltered ("%-*s", addr_width,
|
||||
so->textsection != NULL
|
||||
so->addr_high != 0
|
||||
? hex_string_custom (
|
||||
(LONGEST) so->textsection->endaddr,
|
||||
(LONGEST) so->addr_high,
|
||||
addr_width - 4)
|
||||
: "");
|
||||
printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No");
|
||||
|
@ -64,7 +64,11 @@ struct so_list
|
||||
struct objfile *objfile; /* objfile for loaded lib */
|
||||
struct section_table *sections;
|
||||
struct section_table *sections_end;
|
||||
struct section_table *textsection;
|
||||
|
||||
/* Record the range of addresses belonging to this shared library.
|
||||
There may not be just one (e.g. if two segments are relocated
|
||||
differently); but this is only used for "info sharedlibrary". */
|
||||
CORE_ADDR addr_low, addr_high;
|
||||
};
|
||||
|
||||
struct target_so_ops
|
||||
|
@ -212,7 +212,9 @@ enum target_object
|
||||
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
|
||||
TARGET_OBJECT_AVAILABLE_FEATURES,
|
||||
/* Currently loaded libraries, in XML format. */
|
||||
TARGET_OBJECT_LIBRARIES
|
||||
/* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user