gdb/gdb-6.6-buildid-locate-rpm.patch
DistroBaker 3ce82c330b Merged update from upstream sources
This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/gdb.git#ed8730b4d9720b8c71cb7de29ce2165f730955cc
2020-11-06 01:04:27 +00:00

1500 lines
46 KiB
Diff

From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Fedora GDB patches <invalid@email.com>
Date: Fri, 27 Oct 2017 21:07:50 +0200
Subject: gdb-6.6-buildid-locate-rpm.patch
;;=push+jan
diff --git a/gdb/aclocal.m4 b/gdb/aclocal.m4
--- a/gdb/aclocal.m4
+++ b/gdb/aclocal.m4
@@ -11,7 +11,223 @@
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_default([$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes ],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+ ])
+elif test $pkg_failed = untried; then
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+ ])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ $3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+
+# PKG_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable pkgconfigdir as the location where a module
+# should install pkg-config .pc files. By default the directory is
+# $libdir/pkgconfig, but the default can be changed by passing
+# DIRECTORY. The user can override through the --with-pkgconfigdir
+# parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+ [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_INSTALLDIR
+
+
+# PKG_NOARCH_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable noarch_pkgconfigdir as the location where a
+# module should install arch-independent pkg-config .pc files. By
+# default the directory is $datadir/pkgconfig, but the default can be
+# changed by passing DIRECTORY. The user can override through the
+# --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+ [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_NOARCH_INSTALLDIR
+
+
+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -------------------------------------------
+# Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])# PKG_CHECK_VAR
+
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
diff --git a/gdb/build-id.c b/gdb/build-id.c
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -33,6 +33,7 @@
#include "gdb_bfd.h"
#include "gdbcmd.h"
#include "gdbcore.h"
+#include "inferior.h"
#include "objfiles.h"
#include "observable.h"
#include "symfile.h"
@@ -697,8 +698,374 @@ build_id_to_filename (const struct bfd_build_id *build_id, char **link_return)
return result;
}
+#ifdef HAVE_LIBRPM
+
+#include <rpm/rpmlib.h>
+#include <rpm/rpmts.h>
+#include <rpm/rpmdb.h>
+#include <rpm/header.h>
+#ifdef DLOPEN_LIBRPM
+#include <dlfcn.h>
+#endif
+
+/* This MISSING_RPM_HASH tracker is used to collect all the missing rpm files
+ and avoid their duplicities during a single inferior run. */
+
+static struct htab *missing_rpm_hash;
+
+/* This MISSING_RPM_LIST tracker is used to collect and print as a single line
+ all the rpms right before the nearest GDB prompt. It gets cleared after
+ each such print (it is questionable if we should clear it after the print).
+ */
+
+struct missing_rpm
+ {
+ struct missing_rpm *next;
+ char rpm[1];
+ };
+static struct missing_rpm *missing_rpm_list;
+static int missing_rpm_list_entries;
+
+/* Returns the count of newly added rpms. */
+
+static int
+missing_rpm_enlist (const char *filename)
+{
+ static int rpm_init_done = 0;
+ rpmts ts;
+ rpmdbMatchIterator mi;
+ int count = 0;
+
+#ifdef DLOPEN_LIBRPM
+ /* Duplicate here the declarations to verify they match. The same sanity
+ check is present also in `configure.ac'. */
+ extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg);
+ static char *(*headerFormat_p) (Header h, const char * fmt, errmsg_t *errmsg);
+ extern int rpmReadConfigFiles(const char * file, const char * target);
+ static int (*rpmReadConfigFiles_p) (const char * file, const char * target);
+ extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi);
+ static rpmdbMatchIterator (*rpmdbFreeIterator_p) (rpmdbMatchIterator mi);
+ extern Header rpmdbNextIterator(rpmdbMatchIterator mi);
+ static Header (*rpmdbNextIterator_p) (rpmdbMatchIterator mi);
+ extern rpmts rpmtsCreate(void);
+ static rpmts (*rpmtsCreate_p) (void);
+ extern rpmts rpmtsFree(rpmts ts);
+ static rpmts (*rpmtsFree_p) (rpmts ts);
+ extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
+ const void * keyp, size_t keylen);
+ static rpmdbMatchIterator (*rpmtsInitIterator_p) (const rpmts ts,
+ rpmTag rpmtag,
+ const void *keyp,
+ size_t keylen);
+#else /* !DLOPEN_LIBRPM */
+# define headerFormat_p headerFormat
+# define rpmReadConfigFiles_p rpmReadConfigFiles
+# define rpmdbFreeIterator_p rpmdbFreeIterator
+# define rpmdbNextIterator_p rpmdbNextIterator
+# define rpmtsCreate_p rpmtsCreate
+# define rpmtsFree_p rpmtsFree
+# define rpmtsInitIterator_p rpmtsInitIterator
+#endif /* !DLOPEN_LIBRPM */
+
+ gdb_assert (filename != NULL);
+
+ if (strcmp (filename, BUILD_ID_MAIN_EXECUTABLE_FILENAME) == 0)
+ return 0;
+
+ if (is_target_filename (filename))
+ return 0;
+
+ if (filename[0] != '/')
+ {
+ warning (_("Ignoring non-absolute filename: <%s>"), filename);
+ return 0;
+ }
+
+ if (!rpm_init_done)
+ {
+ static int init_tried;
+
+ /* Already failed the initialization before? */
+ if (init_tried)
+ return 0;
+ init_tried = 1;
+
+#ifdef DLOPEN_LIBRPM
+ {
+ void *h;
+
+ h = dlopen (DLOPEN_LIBRPM, RTLD_LAZY);
+ if (!h)
+ {
+ warning (_("Unable to open \"%s\" (%s), "
+ "missing debuginfos notifications will not be displayed"),
+ DLOPEN_LIBRPM, dlerror ());
+ return 0;
+ }
+
+ if (!((headerFormat_p = (char *(*) (Header h, const char * fmt, errmsg_t *errmsg)) dlsym (h, "headerFormat"))
+ && (rpmReadConfigFiles_p = (int (*) (const char * file, const char * target)) dlsym (h, "rpmReadConfigFiles"))
+ && (rpmdbFreeIterator_p = (rpmdbMatchIterator (*) (rpmdbMatchIterator mi)) dlsym (h, "rpmdbFreeIterator"))
+ && (rpmdbNextIterator_p = (Header (*) (rpmdbMatchIterator mi)) dlsym (h, "rpmdbNextIterator"))
+ && (rpmtsCreate_p = (rpmts (*) (void)) dlsym (h, "rpmtsCreate"))
+ && (rpmtsFree_p = (rpmts (*) (rpmts ts)) dlsym (h, "rpmtsFree"))
+ && (rpmtsInitIterator_p = (rpmdbMatchIterator (*) (const rpmts ts, rpmTag rpmtag, const void *keyp, size_t keylen)) dlsym (h, "rpmtsInitIterator"))))
+ {
+ warning (_("Opened library \"%s\" is incompatible (%s), "
+ "missing debuginfos notifications will not be displayed"),
+ DLOPEN_LIBRPM, dlerror ());
+ if (dlclose (h))
+ warning (_("Error closing library \"%s\": %s\n"), DLOPEN_LIBRPM,
+ dlerror ());
+ return 0;
+ }
+ }
+#endif /* DLOPEN_LIBRPM */
+
+ if (rpmReadConfigFiles_p (NULL, NULL) != 0)
+ {
+ warning (_("Error reading the rpm configuration files"));
+ return 0;
+ }
+
+ rpm_init_done = 1;
+ }
+
+ ts = rpmtsCreate_p ();
+
+ mi = rpmtsInitIterator_p (ts, RPMTAG_BASENAMES, filename, 0);
+ if (mi != NULL)
+ {
+ for (;;)
+ {
+ Header h;
+ char *debuginfo, **slot, *s, *s2;
+ errmsg_t err;
+ size_t srcrpmlen = sizeof (".src.rpm") - 1;
+ size_t debuginfolen = sizeof ("-debuginfo") - 1;
+ rpmdbMatchIterator mi_debuginfo;
+
+ h = rpmdbNextIterator_p (mi);
+ if (h == NULL)
+ break;
+
+ /* Verify the debuginfo file is not already installed. */
+
+ debuginfo = headerFormat_p (h, "%{sourcerpm}-debuginfo.%{arch}",
+ &err);
+ if (!debuginfo)
+ {
+ warning (_("Error querying the rpm file `%s': %s"), filename,
+ err);
+ continue;
+ }
+ /* s = `.src.rpm-debuginfo.%{arch}' */
+ s = strrchr (debuginfo, '-') - srcrpmlen;
+ s2 = NULL;
+ if (s > debuginfo && memcmp (s, ".src.rpm", srcrpmlen) == 0)
+ {
+ /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */
+ s2 = (char *) memrchr (debuginfo, '-', s - debuginfo);
+ }
+ if (s2)
+ {
+ /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
+ s2 = (char *) memrchr (debuginfo, '-', s2 - debuginfo);
+ }
+ if (!s2)
+ {
+ warning (_("Error querying the rpm file `%s': %s"), filename,
+ debuginfo);
+ xfree (debuginfo);
+ continue;
+ }
+ /* s = `.src.rpm-debuginfo.%{arch}' */
+ /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
+ memmove (s2 + debuginfolen, s2, s - s2);
+ memcpy (s2, "-debuginfo", debuginfolen);
+ /* s = `XXXX.%{arch}' */
+ /* strlen ("XXXX") == srcrpmlen + debuginfolen */
+ /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */
+ /* strlen ("XX") == srcrpmlen */
+ memmove (s + debuginfolen, s + srcrpmlen + debuginfolen,
+ strlen (s + srcrpmlen + debuginfolen) + 1);
+ /* s = `-debuginfo-%{version}-%{release}.%{arch}' */
+
+ /* RPMDBI_PACKAGES requires keylen == sizeof (int). */
+ /* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel(). */
+ mi_debuginfo = rpmtsInitIterator_p (ts, (rpmTag) RPMDBI_LABEL, debuginfo, 0);
+ xfree (debuginfo);
+ if (mi_debuginfo)
+ {
+ rpmdbFreeIterator_p (mi_debuginfo);
+ count = 0;
+ break;
+ }
+
+ /* The allocated memory gets utilized below for MISSING_RPM_HASH. */
+ debuginfo = headerFormat_p (h,
+ "%{name}-%{version}-%{release}.%{arch}",
+ &err);
+ if (!debuginfo)
+ {
+ warning (_("Error querying the rpm file `%s': %s"), filename,
+ err);
+ continue;
+ }
+
+ /* Base package name for `debuginfo-install'. We do not use the
+ `yum' command directly as the line
+ yum --enablerepo='*debug*' install NAME-debuginfo.ARCH
+ would be more complicated than just:
+ debuginfo-install NAME-VERSION-RELEASE.ARCH
+ Do not supply the rpm base name (derived from .src.rpm name) as
+ debuginfo-install is unable to install the debuginfo package if
+ the base name PKG binary rpm is not installed while for example
+ PKG-libs would be installed (RH Bug 467901).
+ FUTURE: After multiple debuginfo versions simultaneously installed
+ get supported the support for the VERSION-RELEASE tags handling
+ may need an update. */
+
+ if (missing_rpm_hash == NULL)
+ {
+ /* DEL_F is passed NULL as MISSING_RPM_LIST's HTAB_DELETE
+ should not deallocate the entries. */
+
+ missing_rpm_hash = htab_create_alloc (64, htab_hash_string,
+ (int (*) (const void *, const void *)) streq,
+ NULL, xcalloc, xfree);
+ }
+ slot = (char **) htab_find_slot (missing_rpm_hash, debuginfo, INSERT);
+ /* XCALLOC never returns NULL. */
+ gdb_assert (slot != NULL);
+ if (*slot == NULL)
+ {
+ struct missing_rpm *missing_rpm;
+
+ *slot = debuginfo;
+
+ missing_rpm = (struct missing_rpm *) xmalloc (sizeof (*missing_rpm) + strlen (debuginfo));
+ strcpy (missing_rpm->rpm, debuginfo);
+ missing_rpm->next = missing_rpm_list;
+ missing_rpm_list = missing_rpm;
+ missing_rpm_list_entries++;
+ }
+ else
+ xfree (debuginfo);
+ count++;
+ }
+
+ rpmdbFreeIterator_p (mi);
+ }
+
+ rpmtsFree_p (ts);
+
+ return count;
+}
+
+static bool
+missing_rpm_list_compar (const char *ap, const char *bp)
+{
+ return strcoll (ap, bp) < 0;
+}
+
+/* It returns a NULL-terminated array of strings needing to be FREEd. It may
+ also return only NULL. */
+
+static void
+missing_rpm_list_print (void)
+{
+ struct missing_rpm *list_iter;
+
+ if (missing_rpm_list_entries == 0)
+ return;
+
+ std::vector<const char *> array (missing_rpm_list_entries);
+ size_t idx = 0;
+
+ for (list_iter = missing_rpm_list; list_iter != NULL;
+ list_iter = list_iter->next)
+ {
+ array[idx++] = list_iter->rpm;
+ }
+ gdb_assert (idx == missing_rpm_list_entries);
+
+ std::sort (array.begin (), array.end (), missing_rpm_list_compar);
+
+ /* We zero out the number of missing RPMs here because of a nasty
+ bug (see RHBZ 1801974).
+
+ When we call 'puts_unfiltered' below, if pagination is on and if
+ the number of missing RPMs is big enough to trigger pagination,
+ we will end up in an infinite recursion. The call chain looks
+ like this:
+
+ missing_rpm_list_print -> puts_unfiltered -> fputs_maybe_filtered
+ -> prompt_for_continue -> display_gdb_prompt ->
+ debug_flush_missing -> missing_rpm_list_print ...
+
+ For this reason, we make sure MISSING_RPM_LIST_ENTRIES is zero
+ *before* calling any print function. */
+ missing_rpm_list_entries = 0;
+
+ printf_unfiltered (_("Missing separate debuginfos, use: %s"),
+#ifdef DNF_DEBUGINFO_INSTALL
+ "dnf "
+#endif
+ "debuginfo-install");
+ for (const char *el : array)
+ {
+ puts_unfiltered (" ");
+ puts_unfiltered (el);
+ }
+ puts_unfiltered ("\n");
+
+ while (missing_rpm_list != NULL)
+ {
+ list_iter = missing_rpm_list;
+ missing_rpm_list = list_iter->next;
+ xfree (list_iter);
+ }
+}
+
+static void
+missing_rpm_change (void)
+{
+ debug_flush_missing ();
+
+ gdb_assert (missing_rpm_list == NULL);
+ if (missing_rpm_hash != NULL)
+ {
+ htab_delete (missing_rpm_hash);
+ missing_rpm_hash = NULL;
+ }
+}
+
+enum missing_exec
+ {
+ /* Init state. EXEC_BFD also still could be NULL. */
+ MISSING_EXEC_NOT_TRIED,
+ /* We saw a non-NULL EXEC_BFD but RPM has no info about it. */
+ MISSING_EXEC_NOT_FOUND,
+ /* We found EXEC_BFD by RPM and we either have its symbols (either embedded
+ or separate) or the main executable's RPM is now contained in
+ MISSING_RPM_HASH. */
+ MISSING_EXEC_ENLISTED
+ };
+static enum missing_exec missing_exec = MISSING_EXEC_NOT_TRIED;
+
+#endif /* HAVE_LIBRPM */
+
+void
+debug_flush_missing (void)
+{
+#ifdef HAVE_LIBRPM
+ missing_rpm_list_print ();
+#endif
+}
+
/* This MISSING_FILEPAIR_HASH tracker is used only for the duplicite messages
- Try to install the hash file ...
+ yum --enablerepo='*debug*' install ...
avoidance. */
struct missing_filepair
@@ -752,11 +1119,17 @@ missing_filepair_change (void)
/* All their memory came just from missing_filepair_OBSTACK. */
missing_filepair_hash = NULL;
}
+#ifdef HAVE_LIBRPM
+ missing_exec = MISSING_EXEC_NOT_TRIED;
+#endif
}
static void
debug_print_executable_changed (void)
{
+#ifdef HAVE_LIBRPM
+ missing_rpm_change ();
+#endif
missing_filepair_change ();
}
@@ -823,14 +1196,38 @@ debug_print_missing (const char *binary, const char *debug)
*slot = missing_filepair;
- /* We do not collect and flush these messages as each such message
- already requires its own separate lines. */
+#ifdef HAVE_LIBRPM
+ if (missing_exec == MISSING_EXEC_NOT_TRIED)
+ {
+ const char *execfilename = get_exec_file (0);
- fprintf_unfiltered (gdb_stdlog,
- _("Missing separate debuginfo for %s\n"), binary);
- if (debug != NULL)
- fprintf_unfiltered (gdb_stdlog, _("Try to install the hash file %s\n"),
- debug);
+ if (execfilename != NULL)
+ {
+ if (missing_rpm_enlist (execfilename) == 0)
+ missing_exec = MISSING_EXEC_NOT_FOUND;
+ else
+ missing_exec = MISSING_EXEC_ENLISTED;
+ }
+ }
+ if (missing_exec != MISSING_EXEC_ENLISTED)
+ if ((binary[0] == 0 || missing_rpm_enlist (binary) == 0)
+ && (debug == NULL || missing_rpm_enlist (debug) == 0))
+#endif /* HAVE_LIBRPM */
+ {
+ /* We do not collect and flush these messages as each such message
+ already requires its own separate lines. */
+
+ fprintf_unfiltered (gdb_stdlog,
+ _("Missing separate debuginfo for %s\n"), binary);
+ if (debug != NULL)
+ fprintf_unfiltered (gdb_stdlog, _("Try: %s %s\n"),
+#ifdef DNF_DEBUGINFO_INSTALL
+ "dnf"
+#else
+ "yum"
+#endif
+ " --enablerepo='*debug*' install", debug);
+ }
}
/* See build-id.h. */
diff --git a/gdb/config.in b/gdb/config.in
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -39,6 +39,9 @@
/* Handle .ctf type-info sections */
#undef ENABLE_LIBCTF
+/* librpm version specific library name to dlopen. */
+#undef DLOPEN_LIBRPM
+
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#undef ENABLE_NLS
@@ -247,6 +250,9 @@
/* Define if you have the mpfr library. */
#undef HAVE_LIBMPFR
+/* Define if librpm library is being used. */
+#undef HAVE_LIBRPM
+
/* Define to 1 if you have the <libunwind-ia64.h> header file. */
#undef HAVE_LIBUNWIND_IA64_H
diff --git a/gdb/configure b/gdb/configure
--- a/gdb/configure
+++ b/gdb/configure
@@ -769,6 +769,11 @@ PKG_CONFIG
HAVE_NATIVE_GCORE_TARGET
TARGET_OBS
subdirs
+RPM_LIBS
+RPM_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
GDB_DATADIR
DEBUGDIR
MAKEINFO_EXTRA_FLAGS
@@ -873,6 +878,7 @@ with_gdb_datadir
with_relocated_sources
with_auto_load_dir
with_auto_load_safe_path
+with_rpm
enable_targets
enable_64_bit_bfd
enable_gdbmi
@@ -949,6 +955,8 @@ PKG_CONFIG_PATH
PKG_CONFIG_LIBDIR
DEBUGINFOD_CFLAGS
DEBUGINFOD_LIBS
+RPM_CFLAGS
+RPM_LIBS
YACC
YFLAGS
XMKMF'
@@ -1621,6 +1629,8 @@ Optional Packages:
do not restrict auto-loaded files locations
--with-debuginfod Enable debuginfo lookups with debuginfod
(auto/yes/no)
+ --with-rpm query rpm database for missing debuginfos (yes/no,
+ def. auto=librpm.so)
--with-libunwind-ia64 use libunwind frame unwinding for ia64 targets
--with-curses use the curses library instead of the termcap
library
@@ -1702,6 +1712,8 @@ Some influential environment variables:
C compiler flags for DEBUGINFOD, overriding pkg-config
DEBUGINFOD_LIBS
linker flags for DEBUGINFOD, overriding pkg-config
+ RPM_CFLAGS C compiler flags for RPM, overriding pkg-config
+ RPM_LIBS linker flags for RPM, overriding pkg-config
YACC The `Yet Another Compiler Compiler' implementation to use.
Defaults to the first program found out of: `bison -y', `byacc',
`yacc'.
@@ -6666,6 +6678,494 @@ _ACEOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_auto_load_safe_path" >&5
$as_echo "$with_auto_load_safe_path" >&6; }
+# Integration with rpm library to support missing debuginfo suggestions.
+# --without-rpm: Disable any rpm support.
+# --with-rpm=libname.so: Try to dynamically open `libname.so' during runtime.
+# Even with runtime missing `libname.so' GDB will still other run correctly.
+# Missing `libname.so' during ./configure will abort the configuration.
+# --with-rpm=librpm.so: Like `--with-rpm=libname.so' but try to find specific
+# minor version first such as `librpm-4.6.so' as minor version differences
+# mean API+ABI incompatibility. If the specific match versioned library name
+# could not be found still open dynamically at least `librpm.so'.
+# --with-rpm: Like `--with-rpm=librpm.so' but if any of its detection fails try
+# to find librpm for compilation-time linking by pkg-config. GDB binary will
+# be probably linked with the version specific library (as `librpm-4.6.so').
+# Failure to find librpm by pkg-config will abort the configuration.
+# (default) --with-rpm=auto: Like `--with-rpm=librpm.so' but if even pkg-config
+# cannot find librpm use to the rpmless compilation (like `--without-rpm').
+
+
+# Check whether --with-rpm was given.
+if test "${with_rpm+set}" = set; then :
+ withval=$with_rpm;
+else
+ with_rpm="auto"
+fi
+
+
+
+
+if test "x$with_rpm" != "xno"; then
+ if test "x$with_rpm" = "xyes"; then
+ LIBRPM="librpm.so"
+ RPM_REQUIRE=true
+ DLOPEN_REQUIRE=false
+ elif test "x$with_rpm" = "xauto"; then
+ LIBRPM="librpm.so"
+ RPM_REQUIRE=false
+ DLOPEN_REQUIRE=false
+ else
+ LIBRPM="$with_rpm"
+ RPM_REQUIRE=true
+ DLOPEN_REQUIRE=true
+ fi
+ LIBRPM_STRING='"'"$LIBRPM"'"'
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking specific librpm version" >&5
+$as_echo_n "checking specific librpm version... " >&6; }
+ HAVE_DLOPEN_LIBRPM=false
+ save_LIBS="$LIBS"
+ LIBS="$LIBS -ldl"
+ if test "$cross_compiling" = yes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run test program while cross compiling
+See \`config.log' for more details." "$LINENO" 5; }
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <rpm/rpmlib.h>
+#include <dlfcn.h>
+#include <errno.h>
+
+int
+main ()
+{
+
+ void *h;
+ const char *const *rpmverp;
+ FILE *f;
+
+ f = fopen ("conftest.out", "w");
+ if (!f)
+ {
+ fprintf (stderr, "Cannot write \"%s\": %s\n", "conftest.out",
+ strerror (errno));
+ return 1;
+ }
+ h = dlopen ($LIBRPM_STRING, RTLD_LAZY);
+ if (!h)
+ {
+ fprintf (stderr, "dlopen (\"%s\"): %s\n", $LIBRPM_STRING, dlerror ());
+ return 1;
+ }
+ rpmverp = dlsym (h, "RPMVERSION");
+ if (!rpmverp)
+ {
+ fprintf (stderr, "dlsym (\"RPMVERSION\"): %s\n", dlerror ());
+ return 1;
+ }
+ fprintf (stderr, "RPMVERSION is: \"");
+ fprintf (stderr, "%s\"\n", *rpmverp);
+
+ /* Try to find the specific librpm version only for "librpm.so" as we do
+ not know how to assemble the version string otherwise. */
+
+ if (strcmp ("librpm.so", $LIBRPM_STRING) != 0)
+ {
+ fprintf (f, "%s\n", $LIBRPM_STRING);
+ return 0;
+ }
+ else
+ {
+ char *h2_name;
+ void *h2;
+ int major, minor;
+
+ if (sscanf (*rpmverp, "%d.%d", &major, &minor) != 2)
+ {
+ fprintf (stderr, "Unable to parse RPMVERSION.\n");
+ fprintf (f, "%s\n", $LIBRPM_STRING);
+ return 0;
+ }
+ /* Avoid the square brackets by malloc. */
+ h2_name = malloc (64);
+ sprintf (h2_name, "librpm-%d.%d.so", major, minor);
+ h2 = dlopen (h2_name, RTLD_LAZY);
+ if (!h2)
+ {
+ fprintf (stderr, "dlopen (\"%s\"): %s\n", h2_name, dlerror ());
+ fprintf (f, "%s\n", $LIBRPM_STRING);
+ return 0;
+ }
+ if (h2 != h)
+ {
+ fprintf (stderr, "dlopen of \"%s\" and \"%s\" are different.\n",
+ $LIBRPM_STRING, h2_name);
+ fprintf (f, "%s\n", $LIBRPM_STRING);
+ return 0;
+ }
+ /* Found the valid .so name with a specific version. */
+ fprintf (f, "%s\n", h2_name);
+ return 0;
+ }
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+ DLOPEN_LIBRPM="`cat conftest.out`"
+ if test "x$DLOPEN_LIBRPM" != "x"; then
+ HAVE_DLOPEN_LIBRPM=true
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLOPEN_LIBRPM" >&5
+$as_echo "$DLOPEN_LIBRPM" >&6; }
+ fi
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ rm -f conftest.out
+
+
+
+ if $HAVE_DLOPEN_LIBRPM; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking rpm library API compatibility" >&5
+$as_echo_n "checking rpm library API compatibility... " >&6; }
+ # The compilation requires -Werror to verify anything.
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Duplicate here the declarations to verify they match "elfread.c". */
+#include <rpm/rpmlib.h>
+#include <rpm/rpmts.h>
+#include <rpm/rpmdb.h>
+#include <rpm/header.h>
+extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg);
+extern int rpmReadConfigFiles(const char * file, const char * target);
+extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi);
+extern Header rpmdbNextIterator(rpmdbMatchIterator mi);
+extern rpmts rpmtsCreate(void);
+extern rpmts rpmtsFree(rpmts ts);
+extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
+ const void * keyp, size_t keylen);
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ LIBRPM_COMPAT=true
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ LIBRPM_COMPAT=false
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if ! $LIBRPM_COMPAT; then
+ HAVE_DLOPEN_LIBRPM=false
+ fi
+ fi
+
+ if $HAVE_DLOPEN_LIBRPM; then
+ DLOPEN_LIBRPM_STRING='"'"$DLOPEN_LIBRPM"'"'
+
+cat >>confdefs.h <<_ACEOF
+#define DLOPEN_LIBRPM $DLOPEN_LIBRPM_STRING
+_ACEOF
+
+
+$as_echo "#define HAVE_LIBRPM 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ LIBS="$save_LIBS"
+ if $DLOPEN_REQUIRE; then
+ as_fn_error "Specific name $LIBRPM was requested but it could not be opened." "$LINENO" 5
+ fi
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ PKG_CONFIG=""
+ fi
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for RPM" >&5
+$as_echo_n "checking for RPM... " >&6; }
+
+if test -n "$RPM_CFLAGS"; then
+ pkg_cv_RPM_CFLAGS="$RPM_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rpm\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "rpm") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_RPM_CFLAGS=`$PKG_CONFIG --cflags "rpm" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$RPM_LIBS"; then
+ pkg_cv_RPM_LIBS="$RPM_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rpm\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "rpm") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_RPM_LIBS=`$PKG_CONFIG --libs "rpm" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ RPM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "rpm" 2>&1`
+ else
+ RPM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "rpm" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$RPM_PKG_ERRORS" >&5
+
+ HAVE_LIBRPM=false
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ HAVE_LIBRPM=false
+else
+ RPM_CFLAGS=$pkg_cv_RPM_CFLAGS
+ RPM_LIBS=$pkg_cv_RPM_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ HAVE_LIBRPM=true
+fi
+
+ if $HAVE_LIBRPM; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking rpm library API compatibility" >&5
+$as_echo_n "checking rpm library API compatibility... " >&6; }
+ # The compilation requires -Werror to verify anything.
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Duplicate here the declarations to verify they match "elfread.c". */
+#include <rpm/rpmlib.h>
+#include <rpm/rpmts.h>
+#include <rpm/rpmdb.h>
+#include <rpm/header.h>
+extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg);
+extern int rpmReadConfigFiles(const char * file, const char * target);
+extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi);
+extern Header rpmdbNextIterator(rpmdbMatchIterator mi);
+extern rpmts rpmtsCreate(void);
+extern rpmts rpmtsFree(rpmts ts);
+extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
+ const void * keyp, size_t keylen);
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ LIBRPM_COMPAT=true
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ LIBRPM_COMPAT=false
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if ! $LIBRPM_COMPAT; then
+ HAVE_LIBRPM=false
+ RPM_PKG_ERRORS="Found $LIBRPM API is incompatibile with this GDB"
+ fi
+ fi
+
+ if $HAVE_LIBRPM; then
+
+$as_echo "#define HAVE_LIBRPM 1" >>confdefs.h
+
+ CFLAGS="$CFLAGS $RPM_CFLAGS"
+ LIBS="$LIBS $RPM_LIBS"
+ else
+ if $RPM_REQUIRE; then
+ as_fn_error "$RPM_PKG_ERRORS" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $RPM_PKG_ERRORS" >&5
+$as_echo "$as_me: WARNING: $RPM_PKG_ERRORS" >&2;}
+ fi
+ fi
+ fi
+fi
+
subdirs="$subdirs testsuite"
diff --git a/gdb/configure.ac b/gdb/configure.ac
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -143,6 +143,199 @@ AC_DEFINE_DIR(AUTO_LOAD_SAFE_PATH, escape_dir,
[Directories safe to hold auto-loaded files.])
AC_MSG_RESULT([$with_auto_load_safe_path])
+# Integration with rpm library to support missing debuginfo suggestions.
+# --without-rpm: Disable any rpm support.
+# --with-rpm=libname.so: Try to dynamically open `libname.so' during runtime.
+# Even with runtime missing `libname.so' GDB will still other run correctly.
+# Missing `libname.so' during ./configure will abort the configuration.
+# --with-rpm=librpm.so: Like `--with-rpm=libname.so' but try to find specific
+# minor version first such as `librpm-4.6.so' as minor version differences
+# mean API+ABI incompatibility. If the specific match versioned library name
+# could not be found still open dynamically at least `librpm.so'.
+# --with-rpm: Like `--with-rpm=librpm.so' but if any of its detection fails try
+# to find librpm for compilation-time linking by pkg-config. GDB binary will
+# be probably linked with the version specific library (as `librpm-4.6.so').
+# Failure to find librpm by pkg-config will abort the configuration.
+# (default) --with-rpm=auto: Like `--with-rpm=librpm.so' but if even pkg-config
+# cannot find librpm use to the rpmless compilation (like `--without-rpm').
+
+AC_ARG_WITH([rpm],
+ [AS_HELP_STRING([--with-rpm],
+ [query rpm database for missing debuginfos (yes/no, def. auto=librpm.so)])], [], [with_rpm="auto"])
+
+m4_pattern_allow([^AC_MSG_ERROR$])
+m4_pattern_allow([^AC_MSG_WARN$])
+if test "x$with_rpm" != "xno"; then
+ if test "x$with_rpm" = "xyes"; then
+ LIBRPM="librpm.so"
+ RPM_REQUIRE=true
+ DLOPEN_REQUIRE=false
+ elif test "x$with_rpm" = "xauto"; then
+ LIBRPM="librpm.so"
+ RPM_REQUIRE=false
+ DLOPEN_REQUIRE=false
+ else
+ LIBRPM="$with_rpm"
+ RPM_REQUIRE=true
+ DLOPEN_REQUIRE=true
+ fi
+ LIBRPM_STRING='"'"$LIBRPM"'"'
+
+ AC_MSG_CHECKING([specific librpm version])
+ HAVE_DLOPEN_LIBRPM=false
+ save_LIBS="$LIBS"
+ LIBS="$LIBS -ldl"
+ AC_RUN_IFELSE(AC_LANG_PROGRAM([[
+#include <rpm/rpmlib.h>
+#include <dlfcn.h>
+#include <errno.h>
+ ]], [[
+ void *h;
+ const char *const *rpmverp;
+ FILE *f;
+
+ f = fopen ("conftest.out", "w");
+ if (!f)
+ {
+ fprintf (stderr, "Cannot write \"%s\": %s\n", "conftest.out",
+ strerror (errno));
+ return 1;
+ }
+ h = dlopen ($LIBRPM_STRING, RTLD_LAZY);
+ if (!h)
+ {
+ fprintf (stderr, "dlopen (\"%s\"): %s\n", $LIBRPM_STRING, dlerror ());
+ return 1;
+ }
+ rpmverp = dlsym (h, "RPMVERSION");
+ if (!rpmverp)
+ {
+ fprintf (stderr, "dlsym (\"RPMVERSION\"): %s\n", dlerror ());
+ return 1;
+ }
+ fprintf (stderr, "RPMVERSION is: \"");
+ fprintf (stderr, "%s\"\n", *rpmverp);
+
+ /* Try to find the specific librpm version only for "librpm.so" as we do
+ not know how to assemble the version string otherwise. */
+
+ if (strcmp ("librpm.so", $LIBRPM_STRING) != 0)
+ {
+ fprintf (f, "%s\n", $LIBRPM_STRING);
+ return 0;
+ }
+ else
+ {
+ char *h2_name;
+ void *h2;
+ int major, minor;
+
+ if (sscanf (*rpmverp, "%d.%d", &major, &minor) != 2)
+ {
+ fprintf (stderr, "Unable to parse RPMVERSION.\n");
+ fprintf (f, "%s\n", $LIBRPM_STRING);
+ return 0;
+ }
+ /* Avoid the square brackets by malloc. */
+ h2_name = malloc (64);
+ sprintf (h2_name, "librpm-%d.%d.so", major, minor);
+ h2 = dlopen (h2_name, RTLD_LAZY);
+ if (!h2)
+ {
+ fprintf (stderr, "dlopen (\"%s\"): %s\n", h2_name, dlerror ());
+ fprintf (f, "%s\n", $LIBRPM_STRING);
+ return 0;
+ }
+ if (h2 != h)
+ {
+ fprintf (stderr, "dlopen of \"%s\" and \"%s\" are different.\n",
+ $LIBRPM_STRING, h2_name);
+ fprintf (f, "%s\n", $LIBRPM_STRING);
+ return 0;
+ }
+ /* Found the valid .so name with a specific version. */
+ fprintf (f, "%s\n", h2_name);
+ return 0;
+ }
+ ]]), [
+ DLOPEN_LIBRPM="`cat conftest.out`"
+ if test "x$DLOPEN_LIBRPM" != "x"; then
+ HAVE_DLOPEN_LIBRPM=true
+ AC_MSG_RESULT($DLOPEN_LIBRPM)
+ fi
+ ])
+ rm -f conftest.out
+
+ m4_define([CHECK_LIBRPM_COMPAT], [
+ AC_MSG_CHECKING([rpm library API compatibility])
+ # The compilation requires -Werror to verify anything.
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror"
+ AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[
+/* Duplicate here the declarations to verify they match "elfread.c". */
+#include <rpm/rpmlib.h>
+#include <rpm/rpmts.h>
+#include <rpm/rpmdb.h>
+#include <rpm/header.h>
+extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg);
+extern int rpmReadConfigFiles(const char * file, const char * target);
+extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi);
+extern Header rpmdbNextIterator(rpmdbMatchIterator mi);
+extern rpmts rpmtsCreate(void);
+extern rpmts rpmtsFree(rpmts ts);
+extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
+ const void * keyp, size_t keylen);
+ ]]), [
+ LIBRPM_COMPAT=true
+ AC_MSG_RESULT(yes)
+ ], [
+ LIBRPM_COMPAT=false
+ AC_MSG_RESULT(no)
+ ])
+ CFLAGS="$save_CFLAGS"
+ ])
+
+ if $HAVE_DLOPEN_LIBRPM; then
+ CHECK_LIBRPM_COMPAT
+ if ! $LIBRPM_COMPAT; then
+ HAVE_DLOPEN_LIBRPM=false
+ fi
+ fi
+
+ if $HAVE_DLOPEN_LIBRPM; then
+ DLOPEN_LIBRPM_STRING='"'"$DLOPEN_LIBRPM"'"'
+ AC_DEFINE_UNQUOTED(DLOPEN_LIBRPM, $DLOPEN_LIBRPM_STRING, [librpm version specific library name to dlopen.])
+ AC_DEFINE(HAVE_LIBRPM, 1, [Define if librpm library is being used.])
+ else
+ AC_MSG_RESULT(no)
+ LIBS="$save_LIBS"
+ if $DLOPEN_REQUIRE; then
+ AC_MSG_ERROR([Specific name $LIBRPM was requested but it could not be opened.])
+ fi
+ PKG_CHECK_MODULES(RPM, rpm, [HAVE_LIBRPM=true], [HAVE_LIBRPM=false])
+
+ if $HAVE_LIBRPM; then
+ CHECK_LIBRPM_COMPAT
+ if ! $LIBRPM_COMPAT; then
+ HAVE_LIBRPM=false
+ RPM_PKG_ERRORS="Found $LIBRPM API is incompatibile with this GDB"
+ fi
+ fi
+
+ if $HAVE_LIBRPM; then
+ AC_DEFINE(HAVE_LIBRPM, 1, [Define if librpm library is being used.])
+ CFLAGS="$CFLAGS $RPM_CFLAGS"
+ LIBS="$LIBS $RPM_LIBS"
+ else
+ if $RPM_REQUIRE; then
+ AC_MSG_ERROR($RPM_PKG_ERRORS)
+ else
+ AC_MSG_WARN($RPM_PKG_ERRORS)
+ fi
+ fi
+ fi
+fi
+
AC_CONFIG_SUBDIRS(testsuite)
# Check whether to support alternative target configurations
diff --git a/gdb/event-top.c b/gdb/event-top.c
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -42,6 +42,7 @@
#include "gdbsupport/gdb_select.h"
#include "gdbsupport/gdb-sigmask.h"
#include "async-event.h"
+#include "symfile.h"
/* readline include files. */
#include "readline/readline.h"
@@ -364,6 +365,8 @@ display_gdb_prompt (const char *new_prompt)
/* Reset the nesting depth used when trace-commands is set. */
reset_command_nest_depth ();
+ debug_flush_missing ();
+
/* Do not call the python hook on an explicit prompt change as
passed to this function, as this forms a secondary/local prompt,
IE, displayed but not set. */
@@ -773,7 +776,10 @@ command_line_handler (gdb::unique_xmalloc_ptr<char> &&rl)
command_handler (cmd);
if (ui->prompt_state != PROMPTED)
- display_gdb_prompt (0);
+ {
+ debug_flush_missing ();
+ display_gdb_prompt (0);
+ }
}
}
diff --git a/gdb/symfile.h b/gdb/symfile.h
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -560,6 +560,7 @@ 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);
+extern void debug_flush_missing (void);
#define BUILD_ID_MAIN_EXECUTABLE_FILENAME _("the main executable file")
/* From dwarf2read.c */