perf dso: Add BPF DSO read and size hooks
authorJiri Olsa <jolsa@kernel.org>
Wed, 8 May 2019 13:20:02 +0000 (15:20 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 28 May 2019 21:37:44 +0000 (18:37 -0300)
Add BPF related code into DSO reading paths to return size (bpf_size)
and read the BPF code (bpf_read).

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Song Liu <songliubraving@fb.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stanislav Fomichev <sdf@google.com>
Link: http://lkml.kernel.org/r/20190508132010.14512-5-jolsa@kernel.org
[ Use uintptr_t when casting from u64 to u8 pointers ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/dso.c

index 1e6a045adb8ca7f3b7b7911b3352ad4814d4cea6..1fb18292c2d3d41fc44f8675d2e71e31bbbeb996 100644 (file)
@@ -9,6 +9,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
+#include <bpf/libbpf.h>
+#include "bpf-event.h"
 #include "compress.h"
 #include "namespaces.h"
 #include "path.h"
@@ -706,6 +708,44 @@ bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
        return false;
 }
 
+static ssize_t bpf_read(struct dso *dso, u64 offset, char *data)
+{
+       struct bpf_prog_info_node *node;
+       ssize_t size = DSO__DATA_CACHE_SIZE;
+       u64 len;
+       u8 *buf;
+
+       node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id);
+       if (!node || !node->info_linear) {
+               dso->data.status = DSO_DATA_STATUS_ERROR;
+               return -1;
+       }
+
+       len = node->info_linear->info.jited_prog_len;
+       buf = (u8 *)(uintptr_t)node->info_linear->info.jited_prog_insns;
+
+       if (offset >= len)
+               return -1;
+
+       size = (ssize_t)min(len - offset, (u64)size);
+       memcpy(data, buf + offset, size);
+       return size;
+}
+
+static int bpf_size(struct dso *dso)
+{
+       struct bpf_prog_info_node *node;
+
+       node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id);
+       if (!node || !node->info_linear) {
+               dso->data.status = DSO_DATA_STATUS_ERROR;
+               return -1;
+       }
+
+       dso->data.file_size = node->info_linear->info.jited_prog_len;
+       return 0;
+}
+
 static void
 dso_cache__free(struct dso *dso)
 {
@@ -832,7 +872,11 @@ dso_cache__read(struct dso *dso, struct machine *machine,
        if (!cache)
                return -ENOMEM;
 
-       ret = file_read(dso, machine, cache_offset, cache->data);
+       if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
+               ret = bpf_read(dso, cache_offset, cache->data);
+       else
+               ret = file_read(dso, machine, cache_offset, cache->data);
+
        if (ret > 0) {
                cache->offset = cache_offset;
                cache->size   = ret;
@@ -941,6 +985,9 @@ int dso__data_file_size(struct dso *dso, struct machine *machine)
        if (dso->data.status == DSO_DATA_STATUS_ERROR)
                return -1;
 
+       if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
+               return bpf_size(dso);
+
        return file_size(dso, machine);
 }