From 3600abb9797a8dc17275938e98efe6724092fec0 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Thu, 24 Sep 2026 03:10:36 +0000 Subject: [PATCH] libbpf: Support pointers to static functions in data when linking A pointer to a static function in data, e.g. static int (* const handlers[])(void *ctx) = { foo, bar }; is R_BPF_64_ABS64 relocation against .text section symbol with the offset of the function stored in place. The linker rejects it: relocation against STT_SECTION in non-exec section is not supported! so an object with a table of static functions cannot go through 'bpftool gen object', which all selftests do. Functions move by the offset of input .text in the output section. Add it to the pointer. Swap bytes if the object is of foreign endianness, since data sections are kept in the byte order of the object. Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20260924031042.1690890-12-alexei.starovoitov@gmail.com --- src/linker.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/linker.c b/src/linker.c index 78f92c3..53f64a1 100644 --- a/src/linker.c +++ b/src/linker.c @@ -2274,6 +2274,24 @@ static int linker_append_elf_relos(struct bpf_linker *linker, struct src_obj *ob insn->imm += sec->dst_off / sizeof(struct bpf_insn); else insn->imm += sec->dst_off; + } else if (sym_type == R_BPF_64_ABS64 && + (sec->shdr->sh_flags & SHF_EXECINSTR)) { + /* + * A pointer to a static function in a data section, + * which is stored in place as an offset of the + * function in its section. Data sections are kept + * in the byte order of the object. + */ + void *ptr = dst_linked_sec->raw_data + dst_rel->r_offset; + __u64 off; + + memcpy(&off, ptr, sizeof(off)); + if (linker->swapped_endian) + off = bswap_64(off); + off += sec->dst_off; + if (linker->swapped_endian) + off = bswap_64(off); + memcpy(ptr, &off, sizeof(off)); } else { pr_warn("relocation against STT_SECTION in non-exec section is not supported!\n"); return -EINVAL;