* 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:
Daniel Jacobowitz 2007-07-02 22:01:09 +00:00
parent b0f4b84b5c
commit cfa9d6d991
12 changed files with 657 additions and 37 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

@ -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
View 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 (&current_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;
}

View File

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

View File

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

View File

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