[packages/gdb] - updated to 16.3 (also using current Fedora rpm suggestions solution)

qboosh qboosh at pld-linux.org
Mon May 26 18:31:44 CEST 2025


commit 24b85cb606af569bd5bbae07828d735ce9ab596d
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date:   Mon May 26 18:08:44 2025 +0200

    - updated to 16.3 (also using current Fedora rpm suggestions solution)

 buildid-locate-rpm-pld.patch                       |   29 +-
 gdb-6.3-gstack-20050411.patch                      |  268 -----
 ...ding-warning-missing-debuginfo-rhbz981154.patch |  129 ---
 gdb-6.6-buildid-locate-rpm-librpm-workaround.patch |   19 -
 gdb-6.6-buildid-locate-solib-missing-ids.patch     |  262 -----
 gdb-6.6-buildid-locate.patch                       | 1194 --------------------
 gdb-add-rpm-suggestion-script.patch                | 1011 +++++++++++++++++
 gdb.spec                                           |   36 +-
 8 files changed, 1038 insertions(+), 1910 deletions(-)
---
diff --git a/gdb.spec b/gdb.spec
index ba49a56..0017eb5 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -1,7 +1,6 @@
 # NOTE: -lib package is used by fpc.spec
 
 # TODO
-# - debuginfod (BR: elfutils-debuginfod-devel >= 0.179)
 # - amd-dbgapi (BR: pkgconfig(amd-dbgapi) >= 0.68.0) <https://github.com/ROCm/ROCdbgapi>
 # - change install msg to poldek in buildid-locate-rpm-pld.patch when poldek allows it. LP#493922
 #
@@ -21,20 +20,17 @@ Summary(uk.UTF-8):	Символьний відладчик для С та інш
 Summary(zh_CN.UTF-8):	[开发]C和其他语言的调试器
 Summary(zh_TW.UTF-8):	[.-A開發]C和.$)B其.-A他語.$)B言的調試器
 Name:		gdb
-Version:	15.2
-Release:	3
+Version:	16.3
+Release:	1
 License:	GPL v3+
 Group:		Development/Debuggers
 Source0:	https://ftp.gnu.org/gnu/gdb/%{name}-%{version}.tar.xz
-# Source0-md5:	85c722e2f2baea2b7820a6a7eaea2ce8
+# Source0-md5:	f7a7e2d0a6d28622ac69a3623b23876b
 Source1:	http://www.mif.pg.gda.pl/homepages/ankry/man-PLD/%{name}-non-english-man-pages.tar.bz2
 # Source1-md5:	2e8a48939ae282c12bbacdd54e398247
 Source3:	%{name}-gstack.man
-Patch100:	gdb-6.6-buildid-locate.patch
-Patch101:	gdb-6.6-buildid-locate-solib-missing-ids.patch
-Patch104:	gdb-6.6-buildid-locate-rpm-librpm-workaround.patch
-Patch105:	gdb-6.6-buildid-locate-misleading-warning-missing-debuginfo-rhbz981154.patch
-Patch110:	gdb-6.3-gstack-20050411.patch
+# patch 100 from Fedora
+Patch100:	gdb-add-rpm-suggestion-script.patch
 Patch1000:	%{name}-readline.patch
 Patch1001:	%{name}-info.patch
 Patch1002:	%{name}-passflags.patch
@@ -45,6 +41,7 @@ BuildRequires:	autoconf >= 2.69
 BuildRequires:	automake
 BuildRequires:	babeltrace-devel >= 1.1.0
 BuildRequires:	bison
+BuildRequires:	elfutils-debuginfod-devel >= 0.188
 BuildRequires:	expat-devel
 BuildRequires:	flex >= 2.6.4
 BuildRequires:	gettext-tools >= 0.12.1
@@ -73,7 +70,7 @@ BuildRequires:	xxHash-devel
 BuildRequires:	xz
 BuildRequires:	xz-devel
 BuildRequires:	zlib-devel
-BuildRequires:	zstd-devel
+BuildRequires:	zstd-devel >= 1.4.0
 %if %{with python}
 BuildRequires:	python3-devel >= 1:3.2
 BuildRequires:	python3-modules >= 1:3.2
@@ -82,7 +79,9 @@ Obsoletes:	python-gdb < 7.3
 # for traceback module
 Requires:	python3-modules >= 1:3.2
 %endif
+Requires:	elfutils-debuginfod-libs >= 0.188
 %{?with_guile:Requires:	guile >= 2.0.12}
+Requires:	zstd >= 1.4.0
 BuildRoot:	%{tmpdir}/%{name}-%{version}-root-%(id -u -n)
 
 %define		autoconf_ver	%(rpm -q --qf='%%{VERSION}' autoconf)
@@ -192,10 +191,6 @@ GDB w postaci biblioteki statycznej.
 %{__rm} gdb/m2-exp.c gdb/p-exp.c
 
 %patch -P 100 -p1
-%patch -P 101 -p1
-%patch -P 104 -p1
-%patch -P 105 -p1
-%patch -P 110 -p1
 
 %patch -P 1000 -p1
 %patch -P 1001 -p1
@@ -208,20 +203,21 @@ cat > gdb/version.in << EOF
 %{version}-%{release} (PLD Linux)
 EOF
 
-%{__sed} -i -e '1s,/usr/bin/python$,%{__python},' \
+%{__sed} -i -e '1s,/usr/bin/python$,%{__python3},' \
 	contrib/dg-extract-results.py \
 
-%{__sed} -i -e '1s,/usr/bin/env python$,%{__python},' \
-	gdb/contrib/test_pubnames_and_indexes.py \
+%{__sed} -i -e '1s,/usr/bin/env python$,%{__python3},' \
 	gdb/testsuite/print-ts.py
 
 %{__sed} -i -e '1s,/usr/bin/env python3,%{__python3},' \
+	gdb/contrib/test_pubnames_and_indexes.py \
 	gdb/testsuite/analyze-racy-logs.py \
 	gdb/copyright.py
 
 %{__sed} -i -e '1s,/usr/bin/env bash,/bin/bash,' \
 	gdb/contrib/cc-with-tweaks.sh \
 	gdb/gcore.in \
+	gdb/gstack-1.in \
 	src-release.sh
 
 sed -i -e 's/\[2\.69\]/[%{autoconf_ver}]/' config/override.m4
@@ -323,9 +319,9 @@ cp -p build/libdecnumber/libdecnumber.a $RPM_BUILD_ROOT%{_libdir}
 # These are part of binutils:
 %{__rm} $RPM_BUILD_ROOT%{_localedir}/*/LC_MESSAGES/{bfd,opcodes}.mo
 %{__rm} $RPM_BUILD_ROOT%{_infodir}/{bfd,ctf-spec,sframe-spec}.info*
-%{__rm} $RPM_BUILD_ROOT%{_includedir}/{ansidecl,bfd,bfdlink,ctf,ctf-api,diagnostics,dis-asm,symcat,plugin-api}.h
-%{__rm} $RPM_BUILD_ROOT%{_libdir}/lib{bfd,ctf,ctf-nobfd,opcodes}.la
-%{__rm} $RPM_BUILD_ROOT%{_libdir}/lib{bfd,ctf,ctf-nobfd,opcodes}.a
+%{__rm} $RPM_BUILD_ROOT%{_includedir}/{ansidecl,bfd,bfdlink,ctf,ctf-api,diagnostics,dis-asm,plugin-api,sframe,sframe-api,symcat}.h
+%{__rm} $RPM_BUILD_ROOT%{_libdir}/lib{bfd,ctf,ctf-nobfd,opcodes,sframe}.la
+%{__rm} $RPM_BUILD_ROOT%{_libdir}/lib{bfd,ctf,ctf-nobfd,opcodes,sframe}.a
 
 %clean
 rm -rf $RPM_BUILD_ROOT
diff --git a/buildid-locate-rpm-pld.patch b/buildid-locate-rpm-pld.patch
index a4fd3fb..428b8f2 100644
--- a/buildid-locate-rpm-pld.patch
+++ b/buildid-locate-rpm-pld.patch
@@ -1,18 +1,11 @@
---- gdb-14.1/gdb/build-id.c.old	2014-06-05 14:31:11.000000000 +0200
-+++ gdb-14.1/gdb/build-id.c	2014-06-05 14:33:12.248235380 +0200
-@@ -1306,13 +1306,8 @@ debug_print_missing (const char *binary,
- 	      _("Missing separate debuginfo for %s.\n"), binary);
-   if (debug != NULL)
-     {
--      gdb_printf (gdb_stdlog, _("Try: %s %s\n"),
--#ifdef DNF_DEBUGINFO_INSTALL
--		  "dnf"
--#else
--		  "yum"
--#endif
--		  " --enablerepo='*debug*' install", debug);
-+	    gdb_printf (gdb_stdlog, _("Try to install package that provides `%s' file\n"),
-+			debug);
-     }
- }
- 
+--- gdb-16.3/gdb/python/lib/gdb/command/rpm-suggestions.py.orig	2025-05-25 15:48:56.578577662 +0200
++++ gdb-16.3/gdb/python/lib/gdb/command/rpm-suggestions.py	2025-05-25 21:34:58.842765490 +0200
+@@ -361,7 +361,7 @@ else:
+     # packages for the executable with the given build-id.
+     def print_build_id_suggestions(build_id_list):
+         for build_id in build_id_list:
+-            print("Missing file(s), try: dnf --enablerepo='*debug*' install "
++            print("Missing file(s), try to install packages: "
+                   + build_id_to_usr_lib_filename(build_id, False)
+                   + ' '
+                   + build_id_to_usr_lib_filename(build_id, True, ".debug"))
diff --git a/gdb-6.3-gstack-20050411.patch b/gdb-6.3-gstack-20050411.patch
deleted file mode 100644
index 90fbfa1..0000000
--- a/gdb-6.3-gstack-20050411.patch
+++ /dev/null
@@ -1,268 +0,0 @@
-From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
-From: Andrew Cagney <cagney at gnu.org>
-Date: Fri, 27 Oct 2017 21:07:50 +0200
-Subject: gdb-6.3-gstack-20050411.patch
-
-;; Add a wrapper script to GDB that implements pstack using the
-;; --readnever option.
-;;=push
-
-2004-11-23  Andrew Cagney  <cagney at redhat.com>
-
-	* Makefile.in (uninstall-gstack, install-gstack): New rules, add
-	to install and uninstall.
-	* gstack.sh, gstack.1: New files.
-
-diff --git a/gdb/Makefile.in b/gdb/Makefile.in
---- a/gdb/Makefile.in
-+++ b/gdb/Makefile.in
-@@ -2071,7 +2071,7 @@ info install-info clean-info dvi install-dvi pdf install-pdf html install-html:
- install: all
- 	@$(MAKE) $(FLAGS_TO_PASS) install-only
- 
--install-only: $(CONFIG_INSTALL)
-+install-only: install-gstack $(CONFIG_INSTALL)
- 	transformed_name=`t='$(program_transform_name)'; \
- 			  echo gdb | sed -e "$$t"` ; \
- 		if test "x$$transformed_name" = x; then \
-@@ -2121,7 +2121,25 @@ install-guile:
- install-python:
- 	$(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(GDB_DATADIR)/python/gdb
- 
--uninstall: force $(CONFIG_UNINSTALL)
-+GSTACK=gstack
-+.PHONY: install-gstack
-+install-gstack:
-+	transformed_name=`t='$(program_transform_name)'; \
-+			  echo $(GSTACK) | sed -e "$$t"` ; \
-+		if test "x$$transformed_name" = x; then \
-+		  transformed_name=$(GSTACK) ; \
-+		else \
-+		  true ; \
-+		fi ; \
-+		$(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) ; \
-+		$(INSTALL_PROGRAM) $(srcdir)/$(GSTACK).sh \
-+			$(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) ; \
-+		: $(SHELL) $(srcdir)/../mkinstalldirs \
-+			$(DESTDIR)$(man1dir) ; \
-+		: $(INSTALL_DATA) $(srcdir)/gstack.1 \
-+			$(DESTDIR)$(man1dir)/$$transformed_name.1
-+
-+uninstall: force uninstall-gstack $(CONFIG_UNINSTALL)
- 	transformed_name=`t='$(program_transform_name)'; \
- 			  echo gdb | sed -e $$t` ; \
- 		if test "x$$transformed_name" = x; then \
-@@ -2152,6 +2170,28 @@ uninstall: force $(CONFIG_UNINSTALL)
- 	rm -f $(DESTDIR)$(bindir)/$$transformed_name
- 	@$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
- 
-+.PHONY: uninstall-gstack
-+uninstall-gstack:
-+	transformed_name=`t='$(program_transform_name)'; \
-+			  echo $(GSTACK) | sed -e $$t` ; \
-+		if test "x$$transformed_name" = x; then \
-+		  transformed_name=$(GSTACK) ; \
-+		else \
-+		  true ; \
-+		fi ; \
-+		rm -f $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) \
-+		      $(DESTDIR)$(man1dir)/$$transformed_name.1
-+
-+# The C++ name parser can be built standalone for testing.
-+test-cp-name-parser.o: cp-name-parser.c
-+	$(COMPILE) -DTEST_CPNAMES cp-name-parser.c
-+	$(POSTCOMPILE)
-+
-+test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
-+	$(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) \
-+		-o test-cp-name-parser$(EXEEXT) test-cp-name-parser.o \
-+		$(LIBIBERTY)
-+
- # We do this by grepping through sources.  If that turns out to be too slow,
- # maybe we could just require every .o file to have an initialization routine
- # of a given name (top.o -> _initialize_top, etc.).
-diff --git a/gdb/gstack.sh b/gdb/gstack.sh
-new file mode 100644
---- /dev/null
-+++ b/gdb/gstack.sh
-@@ -0,0 +1,43 @@
-+#!/bin/sh
-+
-+if test $# -ne 1; then
-+    echo "Usage: `basename $0 .sh` <process-id>" 1>&2
-+    exit 1
-+fi
-+
-+if test ! -r /proc/$1; then
-+    echo "Process $1 not found." 1>&2
-+    exit 1
-+fi
-+
-+# GDB doesn't allow "thread apply all bt" when the process isn't
-+# threaded; need to peek at the process to determine if that or the
-+# simpler "bt" should be used.
-+
-+backtrace="bt"
-+if test -d /proc/$1/task ; then
-+    # Newer kernel; has a task/ directory.
-+    if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then
-+	backtrace="thread apply all bt"
-+    fi
-+elif test -f /proc/$1/maps ; then
-+    # Older kernel; go by it loading libpthread.
-+    if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
-+	backtrace="thread apply all bt"
-+    fi
-+fi
-+
-+GDB=${GDB:-gdb}
-+
-+# Run GDB, strip out unwanted noise.
-+# --readnever is no longer used since .gdb_index is now in use.
-+$GDB --quiet -nx $GDBARGS /proc/$1/exe $1 <<EOF 2>&1 |
-+set width 0
-+set height 0
-+set pagination no
-+$backtrace
-+EOF
-+/bin/sed -n \
-+    -e 's/^\((gdb) \)*//' \
-+    -e '/^#/p' \
-+    -e '/^Thread/p'
-diff --git a/gdb/testsuite/gdb.base/gstack.c b/gdb/testsuite/gdb.base/gstack.c
-new file mode 100644
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/gstack.c
-@@ -0,0 +1,43 @@
-+/* This testcase is part of GDB, the GNU debugger.
-+
-+   Copyright 2005, 2007, 2008, 2009 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 <stdio.h>
-+#include <unistd.h>
-+#include <string.h>
-+
-+void
-+func (void)
-+{
-+  const char msg[] = "looping\n";
-+
-+  /* Use the most simple notification not to get caught by attach on exiting
-+     the function.  */
-+  write (1, msg, strlen (msg));
-+
-+  for (;;);
-+}
-+
-+int
-+main (void)
-+{
-+  alarm (60);
-+  nice (100);
-+
-+  func ();
-+
-+  return 0;
-+}
-diff --git a/gdb/testsuite/gdb.base/gstack.exp b/gdb/testsuite/gdb.base/gstack.exp
-new file mode 100644
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/gstack.exp
-@@ -0,0 +1,84 @@
-+# Copyright (C) 2012 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/>.
-+
-+set testfile gstack
-+set executable ${testfile}
-+set binfile [standard_output_file $executable]
-+if {[build_executable ${testfile} ${executable} "" {debug}] == -1} {
-+    return -1
-+}
-+
-+set test "spawn inferior"
-+set command "${binfile}"
-+set res [remote_spawn host $command];
-+if { $res < 0 || $res == "" } {
-+    perror "Spawning $command failed."
-+    fail $test
-+    return
-+}
-+
-+# The spawn id of the test inferior.
-+set test_spawn_id $res
-+
-+set use_gdb_stub 1
-+set pid [exp_pid -i $res]
-+gdb_expect {
-+    -re "looping\r\n" {
-+	pass $test
-+    }
-+    eof {
-+	fail "$test (eof)"
-+	return
-+    }
-+    timeout {
-+	fail "$test (timeout)"
-+	return
-+    }
-+}
-+
-+# Testcase uses the most simple notification not to get caught by attach on
-+# exiting the function.  Still we could retry the gstack command if we fail.
-+
-+set test "spawn gstack"
-+set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $GDB_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
-+set res [remote_spawn host $command];
-+if { $res < 0 || $res == "" } {
-+    perror "Spawning $command failed."
-+    fail $test
-+}
-+
-+set gdb_spawn_id $res
-+
-+gdb_test_multiple "" $test {
-+    -re "^#0 +(0x\[0-9a-f\]+ in )?\\.?func \\(\\) at \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in \\.?main \\(\\) at \[^\r\n\]*\r\nGSTACK-END\r\n\$" {
-+	pass $test
-+    }
-+}
-+
-+gdb_test_multiple "" "gstack exits" {
-+    eof {
-+	set result [wait -i $gdb_spawn_id]
-+	verbose $result
-+
-+	gdb_assert { [lindex $result 2] == 0 } "gstack exits with no error"
-+	gdb_assert { [lindex $result 3] == 0 } "gstack's exit status is 0"
-+
-+	remote_close host
-+	clear_gdb_spawn_id
-+    }
-+}
-+
-+# Kill the test inferior.
-+kill_wait_spawned_process $test_spawn_id
diff --git a/gdb-6.6-buildid-locate-misleading-warning-missing-debuginfo-rhbz981154.patch b/gdb-6.6-buildid-locate-misleading-warning-missing-debuginfo-rhbz981154.patch
deleted file mode 100644
index 985cb6a..0000000
--- a/gdb-6.6-buildid-locate-misleading-warning-missing-debuginfo-rhbz981154.patch
+++ /dev/null
@@ -1,129 +0,0 @@
-From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
-From: Fedora GDB patches <invalid at email.com>
-Date: Fri, 27 Oct 2017 21:07:50 +0200
-Subject: 
- gdb-6.6-buildid-locate-misleading-warning-missing-debuginfo-rhbz981154.patch
-
-;; Fix 'gdb gives highly misleading error when debuginfo pkg is present,
-;; but not corresponding binary pkg' (RH BZ 981154).
-;;=push+jan
-
-Comments by Sergio Durigan Junior <sergiodj at redhat.com>:
-
-  This is the fix for RH BZ #981154
-
-  It is mainly a testcase addition, but a minor fix in the gdb/build-id.c
-  file was also needed.
-
-  gdb/build-id.c was added by:
-
-  commit dc294be54c96414035eed7d53dafdea0a6f31a72
-  Author: Tom Tromey <tromey at redhat.com>
-  Date:   Tue Oct 8 19:56:15 2013 +0000
-
-  and had a little thinko there.  The variable 'filename' needs to be set to
-  NULL after it is free'd, otherwise the code below thinks that it is still
-  valid and doesn't print the necessary warning ("Try: yum install ...").
-
-diff --git a/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
-new file mode 100644
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
-@@ -0,0 +1,97 @@
-+#   Copyright (C) 2014  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/>.
-+
-+standard_testfile "normal.c"
-+
-+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
-+    return -1
-+}
-+
-+# Get the build-id of the file
-+set build_id_debug_file [build_id_debug_filename_get $binfile]
-+regsub -all ".debug$" $build_id_debug_file "" build_id_without_debug
-+
-+# Run to main
-+if { ![runto_main] } {
-+    return -1
-+}
-+
-+# We first need to generate a corefile
-+set escapedfilename [string_to_regexp [standard_output_file gcore.test]]
-+set core_supported 0
-+gdb_test_multiple "gcore [standard_output_file gcore.test]" \
-+	"save a corefile" \
-+{
-+  -re "Saved corefile ${escapedfilename}\[\r\n\]+$gdb_prompt $" {
-+    pass "save a corefile"
-+    global core_supported
-+    set core_supported 1
-+  }
-+  -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" {
-+    unsupported "save a corefile"
-+    global core_supported
-+    set core_supported 0
-+  }
-+}
-+
-+if {!$core_supported} {
-+  return -1
-+}
-+
-+# Move the binfile to a temporary name
-+remote_exec build "mv $binfile ${binfile}.old"
-+
-+# Reinitialize GDB and see if we get a yum/dnf warning
-+gdb_exit
-+gdb_start
-+gdb_reinitialize_dir $srcdir/$subdir
-+
-+with_test_prefix "first run:" {
-+    gdb_test "set build-id-verbose 1" "" \
-+	"set build-id-verbose"
-+
-+    gdb_test "set debug-file-directory [file dirname [standard_output_file gcore.test]]" "" \
-+	"set debug-file-directory"
-+
-+    gdb_test "core-file [standard_output_file gcore.test]" \
-+	"Missing separate debuginfo for the main executable file\r\nTry: (yum|dnf) --enablerepo='\\*debug\\*' install [standard_output_file $build_id_without_debug]\r\n.*" \
-+	"test first yum/dnf warning"
-+}
-+
-+# Now we define and create our .build-id
-+file mkdir [file dirname [standard_output_file ${build_id_without_debug}]]
-+# Cannot use "file link" (from TCL) because it requires the target file to
-+# exist.
-+remote_exec build "ln -s $binfile [standard_output_file ${build_id_without_debug}]"
-+
-+# Reinitialize GDB to get the second yum/dnf warning
-+gdb_exit
-+gdb_start
-+gdb_reinitialize_dir $srcdir/$subdir
-+
-+with_test_prefix "second run:" {
-+    gdb_test "set build-id-verbose 1" "" \
-+	"set build-id-verbose"
-+
-+    gdb_test "set debug-file-directory [file dirname [standard_output_file gcore.test]]" "" \
-+	"set debug-file-directory"
-+
-+    gdb_test "core-file [standard_output_file gcore.test]" \
-+	"Missing separate debuginfo for the main executable file\r\nTry: (yum|dnf) --enablerepo='\\*debug\\*' install $binfile\r\n.*" \
-+	"test second yum/dnf warning"
-+}
-+
-+# Leaving the link there will cause breakage in the next run.
-+remote_exec build "rm -f [standard_output_file ${build_id_without_debug}]"
diff --git a/gdb-6.6-buildid-locate-rpm-librpm-workaround.patch b/gdb-6.6-buildid-locate-rpm-librpm-workaround.patch
deleted file mode 100644
index 2b862a0..0000000
--- a/gdb-6.6-buildid-locate-rpm-librpm-workaround.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
-From: Fedora GDB patches <invalid at email.com>
-Date: Fri, 27 Oct 2017 21:07:50 +0200
-Subject: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch
-
-;; Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879).
-;;=push+jan
-
-diff --git a/gdb/proc-service.list b/gdb/proc-service.list
---- a/gdb/proc-service.list
-+++ b/gdb/proc-service.list
-@@ -37,4 +37,7 @@
-   ps_pstop;
-   ps_ptread;
-   ps_ptwrite;
-+
-+  /* gdb-6.6-buildid-locate-rpm.patch */
-+  rpmsqEnable;
- };
diff --git a/gdb-6.6-buildid-locate-solib-missing-ids.patch b/gdb-6.6-buildid-locate-solib-missing-ids.patch
deleted file mode 100644
index 897f691..0000000
--- a/gdb-6.6-buildid-locate-solib-missing-ids.patch
+++ /dev/null
@@ -1,262 +0,0 @@
-From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
-From: Fedora GDB patches <invalid at email.com>
-Date: Fri, 27 Oct 2017 21:07:50 +0200
-Subject: gdb-6.6-buildid-locate-solib-missing-ids.patch
-
-;; Fix loading of core files without build-ids but with build-ids in executables.
-;; Load strictly build-id-checked core files only if no executable is specified
-;; (Jan Kratochvil, RH BZ 1339862).
-;;=push+jan
-
-gdb returns an incorrect back trace when applying a debuginfo
-https://bugzilla.redhat.com/show_bug.cgi?id=1339862
-
-diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
---- a/gdb/solib-svr4.c
-+++ b/gdb/solib-svr4.c
-@@ -347,11 +347,13 @@ lm_addr_check (const solib &so, bfd *abfd)
- 
- struct svr4_so
- {
--  svr4_so (const char *name, lm_info_svr4_up lm_info)
--    : name (name), lm_info (std::move (lm_info))
-+  svr4_so (const char *name, lm_info_svr4_up lm_info, const char *orig_name = nullptr)
-+    : name (name), original_name (orig_name == nullptr ? name : orig_name),
-+    lm_info (std::move (lm_info))
-   {}
- 
-   std::string name;
-+  std::string original_name;
-   lm_info_svr4_up lm_info;
- };
- 
-@@ -1002,6 +1004,7 @@ so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
- 
-       newobj->so_name = so.name;
-       newobj->so_original_name = so.name;
-+      newobj->so_original_name = so.original_name;
-       newobj->lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
- 
-       dst.push_back (*newobj);
-@@ -1263,11 +1266,28 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
- 	  continue;
- 	}
- 
-+      /* Preserve original name since name may be changed below.  */
-+      gdb::unique_xmalloc_ptr<char> original_name = make_unique_xstrdup (name.get ());
- 	{
--	  struct bfd_build_id *build_id;
-+	  struct bfd_build_id *build_id = nullptr;
- 
--	  build_id = build_id_addr_get (li->l_ld);
--	  if (build_id != NULL)
-+	  /* In the case the main executable was found according to its build-id
-+	     (from a core file) prevent loading a different build of a library
-+	     with accidentally the same SO_NAME.
-+
-+	     It suppresses bogus backtraces (and prints "??" there instead) if
-+	     the on-disk files no longer match the running program version.
-+	     If the main executable was not loaded according to its build-id do
-+	     not do any build-id checking of the libraries.  There may be missing
-+	     build-ids dumped in the core file and we would map all the libraries
-+	     to the only existing file loaded that time - the executable.  */
-+	  if (current_program_space->symfile_object_file != NULL
-+	      && (current_program_space->symfile_object_file->flags
-+		  & OBJF_BUILD_ID_CORE_LOADED) != 0)
-+	    build_id = build_id_addr_get (li->l_ld);
-+
-+
-+	  if (build_id != nullptr)
- 	    {
- 	      char *bid_name, *build_id_filename;
- 
-@@ -1280,23 +1300,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
- 		  xfree (bid_name);
- 		}
- 	      else
--		{
--		  debug_print_missing (name.get (), build_id_filename);
--
--		  /* In the case the main executable was found according to
--		     its build-id (from a core file) prevent loading
--		     a different build of a library with accidentally the
--		     same SO_NAME.
--
--		     It suppresses bogus backtraces (and prints "??" there
--		     instead) if the on-disk files no longer match the
--		     running program version.  */
--
--		  if (current_program_space->symfile_object_file != NULL
--		      && (current_program_space->symfile_object_file->flags
--			  & OBJF_BUILD_ID_CORE_LOADED) != 0)
--		    name = make_unique_xstrdup ("");
--		}
-+		debug_print_missing (name.get (), build_id_filename);
- 
- 	      xfree (build_id_filename);
- 	      xfree (build_id);
-diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c
-new file mode 100644
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c
-@@ -0,0 +1,21 @@
-+/* Copyright 2010 Free Software Foundation, Inc.
-+
-+   This file is part of GDB.
-+
-+   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/>.  */
-+
-+void
-+lib (void)
-+{
-+}
-diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c
-new file mode 100644
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c
-@@ -0,0 +1,25 @@
-+/* Copyright 2010 Free Software Foundation, Inc.
-+
-+   This file is part of GDB.
-+
-+   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 void lib (void);
-+
-+int
-+main (void)
-+{
-+  lib ();
-+  return 0;
-+}
-diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
-new file mode 100644
---- /dev/null
-+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
-@@ -0,0 +1,104 @@
-+# Copyright 2016 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/>.
-+
-+require allow_shlib_tests
-+
-+set testfile "gcore-buildid-exec-but-not-solib"
-+set srcmainfile ${testfile}-main.c
-+set srclibfile ${testfile}-lib.c
-+set libfile [standard_output_file ${testfile}-lib.so]
-+set objfile [standard_output_file ${testfile}-main.o]
-+set executable ${testfile}-main
-+set binfile [standard_output_file ${executable}]
-+set gcorefile [standard_output_file ${executable}.gcore]
-+set outdir [file dirname $binfile]
-+
-+if { [gdb_compile_shlib ${srcdir}/${subdir}/${srclibfile} ${libfile} "debug additional_flags=-Wl,--build-id"] != ""
-+     || [gdb_compile ${srcdir}/${subdir}/${srcmainfile} ${objfile} object {debug}] != "" } {
-+     unsupported "-Wl,--build-id compilation failed"
-+     return -1
-+}
-+set opts [list debug shlib=${libfile} "additional_flags=-Wl,--build-id"]
-+if { [gdb_compile ${objfile} ${binfile} executable $opts] != "" } {
-+     unsupported "-Wl,--build-id compilation failed"
-+     return -1
-+}
-+
-+clean_restart $executable
-+gdb_load_shlib $libfile
-+
-+# Does this gdb support gcore?
-+set test "help gcore"
-+gdb_test_multiple $test $test {
-+    -re "Undefined command: .gcore.*\r\n$gdb_prompt $" {
-+	# gcore command not supported -- nothing to test here.
-+	unsupported "gdb does not support gcore on this target"
-+	return -1;
-+    }
-+    -re "Save a core file .*\r\n$gdb_prompt $" {
-+	pass $test
-+    }
-+}
-+
-+if { ![runto lib] } then {
-+    return -1
-+}
-+
-+set escapedfilename [string_to_regexp ${gcorefile}]
-+
-+set test "save a corefile"
-+gdb_test_multiple "gcore ${gcorefile}" $test {
-+    -re "Saved corefile ${escapedfilename}\r\n$gdb_prompt $" {
-+	pass $test
-+    }
-+    -re "Can't create a corefile\r\n$gdb_prompt $" {
-+	unsupported $test
-+	return -1
-+    }
-+}
-+
-+# Now restart gdb and load the corefile.
-+
-+clean_restart $executable
-+gdb_load_shlib $libfile
-+
-+set buildid [build_id_debug_filename_get $libfile]
-+
-+regsub {\.debug$} $buildid {} buildid
-+
-+set debugdir [standard_output_file ${testfile}-debugdir]
-+file delete -force -- $debugdir
-+
-+file mkdir $debugdir/[file dirname $libfile]
-+file copy $libfile $debugdir/${libfile}
-+
-+file mkdir $debugdir/[file dirname $buildid]
-+file copy $libfile $debugdir/${buildid}
-+
-+remote_exec build "ln -s /lib       ${debugdir}/"
-+remote_exec build "ln -s /lib64     ${debugdir}/"
-+# /usr is not needed, all the libs are in /lib64: libm.so.6 libc.so.6 ld-linux-x86-64.so.2
-+
-+gdb_test_no_output "set solib-absolute-prefix $debugdir" \
-+    "set solib-absolute-prefix"
-+
-+gdb_test_no_output "set debug-file-directory $debugdir" "set debug-file-directory"
-+
-+gdb_test "core ${gcorefile}" "Core was generated by .*" "re-load generated corefile"
-+
-+gdb_test "frame" "#0 \[^\r\n\]* lib .*" "library got loaded"
-+
-+gdb_test "bt"
-+gdb_test "info shared"
diff --git a/gdb-6.6-buildid-locate.patch b/gdb-6.6-buildid-locate.patch
deleted file mode 100644
index d407b43..0000000
--- a/gdb-6.6-buildid-locate.patch
+++ /dev/null
@@ -1,1194 +0,0 @@
-From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
-From: Fedora GDB patches <invalid at email.com>
-Date: Fri, 27 Oct 2017 21:07:50 +0200
-Subject: gdb-6.6-buildid-locate.patch
-
-;; New locating of the matching binaries from the pure core file (build-id).
-;;=push+jan
-
-diff --git a/gdb/build-id.c b/gdb/build-id.c
---- a/gdb/build-id.c
-+++ b/gdb/build-id.c
-@@ -23,9 +23,67 @@
- #include "gdbsupport/gdb_vecs.h"
- #include "symfile.h"
- #include "objfiles.h"
-+#include <sys/stat.h>
-+#include "elf-bfd.h"
-+#include "elf/common.h"
-+#include "elf/external.h"
-+#include "elf/internal.h"
- #include "filenames.h"
-+#include "gdb_bfd.h"
- #include "gdbcore.h"
-+#include "cli/cli-cmds.h"
- #include "cli/cli-style.h"
-+#include "inferior.h"
-+#include "objfiles.h"
-+#include "observable.h"
-+#include "symfile.h"
-+
-+#define BUILD_ID_VERBOSE_NONE 0
-+#define BUILD_ID_VERBOSE_FILENAMES 1
-+#define BUILD_ID_VERBOSE_BINARY_PARSE 2
-+static int build_id_verbose = BUILD_ID_VERBOSE_FILENAMES;
-+static void
-+show_build_id_verbose (struct ui_file *file, int from_tty,
-+		       struct cmd_list_element *c, const char *value)
-+{
-+  gdb_printf (file, _("Verbosity level of the build-id locator is %s.\n"),
-+	      value);
-+}
-+/* Locate NT_GNU_BUILD_ID and return its matching debug filename.
-+   FIXME: NOTE decoding should be unified with the BFD core notes decoding.  */
-+
-+static struct bfd_build_id *
-+build_id_buf_get (bfd *templ, gdb_byte *buf, bfd_size_type size)
-+{
-+  bfd_byte *p;
-+
-+  p = buf;
-+  while (p < buf + size)
-+    {
-+      /* FIXME: bad alignment assumption.  */
-+      Elf_External_Note *xnp = (Elf_External_Note *) p;
-+      size_t namesz = H_GET_32 (templ, xnp->namesz);
-+      size_t descsz = H_GET_32 (templ, xnp->descsz);
-+      bfd_byte *descdata = (gdb_byte *) xnp->name + BFD_ALIGN (namesz, 4);
-+
-+      if (H_GET_32 (templ, xnp->type) == NT_GNU_BUILD_ID
-+	  && namesz == sizeof "GNU"
-+	  && memcmp (xnp->name, "GNU", sizeof "GNU") == 0)
-+	{
-+	  size_t sz = descsz;
-+	  gdb_byte *data = (gdb_byte *) descdata;
-+	  struct bfd_build_id *retval;
-+
-+	  retval = (struct bfd_build_id *) xmalloc (sizeof *retval - 1 + sz);
-+	  retval->size = sz;
-+	  memcpy (retval->data, data, sz);
-+
-+	  return retval;
-+	}
-+      p = descdata + BFD_ALIGN (descsz, 4);
-+    }
-+  return NULL;
-+}
- 
- /* See build-id.h.  */
- 
-@@ -49,6 +107,349 @@ build_id_bfd_get (bfd *abfd)
-   return NULL;
- }
- 
-+/* Core files may have missing (corrupt) SHDR but PDHR is correct there.
-+   bfd_elf_bfd_from_remote_memory () has too much overhead by
-+   allocating/reading all the available ELF PT_LOADs.  */
-+
-+static struct bfd_build_id *
-+build_id_phdr_get (bfd *templ, bfd_vma loadbase, unsigned e_phnum,
-+		   Elf_Internal_Phdr *i_phdr)
-+{
-+  int i;
-+  struct bfd_build_id *retval = NULL;
-+
-+  for (i = 0; i < e_phnum; i++)
-+    if (i_phdr[i].p_type == PT_NOTE && i_phdr[i].p_filesz > 0)
-+      {
-+	Elf_Internal_Phdr *hdr = &i_phdr[i];
-+	gdb_byte *buf;
-+	int err;
-+
-+	buf = (gdb_byte *) xmalloc (hdr->p_filesz);
-+	err = target_read_memory (loadbase + i_phdr[i].p_vaddr, buf,
-+				  hdr->p_filesz);
-+	if (err == 0)
-+	  retval = build_id_buf_get (templ, buf, hdr->p_filesz);
-+	else
-+	  retval = NULL;
-+	xfree (buf);
-+	if (retval != NULL)
-+	  break;
-+      }
-+  return retval;
-+}
-+
-+/* First we validate the file by reading in the ELF header and checking
-+   the magic number.  */
-+
-+static inline bfd_boolean
-+elf_file_p (Elf64_External_Ehdr *x_ehdrp64)
-+{
-+  gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr));
-+  gdb_assert (offsetof (Elf64_External_Ehdr, e_ident)
-+	      == offsetof (Elf32_External_Ehdr, e_ident));
-+  gdb_assert (sizeof (((Elf64_External_Ehdr *) 0)->e_ident)
-+	      == sizeof (((Elf32_External_Ehdr *) 0)->e_ident));
-+
-+  return ((x_ehdrp64->e_ident[EI_MAG0] == ELFMAG0)
-+	  && (x_ehdrp64->e_ident[EI_MAG1] == ELFMAG1)
-+	  && (x_ehdrp64->e_ident[EI_MAG2] == ELFMAG2)
-+	  && (x_ehdrp64->e_ident[EI_MAG3] == ELFMAG3));
-+}
-+
-+/* Translate an ELF file header in external format into an ELF file header in
-+   internal format.  */
-+
-+#define H_GET_WORD(bfd, ptr) (is64 ? H_GET_64 (bfd, (ptr))		\
-+				   : H_GET_32 (bfd, (ptr)))
-+#define H_GET_SIGNED_WORD(bfd, ptr) (is64 ? H_GET_S64 (bfd, (ptr))	\
-+					  : H_GET_S32 (bfd, (ptr)))
-+
-+static void
-+elf_swap_ehdr_in (bfd *abfd,
-+		  const Elf64_External_Ehdr *src64,
-+		  Elf_Internal_Ehdr *dst)
-+{
-+  int is64 = bfd_get_arch_size (abfd) == 64;
-+#define SRC(field) (is64 ? src64->field \
-+			 : ((const Elf32_External_Ehdr *) src64)->field)
-+
-+  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
-+  memcpy (dst->e_ident, SRC (e_ident), EI_NIDENT);
-+  dst->e_type = H_GET_16 (abfd, SRC (e_type));
-+  dst->e_machine = H_GET_16 (abfd, SRC (e_machine));
-+  dst->e_version = H_GET_32 (abfd, SRC (e_version));
-+  if (signed_vma)
-+    dst->e_entry = H_GET_SIGNED_WORD (abfd, SRC (e_entry));
-+  else
-+    dst->e_entry = H_GET_WORD (abfd, SRC (e_entry));
-+  dst->e_phoff = H_GET_WORD (abfd, SRC (e_phoff));
-+  dst->e_shoff = H_GET_WORD (abfd, SRC (e_shoff));
-+  dst->e_flags = H_GET_32 (abfd, SRC (e_flags));
-+  dst->e_ehsize = H_GET_16 (abfd, SRC (e_ehsize));
-+  dst->e_phentsize = H_GET_16 (abfd, SRC (e_phentsize));
-+  dst->e_phnum = H_GET_16 (abfd, SRC (e_phnum));
-+  dst->e_shentsize = H_GET_16 (abfd, SRC (e_shentsize));
-+  dst->e_shnum = H_GET_16 (abfd, SRC (e_shnum));
-+  dst->e_shstrndx = H_GET_16 (abfd, SRC (e_shstrndx));
-+
-+#undef SRC
-+}
-+
-+/* Translate an ELF program header table entry in external format into an
-+   ELF program header table entry in internal format.  */
-+
-+static void
-+elf_swap_phdr_in (bfd *abfd,
-+		  const Elf64_External_Phdr *src64,
-+		  Elf_Internal_Phdr *dst)
-+{
-+  int is64 = bfd_get_arch_size (abfd) == 64;
-+#define SRC(field) (is64 ? src64->field					\
-+			 : ((const Elf32_External_Phdr *) src64)->field)
-+
-+  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
-+
-+  dst->p_type = H_GET_32 (abfd, SRC (p_type));
-+  dst->p_flags = H_GET_32 (abfd, SRC (p_flags));
-+  dst->p_offset = H_GET_WORD (abfd, SRC (p_offset));
-+  if (signed_vma)
-+    {
-+      dst->p_vaddr = H_GET_SIGNED_WORD (abfd, SRC (p_vaddr));
-+      dst->p_paddr = H_GET_SIGNED_WORD (abfd, SRC (p_paddr));
-+    }
-+  else
-+    {
-+      dst->p_vaddr = H_GET_WORD (abfd, SRC (p_vaddr));
-+      dst->p_paddr = H_GET_WORD (abfd, SRC (p_paddr));
-+    }
-+  dst->p_filesz = H_GET_WORD (abfd, SRC (p_filesz));
-+  dst->p_memsz = H_GET_WORD (abfd, SRC (p_memsz));
-+  dst->p_align = H_GET_WORD (abfd, SRC (p_align));
-+
-+#undef SRC
-+}
-+
-+#undef H_GET_SIGNED_WORD
-+#undef H_GET_WORD
-+
-+static Elf_Internal_Phdr *
-+elf_get_phdr (bfd *templ, bfd_vma ehdr_vma, unsigned *e_phnum_pointer,
-+              bfd_vma *loadbase_pointer)
-+{
-+  /* sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr)  */
-+  Elf64_External_Ehdr x_ehdr64;	/* Elf file header, external form */
-+  Elf_Internal_Ehdr i_ehdr;	/* Elf file header, internal form */
-+  bfd_size_type x_phdrs_size;
-+  gdb_byte *x_phdrs_ptr;
-+  Elf_Internal_Phdr *i_phdrs;
-+  int err;
-+  unsigned int i;
-+  bfd_vma loadbase;
-+  int loadbase_set;
-+
-+  gdb_assert (templ != NULL);
-+  gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr));
-+
-+  /* Read in the ELF header in external format.  */
-+  err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr64, sizeof x_ehdr64);
-+  if (err)
-+    {
-+      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
-+        warning (_("build-id: Error reading ELF header at address 0x%lx"),
-+		 (unsigned long) ehdr_vma);
-+      return NULL;
-+    }
-+
-+  /* Now check to see if we have a valid ELF file, and one that BFD can
-+     make use of.  The magic number must match, the address size ('class')
-+     and byte-swapping must match our XVEC entry.  */
-+
-+  if (! elf_file_p (&x_ehdr64)
-+      || x_ehdr64.e_ident[EI_VERSION] != EV_CURRENT
-+      || !((bfd_get_arch_size (templ) == 64
-+            && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS64)
-+           || (bfd_get_arch_size (templ) == 32
-+	       && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS32)))
-+    {
-+      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
-+        warning (_("build-id: Unrecognized ELF header at address 0x%lx"),
-+		 (unsigned long) ehdr_vma);
-+      return NULL;
-+    }
-+
-+  /* Check that file's byte order matches xvec's */
-+  switch (x_ehdr64.e_ident[EI_DATA])
-+    {
-+    case ELFDATA2MSB:		/* Big-endian */
-+      if (! bfd_header_big_endian (templ))
-+	{
-+	  if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
-+	    warning (_("build-id: Unrecognized "
-+		       "big-endian ELF header at address 0x%lx"),
-+		     (unsigned long) ehdr_vma);
-+	  return NULL;
-+	}
-+      break;
-+    case ELFDATA2LSB:		/* Little-endian */
-+      if (! bfd_header_little_endian (templ))
-+	{
-+	  if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
-+	    warning (_("build-id: Unrecognized "
-+		       "little-endian ELF header at address 0x%lx"),
-+		     (unsigned long) ehdr_vma);
-+	  return NULL;
-+	}
-+      break;
-+    case ELFDATANONE:		/* No data encoding specified */
-+    default:			/* Unknown data encoding specified */
-+      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
-+	warning (_("build-id: Unrecognized "
-+		   "ELF header endianity at address 0x%lx"),
-+		 (unsigned long) ehdr_vma);
-+      return NULL;
-+    }
-+
-+  elf_swap_ehdr_in (templ, &x_ehdr64, &i_ehdr);
-+
-+  /* The file header tells where to find the program headers.
-+     These are what we use to actually choose what to read.  */
-+
-+  if (i_ehdr.e_phentsize != (bfd_get_arch_size (templ) == 64
-+                             ? sizeof (Elf64_External_Phdr)
-+			     : sizeof (Elf32_External_Phdr))
-+      || i_ehdr.e_phnum == 0)
-+    {
-+      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
-+	warning (_("build-id: Invalid ELF program headers from the ELF header "
-+		   "at address 0x%lx"), (unsigned long) ehdr_vma);
-+      return NULL;
-+    }
-+
-+  x_phdrs_size = (bfd_get_arch_size (templ) == 64 ? sizeof (Elf64_External_Phdr)
-+						: sizeof (Elf32_External_Phdr));
-+
-+  i_phdrs = (Elf_Internal_Phdr *) xmalloc (i_ehdr.e_phnum * (sizeof *i_phdrs + x_phdrs_size));
-+  x_phdrs_ptr = (gdb_byte *) &i_phdrs[i_ehdr.e_phnum];
-+  err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs_ptr,
-+			    i_ehdr.e_phnum * x_phdrs_size);
-+  if (err)
-+    {
-+      free (i_phdrs);
-+      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
-+        warning (_("build-id: Error reading "
-+		   "ELF program headers at address 0x%lx"),
-+		 (unsigned long) (ehdr_vma + i_ehdr.e_phoff));
-+      return NULL;
-+    }
-+
-+  loadbase = ehdr_vma;
-+  loadbase_set = 0;
-+  for (i = 0; i < i_ehdr.e_phnum; ++i)
-+    {
-+      elf_swap_phdr_in (templ, (Elf64_External_Phdr *)
-+			       (x_phdrs_ptr + i * x_phdrs_size), &i_phdrs[i]);
-+      /* IA-64 vDSO may have two mappings for one segment, where one mapping
-+	 is executable only, and one is read only.  We must not use the
-+	 executable one (PF_R is the first one, PF_X the second one).  */
-+      if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
-+	{
-+	  /* Only the first PT_LOAD segment indicates the file bias.
-+	     Next segments may have P_VADDR arbitrarily higher.
-+	     If the first segment has P_VADDR zero any next segment must not
-+	     confuse us, the first one sets LOADBASE certainly enough.  */
-+	  if (!loadbase_set && i_phdrs[i].p_offset == 0)
-+	    {
-+	      loadbase = ehdr_vma - i_phdrs[i].p_vaddr;
-+	      loadbase_set = 1;
-+	    }
-+	}
-+    }
-+
-+  if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
-+    warning (_("build-id: Found ELF header at address 0x%lx, loadbase 0x%lx"),
-+	     (unsigned long) ehdr_vma, (unsigned long) loadbase);
-+
-+  *e_phnum_pointer = i_ehdr.e_phnum;
-+  *loadbase_pointer = loadbase;
-+  return i_phdrs;
-+}
-+
-+/* BUILD_ID_ADDR_GET gets ADDR located somewhere in the object.
-+   Find the first section before ADDR containing an ELF header.
-+   We rely on the fact the sections from multiple files do not mix.
-+   FIXME: We should check ADDR is contained _inside_ the section with possibly
-+   missing content (P_FILESZ < P_MEMSZ).  These omitted sections are currently
-+   hidden by _BFD_ELF_MAKE_SECTION_FROM_PHDR.  */
-+
-+static CORE_ADDR build_id_addr;
-+struct build_id_addr_sect
-+  {
-+    struct build_id_addr_sect *next;
-+    asection *sect;
-+  };
-+static struct build_id_addr_sect *build_id_addr_sect;
-+
-+static void build_id_addr_candidate (bfd *abfd, asection *sect, void *obj)
-+{
-+  if (build_id_addr >= bfd_section_vma (sect))
-+    {
-+      struct build_id_addr_sect *candidate;
-+
-+      candidate = (struct build_id_addr_sect *) xmalloc (sizeof *candidate);
-+      candidate->next = build_id_addr_sect;
-+      build_id_addr_sect = candidate;
-+      candidate->sect = sect;
-+    }
-+}
-+
-+struct bfd_build_id *
-+build_id_addr_get (CORE_ADDR addr)
-+{
-+  struct build_id_addr_sect *candidate;
-+  struct bfd_build_id *retval = NULL;
-+  Elf_Internal_Phdr *i_phdr = NULL;
-+  bfd_vma loadbase = 0;
-+  unsigned e_phnum = 0;
-+
-+  if (current_program_space->core_bfd () == NULL)
-+    return NULL;
-+
-+  build_id_addr = addr;
-+  gdb_assert (build_id_addr_sect == NULL);
-+  bfd_map_over_sections (current_program_space->core_bfd (),
-+			 build_id_addr_candidate, NULL);
-+
-+  /* Sections are sorted in the high-to-low VMAs order.
-+     Stop the search on the first ELF header we find.
-+     Do not continue the search even if it does not contain NT_GNU_BUILD_ID.  */
-+
-+  for (candidate = build_id_addr_sect; candidate != NULL;
-+       candidate = candidate->next)
-+    {
-+      i_phdr = elf_get_phdr (current_program_space->core_bfd (),
-+			     bfd_section_vma (candidate->sect),
-+			     &e_phnum, &loadbase);
-+      if (i_phdr != NULL)
-+	break;
-+    }
-+
-+  if (i_phdr != NULL)
-+    {
-+      retval = build_id_phdr_get (current_program_space->core_bfd (), loadbase, e_phnum, i_phdr);
-+      xfree (i_phdr);
-+    }
-+
-+  while (build_id_addr_sect != NULL)
-+    {
-+      candidate = build_id_addr_sect;
-+      build_id_addr_sect = candidate->next;
-+      xfree (candidate);
-+    }
-+
-+  return retval;
-+}
-+
- /* See build-id.h.  */
- 
- int
-@@ -73,63 +474,166 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
-   return retval;
- }
- 
-+static char *
-+link_resolve (const char *symlink, int level)
-+{
-+  char buf[PATH_MAX + 1], *retval;
-+  gdb::unique_xmalloc_ptr<char> target;
-+  ssize_t got;
-+
-+  if (level > 10)
-+    return xstrdup (symlink);
-+
-+  got = readlink (symlink, buf, sizeof (buf));
-+  if (got < 0 || got >= sizeof (buf))
-+    return xstrdup (symlink);
-+  buf[got] = '\0';
-+
-+  if (IS_ABSOLUTE_PATH (buf))
-+    target = make_unique_xstrdup (buf);
-+  else
-+    {
-+      const std::string dir (ldirname (symlink));
-+
-+      target = xstrprintf ("%s"
-+#ifndef HAVE_DOS_BASED_FILE_SYSTEM
-+			   "/"
-+#else /* HAVE_DOS_BASED_FILE_SYSTEM */
-+			   "\\"
-+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
-+			   "%s", dir.c_str(), buf);
-+    }
-+
-+  retval = link_resolve (target.get (), level + 1);
-+  return retval;
-+}
-+
- /* Helper for build_id_to_debug_bfd.  LINK is a path to a potential
-    build-id-based separate debug file, potentially a symlink to the real file.
-    If the file exists and matches BUILD_ID, return a BFD reference to it.  */
- 
- static gdb_bfd_ref_ptr
--build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len,
--			 const bfd_byte *build_id)
-+build_id_to_debug_bfd_1 (const std::string &orig_link, size_t build_id_len,
-+			 const bfd_byte *build_id, char **link_return)
- {
-+  gdb_bfd_ref_ptr ret_bfd = {};
-+  std::string ret_link;
-+
-   if (separate_debug_file_debug)
-     {
--      gdb_printf (gdb_stdlog, _("  Trying %s..."), link.c_str ());
--      gdb_flush (gdb_stdlog);
-+      gdb_printf (gdb_stdlog, _("  Trying %s..."), orig_link.c_str ());
-+      gdb_flush (gdb_stdout);
-     }
- 
--  /* lrealpath() is expensive even for the usually non-existent files.  */
--  gdb::unique_xmalloc_ptr<char> filename_holder;
--  const char *filename = nullptr;
--  if (is_target_filename (link))
--    filename = link.c_str ();
--  else if (access (link.c_str (), F_OK) == 0)
-+  for (unsigned seqno = 0;; seqno++)
-     {
--      filename_holder.reset (lrealpath (link.c_str ()));
--      filename = filename_holder.get ();
--    }
-+      std::string link = orig_link;
- 
--  if (filename == NULL)
--    {
--      if (separate_debug_file_debug)
--	gdb_printf (gdb_stdlog,
--		    _(" no, unable to compute real path\n"));
-+      if (seqno > 0)
-+	{
-+	  /* There can be multiple build-id symlinks pointing to real files
-+	     with the same build-id (such as hard links).  Some of the real
-+	     files may not be installed.  */
- 
--      return {};
--    }
-+	  string_appendf (link, ".%u", seqno);
-+	}
- 
--  /* We expect to be silent on the non-existing files.  */
--  gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename, gnutarget);
-+      ret_link = link;
- 
--  if (debug_bfd == NULL)
--    {
--      if (separate_debug_file_debug)
--	gdb_printf (gdb_stdlog, _(" no, unable to open.\n"));
-+      struct stat statbuf_trash;
-+
-+      /* `access' automatically dereferences LINK.  */
-+      if (lstat (link.c_str (), &statbuf_trash) != 0)
-+	{
-+	  /* Stop increasing SEQNO.  */
-+	  break;
-+	}
-+
-+      /* lrealpath() is expensive even for the usually non-existent files.  */
-+      gdb::unique_xmalloc_ptr<char> filename_holder;
-+      const char *filename = nullptr;
-+      if (startswith (link, TARGET_SYSROOT_PREFIX))
-+	filename = link.c_str ();
-+      else if (access (link.c_str (), F_OK) == 0)
-+	{
-+	  filename_holder.reset (lrealpath (link.c_str ()));
-+	  filename = filename_holder.get ();
-+	}
-+
-+      if (filename == NULL)
-+	{
-+	  if (separate_debug_file_debug)
-+	    gdb_printf (gdb_stdlog,
-+	                       _(" no, unable to compute real path\n"));
-+
-+	  continue;
-+	}
-+
-+      /* We expect to be silent on the non-existing files.  */
-+      gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename, gnutarget);
- 
--      return {};
-+      if (debug_bfd == NULL)
-+	{
-+	  if (separate_debug_file_debug)
-+	    gdb_printf (gdb_stdlog, _(" no, unable to open.\n"));
-+
-+	  continue;
-+	}
-+
-+      if (!build_id_verify (debug_bfd.get(), build_id_len, build_id))
-+	{
-+	  if (separate_debug_file_debug)
-+	    gdb_printf (gdb_stdlog,
-+	                _(" no, build-id does not match.\n"));
-+
-+	  continue;
-+	}
-+
-+      ret_bfd = debug_bfd;
-+      break;
-     }
- 
--  if (!build_id_verify (debug_bfd.get(), build_id_len, build_id))
-+  std::string link_all;
-+
-+  if (ret_bfd != NULL)
-     {
-       if (separate_debug_file_debug)
--	gdb_printf (gdb_stdlog, _(" no, build-id does not match.\n"));
--
--      return {};
-+	gdb_printf (gdb_stdlog, _(" yes!\n"));
-+    }
-+  else
-+    {
-+      /* If none of the real files is found report as missing file
-+	 always the non-.%u-suffixed file.  */
-+      std::string link0 = orig_link;
-+
-+      /* If the symlink has target request to install the target.
-+	 BASE-debuginfo.rpm contains the symlink but BASE.rpm may be missing.
-+	 https://bugzilla.redhat.com/show_bug.cgi?id=981154  */
-+      std::string link0_resolved (link_resolve (link0.c_str (), 0));
-+
-+      if (link_all.empty ())
-+	link_all = link0_resolved;
-+      else
-+	{
-+	  /* Use whitespace instead of DIRNAME_SEPARATOR to be compatible with
-+	     its possible use as an argument for installation command.  */
-+	  link_all += " " + link0_resolved;
-+	}
-     }
- 
--  if (separate_debug_file_debug)
--    gdb_printf (gdb_stdlog, _(" yes!\n"));
-+  if (link_return != NULL)
-+    {
-+      if (ret_bfd != NULL)
-+	{
-+	  *link_return = xstrdup (ret_link.c_str ());
-+	}
-+      else
-+	{
-+	  *link_return = xstrdup (link_all.c_str ());
-+	}
-+    }
- 
--  return debug_bfd;
-+  return ret_bfd;
- }
- 
- /* Common code for finding BFDs of a given build-id.  This function
-@@ -138,7 +642,7 @@ build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len,
- 
- static gdb_bfd_ref_ptr
- build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
--			const char *suffix)
-+			const char *suffix, char **link_return)
- {
-   /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
-      cause "/.build-id/..." lookups.  */
-@@ -161,16 +665,17 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
-       if (size > 0)
- 	{
- 	  size--;
--	  string_appendf (link, "%02x/", (unsigned) *data++);
-+	  string_appendf (link, "%02x", (unsigned) *data++);
- 	}
--
-+      if (size > 0)
-+	link += "/";
-       while (size-- > 0)
- 	string_appendf (link, "%02x", (unsigned) *data++);
- 
-       link += suffix;
- 
-       gdb_bfd_ref_ptr debug_bfd
--	= build_id_to_debug_bfd_1 (link, build_id_len, build_id);
-+	= build_id_to_debug_bfd_1 (link, build_id_len, build_id, link_return);
-       if (debug_bfd != NULL)
- 	return debug_bfd;
- 
-@@ -181,7 +686,7 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
-       if (!gdb_sysroot.empty ())
- 	{
- 	  link = gdb_sysroot + link;
--	  debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id);
-+	  debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id, NULL);
- 	  if (debug_bfd != NULL)
- 	    return debug_bfd;
- 	}
-@@ -190,20 +695,178 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
-   return {};
- }
- 
-+char *
-+build_id_to_filename (const struct bfd_build_id *build_id, char **link_return)
-+{
-+  gdb_bfd_ref_ptr abfd;
-+  char *result;
-+
-+  abfd = build_id_to_exec_bfd (build_id->size, build_id->data, link_return);
-+  if (abfd == NULL)
-+    return NULL;
-+
-+  result = xstrdup (bfd_get_filename (abfd.get ()));
-+  return result;
-+}
-+
-+/* This MISSING_FILEPAIR_HASH tracker is used only for the duplicite messages
-+     yum --enablerepo='*debug*' install ...
-+   avoidance.  */
-+
-+struct missing_filepair
-+  {
-+    char *binary;
-+    char *debug;
-+    char data[1];
-+  };
-+
-+static struct htab *missing_filepair_hash;
-+static struct obstack missing_filepair_obstack;
-+
-+static void *
-+missing_filepair_xcalloc (size_t nmemb, size_t nmemb_size)
-+{
-+  void *retval;
-+  size_t size = nmemb * nmemb_size;
-+
-+  retval = obstack_alloc (&missing_filepair_obstack, size);
-+  memset (retval, 0, size);
-+  return retval;
-+}
-+
-+static hashval_t
-+missing_filepair_hash_func (const struct missing_filepair *elem)
-+{
-+  hashval_t retval = 0;
-+
-+  retval ^= htab_hash_string (elem->binary);
-+  if (elem->debug != NULL)
-+    retval ^= htab_hash_string (elem->debug);
-+
-+  return retval;
-+}
-+
-+static int
-+missing_filepair_eq (const struct missing_filepair *elem1,
-+		       const struct missing_filepair *elem2)
-+{
-+  return strcmp (elem1->binary, elem2->binary) == 0
-+         && ((elem1->debug == NULL) == (elem2->debug == NULL))
-+         && (elem1->debug == NULL || strcmp (elem1->debug, elem2->debug) == 0);
-+}
-+
-+static void
-+missing_filepair_change (void)
-+{
-+  if (missing_filepair_hash != NULL)
-+    {
-+      obstack_free (&missing_filepair_obstack, NULL);
-+      /* All their memory came just from missing_filepair_OBSTACK.  */
-+      missing_filepair_hash = NULL;
-+    }
-+}
-+
-+static void
-+debug_print_executable_changed (struct program_space *pspace, bool reload_p)
-+{
-+  missing_filepair_change ();
-+}
-+
-+/* Notify user the file BINARY with (possibly NULL) associated separate debug
-+   information file DEBUG is missing.  DEBUG may or may not be the build-id
-+   file such as would be:
-+     /usr/lib/debug/.build-id/dd/b1d2ce632721c47bb9e8679f369e2295ce71be.debug
-+   */
-+
-+void
-+debug_print_missing (const char *binary, const char *debug)
-+{
-+  size_t binary_len0 = strlen (binary) + 1;
-+  size_t debug_len0 = debug ? strlen (debug) + 1 : 0;
-+  struct missing_filepair missing_filepair_find;
-+  struct missing_filepair *missing_filepair;
-+  struct missing_filepair **slot;
-+
-+  if (build_id_verbose < BUILD_ID_VERBOSE_FILENAMES)
-+    return;
-+
-+  if (missing_filepair_hash == NULL)
-+    {
-+      obstack_init (&missing_filepair_obstack);
-+      missing_filepair_hash = htab_create_alloc (64,
-+	(hashval_t (*) (const void *)) missing_filepair_hash_func,
-+	(int (*) (const void *, const void *)) missing_filepair_eq, NULL,
-+	missing_filepair_xcalloc, NULL);
-+    }
-+
-+  /* Use MISSING_FILEPAIR_FIND first instead of calling obstack_alloc with
-+     obstack_free in the case of a (rare) match.  The problem is ALLOC_F for
-+     MISSING_FILEPAIR_HASH allocates from MISSING_FILEPAIR_OBSTACK maintenance
-+     structures for MISSING_FILEPAIR_HASH.  Calling obstack_free would possibly
-+     not to free only MISSING_FILEPAIR but also some such structures (allocated
-+     during the htab_find_slot call).  */
-+
-+  missing_filepair_find.binary = (char *) binary;
-+  missing_filepair_find.debug = (char *) debug;
-+  slot = (struct missing_filepair **) htab_find_slot (missing_filepair_hash,
-+						      &missing_filepair_find,
-+						      INSERT);
-+
-+  /* While it may be still printed duplicitely with the missing debuginfo file
-+   * it is due to once printing about the binary file build-id link and once
-+   * about the .debug file build-id link as both the build-id symlinks are
-+   * located in the debuginfo package.  */
-+
-+  if (*slot != NULL)
-+    return;
-+
-+  missing_filepair = (struct missing_filepair *) obstack_alloc (&missing_filepair_obstack,
-+								sizeof (*missing_filepair) - 1
-+								+ binary_len0 + debug_len0);
-+  missing_filepair->binary = missing_filepair->data;
-+  memcpy (missing_filepair->binary, binary, binary_len0);
-+  if (debug != NULL)
-+    {
-+      missing_filepair->debug = missing_filepair->binary + binary_len0;
-+      memcpy (missing_filepair->debug, debug, debug_len0);
-+    }
-+  else
-+    missing_filepair->debug = NULL;
-+
-+  *slot = missing_filepair;
-+
-+  /* We do not collect and flush these messages as each such message
-+     already requires its own separate lines.  */
-+
-+  gdb_printf (gdb_stdlog,
-+	      _("Missing separate debuginfo for %s.\n"), binary);
-+  if (debug != NULL)
-+    {
-+      gdb_printf (gdb_stdlog, _("Try: %s %s\n"),
-+#ifdef DNF_DEBUGINFO_INSTALL
-+		  "dnf"
-+#else
-+		  "yum"
-+#endif
-+		  " --enablerepo='*debug*' install", debug);
-+    }
-+}
-+
- /* See build-id.h.  */
- 
- gdb_bfd_ref_ptr
- build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
- {
--  return build_id_to_bfd_suffix (build_id_len, build_id, ".debug");
-+  return build_id_to_bfd_suffix (build_id_len, build_id, ".debug", nullptr);
- }
- 
- /* See build-id.h.  */
- 
- gdb_bfd_ref_ptr
--build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id)
-+build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id,
-+		      char **link_return)
- {
--  return build_id_to_bfd_suffix (build_id_len, build_id, "");
-+  return build_id_to_bfd_suffix (build_id_len, build_id, "", link_return);
- }
- 
- /* See build-id.h.  */
-@@ -224,6 +887,7 @@ find_separate_debug_file_by_buildid (struct objfile *objfile,
- 
-       gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size,
- 						   build_id->data));
-+
-       /* Prevent looping on a stripped .debug file.  */
-       if (abfd != NULL
- 	  && filename_cmp (bfd_get_filename (abfd.get ()),
-@@ -243,3 +907,22 @@ find_separate_debug_file_by_buildid (struct objfile *objfile,
- 
-   return std::string ();
- }
-+
-+void _initialize_build_id ();
-+
-+void
-+_initialize_build_id ()
-+{
-+  add_setshow_zinteger_cmd ("build-id-verbose", no_class, &build_id_verbose,
-+			    _("\
-+Set debugging level of the build-id locator."), _("\
-+Show debugging level of the build-id locator."), _("\
-+Level 1 (default) enables printing the missing debug filenames,\n\
-+level 2 also prints the parsing of binaries to find the identificators."),
-+			    NULL,
-+			    show_build_id_verbose,
-+			    &setlist, &showlist);
-+
-+  gdb::observers::executable_changed.attach (debug_print_executable_changed,
-+                                             "build-id");
-+}
-diff --git a/gdb/build-id.h b/gdb/build-id.h
---- a/gdb/build-id.h
-+++ b/gdb/build-id.h
-@@ -40,12 +40,16 @@ extern int build_id_verify (bfd *abfd,
- extern gdb_bfd_ref_ptr build_id_to_debug_bfd (size_t build_id_len,
- 					      const bfd_byte *build_id);
- 
-+extern char *build_id_to_filename (const struct bfd_build_id *build_id,
-+				   char **link_return);
-+
- /* Find and open a BFD for an executable file given a build-id.  If no BFD
-    can be found, return NULL.  The returned reference to the BFD must be
-    released by the caller.  */
- 
- extern gdb_bfd_ref_ptr build_id_to_exec_bfd (size_t build_id_len,
--					     const bfd_byte *build_id);
-+					     const bfd_byte *build_id,
-+					     char **link_return);
- 
- /* Find the separate debug file for OBJFILE, by using the build-id
-    associated with OBJFILE's BFD.  If successful, returns the file name for the
-diff --git a/gdb/corelow.c b/gdb/corelow.c
---- a/gdb/corelow.c
-+++ b/gdb/corelow.c
-@@ -21,6 +21,9 @@
- #include <signal.h>
- #include <fcntl.h>
- #include "frame.h"
-+#include "auxv.h"
-+#include "build-id.h"
-+#include "elf/common.h"
- #include "inferior.h"
- #include "infrun.h"
- #include "symtab.h"
-@@ -383,6 +386,8 @@ add_to_thread_list (asection *asect, asection *reg_sect, inferior *inf)
-     switch_to_thread (thr);			/* Yes, make it current.  */
- }
- 
-+static bool build_id_core_loads = true;
-+
- /* Issue a message saying we have no core to debug, if FROM_TTY.  */
- 
- static void
-@@ -570,8 +575,10 @@ locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
-   if (build_id == nullptr)
-     return;
- 
-+  char *build_id_filename;
-   gdb_bfd_ref_ptr execbfd
--    = build_id_to_exec_bfd (build_id->size, build_id->data);
-+    = build_id_to_exec_bfd (build_id->size, build_id->data,
-+			    &build_id_filename);
- 
-   if (execbfd == nullptr)
-     {
-@@ -599,7 +606,12 @@ locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
-       exec_file_attach (bfd_get_filename (execbfd.get ()), from_tty);
-       symbol_file_add_main (bfd_get_filename (execbfd.get ()),
- 			    symfile_add_flag (from_tty ? SYMFILE_VERBOSE : 0));
-+      if (current_program_space->symfile_object_file != NULL)
-+	current_program_space->symfile_object_file->flags |=
-+	  OBJF_BUILD_ID_CORE_LOADED;
-     }
-+  else
-+    debug_print_missing (BUILD_ID_MAIN_EXECUTABLE_FILENAME, build_id_filename);
- }
- 
- /* See gdbcore.h.  */
-@@ -1524,4 +1536,11 @@ _initialize_corelow ()
- 	   maintenance_print_core_file_backed_mappings,
- 	   _("Print core file's file-backed mappings."),
- 	   &maintenanceprintlist);
-+
-+  add_setshow_boolean_cmd ("build-id-core-loads", class_files,
-+			   &build_id_core_loads, _("\
-+Set whether CORE-FILE loads the build-id associated files automatically."), _("\
-+Show whether CORE-FILE loads the build-id associated files automatically."),
-+			   NULL, NULL, NULL,
-+			   &setlist, &showlist);
- }
-diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
---- a/gdb/doc/gdb.texinfo
-+++ b/gdb/doc/gdb.texinfo
-@@ -22487,6 +22487,27 @@ information files.
- 
- @end table
- 
-+You can also adjust the current verbosity of the @dfn{build id} locating.
-+
-+ at table @code
-+
-+ at kindex set build-id-verbose
-+ at item set build-id-verbose 0
-+No additional messages are printed.
-+
-+ at item set build-id-verbose 1
-+Missing separate debug filenames are printed.
-+
-+ at item set build-id-verbose 2
-+Missing separate debug filenames are printed and also all the parsing of the
-+binaries to find their @dfn{build id} content is printed.
-+
-+ at kindex show build-id-verbose
-+ at item show build-id-verbose
-+Show the current verbosity value for the @dfn{build id} content locating.
-+
-+ at end table
-+
- @cindex @code{.gnu_debuglink} sections
- @cindex debug link sections
- A debug link is a special section of the executable file named
-diff --git a/gdb/objfiles.h b/gdb/objfiles.h
---- a/gdb/objfiles.h
-+++ b/gdb/objfiles.h
-@@ -877,6 +877,10 @@ struct objfile
-   bool object_format_has_copy_relocs = false;
- };
- 
-+/* This file was loaded according to the BUILD_ID_CORE_LOADS rules.  */
-+
-+#define OBJF_BUILD_ID_CORE_LOADED static_cast<enum objfile_flag>(1 << 12)
-+
- /* A deleter for objfile.  */
- 
- struct objfile_deleter
-diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
---- a/gdb/solib-svr4.c
-+++ b/gdb/solib-svr4.c
-@@ -44,6 +44,7 @@
- #include "auxv.h"
- #include "gdb_bfd.h"
- #include "probe.h"
-+#include "build-id.h"
- 
- #include <map>
- 
-@@ -1262,6 +1263,46 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
- 	  continue;
- 	}
- 
-+	{
-+	  struct bfd_build_id *build_id;
-+
-+	  build_id = build_id_addr_get (li->l_ld);
-+	  if (build_id != NULL)
-+	    {
-+	      char *bid_name, *build_id_filename;
-+
-+	      /* Missing the build-id matching separate debug info file
-+		 would be handled while SO_NAME gets loaded.  */
-+	      bid_name = build_id_to_filename (build_id, &build_id_filename);
-+	      if (bid_name != NULL)
-+		{
-+		  name = make_unique_xstrdup (bid_name);
-+		  xfree (bid_name);
-+		}
-+	      else
-+		{
-+		  debug_print_missing (name.get (), build_id_filename);
-+
-+		  /* In the case the main executable was found according to
-+		     its build-id (from a core file) prevent loading
-+		     a different build of a library with accidentally the
-+		     same SO_NAME.
-+
-+		     It suppresses bogus backtraces (and prints "??" there
-+		     instead) if the on-disk files no longer match the
-+		     running program version.  */
-+
-+		  if (current_program_space->symfile_object_file != NULL
-+		      && (current_program_space->symfile_object_file->flags
-+			  & OBJF_BUILD_ID_CORE_LOADED) != 0)
-+		    name = make_unique_xstrdup ("");
-+		}
-+
-+	      xfree (build_id_filename);
-+	      xfree (build_id);
-+	    }
-+	}
-+
-       /* If this entry has no name, or its name matches the name
- 	 for the main executable, don't include it in the list.  */
-       if (*name == '\0' || match_main (name.get ()))
-diff --git a/gdb/symfile.h b/gdb/symfile.h
---- a/gdb/symfile.h
-+++ b/gdb/symfile.h
-@@ -363,6 +363,11 @@ void map_symbol_filenames (gdb::function_view<symbol_filename_ftype> fun,
-    optional offset to apply to each section.  */
- extern void generic_load (const char *args, int from_tty);
- 
-+/* build-id support.  */
-+extern struct bfd_build_id *build_id_addr_get (CORE_ADDR addr);
-+extern void debug_print_missing (const char *binary, const char *debug);
-+#define BUILD_ID_MAIN_EXECUTABLE_FILENAME _("the main executable file")
-+
- /* From minidebug.c.  */
- 
- extern gdb_bfd_ref_ptr find_separate_debug_file_in_section (struct objfile *);
-diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
---- a/gdb/testsuite/gdb.base/corefile.exp
-+++ b/gdb/testsuite/gdb.base/corefile.exp
-@@ -347,3 +347,33 @@ gdb_test_multiple "core-file $corefile" $test {
- 	pass $test
-     }
- }
-+
-+
-+# Test auto-loading of binary files through build-id from the core file.
-+set buildid [build_id_debug_filename_get $binfile]
-+set wholetest "binfile found by build-id"
-+if {$buildid == ""} {
-+    untested "$wholetest (binary has no build-id)"
-+} else {
-+    gdb_exit
-+    gdb_start
-+
-+    regsub {\.debug$} $buildid {} buildid
-+    set debugdir [standard_output_file ${testfile}-debugdir]
-+    file delete -force -- $debugdir
-+    file mkdir $debugdir/[file dirname $buildid]
-+    file copy $binfile $debugdir/$buildid
-+
-+    set test "show debug-file-directory"
-+    gdb_test_multiple $test $test {
-+	-re "The directory where separate debug symbols are searched for is \"(.*)\"\\.\r\n$gdb_prompt $" {
-+	    set debugdir_orig $expect_out(1,string)
-+	    pass $test
-+	}
-+    }
-+    gdb_test_no_output "set debug-file-directory $debugdir:$debugdir_orig" "set debug-file-directory"
-+    gdb_test "show build-id-core-loads" {Whether CORE-FILE loads the build-id associated files automatically is on\.}
-+    gdb_test "core-file $corefile" "\r\nProgram terminated with .*" "core-file without executable"
-+    gdb_test "info files" "Local exec file:\r\n\[ \t\]*`[string_to_regexp $debugdir/$buildid]', file type .*"
-+    pass $wholetest
-+}
-diff --git a/gdb/testsuite/gdb.base/gdbinit-history.exp b/gdb/testsuite/gdb.base/gdbinit-history.exp
---- a/gdb/testsuite/gdb.base/gdbinit-history.exp
-+++ b/gdb/testsuite/gdb.base/gdbinit-history.exp
-@@ -179,7 +179,8 @@ proc test_empty_history_filename { } {
-     global env
-     global gdb_prompt
- 
--    set common_history [list "set height 0" "set width 0"]
-+    set common_history [list "set height 0" "set width 0" \
-+			    "set build-id-verbose 0"]
- 
-     set test_dir [standard_output_file history_test]
-     remote_exec host "mkdir -p $test_dir"
-diff --git a/gdb/testsuite/gdb.base/new-ui-pending-input.exp b/gdb/testsuite/gdb.base/new-ui-pending-input.exp
---- a/gdb/testsuite/gdb.base/new-ui-pending-input.exp
-+++ b/gdb/testsuite/gdb.base/new-ui-pending-input.exp
-@@ -60,6 +60,9 @@ proc test_command_line_new_ui_pending_input {} {
-     set bpline [gdb_get_line_number "set breakpoint here"]
- 
-     set options ""
-+    append options " -iex \"set height 0\""
-+    append options " -iex \"set width 0\""
-+    append options " -iex \"set build-id-verbose 0\""
-     append options " -iex \"new-ui console $extra_tty_name\""
-     append options " -ex \"b $bpline\""
-     append options " -ex \"run\""
-diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
---- a/gdb/testsuite/lib/gdb.exp
-+++ b/gdb/testsuite/lib/gdb.exp
-@@ -238,7 +238,8 @@ if ![info exists INTERNAL_GDBFLAGS] {
- 		   "-nx" \
- 		   "-q" \
- 		   {-iex "set height 0"} \
--		   {-iex "set width 0"}]]
-+		   {-iex "set width 0"} \
-+		   {-iex "set build-id-verbose 0"}]]
- 
-     # If DEBUGINFOD_URLS is set, gdb will try to download sources and
-     # debug info for f.i. system libraries.  Prevent this.
-@@ -2493,6 +2494,17 @@ proc default_gdb_start { } {
- 	}
-     }
- 
-+    # Turn off the missing warnings as the testsuite does not expect it.
-+    send_gdb "set build-id-verbose 0\n"
-+    gdb_expect 10 {
-+	-re "$gdb_prompt $" {
-+	    verbose "Disabled the missing debug infos warnings." 2
-+	}
-+	timeout {
-+	    warning "Could not disable the missing debug infos warnings.."
-+	}
-+    }
-+
-     gdb_debug_init
-     return 0
- }
-diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
---- a/gdb/testsuite/lib/mi-support.exp
-+++ b/gdb/testsuite/lib/mi-support.exp
-@@ -321,6 +321,16 @@ proc default_mi_gdb_start { { flags {} } } {
- 	    warning "Couldn't set the width to 0."
- 	}
-     }
-+    # Turn off the missing warnings as the testsuite does not expect it.
-+    send_gdb "190-gdb-set build-id-verbose 0\n"
-+    gdb_expect 10 {
-+	-re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" {
-+	    verbose "Disabled the missing debug infos warnings." 2
-+	}
-+	timeout {
-+	    warning "Could not disable the missing debug infos warnings.."
-+	}
-+    }
- 
-     if { $separate_inferior_pty } {
- 	mi_create_inferior_pty
diff --git a/gdb-add-rpm-suggestion-script.patch b/gdb-add-rpm-suggestion-script.patch
new file mode 100644
index 0000000..3e6646d
--- /dev/null
+++ b/gdb-add-rpm-suggestion-script.patch
@@ -0,0 +1,1011 @@
+From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
+From: Andrew Burgess <aburgess at redhat.com>
+Date: Thu, 7 Mar 2024 15:14:23 +0000
+Subject: gdb-add-rpm-suggestion-script.patch
+
+;; Not a backport.  Add a new script which hooks into GDB and suggests
+;; RPMs to install when GDB finds an objfile with no debug info.
+
+gdb: add script which will suggest debuginfo RPMs to install
+
+This script hooks into GDB's missing debug info Python API and
+suggests debuginfo RPMs to install.
+
+diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
+--- a/gdb/data-directory/Makefile.in
++++ b/gdb/data-directory/Makefile.in
+@@ -92,6 +92,7 @@ PYTHON_FILE_LIST = \
+ 	gdb/command/missing_files.py \
+ 	gdb/command/pretty_printers.py \
+ 	gdb/command/prompt.py \
++	gdb/command/rpm-suggestions.py \
+ 	gdb/command/type_printers.py \
+ 	gdb/command/unwinders.py \
+ 	gdb/command/xmethods.py \
+diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
+--- a/gdb/doc/gdb.texinfo
++++ b/gdb/doc/gdb.texinfo
+@@ -186,6 +186,7 @@ software in general.  We will miss him.
+ * Trace File Format::		@value{GDBN} trace file format
+ * Index Section Format::        .gdb_index section format
+ * Debuginfod::                  Download debugging resources with @code{debuginfod}
++* RPM Suggestions::             RPM Suggestions from GDB
+ * Man Pages::                   Manual pages
+ * Copying::                     GNU General Public License says
+                                 how you can copy and share @value{GDBN}
+@@ -50588,6 +50589,111 @@ Show the current verbosity setting.
+ 
+ @end table
+ 
++ at node RPM Suggestions
++ at appendix Receiving RPM installation suggestions
++ at cindex rpm suggestions
++
++When @value{GDBN} loads an executable, or shared library, and cannot
++find the corresponding debug information, @value{GDBN} will check to
++see if an RPM is available which could provide the missing debug
++information.  If a suitable RPM is found then @value{GDBN} will print
++a hint before the next prompt is displayed:
++
++ at smallexample
++(@value{GDBP}) file /bin/ls
++Reading symbols from /bin/ls...
++Reading symbols from .gnu_debugdata for /usr/bin/ls...
++(No debugging symbols found in .gnu_debugdata for /usr/bin/ls)
++Missing rpms, try: dnf --enablerepo='*debug*' install coreutils-debuginfo-9.3-7.fc39.x86_64
++(@value{GDBP})
++ at end smallexample
++
++In this case, installing @file{coreutils-debuginfo-9.3-7.fc39.x86_64}
++will provide the missing debug information for @file{/bin/ls}.  It is
++up to you to install the suggested package, if possible, and after
++that reload the executable in @value{GDBN} so that the newly installed
++debug information can be found.
++
++The RPM suggestion feature can be disabled:
++
++ at table @code
++ at kindex set rpm-suggestion enabled
++ at kindex show rpm-suggestion enabled
++ at cindex rpm suggestions, disabling
++ at item set rpm-suggestion enabled @r{[}on at r{|}off at r{]}
++ at itemx show rpm-suggestion enabled
++When @samp{on} @value{GDBN} will make RPM suggestions where possible.
++When @samp{off} all RPM suggestion will be disabled.
++ at end table
++
++When opening a core file (@pxref{core-file command}), it may be the
++case that not only is the debug information missing, but the
++corresponding executable itself is missing.  For example, if a core
++file is copied from one machine to another in order to debug.
++
++In this case @value{GDBN} is able to suggest a command which will
++install the missing executable based on the build-id of the
++executable.  For example:
++
++ at smallexample
++(@value{GDBP}) core-file /tmp/core.5489
++warning: Can't open file /usr/bin/sl during file-backed mapping note processing
++[New LWP 5489]
++Core was generated by `sl'.
++Program terminated with signal SIGQUIT, Quit.
++#0  0x00007f1b41ced1a7 in ?? ()
++Missing file(s), try: dnf --enablerepo='*debug*' install /usr/lib/.build-id/33/2f1a8e56693960e3beb2d70cd79ddfec451cc3 /usr/lib/debug/.build-id/33/2f1a8e56693960e3beb2d70cd79ddfec451cc3.debug
++(@value{GDBP})
++ at end smallexample
++
++The core file was generated from the @file{/usr/bin/sl} binary, which
++is not present on the machine opening the core file.  @value{GDBN} has
++suggested a command, based on the build-id of the binary, which was
++extracted from the core file, that would install both the missing
++binary, and the corresponding debug information.
++
++Unfortunately, @value{GDBN} doesn't know if the suggested command will
++actually find a matching RPM or not.  Querying the RPM database to see
++which packages, if any, will provide a file with the given build-id,
++is rather slow.  As @file{/usr/bin/sl} is available in an RPM, then
++the above command will succeed.
++
++It is possible to have @value{GDBN} check to see if there is a package
++available before making the suggestion, but this is significantly
++slower.  To enable this mode use the following command:
++
++ at table @code
++ at kindex set rpm-suggestion build-id-mode
++ at kindex show rpm-suggestion build-id-mode
++ at cindex rpm suggestions, build-id-mode
++ at item set rpm-suggestion build-id-mode @r{[}fast at r{|}slow at r{]}
++ at itemx show rpm-suggestion build-id-mode
++When set to @samp{fast}, which is the default, @value{GDBN} will offer
++suggestions based on the build-id of any missing executables or shared
++libraries while opening a core file.  This is fast, but @value{GDBN}
++has not checked if there is a package available that can supply the
++required file, so running the suggested command might not install any
++packages.
++
++When set to @samp{slow}, each time @value{GDBN} encounters an
++executable, or shared library, that is missing, @value{GDBN} will
++check to see if there is an RPM available that will supply the missing
++binary.  If a suitable RPM is found then @value{GDBN} will offer a
++command which will install the missing RPM.  If no suitable RPM is
++found then @value{GDBN} will make no suggestions.
++ at end table
++
++It is possible to review all of the previous RPM suggestions that
++ at value{GDBN} has made using the following command:
++
++ at table @code
++ at kindex info rpm-suggestions
++ at cindex rpm suggestions, listing
++ at item info rpm-suggestions
++List all of the RPM suggestions @value{GDBN} has made since the
++executable was last changed.
++ at end table
++
+ @node Man Pages
+ @appendix Manual pages
+ @cindex Man pages
+diff --git a/gdb/python/lib/gdb/command/rpm-suggestions.py b/gdb/python/lib/gdb/command/rpm-suggestions.py
+new file mode 100644
+--- /dev/null
++++ b/gdb/python/lib/gdb/command/rpm-suggestions.py
+@@ -0,0 +1,527 @@
++# Copyright 2023 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/>.
++
++import gdb
++import gdb.missing_debug
++import gdb.missing_objfile
++
++# These modules are all system modules, and should be available on any
++# correctly setup Python install.
++import sys
++import os
++import subprocess
++import re
++from threading import Thread
++import time
++
++try:
++    import rpm
++except ModuleNotFoundError:
++    # The "RPM suggestions" mechanism will not work without the (python)
++    # rpm module.  Inform the user of this, but wait to do so until
++    # just prior to printing the GDB prompt.  If we do it right away,
++    # the message typically appears before the version and copyright
++    # info, which is easily missed by many users.  Additionally, it
++    # seems that several other packages which parse GDB version info
++    # are confused by an early error message regarding a missing
++    # python3-rpm package, so waiting to print the error allows those
++    # applications to work as they used to.
++    def before_prompt():
++        print(
++            ("\nUnable to load the Python 'rpm' module.  Lack of this module disables\n"
++             "the RPM suggestions mechanism which recommends shell commands for\n"
++             "installing missing debuginfo packages.  To enable this functionality,\n"
++             "please install the python3-rpm package."),
++            file=sys.stderr
++        )
++        gdb.events.before_prompt.disconnect(before_prompt)
++
++    gdb.events.before_prompt.connect(before_prompt)
++
++    # Implement 'info rpm-suggestions' when the 'rpm' module is not
++    # available.  Just throws an error.
++    def info_rpm_suggestions():
++        raise gdb.GdbError("rpm-suggestions are disabled as the Python 'rpm' module is not installed")
++else:
++    # Track all the RPMs suggested during a single debug session so we
++    # don't suggest the same RPM twice.  This is only cleared when the
++    # main executable is changed.
++    __missing_rpms = {}
++
++    # Track any missing RPMs that have been discovered since the last time
++    # the prompt was displayed.  RPMs in here are also present in the
++    # __MISSING_RPMS dictionary, but this dictionary is cleared each time
++    # the prompt is shown.
++    __suggest_rpms = {}
++
++    # Track all the build-ids suggested during a single debug session so we
++    # don't suggest installing using the same build-id twice.  This is only
++    # cleared when the main executable is changed.
++    __missing_build_ids = {}
++
++    # Track any build-ids that have been discovered missing since the last
++    # time the prompt was displayed.  Build-ids in here are also present in
++    # the __MISSING_BUILD_IDS dictionary, but this dictionary is cleared
++    # each time the prompt is shown.
++    __suggest_build_ids = {}
++
++    # The build-id to RPM lookup is very slow.  This cache maps
++    # build-ids to the set of RPM we can suggest installing.  The key
++    # is the build-id string, and the value is a list of RPM names, or
++    # None if there was an error with the build-id to RPM lookup.
++    #
++    # This cache is never cleared, even when the executable is
++    # changed.  The build-ids should be unique, so a build-id lookup
++    # should be good for the lifetime of the session.
++    __build_id_lookup_cache = {}
++
++    # When searching for an RPM given a build-id, if the search takes
++    # too long, then a message is printed to the user.  We only print
++    # the message once between each GDB prompt.  This flag is set True
++    # when the message is printed, and reset to False when a prompt is
++    # displayed.
++    __searching_message_printed = False
++
++    # Add a suggestion to install RPM_NAME (the full name of an RPM)
++    # to the list of suggestions to make the next time a prompt is
++    # displayed.
++    def add_rpm_suggestion(rpm_name):
++        global __missing_rpms
++        global __suggest_rpms
++
++        if not rpm_name in __missing_rpms:
++            __suggest_rpms[rpm_name] = True
++            __missing_rpms[rpm_name] = True
++
++    # Return True if RPM_NAME is installed, where RPM_NAME is the full
++    # name of an RPM.
++    def is_rpm_installed(ts, rpm_name):
++        res = ts.dbMatch(rpm.RPMDBI_LABEL, rpm_name)
++        return len(res) > 0
++
++    # Add a suggestion to install RPMs based on BUILD_ID, a string
++    # containing a build-id, to the list of suggestions to make the next
++    # time a prompt is displayed.
++    def add_build_id_suggestion(build_id):
++        global __missing_build_ids
++        global __suggest_build_ids
++
++        if not build_id in __missing_build_ids:
++            __suggest_build_ids[build_id] = True
++            __missing_build_ids[build_id] = True
++
++    # Return true if '/usr/lib' is in the debug-file-directory list.
++    # System packages install their debug information into /usr/lib,
++    # so if GDB isn't looking in that directory, then there's no
++    # reason to try and figure out a suitable RPM to install.
++    def using_suitable_debug_file_directory():
++        debug_file_directories = gdb.parameter("debug-file-directory")
++        for d in debug_file_directories.split(os.pathsep):
++            if d[:8] == "/usr/lib":
++                return True
++        return False
++
++    # Return True if rpm-suggestion is disabled for any reason.
++    def rpm_suggestion_is_disabled():
++        # If /usr/lib/ is not being used to find debug information
++        # then there's no point offering any RPMs as GDB would not
++        # find the newly installed content.
++        if not using_suitable_debug_file_directory():
++            return True
++
++        # Is 'rpm-suggestion enabled' set to 'off'?
++        if not param_rpm_suggestion_enabled.value:
++            return True
++
++        return False
++
++
++    # Lookup RPMs that might provide the debug information for FILENAME,
++    # which is a string containing the path to an object file GDB could
++    # not find any debug information for.
++    #
++    # If a possible RPM is found then this is added to the globals
++    # __MISSING_RPMS and __SUGGEST_RPMS, which are used elsewhere in this
++    # script.
++    def find_debug_suggestions(filename):
++        if rpm_suggestion_is_disabled():
++            return
++
++        ts = rpm.TransactionSet()
++        mi = ts.dbMatch(rpm.RPMDBI_BASENAMES, filename)
++        for h in mi:
++            # Build the debuginfo package name.
++            obj = h.format("%{name}-debuginfo-%{version}-%{release}.%{arch}")
++            rpm_name = str(obj)
++
++            # Check to see if the package is installed.
++            if is_rpm_installed(ts, rpm_name):
++                continue
++
++            add_rpm_suggestion(rpm_name)
++
++
++    # Return a string which is the filename of the filename
++    # corresponding to BUILD_ID in one of the two locations under
++    # /usr/lib.
++    #
++    # When DEBUG_P is True, return a filename within:
++    # /usr/lib/debug/.build-id/ and when DEBUG_P is False, return a
++    # filename within: /usr/lib/.build-id/.
++    #
++    # The SUFFIX string is appended to the generated filename.
++    def build_id_to_usr_lib_filename(build_id, debug_p, suffix = ""):
++        key = build_id[:2]
++        rst = build_id[2:]
++
++        filename = '/usr/lib'
++        if debug_p:
++            filename += '/debug'
++        filename += '/.build-id/' + key + '/' + rst + suffix
++
++        return filename
++
++    # A regexp object used to match against the output of `dnf`.  This
++    # is initialised the first time it is needed.
++    find_objfile_suggestions_re = None
++
++    # Given BUILD_ID, a string containing a build-id, run a `dnf`
++    # command to figure out if any RPMs can provide a file with that
++    # build-id.
++    #
++    # If any suitable RPMs are found then `add_rpm_suggestion` is called
++    # to register the suggestion.
++    #
++    # This function is pretty slow, which is a shame, as the results
++    # returned are much nicer than just telling the user to try the
++    # lookup command for themselves.
++    def find_objfile_suggestions_in_thread(build_id):
++        global find_objfile_suggestions_re
++
++        if find_objfile_suggestions_re is None:
++            find_objfile_suggestions_re = re.compile("^(.*)-debuginfo-(.*) : Debug information for package (.*)$")
++
++        result = subprocess.run(['dnf', "--enablerepo=*debug*", '--nogpgcheck', '-C', 'provides',
++                                 build_id_to_usr_lib_filename(build_id, True)],
++                                capture_output=True, timeout=30)
++
++        lines = result.stdout.decode('utf-8').splitlines()
++        ts = rpm.TransactionSet()
++
++        for l in lines:
++            m = find_objfile_suggestions_re.match(l)
++            if not m:
++                continue
++            if m.group(1) != m.group(3):
++                return
++
++            main_rpm = m.group(1) + '-' + m.group(2)
++            dbg_rpm = m.group(1) + '-debuginfo-' + m.group(2)
++
++            if not is_rpm_installed(ts, main_rpm):
++                add_rpm_suggestion(main_rpm)
++
++            if not is_rpm_installed(ts, dbg_rpm):
++                add_rpm_suggestion(dbg_rpm)
++
++        return
++
++    # Call `find_objfile_suggestions_in_thread` is a separate thread,
++    # then wait for the thread to complete.  Don't touch any shared
++    # state while waiting for the thread to complete.  There's no
++    # locking on any of our caches, and the worker thread will add RPM
++    # suggestions as it wants.
++    #
++    # If thre thread takes too long to complete then print a message
++    # to the user telling them what's going on.
++    def find_objfile_suggestions_slow_core(build_id):
++        global __searching_message_printed
++
++        thread = Thread(target = find_objfile_suggestions_in_thread, args = (build_id, ))
++        thread.start()
++        start = time.time_ns()
++
++        while thread.is_alive ():
++            time.sleep(0.05)
++            now = time.time_ns ()
++            if not __searching_message_printed and (now - start > 1000000000):
++                print("Searching for packages to install that could improve debugging...")
++                __searching_message_printed = True
++
++        thread.join()
++
++
++    # Given BUILD_ID, a string containing a build-id, lookup suitable
++    # RPMs that could be installed to provide a file with the required
++    # build-id.
++    #
++    # Any suitable RPMs are recorded by calling `add_rpm_suggestion`, and
++    # will be printed before the next prompt.
++    def find_objfile_suggestions_slow(build_id):
++        global __build_id_lookup_cache
++        global __suggest_rpms
++
++        # The code to lookup an RPM given only a build-id is pretty
++        # slow.  Cache the results to try and reduce the UI delays.
++        if build_id in __build_id_lookup_cache:
++            rpms = __build_id_lookup_cache[build_id]
++            if rpms is not None:
++                for r in rpms:
++                    add_rpm_suggestion(r)
++            return
++
++        # Make sure the cache entry exists before we do the lookup.
++        # If, for any reason, the lookup raises an exception, then
++        # having a cache entry will prevent us retrying this lookup in
++        # the future.
++        __build_id_lookup_cache[build_id] = None
++
++        # Now do the lookup.  This is the slow part.
++        find_objfile_suggestions_slow_core(build_id)
++
++        # Fill in the cache, for a given build-id which RPMs were
++        # suggested.
++        rpms = []
++        for r in __suggest_rpms:
++            rpms.append(r)
++        __build_id_lookup_cache[build_id] = rpms
++
++
++    # Given BUILD_ID, a string containing a build-id, just record that we
++    # should advise the user to try installing RPMs based on this build-id.
++    def find_objfile_suggestions_fast(build_id):
++        add_build_id_suggestion(build_id)
++
++    # Given BUILD_ID, a string containing a build-id, which GDB has failed
++    # to find, possibly record some information so that we can, at the next
++    # prompt, give some RPM installation advice to the user.
++    #
++    # We have two different strategies for RPM lookup based on a build-id,
++    # one approach is that we actually lookup the RPMs and only suggest
++    # something if there is a suitable RPM.  However, this is pretty slow,
++    # and users will probably find this annoying.
++    #
++    # So we also have a fast way.  With this approach we just record the
++    # build-id that was missing and tell the user to try installing based on
++    # the build-id.  The downside with this is that if there is no RPM for
++    # that build-id, then the user will try the command, but nothing will
++    # install.
++    def find_objfile_suggestions(build_id):
++        if rpm_suggestion_is_disabled():
++            return
++
++        if param_rpm_suggestion_build_id_mode.fast_mode():
++            find_objfile_suggestions_fast(build_id)
++        else:
++            find_objfile_suggestions_slow(build_id)
++
++    # A missing debug handler class.  Just forwards the name of the
++    # objfile for which we are missing debug information to
++    # find_debug_suggestions.
++    class RPM_MissingDebugHandler(gdb.missing_debug.MissingDebugHandler):
++        def __init__(self):
++            super().__init__("rpm-suggestions")
++
++        def __call__(self, objfile):
++            find_debug_suggestions(objfile.filename)
++            return False
++
++    # A missing objfile handler class.  Just forwards the build-id of
++    # the objfile that is missing to find_objfile_suggestions.
++    class RPM_MissingObjfileHandler(gdb.missing_objfile.MissingObjfileHandler):
++        def __init__(self):
++            super().__init__("rpm-suggestions")
++
++        def __call__(self, pspace, build_id, filename):
++            find_objfile_suggestions(build_id)
++            return False
++
++    # Take a non-empty list of RPM names and print a command line a
++    # user could run to install these RPMs.
++    def print_rpm_suggestions(rpm_name_list):
++        print("Missing rpms, try: dnf --enablerepo='*debug*' install " + ' '.join(rpm_name_list))
++
++    # Take a non-empty list of build-id strings and print a series of
++    # lines that a user could run to instll the RPMs that provide
++    # files with this build-id.
++    #
++    # The printed commands will also install the corresponding debug
++    # packages for the executable with the given build-id.
++    def print_build_id_suggestions(build_id_list):
++        for build_id in build_id_list:
++            print("Missing file(s), try: dnf --enablerepo='*debug*' install "
++                  + build_id_to_usr_lib_filename(build_id, False)
++                  + ' '
++                  + build_id_to_usr_lib_filename(build_id, True, ".debug"))
++
++    # Called before GDB displays its prompt.  If the global __SUGGEST_RPMS
++    # dictionary is not empty, then this hook prints the keys of this
++    # dictionary as strings which are the names of RPMs.  This hook formats
++    # each RPM name into a suggested 'dnf install' command and suggests this
++    # to the user.
++    #
++    # Additionally, if the global __SUGGEST_BUILD_IDS dictionary is not
++    # empty, then this hook uses the keys of this dictionary as build-ids
++    # that were found to be missing, and formats these into some file based
++    # 'dnf install' suggestions to the user.
++    def before_prompt():
++        global __suggest_rpms
++        global __suggest_build_ids
++        global __searching_message_printed
++
++        # We allow the searching message to be printed just once
++        # between prompts.
++        __searching_message_printed = False
++
++        if len(__suggest_rpms) > 0:
++            print_rpm_suggestions(__suggest_rpms.keys())
++            __suggest_rpms = {}
++
++        if len(__suggest_build_ids) > 0:
++            print_build_id_suggestions(__suggest_build_ids.keys())
++            __suggest_build_ids = {}
++
++    # Called when the executable within a progrm space is changed.  Clear
++    # the lists of RPM suggestions.  We only clear the previous suggestion
++    # list when the executable really changes.  If the user simply
++    # recompiles the executable, then we don't both clearing this list.
++    def executable_changed_handler(event):
++        global __missing_rpms
++        global __suggest_rpms
++        global __suggest_build_ids
++        global __missing_build_ids
++
++        if not event.reload:
++            __missing_rpms = {}
++            __suggest_rpms = {}
++            __missing_build_ids = {}
++            __suggest_build_ids = {}
++
++
++    # Attach to the required GDB events.
++    gdb.events.executable_changed.connect(executable_changed_handler)
++    gdb.events.before_prompt.connect(before_prompt)
++
++    # Register the missing debug and missing objfile handlers with GDB.
++    gdb.missing_debug.register_handler(None, RPM_MissingDebugHandler())
++    gdb.missing_objfile.register_handler(None, RPM_MissingObjfileHandler())
++
++    # Implement the core of 'info rpm-suggestions'.  Reprint all rpm
++    # suggestions.
++    def info_rpm_suggestions():
++        global __missing_rpms
++        global __missing_build_ids
++
++        if len(__missing_rpms) == 0 and len(__missing_build_ids) == 0:
++            print("No RPM suggestions have been made so far.")
++            return
++
++        if len(__missing_rpms) > 0:
++            print_rpm_suggestions(__missing_rpms.keys())
++        if len(__missing_build_ids) > 0:
++            print_build_id_suggestions(__missing_build_ids.keys())
++
++####################################################################
++# The following code is outside the 'else' block of the attempt to #
++# load the 'rpm' module.  Nothing after this point depends on the  #
++# 'rpm' module.                                                    #
++####################################################################
++
++# The 'set rpm-suggestion' prefix command.
++class rpm_suggestion_set_prefix(gdb.Command):
++    """Prefix command for 'set' rpm-suggestion related commands."""
++
++    def __init__(self):
++        super().__init__("set rpm-suggestion", gdb.COMMAND_NONE,
++                         gdb.COMPLETE_NONE, True)
++
++# The 'show rpm-suggestion' prefix command.
++class rpm_suggestion_show_prefix(gdb.Command):
++    """Prefix command for 'show' rpm-suggestion related commands."""
++
++    def __init__(self):
++        super().__init__("show rpm-suggestion", gdb.COMMAND_NONE,
++                         gdb.COMPLETE_NONE, True)
++
++# The 'set/show rpm-suggestion enabled' command.
++class rpm_suggestion_enabled(gdb.Parameter):
++    """
++    When 'on' GDB will search for RPMS that might provide additional
++    debug information, or provide missing executables or shared
++    libraries (when opening a core file), and will make suggestions
++    about what should be installed.
++
++    When 'off' GDB will not make these suggestions.
++    """
++
++    set_doc = "Set whether to perform rpm-suggestion."
++    show_doc = "Show whether rpm-suggestion is enabled."
++
++    def __init__(self):
++        super().__init__("rpm-suggestion enabled", gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
++        self.value = True
++
++# The 'set/show rpm-suggestion enabled' command.
++class rpm_suggestion_build_id_mode(gdb.Parameter):
++    """
++    When set to 'fast' (the default), GDB doesn't try to map a build-id to
++    an actual RPM, instead, GDB just suggests a command based on the
++    build-id which might install some RPMs, if there are any RPMs that
++    supply that build-id.  However, it is equally possible that there are no
++    suitable RPMs, and nothing will install.  This approach has almost zero
++    overhead.
++
++    When set to 'slow', GDB first does the build-id to RPM check itself, and
++    only if something is found are RPMs installation commands suggested.
++    The suggested command will include the name of the RPM to install.  This
++    approach is considerably slower as querying the RPM database for the RPM
++    that supplies a specific file is slow.
++    """
++
++    set_doc = "Set how build-id based rpm suggestions should be performed."
++    show_doc = "Show how build-id based rpm suggestions shoud be performed."
++
++    def __init__(self):
++        super().__init__("rpm-suggestion build-id-mode",
++                         gdb.COMMAND_NONE, gdb.PARAM_ENUM, ["fast", "slow"])
++        self.value = "fast"
++
++    def fast_mode(self):
++        return self.value == "fast"
++
++# The 'info rpm-suggestions' command.
++class rpm_suggestion_info(gdb.Command):
++    """Relist RPM suggestions.
++
++    Relist any RPM installation suggestions that have been made
++    since the executable was last changed."""
++    def __init__(self):
++        super().__init__("info rpm-suggestions", gdb.COMMAND_NONE, gdb.COMPLETE_NONE)
++
++    def invoke(self, args, from_tty):
++        if args != "":
++            raise gdb.GdbError("unexpected arguments: %s" % args)
++
++        info_rpm_suggestions ()
++
++
++# Create the 'set/show rpm-suggestion' commands.
++rpm_suggestion_set_prefix()
++rpm_suggestion_show_prefix()
++param_rpm_suggestion_enabled = rpm_suggestion_enabled()
++param_rpm_suggestion_build_id_mode = rpm_suggestion_build_id_mode()
++
++# Create the 'info rpm-suggestions' commands.
++rpm_suggestion_info()
+diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c
+new file mode 100644
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c
+@@ -0,0 +1,21 @@
++/* Copyright 2010 Free Software Foundation, Inc.
++
++   This file is part of GDB.
++
++   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/>.  */
++
++void
++lib (void)
++{
++}
+diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c
+new file mode 100644
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c
+@@ -0,0 +1,25 @@
++/* Copyright 2010 Free Software Foundation, Inc.
++
++   This file is part of GDB.
++
++   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 void lib (void);
++
++int
++main (void)
++{
++  lib ();
++  return 0;
++}
+diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
+new file mode 100644
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
+@@ -0,0 +1,104 @@
++# Copyright 2016 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/>.
++
++require allow_shlib_tests
++
++set testfile "gcore-buildid-exec-but-not-solib"
++set srcmainfile ${testfile}-main.c
++set srclibfile ${testfile}-lib.c
++set libfile [standard_output_file ${testfile}-lib.so]
++set objfile [standard_output_file ${testfile}-main.o]
++set executable ${testfile}-main
++set binfile [standard_output_file ${executable}]
++set gcorefile [standard_output_file ${executable}.gcore]
++set outdir [file dirname $binfile]
++
++if { [gdb_compile_shlib ${srcdir}/${subdir}/${srclibfile} ${libfile} "debug additional_flags=-Wl,--build-id"] != ""
++     || [gdb_compile ${srcdir}/${subdir}/${srcmainfile} ${objfile} object {debug}] != "" } {
++     unsupported "-Wl,--build-id compilation failed"
++     return -1
++}
++set opts [list debug shlib=${libfile} "additional_flags=-Wl,--build-id"]
++if { [gdb_compile ${objfile} ${binfile} executable $opts] != "" } {
++     unsupported "-Wl,--build-id compilation failed"
++     return -1
++}
++
++clean_restart $executable
++gdb_load_shlib $libfile
++
++# Does this gdb support gcore?
++set test "help gcore"
++gdb_test_multiple $test $test {
++    -re "Undefined command: .gcore.*\r\n$gdb_prompt $" {
++	# gcore command not supported -- nothing to test here.
++	unsupported "gdb does not support gcore on this target"
++	return -1;
++    }
++    -re "Save a core file .*\r\n$gdb_prompt $" {
++	pass $test
++    }
++}
++
++if { ![runto lib] } then {
++    return -1
++}
++
++set escapedfilename [string_to_regexp ${gcorefile}]
++
++set test "save a corefile"
++gdb_test_multiple "gcore ${gcorefile}" $test {
++    -re "Saved corefile ${escapedfilename}\r\n$gdb_prompt $" {
++	pass $test
++    }
++    -re "Can't create a corefile\r\n$gdb_prompt $" {
++	unsupported $test
++	return -1
++    }
++}
++
++# Now restart gdb and load the corefile.
++
++clean_restart $executable
++gdb_load_shlib $libfile
++
++set buildid [build_id_debug_filename_get $libfile]
++
++regsub {\.debug$} $buildid {} buildid
++
++set debugdir [standard_output_file ${testfile}-debugdir]
++file delete -force -- $debugdir
++
++file mkdir $debugdir/[file dirname $libfile]
++file copy $libfile $debugdir/${libfile}
++
++file mkdir $debugdir/[file dirname $buildid]
++file copy $libfile $debugdir/${buildid}
++
++remote_exec build "ln -s /lib       ${debugdir}/"
++remote_exec build "ln -s /lib64     ${debugdir}/"
++# /usr is not needed, all the libs are in /lib64: libm.so.6 libc.so.6 ld-linux-x86-64.so.2
++
++gdb_test_no_output "set solib-absolute-prefix $debugdir" \
++    "set solib-absolute-prefix"
++
++gdb_test_no_output "set debug-file-directory $debugdir" "set debug-file-directory"
++
++gdb_test "core ${gcorefile}" "Core was generated by .*" "re-load generated corefile"
++
++gdb_test "frame" "#0 \[^\r\n\]* lib .*" "library got loaded"
++
++gdb_test "bt"
++gdb_test "info shared"
+diff --git a/gdb/testsuite/gdb.base/gdbinit-history.exp b/gdb/testsuite/gdb.base/gdbinit-history.exp
+--- a/gdb/testsuite/gdb.base/gdbinit-history.exp
++++ b/gdb/testsuite/gdb.base/gdbinit-history.exp
+@@ -179,7 +179,8 @@ proc test_empty_history_filename { } {
+     global env
+     global gdb_prompt
+ 
+-    set common_history [list "set height 0" "set width 0"]
++    set common_history [list "set height 0" "set width 0" \
++			    "set rpm-suggestion enabled off"]
+ 
+     set test_dir [standard_output_file history_test]
+     remote_exec host "mkdir -p $test_dir"
+diff --git a/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
+new file mode 100644
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp
+@@ -0,0 +1,60 @@
++# Copyright (C) 2014  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/>.
++
++# Create a core file, then hide the executable.  Restart GDB and load
++# the core file.  Check GDB gives a message suggesting a 'dnf' command
++# to try and install the executable based on its build-id.
++
++standard_testfile "normal.c"
++
++if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
++    return -1
++}
++
++# Get the build-id of the file.
++set build_id_debug_file [build_id_debug_filename_get $binfile]
++regsub -all ".debug$" $build_id_debug_file "" build_id_without_debug
++
++# Run to main.
++if { ![runto_main] } {
++    return -1
++}
++
++# We first need to generate a corefile.
++set corefilename "[standard_output_file gcore.test]"
++if { ![gdb_gcore_cmd "$corefilename" "save corefile"] } {
++    untested "could not generate a corefile"
++    return -1
++}
++
++# Move the binfile to a temporary name.
++remote_exec build "mv $binfile ${binfile}.old"
++
++# Reinitialize GDB and see if we get a dnf suggestion.
++clean_restart
++
++gdb_test "set rpm-suggestion enabled on" "" \
++    "turn on rpm-suggestion feature"
++
++# GDB only makes build-id based RPM suggestions if /usr/lib is in
++# the debug-file-directory list, the reason being that system RPMs
++# will always install under this location.  If GDB is not looking
++# here then there's no point making suggestions.
++gdb_test "set debug-file-directory /usr/lib/" "" \
++    "set debug-file-directory"
++
++gdb_test "core-file [standard_output_file gcore.test]" \
++    "Missing file\\(s\\), try: dnf --enablerepo='\\*debug\\*' install [string_to_regexp /usr/lib/$build_id_without_debug] [string_to_regexp /usr/lib/debug/$build_id_debug_file]" \
++    "test first yum/dnf warning"
+diff --git a/gdb/testsuite/gdb.python/py-missing-debug.py b/gdb/testsuite/gdb.python/py-missing-debug.py
+--- a/gdb/testsuite/gdb.python/py-missing-debug.py
++++ b/gdb/testsuite/gdb.python/py-missing-debug.py
+@@ -19,6 +19,13 @@ from enum import Enum
+ import gdb
+ from gdb.missing_debug import MissingDebugHandler
+ 
++# This is a RHEL/Fedora work around: There's already a
++# missing-debug-info handler registered for these versions of GDB.
++# Discard the handler now so that the tests will pass (the tests
++# assume no handler is currently registered).
++gdb.missing_debug_handlers = []
++
++
+ # A global log that is filled in by instances of the LOG_HANDLER class
+ # when they are called.
+ handler_call_log = []
+@@ -118,4 +125,7 @@ def register(name, locus=None):
+ rhandler = exception_handler()
+ handler_obj = handler()
+ 
++# Discard the rpm-suggestion handler.
++gdb.missing_file_handlers = []
++
+ print("Success")
+diff --git a/gdb/testsuite/gdb.python/py-missing-objfile.py b/gdb/testsuite/gdb.python/py-missing-objfile.py
+--- a/gdb/testsuite/gdb.python/py-missing-objfile.py
++++ b/gdb/testsuite/gdb.python/py-missing-objfile.py
+@@ -164,4 +164,7 @@ def register(name, locus=None):
+ rhandler = exception_handler()
+ handler_obj = handler()
+ 
++# Discard the rpm-suggestion handler.
++gdb.missing_file_handlers = []
++
+ print("Success")
+diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
+--- a/gdb/testsuite/lib/gdb.exp
++++ b/gdb/testsuite/lib/gdb.exp
+@@ -255,7 +255,8 @@ if ![info exists INTERNAL_GDBFLAGS] {
+ 		   "-nx" \
+ 		   "-q" \
+ 		   {-iex "set height 0"} \
+-		   {-iex "set width 0"}]]
++		   {-iex "set width 0"} \
++		   {-iex "set rpm-suggestion enabled off"}]]
+ 
+     # If DEBUGINFOD_URLS is set, gdb will try to download sources and
+     # debug info for f.i. system libraries.  Prevent this.
+@@ -2610,6 +2611,18 @@ proc default_gdb_start { } {
+ 	}
+     }
+ 
++    # Turn off the missing debug info messages as the testsuite does
++    # not expect them.
++    send_gdb "set rpm-suggestion enabled off\n"
++    gdb_expect 10 {
++	-re "$gdb_prompt $" {
++	    verbose "Disabled the missing debug info messages." 2
++	}
++	timeout {
++	    warning "Could not disable the missing debug info messages."
++	}
++    }
++
+     gdb_debug_init
+     return 0
+ }
+diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
+--- a/gdb/testsuite/lib/mi-support.exp
++++ b/gdb/testsuite/lib/mi-support.exp
+@@ -321,6 +321,17 @@ proc default_mi_gdb_start { { flags {} } } {
+ 	    warning "Couldn't set the width to 0."
+ 	}
+     }
++    # Turn off the missing debug info messages as the testsuite does
++    # not expect them.
++    send_gdb "190-gdb-set rpm-suggestion enabled off\n"
++    gdb_expect 10 {
++	-re ".*190-gdb-set rpm-suggestion enabled off\r\n190\\\^done\r\n$mi_gdb_prompt$" {
++	    verbose "Disabled the missing debug info messages." 2
++	}
++	timeout {
++	    warning "Could not disable the missing debug info messages."
++	}
++    }
+ 
+     if { $separate_inferior_pty } {
+ 	mi_create_inferior_pty
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/gdb.git/commitdiff/24b85cb606af569bd5bbae07828d735ce9ab596d



More information about the pld-cvs-commit mailing list