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