diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
| -rw-r--r-- | tools/perf/builtin-script.c | 229 |
1 files changed, 140 insertions, 89 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 1e60ab70b2b1..1be843aa1546 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "util/util.h" | 14 | #include "util/util.h" |
| 15 | #include "util/evlist.h" | 15 | #include "util/evlist.h" |
| 16 | #include "util/evsel.h" | 16 | #include "util/evsel.h" |
| 17 | #include "util/sort.h" | ||
| 17 | #include <linux/bitmap.h> | 18 | #include <linux/bitmap.h> |
| 18 | 19 | ||
| 19 | static char const *script_name; | 20 | static char const *script_name; |
| @@ -28,11 +29,6 @@ static bool system_wide; | |||
| 28 | static const char *cpu_list; | 29 | static const char *cpu_list; |
| 29 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 30 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
| 30 | 31 | ||
| 31 | struct perf_script { | ||
| 32 | struct perf_tool tool; | ||
| 33 | struct perf_session *session; | ||
| 34 | }; | ||
| 35 | |||
| 36 | enum perf_output_field { | 32 | enum perf_output_field { |
| 37 | PERF_OUTPUT_COMM = 1U << 0, | 33 | PERF_OUTPUT_COMM = 1U << 0, |
| 38 | PERF_OUTPUT_TID = 1U << 1, | 34 | PERF_OUTPUT_TID = 1U << 1, |
| @@ -262,14 +258,11 @@ static int perf_session__check_output_opt(struct perf_session *session) | |||
| 262 | return 0; | 258 | return 0; |
| 263 | } | 259 | } |
| 264 | 260 | ||
| 265 | static void print_sample_start(struct pevent *pevent, | 261 | static void print_sample_start(struct perf_sample *sample, |
| 266 | struct perf_sample *sample, | ||
| 267 | struct thread *thread, | 262 | struct thread *thread, |
| 268 | struct perf_evsel *evsel) | 263 | struct perf_evsel *evsel) |
| 269 | { | 264 | { |
| 270 | int type; | ||
| 271 | struct perf_event_attr *attr = &evsel->attr; | 265 | struct perf_event_attr *attr = &evsel->attr; |
| 272 | struct event_format *event; | ||
| 273 | const char *evname = NULL; | 266 | const char *evname = NULL; |
| 274 | unsigned long secs; | 267 | unsigned long secs; |
| 275 | unsigned long usecs; | 268 | unsigned long usecs; |
| @@ -307,20 +300,7 @@ static void print_sample_start(struct pevent *pevent, | |||
| 307 | } | 300 | } |
| 308 | 301 | ||
| 309 | if (PRINT_FIELD(EVNAME)) { | 302 | if (PRINT_FIELD(EVNAME)) { |
| 310 | if (attr->type == PERF_TYPE_TRACEPOINT) { | 303 | evname = perf_evsel__name(evsel); |
| 311 | /* | ||
| 312 | * XXX Do we really need this here? | ||
| 313 | * perf_evlist__set_tracepoint_names should have done | ||
| 314 | * this already | ||
| 315 | */ | ||
| 316 | type = trace_parse_common_type(pevent, | ||
| 317 | sample->raw_data); | ||
| 318 | event = pevent_find_event(pevent, type); | ||
| 319 | if (event) | ||
| 320 | evname = event->name; | ||
| 321 | } else | ||
| 322 | evname = perf_evsel__name(evsel); | ||
| 323 | |||
| 324 | printf("%s: ", evname ? evname : "[unknown]"); | 304 | printf("%s: ", evname ? evname : "[unknown]"); |
| 325 | } | 305 | } |
| 326 | } | 306 | } |
| @@ -401,7 +381,7 @@ static void print_sample_bts(union perf_event *event, | |||
| 401 | printf(" "); | 381 | printf(" "); |
| 402 | else | 382 | else |
| 403 | printf("\n"); | 383 | printf("\n"); |
| 404 | perf_event__print_ip(event, sample, machine, | 384 | perf_evsel__print_ip(evsel, event, sample, machine, |
| 405 | PRINT_FIELD(SYM), PRINT_FIELD(DSO), | 385 | PRINT_FIELD(SYM), PRINT_FIELD(DSO), |
| 406 | PRINT_FIELD(SYMOFFSET)); | 386 | PRINT_FIELD(SYMOFFSET)); |
| 407 | } | 387 | } |
| @@ -415,19 +395,17 @@ static void print_sample_bts(union perf_event *event, | |||
| 415 | printf("\n"); | 395 | printf("\n"); |
| 416 | } | 396 | } |
| 417 | 397 | ||
| 418 | static void process_event(union perf_event *event __unused, | 398 | static void process_event(union perf_event *event, struct perf_sample *sample, |
| 419 | struct pevent *pevent, | 399 | struct perf_evsel *evsel, struct machine *machine, |
| 420 | struct perf_sample *sample, | 400 | struct addr_location *al) |
| 421 | struct perf_evsel *evsel, | ||
| 422 | struct machine *machine, | ||
| 423 | struct thread *thread) | ||
| 424 | { | 401 | { |
| 425 | struct perf_event_attr *attr = &evsel->attr; | 402 | struct perf_event_attr *attr = &evsel->attr; |
| 403 | struct thread *thread = al->thread; | ||
| 426 | 404 | ||
| 427 | if (output[attr->type].fields == 0) | 405 | if (output[attr->type].fields == 0) |
| 428 | return; | 406 | return; |
| 429 | 407 | ||
| 430 | print_sample_start(pevent, sample, thread, evsel); | 408 | print_sample_start(sample, thread, evsel); |
| 431 | 409 | ||
| 432 | if (is_bts_event(attr)) { | 410 | if (is_bts_event(attr)) { |
| 433 | print_sample_bts(event, sample, evsel, machine, thread); | 411 | print_sample_bts(event, sample, evsel, machine, thread); |
| @@ -435,9 +413,8 @@ static void process_event(union perf_event *event __unused, | |||
| 435 | } | 413 | } |
| 436 | 414 | ||
| 437 | if (PRINT_FIELD(TRACE)) | 415 | if (PRINT_FIELD(TRACE)) |
| 438 | print_trace_event(pevent, sample->cpu, sample->raw_data, | 416 | event_format__print(evsel->tp_format, sample->cpu, |
| 439 | sample->raw_size); | 417 | sample->raw_data, sample->raw_size); |
| 440 | |||
| 441 | if (PRINT_FIELD(ADDR)) | 418 | if (PRINT_FIELD(ADDR)) |
| 442 | print_sample_addr(event, sample, machine, thread, attr); | 419 | print_sample_addr(event, sample, machine, thread, attr); |
| 443 | 420 | ||
| @@ -446,7 +423,7 @@ static void process_event(union perf_event *event __unused, | |||
| 446 | printf(" "); | 423 | printf(" "); |
| 447 | else | 424 | else |
| 448 | printf("\n"); | 425 | printf("\n"); |
| 449 | perf_event__print_ip(event, sample, machine, | 426 | perf_evsel__print_ip(evsel, event, sample, machine, |
| 450 | PRINT_FIELD(SYM), PRINT_FIELD(DSO), | 427 | PRINT_FIELD(SYM), PRINT_FIELD(DSO), |
| 451 | PRINT_FIELD(SYMOFFSET)); | 428 | PRINT_FIELD(SYMOFFSET)); |
| 452 | } | 429 | } |
| @@ -454,9 +431,9 @@ static void process_event(union perf_event *event __unused, | |||
| 454 | printf("\n"); | 431 | printf("\n"); |
| 455 | } | 432 | } |
| 456 | 433 | ||
| 457 | static int default_start_script(const char *script __unused, | 434 | static int default_start_script(const char *script __maybe_unused, |
| 458 | int argc __unused, | 435 | int argc __maybe_unused, |
| 459 | const char **argv __unused) | 436 | const char **argv __maybe_unused) |
| 460 | { | 437 | { |
| 461 | return 0; | 438 | return 0; |
| 462 | } | 439 | } |
| @@ -466,8 +443,8 @@ static int default_stop_script(void) | |||
| 466 | return 0; | 443 | return 0; |
| 467 | } | 444 | } |
| 468 | 445 | ||
| 469 | static int default_generate_script(struct pevent *pevent __unused, | 446 | static int default_generate_script(struct pevent *pevent __maybe_unused, |
| 470 | const char *outfile __unused) | 447 | const char *outfile __maybe_unused) |
| 471 | { | 448 | { |
| 472 | return 0; | 449 | return 0; |
| 473 | } | 450 | } |
| @@ -498,14 +475,13 @@ static int cleanup_scripting(void) | |||
| 498 | 475 | ||
| 499 | static const char *input_name; | 476 | static const char *input_name; |
| 500 | 477 | ||
| 501 | static int process_sample_event(struct perf_tool *tool __used, | 478 | static int process_sample_event(struct perf_tool *tool __maybe_unused, |
| 502 | union perf_event *event, | 479 | union perf_event *event, |
| 503 | struct perf_sample *sample, | 480 | struct perf_sample *sample, |
| 504 | struct perf_evsel *evsel, | 481 | struct perf_evsel *evsel, |
| 505 | struct machine *machine) | 482 | struct machine *machine) |
| 506 | { | 483 | { |
| 507 | struct addr_location al; | 484 | struct addr_location al; |
| 508 | struct perf_script *scr = container_of(tool, struct perf_script, tool); | ||
| 509 | struct thread *thread = machine__findnew_thread(machine, event->ip.tid); | 485 | struct thread *thread = machine__findnew_thread(machine, event->ip.tid); |
| 510 | 486 | ||
| 511 | if (thread == NULL) { | 487 | if (thread == NULL) { |
| @@ -537,32 +513,29 @@ static int process_sample_event(struct perf_tool *tool __used, | |||
| 537 | if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) | 513 | if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) |
| 538 | return 0; | 514 | return 0; |
| 539 | 515 | ||
| 540 | scripting_ops->process_event(event, scr->session->pevent, | 516 | scripting_ops->process_event(event, sample, evsel, machine, &al); |
| 541 | sample, evsel, machine, thread); | ||
| 542 | 517 | ||
| 543 | evsel->hists.stats.total_period += sample->period; | 518 | evsel->hists.stats.total_period += sample->period; |
| 544 | return 0; | 519 | return 0; |
| 545 | } | 520 | } |
| 546 | 521 | ||
| 547 | static struct perf_script perf_script = { | 522 | static struct perf_tool perf_script = { |
| 548 | .tool = { | 523 | .sample = process_sample_event, |
| 549 | .sample = process_sample_event, | 524 | .mmap = perf_event__process_mmap, |
| 550 | .mmap = perf_event__process_mmap, | 525 | .comm = perf_event__process_comm, |
| 551 | .comm = perf_event__process_comm, | 526 | .exit = perf_event__process_task, |
| 552 | .exit = perf_event__process_task, | 527 | .fork = perf_event__process_task, |
| 553 | .fork = perf_event__process_task, | 528 | .attr = perf_event__process_attr, |
| 554 | .attr = perf_event__process_attr, | 529 | .event_type = perf_event__process_event_type, |
| 555 | .event_type = perf_event__process_event_type, | 530 | .tracing_data = perf_event__process_tracing_data, |
| 556 | .tracing_data = perf_event__process_tracing_data, | 531 | .build_id = perf_event__process_build_id, |
| 557 | .build_id = perf_event__process_build_id, | 532 | .ordered_samples = true, |
| 558 | .ordered_samples = true, | 533 | .ordering_requires_timestamps = true, |
| 559 | .ordering_requires_timestamps = true, | ||
| 560 | }, | ||
| 561 | }; | 534 | }; |
| 562 | 535 | ||
| 563 | extern volatile int session_done; | 536 | extern volatile int session_done; |
| 564 | 537 | ||
| 565 | static void sig_handler(int sig __unused) | 538 | static void sig_handler(int sig __maybe_unused) |
| 566 | { | 539 | { |
| 567 | session_done = 1; | 540 | session_done = 1; |
| 568 | } | 541 | } |
| @@ -573,7 +546,7 @@ static int __cmd_script(struct perf_session *session) | |||
| 573 | 546 | ||
| 574 | signal(SIGINT, sig_handler); | 547 | signal(SIGINT, sig_handler); |
| 575 | 548 | ||
| 576 | ret = perf_session__process_events(session, &perf_script.tool); | 549 | ret = perf_session__process_events(session, &perf_script); |
| 577 | 550 | ||
| 578 | if (debug_mode) | 551 | if (debug_mode) |
| 579 | pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); | 552 | pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); |
| @@ -672,8 +645,8 @@ static void list_available_languages(void) | |||
| 672 | fprintf(stderr, "\n"); | 645 | fprintf(stderr, "\n"); |
| 673 | } | 646 | } |
| 674 | 647 | ||
| 675 | static int parse_scriptname(const struct option *opt __used, | 648 | static int parse_scriptname(const struct option *opt __maybe_unused, |
| 676 | const char *str, int unset __used) | 649 | const char *str, int unset __maybe_unused) |
| 677 | { | 650 | { |
| 678 | char spec[PATH_MAX]; | 651 | char spec[PATH_MAX]; |
| 679 | const char *script, *ext; | 652 | const char *script, *ext; |
| @@ -718,8 +691,8 @@ static int parse_scriptname(const struct option *opt __used, | |||
| 718 | return 0; | 691 | return 0; |
| 719 | } | 692 | } |
| 720 | 693 | ||
| 721 | static int parse_output_fields(const struct option *opt __used, | 694 | static int parse_output_fields(const struct option *opt __maybe_unused, |
| 722 | const char *arg, int unset __used) | 695 | const char *arg, int unset __maybe_unused) |
| 723 | { | 696 | { |
| 724 | char *tok; | 697 | char *tok; |
| 725 | int i, imax = sizeof(all_output_options) / sizeof(struct output_option); | 698 | int i, imax = sizeof(all_output_options) / sizeof(struct output_option); |
| @@ -1010,8 +983,9 @@ static char *get_script_root(struct dirent *script_dirent, const char *suffix) | |||
| 1010 | return script_root; | 983 | return script_root; |
| 1011 | } | 984 | } |
| 1012 | 985 | ||
| 1013 | static int list_available_scripts(const struct option *opt __used, | 986 | static int list_available_scripts(const struct option *opt __maybe_unused, |
| 1014 | const char *s __used, int unset __used) | 987 | const char *s __maybe_unused, |
| 988 | int unset __maybe_unused) | ||
| 1015 | { | 989 | { |
| 1016 | struct dirent *script_next, *lang_next, script_dirent, lang_dirent; | 990 | struct dirent *script_next, *lang_next, script_dirent, lang_dirent; |
| 1017 | char scripts_path[MAXPATHLEN]; | 991 | char scripts_path[MAXPATHLEN]; |
| @@ -1058,6 +1032,61 @@ static int list_available_scripts(const struct option *opt __used, | |||
| 1058 | exit(0); | 1032 | exit(0); |
| 1059 | } | 1033 | } |
| 1060 | 1034 | ||
| 1035 | /* | ||
| 1036 | * Return -1 if none is found, otherwise the actual scripts number. | ||
| 1037 | * | ||
| 1038 | * Currently the only user of this function is the script browser, which | ||
| 1039 | * will list all statically runnable scripts, select one, execute it and | ||
| 1040 | * show the output in a perf browser. | ||
| 1041 | */ | ||
| 1042 | int find_scripts(char **scripts_array, char **scripts_path_array) | ||
| 1043 | { | ||
| 1044 | struct dirent *script_next, *lang_next, script_dirent, lang_dirent; | ||
| 1045 | char scripts_path[MAXPATHLEN]; | ||
| 1046 | DIR *scripts_dir, *lang_dir; | ||
| 1047 | char lang_path[MAXPATHLEN]; | ||
| 1048 | char *temp; | ||
| 1049 | int i = 0; | ||
| 1050 | |||
| 1051 | snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); | ||
| 1052 | |||
| 1053 | scripts_dir = opendir(scripts_path); | ||
| 1054 | if (!scripts_dir) | ||
| 1055 | return -1; | ||
| 1056 | |||
| 1057 | for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { | ||
| 1058 | snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, | ||
| 1059 | lang_dirent.d_name); | ||
| 1060 | #ifdef NO_LIBPERL | ||
| 1061 | if (strstr(lang_path, "perl")) | ||
| 1062 | continue; | ||
| 1063 | #endif | ||
| 1064 | #ifdef NO_LIBPYTHON | ||
| 1065 | if (strstr(lang_path, "python")) | ||
| 1066 | continue; | ||
| 1067 | #endif | ||
| 1068 | |||
| 1069 | lang_dir = opendir(lang_path); | ||
| 1070 | if (!lang_dir) | ||
| 1071 | continue; | ||
| 1072 | |||
| 1073 | for_each_script(lang_path, lang_dir, script_dirent, script_next) { | ||
| 1074 | /* Skip those real time scripts: xxxtop.p[yl] */ | ||
| 1075 | if (strstr(script_dirent.d_name, "top.")) | ||
| 1076 | continue; | ||
| 1077 | sprintf(scripts_path_array[i], "%s/%s", lang_path, | ||
| 1078 | script_dirent.d_name); | ||
| 1079 | temp = strchr(script_dirent.d_name, '.'); | ||
| 1080 | snprintf(scripts_array[i], | ||
| 1081 | (temp - script_dirent.d_name) + 1, | ||
| 1082 | "%s", script_dirent.d_name); | ||
| 1083 | i++; | ||
| 1084 | } | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | return i; | ||
| 1088 | } | ||
| 1089 | |||
| 1061 | static char *get_script_path(const char *script_root, const char *suffix) | 1090 | static char *get_script_path(const char *script_root, const char *suffix) |
| 1062 | { | 1091 | { |
| 1063 | struct dirent *script_next, *lang_next, script_dirent, lang_dirent; | 1092 | struct dirent *script_next, *lang_next, script_dirent, lang_dirent; |
| @@ -1170,6 +1199,8 @@ static const struct option options[] = { | |||
| 1170 | parse_output_fields), | 1199 | parse_output_fields), |
| 1171 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 1200 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
| 1172 | "system-wide collection from all CPUs"), | 1201 | "system-wide collection from all CPUs"), |
| 1202 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", | ||
| 1203 | "only consider these symbols"), | ||
| 1173 | OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), | 1204 | OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), |
| 1174 | OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", | 1205 | OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", |
| 1175 | "only display events for these comms"), | 1206 | "only display events for these comms"), |
| @@ -1181,21 +1212,26 @@ static const struct option options[] = { | |||
| 1181 | OPT_END() | 1212 | OPT_END() |
| 1182 | }; | 1213 | }; |
| 1183 | 1214 | ||
| 1184 | static bool have_cmd(int argc, const char **argv) | 1215 | static int have_cmd(int argc, const char **argv) |
| 1185 | { | 1216 | { |
| 1186 | char **__argv = malloc(sizeof(const char *) * argc); | 1217 | char **__argv = malloc(sizeof(const char *) * argc); |
| 1187 | 1218 | ||
| 1188 | if (!__argv) | 1219 | if (!__argv) { |
| 1189 | die("malloc"); | 1220 | pr_err("malloc failed\n"); |
| 1221 | return -1; | ||
| 1222 | } | ||
| 1223 | |||
| 1190 | memcpy(__argv, argv, sizeof(const char *) * argc); | 1224 | memcpy(__argv, argv, sizeof(const char *) * argc); |
| 1191 | argc = parse_options(argc, (const char **)__argv, record_options, | 1225 | argc = parse_options(argc, (const char **)__argv, record_options, |
| 1192 | NULL, PARSE_OPT_STOP_AT_NON_OPTION); | 1226 | NULL, PARSE_OPT_STOP_AT_NON_OPTION); |
| 1193 | free(__argv); | 1227 | free(__argv); |
| 1194 | 1228 | ||
| 1195 | return argc != 0; | 1229 | system_wide = (argc == 0); |
| 1230 | |||
| 1231 | return 0; | ||
| 1196 | } | 1232 | } |
| 1197 | 1233 | ||
| 1198 | int cmd_script(int argc, const char **argv, const char *prefix __used) | 1234 | int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) |
| 1199 | { | 1235 | { |
| 1200 | char *rec_script_path = NULL; | 1236 | char *rec_script_path = NULL; |
| 1201 | char *rep_script_path = NULL; | 1237 | char *rep_script_path = NULL; |
| @@ -1259,13 +1295,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) | |||
| 1259 | 1295 | ||
| 1260 | if (pipe(live_pipe) < 0) { | 1296 | if (pipe(live_pipe) < 0) { |
| 1261 | perror("failed to create pipe"); | 1297 | perror("failed to create pipe"); |
| 1262 | exit(-1); | 1298 | return -1; |
| 1263 | } | 1299 | } |
| 1264 | 1300 | ||
| 1265 | pid = fork(); | 1301 | pid = fork(); |
| 1266 | if (pid < 0) { | 1302 | if (pid < 0) { |
| 1267 | perror("failed to fork"); | 1303 | perror("failed to fork"); |
| 1268 | exit(-1); | 1304 | return -1; |
| 1269 | } | 1305 | } |
| 1270 | 1306 | ||
| 1271 | if (!pid) { | 1307 | if (!pid) { |
| @@ -1277,13 +1313,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) | |||
| 1277 | if (is_top_script(argv[0])) { | 1313 | if (is_top_script(argv[0])) { |
| 1278 | system_wide = true; | 1314 | system_wide = true; |
| 1279 | } else if (!system_wide) { | 1315 | } else if (!system_wide) { |
| 1280 | system_wide = !have_cmd(argc - rep_args, | 1316 | if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) { |
| 1281 | &argv[rep_args]); | 1317 | err = -1; |
| 1318 | goto out; | ||
| 1319 | } | ||
| 1282 | } | 1320 | } |
| 1283 | 1321 | ||
| 1284 | __argv = malloc((argc + 6) * sizeof(const char *)); | 1322 | __argv = malloc((argc + 6) * sizeof(const char *)); |
| 1285 | if (!__argv) | 1323 | if (!__argv) { |
| 1286 | die("malloc"); | 1324 | pr_err("malloc failed\n"); |
| 1325 | err = -ENOMEM; | ||
| 1326 | goto out; | ||
| 1327 | } | ||
| 1287 | 1328 | ||
| 1288 | __argv[j++] = "/bin/sh"; | 1329 | __argv[j++] = "/bin/sh"; |
| 1289 | __argv[j++] = rec_script_path; | 1330 | __argv[j++] = rec_script_path; |
| @@ -1305,8 +1346,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) | |||
| 1305 | close(live_pipe[1]); | 1346 | close(live_pipe[1]); |
| 1306 | 1347 | ||
| 1307 | __argv = malloc((argc + 4) * sizeof(const char *)); | 1348 | __argv = malloc((argc + 4) * sizeof(const char *)); |
| 1308 | if (!__argv) | 1349 | if (!__argv) { |
| 1309 | die("malloc"); | 1350 | pr_err("malloc failed\n"); |
| 1351 | err = -ENOMEM; | ||
| 1352 | goto out; | ||
| 1353 | } | ||
| 1354 | |||
| 1310 | j = 0; | 1355 | j = 0; |
| 1311 | __argv[j++] = "/bin/sh"; | 1356 | __argv[j++] = "/bin/sh"; |
| 1312 | __argv[j++] = rep_script_path; | 1357 | __argv[j++] = rep_script_path; |
| @@ -1331,12 +1376,20 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) | |||
| 1331 | 1376 | ||
| 1332 | if (!rec_script_path) | 1377 | if (!rec_script_path) |
| 1333 | system_wide = false; | 1378 | system_wide = false; |
| 1334 | else if (!system_wide) | 1379 | else if (!system_wide) { |
| 1335 | system_wide = !have_cmd(argc - 1, &argv[1]); | 1380 | if (have_cmd(argc - 1, &argv[1]) != 0) { |
| 1381 | err = -1; | ||
| 1382 | goto out; | ||
| 1383 | } | ||
| 1384 | } | ||
| 1336 | 1385 | ||
| 1337 | __argv = malloc((argc + 2) * sizeof(const char *)); | 1386 | __argv = malloc((argc + 2) * sizeof(const char *)); |
| 1338 | if (!__argv) | 1387 | if (!__argv) { |
| 1339 | die("malloc"); | 1388 | pr_err("malloc failed\n"); |
| 1389 | err = -ENOMEM; | ||
| 1390 | goto out; | ||
| 1391 | } | ||
| 1392 | |||
| 1340 | __argv[j++] = "/bin/sh"; | 1393 | __argv[j++] = "/bin/sh"; |
| 1341 | __argv[j++] = script_path; | 1394 | __argv[j++] = script_path; |
| 1342 | if (system_wide) | 1395 | if (system_wide) |
| @@ -1356,12 +1409,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) | |||
| 1356 | setup_pager(); | 1409 | setup_pager(); |
| 1357 | 1410 | ||
| 1358 | session = perf_session__new(input_name, O_RDONLY, 0, false, | 1411 | session = perf_session__new(input_name, O_RDONLY, 0, false, |
| 1359 | &perf_script.tool); | 1412 | &perf_script); |
| 1360 | if (session == NULL) | 1413 | if (session == NULL) |
| 1361 | return -ENOMEM; | 1414 | return -ENOMEM; |
| 1362 | 1415 | ||
| 1363 | perf_script.session = session; | ||
| 1364 | |||
| 1365 | if (cpu_list) { | 1416 | if (cpu_list) { |
| 1366 | if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) | 1417 | if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) |
| 1367 | return -1; | 1418 | return -1; |
| @@ -1387,18 +1438,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) | |||
| 1387 | input = open(session->filename, O_RDONLY); /* input_name */ | 1438 | input = open(session->filename, O_RDONLY); /* input_name */ |
| 1388 | if (input < 0) { | 1439 | if (input < 0) { |
| 1389 | perror("failed to open file"); | 1440 | perror("failed to open file"); |
| 1390 | exit(-1); | 1441 | return -1; |
| 1391 | } | 1442 | } |
| 1392 | 1443 | ||
| 1393 | err = fstat(input, &perf_stat); | 1444 | err = fstat(input, &perf_stat); |
| 1394 | if (err < 0) { | 1445 | if (err < 0) { |
| 1395 | perror("failed to stat file"); | 1446 | perror("failed to stat file"); |
| 1396 | exit(-1); | 1447 | return -1; |
| 1397 | } | 1448 | } |
| 1398 | 1449 | ||
| 1399 | if (!perf_stat.st_size) { | 1450 | if (!perf_stat.st_size) { |
| 1400 | fprintf(stderr, "zero-sized file, nothing to do!\n"); | 1451 | fprintf(stderr, "zero-sized file, nothing to do!\n"); |
| 1401 | exit(0); | 1452 | return 0; |
| 1402 | } | 1453 | } |
| 1403 | 1454 | ||
| 1404 | scripting_ops = script_spec__lookup(generate_script_lang); | 1455 | scripting_ops = script_spec__lookup(generate_script_lang); |
