diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-dwz-bar.c b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-bar.c
new file mode 100644
index 00000000000..bd70ff52458
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-bar.c
@@ -0,0 +1,36 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#include "solib-with-dwz-bar.h"
+#include "solib-with-dwz-common.h"
+
+static int bar_data = 0;
+
+void
+process_bar_data (int value)
+{
+  bar_data += add_some_int (3, value);
+
+}
+
+volatile int *ptr = 0;
+
+void bar_func (void)
+{
+  /* This will hopefully trigger a segfault.  */
+  *ptr = 0;	/* Crash here.  */
+}
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-dwz-bar.h b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-bar.h
new file mode 100644
index 00000000000..d7b014bc90a
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-bar.h
@@ -0,0 +1,25 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#ifndef SOLIB_WITH_DWZ_BAR_H
+#define SOLIB_WITH_DWZ_BAR_H
+
+extern void process_bar_data (int value);
+
+extern void bar_func (void);
+
+#endif /* SOLIB_WITH_DWZ_BAR_H */
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-dwz-common.h b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-common.h
new file mode 100644
index 00000000000..653d5d497c3
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-common.h
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#ifndef SOLIB_WITH_DWZ_COMMON_H
+#define SOLIB_WITH_DWZ_COMMON_H
+
+void breakpt (int a, int b);
+
+static inline int __attribute__((always_inline))
+add_some_int (int a, int b)
+{
+  if (a > b)
+    breakpt (a, b);
+
+  return a + b;
+}
+
+#endif /* SOLIB_WITH_DWZ_COMMON_H */
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-dwz-foo.c b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-foo.c
new file mode 100644
index 00000000000..145a2e29c86
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-foo.c
@@ -0,0 +1,79 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#include "solib-with-dwz-foo.h"
+#include "solib-with-dwz-common.h"
+
+struct foo_data_type
+{
+  int positive_value;
+  int negative_value;
+};
+
+static struct foo_data_type foo_data;
+
+void
+do_callback (foo_callback_type cb)
+{
+  cb ();	/* Call line.  */
+}
+
+void
+process_foo_data (int input)
+{
+#ifdef FOO2
+  int other_value = 4;
+#else
+  int other_value = 6;
+#endif
+
+  if (input > 0)
+    foo_data.positive_value += add_some_int (input, other_value);
+  else
+    foo_data.negative_value += add_some_int (other_value, input);
+}
+
+/* This comment must appear at the end of the source file with no compiled
+   code after it.  When looking for a line number LINENO, GDB looks for a
+   symtab with a line table entry for LINENO or a later line.  It is
+   important for this test that there be no suitable line table entry.  The
+   numbers have no real meaning, I just want to ensure that the 'XXX' line,
+   which is what the test lists is far from any previous source listing.
+
+   0
+   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+   10
+   XXX: Second line to list.
+   10
+   9
+   8
+   7
+   6
+   5
+   4
+   3
+   2
+   1
+   0 */
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-dwz-foo.h b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-foo.h
new file mode 100644
index 00000000000..65eb58ae28c
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-foo.h
@@ -0,0 +1,27 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#ifndef SOLIB_WITH_DWZ_FOO_H
+#define SOLIB_WITH_DWZ_FOO_H
+
+extern void process_foo_data (int value);
+
+typedef void (*foo_callback_type) (void);
+
+extern void do_callback (foo_callback_type cb);
+
+#endif /* SOLIB_WITH_DWZ_FOO_H */
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-dwz-main.c b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-main.c
new file mode 100644
index 00000000000..10214a7e40a
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-dwz-main.c
@@ -0,0 +1,34 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#include "solib-with-dwz-foo.h"
+#include "solib-with-dwz-bar.h"
+
+void
+breakpt (int a, int b)
+{
+  (void) a;
+  (void) b;
+}
+
+int
+main (void)
+{
+  do_callback (bar_func);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.debuginfod/solib-with-dwz.exp b/gdb/testsuite/gdb.debuginfod/solib-with-dwz.exp
new file mode 100644
index 00000000000..d30707d5433
--- /dev/null
+++ b/gdb/testsuite/gdb.debuginfod/solib-with-dwz.exp
@@ -0,0 +1,344 @@
+# Copyright 2025 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 test covers a bug where GDB would try to list source lines from an
+# invalid symtab, and as a result would print a message saying that the
+# source file doesn't exist.
+#
+# Three shared libraries are compiled and their debug information is split
+# into separate .debug files.  Common debug is then extracted using the
+# 'dwz' tool.
+#
+# There are a few critical things required for the bug to manifest:
+#
+# 1. 'foo.c' must be mentioned in the dwz extracted common debug.  To
+#    achieve this two versions of libfoo are compiled with a small
+#    difference.
+#
+# 2. 'foo.c' must NOT be used by libbar.  This is why two copies of libfoo
+#    are created alongside libbar.
+#
+# 3. There must be a DWARF construct in libbar which causes the line table
+#    of the 'dwz' extracted DWARF to be read within the context of parsing
+#    libbar.  In this case we have the 'add_some_int' inlined function that
+#    is used in libbar and libfoo, as such the DW_TAG_subprogram is placed
+#    into the 'dwz' extracted DWARF, but there is a
+#    DW_TAG_inlined_subroutine in the DWARF for both libfoo and libbar.  The
+#    DW_AT_abstract_origin for the inlined subroutine points to the 'dwz'
+#    extracted DWARF file.
+#
+# What happens then is that when GDB interprets the DW_TAG_inlined_subroutine,
+# it goes off to find the DW_AT_abstract_origin, which is in the 'dwz'
+# extracted DWARF.
+#
+# While processing the DW_AT_abstract_origin GDB parses the line table from
+# the 'dwz' extracted DWARF, and creates symtabs (if not exist already).
+#
+# As the 'dwz' extracted DWARF mentions 'foo.c' in its line table, then GDB
+# ends up creating a symtab in libbar, for 'foo.c'.
+#
+# This used to be a problem as GDB could end up trying to use this symtab
+# when listing source code.  This isn't normally an issue as the symtab for
+# 'foo.c' within libbar, though misplaced, is identical to the symtab for
+# 'foo.c' that exists within libfoo.  As such, when GDB computes the source
+# path for either, the same full source path is computed, GDB will then read
+# the same file on disk.
+#
+# However, if debuginfod is involved, then the source lookup has an extra
+# check.  To fetch the source from debuginfod GDB must supply the source
+# filename AND the build-id for the original objfile, in our problematic
+# case this ends up being the build-id for libbar.
+#
+# As 'foo.c' is not a source file that is part of libbar, debuginfod refuses
+# to send this source file back, and claims the file doesn't exist.  GDB
+# would then say that the source file couldn't be found.
+#
+# However, changes in GDB means that this problem no longer exists.  When
+# looking for a source file by name, symtabs that are created for a
+# DW_TAG_partial_unit are ignored, at least in the places we care about.  As
+# a result, GDB now ignores the symtab for 'foo.c' that is created within
+# libbar.
+#
+# There is one remaining issue though, which this test does expose.  While
+# searching the symtabs, GDB will still trigger an attempt to download the
+# source code for 'foo.c' within libbar, even if, later on, GDB decides that
+# the symtab should be ignore on account of it being a DW_TAG_partial_unit.
+# This source code download is unfortunate as to the user it appears like a
+# second (unnecessary) download of the file.  There's an XFAIL in this test
+# related to this issue.
+
+load_lib debuginfod-support.exp
+
+require allow_shlib_tests
+require {istarget "*-linux*"}
+require {!is_remote host}
+require {dwz_version_at_least 0.13}
+
+standard_testfile -main.c -bar.c -foo.c
+
+set libbar_filename [standard_output_file "libbar.so"]
+set libfoo_filename [standard_output_file "libfoo.so"]
+set libfoo_2_filename [standard_output_file "libfoo-2.so"]
+
+# Compile libbar.so.
+if {[build_executable "build libbar.so" $libbar_filename \
+	 $srcfile2 { debug shlib build-id }] == -1} {
+    return
+}
+
+# If we are running with a board that splits the debug information out and
+# adds a .gnu_debuglink, then this test isn't going to work.  We want to be
+# in control of splitting out the debug information, and we definitely don't
+# want a .gnu_debuglink otherwise debuginfod isn't going to be needed.
+if {[section_get $libbar_filename ".gnu_debuglink"] ne ""} {
+    unsupported "debug information has already been split out"
+    return
+}
+
+# Compile libfoo.so.
+if {[build_executable "build libfoo.so" $libfoo_filename \
+	 $srcfile3 { debug shlib build-id }] == -1} {
+    return
+}
+
+# Compile libfoo-2.so.
+if {[build_executable "build libfoo-2.so" $libfoo_2_filename \
+	 $srcfile3 { debug shlib build-id additional_flags=-DFOO2}] == -1} {
+    return
+}
+
+# Build the executable.
+if { [build_executable "build executable" ${binfile} ${srcfile} \
+	  [list debug shlib=${libbar_filename} shlib=${libfoo_filename} shlib_load]] == -1 } {
+    return
+}
+
+# For each library file, move the debug information into a .debug
+# file.  Don't add the gnu-debuglink from the library to the debug
+# file yet as the generated CRC depends on the debug information in
+# the .debug file, and in the next step we will change that debug
+# information using the DWZ tool.
+foreach filename [list $libbar_filename $libfoo_filename $libfoo_2_filename] {
+    if {[gdb_gnu_strip_debug $filename no-debuglink]} {
+	unsupported "produce separate debug info for [file tail $filename]"
+	return
+    }
+}
+
+# Move the .debug files into the debug/ directory.
+set debug_dir [standard_output_file "debug"]
+remote_exec build "mkdir \"$debug_dir\""
+remote_exec build "mv \"${libbar_filename}.debug\" \"${debug_dir}/\""
+remote_exec build "mv \"${libfoo_filename}.debug\" \"${debug_dir}/\""
+remote_exec build "mv \"${libfoo_2_filename}.debug\" \"${debug_dir}/\""
+
+# Run DWZ tool on the separate debug files.  This moves shared debug
+# information into a 'common.dwz' file.  First move into DEBUG_DIR
+# then run DWZ using relative filenames, this means that the link
+# placed into the *.debug files will be relative, and GDB will not be
+# able to find the common.dwz file itself; as a result it will have to
+# download the file via debuginfod.
+with_cwd $debug_dir {
+    set status \
+	[remote_exec build "dwz -m ./common.dwz \
+				   ./libbar.so.debug \
+				   ./libfoo.so.debug \
+				   ./libfoo-2.so.debug"]
+    if {[lindex $status 0] != 0} {
+	unsupported "unable to run dwz tool"
+	return
+    }
+}
+
+# Some earlier versions of dwz would fail to process the .debug files,
+# producing some error output, but still exit with code 0.  A
+# successful execution of dwz should produce no output.
+if {[lindex $status 1] ne ""} {
+    unsupported "unexpected output from dwz tool"
+    return
+}
+
+# Check the debuginfod client cache directory CACHE, look in the directory
+# corresponding to libbar.so, and check to see if the *-foo.c source file,
+# global SRCFILE3, was downloaded.  Return true if the file was downloaded,
+# otherwise, return false.
+proc check_cache_for_foo { cache } {
+    set build_id [get_build_id $::libbar_filename]
+    set cache_dir $cache/$build_id
+    set files [glob -nocomplain -tails -directory $cache_dir \*$::srcfile3]
+    if { [llength $files] > 0 } {
+	return true
+    }
+    return false
+}
+
+# Use DB and DEBUG_DIR to start debuginfod, then start GDB.  Configure GDB
+# so that it cannot find the test source code; we'll download this from
+# debuginfod.  Load the test executable and run until it crashes.  Move up
+# the stack until we're in libfoo.so, specifically, in the file
+# solib-with-dwz-foo.c, then use 'list', this displays source lines around
+# the current location, and sets the default symtab within GDB.  The source
+# will have been downloaded from debuginfod.
+#
+# Now use 'list LINENO', this should display LINENO within the default
+# symtab.
+proc run_test { cache db debug_dir use_filename } {
+    set url [start_debuginfod $db $debug_dir]
+    if { $url == "" } {
+	unresolved "start debuginfod server"
+	return
+    }
+
+    # Point the client to the server.
+    setenv DEBUGINFOD_URLS $url
+
+    clean_restart
+
+    # Set the substitute-path, this prevents GDB from reading the
+    # source code directly from the file system.
+    gdb_test_no_output "set substitute-path $::srcdir /dev/null" \
+	"set substitute-path"
+
+    # And remove SRCDIR from the source directory path, this prevents
+    # GDB from reading the source files relative to this location.
+    gdb_test "with confirm off -- dir" \
+	"^Source directories searched: \\\$cdir:\\\$cwd" \
+	"reset source directory path"
+
+    # Turn on support for debuginfod.
+    gdb_test_no_output "set debuginfod enabled on" \
+	"enabled debuginfod for initial test"
+
+    # Now GDB is configured, load the executable.
+    gdb_load $::binfile
+
+    if { ![runto_main] } {
+	return
+    }
+
+    # This test relies on reading address zero triggering a SIGSEGV.
+    # If address zero is readable then give up now.
+    if { [is_address_zero_readable] } {
+	unsupported "address zero in readable"
+	return
+    }
+
+    set crash_line_num [gdb_get_line_number "Crash here" $::srcfile2]
+
+    gdb_test "continue" \
+	"\r\n$crash_line_num\\s+[string_to_regexp {*ptr = 0;	/* Crash here.  */}]"
+
+    set call_line_num [gdb_get_line_number "Call line" $::srcfile3]
+
+    gdb_test "up" \
+	"\r\n$call_line_num\\s+[string_to_regexp {cb ();	/* Call line.  */}]"
+
+    gdb_test "list" \
+	"\r\n$call_line_num\\s+[string_to_regexp {cb ();	/* Call line.  */}]\r\n.*" \
+	"list default location in $::srcfile3"
+
+    set list_line_num [gdb_get_line_number "Second line to list" $::srcfile3]
+
+    # Try 'list LINENO' or 'list FILE:LINENO'.  GDB will perform a search
+    # for the current symtab or the symtab matching FILE, and could end up
+    # finding the wrong symtab, resulting in a file not found message
+    # instead of the source code being printed.
+
+    if { $use_filename } {
+	set filename_prefix "${::srcfile3}:"
+    } else {
+	set filename_prefix ""
+    }
+
+    set saw_missing_source_warning false
+    set saw_source_download false
+    set saw_expected_source_line false
+    gdb_test_multiple "list $filename_prefix$list_line_num" "list by line number in $::srcfile3" {
+	-re "^list $filename_prefix$list_line_num\r\n" {
+	    exp_continue
+	}
+	-re "^Downloading source file \[^\r\n\]+\r\n" {
+	    set saw_source_download true
+	    exp_continue
+	}
+	-re "^warning:\\s+$::decimal\\s+\[^\r\n\]+: No such file or directory\r\n" {
+	    set saw_missing_source_warning true
+	    exp_continue
+	}
+	-re "^$list_line_num\\s+[string_to_regexp {XXX: Second line to list.}]\r\n" {
+	    set saw_expected_source_line true
+	    exp_continue
+	}
+	-re "^$::gdb_prompt $" {
+	    # If the source download reply from debuginfod is very quick,
+	    # then debuginfod might not even print a line indicating that
+	    # anything was downloaded.  If we get here an still think that
+	    # the source wasn't downloaded, then check the cache, just to
+	    # confirm.
+	    if { !$saw_source_download } {
+		set saw_source_download [check_cache_for_foo $cache]
+	    }
+
+	    # GDB ends up creating a symtab for solib-with-dwz-foo.c
+	    # associated with libbar.so.  This isn't ideal as *-foo.c wasn't
+	    # used within libbar.so.  The symtab is a result of loading the
+	    # file/line table from the DWZ file while processing the DWARF
+	    # for libbar.so.
+	    #
+	    # While performing the 'list LINENO' or 'list FILE:LINENO'
+	    # command GDB performs a search of all symtabs, as part of this
+	    # process GDB tries to establish the full source filename for
+	    # the *-foo.c symtab associated with libbar.so, this in turn
+	    # causes GDB to try and download the source from debuginfod.
+	    #
+	    # This download will fail as *-foo.c is not used within
+	    # libbar.so, but having GDB try to download the file is not
+	    # ideal, even if it is harmless.
+	    #
+	    # If/when this xfail is addressed, the comment at the start of
+	    # this file will need updating too.
+	    setup_xfail "*-*-*"
+	    gdb_assert { !$saw_source_download } \
+		"$gdb_test_name, no source download"
+
+	    gdb_assert { $saw_expected_source_line \
+			     && !$saw_missing_source_warning } \
+		"$gdb_test_name, saw source line"
+	}
+	-re "^\[^\r\n\]*\r\n" {
+	    exp_continue
+	}
+    }
+}
+
+# Create CACHE and DB directories ready for debuginfod to use.
+prepare_for_debuginfod cache db
+
+with_debuginfod_env $cache {
+    foreach_with_prefix use_filename { true false } {
+
+	# Cleanup state the will be created in run_test.  Do this before the
+	# call to make debugging the test easier; the state remains after
+	# calling run_test.
+	unset -nocomplain env(DEBUGINFOD_URLS)
+	file delete -force $cache
+	file delete -force $db
+
+	# Now run the test.
+	run_test $cache $db $debug_dir $use_filename
+	stop_debuginfod
+    }
+}
+
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index f7d9b61fec0..bdd90feef15 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -11780,5 +11780,39 @@ gdb_caching_proc have_startup_shell {} {
     return $supported
 }
 
+# Return the version number of the 'dwz' tool as a list.  If the 'dwz'
+# tool is not found, or the version cannot be established, an empty
+# list is returned.
+#
+# The 'dwz' version is currently of the form 0.12, 0.13, 0.14, etc.
+# So the returned list will have two elements, e.g. { 0 12 }.
+
+proc dwz_version { } {
+    set dwz_program "dwz"
+    set res [catch {exec $dwz_program --version} output]
+
+    # Don't check the exit value of 'dwz' process as 'dwz' doesn't
+    # exit immediately after displaying the version number, and for
+    # some reason, version 0.13 always seems to exit with a code of 1.
+    # The version number is still displayed though.
+
+    set lines [split $output \n]
+    set line [lindex $lines 0]
+    set res [regexp {dwz version[ \t]+([0-9]+)[.]([0-9]+)[^ \t]*$} \
+		 $line dummy dwz_major dwz_minor]
+    if { $res != 1 } {
+	return [list]
+    }
+
+    return [list $dwz_major $dwz_minor]
+}
+
+# Return true if the version of the 'dwz' tool is at least VER.  The
+# VER should have the same form as a 'dwz' version number, e.g. 0.12,
+# 0.13, 0.14, etc.
+proc dwz_version_at_least { ver } {
+    return [version_compare [split $ver .] <= [dwz_version]]
+}
+
 # Always load compatibility stuff.
 load_lib future.exp
