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