perf build-ids: Fall back to debuginfod query if debuginfo not found
authorFrank Ch. Eigler <fche@redhat.com>
Thu, 13 Aug 2020 08:22:04 +0000 (10:22 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 14 Aug 2020 12:51:14 +0000 (09:51 -0300)
During a perf-record, use the -ldebuginfod API to query a debuginfod
server, should the debug data not be found in the usual system
locations.  If successful, the usual $HOME/.debug dir is populated.

Tested with:

  $ find .
  .
  ./ctags-debuginfo-5.8-26.fc31.x86_64.rpm
  ./usr
  ./usr/lib
  ./usr/lib/debug
  ./usr/lib/debug/.build-id
  ./usr/lib/debug/.build-id/ca
  ./usr/lib/debug/.build-id/ca/46f6ae6a0cee57d85abc1d461c49074248908d
  ./usr/lib/debug/.build-id/ca/46f6ae6a0cee57d85abc1d461c49074248908d.debug
  ./usr/lib/debug/usr
  ./usr/lib/debug/usr/bin
  ./usr/lib/debug/usr/bin/ctags-5.8-26.fc31.x86_64.debug

  $ debuginfod  -F .
  ...

  $ rm -rf ~/.debug/ ; mkdir ~/.debug

  $ perf record make tags
    BUILD:   Doing 'make -j8' parallel build
    GEN      tags
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.107 MB perf.data (1483 samples) ]

  $ find ~/.debug | grep ctags
  /home/jolsa/.debug/usr/bin/ctags
  /home/jolsa/.debug/usr/bin/ctags/ca46f6ae6a0cee57d85abc1d461c49074248908d
  /home/jolsa/.debug/usr/bin/ctags/ca46f6ae6a0cee57d85abc1d461c49074248908d/elf
  /home/jolsa/.debug/usr/bin/ctags/ca46f6ae6a0cee57d85abc1d461c49074248908d/probes

  $ rm -rf ~/.debug/ ; mkdir ~/.debug

  $ DEBUGINFOD_URLS=http://localhost:8002 perf record make tags
    BUILD:   Doing 'make -j8' parallel build
    GEN      tags
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.108 MB perf.data (1531 samples) ]

  $ find ~/.debug | grep ctag
  /home/jolsa/.debug/usr/bin/ctags
  /home/jolsa/.debug/usr/bin/ctags/ca46f6ae6a0cee57d85abc1d461c49074248908d
  /home/jolsa/.debug/usr/bin/ctags/ca46f6ae6a0cee57d85abc1d461c49074248908d/debug
  /home/jolsa/.debug/usr/bin/ctags/ca46f6ae6a0cee57d85abc1d461c49074248908d/elf
  /home/jolsa/.debug/usr/bin/ctags/ca46f6ae6a0cee57d85abc1d461c49074248908d/probes

Note the 'debug' file is created in the last run.

Note that currently the debuginfo data are downloaded only on record path,
we still need add this support to perf build-id/report.. and test ;-)

Tested-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Frank Ch. Eigler <fche@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/build/Makefile.feature
tools/build/feature/Makefile
tools/build/feature/test-libdebuginfod.c [new file with mode: 0644]
tools/perf/Makefile.config
tools/perf/Makefile.perf
tools/perf/util/build-id.c

index e7818b4..c1daf4d 100644 (file)
@@ -98,7 +98,8 @@ FEATURE_TESTS_EXTRA :=                  \
          llvm-version                   \
          clang                          \
          libbpf                         \
-         libpfm4
+         libpfm4                        \
+         libdebuginfod
 
 FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
 
index 846ee13..d220fe9 100644 (file)
@@ -26,6 +26,7 @@ FILES=                                          \
          test-libelf-gelf_getnote.bin           \
          test-libelf-getshdrstrndx.bin          \
          test-libelf-mmap.bin                   \
+         test-libdebuginfod.bin                 \
          test-libnuma.bin                       \
          test-numa_num_possible_cpus.bin        \
          test-libperl.bin                       \
@@ -157,6 +158,9 @@ $(OUTPUT)test-libelf-gelf_getnote.bin:
 $(OUTPUT)test-libelf-getshdrstrndx.bin:
        $(BUILD) -lelf
 
+$(OUTPUT)test-libdebuginfod.bin:
+       $(BUILD) -ldebuginfod
+
 $(OUTPUT)test-libnuma.bin:
        $(BUILD) -lnuma
 
diff --git a/tools/build/feature/test-libdebuginfod.c b/tools/build/feature/test-libdebuginfod.c
new file mode 100644 (file)
index 0000000..da22548
--- /dev/null
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <elfutils/debuginfod.h>
+
+int main(void)
+{
+       debuginfod_client* c = debuginfod_begin();
+       return (long)c;
+}
index 5136338..190be4f 100644 (file)
@@ -501,6 +501,14 @@ ifndef NO_LIBELF
     CFLAGS += -DHAVE_ELF_GETSHDRSTRNDX_SUPPORT
   endif
 
+  ifndef NO_LIBDEBUGINFOD
+    $(call feature_check,libdebuginfod)
+    ifeq ($(feature-libdebuginfod), 1)
+      CFLAGS += -DHAVE_DEBUGINFOD_SUPPORT
+      EXTLIBS += -ldebuginfod
+    endif
+  endif
+
   ifndef NO_DWARF
     ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
       msg := $(warning DWARF register mappings have not been defined for architecture $(SRCARCH), DWARF support disabled);
index e339e22..6031167 100644 (file)
@@ -124,6 +124,8 @@ include ../scripts/utilities.mak
 #
 # Define LIBPFM4 to enable libpfm4 events extension.
 #
+# Define NO_LIBDEBUGINFOD if you do not want support debuginfod
+#
 
 # As per kernel Makefile, avoid funny character set dependencies
 unexport LC_ALL
index c076fc7..31207b6 100644 (file)
 #include "probe-file.h"
 #include "strlist.h"
 
+#ifdef HAVE_DEBUGINFOD_SUPPORT
+#include <elfutils/debuginfod.h>
+#endif
+
 #include <linux/ctype.h>
 #include <linux/zalloc.h>
 
@@ -636,6 +640,21 @@ static char *build_id_cache__find_debug(const char *sbuild_id,
        if (realname && access(realname, R_OK))
                zfree(&realname);
        nsinfo__mountns_exit(&nsc);
+
+#ifdef HAVE_DEBUGINFOD_SUPPORT
+        if (realname == NULL) {
+                debuginfod_client* c = debuginfod_begin();
+                if (c != NULL) {
+                        int fd = debuginfod_find_debuginfo(c,
+                                                           (const unsigned char*)sbuild_id, 0,
+                                                           &realname);
+                        if (fd >= 0)
+                                close(fd); /* retaining reference by realname */
+                        debuginfod_end(c);
+                }
+        }
+#endif
+
 out:
        free(debugfile);
        return realname;