diff options
author | Wang Nan <wangnan0@huawei.com> | 2015-11-27 03:47:36 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-11-27 19:59:53 -0500 |
commit | 561bbccac72d08babafaa33fd7fa9100ec4c9fb6 (patch) | |
tree | b7dd063a6d2acc55d05ebfedf3396fcfbd9640bd /tools/lib/bpf | |
parent | 9d759a9b4ac2690077d8b21258e6e95c3e34bfa9 (diff) |
tools lib bpf: Extract and collect map names from BPF object file
This patch collects name of maps in BPF object files and saves them into
'maps' field in 'struct bpf_object'. 'bpf_object__get_map_by_name' is
introduced to retrive fd and definitions of a map through its name.
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: He Kuang <hekuang@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1448614067-197576-3-git-send-email-wangnan0@huawei.com
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib/bpf')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 65 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.h | 3 |
2 files changed, 65 insertions, 3 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index f50982579aa8..a298614ad091 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -165,6 +165,7 @@ struct bpf_program { | |||
165 | 165 | ||
166 | struct bpf_map { | 166 | struct bpf_map { |
167 | int fd; | 167 | int fd; |
168 | char *name; | ||
168 | struct bpf_map_def def; | 169 | struct bpf_map_def def; |
169 | void *priv; | 170 | void *priv; |
170 | bpf_map_clear_priv_t clear_priv; | 171 | bpf_map_clear_priv_t clear_priv; |
@@ -526,12 +527,46 @@ bpf_object__init_maps(struct bpf_object *obj, void *data, | |||
526 | return 0; | 527 | return 0; |
527 | } | 528 | } |
528 | 529 | ||
530 | static void | ||
531 | bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx) | ||
532 | { | ||
533 | int i; | ||
534 | Elf_Data *symbols = obj->efile.symbols; | ||
535 | |||
536 | if (!symbols || maps_shndx < 0) | ||
537 | return; | ||
538 | |||
539 | for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) { | ||
540 | GElf_Sym sym; | ||
541 | size_t map_idx; | ||
542 | const char *map_name; | ||
543 | |||
544 | if (!gelf_getsym(symbols, i, &sym)) | ||
545 | continue; | ||
546 | if (sym.st_shndx != maps_shndx) | ||
547 | continue; | ||
548 | |||
549 | map_name = elf_strptr(obj->efile.elf, | ||
550 | obj->efile.ehdr.e_shstrndx, | ||
551 | sym.st_name); | ||
552 | map_idx = sym.st_value / sizeof(struct bpf_map_def); | ||
553 | if (map_idx >= obj->nr_maps) { | ||
554 | pr_warning("index of map \"%s\" is buggy: %zu > %zu\n", | ||
555 | map_name, map_idx, obj->nr_maps); | ||
556 | continue; | ||
557 | } | ||
558 | obj->maps[map_idx].name = strdup(map_name); | ||
559 | pr_debug("map %zu is \"%s\"\n", map_idx, | ||
560 | obj->maps[map_idx].name); | ||
561 | } | ||
562 | } | ||
563 | |||
529 | static int bpf_object__elf_collect(struct bpf_object *obj) | 564 | static int bpf_object__elf_collect(struct bpf_object *obj) |
530 | { | 565 | { |
531 | Elf *elf = obj->efile.elf; | 566 | Elf *elf = obj->efile.elf; |
532 | GElf_Ehdr *ep = &obj->efile.ehdr; | 567 | GElf_Ehdr *ep = &obj->efile.ehdr; |
533 | Elf_Scn *scn = NULL; | 568 | Elf_Scn *scn = NULL; |
534 | int idx = 0, err = 0; | 569 | int idx = 0, err = 0, maps_shndx = -1; |
535 | 570 | ||
536 | /* Elf is corrupted/truncated, avoid calling elf_strptr. */ | 571 | /* Elf is corrupted/truncated, avoid calling elf_strptr. */ |
537 | if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { | 572 | if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { |
@@ -581,10 +616,11 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
581 | err = bpf_object__init_kversion(obj, | 616 | err = bpf_object__init_kversion(obj, |
582 | data->d_buf, | 617 | data->d_buf, |
583 | data->d_size); | 618 | data->d_size); |
584 | else if (strcmp(name, "maps") == 0) | 619 | else if (strcmp(name, "maps") == 0) { |
585 | err = bpf_object__init_maps(obj, data->d_buf, | 620 | err = bpf_object__init_maps(obj, data->d_buf, |
586 | data->d_size); | 621 | data->d_size); |
587 | else if (sh.sh_type == SHT_SYMTAB) { | 622 | maps_shndx = idx; |
623 | } else if (sh.sh_type == SHT_SYMTAB) { | ||
588 | if (obj->efile.symbols) { | 624 | if (obj->efile.symbols) { |
589 | pr_warning("bpf: multiple SYMTAB in %s\n", | 625 | pr_warning("bpf: multiple SYMTAB in %s\n", |
590 | obj->path); | 626 | obj->path); |
@@ -625,6 +661,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
625 | if (err) | 661 | if (err) |
626 | goto out; | 662 | goto out; |
627 | } | 663 | } |
664 | |||
665 | if (maps_shndx >= 0) | ||
666 | bpf_object__init_maps_name(obj, maps_shndx); | ||
628 | out: | 667 | out: |
629 | return err; | 668 | return err; |
630 | } | 669 | } |
@@ -1086,6 +1125,7 @@ void bpf_object__close(struct bpf_object *obj) | |||
1086 | bpf_object__unload(obj); | 1125 | bpf_object__unload(obj); |
1087 | 1126 | ||
1088 | for (i = 0; i < obj->nr_maps; i++) { | 1127 | for (i = 0; i < obj->nr_maps; i++) { |
1128 | zfree(&obj->maps[i].name); | ||
1089 | if (obj->maps[i].clear_priv) | 1129 | if (obj->maps[i].clear_priv) |
1090 | obj->maps[i].clear_priv(&obj->maps[i], | 1130 | obj->maps[i].clear_priv(&obj->maps[i], |
1091 | obj->maps[i].priv); | 1131 | obj->maps[i].priv); |
@@ -1266,6 +1306,13 @@ int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef) | |||
1266 | return 0; | 1306 | return 0; |
1267 | } | 1307 | } |
1268 | 1308 | ||
1309 | const char *bpf_map__get_name(struct bpf_map *map) | ||
1310 | { | ||
1311 | if (!map) | ||
1312 | return NULL; | ||
1313 | return map->name; | ||
1314 | } | ||
1315 | |||
1269 | int bpf_map__set_private(struct bpf_map *map, void *priv, | 1316 | int bpf_map__set_private(struct bpf_map *map, void *priv, |
1270 | bpf_map_clear_priv_t clear_priv) | 1317 | bpf_map_clear_priv_t clear_priv) |
1271 | { | 1318 | { |
@@ -1318,3 +1365,15 @@ bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) | |||
1318 | return NULL; | 1365 | return NULL; |
1319 | return &obj->maps[idx]; | 1366 | return &obj->maps[idx]; |
1320 | } | 1367 | } |
1368 | |||
1369 | struct bpf_map * | ||
1370 | bpf_object__get_map_by_name(struct bpf_object *obj, const char *name) | ||
1371 | { | ||
1372 | struct bpf_map *pos; | ||
1373 | |||
1374 | bpf_map__for_each(pos, obj) { | ||
1375 | if (strcmp(pos->name, name) == 0) | ||
1376 | return pos; | ||
1377 | } | ||
1378 | return NULL; | ||
1379 | } | ||
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index ef631255dfaa..a51594c7b518 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h | |||
@@ -170,6 +170,8 @@ struct bpf_map_def { | |||
170 | * it is not a uapi header so no need to consider name clash. | 170 | * it is not a uapi header so no need to consider name clash. |
171 | */ | 171 | */ |
172 | struct bpf_map; | 172 | struct bpf_map; |
173 | struct bpf_map * | ||
174 | bpf_object__get_map_by_name(struct bpf_object *obj, const char *name); | ||
173 | 175 | ||
174 | struct bpf_map * | 176 | struct bpf_map * |
175 | bpf_map__next(struct bpf_map *map, struct bpf_object *obj); | 177 | bpf_map__next(struct bpf_map *map, struct bpf_object *obj); |
@@ -180,6 +182,7 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj); | |||
180 | 182 | ||
181 | int bpf_map__get_fd(struct bpf_map *map); | 183 | int bpf_map__get_fd(struct bpf_map *map); |
182 | int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef); | 184 | int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef); |
185 | const char *bpf_map__get_name(struct bpf_map *map); | ||
183 | 186 | ||
184 | typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); | 187 | typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); |
185 | int bpf_map__set_private(struct bpf_map *map, void *priv, | 188 | int bpf_map__set_private(struct bpf_map *map, void *priv, |