1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 // Copyright (C) 2018 Facebook
3 // Author: Yonghong Song <yhs@fb.com>
14 #include <sys/types.h>
22 /* 0: undecided, 1: supported, 2: not supported */
23 static int perf_query_supported
;
24 static bool has_perf_query_support(void)
26 __u64 probe_offset
, probe_addr
;
27 __u32 len
, prog_id
, fd_type
;
31 if (perf_query_supported
)
34 fd
= open("/", O_RDONLY
);
36 p_err("perf_query_support: cannot open directory \"/\" (%s)",
41 /* the following query will fail as no bpf attachment,
42 * the expected errno is ENOTSUPP
46 bpf_task_fd_query(getpid(), fd
, 0, buf
, &len
, &prog_id
,
47 &fd_type
, &probe_offset
, &probe_addr
);
49 if (errno
== 524 /* ENOTSUPP */) {
50 perf_query_supported
= 1;
54 perf_query_supported
= 2;
55 p_err("perf_query_support: %s", strerror(errno
));
57 "HINT: non root or kernel doesn't support TASK_FD_QUERY\n");
62 return perf_query_supported
== 1;
65 static void print_perf_json(int pid
, int fd
, __u32 prog_id
, __u32 fd_type
,
66 char *buf
, __u64 probe_offset
, __u64 probe_addr
)
68 jsonw_start_object(json_wtr
);
69 jsonw_int_field(json_wtr
, "pid", pid
);
70 jsonw_int_field(json_wtr
, "fd", fd
);
71 jsonw_uint_field(json_wtr
, "prog_id", prog_id
);
73 case BPF_FD_TYPE_RAW_TRACEPOINT
:
74 jsonw_string_field(json_wtr
, "fd_type", "raw_tracepoint");
75 jsonw_string_field(json_wtr
, "tracepoint", buf
);
77 case BPF_FD_TYPE_TRACEPOINT
:
78 jsonw_string_field(json_wtr
, "fd_type", "tracepoint");
79 jsonw_string_field(json_wtr
, "tracepoint", buf
);
81 case BPF_FD_TYPE_KPROBE
:
82 jsonw_string_field(json_wtr
, "fd_type", "kprobe");
84 jsonw_string_field(json_wtr
, "func", buf
);
85 jsonw_lluint_field(json_wtr
, "offset", probe_offset
);
87 jsonw_lluint_field(json_wtr
, "addr", probe_addr
);
90 case BPF_FD_TYPE_KRETPROBE
:
91 jsonw_string_field(json_wtr
, "fd_type", "kretprobe");
93 jsonw_string_field(json_wtr
, "func", buf
);
94 jsonw_lluint_field(json_wtr
, "offset", probe_offset
);
96 jsonw_lluint_field(json_wtr
, "addr", probe_addr
);
99 case BPF_FD_TYPE_UPROBE
:
100 jsonw_string_field(json_wtr
, "fd_type", "uprobe");
101 jsonw_string_field(json_wtr
, "filename", buf
);
102 jsonw_lluint_field(json_wtr
, "offset", probe_offset
);
104 case BPF_FD_TYPE_URETPROBE
:
105 jsonw_string_field(json_wtr
, "fd_type", "uretprobe");
106 jsonw_string_field(json_wtr
, "filename", buf
);
107 jsonw_lluint_field(json_wtr
, "offset", probe_offset
);
112 jsonw_end_object(json_wtr
);
115 static void print_perf_plain(int pid
, int fd
, __u32 prog_id
, __u32 fd_type
,
116 char *buf
, __u64 probe_offset
, __u64 probe_addr
)
118 printf("pid %d fd %d: prog_id %u ", pid
, fd
, prog_id
);
120 case BPF_FD_TYPE_RAW_TRACEPOINT
:
121 printf("raw_tracepoint %s\n", buf
);
123 case BPF_FD_TYPE_TRACEPOINT
:
124 printf("tracepoint %s\n", buf
);
126 case BPF_FD_TYPE_KPROBE
:
128 printf("kprobe func %s offset %llu\n", buf
,
131 printf("kprobe addr %llu\n", probe_addr
);
133 case BPF_FD_TYPE_KRETPROBE
:
135 printf("kretprobe func %s offset %llu\n", buf
,
138 printf("kretprobe addr %llu\n", probe_addr
);
140 case BPF_FD_TYPE_UPROBE
:
141 printf("uprobe filename %s offset %llu\n", buf
, probe_offset
);
143 case BPF_FD_TYPE_URETPROBE
:
144 printf("uretprobe filename %s offset %llu\n", buf
,
152 static int show_proc(void)
154 struct dirent
*proc_de
, *pid_fd_de
;
155 __u64 probe_offset
, probe_addr
;
156 __u32 len
, prog_id
, fd_type
;
162 proc
= opendir("/proc");
166 while ((proc_de
= readdir(proc
))) {
168 pch
= proc_de
->d_name
;
170 /* pid should be all numbers */
171 while (isdigit(*pch
)) {
172 pid
= pid
* 10 + *pch
- '0';
178 err
= snprintf(buf
, sizeof(buf
), "/proc/%s/fd", proc_de
->d_name
);
179 if (err
< 0 || err
>= (int)sizeof(buf
))
182 pid_fd
= opendir(buf
);
186 while ((pid_fd_de
= readdir(pid_fd
))) {
188 pch
= pid_fd_de
->d_name
;
190 /* fd should be all numbers */
191 while (isdigit(*pch
)) {
192 fd
= fd
* 10 + *pch
- '0';
198 /* query (pid, fd) for potential perf events */
200 err
= bpf_task_fd_query(pid
, fd
, 0, buf
, &len
,
202 &probe_offset
, &probe_addr
);
207 print_perf_json(pid
, fd
, prog_id
, fd_type
, buf
,
208 probe_offset
, probe_addr
);
210 print_perf_plain(pid
, fd
, prog_id
, fd_type
, buf
,
211 probe_offset
, probe_addr
);
219 static int do_show(int argc
, char **argv
)
223 if (!has_perf_query_support())
227 jsonw_start_array(json_wtr
);
230 jsonw_end_array(json_wtr
);
235 static int do_help(int argc
, char **argv
)
238 "Usage: %1$s %2$s { show | list }\n"
241 " " HELP_SPEC_OPTIONS
" }\n"
248 static const struct cmd cmds
[] = {
255 int do_perf(int argc
, char **argv
)
257 return cmd_select(cmds
, argc
, argv
, do_help
);