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