]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bpf: Add function to extract program source info
authorKumar Kartikeya Dwivedi <memxor@gmail.com>
Thu, 3 Jul 2025 20:48:09 +0000 (13:48 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 4 Jul 2025 02:30:06 +0000 (19:30 -0700)
Prepare a function for use in future patches that can extract the file
info, line info, and the source line number for a given BPF program
provided it's program counter.

Only the basename of the file path is provided, given it can be
excessively long in some cases.

This will be used in later patches to print source info to the BPF
stream.

Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20250703204818.925464-4-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/linux/bpf.h
kernel/bpf/core.c

index f61aeccb23c3ef1f9ef585a9dc232745bb52a566..c3802af11bac738a9e5aa29448912c99c231676b 100644 (file)
@@ -3661,4 +3661,7 @@ static inline bool bpf_is_subprog(const struct bpf_prog *prog)
        return prog->aux->func_idx != 0;
 }
 
+int bpf_prog_get_file_line(struct bpf_prog *prog, unsigned long ip, const char **filep,
+                          const char **linep, int *nump);
+
 #endif /* _LINUX_BPF_H */
index f0def24573ae9ffe40f85c14893bcbc56100894f..2dc5b846ae501d0729ab5007d4799b1e16665b85 100644 (file)
@@ -3213,3 +3213,50 @@ EXPORT_SYMBOL(bpf_stats_enabled_key);
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(xdp_exception);
 EXPORT_TRACEPOINT_SYMBOL_GPL(xdp_bulk_tx);
+
+#ifdef CONFIG_BPF_SYSCALL
+
+int bpf_prog_get_file_line(struct bpf_prog *prog, unsigned long ip, const char **filep,
+                          const char **linep, int *nump)
+{
+       int idx = -1, insn_start, insn_end, len;
+       struct bpf_line_info *linfo;
+       void **jited_linfo;
+       struct btf *btf;
+
+       btf = prog->aux->btf;
+       linfo = prog->aux->linfo;
+       jited_linfo = prog->aux->jited_linfo;
+
+       if (!btf || !linfo || !jited_linfo)
+               return -EINVAL;
+       len = prog->aux->func ? prog->aux->func[prog->aux->func_idx]->len : prog->len;
+
+       linfo = &prog->aux->linfo[prog->aux->linfo_idx];
+       jited_linfo = &prog->aux->jited_linfo[prog->aux->linfo_idx];
+
+       insn_start = linfo[0].insn_off;
+       insn_end = insn_start + len;
+
+       for (int i = 0; i < prog->aux->nr_linfo &&
+            linfo[i].insn_off >= insn_start && linfo[i].insn_off < insn_end; i++) {
+               if (jited_linfo[i] >= (void *)ip)
+                       break;
+               idx = i;
+       }
+
+       if (idx == -1)
+               return -ENOENT;
+
+       /* Get base component of the file path. */
+       *filep = btf_name_by_offset(btf, linfo[idx].file_name_off);
+       *filep = kbasename(*filep);
+       /* Obtain the source line, and strip whitespace in prefix. */
+       *linep = btf_name_by_offset(btf, linfo[idx].line_off);
+       while (isspace(**linep))
+               *linep += 1;
+       *nump = BPF_LINE_INFO_LINE_NUM(linfo[idx].line_col);
+       return 0;
+}
+
+#endif