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