Blame SOURCES/gdb-rhbz1838777-debuginfod.patch

b2f73e
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
b2f73e
From: Keith Seitz <keiths@redhat.com>
b2f73e
Date: Tue, 9 Jun 2020 08:29:41 -0700
b2f73e
Subject: gdb-rhbz1838777-debuginfod.patch
b2f73e
b2f73e
;; Backport debuginofd support.
b2f73e
;; (Aaron Merey, RH BZ 183877)
b2f73e
b2f73e
commit 0d79cdc494d5eb9db26a602d62c92d49f83f407e
b2f73e
Author: Aaron Merey <amerey@redhat.com>
b2f73e
Date:   Wed Feb 26 17:40:49 2020 -0500
b2f73e
b2f73e
    Add debuginfod support to GDB
b2f73e
b2f73e
    debuginfod is a lightweight web service that indexes ELF/DWARF debugging
b2f73e
    resources by build-id and serves them over HTTP.
b2f73e
b2f73e
    This patch enables GDB to query debuginfod servers for separate debug
b2f73e
    files and source code when it is otherwise not able to find them.
b2f73e
b2f73e
    GDB can be built with debuginfod using the --with-debuginfod configure
b2f73e
    option.
b2f73e
b2f73e
    This requires that libdebuginfod be installed and found at configure time.
b2f73e
b2f73e
    debuginfod is packaged with elfutils, starting with version 0.178.
b2f73e
b2f73e
    For more information see https://sourceware.org/elfutils/.
b2f73e
b2f73e
    Tested on x86_64 Fedora 31.
b2f73e
b2f73e
    gdb/ChangeLog:
b2f73e
    2020-02-26  Aaron Merey  <amerey@redhat.com>
b2f73e
b2f73e
            * Makefile.in: Handle optional debuginfod support.
b2f73e
            * NEWS: Update.
b2f73e
            * README: Add --with-debuginfod summary.
b2f73e
            * config.in: Regenerate.
b2f73e
            * configure: Regenerate.
b2f73e
            * configure.ac: Handle optional debuginfod support.
b2f73e
            * debuginfod-support.c: debuginfod helper functions.
b2f73e
            * debuginfod-support.h: Ditto.
b2f73e
            * doc/gdb.texinfo: Add --with-debuginfod to configure options
b2f73e
            summary.
b2f73e
            * dwarf2/read.c (dwarf2_get_dwz_file): Query debuginfod servers
b2f73e
            when a dwz file cannot be found.
b2f73e
            * elfread.c (elf_symfile_read): Query debuginfod servers when a
b2f73e
            debuginfo file cannot be found.
b2f73e
            * source.c (open_source_file): Query debuginfod servers when a
b2f73e
            source file cannot be found.
b2f73e
            * top.c (print_gdb_configuration): Include
b2f73e
            --{with,without}-debuginfod in the output.
b2f73e
b2f73e
    gdb/testsuite/ChangeLog:
b2f73e
    2020-02-26  Aaron Merey  <amerey@redhat.com>
b2f73e
b2f73e
            * gdb.debuginfod: New directory for debuginfod tests.
b2f73e
            * gdb.debuginfod/main.c: New test file.
b2f73e
            * gdb.debuginfod/fetch_src_and_symbols.exp: New tests.
b2f73e
b2f73e
diff --git a/config/debuginfod.m4 b/config/debuginfod.m4
b2f73e
new file mode 100644
b2f73e
--- /dev/null
b2f73e
+++ b/config/debuginfod.m4
b2f73e
@@ -0,0 +1,38 @@
b2f73e
+dnl Copyright (C) 1997-2019 Free Software Foundation, Inc.
b2f73e
+dnl This file is free software, distributed under the terms of the GNU
b2f73e
+dnl General Public License.  As a special exception to the GNU General
b2f73e
+dnl Public License, this file may be distributed as part of a program
b2f73e
+dnl that contains a configuration script generated by Autoconf, under
b2f73e
+dnl the same distribution terms as the rest of that program.
b2f73e
+
b2f73e
+AC_DEFUN([AC_DEBUGINFOD],
b2f73e
+[
b2f73e
+# Enable debuginfod
b2f73e
+AC_ARG_WITH([debuginfod],
b2f73e
+        AC_HELP_STRING([--with-debuginfod],
b2f73e
+                       [Enable debuginfo lookups with debuginfod (auto/yes/no)]),
b2f73e
+        [], [with_debuginfod=auto])
b2f73e
+AC_MSG_CHECKING([whether to use debuginfod])
b2f73e
+AC_MSG_RESULT([$with_debuginfod])
b2f73e
+
b2f73e
+if test "${with_debuginfod}" = no; then
b2f73e
+  AC_MSG_WARN([debuginfod support disabled; some features may be unavailable.])
b2f73e
+else
b2f73e
+  AC_CHECK_LIB([debuginfod], [debuginfod_begin], [have_debuginfod_lib=yes])
b2f73e
+  AC_CHECK_DECL([debuginfod_begin], [have_debuginfod_h=yes], [],
b2f73e
+                [#include <elfutils/debuginfod.h>])
b2f73e
+  if test "x$have_debuginfod_lib" = "xyes" -a \
b2f73e
+          "x$have_debuginfod_h" = "xyes"; then
b2f73e
+    AC_DEFINE([HAVE_LIBDEBUGINFOD], [1],
b2f73e
+              [Define to 1 if debuginfod is enabled.])
b2f73e
+    AC_SUBST([LIBDEBUGINFOD], ["-ldebuginfod"])
b2f73e
+  else
b2f73e
+    AC_SUBST([LIBDEBUGINFOD], [])
b2f73e
+    if test "$with_debuginfod" = yes; then
b2f73e
+      AC_MSG_ERROR([debuginfod is missing or unusable])
b2f73e
+    else
b2f73e
+      AC_MSG_WARN([debuginfod is missing or unusable; some features may be unavailable.])
b2f73e
+    fi
b2f73e
+  fi
b2f73e
+fi
b2f73e
+])
b2f73e
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
b2f73e
--- a/gdb/Makefile.in
b2f73e
+++ b/gdb/Makefile.in
b2f73e
@@ -612,7 +612,8 @@ CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(LIBCTF) $(ZLIB) \
b2f73e
 	@LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
b2f73e
 	$(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
b2f73e
 	$(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) $(LIBICONV) $(LIBMPFR) \
b2f73e
-	$(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS)
b2f73e
+	$(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS) \
b2f73e
+	@LIBDEBUGINFOD@
b2f73e
 CDEPS = $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) $(LIBCTF) \
b2f73e
 	$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU)
b2f73e
 
b2f73e
@@ -1016,6 +1017,7 @@ COMMON_SFILES = \
b2f73e
 	dbxread.c \
b2f73e
 	dcache.c \
b2f73e
 	debug.c \
b2f73e
+	debuginfod-support.c \
b2f73e
 	dictionary.c \
b2f73e
 	disasm.c \
b2f73e
 	disasm-selftests.c \
b2f73e
diff --git a/gdb/NEWS b/gdb/NEWS
b2f73e
--- a/gdb/NEWS
b2f73e
+++ b/gdb/NEWS
b2f73e
@@ -932,6 +932,20 @@ SH-5/SH64 running OpenBSD 	SH-5/SH64 support in sh*-*-openbsd*
b2f73e
      manual for a further description of this feature.
b2f73e
 
b2f73e
 
b2f73e
+* GDB now supports debuginfod, an HTTP server for distributing ELF/DWARF
b2f73e
+  debugging information as well as source code.
b2f73e
+
b2f73e
+  When built with debuginfod, GDB can automatically query debuginfod
b2f73e
+  servers for the separate debug files and source code of the executable
b2f73e
+  being debugged.
b2f73e
+
b2f73e
+  To build GDB with debuginfod, pass --with-debuginfod to configure (this
b2f73e
+  requires libdebuginfod, the debuginfod client library).
b2f73e
+
b2f73e
+  debuginfod is distributed with elfutils, starting with version 0.178.
b2f73e
+
b2f73e
+  You can get the latest version from https://sourceware.org/elfutils.
b2f73e
+
b2f73e
 * New features in the GDB remote stub, GDBserver
b2f73e
 
b2f73e
   ** GDBserver is now able to start inferior processes with a
b2f73e
diff --git a/gdb/README b/gdb/README
b2f73e
--- a/gdb/README
b2f73e
+++ b/gdb/README
b2f73e
@@ -432,6 +432,15 @@ more obscure GDB `configure' options are not listed here.
b2f73e
      Use the curses library instead of the termcap library, for
b2f73e
      text-mode terminal operations.
b2f73e
 
b2f73e
+`--with-debuginfod'
b2f73e
+     Build GDB with libdebuginfod, the debuginfod client library.  Used
b2f73e
+     to automatically fetch source files and separate debug files from
b2f73e
+     debuginfod servers using the associated executable's build ID.
b2f73e
+     Enabled by default if libdebuginfod is installed and found at
b2f73e
+     configure time.  debuginfod is packaged with elfutils, starting
b2f73e
+     with version 0.178.  You can get the latest version from
b2f73e
+     'https://sourceware.org/elfutils/'.
b2f73e
+
b2f73e
 `--with-libunwind-ia64'
b2f73e
      Use the libunwind library for unwinding function call stack on ia64
b2f73e
      target platforms.
b2f73e
diff --git a/gdb/config.in b/gdb/config.in
b2f73e
--- a/gdb/config.in
b2f73e
+++ b/gdb/config.in
b2f73e
@@ -230,6 +230,9 @@
b2f73e
 /* Define if you have the babeltrace library. */
b2f73e
 #undef HAVE_LIBBABELTRACE
b2f73e
 
b2f73e
+/* Define to 1 if debuginfod is enabled. */
b2f73e
+#undef HAVE_LIBDEBUGINFOD
b2f73e
+
b2f73e
 /* Define if you have the expat library. */
b2f73e
 #undef HAVE_LIBEXPAT
b2f73e
 
b2f73e
diff --git a/gdb/configure b/gdb/configure
b2f73e
--- a/gdb/configure
b2f73e
+++ b/gdb/configure
b2f73e
@@ -758,6 +758,7 @@ REPORT_BUGS_TEXI
b2f73e
 REPORT_BUGS_TO
b2f73e
 PKGVERSION
b2f73e
 CODESIGN_CERT
b2f73e
+LIBDEBUGINFOD
b2f73e
 HAVE_NATIVE_GCORE_TARGET
b2f73e
 TARGET_OBS
b2f73e
 subdirs
b2f73e
@@ -875,6 +876,7 @@ enable_64_bit_bfd
b2f73e
 enable_gdbmi
b2f73e
 enable_tui
b2f73e
 enable_gdbtk
b2f73e
+with_debuginfod
b2f73e
 with_libunwind_ia64
b2f73e
 with_curses
b2f73e
 enable_profiling
b2f73e
@@ -1611,6 +1613,8 @@ Optional Packages:
b2f73e
                           do not restrict auto-loaded files locations
b2f73e
   --with-rpm              query rpm database for missing debuginfos (yes/no,
b2f73e
                           def. auto=librpm.so)
b2f73e
+  --with-debuginfod       Enable debuginfo lookups with debuginfod
b2f73e
+                          (auto/yes/no)
b2f73e
   --with-libunwind-ia64   use libunwind frame unwinding for ia64 targets
b2f73e
   --with-curses           use the curses library instead of the termcap
b2f73e
                           library
b2f73e
@@ -2271,6 +2275,52 @@ rm -f conftest.val
b2f73e
 
b2f73e
 } # ac_fn_c_compute_int
b2f73e
 
b2f73e
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
b2f73e
+# ---------------------------------------------
b2f73e
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
b2f73e
+# accordingly.
b2f73e
+ac_fn_c_check_decl ()
b2f73e
+{
b2f73e
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
b2f73e
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
b2f73e
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
b2f73e
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
b2f73e
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
b2f73e
+if eval \${$3+:} false; then :
b2f73e
+  $as_echo_n "(cached) " >&6
b2f73e
+else
b2f73e
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
b2f73e
+/* end confdefs.h.  */
b2f73e
+$4
b2f73e
+int
b2f73e
+main ()
b2f73e
+{
b2f73e
+#ifndef $as_decl_name
b2f73e
+#ifdef __cplusplus
b2f73e
+  (void) $as_decl_use;
b2f73e
+#else
b2f73e
+  (void) $as_decl_name;
b2f73e
+#endif
b2f73e
+#endif
b2f73e
+
b2f73e
+  ;
b2f73e
+  return 0;
b2f73e
+}
b2f73e
+_ACEOF
b2f73e
+if ac_fn_c_try_compile "$LINENO"; then :
b2f73e
+  eval "$3=yes"
b2f73e
+else
b2f73e
+  eval "$3=no"
b2f73e
+fi
b2f73e
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
b2f73e
+fi
b2f73e
+eval ac_res=\$$3
b2f73e
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
b2f73e
+$as_echo "$ac_res" >&6; }
b2f73e
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
b2f73e
+
b2f73e
+} # ac_fn_c_check_decl
b2f73e
+
b2f73e
 # ac_fn_c_check_func LINENO FUNC VAR
b2f73e
 # ----------------------------------
b2f73e
 # Tests whether FUNC exists, setting the cache variable VAR accordingly
b2f73e
@@ -2449,52 +2499,6 @@ $as_echo "$ac_res" >&6; }
b2f73e
 
b2f73e
 } # ac_fn_c_check_type
b2f73e
 
b2f73e
-# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
b2f73e
-# ---------------------------------------------
b2f73e
-# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
b2f73e
-# accordingly.
b2f73e
-ac_fn_c_check_decl ()
b2f73e
-{
b2f73e
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
b2f73e
-  as_decl_name=`echo $2|sed 's/ *(.*//'`
b2f73e
-  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
b2f73e
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
b2f73e
-$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
b2f73e
-if eval \${$3+:} false; then :
b2f73e
-  $as_echo_n "(cached) " >&6
b2f73e
-else
b2f73e
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
b2f73e
-/* end confdefs.h.  */
b2f73e
-$4
b2f73e
-int
b2f73e
-main ()
b2f73e
-{
b2f73e
-#ifndef $as_decl_name
b2f73e
-#ifdef __cplusplus
b2f73e
-  (void) $as_decl_use;
b2f73e
-#else
b2f73e
-  (void) $as_decl_name;
b2f73e
-#endif
b2f73e
-#endif
b2f73e
-
b2f73e
-  ;
b2f73e
-  return 0;
b2f73e
-}
b2f73e
-_ACEOF
b2f73e
-if ac_fn_c_try_compile "$LINENO"; then :
b2f73e
-  eval "$3=yes"
b2f73e
-else
b2f73e
-  eval "$3=no"
b2f73e
-fi
b2f73e
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
b2f73e
-fi
b2f73e
-eval ac_res=\$$3
b2f73e
-	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
b2f73e
-$as_echo "$ac_res" >&6; }
b2f73e
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
b2f73e
-
b2f73e
-} # ac_fn_c_check_decl
b2f73e
-
b2f73e
 # ac_fn_cxx_try_link LINENO
b2f73e
 # -------------------------
b2f73e
 # Try to link conftest.$ac_ext, and return whether this succeeded.
b2f73e
@@ -6658,8 +6662,8 @@ $as_echo_n "checking specific librpm version... " >&6; }
b2f73e
   if test "$cross_compiling" = yes; then :
b2f73e
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
b2f73e
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
b2f73e
-as_fn_error "cannot run test program while cross compiling
b2f73e
-See \`config.log' for more details." "$LINENO" 5; }
b2f73e
+as_fn_error $? "cannot run test program while cross compiling
b2f73e
+See \`config.log' for more details" "$LINENO" 5; }
b2f73e
 else
b2f73e
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
b2f73e
 /* end confdefs.h.  */
b2f73e
@@ -6830,7 +6834,7 @@ $as_echo "#define HAVE_LIBRPM 1" >>confdefs.h
b2f73e
 $as_echo "no" >&6; }
b2f73e
     LIBS="$save_LIBS"
b2f73e
     if $DLOPEN_REQUIRE; then
b2f73e
-      as_fn_error "Specific name $LIBRPM was requested but it could not be opened." "$LINENO" 5
b2f73e
+      as_fn_error $? "Specific name $LIBRPM was requested but it could not be opened." "$LINENO" 5
b2f73e
     fi
b2f73e
 
b2f73e
 
b2f73e
@@ -6845,7 +6849,7 @@ if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
b2f73e
 set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
b2f73e
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
b2f73e
 $as_echo_n "checking for $ac_word... " >&6; }
b2f73e
-if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
b2f73e
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
b2f73e
   $as_echo_n "(cached) " >&6
b2f73e
 else
b2f73e
   case $PKG_CONFIG in
b2f73e
@@ -6859,7 +6863,7 @@ do
b2f73e
   IFS=$as_save_IFS
b2f73e
   test -z "$as_dir" && as_dir=.
b2f73e
     for ac_exec_ext in '' $ac_executable_extensions; do
b2f73e
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
b2f73e
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
b2f73e
     ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
b2f73e
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
b2f73e
     break 2
b2f73e
@@ -6888,7 +6892,7 @@ if test -z "$ac_cv_path_PKG_CONFIG"; then
b2f73e
 set dummy pkg-config; ac_word=$2
b2f73e
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
b2f73e
 $as_echo_n "checking for $ac_word... " >&6; }
b2f73e
-if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
b2f73e
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
b2f73e
   $as_echo_n "(cached) " >&6
b2f73e
 else
b2f73e
   case $ac_pt_PKG_CONFIG in
b2f73e
@@ -6902,7 +6906,7 @@ do
b2f73e
   IFS=$as_save_IFS
b2f73e
   test -z "$as_dir" && as_dir=.
b2f73e
     for ac_exec_ext in '' $ac_executable_extensions; do
b2f73e
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
b2f73e
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
b2f73e
     ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
b2f73e
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
b2f73e
     break 2
b2f73e
@@ -7086,7 +7090,7 @@ $as_echo "#define HAVE_LIBRPM 1" >>confdefs.h
b2f73e
       LIBS="$LIBS $RPM_LIBS"
b2f73e
     else
b2f73e
       if $RPM_REQUIRE; then
b2f73e
-	as_fn_error "$RPM_PKG_ERRORS" "$LINENO" 5
b2f73e
+	as_fn_error $? "$RPM_PKG_ERRORS" "$LINENO" 5
b2f73e
       else
b2f73e
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $RPM_PKG_ERRORS" >&5
b2f73e
 $as_echo "$as_me: WARNING: $RPM_PKG_ERRORS" >&2;}
b2f73e
@@ -7332,8 +7336,92 @@ $as_echo "$as_me: WARNING: gdbtk isn't supported on $host; disabling" >&2;}
b2f73e
     enable_gdbtk=no ;;
b2f73e
 esac
b2f73e
 
b2f73e
-# Libunwind support for ia64.
b2f73e
+# Handle optional debuginfod support
b2f73e
+
b2f73e
+# Enable debuginfod
b2f73e
+
b2f73e
+# Check whether --with-debuginfod was given.
b2f73e
+if test "${with_debuginfod+set}" = set; then :
b2f73e
+  withval=$with_debuginfod;
b2f73e
+else
b2f73e
+  with_debuginfod=auto
b2f73e
+fi
b2f73e
+
b2f73e
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use debuginfod" >&5
b2f73e
+$as_echo_n "checking whether to use debuginfod... " >&6; }
b2f73e
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_debuginfod" >&5
b2f73e
+$as_echo "$with_debuginfod" >&6; }
b2f73e
+
b2f73e
+if test "${with_debuginfod}" = no; then
b2f73e
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: debuginfod support disabled; some features may be unavailable." >&5
b2f73e
+$as_echo "$as_me: WARNING: debuginfod support disabled; some features may be unavailable." >&2;}
b2f73e
+else
b2f73e
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for debuginfod_begin in -ldebuginfod" >&5
b2f73e
+$as_echo_n "checking for debuginfod_begin in -ldebuginfod... " >&6; }
b2f73e
+if ${ac_cv_lib_debuginfod_debuginfod_begin+:} false; then :
b2f73e
+  $as_echo_n "(cached) " >&6
b2f73e
+else
b2f73e
+  ac_check_lib_save_LIBS=$LIBS
b2f73e
+LIBS="-ldebuginfod  $LIBS"
b2f73e
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
b2f73e
+/* end confdefs.h.  */
b2f73e
+
b2f73e
+/* Override any GCC internal prototype to avoid an error.
b2f73e
+   Use char because int might match the return type of a GCC
b2f73e
+   builtin and then its argument prototype would still apply.  */
b2f73e
+#ifdef __cplusplus
b2f73e
+extern "C"
b2f73e
+#endif
b2f73e
+char debuginfod_begin ();
b2f73e
+int
b2f73e
+main ()
b2f73e
+{
b2f73e
+return debuginfod_begin ();
b2f73e
+  ;
b2f73e
+  return 0;
b2f73e
+}
b2f73e
+_ACEOF
b2f73e
+if ac_fn_c_try_link "$LINENO"; then :
b2f73e
+  ac_cv_lib_debuginfod_debuginfod_begin=yes
b2f73e
+else
b2f73e
+  ac_cv_lib_debuginfod_debuginfod_begin=no
b2f73e
+fi
b2f73e
+rm -f core conftest.err conftest.$ac_objext \
b2f73e
+    conftest$ac_exeext conftest.$ac_ext
b2f73e
+LIBS=$ac_check_lib_save_LIBS
b2f73e
+fi
b2f73e
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_debuginfod_debuginfod_begin" >&5
b2f73e
+$as_echo "$ac_cv_lib_debuginfod_debuginfod_begin" >&6; }
b2f73e
+if test "x$ac_cv_lib_debuginfod_debuginfod_begin" = xyes; then :
b2f73e
+  have_debuginfod_lib=yes
b2f73e
+fi
b2f73e
+
b2f73e
+  ac_fn_c_check_decl "$LINENO" "debuginfod_begin" "ac_cv_have_decl_debuginfod_begin" "#include <elfutils/debuginfod.h>
b2f73e
+"
b2f73e
+if test "x$ac_cv_have_decl_debuginfod_begin" = xyes; then :
b2f73e
+  have_debuginfod_h=yes
b2f73e
+fi
b2f73e
+
b2f73e
+  if test "x$have_debuginfod_lib" = "xyes" -a \
b2f73e
+          "x$have_debuginfod_h" = "xyes"; then
b2f73e
+
b2f73e
+$as_echo "#define HAVE_LIBDEBUGINFOD 1" >>confdefs.h
b2f73e
+
b2f73e
+    LIBDEBUGINFOD="-ldebuginfod"
b2f73e
 
b2f73e
+  else
b2f73e
+
b2f73e
+    if test "$with_debuginfod" = yes; then
b2f73e
+      as_fn_error $? "debuginfod is missing or unusable" "$LINENO" 5
b2f73e
+    else
b2f73e
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: debuginfod is missing or unusable; some features may be unavailable." >&5
b2f73e
+$as_echo "$as_me: WARNING: debuginfod is missing or unusable; some features may be unavailable." >&2;}
b2f73e
+    fi
b2f73e
+  fi
b2f73e
+fi
b2f73e
+
b2f73e
+
b2f73e
+# Libunwind support for ia64.
b2f73e
 
b2f73e
 # Check whether --with-libunwind-ia64 was given.
b2f73e
 if test "${with_libunwind_ia64+set}" = set; then :
b2f73e
@@ -16441,7 +16529,7 @@ _ACEOF
b2f73e
 for ac_header in selinux/selinux.h
b2f73e
 do :
b2f73e
   ac_fn_c_check_header_mongrel "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default"
b2f73e
-if test "x$ac_cv_header_selinux_selinux_h" = x""yes; then :
b2f73e
+if test "x$ac_cv_header_selinux_selinux_h" = xyes; then :
b2f73e
   cat >>confdefs.h <<_ACEOF
b2f73e
 #define HAVE_SELINUX_SELINUX_H 1
b2f73e
 _ACEOF
b2f73e
@@ -16452,7 +16540,7 @@ done
b2f73e
 
b2f73e
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for security_get_boolean_active in -lselinux" >&5
b2f73e
 $as_echo_n "checking for security_get_boolean_active in -lselinux... " >&6; }
b2f73e
-if test "${ac_cv_lib_selinux_security_get_boolean_active+set}" = set; then :
b2f73e
+if ${ac_cv_lib_selinux_security_get_boolean_active+:} false; then :
b2f73e
   $as_echo_n "(cached) " >&6
b2f73e
 else
b2f73e
   ac_check_lib_save_LIBS=$LIBS
b2f73e
@@ -16486,7 +16574,7 @@ LIBS=$ac_check_lib_save_LIBS
b2f73e
 fi
b2f73e
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_security_get_boolean_active" >&5
b2f73e
 $as_echo "$ac_cv_lib_selinux_security_get_boolean_active" >&6; }
b2f73e
-if test "x$ac_cv_lib_selinux_security_get_boolean_active" = x""yes; then :
b2f73e
+if test "x$ac_cv_lib_selinux_security_get_boolean_active" = xyes; then :
b2f73e
   cat >>confdefs.h <<_ACEOF
b2f73e
 #define HAVE_LIBSELINUX 1
b2f73e
 _ACEOF
b2f73e
diff --git a/gdb/configure.ac b/gdb/configure.ac
b2f73e
--- a/gdb/configure.ac
b2f73e
+++ b/gdb/configure.ac
b2f73e
@@ -18,6 +18,8 @@ dnl along with this program.  If not, see <http://www.gnu.org/licenses/>.
b2f73e
 
b2f73e
 dnl Process this file with autoconf to produce a configure script.
b2f73e
 
b2f73e
+m4_include(../config/debuginfod.m4)
b2f73e
+
b2f73e
 AC_INIT(main.c)
b2f73e
 AC_CONFIG_HEADERS(config.h:config.in, [echo > stamp-h])
b2f73e
 AM_MAINTAINER_MODE
b2f73e
@@ -516,8 +518,10 @@ case $host_os in
b2f73e
     enable_gdbtk=no ;;
b2f73e
 esac
b2f73e
 
b2f73e
-# Libunwind support for ia64.
b2f73e
+# Handle optional debuginfod support
b2f73e
+AC_DEBUGINFOD
b2f73e
 
b2f73e
+# Libunwind support for ia64.
b2f73e
 AC_ARG_WITH(libunwind-ia64,
b2f73e
 AS_HELP_STRING([--with-libunwind-ia64],
b2f73e
 	       [use libunwind frame unwinding for ia64 targets]),,
b2f73e
diff --git a/gdb/debuginfod-support.c b/gdb/debuginfod-support.c
b2f73e
new file mode 100644
b2f73e
--- /dev/null
b2f73e
+++ b/gdb/debuginfod-support.c
b2f73e
@@ -0,0 +1,155 @@
b2f73e
+/* debuginfod utilities for GDB.
b2f73e
+   Copyright (C) 2020 Free Software Foundation, Inc.
b2f73e
+
b2f73e
+   This file is part of GDB.
b2f73e
+
b2f73e
+   This program is free software; you can redistribute it and/or modify
b2f73e
+   it under the terms of the GNU General Public License as published by
b2f73e
+   the Free Software Foundation; either version 3 of the License, or
b2f73e
+   (at your option) any later version.
b2f73e
+
b2f73e
+   This program is distributed in the hope that it will be useful,
b2f73e
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
b2f73e
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b2f73e
+   GNU General Public License for more details.
b2f73e
+
b2f73e
+   You should have received a copy of the GNU General Public License
b2f73e
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
b2f73e
+
b2f73e
+#include "defs.h"
b2f73e
+#include <errno.h>
b2f73e
+#include "cli/cli-style.h"
b2f73e
+#include "gdbsupport/scoped_fd.h"
b2f73e
+#include "debuginfod-support.h"
b2f73e
+
b2f73e
+#ifndef HAVE_LIBDEBUGINFOD
b2f73e
+scoped_fd
b2f73e
+debuginfod_source_query (const unsigned char *build_id,
b2f73e
+			 int build_id_len,
b2f73e
+			 const char *srcpath,
b2f73e
+			 gdb::unique_xmalloc_ptr<char> *destname)
b2f73e
+{
b2f73e
+  return scoped_fd (-ENOSYS);
b2f73e
+}
b2f73e
+
b2f73e
+scoped_fd
b2f73e
+debuginfod_debuginfo_query (const unsigned char *build_id,
b2f73e
+			    int build_id_len,
b2f73e
+			    const char *filename,
b2f73e
+			    gdb::unique_xmalloc_ptr<char> *destname)
b2f73e
+{
b2f73e
+  return scoped_fd (-ENOSYS);
b2f73e
+}
b2f73e
+#else
b2f73e
+#include <elfutils/debuginfod.h>
b2f73e
+
b2f73e
+/* TODO: Use debuginfod API extensions instead of these globals.  */
b2f73e
+static std::string desc;
b2f73e
+static std::string fname;
b2f73e
+static bool has_printed;
b2f73e
+
b2f73e
+static int
b2f73e
+progressfn (debuginfod_client *c, long cur, long total)
b2f73e
+{
b2f73e
+  if (check_quit_flag ())
b2f73e
+    {
b2f73e
+      printf_filtered ("Cancelling download of %s %ps...\n",
b2f73e
+		       desc.c_str (),
b2f73e
+		       styled_string (file_name_style.style (), fname.c_str ()));
b2f73e
+      return 1;
b2f73e
+    }
b2f73e
+
b2f73e
+  if (!has_printed && total != 0)
b2f73e
+    {
b2f73e
+      /* Print this message only once.  */
b2f73e
+      has_printed = true;
b2f73e
+      printf_filtered ("Downloading %s %ps...\n",
b2f73e
+		       desc.c_str (),
b2f73e
+		       styled_string (file_name_style.style (), fname.c_str ()));
b2f73e
+    }
b2f73e
+
b2f73e
+  return 0;
b2f73e
+}
b2f73e
+
b2f73e
+static debuginfod_client *
b2f73e
+debuginfod_init ()
b2f73e
+{
b2f73e
+  debuginfod_client *c = debuginfod_begin ();
b2f73e
+
b2f73e
+  if (c != nullptr)
b2f73e
+    debuginfod_set_progressfn (c, progressfn);
b2f73e
+
b2f73e
+  return c;
b2f73e
+}
b2f73e
+
b2f73e
+/* See debuginfod-support.h  */
b2f73e
+
b2f73e
+scoped_fd
b2f73e
+debuginfod_source_query (const unsigned char *build_id,
b2f73e
+			 int build_id_len,
b2f73e
+			 const char *srcpath,
b2f73e
+			 gdb::unique_xmalloc_ptr<char> *destname)
b2f73e
+{
b2f73e
+  if (getenv (DEBUGINFOD_URLS_ENV_VAR) == NULL)
b2f73e
+    return scoped_fd (-ENOSYS);
b2f73e
+
b2f73e
+  debuginfod_client *c = debuginfod_init ();
b2f73e
+
b2f73e
+  if (c == nullptr)
b2f73e
+    return scoped_fd (-ENOMEM);
b2f73e
+
b2f73e
+  desc = std::string ("source file");
b2f73e
+  fname = std::string (srcpath);
b2f73e
+  has_printed = false;
b2f73e
+
b2f73e
+  scoped_fd fd (debuginfod_find_source (c,
b2f73e
+					build_id,
b2f73e
+					build_id_len,
b2f73e
+					srcpath,
b2f73e
+					nullptr));
b2f73e
+
b2f73e
+  /* TODO: Add 'set debug debuginfod' command to control when error messages are shown.  */
b2f73e
+  if (fd.get () < 0 && fd.get () != -ENOENT)
b2f73e
+    printf_filtered (_("Download failed: %s.  Continuing without source file %ps.\n"),
b2f73e
+		     safe_strerror (-fd.get ()),
b2f73e
+		     styled_string (file_name_style.style (),  srcpath));
b2f73e
+  else
b2f73e
+    destname->reset (xstrdup (srcpath));
b2f73e
+
b2f73e
+  debuginfod_end (c);
b2f73e
+  return fd;
b2f73e
+}
b2f73e
+
b2f73e
+/* See debuginfod-support.h  */
b2f73e
+
b2f73e
+scoped_fd
b2f73e
+debuginfod_debuginfo_query (const unsigned char *build_id,
b2f73e
+			    int build_id_len,
b2f73e
+			    const char *filename,
b2f73e
+			    gdb::unique_xmalloc_ptr<char> *destname)
b2f73e
+{
b2f73e
+  if (getenv (DEBUGINFOD_URLS_ENV_VAR) == NULL)
b2f73e
+    return scoped_fd (-ENOSYS);
b2f73e
+
b2f73e
+  debuginfod_client *c = debuginfod_init ();
b2f73e
+
b2f73e
+  if (c == nullptr)
b2f73e
+    return scoped_fd (-ENOMEM);
b2f73e
+
b2f73e
+  desc = std::string ("separate debug info for");
b2f73e
+  fname = std::string (filename);
b2f73e
+  has_printed = false;
b2f73e
+  char *dname = nullptr;
b2f73e
+
b2f73e
+  scoped_fd fd (debuginfod_find_debuginfo (c, build_id, build_id_len, &dname));
b2f73e
+
b2f73e
+  if (fd.get () < 0 && fd.get () != -ENOENT)
b2f73e
+    printf_filtered (_("Download failed: %s.  Continuing without debug info for %ps.\n"),
b2f73e
+		     safe_strerror (-fd.get ()),
b2f73e
+		     styled_string (file_name_style.style (),  filename));
b2f73e
+
b2f73e
+  destname->reset (dname);
b2f73e
+  debuginfod_end (c);
b2f73e
+  return fd;
b2f73e
+}
b2f73e
+#endif
b2f73e
diff --git a/gdb/debuginfod-support.h b/gdb/debuginfod-support.h
b2f73e
new file mode 100644
b2f73e
--- /dev/null
b2f73e
+++ b/gdb/debuginfod-support.h
b2f73e
@@ -0,0 +1,62 @@
b2f73e
+/* debuginfod utilities for GDB.
b2f73e
+   Copyright (C) 2020 Free Software Foundation, Inc.
b2f73e
+
b2f73e
+   This file is part of GDB.
b2f73e
+
b2f73e
+   This program is free software; you can redistribute it and/or modify
b2f73e
+   it under the terms of the GNU General Public License as published by
b2f73e
+   the Free Software Foundation; either version 3 of the License, or
b2f73e
+   (at your option) any later version.
b2f73e
+
b2f73e
+   This program is distributed in the hope that it will be useful,
b2f73e
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
b2f73e
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b2f73e
+   GNU General Public License for more details.
b2f73e
+
b2f73e
+   You should have received a copy of the GNU General Public License
b2f73e
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
b2f73e
+
b2f73e
+#ifndef DEBUGINFOD_SUPPORT_H
b2f73e
+#define DEBUGINFOD_SUPPORT_H
b2f73e
+
b2f73e
+/* Query debuginfod servers for a source file associated with an
b2f73e
+   executable with BUILD_ID.  BUILD_ID can be given as a binary blob or
b2f73e
+   a null-terminated string.  If given as a binary blob, BUILD_ID_LEN
b2f73e
+   should be the number of bytes.  If given as a null-terminated string,
b2f73e
+   BUILD_ID_LEN should be 0.
b2f73e
+
b2f73e
+   SRC_PATH should be the source file's absolute path that includes the
b2f73e
+   compilation directory of the CU associated with the source file.
b2f73e
+   For example if a CU's compilation directory is `/my/build` and the
b2f73e
+   source file path is `/my/source/foo.c`, then SRC_PATH should be
b2f73e
+   `/my/build/../source/foo.c`.
b2f73e
+
b2f73e
+   If the file is successfully retrieved, its path on the local machine
b2f73e
+   is stored in DESTNAME.  If GDB is not built with debuginfod, this
b2f73e
+   function returns -ENOSYS.  */
b2f73e
+
b2f73e
+extern scoped_fd
b2f73e
+debuginfod_source_query (const unsigned char *build_id,
b2f73e
+			 int build_id_len,
b2f73e
+			 const char *src_path,
b2f73e
+			 gdb::unique_xmalloc_ptr<char> *destname);
b2f73e
+
b2f73e
+/* Query debuginfod servers for a debug info file with BUILD_ID.
b2f73e
+   BUILD_ID can be given as a binary blob or a null-terminated string.
b2f73e
+   If given as a binary blob, BUILD_ID_LEN should be the number of bytes.
b2f73e
+   If given as a null-terminated string, BUILD_ID_LEN should be 0.
b2f73e
+
b2f73e
+   FILENAME should be the name or path of the main binary associated with
b2f73e
+   the separate debug info.  It is used for printing messages to the user.
b2f73e
+
b2f73e
+   If the file is successfully retrieved, its path on the local machine
b2f73e
+   is stored in DESTNAME.  If GDB is not built with debuginfod, this
b2f73e
+   function returns -ENOSYS.  */
b2f73e
+
b2f73e
+extern scoped_fd
b2f73e
+debuginfod_debuginfo_query (const unsigned char *build_id,
b2f73e
+			    int build_id_len,
b2f73e
+			    const char *filename,
b2f73e
+			    gdb::unique_xmalloc_ptr<char> *destname);
b2f73e
+
b2f73e
+#endif /* DEBUGINFOD_SUPPORT_H */
b2f73e
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
b2f73e
--- a/gdb/doc/gdb.texinfo
b2f73e
+++ b/gdb/doc/gdb.texinfo
b2f73e
@@ -37726,6 +37726,14 @@ supported).
b2f73e
 Use the curses library instead of the termcap library, for text-mode
b2f73e
 terminal operations.
b2f73e
 
b2f73e
+@item --with-debuginfod
b2f73e
+Build @value{GDBN} with libdebuginfod, the debuginfod client library.
b2f73e
+Used to automatically fetch source files and separate debug files from
b2f73e
+debuginfod servers using the associated executable's build ID. Enabled
b2f73e
+by default if libdebuginfod is installed and found at configure time.
b2f73e
+debuginfod is packaged with elfutils, starting with version 0.178. You
b2f73e
+can get the latest version from `https://sourceware.org/elfutils/'.
b2f73e
+
b2f73e
 @item --with-libunwind-ia64
b2f73e
 Use the libunwind library for unwinding function call stack on ia64
b2f73e
 target platforms.  See http://www.nongnu.org/libunwind/index.html for
b2f73e
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
b2f73e
--- a/gdb/dwarf2read.c
b2f73e
+++ b/gdb/dwarf2read.c
b2f73e
@@ -77,6 +77,7 @@
b2f73e
 #include "gdbsupport/selftest.h"
b2f73e
 #include "rust-lang.h"
b2f73e
 #include "gdbsupport/pathstuff.h"
b2f73e
+#include "debuginfod-support.h"
b2f73e
 
b2f73e
 /* When == 1, print basic high level tracing messages.
b2f73e
    When > 1, be more verbose.
b2f73e
@@ -2717,6 +2718,29 @@ dwarf2_get_dwz_file (struct dwarf2_per_objfile *dwarf2_per_objfile)
b2f73e
 	dwz_bfd.reset (nullptr);
b2f73e
     }
b2f73e
 
b2f73e
+  if (dwz_bfd == nullptr)
b2f73e
+    {
b2f73e
+      gdb::unique_xmalloc_ptr<char> alt_filename;
b2f73e
+      const char *origname = dwarf2_per_objfile->objfile->original_name;
b2f73e
+
b2f73e
+      scoped_fd fd (debuginfod_debuginfo_query (buildid,
b2f73e
+						buildid_len,
b2f73e
+						origname,
b2f73e
+						&alt_filename));
b2f73e
+
b2f73e
+      if (fd.get () >= 0)
b2f73e
+	{
b2f73e
+	  /* File successfully retrieved from server.  */
b2f73e
+	  dwz_bfd = gdb_bfd_open (alt_filename.get (), gnutarget, -1);
b2f73e
+
b2f73e
+	  if (dwz_bfd == nullptr)
b2f73e
+	    warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
b2f73e
+		     alt_filename.get ());
b2f73e
+	  else if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
b2f73e
+	    dwz_bfd.reset (nullptr);
b2f73e
+	}
b2f73e
+    }
b2f73e
+
b2f73e
   if (dwz_bfd == NULL)
b2f73e
     dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid, NULL);
b2f73e
 
b2f73e
diff --git a/gdb/elfread.c b/gdb/elfread.c
b2f73e
--- a/gdb/elfread.c
b2f73e
+++ b/gdb/elfread.c
b2f73e
@@ -49,6 +49,8 @@
b2f73e
 #include "mdebugread.h"
b2f73e
 #include "ctfread.h"
b2f73e
 #include "gdbsupport/gdb_string_view.h"
b2f73e
+#include "gdbsupport/scoped_fd.h"
b2f73e
+#include "debuginfod-support.h"
b2f73e
 
b2f73e
 /* Forward declarations.  */
b2f73e
 extern const struct sym_fns elf_sym_fns_gdb_index;
b2f73e
@@ -1313,12 +1315,42 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
b2f73e
 	  symbol_file_add_separate (debug_bfd.get (), debugfile.c_str (),
b2f73e
 				    symfile_flags, objfile);
b2f73e
 	}
b2f73e
-      /* Check if any separate debug info has been extracted out.  */
b2f73e
-      else if (bfd_get_section_by_name (objfile->obfd, ".gnu_debuglink")
b2f73e
-	       != NULL)
b2f73e
-	debug_print_missing (objfile_name (objfile), build_id_filename.get ());
b2f73e
       else
b2f73e
-	has_dwarf2 = false;
b2f73e
+	{
b2f73e
+	  has_dwarf2 = false;
b2f73e
+	  const struct bfd_build_id *build_id = build_id_bfd_shdr_get (objfile->obfd);
b2f73e
+
b2f73e
+	  if (build_id != nullptr)
b2f73e
+	    {
b2f73e
+	      gdb::unique_xmalloc_ptr<char> symfile_path;
b2f73e
+	      scoped_fd fd (debuginfod_debuginfo_query (build_id->data,
b2f73e
+							build_id->size,
b2f73e
+							objfile->original_name,
b2f73e
+							&symfile_path));
b2f73e
+
b2f73e
+	      if (fd.get () >= 0)
b2f73e
+		{
b2f73e
+		  /* File successfully retrieved from server.  */
b2f73e
+		  gdb_bfd_ref_ptr debug_bfd (symfile_bfd_open (symfile_path.get ()));
b2f73e
+
b2f73e
+		  if (debug_bfd == nullptr)
b2f73e
+		    warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
b2f73e
+			     objfile->original_name);
b2f73e
+		  else if (build_id_verify (debug_bfd.get (), build_id->size, build_id->data))
b2f73e
+		    {
b2f73e
+		      symbol_file_add_separate (debug_bfd.get (), symfile_path.get (),
b2f73e
+						symfile_flags, objfile);
b2f73e
+		      has_dwarf2 = true;
b2f73e
+		    }
b2f73e
+		}
b2f73e
+	    }
b2f73e
+	  /* Check if any separate debug info has been extracted out.  */
b2f73e
+	  else if (bfd_get_section_by_name (objfile->obfd, ".gnu_debuglink")
b2f73e
+		   != NULL)
b2f73e
+	    debug_print_missing (objfile_name (objfile), build_id_filename.get ());
b2f73e
+	  else
b2f73e
+	    has_dwarf2 = false;
b2f73e
+	}
b2f73e
     }
b2f73e
 
b2f73e
   /* Read the CTF section only if there is no DWARF info.  */
b2f73e
diff --git a/gdb/source.c b/gdb/source.c
b2f73e
--- a/gdb/source.c
b2f73e
+++ b/gdb/source.c
b2f73e
@@ -47,6 +47,8 @@
b2f73e
 #include "gdbsupport/pathstuff.h"
b2f73e
 #include "source-cache.h"
b2f73e
 #include "cli/cli-style.h"
b2f73e
+#include "build-id.h"
b2f73e
+#include "debuginfod-support.h"
b2f73e
 
b2f73e
 #define OPEN_MODE (O_RDONLY | O_BINARY)
b2f73e
 #define FDOPEN_MODE FOPEN_RB
b2f73e
@@ -1122,6 +1124,34 @@ open_source_file (struct symtab *s)
b2f73e
   s->fullname = NULL;
b2f73e
   scoped_fd fd = find_and_open_source (s->filename, SYMTAB_DIRNAME (s),
b2f73e
 				       &fullname);
b2f73e
+
b2f73e
+  if (fd.get () < 0)
b2f73e
+    {
b2f73e
+      if (SYMTAB_COMPUNIT (s) != nullptr)
b2f73e
+	{
b2f73e
+	  const objfile *ofp = COMPUNIT_OBJFILE (SYMTAB_COMPUNIT (s));
b2f73e
+
b2f73e
+	  std::string srcpath;
b2f73e
+	  if (IS_ABSOLUTE_PATH (s->filename))
b2f73e
+	    srcpath = s->filename;
b2f73e
+	  else if (SYMTAB_DIRNAME (s) != nullptr)
b2f73e
+	    {
b2f73e
+	      srcpath = SYMTAB_DIRNAME (s);
b2f73e
+	      srcpath += SLASH_STRING;
b2f73e
+	      srcpath += s->filename;
b2f73e
+	    }
b2f73e
+
b2f73e
+	  const struct bfd_build_id *build_id = build_id_bfd_shdr_get (ofp->obfd);
b2f73e
+
b2f73e
+	  /* Query debuginfod for the source file.  */
b2f73e
+	  if (build_id != nullptr)
b2f73e
+	    fd = debuginfod_source_query (build_id->data,
b2f73e
+					  build_id->size,
b2f73e
+					  srcpath.c_str (),
b2f73e
+					  &fullname);
b2f73e
+	}
b2f73e
+    }
b2f73e
+
b2f73e
   s->fullname = fullname.release ();
b2f73e
   return fd;
b2f73e
 }
b2f73e
diff --git a/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
b2f73e
new file mode 100644
b2f73e
--- /dev/null
b2f73e
+++ b/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
b2f73e
@@ -0,0 +1,214 @@
b2f73e
+# Copyright 2020 Free Software Foundation, Inc.
b2f73e
+
b2f73e
+# This program is free software; you can redistribute it and/or modify
b2f73e
+# it under the terms of the GNU General Public License as published by
b2f73e
+# the Free Software Foundation; either version 3 of the License, or
b2f73e
+# (at your option) any later version.
b2f73e
+#
b2f73e
+# This program is distributed in the hope that it will be useful,
b2f73e
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
b2f73e
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b2f73e
+# GNU General Public License for more details.
b2f73e
+#
b2f73e
+# You should have received a copy of the GNU General Public License
b2f73e
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
b2f73e
+
b2f73e
+# Test debuginfod functionality
b2f73e
+
b2f73e
+standard_testfile main.c
b2f73e
+
b2f73e
+load_lib dwarf.exp
b2f73e
+
b2f73e
+if { [which debuginfod] == 0 } {
b2f73e
+    untested "cannot find debuginfod"
b2f73e
+    return -1
b2f73e
+}
b2f73e
+
b2f73e
+if { [which curl] == 0 } {
b2f73e
+    untested "cannot find curl"
b2f73e
+    return -1
b2f73e
+}
b2f73e
+
b2f73e
+# Skip testing if gdb was not configured with debuginfod
b2f73e
+if { [string first "with-debuginfod" [exec $GDB --configuration]] == -1 } {
b2f73e
+    untested "gdb not configured with debuginfod"
b2f73e
+    return -1
b2f73e
+}
b2f73e
+
b2f73e
+set cache [standard_output_file ".client_cache"]
b2f73e
+set db [standard_output_file ".debuginfod.db"]
b2f73e
+
b2f73e
+# Delete any preexisting test files
b2f73e
+file delete -force $cache
b2f73e
+file delete -force $db
b2f73e
+
b2f73e
+set sourcetmp [standard_output_file tmp-${srcfile}]
b2f73e
+set outputdir [standard_output_file {}]
b2f73e
+
b2f73e
+# Make a copy source file that we can move around
b2f73e
+if { [catch {file copy -force ${srcdir}/${subdir}/${srcfile} \
b2f73e
+	     [standard_output_file ${sourcetmp}]}] != 0 } {
b2f73e
+    error "create temporary file"
b2f73e
+    return -1
b2f73e
+}
b2f73e
+
b2f73e
+if { [gdb_compile "$sourcetmp" "$binfile" executable {debug}] != "" } {
b2f73e
+    fail "compile"
b2f73e
+    return -1
b2f73e
+}
b2f73e
+
b2f73e
+setenv DEBUGINFOD_URLS ""
b2f73e
+setenv DEBUGINFOD_TIMEOUT 30
b2f73e
+setenv DEBUGINFOD_CACHE_PATH $cache
b2f73e
+
b2f73e
+# Test that gdb cannot find source without debuginfod
b2f73e
+clean_restart $binfile
b2f73e
+gdb_test_no_output "set substitute-path $outputdir /dev/null"
b2f73e
+gdb_test "list" ".*No such file or directory.*"
b2f73e
+
b2f73e
+# Strip symbols into separate file and move it so gdb cannot find it without debuginfod
b2f73e
+if { [gdb_gnu_strip_debug $binfile ""] != 0 } {
b2f73e
+    fail "strip debuginfo"
b2f73e
+    return -1
b2f73e
+}
b2f73e
+
b2f73e
+set debugdir [standard_output_file "debug"]
b2f73e
+set debuginfo [standard_output_file "fetch_src_and_symbols.debug"]
b2f73e
+
b2f73e
+file mkdir $debugdir
b2f73e
+file rename -force $debuginfo $debugdir
b2f73e
+
b2f73e
+# Test that gdb cannot find symbols without debuginfod
b2f73e
+clean_restart $binfile
b2f73e
+gdb_test "file" ".*No symbol file.*"
b2f73e
+
b2f73e
+# Write some assembly that just has a .gnu_debugaltlink section.
b2f73e
+# Copied from testsuite/gdb.dwarf2/dwzbuildid.exp.
b2f73e
+proc write_just_debugaltlink {filename dwzname buildid} {
b2f73e
+    set asm_file [standard_output_file $filename]
b2f73e
+
b2f73e
+    Dwarf::assemble $asm_file {
b2f73e
+	upvar dwzname dwzname
b2f73e
+	upvar buildid buildid
b2f73e
+
b2f73e
+	gnu_debugaltlink $dwzname $buildid
b2f73e
+
b2f73e
+	# Only the DWARF reader checks .gnu_debugaltlink, so make sure
b2f73e
+	# there is a bit of DWARF in here.
b2f73e
+	cu {} {
b2f73e
+	    compile_unit {{language @DW_LANG_C}} {
b2f73e
+	    }
b2f73e
+	}
b2f73e
+    }
b2f73e
+}
b2f73e
+
b2f73e
+# Write some DWARF that also sets the buildid.
b2f73e
+# Copied from testsuite/gdb.dwarf2/dwzbuildid.exp.
b2f73e
+proc write_dwarf_file {filename buildid {value 99}} {
b2f73e
+    set asm_file [standard_output_file $filename]
b2f73e
+
b2f73e
+    Dwarf::assemble $asm_file {
b2f73e
+	declare_labels int_label int_label2
b2f73e
+
b2f73e
+	upvar buildid buildid
b2f73e
+	upvar value value
b2f73e
+
b2f73e
+	build_id $buildid
b2f73e
+
b2f73e
+	cu {} {
b2f73e
+	    compile_unit {{language @DW_LANG_C}} {
b2f73e
+	        int_label2: base_type {
b2f73e
+		    {name int}
b2f73e
+		    {byte_size 4 sdata}
b2f73e
+		    {encoding @DW_ATE_signed}
b2f73e
+		}
b2f73e
+
b2f73e
+		constant {
b2f73e
+		    {name the_int}
b2f73e
+		    {type :$int_label2}
b2f73e
+		    {const_value $value data1}
b2f73e
+		}
b2f73e
+	    }
b2f73e
+	}
b2f73e
+    }
b2f73e
+}
b2f73e
+
b2f73e
+set buildid "01234567890abcdef0123456"
b2f73e
+
b2f73e
+write_just_debugaltlink ${binfile}_has_altlink.S ${binfile}_dwz.o $buildid
b2f73e
+write_dwarf_file ${binfile}_dwz.S $buildid
b2f73e
+
b2f73e
+if {[gdb_compile ${binfile}_has_altlink.S ${binfile}_alt.o object nodebug] != ""} {
b2f73e
+    fail "compile main with altlink"
b2f73e
+    return -1
b2f73e
+}
b2f73e
+
b2f73e
+if {[gdb_compile ${binfile}_dwz.S ${binfile}_dwz.o object nodebug] != ""} {
b2f73e
+    fail "compile altlink"
b2f73e
+    return -1
b2f73e
+}
b2f73e
+
b2f73e
+file rename -force ${binfile}_dwz.o $debugdir
b2f73e
+
b2f73e
+# Test that gdb cannot find dwz without debuginfod.
b2f73e
+clean_restart
b2f73e
+gdb_test "file ${binfile}_alt.o" ".*could not find '.gnu_debugaltlink'.*"
b2f73e
+
b2f73e
+# Find an unused port
b2f73e
+set port 7999
b2f73e
+set found 0
b2f73e
+while { ! $found } {
b2f73e
+  incr port
b2f73e
+  if { $port == 65536 } {
b2f73e
+    fail "no available ports"
b2f73e
+    return -1
b2f73e
+  }
b2f73e
+
b2f73e
+  spawn debuginfod -vvvv -d $db -p $port -F $debugdir
b2f73e
+  expect {
b2f73e
+    "started http server on IPv4 IPv6 port=$port" { set found 1 }
b2f73e
+    "failed to bind to port" { kill_wait_spawned_process $spawn_id }
b2f73e
+    timeout {
b2f73e
+      fail "find port timeout"
b2f73e
+      return -1
b2f73e
+    }
b2f73e
+  }
b2f73e
+}
b2f73e
+
b2f73e
+set metrics [list "ready 1" \
b2f73e
+	     "thread_work_total{role=\"traverse\"} 1" \
b2f73e
+	     "thread_work_pending{role=\"scan\"} 0" \
b2f73e
+	     "thread_busy{role=\"scan\"} 0"]
b2f73e
+
b2f73e
+# Check server metrics to confirm init has completed.
b2f73e
+foreach m $metrics {
b2f73e
+  set timelim 20
b2f73e
+  while { $timelim != 0 } {
b2f73e
+    sleep 0.5
b2f73e
+    catch {exec curl -s http://127.0.0.1:$port/metrics} got
b2f73e
+
b2f73e
+    if { [regexp $m $got] } {
b2f73e
+      break
b2f73e
+    }
b2f73e
+
b2f73e
+    incr timelim -1
b2f73e
+  }
b2f73e
+
b2f73e
+  if { $timelim == 0 } {
b2f73e
+    fail "server init timeout"
b2f73e
+    break
b2f73e
+  }
b2f73e
+}
b2f73e
+
b2f73e
+# Point the client to the server
b2f73e
+setenv DEBUGINFOD_URLS http://127.0.0.1:$port
b2f73e
+
b2f73e
+# gdb should now find the symbol and source files
b2f73e
+clean_restart $binfile
b2f73e
+gdb_test_no_output "set substitute-path $outputdir /dev/null"
b2f73e
+gdb_test "br main" "Breakpoint 1 at.*file.*"
b2f73e
+gdb_test "l" ".*This program is distributed in the hope.*"
b2f73e
+
b2f73e
+# gdb should now find the debugaltlink file
b2f73e
+clean_restart
b2f73e
+gdb_test "file ${binfile}_alt.o" ".*Reading symbols from ${binfile}_alt.o\.\.\.*"
b2f73e
diff --git a/gdb/testsuite/gdb.debuginfod/main.c b/gdb/testsuite/gdb.debuginfod/main.c
b2f73e
new file mode 100644
b2f73e
--- /dev/null
b2f73e
+++ b/gdb/testsuite/gdb.debuginfod/main.c
b2f73e
@@ -0,0 +1,25 @@
b2f73e
+/* This testcase is part of GDB, the GNU debugger.
b2f73e
+
b2f73e
+   Copyright 2020 Free Software Foundation, Inc.
b2f73e
+
b2f73e
+   This program is free software; you can redistribute it and/or modify
b2f73e
+   it under the terms of the GNU General Public License as published by
b2f73e
+   the Free Software Foundation; either version 3 of the License, or
b2f73e
+   (at your option) any later version.
b2f73e
+
b2f73e
+   This program is distributed in the hope that it will be useful,
b2f73e
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
b2f73e
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b2f73e
+   GNU General Public License for more details.
b2f73e
+
b2f73e
+   You should have received a copy of the GNU General Public License
b2f73e
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
b2f73e
+
b2f73e
+/* Dummy main function.  */
b2f73e
+
b2f73e
+int
b2f73e
+main()
b2f73e
+{
b2f73e
+  asm ("main_label: .globl main_label");
b2f73e
+  return 0;
b2f73e
+}
b2f73e
diff --git a/gdb/top.c b/gdb/top.c
b2f73e
--- a/gdb/top.c
b2f73e
+++ b/gdb/top.c
b2f73e
@@ -1513,6 +1513,17 @@ This GDB was configured as follows:\n\
b2f73e
              --without-python\n\
b2f73e
 "));
b2f73e
 #endif
b2f73e
+
b2f73e
+#if HAVE_LIBDEBUGINFOD
b2f73e
+  fprintf_filtered (stream, _("\
b2f73e
+             --with-debuginfod\n\
b2f73e
+"));
b2f73e
+#else
b2f73e
+   fprintf_filtered (stream, _("\
b2f73e
+             --without-debuginfod\n\
b2f73e
+"));
b2f73e
+#endif
b2f73e
+
b2f73e
 #if HAVE_GUILE
b2f73e
   fprintf_filtered (stream, _("\
b2f73e
              --with-guile\n\