diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-03-25 03:53:42 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-03-25 03:53:42 -0300 |
commit | 03dd4cb26d967f9588437b0fc9cc0e8353322bb7 (patch) | |
tree | fa581f6dc1c0596391690d1f67eceef3af8246dc /tools/lib/bpf | |
parent | d4e493caf788ef44982e131ff9c786546904d934 (diff) |
Linux-libre 4.5-gnu
Diffstat (limited to 'tools/lib/bpf')
-rw-r--r-- | tools/lib/bpf/Makefile | 32 | ||||
-rw-r--r-- | tools/lib/bpf/bpf.c | 18 | ||||
-rw-r--r-- | tools/lib/bpf/bpf.h | 2 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.c | 412 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.h | 88 |
5 files changed, 468 insertions, 84 deletions
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index a3caaf3ea..fc1bc75ae 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile @@ -6,6 +6,12 @@ BPF_EXTRAVERSION = 1 MAKEFLAGS += --no-print-directory +ifeq ($(srctree),) +srctree := $(patsubst %/,%,$(dir $(shell pwd))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +#$(info Determined 'srctree' to be $(srctree)) +endif # Makefiles suck: This macro sets a default value of $(2) for the # variable named by $(1), unless the variable has been set by @@ -31,7 +37,8 @@ INSTALL = install DESTDIR ?= DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' -LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) +include $(srctree)/tools/scripts/Makefile.arch + ifeq ($(LP64), 1) libdir_relative = lib64 else @@ -57,13 +64,6 @@ ifndef VERBOSE VERBOSE = 0 endif -ifeq ($(srctree),) -srctree := $(patsubst %/,%,$(dir $(shell pwd))) -srctree := $(patsubst %/,%,$(dir $(srctree))) -srctree := $(patsubst %/,%,$(dir $(srctree))) -#$(info Determined 'srctree' to be $(srctree)) -endif - FEATURE_USER = .libbpf FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf FEATURE_DISPLAY = libelf bpf @@ -71,7 +71,21 @@ FEATURE_DISPLAY = libelf bpf INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES) +check_feat := 1 +NON_CHECK_FEAT_TARGETS := clean TAGS tags cscope help +ifdef MAKECMDGOALS +ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),) + check_feat := 0 +endif +endif + +ifeq ($(check_feat),1) +ifeq ($(FEATURES_DUMP),) include $(srctree)/tools/build/Makefile.feature +else +include $(FEATURES_DUMP) +endif +endif export prefix libdir src obj @@ -178,7 +192,7 @@ config-clean: $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null clean: - $(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ + $(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d .*.cmd \ $(RM) LIBBPF-CFLAGS $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index a6331050a..1f91cc941 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -14,8 +14,8 @@ #include "bpf.h" /* - * When building perf, unistd.h is override. Define __NR_bpf is - * required to be defined. + * When building perf, unistd.h is overrided. __NR_bpf is + * required to be defined explicitly. */ #ifndef __NR_bpf # if defined(__i386__) @@ -83,3 +83,17 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns, log_buf[0] = 0; return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); } + +int bpf_map_update_elem(int fd, void *key, void *value, + u64 flags) +{ + union bpf_attr attr; + + bzero(&attr, sizeof(attr)); + attr.map_fd = fd; + attr.key = ptr_to_u64(key); + attr.value = ptr_to_u64(value); + attr.flags = flags; + + return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); +} diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 854b7361b..a76465541 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -20,4 +20,6 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns, u32 kern_version, char *log_buf, size_t log_buf_sz); +int bpf_map_update_elem(int fd, void *key, void *value, + u64 flags); #endif diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index e176bad19..8334a5a9d 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -152,29 +152,36 @@ struct bpf_program { } *reloc_desc; int nr_reloc; - int fd; + struct { + int nr; + int *fds; + } instances; + bpf_program_prep_t preprocessor; struct bpf_object *obj; void *priv; bpf_program_clear_priv_t clear_priv; }; +struct bpf_map { + int fd; + char *name; + struct bpf_map_def def; + void *priv; + bpf_map_clear_priv_t clear_priv; +}; + static LIST_HEAD(bpf_objects_list); struct bpf_object { char license[64]; u32 kern_version; - void *maps_buf; - size_t maps_buf_sz; struct bpf_program *programs; size_t nr_programs; - int *map_fds; - /* - * This field is required because maps_buf will be freed and - * maps_buf_sz will be set to 0 after loaded. - */ - size_t nr_map_fds; + struct bpf_map *maps; + size_t nr_maps; + bool loaded; /* @@ -188,6 +195,7 @@ struct bpf_object { Elf *elf; GElf_Ehdr ehdr; Elf_Data *symbols; + size_t strtabidx; struct { GElf_Shdr shdr; Elf_Data *data; @@ -206,10 +214,25 @@ struct bpf_object { static void bpf_program__unload(struct bpf_program *prog) { + int i; + if (!prog) return; - zclose(prog->fd); + /* + * If the object is opened but the program was never loaded, + * it is possible that prog->instances.nr == -1. + */ + if (prog->instances.nr > 0) { + for (i = 0; i < prog->instances.nr; i++) + zclose(prog->instances.fds[i]); + } else if (prog->instances.nr != -1) { + pr_warning("Internal error: instances.nr is %d\n", + prog->instances.nr); + } + + prog->instances.nr = -1; + zfree(&prog->instances.fds); } static void bpf_program__exit(struct bpf_program *prog) @@ -260,7 +283,8 @@ bpf_program__init(void *data, size_t size, char *name, int idx, memcpy(prog->insns, data, prog->insns_cnt * sizeof(struct bpf_insn)); prog->idx = idx; - prog->fd = -1; + prog->instances.fds = NULL; + prog->instances.nr = -1; return 0; errout: @@ -469,21 +493,77 @@ static int bpf_object__init_maps(struct bpf_object *obj, void *data, size_t size) { - if (size == 0) { + size_t nr_maps; + int i; + + nr_maps = size / sizeof(struct bpf_map_def); + if (!data || !nr_maps) { pr_debug("%s doesn't need map definition\n", obj->path); return 0; } - obj->maps_buf = malloc(size); - if (!obj->maps_buf) { - pr_warning("malloc maps failed: %s\n", obj->path); + pr_debug("maps in %s: %zd bytes\n", obj->path, size); + + obj->maps = calloc(nr_maps, sizeof(obj->maps[0])); + if (!obj->maps) { + pr_warning("alloc maps for object failed\n"); return -ENOMEM; } + obj->nr_maps = nr_maps; - obj->maps_buf_sz = size; - memcpy(obj->maps_buf, data, size); - pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size); + for (i = 0; i < nr_maps; i++) { + struct bpf_map_def *def = &obj->maps[i].def; + + /* + * fill all fd with -1 so won't close incorrect + * fd (fd=0 is stdin) when failure (zclose won't close + * negative fd)). + */ + obj->maps[i].fd = -1; + + /* Save map definition into obj->maps */ + *def = ((struct bpf_map_def *)data)[i]; + } + return 0; +} + +static int +bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx) +{ + int i; + Elf_Data *symbols = obj->efile.symbols; + + if (!symbols || maps_shndx < 0) + return -EINVAL; + + for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) { + GElf_Sym sym; + size_t map_idx; + const char *map_name; + + if (!gelf_getsym(symbols, i, &sym)) + continue; + if (sym.st_shndx != maps_shndx) + continue; + + map_name = elf_strptr(obj->efile.elf, + obj->efile.strtabidx, + sym.st_name); + map_idx = sym.st_value / sizeof(struct bpf_map_def); + if (map_idx >= obj->nr_maps) { + pr_warning("index of map \"%s\" is buggy: %zu > %zu\n", + map_name, map_idx, obj->nr_maps); + continue; + } + obj->maps[map_idx].name = strdup(map_name); + if (!obj->maps[map_idx].name) { + pr_warning("failed to alloc map name\n"); + return -ENOMEM; + } + pr_debug("map %zu is \"%s\"\n", map_idx, + obj->maps[map_idx].name); + } return 0; } @@ -492,7 +572,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) Elf *elf = obj->efile.elf; GElf_Ehdr *ep = &obj->efile.ehdr; Elf_Scn *scn = NULL; - int idx = 0, err = 0; + int idx = 0, err = 0, maps_shndx = -1; /* Elf is corrupted/truncated, avoid calling elf_strptr. */ if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { @@ -542,16 +622,19 @@ static int bpf_object__elf_collect(struct bpf_object *obj) err = bpf_object__init_kversion(obj, data->d_buf, data->d_size); - else if (strcmp(name, "maps") == 0) + else if (strcmp(name, "maps") == 0) { err = bpf_object__init_maps(obj, data->d_buf, data->d_size); - else if (sh.sh_type == SHT_SYMTAB) { + maps_shndx = idx; + } else if (sh.sh_type == SHT_SYMTAB) { if (obj->efile.symbols) { pr_warning("bpf: multiple SYMTAB in %s\n", obj->path); err = -LIBBPF_ERRNO__FORMAT; - } else + } else { obj->efile.symbols = data; + obj->efile.strtabidx = sh.sh_link; + } } else if ((sh.sh_type == SHT_PROGBITS) && (sh.sh_flags & SHF_EXECINSTR) && (data->d_size > 0)) { @@ -586,6 +669,13 @@ static int bpf_object__elf_collect(struct bpf_object *obj) if (err) goto out; } + + if (!obj->efile.strtabidx || obj->efile.strtabidx >= idx) { + pr_warning("Corrupted ELF file: index of strtab invalid\n"); + return LIBBPF_ERRNO__FORMAT; + } + if (maps_shndx >= 0) + err = bpf_object__init_maps_name(obj, maps_shndx); out: return err; } @@ -668,37 +758,15 @@ static int bpf_object__create_maps(struct bpf_object *obj) { unsigned int i; - size_t nr_maps; - int *pfd; - - nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def); - if (!obj->maps_buf || !nr_maps) { - pr_debug("don't need create maps for %s\n", - obj->path); - return 0; - } - - obj->map_fds = malloc(sizeof(int) * nr_maps); - if (!obj->map_fds) { - pr_warning("realloc perf_bpf_map_fds failed\n"); - return -ENOMEM; - } - obj->nr_map_fds = nr_maps; - /* fill all fd with -1 */ - memset(obj->map_fds, -1, sizeof(int) * nr_maps); - - pfd = obj->map_fds; - for (i = 0; i < nr_maps; i++) { - struct bpf_map_def def; + for (i = 0; i < obj->nr_maps; i++) { + struct bpf_map_def *def = &obj->maps[i].def; + int *pfd = &obj->maps[i].fd; - def = *(struct bpf_map_def *)(obj->maps_buf + - i * sizeof(struct bpf_map_def)); - - *pfd = bpf_create_map(def.type, - def.key_size, - def.value_size, - def.max_entries); + *pfd = bpf_create_map(def->type, + def->key_size, + def->value_size, + def->max_entries); if (*pfd < 0) { size_t j; int err = *pfd; @@ -706,22 +774,17 @@ bpf_object__create_maps(struct bpf_object *obj) pr_warning("failed to create map: %s\n", strerror(errno)); for (j = 0; j < i; j++) - zclose(obj->map_fds[j]); - obj->nr_map_fds = 0; - zfree(&obj->map_fds); + zclose(obj->maps[j].fd); return err; } pr_debug("create map: fd=%d\n", *pfd); - pfd++; } - zfree(&obj->maps_buf); - obj->maps_buf_sz = 0; return 0; } static int -bpf_program__relocate(struct bpf_program *prog, int *map_fds) +bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj) { int i; @@ -741,7 +804,7 @@ bpf_program__relocate(struct bpf_program *prog, int *map_fds) return -LIBBPF_ERRNO__RELOC; } insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; - insns[insn_idx].imm = map_fds[map_idx]; + insns[insn_idx].imm = obj->maps[map_idx].fd; } zfree(&prog->reloc_desc); @@ -760,7 +823,7 @@ bpf_object__relocate(struct bpf_object *obj) for (i = 0; i < obj->nr_programs; i++) { prog = &obj->programs[i]; - err = bpf_program__relocate(prog, obj->map_fds); + err = bpf_program__relocate(prog, obj); if (err) { pr_warning("failed to relocate '%s'\n", prog->section_name); @@ -784,8 +847,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) Elf_Data *data = obj->efile.reloc[i].data; int idx = shdr->sh_info; struct bpf_program *prog; - size_t nr_maps = obj->maps_buf_sz / - sizeof(struct bpf_map_def); + size_t nr_maps = obj->nr_maps; if (shdr->sh_type != SHT_REL) { pr_warning("internal error at %d\n", __LINE__); @@ -860,13 +922,73 @@ static int bpf_program__load(struct bpf_program *prog, char *license, u32 kern_version) { - int err, fd; + int err = 0, fd, i; - err = load_program(prog->insns, prog->insns_cnt, - license, kern_version, &fd); - if (!err) - prog->fd = fd; + if (prog->instances.nr < 0 || !prog->instances.fds) { + if (prog->preprocessor) { + pr_warning("Internal error: can't load program '%s'\n", + prog->section_name); + return -LIBBPF_ERRNO__INTERNAL; + } + + prog->instances.fds = malloc(sizeof(int)); + if (!prog->instances.fds) { + pr_warning("Not enough memory for BPF fds\n"); + return -ENOMEM; + } + prog->instances.nr = 1; + prog->instances.fds[0] = -1; + } + + if (!prog->preprocessor) { + if (prog->instances.nr != 1) { + pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", + prog->section_name, prog->instances.nr); + } + err = load_program(prog->insns, prog->insns_cnt, + license, kern_version, &fd); + if (!err) + prog->instances.fds[0] = fd; + goto out; + } + + for (i = 0; i < prog->instances.nr; i++) { + struct bpf_prog_prep_result result; + bpf_program_prep_t preprocessor = prog->preprocessor; + + bzero(&result, sizeof(result)); + err = preprocessor(prog, i, prog->insns, + prog->insns_cnt, &result); + if (err) { + pr_warning("Preprocessing the %dth instance of program '%s' failed\n", + i, prog->section_name); + goto out; + } + + if (!result.new_insn_ptr || !result.new_insn_cnt) { + pr_debug("Skip loading the %dth instance of program '%s'\n", + i, prog->section_name); + prog->instances.fds[i] = -1; + if (result.pfd) + *result.pfd = -1; + continue; + } + + err = load_program(result.new_insn_ptr, + result.new_insn_cnt, + license, kern_version, &fd); + + if (err) { + pr_warning("Loading the %dth instance of program '%s' failed\n", + i, prog->section_name); + goto out; + } + if (result.pfd) + *result.pfd = fd; + prog->instances.fds[i] = fd; + } +out: if (err) pr_warning("failed to load program '%s'\n", prog->section_name); @@ -970,10 +1092,8 @@ int bpf_object__unload(struct bpf_object *obj) if (!obj) return -EINVAL; - for (i = 0; i < obj->nr_map_fds; i++) - zclose(obj->map_fds[i]); - zfree(&obj->map_fds); - obj->nr_map_fds = 0; + for (i = 0; i < obj->nr_maps; i++) + zclose(obj->maps[i].fd); for (i = 0; i < obj->nr_programs; i++) bpf_program__unload(&obj->programs[i]); @@ -1016,7 +1136,16 @@ void bpf_object__close(struct bpf_object *obj) bpf_object__elf_finish(obj); bpf_object__unload(obj); - zfree(&obj->maps_buf); + for (i = 0; i < obj->nr_maps; i++) { + zfree(&obj->maps[i].name); + if (obj->maps[i].clear_priv) + obj->maps[i].clear_priv(&obj->maps[i], + obj->maps[i].priv); + obj->maps[i].priv = NULL; + obj->maps[i].clear_priv = NULL; + } + zfree(&obj->maps); + obj->nr_maps = 0; if (obj->programs && obj->nr_programs) { for (i = 0; i < obj->nr_programs; i++) @@ -1121,5 +1250,142 @@ const char *bpf_program__title(struct bpf_program *prog, bool needs_copy) int bpf_program__fd(struct bpf_program *prog) { - return prog->fd; + return bpf_program__nth_fd(prog, 0); +} + +int bpf_program__set_prep(struct bpf_program *prog, int nr_instances, + bpf_program_prep_t prep) +{ + int *instances_fds; + + if (nr_instances <= 0 || !prep) + return -EINVAL; + + if (prog->instances.nr > 0 || prog->instances.fds) { + pr_warning("Can't set pre-processor after loading\n"); + return -EINVAL; + } + + instances_fds = malloc(sizeof(int) * nr_instances); + if (!instances_fds) { + pr_warning("alloc memory failed for fds\n"); + return -ENOMEM; + } + + /* fill all fd with -1 */ + memset(instances_fds, -1, sizeof(int) * nr_instances); + + prog->instances.nr = nr_instances; + prog->instances.fds = instances_fds; + prog->preprocessor = prep; + return 0; +} + +int bpf_program__nth_fd(struct bpf_program *prog, int n) +{ + int fd; + + if (n >= prog->instances.nr || n < 0) { + pr_warning("Can't get the %dth fd from program %s: only %d instances\n", + n, prog->section_name, prog->instances.nr); + return -EINVAL; + } + + fd = prog->instances.fds[n]; + if (fd < 0) { + pr_warning("%dth instance of program '%s' is invalid\n", + n, prog->section_name); + return -ENOENT; + } + + return fd; +} + +int bpf_map__get_fd(struct bpf_map *map) +{ + if (!map) + return -EINVAL; + + return map->fd; +} + +int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef) +{ + if (!map || !pdef) + return -EINVAL; + + *pdef = map->def; + return 0; +} + +const char *bpf_map__get_name(struct bpf_map *map) +{ + if (!map) + return NULL; + return map->name; +} + +int bpf_map__set_private(struct bpf_map *map, void *priv, + bpf_map_clear_priv_t clear_priv) +{ + if (!map) + return -EINVAL; + + if (map->priv) { + if (map->clear_priv) + map->clear_priv(map, map->priv); + } + + map->priv = priv; + map->clear_priv = clear_priv; + return 0; +} + +int bpf_map__get_private(struct bpf_map *map, void **ppriv) +{ + if (!map) + return -EINVAL; + + if (ppriv) + *ppriv = map->priv; + return 0; +} + +struct bpf_map * +bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) +{ + size_t idx; + struct bpf_map *s, *e; + + if (!obj || !obj->maps) + return NULL; + + s = obj->maps; + e = obj->maps + obj->nr_maps; + + if (prev == NULL) + return s; + + if ((prev < s) || (prev >= e)) { + pr_warning("error in %s: map handler doesn't belong to object\n", + __func__); + return NULL; + } + + idx = (prev - obj->maps) + 1; + if (idx >= obj->nr_maps) + return NULL; + return &obj->maps[idx]; +} + +struct bpf_map * +bpf_object__get_map_by_name(struct bpf_object *obj, const char *name) +{ + struct bpf_map *pos; + + bpf_map__for_each(pos, obj) { + if (pos->name && !strcmp(pos->name, name)) + return pos; + } + return NULL; } diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index c9a9aef28..a51594c7b 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -88,6 +88,70 @@ const char *bpf_program__title(struct bpf_program *prog, bool needs_copy); int bpf_program__fd(struct bpf_program *prog); +struct bpf_insn; + +/* + * Libbpf allows callers to adjust BPF programs before being loaded + * into kernel. One program in an object file can be transform into + * multiple variants to be attached to different code. + * + * bpf_program_prep_t, bpf_program__set_prep and bpf_program__nth_fd + * are APIs for this propose. + * + * - bpf_program_prep_t: + * It defines 'preprocessor', which is a caller defined function + * passed to libbpf through bpf_program__set_prep(), and will be + * called before program is loaded. The processor should adjust + * the program one time for each instances according to the number + * passed to it. + * + * - bpf_program__set_prep: + * Attachs a preprocessor to a BPF program. The number of instances + * whould be created is also passed through this function. + * + * - bpf_program__nth_fd: + * After the program is loaded, get resuling fds from bpf program for + * each instances. + * + * If bpf_program__set_prep() is not used, the program whould be loaded + * without adjustment during bpf_object__load(). The program has only + * one instance. In this case bpf_program__fd(prog) is equal to + * bpf_program__nth_fd(prog, 0). + */ + +struct bpf_prog_prep_result { + /* + * If not NULL, load new instruction array. + * If set to NULL, don't load this instance. + */ + struct bpf_insn *new_insn_ptr; + int new_insn_cnt; + + /* If not NULL, result fd is set to it */ + int *pfd; +}; + +/* + * Parameters of bpf_program_prep_t: + * - prog: The bpf_program being loaded. + * - n: Index of instance being generated. + * - insns: BPF instructions array. + * - insns_cnt:Number of instructions in insns. + * - res: Output parameter, result of transformation. + * + * Return value: + * - Zero: pre-processing success. + * - Non-zero: pre-processing, stop loading. + */ +typedef int (*bpf_program_prep_t)(struct bpf_program *prog, int n, + struct bpf_insn *insns, int insns_cnt, + struct bpf_prog_prep_result *res); + +int bpf_program__set_prep(struct bpf_program *prog, int nr_instance, + bpf_program_prep_t prep); + +int bpf_program__nth_fd(struct bpf_program *prog, int n); + /* * We don't need __attribute__((packed)) now since it is * unnecessary for 'bpf_map_def' because they are all aligned. @@ -101,4 +165,28 @@ struct bpf_map_def { unsigned int max_entries; }; +/* + * There is another 'struct bpf_map' in include/linux/map.h. However, + * it is not a uapi header so no need to consider name clash. + */ +struct bpf_map; +struct bpf_map * +bpf_object__get_map_by_name(struct bpf_object *obj, const char *name); + +struct bpf_map * +bpf_map__next(struct bpf_map *map, struct bpf_object *obj); +#define bpf_map__for_each(pos, obj) \ + for ((pos) = bpf_map__next(NULL, (obj)); \ + (pos) != NULL; \ + (pos) = bpf_map__next((pos), (obj))) + +int bpf_map__get_fd(struct bpf_map *map); +int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef); +const char *bpf_map__get_name(struct bpf_map *map); + +typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); +int bpf_map__set_private(struct bpf_map *map, void *priv, + bpf_map_clear_priv_t clear_priv); +int bpf_map__get_private(struct bpf_map *map, void **ppriv); + #endif |