aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/bpf/libbpf.c
diff options
context:
space:
mode:
authorJoe Stringer <joe@ovn.org>2017-01-22 20:11:22 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-01-26 09:42:56 -0500
commit94e5adece8b37a23d99fb1f8a5de94b23194f387 (patch)
tree36bfbdfdb6509124a80cf23c1bd436536b603a3d /tools/lib/bpf/libbpf.c
parentd1d0e29cb7d03a6019caa125e4c0288366a4f359 (diff)
tools lib bpf: Fix map offsets in relocation
Commit 4708bbda5cb2 ("tools lib bpf: Fix maps resolution") attempted to fix map resolution by identifying the number of symbols that point to maps, and using this number to resolve each of the maps. However, during relocation the original definition of the map size was still in use. For up to two maps, the calculation was correct if there was a small difference in size between the map definition in libbpf and the one that the client library uses. However if the difference was large, particularly if more than two maps were used in the BPF program, the relocation would fail. For example, when using a map definition with size 28, with three maps, map relocation would count: (sym_offset / sizeof(struct bpf_map_def) => map_idx) (0 / 16 => 0), ie map_idx = 0 (28 / 16 => 1), ie map_idx = 1 (56 / 16 => 3), ie map_idx = 3 So, libbpf reports: libbpf: bpf relocation: map_idx 3 large than 2 Fix map relocation by checking the exact offset of maps when doing relocation. Signed-off-by: Joe Stringer <joe@ovn.org> [Allow different map size in an object] Signed-off-by: Wang Nan <wangnan0@huawei.com> Cc: Alexei Starovoitov <ast@fb.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: netdev@vger.kernel.org Fixes: 4708bbda5cb2 ("tools lib bpf: Fix maps resolution") Link: http://lkml.kernel.org/r/20170123011128.26534-2-joe@ovn.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r--tools/lib/bpf/libbpf.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 84e6b35da4bd..671d5ad07cf1 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -779,7 +779,7 @@ static int
779bpf_program__collect_reloc(struct bpf_program *prog, 779bpf_program__collect_reloc(struct bpf_program *prog,
780 size_t nr_maps, GElf_Shdr *shdr, 780 size_t nr_maps, GElf_Shdr *shdr,
781 Elf_Data *data, Elf_Data *symbols, 781 Elf_Data *data, Elf_Data *symbols,
782 int maps_shndx) 782 int maps_shndx, struct bpf_map *maps)
783{ 783{
784 int i, nrels; 784 int i, nrels;
785 785
@@ -829,7 +829,15 @@ bpf_program__collect_reloc(struct bpf_program *prog,
829 return -LIBBPF_ERRNO__RELOC; 829 return -LIBBPF_ERRNO__RELOC;
830 } 830 }
831 831
832 map_idx = sym.st_value / sizeof(struct bpf_map_def); 832 /* TODO: 'maps' is sorted. We can use bsearch to make it faster. */
833 for (map_idx = 0; map_idx < nr_maps; map_idx++) {
834 if (maps[map_idx].offset == sym.st_value) {
835 pr_debug("relocation: find map %zd (%s) for insn %u\n",
836 map_idx, maps[map_idx].name, insn_idx);
837 break;
838 }
839 }
840
833 if (map_idx >= nr_maps) { 841 if (map_idx >= nr_maps) {
834 pr_warning("bpf relocation: map_idx %d large than %d\n", 842 pr_warning("bpf relocation: map_idx %d large than %d\n",
835 (int)map_idx, (int)nr_maps - 1); 843 (int)map_idx, (int)nr_maps - 1);
@@ -953,7 +961,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
953 err = bpf_program__collect_reloc(prog, nr_maps, 961 err = bpf_program__collect_reloc(prog, nr_maps,
954 shdr, data, 962 shdr, data,
955 obj->efile.symbols, 963 obj->efile.symbols,
956 obj->efile.maps_shndx); 964 obj->efile.maps_shndx,
965 obj->maps);
957 if (err) 966 if (err)
958 return err; 967 return err;
959 } 968 }