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 "util/sort.h" 18 #include "util/data.h" 19 #include <linux/bitmap.h> 20 21 static char const *script_name; 22 static char const *generate_script_lang; 23 static bool debug_mode; 24 static u64 last_timestamp; 25 static u64 nr_unordered; 26 extern const struct option record_options[]; 27 static bool no_callchain; 28 static bool latency_format; 29 static bool system_wide; 30 static const char *cpu_list; 31 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 32 33 enum perf_output_field { 34 PERF_OUTPUT_COMM = 1U << 0, 35 PERF_OUTPUT_TID = 1U << 1, 36 PERF_OUTPUT_PID = 1U << 2, 37 PERF_OUTPUT_TIME = 1U << 3, 38 PERF_OUTPUT_CPU = 1U << 4, 39 PERF_OUTPUT_EVNAME = 1U << 5, 40 PERF_OUTPUT_TRACE = 1U << 6, 41 PERF_OUTPUT_IP = 1U << 7, 42 PERF_OUTPUT_SYM = 1U << 8, 43 PERF_OUTPUT_DSO = 1U << 9, 44 PERF_OUTPUT_ADDR = 1U << 10, 45 PERF_OUTPUT_SYMOFFSET = 1U << 11, 46 PERF_OUTPUT_SRCLINE = 1U << 12, 47 }; 48 49 struct output_option { 50 const char *str; 51 enum perf_output_field field; 52 } all_output_options[] = { 53 {.str = "comm", .field = PERF_OUTPUT_COMM}, 54 {.str = "tid", .field = PERF_OUTPUT_TID}, 55 {.str = "pid", .field = PERF_OUTPUT_PID}, 56 {.str = "time", .field = PERF_OUTPUT_TIME}, 57 {.str = "cpu", .field = PERF_OUTPUT_CPU}, 58 {.str = "event", .field = PERF_OUTPUT_EVNAME}, 59 {.str = "trace", .field = PERF_OUTPUT_TRACE}, 60 {.str = "ip", .field = PERF_OUTPUT_IP}, 61 {.str = "sym", .field = PERF_OUTPUT_SYM}, 62 {.str = "dso", .field = PERF_OUTPUT_DSO}, 63 {.str = "addr", .field = PERF_OUTPUT_ADDR}, 64 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, 65 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 66 }; 67 68 /* default set to maintain compatibility with current format */ 69 static struct { 70 bool user_set; 71 bool wildcard_set; 72 unsigned int print_ip_opts; 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 119 static 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 129 static 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 145 static 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 174 static 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 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { 216 pr_err("Display of source line number requested but sample IP is not\n" 217 "selected. Hence, no address to lookup the source line number.\n"); 218 return -EINVAL; 219 } 220 221 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 222 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", 223 PERF_OUTPUT_TID|PERF_OUTPUT_PID)) 224 return -EINVAL; 225 226 if (PRINT_FIELD(TIME) && 227 perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME", 228 PERF_OUTPUT_TIME)) 229 return -EINVAL; 230 231 if (PRINT_FIELD(CPU) && 232 perf_evsel__check_stype(evsel, PERF_SAMPLE_CPU, "CPU", 233 PERF_OUTPUT_CPU)) 234 return -EINVAL; 235 236 return 0; 237 } 238 239 static void set_print_ip_opts(struct perf_event_attr *attr) 240 { 241 unsigned int type = attr->type; 242 243 output[type].print_ip_opts = 0; 244 if (PRINT_FIELD(IP)) 245 output[type].print_ip_opts |= PRINT_IP_OPT_IP; 246 247 if (PRINT_FIELD(SYM)) 248 output[type].print_ip_opts |= PRINT_IP_OPT_SYM; 249 250 if (PRINT_FIELD(DSO)) 251 output[type].print_ip_opts |= PRINT_IP_OPT_DSO; 252 253 if (PRINT_FIELD(SYMOFFSET)) 254 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; 255 256 if (PRINT_FIELD(SRCLINE)) 257 output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE; 258 } 259 260 /* 261 * verify all user requested events exist and the samples 262 * have the expected data 263 */ 264 static int perf_session__check_output_opt(struct perf_session *session) 265 { 266 int j; 267 struct perf_evsel *evsel; 268 269 for (j = 0; j < PERF_TYPE_MAX; ++j) { 270 evsel = perf_session__find_first_evtype(session, j); 271 272 /* 273 * even if fields is set to 0 (ie., show nothing) event must 274 * exist if user explicitly includes it on the command line 275 */ 276 if (!evsel && output[j].user_set && !output[j].wildcard_set) { 277 pr_err("%s events do not exist. " 278 "Remove corresponding -f option to proceed.\n", 279 event_type(j)); 280 return -1; 281 } 282 283 if (evsel && output[j].fields && 284 perf_evsel__check_attr(evsel, session)) 285 return -1; 286 287 if (evsel == NULL) 288 continue; 289 290 set_print_ip_opts(&evsel->attr); 291 } 292 293 /* 294 * set default for tracepoints to print symbols only 295 * if callchains are present 296 */ 297 if (symbol_conf.use_callchain && 298 !output[PERF_TYPE_TRACEPOINT].user_set) { 299 struct perf_event_attr *attr; 300 301 j = PERF_TYPE_TRACEPOINT; 302 evsel = perf_session__find_first_evtype(session, j); 303 if (evsel == NULL) 304 goto out; 305 306 attr = &evsel->attr; 307 308 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { 309 output[j].fields |= PERF_OUTPUT_IP; 310 output[j].fields |= PERF_OUTPUT_SYM; 311 output[j].fields |= PERF_OUTPUT_DSO; 312 set_print_ip_opts(attr); 313 } 314 } 315 316 out: 317 return 0; 318 } 319 320 static void print_sample_start(struct perf_sample *sample, 321 struct thread *thread, 322 struct perf_evsel *evsel) 323 { 324 struct perf_event_attr *attr = &evsel->attr; 325 unsigned long secs; 326 unsigned long usecs; 327 unsigned long long nsecs; 328 329 if (PRINT_FIELD(COMM)) { 330 if (latency_format) 331 printf("%8.8s ", thread__comm_str(thread)); 332 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) 333 printf("%s ", thread__comm_str(thread)); 334 else 335 printf("%16s ", thread__comm_str(thread)); 336 } 337 338 if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) 339 printf("%5d/%-5d ", sample->pid, sample->tid); 340 else if (PRINT_FIELD(PID)) 341 printf("%5d ", sample->pid); 342 else if (PRINT_FIELD(TID)) 343 printf("%5d ", sample->tid); 344 345 if (PRINT_FIELD(CPU)) { 346 if (latency_format) 347 printf("%3d ", sample->cpu); 348 else 349 printf("[%03d] ", sample->cpu); 350 } 351 352 if (PRINT_FIELD(TIME)) { 353 nsecs = sample->time; 354 secs = nsecs / NSECS_PER_SEC; 355 nsecs -= secs * NSECS_PER_SEC; 356 usecs = nsecs / NSECS_PER_USEC; 357 printf("%5lu.%06lu: ", secs, usecs); 358 } 359 } 360 361 static void print_sample_addr(union perf_event *event, 362 struct perf_sample *sample, 363 struct machine *machine, 364 struct thread *thread, 365 struct perf_event_attr *attr) 366 { 367 struct addr_location al; 368 369 printf("%16" PRIx64, sample->addr); 370 371 if (!sample_addr_correlates_sym(attr)) 372 return; 373 374 perf_event__preprocess_sample_addr(event, sample, machine, thread, &al); 375 376 if (PRINT_FIELD(SYM)) { 377 printf(" "); 378 if (PRINT_FIELD(SYMOFFSET)) 379 symbol__fprintf_symname_offs(al.sym, &al, stdout); 380 else 381 symbol__fprintf_symname(al.sym, stdout); 382 } 383 384 if (PRINT_FIELD(DSO)) { 385 printf(" ("); 386 map__fprintf_dsoname(al.map, stdout); 387 printf(")"); 388 } 389 } 390 391 static void print_sample_bts(union perf_event *event, 392 struct perf_sample *sample, 393 struct perf_evsel *evsel, 394 struct thread *thread, 395 struct addr_location *al) 396 { 397 struct perf_event_attr *attr = &evsel->attr; 398 bool print_srcline_last = false; 399 400 /* print branch_from information */ 401 if (PRINT_FIELD(IP)) { 402 unsigned int print_opts = output[attr->type].print_ip_opts; 403 404 if (symbol_conf.use_callchain && sample->callchain) { 405 printf("\n"); 406 } else { 407 printf(" "); 408 if (print_opts & PRINT_IP_OPT_SRCLINE) { 409 print_srcline_last = true; 410 print_opts &= ~PRINT_IP_OPT_SRCLINE; 411 } 412 } 413 perf_evsel__print_ip(evsel, sample, al, print_opts, 414 PERF_MAX_STACK_DEPTH); 415 } 416 417 /* print branch_to information */ 418 if (PRINT_FIELD(ADDR) || 419 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 420 !output[attr->type].user_set)) { 421 printf(" => "); 422 print_sample_addr(event, sample, al->machine, thread, attr); 423 } 424 425 if (print_srcline_last) 426 map__fprintf_srcline(al->map, al->addr, "\n ", stdout); 427 428 printf("\n"); 429 } 430 431 static void process_event(union perf_event *event, struct perf_sample *sample, 432 struct perf_evsel *evsel, struct thread *thread, 433 struct addr_location *al) 434 { 435 struct perf_event_attr *attr = &evsel->attr; 436 437 if (output[attr->type].fields == 0) 438 return; 439 440 print_sample_start(sample, thread, evsel); 441 442 if (PRINT_FIELD(EVNAME)) { 443 const char *evname = perf_evsel__name(evsel); 444 printf("%s: ", evname ? evname : "[unknown]"); 445 } 446 447 if (is_bts_event(attr)) { 448 print_sample_bts(event, sample, evsel, thread, al); 449 return; 450 } 451 452 if (PRINT_FIELD(TRACE)) 453 event_format__print(evsel->tp_format, sample->cpu, 454 sample->raw_data, sample->raw_size); 455 if (PRINT_FIELD(ADDR)) 456 print_sample_addr(event, sample, al->machine, thread, attr); 457 458 if (PRINT_FIELD(IP)) { 459 if (!symbol_conf.use_callchain) 460 printf(" "); 461 else 462 printf("\n"); 463 464 perf_evsel__print_ip(evsel, sample, al, 465 output[attr->type].print_ip_opts, 466 PERF_MAX_STACK_DEPTH); 467 } 468 469 printf("\n"); 470 } 471 472 static int default_start_script(const char *script __maybe_unused, 473 int argc __maybe_unused, 474 const char **argv __maybe_unused) 475 { 476 return 0; 477 } 478 479 static int default_stop_script(void) 480 { 481 return 0; 482 } 483 484 static int default_generate_script(struct pevent *pevent __maybe_unused, 485 const char *outfile __maybe_unused) 486 { 487 return 0; 488 } 489 490 static struct scripting_ops default_scripting_ops = { 491 .start_script = default_start_script, 492 .stop_script = default_stop_script, 493 .process_event = process_event, 494 .generate_script = default_generate_script, 495 }; 496 497 static struct scripting_ops *scripting_ops; 498 499 static void setup_scripting(void) 500 { 501 setup_perl_scripting(); 502 setup_python_scripting(); 503 504 scripting_ops = &default_scripting_ops; 505 } 506 507 static int cleanup_scripting(void) 508 { 509 pr_debug("\nperf script stopped\n"); 510 511 return scripting_ops->stop_script(); 512 } 513 514 static int process_sample_event(struct perf_tool *tool __maybe_unused, 515 union perf_event *event, 516 struct perf_sample *sample, 517 struct perf_evsel *evsel, 518 struct machine *machine) 519 { 520 struct addr_location al; 521 struct thread *thread = machine__findnew_thread(machine, sample->pid, 522 sample->tid); 523 524 if (thread == NULL) { 525 pr_debug("problem processing %d event, skipping it.\n", 526 event->header.type); 527 return -1; 528 } 529 530 if (debug_mode) { 531 if (sample->time < last_timestamp) { 532 pr_err("Samples misordered, previous: %" PRIu64 533 " this: %" PRIu64 "\n", last_timestamp, 534 sample->time); 535 nr_unordered++; 536 } 537 last_timestamp = sample->time; 538 return 0; 539 } 540 541 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 542 pr_err("problem processing %d event, skipping it.\n", 543 event->header.type); 544 return -1; 545 } 546 547 if (al.filtered) 548 return 0; 549 550 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 551 return 0; 552 553 scripting_ops->process_event(event, sample, evsel, thread, &al); 554 555 evsel->hists.stats.total_period += sample->period; 556 return 0; 557 } 558 559 struct perf_script { 560 struct perf_tool tool; 561 struct perf_session *session; 562 bool show_task_events; 563 bool show_mmap_events; 564 }; 565 566 static int process_attr(struct perf_tool *tool, union perf_event *event, 567 struct perf_evlist **pevlist) 568 { 569 struct perf_script *scr = container_of(tool, struct perf_script, tool); 570 struct perf_evlist *evlist; 571 struct perf_evsel *evsel, *pos; 572 int err; 573 574 err = perf_event__process_attr(tool, event, pevlist); 575 if (err) 576 return err; 577 578 evlist = *pevlist; 579 evsel = perf_evlist__last(*pevlist); 580 581 if (evsel->attr.type >= PERF_TYPE_MAX) 582 return 0; 583 584 evlist__for_each(evlist, pos) { 585 if (pos->attr.type == evsel->attr.type && pos != evsel) 586 return 0; 587 } 588 589 set_print_ip_opts(&evsel->attr); 590 591 return perf_evsel__check_attr(evsel, scr->session); 592 } 593 594 static int process_comm_event(struct perf_tool *tool, 595 union perf_event *event, 596 struct perf_sample *sample, 597 struct machine *machine) 598 { 599 struct thread *thread; 600 struct perf_script *script = container_of(tool, struct perf_script, tool); 601 struct perf_session *session = script->session; 602 struct perf_evsel *evsel = perf_evlist__first(session->evlist); 603 int ret = -1; 604 605 thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid); 606 if (thread == NULL) { 607 pr_debug("problem processing COMM event, skipping it.\n"); 608 return -1; 609 } 610 611 if (perf_event__process_comm(tool, event, sample, machine) < 0) 612 goto out; 613 614 if (!evsel->attr.sample_id_all) { 615 sample->cpu = 0; 616 sample->time = 0; 617 sample->tid = event->comm.tid; 618 sample->pid = event->comm.pid; 619 } 620 print_sample_start(sample, thread, evsel); 621 perf_event__fprintf(event, stdout); 622 ret = 0; 623 624 out: 625 return ret; 626 } 627 628 static int process_fork_event(struct perf_tool *tool, 629 union perf_event *event, 630 struct perf_sample *sample, 631 struct machine *machine) 632 { 633 struct thread *thread; 634 struct perf_script *script = container_of(tool, struct perf_script, tool); 635 struct perf_session *session = script->session; 636 struct perf_evsel *evsel = perf_evlist__first(session->evlist); 637 638 if (perf_event__process_fork(tool, event, sample, machine) < 0) 639 return -1; 640 641 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); 642 if (thread == NULL) { 643 pr_debug("problem processing FORK event, skipping it.\n"); 644 return -1; 645 } 646 647 if (!evsel->attr.sample_id_all) { 648 sample->cpu = 0; 649 sample->time = event->fork.time; 650 sample->tid = event->fork.tid; 651 sample->pid = event->fork.pid; 652 } 653 print_sample_start(sample, thread, evsel); 654 perf_event__fprintf(event, stdout); 655 656 return 0; 657 } 658 static int process_exit_event(struct perf_tool *tool, 659 union perf_event *event, 660 struct perf_sample *sample, 661 struct machine *machine) 662 { 663 struct thread *thread; 664 struct perf_script *script = container_of(tool, struct perf_script, tool); 665 struct perf_session *session = script->session; 666 struct perf_evsel *evsel = perf_evlist__first(session->evlist); 667 668 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); 669 if (thread == NULL) { 670 pr_debug("problem processing EXIT event, skipping it.\n"); 671 return -1; 672 } 673 674 if (!evsel->attr.sample_id_all) { 675 sample->cpu = 0; 676 sample->time = 0; 677 sample->tid = event->comm.tid; 678 sample->pid = event->comm.pid; 679 } 680 print_sample_start(sample, thread, evsel); 681 perf_event__fprintf(event, stdout); 682 683 if (perf_event__process_exit(tool, event, sample, machine) < 0) 684 return -1; 685 686 return 0; 687 } 688 689 static int process_mmap_event(struct perf_tool *tool, 690 union perf_event *event, 691 struct perf_sample *sample, 692 struct machine *machine) 693 { 694 struct thread *thread; 695 struct perf_script *script = container_of(tool, struct perf_script, tool); 696 struct perf_session *session = script->session; 697 struct perf_evsel *evsel = perf_evlist__first(session->evlist); 698 699 if (perf_event__process_mmap(tool, event, sample, machine) < 0) 700 return -1; 701 702 thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid); 703 if (thread == NULL) { 704 pr_debug("problem processing MMAP event, skipping it.\n"); 705 return -1; 706 } 707 708 if (!evsel->attr.sample_id_all) { 709 sample->cpu = 0; 710 sample->time = 0; 711 sample->tid = event->mmap.tid; 712 sample->pid = event->mmap.pid; 713 } 714 print_sample_start(sample, thread, evsel); 715 perf_event__fprintf(event, stdout); 716 717 return 0; 718 } 719 720 static int process_mmap2_event(struct perf_tool *tool, 721 union perf_event *event, 722 struct perf_sample *sample, 723 struct machine *machine) 724 { 725 struct thread *thread; 726 struct perf_script *script = container_of(tool, struct perf_script, tool); 727 struct perf_session *session = script->session; 728 struct perf_evsel *evsel = perf_evlist__first(session->evlist); 729 730 if (perf_event__process_mmap2(tool, event, sample, machine) < 0) 731 return -1; 732 733 thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid); 734 if (thread == NULL) { 735 pr_debug("problem processing MMAP2 event, skipping it.\n"); 736 return -1; 737 } 738 739 if (!evsel->attr.sample_id_all) { 740 sample->cpu = 0; 741 sample->time = 0; 742 sample->tid = event->mmap2.tid; 743 sample->pid = event->mmap2.pid; 744 } 745 print_sample_start(sample, thread, evsel); 746 perf_event__fprintf(event, stdout); 747 748 return 0; 749 } 750 751 static void sig_handler(int sig __maybe_unused) 752 { 753 session_done = 1; 754 } 755 756 static int __cmd_script(struct perf_script *script) 757 { 758 int ret; 759 760 signal(SIGINT, sig_handler); 761 762 /* override event processing functions */ 763 if (script->show_task_events) { 764 script->tool.comm = process_comm_event; 765 script->tool.fork = process_fork_event; 766 script->tool.exit = process_exit_event; 767 } 768 if (script->show_mmap_events) { 769 script->tool.mmap = process_mmap_event; 770 script->tool.mmap2 = process_mmap2_event; 771 } 772 773 ret = perf_session__process_events(script->session, &script->tool); 774 775 if (debug_mode) 776 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 777 778 return ret; 779 } 780 781 struct script_spec { 782 struct list_head node; 783 struct scripting_ops *ops; 784 char spec[0]; 785 }; 786 787 static LIST_HEAD(script_specs); 788 789 static struct script_spec *script_spec__new(const char *spec, 790 struct scripting_ops *ops) 791 { 792 struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1); 793 794 if (s != NULL) { 795 strcpy(s->spec, spec); 796 s->ops = ops; 797 } 798 799 return s; 800 } 801 802 static void script_spec__add(struct script_spec *s) 803 { 804 list_add_tail(&s->node, &script_specs); 805 } 806 807 static struct script_spec *script_spec__find(const char *spec) 808 { 809 struct script_spec *s; 810 811 list_for_each_entry(s, &script_specs, node) 812 if (strcasecmp(s->spec, spec) == 0) 813 return s; 814 return NULL; 815 } 816 817 static struct script_spec *script_spec__findnew(const char *spec, 818 struct scripting_ops *ops) 819 { 820 struct script_spec *s = script_spec__find(spec); 821 822 if (s) 823 return s; 824 825 s = script_spec__new(spec, ops); 826 if (!s) 827 return NULL; 828 829 script_spec__add(s); 830 831 return s; 832 } 833 834 int script_spec_register(const char *spec, struct scripting_ops *ops) 835 { 836 struct script_spec *s; 837 838 s = script_spec__find(spec); 839 if (s) 840 return -1; 841 842 s = script_spec__findnew(spec, ops); 843 if (!s) 844 return -1; 845 846 return 0; 847 } 848 849 static struct scripting_ops *script_spec__lookup(const char *spec) 850 { 851 struct script_spec *s = script_spec__find(spec); 852 if (!s) 853 return NULL; 854 855 return s->ops; 856 } 857 858 static void list_available_languages(void) 859 { 860 struct script_spec *s; 861 862 fprintf(stderr, "\n"); 863 fprintf(stderr, "Scripting language extensions (used in " 864 "perf script -s [spec:]script.[spec]):\n\n"); 865 866 list_for_each_entry(s, &script_specs, node) 867 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name); 868 869 fprintf(stderr, "\n"); 870 } 871 872 static int parse_scriptname(const struct option *opt __maybe_unused, 873 const char *str, int unset __maybe_unused) 874 { 875 char spec[PATH_MAX]; 876 const char *script, *ext; 877 int len; 878 879 if (strcmp(str, "lang") == 0) { 880 list_available_languages(); 881 exit(0); 882 } 883 884 script = strchr(str, ':'); 885 if (script) { 886 len = script - str; 887 if (len >= PATH_MAX) { 888 fprintf(stderr, "invalid language specifier"); 889 return -1; 890 } 891 strncpy(spec, str, len); 892 spec[len] = '\0'; 893 scripting_ops = script_spec__lookup(spec); 894 if (!scripting_ops) { 895 fprintf(stderr, "invalid language specifier"); 896 return -1; 897 } 898 script++; 899 } else { 900 script = str; 901 ext = strrchr(script, '.'); 902 if (!ext) { 903 fprintf(stderr, "invalid script extension"); 904 return -1; 905 } 906 scripting_ops = script_spec__lookup(++ext); 907 if (!scripting_ops) { 908 fprintf(stderr, "invalid script extension"); 909 return -1; 910 } 911 } 912 913 script_name = strdup(script); 914 915 return 0; 916 } 917 918 static int parse_output_fields(const struct option *opt __maybe_unused, 919 const char *arg, int unset __maybe_unused) 920 { 921 char *tok; 922 int i, imax = ARRAY_SIZE(all_output_options); 923 int j; 924 int rc = 0; 925 char *str = strdup(arg); 926 int type = -1; 927 928 if (!str) 929 return -ENOMEM; 930 931 /* first word can state for which event type the user is specifying 932 * the fields. If no type exists, the specified fields apply to all 933 * event types found in the file minus the invalid fields for a type. 934 */ 935 tok = strchr(str, ':'); 936 if (tok) { 937 *tok = '\0'; 938 tok++; 939 if (!strcmp(str, "hw")) 940 type = PERF_TYPE_HARDWARE; 941 else if (!strcmp(str, "sw")) 942 type = PERF_TYPE_SOFTWARE; 943 else if (!strcmp(str, "trace")) 944 type = PERF_TYPE_TRACEPOINT; 945 else if (!strcmp(str, "raw")) 946 type = PERF_TYPE_RAW; 947 else { 948 fprintf(stderr, "Invalid event type in field string.\n"); 949 rc = -EINVAL; 950 goto out; 951 } 952 953 if (output[type].user_set) 954 pr_warning("Overriding previous field request for %s events.\n", 955 event_type(type)); 956 957 output[type].fields = 0; 958 output[type].user_set = true; 959 output[type].wildcard_set = false; 960 961 } else { 962 tok = str; 963 if (strlen(str) == 0) { 964 fprintf(stderr, 965 "Cannot set fields to 'none' for all event types.\n"); 966 rc = -EINVAL; 967 goto out; 968 } 969 970 if (output_set_by_user()) 971 pr_warning("Overriding previous field request for all events.\n"); 972 973 for (j = 0; j < PERF_TYPE_MAX; ++j) { 974 output[j].fields = 0; 975 output[j].user_set = true; 976 output[j].wildcard_set = true; 977 } 978 } 979 980 tok = strtok(tok, ","); 981 while (tok) { 982 for (i = 0; i < imax; ++i) { 983 if (strcmp(tok, all_output_options[i].str) == 0) 984 break; 985 } 986 if (i == imax) { 987 fprintf(stderr, "Invalid field requested.\n"); 988 rc = -EINVAL; 989 goto out; 990 } 991 992 if (type == -1) { 993 /* add user option to all events types for 994 * which it is valid 995 */ 996 for (j = 0; j < PERF_TYPE_MAX; ++j) { 997 if (output[j].invalid_fields & all_output_options[i].field) { 998 pr_warning("\'%s\' not valid for %s events. Ignoring.\n", 999 all_output_options[i].str, event_type(j)); 1000 } else 1001 output[j].fields |= all_output_options[i].field; 1002 } 1003 } else { 1004 if (output[type].invalid_fields & all_output_options[i].field) { 1005 fprintf(stderr, "\'%s\' not valid for %s events.\n", 1006 all_output_options[i].str, event_type(type)); 1007 1008 rc = -EINVAL; 1009 goto out; 1010 } 1011 output[type].fields |= all_output_options[i].field; 1012 } 1013 1014 tok = strtok(NULL, ","); 1015 } 1016 1017 if (type >= 0) { 1018 if (output[type].fields == 0) { 1019 pr_debug("No fields requested for %s type. " 1020 "Events will not be displayed.\n", event_type(type)); 1021 } 1022 } 1023 1024 out: 1025 free(str); 1026 return rc; 1027 } 1028 1029 /* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */ 1030 static int is_directory(const char *base_path, const struct dirent *dent) 1031 { 1032 char path[PATH_MAX]; 1033 struct stat st; 1034 1035 sprintf(path, "%s/%s", base_path, dent->d_name); 1036 if (stat(path, &st)) 1037 return 0; 1038 1039 return S_ISDIR(st.st_mode); 1040 } 1041 1042 #define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\ 1043 while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \ 1044 lang_next) \ 1045 if ((lang_dirent.d_type == DT_DIR || \ 1046 (lang_dirent.d_type == DT_UNKNOWN && \ 1047 is_directory(scripts_path, &lang_dirent))) && \ 1048 (strcmp(lang_dirent.d_name, ".")) && \ 1049 (strcmp(lang_dirent.d_name, ".."))) 1050 1051 #define for_each_script(lang_path, lang_dir, script_dirent, script_next)\ 1052 while (!readdir_r(lang_dir, &script_dirent, &script_next) && \ 1053 script_next) \ 1054 if (script_dirent.d_type != DT_DIR && \ 1055 (script_dirent.d_type != DT_UNKNOWN || \ 1056 !is_directory(lang_path, &script_dirent))) 1057 1058 1059 #define RECORD_SUFFIX "-record" 1060 #define REPORT_SUFFIX "-report" 1061 1062 struct script_desc { 1063 struct list_head node; 1064 char *name; 1065 char *half_liner; 1066 char *args; 1067 }; 1068 1069 static LIST_HEAD(script_descs); 1070 1071 static struct script_desc *script_desc__new(const char *name) 1072 { 1073 struct script_desc *s = zalloc(sizeof(*s)); 1074 1075 if (s != NULL && name) 1076 s->name = strdup(name); 1077 1078 return s; 1079 } 1080 1081 static void script_desc__delete(struct script_desc *s) 1082 { 1083 zfree(&s->name); 1084 zfree(&s->half_liner); 1085 zfree(&s->args); 1086 free(s); 1087 } 1088 1089 static void script_desc__add(struct script_desc *s) 1090 { 1091 list_add_tail(&s->node, &script_descs); 1092 } 1093 1094 static struct script_desc *script_desc__find(const char *name) 1095 { 1096 struct script_desc *s; 1097 1098 list_for_each_entry(s, &script_descs, node) 1099 if (strcasecmp(s->name, name) == 0) 1100 return s; 1101 return NULL; 1102 } 1103 1104 static struct script_desc *script_desc__findnew(const char *name) 1105 { 1106 struct script_desc *s = script_desc__find(name); 1107 1108 if (s) 1109 return s; 1110 1111 s = script_desc__new(name); 1112 if (!s) 1113 goto out_delete_desc; 1114 1115 script_desc__add(s); 1116 1117 return s; 1118 1119 out_delete_desc: 1120 script_desc__delete(s); 1121 1122 return NULL; 1123 } 1124 1125 static const char *ends_with(const char *str, const char *suffix) 1126 { 1127 size_t suffix_len = strlen(suffix); 1128 const char *p = str; 1129 1130 if (strlen(str) > suffix_len) { 1131 p = str + strlen(str) - suffix_len; 1132 if (!strncmp(p, suffix, suffix_len)) 1133 return p; 1134 } 1135 1136 return NULL; 1137 } 1138 1139 static int read_script_info(struct script_desc *desc, const char *filename) 1140 { 1141 char line[BUFSIZ], *p; 1142 FILE *fp; 1143 1144 fp = fopen(filename, "r"); 1145 if (!fp) 1146 return -1; 1147 1148 while (fgets(line, sizeof(line), fp)) { 1149 p = ltrim(line); 1150 if (strlen(p) == 0) 1151 continue; 1152 if (*p != '#') 1153 continue; 1154 p++; 1155 if (strlen(p) && *p == '!') 1156 continue; 1157 1158 p = ltrim(p); 1159 if (strlen(p) && p[strlen(p) - 1] == '\n') 1160 p[strlen(p) - 1] = '\0'; 1161 1162 if (!strncmp(p, "description:", strlen("description:"))) { 1163 p += strlen("description:"); 1164 desc->half_liner = strdup(ltrim(p)); 1165 continue; 1166 } 1167 1168 if (!strncmp(p, "args:", strlen("args:"))) { 1169 p += strlen("args:"); 1170 desc->args = strdup(ltrim(p)); 1171 continue; 1172 } 1173 } 1174 1175 fclose(fp); 1176 1177 return 0; 1178 } 1179 1180 static char *get_script_root(struct dirent *script_dirent, const char *suffix) 1181 { 1182 char *script_root, *str; 1183 1184 script_root = strdup(script_dirent->d_name); 1185 if (!script_root) 1186 return NULL; 1187 1188 str = (char *)ends_with(script_root, suffix); 1189 if (!str) { 1190 free(script_root); 1191 return NULL; 1192 } 1193 1194 *str = '\0'; 1195 return script_root; 1196 } 1197 1198 static int list_available_scripts(const struct option *opt __maybe_unused, 1199 const char *s __maybe_unused, 1200 int unset __maybe_unused) 1201 { 1202 struct dirent *script_next, *lang_next, script_dirent, lang_dirent; 1203 char scripts_path[MAXPATHLEN]; 1204 DIR *scripts_dir, *lang_dir; 1205 char script_path[MAXPATHLEN]; 1206 char lang_path[MAXPATHLEN]; 1207 struct script_desc *desc; 1208 char first_half[BUFSIZ]; 1209 char *script_root; 1210 1211 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1212 1213 scripts_dir = opendir(scripts_path); 1214 if (!scripts_dir) 1215 return -1; 1216 1217 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { 1218 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 1219 lang_dirent.d_name); 1220 lang_dir = opendir(lang_path); 1221 if (!lang_dir) 1222 continue; 1223 1224 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 1225 script_root = get_script_root(&script_dirent, REPORT_SUFFIX); 1226 if (script_root) { 1227 desc = script_desc__findnew(script_root); 1228 snprintf(script_path, MAXPATHLEN, "%s/%s", 1229 lang_path, script_dirent.d_name); 1230 read_script_info(desc, script_path); 1231 free(script_root); 1232 } 1233 } 1234 } 1235 1236 fprintf(stdout, "List of available trace scripts:\n"); 1237 list_for_each_entry(desc, &script_descs, node) { 1238 sprintf(first_half, "%s %s", desc->name, 1239 desc->args ? desc->args : ""); 1240 fprintf(stdout, " %-36s %s\n", first_half, 1241 desc->half_liner ? desc->half_liner : ""); 1242 } 1243 1244 exit(0); 1245 } 1246 1247 /* 1248 * Some scripts specify the required events in their "xxx-record" file, 1249 * this function will check if the events in perf.data match those 1250 * mentioned in the "xxx-record". 1251 * 1252 * Fixme: All existing "xxx-record" are all in good formats "-e event ", 1253 * which is covered well now. And new parsing code should be added to 1254 * cover the future complexing formats like event groups etc. 1255 */ 1256 static int check_ev_match(char *dir_name, char *scriptname, 1257 struct perf_session *session) 1258 { 1259 char filename[MAXPATHLEN], evname[128]; 1260 char line[BUFSIZ], *p; 1261 struct perf_evsel *pos; 1262 int match, len; 1263 FILE *fp; 1264 1265 sprintf(filename, "%s/bin/%s-record", dir_name, scriptname); 1266 1267 fp = fopen(filename, "r"); 1268 if (!fp) 1269 return -1; 1270 1271 while (fgets(line, sizeof(line), fp)) { 1272 p = ltrim(line); 1273 if (*p == '#') 1274 continue; 1275 1276 while (strlen(p)) { 1277 p = strstr(p, "-e"); 1278 if (!p) 1279 break; 1280 1281 p += 2; 1282 p = ltrim(p); 1283 len = strcspn(p, " \t"); 1284 if (!len) 1285 break; 1286 1287 snprintf(evname, len + 1, "%s", p); 1288 1289 match = 0; 1290 evlist__for_each(session->evlist, pos) { 1291 if (!strcmp(perf_evsel__name(pos), evname)) { 1292 match = 1; 1293 break; 1294 } 1295 } 1296 1297 if (!match) { 1298 fclose(fp); 1299 return -1; 1300 } 1301 } 1302 } 1303 1304 fclose(fp); 1305 return 0; 1306 } 1307 1308 /* 1309 * Return -1 if none is found, otherwise the actual scripts number. 1310 * 1311 * Currently the only user of this function is the script browser, which 1312 * will list all statically runnable scripts, select one, execute it and 1313 * show the output in a perf browser. 1314 */ 1315 int find_scripts(char **scripts_array, char **scripts_path_array) 1316 { 1317 struct dirent *script_next, *lang_next, script_dirent, lang_dirent; 1318 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; 1319 DIR *scripts_dir, *lang_dir; 1320 struct perf_session *session; 1321 struct perf_data_file file = { 1322 .path = input_name, 1323 .mode = PERF_DATA_MODE_READ, 1324 }; 1325 char *temp; 1326 int i = 0; 1327 1328 session = perf_session__new(&file, false, NULL); 1329 if (!session) 1330 return -1; 1331 1332 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1333 1334 scripts_dir = opendir(scripts_path); 1335 if (!scripts_dir) { 1336 perf_session__delete(session); 1337 return -1; 1338 } 1339 1340 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { 1341 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, 1342 lang_dirent.d_name); 1343 #ifdef NO_LIBPERL 1344 if (strstr(lang_path, "perl")) 1345 continue; 1346 #endif 1347 #ifdef NO_LIBPYTHON 1348 if (strstr(lang_path, "python")) 1349 continue; 1350 #endif 1351 1352 lang_dir = opendir(lang_path); 1353 if (!lang_dir) 1354 continue; 1355 1356 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 1357 /* Skip those real time scripts: xxxtop.p[yl] */ 1358 if (strstr(script_dirent.d_name, "top.")) 1359 continue; 1360 sprintf(scripts_path_array[i], "%s/%s", lang_path, 1361 script_dirent.d_name); 1362 temp = strchr(script_dirent.d_name, '.'); 1363 snprintf(scripts_array[i], 1364 (temp - script_dirent.d_name) + 1, 1365 "%s", script_dirent.d_name); 1366 1367 if (check_ev_match(lang_path, 1368 scripts_array[i], session)) 1369 continue; 1370 1371 i++; 1372 } 1373 closedir(lang_dir); 1374 } 1375 1376 closedir(scripts_dir); 1377 perf_session__delete(session); 1378 return i; 1379 } 1380 1381 static char *get_script_path(const char *script_root, const char *suffix) 1382 { 1383 struct dirent *script_next, *lang_next, script_dirent, lang_dirent; 1384 char scripts_path[MAXPATHLEN]; 1385 char script_path[MAXPATHLEN]; 1386 DIR *scripts_dir, *lang_dir; 1387 char lang_path[MAXPATHLEN]; 1388 char *__script_root; 1389 1390 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1391 1392 scripts_dir = opendir(scripts_path); 1393 if (!scripts_dir) 1394 return NULL; 1395 1396 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { 1397 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 1398 lang_dirent.d_name); 1399 lang_dir = opendir(lang_path); 1400 if (!lang_dir) 1401 continue; 1402 1403 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 1404 __script_root = get_script_root(&script_dirent, suffix); 1405 if (__script_root && !strcmp(script_root, __script_root)) { 1406 free(__script_root); 1407 closedir(lang_dir); 1408 closedir(scripts_dir); 1409 snprintf(script_path, MAXPATHLEN, "%s/%s", 1410 lang_path, script_dirent.d_name); 1411 return strdup(script_path); 1412 } 1413 free(__script_root); 1414 } 1415 closedir(lang_dir); 1416 } 1417 closedir(scripts_dir); 1418 1419 return NULL; 1420 } 1421 1422 static bool is_top_script(const char *script_path) 1423 { 1424 return ends_with(script_path, "top") == NULL ? false : true; 1425 } 1426 1427 static int has_required_arg(char *script_path) 1428 { 1429 struct script_desc *desc; 1430 int n_args = 0; 1431 char *p; 1432 1433 desc = script_desc__new(NULL); 1434 1435 if (read_script_info(desc, script_path)) 1436 goto out; 1437 1438 if (!desc->args) 1439 goto out; 1440 1441 for (p = desc->args; *p; p++) 1442 if (*p == '<') 1443 n_args++; 1444 out: 1445 script_desc__delete(desc); 1446 1447 return n_args; 1448 } 1449 1450 static int have_cmd(int argc, const char **argv) 1451 { 1452 char **__argv = malloc(sizeof(const char *) * argc); 1453 1454 if (!__argv) { 1455 pr_err("malloc failed\n"); 1456 return -1; 1457 } 1458 1459 memcpy(__argv, argv, sizeof(const char *) * argc); 1460 argc = parse_options(argc, (const char **)__argv, record_options, 1461 NULL, PARSE_OPT_STOP_AT_NON_OPTION); 1462 free(__argv); 1463 1464 system_wide = (argc == 0); 1465 1466 return 0; 1467 } 1468 1469 int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) 1470 { 1471 bool show_full_info = false; 1472 bool header = false; 1473 bool header_only = false; 1474 char *rec_script_path = NULL; 1475 char *rep_script_path = NULL; 1476 struct perf_session *session; 1477 char *script_path = NULL; 1478 const char **__argv; 1479 int i, j, err; 1480 struct perf_script script = { 1481 .tool = { 1482 .sample = process_sample_event, 1483 .mmap = perf_event__process_mmap, 1484 .mmap2 = perf_event__process_mmap2, 1485 .comm = perf_event__process_comm, 1486 .exit = perf_event__process_exit, 1487 .fork = perf_event__process_fork, 1488 .attr = process_attr, 1489 .tracing_data = perf_event__process_tracing_data, 1490 .build_id = perf_event__process_build_id, 1491 .ordered_samples = true, 1492 .ordering_requires_timestamps = true, 1493 }, 1494 }; 1495 const struct option options[] = { 1496 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1497 "dump raw trace in ASCII"), 1498 OPT_INCR('v', "verbose", &verbose, 1499 "be more verbose (show symbol address, etc)"), 1500 OPT_BOOLEAN('L', "Latency", &latency_format, 1501 "show latency attributes (irqs/preemption disabled, etc)"), 1502 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts", 1503 list_available_scripts), 1504 OPT_CALLBACK('s', "script", NULL, "name", 1505 "script file name (lang:script name, script name, or *)", 1506 parse_scriptname), 1507 OPT_STRING('g', "gen-script", &generate_script_lang, "lang", 1508 "generate perf-script.xx script in specified language"), 1509 OPT_STRING('i', "input", &input_name, "file", "input file name"), 1510 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 1511 "do various checks like samples ordering and lost events"), 1512 OPT_BOOLEAN(0, "header", &header, "Show data header."), 1513 OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."), 1514 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1515 "file", "vmlinux pathname"), 1516 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 1517 "file", "kallsyms pathname"), 1518 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain, 1519 "When printing symbols do not display call chain"), 1520 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1521 "Look for files with symbols relative to this directory"), 1522 OPT_CALLBACK('f', "fields", NULL, "str", 1523 "comma separated output fields prepend with 'type:'. " 1524 "Valid types: hw,sw,trace,raw. " 1525 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1526 "addr,symoff", parse_output_fields), 1527 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1528 "system-wide collection from all CPUs"), 1529 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1530 "only consider these symbols"), 1531 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1532 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 1533 "only display events for these comms"), 1534 OPT_BOOLEAN('I', "show-info", &show_full_info, 1535 "display extended information from perf.data file"), 1536 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 1537 "Show the path of [kernel.kallsyms]"), 1538 OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events, 1539 "Show the fork/comm/exit events"), 1540 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events, 1541 "Show the mmap events"), 1542 OPT_END() 1543 }; 1544 const char * const script_usage[] = { 1545 "perf script [<options>]", 1546 "perf script [<options>] record <script> [<record-options>] <command>", 1547 "perf script [<options>] report <script> [script-args]", 1548 "perf script [<options>] <script> [<record-options>] <command>", 1549 "perf script [<options>] <top-script> [script-args]", 1550 NULL 1551 }; 1552 struct perf_data_file file = { 1553 .mode = PERF_DATA_MODE_READ, 1554 }; 1555 1556 setup_scripting(); 1557 1558 argc = parse_options(argc, argv, options, script_usage, 1559 PARSE_OPT_STOP_AT_NON_OPTION); 1560 1561 file.path = input_name; 1562 1563 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 1564 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 1565 if (!rec_script_path) 1566 return cmd_record(argc, argv, NULL); 1567 } 1568 1569 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) { 1570 rep_script_path = get_script_path(argv[1], REPORT_SUFFIX); 1571 if (!rep_script_path) { 1572 fprintf(stderr, 1573 "Please specify a valid report script" 1574 "(see 'perf script -l' for listing)\n"); 1575 return -1; 1576 } 1577 } 1578 1579 /* make sure PERF_EXEC_PATH is set for scripts */ 1580 perf_set_argv_exec_path(perf_exec_path()); 1581 1582 if (argc && !script_name && !rec_script_path && !rep_script_path) { 1583 int live_pipe[2]; 1584 int rep_args; 1585 pid_t pid; 1586 1587 rec_script_path = get_script_path(argv[0], RECORD_SUFFIX); 1588 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX); 1589 1590 if (!rec_script_path && !rep_script_path) { 1591 fprintf(stderr, " Couldn't find script %s\n\n See perf" 1592 " script -l for available scripts.\n", argv[0]); 1593 usage_with_options(script_usage, options); 1594 } 1595 1596 if (is_top_script(argv[0])) { 1597 rep_args = argc - 1; 1598 } else { 1599 int rec_args; 1600 1601 rep_args = has_required_arg(rep_script_path); 1602 rec_args = (argc - 1) - rep_args; 1603 if (rec_args < 0) { 1604 fprintf(stderr, " %s script requires options." 1605 "\n\n See perf script -l for available " 1606 "scripts and options.\n", argv[0]); 1607 usage_with_options(script_usage, options); 1608 } 1609 } 1610 1611 if (pipe(live_pipe) < 0) { 1612 perror("failed to create pipe"); 1613 return -1; 1614 } 1615 1616 pid = fork(); 1617 if (pid < 0) { 1618 perror("failed to fork"); 1619 return -1; 1620 } 1621 1622 if (!pid) { 1623 j = 0; 1624 1625 dup2(live_pipe[1], 1); 1626 close(live_pipe[0]); 1627 1628 if (is_top_script(argv[0])) { 1629 system_wide = true; 1630 } else if (!system_wide) { 1631 if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) { 1632 err = -1; 1633 goto out; 1634 } 1635 } 1636 1637 __argv = malloc((argc + 6) * sizeof(const char *)); 1638 if (!__argv) { 1639 pr_err("malloc failed\n"); 1640 err = -ENOMEM; 1641 goto out; 1642 } 1643 1644 __argv[j++] = "/bin/sh"; 1645 __argv[j++] = rec_script_path; 1646 if (system_wide) 1647 __argv[j++] = "-a"; 1648 __argv[j++] = "-q"; 1649 __argv[j++] = "-o"; 1650 __argv[j++] = "-"; 1651 for (i = rep_args + 1; i < argc; i++) 1652 __argv[j++] = argv[i]; 1653 __argv[j++] = NULL; 1654 1655 execvp("/bin/sh", (char **)__argv); 1656 free(__argv); 1657 exit(-1); 1658 } 1659 1660 dup2(live_pipe[0], 0); 1661 close(live_pipe[1]); 1662 1663 __argv = malloc((argc + 4) * sizeof(const char *)); 1664 if (!__argv) { 1665 pr_err("malloc failed\n"); 1666 err = -ENOMEM; 1667 goto out; 1668 } 1669 1670 j = 0; 1671 __argv[j++] = "/bin/sh"; 1672 __argv[j++] = rep_script_path; 1673 for (i = 1; i < rep_args + 1; i++) 1674 __argv[j++] = argv[i]; 1675 __argv[j++] = "-i"; 1676 __argv[j++] = "-"; 1677 __argv[j++] = NULL; 1678 1679 execvp("/bin/sh", (char **)__argv); 1680 free(__argv); 1681 exit(-1); 1682 } 1683 1684 if (rec_script_path) 1685 script_path = rec_script_path; 1686 if (rep_script_path) 1687 script_path = rep_script_path; 1688 1689 if (script_path) { 1690 j = 0; 1691 1692 if (!rec_script_path) 1693 system_wide = false; 1694 else if (!system_wide) { 1695 if (have_cmd(argc - 1, &argv[1]) != 0) { 1696 err = -1; 1697 goto out; 1698 } 1699 } 1700 1701 __argv = malloc((argc + 2) * sizeof(const char *)); 1702 if (!__argv) { 1703 pr_err("malloc failed\n"); 1704 err = -ENOMEM; 1705 goto out; 1706 } 1707 1708 __argv[j++] = "/bin/sh"; 1709 __argv[j++] = script_path; 1710 if (system_wide) 1711 __argv[j++] = "-a"; 1712 for (i = 2; i < argc; i++) 1713 __argv[j++] = argv[i]; 1714 __argv[j++] = NULL; 1715 1716 execvp("/bin/sh", (char **)__argv); 1717 free(__argv); 1718 exit(-1); 1719 } 1720 1721 if (symbol__init() < 0) 1722 return -1; 1723 if (!script_name) 1724 setup_pager(); 1725 1726 session = perf_session__new(&file, false, &script.tool); 1727 if (session == NULL) 1728 return -ENOMEM; 1729 1730 if (header || header_only) { 1731 perf_session__fprintf_info(session, stdout, show_full_info); 1732 if (header_only) 1733 return 0; 1734 } 1735 1736 script.session = session; 1737 1738 if (cpu_list) { 1739 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1740 return -1; 1741 } 1742 1743 if (!no_callchain) 1744 symbol_conf.use_callchain = true; 1745 else 1746 symbol_conf.use_callchain = false; 1747 1748 if (generate_script_lang) { 1749 struct stat perf_stat; 1750 int input; 1751 1752 if (output_set_by_user()) { 1753 fprintf(stderr, 1754 "custom fields not supported for generated scripts"); 1755 return -1; 1756 } 1757 1758 input = open(file.path, O_RDONLY); /* input_name */ 1759 if (input < 0) { 1760 perror("failed to open file"); 1761 return -1; 1762 } 1763 1764 err = fstat(input, &perf_stat); 1765 if (err < 0) { 1766 perror("failed to stat file"); 1767 return -1; 1768 } 1769 1770 if (!perf_stat.st_size) { 1771 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1772 return 0; 1773 } 1774 1775 scripting_ops = script_spec__lookup(generate_script_lang); 1776 if (!scripting_ops) { 1777 fprintf(stderr, "invalid language specifier"); 1778 return -1; 1779 } 1780 1781 err = scripting_ops->generate_script(session->tevent.pevent, 1782 "perf-script"); 1783 goto out; 1784 } 1785 1786 if (script_name) { 1787 err = scripting_ops->start_script(script_name, argc, argv); 1788 if (err) 1789 goto out; 1790 pr_debug("perf script started with script %s\n\n", script_name); 1791 } 1792 1793 1794 err = perf_session__check_output_opt(session); 1795 if (err < 0) 1796 goto out; 1797 1798 err = __cmd_script(&script); 1799 1800 perf_session__delete(session); 1801 cleanup_scripting(); 1802 out: 1803 return err; 1804 } 1805