Skip to content

Commit 4dda47a

Browse files
mykyta5Kernel Patches Daemon
authored andcommitted
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. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
1 parent c39eb44 commit 4dda47a

4 files changed

Lines changed: 129 additions & 1 deletion

File tree

include/linux/trace_events.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,15 @@ struct trace_event_class {
298298
struct list_head *(*get_fields)(struct trace_event_call *);
299299
struct list_head fields;
300300
int (*raw_init)(struct trace_event_call *);
301+
#ifdef CONFIG_BPF_EVENTS
302+
/*
303+
* Per-template BTF ids set by DECLARE_EVENT_CLASS via BTF_ID() and
304+
* patched by resolve_btfids at link time. NULL for handcrafted classes.
305+
* [0] FUNC __bpf_trace_<template>
306+
* [1] STRUCT trace_event_raw_<template>
307+
*/
308+
const u32 *btf_ids;
309+
#endif
301310
};
302311

303312
extern int trace_event_reg(struct trace_event_call *event,

include/trace/trace_events.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020

2121
#include <linux/trace_events.h>
22+
#include <linux/btf_ids.h>
2223

2324
#ifndef TRACE_SYSTEM_VAR
2425
#define TRACE_SYSTEM_VAR TRACE_SYSTEM
@@ -397,6 +398,27 @@ static inline notrace int trace_event_get_offsets_##call( \
397398
#define _TRACE_PERF_INIT(call)
398399
#endif /* CONFIG_PERF_EVENTS */
399400

401+
#ifdef CONFIG_BPF_EVENTS
402+
/*
403+
* Per-template BTF id list, populated at link time by resolve_btfids:
404+
* [0] FUNC __bpf_trace_<call> (the BPF dispatcher)
405+
* [1] STRUCT trace_event_raw_<call> (the ring-buffer record)
406+
* Exposed via the events/<sys>/<name>/btf_ids tracefs file.
407+
*/
408+
#define _TRACE_BTF_IDS_DECLARE(call) \
409+
extern u32 __bpf_trace_btf_ids_##call[]; \
410+
BTF_ID_LIST_GLOBAL(__bpf_trace_btf_ids_##call, 2) \
411+
BTF_ID(func, __bpf_trace_##call) \
412+
BTF_ID(struct, trace_event_raw_##call)
413+
414+
#define _TRACE_BTF_IDS_INIT(call) \
415+
.btf_ids = __bpf_trace_btf_ids_##call,
416+
417+
#else
418+
#define _TRACE_BTF_IDS_DECLARE(call)
419+
#define _TRACE_BTF_IDS_INIT(call)
420+
#endif /* CONFIG_BPF_EVENTS */
421+
400422
#include "stages/stage6_event_callback.h"
401423

402424

@@ -474,6 +496,7 @@ static inline void ftrace_test_probe_##call(void) \
474496
#undef DECLARE_EVENT_CLASS
475497
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
476498
_TRACE_PERF_PROTO(call, PARAMS(proto)); \
499+
_TRACE_BTF_IDS_DECLARE(call) \
477500
static char print_fmt_##call[] = print; \
478501
static struct trace_event_class __used __refdata event_class_##call = { \
479502
.system = TRACE_SYSTEM_STRING, \
@@ -483,6 +506,7 @@ static struct trace_event_class __used __refdata event_class_##call = { \
483506
.probe = trace_event_raw_event_##call, \
484507
.reg = trace_event_reg, \
485508
_TRACE_PERF_INIT(call) \
509+
_TRACE_BTF_IDS_INIT(call) \
486510
};
487511

488512
#undef DECLARE_EVENT_SYSCALL_CLASS

kernel/trace/trace_events.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/sort.h>
2323
#include <linux/slab.h>
2424
#include <linux/delay.h>
25+
#include <linux/btf.h>
2526

2627
#include <trace/events/sched.h>
2728
#include <trace/syscall.h>
@@ -2200,6 +2201,61 @@ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
22002201
}
22012202
#endif
22022203

2204+
#ifdef CONFIG_BPF_EVENTS
2205+
static ssize_t
2206+
event_btf_ids_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
2207+
{
2208+
struct trace_event_file *file;
2209+
struct trace_event_call *call;
2210+
const struct btf_type *t;
2211+
struct module *mod = NULL;
2212+
u32 raw_id = 0, tp_id = 0, obj_id = 0;
2213+
const u32 *ids;
2214+
struct btf *btf;
2215+
char buf[128];
2216+
int len;
2217+
2218+
/* Module unload could free call->class and ids[] mid-read. */
2219+
scoped_guard(mutex, &event_mutex) {
2220+
file = event_file_file(filp);
2221+
if (!file)
2222+
return -ENODEV;
2223+
2224+
call = file->event_call;
2225+
ids = call->class->btf_ids;
2226+
if (!ids)
2227+
return -ENOENT;
2228+
if (!(call->flags & TRACE_EVENT_FL_DYNAMIC))
2229+
mod = (struct module *)call->module;
2230+
2231+
btf = btf_get_module_btf(mod);
2232+
if (IS_ERR_OR_NULL(btf))
2233+
return -ENOENT;
2234+
2235+
/* Module-local ids in ids[] need base+local relocation. */
2236+
tp_id = btf_relocate_id(btf, ids[1]);
2237+
2238+
/*
2239+
* Without FL_TRACEPOINT the dispatcher is shared (e.g. all
2240+
* per-syscall events fan out from __bpf_trace_sys_enter), so
2241+
* raw_btf_id has no per-event attach point — report 0.
2242+
*/
2243+
if (call->flags & TRACE_EVENT_FL_TRACEPOINT) {
2244+
t = btf_type_by_id(btf, btf_relocate_id(btf, ids[0]));
2245+
raw_id = t ? t->type : 0;
2246+
}
2247+
obj_id = btf_obj_id(btf);
2248+
btf_put(btf);
2249+
}
2250+
2251+
len = scnprintf(buf, sizeof(buf),
2252+
"btf_obj_id: %u\nraw_btf_id: %u\ntp_btf_id: %u\n",
2253+
obj_id, raw_id, tp_id);
2254+
2255+
return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
2256+
}
2257+
#endif
2258+
22032259
static ssize_t
22042260
event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
22052261
loff_t *ppos)
@@ -2700,6 +2756,13 @@ static const struct file_operations ftrace_event_id_fops = {
27002756
};
27012757
#endif
27022758

2759+
#ifdef CONFIG_BPF_EVENTS
2760+
static const struct file_operations ftrace_event_btf_ids_fops = {
2761+
.read = event_btf_ids_read,
2762+
.llseek = default_llseek,
2763+
};
2764+
#endif
2765+
27032766
static const struct file_operations ftrace_event_filter_fops = {
27042767
.open = tracing_open_file_tr,
27052768
.read = event_filter_read,
@@ -3093,6 +3156,14 @@ static int event_callback(const char *name, umode_t *mode, void **data,
30933156
}
30943157
#endif
30953158

3159+
#ifdef CONFIG_BPF_EVENTS
3160+
if (call->class->btf_ids && strcmp(name, "btf_ids") == 0) {
3161+
*mode = TRACE_MODE_READ;
3162+
*fops = &ftrace_event_btf_ids_fops;
3163+
return 1;
3164+
}
3165+
#endif
3166+
30963167
#ifdef CONFIG_HIST_TRIGGERS
30973168
if (strcmp(name, "hist") == 0) {
30983169
*mode = TRACE_MODE_READ;
@@ -3147,7 +3218,14 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
31473218
.callback = event_callback,
31483219
},
31493220
#endif
3150-
#define NR_RO_EVENT_ENTRIES (1 + IS_ENABLED(CONFIG_PERF_EVENTS))
3221+
#ifdef CONFIG_BPF_EVENTS
3222+
{
3223+
.name = "btf_ids",
3224+
.callback = event_callback,
3225+
},
3226+
#endif
3227+
#define NR_RO_EVENT_ENTRIES (1 + IS_ENABLED(CONFIG_PERF_EVENTS) + \
3228+
IS_ENABLED(CONFIG_BPF_EVENTS))
31513229
/* Readonly files must be above this line and counted by NR_RO_EVENT_ENTRIES. */
31523230
{
31533231
.name = "enable",

kernel/trace/trace_syscalls.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,12 +1303,26 @@ struct trace_event_functions exit_syscall_print_funcs = {
13031303
.trace = print_syscall_exit,
13041304
};
13051305

1306+
#ifdef CONFIG_BPF_EVENTS
1307+
/*
1308+
* BTF id lists generated by DECLARE_EVENT_CLASS for the sys_enter and
1309+
* sys_exit tracepoints. The auto-generated event_class_sys_{enter,exit}
1310+
* is unused (per-syscall events share the handcrafted classes below),
1311+
* but the id lists themselves are global and reusable.
1312+
*/
1313+
extern u32 __bpf_trace_btf_ids_sys_enter[];
1314+
extern u32 __bpf_trace_btf_ids_sys_exit[];
1315+
#endif
1316+
13061317
struct trace_event_class __refdata event_class_syscall_enter = {
13071318
.system = "syscalls",
13081319
.reg = syscall_enter_register,
13091320
.fields_array = syscall_enter_fields_array,
13101321
.get_fields = syscall_get_enter_fields,
13111322
.raw_init = init_syscall_trace,
1323+
#ifdef CONFIG_BPF_EVENTS
1324+
.btf_ids = __bpf_trace_btf_ids_sys_enter,
1325+
#endif
13121326
};
13131327

13141328
struct trace_event_class __refdata event_class_syscall_exit = {
@@ -1321,6 +1335,9 @@ struct trace_event_class __refdata event_class_syscall_exit = {
13211335
},
13221336
.fields = LIST_HEAD_INIT(event_class_syscall_exit.fields),
13231337
.raw_init = init_syscall_trace,
1338+
#ifdef CONFIG_BPF_EVENTS
1339+
.btf_ids = __bpf_trace_btf_ids_sys_exit,
1340+
#endif
13241341
};
13251342

13261343
unsigned long __init __weak arch_syscall_addr(int nr)

0 commit comments

Comments
 (0)