* [PATCH] gdb: don't abort shared library reload when one library fails to open
@ 2026-10-07 11:18 Eduard-Petru Jipa
2026-10-07 12:45 ` Rohr, Stephan
0 siblings, 1 reply; 6+ messages in thread
From: Eduard-Petru Jipa @ 2026-10-07 11:18 UTC (permalink / raw)
To: gdb-patches; +Cc: Eduard Jipa
From: Eduard Jipa <ejipa@undo.io>
When the set of shared libraries is reloaded, for example after
'set sysroot' or 'set solib-search-path', reload_shared_libraries_1
calls solib_ops::bfd_open for each library in turn. This can throw an
error, for example if the file found is not in executable format, or
its architecture is not compatible with the target.
Nothing in the loop catches that error, so a single bad library stops
the whole reload. Any libraries after it in the list are not reloaded,
and the error propagates out of the command that triggered the reload.
Catch the error, print it as a warning, and carry on with the rest of
the libraries. This matches what is already done for errors from
solib_map_sections later in the same loop. The library that failed
to open is handled as if it had not been found.
Add a test that builds a sysroot in which the first of two libraries
is not a valid object file, and checks that the second library is
still reloaded from the new sysroot after 'set sysroot'.
Tested on x86_64-linux with no regressions.
---
gdb/solib.c | 13 ++-
.../gdb.base/solib-reload-error-lib.c | 25 ++++++
gdb/testsuite/gdb.base/solib-reload-error.c | 25 ++++++
gdb/testsuite/gdb.base/solib-reload-error.exp | 81 +++++++++++++++++++
4 files changed, 143 insertions(+), 1 deletion(-)
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error-lib.c
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.c
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.exp
diff --git a/gdb/solib.c b/gdb/solib.c
index 7ea3084bf48..ad964e0afe9 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1463,7 +1463,18 @@ reload_shared_libraries_1 (int from_tty)
gdb::unique_xmalloc_ptr<char> filename
= gdb_rl_tilde_expand (so.original_name.c_str ());
- gdb_bfd_ref_ptr abfd = so.ops ().bfd_open (filename.get ());
+ gdb_bfd_ref_ptr abfd;
+ try
+ {
+ abfd = so.ops ().bfd_open (filename.get ());
+ }
+ catch (const gdb_exception_error &e)
+ {
+ exception_fprintf (gdb_stderr, e,
+ _("Error while opening shared library `%ps':\n"),
+ styled_string (file_name_style.style (),
+ filename.get ()));
+ }
if (abfd != NULL)
found_pathname = bfd_get_filename (abfd.get ());
diff --git a/gdb/testsuite/gdb.base/solib-reload-error-lib.c b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
new file mode 100644
index 00000000000..7aaa13fd697
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
@@ -0,0 +1,25 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2026 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 is compiled twice, with LIB_FUNC defined to a different
+ name each time. */
+
+int
+LIB_FUNC (void)
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/solib-reload-error.c b/gdb/testsuite/gdb.base/solib-reload-error.c
new file mode 100644
index 00000000000..465cf7e82e6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error.c
@@ -0,0 +1,25 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2026 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/>. */
+
+extern int lib1_func (void);
+extern int lib2_func (void);
+
+int
+main (void)
+{
+ return lib1_func () + lib2_func ();
+}
diff --git a/gdb/testsuite/gdb.base/solib-reload-error.exp b/gdb/testsuite/gdb.base/solib-reload-error.exp
new file mode 100644
index 00000000000..adbafde1fbe
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error.exp
@@ -0,0 +1,81 @@
+# Copyright 2026 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/>.
+
+# Check that an error opening one shared library while reloading
+# shared libraries (in this case, triggered by 'set sysroot') does not
+# stop GDB from reloading the shared libraries that come after it.
+
+require allow_shlib_tests
+require {!is_remote host}
+
+standard_testfile .c -lib.c
+
+set lib1 [standard_output_file ${testfile}-lib1.so]
+set lib2 [standard_output_file ${testfile}-lib2.so]
+
+if { [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib1 \
+ {debug additional_flags=-DLIB_FUNC=lib1_func}] != ""
+ || [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib2 \
+ {debug additional_flags=-DLIB_FUNC=lib2_func}] != "" } {
+ untested "failed to compile shared libraries"
+ return
+}
+
+# Link against lib1 first, so that it is ahead of lib2 in the list of
+# shared libraries that GDB reloads.
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
+ [list debug shlib=$lib1 shlib=$lib2]] } {
+ return
+}
+
+gdb_load_shlib $lib1
+gdb_load_shlib $lib2
+
+if { ![runto_main] } {
+ return
+}
+
+# The rest of the test relies on lib1 being reloaded before lib2.
+if { [gdb_test "info sharedlibrary" \
+ "[string_to_regexp $lib1]\r\n.*[string_to_regexp $lib2]\r\n.*" \
+ "lib1 is ahead of lib2 in the list"] != 0 } {
+ return
+}
+
+# Build a sysroot in which lib1 is not a valid object file, but lib2
+# is a good copy of the real library.
+set sysroot [standard_output_file sysroot]
+set sysroot_lib1 $sysroot$lib1
+set sysroot_lib2 $sysroot$lib2
+file delete -force $sysroot
+file mkdir [file dirname $sysroot_lib1]
+set fd [open $sysroot_lib1 w]
+puts $fd "This is not an object file."
+close $fd
+file copy $lib2 $sysroot_lib2
+
+# Changing the sysroot reloads every shared library. Opening lib1
+# fails, and GDB should report that and carry on.
+gdb_test "set sysroot $sysroot" \
+ "Error while opening shared library `[string_to_regexp $lib1]':\r\n.*not in executable format.*" \
+ "set sysroot with bad lib1"
+
+# lib2 comes after lib1 in the list, so it is only reloaded from the
+# new sysroot if the error opening lib1 did not stop the reload.
+gdb_test "info sharedlibrary" \
+ "\r\n$hex\[ \t\]+$hex\[ \t\]+Yes\[^\r\n\]*[string_to_regexp $sysroot_lib2]\r\n.*" \
+ "lib2 is reloaded from the new sysroot"
+
+gdb_test "info symbol lib2_func" "lib2_func in section \\.text of [string_to_regexp $sysroot_lib2]"
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH] gdb: don't abort shared library reload when one library fails to open
2026-10-07 11:18 [PATCH] gdb: don't abort shared library reload when one library fails to open Eduard-Petru Jipa
@ 2026-10-07 12:45 ` Rohr, Stephan
2026-10-07 13:36 ` [PATCH v2] " Eduard-Petru Jipa
0 siblings, 1 reply; 6+ messages in thread
From: Rohr, Stephan @ 2026-10-07 12:45 UTC (permalink / raw)
To: Eduard-Petru Jipa, gdb-patches
Hi Eduard,
please see my feedback below:
thanks
stephan
> -----Original Message-----
> From: Eduard-Petru Jipa <ejipa@undo.io>
> Sent: Wednesday, 7 October 2026 13:19
> To: gdb-patches@sourceware.org
> Cc: Eduard Jipa <ejipa@undo.io>
> Subject: [PATCH] gdb: don't abort shared library reload when one library fails
> to open
>
> From: Eduard Jipa <ejipa@undo.io>
>
> When the set of shared libraries is reloaded, for example after
> 'set sysroot' or 'set solib-search-path', reload_shared_libraries_1
> calls solib_ops::bfd_open for each library in turn. This can throw an
> error, for example if the file found is not in executable format, or
> its architecture is not compatible with the target.
>
> Nothing in the loop catches that error, so a single bad library stops
> the whole reload. Any libraries after it in the list are not reloaded,
> and the error propagates out of the command that triggered the reload.
>
> Catch the error, print it as a warning, and carry on with the rest of
> the libraries. This matches what is already done for errors from
> solib_map_sections later in the same loop. The library that failed
> to open is handled as if it had not been found.
>
> Add a test that builds a sysroot in which the first of two libraries
> is not a valid object file, and checks that the second library is
> still reloaded from the new sysroot after 'set sysroot'.
>
> Tested on x86_64-linux with no regressions.
> ---
> gdb/solib.c | 13 ++-
> .../gdb.base/solib-reload-error-lib.c | 25 ++++++
> gdb/testsuite/gdb.base/solib-reload-error.c | 25 ++++++
> gdb/testsuite/gdb.base/solib-reload-error.exp | 81 +++++++++++++++++++
> 4 files changed, 143 insertions(+), 1 deletion(-)
> create mode 100644 gdb/testsuite/gdb.base/solib-reload-error-lib.c
> create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.c
> create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.exp
>
> diff --git a/gdb/solib.c b/gdb/solib.c
> index 7ea3084bf48..ad964e0afe9 100644
> --- a/gdb/solib.c
> +++ b/gdb/solib.c
> @@ -1463,7 +1463,18 @@ reload_shared_libraries_1 (int from_tty)
> gdb::unique_xmalloc_ptr<char> filename
> = gdb_rl_tilde_expand (so.original_name.c_str ());
>
> - gdb_bfd_ref_ptr abfd = so.ops ().bfd_open (filename.get ());
> + gdb_bfd_ref_ptr abfd;
> + try
> + {
> + abfd = so.ops ().bfd_open (filename.get ());
> + }
> + catch (const gdb_exception_error &e)
> + {
> + exception_fprintf (gdb_stderr, e,
> + _("Error while opening shared library `%ps':\n"),
> + styled_string (file_name_style.style (),
> + filename.get ()));
I think this prints the filename twice. I tried it locally, e.g.,
Error while opening shared library [..]/gdb/testsuite/outputs/gdb.base/solib-reload-error/solib-reload-error-lib1.so':
`[..]/gdb/testsuite/outputs/gdb.base/solib-reload-error/sysroot/[..] \
/gdb/testsuite/outputs/gdb.base/solib-reload-error/solib-reload-error-lib1.so': \
not in executable format: file format not recognized
I think it would be nice to simply print
Error while opening shared library <path to lib>: <error>.
Would that be possible? If not, we could drop the first mention of the failing lib?
Also, the commit message mentions "Catch the error, print it as warning [..]" but you use
"exception_printf" here. Either reword the commit message or use "warning ()".
> + }
> if (abfd != NULL)
> found_pathname = bfd_get_filename (abfd.get ());
>
> diff --git a/gdb/testsuite/gdb.base/solib-reload-error-lib.c
> b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
> new file mode 100644
> index 00000000000..7aaa13fd697
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
> @@ -0,0 +1,25 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> + Copyright 2026 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 is compiled twice, with LIB_FUNC defined to a different
> + name each time. */
> +
> +int
> +LIB_FUNC (void)
> +{
> + return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/solib-reload-error.c
> b/gdb/testsuite/gdb.base/solib-reload-error.c
> new file mode 100644
> index 00000000000..465cf7e82e6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/solib-reload-error.c
> @@ -0,0 +1,25 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> + Copyright 2026 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/>. */
> +
> +extern int lib1_func (void);
> +extern int lib2_func (void);
> +
> +int
> +main (void)
> +{
> + return lib1_func () + lib2_func ();
> +}
> diff --git a/gdb/testsuite/gdb.base/solib-reload-error.exp
> b/gdb/testsuite/gdb.base/solib-reload-error.exp
> new file mode 100644
> index 00000000000..adbafde1fbe
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/solib-reload-error.exp
> @@ -0,0 +1,81 @@
> +# Copyright 2026 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/>.
> +
> +# Check that an error opening one shared library while reloading
> +# shared libraries (in this case, triggered by 'set sysroot') does not
> +# stop GDB from reloading the shared libraries that come after it.
> +
> +require allow_shlib_tests
> +require {!is_remote host}
> +
> +standard_testfile .c -lib.c
> +
> +set lib1 [standard_output_file ${testfile}-lib1.so]
> +set lib2 [standard_output_file ${testfile}-lib2.so]
> +
> +if { [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib1 \
> + {debug additional_flags=-DLIB_FUNC=lib1_func}] != ""
> + || [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib2 \
> + {debug additional_flags=-DLIB_FUNC=lib2_func}] != "" } {
> + untested "failed to compile shared libraries"
> + return
> +}
> +
> +# Link against lib1 first, so that it is ahead of lib2 in the list of
> +# shared libraries that GDB reloads.
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
> + [list debug shlib=$lib1 shlib=$lib2]] } {
> + return
> +}
> +
> +gdb_load_shlib $lib1
> +gdb_load_shlib $lib2
> +
> +if { ![runto_main] } {
> + return
> +}
> +
> +# The rest of the test relies on lib1 being reloaded before lib2.
> +if { [gdb_test "info sharedlibrary" \
> + "[string_to_regexp $lib1]\r\n.*[string_to_regexp $lib2]\r\n.*" \
> + "lib1 is ahead of lib2 in the list"] != 0 } {
> + return
> +}
> +
> +# Build a sysroot in which lib1 is not a valid object file, but lib2
> +# is a good copy of the real library.
> +set sysroot [standard_output_file sysroot]
> +set sysroot_lib1 $sysroot$lib1
> +set sysroot_lib2 $sysroot$lib2
> +file delete -force $sysroot
> +file mkdir [file dirname $sysroot_lib1]
> +set fd [open $sysroot_lib1 w]
> +puts $fd "This is not an object file."
> +close $fd
> +file copy $lib2 $sysroot_lib2
> +
> +# Changing the sysroot reloads every shared library. Opening lib1
> +# fails, and GDB should report that and carry on.
> +gdb_test "set sysroot $sysroot" \
> + "Error while opening shared library `[string_to_regexp $lib1]':\r\n.*not in
> executable format.*" \
> + "set sysroot with bad lib1"
> +
> +# lib2 comes after lib1 in the list, so it is only reloaded from the
> +# new sysroot if the error opening lib1 did not stop the reload.
> +gdb_test "info sharedlibrary" \
> + "\r\n$hex\[ \t\]+$hex\[ \t\]+Yes\[^\r\n\]*[string_to_regexp
Could you also cover lib1, i.e., ensure it is not loaded?
> $sysroot_lib2]\r\n.*" \
> + "lib2 is reloaded from the new sysroot"
> +
> +gdb_test "info symbol lib2_func" "lib2_func in section \\.text of
> [string_to_regexp $sysroot_lib2]"
> --
> 2.43.0
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2] gdb: don't abort shared library reload when one library fails to open
2026-10-07 12:45 ` Rohr, Stephan
@ 2026-10-07 13:36 ` Eduard-Petru Jipa
2026-10-07 15:35 ` Rohr, Stephan
0 siblings, 1 reply; 6+ messages in thread
From: Eduard-Petru Jipa @ 2026-10-07 13:36 UTC (permalink / raw)
To: gdb-patches; +Cc: stephan.rohr, Eduard Jipa
From: Eduard Jipa <ejipa@undo.io>
When the set of shared libraries is reloaded, for example after
'set sysroot' or 'set solib-search-path', reload_shared_libraries_1
calls solib_ops::bfd_open for each library in turn. This can throw an
error, for example if the file found is not in executable format, or
its architecture is not compatible with the target.
Nothing in the loop catches that error, so a single bad library stops
the whole reload. Any libraries after it in the list are not reloaded,
and the error propagates out of the command that triggered the reload.
Catch the error, print it, and carry on with the rest of the
libraries. This matches what is already done for errors from
solib_map_sections later in the same loop. The library that failed
to open is handled as if it had not been found.
Add a test that builds a sysroot in which the first of two libraries
is not a valid object file, and checks that, after 'set sysroot', the
first library is no longer loaded and the second library is reloaded
from the new sysroot.
Tested on x86_64-linux with no regressions.
---
Changes in v2:
- Print the library name only once, on a single line.
- Reword the commit message: the error is printed, not emitted with
warning ().
- Test that lib1 is not loaded after the failed reload.
Thank you Stephan for the review.
gdb/solib.c | 11 ++-
.../gdb.base/solib-reload-error-lib.c | 25 ++++++
gdb/testsuite/gdb.base/solib-reload-error.c | 25 ++++++
gdb/testsuite/gdb.base/solib-reload-error.exp | 86 +++++++++++++++++++
4 files changed, 146 insertions(+), 1 deletion(-)
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error-lib.c
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.c
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.exp
diff --git a/gdb/solib.c b/gdb/solib.c
index 7ea3084bf48..cef9a429f45 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1463,7 +1463,16 @@ reload_shared_libraries_1 (int from_tty)
gdb::unique_xmalloc_ptr<char> filename
= gdb_rl_tilde_expand (so.original_name.c_str ());
- gdb_bfd_ref_ptr abfd = so.ops ().bfd_open (filename.get ());
+ gdb_bfd_ref_ptr abfd;
+ try
+ {
+ abfd = so.ops ().bfd_open (filename.get ());
+ }
+ catch (const gdb_exception_error &e)
+ {
+ exception_fprintf (gdb_stderr, e,
+ _("Error while opening shared library: "));
+ }
if (abfd != NULL)
found_pathname = bfd_get_filename (abfd.get ());
diff --git a/gdb/testsuite/gdb.base/solib-reload-error-lib.c b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
new file mode 100644
index 00000000000..7aaa13fd697
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
@@ -0,0 +1,25 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2026 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 is compiled twice, with LIB_FUNC defined to a different
+ name each time. */
+
+int
+LIB_FUNC (void)
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/solib-reload-error.c b/gdb/testsuite/gdb.base/solib-reload-error.c
new file mode 100644
index 00000000000..465cf7e82e6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error.c
@@ -0,0 +1,25 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2026 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/>. */
+
+extern int lib1_func (void);
+extern int lib2_func (void);
+
+int
+main (void)
+{
+ return lib1_func () + lib2_func ();
+}
diff --git a/gdb/testsuite/gdb.base/solib-reload-error.exp b/gdb/testsuite/gdb.base/solib-reload-error.exp
new file mode 100644
index 00000000000..a8db733558a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error.exp
@@ -0,0 +1,86 @@
+# Copyright 2026 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/>.
+
+# Check that an error opening one shared library while reloading
+# shared libraries (in this case, triggered by 'set sysroot') does not
+# stop GDB from reloading the shared libraries that come after it.
+
+require allow_shlib_tests
+require {!is_remote host}
+
+standard_testfile .c -lib.c
+
+set lib1 [standard_output_file ${testfile}-lib1.so]
+set lib2 [standard_output_file ${testfile}-lib2.so]
+
+if { [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib1 \
+ {debug additional_flags=-DLIB_FUNC=lib1_func}] != ""
+ || [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib2 \
+ {debug additional_flags=-DLIB_FUNC=lib2_func}] != "" } {
+ untested "failed to compile shared libraries"
+ return
+}
+
+# Link against lib1 first, so that it is ahead of lib2 in the list of
+# shared libraries that GDB reloads.
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
+ [list debug shlib=$lib1 shlib=$lib2]] } {
+ return
+}
+
+gdb_load_shlib $lib1
+gdb_load_shlib $lib2
+
+if { ![runto_main] } {
+ return
+}
+
+# The rest of the test relies on lib1 being reloaded before lib2.
+if { [gdb_test "info sharedlibrary" \
+ "[string_to_regexp $lib1]\r\n.*[string_to_regexp $lib2]\r\n.*" \
+ "lib1 is ahead of lib2 in the list"] != 0 } {
+ return
+}
+
+# Build a sysroot in which lib1 is not a valid object file, but lib2
+# is a good copy of the real library.
+set sysroot [standard_output_file sysroot]
+set sysroot_lib1 $sysroot$lib1
+set sysroot_lib2 $sysroot$lib2
+file delete -force $sysroot
+file mkdir [file dirname $sysroot_lib1]
+set fd [open $sysroot_lib1 w]
+puts $fd "This is not an object file."
+close $fd
+file copy $lib2 $sysroot_lib2
+
+# Changing the sysroot reloads every shared library. Opening lib1
+# fails, and GDB should report that and carry on.
+gdb_test "set sysroot $sysroot" \
+ "Error while opening shared library: `[string_to_regexp $sysroot_lib1]': not in executable format: .*" \
+ "set sysroot with bad lib1"
+
+# lib1 could not be opened, so its symbols should no longer be loaded.
+gdb_test "info sharedlibrary" \
+ "\r\n\[ \t\]+No\[ \t\]+[string_to_regexp $lib1]\r\n.*" \
+ "lib1 is not loaded"
+
+# lib2 comes after lib1 in the list, so it is only reloaded from the
+# new sysroot if the error opening lib1 did not stop the reload.
+gdb_test "info sharedlibrary" \
+ "\r\n$hex\[ \t\]+$hex\[ \t\]+Yes\[^\r\n\]*[string_to_regexp $sysroot_lib2]\r\n.*" \
+ "lib2 is reloaded from the new sysroot"
+
+gdb_test "info symbol lib2_func" "lib2_func in section \\.text of [string_to_regexp $sysroot_lib2]"
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH v2] gdb: don't abort shared library reload when one library fails to open
2026-10-07 13:36 ` [PATCH v2] " Eduard-Petru Jipa
@ 2026-10-07 15:35 ` Rohr, Stephan
2026-10-08 13:06 ` [PATCH v3] " Eduard-Petru Jipa
0 siblings, 1 reply; 6+ messages in thread
From: Rohr, Stephan @ 2026-10-07 15:35 UTC (permalink / raw)
To: Eduard-Petru Jipa, gdb-patches
Hi Eduard,
I have one suggestion regarding the test, see below.
With that fixed:
Reviewed-By: Rohr, Stephan <stephan.rohr@intel.com>
Thanks
Stephan
> -----Original Message-----
> From: Eduard-Petru Jipa <ejipa@undo.io>
> Sent: Wednesday, 7 October 2026 15:36
> To: gdb-patches@sourceware.org
> Cc: Rohr, Stephan <stephan.rohr@intel.com>; Eduard Jipa <ejipa@undo.io>
> Subject: [PATCH v2] gdb: don't abort shared library reload when one library
> fails to open
>
> From: Eduard Jipa <ejipa@undo.io>
>
> When the set of shared libraries is reloaded, for example after
> 'set sysroot' or 'set solib-search-path', reload_shared_libraries_1
> calls solib_ops::bfd_open for each library in turn. This can throw an
> error, for example if the file found is not in executable format, or
> its architecture is not compatible with the target.
>
> Nothing in the loop catches that error, so a single bad library stops
> the whole reload. Any libraries after it in the list are not reloaded,
> and the error propagates out of the command that triggered the reload.
>
> Catch the error, print it, and carry on with the rest of the
> libraries. This matches what is already done for errors from
> solib_map_sections later in the same loop. The library that failed
> to open is handled as if it had not been found.
>
> Add a test that builds a sysroot in which the first of two libraries
> is not a valid object file, and checks that, after 'set sysroot', the
> first library is no longer loaded and the second library is reloaded
> from the new sysroot.
>
> Tested on x86_64-linux with no regressions.
> ---
>
> Changes in v2:
> - Print the library name only once, on a single line.
> - Reword the commit message: the error is printed, not emitted with
> warning ().
> - Test that lib1 is not loaded after the failed reload.
>
> Thank you Stephan for the review.
>
> gdb/solib.c | 11 ++-
> .../gdb.base/solib-reload-error-lib.c | 25 ++++++
> gdb/testsuite/gdb.base/solib-reload-error.c | 25 ++++++
> gdb/testsuite/gdb.base/solib-reload-error.exp | 86 +++++++++++++++++++
> 4 files changed, 146 insertions(+), 1 deletion(-)
> create mode 100644 gdb/testsuite/gdb.base/solib-reload-error-lib.c
> create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.c
> create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.exp
>
> diff --git a/gdb/solib.c b/gdb/solib.c
> index 7ea3084bf48..cef9a429f45 100644
> --- a/gdb/solib.c
> +++ b/gdb/solib.c
> @@ -1463,7 +1463,16 @@ reload_shared_libraries_1 (int from_tty)
> gdb::unique_xmalloc_ptr<char> filename
> = gdb_rl_tilde_expand (so.original_name.c_str ());
>
> - gdb_bfd_ref_ptr abfd = so.ops ().bfd_open (filename.get ());
> + gdb_bfd_ref_ptr abfd;
> + try
> + {
> + abfd = so.ops ().bfd_open (filename.get ());
> + }
> + catch (const gdb_exception_error &e)
> + {
> + exception_fprintf (gdb_stderr, e,
> + _("Error while opening shared library: "));
> + }
> if (abfd != NULL)
> found_pathname = bfd_get_filename (abfd.get ());
>
> diff --git a/gdb/testsuite/gdb.base/solib-reload-error-lib.c
> b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
> new file mode 100644
> index 00000000000..7aaa13fd697
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
> @@ -0,0 +1,25 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> + Copyright 2026 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 is compiled twice, with LIB_FUNC defined to a different
> + name each time. */
> +
> +int
> +LIB_FUNC (void)
> +{
> + return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/solib-reload-error.c
> b/gdb/testsuite/gdb.base/solib-reload-error.c
> new file mode 100644
> index 00000000000..465cf7e82e6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/solib-reload-error.c
> @@ -0,0 +1,25 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> + Copyright 2026 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/>. */
> +
> +extern int lib1_func (void);
> +extern int lib2_func (void);
> +
> +int
> +main (void)
> +{
> + return lib1_func () + lib2_func ();
> +}
> diff --git a/gdb/testsuite/gdb.base/solib-reload-error.exp
> b/gdb/testsuite/gdb.base/solib-reload-error.exp
> new file mode 100644
> index 00000000000..a8db733558a
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/solib-reload-error.exp
> @@ -0,0 +1,86 @@
> +# Copyright 2026 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/>.
> +
> +# Check that an error opening one shared library while reloading
> +# shared libraries (in this case, triggered by 'set sysroot') does not
> +# stop GDB from reloading the shared libraries that come after it.
> +
> +require allow_shlib_tests
> +require {!is_remote host}
> +
> +standard_testfile .c -lib.c
> +
> +set lib1 [standard_output_file ${testfile}-lib1.so]
> +set lib2 [standard_output_file ${testfile}-lib2.so]
> +
> +if { [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib1 \
> + {debug additional_flags=-DLIB_FUNC=lib1_func}] != ""
> + || [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib2 \
> + {debug additional_flags=-DLIB_FUNC=lib2_func}] != "" } {
> + untested "failed to compile shared libraries"
> + return
> +}
> +
> +# Link against lib1 first, so that it is ahead of lib2 in the list of
> +# shared libraries that GDB reloads.
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
> + [list debug shlib=$lib1 shlib=$lib2]] } {
> + return
> +}
> +
> +gdb_load_shlib $lib1
> +gdb_load_shlib $lib2
> +
> +if { ![runto_main] } {
> + return
> +}
> +
> +# The rest of the test relies on lib1 being reloaded before lib2.
> +if { [gdb_test "info sharedlibrary" \
> + "[string_to_regexp $lib1]\r\n.*[string_to_regexp $lib2]\r\n.*" \
> + "lib1 is ahead of lib2 in the list"] != 0 } {
> + return
> +}
> +
> +# Build a sysroot in which lib1 is not a valid object file, but lib2
> +# is a good copy of the real library.
> +set sysroot [standard_output_file sysroot]
> +set sysroot_lib1 $sysroot$lib1
> +set sysroot_lib2 $sysroot$lib2
> +file delete -force $sysroot
> +file mkdir [file dirname $sysroot_lib1]
> +set fd [open $sysroot_lib1 w]
> +puts $fd "This is not an object file."
> +close $fd
> +file copy $lib2 $sysroot_lib2
> +
> +# Changing the sysroot reloads every shared library. Opening lib1
> +# fails, and GDB should report that and carry on.
> +gdb_test "set sysroot $sysroot" \
> + "Error while opening shared library: `[string_to_regexp $sysroot_lib1]': not
> in executable format: .*" \
> + "set sysroot with bad lib1"
> +
> +# lib1 could not be opened, so its symbols should no longer be loaded.
> +gdb_test "info sharedlibrary" \
> + "\r\n\[ \t\]+No\[ \t\]+[string_to_regexp $lib1]\r\n.*" \
> + "lib1 is not loaded"
> +
> +# lib2 comes after lib1 in the list, so it is only reloaded from the
> +# new sysroot if the error opening lib1 did not stop the reload.
> +gdb_test "info sharedlibrary" \
> + "\r\n$hex\[ \t\]+$hex\[ \t\]+Yes\[^\r\n\]*[string_to_regexp
> $sysroot_lib2]\r\n.*" \
> + "lib2 is reloaded from the new sysroot"
> +
I think we can combine this into a single test statement, e.g.:
gdb_test "info sharedlibrary" \
[multi_line \
"" \
"\[ \t\]+No\[ \t\]+[string_to_regexp $lib1]" \
"$hex\[ \t\]+$hex\[ \t\]+Yes\[^\r\n\]*[string_to_regexp $sysroot_lib2]" \
".*"] \
"lib1 is not loaded and lib2 is reloaded from the new sysroot"
I didn't check this for correctness.
> +gdb_test "info symbol lib2_func" "lib2_func in section \\.text of
> [string_to_regexp $sysroot_lib2]"
> --
> 2.43.0
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3] gdb: don't abort shared library reload when one library fails to open
2026-10-07 15:35 ` Rohr, Stephan
@ 2026-10-08 13:06 ` Eduard-Petru Jipa
2026-10-27 14:25 ` Tom Tromey
0 siblings, 1 reply; 6+ messages in thread
From: Eduard-Petru Jipa @ 2026-10-08 13:06 UTC (permalink / raw)
To: gdb-patches; +Cc: stephan.rohr, Eduard Jipa
From: Eduard Jipa <ejipa@undo.io>
When the set of shared libraries is reloaded, for example after
'set sysroot' or 'set solib-search-path', reload_shared_libraries_1
calls solib_ops::bfd_open for each library in turn. This can throw an
error, for example if the file found is not in executable format, or
its architecture is not compatible with the target.
Nothing in the loop catches that error, so a single bad library stops
the whole reload. Any libraries after it in the list are not reloaded,
and the error propagates out of the command that triggered the reload.
Catch the error, print it, and carry on with the rest of the
libraries. This matches what is already done for errors from
solib_map_sections later in the same loop. The library that failed
to open is handled as if it had not been found.
Add a test that builds a sysroot in which the first of two libraries
is not a valid object file, and checks that, after 'set sysroot', the
first library is no longer loaded and the second library is reloaded
from the new sysroot.
Tested on x86_64-linux with no regressions.
Reviewed-By: Rohr, Stephan <stephan.rohr@intel.com>
---
Changes in v3:
- Combine the two 'info sharedlibrary' checks into a single test.
Changes in v2:
- Print the library name only once, on a single line.
- Reword the commit message: the error is printed, not emitted with
warning ().
- Test that lib1 is not loaded after the failed reload.
Thank you Stephan for the review.
gdb/solib.c | 11 ++-
.../gdb.base/solib-reload-error-lib.c | 25 ++++++
gdb/testsuite/gdb.base/solib-reload-error.c | 25 ++++++
gdb/testsuite/gdb.base/solib-reload-error.exp | 86 +++++++++++++++++++
4 files changed, 146 insertions(+), 1 deletion(-)
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error-lib.c
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.c
create mode 100644 gdb/testsuite/gdb.base/solib-reload-error.exp
diff --git a/gdb/solib.c b/gdb/solib.c
index 7ea3084bf48..cef9a429f45 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1463,7 +1463,16 @@ reload_shared_libraries_1 (int from_tty)
gdb::unique_xmalloc_ptr<char> filename
= gdb_rl_tilde_expand (so.original_name.c_str ());
- gdb_bfd_ref_ptr abfd = so.ops ().bfd_open (filename.get ());
+ gdb_bfd_ref_ptr abfd;
+ try
+ {
+ abfd = so.ops ().bfd_open (filename.get ());
+ }
+ catch (const gdb_exception_error &e)
+ {
+ exception_fprintf (gdb_stderr, e,
+ _("Error while opening shared library: "));
+ }
if (abfd != NULL)
found_pathname = bfd_get_filename (abfd.get ());
diff --git a/gdb/testsuite/gdb.base/solib-reload-error-lib.c b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
new file mode 100644
index 00000000000..7aaa13fd697
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error-lib.c
@@ -0,0 +1,25 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2026 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 is compiled twice, with LIB_FUNC defined to a different
+ name each time. */
+
+int
+LIB_FUNC (void)
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/solib-reload-error.c b/gdb/testsuite/gdb.base/solib-reload-error.c
new file mode 100644
index 00000000000..465cf7e82e6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error.c
@@ -0,0 +1,25 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2026 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/>. */
+
+extern int lib1_func (void);
+extern int lib2_func (void);
+
+int
+main (void)
+{
+ return lib1_func () + lib2_func ();
+}
diff --git a/gdb/testsuite/gdb.base/solib-reload-error.exp b/gdb/testsuite/gdb.base/solib-reload-error.exp
new file mode 100644
index 00000000000..f9e30ef49ab
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-reload-error.exp
@@ -0,0 +1,86 @@
+# Copyright 2026 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/>.
+
+# Check that an error opening one shared library while reloading
+# shared libraries (in this case, triggered by 'set sysroot') does not
+# stop GDB from reloading the shared libraries that come after it.
+
+require allow_shlib_tests
+require {!is_remote host}
+
+standard_testfile .c -lib.c
+
+set lib1 [standard_output_file ${testfile}-lib1.so]
+set lib2 [standard_output_file ${testfile}-lib2.so]
+
+if { [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib1 \
+ {debug additional_flags=-DLIB_FUNC=lib1_func}] != ""
+ || [gdb_compile_shlib $srcdir/$subdir/$srcfile2 $lib2 \
+ {debug additional_flags=-DLIB_FUNC=lib2_func}] != "" } {
+ untested "failed to compile shared libraries"
+ return
+}
+
+# Link against lib1 first, so that it is ahead of lib2 in the list of
+# shared libraries that GDB reloads.
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
+ [list debug shlib=$lib1 shlib=$lib2]] } {
+ return
+}
+
+gdb_load_shlib $lib1
+gdb_load_shlib $lib2
+
+if { ![runto_main] } {
+ return
+}
+
+# The rest of the test relies on lib1 being reloaded before lib2.
+if { [gdb_test "info sharedlibrary" \
+ "[string_to_regexp $lib1]\r\n.*[string_to_regexp $lib2]\r\n.*" \
+ "lib1 is ahead of lib2 in the list"] != 0 } {
+ return
+}
+
+# Build a sysroot in which lib1 is not a valid object file, but lib2
+# is a good copy of the real library.
+set sysroot [standard_output_file sysroot]
+set sysroot_lib1 $sysroot$lib1
+set sysroot_lib2 $sysroot$lib2
+file delete -force $sysroot
+file mkdir [file dirname $sysroot_lib1]
+set fd [open $sysroot_lib1 w]
+puts $fd "This is not an object file."
+close $fd
+file copy $lib2 $sysroot_lib2
+
+# Changing the sysroot reloads every shared library. Opening lib1
+# fails, and GDB should report that and carry on.
+gdb_test "set sysroot $sysroot" \
+ "Error while opening shared library: `[string_to_regexp $sysroot_lib1]': not in executable format: .*" \
+ "set sysroot with bad lib1"
+
+# lib1 could not be opened, so its symbols should no longer be loaded.
+# lib2 comes after lib1 in the list, so it is only reloaded from the
+# new sysroot if the error opening lib1 did not stop the reload.
+gdb_test "info sharedlibrary" \
+ [multi_line \
+ "" \
+ "\[ \t\]+No\[ \t\]+[string_to_regexp $lib1]" \
+ "$hex\[ \t\]+$hex\[ \t\]+Yes\[^\r\n\]*[string_to_regexp $sysroot_lib2]" \
+ ".*"] \
+ "lib1 is not loaded and lib2 is reloaded from the new sysroot"
+
+gdb_test "info symbol lib2_func" "lib2_func in section \\.text of [string_to_regexp $sysroot_lib2]"
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3] gdb: don't abort shared library reload when one library fails to open
2026-10-08 13:06 ` [PATCH v3] " Eduard-Petru Jipa
@ 2026-10-27 14:25 ` Tom Tromey
0 siblings, 0 replies; 6+ messages in thread
From: Tom Tromey @ 2026-10-27 14:25 UTC (permalink / raw)
To: Eduard-Petru Jipa; +Cc: gdb-patches, stephan.rohr
>>>>> Eduard-Petru Jipa <ejipa@undo.io> writes:
> From: Eduard Jipa <ejipa@undo.io>
> When the set of shared libraries is reloaded, for example after
> 'set sysroot' or 'set solib-search-path', reload_shared_libraries_1
> calls solib_ops::bfd_open for each library in turn. This can throw an
> error, for example if the file found is not in executable format, or
> its architecture is not compatible with the target.
> Nothing in the loop catches that error, so a single bad library stops
> the whole reload. Any libraries after it in the list are not reloaded,
> and the error propagates out of the command that triggered the reload.
> Catch the error, print it, and carry on with the rest of the
> libraries. This matches what is already done for errors from
> solib_map_sections later in the same loop. The library that failed
> to open is handled as if it had not been found.
> Add a test that builds a sysroot in which the first of two libraries
> is not a valid object file, and checks that, after 'set sysroot', the
> first library is no longer loaded and the second library is reloaded
> from the new sysroot.
This looks good to me. Thank you for doing this.
Approved-By: Tom Tromey <tom@tromey.com>
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-27 14:25 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-07 11:18 [PATCH] gdb: don't abort shared library reload when one library fails to open Eduard-Petru Jipa
2026-10-07 12:45 ` Rohr, Stephan
2026-10-07 13:36 ` [PATCH v2] " Eduard-Petru Jipa
2026-10-07 15:35 ` Rohr, Stephan
2026-10-08 13:06 ` [PATCH v3] " Eduard-Petru Jipa
2026-10-27 14:25 ` Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox