* [rfc / remote protocol] Remote shared library events
@ 2007-05-09 20:16 Daniel Jacobowitz
2007-05-10 3:18 ` Eli Zaretskii
` (4 more replies)
0 siblings, 5 replies; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-05-09 20:16 UTC (permalink / raw)
To: gdb-patches; +Cc: gdb
System V platforms (like GNU/Linux, Solaris, BSD, et cetera) have a
mostly userspace shared library loader. That means the loader already
has to keep track of what libraries are mapped, and GDB uses the same
data structures that the loader does to find the list. There's also
typically an application function like _dl_debug_state which is called
at every event; GDB can set a breakpoint there to be notified of
events.
Not all platforms work this way. The exceptions I'm looking at
recently are DLL-based platforms: Windows and SymbianOS. Both use an
OS-level loader instead. You have to query the OS to get the list
of libraries, and the OS provides event notification directly instead
of via a magic breakpoint. We can't poke and prod at the OS directly
during remote debugging, so to implement DLL support for these
platforms I extended the remote protocol.
The additions are three new stop replies for the "T" packet to report
events (load, unload, and dll for "something more complicated than
just a load or unload") and two new packets (qfDllInfo and qsDllInfo)
to query the current state. Detailed documentation is below and the
patch is attached.
This patch introduces a new solib_ops vector in solib-target.c. This
vector is target driven; it maintains a list based on the query packet
and event notices, instead of looking through memory.
I have tested this code on SymbianOS, Cygwin, and MinGW32. Pedro
Alves has tested a slightly earlier version on Windows CE (and wrote
the gdbserver bits I used to test it on Windows - thanks!).
What do you think, Kevin especially? I'm not entirely thrilled with
the way this interacts with other solib_ops vectors, but I'm not
unhappy with it either.
Eli, do the manual changes look OK?
All comments welcome!
+@item
+If @var{n} is @samp{load}, then the packet indicates a DLL load event,
+and @var{r} describes the newly loaded library. The library format is
+the same used in @samp{qfDllInfo} replies (@pxref{qfDllInfo}), e.g.@:
+@samp{load:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry may
+end in @samp{,nop} if this library was already mapped, e.g.@: by an
+earlier call to @code{LoadLibrary}. @var{aa} should be @samp{05}, the
+trap signal.
+
+@item
+If @var{n} is @samp{unload}, then the packet indicates a DLL unload
+event, and @var{r} describes the unloaded library. @var{r} is a list
+of comma-separated @samp{Key=Value} pairs, similar to a
+@samp{qfDllInfo} reply. The name, the segment offsets, or both may be
+used to specify which DLL to unload, e.g.@:
+@samp{unload:Name=@var{hexname}} or
+@samp{unload:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry
+may end in @samp{,nop} if this library is still mapped, e.g.@: by
+another open handle. @var{aa} should be @samp{05}, the trap signal.
+
+@item
+If @var{n} is @samp{dll}, then the packet indicates that the loaded
+DLLs have changed. @value{GDBN} should use @samp{qfDllInfo} to fetch
+a new list of loaded libraries. @var{r} is ignored. @var{aa} should
+be @samp{05}, the trap signal.
+@item qfDllInfo
+@itemx qsDllInfo
+@anchor{qfDllInfo}
+@cindex list loaded DLLs, remote request
+@cindex @samp{qfDllInfo} packet
+@cindex @samp{qsDllInfo} packet
+Obtain a list of all loaded DLLs (dynamic link libraries) from the
+target.
+
+Since there may be too many DLLs to fit into one reply packet, this
+query works iteratively: it may require more than one query/reply
+sequence to obtain the entire list. The first query of the sequence
+will be the @samp{qfDllInfo} query; subsequent queries in the
+sequence will be the @samp{qsDllInfo} query.
+
+In response to each query, the target will reply with a list of one or
+more libraries. @value{GDBN} will respond to each reply with a
+request for more libraries (using the @samp{qs} form of the query),
+until the target responds with @samp{l} (lower-case el, for
+@dfn{last}).
+
+If any stopped threads had pending DLL events not yet reported to GDB
+in a @samp{T} stop reply (@pxref{Stop Reply Packets}), then either the
+effects of those events should not be included in the result of the
+@samp{qfDllInfo} or the queued events should be discarded before they
+are reported to @value{GDBN}.
+
+Reply:
+@table @samp
+@item m Name=@var{hexname},TextSeg=@var{textaddr}@r{[},DataSeg=@var{dataaddr}@r{]}
+A single loaded library. @var{hexname} is the name of the library,
+as a hexadecimal sequence of ASCII characters. @var{textaddr} is the
+load address for the text segment of the library. @var{dataaddr} is
+the load address for the data segment of the library, if necessary.
+If only @var{textaddr} is provided, the data segment will be relocated
+by the same amount as the text segment.
+
+Other @samp{Key=Value} pairs may be added later to describe target
+specific data.
+
+@item l
+Marks the end of the list of DLLs. No further @samp{qsDllInfo} packets
+will be sent.
+
+@item m @var{library}; @var{library}@dots{} @r{[}; l@r{[}
+Multiple items may be combined into a single reply packet, if they
+fit. Each @var{library} is a comma-separated list as describe above.
+If the packet ends with @samp{;l} then no further @samp{qsDllInfo}
+packet will be sent.
+@end table
--
Daniel Jacobowitz
CodeSourcery
2007-05-09 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (ALLDEPFILES): Add solib-target.o.
(solib-target.o): New rule.
* infrun.c (handle_inferior_event): Update TARGET_WAITKIND_LOADED
support.
* remote.c (PACKET_qfDllInfo): New constant.
(parse_load_response, remote_get_shared_libraries): New.
(remote_protocol_features): Add qfDllInfo.
(remote_wait, remote_async_wait): Recognize DLL stop replies.
(init_remote_ops): Register remote_get_shared_libraries.
(init_remote_async_ops): Likewise. Fix typo.
(_initialize_remote): Register "set remote dll-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.
* solib.h (solib_add_library, solib_remove_library): New prototypes.
* solist.h (struct so_list): Replace textsection with addr_low and
addr_high.
(struct target_so_ops): Add add_one_solib and remove_one_solib.
* target.c (update_current_target): Add comment about
to_get_shared_libraries.
(target_get_shared_libraries): New.
* target.h (struct target_ops): Add to_get_shared_libraries.
(target_get_shared_libraries): New prototype.
* NEWS: Describe new qfDllInfo and shared library event support.
* gdb.texinfo (Remote Configuration): Document dll-info-packet.
(Stop Reply Packets): Document load, unload, and dll events.
(General Query Packets): Document qfDllInfo and qsDllInfo.
Mention qfDllInfo response to qSupporteed.
---
gdb/Makefile.in | 3
gdb/NEWS | 13 ++
gdb/doc/gdb.texinfo | 95 +++++++++++++++
gdb/infrun.c | 52 +++++++-
gdb/remote.c | 286 +++++++++++++++++++++++++++++++++++++++++++++-
gdb/solib-som.c | 3
gdb/solib-target.c | 323 ++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/solib.c | 39 +++++-
gdb/solib.h | 9 +
gdb/solist.h | 12 +
gdb/target.c | 24 +++
gdb/target.h | 7 +
12 files changed, 846 insertions(+), 20 deletions(-)
Index: gdb/Makefile.in
===================================================================
--- gdb/Makefile.in.orig 2007-05-09 13:27:00.000000000 -0400
+++ gdb/Makefile.in 2007-05-09 15:45:10.000000000 -0400
@@ -1471,6 +1471,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 +2597,8 @@ solib-svr4.o: solib-svr4.c $(defs_h) $(e
$(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) $(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) $(gdb_string_h) $(gregset_h)
Index: gdb/infrun.c
===================================================================
--- gdb/infrun.c.orig 2007-05-09 13:27:00.000000000 -0400
+++ gdb/infrun.c 2007-05-09 13:27:15.000000000 -0400
@@ -1311,13 +1311,16 @@ handle_inferior_event (struct execution_
/* Ignore gracefully during startup of the inferior, as it
might be the shell which has just loaded some objects,
otherwise add the symbols for the newly loaded objects. */
-#ifdef SOLIB_ADD
if (stop_soon == NO_STOP_QUIETLY)
{
+ int breakpoints_were_inserted;
+
/* Remove breakpoints, SOLIB_ADD might adjust
breakpoint addresses via breakpoint_re_set. */
+ breakpoints_were_inserted = breakpoints_inserted;
if (breakpoints_inserted)
remove_breakpoints ();
+ breakpoints_inserted = 0;
/* Check for any newly added shared libraries if we're
supposed to be adding them automatically. Switch
@@ -1339,17 +1342,52 @@ handle_inferior_event (struct execution_
exec/process stratum, instead relying on the target stack
to propagate relevant changes (stop, section table
changed, ...) up to other layers. */
+#ifdef SOLIB_ADD
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
+#else
+ solib_add (NULL, 0, ¤t_target, auto_solib_add);
+#endif
target_terminal_inferior ();
+ /* Try to reenable shared library breakpoints, additional
+ code segments in shared libraries might be mapped in now. */
+ re_enable_breakpoints_in_shlibs ();
+
+ /* If requested, stop when the dynamic linker notifies
+ gdb of events. This allows the user to get control
+ and place breakpoints in initializer routines for
+ dynamically loaded objects (among other things). */
+ if (stop_on_solib_events)
+ {
+ stop_stepping (ecs);
+ return;
+ }
+
+ /* NOTE drow/2006-03-14: This might be a good place to check
+ for "catch load". */
+
/* Reinsert breakpoints and continue. */
- if (breakpoints_inserted)
- insert_breakpoints ();
+ if (breakpoints_were_inserted)
+ {
+ insert_breakpoints ();
+ breakpoints_inserted = 1;
+ }
}
-#endif
- resume (0, TARGET_SIGNAL_0);
- prepare_to_wait (ecs);
- return;
+
+ /* NOTE drow/2006-03-28: For the reason described before the
+ previous if statement, GDB used to automatically resume
+ here. But that's only true if a shell is running; if
+ we've just attached to a process, then that's a whole
+ different case - it might have been stopped at a load
+ event. */
+ if (inferior_ignoring_startup_exec_events || stop_soon == NO_STOP_QUIETLY)
+ {
+ resume (0, TARGET_SIGNAL_0);
+ prepare_to_wait (ecs);
+ return;
+ }
+ else
+ break;
case TARGET_WAITKIND_SPURIOUS:
if (debug_infrun)
Index: gdb/remote.c
===================================================================
--- gdb/remote.c.orig 2007-05-09 13:27:04.000000000 -0400
+++ gdb/remote.c 2007-05-09 15:46:17.000000000 -0400
@@ -899,6 +899,7 @@ enum {
PACKET_Z2,
PACKET_Z3,
PACKET_Z4,
+ PACKET_qfDllInfo,
PACKET_qXfer_auxv,
PACKET_qXfer_features,
PACKET_qXfer_memory_map,
@@ -2150,6 +2151,148 @@ get_offsets (void)
objfile_relocate (symfile_objfile, offs);
}
+/* Parse a load or unload message for a DLL. Loads are required to
+ have all fields, unloads must have at least one. P is not
+ necessarily NUL terminated, but it is always either NUL or semicolon
+ terminated (i.e. *P_END is either NUL or a semicolon) and the containing
+ string is NUL terminated. */
+
+int
+parse_load_response (const char *p, const char *p_end, int is_load)
+{
+ const char *name_start;
+ char *name;
+ CORE_ADDR segments[2];
+ int i, num_segments = 0;
+
+ name = NULL;
+
+ if (p < p_end && strncmp (p, "Name=", 5) == 0)
+ {
+ p += 5;
+
+ name_start = p;
+ while (p < p_end && *p != ',')
+ p++;
+
+ if ((p - name_start) % 2 != 0)
+ return -1;
+
+ name = alloca ((p - name_start) / 2 + 1);
+ i = hex2bin (name_start, name, (p - name_start) / 2);
+ name[i] = '\0';
+
+ if (p < p_end)
+ p++;
+ }
+ else if (is_load)
+ return -1;
+
+ if (p < p_end && strncmp (p, "TextSeg=", 8) == 0)
+ {
+ p += 8;
+
+ segments[0] = 0;
+ while (p < p_end && *p != ',')
+ segments[0] = (segments[0] << 4) + fromhex (*p++);
+ num_segments++;
+
+ if (p < p_end)
+ p++;
+ }
+ else if (is_load)
+ return -1;
+
+ if (p < p_end && strncmp (p, "DataSeg=", 8) == 0)
+ {
+ p += 8;
+
+ if (num_segments == 0)
+ return -1;
+
+ segments[1] = 0;
+ while (p < p_end && *p != ',')
+ segments[1] = (segments[1] << 4) + fromhex (*p++);
+ num_segments++;
+
+ if (p < p_end)
+ p++;
+ }
+
+ if (is_load)
+ solib_add_library (name, num_segments, segments);
+ else
+ {
+ if (num_segments == 0 && name == NULL)
+ return -1;
+
+ solib_remove_library (name, num_segments, segments);
+ }
+
+ return 0;
+}
+
+/* Query the remote side for loaded solibs. */
+
+static void
+remote_get_shared_libraries (struct target_ops *ops)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ /* If qfDllInfo is not available, nothing to do. */
+ if (remote_protocol_packets[PACKET_qfDllInfo].support == PACKET_DISABLE)
+ return;
+
+ putpkt ("qfDllInfo");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_qfDllInfo]) == PACKET_ERROR)
+ {
+ warning (_("Remote failure reply: %s"), rs->buf);
+ return;
+ }
+ else if (remote_protocol_packets[PACKET_qfDllInfo].support == PACKET_DISABLE)
+ /* It wasn't disabled before, but it is now. */
+ return;
+
+ while (rs->buf[0] == 'm')
+ {
+ char *p = rs->buf + 1;
+
+ while (1)
+ {
+ char *p_end = p;
+
+ /* If the packet ends with ";l", we are finished. */
+ if (p[0] == 'l' && p[1] == '\0')
+ return;
+
+ while (*p_end && *p_end != ';')
+ p_end++;
+
+ if (parse_load_response (p, p_end, 1) != 0)
+ {
+ warning (_("Malformed response to DLL query, %s"), rs->buf);
+ return;
+ }
+
+ if (*p_end == ';')
+ p = p_end + 1;
+ else
+ break;
+ }
+
+ putpkt ("qsDllInfo");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ }
+
+ if (strcmp (rs->buf, "l") != 0)
+ warning (_("Malformed response to DLL query, %s"), rs->buf);
+
+ /* We don't need to call solib_add here, because we're being called from
+ ->current_sos (). */
+}
+
/* Stub for catch_exception. */
static void
@@ -2366,6 +2509,8 @@ remote_packet_size (const struct protoco
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
+ { "qfDllInfo", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qfDllInfo },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_auxv },
{ "qXfer:features:read", PACKET_DISABLE, remote_supported_packet,
@@ -3167,6 +3312,7 @@ remote_wait (ptid_t ptid, struct target_
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;
@@ -3222,7 +3368,8 @@ remote_wait (ptid_t ptid, struct target_
/* 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
+ && strncmp (p, "dll", strlen("dll")) != 0)
{
/* Read the ``P'' register number. */
pnum = strtol (p, &p_temp, 16);
@@ -3252,6 +3399,60 @@ Packet: '%s'\n"),
p = unpack_varlen_hex (++p1, &addr);
remote_watch_data_address = (CORE_ADDR)addr;
}
+ else if (strncmp (p, "load", p1 - p) == 0)
+ {
+ p1++;
+ p_temp = p1;
+ while (*p_temp && *p_temp != ';')
+ p_temp++;
+
+ if (p_temp - p1 > 4
+ && strncmp (p_temp - 4, ",nop", 4) == 0)
+ {
+ /* For now, ignore no-op unload events. Later,
+ maybe report them? */
+ }
+ else
+ {
+ parse_load_response (p1, p_temp, 1);
+
+ solibs_changed = 1;
+ }
+
+ p = p_temp;
+ }
+ else if (strncmp (p, "unload", p1 - p) == 0)
+ {
+ p1++;
+ p_temp = p1;
+ while (*p_temp && *p_temp != ';')
+ p_temp++;
+
+ if (p_temp - p1 > 4
+ && strncmp (p_temp - 4, ",nop", 4) == 0)
+ {
+ /* For now, ignore no-op unload events. Later,
+ maybe report them? */
+ }
+ else
+ {
+ parse_load_response (p1, p_temp, 0);
+
+ solibs_changed = 1;
+ }
+
+ p = p_temp;
+ }
+ else if (strncmp (p, "dll", 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. */
@@ -3343,6 +3544,15 @@ Packet: '%s'\n"),
}
}
got_status:
+ if (solibs_changed == -1)
+ {
+ no_shared_libraries (NULL, 0);
+ remote_get_shared_libraries (NULL);
+ }
+
+ if (solibs_changed != 0)
+ status->kind = TARGET_WAITKIND_LOADED;
+
if (thread_num != -1)
{
return pid_to_ptid (thread_num);
@@ -3358,6 +3568,7 @@ remote_async_wait (ptid_t ptid, struct t
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;
@@ -3419,7 +3630,8 @@ remote_async_wait (ptid_t ptid, struct t
/* 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
+ && strncmp (p, "dll", strlen("dll")) != 0)
{
/* Read the register number. */
pnum = strtol (p, &p_temp, 16);
@@ -3449,6 +3661,60 @@ Packet: '%s'\n"),
p = unpack_varlen_hex (++p1, &addr);
remote_watch_data_address = (CORE_ADDR)addr;
}
+ else if (strncmp (p, "load", p1 - p) == 0)
+ {
+ p1++;
+ p_temp = p1;
+ while (*p_temp && *p_temp != ';')
+ p_temp++;
+
+ if (p_temp - p1 > 4
+ && strncmp (p_temp - 4, ",nop", 4) == 0)
+ {
+ /* For now, ignore no-op unload events. Later,
+ maybe report them? */
+ }
+ else
+ {
+ parse_load_response (p1, p_temp, 1);
+
+ solibs_changed = 1;
+ }
+
+ p = p_temp;
+ }
+ else if (strncmp (p, "unload", p1 - p) == 0)
+ {
+ p1++;
+ p_temp = p1;
+ while (*p_temp && *p_temp != ';')
+ p_temp++;
+
+ if (p_temp - p1 > 4
+ && strncmp (p_temp - 4, ",nop", 4) == 0)
+ {
+ /* For now, ignore no-op unload events. Later,
+ maybe report them? */
+ }
+ else
+ {
+ parse_load_response (p1, p_temp, 0);
+
+ solibs_changed = 1;
+ }
+
+ p = p_temp;
+ }
+ else if (strncmp (p, "dll", 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. */
@@ -3542,6 +3808,15 @@ Packet: '%s'\n"),
}
}
got_status:
+ if (solibs_changed == -1)
+ {
+ no_shared_libraries (NULL, 0);
+ remote_get_shared_libraries (NULL);
+ }
+
+ if (solibs_changed != 0)
+ status->kind = TARGET_WAITKIND_LOADED;
+
if (thread_num != -1)
{
return pid_to_ptid (thread_num);
@@ -6224,6 +6499,7 @@ Specify the serial device it is connecte
remote_ops.to_flash_erase = remote_flash_erase;
remote_ops.to_flash_done = remote_flash_done;
remote_ops.to_read_description = remote_read_description;
+ remote_ops.to_get_shared_libraries = remote_get_shared_libraries;
}
/* Set up the extended remote vector by making a copy of the standard
@@ -6356,7 +6632,8 @@ Specify the serial device it is connecte
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;
+ remote_async_ops.to_get_shared_libraries = remote_get_shared_libraries;
}
/* Set up the async extended remote vector by making a copy of the standard
@@ -6625,6 +6902,9 @@ Show the maximum size of the address (in
add_packet_config_cmd (&remote_protocol_packets[PACKET_qSupported],
"qSupported", "supported-packets", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qfDllInfo],
+ "qfDllInfo", "dll-info", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
Index: gdb/solib-som.c
===================================================================
--- gdb/solib-som.c.orig 2007-05-09 13:27:00.000000000 -0400
+++ gdb/solib-som.c 2007-05-09 13:27:15.000000000 -0400
@@ -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;
Index: gdb/solib-target.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/solib-target.c 2007-05-09 13:27:15.000000000 -0400
@@ -0,0 +1,323 @@
+/* Definitions for targets which report shared library events.
+
+ Copyright (C) 2006
+ 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 "gdb_string.h"
+
+struct lm_info
+{
+ struct section_offsets *offsets;
+ int num_bases;
+ CORE_ADDR *segment_bases;
+};
+
+static struct so_list *solib_start;
+static int solibs_fetched;
+
+static struct so_list *
+solib_target_current_sos (void)
+{
+ struct so_list *sop;
+ struct so_list *start = NULL;
+ struct so_list *last = NULL;
+
+ /* If we have not asked the target for the list of shared libraries
+ yet, do it now. */
+ if (!solibs_fetched)
+ {
+ solibs_fetched = 1;
+ target_get_shared_libraries ();
+ }
+
+ for (sop = solib_start; sop; sop = sop->next)
+ {
+ struct so_list *new;
+
+ /* Duplicate the recorded solib. */
+ new = XZALLOC (struct so_list);
+ strcpy (new->so_name, sop->so_name);
+ strcpy (new->so_original_name, sop->so_original_name);
+ new->lm_info = XZALLOC (struct lm_info);
+ if (sop->lm_info->num_bases > 0)
+ {
+ new->lm_info->num_bases = sop->lm_info->num_bases;
+ new->lm_info->segment_bases
+ = xmalloc (sizeof (CORE_ADDR) * new->lm_info->num_bases);
+ memcpy (new->lm_info->segment_bases, sop->lm_info->segment_bases,
+ sizeof (CORE_ADDR) * new->lm_info->num_bases);
+ }
+
+ /* Add it to the list. */
+ if (!start)
+ last = start = new;
+ else
+ {
+ last->next = new;
+ last = new;
+ }
+ }
+
+ 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)
+{
+ struct so_list *sop, *next;
+
+ for (sop = solib_start; sop; sop = next)
+ {
+ next = sop->next;
+
+ free_so (sop);
+ }
+
+ solib_start = NULL;
+ solibs_fetched = 0;
+}
+
+static void
+solib_target_free_so (struct so_list *so)
+{
+ xfree (so->lm_info->offsets);
+ xfree (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;
+
+ 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;
+
+ if (!symfile_map_offsets_to_segments (so->abfd, data,
+ so->lm_info->offsets,
+ so->lm_info->num_bases,
+ so->lm_info->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 (so->lm_info->num_bases > 0);
+ orig_delta = so->lm_info->segment_bases[0] - data->segment_bases[0];
+
+ for (i = 1; i < data->num_segments; i++)
+ {
+ ULONGEST delta;
+
+ /* If we have run out of offsets, assume all remaining segments
+ have the same offset. */
+ if (i >= so->lm_info->num_bases)
+ continue;
+
+ /* If this segment does not have the same offset, do not include
+ it in the library's range. */
+ delta = so->lm_info->segment_bases[i] - data->segment_bases[i];
+ if (delta != orig_delta)
+ break;
+ }
+
+ so->addr_low = so->lm_info->segment_bases[0];
+ so->addr_high = (data->segment_bases[i - 1]
+ + data->segment_sizes[i - 1]);
+
+ 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)
+{
+ /* DLL targets generally have only import stubs (which GDB treats as
+ "PLT entries"), and no runtime binding code. */
+ return in_plt_section (pc, NULL);
+}
+
+static void
+solib_target_add_one_solib (char *soname, int num_bases,
+ CORE_ADDR *segment_bases)
+{
+ struct so_list *new_solib, *so;
+
+ /* We should already have queried the target for shared libraries
+ before this point. If we haven't, we may have just connected;
+ we'll be querying shortly. */
+ if (!solibs_fetched)
+ return;
+
+ /* Check for duplicates already on the list. This can happen, for
+ instance, if we are stopped at a DLL load event when we first
+ connect to a remote target: the DLL will already be in the
+ queried list, but also be reported by the initial wait. */
+ for (so = solib_start; so; so = so->next)
+ if (strcmp (so->so_name, soname) == 0
+ && so->lm_info->num_bases == num_bases
+ && memcmp (so->lm_info->segment_bases, segment_bases,
+ sizeof (CORE_ADDR) * num_bases) == 0)
+ return;
+
+ new_solib = XZALLOC (struct so_list);
+ strncpy (new_solib->so_name, soname, SO_NAME_MAX_PATH_SIZE - 1);
+ new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ strncpy (new_solib->so_original_name, soname, SO_NAME_MAX_PATH_SIZE - 1);
+ new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+
+ new_solib->lm_info = XZALLOC (struct lm_info);
+ new_solib->lm_info->num_bases = num_bases;
+ new_solib->lm_info->segment_bases
+ = xmalloc (sizeof (CORE_ADDR) * num_bases);
+ memcpy (new_solib->lm_info->segment_bases, segment_bases,
+ sizeof (CORE_ADDR) * num_bases);
+
+ if (solib_start == NULL)
+ solib_start = new_solib;
+ else
+ {
+ so = solib_start;
+ while (so->next)
+ so = so->next;
+ so->next = new_solib;
+ }
+
+ /* We do not trigger symbol reading here; the target will do it,
+ after all load events have been processed. */
+}
+
+static void
+solib_target_remove_one_solib (char *soname, int num_bases,
+ CORE_ADDR *segment_bases)
+{
+ struct so_list **slot, *removed;
+
+ /* We should already have queried the target for shared libraries
+ before this point. If we haven't, we may have just connected;
+ we'll be querying shortly. */
+ if (!solibs_fetched)
+ return;
+
+ for (slot = &solib_start; *slot != NULL; slot = &(*slot)->next)
+ {
+ int i;
+
+ if (soname != NULL && strcmp (soname, (*slot)->so_name) != 0)
+ continue;
+
+ if (num_bases != (*slot)->lm_info->num_bases)
+ continue;
+
+ for (i = 0; i < num_bases; i++)
+ if (segment_bases[i] != (*slot)->lm_info->segment_bases[i])
+ break;
+ if (i < num_bases)
+ continue;
+
+ /* Got a match. */
+ break;
+ }
+
+ if (*slot == NULL)
+ return;
+
+ removed = *slot;
+ *slot = removed->next;
+
+ free_so (removed);
+
+ /* We do not trigger symbol unloading here; the target will do it,
+ after all unload events have been processed. */
+}
+
+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;
+ solib_target_so_ops.add_one_solib = solib_target_add_one_solib;
+ solib_target_so_ops.remove_one_solib = solib_target_remove_one_solib;
+
+ current_target_so_ops = &solib_target_so_ops;
+}
Index: gdb/solib.c
===================================================================
--- gdb/solib.c.orig 2007-05-09 13:27:00.000000000 -0400
+++ gdb/solib.c 2007-05-09 13:27:15.000000000 -0400
@@ -306,9 +306,14 @@ 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 DLL, 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;
}
}
@@ -732,15 +737,15 @@ info_sharedlibrary_command (char *ignore
}
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");
@@ -888,6 +893,28 @@ in_solib_dynsym_resolve_code (CORE_ADDR
return ops->in_dynsym_resolve_code (pc);
}
+/* Add a reported shared library to the list. */
+
+void
+solib_add_library (char *soname, int num_bases, CORE_ADDR *segment_bases)
+{
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
+
+ if (ops->add_one_solib != NULL)
+ ops->add_one_solib (soname, num_bases, segment_bases);
+}
+
+/* Remove a reported shared library from the list. */
+
+void
+solib_remove_library (char *soname, int num_bases, CORE_ADDR *segment_bases)
+{
+ struct target_so_ops *ops = solib_ops (current_gdbarch);
+
+ if (ops->remove_one_solib != NULL)
+ ops->remove_one_solib (soname, num_bases, segment_bases);
+}
+
/*
LOCAL FUNCTION
Index: gdb/solist.h
===================================================================
--- gdb/solist.h.orig 2007-05-09 13:27:00.000000000 -0400
+++ gdb/solist.h 2007-05-09 14:06:57.000000000 -0400
@@ -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
@@ -103,7 +107,11 @@ struct target_so_ops
Convenience function for remote debuggers finding host libs. */
int (*find_and_open_solib) (char *soname,
unsigned o_flags, char **temp_pathname);
-
+
+ void (*add_one_solib) (char *soname, int num_bases,
+ CORE_ADDR *segment_bases);
+ void (*remove_one_solib) (char *soname, int num_bases,
+ CORE_ADDR *segment_bases);
};
/* Free the memory associated with a (so_list *). */
Index: gdb/target.c
===================================================================
--- gdb/target.c.orig 2007-05-09 13:27:00.000000000 -0400
+++ gdb/target.c 2007-05-09 13:27:15.000000000 -0400
@@ -467,10 +467,11 @@ update_current_target (void)
INHERIT (to_make_corefile_notes, t);
INHERIT (to_get_thread_local_address, t);
/* Do not inherit to_read_description. */
- INHERIT (to_magic, t);
/* Do not inherit to_memory_map. */
/* Do not inherit to_flash_erase. */
/* Do not inherit to_flash_done. */
+ /* Do not inherit to_get_shared_libraries. */
+ INHERIT (to_magic, t);
}
#undef INHERIT
@@ -1719,6 +1720,27 @@ target_read_description (struct target_o
}
/* Look through the list of possible targets for a target that can
+ fetch shared libraries. */
+
+void
+target_get_shared_libraries (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ {
+ if (t->to_get_shared_libraries != NULL)
+ {
+ t->to_get_shared_libraries (t);
+ break;
+ }
+ }
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_get_shared_libraries ()\n");
+}
+
+/* Look through the list of possible targets for a target that can
execute a run or attach command without any other data. This is
used to locate the default process stratum.
Index: gdb/target.h
===================================================================
--- gdb/target.h.orig 2007-05-09 13:27:00.000000000 -0400
+++ gdb/target.h 2007-05-09 13:27:15.000000000 -0400
@@ -501,6 +501,9 @@ struct target_ops
was available. */
const struct target_desc *(*to_read_description) (struct target_ops *ops);
+ /* Refresh the list of shared libraries. */
+ void (*to_get_shared_libraries) (struct target_ops *ops);
+
int to_magic;
/* Need sub-structure for target machine related rather than comm related?
*/
@@ -1153,6 +1156,10 @@ extern int target_stopped_data_address_p
extern const struct target_desc *target_read_description (struct target_ops *);
+/* Refresh the list of shared libraries from the target. */
+
+extern void target_get_shared_libraries (void);
+
/* Routines for maintenance of the target structures...
add_target: Add a target to the list of all possible targets.
Index: gdb/NEWS
===================================================================
--- gdb/NEWS.orig 2007-05-09 13:54:51.000000000 -0400
+++ gdb/NEWS 2007-05-09 13:55:03.000000000 -0400
@@ -35,6 +35,12 @@ has been rewritten to use the standard G
layout. It also supports a TextSeg= and DataSeg= response when only
segment base addresses (rather than offsets) are available.
+* The GDB remote protocol "T" stop reply packet now supports "dll",
+"load", and "unload" pairs. Combined with the qfDllInfo and qsDllInfo
+packets, these responses allow 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 mem inaccessible-by-default
@@ -93,6 +99,13 @@ qXfer:features:read:
Read an XML target description from the target, which describes its
features.
+qfDllInfo
+qsDllInfo
+ Report the loaded shared libraries. Combined with new T packet
+ responses, these packets allow 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: gdb/doc/gdb.texinfo
===================================================================
--- gdb/doc/gdb.texinfo.orig 2007-05-09 13:54:54.000000000 -0400
+++ gdb/doc/gdb.texinfo 2007-05-09 15:36:15.000000000 -0400
@@ -12897,6 +12897,10 @@ The available settings are:
@tab @code{Z4}
@tab @code{awatch}
+@item @code{dll-info-packet}
+@tab @code{qfDllInfo}
+@tab @code{info sharedlibrary}
+
@item @code{get-thread-local-storage-address-packet}
@tab @code{qGetTLSAddr}
@tab Displaying @code{__thread} variables
@@ -23221,13 +23225,42 @@ If @var{n} is a hexadecimal number, it i
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.
+hex. @var{aa} should be @samp{05}, the trap signal.
+
+@item
+If @var{n} is @samp{load}, then the packet indicates a DLL load event,
+and @var{r} describes the newly loaded library. The library format is
+the same used in @samp{qfDllInfo} replies (@pxref{qfDllInfo}), e.g.@:
+@samp{load:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry may
+end in @samp{,nop} if this library was already mapped, e.g.@: by an
+earlier call to @code{LoadLibrary}. @var{aa} should be @samp{05}, the
+trap signal.
+
+@item
+If @var{n} is @samp{unload}, then the packet indicates a DLL unload
+event, and @var{r} describes the unloaded library. @var{r} is a list
+of comma-separated @samp{Key=Value} pairs, similar to a
+@samp{qfDllInfo} reply. The name, the segment offsets, or both may be
+used to specify which DLL to unload, e.g.@:
+@samp{unload:Name=@var{hexname}} or
+@samp{unload:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry
+may end in @samp{,nop} if this library is still mapped, e.g.@: by
+another open handle. @var{aa} should be @samp{05}, the trap signal.
+
+@item
+If @var{n} is @samp{dll}, then the packet indicates that the loaded
+DLLs have changed. @value{GDBN} should use @samp{qfDllInfo} to fetch
+a new list of loaded libraries. @var{r} is ignored. @var{aa} should
+be @samp{05}, the trap signal.
+
@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
@@ -23341,6 +23374,57 @@ An error (such as memory fault)
The specified memory region's checksum is @var{crc32}.
@end table
+@item qfDllInfo
+@itemx qsDllInfo
+@anchor{qfDllInfo}
+@cindex list loaded DLLs, remote request
+@cindex @samp{qfDllInfo} packet
+@cindex @samp{qsDllInfo} packet
+Obtain a list of all loaded DLLs (dynamic link libraries) from the
+target.
+
+Since there may be too many DLLs to fit into one reply packet, this
+query works iteratively: it may require more than one query/reply
+sequence to obtain the entire list. The first query of the sequence
+will be the @samp{qfDllInfo} query; subsequent queries in the
+sequence will be the @samp{qsDllInfo} query.
+
+In response to each query, the target will reply with a list of one or
+more libraries. @value{GDBN} will respond to each reply with a
+request for more libraries (using the @samp{qs} form of the query),
+until the target responds with @samp{l} (lower-case el, for
+@dfn{last}).
+
+If any stopped threads had pending DLL events not yet reported to GDB
+in a @samp{T} stop reply (@pxref{Stop Reply Packets}), then either the
+effects of those events should not be included in the result of the
+@samp{qfDllInfo} or the queued events should be discarded before they
+are reported to @value{GDBN}.
+
+Reply:
+@table @samp
+@item m Name=@var{hexname},TextSeg=@var{textaddr}@r{[},DataSeg=@var{dataaddr}@r{]}
+A single loaded library. @var{hexname} is the name of the library,
+as a hexadecimal sequence of ASCII characters. @var{textaddr} is the
+load address for the text segment of the library. @var{dataaddr} is
+the load address for the data segment of the library, if necessary.
+If only @var{textaddr} is provided, the data segment will be relocated
+by the same amount as the text segment.
+
+Other @samp{Key=Value} pairs may be added later to describe target
+specific data.
+
+@item l
+Marks the end of the list of DLLs. No further @samp{qsDllInfo} packets
+will be sent.
+
+@item m @var{library}; @var{library}@dots{} @r{[}; l@r{[}
+Multiple items may be combined into a single reply packet, if they
+fit. Each @var{library} is a comma-separated list as describe above.
+If the packet ends with @samp{;l} then no further @samp{qsDllInfo}
+packet will be sent.
+@end table
+
@item qfThreadInfo
@itemx qsThreadInfo
@cindex list active threads, remote request
@@ -23631,6 +23715,11 @@ These are the currently defined stub fea
@tab @samp{-}
@tab No
+@item @samp{qfDllInfo}
+@tab No
+@tab @samp{-}
+@tab Yes
+
@item @samp{qXfer:auxv:read}
@tab No
@tab @samp{-}
@@ -23667,6 +23756,10 @@ stores packets in a NUL-terminated forma
byte in its buffer for the NUL. If this stub feature is not supported,
@value{GDBN} guesses based on the size of the @samp{g} packet response.
+@item qfDllInfo
+The remote stub understands the @samp{qfDllInfo} and @samp{qsDllInfo}
+packets (@pxref{qfDllInfo}).
+
@item qXfer:auxv:read
The remote stub understands the @samp{qXfer:auxv:read} packet
(@pxref{qXfer auxiliary vector read}).
Index: gdb/solib.h
===================================================================
--- gdb/solib.h.orig 2007-01-09 13:11:17.000000000 -0500
+++ gdb/solib.h 2007-05-09 14:06:57.000000000 -0400
@@ -53,6 +53,15 @@ extern char *solib_address (CORE_ADDR);
extern int in_solib_dynsym_resolve_code (CORE_ADDR);
+/* Add a reported shared library to the list. */
+
+void solib_add_library (char *soname, int num_bases, CORE_ADDR *segment_bases);
+
+/* Remove a reported shared library from the list. */
+
+void solib_remove_library (char *soname, int num_bases,
+ CORE_ADDR *segment_bases);
+
/* Discard symbols that were auto-loaded from shared libraries. */
extern void no_shared_libraries (char *ignored, int from_tty);
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-09 20:16 [rfc / remote protocol] Remote shared library events Daniel Jacobowitz
@ 2007-05-10 3:18 ` Eli Zaretskii
2007-05-11 17:24 ` Daniel Jacobowitz
2007-05-10 21:35 ` Mark Kettenis
` (3 subsequent siblings)
4 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2007-05-10 3:18 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches, gdb
> Date: Wed, 9 May 2007 16:16:27 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: gdb@sourceware.org
>
> Eli, do the manual changes look OK?
Yes, but see a few comments below.
> +* The GDB remote protocol "T" stop reply packet now supports "dll",
> +"load", and "unload" pairs. Combined with the qfDllInfo and qsDllInfo
qfDllInfo and qsDllInfo are new, so please say that (as you do below
for T).
> +@item
> +If @var{n} is @samp{load}, then the packet indicates a DLL load event,
> +and @var{r} describes the newly loaded library. The library format is
> +the same used in @samp{qfDllInfo} replies (@pxref{qfDllInfo}), e.g.@:
> +@samp{load:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry may
> +end in @samp{,nop} if this library was already mapped, e.g.@: by an
> +earlier call to @code{LoadLibrary}. @var{aa} should be @samp{05}, the
> +trap signal.
I think we need to explain what is ``hexname'' here, unless it is
already used and explained in the preceding portion of this section.
Also, should we have some index entries here?
> +until the target responds with @samp{l} (lower-case el, for
^^
I believe the letter's name is ``ell''.
> +Reply:
> +@table @samp
> +@item m Name=@var{hexname},TextSeg=@var{textaddr}@r{[},DataSeg=@var{dataaddr}@r{]}
Does this long line look good in print?
> +@item m @var{library}; @var{library}@dots{} @r{[}; l@r{[}
Did you really mean two left [ brackets here?
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-09 20:16 [rfc / remote protocol] Remote shared library events Daniel Jacobowitz
2007-05-10 3:18 ` Eli Zaretskii
@ 2007-05-10 21:35 ` Mark Kettenis
2007-05-11 3:35 ` Daniel Jacobowitz
2007-05-15 13:28 ` Daniel Jacobowitz
2007-05-11 18:02 ` Kevin Buettner
` (2 subsequent siblings)
4 siblings, 2 replies; 17+ messages in thread
From: Mark Kettenis @ 2007-05-10 21:35 UTC (permalink / raw)
To: drow; +Cc: gdb-patches
> Date: Wed, 9 May 2007 16:16:27 -0400
> From: Daniel Jacobowitz <drow@false.org>
>
> Not all platforms work this way. The exceptions I'm looking at
> recently are DLL-based platforms: Windows and SymbianOS. Both use an
> OS-level loader instead. You have to query the OS to get the list
> of libraries, and the OS provides event notification directly instead
> of via a magic breakpoint. We can't poke and prod at the OS directly
> during remote debugging, so to implement DLL support for these
> platforms I extended the remote protocol.
Can we please avoid the term DLL for this stuff? That's just a
particular implementation of shared objects/libraries. This
functionality is generally usable, and not specific to Windows.
> The additions are three new stop replies for the "T" packet to report
> events (load, unload, and dll for "something more complicated than
> just a load or unload") and two new packets (qfDllInfo and qsDllInfo)
> to query the current state. Detailed documentation is below and the
> patch is attached.
>
> This patch introduces a new solib_ops vector in solib-target.c. This
> vector is target driven; it maintains a list based on the query packet
> and event notices, instead of looking through memory.
>
> I have tested this code on SymbianOS, Cygwin, and MinGW32. Pedro
> Alves has tested a slightly earlier version on Windows CE (and wrote
> the gdbserver bits I used to test it on Windows - thanks!).
>
> What do you think, Kevin especially? I'm not entirely thrilled with
> the way this interacts with other solib_ops vectors, but I'm not
> unhappy with it either.
I think this diff needs to be split up. I looked at it twice now, but
I don't see how the bits are related, and the changes to infrun.c make
me very nervous.
Mark
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-10 21:35 ` Mark Kettenis
@ 2007-05-11 3:35 ` Daniel Jacobowitz
2007-05-15 13:28 ` Daniel Jacobowitz
1 sibling, 0 replies; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-05-11 3:35 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On Thu, May 10, 2007 at 11:34:51PM +0200, Mark Kettenis wrote:
> > Date: Wed, 9 May 2007 16:16:27 -0400
> > From: Daniel Jacobowitz <drow@false.org>
> >
> > Not all platforms work this way. The exceptions I'm looking at
> > recently are DLL-based platforms: Windows and SymbianOS. Both use an
> > OS-level loader instead. You have to query the OS to get the list
> > of libraries, and the OS provides event notification directly instead
> > of via a magic breakpoint. We can't poke and prod at the OS directly
> > during remote debugging, so to implement DLL support for these
> > platforms I extended the remote protocol.
>
> Can we please avoid the term DLL for this stuff? That's just a
> particular implementation of shared objects/libraries. This
> functionality is generally usable, and not specific to Windows.
Every platform I've used that needs the OS-provided events called them
DLLs, which was more than just Windows :-) But I've no objection.
I'll rephrase the patch.
I'd rather leave the packet names alone, but if you would rather
change them I can keep the old names in a local patch for now.
> I think this diff needs to be split up. I looked at it twice now, but
> I don't see how the bits are related, and the changes to infrun.c make
> me very nervous.
I can definitely split out the infrun bits; I'll do that tomorrow and
post them with their own explanation. If there's anything else that
you would like split out or clarified, let me know. Better overall
explanation of solib-target coming up too.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-10 3:18 ` Eli Zaretskii
@ 2007-05-11 17:24 ` Daniel Jacobowitz
2007-05-11 17:39 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-05-11 17:24 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On Thu, May 10, 2007 at 06:18:29AM +0300, Eli Zaretskii wrote:
> > +@item
> > +If @var{n} is @samp{load}, then the packet indicates a DLL load event,
> > +and @var{r} describes the newly loaded library. The library format is
> > +the same used in @samp{qfDllInfo} replies (@pxref{qfDllInfo}), e.g.@:
> > +@samp{load:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry may
> > +end in @samp{,nop} if this library was already mapped, e.g.@: by an
> > +earlier call to @code{LoadLibrary}. @var{aa} should be @samp{05}, the
> > +trap signal.
>
> I think we need to explain what is ``hexname'' here, unless it is
> already used and explained in the preceding portion of this section.
It's explained at the target of the @pxref, where TextSeg and textaddr
are also; is that OK?
> Also, should we have some index entries here?
Yep.
> > +until the target responds with @samp{l} (lower-case el, for
> ^^
> I believe the letter's name is ``ell''.
"In reference, it is spelled el or ell." says Wikipedia; I actually
copied this from a few lines further down in the manual. If there's
some reason to change el -> ell let me know and I'll do it consistently.
> > +Reply:
> > +@table @samp
> > +@item m Name=@var{hexname},TextSeg=@var{textaddr}@r{[},DataSeg=@var{dataaddr}@r{]}
>
> Does this long line look good in print?
Yes, it seems to be OK; it's less than half the print area wide in the PDF.
> > +@item m @var{library}; @var{library}@dots{} @r{[}; l@r{[}
>
> Did you really mean two left [ brackets here?
Whoops! I'll have updated documentation in the revised patch, due soon.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-11 17:24 ` Daniel Jacobowitz
@ 2007-05-11 17:39 ` Eli Zaretskii
0 siblings, 0 replies; 17+ messages in thread
From: Eli Zaretskii @ 2007-05-11 17:39 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
> Date: Fri, 11 May 2007 13:24:28 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: gdb-patches@sourceware.org
>
> > I think we need to explain what is ``hexname'' here, unless it is
> > already used and explained in the preceding portion of this section.
>
> It's explained at the target of the @pxref, where TextSeg and textaddr
> are also; is that OK?
Yes.
> > > +until the target responds with @samp{l} (lower-case el, for
> > ^^
> > I believe the letter's name is ``ell''.
>
> "In reference, it is spelled el or ell." says Wikipedia; I actually
> copied this from a few lines further down in the manual. If there's
> some reason to change el -> ell let me know and I'll do it consistently.
I'm just accustomed to ell, but if the manual uses el, let's leave it.
> Whoops! I'll have updated documentation in the revised patch, due soon.
Thanks.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-09 20:16 [rfc / remote protocol] Remote shared library events Daniel Jacobowitz
2007-05-10 3:18 ` Eli Zaretskii
2007-05-10 21:35 ` Mark Kettenis
@ 2007-05-11 18:02 ` Kevin Buettner
2007-05-11 18:21 ` Daniel Jacobowitz
2007-05-11 23:31 ` Pedro Alves
2007-05-16 22:59 ` Jim Blandy
4 siblings, 1 reply; 17+ messages in thread
From: Kevin Buettner @ 2007-05-11 18:02 UTC (permalink / raw)
To: gdb-patches
On Wed, 9 May 2007 16:16:27 -0400
Daniel Jacobowitz <drow@false.org> wrote:
> What do you think, Kevin especially? I'm not entirely thrilled with
> the way this interacts with other solib_ops vectors, but I'm not
> unhappy with it either.
What in particular were you not thrilled with?
I've looked over the solib-specific changes. They look reasonable to
me. I didn't understand the infrun changes. I too would like to see
that put into a different patch.
Kevin
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-11 18:02 ` Kevin Buettner
@ 2007-05-11 18:21 ` Daniel Jacobowitz
0 siblings, 0 replies; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-05-11 18:21 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
On Fri, May 11, 2007 at 11:02:50AM -0700, Kevin Buettner wrote:
> On Wed, 9 May 2007 16:16:27 -0400
> Daniel Jacobowitz <drow@false.org> wrote:
>
> > What do you think, Kevin especially? I'm not entirely thrilled with
> > the way this interacts with other solib_ops vectors, but I'm not
> > unhappy with it either.
>
> What in particular were you not thrilled with?
I had to add two new methods, add_one_library and remove_one_library,
that don't make sense for any of the other things using solib_ops.
I thought for a bit about making this something completely different,
so that you could have both a solib_ops and target-reported libraries;
I think we'll want multiple sorts of libraries someday, but today
I couldn't make it work sensibly.
Also, the in_dynsym_code method is a bit hokey; calling in_plt_section
happens to be right for SymbianOS, but I have a feeling Windows will
want something more (at least, the relevant test is gdb1555.exp, and
it fails on Windows once I add testsuite support to run it there).
I suspect this should be split into a solib_ops specific bit and an
architecture specific bit, or maybe just an architecture specific bit.
Neither of these are big problems, really.
> I've looked over the solib-specific changes. They look reasonable to
> me. I didn't understand the infrun changes. I too would like to see
> that put into a different patch.
Coming right up (well, probably Monday at this point). Test case for
it, too.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-09 20:16 [rfc / remote protocol] Remote shared library events Daniel Jacobowitz
` (2 preceding siblings ...)
2007-05-11 18:02 ` Kevin Buettner
@ 2007-05-11 23:31 ` Pedro Alves
2007-05-16 22:59 ` Jim Blandy
4 siblings, 0 replies; 17+ messages in thread
From: Pedro Alves @ 2007-05-11 23:31 UTC (permalink / raw)
To: gdb-patches
Hi Daniel, all:
First, let me say that I really like this patch. I find
the segment generalization elegant. Makes a lot of sense.
On 5/9/07, Daniel Jacobowitz <drow@false.org> wrote:
> +static void
> +solib_target_remove_one_solib (char *soname, int num_bases,
> + CORE_ADDR *segment_bases)
> +{
> + struct so_list **slot, *removed;
> +
> + /* We should already have queried the target for shared libraries
> + before this point. If we haven't, we may have just connected;
> + we'll be querying shortly. */
> + if (!solibs_fetched)
> + return;
> +
> + for (slot = &solib_start; *slot != NULL; slot = &(*slot)->next)
> + {
> + int i;
> +
> + if (soname != NULL && strcmp (soname, (*slot)->so_name) != 0)
> + continue;
> +
> + if (num_bases != (*slot)->lm_info->num_bases)
> + continue;
> +
> + for (i = 0; i < num_bases; i++)
> + if (segment_bases[i] != (*slot)->lm_info->segment_bases[i])
> + break;
> + if (i < num_bases)
> + continue;
> +
> + /* Got a match. */
> + break;
> + }
> +
> + if (*slot == NULL)
> + return;
This doesn't match what was documented:
"The name, the segment offsets, or both may be used to specify
which DLL to unload"
Specifically, if just the dll name comes along (numbases == 0),
it will fail to find the so.
Also, I see that you've changed the unloading related to the
old version. In that version only one segment was
enough on unload. Is it ever possible to have two sos with
segments loaded at the same address?
While we're on to it, why not drop the "TextSeg", and
"DataSeg" segment names? You are hardcoding text to segment
0 and data to segment 1 on the gdb side
(remote.c:parse_load_response), and as you've already noted,
if some more segments need to be reported, then we'd have
to add name pairs for them. Did you consider having
packets like these instead?:
load:Name=<hex(name)>,Seg_0=<load_addr>,Seg_1=<load_addr>,Seg_2=<load_addr>;
unload:Seg_0=<load_addr>;
... and have parse_load_response handle Seg_nnn generically?
hummm, isn't there the possibility that
'TextSeg == seg[0] && DataSeg == seg[1]' isn't true in some
cases, like when data is loaded before text in memory?
> @@ -103,7 +107,11 @@ struct target_so_ops
> Convenience function for remote debuggers finding host libs. */
> int (*find_and_open_solib) (char *soname,
> unsigned o_flags, char **temp_pathname);
> -
> +
> + void (*add_one_solib) (char *soname, int num_bases,
> + CORE_ADDR *segment_bases);
> + void (*remove_one_solib) (char *soname, int num_bases,
> + CORE_ADDR *segment_bases);
I see this in some places in gdb, and I've been meaning
to ask. I see you're following status quo in that file, but why
aren't these SONAME params in target_so_ops 'const char *' ?
Shouldn't we strive for const correctness?
Not really important for this patch, just curious.
Cheers,
Pedro Alves
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-10 21:35 ` Mark Kettenis
2007-05-11 3:35 ` Daniel Jacobowitz
@ 2007-05-15 13:28 ` Daniel Jacobowitz
2007-05-21 12:00 ` Daniel Jacobowitz
2007-07-02 21:37 ` Daniel Jacobowitz
1 sibling, 2 replies; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-05-15 13:28 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches, Kevin Buettner
On Thu, May 10, 2007 at 11:34:51PM +0200, Mark Kettenis wrote:
> I think this diff needs to be split up. I looked at it twice now, but
> I don't see how the bits are related, and the changes to infrun.c make
> me very nervous.
Here are just the infrun parts. They've gained a test case for the
trickiest part, a cleanup, a better changelog, and an explanation.
First of all, I don't remember why I was testing
inferior_ignoring_startup_exec_events in the last version of this
patch. I discovered that now there are no references to it (there may
have been one when I wrote it). I didn't really need it, so I garbage
collected it.
Secondly, I needed to make TARGET_WAITKIND_LOADED support work with
the current solib.c implementation. You can tell it hasn't been used
in a while since it was conditioned on "#ifdef SOLIB_ADD"; there are
almost no definitions of that left.
Third, while debugging shared library support for SymbianOS I kept
encountering an unpleasant surprise. I would disconnect from the
remote target when it was stopped at a load event (usually because my
GDB crashed :-). When I reconnected, GDB would automatically resume
the program! That's where the ugly stop_soon test was in the last
version of this. For this version, I reviewed every setting and use
of stop_soon and decided that none of them quite matched the case in
stop_remote, so I added a new STOP_QUIETLY_REMOTE (and some comments
about it). This is just like STOP_QUIETLY_NO_SIGSTOP except that it
does not need to hide a SIGSTOP if it finds one. It means we're
connecting to the target for the first time, so we shouldn't decide to
resume it without giving the user a chance to look around.
I hope this version is clearer; what do you think of it?
--
Daniel Jacobowitz
CodeSourcery
2007-05-15 Daniel Jacobowitz <dan@codesourcery.com>
* infrun.c (inferior_ignoring_startup_exec_events): Delete.
(start_remote): Use STOP_QUIETLY_REMOTE.
(handle_inferior_event): Do not condition TARGET_WAITKIND_LOADED
support on a SOLIB_ADD definition. Update breakpoints_inserted.
Update to match shared library event breakpoint support. Only
resume if appropriate. Handle STOP_QUIETLY_REMOTE.
(normal_stop): Handle TARGET_WAITKIND_LOADED.
* fork-child.c (startup_inferior): Do not set
inferior_ignoring_startup_exec_events
* inferior.h (inferior_ignoring_startup_exec_events): Delete
declaration.
(enum stop_kind): Improve documentation. Add STOP_QUIETLY_REMOTE.
* config/gdbserver.exp (gdb_reconnect): New.
* gdb.base/so-disc-shr.c, gdb.base/solib-disc.c,
gdb.base/solib-disc.exp: New files.
* lib/gdb.exp (gdb_test_multiple): Allow tests to match "Ending
remote debugging".
(gdb_compile): Add shlib_load flag.
* lib/gdbserver-support.exp (gdbserver_run): Save the protocol and
port.
(gdbserver_reconnect): New.
---
gdb/fork-child.c | 4 -
gdb/inferior.h | 26 ++------
gdb/infrun.c | 79 ++++++++++++++++++++----
gdb/testsuite/config/gdbserver.exp | 4 +
gdb/testsuite/gdb.base/so-disc-shr.c | 25 +++++++
gdb/testsuite/gdb.base/solib-disc.c | 57 +++++++++++++++++
gdb/testsuite/gdb.base/solib-disc.exp | 104 ++++++++++++++++++++++++++++++++
gdb/testsuite/lib/gdb.exp | 17 ++++-
gdb/testsuite/lib/gdbserver-support.exp | 18 ++++-
9 files changed, 292 insertions(+), 42 deletions(-)
Index: gdb/infrun.c
===================================================================
--- gdb/infrun.c.orig 2007-05-11 09:21:52.000000000 -0400
+++ gdb/infrun.c 2007-05-15 09:10:23.000000000 -0400
@@ -84,7 +84,6 @@ static int prepare_to_proceed (void);
void _initialize_infrun (void);
-int inferior_ignoring_startup_exec_events = 0;
int inferior_ignoring_leading_exec_events = 0;
/* When set, stop the 'step' command if we enter a function which has
@@ -821,7 +820,7 @@ start_remote (int from_tty)
{
init_thread_list ();
init_wait_for_inferior ();
- stop_soon = STOP_QUIETLY;
+ stop_soon = STOP_QUIETLY_REMOTE;
trap_expected = 0;
/* Always go on waiting for the target, regardless of the mode. */
@@ -1308,16 +1307,22 @@ handle_inferior_event (struct execution_
case TARGET_WAITKIND_LOADED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
- /* Ignore gracefully during startup of the inferior, as it
- might be the shell which has just loaded some objects,
- otherwise add the symbols for the newly loaded objects. */
-#ifdef SOLIB_ADD
+ /* Ignore gracefully during startup of the inferior, as it might
+ be the shell which has just loaded some objects, otherwise
+ add the symbols for the newly loaded objects. Also ignore at
+ the beginning of an attach or remote session; we will query
+ the full list of libraries once the connection is
+ established. */
if (stop_soon == NO_STOP_QUIETLY)
{
+ int breakpoints_were_inserted;
+
/* Remove breakpoints, SOLIB_ADD might adjust
breakpoint addresses via breakpoint_re_set. */
+ breakpoints_were_inserted = breakpoints_inserted;
if (breakpoints_inserted)
remove_breakpoints ();
+ breakpoints_inserted = 0;
/* Check for any newly added shared libraries if we're
supposed to be adding them automatically. Switch
@@ -1339,17 +1344,50 @@ handle_inferior_event (struct execution_
exec/process stratum, instead relying on the target stack
to propagate relevant changes (stop, section table
changed, ...) up to other layers. */
+#ifdef SOLIB_ADD
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
+#else
+ solib_add (NULL, 0, ¤t_target, auto_solib_add);
+#endif
target_terminal_inferior ();
+ /* Try to reenable shared library breakpoints, additional
+ code segments in shared libraries might be mapped in now. */
+ re_enable_breakpoints_in_shlibs ();
+
+ /* If requested, stop when the dynamic linker notifies
+ gdb of events. This allows the user to get control
+ and place breakpoints in initializer routines for
+ dynamically loaded objects (among other things). */
+ if (stop_on_solib_events)
+ {
+ stop_stepping (ecs);
+ return;
+ }
+
+ /* NOTE drow/2007-05-11: This might be a good place to check
+ for "catch load". */
+
/* Reinsert breakpoints and continue. */
- if (breakpoints_inserted)
- insert_breakpoints ();
+ if (breakpoints_were_inserted)
+ {
+ insert_breakpoints ();
+ breakpoints_inserted = 1;
+ }
}
-#endif
- resume (0, TARGET_SIGNAL_0);
- prepare_to_wait (ecs);
- return;
+
+ /* If we are skipping through a shell, or through shared library
+ loading that we aren't interested in, resume the program. If
+ we're running the program normally, also resume. But stop if
+ we're attaching or setting up a remote connection. */
+ if (stop_soon == STOP_QUIETLY || stop_soon == NO_STOP_QUIETLY)
+ {
+ resume (0, TARGET_SIGNAL_0);
+ prepare_to_wait (ecs);
+ return;
+ }
+
+ break;
case TARGET_WAITKIND_SPURIOUS:
if (debug_infrun)
@@ -1872,7 +1910,8 @@ handle_inferior_event (struct execution_
&& (stop_signal == TARGET_SIGNAL_ILL
|| stop_signal == TARGET_SIGNAL_SEGV
|| stop_signal == TARGET_SIGNAL_EMT))
- || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP)
+ || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
+ || stop_soon == STOP_QUIETLY_REMOTE)
{
if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
{
@@ -1885,7 +1924,7 @@ handle_inferior_event (struct execution_
/* This is originated from start_remote(), start_inferior() and
shared libraries hook functions. */
- if (stop_soon == STOP_QUIETLY)
+ if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
@@ -3170,6 +3209,18 @@ Further execution is probably impossible
switch (bpstat_ret)
{
case PRINT_UNKNOWN:
+ /* If we had hit a shared library event breakpoint,
+ bpstat_print would print out this message. If we hit
+ an OS-level shared library event, do the same
+ thing. */
+ if (last.kind == TARGET_WAITKIND_LOADED)
+ {
+ printf_filtered (_("Stopped due to shared library event\n"));
+ source_flag = SRC_LINE; /* something bogus */
+ do_frame_printing = 0;
+ break;
+ }
+
/* FIXME: cagney/2002-12-01: Given that a frame ID does
(or should) carry around the function and does (or
should) use that when doing a frame comparison. */
Index: gdb/fork-child.c
===================================================================
--- gdb/fork-child.c.orig 2007-05-11 12:57:25.000000000 -0400
+++ gdb/fork-child.c 2007-05-11 12:57:37.000000000 -0400
@@ -416,10 +416,6 @@ startup_inferior (int ntraps)
init_wait_for_inferior ();
- if (STARTUP_WITH_SHELL)
- inferior_ignoring_startup_exec_events = ntraps;
- else
- inferior_ignoring_startup_exec_events = 0;
inferior_ignoring_leading_exec_events =
target_reported_exec_events_per_exec_call () - 1;
Index: gdb/inferior.h
===================================================================
--- gdb/inferior.h.orig 2007-05-11 12:48:02.000000000 -0400
+++ gdb/inferior.h 2007-05-11 12:57:21.000000000 -0400
@@ -124,20 +124,7 @@ extern int target_executing;
redisplay the prompt until the execution is actually over. */
extern int sync_execution;
-/* This is only valid when inferior_ptid is non-zero.
-
- If this is 0, then exec events should be noticed and responded to
- by the debugger (i.e., be reported to the user).
-
- If this is > 0, then that many subsequent exec events should be
- ignored (i.e., not be reported to the user).
- */
-extern int inferior_ignoring_startup_exec_events;
-
-/* This is only valid when inferior_ignoring_startup_exec_events is
- zero.
-
- Some targets (stupidly) report more than one exec event per actual
+/* Some targets (stupidly) report more than one exec event per actual
call to an event() system call. If only the last such exec event
need actually be noticed and responded to by the debugger (i.e.,
be reported to the user), then this is the number of "leading"
@@ -355,10 +342,12 @@ extern enum step_over_calls_kind step_ov
extern int step_multi;
-/* Nonzero means expecting a trap and caller will handle it
- themselves. It is used when running in the shell before the child
- program has been exec'd; and when running some kinds of remote
- stuff (FIXME?). */
+/* Anything but NO_STOP_QUIETLY means we expect a trap and the caller
+ will handle it themselves. STOP_QUIETLY is used when running in
+ the shell before the child program has been exec'd and when running
+ through shared library loading. STOP_QUIETLY_REMOTE is used when
+ setting up a remote connection; it is like STOP_QUIETLY_NO_SIGSTOP
+ except that there is no need to hide a signal. */
/* It is also used after attach, due to attaching to a process. This
is a bit trickier. When doing an attach, the kernel stops the
@@ -382,6 +371,7 @@ enum stop_kind
{
NO_STOP_QUIETLY = 0,
STOP_QUIETLY,
+ STOP_QUIETLY_REMOTE,
STOP_QUIETLY_NO_SIGSTOP
};
Index: gdb/testsuite/config/gdbserver.exp
===================================================================
--- gdb/testsuite/config/gdbserver.exp.orig 2007-05-15 07:58:34.000000000 -0400
+++ gdb/testsuite/config/gdbserver.exp 2007-05-15 07:58:50.000000000 -0400
@@ -81,3 +81,7 @@ proc gdbserver_gdb_load { } {
proc gdb_reload { } {
return [gdbserver_run ""]
}
+
+proc gdb_reconnect { } {
+ return [gdbserver_reconnect]
+}
Index: gdb/testsuite/gdb.base/so-disc-shr.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.base/so-disc-shr.c 2007-05-15 09:01:21.000000000 -0400
@@ -0,0 +1,25 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2007 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <stdio.h>
+
+void shrfunc (void)
+{
+ printf ("in shrfunc\n");
+}
Index: gdb/testsuite/gdb.base/solib-disc.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.base/solib-disc.c 2007-05-15 09:01:21.000000000 -0400
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2007 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __WIN32__
+#include <windows.h>
+#define dlopen(name, mode) LoadLibrary (name)
+#define dlsym(handle, func) GetProcAddress (handle, func)
+#define dlclose(handle) FreeLibrary (handle)
+#define dlerror() "an error occurred"
+#else
+#include <dlfcn.h>
+#endif
+
+int main()
+{
+ void *handle;
+ void (*func) (void);
+
+ handle = dlopen (SHLIB_NAME, RTLD_LAZY);
+ if (!handle)
+ {
+ fprintf (stderr, dlerror ());
+ exit (1);
+ }
+
+ func = (void (*)(void)) dlsym (handle, "shrfunc");
+ if (!func)
+ {
+ fprintf (stderr, dlerror ());
+ exit (1);
+ }
+
+ func ();
+
+ dlclose (handle);
+
+ return 0;
+}
Index: gdb/testsuite/gdb.base/solib-disc.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.base/solib-disc.exp 2007-05-15 09:01:21.000000000 -0400
@@ -0,0 +1,104 @@
+# Copyright 2007 Free Software Foundation, Inc.
+
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Test connecting and disconnecting at shared library events.
+
+if {[skip_shlib_tests]} {
+ return 0
+}
+
+if { [info proc gdb_reconnect] == "" } {
+ return 0
+}
+
+set testfile solib-disc
+set libfile so-disc-shr
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+set libsrc "${srcdir}/${subdir}/${libfile}.c"
+set libname "${libfile}.so"
+set libobj "${objdir}/${subdir}/${libname}"
+set execsrc "${srcdir}/${subdir}/${srcfile}"
+
+remote_exec build "rm -f ${binfile}"
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+set exec_opts [list debug shlib_load additional_flags=-DSHLIB_NAME\=\"${libname}\"]
+
+if { [gdb_compile_shlib $libsrc $libobj {debug}] != ""
+ || [gdb_compile $execsrc ${binfile} executable $exec_opts] != "" } {
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_load_shlibs $libobj
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+gdb_test "set stop-on-solib-events 1" ""
+
+gdb_test "continue" "Stopped due to shared library event" "continue to load"
+
+set msg "save \$pc after load"
+set saved_pc ""
+gdb_test_multiple "print/x \$pc" $msg {
+ -re "\\\$$decimal = (\[^\r\n\]*)\r\n$gdb_prompt $" {
+ set saved_pc $expect_out(1,string)
+ pass $msg
+ }
+}
+
+gdb_test "disconnect" "Ending remote debugging\\." "disconnect after load"
+if { [gdb_reconnect] == 0 } {
+ pass "reconnect after load"
+} else {
+ fail "reconnect after load"
+ return 0
+}
+
+gdb_test "print/x \$pc" "\\\$$decimal = $saved_pc" "check \$pc after load"
+
+
+gdb_test "continue" "Stopped due to shared library event" "continue to unload"
+
+set msg "save \$pc after unload"
+set saved_pc ""
+gdb_test_multiple "print/x \$pc" $msg {
+ -re "\\\$$decimal = (\[^\r\n\]*)\r\n$gdb_prompt $" {
+ set saved_pc $expect_out(1,string)
+ pass $msg
+ }
+}
+
+gdb_test "disconnect" "Ending remote debugging\\." "disconnect after unload"
+if { [gdb_reconnect] == 0 } {
+ pass "reconnect after unload"
+} else {
+ fail "reconnect after unload"
+ return 0
+}
+
+gdb_test "print/x \$pc" "\\\$$decimal = $saved_pc" "check \$pc after unload"
Index: gdb/testsuite/lib/gdb.exp
===================================================================
--- gdb/testsuite/lib/gdb.exp.orig 2007-05-15 08:18:12.000000000 -0400
+++ gdb/testsuite/lib/gdb.exp 2007-05-15 08:29:30.000000000 -0400
@@ -671,6 +671,9 @@ proc gdb_test_multiple { command message
gdb_suppress_entire_file "GDB died";
set result -1;
}
+ }
+ append code $processed_code
+ append code {
-re "Ending remote debugging.*$gdb_prompt $" {
if ![isnative] then {
warning "Can`t communicate to remote target."
@@ -679,9 +682,6 @@ proc gdb_test_multiple { command message
gdb_start
set result -1
}
- }
- append code $processed_code
- append code {
-re "Undefined\[a-z\]* command:.*$gdb_prompt $" {
perror "Undefined command \"$command\"."
fail "$message"
@@ -1543,6 +1543,17 @@ proc gdb_compile {source dest type optio
lappend options "additional_flags=-rpath ${objdir}/${subdir}"
}
}
+ } elseif { $opt == "shlib_load" } {
+ if { ([istarget "*-*-mingw*"]
+ || [istarget *-*-cygwin*]
+ || [istarget *-*-pe*]
+ || [istarget arm*-*-symbianelf*]
+ || [istarget hppa*-*-hpux*])} {
+ # Do not need anything.
+ } else {
+ lappend new_options "libs=-ldl"
+ lappend new_options "additional_flags=-Wl,-rpath,\\\$ORIGIN"
+ }
} else {
lappend new_options $opt
}
Index: gdb/testsuite/lib/gdbserver-support.exp
===================================================================
--- gdb/testsuite/lib/gdbserver-support.exp.orig 2007-05-15 07:57:23.000000000 -0400
+++ gdb/testsuite/lib/gdbserver-support.exp 2007-05-15 08:16:48.000000000 -0400
@@ -236,9 +236,21 @@ proc gdbserver_spawn { child_args } {
# to it. Return 0 on success, or non-zero on failure.
proc gdbserver_run { child_args } {
+ global gdbserver_protocol
+ global gdbserver_gdbport
+
set res [gdbserver_spawn $child_args]
- set protocol [lindex $res 0]
- set gdbport [lindex $res 1]
+ set gdbserver_protocol [lindex $res 0]
+ set gdbserver_gdbport [lindex $res 1]
+
+ return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
+}
+
+# Reconnect to the previous gdbserver session.
+
+proc gdbserver_reconnect { } {
+ global gdbserver_protocol
+ global gdbserver_gdbport
- return [gdb_target_cmd $protocol $gdbport]
+ return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
}
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-09 20:16 [rfc / remote protocol] Remote shared library events Daniel Jacobowitz
` (3 preceding siblings ...)
2007-05-11 23:31 ` Pedro Alves
@ 2007-05-16 22:59 ` Jim Blandy
2007-05-18 0:27 ` Daniel Jacobowitz
4 siblings, 1 reply; 17+ messages in thread
From: Jim Blandy @ 2007-05-16 22:59 UTC (permalink / raw)
To: gdb-patches; +Cc: gdb
Daniel Jacobowitz <drow@false.org> writes:
> All comments welcome!
>
> +@item
> +If @var{n} is @samp{load}, then the packet indicates a DLL load event,
> +and @var{r} describes the newly loaded library. The library format is
> +the same used in @samp{qfDllInfo} replies (@pxref{qfDllInfo}), e.g.@:
> +@samp{load:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry may
> +end in @samp{,nop} if this library was already mapped, e.g.@: by an
> +earlier call to @code{LoadLibrary}. @var{aa} should be @samp{05}, the
> +trap signal.
> +
> +@item
> +If @var{n} is @samp{unload}, then the packet indicates a DLL unload
> +event, and @var{r} describes the unloaded library. @var{r} is a list
> +of comma-separated @samp{Key=Value} pairs, similar to a
> +@samp{qfDllInfo} reply. The name, the segment offsets, or both may be
> +used to specify which DLL to unload, e.g.@:
> +@samp{unload:Name=@var{hexname}} or
> +@samp{unload:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry
> +may end in @samp{,nop} if this library is still mapped, e.g.@: by
> +another open handle. @var{aa} should be @samp{05}, the trap signal.
> +
> +@item
> +If @var{n} is @samp{dll}, then the packet indicates that the loaded
> +DLLs have changed. @value{GDBN} should use @samp{qfDllInfo} to fetch
> +a new list of loaded libraries. @var{r} is ignored. @var{aa} should
> +be @samp{05}, the trap signal.
It seems odd to me that it's an @var{n} that distinguishes the reason
for the stop; the @var{AA}, the @var{r}, and any other @var{r}:@var{n}
pairs are essentially meaningless. I'd rather see an entirely new
stop reply packet type --- 'L', say --- with subsequent name/value
pairs, like those in a q[fs]DllInfo packet's 'm' response.
> +Reply:
> +@table @samp
> +@item m Name=@var{hexname},TextSeg=@var{textaddr}@r{[},DataSeg=@var{dataaddr}@r{]}
> +A single loaded library. @var{hexname} is the name of the library,
> +as a hexadecimal sequence of ASCII characters. @var{textaddr} is the
> +load address for the text segment of the library. @var{dataaddr} is
> +the load address for the data segment of the library, if necessary.
> +If only @var{textaddr} is provided, the data segment will be relocated
> +by the same amount as the text segment.
> +
> +Other @samp{Key=Value} pairs may be added later to describe target
> +specific data.
Should the protocol allow Key=Value pairs to appear in any order? I
don't think you really need to revise the reply template to show this,
just a note to that effect would be plenty.
> +If the packet ends with @samp{;l} then no further @samp{qsDllInfo}
> +packet will be sent.
Perfect. Same trick as with qXfer.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-16 22:59 ` Jim Blandy
@ 2007-05-18 0:27 ` Daniel Jacobowitz
2007-05-18 16:04 ` Jim Blandy
0 siblings, 1 reply; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-05-18 0:27 UTC (permalink / raw)
To: Jim Blandy; +Cc: gdb-patches, gdb
On Wed, May 16, 2007 at 03:58:52PM -0700, Jim Blandy wrote:
> It seems odd to me that it's an @var{n} that distinguishes the reason
> for the stop; the @var{AA}, the @var{r}, and any other @var{r}:@var{n}
> pairs are essentially meaningless. I'd rather see an entirely new
> stop reply packet type --- 'L', say --- with subsequent name/value
> pairs, like those in a q[fs]DllInfo packet's 'm' response.
I don't know why you say they're meaningless. @var{AA} is unused, but
@var{r} describes the exact reason for the stop (which library was
loaded or unloaded), and other @var{r}:@var{n} pairs are treated
exactly as they are for T packets - they supply useful registers.
I'd have to add the expedited register support to any new reply packet
too, which would make it basically T without the signal number; this
version seems to complicate the protocol less.
> Should the protocol allow Key=Value pairs to appear in any order? I
> don't think you really need to revise the reply template to show this,
> just a note to that effect would be plenty.
Yes indeed.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-18 0:27 ` Daniel Jacobowitz
@ 2007-05-18 16:04 ` Jim Blandy
2007-05-18 16:10 ` Daniel Jacobowitz
0 siblings, 1 reply; 17+ messages in thread
From: Jim Blandy @ 2007-05-18 16:04 UTC (permalink / raw)
To: gdb-patches; +Cc: gdb
Daniel Jacobowitz <drow@false.org> writes:
> On Wed, May 16, 2007 at 03:58:52PM -0700, Jim Blandy wrote:
>> It seems odd to me that it's an @var{n} that distinguishes the reason
>> for the stop; the @var{AA}, the @var{r}, and any other @var{r}:@var{n}
>> pairs are essentially meaningless. I'd rather see an entirely new
>> stop reply packet type --- 'L', say --- with subsequent name/value
>> pairs, like those in a q[fs]DllInfo packet's 'm' response.
>
> I don't know why you say they're meaningless. @var{AA} is unused, but
> @var{r} describes the exact reason for the stop (which library was
> loaded or unloaded), and other @var{r}:@var{n} pairs are treated
> exactly as they are for T packets - they supply useful registers.
> I'd have to add the expedited register support to any new reply packet
> too, which would make it basically T without the signal number; this
> version seems to complicate the protocol less.
Sorry --- of course the @var{r} associated with the dllstop isn't
meaningless. Regarding the other pairs, I didn't realize that one
wanted expedited registers for DLL events; would we actually use them?
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-18 16:04 ` Jim Blandy
@ 2007-05-18 16:10 ` Daniel Jacobowitz
2007-05-18 16:49 ` Jim Blandy
0 siblings, 1 reply; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-05-18 16:10 UTC (permalink / raw)
To: Jim Blandy; +Cc: gdb-patches, gdb
On Fri, May 18, 2007 at 09:04:49AM -0700, Jim Blandy wrote:
> Sorry --- of course the @var{r} associated with the dllstop isn't
> meaningless. Regarding the other pairs, I didn't realize that one
> wanted expedited registers for DLL events; would we actually use them?
Sure. For instance, if stop-on-solib-events was set, we would stop;
or if we were single-stepping multiple instructions we'd (I hope, I
haven't tested this) keep stepping.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-18 16:10 ` Daniel Jacobowitz
@ 2007-05-18 16:49 ` Jim Blandy
0 siblings, 0 replies; 17+ messages in thread
From: Jim Blandy @ 2007-05-18 16:49 UTC (permalink / raw)
To: gdb-patches; +Cc: gdb
Daniel Jacobowitz <drow@false.org> writes:
> On Fri, May 18, 2007 at 09:04:49AM -0700, Jim Blandy wrote:
>> Sorry --- of course the @var{r} associated with the dllstop isn't
>> meaningless. Regarding the other pairs, I didn't realize that one
>> wanted expedited registers for DLL events; would we actually use them?
>
> Sure. For instance, if stop-on-solib-events was set, we would stop;
> or if we were single-stepping multiple instructions we'd (I hope, I
> haven't tested this) keep stepping.
Okay, this makes complete sense.
Humbly, I still don't think it's a great idea to take the trap packet
and give it new roles like this. A DLL change is a new kind of event.
What would you say to this:
*** gdb.texinfo 16 May 2007 14:16:32 -0000 1.405
--- gdb.texinfo 18 May 2007 16:44:40 -0000
***************
*** 23178,23190 ****
@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.
@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
@item W @var{AA}
The process exited, and @var{AA} is the exit status. This is only
applicable to certain targets.
--- 23182,23219 ----
@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. @var{aa} should be @samp{05}, the trap signal.
!
@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
+ @item Lload @var{lib};@var{regs}
+ A dynamically linked library has been loaded. The @var{lib} parameter
+ describes the new library, in the same format used by a
+ @samp{qfDllInfo} reply (@pxref{qfDllInfo}). However, @var{lib} may
+ further end in @samp{,nop} if this library was already mapped, e.g.@:
+ by an earlier call to @code{LoadLibrary}. The @var{regs} parameter is
+ a list of important register values, encoded as for a @samp{T} packet.
+
+ @item Lunload @var{lib};@var{regs}
+ A dynamically linked library has been unloaded. the @var{lib}
+ parameter describes the unloaded library, in the same format used by a
+ @samp{qfDllInfo} reply. The name, the segment offsets, or both may be
+ used to specify which DLL to unload, e.g.@:
+ @samp{unload:Name=@var{hexname}} or
+ @samp{unload:Name=@var{hexname},TextSeg=@var{textaddr}}. The entry
+ may end in @samp{,nop} if this library is still mapped, e.g.@: by
+ another open handle. The @var{regs} parameter is a list of important
+ register values, encoded as for a @samp{T} packet.
+
+ @item Ldll
+ The set of currently loaded dynamically linked libraries has changed.
+ @value{GDBN} should use @samp{qfDllInfo} to fetch a new list of loaded
+ libraries.
+
@item W @var{AA}
The process exited, and @var{AA} is the exit status. This is only
applicable to certain targets.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-15 13:28 ` Daniel Jacobowitz
@ 2007-05-21 12:00 ` Daniel Jacobowitz
2007-07-02 21:37 ` Daniel Jacobowitz
1 sibling, 0 replies; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-05-21 12:00 UTC (permalink / raw)
To: Mark Kettenis, gdb-patches, Kevin Buettner
On Tue, May 15, 2007 at 09:28:26AM -0400, Daniel Jacobowitz wrote:
> Here are just the infrun parts. They've gained a test case for the
> trickiest part, a cleanup, a better changelog, and an explanation.
>
> First of all, I don't remember why I was testing
> inferior_ignoring_startup_exec_events in the last version of this
> patch. I discovered that now there are no references to it (there may
> have been one when I wrote it). I didn't really need it, so I garbage
> collected it.
>
> Secondly, I needed to make TARGET_WAITKIND_LOADED support work with
> the current solib.c implementation. You can tell it hasn't been used
> in a while since it was conditioned on "#ifdef SOLIB_ADD"; there are
> almost no definitions of that left.
>
> Third, while debugging shared library support for SymbianOS I kept
> encountering an unpleasant surprise. I would disconnect from the
> remote target when it was stopped at a load event (usually because my
> GDB crashed :-). When I reconnected, GDB would automatically resume
> the program! That's where the ugly stop_soon test was in the last
> version of this. For this version, I reviewed every setting and use
> of stop_soon and decided that none of them quite matched the case in
> stop_remote, so I added a new STOP_QUIETLY_REMOTE (and some comments
> about it). This is just like STOP_QUIETLY_NO_SIGSTOP except that it
> does not need to hide a SIGSTOP if it finds one. It means we're
> connecting to the target for the first time, so we shouldn't decide to
> resume it without giving the user a chance to look around.
>
> I hope this version is clearer; what do you think of it?
Hi Mark, Kevin,
Did either of you have a chance to look at this? You both had
concerns about the infrun parts of the combined patch, so I'd like to
make sure this version is better and clearer before I go on with the
other pieces.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [rfc / remote protocol] Remote shared library events
2007-05-15 13:28 ` Daniel Jacobowitz
2007-05-21 12:00 ` Daniel Jacobowitz
@ 2007-07-02 21:37 ` Daniel Jacobowitz
1 sibling, 0 replies; 17+ messages in thread
From: Daniel Jacobowitz @ 2007-07-02 21:37 UTC (permalink / raw)
To: gdb-patches
On Tue, May 15, 2007 at 09:28:26AM -0400, Daniel Jacobowitz wrote:
> Here are just the infrun parts. They've gained a test case for the
> trickiest part, a cleanup, a better changelog, and an explanation.
I've checked this in. Please let me know if you have further
questions.
--
Daniel Jacobowitz
CodeSourcery
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
* infrun.c (inferior_ignoring_startup_exec_events): Delete.
(start_remote): Use STOP_QUIETLY_REMOTE.
(handle_inferior_event): Do not condition TARGET_WAITKIND_LOADED
support on a SOLIB_ADD definition. Update breakpoints_inserted.
Update to match shared library event breakpoint support. Only
resume if appropriate. Handle STOP_QUIETLY_REMOTE.
(normal_stop): Handle TARGET_WAITKIND_LOADED.
* fork-child.c (startup_inferior): Do not set
inferior_ignoring_startup_exec_events
* inferior.h (inferior_ignoring_startup_exec_events): Delete
declaration.
(enum stop_kind): Improve documentation. Add STOP_QUIETLY_REMOTE.
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
* config/gdbserver.exp (gdb_reconnect): New.
* gdb.base/so-disc-shr.c, gdb.base/solib-disc.c,
gdb.base/solib-disc.exp: New files.
* lib/gdb.exp (gdb_test_multiple): Allow tests to match "Ending
remote debugging".
(gdb_compile): Add shlib_load flag.
* lib/gdbserver-support.exp (gdbserver_run): Save the protocol and
port.
(gdbserver_reconnect): New.
---
gdb/fork-child.c | 4 -
gdb/inferior.h | 26 ++------
gdb/infrun.c | 79 ++++++++++++++++++++----
gdb/testsuite/config/gdbserver.exp | 4 +
gdb/testsuite/gdb.base/so-disc-shr.c | 25 +++++++
gdb/testsuite/gdb.base/solib-disc.c | 57 +++++++++++++++++
gdb/testsuite/gdb.base/solib-disc.exp | 104 ++++++++++++++++++++++++++++++++
gdb/testsuite/lib/gdb.exp | 17 ++++-
gdb/testsuite/lib/gdbserver-support.exp | 18 ++++-
9 files changed, 292 insertions(+), 42 deletions(-)
Index: gdb/infrun.c
===================================================================
--- gdb/infrun.c.orig 2007-07-02 14:56:47.000000000 -0400
+++ gdb/infrun.c 2007-07-02 14:58:09.000000000 -0400
@@ -84,7 +84,6 @@ static int prepare_to_proceed (void);
void _initialize_infrun (void);
-int inferior_ignoring_startup_exec_events = 0;
int inferior_ignoring_leading_exec_events = 0;
/* When set, stop the 'step' command if we enter a function which has
@@ -828,7 +827,7 @@ start_remote (int from_tty)
{
init_thread_list ();
init_wait_for_inferior ();
- stop_soon = STOP_QUIETLY;
+ stop_soon = STOP_QUIETLY_REMOTE;
trap_expected = 0;
/* Always go on waiting for the target, regardless of the mode. */
@@ -1297,16 +1296,22 @@ handle_inferior_event (struct execution_
case TARGET_WAITKIND_LOADED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
- /* Ignore gracefully during startup of the inferior, as it
- might be the shell which has just loaded some objects,
- otherwise add the symbols for the newly loaded objects. */
-#ifdef SOLIB_ADD
+ /* Ignore gracefully during startup of the inferior, as it might
+ be the shell which has just loaded some objects, otherwise
+ add the symbols for the newly loaded objects. Also ignore at
+ the beginning of an attach or remote session; we will query
+ the full list of libraries once the connection is
+ established. */
if (stop_soon == NO_STOP_QUIETLY)
{
+ int breakpoints_were_inserted;
+
/* Remove breakpoints, SOLIB_ADD might adjust
breakpoint addresses via breakpoint_re_set. */
+ breakpoints_were_inserted = breakpoints_inserted;
if (breakpoints_inserted)
remove_breakpoints ();
+ breakpoints_inserted = 0;
/* Check for any newly added shared libraries if we're
supposed to be adding them automatically. Switch
@@ -1328,17 +1333,50 @@ handle_inferior_event (struct execution_
exec/process stratum, instead relying on the target stack
to propagate relevant changes (stop, section table
changed, ...) up to other layers. */
+#ifdef SOLIB_ADD
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
+#else
+ solib_add (NULL, 0, ¤t_target, auto_solib_add);
+#endif
target_terminal_inferior ();
+ /* Try to reenable shared library breakpoints, additional
+ code segments in shared libraries might be mapped in now. */
+ re_enable_breakpoints_in_shlibs ();
+
+ /* If requested, stop when the dynamic linker notifies
+ gdb of events. This allows the user to get control
+ and place breakpoints in initializer routines for
+ dynamically loaded objects (among other things). */
+ if (stop_on_solib_events)
+ {
+ stop_stepping (ecs);
+ return;
+ }
+
+ /* NOTE drow/2007-05-11: This might be a good place to check
+ for "catch load". */
+
/* Reinsert breakpoints and continue. */
- if (breakpoints_inserted)
- insert_breakpoints ();
+ if (breakpoints_were_inserted)
+ {
+ insert_breakpoints ();
+ breakpoints_inserted = 1;
+ }
}
-#endif
- resume (0, TARGET_SIGNAL_0);
- prepare_to_wait (ecs);
- return;
+
+ /* If we are skipping through a shell, or through shared library
+ loading that we aren't interested in, resume the program. If
+ we're running the program normally, also resume. But stop if
+ we're attaching or setting up a remote connection. */
+ if (stop_soon == STOP_QUIETLY || stop_soon == NO_STOP_QUIETLY)
+ {
+ resume (0, TARGET_SIGNAL_0);
+ prepare_to_wait (ecs);
+ return;
+ }
+
+ break;
case TARGET_WAITKIND_SPURIOUS:
if (debug_infrun)
@@ -1862,7 +1900,8 @@ handle_inferior_event (struct execution_
&& (stop_signal == TARGET_SIGNAL_ILL
|| stop_signal == TARGET_SIGNAL_SEGV
|| stop_signal == TARGET_SIGNAL_EMT))
- || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP)
+ || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP
+ || stop_soon == STOP_QUIETLY_REMOTE)
{
if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
{
@@ -1875,7 +1914,7 @@ handle_inferior_event (struct execution_
/* This is originated from start_remote(), start_inferior() and
shared libraries hook functions. */
- if (stop_soon == STOP_QUIETLY)
+ if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
@@ -3160,6 +3199,18 @@ Further execution is probably impossible
switch (bpstat_ret)
{
case PRINT_UNKNOWN:
+ /* If we had hit a shared library event breakpoint,
+ bpstat_print would print out this message. If we hit
+ an OS-level shared library event, do the same
+ thing. */
+ if (last.kind == TARGET_WAITKIND_LOADED)
+ {
+ printf_filtered (_("Stopped due to shared library event\n"));
+ source_flag = SRC_LINE; /* something bogus */
+ do_frame_printing = 0;
+ break;
+ }
+
/* FIXME: cagney/2002-12-01: Given that a frame ID does
(or should) carry around the function and does (or
should) use that when doing a frame comparison. */
Index: gdb/fork-child.c
===================================================================
--- gdb/fork-child.c.orig 2007-07-02 14:56:45.000000000 -0400
+++ gdb/fork-child.c 2007-07-02 14:58:09.000000000 -0400
@@ -414,10 +414,6 @@ startup_inferior (int ntraps)
init_wait_for_inferior ();
- if (STARTUP_WITH_SHELL)
- inferior_ignoring_startup_exec_events = ntraps;
- else
- inferior_ignoring_startup_exec_events = 0;
inferior_ignoring_leading_exec_events =
target_reported_exec_events_per_exec_call () - 1;
Index: gdb/inferior.h
===================================================================
--- gdb/inferior.h.orig 2007-07-02 14:56:47.000000000 -0400
+++ gdb/inferior.h 2007-07-02 14:58:09.000000000 -0400
@@ -124,20 +124,7 @@ extern int target_executing;
redisplay the prompt until the execution is actually over. */
extern int sync_execution;
-/* This is only valid when inferior_ptid is non-zero.
-
- If this is 0, then exec events should be noticed and responded to
- by the debugger (i.e., be reported to the user).
-
- If this is > 0, then that many subsequent exec events should be
- ignored (i.e., not be reported to the user).
- */
-extern int inferior_ignoring_startup_exec_events;
-
-/* This is only valid when inferior_ignoring_startup_exec_events is
- zero.
-
- Some targets (stupidly) report more than one exec event per actual
+/* Some targets (stupidly) report more than one exec event per actual
call to an event() system call. If only the last such exec event
need actually be noticed and responded to by the debugger (i.e.,
be reported to the user), then this is the number of "leading"
@@ -351,10 +338,12 @@ extern enum step_over_calls_kind step_ov
extern int step_multi;
-/* Nonzero means expecting a trap and caller will handle it
- themselves. It is used when running in the shell before the child
- program has been exec'd; and when running some kinds of remote
- stuff (FIXME?). */
+/* Anything but NO_STOP_QUIETLY means we expect a trap and the caller
+ will handle it themselves. STOP_QUIETLY is used when running in
+ the shell before the child program has been exec'd and when running
+ through shared library loading. STOP_QUIETLY_REMOTE is used when
+ setting up a remote connection; it is like STOP_QUIETLY_NO_SIGSTOP
+ except that there is no need to hide a signal. */
/* It is also used after attach, due to attaching to a process. This
is a bit trickier. When doing an attach, the kernel stops the
@@ -378,6 +367,7 @@ enum stop_kind
{
NO_STOP_QUIETLY = 0,
STOP_QUIETLY,
+ STOP_QUIETLY_REMOTE,
STOP_QUIETLY_NO_SIGSTOP
};
Index: gdb/testsuite/config/gdbserver.exp
===================================================================
--- gdb/testsuite/config/gdbserver.exp.orig 2007-07-02 14:56:17.000000000 -0400
+++ gdb/testsuite/config/gdbserver.exp 2007-07-02 14:58:09.000000000 -0400
@@ -81,3 +81,7 @@ proc gdbserver_gdb_load { } {
proc gdb_reload { } {
return [gdbserver_run ""]
}
+
+proc gdb_reconnect { } {
+ return [gdbserver_reconnect]
+}
Index: gdb/testsuite/gdb.base/so-disc-shr.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.base/so-disc-shr.c 2007-07-02 14:58:09.000000000 -0400
@@ -0,0 +1,25 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2007 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <stdio.h>
+
+void shrfunc (void)
+{
+ printf ("in shrfunc\n");
+}
Index: gdb/testsuite/gdb.base/solib-disc.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.base/solib-disc.c 2007-07-02 14:58:09.000000000 -0400
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2007 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __WIN32__
+#include <windows.h>
+#define dlopen(name, mode) LoadLibrary (name)
+#define dlsym(handle, func) GetProcAddress (handle, func)
+#define dlclose(handle) FreeLibrary (handle)
+#define dlerror() "an error occurred"
+#else
+#include <dlfcn.h>
+#endif
+
+int main()
+{
+ void *handle;
+ void (*func) (void);
+
+ handle = dlopen (SHLIB_NAME, RTLD_LAZY);
+ if (!handle)
+ {
+ fprintf (stderr, dlerror ());
+ exit (1);
+ }
+
+ func = (void (*)(void)) dlsym (handle, "shrfunc");
+ if (!func)
+ {
+ fprintf (stderr, dlerror ());
+ exit (1);
+ }
+
+ func ();
+
+ dlclose (handle);
+
+ return 0;
+}
Index: gdb/testsuite/gdb.base/solib-disc.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.base/solib-disc.exp 2007-07-02 14:58:09.000000000 -0400
@@ -0,0 +1,104 @@
+# Copyright 2007 Free Software Foundation, Inc.
+
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Test connecting and disconnecting at shared library events.
+
+if {[skip_shlib_tests]} {
+ return 0
+}
+
+if { [info proc gdb_reconnect] == "" } {
+ return 0
+}
+
+set testfile solib-disc
+set libfile so-disc-shr
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+set libsrc "${srcdir}/${subdir}/${libfile}.c"
+set libname "${libfile}.so"
+set libobj "${objdir}/${subdir}/${libname}"
+set execsrc "${srcdir}/${subdir}/${srcfile}"
+
+remote_exec build "rm -f ${binfile}"
+
+if [get_compiler_info ${binfile}] {
+ return -1
+}
+
+set exec_opts [list debug shlib_load additional_flags=-DSHLIB_NAME\=\"${libname}\"]
+
+if { [gdb_compile_shlib $libsrc $libobj {debug}] != ""
+ || [gdb_compile $execsrc ${binfile} executable $exec_opts] != "" } {
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_load_shlibs $libobj
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+gdb_test "set stop-on-solib-events 1" ""
+
+gdb_test "continue" "Stopped due to shared library event" "continue to load"
+
+set msg "save \$pc after load"
+set saved_pc ""
+gdb_test_multiple "print/x \$pc" $msg {
+ -re "\\\$$decimal = (\[^\r\n\]*)\r\n$gdb_prompt $" {
+ set saved_pc $expect_out(1,string)
+ pass $msg
+ }
+}
+
+gdb_test "disconnect" "Ending remote debugging\\." "disconnect after load"
+if { [gdb_reconnect] == 0 } {
+ pass "reconnect after load"
+} else {
+ fail "reconnect after load"
+ return 0
+}
+
+gdb_test "print/x \$pc" "\\\$$decimal = $saved_pc" "check \$pc after load"
+
+
+gdb_test "continue" "Stopped due to shared library event" "continue to unload"
+
+set msg "save \$pc after unload"
+set saved_pc ""
+gdb_test_multiple "print/x \$pc" $msg {
+ -re "\\\$$decimal = (\[^\r\n\]*)\r\n$gdb_prompt $" {
+ set saved_pc $expect_out(1,string)
+ pass $msg
+ }
+}
+
+gdb_test "disconnect" "Ending remote debugging\\." "disconnect after unload"
+if { [gdb_reconnect] == 0 } {
+ pass "reconnect after unload"
+} else {
+ fail "reconnect after unload"
+ return 0
+}
+
+gdb_test "print/x \$pc" "\\\$$decimal = $saved_pc" "check \$pc after unload"
Index: gdb/testsuite/lib/gdb.exp
===================================================================
--- gdb/testsuite/lib/gdb.exp.orig 2007-07-02 14:56:17.000000000 -0400
+++ gdb/testsuite/lib/gdb.exp 2007-07-02 14:58:09.000000000 -0400
@@ -671,6 +671,9 @@ proc gdb_test_multiple { command message
gdb_suppress_entire_file "GDB died";
set result -1;
}
+ }
+ append code $processed_code
+ append code {
-re "Ending remote debugging.*$gdb_prompt $" {
if ![isnative] then {
warning "Can`t communicate to remote target."
@@ -679,9 +682,6 @@ proc gdb_test_multiple { command message
gdb_start
set result -1
}
- }
- append code $processed_code
- append code {
-re "Undefined\[a-z\]* command:.*$gdb_prompt $" {
perror "Undefined command \"$command\"."
fail "$message"
@@ -1543,6 +1543,17 @@ proc gdb_compile {source dest type optio
lappend options "additional_flags=-rpath ${objdir}/${subdir}"
}
}
+ } elseif { $opt == "shlib_load" } {
+ if { ([istarget "*-*-mingw*"]
+ || [istarget *-*-cygwin*]
+ || [istarget *-*-pe*]
+ || [istarget arm*-*-symbianelf*]
+ || [istarget hppa*-*-hpux*])} {
+ # Do not need anything.
+ } else {
+ lappend new_options "libs=-ldl"
+ lappend new_options "additional_flags=-Wl,-rpath,\\\$ORIGIN"
+ }
} else {
lappend new_options $opt
}
Index: gdb/testsuite/lib/gdbserver-support.exp
===================================================================
--- gdb/testsuite/lib/gdbserver-support.exp.orig 2007-07-02 14:56:17.000000000 -0400
+++ gdb/testsuite/lib/gdbserver-support.exp 2007-07-02 14:58:09.000000000 -0400
@@ -236,6 +236,9 @@ proc gdbserver_spawn { child_args } {
# to it. Return 0 on success, or non-zero on failure.
proc gdbserver_run { child_args } {
+ global gdbserver_protocol
+ global gdbserver_gdbport
+
# Kill anything running before we try to start gdbserver, in case
# we are sharing a serial connection.
global gdb_prompt
@@ -252,8 +255,17 @@ proc gdbserver_run { child_args } {
}
set res [gdbserver_spawn $child_args]
- set protocol [lindex $res 0]
- set gdbport [lindex $res 1]
+ set gdbserver_protocol [lindex $res 0]
+ set gdbserver_gdbport [lindex $res 1]
+
+ return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
+}
+
+# Reconnect to the previous gdbserver session.
+
+proc gdbserver_reconnect { } {
+ global gdbserver_protocol
+ global gdbserver_gdbport
- return [gdb_target_cmd $protocol $gdbport]
+ return [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
}
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2007-07-02 21:37 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-05-09 20:16 [rfc / remote protocol] Remote shared library events Daniel Jacobowitz
2007-05-10 3:18 ` Eli Zaretskii
2007-05-11 17:24 ` Daniel Jacobowitz
2007-05-11 17:39 ` Eli Zaretskii
2007-05-10 21:35 ` Mark Kettenis
2007-05-11 3:35 ` Daniel Jacobowitz
2007-05-15 13:28 ` Daniel Jacobowitz
2007-05-21 12:00 ` Daniel Jacobowitz
2007-07-02 21:37 ` Daniel Jacobowitz
2007-05-11 18:02 ` Kevin Buettner
2007-05-11 18:21 ` Daniel Jacobowitz
2007-05-11 23:31 ` Pedro Alves
2007-05-16 22:59 ` Jim Blandy
2007-05-18 0:27 ` Daniel Jacobowitz
2007-05-18 16:04 ` Jim Blandy
2007-05-18 16:10 ` Daniel Jacobowitz
2007-05-18 16:49 ` Jim Blandy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox