summaryrefslogtreecommitdiff
path: root/tools/lib
diff options
context:
space:
mode:
authorEmil Tsalapatis <emil@etsalapatis.com>2026-02-17 15:43:45 -0500
committerAndrii Nakryiko <andrii@kernel.org>2026-02-17 14:20:24 -0800
commitd7988720ef3ea5926f1b886b27eddf08abbadba0 (patch)
tree7f6d1f60f28259557ee924b37ce7e84fab4f13a9 /tools/lib
parent7cefbb47ccb2ded187f72db17a46f19d7cf4bf08 (diff)
libbpf: Delay feature gate check until object prepare time
Commit 728ff167910e ("libbpf: Add gating for arena globals relocation feature") adds a feature gate check that loads a map and BPF program to test the running kernel supports large direct offsets for LDIMM64 instructions. This check is currently used to calculate arena symbol offsets during bpf_object__collect_relos, itself called by bpf_object_open. However, the program calling bpf_object_open may not have the permissions to load maps and programs. This is the case with the BPF selftests, where bpftool is invoked at compilation time during skeleton generation. This causes errors as the feature gate unexpectedly fails with -EPERM. Avoid this by moving all the use of the FEAT_LDIMM64_FULL_RANGE_OFF feature gate to BPF object preparation time instead. Fixes: 728ff167910e ("libbpf: Add gating for arena globals relocation feature") Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20260217204345.548648-3-emil@etsalapatis.com
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/bpf/libbpf.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 93e59ed8d9a1..0be7017800fe 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3009,12 +3009,6 @@ static int init_arena_map_data(struct bpf_object *obj, struct bpf_map *map,
memcpy(obj->arena_data, data, data_sz);
obj->arena_data_sz = data_sz;
- /* place globals at the end of the arena (if supported) */
- if (kernel_supports(obj, FEAT_LDIMM64_FULL_RANGE_OFF))
- obj->arena_data_off = mmap_sz - data_alloc_sz;
- else
- obj->arena_data_off = 0;
-
/* make bpf_map__init_value() work for ARENA maps */
map->mmaped = obj->arena_data;
@@ -4672,7 +4666,7 @@ static int bpf_program__record_reloc(struct bpf_program *prog,
reloc_desc->type = RELO_DATA;
reloc_desc->insn_idx = insn_idx;
reloc_desc->map_idx = obj->arena_map_idx;
- reloc_desc->sym_off = sym->st_value + obj->arena_data_off;
+ reloc_desc->sym_off = sym->st_value;
map = &obj->maps[obj->arena_map_idx];
pr_debug("prog '%s': found arena map %d (%s, sec %d, off %zu) for insn %u\n",
@@ -6386,6 +6380,10 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog)
case RELO_DATA:
map = &obj->maps[relo->map_idx];
insn[1].imm = insn[0].imm + relo->sym_off;
+
+ if (relo->map_idx == obj->arena_map_idx)
+ insn[1].imm += obj->arena_data_off;
+
if (obj->gen_loader) {
insn[0].src_reg = BPF_PSEUDO_MAP_IDX_VALUE;
insn[0].imm = relo->map_idx;
@@ -7387,6 +7385,14 @@ static int bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_pat
bpf_object__sort_relos(obj);
}
+ /* place globals at the end of the arena (if supported) */
+ if (obj->arena_map_idx >= 0 && kernel_supports(obj, FEAT_LDIMM64_FULL_RANGE_OFF)) {
+ struct bpf_map *arena_map = &obj->maps[obj->arena_map_idx];
+
+ obj->arena_data_off = bpf_map_mmap_sz(arena_map) -
+ roundup(obj->arena_data_sz, sysconf(_SC_PAGE_SIZE));
+ }
+
/* Before relocating calls pre-process relocations and mark
* few ld_imm64 instructions that points to subprogs.
* Otherwise bpf_object__reloc_code() later would have to consider