aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2019-02-28 02:29:50 -0500
committerIngo Molnar <mingo@kernel.org>2019-02-28 02:29:50 -0500
commitc978b9460fe1d4a1e1effa0abd6bd69b18a098a8 (patch)
treeeecc4c6179dea191c55ac8ef50467573b29a0b06 /tools
parent0a1571243d3f150fa99c6f41f1b8e17a307a2b8b (diff)
parentde667cce7f4f96b6e22da8fd9c065b961f355080 (diff)
Merge tag 'perf-core-for-mingo-5.1-20190225' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: perf annotate: Wei Li: - Fix getting source line failure perf script: Andi Kleen: - Handle missing fields with -F +... perf data: Jiri Olsa: - Prep work to support per-cpu files in a directory. Intel PT: Adrian Hunter: - Improve thread_stack__no_call_return() - Hide x86 retpolines in thread stacks. - exported SQL viewer refactorings, new 'top calls' report.. Alexander Shishkin: - Copy parent's address filter offsets on clone - Fix address filters for vmas with non-zero offset. Applies to ARM's CoreSight as well. python scripts: Tony Jones: - Python3 support for several 'perf script' python scripts. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-annotate.c4
-rw-r--r--tools/perf/builtin-buildid-cache.c4
-rw-r--r--tools/perf/builtin-buildid-list.c8
-rw-r--r--tools/perf/builtin-c2c.c4
-rw-r--r--tools/perf/builtin-diff.c12
-rw-r--r--tools/perf/builtin-evlist.c4
-rw-r--r--tools/perf/builtin-inject.c10
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-kvm.c8
-rw-r--r--tools/perf/builtin-lock.c8
-rw-r--r--tools/perf/builtin-mem.c8
-rw-r--r--tools/perf/builtin-record.c11
-rw-r--r--tools/perf/builtin-report.c6
-rw-r--r--tools/perf/builtin-sched.c16
-rw-r--r--tools/perf/builtin-script.c22
-rw-r--r--tools/perf/builtin-stat.c6
-rw-r--r--tools/perf/builtin-timechart.c8
-rw-r--r--tools/perf/builtin-trace.c8
-rwxr-xr-xtools/perf/scripts/python/exported-sql-viewer.py510
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py21
-rw-r--r--tools/perf/scripts/python/mem-phys-addr.py24
-rwxr-xr-xtools/perf/scripts/python/net_dropmonitor.py10
-rw-r--r--tools/perf/scripts/python/netdev-times.py82
-rw-r--r--tools/perf/scripts/python/powerpc-hcalls.py18
-rw-r--r--tools/perf/scripts/python/sctop.py24
-rwxr-xr-xtools/perf/scripts/python/stackcollapse.py7
-rw-r--r--tools/perf/scripts/python/stat-cpi.py10
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py22
-rw-r--r--tools/perf/scripts/python/syscall-counts.py18
-rw-r--r--tools/perf/util/annotate.c4
-rw-r--r--tools/perf/util/data-convert-bt.c4
-rw-r--r--tools/perf/util/data.c175
-rw-r--r--tools/perf/util/data.h16
-rw-r--r--tools/perf/util/header.c12
-rw-r--r--tools/perf/util/thread-stack.c161
-rw-r--r--tools/perf/util/util.c65
-rw-r--r--tools/perf/util/util.h3
37 files changed, 945 insertions, 390 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7f3c3fea67b4..67f9d9ffacfb 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -441,7 +441,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
441 } 441 }
442 442
443 if (total_nr_samples == 0) { 443 if (total_nr_samples == 0) {
444 ui__error("The %s file has no samples!\n", session->data->file.path); 444 ui__error("The %s data has no samples!\n", session->data->path);
445 goto out; 445 goto out;
446 } 446 }
447 447
@@ -578,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)
578 if (quiet) 578 if (quiet)
579 perf_quiet_option(); 579 perf_quiet_option();
580 580
581 data.file.path = input_name; 581 data.path = input_name;
582 582
583 annotate.session = perf_session__new(&data, false, &annotate.tool); 583 annotate.session = perf_session__new(&data, false, &annotate.tool);
584 if (annotate.session == NULL) 584 if (annotate.session == NULL)
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 115110a4796a..10457b10e568 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -416,8 +416,8 @@ int cmd_buildid_cache(int argc, const char **argv)
416 nsi = nsinfo__new(ns_id); 416 nsi = nsinfo__new(ns_id);
417 417
418 if (missing_filename) { 418 if (missing_filename) {
419 data.file.path = missing_filename; 419 data.path = missing_filename;
420 data.force = force; 420 data.force = force;
421 421
422 session = perf_session__new(&data, false, NULL); 422 session = perf_session__new(&data, false, NULL);
423 if (session == NULL) 423 if (session == NULL)
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 78abbe8d9d5f..f403e19488b5 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -52,11 +52,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
52{ 52{
53 struct perf_session *session; 53 struct perf_session *session;
54 struct perf_data data = { 54 struct perf_data data = {
55 .file = { 55 .path = input_name,
56 .path = input_name, 56 .mode = PERF_DATA_MODE_READ,
57 }, 57 .force = force,
58 .mode = PERF_DATA_MODE_READ,
59 .force = force,
60 }; 58 };
61 59
62 symbol__elf_init(); 60 symbol__elf_init();
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index efaaab23c6fd..4272763a5e96 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -2750,8 +2750,8 @@ static int perf_c2c__report(int argc, const char **argv)
2750 if (!input_name || !strlen(input_name)) 2750 if (!input_name || !strlen(input_name))
2751 input_name = "perf.data"; 2751 input_name = "perf.data";
2752 2752
2753 data.file.path = input_name; 2753 data.path = input_name;
2754 data.force = symbol_conf.force; 2754 data.force = symbol_conf.force;
2755 2755
2756 err = setup_display(display); 2756 err = setup_display(display);
2757 if (err) 2757 if (err)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 751e1971456b..58fe0e88215c 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -708,7 +708,7 @@ static void data__fprintf(void)
708 708
709 data__for_each_file(i, d) 709 data__for_each_file(i, d)
710 fprintf(stdout, "# [%d] %s %s\n", 710 fprintf(stdout, "# [%d] %s %s\n",
711 d->idx, d->data.file.path, 711 d->idx, d->data.path,
712 !d->idx ? "(Baseline)" : ""); 712 !d->idx ? "(Baseline)" : "");
713 713
714 fprintf(stdout, "#\n"); 714 fprintf(stdout, "#\n");
@@ -779,14 +779,14 @@ static int __cmd_diff(void)
779 data__for_each_file(i, d) { 779 data__for_each_file(i, d) {
780 d->session = perf_session__new(&d->data, false, &tool); 780 d->session = perf_session__new(&d->data, false, &tool);
781 if (!d->session) { 781 if (!d->session) {
782 pr_err("Failed to open %s\n", d->data.file.path); 782 pr_err("Failed to open %s\n", d->data.path);
783 ret = -1; 783 ret = -1;
784 goto out_delete; 784 goto out_delete;
785 } 785 }
786 786
787 ret = perf_session__process_events(d->session); 787 ret = perf_session__process_events(d->session);
788 if (ret) { 788 if (ret) {
789 pr_err("Failed to process %s\n", d->data.file.path); 789 pr_err("Failed to process %s\n", d->data.path);
790 goto out_delete; 790 goto out_delete;
791 } 791 }
792 792
@@ -1289,9 +1289,9 @@ static int data_init(int argc, const char **argv)
1289 data__for_each_file(i, d) { 1289 data__for_each_file(i, d) {
1290 struct perf_data *data = &d->data; 1290 struct perf_data *data = &d->data;
1291 1291
1292 data->file.path = use_default ? defaults[i] : argv[i]; 1292 data->path = use_default ? defaults[i] : argv[i];
1293 data->mode = PERF_DATA_MODE_READ, 1293 data->mode = PERF_DATA_MODE_READ,
1294 data->force = force, 1294 data->force = force,
1295 1295
1296 d->idx = i; 1296 d->idx = i;
1297 } 1297 }
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index e06e822ce634..6e4f63b0da4a 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -23,9 +23,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
23 struct perf_session *session; 23 struct perf_session *session;
24 struct perf_evsel *pos; 24 struct perf_evsel *pos;
25 struct perf_data data = { 25 struct perf_data data = {
26 .file = { 26 .path = file_name,
27 .path = file_name,
28 },
29 .mode = PERF_DATA_MODE_READ, 27 .mode = PERF_DATA_MODE_READ,
30 .force = details->force, 28 .force = details->force,
31 }; 29 };
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9bb1f35d5cb7..24086b7f1b14 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -770,10 +770,8 @@ int cmd_inject(int argc, const char **argv)
770 .input_name = "-", 770 .input_name = "-",
771 .samples = LIST_HEAD_INIT(inject.samples), 771 .samples = LIST_HEAD_INIT(inject.samples),
772 .output = { 772 .output = {
773 .file = { 773 .path = "-",
774 .path = "-", 774 .mode = PERF_DATA_MODE_WRITE,
775 },
776 .mode = PERF_DATA_MODE_WRITE,
777 }, 775 },
778 }; 776 };
779 struct perf_data data = { 777 struct perf_data data = {
@@ -786,7 +784,7 @@ int cmd_inject(int argc, const char **argv)
786 "Inject build-ids into the output stream"), 784 "Inject build-ids into the output stream"),
787 OPT_STRING('i', "input", &inject.input_name, "file", 785 OPT_STRING('i', "input", &inject.input_name, "file",
788 "input file name"), 786 "input file name"),
789 OPT_STRING('o', "output", &inject.output.file.path, "file", 787 OPT_STRING('o', "output", &inject.output.path, "file",
790 "output file name"), 788 "output file name"),
791 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, 789 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
792 "Merge sched-stat and sched-switch for getting events " 790 "Merge sched-stat and sched-switch for getting events "
@@ -834,7 +832,7 @@ int cmd_inject(int argc, const char **argv)
834 832
835 inject.tool.ordered_events = inject.sched_stat; 833 inject.tool.ordered_events = inject.sched_stat;
836 834
837 data.file.path = inject.input_name; 835 data.path = inject.input_name;
838 inject.session = perf_session__new(&data, true, &inject.tool); 836 inject.session = perf_session__new(&data, true, &inject.tool);
839 if (inject.session == NULL) 837 if (inject.session == NULL)
840 return -1; 838 return -1;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index b80ec0883537..fa520f4b8095 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1949,7 +1949,7 @@ int cmd_kmem(int argc, const char **argv)
1949 return __cmd_record(argc, argv); 1949 return __cmd_record(argc, argv);
1950 } 1950 }
1951 1951
1952 data.file.path = input_name; 1952 data.path = input_name;
1953 1953
1954 kmem_session = session = perf_session__new(&data, false, &perf_kmem); 1954 kmem_session = session = perf_session__new(&data, false, &perf_kmem);
1955 if (session == NULL) 1955 if (session == NULL)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 3d4cbc4e87c7..dbb6f737a3e2 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1080,11 +1080,9 @@ static int read_events(struct perf_kvm_stat *kvm)
1080 .ordered_events = true, 1080 .ordered_events = true,
1081 }; 1081 };
1082 struct perf_data file = { 1082 struct perf_data file = {
1083 .file = { 1083 .path = kvm->file_name,
1084 .path = kvm->file_name, 1084 .mode = PERF_DATA_MODE_READ,
1085 }, 1085 .force = kvm->force,
1086 .mode = PERF_DATA_MODE_READ,
1087 .force = kvm->force,
1088 }; 1086 };
1089 1087
1090 kvm->tool = eops; 1088 kvm->tool = eops;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6e0189df2b3b..b9810a8d350a 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -866,11 +866,9 @@ static int __cmd_report(bool display_info)
866 .ordered_events = true, 866 .ordered_events = true,
867 }; 867 };
868 struct perf_data data = { 868 struct perf_data data = {
869 .file = { 869 .path = input_name,
870 .path = input_name, 870 .mode = PERF_DATA_MODE_READ,
871 }, 871 .force = force,
872 .mode = PERF_DATA_MODE_READ,
873 .force = force,
874 }; 872 };
875 873
876 session = perf_session__new(&data, false, &eops); 874 session = perf_session__new(&data, false, &eops);
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index ba7e8d87dec3..f45c8b502f63 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -239,11 +239,9 @@ static int process_sample_event(struct perf_tool *tool,
239static int report_raw_events(struct perf_mem *mem) 239static int report_raw_events(struct perf_mem *mem)
240{ 240{
241 struct perf_data data = { 241 struct perf_data data = {
242 .file = { 242 .path = input_name,
243 .path = input_name, 243 .mode = PERF_DATA_MODE_READ,
244 }, 244 .force = mem->force,
245 .mode = PERF_DATA_MODE_READ,
246 .force = mem->force,
247 }; 245 };
248 int ret; 246 int ret;
249 struct perf_session *session = perf_session__new(&data, false, 247 struct perf_session *session = perf_session__new(&data, false,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6c3719ac901d..f3f7f3100336 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -660,10 +660,9 @@ static int process_sample_event(struct perf_tool *tool,
660 660
661static int process_buildids(struct record *rec) 661static int process_buildids(struct record *rec)
662{ 662{
663 struct perf_data *data = &rec->data;
664 struct perf_session *session = rec->session; 663 struct perf_session *session = rec->session;
665 664
666 if (data->size == 0) 665 if (perf_data__size(&rec->data) == 0)
667 return 0; 666 return 0;
668 667
669 /* 668 /*
@@ -851,7 +850,7 @@ record__finish_output(struct record *rec)
851 return; 850 return;
852 851
853 rec->session->header.data_size += rec->bytes_written; 852 rec->session->header.data_size += rec->bytes_written;
854 data->size = lseek(perf_data__fd(data), 0, SEEK_CUR); 853 data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
855 854
856 if (!rec->no_buildid) { 855 if (!rec->no_buildid) {
857 process_buildids(rec); 856 process_buildids(rec);
@@ -919,7 +918,7 @@ record__switch_output(struct record *rec, bool at_exit)
919 918
920 if (!quiet) 919 if (!quiet)
921 fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 920 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
922 data->file.path, timestamp); 921 data->path, timestamp);
923 922
924 /* Output tracking events */ 923 /* Output tracking events */
925 if (!at_exit) { 924 if (!at_exit) {
@@ -1462,7 +1461,7 @@ out_child:
1462 1461
1463 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 1462 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
1464 perf_data__size(data) / 1024.0 / 1024.0, 1463 perf_data__size(data) / 1024.0 / 1024.0,
1465 data->file.path, postfix, samples); 1464 data->path, postfix, samples);
1466 } 1465 }
1467 1466
1468out_delete_session: 1467out_delete_session:
@@ -1863,7 +1862,7 @@ static struct option __record_options[] = {
1863 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1862 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1864 "list of cpus to monitor"), 1863 "list of cpus to monitor"),
1865 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1864 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1866 OPT_STRING('o', "output", &record.data.file.path, "file", 1865 OPT_STRING('o', "output", &record.data.path, "file",
1867 "output file name"), 1866 "output file name"),
1868 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 1867 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
1869 &record.opts.no_inherit_set, 1868 &record.opts.no_inherit_set,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2e8c74d6430c..1532ebde6c4b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -899,7 +899,7 @@ static int __cmd_report(struct report *rep)
899 rep->nr_entries += evsel__hists(pos)->nr_entries; 899 rep->nr_entries += evsel__hists(pos)->nr_entries;
900 900
901 if (rep->nr_entries == 0) { 901 if (rep->nr_entries == 0) {
902 ui__error("The %s file has no samples!\n", data->file.path); 902 ui__error("The %s data has no samples!\n", data->path);
903 return 0; 903 return 0;
904 } 904 }
905 905
@@ -1207,8 +1207,8 @@ int cmd_report(int argc, const char **argv)
1207 input_name = "perf.data"; 1207 input_name = "perf.data";
1208 } 1208 }
1209 1209
1210 data.file.path = input_name; 1210 data.path = input_name;
1211 data.force = symbol_conf.force; 1211 data.force = symbol_conf.force;
1212 1212
1213repeat: 1213repeat:
1214 session = perf_session__new(&data, false, &report.tool); 1214 session = perf_session__new(&data, false, &report.tool);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 640558e9352e..275f2d92a7bf 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1785,11 +1785,9 @@ static int perf_sched__read_events(struct perf_sched *sched)
1785 }; 1785 };
1786 struct perf_session *session; 1786 struct perf_session *session;
1787 struct perf_data data = { 1787 struct perf_data data = {
1788 .file = { 1788 .path = input_name,
1789 .path = input_name, 1789 .mode = PERF_DATA_MODE_READ,
1790 }, 1790 .force = sched->force,
1791 .mode = PERF_DATA_MODE_READ,
1792 .force = sched->force,
1793 }; 1791 };
1794 int rc = -1; 1792 int rc = -1;
1795 1793
@@ -2958,11 +2956,9 @@ static int perf_sched__timehist(struct perf_sched *sched)
2958 { "sched:sched_migrate_task", timehist_migrate_task_event, }, 2956 { "sched:sched_migrate_task", timehist_migrate_task_event, },
2959 }; 2957 };
2960 struct perf_data data = { 2958 struct perf_data data = {
2961 .file = { 2959 .path = input_name,
2962 .path = input_name, 2960 .mode = PERF_DATA_MODE_READ,
2963 }, 2961 .force = sched->force,
2964 .mode = PERF_DATA_MODE_READ,
2965 .force = sched->force,
2966 }; 2962 };
2967 2963
2968 struct perf_session *session; 2964 struct perf_session *session;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 373ea151dc60..2d8cb1d1682c 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -149,6 +149,7 @@ static struct {
149 unsigned int print_ip_opts; 149 unsigned int print_ip_opts;
150 u64 fields; 150 u64 fields;
151 u64 invalid_fields; 151 u64 invalid_fields;
152 u64 user_set_fields;
152} output[OUTPUT_TYPE_MAX] = { 153} output[OUTPUT_TYPE_MAX] = {
153 154
154 [PERF_TYPE_HARDWARE] = { 155 [PERF_TYPE_HARDWARE] = {
@@ -345,7 +346,7 @@ static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
345 if (attr->sample_type & sample_type) 346 if (attr->sample_type & sample_type)
346 return 0; 347 return 0;
347 348
348 if (output[type].user_set) { 349 if (output[type].user_set_fields & field) {
349 if (allow_user_set) 350 if (allow_user_set)
350 return 0; 351 return 0;
351 evname = perf_evsel__name(evsel); 352 evname = perf_evsel__name(evsel);
@@ -2632,10 +2633,13 @@ parse:
2632 pr_warning("\'%s\' not valid for %s events. Ignoring.\n", 2633 pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
2633 all_output_options[i].str, event_type(j)); 2634 all_output_options[i].str, event_type(j));
2634 } else { 2635 } else {
2635 if (change == REMOVE) 2636 if (change == REMOVE) {
2636 output[j].fields &= ~all_output_options[i].field; 2637 output[j].fields &= ~all_output_options[i].field;
2637 else 2638 output[j].user_set_fields &= ~all_output_options[i].field;
2639 } else {
2638 output[j].fields |= all_output_options[i].field; 2640 output[j].fields |= all_output_options[i].field;
2641 output[j].user_set_fields |= all_output_options[i].field;
2642 }
2639 output[j].user_set = true; 2643 output[j].user_set = true;
2640 output[j].wildcard_set = true; 2644 output[j].wildcard_set = true;
2641 } 2645 }
@@ -2951,10 +2955,8 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
2951 DIR *scripts_dir, *lang_dir; 2955 DIR *scripts_dir, *lang_dir;
2952 struct perf_session *session; 2956 struct perf_session *session;
2953 struct perf_data data = { 2957 struct perf_data data = {
2954 .file = { 2958 .path = input_name,
2955 .path = input_name, 2959 .mode = PERF_DATA_MODE_READ,
2956 },
2957 .mode = PERF_DATA_MODE_READ,
2958 }; 2960 };
2959 char *temp; 2961 char *temp;
2960 int i = 0; 2962 int i = 0;
@@ -3427,8 +3429,8 @@ int cmd_script(int argc, const char **argv)
3427 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, 3429 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
3428 PARSE_OPT_STOP_AT_NON_OPTION); 3430 PARSE_OPT_STOP_AT_NON_OPTION);
3429 3431
3430 data.file.path = input_name; 3432 data.path = input_name;
3431 data.force = symbol_conf.force; 3433 data.force = symbol_conf.force;
3432 3434
3433 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 3435 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
3434 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 3436 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
@@ -3654,7 +3656,7 @@ int cmd_script(int argc, const char **argv)
3654 goto out_delete; 3656 goto out_delete;
3655 } 3657 }
3656 3658
3657 input = open(data.file.path, O_RDONLY); /* input_name */ 3659 input = open(data.path, O_RDONLY); /* input_name */
3658 if (input < 0) { 3660 if (input < 0) {
3659 err = -errno; 3661 err = -errno;
3660 perror("failed to open file"); 3662 perror("failed to open file");
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index bb24f9c17f9a..7b8f09b0b8bf 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1322,7 +1322,7 @@ static int __cmd_record(int argc, const char **argv)
1322 PARSE_OPT_STOP_AT_NON_OPTION); 1322 PARSE_OPT_STOP_AT_NON_OPTION);
1323 1323
1324 if (output_name) 1324 if (output_name)
1325 data->file.path = output_name; 1325 data->path = output_name;
1326 1326
1327 if (stat_config.run_count != 1 || forever) { 1327 if (stat_config.run_count != 1 || forever) {
1328 pr_err("Cannot use -r option with perf stat record.\n"); 1328 pr_err("Cannot use -r option with perf stat record.\n");
@@ -1523,8 +1523,8 @@ static int __cmd_report(int argc, const char **argv)
1523 input_name = "perf.data"; 1523 input_name = "perf.data";
1524 } 1524 }
1525 1525
1526 perf_stat.data.file.path = input_name; 1526 perf_stat.data.path = input_name;
1527 perf_stat.data.mode = PERF_DATA_MODE_READ; 1527 perf_stat.data.mode = PERF_DATA_MODE_READ;
1528 1528
1529 session = perf_session__new(&perf_stat.data, false, &perf_stat.tool); 1529 session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
1530 if (session == NULL) 1530 if (session == NULL)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 775b99833e51..9b98687a27b9 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1602,11 +1602,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1602 { "syscalls:sys_exit_select", process_exit_poll }, 1602 { "syscalls:sys_exit_select", process_exit_poll },
1603 }; 1603 };
1604 struct perf_data data = { 1604 struct perf_data data = {
1605 .file = { 1605 .path = input_name,
1606 .path = input_name, 1606 .mode = PERF_DATA_MODE_READ,
1607 }, 1607 .force = tchart->force,
1608 .mode = PERF_DATA_MODE_READ,
1609 .force = tchart->force,
1610 }; 1608 };
1611 1609
1612 struct perf_session *session = perf_session__new(&data, false, 1610 struct perf_session *session = perf_session__new(&data, false,
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 1a11fe656afc..f5b3a1e9c1dd 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -3154,11 +3154,9 @@ static int trace__replay(struct trace *trace)
3154 { "probe:vfs_getname", trace__vfs_getname, }, 3154 { "probe:vfs_getname", trace__vfs_getname, },
3155 }; 3155 };
3156 struct perf_data data = { 3156 struct perf_data data = {
3157 .file = { 3157 .path = input_name,
3158 .path = input_name, 3158 .mode = PERF_DATA_MODE_READ,
3159 }, 3159 .force = trace->force,
3160 .mode = PERF_DATA_MODE_READ,
3161 .force = trace->force,
3162 }; 3160 };
3163 struct perf_session *session; 3161 struct perf_session *session;
3164 struct perf_evsel *evsel; 3162 struct perf_evsel *evsel;
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py
index c3091401df91..09ce73b07d35 100755
--- a/tools/perf/scripts/python/exported-sql-viewer.py
+++ b/tools/perf/scripts/python/exported-sql-viewer.py
@@ -1,3 +1,4 @@
1#!/usr/bin/env python2
1# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
2# exported-sql-viewer.py: view data from sql database 3# exported-sql-viewer.py: view data from sql database
3# Copyright (c) 2014-2018, Intel Corporation. 4# Copyright (c) 2014-2018, Intel Corporation.
@@ -1397,18 +1398,28 @@ class BranchModel(TreeModel):
1397 def HasMoreRecords(self): 1398 def HasMoreRecords(self):
1398 return self.more 1399 return self.more
1399 1400
1401# Report Variables
1402
1403class ReportVars():
1404
1405 def __init__(self, name = "", where_clause = "", limit = ""):
1406 self.name = name
1407 self.where_clause = where_clause
1408 self.limit = limit
1409
1410 def UniqueId(self):
1411 return str(self.where_clause + ";" + self.limit)
1412
1400# Branch window 1413# Branch window
1401 1414
1402class BranchWindow(QMdiSubWindow): 1415class BranchWindow(QMdiSubWindow):
1403 1416
1404 def __init__(self, glb, event_id, name, where_clause, parent=None): 1417 def __init__(self, glb, event_id, report_vars, parent=None):
1405 super(BranchWindow, self).__init__(parent) 1418 super(BranchWindow, self).__init__(parent)
1406 1419
1407 model_name = "Branch Events " + str(event_id) 1420 model_name = "Branch Events " + str(event_id) + " " + report_vars.UniqueId()
1408 if len(where_clause):
1409 model_name = where_clause + " " + model_name
1410 1421
1411 self.model = LookupCreateModel(model_name, lambda: BranchModel(glb, event_id, where_clause)) 1422 self.model = LookupCreateModel(model_name, lambda: BranchModel(glb, event_id, report_vars.where_clause))
1412 1423
1413 self.view = QTreeView() 1424 self.view = QTreeView()
1414 self.view.setUniformRowHeights(True) 1425 self.view.setUniformRowHeights(True)
@@ -1426,7 +1437,7 @@ class BranchWindow(QMdiSubWindow):
1426 1437
1427 self.setWidget(self.vbox.Widget()) 1438 self.setWidget(self.vbox.Widget())
1428 1439
1429 AddSubWindow(glb.mainwindow.mdi_area, self, name + " Branch Events") 1440 AddSubWindow(glb.mainwindow.mdi_area, self, report_vars.name + " Branch Events")
1430 1441
1431 def ResizeColumnToContents(self, column, n): 1442 def ResizeColumnToContents(self, column, n):
1432 # Using the view's resizeColumnToContents() here is extrememly slow 1443 # Using the view's resizeColumnToContents() here is extrememly slow
@@ -1471,47 +1482,134 @@ class BranchWindow(QMdiSubWindow):
1471 else: 1482 else:
1472 self.find_bar.NotFound() 1483 self.find_bar.NotFound()
1473 1484
1474# Dialog data item converted and validated using a SQL table 1485# Line edit data item
1475 1486
1476class SQLTableDialogDataItem(): 1487class LineEditDataItem(object):
1477 1488
1478 def __init__(self, glb, label, placeholder_text, table_name, match_column, column_name1, column_name2, parent): 1489 def __init__(self, glb, label, placeholder_text, parent, id = "", default = ""):
1479 self.glb = glb 1490 self.glb = glb
1480 self.label = label 1491 self.label = label
1481 self.placeholder_text = placeholder_text 1492 self.placeholder_text = placeholder_text
1482 self.table_name = table_name
1483 self.match_column = match_column
1484 self.column_name1 = column_name1
1485 self.column_name2 = column_name2
1486 self.parent = parent 1493 self.parent = parent
1494 self.id = id
1487 1495
1488 self.value = "" 1496 self.value = default
1489 1497
1490 self.widget = QLineEdit() 1498 self.widget = QLineEdit(default)
1491 self.widget.editingFinished.connect(self.Validate) 1499 self.widget.editingFinished.connect(self.Validate)
1492 self.widget.textChanged.connect(self.Invalidate) 1500 self.widget.textChanged.connect(self.Invalidate)
1493 self.red = False 1501 self.red = False
1494 self.error = "" 1502 self.error = ""
1495 self.validated = True 1503 self.validated = True
1496 1504
1497 self.last_id = 0
1498 self.first_time = 0
1499 self.last_time = 2 ** 64
1500 if self.table_name == "<timeranges>":
1501 query = QSqlQuery(self.glb.db)
1502 QueryExec(query, "SELECT id, time FROM samples ORDER BY id DESC LIMIT 1")
1503 if query.next():
1504 self.last_id = int(query.value(0))
1505 self.last_time = int(query.value(1))
1506 QueryExec(query, "SELECT time FROM samples WHERE time != 0 ORDER BY id LIMIT 1")
1507 if query.next():
1508 self.first_time = int(query.value(0))
1509 if placeholder_text:
1510 placeholder_text += ", between " + str(self.first_time) + " and " + str(self.last_time)
1511
1512 if placeholder_text: 1505 if placeholder_text:
1513 self.widget.setPlaceholderText(placeholder_text) 1506 self.widget.setPlaceholderText(placeholder_text)
1514 1507
1508 def TurnTextRed(self):
1509 if not self.red:
1510 palette = QPalette()
1511 palette.setColor(QPalette.Text,Qt.red)
1512 self.widget.setPalette(palette)
1513 self.red = True
1514
1515 def TurnTextNormal(self):
1516 if self.red:
1517 palette = QPalette()
1518 self.widget.setPalette(palette)
1519 self.red = False
1520
1521 def InvalidValue(self, value):
1522 self.value = ""
1523 self.TurnTextRed()
1524 self.error = self.label + " invalid value '" + value + "'"
1525 self.parent.ShowMessage(self.error)
1526
1527 def Invalidate(self):
1528 self.validated = False
1529
1530 def DoValidate(self, input_string):
1531 self.value = input_string.strip()
1532
1533 def Validate(self):
1534 self.validated = True
1535 self.error = ""
1536 self.TurnTextNormal()
1537 self.parent.ClearMessage()
1538 input_string = self.widget.text()
1539 if not len(input_string.strip()):
1540 self.value = ""
1541 return
1542 self.DoValidate(input_string)
1543
1544 def IsValid(self):
1545 if not self.validated:
1546 self.Validate()
1547 if len(self.error):
1548 self.parent.ShowMessage(self.error)
1549 return False
1550 return True
1551
1552 def IsNumber(self, value):
1553 try:
1554 x = int(value)
1555 except:
1556 x = 0
1557 return str(x) == value
1558
1559# Non-negative integer ranges dialog data item
1560
1561class NonNegativeIntegerRangesDataItem(LineEditDataItem):
1562
1563 def __init__(self, glb, label, placeholder_text, column_name, parent):
1564 super(NonNegativeIntegerRangesDataItem, self).__init__(glb, label, placeholder_text, parent)
1565
1566 self.column_name = column_name
1567
1568 def DoValidate(self, input_string):
1569 singles = []
1570 ranges = []
1571 for value in [x.strip() for x in input_string.split(",")]:
1572 if "-" in value:
1573 vrange = value.split("-")
1574 if len(vrange) != 2 or not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1575 return self.InvalidValue(value)
1576 ranges.append(vrange)
1577 else:
1578 if not self.IsNumber(value):
1579 return self.InvalidValue(value)
1580 singles.append(value)
1581 ranges = [("(" + self.column_name + " >= " + r[0] + " AND " + self.column_name + " <= " + r[1] + ")") for r in ranges]
1582 if len(singles):
1583 ranges.append(self.column_name + " IN (" + ",".join(singles) + ")")
1584 self.value = " OR ".join(ranges)
1585
1586# Positive integer dialog data item
1587
1588class PositiveIntegerDataItem(LineEditDataItem):
1589
1590 def __init__(self, glb, label, placeholder_text, parent, id = "", default = ""):
1591 super(PositiveIntegerDataItem, self).__init__(glb, label, placeholder_text, parent, id, default)
1592
1593 def DoValidate(self, input_string):
1594 if not self.IsNumber(input_string.strip()):
1595 return self.InvalidValue(input_string)
1596 value = int(input_string.strip())
1597 if value <= 0:
1598 return self.InvalidValue(input_string)
1599 self.value = str(value)
1600
1601# Dialog data item converted and validated using a SQL table
1602
1603class SQLTableDataItem(LineEditDataItem):
1604
1605 def __init__(self, glb, label, placeholder_text, table_name, match_column, column_name1, column_name2, parent):
1606 super(SQLTableDataItem, self).__init__(glb, label, placeholder_text, parent)
1607
1608 self.table_name = table_name
1609 self.match_column = match_column
1610 self.column_name1 = column_name1
1611 self.column_name2 = column_name2
1612
1515 def ValueToIds(self, value): 1613 def ValueToIds(self, value):
1516 ids = [] 1614 ids = []
1517 query = QSqlQuery(self.glb.db) 1615 query = QSqlQuery(self.glb.db)
@@ -1522,6 +1620,42 @@ class SQLTableDialogDataItem():
1522 ids.append(str(query.value(0))) 1620 ids.append(str(query.value(0)))
1523 return ids 1621 return ids
1524 1622
1623 def DoValidate(self, input_string):
1624 all_ids = []
1625 for value in [x.strip() for x in input_string.split(",")]:
1626 ids = self.ValueToIds(value)
1627 if len(ids):
1628 all_ids.extend(ids)
1629 else:
1630 return self.InvalidValue(value)
1631 self.value = self.column_name1 + " IN (" + ",".join(all_ids) + ")"
1632 if self.column_name2:
1633 self.value = "( " + self.value + " OR " + self.column_name2 + " IN (" + ",".join(all_ids) + ") )"
1634
1635# Sample time ranges dialog data item converted and validated using 'samples' SQL table
1636
1637class SampleTimeRangesDataItem(LineEditDataItem):
1638
1639 def __init__(self, glb, label, placeholder_text, column_name, parent):
1640 self.column_name = column_name
1641
1642 self.last_id = 0
1643 self.first_time = 0
1644 self.last_time = 2 ** 64
1645
1646 query = QSqlQuery(glb.db)
1647 QueryExec(query, "SELECT id, time FROM samples ORDER BY id DESC LIMIT 1")
1648 if query.next():
1649 self.last_id = int(query.value(0))
1650 self.last_time = int(query.value(1))
1651 QueryExec(query, "SELECT time FROM samples WHERE time != 0 ORDER BY id LIMIT 1")
1652 if query.next():
1653 self.first_time = int(query.value(0))
1654 if placeholder_text:
1655 placeholder_text += ", between " + str(self.first_time) + " and " + str(self.last_time)
1656
1657 super(SampleTimeRangesDataItem, self).__init__(glb, label, placeholder_text, parent)
1658
1525 def IdBetween(self, query, lower_id, higher_id, order): 1659 def IdBetween(self, query, lower_id, higher_id, order):
1526 QueryExec(query, "SELECT id FROM samples WHERE id > " + str(lower_id) + " AND id < " + str(higher_id) + " ORDER BY id " + order + " LIMIT 1") 1660 QueryExec(query, "SELECT id FROM samples WHERE id > " + str(lower_id) + " AND id < " + str(higher_id) + " ORDER BY id " + order + " LIMIT 1")
1527 if query.next(): 1661 if query.next():
@@ -1559,7 +1693,6 @@ class SQLTableDialogDataItem():
1559 return str(lower_id) 1693 return str(lower_id)
1560 1694
1561 def ConvertRelativeTime(self, val): 1695 def ConvertRelativeTime(self, val):
1562 print "val ", val
1563 mult = 1 1696 mult = 1
1564 suffix = val[-2:] 1697 suffix = val[-2:]
1565 if suffix == "ms": 1698 if suffix == "ms":
@@ -1581,29 +1714,23 @@ class SQLTableDialogDataItem():
1581 return str(val) 1714 return str(val)
1582 1715
1583 def ConvertTimeRange(self, vrange): 1716 def ConvertTimeRange(self, vrange):
1584 print "vrange ", vrange
1585 if vrange[0] == "": 1717 if vrange[0] == "":
1586 vrange[0] = str(self.first_time) 1718 vrange[0] = str(self.first_time)
1587 if vrange[1] == "": 1719 if vrange[1] == "":
1588 vrange[1] = str(self.last_time) 1720 vrange[1] = str(self.last_time)
1589 vrange[0] = self.ConvertRelativeTime(vrange[0]) 1721 vrange[0] = self.ConvertRelativeTime(vrange[0])
1590 vrange[1] = self.ConvertRelativeTime(vrange[1]) 1722 vrange[1] = self.ConvertRelativeTime(vrange[1])
1591 print "vrange2 ", vrange
1592 if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]): 1723 if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1593 return False 1724 return False
1594 print "ok1"
1595 beg_range = max(int(vrange[0]), self.first_time) 1725 beg_range = max(int(vrange[0]), self.first_time)
1596 end_range = min(int(vrange[1]), self.last_time) 1726 end_range = min(int(vrange[1]), self.last_time)
1597 if beg_range > self.last_time or end_range < self.first_time: 1727 if beg_range > self.last_time or end_range < self.first_time:
1598 return False 1728 return False
1599 print "ok2"
1600 vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True) 1729 vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True)
1601 vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False) 1730 vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False)
1602 print "vrange3 ", vrange
1603 return True 1731 return True
1604 1732
1605 def AddTimeRange(self, value, ranges): 1733 def AddTimeRange(self, value, ranges):
1606 print "value ", value
1607 n = value.count("-") 1734 n = value.count("-")
1608 if n == 1: 1735 if n == 1:
1609 pass 1736 pass
@@ -1621,111 +1748,31 @@ class SQLTableDialogDataItem():
1621 return True 1748 return True
1622 return False 1749 return False
1623 1750
1624 def InvalidValue(self, value): 1751 def DoValidate(self, input_string):
1625 self.value = "" 1752 ranges = []
1626 palette = QPalette() 1753 for value in [x.strip() for x in input_string.split(",")]:
1627 palette.setColor(QPalette.Text,Qt.red) 1754 if not self.AddTimeRange(value, ranges):
1628 self.widget.setPalette(palette) 1755 return self.InvalidValue(value)
1629 self.red = True 1756 ranges = [("(" + self.column_name + " >= " + r[0] + " AND " + self.column_name + " <= " + r[1] + ")") for r in ranges]
1630 self.error = self.label + " invalid value '" + value + "'" 1757 self.value = " OR ".join(ranges)
1631 self.parent.ShowMessage(self.error)
1632 1758
1633 def IsNumber(self, value): 1759# Report Dialog Base
1634 try:
1635 x = int(value)
1636 except:
1637 x = 0
1638 return str(x) == value
1639 1760
1640 def Invalidate(self): 1761class ReportDialogBase(QDialog):
1641 self.validated = False
1642 1762
1643 def Validate(self): 1763 def __init__(self, glb, title, items, partial, parent=None):
1644 input_string = self.widget.text() 1764 super(ReportDialogBase, self).__init__(parent)
1645 self.validated = True
1646 if self.red:
1647 palette = QPalette()
1648 self.widget.setPalette(palette)
1649 self.red = False
1650 if not len(input_string.strip()):
1651 self.error = ""
1652 self.value = ""
1653 return
1654 if self.table_name == "<timeranges>":
1655 ranges = []
1656 for value in [x.strip() for x in input_string.split(",")]:
1657 if not self.AddTimeRange(value, ranges):
1658 return self.InvalidValue(value)
1659 ranges = [("(" + self.column_name1 + " >= " + r[0] + " AND " + self.column_name1 + " <= " + r[1] + ")") for r in ranges]
1660 self.value = " OR ".join(ranges)
1661 elif self.table_name == "<ranges>":
1662 singles = []
1663 ranges = []
1664 for value in [x.strip() for x in input_string.split(",")]:
1665 if "-" in value:
1666 vrange = value.split("-")
1667 if len(vrange) != 2 or not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1668 return self.InvalidValue(value)
1669 ranges.append(vrange)
1670 else:
1671 if not self.IsNumber(value):
1672 return self.InvalidValue(value)
1673 singles.append(value)
1674 ranges = [("(" + self.column_name1 + " >= " + r[0] + " AND " + self.column_name1 + " <= " + r[1] + ")") for r in ranges]
1675 if len(singles):
1676 ranges.append(self.column_name1 + " IN (" + ",".join(singles) + ")")
1677 self.value = " OR ".join(ranges)
1678 elif self.table_name:
1679 all_ids = []
1680 for value in [x.strip() for x in input_string.split(",")]:
1681 ids = self.ValueToIds(value)
1682 if len(ids):
1683 all_ids.extend(ids)
1684 else:
1685 return self.InvalidValue(value)
1686 self.value = self.column_name1 + " IN (" + ",".join(all_ids) + ")"
1687 if self.column_name2:
1688 self.value = "( " + self.value + " OR " + self.column_name2 + " IN (" + ",".join(all_ids) + ") )"
1689 else:
1690 self.value = input_string.strip()
1691 self.error = ""
1692 self.parent.ClearMessage()
1693
1694 def IsValid(self):
1695 if not self.validated:
1696 self.Validate()
1697 if len(self.error):
1698 self.parent.ShowMessage(self.error)
1699 return False
1700 return True
1701
1702# Selected branch report creation dialog
1703
1704class SelectedBranchDialog(QDialog):
1705
1706 def __init__(self, glb, parent=None):
1707 super(SelectedBranchDialog, self).__init__(parent)
1708 1765
1709 self.glb = glb 1766 self.glb = glb
1710 1767
1711 self.name = "" 1768 self.report_vars = ReportVars()
1712 self.where_clause = ""
1713 1769
1714 self.setWindowTitle("Selected Branches") 1770 self.setWindowTitle(title)
1715 self.setMinimumWidth(600) 1771 self.setMinimumWidth(600)
1716 1772
1717 items = ( 1773 self.data_items = [x(glb, self) for x in items]
1718 ("Report name:", "Enter a name to appear in the window title bar", "", "", "", ""), 1774
1719 ("Time ranges:", "Enter time ranges", "<timeranges>", "", "samples.id", ""), 1775 self.partial = partial
1720 ("CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "<ranges>", "", "cpu", ""),
1721 ("Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", ""),
1722 ("PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", ""),
1723 ("TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", ""),
1724 ("DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id"),
1725 ("Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id"),
1726 ("Raw SQL clause: ", "Enter a raw SQL WHERE clause", "", "", "", ""),
1727 )
1728 self.data_items = [SQLTableDialogDataItem(glb, *x, parent=self) for x in items]
1729 1776
1730 self.grid = QGridLayout() 1777 self.grid = QGridLayout()
1731 1778
@@ -1757,23 +1804,28 @@ class SelectedBranchDialog(QDialog):
1757 self.setLayout(self.vbox); 1804 self.setLayout(self.vbox);
1758 1805
1759 def Ok(self): 1806 def Ok(self):
1760 self.name = self.data_items[0].value 1807 vars = self.report_vars
1761 if not self.name: 1808 for d in self.data_items:
1809 if d.id == "REPORTNAME":
1810 vars.name = d.value
1811 if not vars.name:
1762 self.ShowMessage("Report name is required") 1812 self.ShowMessage("Report name is required")
1763 return 1813 return
1764 for d in self.data_items: 1814 for d in self.data_items:
1765 if not d.IsValid(): 1815 if not d.IsValid():
1766 return 1816 return
1767 for d in self.data_items[1:]: 1817 for d in self.data_items[1:]:
1768 if len(d.value): 1818 if d.id == "LIMIT":
1769 if len(self.where_clause): 1819 vars.limit = d.value
1770 self.where_clause += " AND " 1820 elif len(d.value):
1771 self.where_clause += d.value 1821 if len(vars.where_clause):
1772 if len(self.where_clause): 1822 vars.where_clause += " AND "
1773 self.where_clause = " AND ( " + self.where_clause + " ) " 1823 vars.where_clause += d.value
1774 else: 1824 if len(vars.where_clause):
1775 self.ShowMessage("No selection") 1825 if self.partial:
1776 return 1826 vars.where_clause = " AND ( " + vars.where_clause + " ) "
1827 else:
1828 vars.where_clause = " WHERE " + vars.where_clause + " "
1777 self.accept() 1829 self.accept()
1778 1830
1779 def ShowMessage(self, msg): 1831 def ShowMessage(self, msg):
@@ -1782,6 +1834,23 @@ class SelectedBranchDialog(QDialog):
1782 def ClearMessage(self): 1834 def ClearMessage(self):
1783 self.status.setText("") 1835 self.status.setText("")
1784 1836
1837# Selected branch report creation dialog
1838
1839class SelectedBranchDialog(ReportDialogBase):
1840
1841 def __init__(self, glb, parent=None):
1842 title = "Selected Branches"
1843 items = (lambda g, p: LineEditDataItem(g, "Report name:", "Enter a name to appear in the window title bar", p, "REPORTNAME"),
1844 lambda g, p: SampleTimeRangesDataItem(g, "Time ranges:", "Enter time ranges", "samples.id", p),
1845 lambda g, p: NonNegativeIntegerRangesDataItem(g, "CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "cpu", p),
1846 lambda g, p: SQLTableDataItem(g, "Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", "", p),
1847 lambda g, p: SQLTableDataItem(g, "PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", "", p),
1848 lambda g, p: SQLTableDataItem(g, "TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", "", p),
1849 lambda g, p: SQLTableDataItem(g, "DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id", p),
1850 lambda g, p: SQLTableDataItem(g, "Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id", p),
1851 lambda g, p: LineEditDataItem(g, "Raw SQL clause: ", "Enter a raw SQL WHERE clause", p))
1852 super(SelectedBranchDialog, self).__init__(glb, title, items, True, parent)
1853
1785# Event list 1854# Event list
1786 1855
1787def GetEventList(db): 1856def GetEventList(db):
@@ -1792,6 +1861,16 @@ def GetEventList(db):
1792 events.append(query.value(0)) 1861 events.append(query.value(0))
1793 return events 1862 return events
1794 1863
1864# Is a table selectable
1865
1866def IsSelectable(db, table):
1867 query = QSqlQuery(db)
1868 try:
1869 QueryExec(query, "SELECT * FROM " + table + " LIMIT 1")
1870 except:
1871 return False
1872 return True
1873
1795# SQL data preparation 1874# SQL data preparation
1796 1875
1797def SQLTableDataPrep(query, count): 1876def SQLTableDataPrep(query, count):
@@ -1817,12 +1896,13 @@ class SQLTableModel(TableModel):
1817 1896
1818 progress = Signal(object) 1897 progress = Signal(object)
1819 1898
1820 def __init__(self, glb, sql, column_count, parent=None): 1899 def __init__(self, glb, sql, column_headers, parent=None):
1821 super(SQLTableModel, self).__init__(parent) 1900 super(SQLTableModel, self).__init__(parent)
1822 self.glb = glb 1901 self.glb = glb
1823 self.more = True 1902 self.more = True
1824 self.populated = 0 1903 self.populated = 0
1825 self.fetcher = SQLFetcher(glb, sql, lambda x, y=column_count: SQLTableDataPrep(x, y), self.AddSample) 1904 self.column_headers = column_headers
1905 self.fetcher = SQLFetcher(glb, sql, lambda x, y=len(column_headers): SQLTableDataPrep(x, y), self.AddSample)
1826 self.fetcher.done.connect(self.Update) 1906 self.fetcher.done.connect(self.Update)
1827 self.fetcher.Fetch(glb_chunk_sz) 1907 self.fetcher.Fetch(glb_chunk_sz)
1828 1908
@@ -1860,6 +1940,12 @@ class SQLTableModel(TableModel):
1860 def HasMoreRecords(self): 1940 def HasMoreRecords(self):
1861 return self.more 1941 return self.more
1862 1942
1943 def columnCount(self, parent=None):
1944 return len(self.column_headers)
1945
1946 def columnHeader(self, column):
1947 return self.column_headers[column]
1948
1863# SQL automatic table data model 1949# SQL automatic table data model
1864 1950
1865class SQLAutoTableModel(SQLTableModel): 1951class SQLAutoTableModel(SQLTableModel):
@@ -1869,12 +1955,12 @@ class SQLAutoTableModel(SQLTableModel):
1869 if table_name == "comm_threads_view": 1955 if table_name == "comm_threads_view":
1870 # For now, comm_threads_view has no id column 1956 # For now, comm_threads_view has no id column
1871 sql = "SELECT * FROM " + table_name + " WHERE comm_id > $$last_id$$ ORDER BY comm_id LIMIT " + str(glb_chunk_sz) 1957 sql = "SELECT * FROM " + table_name + " WHERE comm_id > $$last_id$$ ORDER BY comm_id LIMIT " + str(glb_chunk_sz)
1872 self.column_headers = [] 1958 column_headers = []
1873 query = QSqlQuery(glb.db) 1959 query = QSqlQuery(glb.db)
1874 if glb.dbref.is_sqlite3: 1960 if glb.dbref.is_sqlite3:
1875 QueryExec(query, "PRAGMA table_info(" + table_name + ")") 1961 QueryExec(query, "PRAGMA table_info(" + table_name + ")")
1876 while query.next(): 1962 while query.next():
1877 self.column_headers.append(query.value(1)) 1963 column_headers.append(query.value(1))
1878 if table_name == "sqlite_master": 1964 if table_name == "sqlite_master":
1879 sql = "SELECT * FROM " + table_name 1965 sql = "SELECT * FROM " + table_name
1880 else: 1966 else:
@@ -1887,14 +1973,8 @@ class SQLAutoTableModel(SQLTableModel):
1887 schema = "public" 1973 schema = "public"
1888 QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'") 1974 QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'")
1889 while query.next(): 1975 while query.next():
1890 self.column_headers.append(query.value(0)) 1976 column_headers.append(query.value(0))
1891 super(SQLAutoTableModel, self).__init__(glb, sql, len(self.column_headers), parent) 1977 super(SQLAutoTableModel, self).__init__(glb, sql, column_headers, parent)
1892
1893 def columnCount(self, parent=None):
1894 return len(self.column_headers)
1895
1896 def columnHeader(self, column):
1897 return self.column_headers[column]
1898 1978
1899# Base class for custom ResizeColumnsToContents 1979# Base class for custom ResizeColumnsToContents
1900 1980
@@ -1997,6 +2077,103 @@ def GetTableList(glb):
1997 tables.append("information_schema.columns") 2077 tables.append("information_schema.columns")
1998 return tables 2078 return tables
1999 2079
2080# Top Calls data model
2081
2082class TopCallsModel(SQLTableModel):
2083
2084 def __init__(self, glb, report_vars, parent=None):
2085 text = ""
2086 if not glb.dbref.is_sqlite3:
2087 text = "::text"
2088 limit = ""
2089 if len(report_vars.limit):
2090 limit = " LIMIT " + report_vars.limit
2091 sql = ("SELECT comm, pid, tid, name,"
2092 " CASE"
2093 " WHEN (short_name = '[kernel.kallsyms]') THEN '[kernel]'" + text +
2094 " ELSE short_name"
2095 " END AS dso,"
2096 " call_time, return_time, (return_time - call_time) AS elapsed_time, branch_count, "
2097 " CASE"
2098 " WHEN (calls.flags = 1) THEN 'no call'" + text +
2099 " WHEN (calls.flags = 2) THEN 'no return'" + text +
2100 " WHEN (calls.flags = 3) THEN 'no call/return'" + text +
2101 " ELSE ''" + text +
2102 " END AS flags"
2103 " FROM calls"
2104 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
2105 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
2106 " INNER JOIN dsos ON symbols.dso_id = dsos.id"
2107 " INNER JOIN comms ON calls.comm_id = comms.id"
2108 " INNER JOIN threads ON calls.thread_id = threads.id" +
2109 report_vars.where_clause +
2110 " ORDER BY elapsed_time DESC" +
2111 limit
2112 )
2113 column_headers = ("Command", "PID", "TID", "Symbol", "Object", "Call Time", "Return Time", "Elapsed Time (ns)", "Branch Count", "Flags")
2114 self.alignment = (Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignLeft)
2115 super(TopCallsModel, self).__init__(glb, sql, column_headers, parent)
2116
2117 def columnAlignment(self, column):
2118 return self.alignment[column]
2119
2120# Top Calls report creation dialog
2121
2122class TopCallsDialog(ReportDialogBase):
2123
2124 def __init__(self, glb, parent=None):
2125 title = "Top Calls by Elapsed Time"
2126 items = (lambda g, p: LineEditDataItem(g, "Report name:", "Enter a name to appear in the window title bar", p, "REPORTNAME"),
2127 lambda g, p: SQLTableDataItem(g, "Commands:", "Only calls with these commands will be included", "comms", "comm", "comm_id", "", p),
2128 lambda g, p: SQLTableDataItem(g, "PIDs:", "Only calls with these process IDs will be included", "threads", "pid", "thread_id", "", p),
2129 lambda g, p: SQLTableDataItem(g, "TIDs:", "Only calls with these thread IDs will be included", "threads", "tid", "thread_id", "", p),
2130 lambda g, p: SQLTableDataItem(g, "DSOs:", "Only calls with these DSOs will be included", "dsos", "short_name", "dso_id", "", p),
2131 lambda g, p: SQLTableDataItem(g, "Symbols:", "Only calls with these symbols will be included", "symbols", "name", "symbol_id", "", p),
2132 lambda g, p: LineEditDataItem(g, "Raw SQL clause: ", "Enter a raw SQL WHERE clause", p),
2133 lambda g, p: PositiveIntegerDataItem(g, "Record limit:", "Limit selection to this number of records", p, "LIMIT", "100"))
2134 super(TopCallsDialog, self).__init__(glb, title, items, False, parent)
2135
2136# Top Calls window
2137
2138class TopCallsWindow(QMdiSubWindow, ResizeColumnsToContentsBase):
2139
2140 def __init__(self, glb, report_vars, parent=None):
2141 super(TopCallsWindow, self).__init__(parent)
2142
2143 self.data_model = LookupCreateModel("Top Calls " + report_vars.UniqueId(), lambda: TopCallsModel(glb, report_vars))
2144 self.model = self.data_model
2145
2146 self.view = QTableView()
2147 self.view.setModel(self.model)
2148 self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
2149 self.view.verticalHeader().setVisible(False)
2150
2151 self.ResizeColumnsToContents()
2152
2153 self.find_bar = FindBar(self, self, True)
2154
2155 self.finder = ChildDataItemFinder(self.model)
2156
2157 self.fetch_bar = FetchMoreRecordsBar(self.data_model, self)
2158
2159 self.vbox = VBox(self.view, self.find_bar.Widget(), self.fetch_bar.Widget())
2160
2161 self.setWidget(self.vbox.Widget())
2162
2163 AddSubWindow(glb.mainwindow.mdi_area, self, report_vars.name)
2164
2165 def Find(self, value, direction, pattern, context):
2166 self.view.setFocus()
2167 self.find_bar.Busy()
2168 self.finder.Find(value, direction, pattern, context, self.FindDone)
2169
2170 def FindDone(self, row):
2171 self.find_bar.Idle()
2172 if row >= 0:
2173 self.view.setCurrentIndex(self.model.index(row, 0, QModelIndex()))
2174 else:
2175 self.find_bar.NotFound()
2176
2000# Action Definition 2177# Action Definition
2001 2178
2002def CreateAction(label, tip, callback, parent=None, shortcut=None): 2179def CreateAction(label, tip, callback, parent=None, shortcut=None):
@@ -2100,6 +2277,7 @@ p.c2 {
2100<p class=c2><a href=#callgraph>1.1 Context-Sensitive Call Graph</a></p> 2277<p class=c2><a href=#callgraph>1.1 Context-Sensitive Call Graph</a></p>
2101<p class=c2><a href=#allbranches>1.2 All branches</a></p> 2278<p class=c2><a href=#allbranches>1.2 All branches</a></p>
2102<p class=c2><a href=#selectedbranches>1.3 Selected branches</a></p> 2279<p class=c2><a href=#selectedbranches>1.3 Selected branches</a></p>
2280<p class=c2><a href=#topcallsbyelapsedtime>1.4 Top calls by elapsed time</a></p>
2103<p class=c1><a href=#tables>2. Tables</a></p> 2281<p class=c1><a href=#tables>2. Tables</a></p>
2104<h1 id=reports>1. Reports</h1> 2282<h1 id=reports>1. Reports</h1>
2105<h2 id=callgraph>1.1 Context-Sensitive Call Graph</h2> 2283<h2 id=callgraph>1.1 Context-Sensitive Call Graph</h2>
@@ -2175,6 +2353,10 @@ ms, us or ns. Also, negative values are relative to the end of trace. Examples:
2175 -10ms- The last 10ms 2353 -10ms- The last 10ms
2176</pre> 2354</pre>
2177N.B. Due to the granularity of timestamps, there could be no branches in any given time range. 2355N.B. Due to the granularity of timestamps, there could be no branches in any given time range.
2356<h2 id=topcallsbyelapsedtime>1.4 Top calls by elapsed time</h2>
2357The Top calls by elapsed time report displays calls in descending order of time elapsed between when the function was called and when it returned.
2358The data is reduced by various selection criteria. A dialog box displays available criteria which are AND'ed together.
2359If not all data is fetched, a Fetch bar is provided. Ctrl-F displays a Find bar.
2178<h1 id=tables>2. Tables</h1> 2360<h1 id=tables>2. Tables</h1>
2179The Tables menu shows all tables and views in the database. Most tables have an associated view 2361The Tables menu shows all tables and views in the database. Most tables have an associated view
2180which displays the information in a more friendly way. Not all data for large tables is fetched 2362which displays the information in a more friendly way. Not all data for large tables is fetched
@@ -2304,10 +2486,14 @@ class MainWindow(QMainWindow):
2304 edit_menu.addAction(CreateAction("&Enlarge Font", "Make text bigger", self.EnlargeFont, self, [QKeySequence("Ctrl++")])) 2486 edit_menu.addAction(CreateAction("&Enlarge Font", "Make text bigger", self.EnlargeFont, self, [QKeySequence("Ctrl++")]))
2305 2487
2306 reports_menu = menu.addMenu("&Reports") 2488 reports_menu = menu.addMenu("&Reports")
2307 reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self)) 2489 if IsSelectable(glb.db, "calls"):
2490 reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self))
2308 2491
2309 self.EventMenu(GetEventList(glb.db), reports_menu) 2492 self.EventMenu(GetEventList(glb.db), reports_menu)
2310 2493
2494 if IsSelectable(glb.db, "calls"):
2495 reports_menu.addAction(CreateAction("&Top calls by elapsed time", "Create a new window displaying top calls by elapsed time", self.NewTopCalls, self))
2496
2311 self.TableMenu(GetTableList(glb), menu) 2497 self.TableMenu(GetTableList(glb), menu)
2312 2498
2313 self.window_menu = WindowMenu(self.mdi_area, menu) 2499 self.window_menu = WindowMenu(self.mdi_area, menu)
@@ -2363,14 +2549,20 @@ class MainWindow(QMainWindow):
2363 def NewCallGraph(self): 2549 def NewCallGraph(self):
2364 CallGraphWindow(self.glb, self) 2550 CallGraphWindow(self.glb, self)
2365 2551
2552 def NewTopCalls(self):
2553 dialog = TopCallsDialog(self.glb, self)
2554 ret = dialog.exec_()
2555 if ret:
2556 TopCallsWindow(self.glb, dialog.report_vars, self)
2557
2366 def NewBranchView(self, event_id): 2558 def NewBranchView(self, event_id):
2367 BranchWindow(self.glb, event_id, "", "", self) 2559 BranchWindow(self.glb, event_id, ReportVars(), self)
2368 2560
2369 def NewSelectedBranchView(self, event_id): 2561 def NewSelectedBranchView(self, event_id):
2370 dialog = SelectedBranchDialog(self.glb, self) 2562 dialog = SelectedBranchDialog(self.glb, self)
2371 ret = dialog.exec_() 2563 ret = dialog.exec_()
2372 if ret: 2564 if ret:
2373 BranchWindow(self.glb, event_id, dialog.name, dialog.where_clause, self) 2565 BranchWindow(self.glb, event_id, dialog.report_vars, self)
2374 2566
2375 def NewTableView(self, table_name): 2567 def NewTableView(self, table_name):
2376 TableWindow(self.glb, table_name, self) 2568 TableWindow(self.glb, table_name, self)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index cafeff3d74db..3648e8b986ec 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -5,6 +5,8 @@
5# Displays system-wide failed system call totals, broken down by pid. 5# Displays system-wide failed system call totals, broken down by pid.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed. 6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7 7
8from __future__ import print_function
9
8import os 10import os
9import sys 11import sys
10 12
@@ -32,7 +34,7 @@ if len(sys.argv) > 1:
32syscalls = autodict() 34syscalls = autodict()
33 35
34def trace_begin(): 36def trace_begin():
35 print "Press control+C to stop and show the summary" 37 print("Press control+C to stop and show the summary")
36 38
37def trace_end(): 39def trace_end():
38 print_error_totals() 40 print_error_totals()
@@ -57,22 +59,21 @@ def syscalls__sys_exit(event_name, context, common_cpu,
57 59
58def print_error_totals(): 60def print_error_totals():
59 if for_comm is not None: 61 if for_comm is not None:
60 print "\nsyscall errors for %s:\n\n" % (for_comm), 62 print("\nsyscall errors for %s:\n" % (for_comm))
61 else: 63 else:
62 print "\nsyscall errors:\n\n", 64 print("\nsyscall errors:\n")
63 65
64 print "%-30s %10s\n" % ("comm [pid]", "count"), 66 print("%-30s %10s" % ("comm [pid]", "count"))
65 print "%-30s %10s\n" % ("------------------------------", \ 67 print("%-30s %10s" % ("------------------------------", "----------"))
66 "----------"),
67 68
68 comm_keys = syscalls.keys() 69 comm_keys = syscalls.keys()
69 for comm in comm_keys: 70 for comm in comm_keys:
70 pid_keys = syscalls[comm].keys() 71 pid_keys = syscalls[comm].keys()
71 for pid in pid_keys: 72 for pid in pid_keys:
72 print "\n%s [%d]\n" % (comm, pid), 73 print("\n%s [%d]" % (comm, pid))
73 id_keys = syscalls[comm][pid].keys() 74 id_keys = syscalls[comm][pid].keys()
74 for id in id_keys: 75 for id in id_keys:
75 print " syscall: %-16s\n" % syscall_name(id), 76 print(" syscall: %-16s" % syscall_name(id))
76 ret_keys = syscalls[comm][pid][id].keys() 77 ret_keys = syscalls[comm][pid][id].keys()
77 for ret, val in sorted(syscalls[comm][pid][id].iteritems(), key = lambda(k, v): (v, k), reverse = True): 78 for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True):
78 print " err = %-20s %10d\n" % (strerror(ret), val), 79 print(" err = %-20s %10d" % (strerror(ret), val))
diff --git a/tools/perf/scripts/python/mem-phys-addr.py b/tools/perf/scripts/python/mem-phys-addr.py
index ebee2c5ae496..fb0bbcbfa0f0 100644
--- a/tools/perf/scripts/python/mem-phys-addr.py
+++ b/tools/perf/scripts/python/mem-phys-addr.py
@@ -4,6 +4,8 @@
4# Copyright (c) 2018, Intel Corporation. 4# Copyright (c) 2018, Intel Corporation.
5 5
6from __future__ import division 6from __future__ import division
7from __future__ import print_function
8
7import os 9import os
8import sys 10import sys
9import struct 11import struct
@@ -31,21 +33,23 @@ def parse_iomem():
31 for i, j in enumerate(f): 33 for i, j in enumerate(f):
32 m = re.split('-|:',j,2) 34 m = re.split('-|:',j,2)
33 if m[2].strip() == 'System RAM': 35 if m[2].strip() == 'System RAM':
34 system_ram.append(long(m[0], 16)) 36 system_ram.append(int(m[0], 16))
35 system_ram.append(long(m[1], 16)) 37 system_ram.append(int(m[1], 16))
36 if m[2].strip() == 'Persistent Memory': 38 if m[2].strip() == 'Persistent Memory':
37 pmem.append(long(m[0], 16)) 39 pmem.append(int(m[0], 16))
38 pmem.append(long(m[1], 16)) 40 pmem.append(int(m[1], 16))
39 41
40def print_memory_type(): 42def print_memory_type():
41 print "Event: %s" % (event_name) 43 print("Event: %s" % (event_name))
42 print "%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), 44 print("%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), end='')
43 print "%-40s %10s %10s\n" % ("----------------------------------------", \ 45 print("%-40s %10s %10s\n" % ("----------------------------------------",
44 "-----------", "-----------"), 46 "-----------", "-----------"),
47 end='');
45 total = sum(load_mem_type_cnt.values()) 48 total = sum(load_mem_type_cnt.values())
46 for mem_type, count in sorted(load_mem_type_cnt.most_common(), \ 49 for mem_type, count in sorted(load_mem_type_cnt.most_common(), \
47 key = lambda(k, v): (v, k), reverse = True): 50 key = lambda kv: (kv[1], kv[0]), reverse = True):
48 print "%-40s %10d %10.1f%%\n" % (mem_type, count, 100 * count / total), 51 print("%-40s %10d %10.1f%%\n" % (mem_type, count, 100 * count / total),
52 end='')
49 53
50def trace_begin(): 54def trace_begin():
51 parse_iomem() 55 parse_iomem()
@@ -80,7 +84,7 @@ def find_memory_type(phys_addr):
80 f.seek(0, 0) 84 f.seek(0, 0)
81 for j in f: 85 for j in f:
82 m = re.split('-|:',j,2) 86 m = re.split('-|:',j,2)
83 if long(m[0], 16) <= phys_addr <= long(m[1], 16): 87 if int(m[0], 16) <= phys_addr <= int(m[1], 16):
84 return m[2] 88 return m[2]
85 return "N/A" 89 return "N/A"
86 90
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index a150164b44a3..212557a02c50 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -1,6 +1,8 @@
1# Monitor the system for dropped packets and proudce a report of drop locations and counts 1# Monitor the system for dropped packets and proudce a report of drop locations and counts
2# SPDX-License-Identifier: GPL-2.0 2# SPDX-License-Identifier: GPL-2.0
3 3
4from __future__ import print_function
5
4import os 6import os
5import sys 7import sys
6 8
@@ -50,19 +52,19 @@ def get_sym(sloc):
50 return (None, 0) 52 return (None, 0)
51 53
52def print_drop_table(): 54def print_drop_table():
53 print "%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT") 55 print("%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT"))
54 for i in drop_log.keys(): 56 for i in drop_log.keys():
55 (sym, off) = get_sym(i) 57 (sym, off) = get_sym(i)
56 if sym == None: 58 if sym == None:
57 sym = i 59 sym = i
58 print "%25s %25s %25s" % (sym, off, drop_log[i]) 60 print("%25s %25s %25s" % (sym, off, drop_log[i]))
59 61
60 62
61def trace_begin(): 63def trace_begin():
62 print "Starting trace (Ctrl-C to dump results)" 64 print("Starting trace (Ctrl-C to dump results)")
63 65
64def trace_end(): 66def trace_end():
65 print "Gathering kallsyms data" 67 print("Gathering kallsyms data")
66 get_kallsyms_table() 68 get_kallsyms_table()
67 print_drop_table() 69 print_drop_table()
68 70
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 9b2050f778f1..267bda49325d 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -8,6 +8,8 @@
8# dev=: show only thing related to specified device 8# dev=: show only thing related to specified device
9# debug: work with debug mode. It shows buffer status. 9# debug: work with debug mode. It shows buffer status.
10 10
11from __future__ import print_function
12
11import os 13import os
12import sys 14import sys
13 15
@@ -17,6 +19,7 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \
17from perf_trace_context import * 19from perf_trace_context import *
18from Core import * 20from Core import *
19from Util import * 21from Util import *
22from functools import cmp_to_key
20 23
21all_event_list = []; # insert all tracepoint event related with this script 24all_event_list = []; # insert all tracepoint event related with this script
22irq_dic = {}; # key is cpu and value is a list which stacks irqs 25irq_dic = {}; # key is cpu and value is a list which stacks irqs
@@ -61,12 +64,12 @@ def diff_msec(src, dst):
61def print_transmit(hunk): 64def print_transmit(hunk):
62 if dev != 0 and hunk['dev'].find(dev) < 0: 65 if dev != 0 and hunk['dev'].find(dev) < 0:
63 return 66 return
64 print "%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" % \ 67 print("%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" %
65 (hunk['dev'], hunk['len'], 68 (hunk['dev'], hunk['len'],
66 nsecs_secs(hunk['queue_t']), 69 nsecs_secs(hunk['queue_t']),
67 nsecs_nsecs(hunk['queue_t'])/1000, 70 nsecs_nsecs(hunk['queue_t'])/1000,
68 diff_msec(hunk['queue_t'], hunk['xmit_t']), 71 diff_msec(hunk['queue_t'], hunk['xmit_t']),
69 diff_msec(hunk['xmit_t'], hunk['free_t'])) 72 diff_msec(hunk['xmit_t'], hunk['free_t'])))
70 73
71# Format for displaying rx packet processing 74# Format for displaying rx packet processing
72PF_IRQ_ENTRY= " irq_entry(+%.3fmsec irq=%d:%s)" 75PF_IRQ_ENTRY= " irq_entry(+%.3fmsec irq=%d:%s)"
@@ -98,55 +101,55 @@ def print_receive(hunk):
98 if show_hunk == 0: 101 if show_hunk == 0:
99 return 102 return
100 103
101 print "%d.%06dsec cpu=%d" % \ 104 print("%d.%06dsec cpu=%d" %
102 (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu) 105 (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu))
103 for i in range(len(irq_list)): 106 for i in range(len(irq_list)):
104 print PF_IRQ_ENTRY % \ 107 print(PF_IRQ_ENTRY %
105 (diff_msec(base_t, irq_list[i]['irq_ent_t']), 108 (diff_msec(base_t, irq_list[i]['irq_ent_t']),
106 irq_list[i]['irq'], irq_list[i]['name']) 109 irq_list[i]['irq'], irq_list[i]['name']))
107 print PF_JOINT 110 print(PF_JOINT)
108 irq_event_list = irq_list[i]['event_list'] 111 irq_event_list = irq_list[i]['event_list']
109 for j in range(len(irq_event_list)): 112 for j in range(len(irq_event_list)):
110 irq_event = irq_event_list[j] 113 irq_event = irq_event_list[j]
111 if irq_event['event'] == 'netif_rx': 114 if irq_event['event'] == 'netif_rx':
112 print PF_NET_RX % \ 115 print(PF_NET_RX %
113 (diff_msec(base_t, irq_event['time']), 116 (diff_msec(base_t, irq_event['time']),
114 irq_event['skbaddr']) 117 irq_event['skbaddr']))
115 print PF_JOINT 118 print(PF_JOINT)
116 print PF_SOFT_ENTRY % \ 119 print(PF_SOFT_ENTRY %
117 diff_msec(base_t, hunk['sirq_ent_t']) 120 diff_msec(base_t, hunk['sirq_ent_t']))
118 print PF_JOINT 121 print(PF_JOINT)
119 event_list = hunk['event_list'] 122 event_list = hunk['event_list']
120 for i in range(len(event_list)): 123 for i in range(len(event_list)):
121 event = event_list[i] 124 event = event_list[i]
122 if event['event_name'] == 'napi_poll': 125 if event['event_name'] == 'napi_poll':
123 print PF_NAPI_POLL % \ 126 print(PF_NAPI_POLL %
124 (diff_msec(base_t, event['event_t']), event['dev']) 127 (diff_msec(base_t, event['event_t']), event['dev']))
125 if i == len(event_list) - 1: 128 if i == len(event_list) - 1:
126 print "" 129 print("")
127 else: 130 else:
128 print PF_JOINT 131 print(PF_JOINT)
129 else: 132 else:
130 print PF_NET_RECV % \ 133 print(PF_NET_RECV %
131 (diff_msec(base_t, event['event_t']), event['skbaddr'], 134 (diff_msec(base_t, event['event_t']), event['skbaddr'],
132 event['len']) 135 event['len']))
133 if 'comm' in event.keys(): 136 if 'comm' in event.keys():
134 print PF_WJOINT 137 print(PF_WJOINT)
135 print PF_CPY_DGRAM % \ 138 print(PF_CPY_DGRAM %
136 (diff_msec(base_t, event['comm_t']), 139 (diff_msec(base_t, event['comm_t']),
137 event['pid'], event['comm']) 140 event['pid'], event['comm']))
138 elif 'handle' in event.keys(): 141 elif 'handle' in event.keys():
139 print PF_WJOINT 142 print(PF_WJOINT)
140 if event['handle'] == "kfree_skb": 143 if event['handle'] == "kfree_skb":
141 print PF_KFREE_SKB % \ 144 print(PF_KFREE_SKB %
142 (diff_msec(base_t, 145 (diff_msec(base_t,
143 event['comm_t']), 146 event['comm_t']),
144 event['location']) 147 event['location']))
145 elif event['handle'] == "consume_skb": 148 elif event['handle'] == "consume_skb":
146 print PF_CONS_SKB % \ 149 print(PF_CONS_SKB %
147 diff_msec(base_t, 150 diff_msec(base_t,
148 event['comm_t']) 151 event['comm_t']))
149 print PF_JOINT 152 print(PF_JOINT)
150 153
151def trace_begin(): 154def trace_begin():
152 global show_tx 155 global show_tx
@@ -172,8 +175,7 @@ def trace_begin():
172 175
173def trace_end(): 176def trace_end():
174 # order all events in time 177 # order all events in time
175 all_event_list.sort(lambda a,b :cmp(a[EINFO_IDX_TIME], 178 all_event_list.sort(key=cmp_to_key(lambda a,b :a[EINFO_IDX_TIME] < b[EINFO_IDX_TIME]))
176 b[EINFO_IDX_TIME]))
177 # process all events 179 # process all events
178 for i in range(len(all_event_list)): 180 for i in range(len(all_event_list)):
179 event_info = all_event_list[i] 181 event_info = all_event_list[i]
@@ -210,19 +212,19 @@ def trace_end():
210 print_receive(receive_hunk_list[i]) 212 print_receive(receive_hunk_list[i])
211 # display transmit hunks 213 # display transmit hunks
212 if show_tx: 214 if show_tx:
213 print " dev len Qdisc " \ 215 print(" dev len Qdisc "
214 " netdevice free" 216 " netdevice free")
215 for i in range(len(tx_free_list)): 217 for i in range(len(tx_free_list)):
216 print_transmit(tx_free_list[i]) 218 print_transmit(tx_free_list[i])
217 if debug: 219 if debug:
218 print "debug buffer status" 220 print("debug buffer status")
219 print "----------------------------" 221 print("----------------------------")
220 print "xmit Qdisc:remain:%d overflow:%d" % \ 222 print("xmit Qdisc:remain:%d overflow:%d" %
221 (len(tx_queue_list), of_count_tx_queue_list) 223 (len(tx_queue_list), of_count_tx_queue_list))
222 print "xmit netdevice:remain:%d overflow:%d" % \ 224 print("xmit netdevice:remain:%d overflow:%d" %
223 (len(tx_xmit_list), of_count_tx_xmit_list) 225 (len(tx_xmit_list), of_count_tx_xmit_list))
224 print "receive:remain:%d overflow:%d" % \ 226 print("receive:remain:%d overflow:%d" %
225 (len(rx_skb_list), of_count_rx_skb_list) 227 (len(rx_skb_list), of_count_rx_skb_list))
226 228
227# called from perf, when it finds a correspoinding event 229# called from perf, when it finds a correspoinding event
228def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec): 230def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
diff --git a/tools/perf/scripts/python/powerpc-hcalls.py b/tools/perf/scripts/python/powerpc-hcalls.py
index 00e0e7476e55..8b78dc790adb 100644
--- a/tools/perf/scripts/python/powerpc-hcalls.py
+++ b/tools/perf/scripts/python/powerpc-hcalls.py
@@ -4,6 +4,8 @@
4# 4#
5# Hypervisor call statisics 5# Hypervisor call statisics
6 6
7from __future__ import print_function
8
7import os 9import os
8import sys 10import sys
9 11
@@ -149,7 +151,7 @@ hcall_table = {
149} 151}
150 152
151def hcall_table_lookup(opcode): 153def hcall_table_lookup(opcode):
152 if (hcall_table.has_key(opcode)): 154 if (opcode in hcall_table):
153 return hcall_table[opcode] 155 return hcall_table[opcode]
154 else: 156 else:
155 return opcode 157 return opcode
@@ -157,8 +159,8 @@ def hcall_table_lookup(opcode):
157print_ptrn = '%-28s%10s%10s%10s%10s' 159print_ptrn = '%-28s%10s%10s%10s%10s'
158 160
159def trace_end(): 161def trace_end():
160 print print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)') 162 print(print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)'))
161 print '-' * 68 163 print('-' * 68)
162 for opcode in output: 164 for opcode in output:
163 h_name = hcall_table_lookup(opcode) 165 h_name = hcall_table_lookup(opcode)
164 time = output[opcode]['time'] 166 time = output[opcode]['time']
@@ -166,14 +168,14 @@ def trace_end():
166 min_t = output[opcode]['min'] 168 min_t = output[opcode]['min']
167 max_t = output[opcode]['max'] 169 max_t = output[opcode]['max']
168 170
169 print print_ptrn % (h_name, cnt, min_t, max_t, time/cnt) 171 print(print_ptrn % (h_name, cnt, min_t, max_t, time//cnt))
170 172
171def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain, 173def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain,
172 opcode, retval): 174 opcode, retval):
173 if (d_enter.has_key(cpu) and d_enter[cpu].has_key(opcode)): 175 if (cpu in d_enter and opcode in d_enter[cpu]):
174 diff = nsecs(sec, nsec) - d_enter[cpu][opcode] 176 diff = nsecs(sec, nsec) - d_enter[cpu][opcode]
175 177
176 if (output.has_key(opcode)): 178 if (opcode in output):
177 output[opcode]['time'] += diff 179 output[opcode]['time'] += diff
178 output[opcode]['cnt'] += 1 180 output[opcode]['cnt'] += 1
179 if (output[opcode]['min'] > diff): 181 if (output[opcode]['min'] > diff):
@@ -190,11 +192,11 @@ def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain,
190 192
191 del d_enter[cpu][opcode] 193 del d_enter[cpu][opcode]
192# else: 194# else:
193# print "Can't find matching hcall_enter event. Ignoring sample" 195# print("Can't find matching hcall_enter event. Ignoring sample")
194 196
195def powerpc__hcall_entry(event_name, context, cpu, sec, nsec, pid, comm, 197def powerpc__hcall_entry(event_name, context, cpu, sec, nsec, pid, comm,
196 callchain, opcode): 198 callchain, opcode):
197 if (d_enter.has_key(cpu)): 199 if (cpu in d_enter):
198 d_enter[cpu][opcode] = nsecs(sec, nsec) 200 d_enter[cpu][opcode] = nsecs(sec, nsec)
199 else: 201 else:
200 d_enter[cpu] = {opcode: nsecs(sec, nsec)} 202 d_enter[cpu] = {opcode: nsecs(sec, nsec)}
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index 61621b93affb..987ffae7c8ca 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -8,7 +8,14 @@
8# will be refreshed every [interval] seconds. The default interval is 8# will be refreshed every [interval] seconds. The default interval is
9# 3 seconds. 9# 3 seconds.
10 10
11import os, sys, thread, time 11from __future__ import print_function
12
13import os, sys, time
14
15try:
16 import thread
17except ImportError:
18 import _thread as thread
12 19
13sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 20sys.path.append(os.environ['PERF_EXEC_PATH'] + \
14 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 21 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
@@ -62,18 +69,19 @@ def print_syscall_totals(interval):
62 while 1: 69 while 1:
63 clear_term() 70 clear_term()
64 if for_comm is not None: 71 if for_comm is not None:
65 print "\nsyscall events for %s:\n\n" % (for_comm), 72 print("\nsyscall events for %s:\n" % (for_comm))
66 else: 73 else:
67 print "\nsyscall events:\n\n", 74 print("\nsyscall events:\n")
68 75
69 print "%-40s %10s\n" % ("event", "count"), 76 print("%-40s %10s" % ("event", "count"))
70 print "%-40s %10s\n" % ("----------------------------------------", \ 77 print("%-40s %10s" %
71 "----------"), 78 ("----------------------------------------",
79 "----------"))
72 80
73 for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \ 81 for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \
74 reverse = True): 82 reverse = True):
75 try: 83 try:
76 print "%-40s %10d\n" % (syscall_name(id), val), 84 print("%-40s %10d" % (syscall_name(id), val))
77 except TypeError: 85 except TypeError:
78 pass 86 pass
79 syscalls.clear() 87 syscalls.clear()
diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py
index 1697b5e18c96..5e703efaddcc 100755
--- a/tools/perf/scripts/python/stackcollapse.py
+++ b/tools/perf/scripts/python/stackcollapse.py
@@ -19,6 +19,8 @@
19# Written by Paolo Bonzini <pbonzini@redhat.com> 19# Written by Paolo Bonzini <pbonzini@redhat.com>
20# Based on Brendan Gregg's stackcollapse-perf.pl script. 20# Based on Brendan Gregg's stackcollapse-perf.pl script.
21 21
22from __future__ import print_function
23
22import os 24import os
23import sys 25import sys
24from collections import defaultdict 26from collections import defaultdict
@@ -120,7 +122,6 @@ def process_event(param_dict):
120 lines[stack_string] = lines[stack_string] + 1 122 lines[stack_string] = lines[stack_string] + 1
121 123
122def trace_end(): 124def trace_end():
123 list = lines.keys() 125 list = sorted(lines)
124 list.sort()
125 for stack in list: 126 for stack in list:
126 print "%s %d" % (stack, lines[stack]) 127 print("%s %d" % (stack, lines[stack]))
diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py
index a81ad8835a74..01fa933ff3cf 100644
--- a/tools/perf/scripts/python/stat-cpi.py
+++ b/tools/perf/scripts/python/stat-cpi.py
@@ -1,5 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2 2
3from __future__ import print_function
4
3data = {} 5data = {}
4times = [] 6times = []
5threads = [] 7threads = []
@@ -19,8 +21,8 @@ def store_key(time, cpu, thread):
19 threads.append(thread) 21 threads.append(thread)
20 22
21def store(time, event, cpu, thread, val, ena, run): 23def store(time, event, cpu, thread, val, ena, run):
22 #print "event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % \ 24 #print("event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" %
23 # (event, cpu, thread, time, val, ena, run) 25 # (event, cpu, thread, time, val, ena, run))
24 26
25 store_key(time, cpu, thread) 27 store_key(time, cpu, thread)
26 key = get_key(time, event, cpu, thread) 28 key = get_key(time, event, cpu, thread)
@@ -58,7 +60,7 @@ def stat__interval(time):
58 if ins != 0: 60 if ins != 0:
59 cpi = cyc/float(ins) 61 cpi = cyc/float(ins)
60 62
61 print "%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins) 63 print("%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins))
62 64
63def trace_end(): 65def trace_end():
64 pass 66 pass
@@ -74,4 +76,4 @@ def trace_end():
74# if ins != 0: 76# if ins != 0:
75# cpi = cyc/float(ins) 77# cpi = cyc/float(ins)
76# 78#
77# print "time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi) 79# print("time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi))
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index daf314cc5dd3..42782487b0e9 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -5,6 +5,8 @@
5# Displays system-wide system call totals, broken down by syscall. 5# Displays system-wide system call totals, broken down by syscall.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed. 6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7 7
8from __future__ import print_function
9
8import os, sys 10import os, sys
9 11
10sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 12sys.path.append(os.environ['PERF_EXEC_PATH'] + \
@@ -31,7 +33,7 @@ if len(sys.argv) > 1:
31syscalls = autodict() 33syscalls = autodict()
32 34
33def trace_begin(): 35def trace_begin():
34 print "Press control+C to stop and show the summary" 36 print("Press control+C to stop and show the summary")
35 37
36def trace_end(): 38def trace_end():
37 print_syscall_totals() 39 print_syscall_totals()
@@ -55,20 +57,20 @@ def syscalls__sys_enter(event_name, context, common_cpu,
55 57
56def print_syscall_totals(): 58def print_syscall_totals():
57 if for_comm is not None: 59 if for_comm is not None:
58 print "\nsyscall events for %s:\n\n" % (for_comm), 60 print("\nsyscall events for %s:\n" % (for_comm))
59 else: 61 else:
60 print "\nsyscall events by comm/pid:\n\n", 62 print("\nsyscall events by comm/pid:\n")
61 63
62 print "%-40s %10s\n" % ("comm [pid]/syscalls", "count"), 64 print("%-40s %10s" % ("comm [pid]/syscalls", "count"))
63 print "%-40s %10s\n" % ("----------------------------------------", \ 65 print("%-40s %10s" % ("----------------------------------------",
64 "----------"), 66 "----------"))
65 67
66 comm_keys = syscalls.keys() 68 comm_keys = syscalls.keys()
67 for comm in comm_keys: 69 for comm in comm_keys:
68 pid_keys = syscalls[comm].keys() 70 pid_keys = syscalls[comm].keys()
69 for pid in pid_keys: 71 for pid in pid_keys:
70 print "\n%s [%d]\n" % (comm, pid), 72 print("\n%s [%d]" % (comm, pid))
71 id_keys = syscalls[comm][pid].keys() 73 id_keys = syscalls[comm][pid].keys()
72 for id, val in sorted(syscalls[comm][pid].iteritems(), \ 74 for id, val in sorted(syscalls[comm][pid].items(), \
73 key = lambda(k, v): (v, k), reverse = True): 75 key = lambda kv: (kv[1], kv[0]), reverse = True):
74 print " %-38s %10d\n" % (syscall_name(id), val), 76 print(" %-38s %10d" % (syscall_name(id), val))
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index e66a7730aeb5..0ebd89cfd42c 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -5,6 +5,8 @@
5# Displays system-wide system call totals, broken down by syscall. 5# Displays system-wide system call totals, broken down by syscall.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed. 6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7 7
8from __future__ import print_function
9
8import os 10import os
9import sys 11import sys
10 12
@@ -28,7 +30,7 @@ if len(sys.argv) > 1:
28syscalls = autodict() 30syscalls = autodict()
29 31
30def trace_begin(): 32def trace_begin():
31 print "Press control+C to stop and show the summary" 33 print("Press control+C to stop and show the summary")
32 34
33def trace_end(): 35def trace_end():
34 print_syscall_totals() 36 print_syscall_totals()
@@ -51,14 +53,14 @@ def syscalls__sys_enter(event_name, context, common_cpu,
51 53
52def print_syscall_totals(): 54def print_syscall_totals():
53 if for_comm is not None: 55 if for_comm is not None:
54 print "\nsyscall events for %s:\n\n" % (for_comm), 56 print("\nsyscall events for %s:\n" % (for_comm))
55 else: 57 else:
56 print "\nsyscall events:\n\n", 58 print("\nsyscall events:\n")
57 59
58 print "%-40s %10s\n" % ("event", "count"), 60 print("%-40s %10s" % ("event", "count"))
59 print "%-40s %10s\n" % ("----------------------------------------", \ 61 print("%-40s %10s" % ("----------------------------------------",
60 "-----------"), 62 "-----------"))
61 63
62 for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \ 64 for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \
63 reverse = True): 65 reverse = True):
64 print "%-40s %10d\n" % (syscall_name(id), val), 66 print("%-40s %10d" % (syscall_name(id), val))
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 2468b8aa0b6b..11a8a447a3af 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1891,6 +1891,7 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1891 struct annotation_options *options, 1891 struct annotation_options *options,
1892 struct arch **parch) 1892 struct arch **parch)
1893{ 1893{
1894 struct annotation *notes = symbol__annotation(sym);
1894 struct annotate_args args = { 1895 struct annotate_args args = {
1895 .privsize = privsize, 1896 .privsize = privsize,
1896 .evsel = evsel, 1897 .evsel = evsel,
@@ -1921,6 +1922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1921 1922
1922 args.ms.map = map; 1923 args.ms.map = map;
1923 args.ms.sym = sym; 1924 args.ms.sym = sym;
1925 notes->start = map__rip_2objdump(map, sym->start);
1924 1926
1925 return symbol__disassemble(sym, &args); 1927 return symbol__disassemble(sym, &args);
1926} 1928}
@@ -2796,8 +2798,6 @@ int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *ev
2796 2798
2797 symbol__calc_percent(sym, evsel); 2799 symbol__calc_percent(sym, evsel);
2798 2800
2799 notes->start = map__rip_2objdump(map, sym->start);
2800
2801 annotation__set_offsets(notes, size); 2801 annotation__set_offsets(notes, size);
2802 annotation__mark_jump_targets(notes, sym); 2802 annotation__mark_jump_targets(notes, sym);
2803 annotation__compute_ipc(notes, size); 2803 annotation__compute_ipc(notes, size);
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 2a36fab76994..26af43ad9ddd 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1578,7 +1578,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1578{ 1578{
1579 struct perf_session *session; 1579 struct perf_session *session;
1580 struct perf_data data = { 1580 struct perf_data data = {
1581 .file = { .path = input, .fd = -1 }, 1581 .path = input,
1582 .mode = PERF_DATA_MODE_READ, 1582 .mode = PERF_DATA_MODE_READ,
1583 .force = opts->force, 1583 .force = opts->force,
1584 }; 1584 };
@@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1650 1650
1651 fprintf(stderr, 1651 fprintf(stderr,
1652 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", 1652 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1653 data.file.path, path); 1653 data.path, path);
1654 1654
1655 fprintf(stderr, 1655 fprintf(stderr,
1656 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples", 1656 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index d8cfc19ddb10..7bd5ddeb7a41 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -7,11 +7,117 @@
7#include <fcntl.h> 7#include <fcntl.h>
8#include <unistd.h> 8#include <unistd.h>
9#include <string.h> 9#include <string.h>
10#include <asm/bug.h>
11#include <sys/types.h>
12#include <dirent.h>
10 13
11#include "data.h" 14#include "data.h"
12#include "util.h" 15#include "util.h"
13#include "debug.h" 16#include "debug.h"
14 17
18static void close_dir(struct perf_data_file *files, int nr)
19{
20 while (--nr >= 1) {
21 close(files[nr].fd);
22 free(files[nr].path);
23 }
24 free(files);
25}
26
27void perf_data__close_dir(struct perf_data *data)
28{
29 close_dir(data->dir.files, data->dir.nr);
30}
31
32int perf_data__create_dir(struct perf_data *data, int nr)
33{
34 struct perf_data_file *files = NULL;
35 int i, ret = -1;
36
37 files = zalloc(nr * sizeof(*files));
38 if (!files)
39 return -ENOMEM;
40
41 data->dir.files = files;
42 data->dir.nr = nr;
43
44 for (i = 0; i < nr; i++) {
45 struct perf_data_file *file = &files[i];
46
47 if (asprintf(&file->path, "%s/data.%d", data->path, i) < 0)
48 goto out_err;
49
50 ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
51 if (ret < 0)
52 goto out_err;
53
54 file->fd = ret;
55 }
56
57 return 0;
58
59out_err:
60 close_dir(files, i);
61 return ret;
62}
63
64int perf_data__open_dir(struct perf_data *data)
65{
66 struct perf_data_file *files = NULL;
67 struct dirent *dent;
68 int ret = -1;
69 DIR *dir;
70 int nr = 0;
71
72 dir = opendir(data->path);
73 if (!dir)
74 return -EINVAL;
75
76 while ((dent = readdir(dir)) != NULL) {
77 struct perf_data_file *file;
78 char path[PATH_MAX];
79 struct stat st;
80
81 snprintf(path, sizeof(path), "%s/%s", data->path, dent->d_name);
82 if (stat(path, &st))
83 continue;
84
85 if (!S_ISREG(st.st_mode) || strncmp(dent->d_name, "data", 4))
86 continue;
87
88 ret = -ENOMEM;
89
90 file = realloc(files, (nr + 1) * sizeof(*files));
91 if (!file)
92 goto out_err;
93
94 files = file;
95 file = &files[nr++];
96
97 file->path = strdup(path);
98 if (!file->path)
99 goto out_err;
100
101 ret = open(file->path, O_RDONLY);
102 if (ret < 0)
103 goto out_err;
104
105 file->fd = ret;
106 file->size = st.st_size;
107 }
108
109 if (!files)
110 return -EINVAL;
111
112 data->dir.files = files;
113 data->dir.nr = nr;
114 return 0;
115
116out_err:
117 close_dir(files, nr);
118 return ret;
119}
120
15static bool check_pipe(struct perf_data *data) 121static bool check_pipe(struct perf_data *data)
16{ 122{
17 struct stat st; 123 struct stat st;
@@ -19,11 +125,11 @@ static bool check_pipe(struct perf_data *data)
19 int fd = perf_data__is_read(data) ? 125 int fd = perf_data__is_read(data) ?
20 STDIN_FILENO : STDOUT_FILENO; 126 STDIN_FILENO : STDOUT_FILENO;
21 127
22 if (!data->file.path) { 128 if (!data->path) {
23 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) 129 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
24 is_pipe = true; 130 is_pipe = true;
25 } else { 131 } else {
26 if (!strcmp(data->file.path, "-")) 132 if (!strcmp(data->path, "-"))
27 is_pipe = true; 133 is_pipe = true;
28 } 134 }
29 135
@@ -37,13 +143,31 @@ static int check_backup(struct perf_data *data)
37{ 143{
38 struct stat st; 144 struct stat st;
39 145
40 if (!stat(data->file.path, &st) && st.st_size) { 146 if (perf_data__is_read(data))
41 /* TODO check errors properly */ 147 return 0;
148
149 if (!stat(data->path, &st) && st.st_size) {
42 char oldname[PATH_MAX]; 150 char oldname[PATH_MAX];
151 int ret;
152
43 snprintf(oldname, sizeof(oldname), "%s.old", 153 snprintf(oldname, sizeof(oldname), "%s.old",
44 data->file.path); 154 data->path);
45 unlink(oldname); 155
46 rename(data->file.path, oldname); 156 ret = rm_rf_perf_data(oldname);
157 if (ret) {
158 pr_err("Can't remove old data: %s (%s)\n",
159 ret == -2 ?
160 "Unknown file found" : strerror(errno),
161 oldname);
162 return -1;
163 }
164
165 if (rename(data->path, oldname)) {
166 pr_err("Can't move data: %s (%s to %s)\n",
167 strerror(errno),
168 data->path, oldname);
169 return -1;
170 }
47 } 171 }
48 172
49 return 0; 173 return 0;
@@ -82,7 +206,7 @@ static int open_file_read(struct perf_data *data)
82 goto out_close; 206 goto out_close;
83 } 207 }
84 208
85 data->size = st.st_size; 209 data->file.size = st.st_size;
86 return fd; 210 return fd;
87 211
88 out_close: 212 out_close:
@@ -95,9 +219,6 @@ static int open_file_write(struct perf_data *data)
95 int fd; 219 int fd;
96 char sbuf[STRERR_BUFSIZE]; 220 char sbuf[STRERR_BUFSIZE];
97 221
98 if (check_backup(data))
99 return -1;
100
101 fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 222 fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
102 S_IRUSR|S_IWUSR); 223 S_IRUSR|S_IWUSR);
103 224
@@ -115,8 +236,22 @@ static int open_file(struct perf_data *data)
115 fd = perf_data__is_read(data) ? 236 fd = perf_data__is_read(data) ?
116 open_file_read(data) : open_file_write(data); 237 open_file_read(data) : open_file_write(data);
117 238
239 if (fd < 0) {
240 free(data->file.path);
241 return -1;
242 }
243
118 data->file.fd = fd; 244 data->file.fd = fd;
119 return fd < 0 ? -1 : 0; 245 return 0;
246}
247
248static int open_file_dup(struct perf_data *data)
249{
250 data->file.path = strdup(data->path);
251 if (!data->file.path)
252 return -ENOMEM;
253
254 return open_file(data);
120} 255}
121 256
122int perf_data__open(struct perf_data *data) 257int perf_data__open(struct perf_data *data)
@@ -124,14 +259,18 @@ int perf_data__open(struct perf_data *data)
124 if (check_pipe(data)) 259 if (check_pipe(data))
125 return 0; 260 return 0;
126 261
127 if (!data->file.path) 262 if (!data->path)
128 data->file.path = "perf.data"; 263 data->path = "perf.data";
129 264
130 return open_file(data); 265 if (check_backup(data))
266 return -1;
267
268 return open_file_dup(data);
131} 269}
132 270
133void perf_data__close(struct perf_data *data) 271void perf_data__close(struct perf_data *data)
134{ 272{
273 free(data->file.path);
135 close(data->file.fd); 274 close(data->file.fd);
136} 275}
137 276
@@ -159,15 +298,15 @@ int perf_data__switch(struct perf_data *data,
159 if (perf_data__is_read(data)) 298 if (perf_data__is_read(data))
160 return -EINVAL; 299 return -EINVAL;
161 300
162 if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0) 301 if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0)
163 return -ENOMEM; 302 return -ENOMEM;
164 303
165 /* 304 /*
166 * Only fire a warning, don't return error, continue fill 305 * Only fire a warning, don't return error, continue fill
167 * original file. 306 * original file.
168 */ 307 */
169 if (rename(data->file.path, new_filepath)) 308 if (rename(data->path, new_filepath))
170 pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath); 309 pr_warning("Failed to rename %s to %s\n", data->path, new_filepath);
171 310
172 if (!at_exit) { 311 if (!at_exit) {
173 close(data->file.fd); 312 close(data->file.fd);
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 4828f7feea89..14b47be2bd69 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -10,16 +10,22 @@ enum perf_data_mode {
10}; 10};
11 11
12struct perf_data_file { 12struct perf_data_file {
13 const char *path; 13 char *path;
14 int fd; 14 int fd;
15 unsigned long size;
15}; 16};
16 17
17struct perf_data { 18struct perf_data {
19 const char *path;
18 struct perf_data_file file; 20 struct perf_data_file file;
19 bool is_pipe; 21 bool is_pipe;
20 bool force; 22 bool force;
21 unsigned long size;
22 enum perf_data_mode mode; 23 enum perf_data_mode mode;
24
25 struct {
26 struct perf_data_file *files;
27 int nr;
28 } dir;
23}; 29};
24 30
25static inline bool perf_data__is_read(struct perf_data *data) 31static inline bool perf_data__is_read(struct perf_data *data)
@@ -44,7 +50,7 @@ static inline int perf_data__fd(struct perf_data *data)
44 50
45static inline unsigned long perf_data__size(struct perf_data *data) 51static inline unsigned long perf_data__size(struct perf_data *data)
46{ 52{
47 return data->size; 53 return data->file.size;
48} 54}
49 55
50int perf_data__open(struct perf_data *data); 56int perf_data__open(struct perf_data *data);
@@ -63,4 +69,8 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
63int perf_data__switch(struct perf_data *data, 69int perf_data__switch(struct perf_data *data,
64 const char *postfix, 70 const char *postfix,
65 size_t pos, bool at_exit); 71 size_t pos, bool at_exit);
72
73int perf_data__create_dir(struct perf_data *data, int nr);
74int perf_data__open_dir(struct perf_data *data);
75void perf_data__close_dir(struct perf_data *data);
66#endif /* __PERF_DATA_H */ 76#endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a2323d777dae..01b324c275b9 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -527,17 +527,11 @@ static int write_event_desc(struct feat_fd *ff,
527static int write_cmdline(struct feat_fd *ff, 527static int write_cmdline(struct feat_fd *ff,
528 struct perf_evlist *evlist __maybe_unused) 528 struct perf_evlist *evlist __maybe_unused)
529{ 529{
530 char buf[MAXPATHLEN]; 530 char pbuf[MAXPATHLEN], *buf;
531 u32 n; 531 int i, ret, n;
532 int i, ret;
533 532
534 /* actual path to perf binary */ 533 /* actual path to perf binary */
535 ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1); 534 buf = perf_exe(pbuf, MAXPATHLEN);
536 if (ret <= 0)
537 return -1;
538
539 /* readlink() does not add null termination */
540 buf[ret] = '\0';
541 535
542 /* account for binary path */ 536 /* account for binary path */
543 n = perf_env.nr_cmdline + 1; 537 n = perf_env.nr_cmdline + 1;
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index f52c0f90915d..a8b45168513c 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -20,6 +20,7 @@
20#include "thread.h" 20#include "thread.h"
21#include "event.h" 21#include "event.h"
22#include "machine.h" 22#include "machine.h"
23#include "env.h"
23#include "util.h" 24#include "util.h"
24#include "debug.h" 25#include "debug.h"
25#include "symbol.h" 26#include "symbol.h"
@@ -29,6 +30,19 @@
29 30
30#define STACK_GROWTH 2048 31#define STACK_GROWTH 2048
31 32
33/*
34 * State of retpoline detection.
35 *
36 * RETPOLINE_NONE: no retpoline detection
37 * X86_RETPOLINE_POSSIBLE: x86 retpoline possible
38 * X86_RETPOLINE_DETECTED: x86 retpoline detected
39 */
40enum retpoline_state_t {
41 RETPOLINE_NONE,
42 X86_RETPOLINE_POSSIBLE,
43 X86_RETPOLINE_DETECTED,
44};
45
32/** 46/**
33 * struct thread_stack_entry - thread stack entry. 47 * struct thread_stack_entry - thread stack entry.
34 * @ret_addr: return address 48 * @ret_addr: return address
@@ -64,6 +78,7 @@ struct thread_stack_entry {
64 * @crp: call/return processor 78 * @crp: call/return processor
65 * @comm: current comm 79 * @comm: current comm
66 * @arr_sz: size of array if this is the first element of an array 80 * @arr_sz: size of array if this is the first element of an array
81 * @rstate: used to detect retpolines
67 */ 82 */
68struct thread_stack { 83struct thread_stack {
69 struct thread_stack_entry *stack; 84 struct thread_stack_entry *stack;
@@ -76,6 +91,7 @@ struct thread_stack {
76 struct call_return_processor *crp; 91 struct call_return_processor *crp;
77 struct comm *comm; 92 struct comm *comm;
78 unsigned int arr_sz; 93 unsigned int arr_sz;
94 enum retpoline_state_t rstate;
79}; 95};
80 96
81/* 97/*
@@ -115,10 +131,16 @@ static int thread_stack__init(struct thread_stack *ts, struct thread *thread,
115 if (err) 131 if (err)
116 return err; 132 return err;
117 133
118 if (thread->mg && thread->mg->machine) 134 if (thread->mg && thread->mg->machine) {
119 ts->kernel_start = machine__kernel_start(thread->mg->machine); 135 struct machine *machine = thread->mg->machine;
120 else 136 const char *arch = perf_env__arch(machine->env);
137
138 ts->kernel_start = machine__kernel_start(machine);
139 if (!strcmp(arch, "x86"))
140 ts->rstate = X86_RETPOLINE_POSSIBLE;
141 } else {
121 ts->kernel_start = 1ULL << 63; 142 ts->kernel_start = 1ULL << 63;
143 }
122 ts->crp = crp; 144 ts->crp = crp;
123 145
124 return 0; 146 return 0;
@@ -638,14 +660,57 @@ static int thread_stack__no_call_return(struct thread *thread,
638 else 660 else
639 parent = root; 661 parent = root;
640 662
641 /* This 'return' had no 'call', so push and pop top of stack */ 663 if (parent->sym == from_al->sym) {
642 cp = call_path__findnew(cpr, parent, fsym, ip, ks); 664 /*
665 * At the bottom of the stack, assume the missing 'call' was
666 * before the trace started. So, pop the current symbol and push
667 * the 'to' symbol.
668 */
669 if (ts->cnt == 1) {
670 err = thread_stack__call_return(thread, ts, --ts->cnt,
671 tm, ref, false);
672 if (err)
673 return err;
674 }
675
676 if (!ts->cnt) {
677 cp = call_path__findnew(cpr, root, tsym, addr, ks);
678
679 return thread_stack__push_cp(ts, addr, tm, ref, cp,
680 true, false);
681 }
682
683 /*
684 * Otherwise assume the 'return' is being used as a jump (e.g.
685 * retpoline) and just push the 'to' symbol.
686 */
687 cp = call_path__findnew(cpr, parent, tsym, addr, ks);
688
689 err = thread_stack__push_cp(ts, 0, tm, ref, cp, true, false);
690 if (!err)
691 ts->stack[ts->cnt - 1].non_call = true;
692
693 return err;
694 }
695
696 /*
697 * Assume 'parent' has not yet returned, so push 'to', and then push and
698 * pop 'from'.
699 */
700
701 cp = call_path__findnew(cpr, parent, tsym, addr, ks);
643 702
644 err = thread_stack__push_cp(ts, addr, tm, ref, cp, true, false); 703 err = thread_stack__push_cp(ts, addr, tm, ref, cp, true, false);
645 if (err) 704 if (err)
646 return err; 705 return err;
647 706
648 return thread_stack__pop_cp(thread, ts, addr, tm, ref, tsym); 707 cp = call_path__findnew(cpr, cp, fsym, ip, ks);
708
709 err = thread_stack__push_cp(ts, ip, tm, ref, cp, true, false);
710 if (err)
711 return err;
712
713 return thread_stack__call_return(thread, ts, --ts->cnt, tm, ref, false);
649} 714}
650 715
651static int thread_stack__trace_begin(struct thread *thread, 716static int thread_stack__trace_begin(struct thread *thread,
@@ -690,6 +755,70 @@ static int thread_stack__trace_end(struct thread_stack *ts,
690 false, true); 755 false, true);
691} 756}
692 757
758static bool is_x86_retpoline(const char *name)
759{
760 const char *p = strstr(name, "__x86_indirect_thunk_");
761
762 return p == name || !strcmp(name, "__indirect_thunk_start");
763}
764
765/*
766 * x86 retpoline functions pollute the call graph. This function removes them.
767 * This does not handle function return thunks, nor is there any improvement
768 * for the handling of inline thunks or extern thunks.
769 */
770static int thread_stack__x86_retpoline(struct thread_stack *ts,
771 struct perf_sample *sample,
772 struct addr_location *to_al)
773{
774 struct thread_stack_entry *tse = &ts->stack[ts->cnt - 1];
775 struct call_path_root *cpr = ts->crp->cpr;
776 struct symbol *sym = tse->cp->sym;
777 struct symbol *tsym = to_al->sym;
778 struct call_path *cp;
779
780 if (sym && is_x86_retpoline(sym->name)) {
781 /*
782 * This is a x86 retpoline fn. It pollutes the call graph by
783 * showing up everywhere there is an indirect branch, but does
784 * not itself mean anything. Here the top-of-stack is removed,
785 * by decrementing the stack count, and then further down, the
786 * resulting top-of-stack is replaced with the actual target.
787 * The result is that the retpoline functions will no longer
788 * appear in the call graph. Note this only affects the call
789 * graph, since all the original branches are left unchanged.
790 */
791 ts->cnt -= 1;
792 sym = ts->stack[ts->cnt - 2].cp->sym;
793 if (sym && sym == tsym && to_al->addr != tsym->start) {
794 /*
795 * Target is back to the middle of the symbol we came
796 * from so assume it is an indirect jmp and forget it
797 * altogether.
798 */
799 ts->cnt -= 1;
800 return 0;
801 }
802 } else if (sym && sym == tsym) {
803 /*
804 * Target is back to the symbol we came from so assume it is an
805 * indirect jmp and forget it altogether.
806 */
807 ts->cnt -= 1;
808 return 0;
809 }
810
811 cp = call_path__findnew(cpr, ts->stack[ts->cnt - 2].cp, tsym,
812 sample->addr, ts->kernel_start);
813 if (!cp)
814 return -ENOMEM;
815
816 /* Replace the top-of-stack with the actual target */
817 ts->stack[ts->cnt - 1].cp = cp;
818
819 return 0;
820}
821
693int thread_stack__process(struct thread *thread, struct comm *comm, 822int thread_stack__process(struct thread *thread, struct comm *comm,
694 struct perf_sample *sample, 823 struct perf_sample *sample,
695 struct addr_location *from_al, 824 struct addr_location *from_al,
@@ -697,6 +826,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
697 struct call_return_processor *crp) 826 struct call_return_processor *crp)
698{ 827{
699 struct thread_stack *ts = thread__stack(thread, sample->cpu); 828 struct thread_stack *ts = thread__stack(thread, sample->cpu);
829 enum retpoline_state_t rstate;
700 int err = 0; 830 int err = 0;
701 831
702 if (ts && !ts->crp) { 832 if (ts && !ts->crp) {
@@ -712,6 +842,10 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
712 ts->comm = comm; 842 ts->comm = comm;
713 } 843 }
714 844
845 rstate = ts->rstate;
846 if (rstate == X86_RETPOLINE_DETECTED)
847 ts->rstate = X86_RETPOLINE_POSSIBLE;
848
715 /* Flush stack on exec */ 849 /* Flush stack on exec */
716 if (ts->comm != comm && thread->pid_ == thread->tid) { 850 if (ts->comm != comm && thread->pid_ == thread->tid) {
717 err = __thread_stack__flush(thread, ts); 851 err = __thread_stack__flush(thread, ts);
@@ -748,10 +882,25 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
748 ts->kernel_start); 882 ts->kernel_start);
749 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref, 883 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
750 cp, false, trace_end); 884 cp, false, trace_end);
885
886 /*
887 * A call to the same symbol but not the start of the symbol,
888 * may be the start of a x86 retpoline.
889 */
890 if (!err && rstate == X86_RETPOLINE_POSSIBLE && to_al->sym &&
891 from_al->sym == to_al->sym &&
892 to_al->addr != to_al->sym->start)
893 ts->rstate = X86_RETPOLINE_DETECTED;
894
751 } else if (sample->flags & PERF_IP_FLAG_RETURN) { 895 } else if (sample->flags & PERF_IP_FLAG_RETURN) {
752 if (!sample->ip || !sample->addr) 896 if (!sample->ip || !sample->addr)
753 return 0; 897 return 0;
754 898
899 /* x86 retpoline 'return' doesn't match the stack */
900 if (rstate == X86_RETPOLINE_DETECTED && ts->cnt > 2 &&
901 ts->stack[ts->cnt - 1].ret_addr != sample->addr)
902 return thread_stack__x86_retpoline(ts, sample, to_al);
903
755 err = thread_stack__pop_cp(thread, ts, sample->addr, 904 err = thread_stack__pop_cp(thread, ts, sample->addr,
756 sample->time, ref, from_al->sym); 905 sample->time, ref, from_al->sym);
757 if (err) { 906 if (err) {
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 3ee410fc047a..d388f80d8703 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -21,6 +21,7 @@
21#include <linux/time64.h> 21#include <linux/time64.h>
22#include <unistd.h> 22#include <unistd.h>
23#include "strlist.h" 23#include "strlist.h"
24#include "string2.h"
24 25
25/* 26/*
26 * XXX We need to find a better place for these things... 27 * XXX We need to find a better place for these things...
@@ -117,7 +118,38 @@ int mkdir_p(char *path, mode_t mode)
117 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 118 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
118} 119}
119 120
120int rm_rf(const char *path) 121static bool match_pat(char *file, const char **pat)
122{
123 int i = 0;
124
125 if (!pat)
126 return true;
127
128 while (pat[i]) {
129 if (strglobmatch(file, pat[i]))
130 return true;
131
132 i++;
133 }
134
135 return false;
136}
137
138/*
139 * The depth specify how deep the removal will go.
140 * 0 - will remove only files under the 'path' directory
141 * 1 .. x - will dive in x-level deep under the 'path' directory
142 *
143 * If specified the pat is array of string patterns ended with NULL,
144 * which are checked upon every file/directory found. Only matching
145 * ones are removed.
146 *
147 * The function returns:
148 * 0 on success
149 * -1 on removal failure with errno set
150 * -2 on pattern failure
151 */
152static int rm_rf_depth_pat(const char *path, int depth, const char **pat)
121{ 153{
122 DIR *dir; 154 DIR *dir;
123 int ret; 155 int ret;
@@ -144,6 +176,9 @@ int rm_rf(const char *path)
144 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) 176 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
145 continue; 177 continue;
146 178
179 if (!match_pat(d->d_name, pat))
180 return -2;
181
147 scnprintf(namebuf, sizeof(namebuf), "%s/%s", 182 scnprintf(namebuf, sizeof(namebuf), "%s/%s",
148 path, d->d_name); 183 path, d->d_name);
149 184
@@ -155,7 +190,7 @@ int rm_rf(const char *path)
155 } 190 }
156 191
157 if (S_ISDIR(statbuf.st_mode)) 192 if (S_ISDIR(statbuf.st_mode))
158 ret = rm_rf(namebuf); 193 ret = depth ? rm_rf_depth_pat(namebuf, depth - 1, pat) : 0;
159 else 194 else
160 ret = unlink(namebuf); 195 ret = unlink(namebuf);
161 } 196 }
@@ -167,6 +202,22 @@ int rm_rf(const char *path)
167 return rmdir(path); 202 return rmdir(path);
168} 203}
169 204
205int rm_rf_perf_data(const char *path)
206{
207 const char *pat[] = {
208 "header",
209 "data.*",
210 NULL,
211 };
212
213 return rm_rf_depth_pat(path, 0, pat);
214}
215
216int rm_rf(const char *path)
217{
218 return rm_rf_depth_pat(path, INT_MAX, NULL);
219}
220
170/* A filter which removes dot files */ 221/* A filter which removes dot files */
171bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d) 222bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
172{ 223{
@@ -517,3 +568,13 @@ out:
517 568
518 return tip; 569 return tip;
519} 570}
571
572char *perf_exe(char *buf, int len)
573{
574 int n = readlink("/proc/self/exe", buf, len);
575 if (n > 0) {
576 buf[n] = 0;
577 return buf;
578 }
579 return strcpy(buf, "perf");
580}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index ece040b799f6..09c1b0f91f65 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -31,6 +31,7 @@ struct strlist;
31 31
32int mkdir_p(char *path, mode_t mode); 32int mkdir_p(char *path, mode_t mode);
33int rm_rf(const char *path); 33int rm_rf(const char *path);
34int rm_rf_perf_data(const char *path);
34struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *)); 35struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *));
35bool lsdir_no_dot_filter(const char *name, struct dirent *d); 36bool lsdir_no_dot_filter(const char *name, struct dirent *d);
36int copyfile(const char *from, const char *to); 37int copyfile(const char *from, const char *to);
@@ -76,6 +77,8 @@ extern bool perf_singlethreaded;
76void perf_set_singlethreaded(void); 77void perf_set_singlethreaded(void);
77void perf_set_multithreaded(void); 78void perf_set_multithreaded(void);
78 79
80char *perf_exe(char *buf, int len);
81
79#ifndef O_CLOEXEC 82#ifndef O_CLOEXEC
80#ifdef __sparc__ 83#ifdef __sparc__
81#define O_CLOEXEC 0x400000 84#define O_CLOEXEC 0x400000