diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 53d77aab62a..05c307bd303 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2021-06-08 Simon Marchi + + * inferior.h (class inferior) : New. + * infcmd.c (post_create_inferior): Set in_initial_library_scan. + * infrun.c (follow_fork_inferior): Likewise. + * linux-thread-db.c (try_thread_db_load): Catch exception thrown + by try_thread_db_load_1 + (thread_db_load): Return early if in_initial_library_scan is + set. + * remote.c (remote_new_objfile): Return early if + in_initial_library_scan is set. + 2021-06-07 Pedro Alves * dwarf2/read.c (struct partial_die_info): Add defaulted copy diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 38947ca265e..8190ba36565 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -315,6 +315,10 @@ post_create_inferior (int from_tty) const unsigned solib_add_generation = current_program_space->solib_add_generation; + scoped_restore restore_in_initial_library_scan + = make_scoped_restore (¤t_inferior ()->in_initial_library_scan, + true); + /* Create the hooks to handle shared library load and unload events. */ solib_create_inferior_hook (from_tty); diff --git a/gdb/inferior.h b/gdb/inferior.h index f4b8b025e35..f61b5889e85 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -522,6 +522,10 @@ class inferior : public refcounted_object architecture/description. */ bool needs_setup = false; + /* True when we are reading the library list of the inferior during an + attach or handling a fork child. */ + bool in_initial_library_scan = false; + /* Private data used by the target vector implementation. */ std::unique_ptr priv; diff --git a/gdb/infrun.c b/gdb/infrun.c index 488bcc1e10b..4bd21fde590 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -521,6 +521,9 @@ holding the child stopped. Try \"set detach-on-fork\" or \ breakpoint. If a "cloned-VM" event was propagated better throughout the core, this wouldn't be required. */ + scoped_restore restore_in_initial_library_scan + = make_scoped_restore (&child_inf->in_initial_library_scan, + true); solib_create_inferior_hook (0); } } @@ -656,6 +659,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \ shared libraries, and install the solib event breakpoint. If a "cloned-VM" event was propagated better throughout the core, this wouldn't be required. */ + scoped_restore restore_in_initial_library_scan + = make_scoped_restore (&child_inf->in_initial_library_scan, true); solib_create_inferior_hook (0); } diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c index 9925b02e778..d1e8c22ac96 100644 --- a/gdb/linux-thread-db.c +++ b/gdb/linux-thread-db.c @@ -1012,8 +1012,17 @@ try_thread_db_load (const char *library, bool check_auto_load_safe) if (strchr (library, '/') != NULL) info->filename = gdb_realpath (library).release (); - if (try_thread_db_load_1 (info)) - return true; + try + { + if (try_thread_db_load_1 (info)) + return true; + } + catch (const gdb_exception_error &except) + { + if (libthread_db_debug) + exception_fprintf (gdb_stdlog, except, + "Warning: While trying to load libthread_db: "); + } /* This library "refused" to work on current inferior. */ delete_thread_db_info (current_inferior ()->process_target (), @@ -1184,10 +1193,15 @@ has_libpthread (void) static bool thread_db_load (void) { - struct thread_db_info *info; + inferior *inf = current_inferior (); - info = get_thread_db_info (current_inferior ()->process_target (), - inferior_ptid.pid ()); + /* When attaching / handling fork child, don't try loading libthread_db + until we know about all shared libraries. */ + if (inf->in_initial_library_scan) + return false; + + thread_db_info *info = get_thread_db_info (inf->process_target (), + inferior_ptid.pid ()); if (info != NULL) return true; diff --git a/gdb/remote.c b/gdb/remote.c index de04aab43dc..39bdd2e4ab0 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -14522,8 +14522,26 @@ remote_new_objfile (struct objfile *objfile) { remote_target *remote = get_current_remote_target (); - if (remote != NULL) /* Have a remote connection. */ - remote->remote_check_symbols (); + /* First, check whether the current inferior's process target is a remote + target. */ + if (remote == nullptr) + return; + + /* When we are attaching or handling a fork child and the shared library + subsystem reads the list of loaded libraries, we receive new objfile + events in between each found library. The libraries are read in an + undefined order, so if we gave the remote side a chance to look up + symbols between each objfile, we might give it an inconsistent picture + of the inferior. It could appear that a library A appears loaded but + a library B does not, even though library A requires library B. That + would present a state that couldn't normally exist in the inferior. + + So, skip these events, we'll give the remote a chance to look up symbols + once all the loaded libraries and their symbols are known to GDB. */ + if (current_inferior ()->in_initial_library_scan) + return; + + remote->remote_check_symbols (); } /* Pull all the tracepoints defined on the target and create local