aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-06-30 22:14:02 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-08-07 09:16:58 -0400
commit340909152ae5a588b9a77a85df35d61ec3523833 (patch)
tree649fb190e49c5f71012cb123524ca2644a8b2936
parentb62f06e81bcf28d47fe736fe2beae40f15f496be (diff)
bpf tools: Record map accessing instructions for each program
This patch records the indices of instructions which are needed to be relocated. That information is saved in the 'reloc_desc' field in 'struct bpf_program'. In the loading phase (this patch takes effect in the opening phase), the collected instructions will be replaced by map loading instructions. Since we are going to close the ELF file and clear all data at the end of the 'opening' phase, the ELF information will no longer be valid in the 'loading' phase. We have to locate the instructions before maps are loaded, instead of directly modifying the instruction. 'struct bpf_map_def' is introduced in this patch to let us know how many maps are defined in the object. This is the third part of map relocation. The principle of map relocation is described in commit message of 'bpf tools: Collect symbol table from SHT_SYMTAB section'. Signed-off-by: Wang Nan <wangnan0@huawei.com> Acked-by: Alexei Starovoitov <ast@plumgrid.com> Cc: Brendan Gregg <brendan.d.gregg@gmail.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: David Ahern <dsahern@gmail.com> Cc: He Kuang <hekuang@huawei.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Kaixu Xia <xiakaixu@huawei.com> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1435716878-189507-15-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/lib/bpf/libbpf.c124
-rw-r--r--tools/lib/bpf/libbpf.h13
2 files changed, 137 insertions, 0 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e8088f8214d1..ac69ae3bd628 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -9,6 +9,7 @@
9#include <stdlib.h> 9#include <stdlib.h>
10#include <stdio.h> 10#include <stdio.h>
11#include <stdarg.h> 11#include <stdarg.h>
12#include <inttypes.h>
12#include <string.h> 13#include <string.h>
13#include <unistd.h> 14#include <unistd.h>
14#include <fcntl.h> 15#include <fcntl.h>
@@ -88,6 +89,12 @@ struct bpf_program {
88 char *section_name; 89 char *section_name;
89 struct bpf_insn *insns; 90 struct bpf_insn *insns;
90 size_t insns_cnt; 91 size_t insns_cnt;
92
93 struct {
94 int insn_idx;
95 int map_idx;
96 } *reloc_desc;
97 int nr_reloc;
91}; 98};
92 99
93struct bpf_object { 100struct bpf_object {
@@ -127,6 +134,9 @@ static void bpf_program__exit(struct bpf_program *prog)
127 134
128 zfree(&prog->section_name); 135 zfree(&prog->section_name);
129 zfree(&prog->insns); 136 zfree(&prog->insns);
137 zfree(&prog->reloc_desc);
138
139 prog->nr_reloc = 0;
130 prog->insns_cnt = 0; 140 prog->insns_cnt = 0;
131 prog->idx = -1; 141 prog->idx = -1;
132} 142}
@@ -481,6 +491,118 @@ out:
481 return err; 491 return err;
482} 492}
483 493
494static struct bpf_program *
495bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
496{
497 struct bpf_program *prog;
498 size_t i;
499
500 for (i = 0; i < obj->nr_programs; i++) {
501 prog = &obj->programs[i];
502 if (prog->idx == idx)
503 return prog;
504 }
505 return NULL;
506}
507
508static int
509bpf_program__collect_reloc(struct bpf_program *prog,
510 size_t nr_maps, GElf_Shdr *shdr,
511 Elf_Data *data, Elf_Data *symbols)
512{
513 int i, nrels;
514
515 pr_debug("collecting relocating info for: '%s'\n",
516 prog->section_name);
517 nrels = shdr->sh_size / shdr->sh_entsize;
518
519 prog->reloc_desc = malloc(sizeof(*prog->reloc_desc) * nrels);
520 if (!prog->reloc_desc) {
521 pr_warning("failed to alloc memory in relocation\n");
522 return -ENOMEM;
523 }
524 prog->nr_reloc = nrels;
525
526 for (i = 0; i < nrels; i++) {
527 GElf_Sym sym;
528 GElf_Rel rel;
529 unsigned int insn_idx;
530 struct bpf_insn *insns = prog->insns;
531 size_t map_idx;
532
533 if (!gelf_getrel(data, i, &rel)) {
534 pr_warning("relocation: failed to get %d reloc\n", i);
535 return -EINVAL;
536 }
537
538 insn_idx = rel.r_offset / sizeof(struct bpf_insn);
539 pr_debug("relocation: insn_idx=%u\n", insn_idx);
540
541 if (!gelf_getsym(symbols,
542 GELF_R_SYM(rel.r_info),
543 &sym)) {
544 pr_warning("relocation: symbol %"PRIx64" not found\n",
545 GELF_R_SYM(rel.r_info));
546 return -EINVAL;
547 }
548
549 if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
550 pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n",
551 insn_idx, insns[insn_idx].code);
552 return -EINVAL;
553 }
554
555 map_idx = sym.st_value / sizeof(struct bpf_map_def);
556 if (map_idx >= nr_maps) {
557 pr_warning("bpf relocation: map_idx %d large than %d\n",
558 (int)map_idx, (int)nr_maps - 1);
559 return -EINVAL;
560 }
561
562 prog->reloc_desc[i].insn_idx = insn_idx;
563 prog->reloc_desc[i].map_idx = map_idx;
564 }
565 return 0;
566}
567
568static int bpf_object__collect_reloc(struct bpf_object *obj)
569{
570 int i, err;
571
572 if (!obj_elf_valid(obj)) {
573 pr_warning("Internal error: elf object is closed\n");
574 return -EINVAL;
575 }
576
577 for (i = 0; i < obj->efile.nr_reloc; i++) {
578 GElf_Shdr *shdr = &obj->efile.reloc[i].shdr;
579 Elf_Data *data = obj->efile.reloc[i].data;
580 int idx = shdr->sh_info;
581 struct bpf_program *prog;
582 size_t nr_maps = obj->maps_buf_sz /
583 sizeof(struct bpf_map_def);
584
585 if (shdr->sh_type != SHT_REL) {
586 pr_warning("internal error at %d\n", __LINE__);
587 return -EINVAL;
588 }
589
590 prog = bpf_object__find_prog_by_idx(obj, idx);
591 if (!prog) {
592 pr_warning("relocation failed: no %d section\n",
593 idx);
594 return -ENOENT;
595 }
596
597 err = bpf_program__collect_reloc(prog, nr_maps,
598 shdr, data,
599 obj->efile.symbols);
600 if (err)
601 return -EINVAL;
602 }
603 return 0;
604}
605
484static int bpf_object__validate(struct bpf_object *obj) 606static int bpf_object__validate(struct bpf_object *obj)
485{ 607{
486 if (obj->kern_version == 0) { 608 if (obj->kern_version == 0) {
@@ -511,6 +633,8 @@ __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
511 goto out; 633 goto out;
512 if (bpf_object__elf_collect(obj)) 634 if (bpf_object__elf_collect(obj))
513 goto out; 635 goto out;
636 if (bpf_object__collect_reloc(obj))
637 goto out;
514 if (bpf_object__validate(obj)) 638 if (bpf_object__validate(obj))
515 goto out; 639 goto out;
516 640
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index dc966dd9fd75..6e75acdb9112 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -30,4 +30,17 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf,
30 size_t obj_buf_sz); 30 size_t obj_buf_sz);
31void bpf_object__close(struct bpf_object *object); 31void bpf_object__close(struct bpf_object *object);
32 32
33/*
34 * We don't need __attribute__((packed)) now since it is
35 * unnecessary for 'bpf_map_def' because they are all aligned.
36 * In addition, using it will trigger -Wpacked warning message,
37 * and will be treated as an error due to -Werror.
38 */
39struct bpf_map_def {
40 unsigned int type;
41 unsigned int key_size;
42 unsigned int value_size;
43 unsigned int max_entries;
44};
45
33#endif 46#endif