1d53dee3fSAndrii Nakryiko // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2d53dee3fSAndrii Nakryiko /* Copyright (c) 2020 Facebook */
3d53dee3fSAndrii Nakryiko #include <vmlinux.h>
4d53dee3fSAndrii Nakryiko #include <bpf/bpf_helpers.h>
5d53dee3fSAndrii Nakryiko #include <bpf/bpf_core_read.h>
6d53dee3fSAndrii Nakryiko #include <bpf/bpf_tracing.h>
7d53dee3fSAndrii Nakryiko #include "pid_iter.h"
8d53dee3fSAndrii Nakryiko
9d53dee3fSAndrii Nakryiko /* keep in sync with the definition in main.h */
10d53dee3fSAndrii Nakryiko enum bpf_obj_type {
11d53dee3fSAndrii Nakryiko BPF_OBJ_UNKNOWN,
12d53dee3fSAndrii Nakryiko BPF_OBJ_PROG,
13d53dee3fSAndrii Nakryiko BPF_OBJ_MAP,
14d53dee3fSAndrii Nakryiko BPF_OBJ_LINK,
15d53dee3fSAndrii Nakryiko BPF_OBJ_BTF,
16d53dee3fSAndrii Nakryiko };
17d53dee3fSAndrii Nakryiko
1867a43462SAlexander Lobakin struct bpf_perf_link___local {
1967a43462SAlexander Lobakin struct bpf_link link;
2067a43462SAlexander Lobakin struct file *perf_file;
2167a43462SAlexander Lobakin } __attribute__((preserve_access_index));
2267a43462SAlexander Lobakin
234cbeeb0dSAlexander Lobakin struct perf_event___local {
244cbeeb0dSAlexander Lobakin u64 bpf_cookie;
254cbeeb0dSAlexander Lobakin } __attribute__((preserve_access_index));
264cbeeb0dSAlexander Lobakin
2744ba7b30SQuentin Monnet enum bpf_link_type___local {
2844ba7b30SQuentin Monnet BPF_LINK_TYPE_PERF_EVENT___local = 7,
2944ba7b30SQuentin Monnet };
3044ba7b30SQuentin Monnet
31d53dee3fSAndrii Nakryiko extern const void bpf_link_fops __ksym;
32d53dee3fSAndrii Nakryiko extern const void bpf_map_fops __ksym;
33d53dee3fSAndrii Nakryiko extern const void bpf_prog_fops __ksym;
34d53dee3fSAndrii Nakryiko extern const void btf_fops __ksym;
35d53dee3fSAndrii Nakryiko
36d53dee3fSAndrii Nakryiko const volatile enum bpf_obj_type obj_type = BPF_OBJ_UNKNOWN;
37d53dee3fSAndrii Nakryiko
get_obj_id(void * ent,enum bpf_obj_type type)38d53dee3fSAndrii Nakryiko static __always_inline __u32 get_obj_id(void *ent, enum bpf_obj_type type)
39d53dee3fSAndrii Nakryiko {
40d53dee3fSAndrii Nakryiko switch (type) {
41d53dee3fSAndrii Nakryiko case BPF_OBJ_PROG:
42d53dee3fSAndrii Nakryiko return BPF_CORE_READ((struct bpf_prog *)ent, aux, id);
43d53dee3fSAndrii Nakryiko case BPF_OBJ_MAP:
44d53dee3fSAndrii Nakryiko return BPF_CORE_READ((struct bpf_map *)ent, id);
45d53dee3fSAndrii Nakryiko case BPF_OBJ_BTF:
46d53dee3fSAndrii Nakryiko return BPF_CORE_READ((struct btf *)ent, id);
47d53dee3fSAndrii Nakryiko case BPF_OBJ_LINK:
48d53dee3fSAndrii Nakryiko return BPF_CORE_READ((struct bpf_link *)ent, id);
49d53dee3fSAndrii Nakryiko default:
50d53dee3fSAndrii Nakryiko return 0;
51d53dee3fSAndrii Nakryiko }
52d53dee3fSAndrii Nakryiko }
53d53dee3fSAndrii Nakryiko
54cbdaf71fSDmitrii Dolgov /* could be used only with BPF_LINK_TYPE_PERF_EVENT links */
get_bpf_cookie(struct bpf_link * link)55cbdaf71fSDmitrii Dolgov static __u64 get_bpf_cookie(struct bpf_link *link)
56cbdaf71fSDmitrii Dolgov {
5767a43462SAlexander Lobakin struct bpf_perf_link___local *perf_link;
584cbeeb0dSAlexander Lobakin struct perf_event___local *event;
59cbdaf71fSDmitrii Dolgov
6067a43462SAlexander Lobakin perf_link = container_of(link, struct bpf_perf_link___local, link);
61cbdaf71fSDmitrii Dolgov event = BPF_CORE_READ(perf_link, perf_file, private_data);
62cbdaf71fSDmitrii Dolgov return BPF_CORE_READ(event, bpf_cookie);
63cbdaf71fSDmitrii Dolgov }
64cbdaf71fSDmitrii Dolgov
65d53dee3fSAndrii Nakryiko SEC("iter/task_file")
iter(struct bpf_iter__task_file * ctx)66d53dee3fSAndrii Nakryiko int iter(struct bpf_iter__task_file *ctx)
67d53dee3fSAndrii Nakryiko {
68d53dee3fSAndrii Nakryiko struct file *file = ctx->file;
69d53dee3fSAndrii Nakryiko struct task_struct *task = ctx->task;
70d53dee3fSAndrii Nakryiko struct pid_iter_entry e;
71d53dee3fSAndrii Nakryiko const void *fops;
72d53dee3fSAndrii Nakryiko
73d53dee3fSAndrii Nakryiko if (!file || !task)
74d53dee3fSAndrii Nakryiko return 0;
75d53dee3fSAndrii Nakryiko
76d53dee3fSAndrii Nakryiko switch (obj_type) {
77d53dee3fSAndrii Nakryiko case BPF_OBJ_PROG:
78d53dee3fSAndrii Nakryiko fops = &bpf_prog_fops;
79d53dee3fSAndrii Nakryiko break;
80d53dee3fSAndrii Nakryiko case BPF_OBJ_MAP:
81d53dee3fSAndrii Nakryiko fops = &bpf_map_fops;
82d53dee3fSAndrii Nakryiko break;
83d53dee3fSAndrii Nakryiko case BPF_OBJ_BTF:
84d53dee3fSAndrii Nakryiko fops = &btf_fops;
85d53dee3fSAndrii Nakryiko break;
86d53dee3fSAndrii Nakryiko case BPF_OBJ_LINK:
87d53dee3fSAndrii Nakryiko fops = &bpf_link_fops;
88d53dee3fSAndrii Nakryiko break;
89d53dee3fSAndrii Nakryiko default:
90d53dee3fSAndrii Nakryiko return 0;
91d53dee3fSAndrii Nakryiko }
92d53dee3fSAndrii Nakryiko
93d53dee3fSAndrii Nakryiko if (file->f_op != fops)
94d53dee3fSAndrii Nakryiko return 0;
95d53dee3fSAndrii Nakryiko
96cbdaf71fSDmitrii Dolgov __builtin_memset(&e, 0, sizeof(e));
97d53dee3fSAndrii Nakryiko e.pid = task->tgid;
98d53dee3fSAndrii Nakryiko e.id = get_obj_id(file->private_data, obj_type);
99cbdaf71fSDmitrii Dolgov
10044ba7b30SQuentin Monnet if (obj_type == BPF_OBJ_LINK &&
10144ba7b30SQuentin Monnet bpf_core_enum_value_exists(enum bpf_link_type___local,
10244ba7b30SQuentin Monnet BPF_LINK_TYPE_PERF_EVENT___local)) {
103cbdaf71fSDmitrii Dolgov struct bpf_link *link = (struct bpf_link *) file->private_data;
104cbdaf71fSDmitrii Dolgov
105ba3647aaSYonghong Song if (BPF_CORE_READ(link, type) == bpf_core_enum_value(enum bpf_link_type___local,
10644ba7b30SQuentin Monnet BPF_LINK_TYPE_PERF_EVENT___local)) {
107cbdaf71fSDmitrii Dolgov e.has_bpf_cookie = true;
108cbdaf71fSDmitrii Dolgov e.bpf_cookie = get_bpf_cookie(link);
109cbdaf71fSDmitrii Dolgov }
110cbdaf71fSDmitrii Dolgov }
111cbdaf71fSDmitrii Dolgov
1124cfb9435SYafang Shao bpf_probe_read_kernel_str(&e.comm, sizeof(e.comm),
113e4d9c232SIlya Leoshkevich task->group_leader->comm);
114d53dee3fSAndrii Nakryiko bpf_seq_write(ctx->meta->seq, &e, sizeof(e));
115d53dee3fSAndrii Nakryiko
116d53dee3fSAndrii Nakryiko return 0;
117d53dee3fSAndrii Nakryiko }
118d53dee3fSAndrii Nakryiko
119d53dee3fSAndrii Nakryiko char LICENSE[] SEC("license") = "Dual BSD/GPL";
120