Skip to content

Commit

Permalink
bcc_elf: add support for debug information from libdebuginfod
Browse files Browse the repository at this point in the history
This change adds debuginfod as a new source for debug
information. By using libdebuginfod we can query a server
for a file containing debug information for a given ELF
binary. The environment variable DEBUGINFOD_URLS has to
be defined to an URL for a debuginfod server providing
debug information files for your distribution or the
federating server provided by the elfutils project:

For example, to use the Fedora server, you would need:
$ export DEBUGINFOD_URLS="https://debuginfod.fedoraproject.org/"

Or for the elfutils server which federates to servers for
openSUSE, Void Linux, Debian and Fedora, among others:
$ export DEBUGINFOD_URLS="https://debuginfod.elfutils.org/"

Calls to the debuginfod_find_debuginfo function from
libdebuginfod will fail if the environment variable is not
set, otherwise the library will attempt to download debug
information for a build ID extracted from the binary in
question and store it in a local cache directory.

Fixes bpftrace/bpftrace#1774

Signed-off-by: Andreas Ziegler <[email protected]>
  • Loading branch information
rupran authored and yonghong-song committed May 9, 2021
1 parent 6e27192 commit 8ddbf3b
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ if(ENABLE_CLANG_JIT)
find_package(BISON)
find_package(FLEX)
find_package(LibElf REQUIRED)
find_package(LibDebuginfod)
if(CLANG_DIR)
set(CMAKE_FIND_ROOT_PATH "${CLANG_DIR}")
include_directories("${CLANG_DIR}/include")
Expand Down
55 changes: 55 additions & 0 deletions cmake/FindLibDebuginfod.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# - Try to find libdebuginfod
# Once done this will define
#
# LIBDEBUGINFOD_FOUND - system has libdebuginfod
# LIBDEBUGINFOD_INCLUDE_DIRS - the libdebuginfod include directory
# LIBDEBUGINFOD_LIBRARIES - Link these to use libdebuginfod
# LIBDEBUGINFOD_DEFINITIONS - Compiler switches required for using libdebuginfod


if (LIBDEBUGINFOD_LIBRARIES AND LIBDEBUGINFOD_INCLUDE_DIRS)
set (LibDebuginfod_FIND_QUIETLY TRUE)
endif (LIBDEBUGINFOD_LIBRARIES AND LIBDEBUGINFOD_INCLUDE_DIRS)

find_path (LIBDEBUGINFOD_INCLUDE_DIRS
NAMES
elfutils/debuginfod.h
PATHS
/usr/include
/usr/include/libelf
/usr/include/elfutils
/usr/local/include
/usr/local/include/libelf
/usr/local/include/elfutils
/opt/local/include
/opt/local/include/libelf
/opt/local/include/elfutils
/sw/include
/sw/include/libelf
/sw/include/elfutils
ENV CPATH)

find_library (LIBDEBUGINFOD_LIBRARIES
NAMES
debuginfod
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
ENV LIBRARY_PATH
ENV LD_LIBRARY_PATH)

include (FindPackageHandleStandardArgs)


# handle the QUIETLY and REQUIRED arguments and set LIBDEBUGINFOD_FOUND to TRUE if all listed variables are TRUE
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDebuginfod DEFAULT_MSG
LIBDEBUGINFOD_LIBRARIES
LIBDEBUGINFOD_INCLUDE_DIRS)

if (LIBDEBUGINFOD_FOUND)
add_definitions(-DHAVE_LIBDEBUGINFOD)
endif (LIBDEBUGINFOD_FOUND)

mark_as_advanced(LIBDEBUGINFOD_INCLUDE_DIRS LIBDEBUGINFOD_LIBRARIES)
6 changes: 6 additions & 0 deletions src/cc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frontends/b)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frontends/clang)
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${LIBELF_INCLUDE_DIRS})
if (LIBDEBUGINFOD_FOUND)
include_directories(${LIBDEBUGINFOD_INCLUDE_DIRS})
endif (LIBDEBUGINFOD_FOUND)
# todo: if check for kernel version
if (CMAKE_USE_LIBBPF_PACKAGE AND LIBBPF_FOUND)
include_directories(${LIBBPF_INCLUDE_DIRS})
Expand Down Expand Up @@ -116,6 +119,9 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${llvm_lib_exclude_f
set(bcc_common_libs b_frontend clang_frontend
-Wl,--whole-archive ${clang_libs} ${llvm_libs} -Wl,--no-whole-archive
${LIBELF_LIBRARIES})
if (LIBDEBUGINFOD_FOUND)
list(APPEND bcc_common_libs ${LIBDEBUGINFOD_LIBRARIES})
endif (LIBDEBUGINFOD_FOUND)
set(bcc_common_libs_for_a ${bcc_common_libs})
set(bcc_common_libs_for_s ${bcc_common_libs})
set(bcc_common_libs_for_lua b_frontend clang_frontend
Expand Down
32 changes: 32 additions & 0 deletions src/cc/bcc_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#ifdef HAVE_LIBDEBUGINFOD
#include <elfutils/debuginfod.h>
#endif

#include <gelf.h>
#include "bcc_elf.h"
Expand Down Expand Up @@ -621,6 +624,31 @@ static char *find_debug_via_symfs(Elf *e, const char* path) {
return result;
}

#ifdef HAVE_LIBDEBUGINFOD
static char *find_debug_via_debuginfod(Elf *e){
char buildid[128];
char *debugpath = NULL;
int fd = -1;

if (!find_buildid(e, buildid))
return NULL;

debuginfod_client *client = debuginfod_begin();
if (!client)
return NULL;

// In case of an error, the function returns a negative error code and
// debugpath stays NULL.
fd = debuginfod_find_debuginfo(client, (const unsigned char *) buildid, 0,
&debugpath);
if (fd >= 0)
close(fd);

debuginfod_end(client);
return debugpath;
}
#endif

static char *find_debug_file(Elf* e, const char* path, int check_crc) {
char *debug_file = NULL;

Expand All @@ -635,6 +663,10 @@ static char *find_debug_file(Elf* e, const char* path, int check_crc) {
debug_file = find_debug_via_buildid(e);
if (!debug_file)
debug_file = find_debug_via_debuglink(e, path, check_crc);
#ifdef HAVE_LIBDEBUGINFOD
if (!debug_file)
debug_file = find_debug_via_debuginfod(e);
#endif

return debug_file;
}
Expand Down

0 comments on commit 8ddbf3b

Please sign in to comment.