diff options
86 files changed, 999 insertions, 1234 deletions
diff --git a/gdb/.gitignore b/gdb/.gitignore index e7e1087..b9b2c6f 100644 --- a/gdb/.gitignore +++ b/gdb/.gitignore @@ -21,7 +21,6 @@ /jv-exp.c /m2-exp.c /objc-exp.c -/observer.h /observer.inc /p-exp.c /rust-exp.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 634a414..fe4ae9f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,52 @@ +2018-03-19 Pedro Alves <palves@redhat.com> + Tom Tromey <tom@tromey.com> + + * unittests/observable-selftests.c: New file. + * common/observable.h: New file. + * observable.h: New file. + * ada-lang.c, ada-tasks.c, agent.c, aix-thread.c, annotate.c, + arm-tdep.c, auto-load.c, auxv.c, break-catch-syscall.c, + breakpoint.c, bsd-uthread.c, cli/cli-interp.c, cli/cli-setshow.c, + corefile.c, dummy-frame.c, event-loop.c, event-top.c, exec.c, + extension.c, frame.c, gdbarch.c, guile/scm-breakpoint.c, + infcall.c, infcmd.c, inferior.c, inflow.c, infrun.c, jit.c, + linux-tdep.c, linux-thread-db.c, m68klinux-tdep.c, + mi/mi-cmd-break.c, mi/mi-interp.c, mi/mi-main.c, objfiles.c, + ppc-linux-nat.c, ppc-linux-tdep.c, printcmd.c, procfs.c, + python/py-breakpoint.c, python/py-finishbreakpoint.c, + python/py-inferior.c, python/py-unwind.c, ravenscar-thread.c, + record-btrace.c, record-full.c, record.c, regcache.c, remote.c, + riscv-tdep.c, sol-thread.c, solib-aix.c, solib-spu.c, solib.c, + spu-multiarch.c, spu-tdep.c, stack.c, symfile-mem.c, symfile.c, + symtab.c, thread.c, top.c, tracepoint.c, tui/tui-hooks.c, + tui/tui-interp.c, valops.c: Update all users. + * tui/tui-hooks.c (tui_bp_created_observer) + (tui_bp_deleted_observer, tui_bp_modified_observer) + (tui_inferior_exit_observer, tui_before_prompt_observer) + (tui_normal_stop_observer, tui_register_changed_observer): + Remove. + (tui_observers_token): New global. + (attach_or_detach, tui_attach_detach_observers): New functions. + (tui_install_hooks, tui_remove_hooks): Use + tui_attach_detach_observers. + * record-btrace.c (record_btrace_thread_observer): Remove. + (record_btrace_thread_observer_token): New global. + * observer.sh: Remove. + * observer.c: Rename to observable.c. + * observable.c (namespace gdb_observers): Define new objects. + (observer_debug): Move into gdb_observers namespace. + (struct observer, struct observer_list, xalloc_observer_list_node) + (xfree_observer_list_node, generic_observer_attach) + (generic_observer_detach, generic_observer_notify): Remove. + (_initialize_observer): Update. + Don't include observer.inc. + * Makefile.in (generated_files): Remove observer.h, observer.inc. + (clean mostlyclean): Likewise. + (observer.h, observer.inc): Remove targets. + (SUBDIR_UNITTESTS_SRCS): Add observable-selftests.c. + (COMMON_SFILES): Use observable.c, not observer.c. + * .gitignore: Remove observer.h. + 2018-03-18 Tom Tromey <tom@tromey.com> * solib.c (gdb_bfd_lookup_symbol_from_symtab): Use diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 44db193..4dd9286 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -423,6 +423,7 @@ SUBDIR_UNITTESTS_SRCS = \ unittests/memory-map-selftests.c \ unittests/memrange-selftests.c \ unittests/offset-type-selftests.c \ + unittests/observable-selftests.c \ unittests/optional-selftests.c \ unittests/ptid-selftests.c \ unittests/rsp-low-selftests.c \ @@ -1057,7 +1058,7 @@ COMMON_SFILES = \ namespace.c \ objc-lang.c \ objfiles.c \ - observer.c \ + observable.c \ opencl-lang.c \ osabi.c \ osdata.c \ @@ -1589,8 +1590,6 @@ generated_files = \ config.h \ gcore \ jit-reader.h \ - observer.h \ - observer.inc \ $(GNULIB_H) \ $(NAT_GENERATED_FILES) @@ -1950,7 +1949,7 @@ tags: TAGS clean mostlyclean: $(CONFIG_CLEAN) @$(MAKE) $(FLAGS_TO_PASS) DO=clean "DODIRS=$(CLEANDIRS)" subdir_do rm -f *.o *.a $(ADD_FILES) *~ init.c-tmp init.l-tmp version.c-tmp - rm -f init.c version.c observer.h observer.inc + rm -f init.c version.c rm -f gdb$(EXEEXT) core make.log rm -f gdb[0-9]$(EXEEXT) rm -f test-cp-name-parser$(EXEEXT) @@ -2137,12 +2136,6 @@ version.c: Makefile version.in $(srcdir)/../bfd/version.h $(srcdir)/common/creat $(ECHO_GEN) $(SHELL) $(srcdir)/common/create-version.sh $(srcdir) \ $(host_alias) $(target_alias) version.c -observer.h: observer.sh doc/observer.texi - ${srcdir}/observer.sh h ${srcdir}/doc/observer.texi observer.h - -observer.inc: observer.sh doc/observer.texi - ${srcdir}/observer.sh inc ${srcdir}/doc/observer.texi observer.inc - lint: $(LINTFILES) $(LINT) $(INCLUDE_CFLAGS) $(LINTFLAGS) $(LINTFILES) \ `echo $(DEPFILES) $(CONFIG_OBS) | sed 's/\.o /\.c /g'` diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index ff9dff5..f8cefc1 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -48,7 +48,7 @@ #include "annotate.h" #include "valprint.h" #include "source.h" -#include "observer.h" +#include "observable.h" #include "vec.h" #include "stack.h" #include "gdb_vecs.h" @@ -14720,9 +14720,9 @@ DWARF attribute."), NULL, xcalloc, xfree); /* The ada-lang observers. */ - observer_attach_new_objfile (ada_new_objfile_observer); - observer_attach_free_objfile (ada_free_objfile_observer); - observer_attach_inferior_exit (ada_inferior_exit); + gdb::observers::new_objfile.attach (ada_new_objfile_observer); + gdb::observers::free_objfile.attach (ada_free_objfile_observer); + gdb::observers::inferior_exit.attach (ada_inferior_exit); /* Setup various context-specific data. */ ada_inferior_data diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c index d95d8b0..bbc0375 100644 --- a/gdb/ada-tasks.c +++ b/gdb/ada-tasks.c @@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "defs.h" -#include "observer.h" +#include "observable.h" #include "gdbcmd.h" #include "target.h" #include "ada-lang.h" @@ -1444,8 +1444,8 @@ _initialize_tasks (void) ada_tasks_inferior_data_handle = register_inferior_data (); /* Attach various observers. */ - observer_attach_normal_stop (ada_tasks_normal_stop_observer); - observer_attach_new_objfile (ada_tasks_new_objfile_observer); + gdb::observers::normal_stop.attach (ada_tasks_normal_stop_observer); + gdb::observers::new_objfile.attach (ada_tasks_new_objfile_observer); /* Some new commands provided by this module. */ add_info ("tasks", info_tasks_command, diff --git a/gdb/agent.c b/gdb/agent.c index 2b7fc8a..1d1f004 100644 --- a/gdb/agent.c +++ b/gdb/agent.c @@ -51,7 +51,7 @@ set_can_use_agent (const char *args, int from_tty, struct cmd_list_element *c) can_use_agent = can_use_agent_off; } -#include "observer.h" +#include "observable.h" #include "objfiles.h" static void @@ -66,7 +66,7 @@ agent_new_objfile (struct objfile *objfile) void _initialize_agent (void) { - observer_attach_new_objfile (agent_new_objfile); + gdb::observers::new_objfile.attach (agent_new_objfile); add_setshow_enum_cmd ("agent", class_run, can_use_agent_enum, diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c index 09d5175..d2b951d 100644 --- a/gdb/aix-thread.c +++ b/gdb/aix-thread.c @@ -46,7 +46,7 @@ #include "regcache.h" #include "gdbcmd.h" #include "ppc-tdep.h" -#include "observer.h" +#include "observable.h" #include "objfiles.h" #include <procinfo.h> @@ -1859,11 +1859,11 @@ _initialize_aix_thread (void) complete_target_initialization (&aix_thread_ops); /* Notice when object files get loaded and unloaded. */ - observer_attach_new_objfile (new_objfile); + gdb::observers::new_objfile.attach (new_objfile); /* Add ourselves to inferior_created event chain. This is needed to enable the thread target on "attach". */ - observer_attach_inferior_created (aix_thread_inferior_created); + gdb::observers::inferior_created.attach (aix_thread_inferior_created); add_setshow_boolean_cmd ("aix-thread", class_maintenance, &debug_aix_thread, _("Set debugging of AIX thread module."), diff --git a/gdb/annotate.c b/gdb/annotate.c index 0c70ff9..495aa2d 100644 --- a/gdb/annotate.c +++ b/gdb/annotate.c @@ -22,7 +22,7 @@ #include "target.h" #include "gdbtypes.h" #include "breakpoint.h" -#include "observer.h" +#include "observable.h" #include "inferior.h" #include "infrun.h" #include "top.h" @@ -592,7 +592,7 @@ breakpoint_changed (struct breakpoint *b) void _initialize_annotate (void) { - observer_attach_breakpoint_created (breakpoint_changed); - observer_attach_breakpoint_deleted (breakpoint_changed); - observer_attach_breakpoint_modified (breakpoint_changed); + gdb::observers::breakpoint_created.attach (breakpoint_changed); + gdb::observers::breakpoint_deleted.attach (breakpoint_changed); + gdb::observers::breakpoint_modified.attach (breakpoint_changed); } diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c index 484bd4e..d41ef72 100644 --- a/gdb/arm-linux-nat.c +++ b/gdb/arm-linux-nat.c @@ -24,7 +24,7 @@ #include "linux-nat.h" #include "target-descriptions.h" #include "auxv.h" -#include "observer.h" +#include "observable.h" #include "gdbthread.h" #include "arm-tdep.h" diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 539ee75..f64df4c 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -44,7 +44,7 @@ #include "remote.h" #include "target-descriptions.h" #include "user-regs.h" -#include "observer.h" +#include "observable.h" #include "arch/arm.h" #include "arch/arm-get-next-pcs.h" @@ -9547,7 +9547,7 @@ _initialize_arm_tdep (void) = register_objfile_data_with_cleanup (NULL, arm_objfile_data_free); /* Add ourselves to objfile event chain. */ - observer_attach_new_objfile (arm_exidx_new_objfile); + gdb::observers::new_objfile.attach (arm_exidx_new_objfile); arm_exidx_data_key = register_objfile_data_with_cleanup (NULL, arm_exidx_data_free); diff --git a/gdb/auto-load.c b/gdb/auto-load.c index 09ecb87..e426468 100644 --- a/gdb/auto-load.c +++ b/gdb/auto-load.c @@ -25,7 +25,7 @@ #include "ui-out.h" #include "filenames.h" #include "command.h" -#include "observer.h" +#include "observable.h" #include "objfiles.h" #include "cli/cli-script.h" #include "gdbcmd.h" @@ -1543,7 +1543,7 @@ _initialize_auto_load (void) = register_program_space_data_with_cleanup (NULL, auto_load_pspace_data_cleanup); - observer_attach_new_objfile (auto_load_new_objfile); + gdb::observers::new_objfile.attach (auto_load_new_objfile); add_setshow_boolean_cmd ("gdb-scripts", class_support, &auto_load_gdb_scripts, _("\ @@ -1653,7 +1653,7 @@ This options has security implications for untrusted inferiors."), show_auto_load_safe_path, auto_load_set_cmdlist_get (), auto_load_show_cmdlist_get ()); - observer_attach_gdb_datadir_changed (auto_load_gdb_datadir_changed); + gdb::observers::gdb_datadir_changed.attach (auto_load_gdb_datadir_changed); cmd = add_cmd ("add-auto-load-safe-path", class_support, add_auto_load_safe_path, @@ -24,7 +24,7 @@ #include "inferior.h" #include "valprint.h" #include "gdbcore.h" -#include "observer.h" +#include "observable.h" #include "filestuff.h" #include "objfiles.h" @@ -579,7 +579,7 @@ This is information provided by the operating system at program startup.")); = register_inferior_data_with_cleanup (NULL, auxv_inferior_data_cleanup); /* Observers used to invalidate the auxv cache when needed. */ - observer_attach_inferior_exit (invalidate_auxv_cache_inf); - observer_attach_inferior_appeared (invalidate_auxv_cache_inf); - observer_attach_executable_changed (invalidate_auxv_cache); + gdb::observers::inferior_exit.attach (invalidate_auxv_cache_inf); + gdb::observers::inferior_appeared.attach (invalidate_auxv_cache_inf); + gdb::observers::executable_changed.attach (invalidate_auxv_cache); } diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c index 42d4938..2fb5e61 100644 --- a/gdb/break-catch-syscall.c +++ b/gdb/break-catch-syscall.c @@ -27,7 +27,7 @@ #include "mi/mi-common.h" #include "valprint.h" #include "arch-utils.h" -#include "observer.h" +#include "observable.h" #include "xml-syscall.h" /* An instance of this type is used to represent a syscall catchpoint. @@ -632,7 +632,7 @@ _initialize_break_catch_syscall (void) { initialize_syscall_catchpoint_ops (); - observer_attach_inferior_exit (clear_syscall_counts); + gdb::observers::inferior_exit.attach (clear_syscall_counts); catch_syscall_inferior_data = register_inferior_data_with_cleanup (NULL, catch_syscall_inferior_data_cleanup); diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 454fda7..85f2fd8 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -49,7 +49,7 @@ #include "block.h" #include "solib.h" #include "solist.h" -#include "observer.h" +#include "observable.h" #include "memattr.h" #include "ada-lang.h" #include "top.h" @@ -903,7 +903,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp, } mark_breakpoint_modified (b); - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } /* Completion for the "condition" command. */ @@ -1172,7 +1172,7 @@ breakpoint_set_commands (struct breakpoint *b, validate_commands_for_breakpoint (b, commands.get ()); b->commands = std::move (commands); - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } /* Set the internal `silent' flag on the breakpoint. Note that this @@ -1186,7 +1186,7 @@ breakpoint_set_silent (struct breakpoint *b, int silent) b->silent = silent; if (old_silent != silent) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } /* Set the thread for this breakpoint. If THREAD is -1, make the @@ -1199,7 +1199,7 @@ breakpoint_set_thread (struct breakpoint *b, int thread) b->thread = thread; if (old_thread != thread) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } /* Set the task for this breakpoint. If TASK is 0, make the @@ -1212,7 +1212,7 @@ breakpoint_set_task (struct breakpoint *b, int task) b->task = task; if (old_task != task) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } void @@ -1269,7 +1269,7 @@ commands_command_1 (const char *arg, int from_tty, { validate_commands_for_breakpoint (b, cmd.get ()); b->commands = cmd; - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } }); } @@ -2655,7 +2655,7 @@ insert_bp_location (struct bp_location *bl, { /* See also: disable_breakpoints_in_shlibs. */ bl->shlib_disabled = 1; - observer_notify_breakpoint_modified (bl->owner); + gdb::observers::breakpoint_modified.notify (bl->owner); if (!*disabled_breaks) { fprintf_unfiltered (tmp_error_stream, @@ -5321,7 +5321,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) bs->stop = 0; /* Increase the hit count even though we don't stop. */ ++(b->hit_count); - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } } @@ -5476,7 +5476,7 @@ bpstat_stop_status (const address_space *aspace, if (bs->stop) { ++(b->hit_count); - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); /* We will stop here. */ if (b->disposition == disp_disable) @@ -7639,7 +7639,7 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib) loc->inserted = 0; /* This may cause duplicate notifications for the same breakpoint. */ - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); if (!disabled_shlib_breaks) { @@ -7722,7 +7722,7 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile) } if (bp_modified) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } } @@ -8250,7 +8250,7 @@ install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_ set_tracepoint_count (breakpoint_count); if (!internal) mention (b); - observer_notify_breakpoint_created (b); + gdb::observers::breakpoint_created.notify (b); if (update_gll) update_global_location_list (UGLL_MAY_INSERT); @@ -9989,7 +9989,7 @@ break_range_command (const char *arg, int from_tty) b->loc->length = length; mention (b); - observer_notify_breakpoint_created (b); + gdb::observers::breakpoint_created.notify (b); update_global_location_list (UGLL_MAY_INSERT); } @@ -11744,7 +11744,7 @@ download_tracepoint_locations (void) t = (struct tracepoint *) b; t->number_on_target = b->number; if (bp_location_downloaded) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } } @@ -13257,7 +13257,7 @@ delete_breakpoint (struct breakpoint *bpt) a problem in that process, we'll be asked to delete the half-created watchpoint. In that case, don't announce the deletion. */ if (bpt->number) - observer_notify_breakpoint_deleted (bpt); + gdb::observers::breakpoint_deleted.notify (bpt); if (breakpoint_chain == bpt) breakpoint_chain = bpt->next; @@ -13732,7 +13732,7 @@ update_breakpoint_locations (struct breakpoint *b, } if (!locations_are_equal (existing_locations, b->loc)) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } /* Find the SaL locations corresponding to the given LOCATION. @@ -14029,7 +14029,7 @@ set_ignore_count (int bptnum, int count, int from_tty) "crossings of breakpoint %d."), count, bptnum); } - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); return; } @@ -14332,7 +14332,7 @@ disable_breakpoint (struct breakpoint *bpt) update_global_location_list (UGLL_DONT_INSERT); - observer_notify_breakpoint_modified (bpt); + gdb::observers::breakpoint_modified.notify (bpt); } /* Enable or disable the breakpoint(s) or breakpoint location(s) @@ -14458,7 +14458,7 @@ enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition, bpt->enable_count = count; update_global_location_list (UGLL_MAY_INSERT); - observer_notify_breakpoint_modified (bpt); + gdb::observers::breakpoint_modified.notify (bpt); } @@ -14938,7 +14938,7 @@ static void trace_pass_set_count (struct tracepoint *tp, int count, int from_tty) { tp->pass_count = count; - observer_notify_breakpoint_modified (tp); + gdb::observers::breakpoint_modified.notify (tp); if (from_tty) printf_filtered (_("Setting tracepoint %d's passcount to %d\n"), tp->number, count); @@ -15578,9 +15578,9 @@ _initialize_breakpoint (void) initialize_breakpoint_ops (); - observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib); - observer_attach_free_objfile (disable_breakpoints_in_freed_objfile); - observer_attach_memory_changed (invalidate_bp_value_on_memory_change); + gdb::observers::solib_unloaded.attach (disable_breakpoints_in_unloaded_shlib); + gdb::observers::free_objfile.attach (disable_breakpoints_in_freed_objfile); + gdb::observers::memory_changed.attach (invalidate_bp_value_on_memory_change); breakpoint_objfile_key = register_objfile_data_with_cleanup (NULL, free_breakpoint_objfile_data); @@ -16131,6 +16131,6 @@ agent-printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\ automatic_hardware_breakpoints = 1; - observer_attach_about_to_proceed (breakpoint_about_to_proceed); - observer_attach_thread_exit (remove_threaded_breakpoints); + gdb::observers::about_to_proceed.attach (breakpoint_about_to_proceed); + gdb::observers::thread_exit.attach (remove_threaded_breakpoints); } diff --git a/gdb/bsd-uthread.c b/gdb/bsd-uthread.c index fdcac41..6c9e3af 100644 --- a/gdb/bsd-uthread.c +++ b/gdb/bsd-uthread.c @@ -22,7 +22,7 @@ #include "gdbthread.h" #include "inferior.h" #include "objfiles.h" -#include "observer.h" +#include "observable.h" #include "regcache.h" #include "solib.h" #include "solist.h" @@ -554,7 +554,7 @@ _initialize_bsd_uthread (void) bsd_uthread_data = gdbarch_data_register_pre_init (bsd_uthread_init); - observer_attach_inferior_created (bsd_uthread_inferior_created); - observer_attach_solib_loaded (bsd_uthread_solib_loaded); - observer_attach_solib_unloaded (bsd_uthread_solib_unloaded); + gdb::observers::inferior_created.attach (bsd_uthread_inferior_created); + gdb::observers::solib_loaded.attach (bsd_uthread_solib_loaded); + gdb::observers::solib_unloaded.attach (bsd_uthread_solib_unloaded); } diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c index 12b677f..bbee809 100644 --- a/gdb/cli/cli-interp.c +++ b/gdb/cli/cli-interp.c @@ -26,7 +26,7 @@ #include "top.h" /* for "execute_command" */ #include "event-top.h" #include "infrun.h" -#include "observer.h" +#include "observable.h" #include "gdbthread.h" #include "thread-fsm.h" @@ -461,14 +461,14 @@ _initialize_cli_interp (void) interp_factory_register (INTERP_CONSOLE, cli_interp_factory); /* If changing this, remember to update tui-interp.c as well. */ - observer_attach_normal_stop (cli_on_normal_stop); - observer_attach_end_stepping_range (cli_on_end_stepping_range); - observer_attach_signal_received (cli_on_signal_received); - observer_attach_signal_exited (cli_on_signal_exited); - observer_attach_exited (cli_on_exited); - observer_attach_no_history (cli_on_no_history); - observer_attach_sync_execution_done (cli_on_sync_execution_done); - observer_attach_command_error (cli_on_command_error); - observer_attach_user_selected_context_changed + gdb::observers::normal_stop.attach (cli_on_normal_stop); + gdb::observers::end_stepping_range.attach (cli_on_end_stepping_range); + gdb::observers::signal_received.attach (cli_on_signal_received); + gdb::observers::signal_exited.attach (cli_on_signal_exited); + gdb::observers::exited.attach (cli_on_exited); + gdb::observers::no_history.attach (cli_on_no_history); + gdb::observers::sync_execution_done.attach (cli_on_sync_execution_done); + gdb::observers::command_error.attach (cli_on_command_error); + gdb::observers::user_selected_context_changed.attach (cli_on_user_selected_context_changed); } diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c index f74a8ac..bb44468 100644 --- a/gdb/cli/cli-setshow.c +++ b/gdb/cli/cli-setshow.c @@ -20,7 +20,7 @@ #include "value.h" #include <ctype.h> #include "arch-utils.h" -#include "observer.h" +#include "observable.h" #include "ui-out.h" @@ -511,20 +511,20 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c) case var_filename: case var_optional_filename: case var_enum: - observer_notify_command_param_changed (name, *(char **) c->var); + gdb::observers::command_param_changed.notify (name, *(char **) c->var); break; case var_boolean: { const char *opt = *(int *) c->var ? "on" : "off"; - observer_notify_command_param_changed (name, opt); + gdb::observers::command_param_changed.notify (name, opt); } break; case var_auto_boolean: { const char *s = auto_boolean_enums[*(enum auto_boolean *) c->var]; - observer_notify_command_param_changed (name, s); + gdb::observers::command_param_changed.notify (name, s); } break; case var_uinteger: @@ -533,7 +533,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c) char s[64]; xsnprintf (s, sizeof s, "%u", *(unsigned int *) c->var); - observer_notify_command_param_changed (name, s); + gdb::observers::command_param_changed.notify (name, s); } break; case var_integer: @@ -543,7 +543,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c) char s[64]; xsnprintf (s, sizeof s, "%d", *(int *) c->var); - observer_notify_command_param_changed (name, s); + gdb::observers::command_param_changed.notify (name, s); } break; } diff --git a/gdb/common/observable.h b/gdb/common/observable.h new file mode 100644 index 0000000..f5666c1 --- /dev/null +++ b/gdb/common/observable.h @@ -0,0 +1,119 @@ +/* Observers + + Copyright (C) 2016-2018 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 <http://www.gnu.org/licenses/>. */ + +#if !defined (GDB_COMMON_OBSERVABLE_H) +#define GDB_COMMON_OBSERVABLE_H + +#include <algorithm> +#include <functional> +#include <vector> + +namespace gdb +{ + +namespace observers +{ + +extern unsigned int observer_debug; + +/* An observer is an entity which is interested in being notified + when GDB reaches certain states, or certain events occur in GDB. + The entity being observed is called the observable. To receive + notifications, the observer attaches a callback to the observable. + One observable can have several observers. + + The observer implementation is also currently not reentrant. In + particular, it is therefore not possible to call the attach or + detach routines during a notification. */ + +/* The type of a key that can be passed to attach, which can be passed + to detach to remove associated observers. Tokens have address + identity, and are thus usually const globals. */ +struct token +{ + token () = default; + + DISABLE_COPY_AND_ASSIGN (token); +}; + +template<typename... T> +class observable +{ +public: + + typedef std::function<void (T...)> func_type; + + explicit observable (const char *name) + : m_name (name) + { + } + + DISABLE_COPY_AND_ASSIGN (observable); + + /* Attach F as an observer to this observable. F cannot be + detached. */ + void attach (const func_type &f) + { + m_observers.emplace_back (nullptr, f); + } + + /* Attach F as an observer to this observable. T is a reference to + a token that can be used to later remove F. */ + void attach (const func_type &f, const token &t) + { + m_observers.emplace_back (&t, f); + } + + /* Remove observers associated with T from this observable. T is + the token that was previously passed to any number of "attach" + calls. */ + void detach (const token &t) + { + auto iter = std::remove_if (m_observers.begin (), + m_observers.end (), + [&] (const std::pair<const token *, + func_type> &e) + { + return e.first == &t; + }); + + m_observers.erase (iter, m_observers.end ()); + } + + /* Notify all observers that are attached to this observable. */ + void notify (T... args) const + { + if (observer_debug) + fprintf_unfiltered (gdb_stdlog, "observable %s notify() called\n", + m_name); + for (auto &&e : m_observers) + e.second (args...); + } + +private: + + std::vector<std::pair<const token *, func_type>> m_observers; + const char *m_name; +}; + +} /* namespace observers */ + +} /* namespace gdb */ + +#endif /* GDB_COMMON_OBSERVABLE_H */ diff --git a/gdb/corefile.c b/gdb/corefile.c index abf9ea6..5a73526 100644 --- a/gdb/corefile.c +++ b/gdb/corefile.c @@ -30,7 +30,7 @@ #include "dis-asm.h" #include <sys/stat.h> #include "completer.h" -#include "observer.h" +#include "observable.h" #include "cli/cli-utils.h" /* You can have any number of hooks for `exec_file_command' command to @@ -408,7 +408,7 @@ write_memory_with_notification (CORE_ADDR memaddr, const bfd_byte *myaddr, ssize_t len) { write_memory (memaddr, myaddr, len); - observer_notify_memory_changed (current_inferior (), memaddr, len, myaddr); + gdb::observers::memory_changed.notify (current_inferior (), memaddr, len, myaddr); } /* Store VALUE at ADDR in the inferior as a LEN-byte unsigned @@ -658,7 +658,7 @@ enum block_enum FIRST_LOCAL_BLOCK = 2 }; -/* User selection used in observer.h and multiple print functions. */ +/* User selection used in observable.h and multiple print functions. */ enum user_selected_what_flag { diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index dca13c6..2441f15 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2018-03-19 Tom Tromey <tom@tromey.com> + + * observer.texi: Remove. + 2018-03-04 John Baldwin <jhb@FreeBSD.org> * gdb.texinfo (Debugging Output): Document "set/show debug diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi deleted file mode 100644 index 8ab8da7..0000000 --- a/gdb/doc/observer.texi +++ /dev/null @@ -1,313 +0,0 @@ -@c -*-texinfo-*- - -@c This file is part of the GDB manual. -@c -@c Copyright (C) 2003-2018 Free Software Foundation, Inc. -@c -@c See the file gdbint.texinfo for copying conditions. -@c -@c Also, the @deftypefun lines from this file are processed into a -@c header file during the GDB build process. Permission is granted -@c to redistribute and/or modify those lines under the terms of the -@c GNU General Public License as published by the Free Software -@c Foundation; either version 3 of the License, or (at your option) -@c any later version. - -@node GDB Observers -@appendix @value{GDBN} Currently available observers - -@section Implementation rationale -@cindex observers implementation rationale - -An @dfn{observer} is an entity which is interested in being notified -when GDB reaches certain states, or certain events occur in GDB. -The entity being observed is called the @dfn{subject}. To receive -notifications, the observer attaches a callback to the subject. -One subject can have several observers. - -@file{observer.c} implements an internal generic low-level event -notification mechanism. This generic event notification mechanism is -then re-used to implement the exported high-level notification -management routines for all possible notifications. - -The current implementation of the generic observer provides support -for contextual data. This contextual data is given to the subject -when attaching the callback. In return, the subject will provide -this contextual data back to the observer as a parameter of the -callback. - -Note that the current support for the contextual data is only partial, -as it lacks a mechanism that would deallocate this data when the -callback is detached. This is not a problem so far, as this contextual -data is only used internally to hold a function pointer. Later on, if -a certain observer needs to provide support for user-level contextual -data, then the generic notification mechanism will need to be -enhanced to allow the observer to provide a routine to deallocate the -data when attaching the callback. - -The observer implementation is also currently not reentrant. -In particular, it is therefore not possible to call the attach -or detach routines during a notification. - -@section Debugging -Observer notifications can be traced using the command @samp{set debug -observer 1} (@pxref{Debugging Output, , Optional messages about -internal happenings, gdb, Debugging with @var{GDBN}}). - -@section @code{normal_stop} Notifications -@cindex @code{normal_stop} observer -@cindex notification about inferior execution stop - -@value{GDBN} notifies all @code{normal_stop} observers when the -inferior execution has just stopped, the associated messages and -annotations have been printed, and the control is about to be returned -to the user. - -Note that the @code{normal_stop} notification is not emitted when -the execution stops due to a breakpoint, and this breakpoint has -a condition that is not met. If the breakpoint has any associated -commands list, the commands are executed after the notification -is emitted. - -The following interfaces are available to manage observers: - -@deftypefun extern struct observer *observer_attach_@var{event} (observer_@var{event}_ftype *@var{f}) -Using the function @var{f}, create an observer that is notified when -ever @var{event} occurs, return the observer. -@end deftypefun - -@deftypefun extern void observer_detach_@var{event} (struct observer *@var{observer}); -Remove @var{observer} from the list of observers to be notified when -@var{event} occurs. -@end deftypefun - -@deftypefun extern void observer_notify_@var{event} (void); -Send a notification to all @var{event} observers. -@end deftypefun - -The following observable events are defined: - -@deftypefun void normal_stop (struct bpstats *@var{bs}, int @var{print_frame}) -The inferior has stopped for real. The @var{bs} argument describes -the breakpoints were are stopped at, if any. Second argument -@var{print_frame} non-zero means display the location where the -inferior has stopped. -@end deftypefun - -@deftypefun void signal_received (enum gdb_signal @var{siggnal}) -The inferior was stopped by a signal. -@end deftypefun - -@deftypefun void end_stepping_range (void) -We are done with a step/next/si/ni command. -@end deftypefun - -@deftypefun void signal_exited (enum gdb_signal @var{siggnal}) -The inferior was terminated by a signal. -@end deftypefun - -@deftypefun void exited (int @var{exitstatus}) -The inferior program is finished. -@end deftypefun - -@deftypefun void no_history (void) -Reverse execution: target ran out of history info. -@end deftypefun - -@deftypefun void sync_execution_done (void) -A synchronous command finished. -@end deftypefun - -@deftypefun void command_error (void) -An error was caught while executing a command. -@end deftypefun - -@deftypefun void target_changed (struct target_ops *@var{target}) -The target's register contents have changed. -@end deftypefun - -@deftypefun void executable_changed (void) -The executable being debugged by GDB has changed: The user decided -to debug a different program, or the program he was debugging has -been modified since being loaded by the debugger (by being recompiled, -for instance). -@end deftypefun - -@deftypefun void inferior_created (struct target_ops *@var{objfile}, int @var{from_tty}) -@value{GDBN} has just connected to an inferior. For @samp{run}, -@value{GDBN} calls this observer while the inferior is still stopped -at the entry-point instruction. For @samp{attach} and @samp{core}, -@value{GDBN} calls this observer immediately after connecting to the -inferior, and before any information on the inferior has been printed. -@end deftypefun - -@deftypefun void record_changed (struct inferior *@var{inferior}, int @var{started}, const char *@var{method}, const char *@var{format}) -The status of process record for inferior @var{inferior} in -@value{GDBN} has changed. The process record is started if -@var{started} is true, and the process record is stopped if -@var{started} is false. - -When @var{started} is true, @var{method} indicates the short name of the method -used for recording. If the method supports multiple formats, @var{format} -indicates which one is being used, otherwise it is NULL. When @var{started} is -false, they are both NULL. -@end deftypefun - -@deftypefun void solib_loaded (struct so_list *@var{solib}) -The shared library specified by @var{solib} has been loaded. Note that -when @value{GDBN} calls this observer, the library's symbols probably -haven't been loaded yet. -@end deftypefun - -@deftypefun void solib_unloaded (struct so_list *@var{solib}) -The shared library specified by @var{solib} has been unloaded. -Note that when @value{GDBN} calls this observer, the library's -symbols have not been unloaded yet, and thus are still available. -@end deftypefun - -@deftypefun void new_objfile (struct objfile *@var{objfile}) -The symbol file specified by @var{objfile} has been loaded. -Called with @var{objfile} equal to @code{NULL} to indicate -previously loaded symbol table data has now been invalidated. -@end deftypefun - -@deftypefun void free_objfile (struct objfile *@var{objfile}) -The object file specified by @var{objfile} is about to be freed. -@end deftypefun - -@deftypefun void new_thread (struct thread_info *@var{t}) -The thread specified by @var{t} has been created. -@end deftypefun - -@deftypefun void thread_exit (struct thread_info *@var{t}, int @var{silent}) -The thread specified by @var{t} has exited. The @var{silent} argument -indicates that @value{GDBN} is removing the thread from its tables -without wanting to notify the user about it. -@end deftypefun - -@deftypefun void thread_stop_requested (ptid_t @var{ptid}) -An explicit stop request was issued to @var{ptid}. If @var{ptid} -equals @var{minus_one_ptid}, the request applied to all threads. If -@code{ptid_is_pid(ptid)} returns true, the request applied to all -threads of the process pointed at by @var{ptid}. Otherwise, the -request applied to the single thread pointed at by @var{ptid}. -@end deftypefun - -@deftypefun void target_resumed (ptid_t @var{ptid}) -The target was resumed. The @var{ptid} parameter specifies which -thread was resume, and may be RESUME_ALL if all threads are resumed. -@end deftypefun - -@deftypefun void about_to_proceed (void) -The target is about to be proceeded. -@end deftypefun - -@deftypefun void breakpoint_created (struct breakpoint *@var{b}) -A new breakpoint @var{b} has been created. -@end deftypefun - -@deftypefun void breakpoint_deleted (struct breakpoint *@var{b}) -A breakpoint has been destroyed. The argument @var{b} is the -pointer to the destroyed breakpoint. -@end deftypefun - -@deftypefun void breakpoint_modified (struct breakpoint *@var{b}) -A breakpoint has been modified in some way. The argument @var{b} -is the modified breakpoint. -@end deftypefun - -@deftypefun void traceframe_changed (int @var{tfnum}, int @var{tpnum}) -The trace frame is changed to @var{tfnum} (e.g., by using the -@code{tfind} command). If @var{tfnum} is negative, it means -@value{GDBN} resumes live debugging. The number of the tracepoint -associated with this traceframe is @var{tpnum}. -@end deftypefun - -@deftypefun void architecture_changed (struct gdbarch *@var{newarch}) -The current architecture has changed. The argument @var{newarch} is -a pointer to the new architecture. -@end deftypefun - -@deftypefun void thread_ptid_changed (ptid_t @var{old_ptid}, ptid_t @var{new_ptid}) -The thread's ptid has changed. The @var{old_ptid} parameter specifies -the old value, and @var{new_ptid} specifies the new value. -@end deftypefun - -@deftypefun void inferior_added (struct inferior *@var{inf}) -The inferior @var{inf} has been added to the list of inferiors. At -this point, it might not be associated with any process. -@end deftypefun - -@deftypefun void inferior_appeared (struct inferior *@var{inf}) -The inferior identified by @var{inf} has been attached to a process. -@end deftypefun - -@deftypefun void inferior_exit (struct inferior *@var{inf}) -Either the inferior associated with @var{inf} has been detached from the -process, or the process has exited. -@end deftypefun - -@deftypefun void inferior_removed (struct inferior *@var{inf}) -The inferior @var{inf} has been removed from the list of inferiors. -This method is called immediately before freeing @var{inf}. -@end deftypefun - -@deftypefun void memory_changed (struct inferior *@var{inferior}, CORE_ADDR @var{addr}, ssize_t @var{len}, const bfd_byte *@var{data}) -Bytes from @var{data} to @var{data} + @var{len} have been written -to the @var{inferior} at @var{addr}. -@end deftypefun - -@deftypefun void before_prompt (const char *@var{current_prompt}) -Called before a top-level prompt is displayed. @var{current_prompt} is -the current top-level prompt. -@end deftypefun - -@deftypefun void gdb_datadir_changed (void) -Variable gdb_datadir has been set. The value may not necessarily change. -@end deftypefun - -@deftypefun void command_param_changed (const char *@var{param}, const char *@var{value}) -The parameter of some @code{set} commands in console are changed. This -method is called after a command @code{set @var{param} @var{value}}. -@var{param} is the parameter of @code{set} command, and @var{value} -is the value of changed parameter. -@end deftypefun - -@deftypefun void tsv_created (const struct trace_state_variable *@var{tsv}) -The new trace state variable @var{tsv} is created. -@end deftypefun - -@deftypefun void tsv_deleted (const struct trace_state_variable *@var{tsv}) -The trace state variable @var{tsv} is deleted. If @var{tsv} is -@code{NULL}, all trace state variables are deleted. -@end deftypefun - -@deftypefun void tsv_modified (const struct trace_state_variable *@var{tsv}) -The trace state value @var{tsv} is modified. -@end deftypefun - -@deftypefun void inferior_call_pre (ptid_t @var{thread}, CORE_ADDR @var{address}) -An inferior function at @var{address} is about to be called in thread -@var{thread}. -@end deftypefun - -@deftypefun void inferior_call_post (ptid_t @var{thread}, CORE_ADDR @var{address}) -The inferior function at @var{address} has just been called. This observer -is called even if the inferior exits during the call. @var{thread} is the -thread in which the function was called, which may be different from the -current thread. -@end deftypefun - -@deftypefun void register_changed (struct frame_info *@var{frame}, int @var{regnum}) -A register in the inferior has been modified by the @value{GDBN} user. -@end deftypefun - -@deftypefun void test_notification (int @var{somearg}) -This observer is used for internal testing. Do not use. -See testsuite/gdb.gdb/observer.exp. -@end deftypefun - -@deftypefun void user_selected_context_changed (user_selected_what @var{selection}) -The user-selected inferior, thread and/or frame has changed. The user_select_what -flag specifies if the inferior, thread and/or frame has changed. -@end deftypefun diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index a67033e..82e7251 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -26,7 +26,7 @@ #include "frame-unwind.h" #include "command.h" #include "gdbcmd.h" -#include "observer.h" +#include "observable.h" #include "gdbthread.h" #include "infcall.h" @@ -424,5 +424,5 @@ _initialize_dummy_frame (void) _("Print the contents of the internal dummy-frame stack."), &maintenanceprintlist); - observer_attach_inferior_created (cleanup_dummy_frames); + gdb::observers::inferior_created.attach (cleanup_dummy_frames); } diff --git a/gdb/event-loop.c b/gdb/event-loop.c index 7934ab4..9ca473e 100644 --- a/gdb/event-loop.c +++ b/gdb/event-loop.c @@ -34,7 +34,7 @@ #include <sys/types.h> #include "gdb_sys_time.h" #include "gdb_select.h" -#include "observer.h" +#include "observable.h" #include "top.h" /* Tell create_file_handler what events we are interested in. @@ -382,7 +382,7 @@ start_event_loop (void) get around to resetting the prompt, which leaves readline in a messed-up state. Reset it here. */ current_ui->prompt_state = PROMPT_NEEDED; - observer_notify_command_error (); + gdb::observers::command_error.notify (); /* This call looks bizarre, but it is required. If the user entered a command that caused an error, after_char_processing_hook won't be called from diff --git a/gdb/event-top.c b/gdb/event-top.c index 0c1528e..5852089 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -32,7 +32,7 @@ #include "cli/cli-script.h" /* for reset_command_nest_depth */ #include "main.h" #include "gdbthread.h" -#include "observer.h" +#include "observable.h" #include "continuations.h" #include "gdbcmd.h" /* for dont_repeat() */ #include "annotate.h" @@ -428,7 +428,7 @@ top_level_prompt (void) /* Give observers a chance of changing the prompt. E.g., the python `gdb.prompt_hook' is installed as an observer. */ - observer_notify_before_prompt (get_prompt ()); + gdb::observers::before_prompt.notify (get_prompt ()); prompt = get_prompt (); @@ -29,7 +29,7 @@ #include "completer.h" #include "value.h" #include "exec.h" -#include "observer.h" +#include "observable.h" #include "arch-utils.h" #include "gdbthread.h" #include "progspace.h" @@ -378,7 +378,7 @@ exec_file_attach (const char *filename, int from_tty) } bfd_cache_close_all (); - observer_notify_executable_changed (); + gdb::observers::executable_changed.notify (); } /* Process the first arg in ARGS as the new exec file. diff --git a/gdb/extension.c b/gdb/extension.c index 67f83b4..4e3b3e9 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -28,7 +28,7 @@ #include "event-top.h" #include "extension.h" #include "extension-priv.h" -#include "observer.h" +#include "observable.h" #include "cli/cli-script.h" #include "python/python.h" #include "guile/guile.h" @@ -945,5 +945,5 @@ ext_lang_before_prompt (const char *current_gdb_prompt) void _initialize_extension (void) { - observer_attach_before_prompt (ext_lang_before_prompt); + gdb::observers::before_prompt.attach (ext_lang_before_prompt); } diff --git a/gdb/frame.c b/gdb/frame.c index 0b04a4e..c792d1f 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -34,7 +34,7 @@ #include "frame-base.h" #include "command.h" #include "gdbcmd.h" -#include "observer.h" +#include "observable.h" #include "objfiles.h" #include "gdbthread.h" #include "block.h" @@ -2923,7 +2923,7 @@ _initialize_frame (void) frame_stash_create (); - observer_attach_target_changed (frame_observer_target_changed); + gdb::observers::target_changed.attach (frame_observer_target_changed); add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, _("\ Set backtrace specific variables.\n\ diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index b8703e5..ddafe25 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -44,7 +44,7 @@ #include "reggroups.h" #include "osabi.h" #include "gdb_obstack.h" -#include "observer.h" +#include "observable.h" #include "regcache.h" #include "objfiles.h" #include "auxv.h" @@ -5457,7 +5457,7 @@ set_target_gdbarch (struct gdbarch *new_gdbarch) gdb_assert (new_gdbarch != NULL); gdb_assert (new_gdbarch->initialized_p); current_inferior ()->gdbarch = new_gdbarch; - observer_notify_architecture_changed (new_gdbarch); + gdb::observers::architecture_changed.notify (new_gdbarch); registers_changed (); } diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c index 642eefd..75c24a5 100644 --- a/gdb/guile/scm-breakpoint.c +++ b/gdb/guile/scm-breakpoint.c @@ -25,7 +25,7 @@ #include "breakpoint.h" #include "gdbcmd.h" #include "gdbthread.h" -#include "observer.h" +#include "observable.h" #include "cli/cli-script.h" #include "ada-lang.h" #include "arch-utils.h" @@ -1327,8 +1327,8 @@ gdbscm_initialize_breakpoints (void) scm_set_smob_free (breakpoint_smob_tag, bpscm_free_breakpoint_smob); scm_set_smob_print (breakpoint_smob_tag, bpscm_print_breakpoint_smob); - observer_attach_breakpoint_created (bpscm_breakpoint_created); - observer_attach_breakpoint_deleted (bpscm_breakpoint_deleted); + gdb::observers::breakpoint_created.attach (bpscm_breakpoint_created); + gdb::observers::breakpoint_deleted.attach (bpscm_breakpoint_deleted); gdbscm_define_integer_constants (breakpoint_integer_constants, 1); gdbscm_define_functions (breakpoint_functions, 1); diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c index eaaa844..bb6ad25 100644 --- a/gdb/inf-loop.c +++ b/gdb/inf-loop.c @@ -29,7 +29,7 @@ #include "continuations.h" #include "interps.h" #include "top.h" -#include "observer.h" +#include "observable.h" /* General function to handle events in the inferior. */ diff --git a/gdb/infcall.c b/gdb/infcall.c index 54f82ba..9f02674 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -35,7 +35,7 @@ #include "ada-lang.h" #include "gdbthread.h" #include "event-top.h" -#include "observer.h" +#include "observable.h" #include "top.h" #include "interps.h" #include "thread-fsm.h" @@ -903,7 +903,7 @@ call_function_by_hand_dummy (struct value *function, target_values_type = values_type; } - observer_notify_inferior_call_pre (inferior_ptid, funaddr); + gdb::observers::inferior_call_pre.notify (inferior_ptid, funaddr); /* Determine the location of the breakpoint (and possibly other stuff) that the called function will return to. The SPARC, for a @@ -1176,7 +1176,7 @@ call_function_by_hand_dummy (struct value *function, e = run_inferior_call (sm, tp, real_pc); - observer_notify_inferior_call_post (call_thread_ptid, funaddr); + gdb::observers::inferior_call_post.notify (call_thread_ptid, funaddr); tp = find_thread_ptid (call_thread_ptid); if (tp != NULL) diff --git a/gdb/infcmd.c b/gdb/infcmd.c index c10a498..9c236b8 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -42,7 +42,7 @@ #include "block.h" #include "solib.h" #include <ctype.h> -#include "observer.h" +#include "observable.h" #include "target-descriptions.h" #include "user-regs.h" #include "cli/cli-decode.h" @@ -499,7 +499,7 @@ post_create_inferior (struct target_ops *target, int from_tty) if the now pushed target supports hardware watchpoints. */ breakpoint_re_set (); - observer_notify_inferior_created (target, from_tty); + gdb::observers::inferior_created.notify (target, from_tty); } /* Kill the inferior if already running. This function is designed diff --git a/gdb/inferior.c b/gdb/inferior.c index c88a23c..4ff5712 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -26,7 +26,7 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "ui-out.h" -#include "observer.h" +#include "observable.h" #include "gdbcore.h" #include "symfile.h" #include "environ.h" @@ -109,7 +109,7 @@ add_inferior_silent (int pid) last->next = inf; } - observer_notify_inferior_added (inf); + gdb::observers::inferior_added.notify (inf); if (pid != 0) inferior_appeared (inf, pid); @@ -176,7 +176,7 @@ delete_inferior (struct inferior *todel) else inferior_list = inf->next; - observer_notify_inferior_removed (inf); + gdb::observers::inferior_removed.notify (inf); /* If this program space is rendered useless, remove it. */ if (program_space_empty_p (inf->pspace)) @@ -206,7 +206,7 @@ exit_inferior_1 (struct inferior *inftoex, int silent) iterate_over_threads (delete_thread_of_inferior, &arg); - observer_notify_inferior_exit (inf); + gdb::observers::inferior_exit.notify (inf); inf->pid = 0; inf->fake_pid_p = 0; @@ -284,7 +284,7 @@ inferior_appeared (struct inferior *inf, int pid) inf->has_exit_code = 0; inf->exit_code = 0; - observer_notify_inferior_appeared (inf); + gdb::observers::inferior_appeared.notify (inf); } void @@ -713,7 +713,7 @@ inferior_command (const char *args, int from_tty) switch_to_thread (tp->ptid); } - observer_notify_user_selected_context_changed + gdb::observers::user_selected_context_changed.notify (USER_SELECTED_INFERIOR | USER_SELECTED_THREAD | USER_SELECTED_FRAME); @@ -724,7 +724,8 @@ inferior_command (const char *args, int from_tty) switch_to_thread (null_ptid); set_current_program_space (inf->pspace); - observer_notify_user_selected_context_changed (USER_SELECTED_INFERIOR); + gdb::observers::user_selected_context_changed.notify + (USER_SELECTED_INFERIOR); } } diff --git a/gdb/inflow.c b/gdb/inflow.c index d971543..08e47d6 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -24,7 +24,7 @@ #include "terminal.h" #include "target.h" #include "gdbthread.h" -#include "observer.h" +#include "observable.h" #include <signal.h> #include <fcntl.h> #include "gdb_select.h" @@ -989,7 +989,7 @@ _initialize_inflow (void) /* OK, figure out whether we have job control. */ have_job_control (); - observer_attach_inferior_exit (inflow_inferior_exit); + gdb::observers::inferior_exit.attach (inflow_inferior_exit); inflow_inferior_data = register_inferior_data_with_cleanup (NULL, inflow_inferior_data_cleanup); diff --git a/gdb/infrun.c b/gdb/infrun.c index 5aeafef..6648698 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -38,7 +38,7 @@ #include "inf-loop.h" #include "regcache.h" #include "value.h" -#include "observer.h" +#include "observable.h" #include "language.h" #include "solib.h" #include "main.h" @@ -2899,7 +2899,7 @@ clear_proceed_status (int step) inferior->control.stop_soon = NO_STOP_QUIETLY; } - observer_notify_about_to_proceed (); + gdb::observers::about_to_proceed.notify (); } /* Returns true if TP is still stopped at a breakpoint that needs @@ -3816,7 +3816,7 @@ check_curr_ui_sync_execution_done (void) && !gdb_in_secondary_prompt_p (ui)) { target_terminal::ours (); - observer_notify_sync_execution_done (); + gdb::observers::sync_execution_done.notify (); ui_register_input_event_handler (ui); } } @@ -5069,7 +5069,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs) /* Support the --return-child-result option. */ return_child_result_value = ecs->ws.value.integer; - observer_notify_exited (ecs->ws.value.integer); + gdb::observers::exited.notify (ecs->ws.value.integer); } else { @@ -5098,7 +5098,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs) Cannot fill $_exitsignal with the correct signal number.\n")); } - observer_notify_signal_exited (ecs->ws.value.sig); + gdb::observers::signal_exited.notify (ecs->ws.value.sig); } gdb_flush (gdb_stdout); @@ -5392,7 +5392,7 @@ Cannot fill $_exitsignal with the correct signal number.\n")); if (handle_stop_requested (ecs)) return; - observer_notify_no_history (); + gdb::observers::no_history.notify (); stop_waiting (ecs); return; } @@ -6096,7 +6096,7 @@ handle_signal_stop (struct execution_control_state *ecs) { /* The signal table tells us to print about this signal. */ target_terminal::ours_for_output (); - observer_notify_signal_received (ecs->event_thread->suspend.stop_signal); + gdb::observers::signal_received.notify (ecs->event_thread->suspend.stop_signal); target_terminal::inferior (); } @@ -8205,7 +8205,7 @@ normal_stop (void) update_thread_list (); if (last.kind == TARGET_WAITKIND_STOPPED && stopped_by_random_signal) - observer_notify_signal_received (inferior_thread ()->suspend.stop_signal); + gdb::observers::signal_received.notify (inferior_thread ()->suspend.stop_signal); /* As with the notification of thread events, we want to delay notifying the user that we've switched thread context until @@ -8330,10 +8330,10 @@ normal_stop (void) /* Notify observers about the stop. This is where the interpreters print the stop event. */ if (!ptid_equal (inferior_ptid, null_ptid)) - observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat, + gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat, stop_print_frame); else - observer_notify_normal_stop (NULL, stop_print_frame); + gdb::observers::normal_stop.notify (NULL, stop_print_frame); annotate_stopped (); @@ -9438,10 +9438,10 @@ enabled by default on some platforms."), inferior_ptid = null_ptid; target_last_wait_ptid = minus_one_ptid; - observer_attach_thread_ptid_changed (infrun_thread_ptid_changed); - observer_attach_thread_stop_requested (infrun_thread_stop_requested); - observer_attach_thread_exit (infrun_thread_thread_exit); - observer_attach_inferior_exit (infrun_inferior_exit); + gdb::observers::thread_ptid_changed.attach (infrun_thread_ptid_changed); + gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested); + gdb::observers::thread_exit.attach (infrun_thread_thread_exit); + gdb::observers::inferior_exit.attach (infrun_inferior_exit); /* Explicitly create without lookup, since that tries to create a value with a void typed value, and when we get here, gdbarch @@ -30,7 +30,7 @@ #include "gdbcmd.h" #include "gdbcore.h" #include "inferior.h" -#include "observer.h" +#include "observable.h" #include "objfiles.h" #include "regcache.h" #include "symfile.h" @@ -1499,9 +1499,9 @@ _initialize_jit (void) show_jit_debug, &setdebuglist, &showdebuglist); - observer_attach_inferior_created (jit_inferior_created); - observer_attach_inferior_exit (jit_inferior_exit_hook); - observer_attach_breakpoint_deleted (jit_breakpoint_deleted); + gdb::observers::inferior_created.attach (jit_inferior_created); + gdb::observers::inferior_exit.attach (jit_inferior_exit_hook); + gdb::observers::breakpoint_deleted.attach (jit_breakpoint_deleted); jit_objfile_data = register_objfile_data_with_cleanup (NULL, free_objfile_data); diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index b5bb162..b4b87dd 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -32,7 +32,7 @@ #include "cli/cli-utils.h" #include "arch-utils.h" #include "gdb_obstack.h" -#include "observer.h" +#include "observable.h" #include "objfiles.h" #include "infcall.h" #include "gdbcmd.h" @@ -2513,8 +2513,8 @@ _initialize_linux_tdep (void) linux_inferior_data = register_inferior_data_with_cleanup (NULL, linux_inferior_data_cleanup); /* Observers used to invalidate the cache when needed. */ - observer_attach_inferior_exit (invalidate_linux_cache_inf); - observer_attach_inferior_appeared (invalidate_linux_cache_inf); + gdb::observers::inferior_exit.attach (invalidate_linux_cache_inf); + gdb::observers::inferior_appeared.attach (invalidate_linux_cache_inf); add_setshow_boolean_cmd ("use-coredump-filter", class_files, &use_coredump_filter, _("\ diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c index 4da27b6..cfedd98 100644 --- a/gdb/linux-thread-db.c +++ b/gdb/linux-thread-db.c @@ -35,7 +35,7 @@ #include "solib.h" #include "solib-svr4.h" #include "gdbcore.h" -#include "observer.h" +#include "observable.h" #include "linux-nat.h" #include "nat/linux-procfs.h" #include "nat/linux-ptrace.h" @@ -960,7 +960,7 @@ thread_db_new_objfile (struct objfile *objfile) if (objfile != NULL /* libpthread with separate debug info has its debug info file already loaded (and notified without successful thread_db initialization) - the time observer_notify_new_objfile is called for the library itself. + the time gdb::observers::new_objfile.notify is called for the library itself. Static executables have their separate debug info loaded already before the inferior has started. */ && objfile->separate_debug_objfile_backlink == NULL @@ -1715,10 +1715,10 @@ Usage: info auto-load libthread-db"), auto_load_info_cmdlist_get ()); /* Add ourselves to objfile event chain. */ - observer_attach_new_objfile (thread_db_new_objfile); + gdb::observers::new_objfile.attach (thread_db_new_objfile); /* Add ourselves to inferior_created event chain. This is needed to handle debugging statically linked programs where the new_objfile observer won't get called for libpthread. */ - observer_attach_inferior_created (thread_db_inferior_created); + gdb::observers::inferior_created.attach (thread_db_inferior_created); } diff --git a/gdb/m68k-linux-tdep.c b/gdb/m68k-linux-tdep.c index e26ceab..11cde0b 100644 --- a/gdb/m68k-linux-tdep.c +++ b/gdb/m68k-linux-tdep.c @@ -32,7 +32,7 @@ #include "glibc-tdep.h" #include "solib-svr4.h" #include "auxv.h" -#include "observer.h" +#include "observable.h" #include "elf/common.h" #include "linux-tdep.h" #include "regset.h" @@ -426,5 +426,5 @@ _initialize_m68k_linux_tdep (void) { gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_LINUX, m68k_linux_init_abi); - observer_attach_inferior_created (m68k_linux_inferior_created); + gdb::observers::inferior_created.attach (m68k_linux_inferior_created); } diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index 243a9d0..c1f5e2d 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -24,7 +24,7 @@ #include "mi-out.h" #include "breakpoint.h" #include "mi-getopt.h" -#include "observer.h" +#include "observable.h" #include "mi-main.h" #include "mi-cmd-break.h" #include "language.h" @@ -84,7 +84,7 @@ setup_breakpoint_reporting (void) { if (! mi_breakpoint_observers_installed) { - observer_attach_breakpoint_created (breakpoint_notify); + gdb::observers::breakpoint_created.attach (breakpoint_notify); mi_breakpoint_observers_installed = 1; } @@ -394,7 +394,7 @@ mi_cmd_break_passcount (const char *command, char **argv, int argc) if (t) { t->pass_count = p; - observer_notify_breakpoint_modified (t); + gdb::observers::breakpoint_modified.notify (t); } else { diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 2ec1d69..0a96138 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -30,7 +30,7 @@ #include "mi-out.h" #include "mi-console.h" #include "mi-common.h" -#include "observer.h" +#include "observable.h" #include "gdbthread.h" #include "solist.h" #include "objfiles.h" @@ -1353,33 +1353,33 @@ _initialize_mi_interp (void) interp_factory_register (INTERP_MI3, mi_interp_factory); interp_factory_register (INTERP_MI, mi_interp_factory); - observer_attach_signal_received (mi_on_signal_received); - observer_attach_end_stepping_range (mi_on_end_stepping_range); - observer_attach_signal_exited (mi_on_signal_exited); - observer_attach_exited (mi_on_exited); - observer_attach_no_history (mi_on_no_history); - observer_attach_new_thread (mi_new_thread); - observer_attach_thread_exit (mi_thread_exit); - observer_attach_inferior_added (mi_inferior_added); - observer_attach_inferior_appeared (mi_inferior_appeared); - observer_attach_inferior_exit (mi_inferior_exit); - observer_attach_inferior_removed (mi_inferior_removed); - observer_attach_record_changed (mi_record_changed); - observer_attach_normal_stop (mi_on_normal_stop); - observer_attach_target_resumed (mi_on_resume); - observer_attach_solib_loaded (mi_solib_loaded); - observer_attach_solib_unloaded (mi_solib_unloaded); - observer_attach_about_to_proceed (mi_about_to_proceed); - observer_attach_traceframe_changed (mi_traceframe_changed); - observer_attach_tsv_created (mi_tsv_created); - observer_attach_tsv_deleted (mi_tsv_deleted); - observer_attach_tsv_modified (mi_tsv_modified); - observer_attach_breakpoint_created (mi_breakpoint_created); - observer_attach_breakpoint_deleted (mi_breakpoint_deleted); - observer_attach_breakpoint_modified (mi_breakpoint_modified); - observer_attach_command_param_changed (mi_command_param_changed); - observer_attach_memory_changed (mi_memory_changed); - observer_attach_sync_execution_done (mi_on_sync_execution_done); - observer_attach_user_selected_context_changed + gdb::observers::signal_received.attach (mi_on_signal_received); + gdb::observers::end_stepping_range.attach (mi_on_end_stepping_range); + gdb::observers::signal_exited.attach (mi_on_signal_exited); + gdb::observers::exited.attach (mi_on_exited); + gdb::observers::no_history.attach (mi_on_no_history); + gdb::observers::new_thread.attach (mi_new_thread); + gdb::observers::thread_exit.attach (mi_thread_exit); + gdb::observers::inferior_added.attach (mi_inferior_added); + gdb::observers::inferior_appeared.attach (mi_inferior_appeared); + gdb::observers::inferior_exit.attach (mi_inferior_exit); + gdb::observers::inferior_removed.attach (mi_inferior_removed); + gdb::observers::record_changed.attach (mi_record_changed); + gdb::observers::normal_stop.attach (mi_on_normal_stop); + gdb::observers::target_resumed.attach (mi_on_resume); + gdb::observers::solib_loaded.attach (mi_solib_loaded); + gdb::observers::solib_unloaded.attach (mi_solib_unloaded); + gdb::observers::about_to_proceed.attach (mi_about_to_proceed); + gdb::observers::traceframe_changed.attach (mi_traceframe_changed); + gdb::observers::tsv_created.attach (mi_tsv_created); + gdb::observers::tsv_deleted.attach (mi_tsv_deleted); + gdb::observers::tsv_modified.attach (mi_tsv_modified); + gdb::observers::breakpoint_created.attach (mi_breakpoint_created); + gdb::observers::breakpoint_deleted.attach (mi_breakpoint_deleted); + gdb::observers::breakpoint_modified.attach (mi_breakpoint_modified); + gdb::observers::command_param_changed.attach (mi_command_param_changed); + gdb::observers::memory_changed.attach (mi_memory_changed); + gdb::observers::sync_execution_done.attach (mi_on_sync_execution_done); + gdb::observers::user_selected_context_changed.attach (mi_user_selected_context_changed); } diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 1716a7f..9c4e44b 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -52,7 +52,7 @@ #include "linespec.h" #include "extension.h" #include "gdbcmd.h" -#include "observer.h" +#include "observable.h" #include "common/gdb_optional.h" #include "common/byte-vector.h" @@ -573,8 +573,8 @@ mi_cmd_thread_select (const char *command, char **argv, int argc) /* Notify if the thread has effectively changed. */ if (!ptid_equal (inferior_ptid, previous_ptid)) { - observer_notify_user_selected_context_changed (USER_SELECTED_THREAD - | USER_SELECTED_FRAME); + gdb::observers::user_selected_context_changed.notify + (USER_SELECTED_THREAD | USER_SELECTED_FRAME); } } @@ -2024,8 +2024,8 @@ mi_execute_command (const char *cmd, int from_tty) if (report_change) { - observer_notify_user_selected_context_changed - (USER_SELECTED_THREAD | USER_SELECTED_FRAME); + gdb::observers::user_selected_context_changed.notify + (USER_SELECTED_THREAD | USER_SELECTED_FRAME); } } } diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 3a57735..98e81c4 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -46,7 +46,7 @@ #include "addrmap.h" #include "arch-utils.h" #include "exec.h" -#include "observer.h" +#include "observable.h" #include "complaints.h" #include "psymtab.h" #include "solist.h" @@ -617,7 +617,7 @@ free_objfile_separate_debug (struct objfile *objfile) objfile::~objfile () { /* First notify observers that this objfile is about to be freed. */ - observer_notify_free_objfile (this); + gdb::observers::free_objfile.notify (this); /* Free all separate debug objfiles. */ free_objfile_separate_debug (this); diff --git a/gdb/observable.c b/gdb/observable.c new file mode 100644 index 0000000..5539b98 --- /dev/null +++ b/gdb/observable.c @@ -0,0 +1,99 @@ +/* GDB Notifications to Observers. + + Copyright (C) 2003-2018 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 <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "observable.h" +#include "command.h" +#include "gdbcmd.h" + +namespace gdb +{ + +namespace observers +{ + +unsigned int observer_debug; + +#define DEFINE_OBSERVABLE(name) decltype (name) name (# name) + +DEFINE_OBSERVABLE (normal_stop); +DEFINE_OBSERVABLE (signal_received); +DEFINE_OBSERVABLE (end_stepping_range); +DEFINE_OBSERVABLE (signal_exited); +DEFINE_OBSERVABLE (exited); +DEFINE_OBSERVABLE (no_history); +DEFINE_OBSERVABLE (sync_execution_done); +DEFINE_OBSERVABLE (command_error); +DEFINE_OBSERVABLE (target_changed); +DEFINE_OBSERVABLE (executable_changed); +DEFINE_OBSERVABLE (inferior_created); +DEFINE_OBSERVABLE (record_changed); +DEFINE_OBSERVABLE (solib_loaded); +DEFINE_OBSERVABLE (solib_unloaded); +DEFINE_OBSERVABLE (new_objfile); +DEFINE_OBSERVABLE (free_objfile); +DEFINE_OBSERVABLE (new_thread); +DEFINE_OBSERVABLE (thread_exit); +DEFINE_OBSERVABLE (thread_stop_requested); +DEFINE_OBSERVABLE (target_resumed); +DEFINE_OBSERVABLE (about_to_proceed); +DEFINE_OBSERVABLE (breakpoint_created); +DEFINE_OBSERVABLE (breakpoint_deleted); +DEFINE_OBSERVABLE (breakpoint_modified); +DEFINE_OBSERVABLE (traceframe_changed); +DEFINE_OBSERVABLE (architecture_changed); +DEFINE_OBSERVABLE (thread_ptid_changed); +DEFINE_OBSERVABLE (inferior_added); +DEFINE_OBSERVABLE (inferior_appeared); +DEFINE_OBSERVABLE (inferior_exit); +DEFINE_OBSERVABLE (inferior_removed); +DEFINE_OBSERVABLE (memory_changed); +DEFINE_OBSERVABLE (before_prompt); +DEFINE_OBSERVABLE (gdb_datadir_changed); +DEFINE_OBSERVABLE (command_param_changed); +DEFINE_OBSERVABLE (tsv_created); +DEFINE_OBSERVABLE (tsv_deleted); +DEFINE_OBSERVABLE (tsv_modified); +DEFINE_OBSERVABLE (inferior_call_pre); +DEFINE_OBSERVABLE (inferior_call_post); +DEFINE_OBSERVABLE (register_changed); +DEFINE_OBSERVABLE (user_selected_context_changed); + +} /* namespace observers */ +} /* namespace gdb */ + +static void +show_observer_debug (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Observer debugging is %s.\n"), value); +} + +void +_initialize_observer (void) +{ + add_setshow_zuinteger_cmd ("observer", class_maintenance, + &gdb::observers::observer_debug, _("\ +Set observer debugging."), _("\ +Show observer debugging."), _("\ +When non-zero, observer debugging is enabled."), + NULL, + show_observer_debug, + &setdebuglist, &showdebuglist); +} diff --git a/gdb/observable.h b/gdb/observable.h new file mode 100644 index 0000000..34447b9 --- /dev/null +++ b/gdb/observable.h @@ -0,0 +1,235 @@ +/* Observers + + Copyright (C) 2016-2018 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 <http://www.gnu.org/licenses/>. */ + +#if !defined (GDB_OBSERVER_H) +#define GDB_OBSERVER_H + +#include "common/observable.h" + +struct bpstats; +struct so_list; +struct objfile; +struct thread_info; +struct inferior; +struct trace_state_variable; + +namespace gdb +{ + +namespace observers +{ + +/* The inferior has stopped for real. The bs argument describes the + breakpoints were are stopped at, if any. Second argument + print_frame non-zero means display the location where the + inferior has stopped. + + gdb notifies all normal_stop observers when the inferior execution + has just stopped, the associated messages and annotations have been + printed, and the control is about to be returned to the user. + + Note that the normal_stop notification is not emitted when the + execution stops due to a breakpoint, and this breakpoint has a + condition that is not met. If the breakpoint has any associated + commands list, the commands are executed after the notification is + emitted. */ +extern observable<struct bpstats *, int> normal_stop; + +/* The inferior was stopped by a signal. */ +extern observable<enum gdb_signal> signal_received; + +/* We are done with a step/next/si/ni command. */ +extern observable<> end_stepping_range; + +/* The inferior was terminated by a signal. */ +extern observable<enum gdb_signal> signal_exited; + +/* The inferior program is finished. */ +extern observable<int> exited; + +/* Reverse execution: target ran out of history info. */ +extern observable<> no_history; + +/* A synchronous command finished. */ +extern observable<> sync_execution_done; + +/* An error was caught while executing a command. */ +extern observable<> command_error; + +/* The target's register contents have changed. */ +extern observable<struct target_ops *> target_changed; + +/* The executable being debugged by GDB has changed: The user + decided to debug a different program, or the program he was + debugging has been modified since being loaded by the debugger + (by being recompiled, for instance). */ +extern observable<> executable_changed; + +/* gdb has just connected to an inferior. For 'run', gdb calls this + observer while the inferior is still stopped at the entry-point + instruction. For 'attach' and 'core', gdb calls this observer + immediately after connecting to the inferior, and before any + information on the inferior has been printed. */ +extern observable<struct target_ops *, int> inferior_created; + +/* The status of process record for inferior inferior in gdb has + changed. The process record is started if started is true, and + the process record is stopped if started is false. + + When started is true, method indicates the short name of the + method used for recording. If the method supports multiple + formats, format indicates which one is being used, otherwise it + is NULL. When started is false, they are both NULL. */ +extern observable<struct inferior *, int, const char *, const char *> + record_changed; + +/* The shared library specified by solib has been loaded. Note that + when gdb calls this observer, the library's symbols probably + haven't been loaded yet. */ +extern observable<struct so_list *> solib_loaded; + +/* The shared library specified by solib has been unloaded. Note + that when gdb calls this observer, the library's symbols have not + been unloaded yet, and thus are still available. */ +extern observable<struct so_list *> solib_unloaded; + +/* The symbol file specified by objfile has been loaded. Called + with objfile equal to NULL to indicate previously loaded symbol + table data has now been invalidated. */ +extern observable<struct objfile *> new_objfile; + +/* The object file specified by objfile is about to be freed. */ +extern observable<struct objfile *> free_objfile; + +/* The thread specified by t has been created. */ +extern observable<struct thread_info *> new_thread; + +/* The thread specified by t has exited. The silent argument + indicates that gdb is removing the thread from its tables without + wanting to notify the user about it. */ +extern observable<struct thread_info *, int> thread_exit; + +/* An explicit stop request was issued to ptid. If ptid equals + minus_one_ptid, the request applied to all threads. If + ptid_is_pid(ptid) returns true, the request applied to all + threads of the process pointed at by ptid. Otherwise, the + request applied to the single thread pointed at by ptid. */ +extern observable<ptid_t> thread_stop_requested; + +/* The target was resumed. The ptid parameter specifies which + thread was resume, and may be RESUME_ALL if all threads are + resumed. */ +extern observable<ptid_t> target_resumed; + +/* The target is about to be proceeded. */ +extern observable<> about_to_proceed; + +/* A new breakpoint b has been created. */ +extern observable<struct breakpoint *> breakpoint_created; + +/* A breakpoint has been destroyed. The argument b is the + pointer to the destroyed breakpoint. */ +extern observable<struct breakpoint *> breakpoint_deleted; + +/* A breakpoint has been modified in some way. The argument b + is the modified breakpoint. */ +extern observable<struct breakpoint *> breakpoint_modified; + +/* The trace frame is changed to tfnum (e.g., by using the 'tfind' + command). If tfnum is negative, it means gdb resumes live + debugging. The number of the tracepoint associated with this + traceframe is tpnum. */ +extern observable<int, int> traceframe_changed; + +/* The current architecture has changed. The argument newarch is a + pointer to the new architecture. */ +extern observable<struct gdbarch *> architecture_changed; + +/* The thread's ptid has changed. The old_ptid parameter specifies + the old value, and new_ptid specifies the new value. */ +extern observable<ptid_t, ptid_t> thread_ptid_changed; + +/* The inferior inf has been added to the list of inferiors. At + this point, it might not be associated with any process. */ +extern observable<struct inferior *> inferior_added; + +/* The inferior identified by inf has been attached to a + process. */ +extern observable<struct inferior *> inferior_appeared; + +/* Either the inferior associated with inf has been detached from + the process, or the process has exited. */ +extern observable<struct inferior *> inferior_exit; + +/* The inferior inf has been removed from the list of inferiors. + This method is called immediately before freeing inf. */ +extern observable<struct inferior *> inferior_removed; + +/* Bytes from data to data + len have been written to the inferior + at addr. */ +extern observable<struct inferior *, CORE_ADDR, ssize_t, const bfd_byte *> + memory_changed; + +/* Called before a top-level prompt is displayed. current_prompt is + the current top-level prompt. */ +extern observable<const char *> before_prompt; + +/* Variable gdb_datadir has been set. The value may not necessarily + change. */ +extern observable<> gdb_datadir_changed; + +/* The parameter of some 'set' commands in console are changed. + This method is called after a command 'set param value'. param + is the parameter of 'set' command, and value is the value of + changed parameter. */ +extern observable<const char *, const char *> command_param_changed; + +/* The new trace state variable tsv is created. */ +extern observable<const struct trace_state_variable *> tsv_created; + +/* The trace state variable tsv is deleted. If tsv is NULL, all + trace state variables are deleted. */ +extern observable<const struct trace_state_variable *> tsv_deleted; + +/* The trace state value tsv is modified. */ +extern observable<const struct trace_state_variable *> tsv_modified; + +/* An inferior function at address is about to be called in thread + thread. */ +extern observable<ptid_t, CORE_ADDR> inferior_call_pre; + +/* The inferior function at address has just been called. This + observer is called even if the inferior exits during the call. + thread is the thread in which the function was called, which may + be different from the current thread. */ +extern observable<ptid_t, CORE_ADDR> inferior_call_post; + +/* A register in the inferior has been modified by the gdb user. */ +extern observable<struct frame_info *, int> register_changed; + +/* The user-selected inferior, thread and/or frame has changed. The + user_select_what flag specifies if the inferior, thread and/or + frame has changed. */ +extern observable<user_selected_what> user_selected_context_changed; + +} /* namespace observers */ + +} /* namespace gdb */ + +#endif /* GDB_OBSERVER_H */ diff --git a/gdb/observer.c b/gdb/observer.c deleted file mode 100644 index 3c0ec2a..0000000 --- a/gdb/observer.c +++ /dev/null @@ -1,215 +0,0 @@ -/* GDB Notifications to Observers. - - Copyright (C) 2003-2018 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 <http://www.gnu.org/licenses/>. */ - -/* An observer is an entity who is interested in being notified when GDB - reaches certain states, or certain events occur in GDB. The entity being - observed is called the Subject. To receive notifications, the observer - attaches a callback to the subject. One subject can have several - observers. - - This file implements an internal generic low-level event notification - mechanism based on the Observer paradigm described in the book "Design - Patterns". This generic event notification mechansim is then re-used - to implement the exported high-level notification management routines - for all possible notifications. - - The current implementation of the generic observer provides support - for contextual data. This contextual data is given to the subject - when attaching the callback. In return, the subject will provide - this contextual data back to the observer as a parameter of the - callback. - - FIXME: The current support for the contextual data is only partial, - as it lacks a mechanism that would deallocate this data when the - callback is detached. This is not a problem so far, as this contextual - data is only used internally to hold a function pointer. Later on, - if a certain observer needs to provide support for user-level - contextual data, then the generic notification mechanism will need - need to be enhanced to allow the observer to provide a routine to - deallocate the data when attaching the callback. - - This file is currently maintained by hand, but the long term plan - if the number of different notifications starts growing is to create - a new script (observer.sh) that would generate this file, and the - associated documentation. */ - -#include "defs.h" -#include "observer.h" -#include "command.h" -#include "gdbcmd.h" - -static unsigned int observer_debug; -static void -show_observer_debug (struct ui_file *file, int from_tty, - struct cmd_list_element *c, const char *value) -{ - fprintf_filtered (file, _("Observer debugging is %s.\n"), value); -} - -/* The internal generic observer. */ - -typedef void (generic_observer_notification_ftype) (const void *data, - const void *args); - -struct observer -{ - generic_observer_notification_ftype *notify; - /* No memory management needed for the following field for now. */ - void *data; -}; - -/* A list of observers, maintained by the subject. A subject is - actually represented by its list of observers. */ - -struct observer_list -{ - struct observer_list *next; - struct observer *observer; -}; - -/* Allocate a struct observer_list, intended to be used as a node - in the list of observers maintained by a subject. */ - -static struct observer_list * -xalloc_observer_list_node (void) -{ - struct observer_list *node = XNEW (struct observer_list); - - node->observer = XNEW (struct observer); - return node; -} - -/* The opposite of xalloc_observer_list_node, frees the memory for - the given node. */ - -static void -xfree_observer_list_node (struct observer_list *node) -{ - xfree (node->observer); - xfree (node); -} - -/* Attach the callback NOTIFY to a SUBJECT. The DATA is also stored, - in order for the subject to provide it back to the observer during - a notification. */ - -static struct observer * -generic_observer_attach (struct observer_list **subject, - generic_observer_notification_ftype * notify, - void *data) -{ - struct observer_list *observer_list = xalloc_observer_list_node (); - - observer_list->next = *subject; - observer_list->observer->notify = notify; - observer_list->observer->data = data; - *subject = observer_list; - - return observer_list->observer; -} - -/* Remove the given OBSERVER from the SUBJECT. Once detached, OBSERVER - should no longer be used, as it is no longer valid. */ - -static void -generic_observer_detach (struct observer_list **subject, - const struct observer *observer) -{ - struct observer_list *previous_node = NULL; - struct observer_list *current_node = *subject; - - while (current_node != NULL) - { - if (current_node->observer == observer) - { - if (previous_node != NULL) - previous_node->next = current_node->next; - else - *subject = current_node->next; - xfree_observer_list_node (current_node); - return; - } - previous_node = current_node; - current_node = current_node->next; - } - - /* We should never reach this point. However, this should not be - a very serious error, so simply report a warning to the user. */ - warning (_("Failed to detach observer")); -} - -/* Send a notification to all the observers of SUBJECT. ARGS is passed to - all observers as an argument to the notification callback. */ - -static void -generic_observer_notify (struct observer_list *subject, const void *args) -{ - struct observer_list *current_node = subject; - - while (current_node != NULL) - { - (*current_node->observer->notify) (current_node->observer->data, args); - current_node = current_node->next; - } -} - - -/* The following code is only used to unit-test the observers from our - testsuite. DO NOT USE IT within observer.c (or anywhere else for - that matter)! */ - -/* If we define these variables and functions as `static', the - compiler will optimize them out. */ - -int observer_test_first_observer = 0; -int observer_test_second_observer = 0; -int observer_test_third_observer = 0; - -void -observer_test_first_notification_function (int arg) -{ - observer_test_first_observer++; -} - -void -observer_test_second_notification_function (int arg) -{ - observer_test_second_observer++; -} - -void -observer_test_third_notification_function (int arg) -{ - observer_test_third_observer++; -} - -void -_initialize_observer (void) -{ - add_setshow_zuinteger_cmd ("observer", class_maintenance, - &observer_debug, _("\ -Set observer debugging."), _("\ -Show observer debugging."), _("\ -When non-zero, observer debugging is enabled."), - NULL, - show_observer_debug, - &setdebuglist, &showdebuglist); -} - -#include "observer.inc" diff --git a/gdb/observer.sh b/gdb/observer.sh deleted file mode 100755 index fa3dcc5..0000000 --- a/gdb/observer.sh +++ /dev/null @@ -1,200 +0,0 @@ -#!/bin/sh -e - -# Make certain that the script is not running in an internationalized -# environment. -LANG=C ; export LANG -LC_ALL=C ; export LC_ALL - -if test $# -ne 3 -then - echo "Usage: $0 <h|inc> <observer.texi> <observer.out>" 1>&2 - exit 0 -fi - -lang=$1 ; shift -texi=$1 ; shift -o=$1 -case $lang in - h) tmp=htmp ;; - inc) tmp=itmp ;; -esac -otmp="`echo $1 | sed -e 's,\.[^.]*$,,'`.$tmp"; shift -echo "Creating ${otmp}" 1>&2 -rm -f ${otmp} - -# Can use any of the following: cat cmp cp diff echo egrep expr false -# grep install-info ln ls mkdir mv pwd rm rmdir sed sleep sort tar -# test touch true - -cat <<EOF >>${otmp} -/* GDB Notifications to Observers. - - Copyright (C) 2004-2018 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 <http://www.gnu.org/licenses/>. - - -- - - This file was generated using observer.sh and observer.texi. */ - -EOF - - -case $lang in - h) cat <<EOF >>${otmp} -#ifndef OBSERVER_H -#define OBSERVER_H - -struct observer; -struct bpstats; -struct so_list; -struct objfile; -struct thread_info; -struct inferior; -struct trace_state_variable; -EOF - ;; -esac - -# We are about to set IFS=:, so DOS-style file names with a drive -# letter and a colon will be in trouble. - -if test -n "$DJGPP" -then - texi=`echo $texi | sed -e 's,^\([a-zA-Z]\):/,/dev/\1/,'` -fi - -# generate a list of events that can be observed - -IFS=: -sed -n ' -/@deftypefun void/{ -# Save original line for later processing into the actual parameter - h -# Convert from: @deftypefun void EVENT (TYPE @var{PARAM},...) -# to event and formals: EVENT:TYPE PARAM, ...: - s/^.* void \([a-z_][a-z_]*\) (\(.*\))$/\1:\2/ - s/@var{//g - s/}//g -# Switch to held - x -# Convert from: @deftypefun void FUNC (TYPE @var{PARAM},...) -# to actuals: PARAM, ... - s/^[^{]*[{]*// - s/[}]*[^}]*$// - s/}[^{]*{/, /g -# Combine held (EVENT:TYPE PARAM, ...:) and pattern (PARAM, ...) into -# FUNC:TYPE PARAM, ...:PARAM, ... - H - x - s/\n/:/g - p -} -' $texi | while read event formal actual -do - case $lang in - h) cat <<EOF >>${otmp} - -/* ${event} notifications. */ - -typedef void (observer_${event}_ftype) (${formal}); - -extern struct observer *observer_attach_${event} (observer_${event}_ftype *f); -extern void observer_detach_${event} (struct observer *observer); -extern void observer_notify_${event} (${formal}); -EOF - ;; - - inc) - cat <<EOF >>${otmp} - -/* ${event} notifications. */ - -static struct observer_list *${event}_subject = NULL; - -EOF - if test "$formal" != "void"; then - cat<<EOF >>${otmp} -struct ${event}_args { `echo "${formal}" | sed -e 's/,/;/g'`; }; - -EOF - fi - cat <<EOF >>${otmp} -static void -observer_${event}_notification_stub (const void *data, const void *args_data) -{ - observer_${event}_ftype *notify = (observer_${event}_ftype *) data; -EOF - - notify_args=`echo ${actual} | sed -e 's/\([a-z0-9_][a-z0-9_]*\)/args->\1/g'` - - if test ! -z "${notify_args}"; then - cat<<EOF >>${otmp} - const struct ${event}_args *args = (const struct ${event}_args *) args_data; -EOF - fi - cat <<EOF >>${otmp} - notify (${notify_args}); -} - -struct observer * -observer_attach_${event} (observer_${event}_ftype *f) -{ - return generic_observer_attach (&${event}_subject, - &observer_${event}_notification_stub, - (void *) f); -} - -void -observer_detach_${event} (struct observer *observer) -{ - generic_observer_detach (&${event}_subject, observer); -} - -void -observer_notify_${event} (${formal}) -{ -EOF - if test "$formal" != "void"; then - cat<<EOF >>${otmp} - struct ${event}_args args; - `echo ${actual} | sed -e 's/\([a-z0-9_][a-z0-9_]*\)/args.\1 = \1/g'`; - -EOF - else - echo "char *args = NULL;" >> ${otmp} - fi - cat<<EOF >>${otmp} - if (observer_debug) - fprintf_unfiltered (gdb_stdlog, "observer_notify_${event}() called\n"); - generic_observer_notify (${event}_subject, &args); -} -EOF - ;; - esac -done - - -case $lang in - h) cat <<EOF >>${otmp} - -#endif /* OBSERVER_H */ -EOF -esac - - -echo Moving ${otmp} to ${o} -mv ${otmp} ${o} diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 8418e4d..1d2769a 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "defs.h" -#include "observer.h" +#include "observable.h" #include "frame.h" #include "inferior.h" #include "gdbthread.h" @@ -2500,7 +2500,7 @@ _initialize_ppc_linux_nat (void) t->to_read_description = ppc_linux_read_description; t->to_auxv_parse = ppc_linux_auxv_parse; - observer_attach_thread_exit (ppc_linux_thread_exit); + gdb::observers::thread_exit.attach (ppc_linux_thread_exit); /* Register the target. */ linux_nat_add_target (t); diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index d6a98fc..04487e7 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -41,7 +41,7 @@ #include "trad-frame.h" #include "frame-unwind.h" #include "tramp-frame.h" -#include "observer.h" +#include "observable.h" #include "auxv.h" #include "elf/common.h" #include "elf/ppc64.h" @@ -1857,9 +1857,9 @@ _initialize_ppc_linux_tdep (void) ppc_linux_init_abi); /* Attach to observers to track __spe_current_active_context. */ - observer_attach_inferior_created (ppc_linux_spe_context_inferior_created); - observer_attach_solib_loaded (ppc_linux_spe_context_solib_loaded); - observer_attach_solib_unloaded (ppc_linux_spe_context_solib_unloaded); + gdb::observers::inferior_created.attach (ppc_linux_spe_context_inferior_created); + gdb::observers::solib_loaded.attach (ppc_linux_spe_context_solib_loaded); + gdb::observers::solib_unloaded.attach (ppc_linux_spe_context_solib_unloaded); /* Initialize the Linux target descriptions. */ initialize_tdesc_powerpc_32l (); diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 9fb2e02..dd81d8f 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -39,7 +39,7 @@ #include "block.h" #include "disasm.h" #include "target-float.h" -#include "observer.h" +#include "observable.h" #include "solist.h" #include "parser-defs.h" #include "charset.h" @@ -2623,7 +2623,7 @@ _initialize_printcmd (void) current_display_number = -1; - observer_attach_free_objfile (clear_dangling_display_expressions); + gdb::observers::free_objfile.attach (clear_dangling_display_expressions); add_info ("address", info_address_command, _("Describe where symbol SYM is stored.")); diff --git a/gdb/procfs.c b/gdb/procfs.c index cd6dcaa..5ca7477 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -45,7 +45,7 @@ #include "inflow.h" #include "auxv.h" #include "procfs.h" -#include "observer.h" +#include "observable.h" #include "common/scoped_fd.h" /* This module provides the interface between GDB and the @@ -3751,7 +3751,7 @@ proc_untrace_sysexit_cmd (const char *args, int from_tty) void _initialize_procfs (void) { - observer_attach_inferior_created (procfs_inferior_created); + gdb::observers::inferior_created.attach (procfs_inferior_created); add_com ("proc-trace-entry", no_class, proc_trace_sysentry_cmd, _("Give a trace of entries into the syscall.")); diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index 5ac3f98..d654b92 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -25,7 +25,7 @@ #include "breakpoint.h" #include "gdbcmd.h" #include "gdbthread.h" -#include "observer.h" +#include "observable.h" #include "cli/cli-script.h" #include "ada-lang.h" #include "arch-utils.h" @@ -1086,9 +1086,9 @@ gdbpy_initialize_breakpoints (void) (PyObject *) &breakpoint_object_type) < 0) return -1; - observer_attach_breakpoint_created (gdbpy_breakpoint_created); - observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted); - observer_attach_breakpoint_modified (gdbpy_breakpoint_modified); + gdb::observers::breakpoint_created.attach (gdbpy_breakpoint_created); + gdb::observers::breakpoint_deleted.attach (gdbpy_breakpoint_deleted); + gdb::observers::breakpoint_modified.attach (gdbpy_breakpoint_modified); /* Add breakpoint types constants. */ for (i = 0; pybp_codes[i].name; ++i) diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c index 7a05ad3..b3978f7 100644 --- a/gdb/python/py-finishbreakpoint.c +++ b/gdb/python/py-finishbreakpoint.c @@ -26,7 +26,7 @@ #include "gdbthread.h" #include "arch-utils.h" #include "language.h" -#include "observer.h" +#include "observable.h" #include "inferior.h" #include "block.h" #include "location.h" @@ -416,8 +416,8 @@ gdbpy_initialize_finishbreakpoints (void) (PyObject *) &finish_breakpoint_object_type) < 0) return -1; - observer_attach_normal_stop (bpfinishpy_handle_stop); - observer_attach_inferior_exit (bpfinishpy_handle_exit); + gdb::observers::normal_stop.attach (bpfinishpy_handle_stop); + gdb::observers::inferior_exit.attach (bpfinishpy_handle_exit); return 0; } diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index 564aa79..d199aaa 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -22,7 +22,7 @@ #include "gdbthread.h" #include "inferior.h" #include "objfiles.h" -#include "observer.h" +#include "observable.h" #include "python-internal.h" #include "arch-utils.h" #include "language.h" @@ -926,18 +926,18 @@ gdbpy_initialize_inferior (void) infpy_inf_data_key = register_inferior_data_with_cleanup (NULL, py_free_inferior); - observer_attach_new_thread (add_thread_object); - observer_attach_thread_exit (delete_thread_object); - observer_attach_normal_stop (python_on_normal_stop); - observer_attach_target_resumed (python_on_resume); - observer_attach_inferior_call_pre (python_on_inferior_call_pre); - observer_attach_inferior_call_post (python_on_inferior_call_post); - observer_attach_memory_changed (python_on_memory_change); - observer_attach_register_changed (python_on_register_change); - observer_attach_inferior_exit (python_inferior_exit); - observer_attach_new_objfile (python_new_objfile); - observer_attach_inferior_added (python_new_inferior); - observer_attach_inferior_removed (python_inferior_deleted); + gdb::observers::new_thread.attach (add_thread_object); + gdb::observers::thread_exit.attach (delete_thread_object); + gdb::observers::normal_stop.attach (python_on_normal_stop); + gdb::observers::target_resumed.attach (python_on_resume); + gdb::observers::inferior_call_pre.attach (python_on_inferior_call_pre); + gdb::observers::inferior_call_post.attach (python_on_inferior_call_post); + gdb::observers::memory_changed.attach (python_on_memory_change); + gdb::observers::register_changed.attach (python_on_register_change); + gdb::observers::inferior_exit.attach (python_inferior_exit); + gdb::observers::new_objfile.attach (python_new_objfile); + gdb::observers::inferior_added.attach (python_new_inferior); + gdb::observers::inferior_removed.attach (python_inferior_deleted); membuf_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&membuf_object_type) < 0) diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c index 906a004..1d235fc 100644 --- a/gdb/python/py-unwind.c +++ b/gdb/python/py-unwind.c @@ -23,7 +23,7 @@ #include "gdb_obstack.h" #include "gdbcmd.h" #include "language.h" -#include "observer.h" +#include "observable.h" #include "python-internal.h" #include "regcache.h" #include "valprint.h" @@ -662,7 +662,7 @@ gdbpy_initialize_unwind (void) &setdebuglist, &showdebuglist); pyuw_gdbarch_data = gdbarch_data_register_post_init (pyuw_gdbarch_data_init); - observer_attach_architecture_changed (pyuw_on_new_gdbarch); + gdb::observers::architecture_changed.attach (pyuw_on_new_gdbarch); if (PyType_Ready (&pending_frame_object_type) < 0) return -1; diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c index 19bdd7d..46e454a 100644 --- a/gdb/ravenscar-thread.c +++ b/gdb/ravenscar-thread.c @@ -25,7 +25,7 @@ #include "inferior.h" #include "command.h" #include "ravenscar-thread.h" -#include "observer.h" +#include "observable.h" #include "gdbcmd.h" #include "top.h" #include "regcache.h" @@ -632,7 +632,7 @@ _initialize_ravenscar (void) /* Notice when the inferior is created in order to push the ravenscar ops if needed. */ - observer_attach_inferior_created (ravenscar_inferior_created); + gdb::observers::inferior_created.attach (ravenscar_inferior_created); complete_target_initialization (&ravenscar_ops); diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index e77a6a7..7264b8e 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -26,7 +26,7 @@ #include "target.h" #include "gdbcmd.h" #include "disasm.h" -#include "observer.h" +#include "observable.h" #include "cli/cli-utils.h" #include "source.h" #include "ui-out.h" @@ -44,8 +44,9 @@ /* The target_ops of record-btrace. */ static struct target_ops record_btrace_ops; -/* A new thread observer enabling branch tracing for the new thread. */ -static struct observer *record_btrace_thread_observer; +/* Token associated with a new-thread observer enabling branch tracing + for the new thread. */ +static const gdb::observers::token record_btrace_thread_observer_token; /* Memory access types used in set/show record btrace replay-memory-access. */ static const char replay_memory_access_read_only[] = "read-only"; @@ -166,8 +167,8 @@ record_btrace_auto_enable (void) { DEBUG ("attach thread observer"); - record_btrace_thread_observer - = observer_attach_new_thread (record_btrace_enable_warn); + gdb::observers::new_thread.attach (record_btrace_enable_warn, + record_btrace_thread_observer_token); } /* Disable automatic tracing of new threads. */ @@ -175,14 +176,9 @@ record_btrace_auto_enable (void) static void record_btrace_auto_disable (void) { - /* The observer may have been detached, already. */ - if (record_btrace_thread_observer == NULL) - return; - DEBUG ("detach thread observer"); - observer_detach_new_thread (record_btrace_thread_observer); - record_btrace_thread_observer = NULL; + gdb::observers::new_thread.detach (record_btrace_thread_observer_token); } /* The record-btrace async event handler function. */ @@ -210,7 +206,7 @@ record_btrace_push_target (void) record_btrace_generating_corefile = 0; format = btrace_format_short_string (record_btrace_conf.format); - observer_notify_record_changed (current_inferior (), 1, "btrace", format); + gdb::observers::record_changed.notify (current_inferior (), 1, "btrace", format); } /* Disable btrace on a set of threads on scope exit. */ @@ -258,8 +254,6 @@ record_btrace_open (const char *args, int from_tty) if (!target_has_execution) error (_("The program is not being run.")); - gdb_assert (record_btrace_thread_observer == NULL); - ALL_NON_EXITED_THREADS (tp) if (args == NULL || *args == 0 || number_is_in_list (args, tp->global_num)) { diff --git a/gdb/record-full.c b/gdb/record-full.c index 82b3c74..abaf99b 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -33,7 +33,7 @@ #include "event-loop.h" #include "inf-loop.h" #include "gdb_bfd.h" -#include "observer.h" +#include "observable.h" #include "infrun.h" #include "common/gdb_unlinker.h" #include "common/byte-vector.h" @@ -851,7 +851,7 @@ record_full_open (const char *name, int from_tty) record_full_init_record_breakpoints (); - observer_notify_record_changed (current_inferior (), 1, "full", NULL); + gdb::observers::record_changed.notify (current_inferior (), 1, "full", NULL); } /* "to_close" target method. Close the process record target. */ diff --git a/gdb/record.c b/gdb/record.c index cd83b99..7c35dc8 100644 --- a/gdb/record.c +++ b/gdb/record.c @@ -21,7 +21,7 @@ #include "gdbcmd.h" #include "completer.h" #include "record.h" -#include "observer.h" +#include "observable.h" #include "inferior.h" #include "common/common-utils.h" #include "cli/cli-utils.h" @@ -311,7 +311,7 @@ cmd_record_stop (const char *args, int from_tty) printf_unfiltered (_("Process record is stopped and all execution " "logs are deleted.\n")); - observer_notify_record_changed (current_inferior (), 0, NULL, NULL); + gdb::observers::record_changed.notify (current_inferior (), 0, NULL, NULL); } /* The "set record" command. */ diff --git a/gdb/regcache.c b/gdb/regcache.c index 8e843b2..3af8ca9 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -24,7 +24,7 @@ #include "gdbcmd.h" #include "regcache.h" #include "reggroups.h" -#include "observer.h" +#include "observable.h" #include "regset.h" #include <forward_list> @@ -1868,8 +1868,9 @@ _initialize_regcache (void) regcache_descr_handle = gdbarch_data_register_post_init (init_regcache_descr); - observer_attach_target_changed (regcache_observer_target_changed); - observer_attach_thread_ptid_changed (regcache::regcache_thread_ptid_changed); + gdb::observers::target_changed.attach (regcache_observer_target_changed); + gdb::observers::thread_ptid_changed.attach + (regcache::regcache_thread_ptid_changed); add_com ("flushregs", class_maintenance, reg_flush_command, _("Force gdb to flush its register cache (maintainer command)")); diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c index e009d81..85612b1 100644 --- a/gdb/remote-notif.c +++ b/gdb/remote-notif.c @@ -34,7 +34,7 @@ #include "defs.h" #include "remote.h" #include "remote-notif.h" -#include "observer.h" +#include "observable.h" #include "event-loop.h" #include "target.h" #include "inferior.h" diff --git a/gdb/remote.c b/gdb/remote.c index 7f409fd..501c443 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -36,7 +36,7 @@ #include "remote-notif.h" #include "regcache.h" #include "value.h" -#include "observer.h" +#include "observable.h" #include "solib.h" #include "cli/cli-decode.h" #include "cli/cli-setshow.h" @@ -3824,9 +3824,9 @@ print_one_stopped_thread (struct thread_info *thread) enum gdb_signal sig = ws->value.sig; if (signal_print_state (sig)) - observer_notify_signal_received (sig); + gdb::observers::signal_received.notify (sig); } - observer_notify_normal_stop (NULL, 1); + gdb::observers::normal_stop.notify (NULL, 1); } /* Process all initial stop replies the remote side sent in response @@ -13925,10 +13925,10 @@ _initialize_remote (void) add_target (&extended_remote_ops); /* Hook into new objfile notification. */ - observer_attach_new_objfile (remote_new_objfile); + gdb::observers::new_objfile.attach (remote_new_objfile); /* We're no longer interested in notification events of an inferior when it exits. */ - observer_attach_inferior_exit (discard_pending_stop_replies); + gdb::observers::inferior_exit.attach (discard_pending_stop_replies); #if 0 init_remote_threadtests (); diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 655db7c..149e5e3 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -53,7 +53,7 @@ #include "common-defs.h" #include "opcode/riscv-opc.h" #include "cli/cli-decode.h" -#include "observer.h" +#include "observable.h" /* The stack must be 16-byte aligned. */ #define SP_ALIGNMENT 16 @@ -2641,8 +2641,8 @@ _initialize_riscv_tdep (void) = register_inferior_data_with_cleanup (NULL, riscv_inferior_data_cleanup); /* Observers used to invalidate the inferior data when needed. */ - observer_attach_inferior_exit (riscv_invalidate_inferior_data); - observer_attach_inferior_appeared (riscv_invalidate_inferior_data); + gdb::observers::inferior_exit.attach (riscv_invalidate_inferior_data); + gdb::observers::inferior_appeared.attach (riscv_invalidate_inferior_data); /* Add root prefix command for all "set debug riscv" and "show debug riscv" commands. */ diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c index 8c54dc2..4f05cd6 100644 --- a/gdb/rs6000-nat.c +++ b/gdb/rs6000-nat.c @@ -33,7 +33,7 @@ #include "rs6000-tdep.h" #include "rs6000-aix-tdep.h" #include "exec.h" -#include "observer.h" +#include "observable.h" #include "xcoffread.h" #include <sys/ptrace.h> diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c index 2c7dd0e..62d839c 100644 --- a/gdb/sol-thread.c +++ b/gdb/sol-thread.c @@ -63,7 +63,7 @@ #include "regcache.h" #include "solib.h" #include "symfile.h" -#include "observer.h" +#include "observable.h" #include "procfs.h" #include "symtab.h" #include "minsyms.h" @@ -1229,7 +1229,7 @@ _initialize_sol_thread (void) _("Show info on Solaris user threads."), &maintenanceinfolist); /* Hook into new_objfile notification. */ - observer_attach_new_objfile (sol_thread_new_objfile); + gdb::observers::new_objfile.attach (sol_thread_new_objfile); return; die: diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c index f11cbcd..5339f11 100644 --- a/gdb/solib-aix.c +++ b/gdb/solib-aix.c @@ -24,7 +24,7 @@ #include "objfiles.h" #include "symtab.h" #include "xcoffread.h" -#include "observer.h" +#include "observable.h" #include "gdbcmd.h" /* Variable controlling the output of the debugging traces for @@ -791,7 +791,7 @@ _initialize_solib_aix (void) solib_aix_inferior_data_handle = register_inferior_data (); - observer_attach_normal_stop (solib_aix_normal_stop_observer); + gdb::observers::normal_stop.attach (solib_aix_normal_stop_observer); /* Debug this file's internals. */ add_setshow_boolean_cmd ("aix-solib", class_maintenance, diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c index 943ebf5..cb735fd 100644 --- a/gdb/solib-spu.c +++ b/gdb/solib-spu.c @@ -30,7 +30,7 @@ #include "solist.h" #include "inferior.h" #include "objfiles.h" -#include "observer.h" +#include "observable.h" #include "breakpoint.h" #include "gdbthread.h" #include "gdb_bfd.h" @@ -545,7 +545,7 @@ spu_solib_loaded (struct so_list *so) void _initialize_spu_solib (void) { - observer_attach_solib_loaded (spu_solib_loaded); + gdb::observers::solib_loaded.attach (spu_solib_loaded); ocl_program_data_key = register_objfile_data (); } diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index c8f5e93..29e74da 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -33,7 +33,7 @@ #include "infrun.h" #include "regcache.h" #include "gdbthread.h" -#include "observer.h" +#include "observable.h" #include "solist.h" #include "solib.h" diff --git a/gdb/solib.c b/gdb/solib.c index 77c1268..5011bd7 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -38,7 +38,7 @@ #include "filenames.h" /* for DOSish file names */ #include "exec.h" #include "solist.h" -#include "observer.h" +#include "observable.h" #include "readline/readline.h" #include "remote.h" #include "solib.h" @@ -824,7 +824,7 @@ update_solib_list (int from_tty) { /* Notify any observer that the shared object has been unloaded before we remove it from GDB's tables. */ - observer_notify_solib_unloaded (gdb); + gdb::observers::solib_unloaded.notify (gdb); current_program_space->deleted_solibs.push_back (gdb->so_name); @@ -885,7 +885,7 @@ update_solib_list (int from_tty) /* Notify any observer that the shared object has been loaded now that we've added it to GDB's tables. */ - observer_notify_solib_loaded (i); + gdb::observers::solib_loaded.notify (i); } /* If a library was not found, issue an appropriate warning @@ -1193,7 +1193,7 @@ clear_solib (void) struct so_list *so = so_list_head; so_list_head = so->next; - observer_notify_solib_unloaded (so); + gdb::observers::solib_unloaded.notify (so); remove_target_sections (so); free_so (so); } @@ -1595,7 +1595,7 @@ _initialize_solib (void) { solib_data = gdbarch_data_register_pre_init (solib_init); - observer_attach_free_objfile (remove_user_added_objfile); + gdb::observers::free_objfile.attach (remove_user_added_objfile); add_com ("sharedlibrary", class_files, sharedlibrary_command, _("Load shared object library symbols for files matching REGEXP.")); diff --git a/gdb/spu-multiarch.c b/gdb/spu-multiarch.c index 7152dda..86782ab 100644 --- a/gdb/spu-multiarch.c +++ b/gdb/spu-multiarch.c @@ -22,7 +22,7 @@ #include "gdbcore.h" #include "gdbcmd.h" #include "arch-utils.h" -#include "observer.h" +#include "observable.h" #include "inferior.h" #include "regcache.h" #include "symfile.h" @@ -410,8 +410,8 @@ _initialize_spu_multiarch (void) complete_target_initialization (&spu_ops); /* Install observers to watch for SPU objects. */ - observer_attach_inferior_created (spu_multiarch_inferior_created); - observer_attach_solib_loaded (spu_multiarch_solib_loaded); - observer_attach_solib_unloaded (spu_multiarch_solib_unloaded); + gdb::observers::inferior_created.attach (spu_multiarch_inferior_created); + gdb::observers::solib_loaded.attach (spu_multiarch_solib_loaded); + gdb::observers::solib_unloaded.attach (spu_multiarch_solib_unloaded); } diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c index 695b5cc..783ef5b 100644 --- a/gdb/spu-tdep.c +++ b/gdb/spu-tdep.c @@ -39,7 +39,7 @@ #include "regcache.h" #include "reggroups.h" #include "block.h" -#include "observer.h" +#include "observable.h" #include "infcall.h" #include "dwarf2.h" #include "dwarf2-frame.h" @@ -2771,14 +2771,14 @@ _initialize_spu_tdep (void) register_gdbarch_init (bfd_arch_spu, spu_gdbarch_init); /* Add ourselves to objfile event chain. */ - observer_attach_new_objfile (spu_overlay_new_objfile); + gdb::observers::new_objfile.attach (spu_overlay_new_objfile); spu_overlay_data = register_objfile_data (); /* Install spu stop-on-load handler. */ - observer_attach_new_objfile (spu_catch_start); + gdb::observers::new_objfile.attach (spu_catch_start); /* Add ourselves to normal_stop event chain. */ - observer_attach_normal_stop (spu_attach_normal_stop); + gdb::observers::normal_stop.attach (spu_attach_normal_stop); /* Add root prefix command for all "set spu"/"show spu" commands. */ add_prefix_cmd ("spu", no_class, set_spu_command, diff --git a/gdb/stack.c b/gdb/stack.c index ebc49d4..aad8fcd 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -51,7 +51,7 @@ #include "safe-ctype.h" #include "symfile.h" #include "extension.h" -#include "observer.h" +#include "observable.h" #include "common/def-vector.h" /* The possible choices of "set print frame-arguments", and the value @@ -2277,7 +2277,7 @@ select_frame_command (const char *level_exp, int from_tty) select_frame (parse_frame_specification (level_exp, NULL)); if (get_selected_frame_if_set () != prev_frame) - observer_notify_user_selected_context_changed (USER_SELECTED_FRAME); + gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME); } /* The "frame" command. With no argument, print the selected frame @@ -2291,7 +2291,7 @@ frame_command (const char *level_exp, int from_tty) select_frame (parse_frame_specification (level_exp, NULL)); if (get_selected_frame_if_set () != prev_frame) - observer_notify_user_selected_context_changed (USER_SELECTED_FRAME); + gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME); else print_selected_thread_frame (current_uiout, USER_SELECTED_FRAME); } @@ -2324,7 +2324,7 @@ static void up_command (const char *count_exp, int from_tty) { up_silently_base (count_exp); - observer_notify_user_selected_context_changed (USER_SELECTED_FRAME); + gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME); } /* Select the frame down one or COUNT_EXP stack levels from the previously @@ -2363,7 +2363,7 @@ static void down_command (const char *count_exp, int from_tty) { down_silently_base (count_exp); - observer_notify_user_selected_context_changed (USER_SELECTED_FRAME); + gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME); } void diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c index 358b2f8..9d8007d 100644 --- a/gdb/symfile-debug.c +++ b/gdb/symfile-debug.c @@ -28,7 +28,7 @@ #include "defs.h" #include "gdbcmd.h" #include "objfiles.h" -#include "observer.h" +#include "observable.h" #include "source.h" #include "symtab.h" #include "symfile.h" diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c index 1653628..c060711 100644 --- a/gdb/symfile-mem.c +++ b/gdb/symfile-mem.c @@ -49,7 +49,7 @@ #include "target.h" #include "value.h" #include "symfile.h" -#include "observer.h" +#include "observable.h" #include "auxv.h" #include "elf/common.h" #include "gdb_bfd.h" @@ -219,5 +219,5 @@ _initialize_symfile_mem (void) /* Want to know of each new inferior so that its vsyscall info can be extracted. */ - observer_attach_inferior_created (add_vsyscall_page); + gdb::observers::inferior_created.attach (add_vsyscall_page); } diff --git a/gdb/symfile.c b/gdb/symfile.c index e202ca2..9571664 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -46,7 +46,7 @@ #include "hashtab.h" #include "readline/readline.h" #include "block.h" -#include "observer.h" +#include "observable.h" #include "exec.h" #include "parser-defs.h" #include "varobj.h" @@ -1152,13 +1152,13 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, if (objfile->sf == NULL) { - observer_notify_new_objfile (objfile); + gdb::observers::new_objfile.notify (objfile); return objfile; /* No symbols. */ } finish_new_objfile (objfile, add_flags); - observer_notify_new_objfile (objfile); + gdb::observers::new_objfile.notify (objfile); bfd_cache_close_all (); return (objfile); @@ -2511,14 +2511,14 @@ reread_symbols (void) clear_symtab_users (0); /* clear_objfile_data for each objfile was called before freeing it and - observer_notify_new_objfile (NULL) has been called by + gdb::observers::new_objfile.notify (NULL) has been called by clear_symtab_users above. Notify the new files now. */ for (auto iter : new_objfiles) - observer_notify_new_objfile (iter); + gdb::observers::new_objfile.notify (objfile); /* At least one objfile has changed, so we can consider that the executable we're debugging has changed too. */ - observer_notify_executable_changed (); + gdb::observers::executable_changed.notify (); } } @@ -2755,7 +2755,7 @@ clear_symtab_users (symfile_add_flags add_flags) clear_displays (); clear_last_displayed_sal (); clear_pc_function_cache (); - observer_notify_new_objfile (NULL); + gdb::observers::new_objfile.notify (NULL); /* Clear globals which might have pointed into a removed objfile. FIXME: It's not clear which of these are supposed to persist @@ -3761,7 +3761,7 @@ _initialize_symfile (void) { struct cmd_list_element *c; - observer_attach_free_objfile (symfile_free_objfile); + gdb::observers::free_objfile.attach (symfile_free_objfile); #define READNOW_READNEVER_HELP \ "The '-readnow' option will cause GDB to read the entire symbol file\n\ diff --git a/gdb/symtab.c b/gdb/symtab.c index 5671953..894a253 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -54,7 +54,7 @@ #include <ctype.h> #include "cp-abi.h" #include "cp-support.h" -#include "observer.h" +#include "observable.h" #include "solist.h" #include "macrotab.h" #include "macroscope.h" @@ -5917,7 +5917,7 @@ If zero then the symbol cache is disabled."), _("Flush the symbol cache for each program space."), &maintenancelist); - observer_attach_executable_changed (symtab_observer_executable_changed); - observer_attach_new_objfile (symtab_new_objfile_observer); - observer_attach_free_objfile (symtab_free_objfile_observer); + gdb::observers::executable_changed.attach (symtab_observer_executable_changed); + gdb::observers::new_objfile.attach (symtab_new_objfile_observer); + gdb::observers::free_objfile.attach (symtab_free_objfile_observer); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index d2fb9a8..c648fc5 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-03-19 Tom Tromey <tom@tromey.com> + + * gdb.gdb/observer.exp: Remove. + 2018-03-19 Andreas Arnez <arnez@linux.vnet.ibm.com> * gdb.trace/actions-changed.exp: Call gdb_breakpoint with the diff --git a/gdb/testsuite/gdb.gdb/observer.exp b/gdb/testsuite/gdb.gdb/observer.exp deleted file mode 100644 index 1b51464..0000000 --- a/gdb/testsuite/gdb.gdb/observer.exp +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright 2003-2018 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/>. - -# This file was written by Joel Brobecker (brobecker@gnat.com), derived -# from xfullpath.exp. - -load_lib selftest-support.exp - -proc attach_first_observer { message } { - gdb_test_no_output "set \$first_obs = observer_attach_test_notification (&observer_test_first_notification_function)" \ - "$message; attach first observer" -} - -proc attach_second_observer { message } { - gdb_test_no_output "set \$second_obs = observer_attach_test_notification (&observer_test_second_notification_function)" \ - "$message; attach second observer" -} - -proc attach_third_observer { message } { - gdb_test_no_output "set \$third_obs = observer_attach_test_notification (&observer_test_third_notification_function)" \ - "$message; attach third observer" -} - -proc detach_first_observer { message } { - gdb_test_no_output "call observer_detach_test_notification (\$first_obs)" \ - "$message; detach first observer" -} - -proc detach_second_observer { message } { - gdb_test_no_output "call observer_detach_test_notification (\$second_obs)" \ - "$message; detach second observer" -} - -proc detach_third_observer { message } { - gdb_test_no_output "call observer_detach_test_notification (\$third_obs)" \ - "$message; detach third observer" -} - -proc check_counters { first second third message } { - gdb_test "print observer_test_first_observer" \ - ".\[0-9\]+ =.*$first" \ - "$message; check first observer counter value" - gdb_test "print observer_test_second_observer" \ - ".\[0-9\]+ =.*$second" \ - "$message; check second observer counter value" - gdb_test "print observer_test_third_observer" \ - ".\[0-9\]+ =.*$third" \ - "$message; check third observer counter value" -} - -proc reset_counters { message } { - gdb_test_no_output "set variable observer_test_first_observer = 0" \ - "$message; reset first observer counter" - gdb_test_no_output "set variable observer_test_second_observer = 0" \ - "$message; reset second observer counter" - gdb_test_no_output "set variable observer_test_third_observer = 0" \ - "$message; reset third observer counter" -} - -proc test_notifications { first second third message args } { - # Do any initialization - for {set i 0} {$i < [llength $args]} {incr i} { - [lindex $args $i] $message - } - reset_counters $message - # Call observer_notify_test_notification. Note that this procedure - # takes one argument, but this argument is ignored by the observer - # callbacks we have installed. So we just pass an arbitrary value. - gdb_test_no_output "call observer_notify_test_notification (0)" \ - "$message; sending notification" - check_counters $first $second $third $message -} - -proc test_observer {} { - # First, try sending a notification without any observer attached. - test_notifications 0 0 0 "no observer attached" - - # Now, attach one observer, and send a notification. - test_notifications 0 1 0 "second observer attached" \ - attach_second_observer - - # Remove the observer, and send a notification. - test_notifications 0 0 0 "second observer detached" \ - detach_second_observer - - # With a new observer. - test_notifications 1 0 0 "1st observer added" \ - attach_first_observer - - # With 2 observers. - test_notifications 1 1 0 "2nd observer added" \ - attach_second_observer - - # With 3 observers. - test_notifications 1 1 1 "3rd observer added" \ - attach_third_observer - - # Remove middle observer. - test_notifications 1 0 1 "2nd observer removed" \ - detach_second_observer - - # Remove first observer. - test_notifications 0 0 1 "1st observer removed" \ - detach_first_observer - - # Remove last observer. - test_notifications 0 0 0 "3rd observer removed" \ - detach_third_observer - - # Go back to 3 observers, and remove them in a different order... - test_notifications 1 1 1 "three observers added" \ - attach_first_observer \ - attach_second_observer \ - attach_third_observer - - # Remove the third observer. - test_notifications 1 1 0 "third observer removed" \ - detach_third_observer - - # Remove the second observer. - test_notifications 1 0 0 "second observer removed" \ - detach_second_observer - - # Remove the first observer, no more observers. - test_notifications 0 0 0 "first observer removed" \ - detach_first_observer - - return 0 -} - -do_self_tests captured_main test_observer diff --git a/gdb/thread.c b/gdb/thread.c index a99fbdc..99f3f5b 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -36,7 +36,7 @@ #include <sys/types.h> #include <signal.h> #include "ui-out.h" -#include "observer.h" +#include "observable.h" #include "annotate.h" #include "cli/cli-decode.h" #include "gdb_regex.h" @@ -207,7 +207,7 @@ set_thread_exited (thread_info *tp, int silent) if (tp->state != THREAD_EXITED) { - observer_notify_thread_exit (tp, silent); + gdb::observers::thread_exit.notify (tp, silent); /* Tag it as exited. */ tp->state = THREAD_EXITED; @@ -299,7 +299,7 @@ add_thread_silent (ptid_t ptid) tp->state = THREAD_STOPPED; switch_to_thread (ptid); - observer_notify_new_thread (tp); + gdb::observers::new_thread.notify (tp); /* All done. */ return tp; @@ -310,7 +310,7 @@ add_thread_silent (ptid_t ptid) } tp = new_thread (inf, ptid); - observer_notify_new_thread (tp); + gdb::observers::new_thread.notify (tp); return tp; } @@ -821,7 +821,7 @@ thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid) tp = find_thread_ptid (old_ptid); tp->ptid = new_ptid; - observer_notify_thread_ptid_changed (old_ptid, new_ptid); + gdb::observers::thread_ptid_changed.notify (old_ptid, new_ptid); } /* See gdbthread.h. */ @@ -901,7 +901,7 @@ set_running (ptid_t ptid, int running) any_started = 1; } if (any_started) - observer_notify_target_resumed (ptid); + gdb::observers::target_resumed.notify (ptid); } static int @@ -1000,7 +1000,7 @@ set_stop_requested (ptid_t ptid, int stop) /* Call the stop requested observer so other components of GDB can react to this request. */ if (stop) - observer_notify_thread_stop_requested (ptid); + gdb::observers::thread_stop_requested.notify (ptid); } void @@ -1037,7 +1037,7 @@ finish_thread_state (ptid_t ptid) } if (any_started) - observer_notify_target_resumed (ptid); + gdb::observers::target_resumed.notify (ptid); } void @@ -1786,8 +1786,8 @@ thread_command (const char *tidstr, int from_tty) } else { - observer_notify_user_selected_context_changed (USER_SELECTED_THREAD - | USER_SELECTED_FRAME); + gdb::observers::user_selected_context_changed.notify + (USER_SELECTED_THREAD | USER_SELECTED_FRAME); } } } @@ -46,7 +46,7 @@ #include "gdbthread.h" #include "extension.h" #include "interps.h" -#include "observer.h" +#include "observable.h" #include "maint.h" #include "filenames.h" #include "frame.h" @@ -1959,7 +1959,7 @@ static void set_gdb_datadir (const char *args, int from_tty, struct cmd_list_element *c) { set_gdb_data_directory (staged_gdb_datadir); - observer_notify_gdb_datadir_changed (); + gdb::observers::gdb_datadir_changed.notify (); } /* "show" command for the gdb_datadir configuration variable. */ diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index f34f103..30fe206 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -36,7 +36,7 @@ #include "completer.h" #include "block.h" #include "dictionary.h" -#include "observer.h" +#include "observable.h" #include "user-regs.h" #include "valprint.h" #include "gdbcore.h" @@ -315,7 +315,7 @@ delete_trace_state_variable (const char *name) for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) if (strcmp (name, tsv->name) == 0) { - observer_notify_tsv_deleted (tsv); + gdb::observers::tsv_deleted.notify (tsv); xfree ((void *)tsv->name); VEC_unordered_remove (tsv_s, tvariables, ix); @@ -390,7 +390,7 @@ trace_variable_command (const char *args, int from_tty) if (tsv->initial_value != initval) { tsv->initial_value = initval; - observer_notify_tsv_modified (tsv); + gdb::observers::tsv_modified.notify (tsv); } printf_filtered (_("Trace state variable $%s " "now has initial value %s.\n"), @@ -402,7 +402,7 @@ trace_variable_command (const char *args, int from_tty) tsv = create_trace_state_variable (name.c_str ()); tsv->initial_value = initval; - observer_notify_tsv_created (tsv); + gdb::observers::tsv_created.notify (tsv); printf_filtered (_("Trace state variable $%s " "created, with initial value %s.\n"), @@ -417,7 +417,7 @@ delete_trace_variable_command (const char *args, int from_tty) if (query (_("Delete all trace state variables? "))) VEC_free (tsv_s, tvariables); dont_repeat (); - observer_notify_tsv_deleted (NULL); + gdb::observers::tsv_deleted.notify (NULL); return; } @@ -1659,7 +1659,7 @@ start_tracing (const char *notes) loc->gdbarch); if (bp_location_downloaded) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } VEC_free (breakpoint_p, tp_vec); @@ -2175,7 +2175,7 @@ tfind_1 (enum trace_find_type type, int num, set_tracepoint_num (tp ? tp->number : target_tracept); if (target_frameno != get_traceframe_number ()) - observer_notify_traceframe_changed (target_frameno, tracepoint_number); + gdb::observers::traceframe_changed.notify (target_frameno, tracepoint_number); set_current_traceframe (target_frameno); @@ -3240,7 +3240,7 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) /* Notify 'breakpoint-modified' observer that at least one of B's locations was changed. */ for (ix = 0; VEC_iterate (breakpoint_p, modified_tp, ix, b); ix++) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); VEC_free (breakpoint_p, modified_tp); free_uploaded_tps (uploaded_tps); @@ -3287,7 +3287,7 @@ create_tsv_from_upload (struct uploaded_tsv *utsv) tsv->initial_value = utsv->initial_value; tsv->builtin = utsv->builtin; - observer_notify_tsv_created (tsv); + gdb::observers::tsv_created.notify (tsv); return tsv; } diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c index 84e416e..efa02e2 100644 --- a/gdb/tui/tui-hooks.c +++ b/gdb/tui/tui-hooks.c @@ -32,7 +32,7 @@ #include "breakpoint.h" #include "ui-out.h" #include "top.h" -#include "observer.h" +#include "observable.h" #include <unistd.h> #include <fcntl.h> @@ -203,14 +203,42 @@ tui_normal_stop (struct bpstats *bs, int print_frame) tui_refresh_frame_and_register_information (/*registers_too_p=*/1); } -/* Observers created when installing TUI hooks. */ -static struct observer *tui_bp_created_observer; -static struct observer *tui_bp_deleted_observer; -static struct observer *tui_bp_modified_observer; -static struct observer *tui_inferior_exit_observer; -static struct observer *tui_before_prompt_observer; -static struct observer *tui_normal_stop_observer; -static struct observer *tui_register_changed_observer; +/* Token associated with observers registered while TUI hooks are + installed. */ +static const gdb::observers::token tui_observers_token; + +/* Attach or detach a single observer, according to ATTACH. */ + +template<typename T> +static void +attach_or_detach (T &observable, typename T::func_type func, bool attach) +{ + if (attach) + observable.attach (func, tui_observers_token); + else + observable.detach (tui_observers_token); +} + +/* Attach or detach TUI observers, according to ATTACH. */ + +static void +tui_attach_detach_observers (bool attach) +{ + attach_or_detach (gdb::observers::breakpoint_created, + tui_event_create_breakpoint, attach); + attach_or_detach (gdb::observers::breakpoint_deleted, + tui_event_delete_breakpoint, attach); + attach_or_detach (gdb::observers::breakpoint_modified, + tui_event_modify_breakpoint, attach); + attach_or_detach (gdb::observers::inferior_exit, + tui_inferior_exit, attach); + attach_or_detach (gdb::observers::before_prompt, + tui_before_prompt, attach); + attach_or_detach (gdb::observers::normal_stop, + tui_normal_stop, attach); + attach_or_detach (gdb::observers::register_changed, + tui_register_changed, attach); +} /* Install the TUI specific hooks. */ void @@ -224,20 +252,7 @@ tui_install_hooks (void) = tui_dummy_print_frame_info_listing_hook; /* Install the event hooks. */ - tui_bp_created_observer - = observer_attach_breakpoint_created (tui_event_create_breakpoint); - tui_bp_deleted_observer - = observer_attach_breakpoint_deleted (tui_event_delete_breakpoint); - tui_bp_modified_observer - = observer_attach_breakpoint_modified (tui_event_modify_breakpoint); - tui_inferior_exit_observer - = observer_attach_inferior_exit (tui_inferior_exit); - tui_before_prompt_observer - = observer_attach_before_prompt (tui_before_prompt); - tui_normal_stop_observer - = observer_attach_normal_stop (tui_normal_stop); - tui_register_changed_observer - = observer_attach_register_changed (tui_register_changed); + tui_attach_detach_observers (true); } /* Remove the TUI specific hooks. */ @@ -246,26 +261,14 @@ tui_remove_hooks (void) { deprecated_print_frame_info_listing_hook = 0; deprecated_query_hook = 0; + /* Remove our observers. */ - observer_detach_breakpoint_created (tui_bp_created_observer); - tui_bp_created_observer = NULL; - observer_detach_breakpoint_deleted (tui_bp_deleted_observer); - tui_bp_deleted_observer = NULL; - observer_detach_breakpoint_modified (tui_bp_modified_observer); - tui_bp_modified_observer = NULL; - observer_detach_inferior_exit (tui_inferior_exit_observer); - tui_inferior_exit_observer = NULL; - observer_detach_before_prompt (tui_before_prompt_observer); - tui_before_prompt_observer = NULL; - observer_detach_normal_stop (tui_normal_stop_observer); - tui_normal_stop_observer = NULL; - observer_detach_register_changed (tui_register_changed_observer); - tui_register_changed_observer = NULL; + tui_attach_detach_observers (false); } void _initialize_tui_hooks (void) { /* Install the permanent hooks. */ - observer_attach_new_objfile (tui_new_objfile_hook); + gdb::observers::new_objfile.attach (tui_new_objfile_hook); } diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c index 3c87198..cf32c90 100644 --- a/gdb/tui/tui-interp.c +++ b/gdb/tui/tui-interp.c @@ -31,7 +31,7 @@ #include "tui/tui.h" #include "tui/tui-io.h" #include "infrun.h" -#include "observer.h" +#include "observable.h" #include "gdbthread.h" /* Set to 1 when the TUI mode must be activated when we first start @@ -326,14 +326,14 @@ _initialize_tui_interp (void) } /* If changing this, remember to update cli-interp.c as well. */ - observer_attach_normal_stop (tui_on_normal_stop); - observer_attach_signal_received (tui_on_signal_received); - observer_attach_end_stepping_range (tui_on_end_stepping_range); - observer_attach_signal_exited (tui_on_signal_exited); - observer_attach_exited (tui_on_exited); - observer_attach_no_history (tui_on_no_history); - observer_attach_sync_execution_done (tui_on_sync_execution_done); - observer_attach_command_error (tui_on_command_error); - observer_attach_user_selected_context_changed + gdb::observers::normal_stop.attach (tui_on_normal_stop); + gdb::observers::signal_received.attach (tui_on_signal_received); + gdb::observers::end_stepping_range.attach (tui_on_end_stepping_range); + gdb::observers::signal_exited.attach (tui_on_signal_exited); + gdb::observers::exited.attach (tui_on_exited); + gdb::observers::no_history.attach (tui_on_no_history); + gdb::observers::sync_execution_done.attach (tui_on_sync_execution_done); + gdb::observers::command_error.attach (tui_on_command_error); + gdb::observers::user_selected_context_changed.attach (tui_on_user_selected_context_changed); } diff --git a/gdb/unittests/observable-selftests.c b/gdb/unittests/observable-selftests.c new file mode 100644 index 0000000..6f2f7e8 --- /dev/null +++ b/gdb/unittests/observable-selftests.c @@ -0,0 +1,135 @@ +/* Self tests for gdb::observers, GDB notifications to observers. + + Copyright (C) 2003-2018 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 <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "selftest.h" +#include "common/observable.h" + +namespace selftests { +namespace observers { + +gdb::observers::observable<int> test_notification ("test_notification"); + +static int test_first_observer = 0; +static int test_second_observer = 0; +static int test_third_observer = 0; + +static void +test_first_notification_function (int arg) +{ + test_first_observer++; +} + +static void +test_second_notification_function (int arg) +{ + test_second_observer++; +} + +static void +test_third_notification_function (int arg) +{ + test_third_observer++; +} + +static void +notify_check_counters (int one, int two, int three) +{ + /* Reset. */ + test_first_observer = 0; + test_second_observer = 0; + test_third_observer = 0; + /* Notify. */ + test_notification.notify (0); + /* Check. */ + SELF_CHECK (one == test_first_observer); + SELF_CHECK (two == test_second_observer); + SELF_CHECK (three == test_third_observer); +} + +static void +run_tests () +{ + /* First, try sending a notification without any observer + attached. */ + notify_check_counters (0, 0, 0); + + const gdb::observers::token token1, token2, token3; + + /* Now, attach one observer, and send a notification. */ + test_notification.attach (&test_second_notification_function, token2); + notify_check_counters (0, 1, 0); + + /* Remove the observer, and send a notification. */ + test_notification.detach (token2); + notify_check_counters (0, 0, 0); + + /* With a new observer. */ + test_notification.attach (&test_first_notification_function, token1); + notify_check_counters (1, 0, 0); + + /* With 2 observers. */ + test_notification.attach (&test_second_notification_function, token2); + notify_check_counters (1, 1, 0); + + /* With 3 observers. */ + test_notification.attach (&test_third_notification_function, token3); + notify_check_counters (1, 1, 1); + + /* Remove middle observer. */ + test_notification.detach (token2); + notify_check_counters (1, 0, 1); + + /* Remove first observer. */ + test_notification.detach (token1); + notify_check_counters (0, 0, 1); + + /* Remove last observer. */ + test_notification.detach (token3); + notify_check_counters (0, 0, 0); + + /* Go back to 3 observers, and remove them in a different + order... */ + test_notification.attach (&test_first_notification_function, token1); + test_notification.attach (&test_second_notification_function, token2); + test_notification.attach (&test_third_notification_function, token3); + notify_check_counters (1, 1, 1); + + /* Remove the third observer. */ + test_notification.detach (token3); + notify_check_counters (1, 1, 0); + + /* Remove the second observer. */ + test_notification.detach (token2); + notify_check_counters (1, 0, 0); + + /* Remove first observer, no more observers. */ + test_notification.detach (token1); + notify_check_counters (0, 0, 0); +} + +} /* namespace observers */ +} /* namespace selftests */ + +void +_initialize_observer_selftest () +{ + selftests::register_test ("gdb::observers", + selftests::observers::run_tests); +} diff --git a/gdb/valops.c b/gdb/valops.c index bf028fd..1f655b5 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -36,7 +36,7 @@ #include "cp-support.h" #include "target-float.h" #include "tracepoint.h" -#include "observer.h" +#include "observable.h" #include "objfiles.h" #include "extension.h" #include "byte-vector.h" @@ -1177,7 +1177,7 @@ value_assign (struct value *toval, struct value *fromval) } } - observer_notify_register_changed (frame, value_reg); + gdb::observers::register_changed.notify (frame, value_reg); break; } @@ -1208,7 +1208,7 @@ value_assign (struct value *toval, struct value *fromval) case lval_register: case lval_computed: - observer_notify_target_changed (¤t_target); + gdb::observers::target_changed.notify (¤t_target); /* Having destroyed the frame cache, restore the selected frame. */ |