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/util.h"
  14#include "util/evlist.h"
  15#include "util/evsel.h"
  16#include <linux/bitmap.h>
  17
  18static char const               *script_name;
  19static char const               *generate_script_lang;
  20static bool                     debug_mode;
  21static u64                      last_timestamp;
  22static u64                      nr_unordered;
  23extern const struct option      record_options[];
  24static bool                     no_callchain;
  25static bool                     show_full_info;
  26static const char               *cpu_list;
  27static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
  28
  29enum perf_output_field {
  30        PERF_OUTPUT_COMM            = 1U << 0,
  31        PERF_OUTPUT_TID             = 1U << 1,
  32        PERF_OUTPUT_PID             = 1U << 2,
  33        PERF_OUTPUT_TIME            = 1U << 3,
  34        PERF_OUTPUT_CPU             = 1U << 4,
  35        PERF_OUTPUT_EVNAME          = 1U << 5,
  36        PERF_OUTPUT_TRACE           = 1U << 6,
  37        PERF_OUTPUT_IP              = 1U << 7,
  38        PERF_OUTPUT_SYM             = 1U << 8,
  39        PERF_OUTPUT_DSO             = 1U << 9,
  40        PERF_OUTPUT_ADDR            = 1U << 10,
  41};
  42
  43struct output_option {
  44        const char *str;
  45        enum perf_output_field field;
  46} all_output_options[] = {
  47        {.str = "comm",  .field = PERF_OUTPUT_COMM},
  48        {.str = "tid",   .field = PERF_OUTPUT_TID},
  49        {.str = "pid",   .field = PERF_OUTPUT_PID},
  50        {.str = "time",  .field = PERF_OUTPUT_TIME},
  51        {.str = "cpu",   .field = PERF_OUTPUT_CPU},
  52        {.str = "event", .field = PERF_OUTPUT_EVNAME},
  53        {.str = "trace", .field = PERF_OUTPUT_TRACE},
  54        {.str = "ip",    .field = PERF_OUTPUT_IP},
  55        {.str = "sym",   .field = PERF_OUTPUT_SYM},
  56        {.str = "dso",   .field = PERF_OUTPUT_DSO},
  57        {.str = "addr",  .field = PERF_OUTPUT_ADDR},
  58};
  59
  60/* default set to maintain compatibility with current format */
  61static struct {
  62        bool user_set;
  63        bool wildcard_set;
  64        u64 fields;
  65        u64 invalid_fields;
  66} output[PERF_TYPE_MAX] = {
  67
  68        [PERF_TYPE_HARDWARE] = {
  69                .user_set = false,
  70
  71                .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
  72                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
  73                              PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
  74                                  PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
  75
  76                .invalid_fields = PERF_OUTPUT_TRACE,
  77        },
  78
  79        [PERF_TYPE_SOFTWARE] = {
  80                .user_set = false,
  81
  82                .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
  83                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
  84                              PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
  85                                  PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
  86
  87                .invalid_fields = PERF_OUTPUT_TRACE,
  88        },
  89
  90        [PERF_TYPE_TRACEPOINT] = {
  91                .user_set = false,
  92
  93                .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
  94                                  PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
  95                                  PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
  96        },
  97
  98        [PERF_TYPE_RAW] = {
  99                .user_set = false,
 100
 101                .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
 102                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
 103                              PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
 104                                  PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
 105
 106                .invalid_fields = PERF_OUTPUT_TRACE,
 107        },
 108};
 109
 110static bool output_set_by_user(void)
 111{
 112        int j;
 113        for (j = 0; j < PERF_TYPE_MAX; ++j) {
 114                if (output[j].user_set)
 115                        return true;
 116        }
 117        return false;
 118}
 119
 120static const char *output_field2str(enum perf_output_field field)
 121{
 122        int i, imax = ARRAY_SIZE(all_output_options);
 123        const char *str = "";
 124
 125        for (i = 0; i < imax; ++i) {
 126                if (all_output_options[i].field == field) {
 127                        str = all_output_options[i].str;
 128                        break;
 129                }
 130        }
 131        return str;
 132}
 133
 134#define PRINT_FIELD(x)  (output[attr->type].fields & PERF_OUTPUT_##x)
 135
 136static int perf_event_attr__check_stype(struct perf_event_attr *attr,
 137                                  u64 sample_type, const char *sample_msg,
 138                                  enum perf_output_field field)
 139{
 140        int type = attr->type;
 141        const char *evname;
 142
 143        if (attr->sample_type & sample_type)
 144                return 0;
 145
 146        if (output[type].user_set) {
 147                evname = __event_name(attr->type, attr->config);
 148                pr_err("Samples for '%s' event do not have %s attribute set. "
 149                       "Cannot print '%s' field.\n",
 150                       evname, sample_msg, output_field2str(field));
 151                return -1;
 152        }
 153
 154        /* user did not ask for it explicitly so remove from the default list */
 155        output[type].fields &= ~field;
 156        evname = __event_name(attr->type, attr->config);
 157        pr_debug("Samples for '%s' event do not have %s attribute set. "
 158                 "Skipping '%s' field.\n",
 159                 evname, sample_msg, output_field2str(field));
 160
 161        return 0;
 162}
 163
 164static int perf_evsel__check_attr(struct perf_evsel *evsel,
 165                                  struct perf_session *session)
 166{
 167        struct perf_event_attr *attr = &evsel->attr;
 168
 169        if (PRINT_FIELD(TRACE) &&
 170                !perf_session__has_traces(session, "record -R"))
 171                return -EINVAL;
 172
 173        if (PRINT_FIELD(IP)) {
 174                if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
 175                                           PERF_OUTPUT_IP))
 176                        return -EINVAL;
 177
 178                if (!no_callchain &&
 179                    !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
 180                        symbol_conf.use_callchain = false;
 181        }
 182
 183        if (PRINT_FIELD(ADDR) &&
 184                perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR",
 185                                       PERF_OUTPUT_ADDR))
 186                return -EINVAL;
 187
 188        if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
 189                pr_err("Display of symbols requested but neither sample IP nor "
 190                           "sample address\nis selected. Hence, no addresses to convert "
 191                       "to symbols.\n");
 192                return -EINVAL;
 193        }
 194        if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
 195                pr_err("Display of DSO requested but neither sample IP nor "
 196                           "sample address\nis selected. Hence, no addresses to convert "
 197                       "to DSO.\n");
 198                return -EINVAL;
 199        }
 200
 201        if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
 202                perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
 203                                       PERF_OUTPUT_TID|PERF_OUTPUT_PID))
 204                return -EINVAL;
 205
 206        if (PRINT_FIELD(TIME) &&
 207                perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME",
 208                                       PERF_OUTPUT_TIME))
 209                return -EINVAL;
 210
 211        if (PRINT_FIELD(CPU) &&
 212                perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU",
 213                                       PERF_OUTPUT_CPU))
 214                return -EINVAL;
 215
 216        return 0;
 217}
 218
 219/*
 220 * verify all user requested events exist and the samples
 221 * have the expected data
 222 */
 223static int perf_session__check_output_opt(struct perf_session *session)
 224{
 225        int j;
 226        struct perf_evsel *evsel;
 227
 228        for (j = 0; j < PERF_TYPE_MAX; ++j) {
 229                evsel = perf_session__find_first_evtype(session, j);
 230
 231                /*
 232                 * even if fields is set to 0 (ie., show nothing) event must
 233                 * exist if user explicitly includes it on the command line
 234                 */
 235                if (!evsel && output[j].user_set && !output[j].wildcard_set) {
 236                        pr_err("%s events do not exist. "
 237                               "Remove corresponding -f option to proceed.\n",
 238                               event_type(j));
 239                        return -1;
 240                }
 241
 242                if (evsel && output[j].fields &&
 243                        perf_evsel__check_attr(evsel, session))
 244                        return -1;
 245        }
 246
 247        return 0;
 248}
 249
 250static void print_sample_start(struct perf_sample *sample,
 251                               struct thread *thread,
 252                               struct perf_event_attr *attr)
 253{
 254        int type;
 255        struct event *event;
 256        const char *evname = NULL;
 257        unsigned long secs;
 258        unsigned long usecs;
 259        unsigned long long nsecs;
 260
 261        if (PRINT_FIELD(COMM)) {
 262                if (latency_format)
 263                        printf("%8.8s ", thread->comm);
 264                else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
 265                        printf("%s ", thread->comm);
 266                else
 267                        printf("%16s ", thread->comm);
 268        }
 269
 270        if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
 271                printf("%5d/%-5d ", sample->pid, sample->tid);
 272        else if (PRINT_FIELD(PID))
 273                printf("%5d ", sample->pid);
 274        else if (PRINT_FIELD(TID))
 275                printf("%5d ", sample->tid);
 276
 277        if (PRINT_FIELD(CPU)) {
 278                if (latency_format)
 279                        printf("%3d ", sample->cpu);
 280                else
 281                        printf("[%03d] ", sample->cpu);
 282        }
 283
 284        if (PRINT_FIELD(TIME)) {
 285                nsecs = sample->time;
 286                secs = nsecs / NSECS_PER_SEC;
 287                nsecs -= secs * NSECS_PER_SEC;
 288                usecs = nsecs / NSECS_PER_USEC;
 289                printf("%5lu.%06lu: ", secs, usecs);
 290        }
 291
 292        if (PRINT_FIELD(EVNAME)) {
 293                if (attr->type == PERF_TYPE_TRACEPOINT) {
 294                        type = trace_parse_common_type(sample->raw_data);
 295                        event = trace_find_event(type);
 296                        if (event)
 297                                evname = event->name;
 298                } else
 299                        evname = __event_name(attr->type, attr->config);
 300
 301                printf("%s: ", evname ? evname : "(unknown)");
 302        }
 303}
 304
 305static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
 306{
 307        if ((attr->type == PERF_TYPE_SOFTWARE) &&
 308            ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) ||
 309             (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) ||
 310             (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
 311                return true;
 312
 313        return false;
 314}
 315
 316static void print_sample_addr(union perf_event *event,
 317                          struct perf_sample *sample,
 318                          struct perf_session *session,
 319                          struct thread *thread,
 320                          struct perf_event_attr *attr)
 321{
 322        struct addr_location al;
 323        u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 324        const char *symname, *dsoname;
 325
 326        printf("%16" PRIx64, sample->addr);
 327
 328        if (!sample_addr_correlates_sym(attr))
 329                return;
 330
 331        thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
 332                              event->ip.pid, sample->addr, &al);
 333        if (!al.map)
 334                thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE,
 335                                      event->ip.pid, sample->addr, &al);
 336
 337        al.cpu = sample->cpu;
 338        al.sym = NULL;
 339
 340        if (al.map)
 341                al.sym = map__find_symbol(al.map, al.addr, NULL);
 342
 343        if (PRINT_FIELD(SYM)) {
 344                if (al.sym && al.sym->name)
 345                        symname = al.sym->name;
 346                else
 347                        symname = "";
 348
 349                printf(" %16s", symname);
 350        }
 351
 352        if (PRINT_FIELD(DSO)) {
 353                if (al.map && al.map->dso && al.map->dso->name)
 354                        dsoname = al.map->dso->name;
 355                else
 356                        dsoname = "";
 357
 358                printf(" (%s)", dsoname);
 359        }
 360}
 361
 362static void process_event(union perf_event *event __unused,
 363                          struct perf_sample *sample,
 364                          struct perf_evsel *evsel,
 365                          struct perf_session *session,
 366                          struct thread *thread)
 367{
 368        struct perf_event_attr *attr = &evsel->attr;
 369
 370        if (output[attr->type].fields == 0)
 371                return;
 372
 373        print_sample_start(sample, thread, attr);
 374
 375        if (PRINT_FIELD(TRACE))
 376                print_trace_event(sample->cpu, sample->raw_data,
 377                                  sample->raw_size);
 378
 379        if (PRINT_FIELD(ADDR))
 380                print_sample_addr(event, sample, session, thread, attr);
 381
 382        if (PRINT_FIELD(IP)) {
 383                if (!symbol_conf.use_callchain)
 384                        printf(" ");
 385                else
 386                        printf("\n");
 387                perf_session__print_ip(event, sample, session,
 388                                              PRINT_FIELD(SYM), PRINT_FIELD(DSO));
 389        }
 390
 391        printf("\n");
 392}
 393
 394static int default_start_script(const char *script __unused,
 395                                int argc __unused,
 396                                const char **argv __unused)
 397{
 398        return 0;
 399}
 400
 401static int default_stop_script(void)
 402{
 403        return 0;
 404}
 405
 406static int default_generate_script(const char *outfile __unused)
 407{
 408        return 0;
 409}
 410
 411static struct scripting_ops default_scripting_ops = {
 412        .start_script           = default_start_script,
 413        .stop_script            = default_stop_script,
 414        .process_event          = process_event,
 415        .generate_script        = default_generate_script,
 416};
 417
 418static struct scripting_ops     *scripting_ops;
 419
 420static void setup_scripting(void)
 421{
 422        setup_perl_scripting();
 423        setup_python_scripting();
 424
 425        scripting_ops = &default_scripting_ops;
 426}
 427
 428static int cleanup_scripting(void)
 429{
 430        pr_debug("\nperf script stopped\n");
 431
 432        return scripting_ops->stop_script();
 433}
 434
 435static char const               *input_name = "perf.data";
 436
 437static int process_sample_event(union perf_event *event,
 438                                struct perf_sample *sample,
 439                                struct perf_evsel *evsel,
 440                                struct perf_session *session)
 441{
 442        struct thread *thread = perf_session__findnew(session, event->ip.pid);
 443
 444        if (thread == NULL) {
 445                pr_debug("problem processing %d event, skipping it.\n",
 446                         event->header.type);
 447                return -1;
 448        }
 449
 450        if (debug_mode) {
 451                if (sample->time < last_timestamp) {
 452                        pr_err("Samples misordered, previous: %" PRIu64
 453                                " this: %" PRIu64 "\n", last_timestamp,
 454                                sample->time);
 455                        nr_unordered++;
 456                }
 457                last_timestamp = sample->time;
 458                return 0;
 459        }
 460
 461        if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
 462                return 0;
 463
 464        scripting_ops->process_event(event, sample, evsel, session, thread);
 465
 466        session->hists.stats.total_period += sample->period;
 467        return 0;
 468}
 469
 470static struct perf_event_ops event_ops = {
 471        .sample          = process_sample_event,
 472        .mmap            = perf_event__process_mmap,
 473        .comm            = perf_event__process_comm,
 474        .exit            = perf_event__process_task,
 475        .fork            = perf_event__process_task,
 476        .attr            = perf_event__process_attr,
 477        .event_type      = perf_event__process_event_type,
 478        .tracing_data    = perf_event__process_tracing_data,
 479        .build_id        = perf_event__process_build_id,
 480        .ordered_samples = true,
 481        .ordering_requires_timestamps = true,
 482};
 483
 484extern volatile int session_done;
 485
 486static void sig_handler(int sig __unused)
 487{
 488        session_done = 1;
 489}
 490
 491static int __cmd_script(struct perf_session *session)
 492{
 493        int ret;
 494
 495        signal(SIGINT, sig_handler);
 496
 497        ret = perf_session__process_events(session, &event_ops);
 498
 499        if (debug_mode)
 500                pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
 501
 502        return ret;
 503}
 504
 505struct script_spec {
 506        struct list_head        node;
 507        struct scripting_ops    *ops;
 508        char                    spec[0];
 509};
 510
 511static LIST_HEAD(script_specs);
 512
 513static struct script_spec *script_spec__new(const char *spec,
 514                                            struct scripting_ops *ops)
 515{
 516        struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);
 517
 518        if (s != NULL) {
 519                strcpy(s->spec, spec);
 520                s->ops = ops;
 521        }
 522
 523        return s;
 524}
 525
 526static void script_spec__delete(struct script_spec *s)
 527{
 528        free(s->spec);
 529        free(s);
 530}
 531
 532static void script_spec__add(struct script_spec *s)
 533{
 534        list_add_tail(&s->node, &script_specs);
 535}
 536
 537static struct script_spec *script_spec__find(const char *spec)
 538{
 539        struct script_spec *s;
 540
 541        list_for_each_entry(s, &script_specs, node)
 542                if (strcasecmp(s->spec, spec) == 0)
 543                        return s;
 544        return NULL;
 545}
 546
 547static struct script_spec *script_spec__findnew(const char *spec,
 548                                                struct scripting_ops *ops)
 549{
 550        struct script_spec *s = script_spec__find(spec);
 551
 552        if (s)
 553                return s;
 554
 555        s = script_spec__new(spec, ops);
 556        if (!s)
 557                goto out_delete_spec;
 558
 559        script_spec__add(s);
 560
 561        return s;
 562
 563out_delete_spec:
 564        script_spec__delete(s);
 565
 566        return NULL;
 567}
 568
 569int script_spec_register(const char *spec, struct scripting_ops *ops)
 570{
 571        struct script_spec *s;
 572
 573        s = script_spec__find(spec);
 574        if (s)
 575                return -1;
 576
 577        s = script_spec__findnew(spec, ops);
 578        if (!s)
 579                return -1;
 580
 581        return 0;
 582}
 583
 584static struct scripting_ops *script_spec__lookup(const char *spec)
 585{
 586        struct script_spec *s = script_spec__find(spec);
 587        if (!s)
 588                return NULL;
 589
 590        return s->ops;
 591}
 592
 593static void list_available_languages(void)
 594{
 595        struct script_spec *s;
 596
 597        fprintf(stderr, "\n");
 598        fprintf(stderr, "Scripting language extensions (used in "
 599                "perf script -s [spec:]script.[spec]):\n\n");
 600
 601        list_for_each_entry(s, &script_specs, node)
 602                fprintf(stderr, "  %-42s [%s]\n", s->spec, s->ops->name);
 603
 604        fprintf(stderr, "\n");
 605}
 606
 607static int parse_scriptname(const struct option *opt __used,
 608                            const char *str, int unset __used)
 609{
 610        char spec[PATH_MAX];
 611        const char *script, *ext;
 612        int len;
 613
 614        if (strcmp(str, "lang") == 0) {
 615                list_available_languages();
 616                exit(0);
 617        }
 618
 619        script = strchr(str, ':');
 620        if (script) {
 621                len = script - str;
 622                if (len >= PATH_MAX) {
 623                        fprintf(stderr, "invalid language specifier");
 624                        return -1;
 625                }
 626                strncpy(spec, str, len);
 627                spec[len] = '\0';
 628                scripting_ops = script_spec__lookup(spec);
 629                if (!scripting_ops) {
 630                        fprintf(stderr, "invalid language specifier");
 631                        return -1;
 632                }
 633                script++;
 634        } else {
 635                script = str;
 636                ext = strrchr(script, '.');
 637                if (!ext) {
 638                        fprintf(stderr, "invalid script extension");
 639                        return -1;
 640                }
 641                scripting_ops = script_spec__lookup(++ext);
 642                if (!scripting_ops) {
 643                        fprintf(stderr, "invalid script extension");
 644                        return -1;
 645                }
 646        }
 647
 648        script_name = strdup(script);
 649
 650        return 0;
 651}
 652
 653static int parse_output_fields(const struct option *opt __used,
 654                            const char *arg, int unset __used)
 655{
 656        char *tok;
 657        int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
 658        int j;
 659        int rc = 0;
 660        char *str = strdup(arg);
 661        int type = -1;
 662
 663        if (!str)
 664                return -ENOMEM;
 665
 666        /* first word can state for which event type the user is specifying
 667         * the fields. If no type exists, the specified fields apply to all
 668         * event types found in the file minus the invalid fields for a type.
 669         */
 670        tok = strchr(str, ':');
 671        if (tok) {
 672                *tok = '\0';
 673                tok++;
 674                if (!strcmp(str, "hw"))
 675                        type = PERF_TYPE_HARDWARE;
 676                else if (!strcmp(str, "sw"))
 677                        type = PERF_TYPE_SOFTWARE;
 678                else if (!strcmp(str, "trace"))
 679                        type = PERF_TYPE_TRACEPOINT;
 680                else if (!strcmp(str, "raw"))
 681                        type = PERF_TYPE_RAW;
 682                else {
 683                        fprintf(stderr, "Invalid event type in field string.\n");
 684                        return -EINVAL;
 685                }
 686
 687                if (output[type].user_set)
 688                        pr_warning("Overriding previous field request for %s events.\n",
 689                                   event_type(type));
 690
 691                output[type].fields = 0;
 692                output[type].user_set = true;
 693                output[type].wildcard_set = false;
 694
 695        } else {
 696                tok = str;
 697                if (strlen(str) == 0) {
 698                        fprintf(stderr,
 699                                "Cannot set fields to 'none' for all event types.\n");
 700                        rc = -EINVAL;
 701                        goto out;
 702                }
 703
 704                if (output_set_by_user())
 705                        pr_warning("Overriding previous field request for all events.\n");
 706
 707                for (j = 0; j < PERF_TYPE_MAX; ++j) {
 708                        output[j].fields = 0;
 709                        output[j].user_set = true;
 710                        output[j].wildcard_set = true;
 711                }
 712        }
 713
 714        tok = strtok(tok, ",");
 715        while (tok) {
 716                for (i = 0; i < imax; ++i) {
 717                        if (strcmp(tok, all_output_options[i].str) == 0)
 718                                break;
 719                }
 720                if (i == imax) {
 721                        fprintf(stderr, "Invalid field requested.\n");
 722                        rc = -EINVAL;
 723                        goto out;
 724                }
 725
 726                if (type == -1) {
 727                        /* add user option to all events types for
 728                         * which it is valid
 729                         */
 730                        for (j = 0; j < PERF_TYPE_MAX; ++j) {
 731                                if (output[j].invalid_fields & all_output_options[i].field) {
 732                                        pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
 733                                                   all_output_options[i].str, event_type(j));
 734                                } else
 735                                        output[j].fields |= all_output_options[i].field;
 736                        }
 737                } else {
 738                        if (output[type].invalid_fields & all_output_options[i].field) {
 739                                fprintf(stderr, "\'%s\' not valid for %s events.\n",
 740                                         all_output_options[i].str, event_type(type));
 741
 742                                rc = -EINVAL;
 743                                goto out;
 744                        }
 745                        output[type].fields |= all_output_options[i].field;
 746                }
 747
 748                tok = strtok(NULL, ",");
 749        }
 750
 751        if (type >= 0) {
 752                if (output[type].fields == 0) {
 753                        pr_debug("No fields requested for %s type. "
 754                                 "Events will not be displayed.\n", event_type(type));
 755                }
 756        }
 757
 758out:
 759        free(str);
 760        return rc;
 761}
 762
 763/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */
 764static int is_directory(const char *base_path, const struct dirent *dent)
 765{
 766        char path[PATH_MAX];
 767        struct stat st;
 768
 769        sprintf(path, "%s/%s", base_path, dent->d_name);
 770        if (stat(path, &st))
 771                return 0;
 772
 773        return S_ISDIR(st.st_mode);
 774}
 775
 776#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\
 777        while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) &&     \
 778               lang_next)                                               \
 779                if ((lang_dirent.d_type == DT_DIR ||                    \
 780                     (lang_dirent.d_type == DT_UNKNOWN &&               \
 781                      is_directory(scripts_path, &lang_dirent))) &&     \
 782                    (strcmp(lang_dirent.d_name, ".")) &&                \
 783                    (strcmp(lang_dirent.d_name, "..")))
 784
 785#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\
 786        while (!readdir_r(lang_dir, &script_dirent, &script_next) &&    \
 787               script_next)                                             \
 788                if (script_dirent.d_type != DT_DIR &&                   \
 789                    (script_dirent.d_type != DT_UNKNOWN ||              \
 790                     !is_directory(lang_path, &script_dirent)))
 791
 792
 793#define RECORD_SUFFIX                   "-record"
 794#define REPORT_SUFFIX                   "-report"
 795
 796struct script_desc {
 797        struct list_head        node;
 798        char                    *name;
 799        char                    *half_liner;
 800        char                    *args;
 801};
 802
 803static LIST_HEAD(script_descs);
 804
 805static struct script_desc *script_desc__new(const char *name)
 806{
 807        struct script_desc *s = zalloc(sizeof(*s));
 808
 809        if (s != NULL && name)
 810                s->name = strdup(name);
 811
 812        return s;
 813}
 814
 815static void script_desc__delete(struct script_desc *s)
 816{
 817        free(s->name);
 818        free(s->half_liner);
 819        free(s->args);
 820        free(s);
 821}
 822
 823static void script_desc__add(struct script_desc *s)
 824{
 825        list_add_tail(&s->node, &script_descs);
 826}
 827
 828static struct script_desc *script_desc__find(const char *name)
 829{
 830        struct script_desc *s;
 831
 832        list_for_each_entry(s, &script_descs, node)
 833                if (strcasecmp(s->name, name) == 0)
 834                        return s;
 835        return NULL;
 836}
 837
 838static struct script_desc *script_desc__findnew(const char *name)
 839{
 840        struct script_desc *s = script_desc__find(name);
 841
 842        if (s)
 843                return s;
 844
 845        s = script_desc__new(name);
 846        if (!s)
 847                goto out_delete_desc;
 848
 849        script_desc__add(s);
 850
 851        return s;
 852
 853out_delete_desc:
 854        script_desc__delete(s);
 855
 856        return NULL;
 857}
 858
 859static const char *ends_with(const char *str, const char *suffix)
 860{
 861        size_t suffix_len = strlen(suffix);
 862        const char *p = str;
 863
 864        if (strlen(str) > suffix_len) {
 865                p = str + strlen(str) - suffix_len;
 866                if (!strncmp(p, suffix, suffix_len))
 867                        return p;
 868        }
 869
 870        return NULL;
 871}
 872
 873static char *ltrim(char *str)
 874{
 875        int len = strlen(str);
 876
 877        while (len && isspace(*str)) {
 878                len--;
 879                str++;
 880        }
 881
 882        return str;
 883}
 884
 885static int read_script_info(struct script_desc *desc, const char *filename)
 886{
 887        char line[BUFSIZ], *p;
 888        FILE *fp;
 889
 890        fp = fopen(filename, "r");
 891        if (!fp)
 892                return -1;
 893
 894        while (fgets(line, sizeof(line), fp)) {
 895                p = ltrim(line);
 896                if (strlen(p) == 0)
 897                        continue;
 898                if (*p != '#')
 899                        continue;
 900                p++;
 901                if (strlen(p) && *p == '!')
 902                        continue;
 903
 904                p = ltrim(p);
 905                if (strlen(p) && p[strlen(p) - 1] == '\n')
 906                        p[strlen(p) - 1] = '\0';
 907
 908                if (!strncmp(p, "description:", strlen("description:"))) {
 909                        p += strlen("description:");
 910                        desc->half_liner = strdup(ltrim(p));
 911                        continue;
 912                }
 913
 914                if (!strncmp(p, "args:", strlen("args:"))) {
 915                        p += strlen("args:");
 916                        desc->args = strdup(ltrim(p));
 917                        continue;
 918                }
 919        }
 920
 921        fclose(fp);
 922
 923        return 0;
 924}
 925
 926static int list_available_scripts(const struct option *opt __used,
 927                                  const char *s __used, int unset __used)
 928{
 929        struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
 930        char scripts_path[MAXPATHLEN];
 931        DIR *scripts_dir, *lang_dir;
 932        char script_path[MAXPATHLEN];
 933        char lang_path[MAXPATHLEN];
 934        struct script_desc *desc;
 935        char first_half[BUFSIZ];
 936        char *script_root;
 937        char *str;
 938
 939        snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
 940
 941        scripts_dir = opendir(scripts_path);
 942        if (!scripts_dir)
 943                return -1;
 944
 945        for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
 946                snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
 947                         lang_dirent.d_name);
 948                lang_dir = opendir(lang_path);
 949                if (!lang_dir)
 950                        continue;
 951
 952                for_each_script(lang_path, lang_dir, script_dirent, script_next) {
 953                        script_root = strdup(script_dirent.d_name);
 954                        str = (char *)ends_with(script_root, REPORT_SUFFIX);
 955                        if (str) {
 956                                *str = '\0';
 957                                desc = script_desc__findnew(script_root);
 958                                snprintf(script_path, MAXPATHLEN, "%s/%s",
 959                                         lang_path, script_dirent.d_name);
 960                                read_script_info(desc, script_path);
 961                        }
 962                        free(script_root);
 963                }
 964        }
 965
 966        fprintf(stdout, "List of available trace scripts:\n");
 967        list_for_each_entry(desc, &script_descs, node) {
 968                sprintf(first_half, "%s %s", desc->name,
 969                        desc->args ? desc->args : "");
 970                fprintf(stdout, "  %-36s %s\n", first_half,
 971                        desc->half_liner ? desc->half_liner : "");
 972        }
 973
 974        exit(0);
 975}
 976
 977static char *get_script_path(const char *script_root, const char *suffix)
 978{
 979        struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
 980        char scripts_path[MAXPATHLEN];
 981        char script_path[MAXPATHLEN];
 982        DIR *scripts_dir, *lang_dir;
 983        char lang_path[MAXPATHLEN];
 984        char *str, *__script_root;
 985        char *path = NULL;
 986
 987        snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
 988
 989        scripts_dir = opendir(scripts_path);
 990        if (!scripts_dir)
 991                return NULL;
 992
 993        for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
 994                snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
 995                         lang_dirent.d_name);
 996                lang_dir = opendir(lang_path);
 997                if (!lang_dir)
 998                        continue;
 999
1000                for_each_script(lang_path, lang_dir, script_dirent, script_next) {
1001                        __script_root = strdup(script_dirent.d_name);
1002                        str = (char *)ends_with(__script_root, suffix);
1003                        if (str) {
1004                                *str = '\0';
1005                                if (strcmp(__script_root, script_root))
1006                                        continue;
1007                                snprintf(script_path, MAXPATHLEN, "%s/%s",
1008                                         lang_path, script_dirent.d_name);
1009                                path = strdup(script_path);
1010                                free(__script_root);
1011                                break;
1012                        }
1013                        free(__script_root);
1014                }
1015        }
1016
1017        return path;
1018}
1019
1020static bool is_top_script(const char *script_path)
1021{
1022        return ends_with(script_path, "top") == NULL ? false : true;
1023}
1024
1025static int has_required_arg(char *script_path)
1026{
1027        struct script_desc *desc;
1028        int n_args = 0;
1029        char *p;
1030
1031        desc = script_desc__new(NULL);
1032
1033        if (read_script_info(desc, script_path))
1034                goto out;
1035
1036        if (!desc->args)
1037                goto out;
1038
1039        for (p = desc->args; *p; p++)
1040                if (*p == '<')
1041                        n_args++;
1042out:
1043        script_desc__delete(desc);
1044
1045        return n_args;
1046}
1047
1048static const char * const script_usage[] = {
1049        "perf script [<options>]",
1050        "perf script [<options>] record <script> [<record-options>] <command>",
1051        "perf script [<options>] report <script> [script-args]",
1052        "perf script [<options>] <script> [<record-options>] <command>",
1053        "perf script [<options>] <top-script> [script-args]",
1054        NULL
1055};
1056
1057static const struct option options[] = {
1058        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1059                    "dump raw trace in ASCII"),
1060        OPT_INCR('v', "verbose", &verbose,
1061                    "be more verbose (show symbol address, etc)"),
1062        OPT_BOOLEAN('L', "Latency", &latency_format,
1063                    "show latency attributes (irqs/preemption disabled, etc)"),
1064        OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
1065                           list_available_scripts),
1066        OPT_CALLBACK('s', "script", NULL, "name",
1067                     "script file name (lang:script name, script name, or *)",
1068                     parse_scriptname),
1069        OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
1070                   "generate perf-script.xx script in specified language"),
1071        OPT_STRING('i', "input", &input_name, "file",
1072                    "input file name"),
1073        OPT_BOOLEAN('d', "debug-mode", &debug_mode,
1074                   "do various checks like samples ordering and lost events"),
1075        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1076                   "file", "vmlinux pathname"),
1077        OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
1078                   "file", "kallsyms pathname"),
1079        OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
1080                    "When printing symbols do not display call chain"),
1081        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1082                    "Look for files with symbols relative to this directory"),
1083        OPT_CALLBACK('f', "fields", NULL, "str",
1084                     "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
1085                     parse_output_fields),
1086        OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
1087        OPT_BOOLEAN('I', "show-info", &show_full_info,
1088                    "display extended information from perf.data file"),
1089        OPT_END()
1090};
1091
1092static bool have_cmd(int argc, const char **argv)
1093{
1094        char **__argv = malloc(sizeof(const char *) * argc);
1095
1096        if (!__argv)
1097                die("malloc");
1098        memcpy(__argv, argv, sizeof(const char *) * argc);
1099        argc = parse_options(argc, (const char **)__argv, record_options,
1100                             NULL, PARSE_OPT_STOP_AT_NON_OPTION);
1101        free(__argv);
1102
1103        return argc != 0;
1104}
1105
1106int cmd_script(int argc, const char **argv, const char *prefix __used)
1107{
1108        char *rec_script_path = NULL;
1109        char *rep_script_path = NULL;
1110        struct perf_session *session;
1111        char *script_path = NULL;
1112        const char **__argv;
1113        bool system_wide;
1114        int i, j, err;
1115
1116        setup_scripting();
1117
1118        argc = parse_options(argc, argv, options, script_usage,
1119                             PARSE_OPT_STOP_AT_NON_OPTION);
1120
1121        if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
1122                rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
1123                if (!rec_script_path)
1124                        return cmd_record(argc, argv, NULL);
1125        }
1126
1127        if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
1128                rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
1129                if (!rep_script_path) {
1130                        fprintf(stderr,
1131                                "Please specify a valid report script"
1132                                "(see 'perf script -l' for listing)\n");
1133                        return -1;
1134                }
1135        }
1136
1137        /* make sure PERF_EXEC_PATH is set for scripts */
1138        perf_set_argv_exec_path(perf_exec_path());
1139
1140        if (argc && !script_name && !rec_script_path && !rep_script_path) {
1141                int live_pipe[2];
1142                int rep_args;
1143                pid_t pid;
1144
1145                rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
1146                rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
1147
1148                if (!rec_script_path && !rep_script_path) {
1149                        fprintf(stderr, " Couldn't find script %s\n\n See perf"
1150                                " script -l for available scripts.\n", argv[0]);
1151                        usage_with_options(script_usage, options);
1152                }
1153
1154                if (is_top_script(argv[0])) {
1155                        rep_args = argc - 1;
1156                } else {
1157                        int rec_args;
1158
1159                        rep_args = has_required_arg(rep_script_path);
1160                        rec_args = (argc - 1) - rep_args;
1161                        if (rec_args < 0) {
1162                                fprintf(stderr, " %s script requires options."
1163                                        "\n\n See perf script -l for available "
1164                                        "scripts and options.\n", argv[0]);
1165                                usage_with_options(script_usage, options);
1166                        }
1167                }
1168
1169                if (pipe(live_pipe) < 0) {
1170                        perror("failed to create pipe");
1171                        exit(-1);
1172                }
1173
1174                pid = fork();
1175                if (pid < 0) {
1176                        perror("failed to fork");
1177                        exit(-1);
1178                }
1179
1180                if (!pid) {
1181                        system_wide = true;
1182                        j = 0;
1183
1184                        dup2(live_pipe[1], 1);
1185                        close(live_pipe[0]);
1186
1187                        if (!is_top_script(argv[0]))
1188                                system_wide = !have_cmd(argc - rep_args,
1189                                                        &argv[rep_args]);
1190
1191                        __argv = malloc((argc + 6) * sizeof(const char *));
1192                        if (!__argv)
1193                                die("malloc");
1194
1195                        __argv[j++] = "/bin/sh";
1196                        __argv[j++] = rec_script_path;
1197                        if (system_wide)
1198                                __argv[j++] = "-a";
1199                        __argv[j++] = "-q";
1200                        __argv[j++] = "-o";
1201                        __argv[j++] = "-";
1202                        for (i = rep_args + 1; i < argc; i++)
1203                                __argv[j++] = argv[i];
1204                        __argv[j++] = NULL;
1205
1206                        execvp("/bin/sh", (char **)__argv);
1207                        free(__argv);
1208                        exit(-1);
1209                }
1210
1211                dup2(live_pipe[0], 0);
1212                close(live_pipe[1]);
1213
1214                __argv = malloc((argc + 4) * sizeof(const char *));
1215                if (!__argv)
1216                        die("malloc");
1217                j = 0;
1218                __argv[j++] = "/bin/sh";
1219                __argv[j++] = rep_script_path;
1220                for (i = 1; i < rep_args + 1; i++)
1221                        __argv[j++] = argv[i];
1222                __argv[j++] = "-i";
1223                __argv[j++] = "-";
1224                __argv[j++] = NULL;
1225
1226                execvp("/bin/sh", (char **)__argv);
1227                free(__argv);
1228                exit(-1);
1229        }
1230
1231        if (rec_script_path)
1232                script_path = rec_script_path;
1233        if (rep_script_path)
1234                script_path = rep_script_path;
1235
1236        if (script_path) {
1237                system_wide = false;
1238                j = 0;
1239
1240                if (rec_script_path)
1241                        system_wide = !have_cmd(argc - 1, &argv[1]);
1242
1243                __argv = malloc((argc + 2) * sizeof(const char *));
1244                if (!__argv)
1245                        die("malloc");
1246                __argv[j++] = "/bin/sh";
1247                __argv[j++] = script_path;
1248                if (system_wide)
1249                        __argv[j++] = "-a";
1250                for (i = 2; i < argc; i++)
1251                        __argv[j++] = argv[i];
1252                __argv[j++] = NULL;
1253
1254                execvp("/bin/sh", (char **)__argv);
1255                free(__argv);
1256                exit(-1);
1257        }
1258
1259        if (symbol__init() < 0)
1260                return -1;
1261        if (!script_name)
1262                setup_pager();
1263
1264        session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
1265        if (session == NULL)
1266                return -ENOMEM;
1267
1268        if (cpu_list) {
1269                if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
1270                        return -1;
1271        }
1272
1273        perf_session__fprintf_info(session, stdout, show_full_info);
1274
1275        if (!no_callchain)
1276                symbol_conf.use_callchain = true;
1277        else
1278                symbol_conf.use_callchain = false;
1279
1280        if (generate_script_lang) {
1281                struct stat perf_stat;
1282                int input;
1283
1284                if (output_set_by_user()) {
1285                        fprintf(stderr,
1286                                "custom fields not supported for generated scripts");
1287                        return -1;
1288                }
1289
1290                input = open(input_name, O_RDONLY);
1291                if (input < 0) {
1292                        perror("failed to open file");
1293                        exit(-1);
1294                }
1295
1296                err = fstat(input, &perf_stat);
1297                if (err < 0) {
1298                        perror("failed to stat file");
1299                        exit(-1);
1300                }
1301
1302                if (!perf_stat.st_size) {
1303                        fprintf(stderr, "zero-sized file, nothing to do!\n");
1304                        exit(0);
1305                }
1306
1307                scripting_ops = script_spec__lookup(generate_script_lang);
1308                if (!scripting_ops) {
1309                        fprintf(stderr, "invalid language specifier");
1310                        return -1;
1311                }
1312
1313                err = scripting_ops->generate_script("perf-script");
1314                goto out;
1315        }
1316
1317        if (script_name) {
1318                err = scripting_ops->start_script(script_name, argc, argv);
1319                if (err)
1320                        goto out;
1321                pr_debug("perf script started with script %s\n\n", script_name);
1322        }
1323
1324
1325        err = perf_session__check_output_opt(session);
1326        if (err < 0)
1327                goto out;
1328
1329        err = __cmd_script(session);
1330
1331        perf_session__delete(session);
1332        cleanup_scripting();
1333out:
1334        return err;
1335}
1336
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.