diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2019-02-19 14:11:56 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2019-02-19 14:11:56 -0500 |
| commit | d19f856479feef7c1383f02b87688563a0ef7a14 (patch) | |
| tree | eccabd92b89d36b9ad387cb04605cff7ea119ea9 | |
| parent | 03d309711d687460d1345de8a0363f45b1c8cd11 (diff) | |
perf bpf: Add bpf_map dumper
At some point I'll suggest moving this to libbpf, for now I'll
experiment with ways to dump BPF maps set by events in 'perf trace',
starting with a very basic dumper for the current very limited needs
of the augmented_raw_syscalls code: dumping booleans.
Having functions that apply to the map keys and values and do table
lookup in things like syscall id to string tables should come next.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Yonghong Song <yhs@fb.com>
Link: https://lkml.kernel.org/n/tip-lz14w0esqyt1333aon05jpwc@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/util/Build | 1 | ||||
| -rw-r--r-- | tools/perf/util/bpf_map.c | 72 | ||||
| -rw-r--r-- | tools/perf/util/bpf_map.h | 22 |
3 files changed, 95 insertions, 0 deletions
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 3008d49fa587..8dd3102301ea 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
| @@ -115,6 +115,7 @@ perf-y += branch.o | |||
| 115 | perf-y += mem2node.o | 115 | perf-y += mem2node.o |
| 116 | 116 | ||
| 117 | perf-$(CONFIG_LIBBPF) += bpf-loader.o | 117 | perf-$(CONFIG_LIBBPF) += bpf-loader.o |
| 118 | perf-$(CONFIG_LIBBPF) += bpf_map.o | ||
| 118 | perf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o | 119 | perf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o |
| 119 | perf-$(CONFIG_LIBELF) += symbol-elf.o | 120 | perf-$(CONFIG_LIBELF) += symbol-elf.o |
| 120 | perf-$(CONFIG_LIBELF) += probe-file.o | 121 | perf-$(CONFIG_LIBELF) += probe-file.o |
diff --git a/tools/perf/util/bpf_map.c b/tools/perf/util/bpf_map.c new file mode 100644 index 000000000000..eb853ca67cf4 --- /dev/null +++ b/tools/perf/util/bpf_map.c | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
| 2 | |||
| 3 | #include "util/bpf_map.h" | ||
| 4 | #include <bpf/bpf.h> | ||
| 5 | #include <bpf/libbpf.h> | ||
| 6 | #include <linux/err.h> | ||
| 7 | #include <linux/kernel.h> | ||
| 8 | #include <stdbool.h> | ||
| 9 | #include <stdlib.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | |||
| 12 | static bool bpf_map_def__is_per_cpu(const struct bpf_map_def *def) | ||
| 13 | { | ||
| 14 | return def->type == BPF_MAP_TYPE_PERCPU_HASH || | ||
| 15 | def->type == BPF_MAP_TYPE_PERCPU_ARRAY || | ||
| 16 | def->type == BPF_MAP_TYPE_LRU_PERCPU_HASH || | ||
| 17 | def->type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE; | ||
| 18 | } | ||
| 19 | |||
| 20 | static void *bpf_map_def__alloc_value(const struct bpf_map_def *def) | ||
| 21 | { | ||
| 22 | if (bpf_map_def__is_per_cpu(def)) | ||
| 23 | return malloc(round_up(def->value_size, 8) * sysconf(_SC_NPROCESSORS_CONF)); | ||
| 24 | |||
| 25 | return malloc(def->value_size); | ||
| 26 | } | ||
| 27 | |||
| 28 | int bpf_map__fprintf(struct bpf_map *map, FILE *fp) | ||
| 29 | { | ||
| 30 | const struct bpf_map_def *def = bpf_map__def(map); | ||
| 31 | void *prev_key = NULL, *key, *value; | ||
| 32 | int fd = bpf_map__fd(map), err; | ||
| 33 | int printed = 0; | ||
| 34 | |||
| 35 | if (fd < 0) | ||
| 36 | return fd; | ||
| 37 | |||
| 38 | if (IS_ERR(def)) | ||
| 39 | return PTR_ERR(def); | ||
| 40 | |||
| 41 | err = -ENOMEM; | ||
| 42 | key = malloc(def->key_size); | ||
| 43 | if (key == NULL) | ||
| 44 | goto out; | ||
| 45 | |||
| 46 | value = bpf_map_def__alloc_value(def); | ||
| 47 | if (value == NULL) | ||
| 48 | goto out_free_key; | ||
| 49 | |||
| 50 | while ((err = bpf_map_get_next_key(fd, prev_key, key) == 0)) { | ||
| 51 | int intkey = *(int *)key; | ||
| 52 | |||
| 53 | if (!bpf_map_lookup_elem(fd, key, value)) { | ||
| 54 | bool boolval = *(bool *)value; | ||
| 55 | if (boolval) | ||
| 56 | printed += fprintf(fp, "[%d] = %d,\n", intkey, boolval); | ||
| 57 | } else { | ||
| 58 | printed += fprintf(fp, "[%d] = ERROR,\n", intkey); | ||
| 59 | } | ||
| 60 | |||
| 61 | prev_key = key; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (err == ENOENT) | ||
| 65 | err = printed; | ||
| 66 | |||
| 67 | free(value); | ||
| 68 | out_free_key: | ||
| 69 | free(key); | ||
| 70 | out: | ||
| 71 | return err; | ||
| 72 | } | ||
diff --git a/tools/perf/util/bpf_map.h b/tools/perf/util/bpf_map.h new file mode 100644 index 000000000000..d6abd5e47af8 --- /dev/null +++ b/tools/perf/util/bpf_map.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
| 2 | #ifndef __PERF_BPF_MAP_H | ||
| 3 | #define __PERF_BPF_MAP_H 1 | ||
| 4 | |||
| 5 | #include <stdio.h> | ||
| 6 | #include <linux/compiler.h> | ||
| 7 | struct bpf_map; | ||
| 8 | |||
| 9 | #ifdef HAVE_LIBBPF_SUPPORT | ||
| 10 | |||
| 11 | int bpf_map__fprintf(struct bpf_map *map, FILE *fp); | ||
| 12 | |||
| 13 | #else | ||
| 14 | |||
| 15 | static inline int bpf_map__fprintf(struct bpf_map *map __maybe_unused, FILE *fp __maybe_unused) | ||
| 16 | { | ||
| 17 | return 0; | ||
| 18 | } | ||
| 19 | |||
| 20 | #endif // HAVE_LIBBPF_SUPPORT | ||
| 21 | |||
| 22 | #endif // __PERF_BPF_MAP_H | ||
