* Makefile.in (XMLFILES): Add library-list.dtd.
authorDaniel Jacobowitz <drow@false.org>
Mon, 2 Jul 2007 22:01:09 +0000 (22:01 +0000)
committerDaniel Jacobowitz <drow@false.org>
Mon, 2 Jul 2007 22:01:09 +0000 (22:01 +0000)
(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.

12 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/features/library-list.dtd [new file with mode: 0644]
gdb/remote.c
gdb/solib-som.c
gdb/solib-target.c [new file with mode: 0644]
gdb/solib.c
gdb/solist.h
gdb/target.h

index 3a517a9a605e0000e867d206fe0da2eb61ffb621..e1f7e3efdb244f2a7f1c1e1138a8f4667bdb199c 100644 (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.
index 3d0fa409a307f6ea9ebe07394773c98306edcc8a..5d7185565ff28a0aabb05649aabba701083ab91d 100644 (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)
index 19d78624cb9a0efb512fb22d97d84440862dd6d7..81480738c4c8c3673a81b1c059dde670a04572f6 100644 (file)
--- a/gdb/NEWS
+++ b/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.
index aec7b2c1bd36bafa8a56d01515734e9a6fcc3e3f..24cfe28ba5c9fba52191ef58acdc7f970681363d 100644 (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.
index 5ce205fd1f4f3d70a46a2a7e8677ecdde6976306..ee592d91cb40012b5463de3ead716940c788501e 100644 (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
diff --git a/gdb/features/library-list.dtd b/gdb/features/library-list.dtd
new file mode 100644 (file)
index 0000000..44aa8c8
--- /dev/null
@@ -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>
index 8b4c4430eda84a80626bd0e9ec4d496be8423b8f..050930a3a31926de63b2291238f51d0eeeaa23cd 100644 (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);
 
index 9ef770892fb143caa5486d58751e402cf4dbdf83..dcc5f63cbb4ec1ee1f11b655ef4866184c14be1a 100644 (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;
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
new file mode 100644 (file)
index 0000000..2009df4
--- /dev/null
@@ -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;
+}
index 4cdb3a532ccd3f73e5cc731fcb26e654c1aaacfa..f48b0a2aae3d6596fbc2bf83edff7eeef4c16129 100644 (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");
index 08d8e7690b9deb0686058b3b88b78eca51e9b867..c8836867b4627a165834f14ec332decba8fed990 100644 (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
index 7cde49b64507a4c90b441f7ee22d6e6abbe83692..d6e82e254a6d13b77fa093b2cfaa4549baa82160 100644 (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, ... */
 };