2011-09-09 Gary Benson * Makefile.in (SFILES): Add solib-bp-disable.c. (HFILES_NO_SRCDIR): Add solib-bp-disable.h. (COMMON_OBS): Add solib-bp-disable.o. * infrun.c: Include solib-bp-disable.h. (set_stop_on_solib_events): New function. (_initialize_infrun): Add set_stop_on_solib_events. * solib-bp-disable.c: New file. * solib-bp-disable.h: Likewise. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 826d339..9e947d4 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -720,7 +720,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ serial.c ser-base.c ser-unix.c \ - solib.c solib-target.c source.c \ + solib.c solib-bp-disable.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ target.c target-descriptions.c target-memory.c \ @@ -821,7 +821,7 @@ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ gnulib/stddef.in.h inline-frame.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ -common/linux-osdata.h +common/linux-osdata.h solib-bp-disable.h # Header files that already have srcdir in them, or which are in objdir. @@ -902,7 +902,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ reggroups.o regset.o \ trad-frame.o \ tramp-frame.o \ - solib.o solib-target.o \ + solib.o solib-bp-disable.o solib-target.o \ prologue-value.o memory-map.o memrange.o \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ diff --git a/gdb/infrun.c b/gdb/infrun.c index 2b4f6db..fd57f49 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "solib-bp-disable.h" /* Prototypes for local functions */ @@ -320,6 +321,13 @@ static struct symbol *step_start_function; /* Nonzero if we want to give control to the user when we're notified of shared library events by the dynamic linker. */ int stop_on_solib_events; + +static void +set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c) +{ + update_solib_breakpoints (); +} + static void show_stop_on_solib_events (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -7096,7 +7104,7 @@ Show stopping for shared library events."), _("\ If nonzero, gdb will give control to the user when the dynamic linker\n\ notifies gdb of shared library events. The most common event of interest\n\ to the user would be loading/unloading of a new library."), - NULL, + set_stop_on_solib_events, show_stop_on_solib_events, &setlist, &showlist); diff --git a/gdb/solib-bp-disable.c b/gdb/solib-bp-disable.c new file mode 100644 index 0000000..c243a73 --- /dev/null +++ b/gdb/solib-bp-disable.c @@ -0,0 +1,153 @@ +/* Disable the shared library event breakpoint when unnecessary. + + Copyright (C) 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 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 . */ + +#include "defs.h" + +#include "breakpoint.h" +#include "inferior.h" +#include "observer.h" +#include "solib-bp-disable.h" +#include "solist.h" +#include "target.h" + +/* Nonzero if multi-threaded inferior support is present. */ + +static int +multi_thread_support_availabie (void) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_find_new_threads != NULL) + return 1; + + return 0; +} + +/* Nonzero if this breakpoint is pending in the current program space. */ + +static int +breakpoint_is_pending (struct breakpoint *b, void *arg) +{ + struct bp_location *loc; + + if (b->pspace != current_program_space) + return 0; + + if (b->loc == NULL) + return 1; + + for (loc = b->loc; loc; loc = loc->next) + if (loc->shlib_disabled && loc->pspace == current_program_space) + return 1; + + return 0; +} + +/* Nonzero if pending breakpoints exist in the current program space. */ + +static int +pending_breakpoints_exist (void) +{ + return iterate_over_breakpoints (breakpoint_is_pending, NULL) != NULL; +} + +/* Enable or disable a single solib event breakpoint as appropriate. */ + +static int +update_solib_breakpoint (struct breakpoint *b, void *arg) +{ + int enable = *(int *) arg; + struct bp_location *loc; + + if (b->pspace != current_program_space) + return 0; + + if (b->type != bp_shlib_event) + return 0; + + for (loc = b->loc; loc; loc = loc->next) + if (loc->pspace == current_program_space) + { + if (enable && b->enable_state == bp_disabled) + b->enable_state = bp_enabled; + else if (!enable && b->enable_state == bp_enabled) + b->enable_state = bp_disabled; + } + + return 0; +} + +/* Enable or disable solib event breakpoints as appropriate. */ + +void +update_solib_breakpoints () +{ + int enable = stop_on_solib_events + || !multi_thread_support_availabie () + || pending_breakpoints_exist (); + + iterate_over_breakpoints (update_solib_breakpoint, &enable); +} + +/* Wrappers to match the observer function pointer prototypes. */ + +static void +breakpoint_event (struct breakpoint *b) +{ + update_solib_breakpoints (); +} + +static void +inferior_event (struct target_ops *ops, int from_tty) +{ + update_solib_breakpoints (); +} + +static void +solib_event (struct so_list *s) +{ + update_solib_breakpoints (); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_solib_bp_disable; + +void +_initialize_solib_bp_disable (void) +{ + /* Observe breakpoint operations so we can enable the shared + library event breakpoint if there are breakpoints pending + on shared library loads. */ + observer_attach_breakpoint_created (breakpoint_event); + observer_attach_breakpoint_modified (breakpoint_event); + observer_attach_breakpoint_deleted (breakpoint_event); + + /* We also need to watch for inferior creation, because the + creation of the shared library event breakpoint does not + cause a breakpoint_created notification so inferior_created + is the next best thing. */ + observer_attach_inferior_created (inferior_event); + + /* Observe shared libraries being loaded and unloaded so we + can disable the shared library event breakpoint once a + thread debugging library has been loaded. */ + observer_attach_solib_loaded (solib_event); + observer_attach_solib_unloaded (solib_event); +} diff --git a/gdb/solib-bp-disable.h b/gdb/solib-bp-disable.h new file mode 100644 index 0000000..da883ab --- /dev/null +++ b/gdb/solib-bp-disable.h @@ -0,0 +1,27 @@ +/* Disable the shared library event breakpoint when unnecessary. + + Copyright (C) 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 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 . */ + +#ifndef SOLIB_BP_DISABLE_H +#define SOLIB_BP_DISABLE_H + +/* Enable or disable solib event breakpoints as appropriate. */ + +extern void update_solib_breakpoints (void); + +#endif /* SOLIB_BP_DISABLE_H */