mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
12 Commits
gdb-11.2-r
...
users/amer
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
638d40988a | ||
|
|
02b0255c7d | ||
|
|
3e7611cfe2 | ||
|
|
70eb9acb8b | ||
|
|
6c29562bea | ||
|
|
1cbbbf89e1 | ||
|
|
59a48afbda | ||
|
|
bb580a3ff6 | ||
|
|
4aac9827d7 | ||
|
|
c63e72b013 | ||
|
|
f7d53a9054 | ||
|
|
7d33860d1d |
@@ -616,7 +616,8 @@ CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(LIBCTF) $(ZLIB) \
|
||||
@LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
|
||||
$(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
|
||||
$(WIN32LIBS) $(LIBGNU) $(LIBICONV) \
|
||||
$(LIBMPFR) $(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS)
|
||||
$(LIBMPFR) $(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS) \
|
||||
@LIBDEBUGINFOD@
|
||||
CDEPS = $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) $(LIBCTF) \
|
||||
$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU) \
|
||||
$(LIBSUPPORT)
|
||||
@@ -990,6 +991,7 @@ COMMON_SFILES = \
|
||||
dbxread.c \
|
||||
dcache.c \
|
||||
debug.c \
|
||||
debuginfod-support.c \
|
||||
dictionary.c \
|
||||
disasm.c \
|
||||
disasm-selftests.c \
|
||||
|
||||
14
gdb/NEWS
14
gdb/NEWS
@@ -3,6 +3,20 @@
|
||||
|
||||
*** Changes since GDB 9
|
||||
|
||||
* 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.
|
||||
|
||||
* Debugging MS-Windows processes now sets $_exitsignal when the
|
||||
inferior is terminated by a signal, instead of setting $_exitcode.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -227,6 +227,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
|
||||
|
||||
|
||||
182
gdb/configure
vendored
182
gdb/configure
vendored
@@ -758,6 +758,7 @@ REPORT_BUGS_TEXI
|
||||
REPORT_BUGS_TO
|
||||
PKGVERSION
|
||||
CODESIGN_CERT
|
||||
LIBDEBUGINFOD
|
||||
HAVE_NATIVE_GCORE_TARGET
|
||||
TARGET_OBS
|
||||
subdirs
|
||||
@@ -869,6 +870,7 @@ enable_64_bit_bfd
|
||||
enable_gdbmi
|
||||
enable_tui
|
||||
enable_gdbtk
|
||||
with_debuginfod
|
||||
with_libunwind_ia64
|
||||
with_curses
|
||||
enable_profiling
|
||||
@@ -1598,6 +1600,8 @@ Optional Packages:
|
||||
[--with-auto-load-dir]
|
||||
--without-auto-load-safe-path
|
||||
do not restrict auto-loaded files locations
|
||||
--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
|
||||
@@ -2251,6 +2255,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
|
||||
@@ -2372,52 +2422,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_c_check_member LINENO AGGR MEMBER VAR INCLUDES
|
||||
# ----------------------------------------------------
|
||||
# Tries to find if the field MEMBER exists in type AGGR, after including
|
||||
@@ -6824,8 +6828,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 :
|
||||
|
||||
@@ -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
|
||||
@@ -323,8 +325,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]),,
|
||||
|
||||
150
gdb/debuginfod-support.c
Normal file
150
gdb/debuginfod-support.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/* 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 <errno.h>
|
||||
#include "defs.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 const char *fname;
|
||||
static bool has_printed;
|
||||
|
||||
static int
|
||||
progressfn (debuginfod_client *c, long cur, long total)
|
||||
{
|
||||
if (check_quit_flag ())
|
||||
{
|
||||
printf_unfiltered ("Cancelling download of %ps...\n",
|
||||
styled_string (file_name_style.style (), fname));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!has_printed && total != 0)
|
||||
{
|
||||
/* Print this message only once. */
|
||||
has_printed = true;
|
||||
printf_unfiltered ("Debuginfod downloading %ps...\n",
|
||||
styled_string (file_name_style.style (), fname));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
fname = 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"),
|
||||
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);
|
||||
|
||||
fname = 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"),
|
||||
strerror (-fd.get ()),
|
||||
styled_string (file_name_style.style (), filename));
|
||||
|
||||
destname->reset (dname);
|
||||
debuginfod_end (c);
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
59
gdb/debuginfod-support.h
Normal file
59
gdb/debuginfod-support.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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 FILENAME. 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 debuginfo 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.
|
||||
|
||||
If the file is successfully retrieved, its path on the local machine
|
||||
is stored in FILENAME. 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 */
|
||||
@@ -37794,6 +37794,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
|
||||
|
||||
@@ -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.
|
||||
@@ -2746,6 +2747,29 @@ dwarf2_get_dwz_file (struct dwarf2_per_objfile *dwarf2_per_objfile)
|
||||
if (dwz_bfd == NULL)
|
||||
dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
|
||||
|
||||
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)
|
||||
error (_("could not find '.gnu_debugaltlink' file for %s"),
|
||||
objfile_name (dwarf2_per_objfile->objfile));
|
||||
|
||||
@@ -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;
|
||||
@@ -1316,8 +1318,36 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
|
||||
symbol_file_add_separate (debug_bfd.get (), debugfile.c_str (),
|
||||
symfile_flags, objfile);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
has_dwarf2 = false;
|
||||
const struct bfd_build_id *build_id = build_id_bfd_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the CTF section only if there is no DWARF info. */
|
||||
|
||||
30
gdb/source.c
30
gdb/source.c
@@ -48,6 +48,8 @@
|
||||
#include "source-cache.h"
|
||||
#include "cli/cli-style.h"
|
||||
#include "observable.h"
|
||||
#include "build-id.h"
|
||||
#include "debuginfod-support.h"
|
||||
|
||||
#define OPEN_MODE (O_RDONLY | O_BINARY)
|
||||
#define FDOPEN_MODE FOPEN_RB
|
||||
@@ -1153,6 +1155,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
|
||||
{
|
||||
srcpath = SYMTAB_DIRNAME (s);
|
||||
srcpath += SLASH_STRING;
|
||||
srcpath += s->filename;
|
||||
}
|
||||
|
||||
const struct bfd_build_id *build_id = build_id_bfd_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;
|
||||
}
|
||||
|
||||
214
gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
Normal file
214
gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
Normal file
@@ -0,0 +1,214 @@
|
||||
# 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" [exec $GDB --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
|
||||
}
|
||||
|
||||
setenv DEBUGINFOD_URLS ""
|
||||
setenv DEBUGINFOD_TIMEOUT 30
|
||||
setenv DEBUGINFOD_CACHE_PATH $cache
|
||||
|
||||
# Test that gdb cannot find source without debuginfod
|
||||
clean_restart $binfile
|
||||
gdb_test_no_output "set substitute-path $outputdir /dev/null"
|
||||
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.*"
|
||||
|
||||
# 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}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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'.*"
|
||||
|
||||
# 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"
|
||||
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\.\.\.*"
|
||||
25
gdb/testsuite/gdb.debuginfod/main.c
Normal file
25
gdb/testsuite/gdb.debuginfod/main.c
Normal file
@@ -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;
|
||||
}
|
||||
10
gdb/top.c
10
gdb/top.c
@@ -1528,6 +1528,16 @@ This GDB was configured as follows:\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\
|
||||
|
||||
Reference in New Issue
Block a user