Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+95
+1
tools/perf/util/Build
··· 115 115 perf-y += mem2node.o 116 116 117 117 perf-$(CONFIG_LIBBPF) += bpf-loader.o 118 + perf-$(CONFIG_LIBBPF) += bpf_map.o 118 119 perf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 119 120 perf-$(CONFIG_LIBELF) += symbol-elf.o 120 121 perf-$(CONFIG_LIBELF) += probe-file.o
+72
tools/perf/util/bpf_map.c
··· 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 + }
+22
tools/perf/util/bpf_map.h
··· 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