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 | |
| 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')
| -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, |
