* [PATCH bpf-next v2 1/3] bpf: Make btf_get_module_btf() and btf_relocate_id() non-static
2026-05-18 15:23 [PATCH bpf-next v2 0/3] tracing: Expose tracepoint BTF ids via tracefs Mykyta Yatsenko
@ 2026-05-18 15:23 ` Mykyta Yatsenko
2026-05-18 15:23 ` [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs Mykyta Yatsenko
2026-05-18 15:23 ` [PATCH bpf-next v2 3/3] selftests/bpf: Add test for tracepoint btf_ids tracefs file Mykyta Yatsenko
2 siblings, 0 replies; 9+ messages in thread
From: Mykyta Yatsenko @ 2026-05-18 15:23 UTC (permalink / raw)
To: bpf, ast, andrii, daniel, kafai, kernel-team, eddyz87, memxor,
rostedt
Cc: Mykyta Yatsenko, linux-trace-kernel
From: Mykyta Yatsenko <yatsenko@meta.com>
Drop the static qualifier and add prototypes to <linux/btf.h> so the
tracing core can look up module BTF and translate ids stored by
resolve_btfids (which are local to a module's split BTF) into the
runtime ids used by the kernel.
Used by the upcoming events/<sys>/<event>/btf_ids tracefs interface.
Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
---
include/linux/btf.h | 2 ++
kernel/bpf/btf.c | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/linux/btf.h b/include/linux/btf.h
index 240401d9b25b..273a93a3b2bd 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -235,6 +235,8 @@ int btf_check_and_fixup_fields(const struct btf *btf, struct btf_record *rec);
bool btf_type_is_void(const struct btf_type *t);
s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind);
s32 bpf_find_btf_id(const char *name, u32 kind, struct btf **btf_p);
+struct btf *btf_get_module_btf(const struct module *module);
+__u32 btf_relocate_id(const struct btf *btf, __u32 id);
const struct btf_type *btf_type_skip_modifiers(const struct btf *btf,
u32 id, u32 *res_id);
const struct btf_type *btf_type_resolve_ptr(const struct btf *btf,
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 17d4ab0a8206..4c33dc7b0aef 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6429,7 +6429,7 @@ struct btf *btf_parse_vmlinux(void)
* split BTF ids will need to be mapped to actual base/split ids for
* BTF now that it has been relocated.
*/
-static __u32 btf_relocate_id(const struct btf *btf, __u32 id)
+__u32 btf_relocate_id(const struct btf *btf, __u32 id)
{
if (!btf->base_btf || !btf->base_id_map)
return id;
@@ -8496,7 +8496,7 @@ struct module *btf_try_get_module(const struct btf *btf)
/* Returns struct btf corresponding to the struct module.
* This function can return NULL or ERR_PTR.
*/
-static struct btf *btf_get_module_btf(const struct module *module)
+struct btf *btf_get_module_btf(const struct module *module)
{
#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
struct btf_module *btf_mod, *tmp;
--
2.53.0-Meta
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs
2026-05-18 15:23 [PATCH bpf-next v2 0/3] tracing: Expose tracepoint BTF ids via tracefs Mykyta Yatsenko
2026-05-18 15:23 ` [PATCH bpf-next v2 1/3] bpf: Make btf_get_module_btf() and btf_relocate_id() non-static Mykyta Yatsenko
@ 2026-05-18 15:23 ` Mykyta Yatsenko
2026-05-26 10:07 ` Mykyta Yatsenko
2026-05-18 15:23 ` [PATCH bpf-next v2 3/3] selftests/bpf: Add test for tracepoint btf_ids tracefs file Mykyta Yatsenko
2 siblings, 1 reply; 9+ messages in thread
From: Mykyta Yatsenko @ 2026-05-18 15:23 UTC (permalink / raw)
To: bpf, ast, andrii, daniel, kafai, kernel-team, eddyz87, memxor,
rostedt
Cc: Mykyta Yatsenko, linux-trace-kernel
From: Mykyta Yatsenko <yatsenko@meta.com>
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>
---
include/linux/trace_events.h | 9 +++++
include/trace/trace_events.h | 24 +++++++++++++
kernel/trace/trace_events.c | 80 ++++++++++++++++++++++++++++++++++++++++++-
kernel/trace/trace_syscalls.c | 17 +++++++++
4 files changed, 129 insertions(+), 1 deletion(-)
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index d49338c44014..3d55b3cc014a 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -298,6 +298,15 @@ struct trace_event_class {
struct list_head *(*get_fields)(struct trace_event_call *);
struct list_head fields;
int (*raw_init)(struct trace_event_call *);
+#ifdef CONFIG_BPF_EVENTS
+ /*
+ * Per-template BTF ids set by DECLARE_EVENT_CLASS via BTF_ID() and
+ * patched by resolve_btfids at link time. NULL for handcrafted classes.
+ * [0] FUNC __bpf_trace_<template>
+ * [1] STRUCT trace_event_raw_<template>
+ */
+ const u32 *btf_ids;
+#endif
};
extern int trace_event_reg(struct trace_event_call *event,
diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h
index fbc07d353be6..09ad57ac4b73 100644
--- a/include/trace/trace_events.h
+++ b/include/trace/trace_events.h
@@ -19,6 +19,7 @@
*/
#include <linux/trace_events.h>
+#include <linux/btf_ids.h>
#ifndef TRACE_SYSTEM_VAR
#define TRACE_SYSTEM_VAR TRACE_SYSTEM
@@ -397,6 +398,27 @@ static inline notrace int trace_event_get_offsets_##call( \
#define _TRACE_PERF_INIT(call)
#endif /* CONFIG_PERF_EVENTS */
+#ifdef CONFIG_BPF_EVENTS
+/*
+ * Per-template BTF id list, populated at link time by resolve_btfids:
+ * [0] FUNC __bpf_trace_<call> (the BPF dispatcher)
+ * [1] STRUCT trace_event_raw_<call> (the ring-buffer record)
+ * Exposed via the events/<sys>/<name>/btf_ids tracefs file.
+ */
+#define _TRACE_BTF_IDS_DECLARE(call) \
+ extern u32 __bpf_trace_btf_ids_##call[]; \
+ BTF_ID_LIST_GLOBAL(__bpf_trace_btf_ids_##call, 2) \
+ BTF_ID(func, __bpf_trace_##call) \
+ BTF_ID(struct, trace_event_raw_##call)
+
+#define _TRACE_BTF_IDS_INIT(call) \
+ .btf_ids = __bpf_trace_btf_ids_##call,
+
+#else
+#define _TRACE_BTF_IDS_DECLARE(call)
+#define _TRACE_BTF_IDS_INIT(call)
+#endif /* CONFIG_BPF_EVENTS */
+
#include "stages/stage6_event_callback.h"
@@ -474,6 +496,7 @@ static inline void ftrace_test_probe_##call(void) \
#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
_TRACE_PERF_PROTO(call, PARAMS(proto)); \
+_TRACE_BTF_IDS_DECLARE(call) \
static char print_fmt_##call[] = print; \
static struct trace_event_class __used __refdata event_class_##call = { \
.system = TRACE_SYSTEM_STRING, \
@@ -483,6 +506,7 @@ static struct trace_event_class __used __refdata event_class_##call = { \
.probe = trace_event_raw_event_##call, \
.reg = trace_event_reg, \
_TRACE_PERF_INIT(call) \
+ _TRACE_BTF_IDS_INIT(call) \
};
#undef DECLARE_EVENT_SYSCALL_CLASS
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index c46e623e7e0d..b1c07f078f8d 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>
@@ -2200,6 +2201,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)
@@ -2700,6 +2756,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,
@@ -3093,6 +3156,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;
@@ -3147,7 +3218,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 e98ee7e1e66f..9134461a8def 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)
--
2.53.0-Meta
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs
2026-05-18 15:23 ` [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs Mykyta Yatsenko
@ 2026-05-26 10:07 ` Mykyta Yatsenko
2026-05-27 1:57 ` Steven Rostedt
0 siblings, 1 reply; 9+ messages in thread
From: Mykyta Yatsenko @ 2026-05-26 10:07 UTC (permalink / raw)
To: bpf, rostedt
Cc: Mykyta Yatsenko, linux-trace-kernel, Andrii Nakryiko,
Alexei Starovoitov
Hi Steven,
Gentle ping on this patch from the series.
Since this part touches tracing, I’d appreciate your thoughts on the
tracing changes whenever you have a chance.
Thanks,
Mykyta
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs
2026-05-26 10:07 ` Mykyta Yatsenko
@ 2026-05-27 1:57 ` Steven Rostedt
2026-06-03 22:41 ` Andrii Nakryiko
0 siblings, 1 reply; 9+ messages in thread
From: Steven Rostedt @ 2026-05-27 1:57 UTC (permalink / raw)
To: Mykyta Yatsenko
Cc: bpf, Mykyta Yatsenko, linux-trace-kernel, Andrii Nakryiko,
Alexei Starovoitov
On Tue, 26 May 2026 11:07:56 +0100
Mykyta Yatsenko <mykyta.yatsenko5@gmail.com> wrote:
> Hi Steven,
>
> Gentle ping on this patch from the series.
>
> Since this part touches tracing, I’d appreciate your thoughts on the
> tracing changes whenever you have a chance.
>
Hi,
I've been looking at this and was wondering if there are ways to not
extend the trace_event_class structure. It's added for most trace
events (actually each DECLARE_EVENT_CLASS). Although when things like
BTF is enabled, this is a very small amount of extra memory.
I haven't been ignoring this. I've just been thinking about other
approaches, but haven't come up with anything. Of course, I haven't
been spending that much time on it, as I've been focused on other
things.
-- Steve
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs
2026-05-27 1:57 ` Steven Rostedt
@ 2026-06-03 22:41 ` Andrii Nakryiko
2026-06-03 22:50 ` Steven Rostedt
0 siblings, 1 reply; 9+ messages in thread
From: Andrii Nakryiko @ 2026-06-03 22:41 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mykyta Yatsenko, bpf, Mykyta Yatsenko, linux-trace-kernel,
Andrii Nakryiko, Alexei Starovoitov
On Tue, May 26, 2026 at 6:57 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Tue, 26 May 2026 11:07:56 +0100
> Mykyta Yatsenko <mykyta.yatsenko5@gmail.com> wrote:
>
> > Hi Steven,
> >
> > Gentle ping on this patch from the series.
> >
> > Since this part touches tracing, I’d appreciate your thoughts on the
> > tracing changes whenever you have a chance.
> >
>
> Hi,
>
> I've been looking at this and was wondering if there are ways to not
> extend the trace_event_class structure. It's added for most trace
> events (actually each DECLARE_EVENT_CLASS). Although when things like
> BTF is enabled, this is a very small amount of extra memory.
>
> I haven't been ignoring this. I've just been thinking about other
> approaches, but haven't come up with anything. Of course, I haven't
> been spending that much time on it, as I've been focused on other
> things.
Just in theory, what alternative would there be besides having one
extra pointer in trace_event_class struct? Some sort of lookup by name
or something? E.g., if we know "call" part at runtime for any given
tracepoint for
.btf_ids = __bpf_trace_btf_ids_##call,
we can probably lookup symbol from kallsyms and fetch BTF IDs that way
without extending the struct?
FWIW, this type info for tracepoints (classic and raw both) are very
useful, because right now one needs to do a bunch of work (subject to
break due to kernel type/name changes, etc) to find this, and for
various generic tracing tooling this type information is actually a
necessity to be useful.
That's just to say that it would be great to have this in some form of
shape, so please help getting this into acceptable form, thanks!
>
> -- Steve
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs
2026-06-03 22:41 ` Andrii Nakryiko
@ 2026-06-03 22:50 ` Steven Rostedt
2026-06-03 23:51 ` Andrii Nakryiko
0 siblings, 1 reply; 9+ messages in thread
From: Steven Rostedt @ 2026-06-03 22:50 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Mykyta Yatsenko, bpf, Mykyta Yatsenko, linux-trace-kernel,
Andrii Nakryiko, Alexei Starovoitov
On Wed, 3 Jun 2026 15:41:50 -0700
Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
> That's just to say that it would be great to have this in some form of
> shape, so please help getting this into acceptable form, thanks!
As I said, I'm not against it. I was hoping to find something to help
alleviate the memory usage.
I'll likely take these as is, but I'm currently on vacation and it will
have to wait until next week.
-- Steve
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs
2026-06-03 22:50 ` Steven Rostedt
@ 2026-06-03 23:51 ` Andrii Nakryiko
0 siblings, 0 replies; 9+ messages in thread
From: Andrii Nakryiko @ 2026-06-03 23:51 UTC (permalink / raw)
To: Steven Rostedt
Cc: Mykyta Yatsenko, bpf, Mykyta Yatsenko, linux-trace-kernel,
Andrii Nakryiko, Alexei Starovoitov
On Wed, Jun 3, 2026 at 3:51 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Wed, 3 Jun 2026 15:41:50 -0700
> Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
>
> > That's just to say that it would be great to have this in some form of
> > shape, so please help getting this into acceptable form, thanks!
>
> As I said, I'm not against it. I was hoping to find something to help
> alleviate the memory usage.
>
> I'll likely take these as is, but I'm currently on vacation and it will
> have to wait until next week.
>
Yeah, no worries, I was just going through my backlog and trying to
think if we can avoid extending the tracepoint class struct. Besides
the somewhat dirty kallsyms symbol lookup logic, I don't see any other
way.
Enjoy your vacation!
> -- Steve
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH bpf-next v2 3/3] selftests/bpf: Add test for tracepoint btf_ids tracefs file
2026-05-18 15:23 [PATCH bpf-next v2 0/3] tracing: Expose tracepoint BTF ids via tracefs Mykyta Yatsenko
2026-05-18 15:23 ` [PATCH bpf-next v2 1/3] bpf: Make btf_get_module_btf() and btf_relocate_id() non-static Mykyta Yatsenko
2026-05-18 15:23 ` [PATCH bpf-next v2 2/3] tracing: Expose tracepoint BTF ids via tracefs Mykyta Yatsenko
@ 2026-05-18 15:23 ` Mykyta Yatsenko
2 siblings, 0 replies; 9+ messages in thread
From: Mykyta Yatsenko @ 2026-05-18 15:23 UTC (permalink / raw)
To: bpf, ast, andrii, daniel, kafai, kernel-team, eddyz87, memxor,
rostedt
Cc: Mykyta Yatsenko, linux-trace-kernel
From: Mykyta Yatsenko <yatsenko@meta.com>
Read events/bpf_testmod/bpf_testmod_test_read/btf_ids and verify the
exported FUNC_PROTO matches the testmod tracepoint signature
(__data, struct task_struct *task, struct bpf_testmod_test_read_ctx
*ctx) and the record struct trace_event_raw_bpf_testmod_test_read
carries the fields declared by TP_STRUCT__entry.
Use the testmod tracepoint so the test exercises the module/split-BTF
path (btf_relocate_id) rather than vmlinux only, and falls back from
/sys/kernel/tracing to /sys/kernel/debug/tracing when tracefs is not
mounted at the new location.
Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
---
.../testing/selftests/bpf/prog_tests/tp_btf_ids.c | 132 +++++++++++++++++++++
1 file changed, 132 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/tp_btf_ids.c b/tools/testing/selftests/bpf/prog_tests/tp_btf_ids.c
new file mode 100644
index 000000000000..c0e7e11e71b8
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/tp_btf_ids.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include <bpf/btf.h>
+
+#define TRACEFS "/sys/kernel/tracing"
+#define DEBUGFS_TRACING "/sys/kernel/debug/tracing"
+#define EVENT_SUBPATH "events/bpf_testmod/bpf_testmod_test_read/btf_ids"
+
+struct btf_ids_info {
+ __u32 obj_id;
+ __u32 raw_id;
+ __u32 tp_id;
+};
+
+static const char *btf_ids_path(char *buf, size_t sz)
+{
+ if (access(TRACEFS "/trace", F_OK) == 0)
+ snprintf(buf, sz, "%s/%s", TRACEFS, EVENT_SUBPATH);
+ else
+ snprintf(buf, sz, "%s/%s", DEBUGFS_TRACING, EVENT_SUBPATH);
+ return buf;
+}
+
+static int read_btf_ids(struct btf_ids_info *info)
+{
+ char path[256], buf[256];
+ int fd, n;
+
+ fd = open(btf_ids_path(path, sizeof(path)), O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ n = read(fd, buf, sizeof(buf) - 1);
+ close(fd);
+ if (n <= 0)
+ return -EIO;
+ buf[n] = '\0';
+
+ if (sscanf(buf,
+ "btf_obj_id: %u\nraw_btf_id: %u\ntp_btf_id: %u\n",
+ &info->obj_id, &info->raw_id, &info->tp_id) != 3)
+ return -EINVAL;
+ return 0;
+}
+
+static const char *param_name(struct btf *btf, const struct btf_param *p)
+{
+ return btf__name_by_offset(btf, p->name_off);
+}
+
+static const char *member_name(struct btf *btf, const struct btf_member *m)
+{
+ return btf__name_by_offset(btf, m->name_off);
+}
+
+void test_tp_btf_ids(void)
+{
+ const struct btf_type *proto_t, *rec_t;
+ const struct btf_param *params;
+ const struct btf_member *members;
+ struct btf_ids_info info;
+ struct btf *vmlinux_btf, *btf;
+ const char *name;
+ int err;
+
+ if (!env.has_testmod) {
+ test__skip();
+ return;
+ }
+
+ err = read_btf_ids(&info);
+ if (!ASSERT_OK(err, "read btf_ids"))
+ return;
+
+ ASSERT_GT(info.obj_id, 0, "obj_id non-zero");
+ ASSERT_GT(info.raw_id, 0, "raw_id non-zero");
+ ASSERT_GT(info.tp_id, 0, "tp_id non-zero");
+
+ vmlinux_btf = btf__load_vmlinux_btf();
+ if (!ASSERT_OK_PTR(vmlinux_btf, "load vmlinux BTF"))
+ return;
+
+ /* Module BTF is split BTF; load with vmlinux as base. */
+ btf = btf__load_from_kernel_by_id_split(info.obj_id, vmlinux_btf);
+ if (!ASSERT_OK_PTR(btf, "load module BTF")) {
+ btf__free(vmlinux_btf);
+ return;
+ }
+
+ /*
+ * raw_btf_id should be the FUNC_PROTO of __bpf_trace_<call>:
+ * void *__data, struct task_struct *task,
+ * struct bpf_testmod_test_read_ctx *ctx
+ */
+ proto_t = btf__type_by_id(btf, info.raw_id);
+ if (!ASSERT_OK_PTR(proto_t, "raw type_by_id"))
+ goto out;
+ if (!ASSERT_TRUE(btf_is_func_proto(proto_t), "raw is FUNC_PROTO"))
+ goto out;
+ if (!ASSERT_EQ(btf_vlen(proto_t), 3, "func_proto arg count"))
+ goto out;
+
+ params = btf_params(proto_t);
+ ASSERT_STREQ(param_name(btf, ¶ms[0]), "__data", "arg0 name");
+ ASSERT_STREQ(param_name(btf, ¶ms[1]), "task", "arg1 name");
+ ASSERT_STREQ(param_name(btf, ¶ms[2]), "ctx", "arg2 name");
+
+ /*
+ * tp_btf_id should be STRUCT trace_event_raw_<call> with the
+ * fields declared by TP_STRUCT__entry plus the common header.
+ */
+ rec_t = btf__type_by_id(btf, info.tp_id);
+ if (!ASSERT_OK_PTR(rec_t, "tp type_by_id"))
+ goto out;
+ if (!ASSERT_TRUE(btf_is_struct(rec_t), "tp is STRUCT"))
+ goto out;
+ name = btf__name_by_offset(btf, rec_t->name_off);
+ ASSERT_STREQ(name, "trace_event_raw_bpf_testmod_test_read",
+ "tp struct name");
+ if (!ASSERT_GE(btf_vlen(rec_t), 5, "tp struct field count"))
+ goto out;
+
+ members = btf_members(rec_t);
+ ASSERT_STREQ(member_name(btf, &members[0]), "ent", "field0 name");
+ ASSERT_STREQ(member_name(btf, &members[1]), "pid", "field1 name");
+ ASSERT_STREQ(member_name(btf, &members[2]), "comm", "field2 name");
+ ASSERT_STREQ(member_name(btf, &members[3]), "off", "field3 name");
+ ASSERT_STREQ(member_name(btf, &members[4]), "len", "field4 name");
+out:
+ btf__free(btf);
+ btf__free(vmlinux_btf);
+}
--
2.53.0-Meta
^ permalink raw reply related [flat|nested] 9+ messages in thread