Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: print correct offset for pseudo calls in disasm_insn()

Adjust disasm_helpers.c:disasm_insn() to account for the following
part of the verifier.c:jit_subprogs:

for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
/* ... */
if (!bpf_pseudo_call(insn))
continue;
insn->off = env->insn_aux_data[i].call_imm;
subprog = find_subprog(env, i + insn->off + 1);
insn->imm = subprog;
}

Where verifier moves offset of the subprogram to the insn->off field.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240722233844.1406874-6-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>

authored by

Eduard Zingerman and committed by
Andrii Nakryiko
203e6aba 424ebaa3

+18
+18
tools/testing/selftests/bpf/disasm_helpers.c
··· 4 4 #include "disasm.h" 5 5 6 6 struct print_insn_context { 7 + char scratch[16]; 7 8 char *buf; 8 9 size_t sz; 9 10 }; ··· 19 18 va_end(args); 20 19 } 21 20 21 + static const char *print_call_cb(void *private_data, const struct bpf_insn *insn) 22 + { 23 + struct print_insn_context *ctx = private_data; 24 + 25 + /* For pseudo calls verifier.c:jit_subprogs() hides original 26 + * imm to insn->off and changes insn->imm to be an index of 27 + * the subprog instead. 28 + */ 29 + if (insn->src_reg == BPF_PSEUDO_CALL) { 30 + snprintf(ctx->scratch, sizeof(ctx->scratch), "%+d", insn->off); 31 + return ctx->scratch; 32 + } 33 + 34 + return NULL; 35 + } 36 + 22 37 struct bpf_insn *disasm_insn(struct bpf_insn *insn, char *buf, size_t buf_sz) 23 38 { 24 39 struct print_insn_context ctx = { ··· 43 26 }; 44 27 struct bpf_insn_cbs cbs = { 45 28 .cb_print = print_insn_cb, 29 + .cb_call = print_call_cb, 46 30 .private_data = &ctx, 47 31 }; 48 32 char *tmp, *pfx_end, *sfx_start;