Blame SOURCES/dyninst-10.2.1-dbid.patch

46998e
Debuginfod is a lightweight web service that indexes ELF/DWARF debugging
46998e
resources by build-id and serves them over HTTP.
46998e
46998e
This patch enables dyninst to query debuginfod servers for a file's
46998e
separate debuginfo when it otherwise cannot be found.
46998e
46998e
This patch also adds a cmake option -DENABLE_DEBUGINFOD to control
46998e
whether dyninst is built with debuginfod support.
46998e
46998e
This requires having the debuginfod client library (libdebuginfod)
46998e
and header installed.
46998e
46998e
Debuginfod is distributed with elfutils, for more information see
46998e
https://sourceware.org/elfutils/Debuginfod.html
46998e
---
46998e
 cmake/ElfUtils.cmake                  | 37 ++++++++---
46998e
 cmake/Modules/FindLibDebuginfod.cmake | 76 +++++++++++++++++++++
46998e
 cmake/options.cmake                   |  2 +
46998e
 elf/CMakeLists.txt                    |  3 +
46998e
 elf/src/Elf_X.C                       | 95 ++++++++++++++++++++-------
46998e
 5 files changed, 178 insertions(+), 35 deletions(-)
46998e
 create mode 100644 cmake/Modules/FindLibDebuginfod.cmake
46998e
46998e
--- dyninst-10.2.1/dyninst-10.2.1/cmake/ElfUtils.cmake
46998e
+++ dyninst-10.2.1/dyninst-10.2.1/cmake/ElfUtils.cmake
46998e
@@ -28,7 +28,7 @@
46998e
 #
46998e
 #======================================================================================
46998e
 
46998e
-if(LibElf_FOUND AND LibDwarf_FOUND)
46998e
+if(LibElf_FOUND AND LibDwarf_FOUND AND (LibDebuginfod_FOUND OR NOT ENABLE_DEBUGINFOD))
46998e
   return()
46998e
 endif()
46998e
 
46998e
@@ -37,7 +37,12 @@ if(NOT UNIX)
46998e
 endif()
46998e
 
46998e
 # Minimum acceptable version of elfutils
46998e
-set(_min_version 0.178)
46998e
+if(ENABLE_DEBUGINFOD)
46998e
+  set(_min_version 0.179)
46998e
+else()
46998e
+  set(_min_version 0.178)
46998e
+endif()
46998e
+
46998e
 set(ElfUtils_MIN_VERSION ${_min_version}
46998e
     CACHE STRING "Minimum acceptable elfutils version")
46998e
 if(${ElfUtils_MIN_VERSION} VERSION_LESS ${_min_version})
46998e
@@ -62,7 +67,7 @@ set(ElfUtils_LIBRARYDIR "${ElfUtils_ROOT_DIR}/lib"
46998e
     CACHE PATH "Hint directory that contains the elfutils library files")
46998e
 
46998e
 # libelf/dwarf-specific directory hints
46998e
-foreach(l LibElf LibDwarf)
46998e
+foreach(l LibElf LibDwarf LibDebuginfod)
46998e
   foreach(d ROOT_DIR INCLUDEDIR LIBRARYDIR)
46998e
     set(${l}_${d} ${ElfUtils_${d}})
46998e
   endforeach()
46998e
@@ -72,18 +77,30 @@ endforeach()
46998e
 
46998e
 find_package(LibElf ${ElfUtils_MIN_VERSION})
46998e
 
46998e
-# Don't search for libdw if we didn't find a suitable libelf
46998e
+# Don't search for libdw or libdebuginfod if we didn't find a suitable libelf
46998e
 if(LibElf_FOUND)
46998e
   find_package(LibDwarf ${ElfUtils_MIN_VERSION})
46998e
+  if (ENABLE_DEBUGINFOD)
46998e
+    find_package(LibDebuginfod ${ElfUtils_MIN_VERSION})
46998e
+  endif()
46998e
 endif()
46998e
 
46998e
 # -------------- SOURCE BUILD -------------------------------------------------
46998e
-if(LibElf_FOUND AND LibDwarf_FOUND)
46998e
-  set(_eu_root ${ElfUtils_ROOT_DIR})
46998e
-  set(_eu_inc_dirs ${LibElf_INCLUDE_DIRS} ${LibDwarf_INCLUDE_DIRS})
46998e
-  set(_eu_lib_dirs ${LibElf_LIBRARY_DIRS} ${LibDwarf_LIBRARY_DIRS})
46998e
-  set(_eu_libs ${LibElf_LIBRARIES} ${LibDwarf_LIBRARIES})
46998e
+if(LibElf_FOUND AND LibDwarf_FOUND AND (NOT ENABLE_DEBUGINFOD OR LibDebuginfod_FOUND))
46998e
+  if(ENABLE_DEBUGINFOD AND LibDebuginfod_FOUND)
46998e
+    set(_eu_root ${ElfUtils_ROOT_DIR})
46998e
+    set(_eu_inc_dirs ${LibElf_INCLUDE_DIRS} ${LibDwarf_INCLUDE_DIRS} ${LibDebuginfod_INCLUDE_DIRS})
46998e
+    set(_eu_lib_dirs ${LibElf_LIBRARY_DIRS} ${LibDwarf_LIBRARY_DIRS} ${LibDebuginfod_LIBRARY_DIRS})
46998e
+    set(_eu_libs ${LibElf_LIBRARIES} ${LibDwarf_LIBRARIES} ${LibDebuginfod_LIBRARIES})
46998e
+  else()
46998e
+    set(_eu_root ${ElfUtils_ROOT_DIR})
46998e
+    set(_eu_inc_dirs ${LibElf_INCLUDE_DIRS} ${LibDwarf_INCLUDE_DIRS})
46998e
+    set(_eu_lib_dirs ${LibElf_LIBRARY_DIRS} ${LibDwarf_LIBRARY_DIRS})
46998e
+    set(_eu_libs ${LibElf_LIBRARIES} ${LibDwarf_LIBRARIES})
46998e
+  endif()
46998e
   add_library(ElfUtils SHARED IMPORTED)
46998e
+elseif(ENABLE_DEBUGINFOD AND NOT LibDebuginfod_FOUND)
46998e
+  message(FATAL_ERROR "Debuginfod enabled but not found")
46998e
 elseif(NOT (LibElf_FOUND AND LibDwarf_FOUND) AND STERILE_BUILD)
46998e
   message(FATAL_ERROR "Elfutils not found and cannot be downloaded because build is sterile.")
46998e
 else()
46998e
@@ -104,7 +121,7 @@ else()
46998e
   if(NOT (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") OR NOT (${CMAKE_C_COMPILER_ID} STREQUAL "GNU"))
46998e
     message(FATAL_ERROR "ElfUtils will only build with the GNU compiler")
46998e
   endif()
46998e
-  
46998e
+
46998e
   include(ExternalProject)
46998e
   externalproject_add(
46998e
     ElfUtils
46998e
46998e
--- /dedyninst-10.2.1/dyninst-10.2.1/null
46998e
+++ b/cmake/Modules/FindLibDebuginfod.cmake
46998e
@@ -0,0 +1,76 @@
46998e
+#========================================================================================
46998e
+# FindDebuginfod
46998e
+# -----------
46998e
+#
46998e
+# Find debuginfod library and headers
46998e
+#
46998e
+# The module defines the following variables:
46998e
+#
46998e
+# This module reads hints about search locations from variables::
46998e
+#
46998e
+#       LibDebuginfod_ROOT_DIR         - Base directory the of libdebuginfod installation
46998e
+#       LibDebuginfod_INCLUDEDIR       - Hint directory that contains the libdebuginfod headers files
46998e
+#       LibDebuginfod_LIBRARYDIR       - Hint directory that contains the libdebuginfod library files
46998e
+#
46998e
+# and saves search results persistently in CMake cache entries::
46998e
+#
46998e
+#       LibDebuginfod_FOUND            - True if headers and requested libraries were found
46998e
+#       LibDebuginfod_INCLUDE_DIRS     - libdebuginfod include directories
46998e
+#       LibDebuginfod_LIBRARY_DIRS     - Link directories for libdebuginfod libraries
46998e
+#       LibDebuginfod_LIBRARIES        - libdebuginfod library files
46998e
+#
46998e
+# Utilize package config (e.g. /usr/lib64/pkgconfig/libdebuginfod.pc) to fetch
46998e
+# version information.
46998e
+#
46998e
+#========================================================================================
46998e
+
46998e
+find_package(PkgConfig QUIET)
46998e
+pkg_check_modules(PC_Debuginfod QUIET REQUIRED libdebuginfod>=${ElfUtils_MIN_VERSION})
46998e
+set(LibDebuginfod_VERSION "${PC_Debuginfod_VERSION}")
46998e
+
46998e
+find_path(LibDebuginfod_INCLUDE_DIRS
46998e
+          NAMES
46998e
+            debuginfod.h
46998e
+          HINTS
46998e
+            ${PC_Debuginfod_INCLUDEDIR}
46998e
+            ${PC_Debuginfod_INCLUDE_DIRS}
46998e
+            ${LibDebuginfod_ROOT_DIR}/include
46998e
+            ${LibDebuginfod_ROOT_DIR}
46998e
+            ${LibDebuginfod_INCLUDEDIR}
46998e
+          PATHS
46998e
+            ${DYNINST_SYSTEM_INCLUDE_PATHS}
46998e
+          PATH_SUFFIXES
46998e
+            ${_path_suffixes}
46998e
+          DOC
46998e
+            "libdebuginfod include directories")
46998e
+
46998e
+find_library(LibDebuginfod_LIBRARIES
46998e
+             NAMES
46998e
+               libdebuginfod.so.1 libdebuginfod.so
46998e
+             HINTS
46998e
+               ${PC_Debuginfod_LIBDIR}
46998e
+               ${PC_Debuginfod_LIBRARY_DIRS}
46998e
+               ${LibDebuginfod_ROOT_DIR}/lib
46998e
+               ${LibDebuginfod_ROOT_DIR}
46998e
+               ${LibDebuginfod_LIBRARYDIR}
46998e
+             PATHS
46998e
+               ${DYNINST_SYSTEM_LIBRARY_PATHS}
46998e
+             PATH_SUFFIXES
46998e
+               ${_path_suffixes})
46998e
+
46998e
+include(FindPackageHandleStandardArgs)
46998e
+find_package_handle_standard_args(LibDebuginfod
46998e
+                                  FOUND_VAR
46998e
+                                    LibDebuginfod_FOUND
46998e
+                                  REQUIRED_VARS
46998e
+                                    LibDebuginfod_INCLUDE_DIRS
46998e
+                                    LibDebuginfod_LIBRARIES
46998e
+                                  VERSION_VAR
46998e
+                                    LibDebuginfod_VERSION)
46998e
+
46998e
+if(LibDebuginfod_FOUND)
46998e
+  set(LibDebuginfod_INCLUDE_DIRS ${LibDebuginfod_INCLUDE_DIRS})
46998e
+  set(LibDebuginfod_LIBRARIES ${LibDebuginfod_LIBRARIES})
46998e
+  get_filename_component(_debuginfod_dir ${LibDebuginfod_LIBRARIES} DIRECTORY)
46998e
+  set(LibDebuginfod_LIBRARY_DIRS ${_debuginfod_dir} "${_debuginfod_dir}/elfutils")
46998e
+endif()
46998e
46998e
--- dyninst-10.2.1/dyninst-10.2.1/cmake/options.cmake
46998e
+++ dyninst-10.2.1/dyninst-10.2.1/cmake/options.cmake
46998e
@@ -16,6 +16,8 @@ option(USE_COTIRE "Enable Cotire precompiled headers")
46998e
 
46998e
 option (ENABLE_LTO "Enable Link-Time Optimization" OFF)
46998e
 
46998e
+option(ENABLE_DEBUGINFOD "Enable debuginfod support" OFF)
46998e
+
46998e
 # Some global on/off switches
46998e
 if (LIGHTWEIGHT_SYMTAB)
46998e
 add_definitions (-DWITHOUT_SYMTAB_API -DWITH_SYMLITE)
46998e
46998e
--- dyninst-10.2.1/dyninst-10.2.1/elf/CMakeLists.txt
46998e
+++ dyninst-10.2.1/dyninst-10.2.1/elf/CMakeLists.txt
46998e
@@ -27,5 +27,8 @@ endif()
46998e
 add_dependencies(dynElf ElfUtils)
46998e
 target_link_private_libraries(dynElf ${ElfUtils_LIBRARIES})
46998e
 
46998e
+if (ENABLE_DEBUGINFOD AND LibDebuginfod_FOUND)
46998e
+  add_definitions(-DDEBUGINFOD_LIB)
46998e
+endif()
46998e
 
46998e
 add_definitions(-DDYNELF_LIB)
46998e
46998e
46998e
--- dyninst-10.2.1/dyninst-10.2.1/elf/src/Elf_X.C
46998e
+++ dyninst-10.2.1/dyninst-10.2.1/elf/src/Elf_X.C
46998e
@@ -47,6 +47,9 @@
46998e
 #include <sstream>
46998e
 #include <libelf.h>
46998e
 
46998e
+#if DEBUGINFOD_LIB
46998e
+#include <elfutils/debuginfod.h>
46998e
+#endif
46998e
 
46998e
 using namespace std;
46998e
 using boost::crc_32_type;
46998e
@@ -1722,37 +1725,79 @@ bool Elf_X::findDebugFile(std::string origfilename, string &output_name, char* &
46998e
      }
46998e
   }
46998e
 
46998e
-  if (debugFileFromDebugLink.empty())
46998e
-     return false;
46998e
+  if (!debugFileFromDebugLink.empty()) {
46998e
+     char *mfPathNameCopy = strdup(origfilename.c_str());
46998e
+     string objectFileDirName = dirname(mfPathNameCopy);
46998e
 
46998e
-  char *mfPathNameCopy = strdup(origfilename.c_str());
46998e
-  string objectFileDirName = dirname(mfPathNameCopy);
46998e
+     vector<string> fnames = list_of
46998e
+       (objectFileDirName + "/" + debugFileFromDebugLink)
46998e
+       (objectFileDirName + "/.debug/" + debugFileFromDebugLink)
46998e
+       ("/usr/lib/debug/" + objectFileDirName + "/" + debugFileFromDebugLink);
46998e
 
46998e
-  vector<string> fnames = list_of
46998e
-    (objectFileDirName + "/" + debugFileFromDebugLink)
46998e
-    (objectFileDirName + "/.debug/" + debugFileFromDebugLink)
46998e
-    ("/usr/lib/debug/" + objectFileDirName + "/" + debugFileFromDebugLink);
46998e
+     free(mfPathNameCopy);
46998e
 
46998e
-  free(mfPathNameCopy);
46998e
+     for(unsigned i = 0; i < fnames.size(); i++) {
46998e
+        bool result = loadDebugFileFromDisk(fnames[i], output_buffer, output_buffer_size);
46998e
+        if (!result)
46998e
+           continue;
46998e
 
46998e
-  for(unsigned i = 0; i < fnames.size(); i++) {
46998e
-     bool result = loadDebugFileFromDisk(fnames[i], output_buffer, output_buffer_size);
46998e
-     if (!result)
46998e
-        continue;
46998e
-    
46998e
-    boost::crc_32_type crcComputer;
46998e
-    crcComputer.process_bytes(output_buffer, output_buffer_size);
46998e
-    if(crcComputer.checksum() != debugFileCrc) {
46998e
-       munmap(output_buffer, output_buffer_size);
46998e
-       continue;
46998e
-    }
46998e
+        boost::crc_32_type crcComputer;
46998e
+        crcComputer.process_bytes(output_buffer, output_buffer_size);
46998e
+        if(crcComputer.checksum() != debugFileCrc) {
46998e
+           munmap(output_buffer, output_buffer_size);
46998e
+           continue;
46998e
+        }
46998e
+
46998e
+        output_name = fnames[i];
46998e
+        cached_debug_buffer = output_buffer;
46998e
+        cached_debug_size = output_buffer_size;
46998e
+        cached_debug_name = output_name;
46998e
+        return true;
46998e
+     }
46998e
+  }
46998e
 
46998e
-    output_name = fnames[i];
46998e
-    cached_debug_buffer = output_buffer;
46998e
-    cached_debug_size = output_buffer_size;
46998e
-    cached_debug_name = output_name;
46998e
-    return true;
46998e
+#ifdef DEBUGINFOD_LIB
46998e
+  if (!debugFileFromBuildID.empty()) {
46998e
+     // Given /usr/lib/debug/.buildid/XX/YYYYYY.debug, isolate XXYYYYYY.
46998e
+     size_t idx1 = debugFileFromBuildID.find_last_of("/");
46998e
+     size_t idx2 = debugFileFromBuildID.find_last_of(".");
46998e
+
46998e
+     if (idx1 == string::npos || idx2 == string::npos
46998e
+         || idx1 < 2 || idx1 > idx2)
46998e
+        return false;
46998e
+
46998e
+     idx1 -= 2;
46998e
+     string buildid(debugFileFromBuildID.substr(idx1, idx2 - idx1));
46998e
+     buildid.erase(2, 1);
46998e
+
46998e
+     debuginfod_client *client = debuginfod_begin();
46998e
+     if (client == NULL)
46998e
+        return false;
46998e
+
46998e
+     char *filename;
46998e
+     int fd = debuginfod_find_debuginfo(client,
46998e
+                                        (const unsigned char *)buildid.c_str(),
46998e
+                                        0, &filename);
46998e
+     debuginfod_end(client);
46998e
+
46998e
+     if (fd >= 0) {
46998e
+        string fname = string(filename);
46998e
+        free(filename);
46998e
+        close(fd);
46998e
+
46998e
+        bool result = loadDebugFileFromDisk(fname,
46998e
+                                            output_buffer,
46998e
+                                            output_buffer_size);
46998e
+        if (result) {
46998e
+           output_name = fname;
46998e
+           cached_debug_buffer = output_buffer;
46998e
+           cached_debug_size = output_buffer_size;
46998e
+           cached_debug_name = output_name;
46998e
+           return true;
46998e
+        }
46998e
+     }
46998e
   }
46998e
+#endif
46998e
 
46998e
   return false;
46998e
 }