[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