Merge branch 'for-next' into for-linus
[safe/jmp/linux-2.6] / 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/exec_cmd.h"
12 #include "util/cache.h"
13 #include "util/quote.h"
14 #include "util/run-command.h"
15 #include "util/parse-events.h"
16 #include "util/string.h"
17 #include "util/debugfs.h"
18
19 const char perf_usage_string[] =
20         "perf [--version] [--help] COMMAND [ARGS]";
21
22 const char perf_more_info_string[] =
23         "See 'perf help COMMAND' for more information on a specific command.";
24
25 static int use_pager = -1;
26 struct pager_config {
27         const char *cmd;
28         int val;
29 };
30
31 static char debugfs_mntpt[MAXPATHLEN];
32
33 static int pager_command_config(const char *var, const char *value, void *data)
34 {
35         struct pager_config *c = data;
36         if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd))
37                 c->val = perf_config_bool(var, value);
38         return 0;
39 }
40
41 /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
42 int check_pager_config(const char *cmd)
43 {
44         struct pager_config c;
45         c.cmd = cmd;
46         c.val = -1;
47         perf_config(pager_command_config, &c);
48         return c.val;
49 }
50
51 static void commit_pager_choice(void)
52 {
53         switch (use_pager) {
54         case 0:
55                 setenv("PERF_PAGER", "cat", 1);
56                 break;
57         case 1:
58                 /* setup_pager(); */
59                 break;
60         default:
61                 break;
62         }
63 }
64
65 static void set_debugfs_path(void)
66 {
67         char *path;
68
69         path = getenv(PERF_DEBUGFS_ENVIRONMENT);
70         snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
71                  "tracing/events");
72 }
73
74 static int handle_options(const char ***argv, int *argc, int *envchanged)
75 {
76         int handled = 0;
77
78         while (*argc > 0) {
79                 const char *cmd = (*argv)[0];
80                 if (cmd[0] != '-')
81                         break;
82
83                 /*
84                  * For legacy reasons, the "version" and "help"
85                  * commands can be written with "--" prepended
86                  * to make them look like flags.
87                  */
88                 if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
89                         break;
90
91                 /*
92                  * Check remaining flags.
93                  */
94                 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
95                         cmd += strlen(CMD_EXEC_PATH);
96                         if (*cmd == '=')
97                                 perf_set_argv_exec_path(cmd + 1);
98                         else {
99                                 puts(perf_exec_path());
100                                 exit(0);
101                         }
102                 } else if (!strcmp(cmd, "--html-path")) {
103                         puts(system_path(PERF_HTML_PATH));
104                         exit(0);
105                 } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
106                         use_pager = 1;
107                 } else if (!strcmp(cmd, "--no-pager")) {
108                         use_pager = 0;
109                         if (envchanged)
110                                 *envchanged = 1;
111                 } else if (!strcmp(cmd, "--perf-dir")) {
112                         if (*argc < 2) {
113                                 fprintf(stderr, "No directory given for --perf-dir.\n");
114                                 usage(perf_usage_string);
115                         }
116                         setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1);
117                         if (envchanged)
118                                 *envchanged = 1;
119                         (*argv)++;
120                         (*argc)--;
121                         handled++;
122                 } else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
123                         setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
124                         if (envchanged)
125                                 *envchanged = 1;
126                 } else if (!strcmp(cmd, "--work-tree")) {
127                         if (*argc < 2) {
128                                 fprintf(stderr, "No directory given for --work-tree.\n");
129                                 usage(perf_usage_string);
130                         }
131                         setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
132                         if (envchanged)
133                                 *envchanged = 1;
134                         (*argv)++;
135                         (*argc)--;
136                 } else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
137                         setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
138                         if (envchanged)
139                                 *envchanged = 1;
140                 } else if (!strcmp(cmd, "--debugfs-dir")) {
141                         if (*argc < 2) {
142                                 fprintf(stderr, "No directory given for --debugfs-dir.\n");
143                                 usage(perf_usage_string);
144                         }
145                         strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
146                         debugfs_mntpt[MAXPATHLEN - 1] = '\0';
147                         if (envchanged)
148                                 *envchanged = 1;
149                         (*argv)++;
150                         (*argc)--;
151                 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
152                         strncpy(debugfs_mntpt, cmd + strlen(CMD_DEBUGFS_DIR), MAXPATHLEN);
153                         debugfs_mntpt[MAXPATHLEN - 1] = '\0';
154                         if (envchanged)
155                                 *envchanged = 1;
156                 } else {
157                         fprintf(stderr, "Unknown option: %s\n", cmd);
158                         usage(perf_usage_string);
159                 }
160
161                 (*argv)++;
162                 (*argc)--;
163                 handled++;
164         }
165         return handled;
166 }
167
168 static int handle_alias(int *argcp, const char ***argv)
169 {
170         int envchanged = 0, ret = 0, saved_errno = errno;
171         int count, option_count;
172         const char **new_argv;
173         const char *alias_command;
174         char *alias_string;
175
176         alias_command = (*argv)[0];
177         alias_string = alias_lookup(alias_command);
178         if (alias_string) {
179                 if (alias_string[0] == '!') {
180                         if (*argcp > 1) {
181                                 struct strbuf buf;
182
183                                 strbuf_init(&buf, PATH_MAX);
184                                 strbuf_addstr(&buf, alias_string);
185                                 sq_quote_argv(&buf, (*argv) + 1, PATH_MAX);
186                                 free(alias_string);
187                                 alias_string = buf.buf;
188                         }
189                         ret = system(alias_string + 1);
190                         if (ret >= 0 && WIFEXITED(ret) &&
191                             WEXITSTATUS(ret) != 127)
192                                 exit(WEXITSTATUS(ret));
193                         die("Failed to run '%s' when expanding alias '%s'",
194                             alias_string + 1, alias_command);
195                 }
196                 count = split_cmdline(alias_string, &new_argv);
197                 if (count < 0)
198                         die("Bad alias.%s string", alias_command);
199                 option_count = handle_options(&new_argv, &count, &envchanged);
200                 if (envchanged)
201                         die("alias '%s' changes environment variables\n"
202                                  "You can use '!perf' in the alias to do this.",
203                                  alias_command);
204                 memmove(new_argv - option_count, new_argv,
205                                 count * sizeof(char *));
206                 new_argv -= option_count;
207
208                 if (count < 1)
209                         die("empty alias for %s", alias_command);
210
211                 if (!strcmp(alias_command, new_argv[0]))
212                         die("recursive alias: %s", alias_command);
213
214                 new_argv = realloc(new_argv, sizeof(char *) *
215                                     (count + *argcp + 1));
216                 /* insert after command name */
217                 memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
218                 new_argv[count + *argcp] = NULL;
219
220                 *argv = new_argv;
221                 *argcp += count - 1;
222
223                 ret = 1;
224         }
225
226         errno = saved_errno;
227
228         return ret;
229 }
230
231 const char perf_version_string[] = PERF_VERSION;
232
233 #define RUN_SETUP       (1<<0)
234 #define USE_PAGER       (1<<1)
235 /*
236  * require working tree to be present -- anything uses this needs
237  * RUN_SETUP for reading from the configuration file.
238  */
239 #define NEED_WORK_TREE  (1<<2)
240
241 struct cmd_struct {
242         const char *cmd;
243         int (*fn)(int, const char **, const char *);
244         int option;
245 };
246
247 static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
248 {
249         int status;
250         struct stat st;
251         const char *prefix;
252
253         prefix = NULL;
254         if (p->option & RUN_SETUP)
255                 prefix = NULL; /* setup_perf_directory(); */
256
257         if (use_pager == -1 && p->option & RUN_SETUP)
258                 use_pager = check_pager_config(p->cmd);
259         if (use_pager == -1 && p->option & USE_PAGER)
260                 use_pager = 1;
261         commit_pager_choice();
262         set_debugfs_path();
263
264         status = p->fn(argc, argv, prefix);
265         if (status)
266                 return status & 0xff;
267
268         /* Somebody closed stdout? */
269         if (fstat(fileno(stdout), &st))
270                 return 0;
271         /* Ignore write errors for pipes and sockets.. */
272         if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
273                 return 0;
274
275         /* Check for ENOSPC and EIO errors.. */
276         if (fflush(stdout))
277                 die("write failure on standard output: %s", strerror(errno));
278         if (ferror(stdout))
279                 die("unknown write failure on standard output");
280         if (fclose(stdout))
281                 die("close failed on standard output: %s", strerror(errno));
282         return 0;
283 }
284
285 static void handle_internal_command(int argc, const char **argv)
286 {
287         const char *cmd = argv[0];
288         static struct cmd_struct commands[] = {
289                 { "buildid-cache", cmd_buildid_cache, 0 },
290                 { "buildid-list", cmd_buildid_list, 0 },
291                 { "diff",       cmd_diff,       0 },
292                 { "help",       cmd_help,       0 },
293                 { "list",       cmd_list,       0 },
294                 { "record",     cmd_record,     0 },
295                 { "report",     cmd_report,     0 },
296                 { "bench",      cmd_bench,      0 },
297                 { "stat",       cmd_stat,       0 },
298                 { "timechart",  cmd_timechart,  0 },
299                 { "top",        cmd_top,        0 },
300                 { "annotate",   cmd_annotate,   0 },
301                 { "version",    cmd_version,    0 },
302                 { "trace",      cmd_trace,      0 },
303                 { "sched",      cmd_sched,      0 },
304                 { "probe",      cmd_probe,      0 },
305                 { "kmem",       cmd_kmem,       0 },
306                 { "lock",       cmd_lock,       0 },
307         };
308         unsigned int i;
309         static const char ext[] = STRIP_EXTENSION;
310
311         if (sizeof(ext) > 1) {
312                 i = strlen(argv[0]) - strlen(ext);
313                 if (i > 0 && !strcmp(argv[0] + i, ext)) {
314                         char *argv0 = strdup(argv[0]);
315                         argv[0] = cmd = argv0;
316                         argv0[i] = '\0';
317                 }
318         }
319
320         /* Turn "perf cmd --help" into "perf help cmd" */
321         if (argc > 1 && !strcmp(argv[1], "--help")) {
322                 argv[1] = argv[0];
323                 argv[0] = cmd = "help";
324         }
325
326         for (i = 0; i < ARRAY_SIZE(commands); i++) {
327                 struct cmd_struct *p = commands+i;
328                 if (strcmp(p->cmd, cmd))
329                         continue;
330                 exit(run_builtin(p, argc, argv));
331         }
332 }
333
334 static void execv_dashed_external(const char **argv)
335 {
336         struct strbuf cmd = STRBUF_INIT;
337         const char *tmp;
338         int status;
339
340         strbuf_addf(&cmd, "perf-%s", argv[0]);
341
342         /*
343          * argv[0] must be the perf command, but the argv array
344          * belongs to the caller, and may be reused in
345          * subsequent loop iterations. Save argv[0] and
346          * restore it on error.
347          */
348         tmp = argv[0];
349         argv[0] = cmd.buf;
350
351         /*
352          * if we fail because the command is not found, it is
353          * OK to return. Otherwise, we just pass along the status code.
354          */
355         status = run_command_v_opt(argv, 0);
356         if (status != -ERR_RUN_COMMAND_EXEC) {
357                 if (IS_RUN_COMMAND_ERR(status))
358                         die("unable to run '%s'", argv[0]);
359                 exit(-status);
360         }
361         errno = ENOENT; /* as if we called execvp */
362
363         argv[0] = tmp;
364
365         strbuf_release(&cmd);
366 }
367
368 static int run_argv(int *argcp, const char ***argv)
369 {
370         int done_alias = 0;
371
372         while (1) {
373                 /* See if it's an internal command */
374                 handle_internal_command(*argcp, *argv);
375
376                 /* .. then try the external ones */
377                 execv_dashed_external(*argv);
378
379                 /* It could be an alias -- this works around the insanity
380                  * of overriding "perf log" with "perf show" by having
381                  * alias.log = show
382                  */
383                 if (done_alias || !handle_alias(argcp, argv))
384                         break;
385                 done_alias = 1;
386         }
387
388         return done_alias;
389 }
390
391 /* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
392 static void get_debugfs_mntpt(void)
393 {
394         const char *path = debugfs_mount(NULL);
395
396         if (path)
397                 strncpy(debugfs_mntpt, path, sizeof(debugfs_mntpt));
398         else
399                 debugfs_mntpt[0] = '\0';
400 }
401
402 int main(int argc, const char **argv)
403 {
404         const char *cmd;
405
406         cmd = perf_extract_argv0_path(argv[0]);
407         if (!cmd)
408                 cmd = "perf-help";
409         /* get debugfs mount point from /proc/mounts */
410         get_debugfs_mntpt();
411         /*
412          * "perf-xxxx" is the same as "perf xxxx", but we obviously:
413          *
414          *  - cannot take flags in between the "perf" and the "xxxx".
415          *  - cannot execute it externally (since it would just do
416          *    the same thing over again)
417          *
418          * So we just directly call the internal command handler, and
419          * die if that one cannot handle it.
420          */
421         if (!prefixcmp(cmd, "perf-")) {
422                 cmd += 5;
423                 argv[0] = cmd;
424                 handle_internal_command(argc, argv);
425                 die("cannot handle %s internally", cmd);
426         }
427
428         /* Look for flags.. */
429         argv++;
430         argc--;
431         handle_options(&argv, &argc, NULL);
432         commit_pager_choice();
433         set_debugfs_path();
434         if (argc > 0) {
435                 if (!prefixcmp(argv[0], "--"))
436                         argv[0] += 2;
437         } else {
438                 /* The user didn't specify a command; give them help */
439                 printf("\n usage: %s\n\n", perf_usage_string);
440                 list_common_cmds_help();
441                 printf("\n %s\n\n", perf_more_info_string);
442                 exit(1);
443         }
444         cmd = argv[0];
445
446         /*
447          * We use PATH to find perf commands, but we prepend some higher
448          * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
449          * environment, and the $(perfexecdir) from the Makefile at build
450          * time.
451          */
452         setup_path();
453
454         while (1) {
455                 static int done_help;
456                 static int was_alias;
457
458                 was_alias = run_argv(&argc, &argv);
459                 if (errno != ENOENT)
460                         break;
461
462                 if (was_alias) {
463                         fprintf(stderr, "Expansion of alias '%s' failed; "
464                                 "'%s' is not a perf-command\n",
465                                 cmd, argv[0]);
466                         exit(1);
467                 }
468                 if (!done_help) {
469                         cmd = argv[0] = help_unknown_cmd(cmd);
470                         done_help = 1;
471                 } else
472                         break;
473         }
474
475         fprintf(stderr, "Failed to run command '%s': %s\n",
476                 cmd, strerror(errno));
477
478         return 1;
479 }