Blame SOURCES/gdb-rhbz1971095-libthread_db-update-1of5.patch

405ea9
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
405ea9
From: Simon Marchi <simon.marchi@polymtl.ca>
405ea9
Date: Tue, 8 Jun 2021 16:50:53 -0400
405ea9
Subject: gdb-rhbz1971095-libthread_db-update-1of5.patch
405ea9
405ea9
;; Backport "gdb: try to load libthread_db only after reading all
405ea9
;; shared libraries when attaching / handling a fork child"
405ea9
;; (Simon Marchi, RH BZ 1971095)
405ea9
405ea9
When trying to attach to a pthread process on a Linux system with glibc 2.33,
405ea9
we get:
405ea9
405ea9
    $ ./gdb -q -nx --data-directory=data-directory -p 1472010
405ea9
    Attaching to process 1472010
405ea9
    [New LWP 1472013]
405ea9
    [New LWP 1472014]
405ea9
    [New LWP 1472015]
405ea9
    Error while reading shared library symbols for /usr/lib/libpthread.so.0:
405ea9
    Cannot find user-level thread for LWP 1472015: generic error
405ea9
    0x00007ffff6d3637f in poll () from /usr/lib/libc.so.6
405ea9
    (gdb)
405ea9
405ea9
When attaching to a process (or handling a fork child, an operation very
405ea9
similar to attaching), GDB reads the shared library list from the
405ea9
process.  For each shared library (if "set auto-solib-add" is on), it
405ea9
reads its symbols and calls the "new_objfile" observable.
405ea9
405ea9
The libthread-db code monitors this observable, and if it sees an
405ea9
objfile named somewhat like "libpthread.so" go by, it tries to load
405ea9
libthread_db.so in the GDB process itself.  libthread_db knows how to
405ea9
navigate libpthread's data structures to get information about the
405ea9
existing threads.
405ea9
405ea9
To locate these data structures, libthread_db calls ps_pglobal_lookup
405ea9
(implemented in proc-service.c), passing in a symbol name and expecting
405ea9
an address in return.
405ea9
405ea9
Before glibc 2.33, libthread_db always asked for symbols found in
405ea9
libpthread.  There was no ordering problem: since we were always trying
405ea9
to load libthread_db in reaction to processing libpthread (and reading
405ea9
in its symbols) and libthread_db only asked symbols from libpthread, the
405ea9
requested symbols could always be found.  Starting with glibc 2.33,
405ea9
libthread_db now asks for a symbol name that can be found in
405ea9
/lib/ld-linux-x86-64.so.2 (_rtld_global).  And the ordering in which GDB
405ea9
reads the shared libraries from the inferior when attaching is
405ea9
unfortunate, in that libpthread is processed before ld-linux.  So when
405ea9
loading libthread_db in reaction to processing libpthread, and
405ea9
libthread_db requests the symbol that is from ld-linux, GDB is not yet
405ea9
able to supply it.
405ea9
405ea9
That problematic symbol lookup happens in the thread_from_lwp function,
405ea9
when we call td_ta_map_lwp2thr_p, and an exception is thrown at this
405ea9
point:
405ea9
405ea9
    #0  0x00007ffff6681012 in __cxxabiv1::__cxa_throw (obj=0x60e000006100, tinfo=0x555560033b50 <typeinfo for gdb_exception_error>, dest=0x55555d9404bc <gdb_exception_error::~gdb_exception_error()>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:78
405ea9
    #1  0x000055555e5d3734 in throw_it(return_reason, errors, const char *, typedef __va_list_tag __va_list_tag *) (reason=RETURN_ERROR, error=GENERIC_ERROR, fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", ap=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdbsupport/common-exceptions.cc:200
405ea9
    #2  0x000055555e5d37d4 in throw_verror (error=GENERIC_ERROR, fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", ap=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdbsupport/common-exceptions.cc:208
405ea9
    #3  0x000055555e0b0ed2 in verror (string=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", args=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdb/utils.c:171
405ea9
    #4  0x000055555e5e898a in error (fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s") at /home/simark/src/binutils-gdb/gdbsupport/errors.cc:43
405ea9
    #5  0x000055555d06b4bc in thread_from_lwp (stopped=0x617000035d80, ptid=...) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:418
405ea9
    #6  0x000055555d07040d in try_thread_db_load_1 (info=0x60c000011140) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:912
405ea9
    #7  0x000055555d071103 in try_thread_db_load (library=0x55555f0c62a0 "libthread_db.so.1", check_auto_load_safe=false) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1014
405ea9
    #8  0x000055555d072168 in try_thread_db_load_from_sdir () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1091
405ea9
    #9  0x000055555d072d1c in thread_db_load_search () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1146
405ea9
    #10 0x000055555d07365c in thread_db_load () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1203
405ea9
    #11 0x000055555d07373e in check_for_thread_db () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1246
405ea9
    #12 0x000055555d0738ab in thread_db_new_objfile (objfile=0x61300000c0c0) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1275
405ea9
    #13 0x000055555bd10740 in std::__invoke_impl<void, void (*&)(objfile*), objfile*> (__f=@0x616000068d88: 0x55555d073745 <thread_db_new_objfile(objfile*)>) at /usr/include/c++/10.2.0/bits/invoke.h:60
405ea9
    #14 0x000055555bd02096 in std::__invoke_r<void, void (*&)(objfile*), objfile*> (__fn=@0x616000068d88: 0x55555d073745 <thread_db_new_objfile(objfile*)>) at /usr/include/c++/10.2.0/bits/invoke.h:153
405ea9
    #15 0x000055555bce0392 in std::_Function_handler<void (objfile*), void (*)(objfile*)>::_M_invoke(std::_Any_data const&, objfile*&&) (__functor=..., __args#0=@0x7fffffffb4a0: 0x61300000c0c0) at /usr/include/c++/10.2.0/bits/std_function.h:291
405ea9
    #16 0x000055555d3595c0 in std::function<void (objfile*)>::operator()(objfile*) const (this=0x616000068d88, __args#0=0x61300000c0c0) at /usr/include/c++/10.2.0/bits/std_function.h:622
405ea9
    #17 0x000055555d356b7f in gdb::observers::observable<objfile*>::notify (this=0x555566727020 <gdb::observers::new_objfile>, args#0=0x61300000c0c0) at /home/simark/src/binutils-gdb/gdb/../gdbsupport/observable.h:106
405ea9
    #18 0x000055555da3f228 in symbol_file_add_with_addrs (abfd=0x61200001ccc0, name=0x6190000d9090 "/usr/lib/libpthread.so.0", add_flags=..., addrs=0x7fffffffbc10, flags=..., parent=0x0) at /home/simark/src/binutils-gdb/gdb/symfile.c:1131
405ea9
    #19 0x000055555da3f763 in symbol_file_add_from_bfd (abfd=0x61200001ccc0, name=0x6190000d9090 "/usr/lib/libpthread.so.0", add_flags=<error reading variable: Cannot access memory at address 0xffffffffffffffb0>, addrs=0x7fffffffbc10, flags=<error reading variable: Cannot access memory at address 0xffffffffffffffc0>, parent=0x0) at /home/simark/src/binutils-gdb/gdb/symfile.c:1167
405ea9
    #20 0x000055555d95f9fa in solib_read_symbols (so=0x6190000d8e80, flags=...) at /home/simark/src/binutils-gdb/gdb/solib.c:681
405ea9
    #21 0x000055555d96233d in solib_add (pattern=0x0, from_tty=0, readsyms=1) at /home/simark/src/binutils-gdb/gdb/solib.c:987
405ea9
    #22 0x000055555d93646e in enable_break (info=0x608000008f20, from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:2238
405ea9
    #23 0x000055555d93cfc0 in svr4_solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:3049
405ea9
    #24 0x000055555d96610d in solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib.c:1195
405ea9
    #25 0x000055555cdee318 in post_create_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:318
405ea9
    #26 0x000055555ce00e6e in setup_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:2439
405ea9
    #27 0x000055555ce59c34 in handle_one (event=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:4887
405ea9
    #28 0x000055555ce5cd00 in stop_all_threads () at /home/simark/src/binutils-gdb/gdb/infrun.c:5064
405ea9
    #29 0x000055555ce7f0da in stop_waiting (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:8006
405ea9
    #30 0x000055555ce67f5c in handle_signal_stop (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:6062
405ea9
    #31 0x000055555ce63653 in handle_inferior_event (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:5727
405ea9
    #32 0x000055555ce4f297 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:4105
405ea9
    #33 0x000055555cdbe3bf in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
405ea9
    #34 0x000055555d018047 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
405ea9
    #35 0x000055555e5ea77e in handle_file_event (file_ptr=0x60600008b1c0, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
405ea9
    #36 0x000055555e5eb09c in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
405ea9
    #37 0x000055555e5e8d19 in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
405ea9
    #38 0x000055555dd6e0d4 in wait_sync_command_done () at /home/simark/src/binutils-gdb/gdb/top.c:528
405ea9
    #39 0x000055555dd6e372 in maybe_wait_sync_command_done (was_sync=0) at /home/simark/src/binutils-gdb/gdb/top.c:545
405ea9
    #40 0x000055555d0ec7c8 in catch_command_errors (command=0x55555ce01bb8 <attach_command(char const*, int)>, arg=0x7fffffffe28d "1472010", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:452
405ea9
    #41 0x000055555d0f03ad in captured_main_1 (context=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1149
405ea9
    #42 0x000055555d0f1239 in captured_main (data=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1232
405ea9
    #43 0x000055555d0f1315 in gdb_main (args=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1257
405ea9
    #44 0x000055555bb70cf9 in main (argc=7, argv=0x7fffffffde88) at /home/simark/src/binutils-gdb/gdb/gdb.c:32
405ea9
405ea9
The exception is caught here:
405ea9
405ea9
    #0  __cxxabiv1::__cxa_begin_catch (exc_obj_in=0x60e0000060e0) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_catch.cc:84
405ea9
    #1  0x000055555d95fded in solib_read_symbols (so=0x6190000d8e80, flags=...) at /home/simark/src/binutils-gdb/gdb/solib.c:689
405ea9
    #2  0x000055555d96233d in solib_add (pattern=0x0, from_tty=0, readsyms=1) at /home/simark/src/binutils-gdb/gdb/solib.c:987
405ea9
    #3  0x000055555d93646e in enable_break (info=0x608000008f20, from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:2238
405ea9
    #4  0x000055555d93cfc0 in svr4_solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:3049
405ea9
    #5  0x000055555d96610d in solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib.c:1195
405ea9
    #6  0x000055555cdee318 in post_create_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:318
405ea9
    #7  0x000055555ce00e6e in setup_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:2439
405ea9
    #8  0x000055555ce59c34 in handle_one (event=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:4887
405ea9
    #9  0x000055555ce5cd00 in stop_all_threads () at /home/simark/src/binutils-gdb/gdb/infrun.c:5064
405ea9
    #10 0x000055555ce7f0da in stop_waiting (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:8006
405ea9
    #11 0x000055555ce67f5c in handle_signal_stop (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:6062
405ea9
    #12 0x000055555ce63653 in handle_inferior_event (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:5727
405ea9
    #13 0x000055555ce4f297 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:4105
405ea9
    #14 0x000055555cdbe3bf in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
405ea9
    #15 0x000055555d018047 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
405ea9
    #16 0x000055555e5ea77e in handle_file_event (file_ptr=0x60600008b1c0, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
405ea9
    #17 0x000055555e5eb09c in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
405ea9
    #18 0x000055555e5e8d19 in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
405ea9
    #19 0x000055555dd6e0d4 in wait_sync_command_done () at /home/simark/src/binutils-gdb/gdb/top.c:528
405ea9
    #20 0x000055555dd6e372 in maybe_wait_sync_command_done (was_sync=0) at /home/simark/src/binutils-gdb/gdb/top.c:545
405ea9
    #21 0x000055555d0ec7c8 in catch_command_errors (command=0x55555ce01bb8 <attach_command(char const*, int)>, arg=0x7fffffffe28d "1472010", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:452
405ea9
    #22 0x000055555d0f03ad in captured_main_1 (context=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1149
405ea9
    #23 0x000055555d0f1239 in captured_main (data=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1232
405ea9
    #24 0x000055555d0f1315 in gdb_main (args=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1257
405ea9
    #25 0x000055555bb70cf9 in main (argc=7, argv=0x7fffffffde88) at /home/simark/src/binutils-gdb/gdb/gdb.c:32
405ea9
405ea9
Catching the exception at this point means that the thread_db_info
405ea9
object for this inferior will be left in place, despite the failure to
405ea9
load libthread_db.  This means that there won't be further attempts at
405ea9
loading libthread_db, because thread_db_load will think that
405ea9
libthread_db is already loaded for this inferior and will always exit
405ea9
early.  To fix this, add a try/catch around calling try_thread_db_load_1
405ea9
in try_thread_db_load, such that if some exception is thrown while
405ea9
trying to load libthread_db, we reset / delete the thread_db_info for
405ea9
that inferior.  That alone makes attach work fine again, because
405ea9
check_for_thread_db is called again in the thread_db_inferior_created
405ea9
observer (that happens after we learned about all shared libraries and
405ea9
their symbols), and libthread_db is successfully loaded then.
405ea9
405ea9
When attaching, I think that the inferior_created observer is a good
405ea9
place to try to load libthread_db: it is called once everything has
405ea9
stabilized, when we learned about all shared libraries.
405ea9
405ea9
The only problem then is that when we first try (and fail) to load
405ea9
libthread_db, in reaction to learning about libpthread, we show this
405ea9
warning:
405ea9
405ea9
    warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
405ea9
405ea9
This is misleading, because we do succeed in loading it later.  So when
405ea9
attaching, I think we shouldn't try to load libthread_db in reaction to
405ea9
the new_objfile events, we should wait until we have learned about all
405ea9
shared libraries (using the inferior_created observable).  To do so, add
405ea9
an `in_initial_library_scan` flag to struct inferior.  This flag is used
405ea9
to postpone loading libthread_db if we are attaching or handling a fork
405ea9
child.
405ea9
405ea9
When debugging remotely with GDBserver, the same problem happens, except
405ea9
that the qSymbol mechanism (allowing the remote side to ask GDB for
405ea9
symbols values) is involved.  The fix there is the same idea, we make
405ea9
GDB wait until all shared libraries and their symbols are known before
405ea9
sending out a qSymbol packet.  This way, we never present the remote
405ea9
side a state where libpthread.so's symbols are known but ld-linux's
405ea9
symbols aren't.
405ea9
405ea9
gdb/ChangeLog:
405ea9
405ea9
	* inferior.h (class inferior) <in_initial_library_scan>: New.
405ea9
	* infcmd.c (post_create_inferior): Set in_initial_library_scan.
405ea9
	* infrun.c (follow_fork_inferior): Likewise.
405ea9
	* linux-thread-db.c (try_thread_db_load): Catch exception thrown
405ea9
	by try_thread_db_load_1
405ea9
	(thread_db_load): Return early if in_initial_library_scan is
405ea9
	set.
405ea9
	* remote.c (remote_new_objfile): Return early if
405ea9
	in_initial_library_scan is set.
405ea9
405ea9
Change-Id: I7a279836cfbb2b362b4fde11b196b4aab82f5efb
405ea9
405ea9
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
405ea9
--- a/gdb/infcmd.c
405ea9
+++ b/gdb/infcmd.c
405ea9
@@ -313,6 +313,10 @@ post_create_inferior (struct target_ops *target, int from_tty)
405ea9
       const unsigned solib_add_generation
405ea9
 	= current_program_space->solib_add_generation;
405ea9
 
405ea9
+      scoped_restore restore_in_initial_library_scan
405ea9
+	= make_scoped_restore (&current_inferior ()->in_initial_library_scan,
405ea9
+			       true);
405ea9
+
405ea9
       /* Create the hooks to handle shared library load and unload
405ea9
 	 events.  */
405ea9
       solib_create_inferior_hook (from_tty);
405ea9
diff --git a/gdb/inferior.h b/gdb/inferior.h
405ea9
--- a/gdb/inferior.h
405ea9
+++ b/gdb/inferior.h
405ea9
@@ -511,6 +511,10 @@ class inferior : public refcounted_object
405ea9
      architecture/description.  */
405ea9
   bool needs_setup = false;
405ea9
 
405ea9
+  /* True when we are reading the library list of the inferior during an
405ea9
+     attach or handling a fork child.  */
405ea9
+  bool in_initial_library_scan = false;
405ea9
+
405ea9
   /* Private data used by the target vector implementation.  */
405ea9
   std::unique_ptr<private_inferior> priv;
405ea9
 
405ea9
diff --git a/gdb/infrun.c b/gdb/infrun.c
405ea9
--- a/gdb/infrun.c
405ea9
+++ b/gdb/infrun.c
405ea9
@@ -540,6 +540,9 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
405ea9
 		 breakpoint.  If a "cloned-VM" event was propagated
405ea9
 		 better throughout the core, this wouldn't be
405ea9
 		 required.  */
405ea9
+	      scoped_restore restore_in_initial_library_scan
405ea9
+		= make_scoped_restore (&child_inf->in_initial_library_scan,
405ea9
+				       true);
405ea9
 	      solib_create_inferior_hook (0);
405ea9
 	    }
405ea9
 	}
405ea9
@@ -675,6 +678,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
405ea9
 	     shared libraries, and install the solib event breakpoint.
405ea9
 	     If a "cloned-VM" event was propagated better throughout
405ea9
 	     the core, this wouldn't be required.  */
405ea9
+	  scoped_restore restore_in_initial_library_scan
405ea9
+	    = make_scoped_restore (&child_inf->in_initial_library_scan, true);
405ea9
 	  solib_create_inferior_hook (0);
405ea9
 	}
405ea9
 
405ea9
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
405ea9
--- a/gdb/linux-thread-db.c
405ea9
+++ b/gdb/linux-thread-db.c
405ea9
@@ -1012,8 +1012,17 @@ try_thread_db_load (const char *library, bool check_auto_load_safe)
405ea9
   if (strchr (library, '/') != NULL)
405ea9
     info->filename = gdb_realpath (library).release ();
405ea9
 
405ea9
-  if (try_thread_db_load_1 (info))
405ea9
-    return true;
405ea9
+  try
405ea9
+    {
405ea9
+      if (try_thread_db_load_1 (info))
405ea9
+	return true;
405ea9
+    }
405ea9
+  catch (const gdb_exception_error &except)
405ea9
+    {
405ea9
+      if (libthread_db_debug)
405ea9
+	exception_fprintf (gdb_stdlog, except,
405ea9
+			   "Warning: While trying to load libthread_db: ");
405ea9
+    }
405ea9
 
405ea9
   /* This library "refused" to work on current inferior.  */
405ea9
   delete_thread_db_info (current_inferior ()->process_target (),
405ea9
@@ -1184,10 +1193,15 @@ has_libpthread (void)
405ea9
 static bool
405ea9
 thread_db_load (void)
405ea9
 {
405ea9
-  struct thread_db_info *info;
405ea9
+  inferior *inf = current_inferior ();
405ea9
 
405ea9
-  info = get_thread_db_info (current_inferior ()->process_target (),
405ea9
-			     inferior_ptid.pid ());
405ea9
+  /* When attaching / handling fork child, don't try loading libthread_db
405ea9
+     until we know about all shared libraries.  */
405ea9
+  if (inf->in_initial_library_scan)
405ea9
+    return false;
405ea9
+
405ea9
+  thread_db_info *info = get_thread_db_info (inf->process_target (),
405ea9
+					     inferior_ptid.pid ());
405ea9
 
405ea9
   if (info != NULL)
405ea9
     return true;
405ea9
diff --git a/gdb/remote.c b/gdb/remote.c
405ea9
--- a/gdb/remote.c
405ea9
+++ b/gdb/remote.c
405ea9
@@ -14299,8 +14299,26 @@ remote_new_objfile (struct objfile *objfile)
405ea9
 {
405ea9
   remote_target *remote = get_current_remote_target ();
405ea9
 
405ea9
-  if (remote != NULL)			/* Have a remote connection.  */
405ea9
-    remote->remote_check_symbols ();
405ea9
+  /* First, check whether the current inferior's process target is a remote
405ea9
+     target.  */
405ea9
+  if (remote == nullptr)
405ea9
+    return;
405ea9
+
405ea9
+  /* When we are attaching or handling a fork child and the shared library
405ea9
+     subsystem reads the list of loaded libraries, we receive new objfile
405ea9
+     events in between each found library.  The libraries are read in an
405ea9
+     undefined order, so if we gave the remote side a chance to look up
405ea9
+     symbols between each objfile, we might give it an inconsistent picture
405ea9
+     of the inferior.  It could appear that a library A appears loaded but
405ea9
+     a library B does not, even though library A requires library B.  That
405ea9
+     would present a state that couldn't normally exist in the inferior.
405ea9
+
405ea9
+     So, skip these events, we'll give the remote a chance to look up symbols
405ea9
+     once all the loaded libraries and their symbols are known to GDB.  */
405ea9
+    if (current_inferior ()->in_initial_library_scan)
405ea9
+      return;
405ea9
+
405ea9
+  remote->remote_check_symbols ();
405ea9
 }
405ea9
 
405ea9
 /* Pull all the tracepoints defined on the target and create local