bcc_elf: add support for debug information from libdebuginfod
authorAndreas Ziegler <andreas.ziegler@fau.de>
Thu, 29 Apr 2021 10:18:40 +0000 (12:18 +0200)
committeryonghong-song <ys114321@gmail.com>
Sun, 9 May 2021 06:37:26 +0000 (23:37 -0700)
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 iovisor/bpftrace#1774

Signed-off-by: Andreas Ziegler <andreas.ziegler@fau.de>
CMakeLists.txt
cmake/FindLibDebuginfod.cmake [new file with mode: 0644]
src/cc/CMakeLists.txt
src/cc/bcc_elf.c

index 720969147241a5bb1f0c147afb41eb47bf438120..09707b1f51132460dc568c6b74f9f4027fcf7244 100644 (file)
@@ -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")
diff --git a/cmake/FindLibDebuginfod.cmake b/cmake/FindLibDebuginfod.cmake
new file mode 100644 (file)
index 0000000..df79ce9
--- /dev/null
@@ -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)
index 931de2d9674ce2dabde98c256843ad74767aef51..09e5218b1a4ef051ddc0bbb2831f2248d4a78127 100644 (file)
@@ -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})
@@ -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
index 7459bfa18b33533c36deafe7e1b4f6a418f1471c..e2909d7c92d9a869d6993147e38532fb8b282917 100644 (file)
@@ -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"
@@ -621,6 +624,31 @@ out:
   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;
 
@@ -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;
 }