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