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