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.c96
1 files changed, 70 insertions, 26 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index f57035b89c15..9708a1290571 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -44,6 +44,7 @@ enum perf_output_field {
44 PERF_OUTPUT_ADDR = 1U << 10, 44 PERF_OUTPUT_ADDR = 1U << 10,
45 PERF_OUTPUT_SYMOFFSET = 1U << 11, 45 PERF_OUTPUT_SYMOFFSET = 1U << 11,
46 PERF_OUTPUT_SRCLINE = 1U << 12, 46 PERF_OUTPUT_SRCLINE = 1U << 12,
47 PERF_OUTPUT_PERIOD = 1U << 13,
47}; 48};
48 49
49struct output_option { 50struct output_option {
@@ -63,6 +64,7 @@ struct output_option {
63 {.str = "addr", .field = PERF_OUTPUT_ADDR}, 64 {.str = "addr", .field = PERF_OUTPUT_ADDR},
64 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, 65 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
65 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 66 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
67 {.str = "period", .field = PERF_OUTPUT_PERIOD},
66}; 68};
67 69
68/* default set to maintain compatibility with current format */ 70/* default set to maintain compatibility with current format */
@@ -80,7 +82,8 @@ static struct {
80 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 82 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
81 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 83 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
82 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 84 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
83 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 85 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
86 PERF_OUTPUT_PERIOD,
84 87
85 .invalid_fields = PERF_OUTPUT_TRACE, 88 .invalid_fields = PERF_OUTPUT_TRACE,
86 }, 89 },
@@ -91,7 +94,8 @@ static struct {
91 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 94 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
92 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 95 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
93 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 96 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
94 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 97 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
98 PERF_OUTPUT_PERIOD,
95 99
96 .invalid_fields = PERF_OUTPUT_TRACE, 100 .invalid_fields = PERF_OUTPUT_TRACE,
97 }, 101 },
@@ -110,7 +114,8 @@ static struct {
110 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 114 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
111 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 115 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
112 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 116 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
113 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 117 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
118 PERF_OUTPUT_PERIOD,
114 119
115 .invalid_fields = PERF_OUTPUT_TRACE, 120 .invalid_fields = PERF_OUTPUT_TRACE,
116 }, 121 },
@@ -184,10 +189,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", 189 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
185 PERF_OUTPUT_IP)) 190 PERF_OUTPUT_IP))
186 return -EINVAL; 191 return -EINVAL;
187
188 if (!no_callchain &&
189 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
190 symbol_conf.use_callchain = false;
191 } 192 }
192 193
193 if (PRINT_FIELD(ADDR) && 194 if (PRINT_FIELD(ADDR) &&
@@ -233,6 +234,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
233 PERF_OUTPUT_CPU)) 234 PERF_OUTPUT_CPU))
234 return -EINVAL; 235 return -EINVAL;
235 236
237 if (PRINT_FIELD(PERIOD) &&
238 perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD",
239 PERF_OUTPUT_PERIOD))
240 return -EINVAL;
241
236 return 0; 242 return 0;
237} 243}
238 244
@@ -290,6 +296,19 @@ static int perf_session__check_output_opt(struct perf_session *session)
290 set_print_ip_opts(&evsel->attr); 296 set_print_ip_opts(&evsel->attr);
291 } 297 }
292 298
299 if (!no_callchain) {
300 bool use_callchain = false;
301
302 evlist__for_each(session->evlist, evsel) {
303 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
304 use_callchain = true;
305 break;
306 }
307 }
308 if (!use_callchain)
309 symbol_conf.use_callchain = false;
310 }
311
293 /* 312 /*
294 * set default for tracepoints to print symbols only 313 * set default for tracepoints to print symbols only
295 * if callchains are present 314 * if callchains are present
@@ -439,6 +458,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
439 458
440 print_sample_start(sample, thread, evsel); 459 print_sample_start(sample, thread, evsel);
441 460
461 if (PRINT_FIELD(PERIOD))
462 printf("%10" PRIu64 " ", sample->period);
463
442 if (PRINT_FIELD(EVNAME)) { 464 if (PRINT_FIELD(EVNAME)) {
443 const char *evname = perf_evsel__name(evsel); 465 const char *evname = perf_evsel__name(evsel);
444 printf("%s: ", evname ? evname : "[unknown]"); 466 printf("%s: ", evname ? evname : "[unknown]");
@@ -476,6 +498,11 @@ static int default_start_script(const char *script __maybe_unused,
476 return 0; 498 return 0;
477} 499}
478 500
501static int default_flush_script(void)
502{
503 return 0;
504}
505
479static int default_stop_script(void) 506static int default_stop_script(void)
480{ 507{
481 return 0; 508 return 0;
@@ -489,6 +516,7 @@ static int default_generate_script(struct pevent *pevent __maybe_unused,
489 516
490static struct scripting_ops default_scripting_ops = { 517static struct scripting_ops default_scripting_ops = {
491 .start_script = default_start_script, 518 .start_script = default_start_script,
519 .flush_script = default_flush_script,
492 .stop_script = default_stop_script, 520 .stop_script = default_stop_script,
493 .process_event = process_event, 521 .process_event = process_event,
494 .generate_script = default_generate_script, 522 .generate_script = default_generate_script,
@@ -504,6 +532,11 @@ static void setup_scripting(void)
504 scripting_ops = &default_scripting_ops; 532 scripting_ops = &default_scripting_ops;
505} 533}
506 534
535static int flush_scripting(void)
536{
537 return scripting_ops->flush_script();
538}
539
507static int cleanup_scripting(void) 540static int cleanup_scripting(void)
508{ 541{
509 pr_debug("\nperf script stopped\n"); 542 pr_debug("\nperf script stopped\n");
@@ -552,7 +585,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
552 585
553 scripting_ops->process_event(event, sample, evsel, thread, &al); 586 scripting_ops->process_event(event, sample, evsel, thread, &al);
554 587
555 evsel->hists.stats.total_period += sample->period;
556 return 0; 588 return 0;
557} 589}
558 590
@@ -1471,12 +1503,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1471 bool show_full_info = false; 1503 bool show_full_info = false;
1472 bool header = false; 1504 bool header = false;
1473 bool header_only = false; 1505 bool header_only = false;
1506 bool script_started = false;
1474 char *rec_script_path = NULL; 1507 char *rec_script_path = NULL;
1475 char *rep_script_path = NULL; 1508 char *rep_script_path = NULL;
1476 struct perf_session *session; 1509 struct perf_session *session;
1477 char *script_path = NULL; 1510 char *script_path = NULL;
1478 const char **__argv; 1511 const char **__argv;
1479 int i, j, err; 1512 int i, j, err = 0;
1480 struct perf_script script = { 1513 struct perf_script script = {
1481 .tool = { 1514 .tool = {
1482 .sample = process_sample_event, 1515 .sample = process_sample_event,
@@ -1488,7 +1521,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1488 .attr = process_attr, 1521 .attr = process_attr,
1489 .tracing_data = perf_event__process_tracing_data, 1522 .tracing_data = perf_event__process_tracing_data,
1490 .build_id = perf_event__process_build_id, 1523 .build_id = perf_event__process_build_id,
1491 .ordered_samples = true, 1524 .ordered_events = true,
1492 .ordering_requires_timestamps = true, 1525 .ordering_requires_timestamps = true,
1493 }, 1526 },
1494 }; 1527 };
@@ -1523,7 +1556,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1523 "comma separated output fields prepend with 'type:'. " 1556 "comma separated output fields prepend with 'type:'. "
1524 "Valid types: hw,sw,trace,raw. " 1557 "Valid types: hw,sw,trace,raw. "
1525 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1558 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1526 "addr,symoff", parse_output_fields), 1559 "addr,symoff,period", parse_output_fields),
1527 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1560 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1528 "system-wide collection from all CPUs"), 1561 "system-wide collection from all CPUs"),
1529 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1562 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -1718,26 +1751,28 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1718 exit(-1); 1751 exit(-1);
1719 } 1752 }
1720 1753
1721 if (symbol__init() < 0)
1722 return -1;
1723 if (!script_name) 1754 if (!script_name)
1724 setup_pager(); 1755 setup_pager();
1725 1756
1726 session = perf_session__new(&file, false, &script.tool); 1757 session = perf_session__new(&file, false, &script.tool);
1727 if (session == NULL) 1758 if (session == NULL)
1728 return -ENOMEM; 1759 return -1;
1729 1760
1730 if (header || header_only) { 1761 if (header || header_only) {
1731 perf_session__fprintf_info(session, stdout, show_full_info); 1762 perf_session__fprintf_info(session, stdout, show_full_info);
1732 if (header_only) 1763 if (header_only)
1733 return 0; 1764 goto out_delete;
1734 } 1765 }
1735 1766
1767 if (symbol__init(&session->header.env) < 0)
1768 goto out_delete;
1769
1736 script.session = session; 1770 script.session = session;
1737 1771
1738 if (cpu_list) { 1772 if (cpu_list) {
1739 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1773 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
1740 return -1; 1774 if (err < 0)
1775 goto out_delete;
1741 } 1776 }
1742 1777
1743 if (!no_callchain) 1778 if (!no_callchain)
@@ -1752,53 +1787,62 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1752 if (output_set_by_user()) { 1787 if (output_set_by_user()) {
1753 fprintf(stderr, 1788 fprintf(stderr,
1754 "custom fields not supported for generated scripts"); 1789 "custom fields not supported for generated scripts");
1755 return -1; 1790 err = -EINVAL;
1791 goto out_delete;
1756 } 1792 }
1757 1793
1758 input = open(file.path, O_RDONLY); /* input_name */ 1794 input = open(file.path, O_RDONLY); /* input_name */
1759 if (input < 0) { 1795 if (input < 0) {
1796 err = -errno;
1760 perror("failed to open file"); 1797 perror("failed to open file");
1761 return -1; 1798 goto out_delete;
1762 } 1799 }
1763 1800
1764 err = fstat(input, &perf_stat); 1801 err = fstat(input, &perf_stat);
1765 if (err < 0) { 1802 if (err < 0) {
1766 perror("failed to stat file"); 1803 perror("failed to stat file");
1767 return -1; 1804 goto out_delete;
1768 } 1805 }
1769 1806
1770 if (!perf_stat.st_size) { 1807 if (!perf_stat.st_size) {
1771 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1808 fprintf(stderr, "zero-sized file, nothing to do!\n");
1772 return 0; 1809 goto out_delete;
1773 } 1810 }
1774 1811
1775 scripting_ops = script_spec__lookup(generate_script_lang); 1812 scripting_ops = script_spec__lookup(generate_script_lang);
1776 if (!scripting_ops) { 1813 if (!scripting_ops) {
1777 fprintf(stderr, "invalid language specifier"); 1814 fprintf(stderr, "invalid language specifier");
1778 return -1; 1815 err = -ENOENT;
1816 goto out_delete;
1779 } 1817 }
1780 1818
1781 err = scripting_ops->generate_script(session->tevent.pevent, 1819 err = scripting_ops->generate_script(session->tevent.pevent,
1782 "perf-script"); 1820 "perf-script");
1783 goto out; 1821 goto out_delete;
1784 } 1822 }
1785 1823
1786 if (script_name) { 1824 if (script_name) {
1787 err = scripting_ops->start_script(script_name, argc, argv); 1825 err = scripting_ops->start_script(script_name, argc, argv);
1788 if (err) 1826 if (err)
1789 goto out; 1827 goto out_delete;
1790 pr_debug("perf script started with script %s\n\n", script_name); 1828 pr_debug("perf script started with script %s\n\n", script_name);
1829 script_started = true;
1791 } 1830 }
1792 1831
1793 1832
1794 err = perf_session__check_output_opt(session); 1833 err = perf_session__check_output_opt(session);
1795 if (err < 0) 1834 if (err < 0)
1796 goto out; 1835 goto out_delete;
1797 1836
1798 err = __cmd_script(&script); 1837 err = __cmd_script(&script);
1799 1838
1839 flush_scripting();
1840
1841out_delete:
1800 perf_session__delete(session); 1842 perf_session__delete(session);
1801 cleanup_scripting(); 1843
1844 if (script_started)
1845 cleanup_scripting();
1802out: 1846out:
1803 return err; 1847 return err;
1804} 1848}