gdb: add all_objfiles_removed observer

The new_objfile observer is currently used to indicate both when a new
objfile is added to program space (when passed non-nullptr) and when all
objfiles of a program space were just removed (when passed nullptr).
I think this is confusing (and Andrew apparently thinks so too [1]).
Add a new "all_objfiles_removed" observer to remove the second role from
"new_objfile".

Some existing users of new_objfile do nothing if the passed objfile is
nullptr.  For them, we can simply drop the nullptr check.  For others,
add a new all_objfiles_removed callback, and refactor things a bit to
keep the existing behavior as much as possible.

Some callbacks relied on current_program_space, and following
the refactoring now use either objfile->pspace or the pspace passed to
all_objfiles_removed.  I think this should be relatively safe, and in
general a step in the right direction.

On the notify side, I found only one call site to change from
new_objfile to all_objfiles_removed, in clear_symtab_users.  It is not
entirely clear to me that this is entirely correct.  clear_symtab_users
appears to be called in spots that don't remove all objfiles
(functions finish_new_objfile, remove_symbol_file_command, reread_symbols,
do_module_cleanups).  But I think that this patch at least makes the
current code clearer.

[1] a0a031bce0

Change-Id: Icb648f72862e056267f30f44dd439bd4ec766f13
Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
Simon Marchi
2023-10-03 22:20:21 -04:00
parent 74ce4f8ecf
commit 74daa597e7
16 changed files with 105 additions and 102 deletions

View File

@@ -13884,7 +13884,7 @@ static struct cmd_list_element *show_ada_list;
static void static void
ada_new_objfile_observer (struct objfile *objfile) ada_new_objfile_observer (struct objfile *objfile)
{ {
ada_clear_symbol_cache (current_program_space); ada_clear_symbol_cache (objfile->pspace);
} }
/* This module's 'free_objfile' observer. */ /* This module's 'free_objfile' observer. */
@@ -13892,7 +13892,7 @@ ada_new_objfile_observer (struct objfile *objfile)
static void static void
ada_free_objfile_observer (struct objfile *objfile) ada_free_objfile_observer (struct objfile *objfile)
{ {
ada_clear_symbol_cache (current_program_space); ada_clear_symbol_cache (objfile->pspace);
} }
/* Charsets known to GNAT. */ /* Charsets known to GNAT. */
@@ -14025,6 +14025,8 @@ DWARF attribute."),
/* The ada-lang observers. */ /* The ada-lang observers. */
gdb::observers::new_objfile.attach (ada_new_objfile_observer, "ada-lang"); gdb::observers::new_objfile.attach (ada_new_objfile_observer, "ada-lang");
gdb::observers::all_objfiles_removed.attach (ada_clear_symbol_cache,
"ada-lang");
gdb::observers::free_objfile.attach (ada_free_objfile_observer, "ada-lang"); gdb::observers::free_objfile.attach (ada_free_objfile_observer, "ada-lang");
gdb::observers::inferior_exit.attach (ada_inferior_exit, "ada-lang"); gdb::observers::inferior_exit.attach (ada_inferior_exit, "ada-lang");

View File

@@ -1469,38 +1469,31 @@ ada_tasks_normal_stop_observer (struct bpstat *unused_args, int unused_args2)
ada_task_list_changed (current_inferior ()); ada_task_list_changed (current_inferior ());
} }
/* A routine to be called when the objfiles have changed. */ /* Clear data associated to PSPACE and all inferiors using that program
space. */
static void static void
ada_tasks_new_objfile_observer (struct objfile *objfile) ada_tasks_clear_pspace_data (program_space *pspace)
{ {
/* Invalidate the relevant data in our program-space data. */
if (objfile == NULL)
{
/* All objfiles are being cleared, so we should clear all
our caches for all program spaces. */
for (struct program_space *pspace : program_spaces)
ada_tasks_invalidate_pspace_data (pspace);
}
else
{
/* The associated program-space data might have changed after /* The associated program-space data might have changed after
this objfile was added. Invalidate all cached data. */ this objfile was added. Invalidate all cached data. */
ada_tasks_invalidate_pspace_data (objfile->pspace); ada_tasks_invalidate_pspace_data (pspace);
}
/* Invalidate the per-inferior cache for all inferiors using /* Invalidate the per-inferior cache for all inferiors using
this objfile (or, in other words, for all inferiors who have this program space. */
the same program-space as the objfile's program space).
If all objfiles are being cleared (OBJFILE is NULL), then
clear the caches for all inferiors. */
for (inferior *inf : all_inferiors ()) for (inferior *inf : all_inferiors ())
if (objfile == NULL || inf->pspace == objfile->pspace) if (inf->pspace == pspace)
ada_tasks_invalidate_inferior_data (inf); ada_tasks_invalidate_inferior_data (inf);
} }
/* Called when a new objfile was added. */
static void
ada_tasks_new_objfile_observer (objfile *objfile)
{
ada_tasks_clear_pspace_data (objfile->pspace);
}
/* The qcs command line flags for the "task apply" commands. Keep /* The qcs command line flags for the "task apply" commands. Keep
this in sync with the "frame apply" commands. */ this in sync with the "frame apply" commands. */
@@ -1667,6 +1660,8 @@ _initialize_tasks ()
"ada-tasks"); "ada-tasks");
gdb::observers::new_objfile.attach (ada_tasks_new_objfile_observer, gdb::observers::new_objfile.attach (ada_tasks_new_objfile_observer,
"ada-tasks"); "ada-tasks");
gdb::observers::all_objfiles_removed.attach (ada_tasks_clear_pspace_data,
"ada-tasks");
static struct cmd_list_element *task_cmd_list; static struct cmd_list_element *task_cmd_list;
static struct cmd_list_element *task_apply_list; static struct cmd_list_element *task_apply_list;

View File

@@ -65,7 +65,7 @@ set_can_use_agent (const char *args, int from_tty, struct cmd_list_element *c)
static void static void
agent_new_objfile (struct objfile *objfile) agent_new_objfile (struct objfile *objfile)
{ {
if (objfile == NULL || agent_loaded_p ()) if (agent_loaded_p ())
return; return;
if (can_use_agent == can_use_agent_off) if (can_use_agent == can_use_agent_off)

View File

@@ -1109,13 +1109,12 @@ pd_disable (inferior *inf)
/* new_objfile observer callback. /* new_objfile observer callback.
If OBJFILE is non-null, check whether a threaded application is Check whether a threaded application is being debugged, and if so, prepare
being debugged, and if so, prepare for thread debugging. */ for thread debugging. */
static void static void
new_objfile (struct objfile *objfile) new_objfile (struct objfile *objfile)
{ {
if (objfile)
pd_enable (current_inferior ()); pd_enable (current_inferior ());
} }

View File

@@ -2543,7 +2543,7 @@ arm_exidx_new_objfile (struct objfile *objfile)
LONGEST i; LONGEST i;
/* If we've already touched this file, do nothing. */ /* If we've already touched this file, do nothing. */
if (!objfile || arm_exidx_data_key.get (objfile->obfd.get ()) != NULL) if (arm_exidx_data_key.get (objfile->obfd.get ()) != nullptr)
return; return;
/* Read contents of exception table and index. */ /* Read contents of exception table and index. */

View File

@@ -1138,7 +1138,11 @@ auto_load_section_scripts (struct objfile *objfile, const char *section_name)
} }
} }
/* Load any auto-loaded scripts for OBJFILE. */ /* Load any auto-loaded scripts for OBJFILE.
Two flavors of auto-loaded scripts are supported.
1) based on the path to the objfile
2) from .debug_gdb_scripts section */
void void
load_auto_scripts_for_objfile (struct objfile *objfile) load_auto_scripts_for_objfile (struct objfile *objfile)
@@ -1160,25 +1164,6 @@ load_auto_scripts_for_objfile (struct objfile *objfile)
auto_load_section_scripts (objfile, AUTO_SECTION_NAME); auto_load_section_scripts (objfile, AUTO_SECTION_NAME);
} }
/* This is a new_objfile observer callback to auto-load scripts.
Two flavors of auto-loaded scripts are supported.
1) based on the path to the objfile
2) from .debug_gdb_scripts section */
static void
auto_load_new_objfile (struct objfile *objfile)
{
if (!objfile)
{
/* OBJFILE is NULL when loading a new "main" symbol-file. */
clear_section_scripts (current_program_space);
return;
}
load_auto_scripts_for_objfile (objfile);
}
/* Collect scripts to be printed in a vec. */ /* Collect scripts to be printed in a vec. */
struct collect_matching_scripts_data struct collect_matching_scripts_data
@@ -1531,9 +1516,11 @@ _initialize_auto_load ()
python_name_help, guile_name_help; python_name_help, guile_name_help;
const char *suffix; const char *suffix;
gdb::observers::new_objfile.attach (auto_load_new_objfile, gdb::observers::new_objfile.attach (load_auto_scripts_for_objfile,
auto_load_new_objfile_observer_token, auto_load_new_objfile_observer_token,
"auto-load"); "auto-load");
gdb::observers::all_objfiles_removed.attach (clear_section_scripts,
"auto-load");
add_setshow_boolean_cmd ("gdb-scripts", class_support, add_setshow_boolean_cmd ("gdb-scripts", class_support,
&auto_load_gdb_scripts, _("\ &auto_load_gdb_scripts, _("\
Enable or disable auto-loading of canned sequences of commands scripts."), _("\ Enable or disable auto-loading of canned sequences of commands scripts."), _("\

View File

@@ -344,23 +344,14 @@ invalidate_auxv_cache_inf (struct inferior *inf)
auxv_inferior_data.clear (inf); auxv_inferior_data.clear (inf);
} }
/* Invalidate current inferior's auxv cache when all symbol table data is /* Invalidate the auxv cache for all inferiors using PSPACE. */
cleared (indicated by OBJFILE being nullptr). */
static void static void
auxv_new_objfile_observer (struct objfile *objfile) auxv_all_objfiles_removed (program_space *pspace)
{ {
if (objfile == nullptr)
{
/* When OBJFILE is nullptr, this indicates that all symbol files have
been unloaded from the current program space. Discard cached auxv
information from any inferior within the effected program space. */
for (inferior *inf : all_inferiors ()) for (inferior *inf : all_inferiors ())
{
if (inf->pspace == current_program_space) if (inf->pspace == current_program_space)
invalidate_auxv_cache_inf (inf); invalidate_auxv_cache_inf (inf);
}
}
} }
/* See auxv.h. */ /* See auxv.h. */
@@ -624,5 +615,6 @@ This is information provided by the operating system at program startup."));
/* Observers used to invalidate the auxv cache when needed. */ /* Observers used to invalidate the auxv cache when needed. */
gdb::observers::inferior_exit.attach (invalidate_auxv_cache_inf, "auxv"); gdb::observers::inferior_exit.attach (invalidate_auxv_cache_inf, "auxv");
gdb::observers::inferior_appeared.attach (invalidate_auxv_cache_inf, "auxv"); gdb::observers::inferior_appeared.attach (invalidate_auxv_cache_inf, "auxv");
gdb::observers::new_objfile.attach (auxv_new_objfile_observer, "auxv"); gdb::observers::all_objfiles_removed.attach (auxv_all_objfiles_removed,
"auxv");
} }

View File

@@ -1278,13 +1278,12 @@ thread_db_new_objfile (struct objfile *objfile)
/* This observer must always be called with inferior_ptid set /* This observer must always be called with inferior_ptid set
correctly. */ correctly. */
if (objfile != NULL if (/* libpthread with separate debug info has its debug info file already
/* libpthread with separate debug info has its debug info file already
loaded (and notified without successful thread_db initialization) loaded (and notified without successful thread_db initialization)
the time gdb::observers::new_objfile.notify 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 Static executables have their separate debug info loaded already
before the inferior has started. */ before the inferior has started. */
&& objfile->separate_debug_objfile_backlink == NULL objfile->separate_debug_objfile_backlink == NULL
/* Only check for thread_db if we loaded libpthread, /* Only check for thread_db if we loaded libpthread,
or if this is the main symbol file. or if this is the main symbol file.
We need to check OBJF_MAINLINE to handle the case of debugging We need to check OBJF_MAINLINE to handle the case of debugging

View File

@@ -42,6 +42,7 @@ DEFINE_OBSERVABLE (inferior_forked);
DEFINE_OBSERVABLE (solib_loaded); DEFINE_OBSERVABLE (solib_loaded);
DEFINE_OBSERVABLE (solib_unloaded); DEFINE_OBSERVABLE (solib_unloaded);
DEFINE_OBSERVABLE (new_objfile); DEFINE_OBSERVABLE (new_objfile);
DEFINE_OBSERVABLE (all_objfiles_removed);
DEFINE_OBSERVABLE (free_objfile); DEFINE_OBSERVABLE (free_objfile);
DEFINE_OBSERVABLE (new_thread); DEFINE_OBSERVABLE (new_thread);
DEFINE_OBSERVABLE (thread_exit); DEFINE_OBSERVABLE (thread_exit);

View File

@@ -107,11 +107,12 @@ extern observable<struct so_list */* solib */> solib_loaded;
extern observable<struct program_space */* pspace */, struct so_list */* solib */> extern observable<struct program_space */* pspace */, struct so_list */* solib */>
solib_unloaded; solib_unloaded;
/* The symbol file specified by OBJFILE has been loaded. Called /* The symbol file specified by OBJFILE has been loaded. */
with OBJFILE equal to NULL to indicate previously loaded symbol
table data has now been invalidated. */
extern observable<struct objfile */* objfile */> new_objfile; extern observable<struct objfile */* objfile */> new_objfile;
/* All objfiles from PSPACE were removed. */
extern observable<program_space */* pspace */> all_objfiles_removed;
/* The object file specified by OBJFILE is about to be freed. */ /* The object file specified by OBJFILE is about to be freed. */
extern observable<struct objfile */* objfile */> free_objfile; extern observable<struct objfile */* objfile */> free_objfile;

View File

@@ -190,20 +190,22 @@ python_new_objfile (struct objfile *objfile)
if (!gdb_python_initialized) if (!gdb_python_initialized)
return; return;
gdbpy_enter enter_py (objfile != NULL gdbpy_enter enter_py (objfile->arch ());
? objfile->arch ()
: target_gdbarch ());
if (objfile == NULL)
{
if (emit_clear_objfiles_event (current_program_space) < 0)
gdbpy_print_stack ();
}
else
{
if (emit_new_objfile_event (objfile) < 0) if (emit_new_objfile_event (objfile) < 0)
gdbpy_print_stack (); gdbpy_print_stack ();
} }
static void
python_all_objfiles_removed (program_space *pspace)
{
if (!gdb_python_initialized)
return;
gdbpy_enter enter_py (target_gdbarch ());
if (emit_clear_objfiles_event (pspace) < 0)
gdbpy_print_stack ();
} }
/* Emit a Python event when an objfile is about to be removed. */ /* Emit a Python event when an objfile is about to be removed. */
@@ -1020,6 +1022,8 @@ gdbpy_initialize_inferior (void)
gdb::observers::new_objfile.attach gdb::observers::new_objfile.attach
(python_new_objfile, "py-inferior", (python_new_objfile, "py-inferior",
{ &auto_load_new_objfile_observer_token }); { &auto_load_new_objfile_observer_token });
gdb::observers::all_objfiles_removed.attach (python_all_objfiles_removed,
"py-inferior");
gdb::observers::free_objfile.attach (python_free_objfile, "py-inferior"); gdb::observers::free_objfile.attach (python_free_objfile, "py-inferior");
gdb::observers::inferior_added.attach (python_new_inferior, "py-inferior"); gdb::observers::inferior_added.attach (python_new_inferior, "py-inferior");
gdb::observers::inferior_removed.attach (python_inferior_deleted, gdb::observers::inferior_removed.attach (python_inferior_deleted,

View File

@@ -14963,14 +14963,12 @@ show_remote_cmd (const char *args, int from_tty)
} }
} }
/* Some change happened in PSPACE's objfile list (obfiles added or removed),
offer all inferiors using that program space a change to look up symbols. */
/* Function to be called whenever a new objfile (shlib) is detected. */
static void static void
remote_new_objfile (struct objfile *objfile) remote_objfile_changed_check_symbols (program_space *pspace)
{ {
/* The objfile change happened in that program space. */
program_space *pspace = current_program_space;
/* The affected program space is possibly shared by multiple inferiors. /* The affected program space is possibly shared by multiple inferiors.
Consider sending a qSymbol packet for each of the inferiors using that Consider sending a qSymbol packet for each of the inferiors using that
program space. */ program space. */
@@ -15019,6 +15017,14 @@ remote_new_objfile (struct objfile *objfile)
} }
} }
/* Function to be called whenever a new objfile (shlib) is detected. */
static void
remote_new_objfile (struct objfile *objfile)
{
remote_objfile_changed_check_symbols (objfile->pspace);
}
/* Pull all the tracepoints defined on the target and create local /* Pull all the tracepoints defined on the target and create local
data structures representing them. We don't want to create real data structures representing them. We don't want to create real
tracepoints yet, we don't want to mess up the user's existing tracepoints yet, we don't want to mess up the user's existing
@@ -15333,6 +15339,8 @@ _initialize_remote ()
/* Hook into new objfile notification. */ /* Hook into new objfile notification. */
gdb::observers::new_objfile.attach (remote_new_objfile, "remote"); gdb::observers::new_objfile.attach (remote_new_objfile, "remote");
gdb::observers::all_objfiles_removed.attach
(remote_objfile_changed_check_symbols, "remote");
#if 0 #if 0
init_remote_threadtests (); init_remote_threadtests ();

View File

@@ -668,7 +668,6 @@ check_for_thread_db (void)
static void static void
sol_thread_new_objfile (struct objfile *objfile) sol_thread_new_objfile (struct objfile *objfile)
{ {
if (objfile != NULL)
check_for_thread_db (); check_for_thread_db ();
} }

View File

@@ -2915,7 +2915,7 @@ clear_symtab_users (symfile_add_flags add_flags)
clear_displays (); clear_displays ();
clear_last_displayed_sal (); clear_last_displayed_sal ();
clear_pc_function_cache (); clear_pc_function_cache ();
gdb::observers::new_objfile.notify (NULL); gdb::observers::all_objfiles_removed.notify (current_program_space);
/* Now that the various caches have been cleared, we can re_set /* Now that the various caches have been cleared, we can re_set
our breakpoints without risking it using stale data. */ our breakpoints without risking it using stale data. */

View File

@@ -1695,13 +1695,18 @@ maintenance_print_symbol_cache_statistics (const char *args, int from_tty)
static void static void
symtab_new_objfile_observer (struct objfile *objfile) symtab_new_objfile_observer (struct objfile *objfile)
{ {
/* Ideally we'd use OBJFILE->pspace, but OBJFILE may be NULL. */ symbol_cache_flush (objfile->pspace);
symbol_cache_flush (current_program_space); }
/* When all objfiles have been removed (OBJFILE is nullptr), then forget /* This module's 'all_objfiles_removed' observer. */
everything we know about the main function. */
if (objfile == nullptr) static void
set_main_name (current_program_space, nullptr, language_unknown); symtab_all_objfiles_removed (program_space *pspace)
{
symbol_cache_flush (pspace);
/* Forget everything we know about the main function. */
set_main_name (pspace, nullptr, language_unknown);
} }
/* This module's 'free_objfile' observer. */ /* This module's 'free_objfile' observer. */
@@ -7022,5 +7027,7 @@ the use of prologue scanners."),
deprecate_cmd (c, "maintenancelist flush symbol-cache"); deprecate_cmd (c, "maintenancelist flush symbol-cache");
gdb::observers::new_objfile.attach (symtab_new_objfile_observer, "symtab"); gdb::observers::new_objfile.attach (symtab_new_objfile_observer, "symtab");
gdb::observers::all_objfiles_removed.attach (symtab_all_objfiles_removed,
"symtab");
gdb::observers::free_objfile.attach (symtab_free_objfile_observer, "symtab"); gdb::observers::free_objfile.attach (symtab_free_objfile_observer, "symtab");
} }

View File

@@ -49,13 +49,20 @@
#include "gdb_curses.h" #include "gdb_curses.h"
static void static void tui_on_objfiles_changed ()
tui_new_objfile_hook (struct objfile* objfile)
{ {
if (tui_active) if (tui_active)
tui_display_main (); tui_display_main ();
} }
static void
tui_new_objfile_hook (struct objfile* objfile)
{ tui_on_objfiles_changed (); }
static void
tui_all_objfiles_removed (program_space *pspace)
{ tui_on_objfiles_changed (); }
/* Prevent recursion of deprecated_register_changed_hook(). */ /* Prevent recursion of deprecated_register_changed_hook(). */
static bool tui_refreshing_registers = false; static bool tui_refreshing_registers = false;
@@ -283,4 +290,6 @@ _initialize_tui_hooks ()
{ {
/* Install the permanent hooks. */ /* Install the permanent hooks. */
gdb::observers::new_objfile.attach (tui_new_objfile_hook, "tui-hooks"); gdb::observers::new_objfile.attach (tui_new_objfile_hook, "tui-hooks");
gdb::observers::all_objfiles_removed.attach (tui_all_objfiles_removed,
"tui-hooks");
} }