diff options
| author | Mykyta Yatsenko <yatsenko@meta.com> | 2026-05-18 08:23:16 -0700 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2026-07-28 07:18:48 -0400 |
| commit | eadc0725ab8d38c05148fce49f8d5c6a0e01f062 (patch) | |
| tree | 2ca91ce64b7c929e6cf9f593a16e988ba4cfe4a9 /kernel/trace | |
| parent | f8c9b3051ded5a397172aee79271cc46529ca8f2 (diff) | |
| download | linux-next-eadc0725ab8d38c05148fce49f8d5c6a0e01f062.tar.gz linux-next-eadc0725ab8d38c05148fce49f8d5c6a0e01f062.zip | |
tracing: Expose tracepoint BTF ids via tracefs
Add events/<sys>/<event>/btf_ids, a per-template file that exposes
the BTF ids resolve_btfids fills in for each tracepoint:
btf_obj_id BTF object owning the ids below
raw_btf_id FUNC_PROTO of __bpf_trace_<call> (named args), consumed
by raw_tp / tp_btf BPF programs
tp_btf_id trace_event_raw_<call> ring-buffer record, consumed by
classic BPF_PROG_TYPE_TRACEPOINT programs
DECLARE_EVENT_CLASS now emits a 2-entry BTF_ID_LIST (FUNC __bpf_trace_*
and STRUCT trace_event_raw_*) and stores the pointer in
trace_event_class.
Per-syscall events under syscalls/ share the handcrafted classes
event_class_syscall_{enter,exit} instead of going through
DECLARE_EVENT_CLASS. Wire those classes to the BTF id lists
generated for sys_enter / sys_exit so all ~700 per-syscall
events expose the shared dispatcher prototype and record.
The per-syscall events do not own their own tracepoint
(they share sys_enter/sys_exit), so raw_btf_id is reported as 0
on those events; the meaningful raw_btf_id is exposed on
raw_syscalls/sys_{enter,exit}/btf_ids where raw_tp / tp_btf
programs can actually attach.
Link: https://patch.msgid.link/20260518-generic_tracepoint-v2-2-b755a5cf67bb@meta.com
Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/trace_events.c | 80 | ||||
| -rw-r--r-- | kernel/trace/trace_syscalls.c | 17 |
2 files changed, 96 insertions, 1 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 956692856fa8..e0449e648871 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -22,6 +22,7 @@ #include <linux/sort.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/btf.h> #include <trace/events/sched.h> #include <trace/syscall.h> @@ -2202,6 +2203,61 @@ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) } #endif +#ifdef CONFIG_BPF_EVENTS +static ssize_t +event_btf_ids_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + struct trace_event_file *file; + struct trace_event_call *call; + const struct btf_type *t; + struct module *mod = NULL; + u32 raw_id = 0, tp_id = 0, obj_id = 0; + const u32 *ids; + struct btf *btf; + char buf[128]; + int len; + + /* Module unload could free call->class and ids[] mid-read. */ + scoped_guard(mutex, &event_mutex) { + file = event_file_file(filp); + if (!file) + return -ENODEV; + + call = file->event_call; + ids = call->class->btf_ids; + if (!ids) + return -ENOENT; + if (!(call->flags & TRACE_EVENT_FL_DYNAMIC)) + mod = (struct module *)call->module; + + btf = btf_get_module_btf(mod); + if (IS_ERR_OR_NULL(btf)) + return -ENOENT; + + /* Module-local ids in ids[] need base+local relocation. */ + tp_id = btf_relocate_id(btf, ids[1]); + + /* + * Without FL_TRACEPOINT the dispatcher is shared (e.g. all + * per-syscall events fan out from __bpf_trace_sys_enter), so + * raw_btf_id has no per-event attach point — report 0. + */ + if (call->flags & TRACE_EVENT_FL_TRACEPOINT) { + t = btf_type_by_id(btf, btf_relocate_id(btf, ids[0])); + raw_id = t ? t->type : 0; + } + obj_id = btf_obj_id(btf); + btf_put(btf); + } + + len = scnprintf(buf, sizeof(buf), + "btf_obj_id: %u\nraw_btf_id: %u\ntp_btf_id: %u\n", + obj_id, raw_id, tp_id); + + return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); +} +#endif + static ssize_t event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) @@ -2702,6 +2758,13 @@ static const struct file_operations ftrace_event_id_fops = { }; #endif +#ifdef CONFIG_BPF_EVENTS +static const struct file_operations ftrace_event_btf_ids_fops = { + .read = event_btf_ids_read, + .llseek = default_llseek, +}; +#endif + static const struct file_operations ftrace_event_filter_fops = { .open = tracing_open_file_tr, .read = event_filter_read, @@ -3095,6 +3158,14 @@ static int event_callback(const char *name, umode_t *mode, void **data, } #endif +#ifdef CONFIG_BPF_EVENTS + if (call->class->btf_ids && strcmp(name, "btf_ids") == 0) { + *mode = TRACE_MODE_READ; + *fops = &ftrace_event_btf_ids_fops; + return 1; + } +#endif + #ifdef CONFIG_HIST_TRIGGERS if (strcmp(name, "hist") == 0) { *mode = TRACE_MODE_READ; @@ -3149,7 +3220,14 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file) .callback = event_callback, }, #endif -#define NR_RO_EVENT_ENTRIES (1 + IS_ENABLED(CONFIG_PERF_EVENTS)) +#ifdef CONFIG_BPF_EVENTS + { + .name = "btf_ids", + .callback = event_callback, + }, +#endif +#define NR_RO_EVENT_ENTRIES (1 + IS_ENABLED(CONFIG_PERF_EVENTS) + \ + IS_ENABLED(CONFIG_BPF_EVENTS)) /* Readonly files must be above this line and counted by NR_RO_EVENT_ENTRIES. */ { .name = "enable", diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 8a4f3c75e39f..48ef1a93e576 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -1303,12 +1303,26 @@ struct trace_event_functions exit_syscall_print_funcs = { .trace = print_syscall_exit, }; +#ifdef CONFIG_BPF_EVENTS +/* + * BTF id lists generated by DECLARE_EVENT_CLASS for the sys_enter and + * sys_exit tracepoints. The auto-generated event_class_sys_{enter,exit} + * is unused (per-syscall events share the handcrafted classes below), + * but the id lists themselves are global and reusable. + */ +extern u32 __bpf_trace_btf_ids_sys_enter[]; +extern u32 __bpf_trace_btf_ids_sys_exit[]; +#endif + struct trace_event_class __refdata event_class_syscall_enter = { .system = "syscalls", .reg = syscall_enter_register, .fields_array = syscall_enter_fields_array, .get_fields = syscall_get_enter_fields, .raw_init = init_syscall_trace, +#ifdef CONFIG_BPF_EVENTS + .btf_ids = __bpf_trace_btf_ids_sys_enter, +#endif }; struct trace_event_class __refdata event_class_syscall_exit = { @@ -1321,6 +1335,9 @@ struct trace_event_class __refdata event_class_syscall_exit = { }, .fields = LIST_HEAD_INIT(event_class_syscall_exit.fields), .raw_init = init_syscall_trace, +#ifdef CONFIG_BPF_EVENTS + .btf_ids = __bpf_trace_btf_ids_sys_exit, +#endif }; unsigned long __init __weak arch_syscall_addr(int nr) |
