Skip to content

Commit

Permalink
perf bpf: Save BTF information as headers to perf.data
Browse files Browse the repository at this point in the history
This patch enables 'perf record' to save BTF information as headers to
perf.data.

A new header type HEADER_BPF_BTF is introduced for this data.

Committer testing:

As root, being on the kernel sources top level directory, run:

    # perf trace -e tools/perf/examples/bpf/augmented_raw_syscalls.c -e *msg

Just to compile and load a BPF program that attaches to the
raw_syscalls:sys_{enter,exit} tracepoints to trace the syscalls ending
in "msg" (recvmsg, sendmsg, recvmmsg, sendmmsg, etc).

Make sure you have a recent enough clang, say version 9, to get the
BTF ELF sections needed for this testing:

  # clang --version | head -1
  clang version 9.0.0 (https://git.llvm.org/git/clang.git/ 7906282d3afec5dfdc2b27943fd6c0309086c507) (https://git.llvm.org/git/llvm.git/ a1b5de1ff8ae8bc79dc8e86e1f82565229bd0500)
  # readelf -SW tools/perf/examples/bpf/augmented_raw_syscalls.o | grep BTF
    [22] .BTF              PROGBITS        0000000000000000 000ede 000b0e 00      0   0  1
    [23] .BTF.ext          PROGBITS        0000000000000000 0019ec 0002a0 00      0   0  1
    [24] .rel.BTF.ext      REL             0000000000000000 002fa8 000270 10     30  23  8

Then do a systemwide perf record session for a few seconds:

  # perf record -a sleep 2s

Then look at:

  # perf report --header-only | grep b[pt]f
  # event : name = cycles:ppp, , id = { 1116204, 1116205, 1116206, 1116207, 1116208, 1116209, 1116210, 1116211 }, size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|PERIOD, read_format = ID, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, enable_on_exec = 1, task = 1, precise_ip = 3, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, ksymbol = 1, bpf_event = 1
  # bpf_prog_info of id 13
  # bpf_prog_info of id 14
  # bpf_prog_info of id 15
  # bpf_prog_info of id 16
  # bpf_prog_info of id 17
  # bpf_prog_info of id 18
  # bpf_prog_info of id 21
  # bpf_prog_info of id 22
  # bpf_prog_info of id 51
  # bpf_prog_info of id 52
  # btf info of id 8
  #

We need to show more info about these BPF and BTF entries , but that can
be done later.

Signed-off-by: Song Liu <songliubraving@fb.com>
Reviewed-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stanislav Fomichev <sdf@google.com>
Cc: kernel-team@fb.com
Link: http://lkml.kernel.org/r/20190312053051.2690567-10-songliubraving@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Song Liu authored and Arnaldo Carvalho de Melo committed Mar 19, 2019
1 parent 3792cb2 commit a70a112
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 1 deletion.
101 changes: 100 additions & 1 deletion tools/perf/util/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,39 @@ static int write_bpf_prog_info(struct feat_fd *ff __maybe_unused,
}
#endif // HAVE_LIBBPF_SUPPORT

static int write_bpf_btf(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
struct perf_env *env = &ff->ph->env;
struct rb_root *root;
struct rb_node *next;
int ret;

down_read(&env->bpf_progs.lock);

ret = do_write(ff, &env->bpf_progs.btfs_cnt,
sizeof(env->bpf_progs.btfs_cnt));

if (ret < 0)
goto out;

root = &env->bpf_progs.btfs;
next = rb_first(root);
while (next) {
struct btf_node *node;

node = rb_entry(next, struct btf_node, rb_node);
next = rb_next(&node->rb_node);
ret = do_write(ff, &node->id,
sizeof(u32) * 2 + node->data_size);
if (ret < 0)
goto out;
}
out:
up_read(&env->bpf_progs.lock);
return ret;
}

static int cpu_cache_level__sort(const void *a, const void *b)
{
struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
Expand Down Expand Up @@ -1442,6 +1475,28 @@ static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp)
up_read(&env->bpf_progs.lock);
}

static void print_bpf_btf(struct feat_fd *ff, FILE *fp)
{
struct perf_env *env = &ff->ph->env;
struct rb_root *root;
struct rb_node *next;

down_read(&env->bpf_progs.lock);

root = &env->bpf_progs.btfs;
next = rb_first(root);

while (next) {
struct btf_node *node;

node = rb_entry(next, struct btf_node, rb_node);
next = rb_next(&node->rb_node);
fprintf(fp, "# btf info of id %u\n", node->id);
}

up_read(&env->bpf_progs.lock);
}

static void free_event_desc(struct perf_evsel *events)
{
struct perf_evsel *evsel;
Expand Down Expand Up @@ -2564,6 +2619,49 @@ static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data _
}
#endif // HAVE_LIBBPF_SUPPORT

static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused)
{
struct perf_env *env = &ff->ph->env;
u32 count, i;

if (ff->ph->needs_swap) {
pr_warning("interpreting btf from systems with endianity is not yet supported\n");
return 0;
}

if (do_read_u32(ff, &count))
return -1;

down_write(&env->bpf_progs.lock);

for (i = 0; i < count; ++i) {
struct btf_node *node;
u32 id, data_size;

if (do_read_u32(ff, &id))
return -1;
if (do_read_u32(ff, &data_size))
return -1;

node = malloc(sizeof(struct btf_node) + data_size);
if (!node)
return -1;

node->id = id;
node->data_size = data_size;

if (__do_read(ff, node->data, data_size)) {
free(node);
return -1;
}

perf_env__insert_btf(env, node);
}

up_write(&env->bpf_progs.lock);
return 0;
}

struct feature_ops {
int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
void (*print)(struct feat_fd *ff, FILE *fp);
Expand Down Expand Up @@ -2625,7 +2723,8 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
FEAT_OPR(CLOCKID, clockid, false),
FEAT_OPN(DIR_FORMAT, dir_format, false),
FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false)
FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false),
FEAT_OPR(BPF_BTF, bpf_btf, false),
};

struct header_print_data {
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum {
HEADER_CLOCKID,
HEADER_DIR_FORMAT,
HEADER_BPF_PROG_INFO,
HEADER_BPF_BTF,
HEADER_LAST_FEATURE,
HEADER_FEAT_BITS = 256,
};
Expand Down

0 comments on commit a70a112

Please sign in to comment.