1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * perf.c
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Performance analysis utility.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This is the main hub from which the sub-commands (perf stat,
7*4882a593Smuzhiyun * perf top, perf record, perf report, etc.) are started.
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun #include "builtin.h"
10*4882a593Smuzhiyun #include "perf.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "util/build-id.h"
13*4882a593Smuzhiyun #include "util/cache.h"
14*4882a593Smuzhiyun #include "util/env.h"
15*4882a593Smuzhiyun #include <internal/lib.h> // page_size
16*4882a593Smuzhiyun #include <subcmd/exec-cmd.h>
17*4882a593Smuzhiyun #include "util/config.h"
18*4882a593Smuzhiyun #include <subcmd/run-command.h>
19*4882a593Smuzhiyun #include "util/parse-events.h"
20*4882a593Smuzhiyun #include <subcmd/parse-options.h>
21*4882a593Smuzhiyun #include "util/bpf-loader.h"
22*4882a593Smuzhiyun #include "util/debug.h"
23*4882a593Smuzhiyun #include "util/event.h"
24*4882a593Smuzhiyun #include "util/util.h" // usage()
25*4882a593Smuzhiyun #include "ui/ui.h"
26*4882a593Smuzhiyun #include "perf-sys.h"
27*4882a593Smuzhiyun #include <api/fs/fs.h>
28*4882a593Smuzhiyun #include <api/fs/tracing_path.h>
29*4882a593Smuzhiyun #include <perf/core.h>
30*4882a593Smuzhiyun #include <errno.h>
31*4882a593Smuzhiyun #include <pthread.h>
32*4882a593Smuzhiyun #include <signal.h>
33*4882a593Smuzhiyun #include <stdlib.h>
34*4882a593Smuzhiyun #include <time.h>
35*4882a593Smuzhiyun #include <sys/types.h>
36*4882a593Smuzhiyun #include <sys/stat.h>
37*4882a593Smuzhiyun #include <unistd.h>
38*4882a593Smuzhiyun #include <linux/kernel.h>
39*4882a593Smuzhiyun #include <linux/string.h>
40*4882a593Smuzhiyun #include <linux/zalloc.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun const char perf_usage_string[] =
43*4882a593Smuzhiyun "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun const char perf_more_info_string[] =
46*4882a593Smuzhiyun "See 'perf help COMMAND' for more information on a specific command.";
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static int use_pager = -1;
49*4882a593Smuzhiyun const char *input_name;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun struct cmd_struct {
52*4882a593Smuzhiyun const char *cmd;
53*4882a593Smuzhiyun int (*fn)(int, const char **);
54*4882a593Smuzhiyun int option;
55*4882a593Smuzhiyun };
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun static struct cmd_struct commands[] = {
58*4882a593Smuzhiyun { "buildid-cache", cmd_buildid_cache, 0 },
59*4882a593Smuzhiyun { "buildid-list", cmd_buildid_list, 0 },
60*4882a593Smuzhiyun { "config", cmd_config, 0 },
61*4882a593Smuzhiyun { "c2c", cmd_c2c, 0 },
62*4882a593Smuzhiyun { "diff", cmd_diff, 0 },
63*4882a593Smuzhiyun { "evlist", cmd_evlist, 0 },
64*4882a593Smuzhiyun { "help", cmd_help, 0 },
65*4882a593Smuzhiyun { "kallsyms", cmd_kallsyms, 0 },
66*4882a593Smuzhiyun { "list", cmd_list, 0 },
67*4882a593Smuzhiyun { "record", cmd_record, 0 },
68*4882a593Smuzhiyun { "report", cmd_report, 0 },
69*4882a593Smuzhiyun { "bench", cmd_bench, 0 },
70*4882a593Smuzhiyun { "stat", cmd_stat, 0 },
71*4882a593Smuzhiyun { "timechart", cmd_timechart, 0 },
72*4882a593Smuzhiyun { "top", cmd_top, 0 },
73*4882a593Smuzhiyun { "annotate", cmd_annotate, 0 },
74*4882a593Smuzhiyun { "version", cmd_version, 0 },
75*4882a593Smuzhiyun { "script", cmd_script, 0 },
76*4882a593Smuzhiyun { "sched", cmd_sched, 0 },
77*4882a593Smuzhiyun #ifdef HAVE_LIBELF_SUPPORT
78*4882a593Smuzhiyun { "probe", cmd_probe, 0 },
79*4882a593Smuzhiyun #endif
80*4882a593Smuzhiyun { "kmem", cmd_kmem, 0 },
81*4882a593Smuzhiyun { "lock", cmd_lock, 0 },
82*4882a593Smuzhiyun { "kvm", cmd_kvm, 0 },
83*4882a593Smuzhiyun { "test", cmd_test, 0 },
84*4882a593Smuzhiyun #if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)
85*4882a593Smuzhiyun { "trace", cmd_trace, 0 },
86*4882a593Smuzhiyun #endif
87*4882a593Smuzhiyun { "inject", cmd_inject, 0 },
88*4882a593Smuzhiyun { "mem", cmd_mem, 0 },
89*4882a593Smuzhiyun { "data", cmd_data, 0 },
90*4882a593Smuzhiyun { "ftrace", cmd_ftrace, 0 },
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun struct pager_config {
94*4882a593Smuzhiyun const char *cmd;
95*4882a593Smuzhiyun int val;
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun
pager_command_config(const char * var,const char * value,void * data)98*4882a593Smuzhiyun static int pager_command_config(const char *var, const char *value, void *data)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun struct pager_config *c = data;
101*4882a593Smuzhiyun if (strstarts(var, "pager.") && !strcmp(var + 6, c->cmd))
102*4882a593Smuzhiyun c->val = perf_config_bool(var, value);
103*4882a593Smuzhiyun return 0;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
check_pager_config(const char * cmd)107*4882a593Smuzhiyun static int check_pager_config(const char *cmd)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun int err;
110*4882a593Smuzhiyun struct pager_config c;
111*4882a593Smuzhiyun c.cmd = cmd;
112*4882a593Smuzhiyun c.val = -1;
113*4882a593Smuzhiyun err = perf_config(pager_command_config, &c);
114*4882a593Smuzhiyun return err ?: c.val;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
browser_command_config(const char * var,const char * value,void * data)117*4882a593Smuzhiyun static int browser_command_config(const char *var, const char *value, void *data)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun struct pager_config *c = data;
120*4882a593Smuzhiyun if (strstarts(var, "tui.") && !strcmp(var + 4, c->cmd))
121*4882a593Smuzhiyun c->val = perf_config_bool(var, value);
122*4882a593Smuzhiyun if (strstarts(var, "gtk.") && !strcmp(var + 4, c->cmd))
123*4882a593Smuzhiyun c->val = perf_config_bool(var, value) ? 2 : 0;
124*4882a593Smuzhiyun return 0;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /*
128*4882a593Smuzhiyun * returns 0 for "no tui", 1 for "use tui", 2 for "use gtk",
129*4882a593Smuzhiyun * and -1 for "not specified"
130*4882a593Smuzhiyun */
check_browser_config(const char * cmd)131*4882a593Smuzhiyun static int check_browser_config(const char *cmd)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun int err;
134*4882a593Smuzhiyun struct pager_config c;
135*4882a593Smuzhiyun c.cmd = cmd;
136*4882a593Smuzhiyun c.val = -1;
137*4882a593Smuzhiyun err = perf_config(browser_command_config, &c);
138*4882a593Smuzhiyun return err ?: c.val;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
commit_pager_choice(void)141*4882a593Smuzhiyun static void commit_pager_choice(void)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun switch (use_pager) {
144*4882a593Smuzhiyun case 0:
145*4882a593Smuzhiyun setenv(PERF_PAGER_ENVIRONMENT, "cat", 1);
146*4882a593Smuzhiyun break;
147*4882a593Smuzhiyun case 1:
148*4882a593Smuzhiyun /* setup_pager(); */
149*4882a593Smuzhiyun break;
150*4882a593Smuzhiyun default:
151*4882a593Smuzhiyun break;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun struct option options[] = {
156*4882a593Smuzhiyun OPT_ARGUMENT("help", "help"),
157*4882a593Smuzhiyun OPT_ARGUMENT("version", "version"),
158*4882a593Smuzhiyun OPT_ARGUMENT("exec-path", "exec-path"),
159*4882a593Smuzhiyun OPT_ARGUMENT("html-path", "html-path"),
160*4882a593Smuzhiyun OPT_ARGUMENT("paginate", "paginate"),
161*4882a593Smuzhiyun OPT_ARGUMENT("no-pager", "no-pager"),
162*4882a593Smuzhiyun OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
163*4882a593Smuzhiyun OPT_ARGUMENT("buildid-dir", "buildid-dir"),
164*4882a593Smuzhiyun OPT_ARGUMENT("list-cmds", "list-cmds"),
165*4882a593Smuzhiyun OPT_ARGUMENT("list-opts", "list-opts"),
166*4882a593Smuzhiyun OPT_ARGUMENT("debug", "debug"),
167*4882a593Smuzhiyun OPT_END()
168*4882a593Smuzhiyun };
169*4882a593Smuzhiyun
handle_options(const char *** argv,int * argc,int * envchanged)170*4882a593Smuzhiyun static int handle_options(const char ***argv, int *argc, int *envchanged)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun int handled = 0;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun while (*argc > 0) {
175*4882a593Smuzhiyun const char *cmd = (*argv)[0];
176*4882a593Smuzhiyun if (cmd[0] != '-')
177*4882a593Smuzhiyun break;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /*
180*4882a593Smuzhiyun * For legacy reasons, the "version" and "help"
181*4882a593Smuzhiyun * commands can be written with "--" prepended
182*4882a593Smuzhiyun * to make them look like flags.
183*4882a593Smuzhiyun */
184*4882a593Smuzhiyun if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
185*4882a593Smuzhiyun break;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /*
188*4882a593Smuzhiyun * Shortcut for '-h' and '-v' options to invoke help
189*4882a593Smuzhiyun * and version command.
190*4882a593Smuzhiyun */
191*4882a593Smuzhiyun if (!strcmp(cmd, "-h")) {
192*4882a593Smuzhiyun (*argv)[0] = "--help";
193*4882a593Smuzhiyun break;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (!strcmp(cmd, "-v")) {
197*4882a593Smuzhiyun (*argv)[0] = "--version";
198*4882a593Smuzhiyun break;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (!strcmp(cmd, "-vv")) {
202*4882a593Smuzhiyun (*argv)[0] = "version";
203*4882a593Smuzhiyun version_verbose = 1;
204*4882a593Smuzhiyun break;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /*
208*4882a593Smuzhiyun * Check remaining flags.
209*4882a593Smuzhiyun */
210*4882a593Smuzhiyun if (strstarts(cmd, CMD_EXEC_PATH)) {
211*4882a593Smuzhiyun cmd += strlen(CMD_EXEC_PATH);
212*4882a593Smuzhiyun if (*cmd == '=')
213*4882a593Smuzhiyun set_argv_exec_path(cmd + 1);
214*4882a593Smuzhiyun else {
215*4882a593Smuzhiyun puts(get_argv_exec_path());
216*4882a593Smuzhiyun exit(0);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun } else if (!strcmp(cmd, "--html-path")) {
219*4882a593Smuzhiyun puts(system_path(PERF_HTML_PATH));
220*4882a593Smuzhiyun exit(0);
221*4882a593Smuzhiyun } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
222*4882a593Smuzhiyun use_pager = 1;
223*4882a593Smuzhiyun } else if (!strcmp(cmd, "--no-pager")) {
224*4882a593Smuzhiyun use_pager = 0;
225*4882a593Smuzhiyun if (envchanged)
226*4882a593Smuzhiyun *envchanged = 1;
227*4882a593Smuzhiyun } else if (!strcmp(cmd, "--debugfs-dir")) {
228*4882a593Smuzhiyun if (*argc < 2) {
229*4882a593Smuzhiyun fprintf(stderr, "No directory given for --debugfs-dir.\n");
230*4882a593Smuzhiyun usage(perf_usage_string);
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun tracing_path_set((*argv)[1]);
233*4882a593Smuzhiyun if (envchanged)
234*4882a593Smuzhiyun *envchanged = 1;
235*4882a593Smuzhiyun (*argv)++;
236*4882a593Smuzhiyun (*argc)--;
237*4882a593Smuzhiyun } else if (!strcmp(cmd, "--buildid-dir")) {
238*4882a593Smuzhiyun if (*argc < 2) {
239*4882a593Smuzhiyun fprintf(stderr, "No directory given for --buildid-dir.\n");
240*4882a593Smuzhiyun usage(perf_usage_string);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun set_buildid_dir((*argv)[1]);
243*4882a593Smuzhiyun if (envchanged)
244*4882a593Smuzhiyun *envchanged = 1;
245*4882a593Smuzhiyun (*argv)++;
246*4882a593Smuzhiyun (*argc)--;
247*4882a593Smuzhiyun } else if (strstarts(cmd, CMD_DEBUGFS_DIR)) {
248*4882a593Smuzhiyun tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
249*4882a593Smuzhiyun fprintf(stderr, "dir: %s\n", tracing_path_mount());
250*4882a593Smuzhiyun if (envchanged)
251*4882a593Smuzhiyun *envchanged = 1;
252*4882a593Smuzhiyun } else if (!strcmp(cmd, "--list-cmds")) {
253*4882a593Smuzhiyun unsigned int i;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(commands); i++) {
256*4882a593Smuzhiyun struct cmd_struct *p = commands+i;
257*4882a593Smuzhiyun printf("%s ", p->cmd);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun putchar('\n');
260*4882a593Smuzhiyun exit(0);
261*4882a593Smuzhiyun } else if (!strcmp(cmd, "--list-opts")) {
262*4882a593Smuzhiyun unsigned int i;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
265*4882a593Smuzhiyun struct option *p = options+i;
266*4882a593Smuzhiyun printf("--%s ", p->long_name);
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun putchar('\n');
269*4882a593Smuzhiyun exit(0);
270*4882a593Smuzhiyun } else if (!strcmp(cmd, "--debug")) {
271*4882a593Smuzhiyun if (*argc < 2) {
272*4882a593Smuzhiyun fprintf(stderr, "No variable specified for --debug.\n");
273*4882a593Smuzhiyun usage(perf_usage_string);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun if (perf_debug_option((*argv)[1]))
276*4882a593Smuzhiyun usage(perf_usage_string);
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun (*argv)++;
279*4882a593Smuzhiyun (*argc)--;
280*4882a593Smuzhiyun } else {
281*4882a593Smuzhiyun fprintf(stderr, "Unknown option: %s\n", cmd);
282*4882a593Smuzhiyun usage(perf_usage_string);
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun (*argv)++;
286*4882a593Smuzhiyun (*argc)--;
287*4882a593Smuzhiyun handled++;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun return handled;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun #define RUN_SETUP (1<<0)
293*4882a593Smuzhiyun #define USE_PAGER (1<<1)
294*4882a593Smuzhiyun
run_builtin(struct cmd_struct * p,int argc,const char ** argv)295*4882a593Smuzhiyun static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun int status;
298*4882a593Smuzhiyun struct stat st;
299*4882a593Smuzhiyun char sbuf[STRERR_BUFSIZE];
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if (use_browser == -1)
302*4882a593Smuzhiyun use_browser = check_browser_config(p->cmd);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (use_pager == -1 && p->option & RUN_SETUP)
305*4882a593Smuzhiyun use_pager = check_pager_config(p->cmd);
306*4882a593Smuzhiyun if (use_pager == -1 && p->option & USE_PAGER)
307*4882a593Smuzhiyun use_pager = 1;
308*4882a593Smuzhiyun commit_pager_choice();
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun perf_env__init(&perf_env);
311*4882a593Smuzhiyun perf_env__set_cmdline(&perf_env, argc, argv);
312*4882a593Smuzhiyun status = p->fn(argc, argv);
313*4882a593Smuzhiyun perf_config__exit();
314*4882a593Smuzhiyun exit_browser(status);
315*4882a593Smuzhiyun perf_env__exit(&perf_env);
316*4882a593Smuzhiyun bpf__clear();
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun if (status)
319*4882a593Smuzhiyun return status & 0xff;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* Somebody closed stdout? */
322*4882a593Smuzhiyun if (fstat(fileno(stdout), &st))
323*4882a593Smuzhiyun return 0;
324*4882a593Smuzhiyun /* Ignore write errors for pipes and sockets.. */
325*4882a593Smuzhiyun if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
326*4882a593Smuzhiyun return 0;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun status = 1;
329*4882a593Smuzhiyun /* Check for ENOSPC and EIO errors.. */
330*4882a593Smuzhiyun if (fflush(stdout)) {
331*4882a593Smuzhiyun fprintf(stderr, "write failure on standard output: %s",
332*4882a593Smuzhiyun str_error_r(errno, sbuf, sizeof(sbuf)));
333*4882a593Smuzhiyun goto out;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun if (ferror(stdout)) {
336*4882a593Smuzhiyun fprintf(stderr, "unknown write failure on standard output");
337*4882a593Smuzhiyun goto out;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun if (fclose(stdout)) {
340*4882a593Smuzhiyun fprintf(stderr, "close failed on standard output: %s",
341*4882a593Smuzhiyun str_error_r(errno, sbuf, sizeof(sbuf)));
342*4882a593Smuzhiyun goto out;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun status = 0;
345*4882a593Smuzhiyun out:
346*4882a593Smuzhiyun return status;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
handle_internal_command(int argc,const char ** argv)349*4882a593Smuzhiyun static void handle_internal_command(int argc, const char **argv)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun const char *cmd = argv[0];
352*4882a593Smuzhiyun unsigned int i;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun /* Turn "perf cmd --help" into "perf help cmd" */
355*4882a593Smuzhiyun if (argc > 1 && !strcmp(argv[1], "--help")) {
356*4882a593Smuzhiyun argv[1] = argv[0];
357*4882a593Smuzhiyun argv[0] = cmd = "help";
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(commands); i++) {
361*4882a593Smuzhiyun struct cmd_struct *p = commands+i;
362*4882a593Smuzhiyun if (strcmp(p->cmd, cmd))
363*4882a593Smuzhiyun continue;
364*4882a593Smuzhiyun exit(run_builtin(p, argc, argv));
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
execv_dashed_external(const char ** argv)368*4882a593Smuzhiyun static void execv_dashed_external(const char **argv)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun char *cmd;
371*4882a593Smuzhiyun const char *tmp;
372*4882a593Smuzhiyun int status;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun if (asprintf(&cmd, "perf-%s", argv[0]) < 0)
375*4882a593Smuzhiyun goto do_die;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /*
378*4882a593Smuzhiyun * argv[0] must be the perf command, but the argv array
379*4882a593Smuzhiyun * belongs to the caller, and may be reused in
380*4882a593Smuzhiyun * subsequent loop iterations. Save argv[0] and
381*4882a593Smuzhiyun * restore it on error.
382*4882a593Smuzhiyun */
383*4882a593Smuzhiyun tmp = argv[0];
384*4882a593Smuzhiyun argv[0] = cmd;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun /*
387*4882a593Smuzhiyun * if we fail because the command is not found, it is
388*4882a593Smuzhiyun * OK to return. Otherwise, we just pass along the status code.
389*4882a593Smuzhiyun */
390*4882a593Smuzhiyun status = run_command_v_opt(argv, 0);
391*4882a593Smuzhiyun if (status != -ERR_RUN_COMMAND_EXEC) {
392*4882a593Smuzhiyun if (IS_RUN_COMMAND_ERR(status)) {
393*4882a593Smuzhiyun do_die:
394*4882a593Smuzhiyun pr_err("FATAL: unable to run '%s'", argv[0]);
395*4882a593Smuzhiyun status = -128;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun exit(-status);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun errno = ENOENT; /* as if we called execvp */
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun argv[0] = tmp;
402*4882a593Smuzhiyun zfree(&cmd);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
run_argv(int * argcp,const char *** argv)405*4882a593Smuzhiyun static int run_argv(int *argcp, const char ***argv)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun /* See if it's an internal command */
408*4882a593Smuzhiyun handle_internal_command(*argcp, *argv);
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun /* .. then try the external ones */
411*4882a593Smuzhiyun execv_dashed_external(*argv);
412*4882a593Smuzhiyun return 0;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
pthread__block_sigwinch(void)415*4882a593Smuzhiyun static void pthread__block_sigwinch(void)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun sigset_t set;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun sigemptyset(&set);
420*4882a593Smuzhiyun sigaddset(&set, SIGWINCH);
421*4882a593Smuzhiyun pthread_sigmask(SIG_BLOCK, &set, NULL);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
pthread__unblock_sigwinch(void)424*4882a593Smuzhiyun void pthread__unblock_sigwinch(void)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun sigset_t set;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun sigemptyset(&set);
429*4882a593Smuzhiyun sigaddset(&set, SIGWINCH);
430*4882a593Smuzhiyun pthread_sigmask(SIG_UNBLOCK, &set, NULL);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
libperf_print(enum libperf_print_level level,const char * fmt,va_list ap)433*4882a593Smuzhiyun static int libperf_print(enum libperf_print_level level,
434*4882a593Smuzhiyun const char *fmt, va_list ap)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun return veprintf(level, verbose, fmt, ap);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
main(int argc,const char ** argv)439*4882a593Smuzhiyun int main(int argc, const char **argv)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun int err;
442*4882a593Smuzhiyun const char *cmd;
443*4882a593Smuzhiyun char sbuf[STRERR_BUFSIZE];
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun /* libsubcmd init */
446*4882a593Smuzhiyun exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
447*4882a593Smuzhiyun pager_init(PERF_PAGER_ENVIRONMENT);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun libperf_init(libperf_print);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun cmd = extract_argv0_path(argv[0]);
452*4882a593Smuzhiyun if (!cmd)
453*4882a593Smuzhiyun cmd = "perf-help";
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun srandom(time(NULL));
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
458*4882a593Smuzhiyun config_exclusive_filename = getenv("PERF_CONFIG");
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun err = perf_config(perf_default_config, NULL);
461*4882a593Smuzhiyun if (err)
462*4882a593Smuzhiyun return err;
463*4882a593Smuzhiyun set_buildid_dir(NULL);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun /*
466*4882a593Smuzhiyun * "perf-xxxx" is the same as "perf xxxx", but we obviously:
467*4882a593Smuzhiyun *
468*4882a593Smuzhiyun * - cannot take flags in between the "perf" and the "xxxx".
469*4882a593Smuzhiyun * - cannot execute it externally (since it would just do
470*4882a593Smuzhiyun * the same thing over again)
471*4882a593Smuzhiyun *
472*4882a593Smuzhiyun * So we just directly call the internal command handler. If that one
473*4882a593Smuzhiyun * fails to handle this, then maybe we just run a renamed perf binary
474*4882a593Smuzhiyun * that contains a dash in its name. To handle this scenario, we just
475*4882a593Smuzhiyun * fall through and ignore the "xxxx" part of the command string.
476*4882a593Smuzhiyun */
477*4882a593Smuzhiyun if (strstarts(cmd, "perf-")) {
478*4882a593Smuzhiyun cmd += 5;
479*4882a593Smuzhiyun argv[0] = cmd;
480*4882a593Smuzhiyun handle_internal_command(argc, argv);
481*4882a593Smuzhiyun /*
482*4882a593Smuzhiyun * If the command is handled, the above function does not
483*4882a593Smuzhiyun * return undo changes and fall through in such a case.
484*4882a593Smuzhiyun */
485*4882a593Smuzhiyun cmd -= 5;
486*4882a593Smuzhiyun argv[0] = cmd;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun if (strstarts(cmd, "trace")) {
489*4882a593Smuzhiyun #if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)
490*4882a593Smuzhiyun setup_path();
491*4882a593Smuzhiyun argv[0] = "trace";
492*4882a593Smuzhiyun return cmd_trace(argc, argv);
493*4882a593Smuzhiyun #else
494*4882a593Smuzhiyun fprintf(stderr,
495*4882a593Smuzhiyun "trace command not available: missing audit-libs devel package at build time.\n");
496*4882a593Smuzhiyun goto out;
497*4882a593Smuzhiyun #endif
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun /* Look for flags.. */
500*4882a593Smuzhiyun argv++;
501*4882a593Smuzhiyun argc--;
502*4882a593Smuzhiyun handle_options(&argv, &argc, NULL);
503*4882a593Smuzhiyun commit_pager_choice();
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (argc > 0) {
506*4882a593Smuzhiyun if (strstarts(argv[0], "--"))
507*4882a593Smuzhiyun argv[0] += 2;
508*4882a593Smuzhiyun } else {
509*4882a593Smuzhiyun /* The user didn't specify a command; give them help */
510*4882a593Smuzhiyun printf("\n usage: %s\n\n", perf_usage_string);
511*4882a593Smuzhiyun list_common_cmds_help();
512*4882a593Smuzhiyun printf("\n %s\n\n", perf_more_info_string);
513*4882a593Smuzhiyun goto out;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun cmd = argv[0];
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun test_attr__init();
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun /*
520*4882a593Smuzhiyun * We use PATH to find perf commands, but we prepend some higher
521*4882a593Smuzhiyun * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
522*4882a593Smuzhiyun * environment, and the $(perfexecdir) from the Makefile at build
523*4882a593Smuzhiyun * time.
524*4882a593Smuzhiyun */
525*4882a593Smuzhiyun setup_path();
526*4882a593Smuzhiyun /*
527*4882a593Smuzhiyun * Block SIGWINCH notifications so that the thread that wants it can
528*4882a593Smuzhiyun * unblock and get syscalls like select interrupted instead of waiting
529*4882a593Smuzhiyun * forever while the signal goes to some other non interested thread.
530*4882a593Smuzhiyun */
531*4882a593Smuzhiyun pthread__block_sigwinch();
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun perf_debug_setup();
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun while (1) {
536*4882a593Smuzhiyun static int done_help;
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun run_argv(&argc, &argv);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun if (errno != ENOENT)
541*4882a593Smuzhiyun break;
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun if (!done_help) {
544*4882a593Smuzhiyun cmd = argv[0] = help_unknown_cmd(cmd);
545*4882a593Smuzhiyun done_help = 1;
546*4882a593Smuzhiyun } else
547*4882a593Smuzhiyun break;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun fprintf(stderr, "Failed to run command '%s': %s\n",
551*4882a593Smuzhiyun cmd, str_error_r(errno, sbuf, sizeof(sbuf)));
552*4882a593Smuzhiyun out:
553*4882a593Smuzhiyun return 1;
554*4882a593Smuzhiyun }
555