Dynamic tracepoints can be created using debugfs, perf or similar tools. For example: $ perf probe -a 'tcp_listendrop sk' This command creates a new tracepoint under debugfs: $ ls /sys/kernel/debug/tracing/events/probe/tcp_listendrop/ enable filter format hist id trigger Notably, the probed function tcp_listendrop() is an inlined kernel function. Although this dynamic tracepoint appears as a tracepoint, it is internally implemented as a kprobe. Therefore, if we want to attach a bpf prog to it, the bpf prog must be loaded as a kprobe prog. The primary motivation for adding support for dynamic tracepoints is to simplify tracing of inlined kernel functions using BPF tools, such as bpftrace. By leveraging tools like perf, users can create a dynamic tracepoint for an inlined kernel function and then attach a BPF program to it. To achieve this, a new section, SEC("kprobe/SUBSYSTEM/PROBE"), has been introduced. Suggested-by: Jiri Olsa <olsajiri@xxxxxxxxx> Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> Cc: Daniel Xu <dxu@xxxxxxxxx> --- tools/lib/bpf/libbpf.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 66173ddb5a2d..23ea9272491b 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -11600,11 +11600,34 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog, return libbpf_err_ptr(err); } +/* A dynamic tracepoint: "kprobe/SUBSYSTEM/PROBE" */ +static int attach_dynamic_tracepoint(const struct bpf_program *prog, const char *func_name, + struct bpf_link **link) +{ + char *tp_subsys, *tp_name; + + tp_subsys = strdup(func_name); + if (!tp_subsys) + return -ENOMEM; + + tp_name = strchr(tp_subsys, '/'); + if (!tp_name) { + free(tp_subsys); + return -EINVAL; + } + + *tp_name = '\0'; + tp_name++; + *link = bpf_program__attach_tracepoint(prog, tp_subsys, tp_name); + free(tp_subsys); + return libbpf_get_error(*link); +} + static int attach_kprobe(const struct bpf_program *prog, long cookie, struct bpf_link **link) { DECLARE_LIBBPF_OPTS(bpf_kprobe_opts, opts); + const char *func_name, *dynamic_tp; unsigned long offset = 0; - const char *func_name; char *func; int n; @@ -11620,6 +11643,10 @@ static int attach_kprobe(const struct bpf_program *prog, long cookie, struct bpf else func_name = prog->sec_name + sizeof("kprobe/") - 1; + dynamic_tp = strchr(func_name, '/'); + if (dynamic_tp) + return attach_dynamic_tracepoint(prog, func_name, link); + n = sscanf(func_name, "%m[a-zA-Z0-9_.]+%li", &func, &offset); if (n < 1) { pr_warn("kprobe name is invalid: %s\n", func_name); -- 2.43.5