Skip to content

Commit

Permalink
perf bpf: Save BTF in a rbtree in perf_env
Browse files Browse the repository at this point in the history
BTF contains information necessary to annotate BPF programs. This patch
saves BTF for BPF programs loaded in the system.

Signed-off-by: Song Liu <songliubraving@fb.com>
Reviewed-by: Jiri Olsa <jolsa@kernel.org>
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-9-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 606f972 commit 3792cb2
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
23 changes: 23 additions & 0 deletions tools/perf/util/bpf-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,28 @@ int machine__process_bpf_event(struct machine *machine __maybe_unused,
return 0;
}

static int perf_env__fetch_btf(struct perf_env *env,
u32 btf_id,
struct btf *btf)
{
struct btf_node *node;
u32 data_size;
const void *data;

data = btf__get_raw_data(btf, &data_size);

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

node->id = btf_id;
node->data_size = data_size;
memcpy(node->data, data, data_size);

perf_env__insert_btf(env, node);
return 0;
}

/*
* Synthesize PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT for one bpf
* program. One PERF_RECORD_BPF_EVENT is generated for the program. And
Expand Down Expand Up @@ -113,6 +135,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
goto out;
}
has_btf = true;
perf_env__fetch_btf(env, info->btf_id, btf);
}

/* Synthesize PERF_RECORD_KSYMBOL */
Expand Down
7 changes: 7 additions & 0 deletions tools/perf/util/bpf-event.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ struct bpf_prog_info_node {
struct rb_node rb_node;
};

struct btf_node {
struct rb_node rb_node;
u32 id;
u32 data_size;
char data[];
};

#ifdef HAVE_LIBBPF_SUPPORT
int machine__process_bpf_event(struct machine *machine, union perf_event *event,
struct perf_sample *sample);
Expand Down
67 changes: 67 additions & 0 deletions tools/perf/util/env.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,58 @@ struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
return node;
}

void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
{
struct rb_node *parent = NULL;
__u32 btf_id = btf_node->id;
struct btf_node *node;
struct rb_node **p;

down_write(&env->bpf_progs.lock);
p = &env->bpf_progs.btfs.rb_node;

while (*p != NULL) {
parent = *p;
node = rb_entry(parent, struct btf_node, rb_node);
if (btf_id < node->id) {
p = &(*p)->rb_left;
} else if (btf_id > node->id) {
p = &(*p)->rb_right;
} else {
pr_debug("duplicated btf %u\n", btf_id);
goto out;
}
}

rb_link_node(&btf_node->rb_node, parent, p);
rb_insert_color(&btf_node->rb_node, &env->bpf_progs.btfs);
env->bpf_progs.btfs_cnt++;
out:
up_write(&env->bpf_progs.lock);
}

struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id)
{
struct btf_node *node = NULL;
struct rb_node *n;

down_read(&env->bpf_progs.lock);
n = env->bpf_progs.btfs.rb_node;

while (n) {
node = rb_entry(n, struct btf_node, rb_node);
if (btf_id < node->id)
n = n->rb_left;
else if (btf_id > node->id)
n = n->rb_right;
else
break;
}

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

/* purge data in bpf_progs.infos tree */
static void perf_env__purge_bpf(struct perf_env *env)
{
Expand All @@ -86,6 +138,20 @@ static void perf_env__purge_bpf(struct perf_env *env)

env->bpf_progs.infos_cnt = 0;

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);
rb_erase(&node->rb_node, root);
free(node);
}

env->bpf_progs.btfs_cnt = 0;

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

Expand Down Expand Up @@ -123,6 +189,7 @@ void perf_env__exit(struct perf_env *env)
void perf_env__init(struct perf_env *env)
{
env->bpf_progs.infos = RB_ROOT;
env->bpf_progs.btfs = RB_ROOT;
init_rwsem(&env->bpf_progs.lock);
}

Expand Down
5 changes: 5 additions & 0 deletions tools/perf/util/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,13 @@ struct perf_env {
struct rw_semaphore lock;
struct rb_root infos;
u32 infos_cnt;
struct rb_root btfs;
u32 btfs_cnt;
} bpf_progs;
};

struct bpf_prog_info_node;
struct btf_node;

extern struct perf_env perf_env;

Expand All @@ -99,4 +102,6 @@ void perf_env__insert_bpf_prog_info(struct perf_env *env,
struct bpf_prog_info_node *info_node);
struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
__u32 prog_id);
void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node);
struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id);
#endif /* __PERF_ENV_H */

0 comments on commit 3792cb2

Please sign in to comment.