* [4/4] RFC: implement catch load and catch unload
@ 2012-01-19 21:03 Tom Tromey
2012-01-19 22:04 ` Eli Zaretskii
` (4 more replies)
0 siblings, 5 replies; 23+ messages in thread
From: Tom Tromey @ 2012-01-19 21:03 UTC (permalink / raw)
To: gdb-patches
This patch actually implements catch load and catch unload. It also
changes 'set stop-on-solib-events' to print information about what
libraries were loaded or unloaded.
This patch has a few oddities. I would appreciate comment on them.
* If you have a catchpoint and also set stop-on-solib-events, the latter
will always take precedence. This is unfortunate but I think it is an
artifact of the bp_shlib_event breakpoint coming first in the
breakpoint list.
I don't think this is a very big deal. I'd like to consider
stop-on-solib-events as being essentially deprecated by the new
commands.
* There is a change in bpstat_stop_status that is somewhat hacky. We
have to do a pass here to handle an solib event, because we need to
load libraries at a point (1) after the catchpoint's breakpoint_hit
method is invoked, but (2) before the catchpoint's check_status method
is invoked. This is needed so that we can properly collect the names
of added and removed solibs.
* There is a change in internal_bkpt_check_status that is somewhat
hacky. This was the simplest way I could find to make it so that
"catch load" reported the catchpoint; without this, bpstat_print would
find the internal bp_shlib_event bpstat and print it instead, even if
stop-on-solib-events was not set.
Oh, I just remembered something else -- I have yet to test this on a
TARGET_WAITKIND_LOADED target. I will do that and ensure there are no
regressions before checking it in.
Tom
From 8343621246f42269a485e0f53277ea0b41a398ab Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Thu, 19 Jan 2012 12:20:36 -0700
Subject: [PATCH 4/4] the patch
gdb
PR symtab/12406:
* solib.c (update_solib_list): Update the program space's
added_solibs and deleted_solibs fields.
* progspace.h (struct program_space) <added_solibs,
deleted_solibs>: New fields.
(clear_program_space_solib_cache): Declare.
* progspace.c (release_program_space): Call
clear_program_space_solib_cache.
(clear_program_space_solib_cache): New function.
* infrun.c (handle_inferior_event) <TARGET_WAITKIND_LOADED>: Call
bpstat_stop_status. Use handle_solib_event.
* breakpoint.c: Include gdb_regex.h.
(print_solib_event): New function.
(bpstat_print): Use print_solib_event.
(bpstat_stop_status): Add special case for bp_shlib_event.
(handle_solib_event): New function.
(bpstat_what): Use handle_solib_event.
(struct solib_catchpoint): New.
(dtor_catch_solib, insert_catch_solib, remove_catch_solib)
(breakpoint_hit_catch_solib, check_status_catch_solib)
(print_it_catch_solib, print_one_catch_solib)
(print_mention_catch_solib, print_recreate_catch_solib): New
functions.
(catch_solib_breakpoint_ops): New global.
(catch_load_or_unload, catch_load_command_1)
(catch_unload_command_1): New functions.
(internal_bkpt_check_status): Add special case for
bp_shlib_event.
(internal_bkpt_print_it): Use print_solib_event.
(initialize_breakpoint_ops): Initialize
catch_solib_breakpoint_ops.
(_initialize_breakpoint): Register "catch load" and "catch
unload".
* breakpoint.h (handle_solib_event): Declare.
* NEWS: Add entry for "catch load" and "catch unload".
gdb/doc
* gdb.texinfo (Set Catchpoints): Document "catch load" and "catch
unload".
(Files): Mention new catch commands.
(GDB/MI Async Records): Likewise.
gdb/testsuite
* lib/mi-support.exp (mi_expect_stop): Add special case for
solib-event.
* gdb.base/catch-load-so.c: New file.
* gdb.base/catch-load.exp: New file.
* gdb.base/catch-load.c: New file.
* gdb.base/break-interp.exp (reach_1): Update regexp.
---
gdb/NEWS | 5 +
gdb/breakpoint.c | 426 ++++++++++++++++++++++++++++--
gdb/breakpoint.h | 2 +
gdb/doc/gdb.texinfo | 21 ++-
gdb/infrun.c | 41 ++--
gdb/progspace.c | 17 ++
gdb/progspace.h | 17 ++
gdb/solib.c | 4 +
gdb/testsuite/gdb.base/break-interp.exp | 2 +-
gdb/testsuite/gdb.base/catch-load-so.c | 22 ++
gdb/testsuite/gdb.base/catch-load.c | 35 +++
gdb/testsuite/gdb.base/catch-load.exp | 120 +++++++++
gdb/testsuite/lib/mi-support.exp | 2 +
13 files changed, 660 insertions(+), 54 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/catch-load-so.c
create mode 100644 gdb/testsuite/gdb.base/catch-load.c
create mode 100644 gdb/testsuite/gdb.base/catch-load.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index eaf0b9d..6d8f8f7 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -28,6 +28,11 @@
now set a breakpoint in build/gcc/expr.c, but not
build/libcpp/expr.c.
+* New commands
+
+ ** "catch load" and "catch unload" can be used to stop when a shared
+ library is loaded or unloaded, respectively.
+
*** Changes in GDB 7.4
* GDB now handles ambiguous linespecs more consistently; the existing
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 1b43b43..f2710ee 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -65,6 +65,7 @@
#include "stack.h"
#include "skip.h"
#include "record.h"
+#include "gdb_regex.h"
/* readline include files */
#include "readline/readline.h"
@@ -259,6 +260,11 @@ static int is_masked_watchpoint (const struct breakpoint *b);
static int strace_marker_p (struct breakpoint *b);
+static void init_catchpoint (struct breakpoint *b,
+ struct gdbarch *gdbarch, int tempflag,
+ char *cond_string,
+ const struct breakpoint_ops *ops);
+
/* The abstract base class all breakpoint_ops structures inherit
from. */
static struct breakpoint_ops base_breakpoint_ops;
@@ -3489,6 +3495,82 @@ print_bp_stop_message (bpstat bs)
}
}
+/* A helper function that prints a shared library stopped event. */
+
+static void
+print_solib_event (int is_catchpoint)
+{
+ int any_deleted
+ = !VEC_empty (char_ptr, current_program_space->deleted_solibs);
+ int any_added
+ = !VEC_empty (so_list_ptr, current_program_space->added_solibs);
+
+ if (!is_catchpoint)
+ {
+ if (any_added || any_deleted)
+ ui_out_text (current_uiout,
+ _("Stopped due to shared library event:\n"));
+ else
+ ui_out_text (current_uiout,
+ _("Stopped due to spurious shared library event (no "
+ "libraries added or removed)\n"));
+ }
+
+ if (ui_out_is_mi_like_p (current_uiout))
+ {
+ ui_out_field_string (current_uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
+ if (!any_added && !any_deleted)
+ ui_out_field_int (current_uiout, "spurious", 1);
+ }
+
+ if (any_deleted)
+ {
+ struct cleanup *cleanup;
+ char *name;
+ int ix;
+
+ ui_out_text (current_uiout, _(" Inferior unloaded "));
+ cleanup = make_cleanup_ui_out_list_begin_end (current_uiout,
+ "removed");
+ for (ix = 0;
+ VEC_iterate (char_ptr, current_program_space->deleted_solibs,
+ ix, name);
+ ++ix)
+ {
+ if (ix > 0)
+ ui_out_text (current_uiout, " ");
+ ui_out_field_string (current_uiout, "library", name);
+ ui_out_text (current_uiout, "\n");
+ }
+
+ do_cleanups (cleanup);
+ }
+
+ if (any_added)
+ {
+ struct so_list *iter;
+ int ix;
+ struct cleanup *cleanup;
+
+ ui_out_text (current_uiout, _(" Inferior loaded "));
+ cleanup = make_cleanup_ui_out_list_begin_end (current_uiout,
+ "added");
+ for (ix = 0;
+ VEC_iterate (so_list_ptr, current_program_space->added_solibs,
+ ix, iter);
+ ++ix)
+ {
+ if (ix > 0)
+ ui_out_text (current_uiout, " ");
+ ui_out_field_string (current_uiout, "library", iter->so_name);
+ ui_out_text (current_uiout, "\n");
+ }
+
+ do_cleanups (cleanup);
+ }
+}
+
/* Print a message indicating what happened. This is called from
normal_stop(). The input to this routine is the head of the bpstat
list - a list of the eventpoints that caused this stop. KIND is
@@ -3533,10 +3615,7 @@ bpstat_print (bpstat bs, int kind)
OS-level shared library event, do the same thing. */
if (kind == TARGET_WAITKIND_LOADED)
{
- ui_out_text (current_uiout, _("Stopped due to shared library event\n"));
- if (ui_out_is_mi_like_p (current_uiout))
- ui_out_field_string (current_uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
+ print_solib_event (0);
return PRINT_NOTHING;
}
@@ -4221,6 +4300,19 @@ bpstat_stop_status (struct address_space *aspace,
}
}
+ /* A bit of special processing for shlib breakpoints. We need to
+ process solib loading here, so that the lists of loaded and
+ unloaded libraries are correct before we handle "catch load" and
+ "catch unload". */
+ for (bs = bs_head; bs != NULL; bs = bs->next)
+ {
+ if (bs->breakpoint_at->type == bp_shlib_event)
+ {
+ handle_solib_event ();
+ break;
+ }
+ }
+
/* Now go through the locations that caused the target to stop, and
check whether we're interested in reporting this stop to higher
layers, or whether we should resume the target transparently. */
@@ -4308,6 +4400,25 @@ handle_jit_event (void)
target_terminal_inferior ();
}
+/* Handle an solib event by calling solib_add. */
+
+void
+handle_solib_event (void)
+{
+ clear_program_space_solib_cache (current_inferior ()->pspace);
+
+ /* Check for any newly added shared libraries if we're supposed to
+ be adding them automatically. Switch terminal for any messages
+ produced by breakpoint_re_set. */
+ target_terminal_ours_for_output ();
+#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 ();
+}
+
/* Prepare WHAT final decision for infrun. */
/* Decide what infrun needs to do with this bpstat. */
@@ -4485,27 +4596,6 @@ bpstat_what (bpstat bs_head)
/* These operations may affect the bs->breakpoint_at state so they are
delayed after MAIN_ACTION is decided above. */
- if (shlib_event)
- {
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "bpstat_what: bp_shlib_event\n");
-
- /* Check for any newly added shared libraries if we're supposed
- to be adding them automatically. */
-
- /* Switch terminal for any messages produced by
- breakpoint_re_set. */
- target_terminal_ours_for_output ();
-
-#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 ();
- }
-
if (jit_event)
{
if (debug_infrun)
@@ -6436,6 +6526,257 @@ print_recreate_catch_vfork (struct breakpoint *b, struct ui_file *fp)
static struct breakpoint_ops catch_vfork_breakpoint_ops;
+struct solib_catchpoint
+{
+ /* The base class. */
+ struct breakpoint base;
+
+ /* True for "catch load". */
+ unsigned char is_load;
+
+ /* Regular expression to match, if any. */
+ char *regex;
+ regex_t compiled;
+};
+
+static void
+dtor_catch_solib (struct breakpoint *b)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) b;
+
+ if (self->regex)
+ regfree (&self->compiled);
+ xfree (self->regex);
+
+ base_breakpoint_ops.dtor (b);
+}
+
+static int
+insert_catch_solib (struct bp_location *ignore)
+{
+ return 0;
+}
+
+static int
+remove_catch_solib (struct bp_location *ignore)
+{
+ return 0;
+}
+
+static int
+breakpoint_hit_catch_solib (const struct bp_location *bl,
+ struct address_space *aspace,
+ CORE_ADDR bp_addr,
+ const struct target_waitstatus *ws)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) bl->owner;
+ struct breakpoint *other;
+
+ if (ws->kind == TARGET_WAITKIND_LOADED)
+ return 1;
+
+ ALL_BREAKPOINTS (other)
+ {
+ struct bp_location *other_bl;
+
+ if (other == bl->owner)
+ continue;
+
+ if (other->type != bp_shlib_event)
+ continue;
+
+ if (self->base.pspace != NULL && other->pspace != self->base.pspace)
+ continue;
+
+ for (other_bl = other->loc; other_bl != NULL; other_bl = other_bl->next)
+ {
+ if (other->ops->breakpoint_hit (other_bl, aspace, bp_addr, ws))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+check_status_catch_solib (struct bpstats *bs)
+{
+ struct solib_catchpoint *self
+ = (struct solib_catchpoint *) bs->breakpoint_at;
+ int ix;
+
+ if (self->is_load)
+ {
+ struct so_list *iter;
+
+ for (ix = 0;
+ VEC_iterate (so_list_ptr, current_program_space->added_solibs,
+ ix, iter);
+ ++ix)
+ {
+ if (!self->regex
+ || regexec (&self->compiled, iter->so_name, 0, NULL, 0) == 0)
+ return;
+ }
+ }
+ else
+ {
+ char *iter;
+
+ for (ix = 0;
+ VEC_iterate (char_ptr, current_program_space->deleted_solibs,
+ ix, iter);
+ ++ix)
+ {
+ if (!self->regex
+ || regexec (&self->compiled, iter, 0, NULL, 0) == 0)
+ return;
+ }
+ }
+
+ bs->stop = 0;
+ bs->print_it = print_it_noop;
+}
+
+static enum print_stop_action
+print_it_catch_solib (bpstat bs)
+{
+ struct breakpoint *b = bs->breakpoint_at;
+ struct ui_out *uiout = current_uiout;
+
+ annotate_catchpoint (b->number);
+ if (b->disposition == disp_del)
+ ui_out_text (uiout, "\nTemporary catchpoint ");
+ else
+ ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_field_int (uiout, "bkptno", b->number);
+ ui_out_text (uiout, "\n");
+ if (ui_out_is_mi_like_p (uiout))
+ ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ print_solib_event (1);
+ return PRINT_SRC_AND_LOC;
+}
+
+static void
+print_one_catch_solib (struct breakpoint *b, struct bp_location **locs)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) b;
+ struct value_print_options opts;
+ struct ui_out *uiout = current_uiout;
+ char *msg;
+
+ get_user_print_options (&opts);
+ /* Field 4, the address, is omitted (which makes the columns not
+ line up too nicely with the headers, but the effect is relatively
+ readable). */
+ if (opts.addressprint)
+ {
+ annotate_field (4);
+ ui_out_field_skip (uiout, "addr");
+ }
+
+ annotate_field (5);
+ if (self->is_load)
+ {
+ if (self->regex)
+ msg = xstrprintf (_("load of library matching %s"), self->regex);
+ else
+ msg = xstrdup (_("load of library"));
+ }
+ else
+ {
+ if (self->regex)
+ msg = xstrprintf (_("unload of library matching %s"), self->regex);
+ else
+ msg = xstrdup (_("unload of library"));
+ }
+ ui_out_field_string (uiout, "what", msg);
+ xfree (msg);
+}
+
+static void
+print_mention_catch_solib (struct breakpoint *b)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) b;
+
+ printf_filtered (_("Catchpoint %d (%s)"), b->number,
+ self->is_load ? "load" : "unload");
+}
+
+static void
+print_recreate_catch_solib (struct breakpoint *b, struct ui_file *fp)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) b;
+
+ fprintf_unfiltered (fp, "%s %s",
+ b->disposition == disp_del ? "tcatch" : "catch",
+ self->is_load ? "load" : "unload");
+ if (self->regex)
+ fprintf_unfiltered (fp, " %s", self->regex);
+ fprintf_unfiltered (fp, "\n");
+}
+
+static struct breakpoint_ops catch_solib_breakpoint_ops;
+
+/* A helper function that does all the work for "catch load" and
+ "catch unload". */
+
+static void
+catch_load_or_unload (char *arg, int from_tty, int is_load,
+ struct cmd_list_element *command)
+{
+ struct solib_catchpoint *c;
+ struct gdbarch *gdbarch = get_current_arch ();
+ int tempflag;
+ regex_t compiled;
+ struct cleanup *cleanup;
+
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
+ arg = skip_spaces (arg);
+
+ c = XCNEW (struct solib_catchpoint);
+ cleanup = make_cleanup (xfree, c);
+
+ if (*arg != '\0')
+ {
+ int errcode;
+
+ errcode = regcomp (&c->compiled, arg, REG_NOSUB);
+ if (errcode != 0)
+ {
+ char *err = get_regcomp_error (errcode, &c->compiled);
+
+ make_cleanup (xfree, err);
+ error (_("Invalid regexp (%s): %s"), err, arg);
+ }
+ c->regex = xstrdup (arg);
+ }
+
+ c->is_load = is_load;
+ init_catchpoint (&c->base, gdbarch, tempflag, NULL,
+ &catch_solib_breakpoint_ops);
+
+ install_breakpoint (0, &c->base, 1);
+ discard_cleanups (cleanup);
+}
+
+static void
+catch_load_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
+{
+ catch_load_or_unload (arg, from_tty, 1, command);
+}
+
+static void
+catch_unload_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
+{
+ catch_load_or_unload (arg, from_tty, 0, command);
+}
+
/* An instance of this type is used to represent a syscall catchpoint.
It includes a "struct breakpoint" as a kind of base class; users
downcast to "struct breakpoint *" when needed. A breakpoint is
@@ -11179,6 +11520,9 @@ internal_bkpt_check_status (bpstat bs)
{
/* We do not stop for these. */
bs->stop = 0;
+
+ if (bs->breakpoint_at->type == bp_shlib_event && !stop_on_solib_events)
+ bs->print_it = print_it_noop;
}
static enum print_stop_action
@@ -11195,10 +11539,7 @@ internal_bkpt_print_it (bpstat bs)
/* Did we stop because the user set the stop_on_solib_events
variable? (If so, we report this as a generic, "Stopped due
to shlib event" message.) */
- ui_out_text (uiout, _("Stopped due to shared library event\n"));
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
+ print_solib_event (0);
break;
case bp_thread_event:
@@ -13837,6 +14178,19 @@ initialize_breakpoint_ops (void)
ops->print_one = print_one_catch_syscall;
ops->print_mention = print_mention_catch_syscall;
ops->print_recreate = print_recreate_catch_syscall;
+
+ /* Solib-related catchpoints. */
+ ops = &catch_solib_breakpoint_ops;
+ *ops = base_breakpoint_ops;
+ ops->dtor = dtor_catch_solib;
+ ops->insert_location = insert_catch_solib;
+ ops->remove_location = remove_catch_solib;
+ ops->breakpoint_hit = breakpoint_hit_catch_solib;
+ ops->check_status = check_status_catch_solib;
+ ops->print_it = print_it_catch_solib;
+ ops->print_one = print_one_catch_solib;
+ ops->print_mention = print_mention_catch_solib;
+ ops->print_recreate = print_recreate_catch_solib;
}
void
@@ -14140,6 +14494,20 @@ Catch an exception, when thrown."),
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
+ add_catch_command ("load", _("Catch loads of shared libraries.\n\
+Usage: catch load [REGEX]\n\
+If REGEX is given, only stop for libraries matching the regular expression."),
+ catch_load_command_1,
+ NULL,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("unload", _("Catch unloads of shared libraries.\n\
+Usage: catch unload [REGEX]\n\
+If REGEX is given, only stop for libraries matching the regular expression."),
+ catch_unload_command_1,
+ NULL,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
add_catch_command ("syscall", _("\
Catch system calls by their names and/or numbers.\n\
Arguments say which system calls to catch. If no arguments\n\
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index f1c2c52..0fc2e09 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1414,4 +1414,6 @@ extern int user_breakpoint_p (struct breakpoint *);
/* Attempt to determine architecture of location identified by SAL. */
extern struct gdbarch *get_sal_arch (struct symtab_and_line sal);
+extern void handle_solib_event (void);
+
#endif /* !defined (BREAKPOINT_H) */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 49db189..a850968 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4113,6 +4113,12 @@ and @sc{gnu}/Linux.
A call to @code{vfork}. This is currently only available for HP-UX
and @sc{gnu}/Linux.
+@item load @r{[}regexp@r{]}
+@itemx unload @r{[}regexp@r{]}
+The loading or unloading of a shared library. If @var{regexp} is
+given, then the catchpoint will stop only if it matches one of the
+affected libraries.
+
@end table
@item tcatch @var{event}
@@ -15598,8 +15604,14 @@ discarded.
@end table
Sometimes you may wish that @value{GDBN} stops and gives you control
-when any of shared library events happen. Use the @code{set
-stop-on-solib-events} command for this:
+when any of shared library events happen. The best way to do this is
+to use @code{catch load} and @code{catch unload} (@pxref{Set
+Catchpoints}).
+
+@value{GDBN} also supports the the @code{set stop-on-solib-events}
+command for this. This command exists for historical reasons. It is
+less useful than setting a catchpoint, because it does not allow for
+conditions or commands as a catchpoint does.
@table @code
@item set stop-on-solib-events
@@ -26299,8 +26311,9 @@ The inferior exited normally.
A signal was received by the inferior.
@item solib-event
The inferior has stopped due to a library being loaded or unloaded.
-This can only happen when @code{stop-on-solib-events} (@pxref{Files})
-is set.
+This can happen when @code{stop-on-solib-events} (@pxref{Files}) is
+set or when a @code{catch load} or @code{catch unload} catchpoint is
+in use (@pxref{Set Catchpoints}).
@item fork
The inferior has forked. This is reported when @code{catch fork}
(@pxref{Set Catchpoints}) has been used.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 53065c8..68ab851 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3323,28 +3323,32 @@ handle_inferior_event (struct execution_control_state *ecs)
established. */
if (stop_soon == NO_STOP_QUIETLY)
{
- /* Check for any newly added shared libraries if we're
- supposed to be adding them automatically. Switch
- terminal for any messages produced by
- breakpoint_re_set. */
- target_terminal_ours_for_output ();
- /* NOTE: cagney/2003-11-25: Make certain that the target
- stack's section table is kept up-to-date. Architectures,
- (e.g., PPC64), use the section table to perform
- operations such as address => section name and hence
- require the table to contain all sections (including
- those found in shared libraries). */
-#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 ();
+ struct regcache *regcache;
+
+ if (!ptid_equal (ecs->ptid, inferior_ptid))
+ context_switch (ecs->ptid);
+ regcache = get_thread_regcache (ecs->ptid);
+
+ handle_solib_event ();
+
+ ecs->event_thread->control.stop_bpstat
+ = bpstat_stop_status (get_regcache_aspace (regcache),
+ stop_pc, ecs->ptid, &ecs->ws);
+ ecs->random_signal
+ = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+
+ if (!ecs->random_signal)
+ {
+ /* A catchpoint triggered. */
+ ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_TRAP;
+ goto process_event_stop_test;
+ }
/* 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). */
+ ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
if (stop_on_solib_events)
{
/* Make sure we print "Stopped due to solib-event" in
@@ -3354,9 +3358,6 @@ handle_inferior_event (struct execution_control_state *ecs)
stop_stepping (ecs);
return;
}
-
- /* NOTE drow/2007-05-11: This might be a good place to check
- for "catch load". */
}
/* If we are skipping through a shell, or through shared library
diff --git a/gdb/progspace.c b/gdb/progspace.c
index 7175fa6..54531d9 100644
--- a/gdb/progspace.c
+++ b/gdb/progspace.c
@@ -149,6 +149,7 @@ release_program_space (struct program_space *pspace)
free_address_space (pspace->aspace);
resize_section_table (&pspace->target_sections,
-resize_section_table (&pspace->target_sections, 0));
+ clear_program_space_solib_cache (pspace);
/* Discard any data modules have associated with the PSPACE. */
program_space_free_data (pspace);
xfree (pspace);
@@ -503,6 +504,22 @@ switch_to_program_space_and_thread (struct program_space *pspace)
\f
+/* See progspace.h. */
+
+void
+clear_program_space_solib_cache (struct program_space *pspace)
+{
+ int ix;
+ char *name;
+
+ VEC_free (so_list_ptr, pspace->added_solibs);
+ for (ix = 0; VEC_iterate (char_ptr, pspace->deleted_solibs, ix, name); ++ix)
+ xfree (name);
+ VEC_free (char_ptr, pspace->deleted_solibs);
+}
+
+\f
+
/* Keep a registry of per-program_space data-pointers required by other GDB
modules. */
diff --git a/gdb/progspace.h b/gdb/progspace.h
index 9822f70..3db3938 100644
--- a/gdb/progspace.h
+++ b/gdb/progspace.h
@@ -23,6 +23,7 @@
#include "target.h"
#include "vec.h"
+#include "gdb_vecs.h"
struct target_ops;
struct bfd;
@@ -32,6 +33,9 @@ struct exec;
struct address_space;
struct program_space_data;
+typedef struct so_list *so_list_ptr;
+DEF_VEC_P (so_list_ptr);
+
/* A program space represents a symbolic view of an address space.
Roughly speaking, it holds all the data associated with a
non-running-yet program (main executable, main symbols), and when
@@ -188,6 +192,14 @@ struct program_space
/* Number of calls to solib_add. */
unsigned solib_add_generation;
+ /* When an solib is added, it is also added to this vector. This
+ is so we can properly report solib changes to the user. */
+ VEC (so_list_ptr) *added_solibs;
+
+ /* When an solib is removed, its name is added to this vector.
+ This is so we can properly report solib changes to the user. */
+ VEC (char_ptr) *deleted_solibs;
+
/* Per pspace data-pointers required by other GDB modules. */
void **data;
unsigned num_data;
@@ -278,6 +290,11 @@ extern void update_address_spaces (void);
anymore. */
extern void prune_program_spaces (void);
+/* Reset saved solib data at the start of an solib event. This lets
+ us properly collect the data when calling solib_add, so it can then
+ later be printed. */
+extern void clear_program_space_solib_cache (struct program_space *);
+
/* Keep a registry of per-pspace data-pointers required by other GDB
modules. */
diff --git a/gdb/solib.c b/gdb/solib.c
index f591785..84b9019 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -758,6 +758,9 @@ update_solib_list (int from_tty, struct target_ops *target)
unloaded before we remove it from GDB's tables. */
observer_notify_solib_unloaded (gdb);
+ VEC_safe_push (char_ptr, current_program_space->deleted_solibs,
+ xstrdup (gdb->so_name));
+
*gdb_link = gdb->next;
/* Unless the user loaded it explicitly, free SO's objfile. */
@@ -793,6 +796,7 @@ update_solib_list (int from_tty, struct target_ops *target)
volatile struct gdb_exception e;
i->pspace = current_program_space;
+ VEC_safe_push (so_list_ptr, current_program_space->added_solibs, i);
TRY_CATCH (e, RETURN_MASK_ERROR)
{
diff --git a/gdb/testsuite/gdb.base/break-interp.exp b/gdb/testsuite/gdb.base/break-interp.exp
index 5882cfe..04b5eab 100644
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -155,7 +155,7 @@ proc reach_1 {func command displacement} {
pass $test
}
}
- -re "Stopped due to shared library event\r\n$gdb_prompt $" {
+ -re "Stopped due to (spurious )?shared library event.*\r\n$gdb_prompt $" {
if {$func == "_dl_debug_state"} {
if {$debug_state_count == 0} {
# First stop does not yet relocate the _start function
diff --git a/gdb/testsuite/gdb.base/catch-load-so.c b/gdb/testsuite/gdb.base/catch-load-so.c
new file mode 100644
index 0000000..9676479
--- /dev/null
+++ b/gdb/testsuite/gdb.base/catch-load-so.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2012 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+int
+f(void)
+{
+ return 23;
+}
diff --git a/gdb/testsuite/gdb.base/catch-load.c b/gdb/testsuite/gdb.base/catch-load.c
new file mode 100644
index 0000000..170f581
--- /dev/null
+++ b/gdb/testsuite/gdb.base/catch-load.c
@@ -0,0 +1,35 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2012 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+/* This is updated by the .exp file. */
+char *libname = "catch-load-so.so";
+
+int
+main ()
+{
+ void *h;
+
+ h = dlopen (libname, RTLD_LAZY);
+
+ dlclose (h);
+
+ h = NULL; /* final breakpoint here */
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/catch-load.exp b/gdb/testsuite/gdb.base/catch-load.exp
new file mode 100644
index 0000000..2a7c910
--- /dev/null
+++ b/gdb/testsuite/gdb.base/catch-load.exp
@@ -0,0 +1,120 @@
+# Copyright 2012 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+if {[skip_shlib_tests]} {
+ untested catch-load.exp
+ return -1
+}
+
+if {[get_compiler_info not-used]} {
+ warning "Could not get compiler info"
+ untested catch-load.exp
+ return -1
+}
+
+set testfile catch-load
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug shlib_load}] != "" } {
+ untested catch-load.exp
+ return -1
+}
+
+set testfile2 catch-load-so
+set srcfile2 ${testfile2}.c
+set binfile2 ${objdir}/${subdir}/${testfile2}.so
+set binfile2_dlopen [shlib_target_file ${testfile2}.so]
+if { [gdb_compile_shlib "${srcdir}/${subdir}/${srcfile2}" ${binfile2} {debug}] != "" } {
+ untested catch-load.exp
+ return -1
+}
+
+# Run one set of tests.
+# SCENARIO is the name of the test scenario, it is just used in test
+# names.
+# KIND is is passed to the "catch" command.
+# MATCH is a boolean saying whether we expect the catchpoint to be hit.
+proc one_catch_load_test {scenario kind match sostop} {
+ global verbose testfile testfile2 binfile2_dlopen
+ global pf_prefix srcfile
+ global decimal gdb_prompt
+
+ set saved_prefix $pf_prefix
+ append pf_prefix "${scenario}:"
+
+ clean_restart $testfile
+ gdb_load_shlibs $binfile2_dlopen
+
+ if {![runto_main]} {
+ fail "can't run to main"
+ set pf_prefix $saved_prefix
+ return
+ }
+
+ gdb_breakpoint [gdb_get_line_number "final breakpoint here"]
+ gdb_test_no_output "set var libname = \"$binfile2_dlopen\""
+ gdb_test_no_output "set stop-on-solib-events $sostop"
+ gdb_test "catch $kind" "Catchpoint $decimal \\(.*\\)"
+
+ send_gdb "continue\n"
+ gdb_expect {
+ -re "Catchpoint $decimal\r\n.*loaded .*/$testfile2.*\r\n.*$gdb_prompt $" {
+ if {$match} {
+ pass "continue"
+ } else {
+ fail "continue"
+ }
+ }
+
+ -re "Stopped due to spurious shared library event .no libraries added or removed.\r\n$gdb_prompt $" {
+ if {$sostop} {
+ pass "continue"
+ } else {
+ fail "continue"
+ }
+ }
+
+ -re "Breakpoint $decimal, .*\r\n$gdb_prompt $" {
+ if {!$match} {
+ pass "continue"
+ } else {
+ fail "continue"
+ }
+ }
+
+ -re ".*$gdb_prompt $" {
+ fail "continue"
+ }
+ }
+
+ set pf_prefix $saved_prefix
+}
+
+one_catch_load_test "plain load" "load" 1 0
+one_catch_load_test "plain load with stop-on-solib-events" "load" 1 1
+one_catch_load_test "rx load" "load $testfile2" 1 0
+one_catch_load_test "rx load with stop-on-solib-events" "load $testfile2" 1 1
+one_catch_load_test "non-matching load" "load zardoz" 0 0
+one_catch_load_test "non-matching load with stop-on-solib-events" \
+ "load zardoz" 0 1
+
+one_catch_load_test "plain unload" "unload" 1 0
+one_catch_load_test "plain unload with stop-on-solib-events" "unload" 1 1
+one_catch_load_test "rx unload" "unload $testfile2" 1 0
+one_catch_load_test "rx unload with stop-on-solib-events" \
+ "unload $testfile2" 1 1
+one_catch_load_test "non-matching unload" "unload zardoz" 0 0
+one_catch_load_test "non-matching unload with stop-on-solib-events" \
+ "unload zardoz" 0 1
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 4d40a1e..b013311 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -1060,6 +1060,8 @@ proc mi_expect_stop { reason func args file line extra test } {
set bn ""
if { $reason == "breakpoint-hit" } {
set bn {bkptno="[0-9]+",}
+ } elseif { $reason == "solib-event" } {
+ set bn ".*,"
}
set r ""
--
1.7.6.5
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [4/4] RFC: implement catch load and catch unload
2012-01-19 21:03 [4/4] RFC: implement catch load and catch unload Tom Tromey
@ 2012-01-19 22:04 ` Eli Zaretskii
2012-01-20 15:12 ` Tom Tromey
2012-01-20 17:40 ` Pedro Alves
` (3 subsequent siblings)
4 siblings, 1 reply; 23+ messages in thread
From: Eli Zaretskii @ 2012-01-19 22:04 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
> From: Tom Tromey <tromey@redhat.com>
> Date: Thu, 19 Jan 2012 13:35:57 -0700
>
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -28,6 +28,11 @@
> now set a breakpoint in build/gcc/expr.c, but not
> build/libcpp/expr.c.
>
> +* New commands
> +
> + ** "catch load" and "catch unload" can be used to stop when a shared
> + library is loaded or unloaded, respectively.
> +
This part is okay.
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
This part is also okay, but I have one minor comment:
> +@item load @r{[}regexp@r{]}
> +@itemx unload @r{[}regexp@r{]}
> +The loading or unloading of a shared library. If @var{regexp} is
> +given, then the catchpoint will stop only if it matches one of the
> +affected libraries. ^^
That "it" in the last sentence is ambiguous: can be interpreted to
reference the catchpoint instead of the regexp. How about replacing
it with "the regular expression"?
Thanks.
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [4/4] RFC: implement catch load and catch unload
2012-01-19 21:03 [4/4] RFC: implement catch load and catch unload Tom Tromey
2012-01-19 22:04 ` Eli Zaretskii
@ 2012-01-20 17:40 ` Pedro Alves
2012-01-24 17:31 ` Tom Tromey
2012-01-20 17:44 ` Yao Qi
` (2 subsequent siblings)
4 siblings, 1 reply; 23+ messages in thread
From: Pedro Alves @ 2012-01-20 17:40 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Handling this piecemeal.
On 01/19/2012 08:35 PM, Tom Tromey wrote:
> * There is a change in internal_bkpt_check_status that is somewhat
> hacky. This was the simplest way I could find to make it so that
> "catch load" reported the catchpoint; without this, bpstat_print would
> find the internal bp_shlib_event bpstat and print it instead, even if
> stop-on-solib-events was not set.
Hmm. Should we ever print if the breakpoint does not cause a stop? IOW,
can't we make that unconditional if we're also clearing bs->stop?
Related, it looks like there's a bug here:
bpstat_stop_status:
if (bs->stop)
{
...
/* Print nothing for this entry if we don't stop or don't print. */
if (bs->stop == 0 || bs->print == 0)
bs->print_it = print_it_noop;
}
That "Print nothing" only triggers if we think to stop, and then the
conditions evaluate false, or the breakpoint is silent. That should
probably be moved out of the `if (bs->stop) condition' above.
Having said that, I've put it in patch form, on top of mainline. WDYT?
* breakpoint.c (bpstat_stop_status): Moving clearing print_it
outside `bs->stop' block.
(bpstat_what): Rework bp_shlib_event handling.
(internal_bkpt_check_status): If the breakpoint is a
bp_shlib_event, then set bs->stop and bs->print if
stop_on_solib_events is set.
---
gdb/breakpoint.c | 37 ++++++++++++++++++++-----------------
1 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index f6a0276..3f3a417 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4257,10 +4257,12 @@ bpstat_stop_status (struct address_space *aspace,
bs->print = 0;
}
- /* Print nothing for this entry if we don't stop or don't print. */
- if (bs->stop == 0 || bs->print == 0)
- bs->print_it = print_it_noop;
}
+
+ /* Print nothing for this entry if we don't stop or don't
+ print. */
+ if (!bs->stop || !bs->print)
+ bs->print_it = print_it_noop;
}
/* If we aren't stopping, the value of some hardware watchpoint may
@@ -4341,6 +4343,9 @@ bpstat_what (bpstat bs_head)
else
bptype = bs->breakpoint_at->type;
+ if (bptype == bp_shlib_event)
+ shlib_event = 1;
+
switch (bptype)
{
case bp_none:
@@ -4349,6 +4354,7 @@ bpstat_what (bpstat bs_head)
case bp_hardware_breakpoint:
case bp_until:
case bp_finish:
+ case bp_shlib_event:
if (bs->stop)
{
if (bs->print)
@@ -4426,18 +4432,6 @@ bpstat_what (bpstat bs_head)
This requires no further action. */
}
break;
- case bp_shlib_event:
- shlib_event = 1;
-
- /* 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)
- this_action = BPSTAT_WHAT_STOP_NOISY;
- else
- this_action = BPSTAT_WHAT_SINGLE;
- break;
case bp_jit_event:
jit_event = 1;
this_action = BPSTAT_WHAT_SINGLE;
@@ -11144,8 +11138,17 @@ internal_bkpt_re_set (struct breakpoint *b)
static void
internal_bkpt_check_status (bpstat bs)
{
- /* We do not stop for these. */
- bs->stop = 0;
+ if (bs->breakpoint_at->type == bp_shlib_event)
+ {
+ /* 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). */
+ bs->stop = stop_on_solib_events;
+ bs->print = stop_on_solib_events;
+ }
+ else
+ bs->stop = 0;
}
static enum print_stop_action
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [4/4] RFC: implement catch load and catch unload
2012-01-20 17:40 ` Pedro Alves
@ 2012-01-24 17:31 ` Tom Tromey
2012-01-24 19:40 ` Pedro Alves
0 siblings, 1 reply; 23+ messages in thread
From: Tom Tromey @ 2012-01-24 17:31 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
Pedro> Hmm. Should we ever print if the breakpoint does not cause a stop? IOW,
Pedro> can't we make that unconditional if we're also clearing bs->stop?
Pedro> Related, it looks like there's a bug here:
[...]
Yeah, I was contemplating something along these lines as well, though a
slightly different take: I was wondering why bpstat_print will call
print_bp_stop_message for a bpstat with stop=0.
I think your patch is fine. If you want to check it in, I will rebase
on top of it.
Tom
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [4/4] RFC: implement catch load and catch unload
2012-01-19 21:03 [4/4] RFC: implement catch load and catch unload Tom Tromey
2012-01-19 22:04 ` Eli Zaretskii
2012-01-20 17:40 ` Pedro Alves
@ 2012-01-20 17:44 ` Yao Qi
2012-01-20 19:45 ` Pedro Alves
2012-01-24 22:11 ` Tom Tromey
4 siblings, 0 replies; 23+ messages in thread
From: Yao Qi @ 2012-01-20 17:44 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 01/19/2012 12:35 PM, Tom Tromey wrote:
> + send_gdb "continue\n"
> + gdb_expect {
I am thinking why don't we use gdb_test_multiple here?
> + -re "Catchpoint $decimal\r\n.*loaded .*/$testfile2.*\r\n.*$gdb_prompt $" {
> + if {$match} {
> + pass "continue"
> + } else {
> + fail "continue"
> + }
> + }
> +
> + -re "Stopped due to spurious shared library event .no libraries added or removed.\r\n$gdb_prompt $" {
> + if {$sostop} {
> + pass "continue"
> + } else {
> + fail "continue"
> + }
> + }
> +
> + -re "Breakpoint $decimal, .*\r\n$gdb_prompt $" {
> + if {!$match} {
> + pass "continue"
> + } else {
> + fail "continue"
> + }
> + }
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [4/4] RFC: implement catch load and catch unload
2012-01-19 21:03 [4/4] RFC: implement catch load and catch unload Tom Tromey
` (2 preceding siblings ...)
2012-01-20 17:44 ` Yao Qi
@ 2012-01-20 19:45 ` Pedro Alves
2012-01-24 17:07 ` Tom Tromey
2012-01-24 17:22 ` Tom Tromey
2012-01-24 22:11 ` Tom Tromey
4 siblings, 2 replies; 23+ messages in thread
From: Pedro Alves @ 2012-01-20 19:45 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 01/19/2012 08:35 PM, Tom Tromey wrote:
> This patch actually implements catch load and catch unload. It also
> changes 'set stop-on-solib-events' to print information about what
> libraries were loaded or unloaded.
>
> This patch has a few oddities. I would appreciate comment on them.
>
> * If you have a catchpoint and also set stop-on-solib-events, the latter
> will always take precedence. This is unfortunate but I think it is an
> artifact of the bp_shlib_event breakpoint coming first in the
> breakpoint list.
>
> I don't think this is a very big deal. I'd like to consider
> stop-on-solib-events as being essentially deprecated by the new
> commands.
I think that's fine.
> * There is a change in bpstat_stop_status that is somewhat hacky. We
> have to do a pass here to handle an solib event, because we need to
> load libraries at a point (1) after the catchpoint's breakpoint_hit
> method is invoked, but (2) before the catchpoint's check_status method
> is invoked. This is needed so that we can properly collect the names
> of added and removed solibs.
I'm okay with this.
> gdb
> PR symtab/12406:
> * solib.c (update_solib_list): Update the program space's
> added_solibs and deleted_solibs fields.
> * progspace.h (struct program_space) <added_solibs,
> deleted_solibs>: New fields.
> (clear_program_space_solib_cache): Declare.
> * progspace.c (release_program_space): Call
> clear_program_space_solib_cache.
> (clear_program_space_solib_cache): New function.
> * infrun.c (handle_inferior_event) <TARGET_WAITKIND_LOADED>: Call
> bpstat_stop_status. Use handle_solib_event.
> * breakpoint.c: Include gdb_regex.h.
> (print_solib_event): New function.
> (bpstat_print): Use print_solib_event.
> (bpstat_stop_status): Add special case for bp_shlib_event.
> (handle_solib_event): New function.
> (bpstat_what): Use handle_solib_event.
> (struct solib_catchpoint): New.
> (dtor_catch_solib, insert_catch_solib, remove_catch_solib)
> (breakpoint_hit_catch_solib, check_status_catch_solib)
> (print_it_catch_solib, print_one_catch_solib)
> (print_mention_catch_solib, print_recreate_catch_solib): New
> functions.
> (catch_solib_breakpoint_ops): New global.
> (catch_load_or_unload, catch_load_command_1)
> (catch_unload_command_1): New functions.
> (internal_bkpt_check_status): Add special case for
> bp_shlib_event.
> (internal_bkpt_print_it): Use print_solib_event.
> (initialize_breakpoint_ops): Initialize
> catch_solib_breakpoint_ops.
> (_initialize_breakpoint): Register "catch load" and "catch
> unload".
> * breakpoint.h (handle_solib_event): Declare.
> * NEWS: Add entry for "catch load" and "catch unload".
> gdb/doc
> * gdb.texinfo (Set Catchpoints): Document "catch load" and "catch
> unload".
> (Files): Mention new catch commands.
> (GDB/MI Async Records): Likewise.
> gdb/testsuite
> * lib/mi-support.exp (mi_expect_stop): Add special case for
> solib-event.
> * gdb.base/catch-load-so.c: New file.
> * gdb.base/catch-load.exp: New file.
> * gdb.base/catch-load.c: New file.
> * gdb.base/break-interp.exp (reach_1): Update regexp.
> ---
> gdb/NEWS | 5 +
> gdb/breakpoint.c | 426 ++++++++++++++++++++++++++++--
> gdb/breakpoint.h | 2 +
> gdb/doc/gdb.texinfo | 21 ++-
> gdb/infrun.c | 41 ++--
> gdb/progspace.c | 17 ++
> gdb/progspace.h | 17 ++
> gdb/solib.c | 4 +
> gdb/testsuite/gdb.base/break-interp.exp | 2 +-
> gdb/testsuite/gdb.base/catch-load-so.c | 22 ++
> gdb/testsuite/gdb.base/catch-load.c | 35 +++
> gdb/testsuite/gdb.base/catch-load.exp | 120 +++++++++
> gdb/testsuite/lib/mi-support.exp | 2 +
> 13 files changed, 660 insertions(+), 54 deletions(-)
> create mode 100644 gdb/testsuite/gdb.base/catch-load-so.c
> create mode 100644 gdb/testsuite/gdb.base/catch-load.c
> create mode 100644 gdb/testsuite/gdb.base/catch-load.exp
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index eaf0b9d..6d8f8f7 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -28,6 +28,11 @@
> now set a breakpoint in build/gcc/expr.c, but not
> build/libcpp/expr.c.
>
> +* New commands
> +
> + ** "catch load" and "catch unload" can be used to stop when a shared
> + library is loaded or unloaded, respectively.
> +
> *** Changes in GDB 7.4
>
> * GDB now handles ambiguous linespecs more consistently; the existing
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 1b43b43..f2710ee 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -65,6 +65,7 @@
> #include "stack.h"
> #include "skip.h"
> #include "record.h"
> +#include "gdb_regex.h"
>
> /* readline include files */
> #include "readline/readline.h"
> @@ -259,6 +260,11 @@ static int is_masked_watchpoint (const struct breakpoint *b);
>
> static int strace_marker_p (struct breakpoint *b);
>
> +static void init_catchpoint (struct breakpoint *b,
> + struct gdbarch *gdbarch, int tempflag,
> + char *cond_string,
> + const struct breakpoint_ops *ops);
> +
> /* The abstract base class all breakpoint_ops structures inherit
> from. */
> static struct breakpoint_ops base_breakpoint_ops;
> @@ -3489,6 +3495,82 @@ print_bp_stop_message (bpstat bs)
> }
> }
>
> +/* A helper function that prints a shared library stopped event. */
> +
> +static void
> +print_solib_event (int is_catchpoint)
> +{
> + int any_deleted
> + = !VEC_empty (char_ptr, current_program_space->deleted_solibs);
> + int any_added
> + = !VEC_empty (so_list_ptr, current_program_space->added_solibs);
> +
> + if (!is_catchpoint)
> + {
> + if (any_added || any_deleted)
> + ui_out_text (current_uiout,
> + _("Stopped due to shared library event:\n"));
> + else
> + ui_out_text (current_uiout,
> + _("Stopped due to spurious shared library event (no "
> + "libraries added or removed)\n"));
I know Eclipse used to rely "set stop-on-solib-events 1". Not sure they
still do. So if it doesn't convert to the MI events, it'll break. Maybe
just one more reason to make sure they do adjust. :-)
> + }
> +
> + if (ui_out_is_mi_like_p (current_uiout))
> + {
> + ui_out_field_string (current_uiout, "reason",
> + async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
> + if (!any_added && !any_deleted)
> + ui_out_field_int (current_uiout, "spurious", 1);
Do we need "spurious"? We get the same info from neither "removed" nor "added"
being present. I'm not super fond of using the word "spurious" because the stop
had some reason, and in my mind, something spurious is something that should
not have happened. But in this case, the stop means something, but we're not
interpreting it. Maybe for "catch ...", we shouldn't report a stop in
the "spurious" case?
>
> - if (shlib_event)
The shlib_event local should be removed then.
> - {
> - if (debug_infrun)
> - fprintf_unfiltered (gdb_stdlog, "bpstat_what: bp_shlib_event\n");
> -
> - /* Check for any newly added shared libraries if we're supposed
> - to be adding them automatically. */
> -
> - /* Switch terminal for any messages produced by
> - breakpoint_re_set. */
> - target_terminal_ours_for_output ();
> -
> -#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 ();
> - }
> -
> +struct solib_catchpoint
Missing introduction comment.
> +{
> + /* The base class. */
> + struct breakpoint base;
> +
> + /* True for "catch load". */
> + unsigned char is_load;
It helps the reader to mention catch unload explicitly:
/* True for "catch load", false for "catch unload" */
> +
> + /* Regular expression to match, if any. */
> + char *regex;
> + regex_t compiled;
> +};
> +
> +static int
> +breakpoint_hit_catch_solib (const struct bp_location *bl,
> + struct address_space *aspace,
> + CORE_ADDR bp_addr,
> + const struct target_waitstatus *ws)
> +{
> + struct solib_catchpoint *self = (struct solib_catchpoint *) bl->owner;
> + struct breakpoint *other;
> +
> + if (ws->kind == TARGET_WAITKIND_LOADED)
> + return 1;
> +
> + ALL_BREAKPOINTS (other)
> + {
> + struct bp_location *other_bl;
> +
> + if (other == bl->owner)
> + continue;
> +
> + if (other->type != bp_shlib_event)
> + continue;
> +
> + if (self->base.pspace != NULL && other->pspace != self->base.pspace)
> + continue;
So a consequence of this is that "catch load" is only active for the
inferior was current when the catchpoint was created, right? Was that the
intention? If we already had itsets, we could make it trigger on all
inferiors by default, and then use itsets to filter.
> +
> + for (other_bl = other->loc; other_bl != NULL; other_bl = other_bl->next)
> + {
> + if (other->ops->breakpoint_hit (other_bl, aspace, bp_addr, ws))
> + return 1;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/* A helper function that does all the work for "catch load" and
> + "catch unload". */
> +
> +static void
> +catch_load_or_unload (char *arg, int from_tty, int is_load,
> + struct cmd_list_element *command)
> +{
> + struct solib_catchpoint *c;
> + struct gdbarch *gdbarch = get_current_arch ();
> + int tempflag;
> + regex_t compiled;
> + struct cleanup *cleanup;
> +
> + tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
> +
> + if (!arg)
> + arg = "";
> + arg = skip_spaces (arg);
> +
> + c = XCNEW (struct solib_catchpoint);
> + cleanup = make_cleanup (xfree, c);
> +
> + if (*arg != '\0')
> + {
> + int errcode;
> +
> + errcode = regcomp (&c->compiled, arg, REG_NOSUB);
> + if (errcode != 0)
> + {
> + char *err = get_regcomp_error (errcode, &c->compiled);
> +
> + make_cleanup (xfree, err);
> + error (_("Invalid regexp (%s): %s"), err, arg);
> + }
> + c->regex = xstrdup (arg);
> + }
> +
> + c->is_load = is_load;
> + init_catchpoint (&c->base, gdbarch, tempflag, NULL,
> + &catch_solib_breakpoint_ops);
> +
> + install_breakpoint (0, &c->base, 1);
> + discard_cleanups (cleanup);
It's more correct to discard the cleanups before installing the breakpoint.
The first thing install_breakpoint does it put the breakpoint in the
breakpoint chain. Once that is done, we shouldn't delete it with the
cleanup anymore.
> +
> +# Run one set of tests.
> +# SCENARIO is the name of the test scenario, it is just used in test
> +# names.
> +# KIND is is passed to the "catch" command.
Double is.
> +# MATCH is a boolean saying whether we expect the catchpoint to be hit.
> +proc one_catch_load_test {scenario kind match sostop} {
> + global verbose testfile testfile2 binfile2_dlopen
> + global pf_prefix srcfile
> + global decimal gdb_prompt
> +
> + set saved_prefix $pf_prefix
> + append pf_prefix "${scenario}:"
> +
> + clean_restart $testfile
> + gdb_load_shlibs $binfile2_dlopen
> +
> + if {![runto_main]} {
> + fail "can't run to main"
> + set pf_prefix $saved_prefix
> + return
> + }
> +
> + gdb_breakpoint [gdb_get_line_number "final breakpoint here"]
> + gdb_test_no_output "set var libname = \"$binfile2_dlopen\""
> + gdb_test_no_output "set stop-on-solib-events $sostop"
> + gdb_test "catch $kind" "Catchpoint $decimal \\(.*\\)"
> +
> + send_gdb "continue\n"
> + gdb_expect {
> + -re "Catchpoint $decimal\r\n.*loaded .*/$testfile2.*\r\n.*$gdb_prompt $" {
gdb_test_multiple?
Otherwise looks good to me. Thanks for doing this.
--
Pedro Alves
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [4/4] RFC: implement catch load and catch unload
2012-01-20 19:45 ` Pedro Alves
@ 2012-01-24 17:07 ` Tom Tromey
2012-01-24 17:28 ` Marc Khouzam
2012-01-24 17:22 ` Tom Tromey
1 sibling, 1 reply; 23+ messages in thread
From: Tom Tromey @ 2012-01-24 17:07 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, marc.khouzam
CC'ing Marc Khouzam for this one sub-thread.
Pedro> I know Eclipse used to rely "set stop-on-solib-events 1". Not sure they
Pedro> still do. So if it doesn't convert to the MI events, it'll break. Maybe
Pedro> just one more reason to make sure they do adjust. :-)
I think the change here occurred with the patch to PR 8444. That patch
changed a printf_filtered to ui_out_text. I can add the printf_filtered
back -- but I think it would be better for Eclipse and other MI clients
to just start examining the new *stopped reasons. (The MI docs have a
list of these...)
Marc, I am curious to know what Eclipse uses this for.
Tom
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [4/4] RFC: implement catch load and catch unload
2012-01-24 17:07 ` Tom Tromey
@ 2012-01-24 17:28 ` Marc Khouzam
2012-01-24 18:25 ` Tom Tromey
0 siblings, 1 reply; 23+ messages in thread
From: Marc Khouzam @ 2012-01-24 17:28 UTC (permalink / raw)
To: 'Tom Tromey', 'Pedro Alves'
Cc: 'gdb-patches@sourceware.org'
> -----Original Message-----
> From: Tom Tromey [mailto:tromey@redhat.com]
> Sent: Tuesday, January 24, 2012 11:56 AM
> To: Pedro Alves
> Cc: gdb-patches@sourceware.org; Marc Khouzam
> Subject: Re: [4/4] RFC: implement catch load and catch unload
>
> CC'ing Marc Khouzam for this one sub-thread.
>
> Pedro> I know Eclipse used to rely "set stop-on-solib-events
> 1". Not sure they
> Pedro> still do. So if it doesn't convert to the MI events,
> it'll break. Maybe
> Pedro> just one more reason to make sure they do adjust. :-)
>
> I think the change here occurred with the patch to PR 8444.
> That patch
> changed a printf_filtered to ui_out_text. I can add the
> printf_filtered
> back -- but I think it would be better for Eclipse and other
> MI clients
> to just start examining the new *stopped reasons. (The MI docs have a
> list of these...)
>
> Marc, I am curious to know what Eclipse uses this for.
The default GDB integration (DSF) does not use it. In fact, we
don't offer that feature to our users (but we should).
However, the legacy GDB integration (CDI) does use it:
[1,327,424,864,825] 8-gdb-set stop-on-solib-events 1
[1,327,424,864,826] 8^done
Not having this command won't prevent CDI from debugging,
but will have two impacts, as far as I know:
1- no more user feature to stop on lib events
2- breakpoints set on non-loaded libs will no longer be
installed (since CDI does not use pending breakpoints, but
tries to plant failed bps at each new lib load event)
We do tell people that CDI is not being maintained.
I guess eventually, we have to expect some degradation
as GDB keeps evolving.
Thanks for keeping me in the loop. Once you decide how
you want GDB to move forward, if needed, I'll open a bug
on CDI to track the breakage.
Thanks
Marc
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [4/4] RFC: implement catch load and catch unload
2012-01-24 17:28 ` Marc Khouzam
@ 2012-01-24 18:25 ` Tom Tromey
2012-01-24 18:32 ` Marc Khouzam
0 siblings, 1 reply; 23+ messages in thread
From: Tom Tromey @ 2012-01-24 18:25 UTC (permalink / raw)
To: Marc Khouzam; +Cc: 'Pedro Alves', 'gdb-patches@sourceware.org'
>>>>> "Marc" == Marc Khouzam <marc.khouzam@ericsson.com> writes:
Marc> Not having this command won't prevent CDI from debugging,
Marc> but will have two impacts, as far as I know:
Marc> 1- no more user feature to stop on lib events
Marc> 2- breakpoints set on non-loaded libs will no longer be
Marc> installed (since CDI does not use pending breakpoints, but
Marc> tries to plant failed bps at each new lib load event)
Just to be clear -- the command still exists and works.
What changed is how gdb reports it. It used to be that you would get:
-exec-continue
~"Stopped due to shared library event."
*stopped
Now you will get:
-exec-continue
*stopped,reason="solib-event",[more stuff]
I can even restore the old output if you really need it; though I'd
prefer we just keep on with a more purely MI solution.
Tom
^ permalink raw reply [flat|nested] 23+ messages in thread* RE: [4/4] RFC: implement catch load and catch unload
2012-01-24 18:25 ` Tom Tromey
@ 2012-01-24 18:32 ` Marc Khouzam
2012-01-24 19:15 ` Tom Tromey
0 siblings, 1 reply; 23+ messages in thread
From: Marc Khouzam @ 2012-01-24 18:32 UTC (permalink / raw)
To: 'Tom Tromey'
Cc: 'Pedro Alves', 'gdb-patches@sourceware.org'
> -----Original Message-----
> From: Tom Tromey [mailto:tromey@redhat.com]
> Sent: Tuesday, January 24, 2012 12:36 PM
> To: Marc Khouzam
> Cc: 'Pedro Alves'; 'gdb-patches@sourceware.org'
> Subject: Re: [4/4] RFC: implement catch load and catch unload
>
> >>>>> "Marc" == Marc Khouzam <marc.khouzam@ericsson.com> writes:
>
> Marc> Not having this command won't prevent CDI from debugging,
> Marc> but will have two impacts, as far as I know:
> Marc> 1- no more user feature to stop on lib events
> Marc> 2- breakpoints set on non-loaded libs will no longer be
> Marc> installed (since CDI does not use pending breakpoints, but
> Marc> tries to plant failed bps at each new lib load event)
>
> Just to be clear -- the command still exists and works.
> What changed is how gdb reports it. It used to be that you would get:
>
> -exec-continue
> ~"Stopped due to shared library event."
> *stopped
>
> Now you will get:
>
> -exec-continue
> *stopped,reason="solib-event",[more stuff]
>
> I can even restore the old output if you really need it; though I'd
> prefer we just keep on with a more purely MI solution.
Funny. I found the following comment in our code:
// GDB does not have reason when stopping on shared, hopefully
// this will be fix in newer version meanwhile, we will use a hack
// to cope. On most platform we can detect this state by looking at the
// console stream for the phrase:
// ~"Stopped due to shared library event\n"
The good news is we do look for the 'reason' field first.
Surprisingly we look for "shlib-event", but it is a one-line fix
to use "solib-event" instead.
Is the change already in HEAD? I can test with that just to be sure
I haven't missed something.
Thanks
Marc
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [4/4] RFC: implement catch load and catch unload
2012-01-24 18:32 ` Marc Khouzam
@ 2012-01-24 19:15 ` Tom Tromey
2012-01-24 20:36 ` Marc Khouzam
0 siblings, 1 reply; 23+ messages in thread
From: Tom Tromey @ 2012-01-24 19:15 UTC (permalink / raw)
To: Marc Khouzam; +Cc: 'Pedro Alves', 'gdb-patches@sourceware.org'
>>>>> "Marc" == Marc Khouzam <marc.khouzam@ericsson.com> writes:
Marc> Is the change already in HEAD? I can test with that just to be sure
Marc> I haven't missed something.
Yes; it is also in 7.4:
2011-11-22 Tom Tromey <tromey@redhat.com>
PR mi/8444:
* mi/mi-common.h (EXEC_ASYNC_SOLIB_EVENT, EXEC_ASYNC_FORK)
(EXEC_ASYNC_VFORK, EXEC_ASYNC_SYSCALL_ENTRY)
(EXEC_ASYNC_SYSCALL_RETURN, EXEC_ASYNC_EXEC): New constants.
* mi/mi-common.c (async_reason_string_lookup): Add new reasons.
* breakpoint.c (print_it_catch_fork, print_it_catch_vfork)
(print_it_catch_syscall, print_it_catch_exec)
(internal_bkpt_print_it): Use ui_out. Emit stop reason.
(bpstat_print): Add 'kind' argument. Handle
TARGET_WAITKIND_LOADED.
* infrun.c (normal_stop): Update for bpstat_print change. Don't
handle TARGET_WAITKIND_LOADED here.
* breakpoint.h (bpstat_print): Update.
Tom
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [4/4] RFC: implement catch load and catch unload
2012-01-24 19:15 ` Tom Tromey
@ 2012-01-24 20:36 ` Marc Khouzam
0 siblings, 0 replies; 23+ messages in thread
From: Marc Khouzam @ 2012-01-24 20:36 UTC (permalink / raw)
To: 'Tom Tromey'
Cc: 'Pedro Alves', 'gdb-patches@sourceware.org'
> -----Original Message-----
> From: Tom Tromey [mailto:tromey@redhat.com]
> Sent: Tuesday, January 24, 2012 1:56 PM
> To: Marc Khouzam
> Cc: 'Pedro Alves'; 'gdb-patches@sourceware.org'
> Subject: Re: [4/4] RFC: implement catch load and catch unload
>
> >>>>> "Marc" == Marc Khouzam <marc.khouzam@ericsson.com> writes:
>
> Marc> Is the change already in HEAD? I can test with that
> just to be sure
> Marc> I haven't missed something.
>
> Yes; it is also in 7.4:
>
> 2011-11-22 Tom Tromey <tromey@redhat.com>
>
> PR mi/8444:
> * mi/mi-common.h (EXEC_ASYNC_SOLIB_EVENT, EXEC_ASYNC_FORK)
> (EXEC_ASYNC_VFORK, EXEC_ASYNC_SYSCALL_ENTRY)
> (EXEC_ASYNC_SYSCALL_RETURN, EXEC_ASYNC_EXEC): New constants.
> * mi/mi-common.c (async_reason_string_lookup): Add new reasons.
> * breakpoint.c (print_it_catch_fork, print_it_catch_vfork)
> (print_it_catch_syscall, print_it_catch_exec)
> (internal_bkpt_print_it): Use ui_out. Emit stop reason.
> (bpstat_print): Add 'kind' argument. Handle
> TARGET_WAITKIND_LOADED.
> * infrun.c (normal_stop): Update for bpstat_print change. Don't
> handle TARGET_WAITKIND_LOADED here.
> * breakpoint.h (bpstat_print): Update.
Ok, looks ok with a single line change to use 'solib-event' instead
of 'shlib-event'. Again, this is for the legacy/deprecated GDB
integration. Our default integration is ok.
Until the next version of eclipse is released with
that fix, the legacy integration will stop at every solib event,
even if the user doesn't want it to.
Thanks Tom and Pedro for pointing this out.
Marc
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [4/4] RFC: implement catch load and catch unload
2012-01-20 19:45 ` Pedro Alves
2012-01-24 17:07 ` Tom Tromey
@ 2012-01-24 17:22 ` Tom Tromey
2012-01-24 19:17 ` Pedro Alves
1 sibling, 1 reply; 23+ messages in thread
From: Tom Tromey @ 2012-01-24 17:22 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
>> + ui_out_field_int (current_uiout, "spurious", 1);
Pedro> Do we need "spurious"? We get the same info from neither
Pedro> "removed" nor "added" being present. I'm not super fond of using
Pedro> the word "spurious" because the stop had some reason, and in my
Pedro> mind, something spurious is something that should not have
Pedro> happened. But in this case, the stop means something, but we're
Pedro> not interpreting it.
I removed it. I also removed it from the ui_out_text call.
Pedro> Maybe for "catch ...", we shouldn't report a stop in the
Pedro> "spurious" case?
We don't -- check_status_catch_solib will filter them out.
>> - if (shlib_event)
Pedro> The shlib_event local should be removed then.
Thanks, I did this. I fixed up the other little details too.
>> + if (self->base.pspace != NULL && other->pspace != self->base.pspace)
>> + continue;
Pedro> So a consequence of this is that "catch load" is only active for
Pedro> the inferior was current when the catchpoint was created, right?
Pedro> Was that the intention? If we already had itsets, we could make
Pedro> it trigger on all inferiors by default, and then use itsets to
Pedro> filter.
I just made it work the way other catchpoints seem to work. They are
also pspace-specific. It seemed ok to do this, to me, on the theory
that one more spot to change for itsets won't be a big burden; while on
the other hand being different here doesn't seem beneficial.
Tom
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [4/4] RFC: implement catch load and catch unload
2012-01-24 17:22 ` Tom Tromey
@ 2012-01-24 19:17 ` Pedro Alves
0 siblings, 0 replies; 23+ messages in thread
From: Pedro Alves @ 2012-01-24 19:17 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 01/24/2012 05:07 PM, Tom Tromey wrote:
>>> + ui_out_field_int (current_uiout, "spurious", 1);
>
> Pedro> Do we need "spurious"? We get the same info from neither
> Pedro> "removed" nor "added" being present. I'm not super fond of using
> Pedro> the word "spurious" because the stop had some reason, and in my
> Pedro> mind, something spurious is something that should not have
> Pedro> happened. But in this case, the stop means something, but we're
> Pedro> not interpreting it.
>
> I removed it. I also removed it from the ui_out_text call.
Thanks.
> Pedro> Maybe for "catch ...", we shouldn't report a stop in the
> Pedro> "spurious" case?
>
> We don't -- check_status_catch_solib will filter them out.
Ah, missed that. Great.
>>> + if (self->base.pspace != NULL && other->pspace != self->base.pspace)
>>> + continue;
>
> Pedro> So a consequence of this is that "catch load" is only active for
> Pedro> the inferior was current when the catchpoint was created, right?
> Pedro> Was that the intention? If we already had itsets, we could make
> Pedro> it trigger on all inferiors by default, and then use itsets to
> Pedro> filter.
>
> I just made it work the way other catchpoints seem to work. They are
> also pspace-specific. It seemed ok to do this, to me, on the theory
> that one more spot to change for itsets won't be a big burden; while on
> the other hand being different here doesn't seem beneficial.
Okay, that's reasonable.
--
Pedro Alves
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [4/4] RFC: implement catch load and catch unload
2012-01-19 21:03 [4/4] RFC: implement catch load and catch unload Tom Tromey
` (3 preceding siblings ...)
2012-01-20 19:45 ` Pedro Alves
@ 2012-01-24 22:11 ` Tom Tromey
2012-01-25 11:06 ` Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload] Jan Kratochvil
2012-02-20 8:28 ` [commit] catch-load.exp: Fix racy FAILs " Jan Kratochvil
4 siblings, 2 replies; 23+ messages in thread
From: Tom Tromey @ 2012-01-24 22:11 UTC (permalink / raw)
To: gdb-patches
Here is the version I am checking in. I think it takes all the comments
into account.
Tom
From 58fde0b8895021fe57e5e4d97132bdca5e0789d1 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Thu, 19 Jan 2012 12:20:36 -0700
Subject: [PATCH 4/4] the patch
gdb
PR symtab/12406:
* solib.c (update_solib_list): Update the program space's
added_solibs and deleted_solibs fields.
* progspace.h (struct program_space) <added_solibs,
deleted_solibs>: New fields.
(clear_program_space_solib_cache): Declare.
* progspace.c (release_program_space): Call
clear_program_space_solib_cache.
(clear_program_space_solib_cache): New function.
* infrun.c (handle_inferior_event) <TARGET_WAITKIND_LOADED>: Call
bpstat_stop_status. Use handle_solib_event.
* breakpoint.c: Include gdb_regex.h.
(print_solib_event): New function.
(bpstat_print): Use print_solib_event.
(bpstat_stop_status): Add special case for bp_shlib_event.
(handle_solib_event): New function.
(bpstat_what): Use handle_solib_event.
(struct solib_catchpoint): New.
(dtor_catch_solib, insert_catch_solib, remove_catch_solib)
(breakpoint_hit_catch_solib, check_status_catch_solib)
(print_it_catch_solib, print_one_catch_solib)
(print_mention_catch_solib, print_recreate_catch_solib): New
functions.
(catch_solib_breakpoint_ops): New global.
(catch_load_or_unload, catch_load_command_1)
(catch_unload_command_1): New functions.
(internal_bkpt_check_status): Add special case for
bp_shlib_event.
(internal_bkpt_print_it): Use print_solib_event.
(initialize_breakpoint_ops): Initialize
catch_solib_breakpoint_ops.
(_initialize_breakpoint): Register "catch load" and "catch
unload".
* breakpoint.h (handle_solib_event): Declare.
* NEWS: Add entry for "catch load" and "catch unload".
gdb/doc
* gdb.texinfo (Set Catchpoints): Document "catch load" and "catch
unload".
(Files): Mention new catch commands.
(GDB/MI Async Records): Likewise.
gdb/testsuite
* lib/mi-support.exp (mi_expect_stop): Add special case for
solib-event.
* gdb.base/catch-load-so.c: New file.
* gdb.base/catch-load.exp: New file.
* gdb.base/catch-load.c: New file.
* gdb.base/break-interp.exp (reach_1): Update regexp.
---
gdb/NEWS | 5 +
gdb/breakpoint.c | 433 ++++++++++++++++++++++++++++---
gdb/breakpoint.h | 2 +
gdb/doc/gdb.texinfo | 21 ++-
gdb/infrun.c | 41 ++--
gdb/progspace.c | 17 ++
gdb/progspace.h | 17 ++
gdb/solib.c | 4 +
gdb/testsuite/gdb.base/break-interp.exp | 2 +-
gdb/testsuite/gdb.base/catch-load-so.c | 22 ++
gdb/testsuite/gdb.base/catch-load.c | 35 +++
gdb/testsuite/gdb.base/catch-load.exp | 120 +++++++++
gdb/testsuite/lib/mi-support.exp | 2 +
13 files changed, 660 insertions(+), 61 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/catch-load-so.c
create mode 100644 gdb/testsuite/gdb.base/catch-load.c
create mode 100644 gdb/testsuite/gdb.base/catch-load.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index 3d51c02..4798b7b 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -34,6 +34,11 @@
* The command "info catch" has been removed. It has been disabled
since December 2007.
+* New commands
+
+ ** "catch load" and "catch unload" can be used to stop when a shared
+ library is loaded or unloaded, respectively.
+
*** Changes in GDB 7.4
* GDB now handles ambiguous linespecs more consistently; the existing
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index cf81498..0da099b 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -65,6 +65,7 @@
#include "stack.h"
#include "skip.h"
#include "record.h"
+#include "gdb_regex.h"
/* readline include files */
#include "readline/readline.h"
@@ -259,6 +260,11 @@ static int is_masked_watchpoint (const struct breakpoint *b);
static int strace_marker_p (struct breakpoint *b);
+static void init_catchpoint (struct breakpoint *b,
+ struct gdbarch *gdbarch, int tempflag,
+ char *cond_string,
+ const struct breakpoint_ops *ops);
+
/* The abstract base class all breakpoint_ops structures inherit
from. */
static struct breakpoint_ops base_breakpoint_ops;
@@ -3490,6 +3496,78 @@ print_bp_stop_message (bpstat bs)
}
}
+/* A helper function that prints a shared library stopped event. */
+
+static void
+print_solib_event (int is_catchpoint)
+{
+ int any_deleted
+ = !VEC_empty (char_ptr, current_program_space->deleted_solibs);
+ int any_added
+ = !VEC_empty (so_list_ptr, current_program_space->added_solibs);
+
+ if (!is_catchpoint)
+ {
+ if (any_added || any_deleted)
+ ui_out_text (current_uiout,
+ _("Stopped due to shared library event:\n"));
+ else
+ ui_out_text (current_uiout,
+ _("Stopped due to shared library event (no "
+ "libraries added or removed)\n"));
+ }
+
+ if (ui_out_is_mi_like_p (current_uiout))
+ ui_out_field_string (current_uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
+
+ if (any_deleted)
+ {
+ struct cleanup *cleanup;
+ char *name;
+ int ix;
+
+ ui_out_text (current_uiout, _(" Inferior unloaded "));
+ cleanup = make_cleanup_ui_out_list_begin_end (current_uiout,
+ "removed");
+ for (ix = 0;
+ VEC_iterate (char_ptr, current_program_space->deleted_solibs,
+ ix, name);
+ ++ix)
+ {
+ if (ix > 0)
+ ui_out_text (current_uiout, " ");
+ ui_out_field_string (current_uiout, "library", name);
+ ui_out_text (current_uiout, "\n");
+ }
+
+ do_cleanups (cleanup);
+ }
+
+ if (any_added)
+ {
+ struct so_list *iter;
+ int ix;
+ struct cleanup *cleanup;
+
+ ui_out_text (current_uiout, _(" Inferior loaded "));
+ cleanup = make_cleanup_ui_out_list_begin_end (current_uiout,
+ "added");
+ for (ix = 0;
+ VEC_iterate (so_list_ptr, current_program_space->added_solibs,
+ ix, iter);
+ ++ix)
+ {
+ if (ix > 0)
+ ui_out_text (current_uiout, " ");
+ ui_out_field_string (current_uiout, "library", iter->so_name);
+ ui_out_text (current_uiout, "\n");
+ }
+
+ do_cleanups (cleanup);
+ }
+}
+
/* Print a message indicating what happened. This is called from
normal_stop(). The input to this routine is the head of the bpstat
list - a list of the eventpoints that caused this stop. KIND is
@@ -3534,10 +3612,7 @@ bpstat_print (bpstat bs, int kind)
OS-level shared library event, do the same thing. */
if (kind == TARGET_WAITKIND_LOADED)
{
- ui_out_text (current_uiout, _("Stopped due to shared library event\n"));
- if (ui_out_is_mi_like_p (current_uiout))
- ui_out_field_string (current_uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
+ print_solib_event (0);
return PRINT_NOTHING;
}
@@ -4222,6 +4297,19 @@ bpstat_stop_status (struct address_space *aspace,
}
}
+ /* A bit of special processing for shlib breakpoints. We need to
+ process solib loading here, so that the lists of loaded and
+ unloaded libraries are correct before we handle "catch load" and
+ "catch unload". */
+ for (bs = bs_head; bs != NULL; bs = bs->next)
+ {
+ if (bs->breakpoint_at->type == bp_shlib_event)
+ {
+ handle_solib_event ();
+ break;
+ }
+ }
+
/* Now go through the locations that caused the target to stop, and
check whether we're interested in reporting this stop to higher
layers, or whether we should resume the target transparently. */
@@ -4311,6 +4399,25 @@ handle_jit_event (void)
target_terminal_inferior ();
}
+/* Handle an solib event by calling solib_add. */
+
+void
+handle_solib_event (void)
+{
+ clear_program_space_solib_cache (current_inferior ()->pspace);
+
+ /* Check for any newly added shared libraries if we're supposed to
+ be adding them automatically. Switch terminal for any messages
+ produced by breakpoint_re_set. */
+ target_terminal_ours_for_output ();
+#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 ();
+}
+
/* Prepare WHAT final decision for infrun. */
/* Decide what infrun needs to do with this bpstat. */
@@ -4319,10 +4426,6 @@ struct bpstat_what
bpstat_what (bpstat bs_head)
{
struct bpstat_what retval;
- /* We need to defer calling `solib_add', as adding new symbols
- resets breakpoints, which in turn deletes breakpoint locations,
- and hence may clear unprocessed entries in the BS chain. */
- int shlib_event = 0;
int jit_event = 0;
bpstat bs;
@@ -4346,9 +4449,6 @@ bpstat_what (bpstat bs_head)
else
bptype = bs->breakpoint_at->type;
- if (bptype == bp_shlib_event)
- shlib_event = 1;
-
switch (bptype)
{
case bp_none:
@@ -4480,27 +4580,6 @@ bpstat_what (bpstat bs_head)
/* These operations may affect the bs->breakpoint_at state so they are
delayed after MAIN_ACTION is decided above. */
- if (shlib_event)
- {
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "bpstat_what: bp_shlib_event\n");
-
- /* Check for any newly added shared libraries if we're supposed
- to be adding them automatically. */
-
- /* Switch terminal for any messages produced by
- breakpoint_re_set. */
- target_terminal_ours_for_output ();
-
-#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 ();
- }
-
if (jit_event)
{
if (debug_infrun)
@@ -6431,6 +6510,264 @@ print_recreate_catch_vfork (struct breakpoint *b, struct ui_file *fp)
static struct breakpoint_ops catch_vfork_breakpoint_ops;
+/* An instance of this type is used to represent an solib catchpoint.
+ It includes a "struct breakpoint" as a kind of base class; users
+ downcast to "struct breakpoint *" when needed. A breakpoint is
+ really of this type iff its ops pointer points to
+ CATCH_SOLIB_BREAKPOINT_OPS. */
+
+struct solib_catchpoint
+{
+ /* The base class. */
+ struct breakpoint base;
+
+ /* True for "catch load", false for "catch unload". */
+ unsigned char is_load;
+
+ /* Regular expression to match, if any. COMPILED is only valid when
+ REGEX is non-NULL. */
+ char *regex;
+ regex_t compiled;
+};
+
+static void
+dtor_catch_solib (struct breakpoint *b)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) b;
+
+ if (self->regex)
+ regfree (&self->compiled);
+ xfree (self->regex);
+
+ base_breakpoint_ops.dtor (b);
+}
+
+static int
+insert_catch_solib (struct bp_location *ignore)
+{
+ return 0;
+}
+
+static int
+remove_catch_solib (struct bp_location *ignore)
+{
+ return 0;
+}
+
+static int
+breakpoint_hit_catch_solib (const struct bp_location *bl,
+ struct address_space *aspace,
+ CORE_ADDR bp_addr,
+ const struct target_waitstatus *ws)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) bl->owner;
+ struct breakpoint *other;
+
+ if (ws->kind == TARGET_WAITKIND_LOADED)
+ return 1;
+
+ ALL_BREAKPOINTS (other)
+ {
+ struct bp_location *other_bl;
+
+ if (other == bl->owner)
+ continue;
+
+ if (other->type != bp_shlib_event)
+ continue;
+
+ if (self->base.pspace != NULL && other->pspace != self->base.pspace)
+ continue;
+
+ for (other_bl = other->loc; other_bl != NULL; other_bl = other_bl->next)
+ {
+ if (other->ops->breakpoint_hit (other_bl, aspace, bp_addr, ws))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+check_status_catch_solib (struct bpstats *bs)
+{
+ struct solib_catchpoint *self
+ = (struct solib_catchpoint *) bs->breakpoint_at;
+ int ix;
+
+ if (self->is_load)
+ {
+ struct so_list *iter;
+
+ for (ix = 0;
+ VEC_iterate (so_list_ptr, current_program_space->added_solibs,
+ ix, iter);
+ ++ix)
+ {
+ if (!self->regex
+ || regexec (&self->compiled, iter->so_name, 0, NULL, 0) == 0)
+ return;
+ }
+ }
+ else
+ {
+ char *iter;
+
+ for (ix = 0;
+ VEC_iterate (char_ptr, current_program_space->deleted_solibs,
+ ix, iter);
+ ++ix)
+ {
+ if (!self->regex
+ || regexec (&self->compiled, iter, 0, NULL, 0) == 0)
+ return;
+ }
+ }
+
+ bs->stop = 0;
+ bs->print_it = print_it_noop;
+}
+
+static enum print_stop_action
+print_it_catch_solib (bpstat bs)
+{
+ struct breakpoint *b = bs->breakpoint_at;
+ struct ui_out *uiout = current_uiout;
+
+ annotate_catchpoint (b->number);
+ if (b->disposition == disp_del)
+ ui_out_text (uiout, "\nTemporary catchpoint ");
+ else
+ ui_out_text (uiout, "\nCatchpoint ");
+ ui_out_field_int (uiout, "bkptno", b->number);
+ ui_out_text (uiout, "\n");
+ if (ui_out_is_mi_like_p (uiout))
+ ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ print_solib_event (1);
+ return PRINT_SRC_AND_LOC;
+}
+
+static void
+print_one_catch_solib (struct breakpoint *b, struct bp_location **locs)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) b;
+ struct value_print_options opts;
+ struct ui_out *uiout = current_uiout;
+ char *msg;
+
+ get_user_print_options (&opts);
+ /* Field 4, the address, is omitted (which makes the columns not
+ line up too nicely with the headers, but the effect is relatively
+ readable). */
+ if (opts.addressprint)
+ {
+ annotate_field (4);
+ ui_out_field_skip (uiout, "addr");
+ }
+
+ annotate_field (5);
+ if (self->is_load)
+ {
+ if (self->regex)
+ msg = xstrprintf (_("load of library matching %s"), self->regex);
+ else
+ msg = xstrdup (_("load of library"));
+ }
+ else
+ {
+ if (self->regex)
+ msg = xstrprintf (_("unload of library matching %s"), self->regex);
+ else
+ msg = xstrdup (_("unload of library"));
+ }
+ ui_out_field_string (uiout, "what", msg);
+ xfree (msg);
+}
+
+static void
+print_mention_catch_solib (struct breakpoint *b)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) b;
+
+ printf_filtered (_("Catchpoint %d (%s)"), b->number,
+ self->is_load ? "load" : "unload");
+}
+
+static void
+print_recreate_catch_solib (struct breakpoint *b, struct ui_file *fp)
+{
+ struct solib_catchpoint *self = (struct solib_catchpoint *) b;
+
+ fprintf_unfiltered (fp, "%s %s",
+ b->disposition == disp_del ? "tcatch" : "catch",
+ self->is_load ? "load" : "unload");
+ if (self->regex)
+ fprintf_unfiltered (fp, " %s", self->regex);
+ fprintf_unfiltered (fp, "\n");
+}
+
+static struct breakpoint_ops catch_solib_breakpoint_ops;
+
+/* A helper function that does all the work for "catch load" and
+ "catch unload". */
+
+static void
+catch_load_or_unload (char *arg, int from_tty, int is_load,
+ struct cmd_list_element *command)
+{
+ struct solib_catchpoint *c;
+ struct gdbarch *gdbarch = get_current_arch ();
+ int tempflag;
+ regex_t compiled;
+ struct cleanup *cleanup;
+
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
+ arg = skip_spaces (arg);
+
+ c = XCNEW (struct solib_catchpoint);
+ cleanup = make_cleanup (xfree, c);
+
+ if (*arg != '\0')
+ {
+ int errcode;
+
+ errcode = regcomp (&c->compiled, arg, REG_NOSUB);
+ if (errcode != 0)
+ {
+ char *err = get_regcomp_error (errcode, &c->compiled);
+
+ make_cleanup (xfree, err);
+ error (_("Invalid regexp (%s): %s"), err, arg);
+ }
+ c->regex = xstrdup (arg);
+ }
+
+ c->is_load = is_load;
+ init_catchpoint (&c->base, gdbarch, tempflag, NULL,
+ &catch_solib_breakpoint_ops);
+
+ discard_cleanups (cleanup);
+ install_breakpoint (0, &c->base, 1);
+}
+
+static void
+catch_load_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
+{
+ catch_load_or_unload (arg, from_tty, 1, command);
+}
+
+static void
+catch_unload_command_1 (char *arg, int from_tty,
+ struct cmd_list_element *command)
+{
+ catch_load_or_unload (arg, from_tty, 0, command);
+}
+
/* An instance of this type is used to represent a syscall catchpoint.
It includes a "struct breakpoint" as a kind of base class; users
downcast to "struct breakpoint *" when needed. A breakpoint is
@@ -11199,10 +11536,7 @@ internal_bkpt_print_it (bpstat bs)
/* Did we stop because the user set the stop_on_solib_events
variable? (If so, we report this as a generic, "Stopped due
to shlib event" message.) */
- ui_out_text (uiout, _("Stopped due to shared library event\n"));
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason",
- async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
+ print_solib_event (0);
break;
case bp_thread_event:
@@ -13841,6 +14175,19 @@ initialize_breakpoint_ops (void)
ops->print_one = print_one_catch_syscall;
ops->print_mention = print_mention_catch_syscall;
ops->print_recreate = print_recreate_catch_syscall;
+
+ /* Solib-related catchpoints. */
+ ops = &catch_solib_breakpoint_ops;
+ *ops = base_breakpoint_ops;
+ ops->dtor = dtor_catch_solib;
+ ops->insert_location = insert_catch_solib;
+ ops->remove_location = remove_catch_solib;
+ ops->breakpoint_hit = breakpoint_hit_catch_solib;
+ ops->check_status = check_status_catch_solib;
+ ops->print_it = print_it_catch_solib;
+ ops->print_one = print_one_catch_solib;
+ ops->print_mention = print_mention_catch_solib;
+ ops->print_recreate = print_recreate_catch_solib;
}
void
@@ -14144,6 +14491,20 @@ Catch an exception, when thrown."),
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
+ add_catch_command ("load", _("Catch loads of shared libraries.\n\
+Usage: catch load [REGEX]\n\
+If REGEX is given, only stop for libraries matching the regular expression."),
+ catch_load_command_1,
+ NULL,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+ add_catch_command ("unload", _("Catch unloads of shared libraries.\n\
+Usage: catch unload [REGEX]\n\
+If REGEX is given, only stop for libraries matching the regular expression."),
+ catch_unload_command_1,
+ NULL,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
add_catch_command ("syscall", _("\
Catch system calls by their names and/or numbers.\n\
Arguments say which system calls to catch. If no arguments\n\
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index dbae228..aa66790 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1419,4 +1419,6 @@ extern int user_breakpoint_p (struct breakpoint *);
/* Attempt to determine architecture of location identified by SAL. */
extern struct gdbarch *get_sal_arch (struct symtab_and_line sal);
+extern void handle_solib_event (void);
+
#endif /* !defined (BREAKPOINT_H) */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a1e937d..fa728db 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4113,6 +4113,12 @@ and @sc{gnu}/Linux.
A call to @code{vfork}. This is currently only available for HP-UX
and @sc{gnu}/Linux.
+@item load @r{[}regexp@r{]}
+@itemx unload @r{[}regexp@r{]}
+The loading or unloading of a shared library. If @var{regexp} is
+given, then the catchpoint will stop only if the regular expression
+matches one of the affected libraries.
+
@end table
@item tcatch @var{event}
@@ -15588,8 +15594,14 @@ discarded.
@end table
Sometimes you may wish that @value{GDBN} stops and gives you control
-when any of shared library events happen. Use the @code{set
-stop-on-solib-events} command for this:
+when any of shared library events happen. The best way to do this is
+to use @code{catch load} and @code{catch unload} (@pxref{Set
+Catchpoints}).
+
+@value{GDBN} also supports the the @code{set stop-on-solib-events}
+command for this. This command exists for historical reasons. It is
+less useful than setting a catchpoint, because it does not allow for
+conditions or commands as a catchpoint does.
@table @code
@item set stop-on-solib-events
@@ -26293,8 +26305,9 @@ The inferior exited normally.
A signal was received by the inferior.
@item solib-event
The inferior has stopped due to a library being loaded or unloaded.
-This can only happen when @code{stop-on-solib-events} (@pxref{Files})
-is set.
+This can happen when @code{stop-on-solib-events} (@pxref{Files}) is
+set or when a @code{catch load} or @code{catch unload} catchpoint is
+in use (@pxref{Set Catchpoints}).
@item fork
The inferior has forked. This is reported when @code{catch fork}
(@pxref{Set Catchpoints}) has been used.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index de4a8b7..bb4139a 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3316,28 +3316,32 @@ handle_inferior_event (struct execution_control_state *ecs)
established. */
if (stop_soon == NO_STOP_QUIETLY)
{
- /* Check for any newly added shared libraries if we're
- supposed to be adding them automatically. Switch
- terminal for any messages produced by
- breakpoint_re_set. */
- target_terminal_ours_for_output ();
- /* NOTE: cagney/2003-11-25: Make certain that the target
- stack's section table is kept up-to-date. Architectures,
- (e.g., PPC64), use the section table to perform
- operations such as address => section name and hence
- require the table to contain all sections (including
- those found in shared libraries). */
-#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 ();
+ struct regcache *regcache;
+
+ if (!ptid_equal (ecs->ptid, inferior_ptid))
+ context_switch (ecs->ptid);
+ regcache = get_thread_regcache (ecs->ptid);
+
+ handle_solib_event ();
+
+ ecs->event_thread->control.stop_bpstat
+ = bpstat_stop_status (get_regcache_aspace (regcache),
+ stop_pc, ecs->ptid, &ecs->ws);
+ ecs->random_signal
+ = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat);
+
+ if (!ecs->random_signal)
+ {
+ /* A catchpoint triggered. */
+ ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_TRAP;
+ goto process_event_stop_test;
+ }
/* 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). */
+ ecs->event_thread->suspend.stop_signal = TARGET_SIGNAL_0;
if (stop_on_solib_events)
{
/* Make sure we print "Stopped due to solib-event" in
@@ -3347,9 +3351,6 @@ handle_inferior_event (struct execution_control_state *ecs)
stop_stepping (ecs);
return;
}
-
- /* NOTE drow/2007-05-11: This might be a good place to check
- for "catch load". */
}
/* If we are skipping through a shell, or through shared library
diff --git a/gdb/progspace.c b/gdb/progspace.c
index 7175fa6..54531d9 100644
--- a/gdb/progspace.c
+++ b/gdb/progspace.c
@@ -149,6 +149,7 @@ release_program_space (struct program_space *pspace)
free_address_space (pspace->aspace);
resize_section_table (&pspace->target_sections,
-resize_section_table (&pspace->target_sections, 0));
+ clear_program_space_solib_cache (pspace);
/* Discard any data modules have associated with the PSPACE. */
program_space_free_data (pspace);
xfree (pspace);
@@ -503,6 +504,22 @@ switch_to_program_space_and_thread (struct program_space *pspace)
\f
+/* See progspace.h. */
+
+void
+clear_program_space_solib_cache (struct program_space *pspace)
+{
+ int ix;
+ char *name;
+
+ VEC_free (so_list_ptr, pspace->added_solibs);
+ for (ix = 0; VEC_iterate (char_ptr, pspace->deleted_solibs, ix, name); ++ix)
+ xfree (name);
+ VEC_free (char_ptr, pspace->deleted_solibs);
+}
+
+\f
+
/* Keep a registry of per-program_space data-pointers required by other GDB
modules. */
diff --git a/gdb/progspace.h b/gdb/progspace.h
index 9822f70..3db3938 100644
--- a/gdb/progspace.h
+++ b/gdb/progspace.h
@@ -23,6 +23,7 @@
#include "target.h"
#include "vec.h"
+#include "gdb_vecs.h"
struct target_ops;
struct bfd;
@@ -32,6 +33,9 @@ struct exec;
struct address_space;
struct program_space_data;
+typedef struct so_list *so_list_ptr;
+DEF_VEC_P (so_list_ptr);
+
/* A program space represents a symbolic view of an address space.
Roughly speaking, it holds all the data associated with a
non-running-yet program (main executable, main symbols), and when
@@ -188,6 +192,14 @@ struct program_space
/* Number of calls to solib_add. */
unsigned solib_add_generation;
+ /* When an solib is added, it is also added to this vector. This
+ is so we can properly report solib changes to the user. */
+ VEC (so_list_ptr) *added_solibs;
+
+ /* When an solib is removed, its name is added to this vector.
+ This is so we can properly report solib changes to the user. */
+ VEC (char_ptr) *deleted_solibs;
+
/* Per pspace data-pointers required by other GDB modules. */
void **data;
unsigned num_data;
@@ -278,6 +290,11 @@ extern void update_address_spaces (void);
anymore. */
extern void prune_program_spaces (void);
+/* Reset saved solib data at the start of an solib event. This lets
+ us properly collect the data when calling solib_add, so it can then
+ later be printed. */
+extern void clear_program_space_solib_cache (struct program_space *);
+
/* Keep a registry of per-pspace data-pointers required by other GDB
modules. */
diff --git a/gdb/solib.c b/gdb/solib.c
index f591785..84b9019 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -758,6 +758,9 @@ update_solib_list (int from_tty, struct target_ops *target)
unloaded before we remove it from GDB's tables. */
observer_notify_solib_unloaded (gdb);
+ VEC_safe_push (char_ptr, current_program_space->deleted_solibs,
+ xstrdup (gdb->so_name));
+
*gdb_link = gdb->next;
/* Unless the user loaded it explicitly, free SO's objfile. */
@@ -793,6 +796,7 @@ update_solib_list (int from_tty, struct target_ops *target)
volatile struct gdb_exception e;
i->pspace = current_program_space;
+ VEC_safe_push (so_list_ptr, current_program_space->added_solibs, i);
TRY_CATCH (e, RETURN_MASK_ERROR)
{
diff --git a/gdb/testsuite/gdb.base/break-interp.exp b/gdb/testsuite/gdb.base/break-interp.exp
index 5882cfe..04b5eab 100644
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -155,7 +155,7 @@ proc reach_1 {func command displacement} {
pass $test
}
}
- -re "Stopped due to shared library event\r\n$gdb_prompt $" {
+ -re "Stopped due to (spurious )?shared library event.*\r\n$gdb_prompt $" {
if {$func == "_dl_debug_state"} {
if {$debug_state_count == 0} {
# First stop does not yet relocate the _start function
diff --git a/gdb/testsuite/gdb.base/catch-load-so.c b/gdb/testsuite/gdb.base/catch-load-so.c
new file mode 100644
index 0000000..9676479
--- /dev/null
+++ b/gdb/testsuite/gdb.base/catch-load-so.c
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2012 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+int
+f(void)
+{
+ return 23;
+}
diff --git a/gdb/testsuite/gdb.base/catch-load.c b/gdb/testsuite/gdb.base/catch-load.c
new file mode 100644
index 0000000..170f581
--- /dev/null
+++ b/gdb/testsuite/gdb.base/catch-load.c
@@ -0,0 +1,35 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2012 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+/* This is updated by the .exp file. */
+char *libname = "catch-load-so.so";
+
+int
+main ()
+{
+ void *h;
+
+ h = dlopen (libname, RTLD_LAZY);
+
+ dlclose (h);
+
+ h = NULL; /* final breakpoint here */
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/catch-load.exp b/gdb/testsuite/gdb.base/catch-load.exp
new file mode 100644
index 0000000..af7114a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/catch-load.exp
@@ -0,0 +1,120 @@
+# Copyright 2012 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+if {[skip_shlib_tests]} {
+ untested catch-load.exp
+ return -1
+}
+
+if {[get_compiler_info not-used]} {
+ warning "Could not get compiler info"
+ untested catch-load.exp
+ return -1
+}
+
+set testfile catch-load
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug shlib_load}] != "" } {
+ untested catch-load.exp
+ return -1
+}
+
+set testfile2 catch-load-so
+set srcfile2 ${testfile2}.c
+set binfile2 ${objdir}/${subdir}/${testfile2}.so
+set binfile2_dlopen [shlib_target_file ${testfile2}.so]
+if { [gdb_compile_shlib "${srcdir}/${subdir}/${srcfile2}" ${binfile2} {debug}] != "" } {
+ untested catch-load.exp
+ return -1
+}
+
+# Run one set of tests.
+# SCENARIO is the name of the test scenario, it is just used in test
+# names.
+# KIND is passed to the "catch" command.
+# MATCH is a boolean saying whether we expect the catchpoint to be hit.
+proc one_catch_load_test {scenario kind match sostop} {
+ global verbose testfile testfile2 binfile2_dlopen
+ global pf_prefix srcfile
+ global decimal gdb_prompt
+
+ set saved_prefix $pf_prefix
+ append pf_prefix "${scenario}:"
+
+ clean_restart $testfile
+ gdb_load_shlibs $binfile2_dlopen
+
+ if {![runto_main]} {
+ fail "can't run to main"
+ set pf_prefix $saved_prefix
+ return
+ }
+
+ gdb_breakpoint [gdb_get_line_number "final breakpoint here"]
+ gdb_test_no_output "set var libname = \"$binfile2_dlopen\""
+ gdb_test_no_output "set stop-on-solib-events $sostop"
+ gdb_test "catch $kind" "Catchpoint $decimal \\(.*\\)"
+
+ send_gdb "continue\n"
+ gdb_test_multiple "continue" "continue" {
+ -re "Catchpoint $decimal\r\n.*loaded .*/$testfile2.*\r\n.*$gdb_prompt $" {
+ if {$match} {
+ pass "continue"
+ } else {
+ fail "continue"
+ }
+ }
+
+ -re "Stopped due to shared library event.*\r\n$gdb_prompt $" {
+ if {$sostop} {
+ pass "continue"
+ } else {
+ fail "continue"
+ }
+ }
+
+ -re "Breakpoint $decimal, .*\r\n$gdb_prompt $" {
+ if {!$match} {
+ pass "continue"
+ } else {
+ fail "continue"
+ }
+ }
+
+ -re ".*$gdb_prompt $" {
+ fail "continue"
+ }
+ }
+
+ set pf_prefix $saved_prefix
+}
+
+one_catch_load_test "plain load" "load" 1 0
+one_catch_load_test "plain load with stop-on-solib-events" "load" 1 1
+one_catch_load_test "rx load" "load $testfile2" 1 0
+one_catch_load_test "rx load with stop-on-solib-events" "load $testfile2" 1 1
+one_catch_load_test "non-matching load" "load zardoz" 0 0
+one_catch_load_test "non-matching load with stop-on-solib-events" \
+ "load zardoz" 0 1
+
+one_catch_load_test "plain unload" "unload" 1 0
+one_catch_load_test "plain unload with stop-on-solib-events" "unload" 1 1
+one_catch_load_test "rx unload" "unload $testfile2" 1 0
+one_catch_load_test "rx unload with stop-on-solib-events" \
+ "unload $testfile2" 1 1
+one_catch_load_test "non-matching unload" "unload zardoz" 0 0
+one_catch_load_test "non-matching unload with stop-on-solib-events" \
+ "unload zardoz" 0 1
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 4d40a1e..206f7b3 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -1060,6 +1060,8 @@ proc mi_expect_stop { reason func args file line extra test } {
set bn ""
if { $reason == "breakpoint-hit" } {
set bn {bkptno="[0-9]+",}
+ } elseif { $reason == "solib-event" } {
+ set bn ".*"
}
set r ""
--
1.7.6.5
^ permalink raw reply [flat|nested] 23+ messages in thread* Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload]
2012-01-24 22:11 ` Tom Tromey
@ 2012-01-25 11:06 ` Jan Kratochvil
2012-01-25 11:18 ` Regression for gdb.base/solib-disc.exp [Re: Regression for gdb.mi/mi-nsmoribund.exp] Jan Kratochvil
2012-01-25 16:20 ` Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload] Tom Tromey
2012-02-20 8:28 ` [commit] catch-load.exp: Fix racy FAILs " Jan Kratochvil
1 sibling, 2 replies; 23+ messages in thread
From: Jan Kratochvil @ 2012-01-25 11:06 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Tue, 24 Jan 2012 22:36:21 +0100, Tom Tromey wrote:
> Here is the version I am checking in.
commit 23be81b20039c057ad0af30082f6f8a16a7643e9
Author: Tom Tromey <tromey@redhat.com>
Date: Tue Jan 24 21:39:14 2012 +0000
PR symtab/12406:
It is crashing on all the tested Fedora distros for:
gdb.mi/mi-nsmoribund.exp
Thanks,
Jan
^ permalink raw reply [flat|nested] 23+ messages in thread* Regression for gdb.base/solib-disc.exp [Re: Regression for gdb.mi/mi-nsmoribund.exp]
2012-01-25 11:06 ` Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload] Jan Kratochvil
@ 2012-01-25 11:18 ` Jan Kratochvil
2012-01-25 17:09 ` Tom Tromey
2012-01-25 16:20 ` Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload] Tom Tromey
1 sibling, 1 reply; 23+ messages in thread
From: Jan Kratochvil @ 2012-01-25 11:18 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Wed, 25 Jan 2012 12:03:12 +0100, Jan Kratochvil wrote:
> On Tue, 24 Jan 2012 22:36:21 +0100, Tom Tromey wrote:
> > Here is the version I am checking in.
>
> commit 23be81b20039c057ad0af30082f6f8a16a7643e9
> Author: Tom Tromey <tromey@redhat.com>
> Date: Tue Jan 24 21:39:14 2012 +0000
> PR symtab/12406:
>
> It is crashing on all the tested Fedora distros for:
> gdb.mi/mi-nsmoribund.exp
And with gdbserver it is regressing:
-PASS: gdb.base/solib-disc.exp: continue to load
+FAIL: gdb.base/solib-disc.exp: continue to load
-PASS: gdb.base/solib-disc.exp: continue to unload
+FAIL: gdb.base/solib-disc.exp: continue to unload
I cannot evaluate the full testsuite results these days due to pending:
Performance regression (12x): Re: RFC: add relative file name handling for linespecs
http://sourceware.org/ml/gdb-patches/2012-01/msg00697.html
Thanks,
Jan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Regression for gdb.base/solib-disc.exp [Re: Regression for gdb.mi/mi-nsmoribund.exp]
2012-01-25 11:18 ` Regression for gdb.base/solib-disc.exp [Re: Regression for gdb.mi/mi-nsmoribund.exp] Jan Kratochvil
@ 2012-01-25 17:09 ` Tom Tromey
2012-01-25 17:27 ` Jan Kratochvil
0 siblings, 1 reply; 23+ messages in thread
From: Tom Tromey @ 2012-01-25 17:09 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches
>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
Jan> And with gdbserver it is regressing:
Jan> -PASS: gdb.base/solib-disc.exp: continue to load
Jan> +FAIL: gdb.base/solib-disc.exp: continue to load
Jan> -PASS: gdb.base/solib-disc.exp: continue to unload
Jan> +FAIL: gdb.base/solib-disc.exp: continue to unload
Here is the patch I am checking in.
The problem was just that the regexps needed updating.
Jan> I cannot evaluate the full testsuite results these days due to pending:
Jan> Performance regression (12x): Re: RFC: add relative file name
Jan> handling for linespecs
Jan> http://sourceware.org/ml/gdb-patches/2012-01/msg00697.html
This is next on my list.
Tom
2012-01-25 Tom Tromey <tromey@redhat.com>
* gdb.base/solib-disc.exp: Fix regexps.
diff --git a/gdb/testsuite/gdb.base/solib-disc.exp b/gdb/testsuite/gdb.base/solib-disc.exp
index e0d4875..0b1e9e7 100644
--- a/gdb/testsuite/gdb.base/solib-disc.exp
+++ b/gdb/testsuite/gdb.base/solib-disc.exp
@@ -62,7 +62,7 @@ if ![runto_main] then {
gdb_test_no_output "set stop-on-solib-events 1"
-gdb_test "continue" "Stopped due to shared library event" "continue to load"
+gdb_test "continue" "Stopped due to shared library event.*" "continue to load"
set msg "save \$pc after load"
set saved_pc ""
@@ -84,7 +84,7 @@ if { [gdb_reconnect] == 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"
+gdb_test "continue" "Stopped due to shared library event.*" "continue to unload"
set msg "save \$pc after unload"
set saved_pc ""
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: Regression for gdb.base/solib-disc.exp [Re: Regression for gdb.mi/mi-nsmoribund.exp]
2012-01-25 17:09 ` Tom Tromey
@ 2012-01-25 17:27 ` Jan Kratochvil
0 siblings, 0 replies; 23+ messages in thread
From: Jan Kratochvil @ 2012-01-25 17:27 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Wed, 25 Jan 2012 17:20:11 +0100, Tom Tromey wrote:
> The problem was just that the regexps needed updating.
Stopped due to shared library event (no libraries added or removed)^M
(gdb) FAIL: gdb.base/solib-disc.exp: continue to load
> -gdb_test "continue" "Stopped due to shared library event" "continue to load"
> +gdb_test "continue" "Stopped due to shared library event.*" "continue to load"
True, thanks.
Jan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload]
2012-01-25 11:06 ` Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload] Jan Kratochvil
2012-01-25 11:18 ` Regression for gdb.base/solib-disc.exp [Re: Regression for gdb.mi/mi-nsmoribund.exp] Jan Kratochvil
@ 2012-01-25 16:20 ` Tom Tromey
1 sibling, 0 replies; 23+ messages in thread
From: Tom Tromey @ 2012-01-25 16:20 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches
>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
Jan> commit 23be81b20039c057ad0af30082f6f8a16a7643e9
Jan> Author: Tom Tromey <tromey@redhat.com>
Jan> Date: Tue Jan 24 21:39:14 2012 +0000
Jan> PR symtab/12406:
Jan> It is crashing on all the tested Fedora distros for:
Jan> gdb.mi/mi-nsmoribund.exp
Here's the fix.
Built and regtested on x86-64 F15.
Tom
2012-01-25 Tom Tromey <tromey@redhat.com>
* breakpoint.c (bpstat_stop_status): Check 'breakpoint_at' before
dereferencing.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 0da099b..ec7f348 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4303,7 +4303,7 @@ bpstat_stop_status (struct address_space *aspace,
"catch unload". */
for (bs = bs_head; bs != NULL; bs = bs->next)
{
- if (bs->breakpoint_at->type == bp_shlib_event)
+ if (bs->breakpoint_at && bs->breakpoint_at->type == bp_shlib_event)
{
handle_solib_event ();
break;
^ permalink raw reply [flat|nested] 23+ messages in thread
* [commit] catch-load.exp: Fix racy FAILs [Re: [4/4] RFC: implement catch load and catch unload]
2012-01-24 22:11 ` Tom Tromey
2012-01-25 11:06 ` Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload] Jan Kratochvil
@ 2012-02-20 8:28 ` Jan Kratochvil
1 sibling, 0 replies; 23+ messages in thread
From: Jan Kratochvil @ 2012-02-20 8:28 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Tue, 24 Jan 2012 22:36:21 +0100, Tom Tromey wrote:
> gdb/testsuite
> * gdb.base/catch-load.exp: New file.
catch unload zardoz
Catchpoint 3 (unload)
(gdb) PASS: gdb.base/catch-load.exp:non-matching unload with stop-on-solib-events: catch unload zardoz
continue
Continuing.
Stopped due to shared library event (no libraries added or removed)
-(gdb) continue
-Continuing.
-Stopped due to shared library event:
- Inferior loaded gdb/testsuite.unix.-m32/gdb.base/catch-load-so.so
-(gdb) PASS: gdb.base/catch-load.exp:non-matching unload with stop-on-solib-events: continue
+c(gdb) FAIL: gdb.base/catch-load.exp:non-matching unload with stop-on-solib-events: continue
testcase gdb/testsuite/gdb.base/catch-load.exp completed in 18 seconds
Checked in, it looks to me like an obvious duplicate entry there.
Thanks,
Jan
http://sourceware.org/ml/gdb-cvs/2012-02/msg00112.html
--- src/gdb/testsuite/ChangeLog 2012/02/19 13:05:27 1.3079
+++ src/gdb/testsuite/ChangeLog 2012/02/20 06:20:27 1.3080
@@ -1,3 +1,9 @@
+2012-02-20 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ Fix racy FAILs.
+ * gdb.base/catch-load.exp (one_catch_load_test): Remove duplicate
+ "continue" command.
+
2012-02-19 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix for gdbserver non-extended mode.
--- src/gdb/testsuite/gdb.base/catch-load.exp 2012/01/24 21:39:18 1.1
+++ src/gdb/testsuite/gdb.base/catch-load.exp 2012/02/20 06:20:28 1.2
@@ -68,7 +68,6 @@
gdb_test_no_output "set stop-on-solib-events $sostop"
gdb_test "catch $kind" "Catchpoint $decimal \\(.*\\)"
- send_gdb "continue\n"
gdb_test_multiple "continue" "continue" {
-re "Catchpoint $decimal\r\n.*loaded .*/$testfile2.*\r\n.*$gdb_prompt $" {
if {$match} {
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2012-02-20 6:22 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-19 21:03 [4/4] RFC: implement catch load and catch unload Tom Tromey
2012-01-19 22:04 ` Eli Zaretskii
2012-01-20 15:12 ` Tom Tromey
2012-01-20 17:40 ` Pedro Alves
2012-01-24 17:31 ` Tom Tromey
2012-01-24 19:40 ` Pedro Alves
2012-01-20 17:44 ` Yao Qi
2012-01-20 19:45 ` Pedro Alves
2012-01-24 17:07 ` Tom Tromey
2012-01-24 17:28 ` Marc Khouzam
2012-01-24 18:25 ` Tom Tromey
2012-01-24 18:32 ` Marc Khouzam
2012-01-24 19:15 ` Tom Tromey
2012-01-24 20:36 ` Marc Khouzam
2012-01-24 17:22 ` Tom Tromey
2012-01-24 19:17 ` Pedro Alves
2012-01-24 22:11 ` Tom Tromey
2012-01-25 11:06 ` Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload] Jan Kratochvil
2012-01-25 11:18 ` Regression for gdb.base/solib-disc.exp [Re: Regression for gdb.mi/mi-nsmoribund.exp] Jan Kratochvil
2012-01-25 17:09 ` Tom Tromey
2012-01-25 17:27 ` Jan Kratochvil
2012-01-25 16:20 ` Regression for gdb.mi/mi-nsmoribund.exp [Re: [4/4] RFC: implement catch load and catch unload] Tom Tromey
2012-02-20 8:28 ` [commit] catch-load.exp: Fix racy FAILs " Jan Kratochvil
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox