aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c229
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
19static char const *script_name; 20static char const *script_name;
@@ -28,11 +29,6 @@ static bool system_wide;
28static const char *cpu_list; 29static const char *cpu_list;
29static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 30static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
30 31
31struct perf_script {
32 struct perf_tool tool;
33 struct perf_session *session;
34};
35
36enum perf_output_field { 32enum 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
265static void print_sample_start(struct pevent *pevent, 261static 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
418static void process_event(union perf_event *event __unused, 398static 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
457static int default_start_script(const char *script __unused, 434static 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
469static int default_generate_script(struct pevent *pevent __unused, 446static 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
499static const char *input_name; 476static const char *input_name;
500 477
501static int process_sample_event(struct perf_tool *tool __used, 478static 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
547static struct perf_script perf_script = { 522static 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
563extern volatile int session_done; 536extern volatile int session_done;
564 537
565static void sig_handler(int sig __unused) 538static 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
675static int parse_scriptname(const struct option *opt __used, 648static 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
721static int parse_output_fields(const struct option *opt __used, 694static 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
1013static int list_available_scripts(const struct option *opt __used, 986static 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 */
1042int 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
1061static char *get_script_path(const char *script_root, const char *suffix) 1090static 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
1184static bool have_cmd(int argc, const char **argv) 1215static 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
1198int cmd_script(int argc, const char **argv, const char *prefix __used) 1234int 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);