Skip to content

Commit 7cc13ad

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
bpf: emit source code file name and line number in verifier log
As BPF applications grow in size and complexity and are separated into multiple .bpf.c files that are statically linked together, it becomes harder and harder to match verifier's BPF assembly level output to original C code. While often annotated C source code is unique enough to be able to identify the file it belongs to, quite often this is actually problematic as parts of source code can be quite generic. Long story short, it is very useful to see source code file name and line number information along with the original C code. Verifier already knows this information, we just need to output it. This patch extends verifier log with file name and line number information, emitted next to original (presumably C) source code, annotating BPF assembly output, like so: ; <original C code> @ <filename>.bpf.c:<line> If file name has directory names in it, they are stripped away. This should be fine in practice as file names tend to be pretty unique with C code anyways, and keeping log size smaller is always good. In practice this might look something like below, where some code is coming from application files, while others are from libbpf's usdt.bpf.h header file: ; if (STROBEMETA_READ( @ strobemeta_probe.bpf.c:534 5592: (79) r1 = *(u64 *)(r10 -56) ; R1_w=mem_or_null(id=1589,sz=7680) R10=fp0 5593: (7b) *(u64 *)(r10 -56) = r1 ; R1_w=mem_or_null(id=1589,sz=7680) R10=fp0 5594: (79) r3 = *(u64 *)(r10 -8) ; R3_w=scalar() R10=fp0 fp-8=mmmmmmmm ... 170: (71) r1 = *(u8 *)(r8 +15) ; frame1: R1_w=scalar(...) R8_w=map_value(map=__bpf_usdt_spec,ks=4,vs=208) 171: (67) r1 <<= 56 ; frame1: R1_w=scalar(...) 172: (c7) r1 s>>= 56 ; frame1: R1_w=scalar(smin=smin32=-128,smax=smax32=127) ; val <<= arg_spec->arg_bitshift; @ usdt.bpf.h:183 173: (67) r1 <<= 32 ; frame1: R1_w=scalar(...) 174: (77) r1 >>= 32 ; frame1: R1_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) 175: (79) r2 = *(u64 *)(r10 -8) ; frame1: R2_w=scalar() R10=fp0 fp-8=mmmmmmmm 176: (6f) r2 <<= r1 ; frame1: R1_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) R2_w=scalar() 177: (7b) *(u64 *)(r10 -8) = r2 ; frame1: R2_w=scalar(id=61) R10=fp0 fp-8_w=scalar(id=61) ; if (arg_spec->arg_signed) @ usdt.bpf.h:184 178: (bf) r3 = r2 ; frame1: R2_w=scalar(id=61) R3_w=scalar(id=61) 179: (7f) r3 >>= r1 ; frame1: R1_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) R3_w=scalar() ; if (arg_spec->arg_signed) @ usdt.bpf.h:184 180: (71) r4 = *(u8 *)(r8 +14) 181: safe log_fixup tests needed a minor adjustment as verifier log output increased a bit and that test is quite sensitive to such changes. Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/r/20240212235944.2816107-1-andrii@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 96adbf7 commit 7cc13ad

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

kernel/bpf/log.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/bpf.h>
1010
#include <linux/bpf_verifier.h>
1111
#include <linux/math64.h>
12+
#include <linux/string.h>
1213

1314
#define verbose(env, fmt, args...) bpf_verifier_log_write(env, fmt, ##args)
1415

@@ -362,6 +363,8 @@ __printf(3, 4) void verbose_linfo(struct bpf_verifier_env *env,
362363
const char *prefix_fmt, ...)
363364
{
364365
const struct bpf_line_info *linfo;
366+
const struct btf *btf;
367+
const char *s, *fname;
365368

366369
if (!bpf_verifier_log_needed(&env->log))
367370
return;
@@ -378,9 +381,15 @@ __printf(3, 4) void verbose_linfo(struct bpf_verifier_env *env,
378381
va_end(args);
379382
}
380383

381-
verbose(env, "%s\n",
382-
ltrim(btf_name_by_offset(env->prog->aux->btf,
383-
linfo->line_off)));
384+
btf = env->prog->aux->btf;
385+
s = ltrim(btf_name_by_offset(btf, linfo->line_off));
386+
verbose(env, "%s", s); /* source code line */
387+
388+
s = btf_name_by_offset(btf, linfo->file_name_off);
389+
/* leave only file name */
390+
fname = strrchr(s, '/');
391+
fname = fname ? fname + 1 : s;
392+
verbose(env, " @ %s:%u\n", fname, BPF_LINE_INFO_LINE_NUM(linfo->line_col));
384393

385394
env->prev_linfo = linfo;
386395
}

tools/testing/selftests/bpf/prog_tests/log_fixup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ void test_log_fixup(void)
169169
if (test__start_subtest("bad_core_relo_trunc_none"))
170170
bad_core_relo(0, TRUNC_NONE /* full buf */);
171171
if (test__start_subtest("bad_core_relo_trunc_partial"))
172-
bad_core_relo(280, TRUNC_PARTIAL /* truncate original log a bit */);
172+
bad_core_relo(300, TRUNC_PARTIAL /* truncate original log a bit */);
173173
if (test__start_subtest("bad_core_relo_trunc_full"))
174-
bad_core_relo(220, TRUNC_FULL /* truncate also libbpf's message patch */);
174+
bad_core_relo(240, TRUNC_FULL /* truncate also libbpf's message patch */);
175175
if (test__start_subtest("bad_core_relo_subprog"))
176176
bad_core_relo_subprog();
177177
if (test__start_subtest("missing_map"))

0 commit comments

Comments
 (0)