]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/perf/perf.c
iio: pressure: bmp280: add support for BMP180
[karo-tx-linux.git] / tools / perf / perf.c
1 /*
2  * perf.c
3  *
4  * Performance analysis utility.
5  *
6  * This is the main hub from which the sub-commands (perf stat,
7  * perf top, perf record, perf report, etc.) are started.
8  */
9 #include "builtin.h"
10
11 #include "util/env.h"
12 #include <subcmd/exec-cmd.h>
13 #include "util/cache.h"
14 #include "util/quote.h"
15 #include <subcmd/run-command.h>
16 #include "util/parse-events.h"
17 #include <subcmd/parse-options.h>
18 #include "util/bpf-loader.h"
19 #include "util/debug.h"
20 #include <api/fs/tracing_path.h>
21 #include <pthread.h>
22 #include <stdlib.h>
23 #include <time.h>
24
25 const char perf_usage_string[] =
26         "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
27
28 const char perf_more_info_string[] =
29         "See 'perf help COMMAND' for more information on a specific command.";
30
31 int use_browser = -1;
32 static int use_pager = -1;
33 const char *input_name;
34
35 struct cmd_struct {
36         const char *cmd;
37         int (*fn)(int, const char **, const char *);
38         int option;
39 };
40
41 static struct cmd_struct commands[] = {
42         { "buildid-cache", cmd_buildid_cache, 0 },
43         { "buildid-list", cmd_buildid_list, 0 },
44         { "config",     cmd_config,     0 },
45         { "diff",       cmd_diff,       0 },
46         { "evlist",     cmd_evlist,     0 },
47         { "help",       cmd_help,       0 },
48         { "list",       cmd_list,       0 },
49         { "record",     cmd_record,     0 },
50         { "report",     cmd_report,     0 },
51         { "bench",      cmd_bench,      0 },
52         { "stat",       cmd_stat,       0 },
53         { "timechart",  cmd_timechart,  0 },
54         { "top",        cmd_top,        0 },
55         { "annotate",   cmd_annotate,   0 },
56         { "version",    cmd_version,    0 },
57         { "script",     cmd_script,     0 },
58         { "sched",      cmd_sched,      0 },
59 #ifdef HAVE_LIBELF_SUPPORT
60         { "probe",      cmd_probe,      0 },
61 #endif
62         { "kmem",       cmd_kmem,       0 },
63         { "lock",       cmd_lock,       0 },
64         { "kvm",        cmd_kvm,        0 },
65         { "test",       cmd_test,       0 },
66 #ifdef HAVE_LIBAUDIT_SUPPORT
67         { "trace",      cmd_trace,      0 },
68 #endif
69         { "inject",     cmd_inject,     0 },
70         { "mem",        cmd_mem,        0 },
71         { "data",       cmd_data,       0 },
72 };
73
74 struct pager_config {
75         const char *cmd;
76         int val;
77 };
78
79 static int pager_command_config(const char *var, const char *value, void *data)
80 {
81         struct pager_config *c = data;
82         if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd))
83                 c->val = perf_config_bool(var, value);
84         return 0;
85 }
86
87 /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
88 int check_pager_config(const char *cmd)
89 {
90         struct pager_config c;
91         c.cmd = cmd;
92         c.val = -1;
93         perf_config(pager_command_config, &c);
94         return c.val;
95 }
96
97 static int browser_command_config(const char *var, const char *value, void *data)
98 {
99         struct pager_config *c = data;
100         if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd))
101                 c->val = perf_config_bool(var, value);
102         if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd))
103                 c->val = perf_config_bool(var, value) ? 2 : 0;
104         return 0;
105 }
106
107 /*
108  * returns 0 for "no tui", 1 for "use tui", 2 for "use gtk",
109  * and -1 for "not specified"
110  */
111 static int check_browser_config(const char *cmd)
112 {
113         struct pager_config c;
114         c.cmd = cmd;
115         c.val = -1;
116         perf_config(browser_command_config, &c);
117         return c.val;
118 }
119
120 static void commit_pager_choice(void)
121 {
122         switch (use_pager) {
123         case 0:
124                 setenv(PERF_PAGER_ENVIRONMENT, "cat", 1);
125                 break;
126         case 1:
127                 /* setup_pager(); */
128                 break;
129         default:
130                 break;
131         }
132 }
133
134 struct option options[] = {
135         OPT_ARGUMENT("help", "help"),
136         OPT_ARGUMENT("version", "version"),
137         OPT_ARGUMENT("exec-path", "exec-path"),
138         OPT_ARGUMENT("html-path", "html-path"),
139         OPT_ARGUMENT("paginate", "paginate"),
140         OPT_ARGUMENT("no-pager", "no-pager"),
141         OPT_ARGUMENT("perf-dir", "perf-dir"),
142         OPT_ARGUMENT("work-tree", "work-tree"),
143         OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
144         OPT_ARGUMENT("buildid-dir", "buildid-dir"),
145         OPT_ARGUMENT("list-cmds", "list-cmds"),
146         OPT_ARGUMENT("list-opts", "list-opts"),
147         OPT_ARGUMENT("debug", "debug"),
148         OPT_END()
149 };
150
151 static int handle_options(const char ***argv, int *argc, int *envchanged)
152 {
153         int handled = 0;
154
155         while (*argc > 0) {
156                 const char *cmd = (*argv)[0];
157                 if (cmd[0] != '-')
158                         break;
159
160                 /*
161                  * For legacy reasons, the "version" and "help"
162                  * commands can be written with "--" prepended
163                  * to make them look like flags.
164                  */
165                 if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
166                         break;
167
168                 /*
169                  * Shortcut for '-h' and '-v' options to invoke help
170                  * and version command.
171                  */
172                 if (!strcmp(cmd, "-h")) {
173                         (*argv)[0] = "--help";
174                         break;
175                 }
176
177                 if (!strcmp(cmd, "-v")) {
178                         (*argv)[0] = "--version";
179                         break;
180                 }
181
182                 /*
183                  * Check remaining flags.
184                  */
185                 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
186                         cmd += strlen(CMD_EXEC_PATH);
187                         if (*cmd == '=')
188                                 set_argv_exec_path(cmd + 1);
189                         else {
190                                 puts(get_argv_exec_path());
191                                 exit(0);
192                         }
193                 } else if (!strcmp(cmd, "--html-path")) {
194                         puts(system_path(PERF_HTML_PATH));
195                         exit(0);
196                 } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
197                         use_pager = 1;
198                 } else if (!strcmp(cmd, "--no-pager")) {
199                         use_pager = 0;
200                         if (envchanged)
201                                 *envchanged = 1;
202                 } else if (!strcmp(cmd, "--perf-dir")) {
203                         if (*argc < 2) {
204                                 fprintf(stderr, "No directory given for --perf-dir.\n");
205                                 usage(perf_usage_string);
206                         }
207                         setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1);
208                         if (envchanged)
209                                 *envchanged = 1;
210                         (*argv)++;
211                         (*argc)--;
212                         handled++;
213                 } else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
214                         setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
215                         if (envchanged)
216                                 *envchanged = 1;
217                 } else if (!strcmp(cmd, "--work-tree")) {
218                         if (*argc < 2) {
219                                 fprintf(stderr, "No directory given for --work-tree.\n");
220                                 usage(perf_usage_string);
221                         }
222                         setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
223                         if (envchanged)
224                                 *envchanged = 1;
225                         (*argv)++;
226                         (*argc)--;
227                 } else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
228                         setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
229                         if (envchanged)
230                                 *envchanged = 1;
231                 } else if (!strcmp(cmd, "--debugfs-dir")) {
232                         if (*argc < 2) {
233                                 fprintf(stderr, "No directory given for --debugfs-dir.\n");
234                                 usage(perf_usage_string);
235                         }
236                         tracing_path_set((*argv)[1]);
237                         if (envchanged)
238                                 *envchanged = 1;
239                         (*argv)++;
240                         (*argc)--;
241                 } else if (!strcmp(cmd, "--buildid-dir")) {
242                         if (*argc < 2) {
243                                 fprintf(stderr, "No directory given for --buildid-dir.\n");
244                                 usage(perf_usage_string);
245                         }
246                         set_buildid_dir((*argv)[1]);
247                         if (envchanged)
248                                 *envchanged = 1;
249                         (*argv)++;
250                         (*argc)--;
251                 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
252                         tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
253                         fprintf(stderr, "dir: %s\n", tracing_path);
254                         if (envchanged)
255                                 *envchanged = 1;
256                 } else if (!strcmp(cmd, "--list-cmds")) {
257                         unsigned int i;
258
259                         for (i = 0; i < ARRAY_SIZE(commands); i++) {
260                                 struct cmd_struct *p = commands+i;
261                                 printf("%s ", p->cmd);
262                         }
263                         putchar('\n');
264                         exit(0);
265                 } else if (!strcmp(cmd, "--list-opts")) {
266                         unsigned int i;
267
268                         for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
269                                 struct option *p = options+i;
270                                 printf("--%s ", p->long_name);
271                         }
272                         putchar('\n');
273                         exit(0);
274                 } else if (!strcmp(cmd, "--debug")) {
275                         if (*argc < 2) {
276                                 fprintf(stderr, "No variable specified for --debug.\n");
277                                 usage(perf_usage_string);
278                         }
279                         if (perf_debug_option((*argv)[1]))
280                                 usage(perf_usage_string);
281
282                         (*argv)++;
283                         (*argc)--;
284                 } else {
285                         fprintf(stderr, "Unknown option: %s\n", cmd);
286                         usage(perf_usage_string);
287                 }
288
289                 (*argv)++;
290                 (*argc)--;
291                 handled++;
292         }
293         return handled;
294 }
295
296 static int handle_alias(int *argcp, const char ***argv)
297 {
298         int envchanged = 0, ret = 0, saved_errno = errno;
299         int count, option_count;
300         const char **new_argv;
301         const char *alias_command;
302         char *alias_string;
303
304         alias_command = (*argv)[0];
305         alias_string = alias_lookup(alias_command);
306         if (alias_string) {
307                 if (alias_string[0] == '!') {
308                         if (*argcp > 1) {
309                                 struct strbuf buf;
310
311                                 strbuf_init(&buf, PATH_MAX);
312                                 strbuf_addstr(&buf, alias_string);
313                                 sq_quote_argv(&buf, (*argv) + 1, PATH_MAX);
314                                 free(alias_string);
315                                 alias_string = buf.buf;
316                         }
317                         ret = system(alias_string + 1);
318                         if (ret >= 0 && WIFEXITED(ret) &&
319                             WEXITSTATUS(ret) != 127)
320                                 exit(WEXITSTATUS(ret));
321                         die("Failed to run '%s' when expanding alias '%s'",
322                             alias_string + 1, alias_command);
323                 }
324                 count = split_cmdline(alias_string, &new_argv);
325                 if (count < 0)
326                         die("Bad alias.%s string", alias_command);
327                 option_count = handle_options(&new_argv, &count, &envchanged);
328                 if (envchanged)
329                         die("alias '%s' changes environment variables\n"
330                                  "You can use '!perf' in the alias to do this.",
331                                  alias_command);
332                 memmove(new_argv - option_count, new_argv,
333                                 count * sizeof(char *));
334                 new_argv -= option_count;
335
336                 if (count < 1)
337                         die("empty alias for %s", alias_command);
338
339                 if (!strcmp(alias_command, new_argv[0]))
340                         die("recursive alias: %s", alias_command);
341
342                 new_argv = realloc(new_argv, sizeof(char *) *
343                                     (count + *argcp + 1));
344                 /* insert after command name */
345                 memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
346                 new_argv[count + *argcp] = NULL;
347
348                 *argv = new_argv;
349                 *argcp += count - 1;
350
351                 ret = 1;
352         }
353
354         errno = saved_errno;
355
356         return ret;
357 }
358
359 const char perf_version_string[] = PERF_VERSION;
360
361 #define RUN_SETUP       (1<<0)
362 #define USE_PAGER       (1<<1)
363 /*
364  * require working tree to be present -- anything uses this needs
365  * RUN_SETUP for reading from the configuration file.
366  */
367 #define NEED_WORK_TREE  (1<<2)
368
369 static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
370 {
371         int status;
372         struct stat st;
373         const char *prefix;
374         char sbuf[STRERR_BUFSIZE];
375
376         prefix = NULL;
377         if (p->option & RUN_SETUP)
378                 prefix = NULL; /* setup_perf_directory(); */
379
380         if (use_browser == -1)
381                 use_browser = check_browser_config(p->cmd);
382
383         if (use_pager == -1 && p->option & RUN_SETUP)
384                 use_pager = check_pager_config(p->cmd);
385         if (use_pager == -1 && p->option & USE_PAGER)
386                 use_pager = 1;
387         commit_pager_choice();
388
389         perf_env__set_cmdline(&perf_env, argc, argv);
390         status = p->fn(argc, argv, prefix);
391         exit_browser(status);
392         perf_env__exit(&perf_env);
393         bpf__clear();
394
395         if (status)
396                 return status & 0xff;
397
398         /* Somebody closed stdout? */
399         if (fstat(fileno(stdout), &st))
400                 return 0;
401         /* Ignore write errors for pipes and sockets.. */
402         if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
403                 return 0;
404
405         status = 1;
406         /* Check for ENOSPC and EIO errors.. */
407         if (fflush(stdout)) {
408                 fprintf(stderr, "write failure on standard output: %s",
409                         strerror_r(errno, sbuf, sizeof(sbuf)));
410                 goto out;
411         }
412         if (ferror(stdout)) {
413                 fprintf(stderr, "unknown write failure on standard output");
414                 goto out;
415         }
416         if (fclose(stdout)) {
417                 fprintf(stderr, "close failed on standard output: %s",
418                         strerror_r(errno, sbuf, sizeof(sbuf)));
419                 goto out;
420         }
421         status = 0;
422 out:
423         return status;
424 }
425
426 static void handle_internal_command(int argc, const char **argv)
427 {
428         const char *cmd = argv[0];
429         unsigned int i;
430         static const char ext[] = STRIP_EXTENSION;
431
432         if (sizeof(ext) > 1) {
433                 i = strlen(argv[0]) - strlen(ext);
434                 if (i > 0 && !strcmp(argv[0] + i, ext)) {
435                         char *argv0 = strdup(argv[0]);
436                         argv[0] = cmd = argv0;
437                         argv0[i] = '\0';
438                 }
439         }
440
441         /* Turn "perf cmd --help" into "perf help cmd" */
442         if (argc > 1 && !strcmp(argv[1], "--help")) {
443                 argv[1] = argv[0];
444                 argv[0] = cmd = "help";
445         }
446
447         for (i = 0; i < ARRAY_SIZE(commands); i++) {
448                 struct cmd_struct *p = commands+i;
449                 if (strcmp(p->cmd, cmd))
450                         continue;
451                 exit(run_builtin(p, argc, argv));
452         }
453 }
454
455 static void execv_dashed_external(const char **argv)
456 {
457         char *cmd;
458         const char *tmp;
459         int status;
460
461         if (asprintf(&cmd, "perf-%s", argv[0]) < 0)
462                 goto do_die;
463
464         /*
465          * argv[0] must be the perf command, but the argv array
466          * belongs to the caller, and may be reused in
467          * subsequent loop iterations. Save argv[0] and
468          * restore it on error.
469          */
470         tmp = argv[0];
471         argv[0] = cmd;
472
473         /*
474          * if we fail because the command is not found, it is
475          * OK to return. Otherwise, we just pass along the status code.
476          */
477         status = run_command_v_opt(argv, 0);
478         if (status != -ERR_RUN_COMMAND_EXEC) {
479                 if (IS_RUN_COMMAND_ERR(status)) {
480 do_die:
481                         die("unable to run '%s'", argv[0]);
482                 }
483                 exit(-status);
484         }
485         errno = ENOENT; /* as if we called execvp */
486
487         argv[0] = tmp;
488         zfree(&cmd);
489 }
490
491 static int run_argv(int *argcp, const char ***argv)
492 {
493         int done_alias = 0;
494
495         while (1) {
496                 /* See if it's an internal command */
497                 handle_internal_command(*argcp, *argv);
498
499                 /* .. then try the external ones */
500                 execv_dashed_external(*argv);
501
502                 /* It could be an alias -- this works around the insanity
503                  * of overriding "perf log" with "perf show" by having
504                  * alias.log = show
505                  */
506                 if (done_alias || !handle_alias(argcp, argv))
507                         break;
508                 done_alias = 1;
509         }
510
511         return done_alias;
512 }
513
514 static void pthread__block_sigwinch(void)
515 {
516         sigset_t set;
517
518         sigemptyset(&set);
519         sigaddset(&set, SIGWINCH);
520         pthread_sigmask(SIG_BLOCK, &set, NULL);
521 }
522
523 void pthread__unblock_sigwinch(void)
524 {
525         sigset_t set;
526
527         sigemptyset(&set);
528         sigaddset(&set, SIGWINCH);
529         pthread_sigmask(SIG_UNBLOCK, &set, NULL);
530 }
531
532 int main(int argc, const char **argv)
533 {
534         const char *cmd;
535         char sbuf[STRERR_BUFSIZE];
536
537         /* libsubcmd init */
538         exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
539         pager_init(PERF_PAGER_ENVIRONMENT);
540
541         /* The page_size is placed in util object. */
542         page_size = sysconf(_SC_PAGE_SIZE);
543         cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
544
545         cmd = extract_argv0_path(argv[0]);
546         if (!cmd)
547                 cmd = "perf-help";
548
549         srandom(time(NULL));
550
551         perf_config(perf_default_config, NULL);
552
553         /* get debugfs/tracefs mount point from /proc/mounts */
554         tracing_path_mount();
555
556         /*
557          * "perf-xxxx" is the same as "perf xxxx", but we obviously:
558          *
559          *  - cannot take flags in between the "perf" and the "xxxx".
560          *  - cannot execute it externally (since it would just do
561          *    the same thing over again)
562          *
563          * So we just directly call the internal command handler, and
564          * die if that one cannot handle it.
565          */
566         if (!prefixcmp(cmd, "perf-")) {
567                 cmd += 5;
568                 argv[0] = cmd;
569                 handle_internal_command(argc, argv);
570                 fprintf(stderr, "cannot handle %s internally", cmd);
571                 goto out;
572         }
573         if (!prefixcmp(cmd, "trace")) {
574 #ifdef HAVE_LIBAUDIT_SUPPORT
575                 set_buildid_dir(NULL);
576                 setup_path();
577                 argv[0] = "trace";
578                 return cmd_trace(argc, argv, NULL);
579 #else
580                 fprintf(stderr,
581                         "trace command not available: missing audit-libs devel package at build time.\n");
582                 goto out;
583 #endif
584         }
585         /* Look for flags.. */
586         argv++;
587         argc--;
588         handle_options(&argv, &argc, NULL);
589         commit_pager_choice();
590         set_buildid_dir(NULL);
591
592         if (argc > 0) {
593                 if (!prefixcmp(argv[0], "--"))
594                         argv[0] += 2;
595         } else {
596                 /* The user didn't specify a command; give them help */
597                 printf("\n usage: %s\n\n", perf_usage_string);
598                 list_common_cmds_help();
599                 printf("\n %s\n\n", perf_more_info_string);
600                 goto out;
601         }
602         cmd = argv[0];
603
604         test_attr__init();
605
606         /*
607          * We use PATH to find perf commands, but we prepend some higher
608          * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
609          * environment, and the $(perfexecdir) from the Makefile at build
610          * time.
611          */
612         setup_path();
613         /*
614          * Block SIGWINCH notifications so that the thread that wants it can
615          * unblock and get syscalls like select interrupted instead of waiting
616          * forever while the signal goes to some other non interested thread.
617          */
618         pthread__block_sigwinch();
619
620         perf_debug_setup();
621
622         while (1) {
623                 static int done_help;
624                 int was_alias = run_argv(&argc, &argv);
625
626                 if (errno != ENOENT)
627                         break;
628
629                 if (was_alias) {
630                         fprintf(stderr, "Expansion of alias '%s' failed; "
631                                 "'%s' is not a perf-command\n",
632                                 cmd, argv[0]);
633                         goto out;
634                 }
635                 if (!done_help) {
636                         cmd = argv[0] = help_unknown_cmd(cmd);
637                         done_help = 1;
638                 } else
639                         break;
640         }
641
642         fprintf(stderr, "Failed to run command '%s': %s\n",
643                 cmd, strerror_r(errno, sbuf, sizeof(sbuf)));
644 out:
645         return 1;
646 }