Skip to content

Commit

Permalink
libbpf: Add support for dynamic tracepoint
Browse files Browse the repository at this point in the history
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@gmail.com>
Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Cc: Daniel Xu <dxu@dxuuu.xyz>
  • Loading branch information
laoar authored and intel-lab-lkp committed Jan 12, 2025
1 parent be339dd commit a27e9e7
Showing 1 changed file with 28 additions and 1 deletion.
29 changes: 28 additions & 1 deletion tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -11623,11 +11623,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;

Expand All @@ -11643,6 +11666,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);
Expand Down

0 comments on commit a27e9e7

Please sign in to comment.