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