linux/tools/perf/builtin-script.c
<<
>>
Prefs
   1#include "builtin.h"
   2
   3#include "perf.h"
   4#include "util/cache.h"
   5#include "util/debug.h"
   6#include "util/exec_cmd.h"
   7#include "util/header.h"
   8#include "util/parse-options.h"
   9#include "util/session.h"
  10#include "util/symbol.h"
  11#include "util/thread.h"
  12#include "util/trace-event.h"
  13#include "util/parse-options.h"
  14#include "util/util.h"
  15
  16static char const               *script_name;
  17static char const               *generate_script_lang;
  18static bool                     debug_mode;
  19static u64                      last_timestamp;
  20static u64                      nr_unordered;
  21extern const struct option      record_options[];
  22
  23static int default_start_script(const char *script __unused,
  24                                int argc __unused,
  25                                const char **argv __unused)
  26{
  27        return 0;
  28}
  29
  30static int default_stop_script(void)
  31{
  32        return 0;
  33}
  34
  35static int default_generate_script(const char *outfile __unused)
  36{
  37        return 0;
  38}
  39
  40static struct scripting_ops default_scripting_ops = {
  41        .start_script           = default_start_script,
  42        .stop_script            = default_stop_script,
  43        .process_event          = print_event,
  44        .generate_script        = default_generate_script,
  45};
  46
  47static struct scripting_ops     *scripting_ops;
  48
  49static void setup_scripting(void)
  50{
  51        setup_perl_scripting();
  52        setup_python_scripting();
  53
  54        scripting_ops = &default_scripting_ops;
  55}
  56
  57static int cleanup_scripting(void)
  58{
  59        pr_debug("\nperf script stopped\n");
  60
  61        return scripting_ops->stop_script();
  62}
  63
  64static char const               *input_name = "perf.data";
  65
  66static int process_sample_event(event_t *event, struct sample_data *sample,
  67                                struct perf_session *session)
  68{
  69        struct thread *thread = perf_session__findnew(session, event->ip.pid);
  70
  71        if (thread == NULL) {
  72                pr_debug("problem processing %d event, skipping it.\n",
  73                         event->header.type);
  74                return -1;
  75        }
  76
  77        if (session->sample_type & PERF_SAMPLE_RAW) {
  78                if (debug_mode) {
  79                        if (sample->time < last_timestamp) {
  80                                pr_err("Samples misordered, previous: %" PRIu64
  81                                        " this: %" PRIu64 "\n", last_timestamp,
  82                                        sample->time);
  83                                nr_unordered++;
  84                        }
  85                        last_timestamp = sample->time;
  86                        return 0;
  87                }
  88                /*
  89                 * FIXME: better resolve from pid from the struct trace_entry
  90                 * field, although it should be the same than this perf
  91                 * event pid
  92                 */
  93                scripting_ops->process_event(sample->cpu, sample->raw_data,
  94                                             sample->raw_size,
  95                                             sample->time, thread->comm);
  96        }
  97
  98        session->hists.stats.total_period += sample->period;
  99        return 0;
 100}
 101
 102static struct perf_event_ops event_ops = {
 103        .sample = process_sample_event,
 104        .comm   = event__process_comm,
 105        .attr   = event__process_attr,
 106        .event_type = event__process_event_type,
 107        .tracing_data = event__process_tracing_data,
 108        .build_id = event__process_build_id,
 109        .ordering_requires_timestamps = true,
 110        .ordered_samples = true,
 111};
 112
 113extern volatile int session_done;
 114
 115static void sig_handler(int sig __unused)
 116{
 117        session_done = 1;
 118}
 119
 120static int __cmd_script(struct perf_session *session)
 121{
 122        int ret;
 123
 124        signal(SIGINT, sig_handler);
 125
 126        ret = perf_session__process_events(session, &event_ops);
 127
 128        if (debug_mode)
 129                pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
 130
 131        return ret;
 132}
 133
 134struct script_spec {
 135        struct list_head        node;
 136        struct scripting_ops    *ops;
 137        char                    spec[0];
 138};
 139
 140static LIST_HEAD(script_specs);
 141
 142static struct script_spec *script_spec__new(const char *spec,
 143                                            struct scripting_ops *ops)
 144{
 145        struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);
 146
 147        if (s != NULL) {
 148                strcpy(s->spec, spec);
 149                s->ops = ops;
 150        }
 151
 152        return s;
 153}
 154
 155static void script_spec__delete(struct script_spec *s)
 156{
 157        free(s->spec);
 158        free(s);
 159}
 160
 161static void script_spec__add(struct script_spec *s)
 162{
 163        list_add_tail(&s->node, &script_specs);
 164}
 165
 166static struct script_spec *script_spec__find(const char *spec)
 167{
 168        struct script_spec *s;
 169
 170        list_for_each_entry(s, &script_specs, node)
 171                if (strcasecmp(s->spec, spec) == 0)
 172                        return s;
 173        return NULL;
 174}
 175
 176static struct script_spec *script_spec__findnew(const char *spec,
 177                                                struct scripting_ops *ops)
 178{
 179        struct script_spec *s = script_spec__find(spec);
 180
 181        if (s)
 182                return s;
 183
 184        s = script_spec__new(spec, ops);
 185        if (!s)
 186                goto out_delete_spec;
 187
 188        script_spec__add(s);
 189
 190        return s;
 191
 192out_delete_spec:
 193        script_spec__delete(s);
 194
 195        return NULL;
 196}
 197
 198int script_spec_register(const char *spec, struct scripting_ops *ops)
 199{
 200        struct script_spec *s;
 201
 202        s = script_spec__find(spec);
 203        if (s)
 204                return -1;
 205
 206        s = script_spec__findnew(spec, ops);
 207        if (!s)
 208                return -1;
 209
 210        return 0;
 211}
 212
 213static struct scripting_ops *script_spec__lookup(const char *spec)
 214{
 215        struct script_spec *s = script_spec__find(spec);
 216        if (!s)
 217                return NULL;
 218
 219        return s->ops;
 220}
 221
 222static void list_available_languages(void)
 223{
 224        struct script_spec *s;
 225
 226        fprintf(stderr, "\n");
 227        fprintf(stderr, "Scripting language extensions (used in "
 228                "perf script -s [spec:]script.[spec]):\n\n");
 229
 230        list_for_each_entry(s, &script_specs, node)
 231                fprintf(stderr, "  %-42s [%s]\n", s->spec, s->ops->name);
 232
 233        fprintf(stderr, "\n");
 234}
 235
 236static int parse_scriptname(const struct option *opt __used,
 237                            const char *str, int unset __used)
 238{
 239        char spec[PATH_MAX];
 240        const char *script, *ext;
 241        int len;
 242
 243        if (strcmp(str, "lang") == 0) {
 244                list_available_languages();
 245                exit(0);
 246        }
 247
 248        script = strchr(str, ':');
 249        if (script) {
 250                len = script - str;
 251                if (len >= PATH_MAX) {
 252                        fprintf(stderr, "invalid language specifier");
 253                        return -1;
 254                }
 255                strncpy(spec, str, len);
 256                spec[len] = '\0';
 257                scripting_ops = script_spec__lookup(spec);
 258                if (!scripting_ops) {
 259                        fprintf(stderr, "invalid language specifier");
 260                        return -1;
 261                }
 262                script++;
 263        } else {
 264                script = str;
 265                ext = strrchr(script, '.');
 266                if (!ext) {
 267                        fprintf(stderr, "invalid script extension");
 268                        return -1;
 269                }
 270                scripting_ops = script_spec__lookup(++ext);
 271                if (!scripting_ops) {
 272                        fprintf(stderr, "invalid script extension");
 273                        return -1;
 274                }
 275        }
 276
 277        script_name = strdup(script);
 278
 279        return 0;
 280}
 281
 282/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */
 283static int is_directory(const char *base_path, const struct dirent *dent)
 284{
 285        char path[PATH_MAX];
 286        struct stat st;
 287
 288        sprintf(path, "%s/%s", base_path, dent->d_name);
 289        if (stat(path, &st))
 290                return 0;
 291
 292        return S_ISDIR(st.st_mode);
 293}
 294
 295#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\
 296        while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) &&     \
 297               lang_next)                                               \
 298                if ((lang_dirent.d_type == DT_DIR ||                    \
 299                     (lang_dirent.d_type == DT_UNKNOWN &&               \
 300                      is_directory(scripts_path, &lang_dirent))) &&     \
 301                    (strcmp(lang_dirent.d_name, ".")) &&                \
 302                    (strcmp(lang_dirent.d_name, "..")))
 303
 304#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\
 305        while (!readdir_r(lang_dir, &script_dirent, &script_next) &&    \
 306               script_next)                                             \
 307                if (script_dirent.d_type != DT_DIR &&                   \
 308                    (script_dirent.d_type != DT_UNKNOWN ||              \
 309                     !is_directory(lang_path, &script_dirent)))
 310
 311
 312#define RECORD_SUFFIX                   "-record"
 313#define REPORT_SUFFIX                   "-report"
 314
 315struct script_desc {
 316        struct list_head        node;
 317        char                    *name;
 318        char                    *half_liner;
 319        char                    *args;
 320};
 321
 322static LIST_HEAD(script_descs);
 323
 324static struct script_desc *script_desc__new(const char *name)
 325{
 326        struct script_desc *s = zalloc(sizeof(*s));
 327
 328        if (s != NULL && name)
 329                s->name = strdup(name);
 330
 331        return s;
 332}
 333
 334static void script_desc__delete(struct script_desc *s)
 335{
 336        free(s->name);
 337        free(s->half_liner);
 338        free(s->args);
 339        free(s);
 340}
 341
 342static void script_desc__add(struct script_desc *s)
 343{
 344        list_add_tail(&s->node, &script_descs);
 345}
 346
 347static struct script_desc *script_desc__find(const char *name)
 348{
 349        struct script_desc *s;
 350
 351        list_for_each_entry(s, &script_descs, node)
 352                if (strcasecmp(s->name, name) == 0)
 353                        return s;
 354        return NULL;
 355}
 356
 357static struct script_desc *script_desc__findnew(const char *name)
 358{
 359        struct script_desc *s = script_desc__find(name);
 360
 361        if (s)
 362                return s;
 363
 364        s = script_desc__new(name);
 365        if (!s)
 366                goto out_delete_desc;
 367
 368        script_desc__add(s);
 369
 370        return s;
 371
 372out_delete_desc:
 373        script_desc__delete(s);
 374
 375        return NULL;
 376}
 377
 378static const char *ends_with(const char *str, const char *suffix)
 379{
 380        size_t suffix_len = strlen(suffix);
 381        const char *p = str;
 382
 383        if (strlen(str) > suffix_len) {
 384                p = str + strlen(str) - suffix_len;
 385                if (!strncmp(p, suffix, suffix_len))
 386                        return p;
 387        }
 388
 389        return NULL;
 390}
 391
 392static char *ltrim(char *str)
 393{
 394        int len = strlen(str);
 395
 396        while (len && isspace(*str)) {
 397                len--;
 398                str++;
 399        }
 400
 401        return str;
 402}
 403
 404static int read_script_info(struct script_desc *desc, const char *filename)
 405{
 406        char line[BUFSIZ], *p;
 407        FILE *fp;
 408
 409        fp = fopen(filename, "r");
 410        if (!fp)
 411                return -1;
 412
 413        while (fgets(line, sizeof(line), fp)) {
 414                p = ltrim(line);
 415                if (strlen(p) == 0)
 416                        continue;
 417                if (*p != '#')
 418                        continue;
 419                p++;
 420                if (strlen(p) && *p == '!')
 421                        continue;
 422
 423                p = ltrim(p);
 424                if (strlen(p) && p[strlen(p) - 1] == '\n')
 425                        p[strlen(p) - 1] = '\0';
 426
 427                if (!strncmp(p, "description:", strlen("description:"))) {
 428                        p += strlen("description:");
 429                        desc->half_liner = strdup(ltrim(p));
 430                        continue;
 431                }
 432
 433                if (!strncmp(p, "args:", strlen("args:"))) {
 434                        p += strlen("args:");
 435                        desc->args = strdup(ltrim(p));
 436                        continue;
 437                }
 438        }
 439
 440        fclose(fp);
 441
 442        return 0;
 443}
 444
 445static int list_available_scripts(const struct option *opt __used,
 446                                  const char *s __used, int unset __used)
 447{
 448        struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
 449        char scripts_path[MAXPATHLEN];
 450        DIR *scripts_dir, *lang_dir;
 451        char script_path[MAXPATHLEN];
 452        char lang_path[MAXPATHLEN];
 453        struct script_desc *desc;
 454        char first_half[BUFSIZ];
 455        char *script_root;
 456        char *str;
 457
 458        snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
 459
 460        scripts_dir = opendir(scripts_path);
 461        if (!scripts_dir)
 462                return -1;
 463
 464        for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
 465                snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
 466                         lang_dirent.d_name);
 467                lang_dir = opendir(lang_path);
 468                if (!lang_dir)
 469                        continue;
 470
 471                for_each_script(lang_path, lang_dir, script_dirent, script_next) {
 472                        script_root = strdup(script_dirent.d_name);
 473                        str = (char *)ends_with(script_root, REPORT_SUFFIX);
 474                        if (str) {
 475                                *str = '\0';
 476                                desc = script_desc__findnew(script_root);
 477                                snprintf(script_path, MAXPATHLEN, "%s/%s",
 478                                         lang_path, script_dirent.d_name);
 479                                read_script_info(desc, script_path);
 480                        }
 481                        free(script_root);
 482                }
 483        }
 484
 485        fprintf(stdout, "List of available trace scripts:\n");
 486        list_for_each_entry(desc, &script_descs, node) {
 487                sprintf(first_half, "%s %s", desc->name,
 488                        desc->args ? desc->args : "");
 489                fprintf(stdout, "  %-36s %s\n", first_half,
 490                        desc->half_liner ? desc->half_liner : "");
 491        }
 492
 493        exit(0);
 494}
 495
 496static char *get_script_path(const char *script_root, const char *suffix)
 497{
 498        struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
 499        char scripts_path[MAXPATHLEN];
 500        char script_path[MAXPATHLEN];
 501        DIR *scripts_dir, *lang_dir;
 502        char lang_path[MAXPATHLEN];
 503        char *str, *__script_root;
 504        char *path = NULL;
 505
 506        snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
 507
 508        scripts_dir = opendir(scripts_path);
 509        if (!scripts_dir)
 510                return NULL;
 511
 512        for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
 513                snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
 514                         lang_dirent.d_name);
 515                lang_dir = opendir(lang_path);
 516                if (!lang_dir)
 517                        continue;
 518
 519                for_each_script(lang_path, lang_dir, script_dirent, script_next) {
 520                        __script_root = strdup(script_dirent.d_name);
 521                        str = (char *)ends_with(__script_root, suffix);
 522                        if (str) {
 523                                *str = '\0';
 524                                if (strcmp(__script_root, script_root))
 525                                        continue;
 526                                snprintf(script_path, MAXPATHLEN, "%s/%s",
 527                                         lang_path, script_dirent.d_name);
 528                                path = strdup(script_path);
 529                                free(__script_root);
 530                                break;
 531                        }
 532                        free(__script_root);
 533                }
 534        }
 535
 536        return path;
 537}
 538
 539static bool is_top_script(const char *script_path)
 540{
 541        return ends_with(script_path, "top") == NULL ? false : true;
 542}
 543
 544static int has_required_arg(char *script_path)
 545{
 546        struct script_desc *desc;
 547        int n_args = 0;
 548        char *p;
 549
 550        desc = script_desc__new(NULL);
 551
 552        if (read_script_info(desc, script_path))
 553                goto out;
 554
 555        if (!desc->args)
 556                goto out;
 557
 558        for (p = desc->args; *p; p++)
 559                if (*p == '<')
 560                        n_args++;
 561out:
 562        script_desc__delete(desc);
 563
 564        return n_args;
 565}
 566
 567static const char * const script_usage[] = {
 568        "perf script [<options>]",
 569        "perf script [<options>] record <script> [<record-options>] <command>",
 570        "perf script [<options>] report <script> [script-args]",
 571        "perf script [<options>] <script> [<record-options>] <command>",
 572        "perf script [<options>] <top-script> [script-args]",
 573        NULL
 574};
 575
 576static const struct option options[] = {
 577        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
 578                    "dump raw trace in ASCII"),
 579        OPT_INCR('v', "verbose", &verbose,
 580                    "be more verbose (show symbol address, etc)"),
 581        OPT_BOOLEAN('L', "Latency", &latency_format,
 582                    "show latency attributes (irqs/preemption disabled, etc)"),
 583        OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
 584                           list_available_scripts),
 585        OPT_CALLBACK('s', "script", NULL, "name",
 586                     "script file name (lang:script name, script name, or *)",
 587                     parse_scriptname),
 588        OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
 589                   "generate perf-script.xx script in specified language"),
 590        OPT_STRING('i', "input", &input_name, "file",
 591                    "input file name"),
 592        OPT_BOOLEAN('d', "debug-mode", &debug_mode,
 593                   "do various checks like samples ordering and lost events"),
 594
 595        OPT_END()
 596};
 597
 598static bool have_cmd(int argc, const char **argv)
 599{
 600        char **__argv = malloc(sizeof(const char *) * argc);
 601
 602        if (!__argv)
 603                die("malloc");
 604        memcpy(__argv, argv, sizeof(const char *) * argc);
 605        argc = parse_options(argc, (const char **)__argv, record_options,
 606                             NULL, PARSE_OPT_STOP_AT_NON_OPTION);
 607        free(__argv);
 608
 609        return argc != 0;
 610}
 611
 612int cmd_script(int argc, const char **argv, const char *prefix __used)
 613{
 614        char *rec_script_path = NULL;
 615        char *rep_script_path = NULL;
 616        struct perf_session *session;
 617        char *script_path = NULL;
 618        const char **__argv;
 619        bool system_wide;
 620        int i, j, err;
 621
 622        setup_scripting();
 623
 624        argc = parse_options(argc, argv, options, script_usage,
 625                             PARSE_OPT_STOP_AT_NON_OPTION);
 626
 627        if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
 628                rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
 629                if (!rec_script_path)
 630                        return cmd_record(argc, argv, NULL);
 631        }
 632
 633        if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
 634                rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
 635                if (!rep_script_path) {
 636                        fprintf(stderr,
 637                                "Please specify a valid report script"
 638                                "(see 'perf script -l' for listing)\n");
 639                        return -1;
 640                }
 641        }
 642
 643        /* make sure PERF_EXEC_PATH is set for scripts */
 644        perf_set_argv_exec_path(perf_exec_path());
 645
 646        if (argc && !script_name && !rec_script_path && !rep_script_path) {
 647                int live_pipe[2];
 648                int rep_args;
 649                pid_t pid;
 650
 651                rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
 652                rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
 653
 654                if (!rec_script_path && !rep_script_path) {
 655                        fprintf(stderr, " Couldn't find script %s\n\n See perf"
 656                                " script -l for available scripts.\n", argv[0]);
 657                        usage_with_options(script_usage, options);
 658                }
 659
 660                if (is_top_script(argv[0])) {
 661                        rep_args = argc - 1;
 662                } else {
 663                        int rec_args;
 664
 665                        rep_args = has_required_arg(rep_script_path);
 666                        rec_args = (argc - 1) - rep_args;
 667                        if (rec_args < 0) {
 668                                fprintf(stderr, " %s script requires options."
 669                                        "\n\n See perf script -l for available "
 670                                        "scripts and options.\n", argv[0]);
 671                                usage_with_options(script_usage, options);
 672                        }
 673                }
 674
 675                if (pipe(live_pipe) < 0) {
 676                        perror("failed to create pipe");
 677                        exit(-1);
 678                }
 679
 680                pid = fork();
 681                if (pid < 0) {
 682                        perror("failed to fork");
 683                        exit(-1);
 684                }
 685
 686                if (!pid) {
 687                        system_wide = true;
 688                        j = 0;
 689
 690                        dup2(live_pipe[1], 1);
 691                        close(live_pipe[0]);
 692
 693                        if (!is_top_script(argv[0]))
 694                                system_wide = !have_cmd(argc - rep_args,
 695                                                        &argv[rep_args]);
 696
 697                        __argv = malloc((argc + 6) * sizeof(const char *));
 698                        if (!__argv)
 699                                die("malloc");
 700
 701                        __argv[j++] = "/bin/sh";
 702                        __argv[j++] = rec_script_path;
 703                        if (system_wide)
 704                                __argv[j++] = "-a";
 705                        __argv[j++] = "-q";
 706                        __argv[j++] = "-o";
 707                        __argv[j++] = "-";
 708                        for (i = rep_args + 1; i < argc; i++)
 709                                __argv[j++] = argv[i];
 710                        __argv[j++] = NULL;
 711
 712                        execvp("/bin/sh", (char **)__argv);
 713                        free(__argv);
 714                        exit(-1);
 715                }
 716
 717                dup2(live_pipe[0], 0);
 718                close(live_pipe[1]);
 719
 720                __argv = malloc((argc + 4) * sizeof(const char *));
 721                if (!__argv)
 722                        die("malloc");
 723                j = 0;
 724                __argv[j++] = "/bin/sh";
 725                __argv[j++] = rep_script_path;
 726                for (i = 1; i < rep_args + 1; i++)
 727                        __argv[j++] = argv[i];
 728                __argv[j++] = "-i";
 729                __argv[j++] = "-";
 730                __argv[j++] = NULL;
 731
 732                execvp("/bin/sh", (char **)__argv);
 733                free(__argv);
 734                exit(-1);
 735        }
 736
 737        if (rec_script_path)
 738                script_path = rec_script_path;
 739        if (rep_script_path)
 740                script_path = rep_script_path;
 741
 742        if (script_path) {
 743                system_wide = false;
 744                j = 0;
 745
 746                if (rec_script_path)
 747                        system_wide = !have_cmd(argc - 1, &argv[1]);
 748
 749                __argv = malloc((argc + 2) * sizeof(const char *));
 750                if (!__argv)
 751                        die("malloc");
 752                __argv[j++] = "/bin/sh";
 753                __argv[j++] = script_path;
 754                if (system_wide)
 755                        __argv[j++] = "-a";
 756                for (i = 2; i < argc; i++)
 757                        __argv[j++] = argv[i];
 758                __argv[j++] = NULL;
 759
 760                execvp("/bin/sh", (char **)__argv);
 761                free(__argv);
 762                exit(-1);
 763        }
 764
 765        if (symbol__init() < 0)
 766                return -1;
 767        if (!script_name)
 768                setup_pager();
 769
 770        session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
 771        if (session == NULL)
 772                return -ENOMEM;
 773
 774        if (strcmp(input_name, "-") &&
 775            !perf_session__has_traces(session, "record -R"))
 776                return -EINVAL;
 777
 778        if (generate_script_lang) {
 779                struct stat perf_stat;
 780
 781                int input = open(input_name, O_RDONLY);
 782                if (input < 0) {
 783                        perror("failed to open file");
 784                        exit(-1);
 785                }
 786
 787                err = fstat(input, &perf_stat);
 788                if (err < 0) {
 789                        perror("failed to stat file");
 790                        exit(-1);
 791                }
 792
 793                if (!perf_stat.st_size) {
 794                        fprintf(stderr, "zero-sized file, nothing to do!\n");
 795                        exit(0);
 796                }
 797
 798                scripting_ops = script_spec__lookup(generate_script_lang);
 799                if (!scripting_ops) {
 800                        fprintf(stderr, "invalid language specifier");
 801                        return -1;
 802                }
 803
 804                err = scripting_ops->generate_script("perf-script");
 805                goto out;
 806        }
 807
 808        if (script_name) {
 809                err = scripting_ops->start_script(script_name, argc, argv);
 810                if (err)
 811                        goto out;
 812                pr_debug("perf script started with script %s\n\n", script_name);
 813        }
 814
 815        err = __cmd_script(session);
 816
 817        perf_session__delete(session);
 818        cleanup_scripting();
 819out:
 820        return err;
 821}
 822