~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/bpf/bpftool/perf.c

Version: ~ [ linux-4.20-rc6 ] ~ [ linux-4.19.8 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.87 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.144 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.166 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.128 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.61 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.31.14 ] ~ [ linux-2.6.30.10 ] ~ [ linux-2.6.29.6 ] ~ [ linux-2.6.28.10 ] ~ [ linux-2.6.27.62 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0+
  2 // Copyright (C) 2018 Facebook
  3 // Author: Yonghong Song <yhs@fb.com>
  4 
  5 #define _GNU_SOURCE
  6 #include <ctype.h>
  7 #include <errno.h>
  8 #include <fcntl.h>
  9 #include <stdlib.h>
 10 #include <string.h>
 11 #include <sys/stat.h>
 12 #include <sys/types.h>
 13 #include <unistd.h>
 14 #include <ftw.h>
 15 
 16 #include <bpf.h>
 17 
 18 #include "main.h"
 19 
 20 /* 0: undecided, 1: supported, 2: not supported */
 21 static int perf_query_supported;
 22 static bool has_perf_query_support(void)
 23 {
 24         __u64 probe_offset, probe_addr;
 25         __u32 len, prog_id, fd_type;
 26         char buf[256];
 27         int fd;
 28 
 29         if (perf_query_supported)
 30                 goto out;
 31 
 32         fd = open("/", O_RDONLY);
 33         if (fd < 0) {
 34                 p_err("perf_query_support: cannot open directory \"/\" (%s)",
 35                       strerror(errno));
 36                 goto out;
 37         }
 38 
 39         /* the following query will fail as no bpf attachment,
 40          * the expected errno is ENOTSUPP
 41          */
 42         errno = 0;
 43         len = sizeof(buf);
 44         bpf_task_fd_query(getpid(), fd, 0, buf, &len, &prog_id,
 45                           &fd_type, &probe_offset, &probe_addr);
 46 
 47         if (errno == 524 /* ENOTSUPP */) {
 48                 perf_query_supported = 1;
 49                 goto close_fd;
 50         }
 51 
 52         perf_query_supported = 2;
 53         p_err("perf_query_support: %s", strerror(errno));
 54         fprintf(stderr,
 55                 "HINT: non root or kernel doesn't support TASK_FD_QUERY\n");
 56 
 57 close_fd:
 58         close(fd);
 59 out:
 60         return perf_query_supported == 1;
 61 }
 62 
 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)
 65 {
 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);
 70         switch (fd_type) {
 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);
 74                 break;
 75         case BPF_FD_TYPE_TRACEPOINT:
 76                 jsonw_string_field(json_wtr, "fd_type", "tracepoint");
 77                 jsonw_string_field(json_wtr, "tracepoint", buf);
 78                 break;
 79         case BPF_FD_TYPE_KPROBE:
 80                 jsonw_string_field(json_wtr, "fd_type", "kprobe");
 81                 if (buf[0] != '\0') {
 82                         jsonw_string_field(json_wtr, "func", buf);
 83                         jsonw_lluint_field(json_wtr, "offset", probe_offset);
 84                 } else {
 85                         jsonw_lluint_field(json_wtr, "addr", probe_addr);
 86                 }
 87                 break;
 88         case BPF_FD_TYPE_KRETPROBE:
 89                 jsonw_string_field(json_wtr, "fd_type", "kretprobe");
 90                 if (buf[0] != '\0') {
 91                         jsonw_string_field(json_wtr, "func", buf);
 92                         jsonw_lluint_field(json_wtr, "offset", probe_offset);
 93                 } else {
 94                         jsonw_lluint_field(json_wtr, "addr", probe_addr);
 95                 }
 96                 break;
 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);
101                 break;
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);
106                 break;
107         }
108         jsonw_end_object(json_wtr);
109 }
110 
111 static void print_perf_plain(int pid, int fd, __u32 prog_id, __u32 fd_type,
112                              char *buf, __u64 probe_offset, __u64 probe_addr)
113 {
114         printf("pid %d  fd %d: prog_id %u  ", pid, fd, prog_id);
115         switch (fd_type) {
116         case BPF_FD_TYPE_RAW_TRACEPOINT:
117                 printf("raw_tracepoint  %s\n", buf);
118                 break;
119         case BPF_FD_TYPE_TRACEPOINT:
120                 printf("tracepoint  %s\n", buf);
121                 break;
122         case BPF_FD_TYPE_KPROBE:
123                 if (buf[0] != '\0')
124                         printf("kprobe  func %s  offset %llu\n", buf,
125                                probe_offset);
126                 else
127                         printf("kprobe  addr %llu\n", probe_addr);
128                 break;
129         case BPF_FD_TYPE_KRETPROBE:
130                 if (buf[0] != '\0')
131                         printf("kretprobe  func %s  offset %llu\n", buf,
132                                probe_offset);
133                 else
134                         printf("kretprobe  addr %llu\n", probe_addr);
135                 break;
136         case BPF_FD_TYPE_UPROBE:
137                 printf("uprobe  filename %s  offset %llu\n", buf, probe_offset);
138                 break;
139         case BPF_FD_TYPE_URETPROBE:
140                 printf("uretprobe  filename %s  offset %llu\n", buf,
141                        probe_offset);
142                 break;
143         }
144 }
145 
146 static int show_proc(const char *fpath, const struct stat *sb,
147                      int tflag, struct FTW *ftwbuf)
148 {
149         __u64 probe_offset, probe_addr;
150         __u32 len, prog_id, fd_type;
151         int err, pid = 0, fd = 0;
152         const char *pch;
153         char buf[4096];
154 
155         /* prefix always /proc */
156         pch = fpath + 5;
157         if (*pch == '\0')
158                 return 0;
159 
160         /* pid should be all numbers */
161         pch++;
162         while (isdigit(*pch)) {
163                 pid = pid * 10 + *pch - '';
164                 pch++;
165         }
166         if (*pch == '\0')
167                 return 0;
168         if (*pch != '/')
169                 return FTW_SKIP_SUBTREE;
170 
171         /* check /proc/<pid>/fd directory */
172         pch++;
173         if (strncmp(pch, "fd", 2))
174                 return FTW_SKIP_SUBTREE;
175         pch += 2;
176         if (*pch == '\0')
177                 return 0;
178         if (*pch != '/')
179                 return FTW_SKIP_SUBTREE;
180 
181         /* check /proc/<pid>/fd/<fd_num> */
182         pch++;
183         while (isdigit(*pch)) {
184                 fd = fd * 10 + *pch - '';
185                 pch++;
186         }
187         if (*pch != '\0')
188                 return FTW_SKIP_SUBTREE;
189 
190         /* query (pid, fd) for potential perf events */
191         len = sizeof(buf);
192         err = bpf_task_fd_query(pid, fd, 0, buf, &len, &prog_id, &fd_type,
193                                 &probe_offset, &probe_addr);
194         if (err < 0)
195                 return 0;
196 
197         if (json_output)
198                 print_perf_json(pid, fd, prog_id, fd_type, buf, probe_offset,
199                                 probe_addr);
200         else
201                 print_perf_plain(pid, fd, prog_id, fd_type, buf, probe_offset,
202                                  probe_addr);
203 
204         return 0;
205 }
206 
207 static int do_show(int argc, char **argv)
208 {
209         int flags = FTW_ACTIONRETVAL | FTW_PHYS;
210         int err = 0, nopenfd = 16;
211 
212         if (!has_perf_query_support())
213                 return -1;
214 
215         if (json_output)
216                 jsonw_start_array(json_wtr);
217         if (nftw("/proc", show_proc, nopenfd, flags) == -1) {
218                 p_err("%s", strerror(errno));
219                 err = -1;
220         }
221         if (json_output)
222                 jsonw_end_array(json_wtr);
223 
224         return err;
225 }
226 
227 static int do_help(int argc, char **argv)
228 {
229         fprintf(stderr,
230                 "Usage: %s %s { show | list | help }\n"
231                 "",
232                 bin_name, argv[-2]);
233 
234         return 0;
235 }
236 
237 static const struct cmd cmds[] = {
238         { "show",       do_show },
239         { "list",       do_show },
240         { "help",       do_help },
241         { 0 }
242 };
243 
244 int do_perf(int argc, char **argv)
245 {
246         return cmd_select(cmds, argc, argv, do_help);
247 }
248 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp