Add support for debuginfod to the binutils (disable by default, enabled via a configure time option).

debuginfod is a lightweight web service that indexes ELF/DWARF
debugging resources by build-id and serves them over HTTP. This patch
enables objdump and readelf to query debuginfod servers when they are
otherwise not able to find separate debug files. Binutils 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/.

toplevel* config/debuginfod.m4: New file. Add macro AC_DEBUGINFOD. Adds
        new configure option --with-debuginfod.
        * configure: Regenerate.
        * configure.ac: Call AC_DEBUGINFOD.

binutils* Makefile.am (readelf_LDADD, objdump_LDADD): Add libdebuginfod.
        * Makefile.in: Regenerate.
        * NEWS: Update.
        * config.in: Regenerate.
        * configure: Regenerate.
        * configure.ac: Call AC_DEBUGINFOD.
        * doc/Makefile.in: Regenerate.
        * doc/binutils.texi: Add section on using binutils
        with debuginfod.
        * dwarf.c (debuginfod_fetch_separate_debug_info): New function.
        Query debuginfod servers for the target debug file.
        (load_separate_debug_info): Call
        debuginfod_fetch_separate_debug_info if configured with
        debuginfod.
        (load_separate_debug_files): Add file argument to
        load_separate_debug_info calls.
        * dwarf.h (get_build_id): Add declaration.
        * objdump.c (get_build_id): New function. Get build-id of file.
        * readelf.c (get_build_id): Likewise.
        * testsuite/binutils-all/debuginfod.exp: New tests.
        * testsuite/binutils-all/linkdebug.s: Add .note.gnu.build-id
        section.
This commit is contained in:
Aaron Merey 2020-01-09 13:19:20 +00:00 committed by Nick Clifton
parent 40c75bc8b0
commit 301a9420d9
16 changed files with 647 additions and 61 deletions

View File

@ -53,6 +53,8 @@ AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC)
LIBICONV = @LIBICONV@
LIBDEBUGINFOD = @LIBDEBUGINFOD@
# these two are almost the same program
AR_PROG=ar
RANLIB_PROG=ranlib
@ -245,7 +247,7 @@ objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
strings_SOURCES = strings.c $(BULIBS)
readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS)
readelf_LDADD = $(LIBINTL) $(LIBCTF_NOBFD) $(LIBIBERTY) $(ZLIB)
readelf_LDADD = $(LIBINTL) $(LIBCTF_NOBFD) $(LIBIBERTY) $(ZLIB) $(LIBDEBUGINFOD)
elfedit_SOURCES = elfedit.c version.c $(ELFLIBS)
elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
@ -256,7 +258,7 @@ nm_new_SOURCES = nm.c $(BULIBS)
objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS)
EXTRA_objdump_SOURCES = od-xcoff.c
objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) $(LIBDEBUGINFOD)
objdump.@OBJEXT@:objdump.c
if am__fastdepCC

View File

@ -138,7 +138,9 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
$(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \
$(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
$(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac
$(top_srcdir)/../bfd/version.m4 \
$(top_srcdir)/../config/debuginfod.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
@ -449,6 +451,7 @@ LDFLAGS = @LDFLAGS@
LEX = `if [ -f ../flex/flex ]; then echo ../flex/flex; else echo @LEX@; fi`
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBDEBUGINFOD = @LIBDEBUGINFOD@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBINTL_DEP = @LIBINTL_DEP@
@ -706,14 +709,14 @@ size_SOURCES = size.c $(BULIBS)
objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
strings_SOURCES = strings.c $(BULIBS)
readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS)
readelf_LDADD = $(LIBINTL) $(LIBCTF_NOBFD) $(LIBIBERTY) $(ZLIB)
readelf_LDADD = $(LIBINTL) $(LIBCTF_NOBFD) $(LIBIBERTY) $(ZLIB) $(LIBDEBUGINFOD)
elfedit_SOURCES = elfedit.c version.c $(ELFLIBS)
elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
nm_new_SOURCES = nm.c $(BULIBS)
objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS)
EXTRA_objdump_SOURCES = od-xcoff.c
objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) $(LIBDEBUGINFOD)
cxxfilt_SOURCES = cxxfilt.c $(BULIBS)
ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c binemul.c \
emul_$(EMULATION).c $(BULIBS)

View File

@ -1,5 +1,14 @@
-*- text -*-
* Binutils now supports debuginfod, an HTTP server for distributing
ELF/DWARF debugging information as well as source code. When built with
debuginfod, readelf and objdump can automatically query debuginfod
servers for separate debug files when they otherwise cannot be found.
To build binutils with debuginfod, pass --with-debuginfod to configure.
This requires libdebuginfod, the debuginfod client library. debuginfod
is distributed with elfutils, starting with version 0.178. For more
information see https://sourceware.org/elfutils.
* Add --output option to the "ar" program. This option can be used to specify
the output directory when extracting members from an archive.

View File

@ -109,6 +109,9 @@
/* Define if your <locale.h> file defines LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define to 1 if debuginfod is enabled. */
#undef HAVE_LIBDEBUGINFOD
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H

184
binutils/configure vendored
View File

@ -684,6 +684,7 @@ WARN_WRITE_STRINGS
NO_WERROR
WARN_CFLAGS_FOR_BUILD
WARN_CFLAGS
LIBDEBUGINFOD
OTOOL64
OTOOL
LIPO
@ -813,6 +814,7 @@ enable_largefile
enable_targets
enable_deterministic_archives
enable_default_strings_all
with_debuginfod
enable_werror
enable_build_warnings
enable_nls
@ -1483,6 +1485,8 @@ Optional Packages:
--with-pic try to use only PIC/non-PIC objects [default=use
both]
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-debuginfod Enable debuginfo lookups with debuginfod
(auto/yes/no)
--with-system-zlib use installed libz
--with-gnu-ld assume the C compiler uses GNU ld default=no
--with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
@ -1932,6 +1936,52 @@ $as_echo "$ac_res" >&6; }
} # ac_fn_c_check_func
# 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_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
@ -2168,52 +2218,6 @@ $as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # 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
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
@ -11523,7 +11527,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11526 "configure"
#line 11530 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -11629,7 +11633,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11632 "configure"
#line 11636 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -12236,6 +12240,90 @@ fi
# 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
cat >>confdefs.h <<_ACEOF
#define DEFAULT_STRINGS_ALL $default_strings_all
_ACEOF

View File

@ -18,6 +18,7 @@ dnl <http://www.gnu.org/licenses/>.
dnl
m4_include([../bfd/version.m4])
m4_include([../config/debuginfod.m4])
AC_INIT([binutils], BFD_VERSION)
AC_CONFIG_SRCDIR(ar.c)
@ -63,6 +64,8 @@ else
default_strings_all=1
fi], [default_strings_all=1])
AC_DEBUGINFOD
AC_DEFINE_UNQUOTED(DEFAULT_STRINGS_ALL, $default_strings_all,
[Should strings use -a behavior by default?])

View File

@ -127,7 +127,9 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
$(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \
$(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
$(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac
$(top_srcdir)/../bfd/version.m4 \
$(top_srcdir)/../config/debuginfod.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@ -284,6 +286,7 @@ LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBDEBUGINFOD = @LIBDEBUGINFOD@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBINTL_DEP = @LIBINTL_DEP@

View File

@ -154,6 +154,7 @@ in the section entitled ``GNU Free Documentation License''.
* elfedit:: Update ELF header and property of ELF files
* Common Options:: Command-line options for all utilities
* Selecting the Target System:: How these utilities determine the target
* debuginfod:: Using binutils with debuginfod
* Reporting Bugs:: Reporting Bugs
* GNU Free Documentation License:: GNU Free Documentation License
* Binutils Index:: Binutils Index
@ -5201,6 +5202,23 @@ Ways to specify:
deduced from the input file
@end enumerate
@node debuginfod
@chapter debuginfod
@cindex separate debug files
debuginfod is a web service that indexes ELF/DWARF debugging resources
by build-id and serves them over HTTP.
Binutils can be built with the debuginfod client library
@code{libdebuginfod} using the @option{--with-debuginfod} configure option.
This option is enabled by default if @code{libdebuginfod} is installed
and found at configure time. This allows @command{objdump} and
@command{readelf} to automatically query debuginfod servers for
separate debug files when the files are otherwise not found.
debuginfod is packaged with elfutils, starting with version 0.178.
You can get the latest version from `https://sourceware.org/elfutils/'.
@node Reporting Bugs
@chapter Reporting Bugs
@cindex bugs

View File

@ -32,6 +32,10 @@
#include "safe-ctype.h"
#include <assert.h>
#ifdef HAVE_LIBDEBUGINFOD
#include <elfutils/debuginfod.h>
#endif
#undef MAX
#undef MIN
#define MAX(a, b) ((a) > (b) ? (a) : (b))
@ -10128,12 +10132,83 @@ add_separate_debug_file (const char * filename, void * handle)
first_separate_info = i;
}
#if HAVE_LIBDEBUGINFOD
/* Query debuginfod servers for the target debuglink or debugaltlink
file. If successful, store the path of the file in filename and
return TRUE, otherwise return FALSE. */
static bfd_boolean
debuginfod_fetch_separate_debug_info (struct dwarf_section * section,
char ** filename,
void * file)
{
size_t build_id_len;
unsigned char * build_id;
if (strcmp (section->uncompressed_name, ".gnu_debuglink") == 0)
{
/* Get the build-id of file. */
build_id = get_build_id (file);
build_id_len = 0;
}
else if (strcmp (section->uncompressed_name, ".gnu_debugaltlink") == 0)
{
/* Get the build-id of the debugaltlink file. */
unsigned int filelen;
filelen = strnlen ((const char *)section->start, section->size);
if (filelen == section->size)
/* Corrupt debugaltlink. */
return FALSE;
build_id = section->start + filelen + 1;
build_id_len = section->size - (filelen + 1);
if (build_id_len == 0)
return FALSE;
}
else
return FALSE;
if (build_id)
{
int fd;
debuginfod_client * client;
client = debuginfod_begin ();
if (client == NULL)
return FALSE;
/* Query debuginfod servers for the target file. If found its path
will be stored in filename. */
fd = debuginfod_find_debuginfo (client, build_id, build_id_len, filename);
debuginfod_end (client);
/* Only free build_id if we allocated space for a hex string
in get_build_id (). */
if (build_id_len == 0)
free (build_id);
if (fd >= 0)
{
/* File successfully retrieved. Close fd since we want to
use open_debug_file () on filename instead. */
close (fd);
return TRUE;
}
}
return FALSE;
}
#endif
static void *
load_separate_debug_info (const char * main_filename,
struct dwarf_section * xlink,
parse_func_type parse_func,
check_func_type check_func,
void * func_data)
void * func_data,
void * file ATTRIBUTE_UNUSED)
{
const char * separate_filename;
char * debug_filename;
@ -10235,6 +10310,23 @@ load_separate_debug_info (const char * main_filename,
if (check_func (debug_filename, func_data))
goto found;
#if HAVE_LIBDEBUGINFOD
{
char * tmp_filename;
if (debuginfod_fetch_separate_debug_info (xlink,
& tmp_filename,
file))
{
/* File successfully downloaded from server, replace
debug_filename with the file's path. */
free (debug_filename);
debug_filename = tmp_filename;
goto found;
}
}
#endif
/* Failed to find the file. */
warn (_("could not find separate debug file '%s'\n"), separate_filename);
warn (_("tried: %s\n"), debug_filename);
@ -10264,6 +10356,16 @@ load_separate_debug_info (const char * main_filename,
sprintf (debug_filename, "%s", separate_filename);
warn (_("tried: %s\n"), debug_filename);
#if HAVE_LIBDEBUGINFOD
{
char *urls = getenv (DEBUGINFOD_URLS_ENV_VAR);
if (urls == NULL)
urls = "";
warn (_("tried: DEBUGINFOD_URLS=%s\n"), urls);
}
#endif
free (canon_dir);
free (debug_filename);
return NULL;
@ -10410,7 +10512,8 @@ load_separate_debug_files (void * file, const char * filename)
& debug_displays[gnu_debugaltlink].section,
parse_gnu_debugaltlink,
check_gnu_debugaltlink,
& build_id_data);
& build_id_data,
file);
}
if (load_debug_section (gnu_debuglink, file))
@ -10421,7 +10524,8 @@ load_separate_debug_files (void * file, const char * filename)
& debug_displays[gnu_debuglink].section,
parse_gnu_debuglink,
check_gnu_debuglink,
& crc32);
& crc32,
file);
}
if (first_separate_info != NULL)

View File

@ -256,6 +256,10 @@ extern bfd_boolean reloc_at (struct dwarf_section *, dwarf_vma);
extern dwarf_vma read_leb128 (unsigned char *, const unsigned char *const,
bfd_boolean, unsigned int *, int *);
#if HAVE_LIBDEBUGINFOD
extern unsigned char * get_build_id (void *);
#endif
static inline void
report_leb_status (int status)
{

View File

@ -2945,6 +2945,33 @@ open_debug_file (const char * pathname)
return data;
}
#if HAVE_LIBDEBUGINFOD
/* Return a hex string represention of the build-id. */
unsigned char *
get_build_id (void * data)
{
unsigned i;
char * build_id_str;
bfd * abfd = (bfd *) data;
const struct bfd_build_id * build_id;
build_id = abfd->build_id;
if (build_id == NULL)
return NULL;
build_id_str = malloc (build_id->size * 2 + 1);
if (build_id_str == NULL)
return NULL;
for (i = 0; i < build_id->size; i++)
sprintf (build_id_str + (i * 2), "%02x", build_id->data[i]);
build_id_str[build_id->size * 2] = '\0';
return (unsigned char *)build_id_str;
}
#endif /* HAVE_LIBDEBUGINFOD */
static void
dump_dwarf_section (bfd *abfd, asection *section,
void *arg ATTRIBUTE_UNUSED)

View File

@ -14194,6 +14194,138 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
return TRUE;
}
#if HAVE_LIBDEBUGINFOD
/* Return a hex string representation of the build-id. */
unsigned char *
get_build_id (void * data)
{
Filedata * filedata = (Filedata *)data;
Elf_Internal_Shdr * shdr;
unsigned long i;
/* Iterate through notes to find note.gnu.build-id. */
for (i = 0, shdr = filedata->section_headers;
i < filedata->file_header.e_shnum && shdr != NULL;
i++, shdr++)
{
if (shdr->sh_type != SHT_NOTE)
continue;
char * next;
char * end;
size_t data_remaining;
size_t min_notesz;
Elf_External_Note * enote;
Elf_Internal_Note inote;
bfd_vma offset = shdr->sh_offset;
bfd_vma align = shdr->sh_addralign;
bfd_vma length = shdr->sh_size;
enote = (Elf_External_Note *) get_section_contents (shdr, filedata);
if (enote == NULL)
continue;
if (align < 4)
align = 4;
else if (align != 4 && align != 8)
continue;
end = (char *) enote + length;
data_remaining = end - (char *) enote;
if (!is_ia64_vms (filedata))
{
min_notesz = offsetof (Elf_External_Note, name);
if (data_remaining < min_notesz)
{
warn (ngettext ("debuginfod: Corrupt note: only %ld byte remains, "
"not enough for a full note\n",
"Corrupt note: only %ld bytes remain, "
"not enough for a full note\n",
data_remaining),
(long) data_remaining);
break;
}
data_remaining -= min_notesz;
inote.type = BYTE_GET (enote->type);
inote.namesz = BYTE_GET (enote->namesz);
inote.namedata = enote->name;
inote.descsz = BYTE_GET (enote->descsz);
inote.descdata = ((char *) enote
+ ELF_NOTE_DESC_OFFSET (inote.namesz, align));
inote.descpos = offset + (inote.descdata - (char *) enote);
next = ((char *) enote
+ ELF_NOTE_NEXT_OFFSET (inote.namesz, inote.descsz, align));
}
else
{
Elf64_External_VMS_Note *vms_enote;
/* PR binutils/15191
Make sure that there is enough data to read. */
min_notesz = offsetof (Elf64_External_VMS_Note, name);
if (data_remaining < min_notesz)
{
warn (ngettext ("debuginfod: Corrupt note: only %ld byte remains, "
"not enough for a full note\n",
"Corrupt note: only %ld bytes remain, "
"not enough for a full note\n",
data_remaining),
(long) data_remaining);
break;
}
data_remaining -= min_notesz;
vms_enote = (Elf64_External_VMS_Note *) enote;
inote.type = BYTE_GET (vms_enote->type);
inote.namesz = BYTE_GET (vms_enote->namesz);
inote.namedata = vms_enote->name;
inote.descsz = BYTE_GET (vms_enote->descsz);
inote.descdata = inote.namedata + align_power (inote.namesz, 3);
inote.descpos = offset + (inote.descdata - (char *) enote);
next = inote.descdata + align_power (inote.descsz, 3);
}
/* Skip malformed notes. */
if ((size_t) (inote.descdata - inote.namedata) < inote.namesz
|| (size_t) (inote.descdata - inote.namedata) > data_remaining
|| (size_t) (next - inote.descdata) < inote.descsz
|| ((size_t) (next - inote.descdata)
> data_remaining - (size_t) (inote.descdata - inote.namedata)))
{
warn (_("debuginfod: note with invalid namesz and/or descsz found\n"));
warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx, alignment: %u\n"),
inote.type, inote.namesz, inote.descsz, (int) align);
continue;
}
/* Check if this is the build-id note. If so then convert the build-id
bytes to a hex string. */
if (inote.namesz > 0
&& const_strneq (inote.namedata, "GNU")
&& inote.type == NT_GNU_BUILD_ID)
{
unsigned long j;
char * build_id;
build_id = malloc (inote.descsz * 2 + 1);
if (build_id == NULL)
return NULL;
for (j = 0; j < inote.descsz; ++j)
sprintf (build_id + (j * 2), "%02x", inote.descdata[j] & 0xff);
build_id[inote.descsz * 2] = '\0';
return (unsigned char *)build_id;
}
}
return NULL;
}
#endif /* HAVE_LIBDEBUGINFOD */
/* If this is not NULL, load_debug_section will only look for sections
within the list of sections given here. */
static unsigned int * section_subset = NULL;

View File

@ -18,9 +18,22 @@
/* This is the separate debug info file. */
/* Create a .debug_abbrev section for use by the .debug_info section
/* Create .note.gnu.build-id note for use by the .gnu_debugaltlink
in the main object file. */
.section .note.gnu.build-id,"a",%note
.balign 4
.dc.l 0x04 ;# Name size
.dc.l 0x18 ;# Description size
.dc.l 0x03 ;# Type
.asciz "GNU" ;# Name
.dc.b 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
.dc.b 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
.dc.b 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
/* Create a .debug_abbrev section for use by the .debug_info section
in the main object file. */
.section .debug_abbrev,"",%progbits
abbrevs:
.uleb128 0x01 ;# Abbrev code.

38
config/debuginfod.m4 Normal file
View File

@ -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
])

139
configure vendored
View File

@ -690,6 +690,7 @@ extra_mpc_gmp_configure_flags
extra_mpfr_configure_flags
gmpinc
gmplibs
LIBDEBUGINFOD
do_compare
GNATMAKE
GNATBIND
@ -790,6 +791,7 @@ enable_libssp
enable_libstdcxx
enable_liboffloadmic
enable_bootstrap
with_debuginfod
with_mpc
with_mpc_include
with_mpc_lib
@ -1553,6 +1555,8 @@ Optional Packages:
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-build-libsubdir=DIR Directory where to find libraries for build system
--with-system-zlib use installed libz
--with-debuginfod Enable debuginfo lookups with debuginfod
(auto/yes/no)
--with-mpc=PATH specify prefix directory for installed MPC package.
Equivalent to --with-mpc-include=PATH/include plus
--with-mpc-lib=PATH/lib
@ -1921,6 +1925,52 @@ fi
as_fn_set_status $ac_retval
} # ac_fn_c_try_link
# 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
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
@ -5433,6 +5483,92 @@ gmplibs="-lmpc -lmpfr -lgmp"
gmpinc=
have_gmp=no
# Check for debuginfod
# 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
# Specify a location for mpc
# check for this first so it ends up on the link line before mpfr.
@ -5587,8 +5723,7 @@ if test -d ${srcdir}/gcc && test "x$have_gmp" = xno; then
# Check for the recommended and required versions of GMP.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the correct version of gmp.h" >&5
$as_echo_n "checking for the correct version of gmp.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include "gmp.h"
int

View File

@ -23,6 +23,7 @@ m4_include(config/acx.m4)
m4_include(config/override.m4)
m4_include(config/proginstall.m4)
m4_include(config/elf.m4)
m4_include(config/debuginfod.m4)
m4_include([libtool.m4])
m4_include([ltoptions.m4])
m4_include([ltsugar.m4])
@ -1363,6 +1364,9 @@ gmplibs="-lmpc -lmpfr -lgmp"
gmpinc=
have_gmp=no
# Check for debuginfod
AC_DEBUGINFOD
# Specify a location for mpc
# check for this first so it ends up on the link line before mpfr.
AC_ARG_WITH(mpc,