forked from mirrors/linux
		
	perf bpf: Save BTF in a rbtree in perf_env
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>
This commit is contained in:
		
							parent
							
								
									606f972b13
								
							
						
					
					
						commit
						3792cb2ff4
					
				
					 4 changed files with 102 additions and 0 deletions
				
			
		|  | @ -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 | ||||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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) | ||||
| { | ||||
|  | @ -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); | ||||
| } | ||||
| 
 | ||||
|  | @ -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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  | @ -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 */ | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Song Liu
						Song Liu