Blame SOURCES/gdb-rhbz1838777-debuginfod.patch

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