1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 // Copyright (C) 2018 Facebook
3 // Author: Yonghong Song <yhs@fb.com>
12 #include <sys/types.h>
20 /* 0: undecided, 1: supported, 2: not supported */
21 static int perf_query_supported
;
22 static bool has_perf_query_support(void)
24 __u64 probe_offset
, probe_addr
;
25 __u32 len
, prog_id
, fd_type
;
29 if (perf_query_supported
)
32 fd
= open("/", O_RDONLY
);
34 p_err("perf_query_support: cannot open directory \"/\" (%s)",
39 /* the following query will fail as no bpf attachment,
40 * the expected errno is ENOTSUPP
44 bpf_task_fd_query(getpid(), fd
, 0, buf
, &len
, &prog_id
,
45 &fd_type
, &probe_offset
, &probe_addr
);
47 if (errno
== 524 /* ENOTSUPP */) {
48 perf_query_supported
= 1;
52 perf_query_supported
= 2;
53 p_err("perf_query_support: %s", strerror(errno
));
55 "HINT: non root or kernel doesn't support TASK_FD_QUERY\n");
60 return perf_query_supported
== 1;
63 static void print_perf_json(int pid
, int fd
, __u32 prog_id
, __u32 fd_type
,
64 char *buf
, __u64 probe_offset
, __u64 probe_addr
)
66 jsonw_start_object(json_wtr
);
67 jsonw_int_field(json_wtr
, "pid", pid
);
68 jsonw_int_field(json_wtr
, "fd", fd
);
69 jsonw_uint_field(json_wtr
, "prog_id", prog_id
);
71 case BPF_FD_TYPE_RAW_TRACEPOINT
:
72 jsonw_string_field(json_wtr
, "fd_type", "raw_tracepoint");
73 jsonw_string_field(json_wtr
, "tracepoint", buf
);
75 case BPF_FD_TYPE_TRACEPOINT
:
76 jsonw_string_field(json_wtr
, "fd_type", "tracepoint");
77 jsonw_string_field(json_wtr
, "tracepoint", buf
);
79 case BPF_FD_TYPE_KPROBE
:
80 jsonw_string_field(json_wtr
, "fd_type", "kprobe");
82 jsonw_string_field(json_wtr
, "func", buf
);
83 jsonw_lluint_field(json_wtr
, "offset", probe_offset
);
85 jsonw_lluint_field(json_wtr
, "addr", probe_addr
);
88 case BPF_FD_TYPE_KRETPROBE
:
89 jsonw_string_field(json_wtr
, "fd_type", "kretprobe");
91 jsonw_string_field(json_wtr
, "func", buf
);
92 jsonw_lluint_field(json_wtr
, "offset", probe_offset
);
94 jsonw_lluint_field(json_wtr
, "addr", probe_addr
);
97 case BPF_FD_TYPE_UPROBE
:
98 jsonw_string_field(json_wtr
, "fd_type", "uprobe");
99 jsonw_string_field(json_wtr
, "filename", buf
);
100 jsonw_lluint_field(json_wtr
, "offset", probe_offset
);
102 case BPF_FD_TYPE_URETPROBE
:
103 jsonw_string_field(json_wtr
, "fd_type", "uretprobe");
104 jsonw_string_field(json_wtr
, "filename", buf
);
105 jsonw_lluint_field(json_wtr
, "offset", probe_offset
);
110 jsonw_end_object(json_wtr
);
113 static void print_perf_plain(int pid
, int fd
, __u32 prog_id
, __u32 fd_type
,
114 char *buf
, __u64 probe_offset
, __u64 probe_addr
)
116 printf("pid %d fd %d: prog_id %u ", pid
, fd
, prog_id
);
118 case BPF_FD_TYPE_RAW_TRACEPOINT
:
119 printf("raw_tracepoint %s\n", buf
);
121 case BPF_FD_TYPE_TRACEPOINT
:
122 printf("tracepoint %s\n", buf
);
124 case BPF_FD_TYPE_KPROBE
:
126 printf("kprobe func %s offset %llu\n", buf
,
129 printf("kprobe addr %llu\n", probe_addr
);
131 case BPF_FD_TYPE_KRETPROBE
:
133 printf("kretprobe func %s offset %llu\n", buf
,
136 printf("kretprobe addr %llu\n", probe_addr
);
138 case BPF_FD_TYPE_UPROBE
:
139 printf("uprobe filename %s offset %llu\n", buf
, probe_offset
);
141 case BPF_FD_TYPE_URETPROBE
:
142 printf("uretprobe filename %s offset %llu\n", buf
,
150 static int show_proc(const char *fpath
, const struct stat
*sb
,
151 int tflag
, struct FTW
*ftwbuf
)
153 __u64 probe_offset
, probe_addr
;
154 __u32 len
, prog_id
, fd_type
;
155 int err
, pid
= 0, fd
= 0;
159 /* prefix always /proc */
164 /* pid should be all numbers */
166 while (isdigit(*pch
)) {
167 pid
= pid
* 10 + *pch
- '0';
173 return FTW_SKIP_SUBTREE
;
175 /* check /proc/<pid>/fd directory */
177 if (strncmp(pch
, "fd", 2))
178 return FTW_SKIP_SUBTREE
;
183 return FTW_SKIP_SUBTREE
;
185 /* check /proc/<pid>/fd/<fd_num> */
187 while (isdigit(*pch
)) {
188 fd
= fd
* 10 + *pch
- '0';
192 return FTW_SKIP_SUBTREE
;
194 /* query (pid, fd) for potential perf events */
196 err
= bpf_task_fd_query(pid
, fd
, 0, buf
, &len
, &prog_id
, &fd_type
,
197 &probe_offset
, &probe_addr
);
202 print_perf_json(pid
, fd
, prog_id
, fd_type
, buf
, probe_offset
,
205 print_perf_plain(pid
, fd
, prog_id
, fd_type
, buf
, probe_offset
,
211 static int do_show(int argc
, char **argv
)
213 int flags
= FTW_ACTIONRETVAL
| FTW_PHYS
;
214 int err
= 0, nopenfd
= 16;
216 if (!has_perf_query_support())
220 jsonw_start_array(json_wtr
);
221 if (nftw("/proc", show_proc
, nopenfd
, flags
) == -1) {
222 p_err("%s", strerror(errno
));
226 jsonw_end_array(json_wtr
);
231 static int do_help(int argc
, char **argv
)
234 "Usage: %s %s { show | list | help }\n"
241 static const struct cmd cmds
[] = {
248 int do_perf(int argc
, char **argv
)
250 return cmd_select(cmds
, argc
, argv
, do_help
);