mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
		
			
				
	
	
		
			72 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			72 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 | 
						|
 | 
						|
#include "util/bpf_map.h"
 | 
						|
#include <bpf/bpf.h>
 | 
						|
#include <bpf/libbpf.h>
 | 
						|
#include <linux/err.h>
 | 
						|
#include <linux/kernel.h>
 | 
						|
#include <stdbool.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
static bool bpf_map_def__is_per_cpu(const struct bpf_map_def *def)
 | 
						|
{
 | 
						|
	return def->type == BPF_MAP_TYPE_PERCPU_HASH ||
 | 
						|
	       def->type == BPF_MAP_TYPE_PERCPU_ARRAY ||
 | 
						|
	       def->type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
 | 
						|
	       def->type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
 | 
						|
}
 | 
						|
 | 
						|
static void *bpf_map_def__alloc_value(const struct bpf_map_def *def)
 | 
						|
{
 | 
						|
	if (bpf_map_def__is_per_cpu(def))
 | 
						|
		return malloc(round_up(def->value_size, 8) * sysconf(_SC_NPROCESSORS_CONF));
 | 
						|
 | 
						|
	return malloc(def->value_size);
 | 
						|
}
 | 
						|
 | 
						|
int bpf_map__fprintf(struct bpf_map *map, FILE *fp)
 | 
						|
{
 | 
						|
	const struct bpf_map_def *def = bpf_map__def(map);
 | 
						|
	void *prev_key = NULL, *key, *value;
 | 
						|
	int fd = bpf_map__fd(map), err;
 | 
						|
	int printed = 0;
 | 
						|
 | 
						|
	if (fd < 0)
 | 
						|
		return fd;
 | 
						|
 | 
						|
	if (IS_ERR(def))
 | 
						|
		return PTR_ERR(def);
 | 
						|
 | 
						|
	err = -ENOMEM;
 | 
						|
	key = malloc(def->key_size);
 | 
						|
	if (key == NULL)
 | 
						|
		goto out;
 | 
						|
 | 
						|
	value = bpf_map_def__alloc_value(def);
 | 
						|
	if (value == NULL)
 | 
						|
		goto out_free_key;
 | 
						|
 | 
						|
	while ((err = bpf_map_get_next_key(fd, prev_key, key) == 0)) {
 | 
						|
		int intkey = *(int *)key;
 | 
						|
 | 
						|
		if (!bpf_map_lookup_elem(fd, key, value)) {
 | 
						|
			bool boolval = *(bool *)value;
 | 
						|
			if (boolval)
 | 
						|
				printed += fprintf(fp, "[%d] = %d,\n", intkey, boolval);
 | 
						|
		} else {
 | 
						|
			printed += fprintf(fp, "[%d] = ERROR,\n", intkey);
 | 
						|
		}
 | 
						|
 | 
						|
		prev_key = key;
 | 
						|
	}
 | 
						|
 | 
						|
	if (err == ENOENT)
 | 
						|
		err = printed;
 | 
						|
 | 
						|
	free(value);
 | 
						|
out_free_key:
 | 
						|
	free(key);
 | 
						|
out:
 | 
						|
	return err;
 | 
						|
}
 |