Blame view

tools/perf/perf.c 12.7 KB
bf9e18763   Ingo Molnar   perf_counter tool...
1
2
3
4
5
6
7
8
  /*
   * perf.c
   *
   * Performance analysis utility.
   *
   * This is the main hub from which the sub-commands (perf stat,
   * perf top, perf record, perf report, etc.) are started.
   */
078006012   Ingo Molnar   perf_counter tool...
9
  #include "builtin.h"
c1a604dff   Arnaldo Carvalho de Melo   perf tools: Remov...
10
  #include "perf.h"
bf9e18763   Ingo Molnar   perf_counter tool...
11

4cb3c6d54   Arnaldo Carvalho de Melo   perf event: Remov...
12
  #include "util/build-id.h"
8520a98db   Arnaldo Carvalho de Melo   perf debug: Remov...
13
  #include "util/cache.h"
aa36ddd7a   Arnaldo Carvalho de Melo   perf env: Introdu...
14
  #include "util/env.h"
20f2be1d4   Jiri Olsa   libperf: Move 'pa...
15
  #include <internal/lib.h> // page_size
4b6ab94ea   Josh Poimboeuf   perf subcmd: Crea...
16
  #include <subcmd/exec-cmd.h>
41840d211   Taeung Song   perf config: Move...
17
  #include "util/config.h"
4b6ab94ea   Josh Poimboeuf   perf subcmd: Crea...
18
  #include <subcmd/run-command.h>
5beeded12   Jason Baron   perf_counter: Det...
19
  #include "util/parse-events.h"
4b6ab94ea   Josh Poimboeuf   perf subcmd: Crea...
20
  #include <subcmd/parse-options.h>
84c86ca12   Wang Nan   perf tools: Enabl...
21
  #include "util/bpf-loader.h"
bbb2cea7e   Jiri Olsa   perf tools: Add -...
22
  #include "util/debug.h"
5ab8c689f   Arnaldo Carvalho de Melo   perf tools: Move ...
23
  #include "util/event.h"
20f2be1d4   Jiri Olsa   libperf: Move 'pa...
24
  #include "util/util.h" // usage()
fa0d98462   Arnaldo Carvalho de Melo   perf tools: Remov...
25
  #include "ui/ui.h"
91854f9a0   Arnaldo Carvalho de Melo   perf tools: Move ...
26
  #include "perf-sys.h"
4cb93446c   Arnaldo Carvalho de Melo   perf tools: Set t...
27
  #include <api/fs/fs.h>
592d5a6ba   Jiri Olsa   tools lib api fs:...
28
  #include <api/fs/tracing_path.h>
20f2be1d4   Jiri Olsa   libperf: Move 'pa...
29
  #include <perf/core.h>
a43783aee   Arnaldo Carvalho de Melo   perf tools: Inclu...
30
  #include <errno.h>
27683dc5c   Irina Tirdea   perf tools: inclu...
31
  #include <pthread.h>
9607ad3a6   Arnaldo Carvalho de Melo   perf tools: Add s...
32
  #include <signal.h>
14cbfbeb7   Namhyung Kim   perf report: Show...
33
34
  #include <stdlib.h>
  #include <time.h>
7a8ef4c4b   Arnaldo Carvalho de Melo   perf tools: Remov...
35
36
37
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <unistd.h>
877a7a110   Arnaldo Carvalho de Melo   perf tools: Add i...
38
  #include <linux/kernel.h>
8520a98db   Arnaldo Carvalho de Melo   perf debug: Remov...
39
  #include <linux/string.h>
7f7c536f2   Arnaldo Carvalho de Melo   tools lib: Adopt ...
40
  #include <linux/zalloc.h>
078006012   Ingo Molnar   perf_counter tool...
41
42
  
  const char perf_usage_string[] =
78a1b503c   Jiri Olsa   perf tools: Fix p...
43
  	"perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
078006012   Ingo Molnar   perf_counter tool...
44
45
46
47
48
  
  const char perf_more_info_string[] =
  	"See 'perf help COMMAND' for more information on a specific command.";
  
  static int use_pager = -1;
70cb4e963   Feng Tang   perf tools: Add a...
49
  const char *input_name;
5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
50

98a4179c9   Frederic Weisbecker   perf tools: Initi...
51
52
  struct cmd_struct {
  	const char *cmd;
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
53
  	int (*fn)(int, const char **);
98a4179c9   Frederic Weisbecker   perf tools: Initi...
54
55
56
57
58
59
  	int option;
  };
  
  static struct cmd_struct commands[] = {
  	{ "buildid-cache", cmd_buildid_cache, 0 },
  	{ "buildid-list", cmd_buildid_list, 0 },
30862f2c5   Taeung Song   perf tools: Add '...
60
  	{ "config",	cmd_config,	0 },
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
61
  	{ "c2c",	cmd_c2c,	0 },
98a4179c9   Frederic Weisbecker   perf tools: Initi...
62
63
64
  	{ "diff",	cmd_diff,	0 },
  	{ "evlist",	cmd_evlist,	0 },
  	{ "help",	cmd_help,	0 },
355637717   Arnaldo Carvalho de Melo   perf kallsyms: In...
65
  	{ "kallsyms",	cmd_kallsyms,	0 },
98a4179c9   Frederic Weisbecker   perf tools: Initi...
66
67
68
69
70
71
72
73
74
75
76
  	{ "list",	cmd_list,	0 },
  	{ "record",	cmd_record,	0 },
  	{ "report",	cmd_report,	0 },
  	{ "bench",	cmd_bench,	0 },
  	{ "stat",	cmd_stat,	0 },
  	{ "timechart",	cmd_timechart,	0 },
  	{ "top",	cmd_top,	0 },
  	{ "annotate",	cmd_annotate,	0 },
  	{ "version",	cmd_version,	0 },
  	{ "script",	cmd_script,	0 },
  	{ "sched",	cmd_sched,	0 },
89fe808ae   Ingo Molnar   tools/perf: Stand...
77
  #ifdef HAVE_LIBELF_SUPPORT
98a4179c9   Frederic Weisbecker   perf tools: Initi...
78
  	{ "probe",	cmd_probe,	0 },
393be2e37   Namhyung Kim   perf symbols: Sup...
79
  #endif
98a4179c9   Frederic Weisbecker   perf tools: Initi...
80
81
82
83
  	{ "kmem",	cmd_kmem,	0 },
  	{ "lock",	cmd_lock,	0 },
  	{ "kvm",	cmd_kvm,	0 },
  	{ "test",	cmd_test,	0 },
22e9af4e9   Jin Yao   perf tools: Renam...
84
  #if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)
514f1c67c   Arnaldo Carvalho de Melo   perf trace: New tool
85
  	{ "trace",	cmd_trace,	0 },
4d29089c2   Namhyung Kim   perf tools: Check...
86
  #endif
98a4179c9   Frederic Weisbecker   perf tools: Initi...
87
  	{ "inject",	cmd_inject,	0 },
028f12ee6   Stephane Eranian   perf tools: Add n...
88
  	{ "mem",	cmd_mem,	0 },
2245bf141   Jiri Olsa   perf tools: Add n...
89
  	{ "data",	cmd_data,	0 },
d01f4e8db   Namhyung Kim   perf ftrace: Intr...
90
  	{ "ftrace",	cmd_ftrace,	0 },
98a4179c9   Frederic Weisbecker   perf tools: Initi...
91
  };
078006012   Ingo Molnar   perf_counter tool...
92
93
94
95
96
97
98
99
  struct pager_config {
  	const char *cmd;
  	int val;
  };
  
  static int pager_command_config(const char *var, const char *value, void *data)
  {
  	struct pager_config *c = data;
8e99b6d45   Arnaldo Carvalho de Melo   tools include: Ad...
100
  	if (strstarts(var, "pager.") && !strcmp(var + 6, c->cmd))
078006012   Ingo Molnar   perf_counter tool...
101
102
103
104
105
  		c->val = perf_config_bool(var, value);
  	return 0;
  }
  
  /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
a3b70b3bb   Arnaldo Carvalho de Melo   perf tools: Remov...
106
  static int check_pager_config(const char *cmd)
078006012   Ingo Molnar   perf_counter tool...
107
  {
ecc4c5614   Arnaldo Carvalho de Melo   perf tools: Propa...
108
  	int err;
078006012   Ingo Molnar   perf_counter tool...
109
110
111
  	struct pager_config c;
  	c.cmd = cmd;
  	c.val = -1;
ecc4c5614   Arnaldo Carvalho de Melo   perf tools: Propa...
112
113
  	err = perf_config(pager_command_config, &c);
  	return err ?: c.val;
078006012   Ingo Molnar   perf_counter tool...
114
  }
0020ce238   Namhyung Kim   perf tools: Add g...
115
  static int browser_command_config(const char *var, const char *value, void *data)
5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
116
117
  {
  	struct pager_config *c = data;
8e99b6d45   Arnaldo Carvalho de Melo   tools include: Ad...
118
  	if (strstarts(var, "tui.") && !strcmp(var + 4, c->cmd))
5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
119
  		c->val = perf_config_bool(var, value);
8e99b6d45   Arnaldo Carvalho de Melo   tools include: Ad...
120
  	if (strstarts(var, "gtk.") && !strcmp(var + 4, c->cmd))
0020ce238   Namhyung Kim   perf tools: Add g...
121
  		c->val = perf_config_bool(var, value) ? 2 : 0;
5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
122
123
  	return 0;
  }
0020ce238   Namhyung Kim   perf tools: Add g...
124
125
126
127
128
  /*
   * returns 0 for "no tui", 1 for "use tui", 2 for "use gtk",
   * and -1 for "not specified"
   */
  static int check_browser_config(const char *cmd)
5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
129
  {
ecc4c5614   Arnaldo Carvalho de Melo   perf tools: Propa...
130
  	int err;
5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
131
132
133
  	struct pager_config c;
  	c.cmd = cmd;
  	c.val = -1;
ecc4c5614   Arnaldo Carvalho de Melo   perf tools: Propa...
134
135
  	err = perf_config(browser_command_config, &c);
  	return err ?: c.val;
5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
136
  }
4c574159d   Thiago Farina   tools/perf/perf.c...
137
138
  static void commit_pager_choice(void)
  {
078006012   Ingo Molnar   perf_counter tool...
139
140
  	switch (use_pager) {
  	case 0:
096d35585   Josh Poimboeuf   perf tools: Provi...
141
  		setenv(PERF_PAGER_ENVIRONMENT, "cat", 1);
078006012   Ingo Molnar   perf_counter tool...
142
143
144
145
146
147
148
149
  		break;
  	case 1:
  		/* setup_pager(); */
  		break;
  	default:
  		break;
  	}
  }
7335399a6   Yunlong Song   perf tools: Fix t...
150
151
152
153
154
155
156
  struct option options[] = {
  	OPT_ARGUMENT("help", "help"),
  	OPT_ARGUMENT("version", "version"),
  	OPT_ARGUMENT("exec-path", "exec-path"),
  	OPT_ARGUMENT("html-path", "html-path"),
  	OPT_ARGUMENT("paginate", "paginate"),
  	OPT_ARGUMENT("no-pager", "no-pager"),
7335399a6   Yunlong Song   perf tools: Fix t...
157
158
159
160
161
162
163
  	OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
  	OPT_ARGUMENT("buildid-dir", "buildid-dir"),
  	OPT_ARGUMENT("list-cmds", "list-cmds"),
  	OPT_ARGUMENT("list-opts", "list-opts"),
  	OPT_ARGUMENT("debug", "debug"),
  	OPT_END()
  };
4c574159d   Thiago Farina   tools/perf/perf.c...
164
  static int handle_options(const char ***argv, int *argc, int *envchanged)
078006012   Ingo Molnar   perf_counter tool...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  {
  	int handled = 0;
  
  	while (*argc > 0) {
  		const char *cmd = (*argv)[0];
  		if (cmd[0] != '-')
  			break;
  
  		/*
  		 * For legacy reasons, the "version" and "help"
  		 * commands can be written with "--" prepended
  		 * to make them look like flags.
  		 */
  		if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
  			break;
  
  		/*
a1853e2c6   Jiri Olsa   perf tools: Handl...
182
183
184
185
186
187
188
189
190
191
192
193
  		 * Shortcut for '-h' and '-v' options to invoke help
  		 * and version command.
  		 */
  		if (!strcmp(cmd, "-h")) {
  			(*argv)[0] = "--help";
  			break;
  		}
  
  		if (!strcmp(cmd, "-v")) {
  			(*argv)[0] = "--version";
  			break;
  		}
3aa94b10a   Jin Yao   perf tools: Add '...
194
195
196
197
198
  		if (!strcmp(cmd, "-vv")) {
  			(*argv)[0] = "version";
  			version_verbose = 1;
  			break;
  		}
a1853e2c6   Jiri Olsa   perf tools: Handl...
199
  		/*
078006012   Ingo Molnar   perf_counter tool...
200
201
  		 * Check remaining flags.
  		 */
8e99b6d45   Arnaldo Carvalho de Melo   tools include: Ad...
202
  		if (strstarts(cmd, CMD_EXEC_PATH)) {
cfed95a69   Vincent Legoll   perf tools: Do no...
203
  			cmd += strlen(CMD_EXEC_PATH);
078006012   Ingo Molnar   perf_counter tool...
204
  			if (*cmd == '=')
46113a54b   Josh Poimboeuf   perf tools: Remov...
205
  				set_argv_exec_path(cmd + 1);
078006012   Ingo Molnar   perf_counter tool...
206
  			else {
46113a54b   Josh Poimboeuf   perf tools: Remov...
207
  				puts(get_argv_exec_path());
078006012   Ingo Molnar   perf_counter tool...
208
209
210
211
212
213
214
215
216
217
218
  				exit(0);
  			}
  		} else if (!strcmp(cmd, "--html-path")) {
  			puts(system_path(PERF_HTML_PATH));
  			exit(0);
  		} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
  			use_pager = 1;
  		} else if (!strcmp(cmd, "--no-pager")) {
  			use_pager = 0;
  			if (envchanged)
  				*envchanged = 1;
5beeded12   Jason Baron   perf_counter: Det...
219
220
221
222
223
224
  		} else if (!strcmp(cmd, "--debugfs-dir")) {
  			if (*argc < 2) {
  				fprintf(stderr, "No directory given for --debugfs-dir.
  ");
  				usage(perf_usage_string);
  			}
65d4b2651   Jiri Olsa   perf tools: Move ...
225
  			tracing_path_set((*argv)[1]);
5beeded12   Jason Baron   perf_counter: Det...
226
227
228
229
  			if (envchanged)
  				*envchanged = 1;
  			(*argv)++;
  			(*argc)--;
99ce8e9fc   Jiri Olsa   perf tools: Add -...
230
231
232
233
234
235
236
237
238
239
240
  		} else if (!strcmp(cmd, "--buildid-dir")) {
  			if (*argc < 2) {
  				fprintf(stderr, "No directory given for --buildid-dir.
  ");
  				usage(perf_usage_string);
  			}
  			set_buildid_dir((*argv)[1]);
  			if (envchanged)
  				*envchanged = 1;
  			(*argv)++;
  			(*argc)--;
8e99b6d45   Arnaldo Carvalho de Melo   tools include: Ad...
241
  		} else if (strstarts(cmd, CMD_DEBUGFS_DIR)) {
65d4b2651   Jiri Olsa   perf tools: Move ...
242
  			tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
17c257e86   Arnaldo Carvalho de Melo   tools lib api: Un...
243
244
  			fprintf(stderr, "dir: %s
  ", tracing_path_mount());
5beeded12   Jason Baron   perf_counter: Det...
245
246
  			if (envchanged)
  				*envchanged = 1;
98a4179c9   Frederic Weisbecker   perf tools: Initi...
247
248
249
250
251
252
253
  		} else if (!strcmp(cmd, "--list-cmds")) {
  			unsigned int i;
  
  			for (i = 0; i < ARRAY_SIZE(commands); i++) {
  				struct cmd_struct *p = commands+i;
  				printf("%s ", p->cmd);
  			}
ed4575206   Yunlong Song   perf list: Avoid ...
254
255
  			putchar('
  ');
98a4179c9   Frederic Weisbecker   perf tools: Initi...
256
  			exit(0);
7335399a6   Yunlong Song   perf tools: Fix t...
257
258
259
260
261
262
263
264
265
266
  		} else if (!strcmp(cmd, "--list-opts")) {
  			unsigned int i;
  
  			for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
  				struct option *p = options+i;
  				printf("--%s ", p->long_name);
  			}
  			putchar('
  ');
  			exit(0);
bbb2cea7e   Jiri Olsa   perf tools: Add -...
267
268
269
270
271
272
273
274
275
276
277
  		} else if (!strcmp(cmd, "--debug")) {
  			if (*argc < 2) {
  				fprintf(stderr, "No variable specified for --debug.
  ");
  				usage(perf_usage_string);
  			}
  			if (perf_debug_option((*argv)[1]))
  				usage(perf_usage_string);
  
  			(*argv)++;
  			(*argc)--;
078006012   Ingo Molnar   perf_counter tool...
278
279
280
281
282
283
284
285
286
287
288
289
  		} else {
  			fprintf(stderr, "Unknown option: %s
  ", cmd);
  			usage(perf_usage_string);
  		}
  
  		(*argv)++;
  		(*argc)--;
  		handled++;
  	}
  	return handled;
  }
078006012   Ingo Molnar   perf_counter tool...
290
291
  #define RUN_SETUP	(1<<0)
  #define USE_PAGER	(1<<1)
078006012   Ingo Molnar   perf_counter tool...
292

078006012   Ingo Molnar   perf_counter tool...
293
294
295
296
  static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
  {
  	int status;
  	struct stat st;
b2348e1d8   Masami Hiramatsu   perf: Use strerro...
297
  	char sbuf[STRERR_BUFSIZE];
078006012   Ingo Molnar   perf_counter tool...
298

5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
299
  	if (use_browser == -1)
0020ce238   Namhyung Kim   perf tools: Add g...
300
  		use_browser = check_browser_config(p->cmd);
5d06e6915   Arnaldo Carvalho de Melo   perf tui: Allow d...
301

078006012   Ingo Molnar   perf_counter tool...
302
303
304
305
306
  	if (use_pager == -1 && p->option & RUN_SETUP)
  		use_pager = check_pager_config(p->cmd);
  	if (use_pager == -1 && p->option & USE_PAGER)
  		use_pager = 1;
  	commit_pager_choice();
e4378f0cb   Song Liu   perf bpf: Save bp...
307
  	perf_env__init(&perf_env);
2bdb2c272   Josh Poimboeuf   perf tools: Save ...
308
  	perf_env__set_cmdline(&perf_env, argc, argv);
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
309
  	status = p->fn(argc, argv);
8a0a9c7e9   Taeung Song   perf config: Intr...
310
  	perf_config__exit();
f3a1f0ea9   Arnaldo Carvalho de Melo   perf newt: Proper...
311
  	exit_browser(status);
aa36ddd7a   Arnaldo Carvalho de Melo   perf env: Introdu...
312
  	perf_env__exit(&perf_env);
84c86ca12   Wang Nan   perf tools: Enabl...
313
  	bpf__clear();
f3a1f0ea9   Arnaldo Carvalho de Melo   perf newt: Proper...
314

078006012   Ingo Molnar   perf_counter tool...
315
316
317
318
319
320
321
322
323
  	if (status)
  		return status & 0xff;
  
  	/* Somebody closed stdout? */
  	if (fstat(fileno(stdout), &st))
  		return 0;
  	/* Ignore write errors for pipes and sockets.. */
  	if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
  		return 0;
2a16bf8c1   Arnaldo Carvalho de Melo   perf tools: Remov...
324
  	status = 1;
078006012   Ingo Molnar   perf_counter tool...
325
  	/* Check for ENOSPC and EIO errors.. */
2a16bf8c1   Arnaldo Carvalho de Melo   perf tools: Remov...
326
  	if (fflush(stdout)) {
b2348e1d8   Masami Hiramatsu   perf: Use strerro...
327
  		fprintf(stderr, "write failure on standard output: %s",
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
328
  			str_error_r(errno, sbuf, sizeof(sbuf)));
2a16bf8c1   Arnaldo Carvalho de Melo   perf tools: Remov...
329
330
331
332
333
334
335
  		goto out;
  	}
  	if (ferror(stdout)) {
  		fprintf(stderr, "unknown write failure on standard output");
  		goto out;
  	}
  	if (fclose(stdout)) {
b2348e1d8   Masami Hiramatsu   perf: Use strerro...
336
  		fprintf(stderr, "close failed on standard output: %s",
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
337
  			str_error_r(errno, sbuf, sizeof(sbuf)));
2a16bf8c1   Arnaldo Carvalho de Melo   perf tools: Remov...
338
339
340
341
342
  		goto out;
  	}
  	status = 0;
  out:
  	return status;
078006012   Ingo Molnar   perf_counter tool...
343
344
345
346
347
  }
  
  static void handle_internal_command(int argc, const char **argv)
  {
  	const char *cmd = argv[0];
f37a291c5   Ingo Molnar   perf_counter tool...
348
  	unsigned int i;
078006012   Ingo Molnar   perf_counter tool...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  
  	/* Turn "perf cmd --help" into "perf help cmd" */
  	if (argc > 1 && !strcmp(argv[1], "--help")) {
  		argv[1] = argv[0];
  		argv[0] = cmd = "help";
  	}
  
  	for (i = 0; i < ARRAY_SIZE(commands); i++) {
  		struct cmd_struct *p = commands+i;
  		if (strcmp(p->cmd, cmd))
  			continue;
  		exit(run_builtin(p, argc, argv));
  	}
  }
  
  static void execv_dashed_external(const char **argv)
  {
5104ffb22   Arnaldo Carvalho de Melo   perf tools: Use a...
366
  	char *cmd;
078006012   Ingo Molnar   perf_counter tool...
367
368
  	const char *tmp;
  	int status;
5104ffb22   Arnaldo Carvalho de Melo   perf tools: Use a...
369
370
  	if (asprintf(&cmd, "perf-%s", argv[0]) < 0)
  		goto do_die;
078006012   Ingo Molnar   perf_counter tool...
371
372
373
374
375
376
377
378
  
  	/*
  	 * argv[0] must be the perf command, but the argv array
  	 * belongs to the caller, and may be reused in
  	 * subsequent loop iterations. Save argv[0] and
  	 * restore it on error.
  	 */
  	tmp = argv[0];
5104ffb22   Arnaldo Carvalho de Melo   perf tools: Use a...
379
  	argv[0] = cmd;
078006012   Ingo Molnar   perf_counter tool...
380
381
382
383
384
385
386
  
  	/*
  	 * if we fail because the command is not found, it is
  	 * OK to return. Otherwise, we just pass along the status code.
  	 */
  	status = run_command_v_opt(argv, 0);
  	if (status != -ERR_RUN_COMMAND_EXEC) {
5104ffb22   Arnaldo Carvalho de Melo   perf tools: Use a...
387
388
  		if (IS_RUN_COMMAND_ERR(status)) {
  do_die:
427748068   Arnaldo Carvalho de Melo   perf tools: Remov...
389
390
  			pr_err("FATAL: unable to run '%s'", argv[0]);
  			status = -128;
5104ffb22   Arnaldo Carvalho de Melo   perf tools: Use a...
391
  		}
078006012   Ingo Molnar   perf_counter tool...
392
393
394
395
396
  		exit(-status);
  	}
  	errno = ENOENT; /* as if we called execvp */
  
  	argv[0] = tmp;
5104ffb22   Arnaldo Carvalho de Melo   perf tools: Use a...
397
  	zfree(&cmd);
078006012   Ingo Molnar   perf_counter tool...
398
399
400
401
  }
  
  static int run_argv(int *argcp, const char ***argv)
  {
c68677014   Arnaldo Carvalho de Melo   perf tools: Remov...
402
403
  	/* See if it's an internal command */
  	handle_internal_command(*argcp, *argv);
078006012   Ingo Molnar   perf_counter tool...
404

c68677014   Arnaldo Carvalho de Melo   perf tools: Remov...
405
406
407
  	/* .. then try the external ones */
  	execv_dashed_external(*argv);
  	return 0;
078006012   Ingo Molnar   perf_counter tool...
408
  }
3af6e3386   Arnaldo Carvalho de Melo   perf ui browser: ...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  static void pthread__block_sigwinch(void)
  {
  	sigset_t set;
  
  	sigemptyset(&set);
  	sigaddset(&set, SIGWINCH);
  	pthread_sigmask(SIG_BLOCK, &set, NULL);
  }
  
  void pthread__unblock_sigwinch(void)
  {
  	sigset_t set;
  
  	sigemptyset(&set);
  	sigaddset(&set, SIGWINCH);
  	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
  }
428dab813   Jiri Olsa   libperf: Merge li...
426
427
428
429
430
  static int libperf_print(enum libperf_print_level level,
  			 const char *fmt, va_list ap)
  {
  	return eprintf(level, verbose, fmt, ap);
  }
078006012   Ingo Molnar   perf_counter tool...
431
432
  int main(int argc, const char **argv)
  {
ecc4c5614   Arnaldo Carvalho de Melo   perf tools: Propa...
433
  	int err;
078006012   Ingo Molnar   perf_counter tool...
434
  	const char *cmd;
b2348e1d8   Masami Hiramatsu   perf: Use strerro...
435
  	char sbuf[STRERR_BUFSIZE];
078006012   Ingo Molnar   perf_counter tool...
436

096d35585   Josh Poimboeuf   perf tools: Provi...
437
438
439
  	/* libsubcmd init */
  	exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
  	pager_init(PERF_PAGER_ENVIRONMENT);
428dab813   Jiri Olsa   libperf: Merge li...
440
  	libperf_init(libperf_print);
0c1fe6b2f   Arnaldo Carvalho de Melo   perf tools: Have ...
441

46113a54b   Josh Poimboeuf   perf tools: Remov...
442
  	cmd = extract_argv0_path(argv[0]);
078006012   Ingo Molnar   perf_counter tool...
443
444
  	if (!cmd)
  		cmd = "perf-help";
65d4b2651   Jiri Olsa   perf tools: Move ...
445

14cbfbeb7   Namhyung Kim   perf report: Show...
446
  	srandom(time(NULL));
61a461fcb   Arnaldo Carvalho de Melo   perf config: Hono...
447
448
  	/* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
  	config_exclusive_filename = getenv("PERF_CONFIG");
ecc4c5614   Arnaldo Carvalho de Melo   perf tools: Propa...
449
450
451
  	err = perf_config(perf_default_config, NULL);
  	if (err)
  		return err;
58cb9d650   Taeung Song   perf config: Remo...
452
  	set_buildid_dir(NULL);
b8cbb3490   Wang Nan   perf config: Brin...
453

078006012   Ingo Molnar   perf_counter tool...
454
455
456
457
458
459
460
  	/*
  	 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
  	 *
  	 *  - cannot take flags in between the "perf" and the "xxxx".
  	 *  - cannot execute it externally (since it would just do
  	 *    the same thing over again)
  	 *
3192f1ed3   Milian Wolff   perf tools: Suppo...
461
462
463
464
  	 * So we just directly call the internal command handler. If that one
  	 * fails to handle this, then maybe we just run a renamed perf binary
  	 * that contains a dash in its name. To handle this scenario, we just
  	 * fall through and ignore the "xxxx" part of the command string.
078006012   Ingo Molnar   perf_counter tool...
465
  	 */
8e99b6d45   Arnaldo Carvalho de Melo   tools include: Ad...
466
  	if (strstarts(cmd, "perf-")) {
266dfb0b5   Peter Zijlstra   perf_counter: Fix...
467
  		cmd += 5;
078006012   Ingo Molnar   perf_counter tool...
468
469
  		argv[0] = cmd;
  		handle_internal_command(argc, argv);
3192f1ed3   Milian Wolff   perf tools: Suppo...
470
471
472
473
474
475
  		/*
  		 * If the command is handled, the above function does not
  		 * return undo changes and fall through in such a case.
  		 */
  		cmd -= 5;
  		argv[0] = cmd;
078006012   Ingo Molnar   perf_counter tool...
476
  	}
8e99b6d45   Arnaldo Carvalho de Melo   tools include: Ad...
477
  	if (strstarts(cmd, "trace")) {
22e9af4e9   Jin Yao   perf tools: Renam...
478
  #if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)
b52bc2341   Arnaldo Carvalho de Melo   perf trace: Add '...
479
480
  		setup_path();
  		argv[0] = "trace";
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
481
  		return cmd_trace(argc, argv);
1b5726220   Arnaldo Carvalho de Melo   perf trace: Warn ...
482
483
484
485
486
  #else
  		fprintf(stderr,
  			"trace command not available: missing audit-libs devel package at build time.
  ");
  		goto out;
b52bc2341   Arnaldo Carvalho de Melo   perf trace: Add '...
487
  #endif
1b5726220   Arnaldo Carvalho de Melo   perf trace: Warn ...
488
  	}
078006012   Ingo Molnar   perf_counter tool...
489
490
491
492
493
  	/* Look for flags.. */
  	argv++;
  	argc--;
  	handle_options(&argv, &argc, NULL);
  	commit_pager_choice();
45de34bbe   Stephane Eranian   perf buildid: add...
494

078006012   Ingo Molnar   perf_counter tool...
495
  	if (argc > 0) {
8e99b6d45   Arnaldo Carvalho de Melo   tools include: Ad...
496
  		if (strstarts(argv[0], "--"))
078006012   Ingo Molnar   perf_counter tool...
497
498
499
  			argv[0] += 2;
  	} else {
  		/* The user didn't specify a command; give them help */
502fc5c72   Ingo Molnar   perf_counter tool...
500
501
502
503
  		printf("
   usage: %s
  
  ", perf_usage_string);
078006012   Ingo Molnar   perf_counter tool...
504
  		list_common_cmds_help();
502fc5c72   Ingo Molnar   perf_counter tool...
505
506
507
508
  		printf("
   %s
  
  ", perf_more_info_string);
2a16bf8c1   Arnaldo Carvalho de Melo   perf tools: Remov...
509
  		goto out;
078006012   Ingo Molnar   perf_counter tool...
510
511
  	}
  	cmd = argv[0];
52502bf20   Jiri Olsa   perf tests: Add f...
512
  	test_attr__init();
078006012   Ingo Molnar   perf_counter tool...
513
514
  	/*
  	 * We use PATH to find perf commands, but we prepend some higher
659431fca   Uwe Kleine-König   fix typos "precid...
515
  	 * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
078006012   Ingo Molnar   perf_counter tool...
516
517
518
519
  	 * environment, and the $(perfexecdir) from the Makefile at build
  	 * time.
  	 */
  	setup_path();
3af6e3386   Arnaldo Carvalho de Melo   perf ui browser: ...
520
521
522
523
524
525
  	/*
  	 * Block SIGWINCH notifications so that the thread that wants it can
  	 * unblock and get syscalls like select interrupted instead of waiting
  	 * forever while the signal goes to some other non interested thread.
  	 */
  	pthread__block_sigwinch();
078006012   Ingo Molnar   perf_counter tool...
526

dd629cc09   Jiri Olsa   perf tools: Initi...
527
  	perf_debug_setup();
078006012   Ingo Molnar   perf_counter tool...
528
  	while (1) {
4c574159d   Thiago Farina   tools/perf/perf.c...
529
  		static int done_help;
c68677014   Arnaldo Carvalho de Melo   perf tools: Remov...
530
531
  
  		run_argv(&argc, &argv);
8035e4288   Ingo Molnar   perf_counter tool...
532

078006012   Ingo Molnar   perf_counter tool...
533
534
  		if (errno != ENOENT)
  			break;
8035e4288   Ingo Molnar   perf_counter tool...
535

078006012   Ingo Molnar   perf_counter tool...
536
537
538
539
540
541
542
543
544
  		if (!done_help) {
  			cmd = argv[0] = help_unknown_cmd(cmd);
  			done_help = 1;
  		} else
  			break;
  	}
  
  	fprintf(stderr, "Failed to run command '%s': %s
  ",
c8b5f2c96   Arnaldo Carvalho de Melo   tools: Introduce ...
545
  		cmd, str_error_r(errno, sbuf, sizeof(sbuf)));
2a16bf8c1   Arnaldo Carvalho de Melo   perf tools: Remov...
546
  out:
078006012   Ingo Molnar   perf_counter tool...
547
548
  	return 1;
  }