summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-10 18:22:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-10 18:22:03 -0400
commit12ad143e1b803e541e48b8ba40f550250259ecdd (patch)
tree5202b407df21e5abaeb294d1ecddcf0a2eca7f8b /tools
parent262d6a9a63a387c8dfa9eb4f7713e159c941e52c (diff)
parentb339da480315505aa28a723a983217ebcff95c86 (diff)
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Thomas Gleixner: "Perf updates and fixes: Kernel: - Handle events which have the bpf_event attribute set as side band events as they carry information about BPF programs. - Add missing switch-case fall-through comments Libraries: - Fix leaks and double frees in error code paths. - Prevent buffer overflows in libtraceevent Tools: - Improvements in handling Intel BT/PTS - Add BTF ELF markers to perf trace BPF programs to improve output - Support --time, --cpu, --pid and --tid filters for perf diff - Calculate the column width in perf annotate as the hardcoded 6 characters for the instruction are not sufficient - Small fixes all over the place" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (38 commits) perf/core: Mark expected switch fall-through perf/x86/intel/uncore: Fix client IMC events return huge result perf/ring_buffer: Use high order allocations for AUX buffers optimistically perf data: Force perf_data__open|close zero data->file.path perf session: Fix double free in perf_data__close perf evsel: Probe for precise_ip with simple attr perf tools: Read and store caps/max_precise in perf_pmu perf hist: Fix memory leak of srcline perf hist: Add error path into hist_entry__init perf c2c: Fix c2c report for empty numa node perf script python: Add Python3 support to intel-pt-events.py perf script python: Add Python3 support to event_analyzing_sample.py perf script python: add Python3 support to check-perf-trace.py perf script python: Add Python3 support to futex-contention.py perf script python: Remove mixed indentation perf diff: Support --pid/--tid filter options perf diff: Support --cpu filter option perf diff: Support --time filter option perf thread: Generalize function to copy from thread addr space from intel-bts code perf annotate: Calculate the max instruction name, align column to that ...
Diffstat (limited to 'tools')
-rw-r--r--tools/lib/traceevent/event-parse.c2
-rw-r--r--tools/perf/Documentation/perf-diff.txt56
-rw-r--r--tools/perf/arch/arm64/annotate/instructions.c2
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c2
-rw-r--r--tools/perf/builtin-c2c.c8
-rw-r--r--tools/perf/builtin-diff.c168
-rw-r--r--tools/perf/builtin-report.c38
-rw-r--r--tools/perf/builtin-script.c39
-rw-r--r--tools/perf/include/bpf/bpf.h8
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py76
-rw-r--r--tools/perf/scripts/python/compaction-times.py8
-rw-r--r--tools/perf/scripts/python/event_analyzing_sample.py48
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py16
-rw-r--r--tools/perf/scripts/python/export-to-sqlite.py12
-rwxr-xr-xtools/perf/scripts/python/exported-sql-viewer.py354
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py38
-rw-r--r--tools/perf/scripts/python/futex-contention.py10
-rw-r--r--tools/perf/scripts/python/intel-pt-events.py60
-rw-r--r--tools/perf/scripts/python/mem-phys-addr.py7
-rwxr-xr-xtools/perf/scripts/python/net_dropmonitor.py2
-rw-r--r--tools/perf/scripts/python/netdev-times.py12
-rw-r--r--tools/perf/scripts/python/sched-migration.py6
-rw-r--r--tools/perf/scripts/python/sctop.py13
-rwxr-xr-xtools/perf/scripts/python/stackcollapse.py2
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py47
-rw-r--r--tools/perf/scripts/python/syscall-counts.py31
-rw-r--r--tools/perf/trace/beauty/msg_flags.c2
-rw-r--r--tools/perf/util/annotate.c74
-rw-r--r--tools/perf/util/annotate.h7
-rw-r--r--tools/perf/util/auxtrace.c3
-rw-r--r--tools/perf/util/c++/clang.cpp2
-rw-r--r--tools/perf/util/data.c4
-rw-r--r--tools/perf/util/db-export.c15
-rw-r--r--tools/perf/util/db-export.h3
-rw-r--r--tools/perf/util/evlist.c25
-rw-r--r--tools/perf/util/evsel.c8
-rw-r--r--tools/perf/util/hist.c51
-rw-r--r--tools/perf/util/intel-bts.c20
-rw-r--r--tools/perf/util/intel-pt.c2
-rw-r--r--tools/perf/util/pmu.c14
-rw-r--r--tools/perf/util/pmu.h1
-rw-r--r--tools/perf/util/probe-event.c9
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c8
-rw-r--r--tools/perf/util/session.c4
-rw-r--r--tools/perf/util/thread-stack.c16
-rw-r--r--tools/perf/util/thread-stack.h6
-rw-r--r--tools/perf/util/thread.c23
-rw-r--r--tools/perf/util/thread.h3
-rw-r--r--tools/perf/util/time-utils.c51
-rw-r--r--tools/perf/util/time-utils.h6
50 files changed, 975 insertions, 447 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index abd4fa5d3088..87494c7c619d 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -2457,7 +2457,7 @@ static int arg_num_eval(struct tep_print_arg *arg, long long *val)
2457static char *arg_eval (struct tep_print_arg *arg) 2457static char *arg_eval (struct tep_print_arg *arg)
2458{ 2458{
2459 long long val; 2459 long long val;
2460 static char buf[20]; 2460 static char buf[24];
2461 2461
2462 switch (arg->type) { 2462 switch (arg->type) {
2463 case TEP_PRINT_ATOM: 2463 case TEP_PRINT_ATOM:
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index a79c84ae61aa..da7809b15cc9 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -118,6 +118,62 @@ OPTIONS
118 sum of shown entries will be always 100%. "absolute" means it retains 118 sum of shown entries will be always 100%. "absolute" means it retains
119 the original value before and after the filter is applied. 119 the original value before and after the filter is applied.
120 120
121--time::
122 Analyze samples within given time window. It supports time
123 percent with multiple time ranges. Time string is 'a%/n,b%/m,...'
124 or 'a%-b%,c%-%d,...'.
125
126 For example:
127
128 Select the second 10% time slice to diff:
129
130 perf diff --time 10%/2
131
132 Select from 0% to 10% time slice to diff:
133
134 perf diff --time 0%-10%
135
136 Select the first and the second 10% time slices to diff:
137
138 perf diff --time 10%/1,10%/2
139
140 Select from 0% to 10% and 30% to 40% slices to diff:
141
142 perf diff --time 0%-10%,30%-40%
143
144 It also supports analyzing samples within a given time window
145 <start>,<stop>. Times have the format seconds.microseconds. If 'start'
146 is not given (i.e., time string is ',x.y') then analysis starts at
147 the beginning of the file. If stop time is not given (i.e, time
148 string is 'x.y,') then analysis goes to the end of the file. Time string is
149 'a1.b1,c1.d1:a2.b2,c2.d2'. Use ':' to separate timestamps for different
150 perf.data files.
151
152 For example, we get the timestamp information from 'perf script'.
153
154 perf script -i perf.data.old
155 mgen 13940 [000] 3946.361400: ...
156
157 perf script -i perf.data
158 mgen 13940 [000] 3971.150589 ...
159
160 perf diff --time 3946.361400,:3971.150589,
161
162 It analyzes the perf.data.old from the timestamp 3946.361400 to
163 the end of perf.data.old and analyzes the perf.data from the
164 timestamp 3971.150589 to the end of perf.data.
165
166--cpu:: Only diff samples for the list of CPUs provided. Multiple CPUs can
167 be provided as a comma-separated list with no space: 0,1. Ranges of
168 CPUs are specified with -: 0-2. Default is to report samples on all
169 CPUs.
170
171--pid=::
172 Only diff samples for given process ID (comma separated list).
173
174--tid=::
175 Only diff samples for given thread ID (comma separated list).
176
121COMPARISON 177COMPARISON
122---------- 178----------
123The comparison is governed by the baseline file. The baseline perf.data 179The comparison is governed by the baseline file. The baseline perf.data
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 76c6345a57d5..8f70a1b282df 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -58,7 +58,7 @@ out_free_source:
58} 58}
59 59
60static int mov__scnprintf(struct ins *ins, char *bf, size_t size, 60static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
61 struct ins_operands *ops); 61 struct ins_operands *ops, int max_ins_name);
62 62
63static struct ins_ops arm64_mov_ops = { 63static struct ins_ops arm64_mov_ops = {
64 .parse = arm64_mov__parse, 64 .parse = arm64_mov__parse,
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index de0dd66dbb48..89bb8f2c54ce 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -46,7 +46,7 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
46} 46}
47 47
48static int call__scnprintf(struct ins *ins, char *bf, size_t size, 48static int call__scnprintf(struct ins *ins, char *bf, size_t size,
49 struct ins_operands *ops); 49 struct ins_operands *ops, int max_ins_name);
50 50
51static struct ins_ops s390_call_ops = { 51static struct ins_ops s390_call_ops = {
52 .parse = s390_call__parse, 52 .parse = s390_call__parse,
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 4272763a5e96..9e6cc868bdb4 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -2056,6 +2056,12 @@ static int setup_nodes(struct perf_session *session)
2056 if (!set) 2056 if (!set)
2057 return -ENOMEM; 2057 return -ENOMEM;
2058 2058
2059 nodes[node] = set;
2060
2061 /* empty node, skip */
2062 if (cpu_map__empty(map))
2063 continue;
2064
2059 for (cpu = 0; cpu < map->nr; cpu++) { 2065 for (cpu = 0; cpu < map->nr; cpu++) {
2060 set_bit(map->map[cpu], set); 2066 set_bit(map->map[cpu], set);
2061 2067
@@ -2064,8 +2070,6 @@ static int setup_nodes(struct perf_session *session)
2064 2070
2065 cpu2node[map->map[cpu]] = node; 2071 cpu2node[map->map[cpu]] = node;
2066 } 2072 }
2067
2068 nodes[node] = set;
2069 } 2073 }
2070 2074
2071 setup_nodes_header(); 2075 setup_nodes_header();
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 58fe0e88215c..6e7920793729 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -19,12 +19,21 @@
19#include "util/util.h" 19#include "util/util.h"
20#include "util/data.h" 20#include "util/data.h"
21#include "util/config.h" 21#include "util/config.h"
22#include "util/time-utils.h"
22 23
23#include <errno.h> 24#include <errno.h>
24#include <inttypes.h> 25#include <inttypes.h>
25#include <stdlib.h> 26#include <stdlib.h>
26#include <math.h> 27#include <math.h>
27 28
29struct perf_diff {
30 struct perf_tool tool;
31 const char *time_str;
32 struct perf_time_interval *ptime_range;
33 int range_size;
34 int range_num;
35};
36
28/* Diff command specific HPP columns. */ 37/* Diff command specific HPP columns. */
29enum { 38enum {
30 PERF_HPP_DIFF__BASELINE, 39 PERF_HPP_DIFF__BASELINE,
@@ -74,6 +83,9 @@ static unsigned int sort_compute = 1;
74static s64 compute_wdiff_w1; 83static s64 compute_wdiff_w1;
75static s64 compute_wdiff_w2; 84static s64 compute_wdiff_w2;
76 85
86static const char *cpu_list;
87static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
88
77enum { 89enum {
78 COMPUTE_DELTA, 90 COMPUTE_DELTA,
79 COMPUTE_RATIO, 91 COMPUTE_RATIO,
@@ -323,22 +335,33 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
323 return -1; 335 return -1;
324} 336}
325 337
326static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, 338static int diff__process_sample_event(struct perf_tool *tool,
327 union perf_event *event, 339 union perf_event *event,
328 struct perf_sample *sample, 340 struct perf_sample *sample,
329 struct perf_evsel *evsel, 341 struct perf_evsel *evsel,
330 struct machine *machine) 342 struct machine *machine)
331{ 343{
344 struct perf_diff *pdiff = container_of(tool, struct perf_diff, tool);
332 struct addr_location al; 345 struct addr_location al;
333 struct hists *hists = evsel__hists(evsel); 346 struct hists *hists = evsel__hists(evsel);
334 int ret = -1; 347 int ret = -1;
335 348
349 if (perf_time__ranges_skip_sample(pdiff->ptime_range, pdiff->range_num,
350 sample->time)) {
351 return 0;
352 }
353
336 if (machine__resolve(machine, &al, sample) < 0) { 354 if (machine__resolve(machine, &al, sample) < 0) {
337 pr_warning("problem processing %d event, skipping it.\n", 355 pr_warning("problem processing %d event, skipping it.\n",
338 event->header.type); 356 event->header.type);
339 return -1; 357 return -1;
340 } 358 }
341 359
360 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) {
361 ret = 0;
362 goto out_put;
363 }
364
342 if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample, true)) { 365 if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample, true)) {
343 pr_warning("problem incrementing symbol period, skipping event\n"); 366 pr_warning("problem incrementing symbol period, skipping event\n");
344 goto out_put; 367 goto out_put;
@@ -359,17 +382,19 @@ out_put:
359 return ret; 382 return ret;
360} 383}
361 384
362static struct perf_tool tool = { 385static struct perf_diff pdiff = {
363 .sample = diff__process_sample_event, 386 .tool = {
364 .mmap = perf_event__process_mmap, 387 .sample = diff__process_sample_event,
365 .mmap2 = perf_event__process_mmap2, 388 .mmap = perf_event__process_mmap,
366 .comm = perf_event__process_comm, 389 .mmap2 = perf_event__process_mmap2,
367 .exit = perf_event__process_exit, 390 .comm = perf_event__process_comm,
368 .fork = perf_event__process_fork, 391 .exit = perf_event__process_exit,
369 .lost = perf_event__process_lost, 392 .fork = perf_event__process_fork,
370 .namespaces = perf_event__process_namespaces, 393 .lost = perf_event__process_lost,
371 .ordered_events = true, 394 .namespaces = perf_event__process_namespaces,
372 .ordering_requires_timestamps = true, 395 .ordered_events = true,
396 .ordering_requires_timestamps = true,
397 },
373}; 398};
374 399
375static struct perf_evsel *evsel_match(struct perf_evsel *evsel, 400static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
@@ -771,19 +796,117 @@ static void data__free(struct data__file *d)
771 } 796 }
772} 797}
773 798
799static int abstime_str_dup(char **pstr)
800{
801 char *str = NULL;
802
803 if (pdiff.time_str && strchr(pdiff.time_str, ':')) {
804 str = strdup(pdiff.time_str);
805 if (!str)
806 return -ENOMEM;
807 }
808
809 *pstr = str;
810 return 0;
811}
812
813static int parse_absolute_time(struct data__file *d, char **pstr)
814{
815 char *p = *pstr;
816 int ret;
817
818 /*
819 * Absolute timestamp for one file has the format: a.b,c.d
820 * For multiple files, the format is: a.b,c.d:a.b,c.d
821 */
822 p = strchr(*pstr, ':');
823 if (p) {
824 if (p == *pstr) {
825 pr_err("Invalid time string\n");
826 return -EINVAL;
827 }
828
829 *p = 0;
830 p++;
831 if (*p == 0) {
832 pr_err("Invalid time string\n");
833 return -EINVAL;
834 }
835 }
836
837 ret = perf_time__parse_for_ranges(*pstr, d->session,
838 &pdiff.ptime_range,
839 &pdiff.range_size,
840 &pdiff.range_num);
841 if (ret < 0)
842 return ret;
843
844 if (!p || *p == 0)
845 *pstr = NULL;
846 else
847 *pstr = p;
848
849 return ret;
850}
851
852static int parse_percent_time(struct data__file *d)
853{
854 int ret;
855
856 ret = perf_time__parse_for_ranges(pdiff.time_str, d->session,
857 &pdiff.ptime_range,
858 &pdiff.range_size,
859 &pdiff.range_num);
860 return ret;
861}
862
863static int parse_time_str(struct data__file *d, char *abstime_ostr,
864 char **pabstime_tmp)
865{
866 int ret = 0;
867
868 if (abstime_ostr)
869 ret = parse_absolute_time(d, pabstime_tmp);
870 else if (pdiff.time_str)
871 ret = parse_percent_time(d);
872
873 return ret;
874}
875
774static int __cmd_diff(void) 876static int __cmd_diff(void)
775{ 877{
776 struct data__file *d; 878 struct data__file *d;
777 int ret = -EINVAL, i; 879 int ret, i;
880 char *abstime_ostr, *abstime_tmp;
881
882 ret = abstime_str_dup(&abstime_ostr);
883 if (ret)
884 return ret;
885
886 abstime_tmp = abstime_ostr;
887 ret = -EINVAL;
778 888
779 data__for_each_file(i, d) { 889 data__for_each_file(i, d) {
780 d->session = perf_session__new(&d->data, false, &tool); 890 d->session = perf_session__new(&d->data, false, &pdiff.tool);
781 if (!d->session) { 891 if (!d->session) {
782 pr_err("Failed to open %s\n", d->data.path); 892 pr_err("Failed to open %s\n", d->data.path);
783 ret = -1; 893 ret = -1;
784 goto out_delete; 894 goto out_delete;
785 } 895 }
786 896
897 if (pdiff.time_str) {
898 ret = parse_time_str(d, abstime_ostr, &abstime_tmp);
899 if (ret < 0)
900 goto out_delete;
901 }
902
903 if (cpu_list) {
904 ret = perf_session__cpu_bitmap(d->session, cpu_list,
905 cpu_bitmap);
906 if (ret < 0)
907 goto out_delete;
908 }
909
787 ret = perf_session__process_events(d->session); 910 ret = perf_session__process_events(d->session);
788 if (ret) { 911 if (ret) {
789 pr_err("Failed to process %s\n", d->data.path); 912 pr_err("Failed to process %s\n", d->data.path);
@@ -791,6 +914,9 @@ static int __cmd_diff(void)
791 } 914 }
792 915
793 perf_evlist__collapse_resort(d->session->evlist); 916 perf_evlist__collapse_resort(d->session->evlist);
917
918 if (pdiff.ptime_range)
919 zfree(&pdiff.ptime_range);
794 } 920 }
795 921
796 data_process(); 922 data_process();
@@ -802,6 +928,13 @@ static int __cmd_diff(void)
802 } 928 }
803 929
804 free(data__files); 930 free(data__files);
931
932 if (pdiff.ptime_range)
933 zfree(&pdiff.ptime_range);
934
935 if (abstime_ostr)
936 free(abstime_ostr);
937
805 return ret; 938 return ret;
806} 939}
807 940
@@ -849,6 +982,13 @@ static const struct option options[] = {
849 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), 982 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
850 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 983 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
851 "How to display percentage of filtered entries", parse_filter_percentage), 984 "How to display percentage of filtered entries", parse_filter_percentage),
985 OPT_STRING(0, "time", &pdiff.time_str, "str",
986 "Time span (time percent or absolute timestamp)"),
987 OPT_STRING(0, "cpu", &cpu_list, "cpu", "list of cpus to profile"),
988 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
989 "only consider symbols in these pids"),
990 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
991 "only consider symbols in these tids"),
852 OPT_END() 992 OPT_END()
853}; 993};
854 994
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 1532ebde6c4b..ee93c18a6685 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1375,36 +1375,13 @@ repeat:
1375 if (symbol__init(&session->header.env) < 0) 1375 if (symbol__init(&session->header.env) < 0)
1376 goto error; 1376 goto error;
1377 1377
1378 report.ptime_range = perf_time__range_alloc(report.time_str, 1378 if (report.time_str) {
1379 &report.range_size); 1379 ret = perf_time__parse_for_ranges(report.time_str, session,
1380 if (!report.ptime_range) { 1380 &report.ptime_range,
1381 ret = -ENOMEM; 1381 &report.range_size,
1382 goto error; 1382 &report.range_num);
1383 } 1383 if (ret < 0)
1384
1385 if (perf_time__parse_str(report.ptime_range, report.time_str) != 0) {
1386 if (session->evlist->first_sample_time == 0 &&
1387 session->evlist->last_sample_time == 0) {
1388 pr_err("HINT: no first/last sample time found in perf data.\n"
1389 "Please use latest perf binary to execute 'perf record'\n"
1390 "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n");
1391 ret = -EINVAL;
1392 goto error;
1393 }
1394
1395 report.range_num = perf_time__percent_parse_str(
1396 report.ptime_range, report.range_size,
1397 report.time_str,
1398 session->evlist->first_sample_time,
1399 session->evlist->last_sample_time);
1400
1401 if (report.range_num < 0) {
1402 pr_err("Invalid time string\n");
1403 ret = -EINVAL;
1404 goto error; 1384 goto error;
1405 }
1406 } else {
1407 report.range_num = 1;
1408 } 1385 }
1409 1386
1410 if (session->tevent.pevent && 1387 if (session->tevent.pevent &&
@@ -1426,7 +1403,8 @@ repeat:
1426 ret = 0; 1403 ret = 0;
1427 1404
1428error: 1405error:
1429 zfree(&report.ptime_range); 1406 if (report.ptime_range)
1407 zfree(&report.ptime_range);
1430 1408
1431 perf_session__delete(session); 1409 perf_session__delete(session);
1432 return ret; 1410 return ret;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 2d8cb1d1682c..53f78cf3113f 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -3699,37 +3699,13 @@ int cmd_script(int argc, const char **argv)
3699 if (err < 0) 3699 if (err < 0)
3700 goto out_delete; 3700 goto out_delete;
3701 3701
3702 script.ptime_range = perf_time__range_alloc(script.time_str, 3702 if (script.time_str) {
3703 &script.range_size); 3703 err = perf_time__parse_for_ranges(script.time_str, session,
3704 if (!script.ptime_range) { 3704 &script.ptime_range,
3705 err = -ENOMEM; 3705 &script.range_size,
3706 goto out_delete; 3706 &script.range_num);
3707 } 3707 if (err < 0)
3708
3709 /* needs to be parsed after looking up reference time */
3710 if (perf_time__parse_str(script.ptime_range, script.time_str) != 0) {
3711 if (session->evlist->first_sample_time == 0 &&
3712 session->evlist->last_sample_time == 0) {
3713 pr_err("HINT: no first/last sample time found in perf data.\n"
3714 "Please use latest perf binary to execute 'perf record'\n"
3715 "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n");
3716 err = -EINVAL;
3717 goto out_delete;
3718 }
3719
3720 script.range_num = perf_time__percent_parse_str(
3721 script.ptime_range, script.range_size,
3722 script.time_str,
3723 session->evlist->first_sample_time,
3724 session->evlist->last_sample_time);
3725
3726 if (script.range_num < 0) {
3727 pr_err("Invalid time string\n");
3728 err = -EINVAL;
3729 goto out_delete; 3708 goto out_delete;
3730 }
3731 } else {
3732 script.range_num = 1;
3733 } 3709 }
3734 3710
3735 err = __cmd_script(&script); 3711 err = __cmd_script(&script);
@@ -3737,7 +3713,8 @@ int cmd_script(int argc, const char **argv)
3737 flush_scripting(); 3713 flush_scripting();
3738 3714
3739out_delete: 3715out_delete:
3740 zfree(&script.ptime_range); 3716 if (script.ptime_range)
3717 zfree(&script.ptime_range);
3741 3718
3742 perf_evlist__free_stats(session->evlist); 3719 perf_evlist__free_stats(session->evlist);
3743 perf_session__delete(session); 3720 perf_session__delete(session);
diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h
index 5df7ed9d9020..2eac6d804b2d 100644
--- a/tools/perf/include/bpf/bpf.h
+++ b/tools/perf/include/bpf/bpf.h
@@ -24,7 +24,13 @@ struct bpf_map SEC("maps") name = { \
24 .key_size = sizeof(type_key), \ 24 .key_size = sizeof(type_key), \
25 .value_size = sizeof(type_val), \ 25 .value_size = sizeof(type_val), \
26 .max_entries = _max_entries, \ 26 .max_entries = _max_entries, \
27} 27}; \
28struct ____btf_map_##name { \
29 type_key key; \
30 type_val value; \
31}; \
32struct ____btf_map_##name __attribute__((section(".maps." #name), used)) \
33 ____btf_map_##name = { }
28 34
29/* 35/*
30 * FIXME: this should receive .max_entries as a parameter, as careful 36 * FIXME: this should receive .max_entries as a parameter, as careful
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 334599c6032c..d2c22954800d 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -7,6 +7,8 @@
7# events, etc. Basically, if this script runs successfully and 7# events, etc. Basically, if this script runs successfully and
8# displays expected results, Python scripting support should be ok. 8# displays expected results, Python scripting support should be ok.
9 9
10from __future__ import print_function
11
10import os 12import os
11import sys 13import sys
12 14
@@ -19,64 +21,64 @@ from perf_trace_context import *
19unhandled = autodict() 21unhandled = autodict()
20 22
21def trace_begin(): 23def trace_begin():
22 print "trace_begin" 24 print("trace_begin")
23 pass 25 pass
24 26
25def trace_end(): 27def trace_end():
26 print_unhandled() 28 print_unhandled()
27 29
28def irq__softirq_entry(event_name, context, common_cpu, 30def irq__softirq_entry(event_name, context, common_cpu,
29 common_secs, common_nsecs, common_pid, common_comm, 31 common_secs, common_nsecs, common_pid, common_comm,
30 common_callchain, vec): 32 common_callchain, vec):
31 print_header(event_name, common_cpu, common_secs, common_nsecs, 33 print_header(event_name, common_cpu, common_secs, common_nsecs,
32 common_pid, common_comm) 34 common_pid, common_comm)
33 35
34 print_uncommon(context) 36 print_uncommon(context)
35 37
36 print "vec=%s\n" % \ 38 print("vec=%s" % (symbol_str("irq__softirq_entry", "vec", vec)))
37 (symbol_str("irq__softirq_entry", "vec", vec)),
38 39
39def kmem__kmalloc(event_name, context, common_cpu, 40def kmem__kmalloc(event_name, context, common_cpu,
40 common_secs, common_nsecs, common_pid, common_comm, 41 common_secs, common_nsecs, common_pid, common_comm,
41 common_callchain, call_site, ptr, bytes_req, bytes_alloc, 42 common_callchain, call_site, ptr, bytes_req, bytes_alloc,
42 gfp_flags): 43 gfp_flags):
43 print_header(event_name, common_cpu, common_secs, common_nsecs, 44 print_header(event_name, common_cpu, common_secs, common_nsecs,
44 common_pid, common_comm) 45 common_pid, common_comm)
45 46
46 print_uncommon(context) 47 print_uncommon(context)
47 48
48 print "call_site=%u, ptr=%u, bytes_req=%u, " \ 49 print("call_site=%u, ptr=%u, bytes_req=%u, "
49 "bytes_alloc=%u, gfp_flags=%s\n" % \ 50 "bytes_alloc=%u, gfp_flags=%s" %
50 (call_site, ptr, bytes_req, bytes_alloc, 51 (call_site, ptr, bytes_req, bytes_alloc,
51 52 flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)))
52 flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)),
53 53
54def trace_unhandled(event_name, context, event_fields_dict): 54def trace_unhandled(event_name, context, event_fields_dict):
55 try: 55 try:
56 unhandled[event_name] += 1 56 unhandled[event_name] += 1
57 except TypeError: 57 except TypeError:
58 unhandled[event_name] = 1 58 unhandled[event_name] = 1
59 59
60def print_header(event_name, cpu, secs, nsecs, pid, comm): 60def print_header(event_name, cpu, secs, nsecs, pid, comm):
61 print "%-20s %5u %05u.%09u %8u %-20s " % \ 61 print("%-20s %5u %05u.%09u %8u %-20s " %
62 (event_name, cpu, secs, nsecs, pid, comm), 62 (event_name, cpu, secs, nsecs, pid, comm),
63 end=' ')
63 64
64# print trace fields not included in handler args 65# print trace fields not included in handler args
65def print_uncommon(context): 66def print_uncommon(context):
66 print "common_preempt_count=%d, common_flags=%s, common_lock_depth=%d, " \ 67 print("common_preempt_count=%d, common_flags=%s, "
67 % (common_pc(context), trace_flag_str(common_flags(context)), \ 68 "common_lock_depth=%d, " %
68 common_lock_depth(context)) 69 (common_pc(context), trace_flag_str(common_flags(context)),
70 common_lock_depth(context)))
69 71
70def print_unhandled(): 72def print_unhandled():
71 keys = unhandled.keys() 73 keys = unhandled.keys()
72 if not keys: 74 if not keys:
73 return 75 return
74 76
75 print "\nunhandled events:\n\n", 77 print("\nunhandled events:\n")
76 78
77 print "%-40s %10s\n" % ("event", "count"), 79 print("%-40s %10s" % ("event", "count"))
78 print "%-40s %10s\n" % ("----------------------------------------", \ 80 print("%-40s %10s" % ("----------------------------------------",
79 "-----------"), 81 "-----------"))
80 82
81 for event_name in keys: 83 for event_name in keys:
82 print "%-40s %10d\n" % (event_name, unhandled[event_name]) 84 print("%-40s %10d\n" % (event_name, unhandled[event_name]))
diff --git a/tools/perf/scripts/python/compaction-times.py b/tools/perf/scripts/python/compaction-times.py
index 239cb0568ec3..2560a042dc6f 100644
--- a/tools/perf/scripts/python/compaction-times.py
+++ b/tools/perf/scripts/python/compaction-times.py
@@ -216,15 +216,15 @@ def compaction__mm_compaction_migratepages(event_name, context, common_cpu,
216 pair(nr_migrated, nr_failed), None, None) 216 pair(nr_migrated, nr_failed), None, None)
217 217
218def compaction__mm_compaction_isolate_freepages(event_name, context, common_cpu, 218def compaction__mm_compaction_isolate_freepages(event_name, context, common_cpu,
219 common_secs, common_nsecs, common_pid, common_comm, 219 common_secs, common_nsecs, common_pid, common_comm,
220 common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): 220 common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken):
221 221
222 chead.increment_pending(common_pid, 222 chead.increment_pending(common_pid,
223 None, pair(nr_scanned, nr_taken), None) 223 None, pair(nr_scanned, nr_taken), None)
224 224
225def compaction__mm_compaction_isolate_migratepages(event_name, context, common_cpu, 225def compaction__mm_compaction_isolate_migratepages(event_name, context, common_cpu,
226 common_secs, common_nsecs, common_pid, common_comm, 226 common_secs, common_nsecs, common_pid, common_comm,
227 common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken): 227 common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken):
228 228
229 chead.increment_pending(common_pid, 229 chead.increment_pending(common_pid,
230 None, None, pair(nr_scanned, nr_taken)) 230 None, None, pair(nr_scanned, nr_taken))
diff --git a/tools/perf/scripts/python/event_analyzing_sample.py b/tools/perf/scripts/python/event_analyzing_sample.py
index 4e843b9864ec..aa1e2cfa26a6 100644
--- a/tools/perf/scripts/python/event_analyzing_sample.py
+++ b/tools/perf/scripts/python/event_analyzing_sample.py
@@ -15,6 +15,8 @@
15# for a x86 HW PMU event: PEBS with load latency data. 15# for a x86 HW PMU event: PEBS with load latency data.
16# 16#
17 17
18from __future__ import print_function
19
18import os 20import os
19import sys 21import sys
20import math 22import math
@@ -37,7 +39,7 @@ con = sqlite3.connect("/dev/shm/perf.db")
37con.isolation_level = None 39con.isolation_level = None
38 40
39def trace_begin(): 41def trace_begin():
40 print "In trace_begin:\n" 42 print("In trace_begin:\n")
41 43
42 # 44 #
43 # Will create several tables at the start, pebs_ll is for PEBS data with 45 # Will create several tables at the start, pebs_ll is for PEBS data with
@@ -76,12 +78,12 @@ def process_event(param_dict):
76 name = param_dict["ev_name"] 78 name = param_dict["ev_name"]
77 79
78 # Symbol and dso info are not always resolved 80 # Symbol and dso info are not always resolved
79 if (param_dict.has_key("dso")): 81 if ("dso" in param_dict):
80 dso = param_dict["dso"] 82 dso = param_dict["dso"]
81 else: 83 else:
82 dso = "Unknown_dso" 84 dso = "Unknown_dso"
83 85
84 if (param_dict.has_key("symbol")): 86 if ("symbol" in param_dict):
85 symbol = param_dict["symbol"] 87 symbol = param_dict["symbol"]
86 else: 88 else:
87 symbol = "Unknown_symbol" 89 symbol = "Unknown_symbol"
@@ -102,7 +104,7 @@ def insert_db(event):
102 event.ip, event.status, event.dse, event.dla, event.lat)) 104 event.ip, event.status, event.dse, event.dla, event.lat))
103 105
104def trace_end(): 106def trace_end():
105 print "In trace_end:\n" 107 print("In trace_end:\n")
106 # We show the basic info for the 2 type of event classes 108 # We show the basic info for the 2 type of event classes
107 show_general_events() 109 show_general_events()
108 show_pebs_ll() 110 show_pebs_ll()
@@ -123,29 +125,29 @@ def show_general_events():
123 # Check the total record number in the table 125 # Check the total record number in the table
124 count = con.execute("select count(*) from gen_events") 126 count = con.execute("select count(*) from gen_events")
125 for t in count: 127 for t in count:
126 print "There is %d records in gen_events table" % t[0] 128 print("There is %d records in gen_events table" % t[0])
127 if t[0] == 0: 129 if t[0] == 0:
128 return 130 return
129 131
130 print "Statistics about the general events grouped by thread/symbol/dso: \n" 132 print("Statistics about the general events grouped by thread/symbol/dso: \n")
131 133
132 # Group by thread 134 # Group by thread
133 commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)") 135 commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)")
134 print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) 136 print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42))
135 for row in commq: 137 for row in commq:
136 print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) 138 print("%16s %8d %s" % (row[0], row[1], num2sym(row[1])))
137 139
138 # Group by symbol 140 # Group by symbol
139 print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) 141 print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58))
140 symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)") 142 symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)")
141 for row in symbolq: 143 for row in symbolq:
142 print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 144 print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
143 145
144 # Group by dso 146 # Group by dso
145 print "\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74) 147 print("\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74))
146 dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)") 148 dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)")
147 for row in dsoq: 149 for row in dsoq:
148 print "%40s %8d %s" % (row[0], row[1], num2sym(row[1])) 150 print("%40s %8d %s" % (row[0], row[1], num2sym(row[1])))
149 151
150# 152#
151# This function just shows the basic info, and we could do more with the 153# This function just shows the basic info, and we could do more with the
@@ -156,35 +158,35 @@ def show_pebs_ll():
156 158
157 count = con.execute("select count(*) from pebs_ll") 159 count = con.execute("select count(*) from pebs_ll")
158 for t in count: 160 for t in count:
159 print "There is %d records in pebs_ll table" % t[0] 161 print("There is %d records in pebs_ll table" % t[0])
160 if t[0] == 0: 162 if t[0] == 0:
161 return 163 return
162 164
163 print "Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n" 165 print("Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n")
164 166
165 # Group by thread 167 # Group by thread
166 commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)") 168 commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)")
167 print "\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42) 169 print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42))
168 for row in commq: 170 for row in commq:
169 print "%16s %8d %s" % (row[0], row[1], num2sym(row[1])) 171 print("%16s %8d %s" % (row[0], row[1], num2sym(row[1])))
170 172
171 # Group by symbol 173 # Group by symbol
172 print "\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58) 174 print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58))
173 symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)") 175 symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)")
174 for row in symbolq: 176 for row in symbolq:
175 print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 177 print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
176 178
177 # Group by dse 179 # Group by dse
178 dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)") 180 dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)")
179 print "\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58) 181 print("\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58))
180 for row in dseq: 182 for row in dseq:
181 print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 183 print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
182 184
183 # Group by latency 185 # Group by latency
184 latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat") 186 latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat")
185 print "\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58) 187 print("\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58))
186 for row in latq: 188 for row in latq:
187 print "%32s %8d %s" % (row[0], row[1], num2sym(row[1])) 189 print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
188 190
189def trace_unhandled(event_name, context, event_fields_dict): 191def trace_unhandled(event_name, context, event_fields_dict):
190 print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) 192 print (' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 30130213da7e..390a351d15ea 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -394,7 +394,8 @@ if perf_db_export_calls:
394 'call_id bigint,' 394 'call_id bigint,'
395 'return_id bigint,' 395 'return_id bigint,'
396 'parent_call_path_id bigint,' 396 'parent_call_path_id bigint,'
397 'flags integer)') 397 'flags integer,'
398 'parent_id bigint)')
398 399
399do_query(query, 'CREATE VIEW machines_view AS ' 400do_query(query, 'CREATE VIEW machines_view AS '
400 'SELECT ' 401 'SELECT '
@@ -478,8 +479,9 @@ if perf_db_export_calls:
478 'branch_count,' 479 'branch_count,'
479 'call_id,' 480 'call_id,'
480 'return_id,' 481 'return_id,'
481 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' 482 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE CAST ( flags AS VARCHAR(6) ) END AS flags,'
482 'parent_call_path_id' 483 'parent_call_path_id,'
484 'calls.parent_id'
483 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') 485 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
484 486
485do_query(query, 'CREATE VIEW samples_view AS ' 487do_query(query, 'CREATE VIEW samples_view AS '
@@ -575,6 +577,7 @@ def trace_begin():
575 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 577 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
576 if perf_db_export_calls or perf_db_export_callchains: 578 if perf_db_export_calls or perf_db_export_callchains:
577 call_path_table(0, 0, 0, 0) 579 call_path_table(0, 0, 0, 0)
580 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
578 581
579unhandled_count = 0 582unhandled_count = 0
580 583
@@ -657,6 +660,7 @@ def trace_end():
657 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),' 660 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),'
658 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)') 661 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)')
659 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 662 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
663 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
660 664
661 if (unhandled_count): 665 if (unhandled_count):
662 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 666 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events"
@@ -728,7 +732,7 @@ def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
728 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip) 732 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip)
729 call_path_file.write(value) 733 call_path_file.write(value)
730 734
731def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x): 735def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, parent_id, *x):
732 fmt = "!hiqiqiqiqiqiqiqiqiqiqii" 736 fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiq"
733 value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags) 737 value = struct.pack(fmt, 12, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id)
734 call_file.write(value) 738 call_file.write(value)
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py
index ed237f2ed03f..eb63e6c7107f 100644
--- a/tools/perf/scripts/python/export-to-sqlite.py
+++ b/tools/perf/scripts/python/export-to-sqlite.py
@@ -222,7 +222,8 @@ if perf_db_export_calls:
222 'call_id bigint,' 222 'call_id bigint,'
223 'return_id bigint,' 223 'return_id bigint,'
224 'parent_call_path_id bigint,' 224 'parent_call_path_id bigint,'
225 'flags integer)') 225 'flags integer,'
226 'parent_id bigint)')
226 227
227# printf was added to sqlite in version 3.8.3 228# printf was added to sqlite in version 3.8.3
228sqlite_has_printf = False 229sqlite_has_printf = False
@@ -321,7 +322,8 @@ if perf_db_export_calls:
321 'call_id,' 322 'call_id,'
322 'return_id,' 323 'return_id,'
323 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,' 324 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,'
324 'parent_call_path_id' 325 'parent_call_path_id,'
326 'parent_id'
325 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') 327 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
326 328
327do_query(query, 'CREATE VIEW samples_view AS ' 329do_query(query, 'CREATE VIEW samples_view AS '
@@ -373,7 +375,7 @@ if perf_db_export_calls or perf_db_export_callchains:
373 call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)") 375 call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")
374if perf_db_export_calls: 376if perf_db_export_calls:
375 call_query = QSqlQuery(db) 377 call_query = QSqlQuery(db)
376 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") 378 call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
377 379
378def trace_begin(): 380def trace_begin():
379 print datetime.datetime.today(), "Writing records..." 381 print datetime.datetime.today(), "Writing records..."
@@ -388,6 +390,7 @@ def trace_begin():
388 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 390 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
389 if perf_db_export_calls or perf_db_export_callchains: 391 if perf_db_export_calls or perf_db_export_callchains:
390 call_path_table(0, 0, 0, 0) 392 call_path_table(0, 0, 0, 0)
393 call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
391 394
392unhandled_count = 0 395unhandled_count = 0
393 396
@@ -397,6 +400,7 @@ def trace_end():
397 print datetime.datetime.today(), "Adding indexes" 400 print datetime.datetime.today(), "Adding indexes"
398 if perf_db_export_calls: 401 if perf_db_export_calls:
399 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)') 402 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
403 do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
400 404
401 if (unhandled_count): 405 if (unhandled_count):
402 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events" 406 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events"
@@ -452,4 +456,4 @@ def call_path_table(*x):
452 bind_exec(call_path_query, 4, x) 456 bind_exec(call_path_query, 4, x)
453 457
454def call_return_table(*x): 458def call_return_table(*x):
455 bind_exec(call_query, 11, x) 459 bind_exec(call_query, 12, x)
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py
index 09ce73b07d35..afec9479ca7f 100755
--- a/tools/perf/scripts/python/exported-sql-viewer.py
+++ b/tools/perf/scripts/python/exported-sql-viewer.py
@@ -167,9 +167,10 @@ class Thread(QThread):
167 167
168class TreeModel(QAbstractItemModel): 168class TreeModel(QAbstractItemModel):
169 169
170 def __init__(self, root, parent=None): 170 def __init__(self, glb, parent=None):
171 super(TreeModel, self).__init__(parent) 171 super(TreeModel, self).__init__(parent)
172 self.root = root 172 self.glb = glb
173 self.root = self.GetRoot()
173 self.last_row_read = 0 174 self.last_row_read = 0
174 175
175 def Item(self, parent): 176 def Item(self, parent):
@@ -557,24 +558,12 @@ class CallGraphRootItem(CallGraphLevelItemBase):
557 self.child_items.append(child_item) 558 self.child_items.append(child_item)
558 self.child_count += 1 559 self.child_count += 1
559 560
560# Context-sensitive call graph data model 561# Context-sensitive call graph data model base
561 562
562class CallGraphModel(TreeModel): 563class CallGraphModelBase(TreeModel):
563 564
564 def __init__(self, glb, parent=None): 565 def __init__(self, glb, parent=None):
565 super(CallGraphModel, self).__init__(CallGraphRootItem(glb), parent) 566 super(CallGraphModelBase, self).__init__(glb, parent)
566 self.glb = glb
567
568 def columnCount(self, parent=None):
569 return 7
570
571 def columnHeader(self, column):
572 headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
573 return headers[column]
574
575 def columnAlignment(self, column):
576 alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]
577 return alignment[column]
578 567
579 def FindSelect(self, value, pattern, query): 568 def FindSelect(self, value, pattern, query):
580 if pattern: 569 if pattern:
@@ -594,34 +583,7 @@ class CallGraphModel(TreeModel):
594 match = " GLOB '" + str(value) + "'" 583 match = " GLOB '" + str(value) + "'"
595 else: 584 else:
596 match = " = '" + str(value) + "'" 585 match = " = '" + str(value) + "'"
597 QueryExec(query, "SELECT call_path_id, comm_id, thread_id" 586 self.DoFindSelect(query, match)
598 " FROM calls"
599 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
600 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
601 " WHERE symbols.name" + match +
602 " GROUP BY comm_id, thread_id, call_path_id"
603 " ORDER BY comm_id, thread_id, call_path_id")
604
605 def FindPath(self, query):
606 # Turn the query result into a list of ids that the tree view can walk
607 # to open the tree at the right place.
608 ids = []
609 parent_id = query.value(0)
610 while parent_id:
611 ids.insert(0, parent_id)
612 q2 = QSqlQuery(self.glb.db)
613 QueryExec(q2, "SELECT parent_id"
614 " FROM call_paths"
615 " WHERE id = " + str(parent_id))
616 if not q2.next():
617 break
618 parent_id = q2.value(0)
619 # The call path root is not used
620 if ids[0] == 1:
621 del ids[0]
622 ids.insert(0, query.value(2))
623 ids.insert(0, query.value(1))
624 return ids
625 587
626 def Found(self, query, found): 588 def Found(self, query, found):
627 if found: 589 if found:
@@ -675,6 +637,201 @@ class CallGraphModel(TreeModel):
675 def FindDone(self, thread, callback, ids): 637 def FindDone(self, thread, callback, ids):
676 callback(ids) 638 callback(ids)
677 639
640# Context-sensitive call graph data model
641
642class CallGraphModel(CallGraphModelBase):
643
644 def __init__(self, glb, parent=None):
645 super(CallGraphModel, self).__init__(glb, parent)
646
647 def GetRoot(self):
648 return CallGraphRootItem(self.glb)
649
650 def columnCount(self, parent=None):
651 return 7
652
653 def columnHeader(self, column):
654 headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
655 return headers[column]
656
657 def columnAlignment(self, column):
658 alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]
659 return alignment[column]
660
661 def DoFindSelect(self, query, match):
662 QueryExec(query, "SELECT call_path_id, comm_id, thread_id"
663 " FROM calls"
664 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
665 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
666 " WHERE symbols.name" + match +
667 " GROUP BY comm_id, thread_id, call_path_id"
668 " ORDER BY comm_id, thread_id, call_path_id")
669
670 def FindPath(self, query):
671 # Turn the query result into a list of ids that the tree view can walk
672 # to open the tree at the right place.
673 ids = []
674 parent_id = query.value(0)
675 while parent_id:
676 ids.insert(0, parent_id)
677 q2 = QSqlQuery(self.glb.db)
678 QueryExec(q2, "SELECT parent_id"
679 " FROM call_paths"
680 " WHERE id = " + str(parent_id))
681 if not q2.next():
682 break
683 parent_id = q2.value(0)
684 # The call path root is not used
685 if ids[0] == 1:
686 del ids[0]
687 ids.insert(0, query.value(2))
688 ids.insert(0, query.value(1))
689 return ids
690
691# Call tree data model level 2+ item base
692
693class CallTreeLevelTwoPlusItemBase(CallGraphLevelItemBase):
694
695 def __init__(self, glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item):
696 super(CallTreeLevelTwoPlusItemBase, self).__init__(glb, row, parent_item)
697 self.comm_id = comm_id
698 self.thread_id = thread_id
699 self.calls_id = calls_id
700 self.branch_count = branch_count
701 self.time = time
702
703 def Select(self):
704 self.query_done = True;
705 if self.calls_id == 0:
706 comm_thread = " AND comm_id = " + str(self.comm_id) + " AND thread_id = " + str(self.thread_id)
707 else:
708 comm_thread = ""
709 query = QSqlQuery(self.glb.db)
710 QueryExec(query, "SELECT calls.id, name, short_name, call_time, return_time - call_time, branch_count"
711 " FROM calls"
712 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
713 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
714 " INNER JOIN dsos ON symbols.dso_id = dsos.id"
715 " WHERE calls.parent_id = " + str(self.calls_id) + comm_thread +
716 " ORDER BY call_time, calls.id")
717 while query.next():
718 child_item = CallTreeLevelThreeItem(self.glb, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), int(query.value(5)), self)
719 self.child_items.append(child_item)
720 self.child_count += 1
721
722# Call tree data model level three item
723
724class CallTreeLevelThreeItem(CallTreeLevelTwoPlusItemBase):
725
726 def __init__(self, glb, row, comm_id, thread_id, calls_id, name, dso, count, time, branch_count, parent_item):
727 super(CallTreeLevelThreeItem, self).__init__(glb, row, comm_id, thread_id, calls_id, time, branch_count, parent_item)
728 dso = dsoname(dso)
729 self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ]
730 self.dbid = calls_id
731
732# Call tree data model level two item
733
734class CallTreeLevelTwoItem(CallTreeLevelTwoPlusItemBase):
735
736 def __init__(self, glb, row, comm_id, thread_id, pid, tid, parent_item):
737 super(CallTreeLevelTwoItem, self).__init__(glb, row, comm_id, thread_id, 0, 0, 0, parent_item)
738 self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""]
739 self.dbid = thread_id
740
741 def Select(self):
742 super(CallTreeLevelTwoItem, self).Select()
743 for child_item in self.child_items:
744 self.time += child_item.time
745 self.branch_count += child_item.branch_count
746 for child_item in self.child_items:
747 child_item.data[4] = PercentToOneDP(child_item.time, self.time)
748 child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count)
749
750# Call tree data model level one item
751
752class CallTreeLevelOneItem(CallGraphLevelItemBase):
753
754 def __init__(self, glb, row, comm_id, comm, parent_item):
755 super(CallTreeLevelOneItem, self).__init__(glb, row, parent_item)
756 self.data = [comm, "", "", "", "", "", ""]
757 self.dbid = comm_id
758
759 def Select(self):
760 self.query_done = True;
761 query = QSqlQuery(self.glb.db)
762 QueryExec(query, "SELECT thread_id, pid, tid"
763 " FROM comm_threads"
764 " INNER JOIN threads ON thread_id = threads.id"
765 " WHERE comm_id = " + str(self.dbid))
766 while query.next():
767 child_item = CallTreeLevelTwoItem(self.glb, self.child_count, self.dbid, query.value(0), query.value(1), query.value(2), self)
768 self.child_items.append(child_item)
769 self.child_count += 1
770
771# Call tree data model root item
772
773class CallTreeRootItem(CallGraphLevelItemBase):
774
775 def __init__(self, glb):
776 super(CallTreeRootItem, self).__init__(glb, 0, None)
777 self.dbid = 0
778 self.query_done = True;
779 query = QSqlQuery(glb.db)
780 QueryExec(query, "SELECT id, comm FROM comms")
781 while query.next():
782 if not query.value(0):
783 continue
784 child_item = CallTreeLevelOneItem(glb, self.child_count, query.value(0), query.value(1), self)
785 self.child_items.append(child_item)
786 self.child_count += 1
787
788# Call Tree data model
789
790class CallTreeModel(CallGraphModelBase):
791
792 def __init__(self, glb, parent=None):
793 super(CallTreeModel, self).__init__(glb, parent)
794
795 def GetRoot(self):
796 return CallTreeRootItem(self.glb)
797
798 def columnCount(self, parent=None):
799 return 7
800
801 def columnHeader(self, column):
802 headers = ["Call Path", "Object", "Call Time", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
803 return headers[column]
804
805 def columnAlignment(self, column):
806 alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]
807 return alignment[column]
808
809 def DoFindSelect(self, query, match):
810 QueryExec(query, "SELECT calls.id, comm_id, thread_id"
811 " FROM calls"
812 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
813 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
814 " WHERE symbols.name" + match +
815 " ORDER BY comm_id, thread_id, call_time, calls.id")
816
817 def FindPath(self, query):
818 # Turn the query result into a list of ids that the tree view can walk
819 # to open the tree at the right place.
820 ids = []
821 parent_id = query.value(0)
822 while parent_id:
823 ids.insert(0, parent_id)
824 q2 = QSqlQuery(self.glb.db)
825 QueryExec(q2, "SELECT parent_id"
826 " FROM calls"
827 " WHERE id = " + str(parent_id))
828 if not q2.next():
829 break
830 parent_id = q2.value(0)
831 ids.insert(0, query.value(2))
832 ids.insert(0, query.value(1))
833 return ids
834
678# Vertical widget layout 835# Vertical widget layout
679 836
680class VBox(): 837class VBox():
@@ -693,28 +850,16 @@ class VBox():
693 def Widget(self): 850 def Widget(self):
694 return self.vbox 851 return self.vbox
695 852
696# Context-sensitive call graph window 853# Tree window base
697
698class CallGraphWindow(QMdiSubWindow):
699
700 def __init__(self, glb, parent=None):
701 super(CallGraphWindow, self).__init__(parent)
702
703 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x))
704
705 self.view = QTreeView()
706 self.view.setModel(self.model)
707
708 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):
709 self.view.setColumnWidth(c, w)
710
711 self.find_bar = FindBar(self, self)
712 854
713 self.vbox = VBox(self.view, self.find_bar.Widget()) 855class TreeWindowBase(QMdiSubWindow):
714 856
715 self.setWidget(self.vbox.Widget()) 857 def __init__(self, parent=None):
858 super(TreeWindowBase, self).__init__(parent)
716 859
717 AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph") 860 self.model = None
861 self.view = None
862 self.find_bar = None
718 863
719 def DisplayFound(self, ids): 864 def DisplayFound(self, ids):
720 if not len(ids): 865 if not len(ids):
@@ -747,6 +892,53 @@ class CallGraphWindow(QMdiSubWindow):
747 if not found: 892 if not found:
748 self.find_bar.NotFound() 893 self.find_bar.NotFound()
749 894
895
896# Context-sensitive call graph window
897
898class CallGraphWindow(TreeWindowBase):
899
900 def __init__(self, glb, parent=None):
901 super(CallGraphWindow, self).__init__(parent)
902
903 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x))
904
905 self.view = QTreeView()
906 self.view.setModel(self.model)
907
908 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):
909 self.view.setColumnWidth(c, w)
910
911 self.find_bar = FindBar(self, self)
912
913 self.vbox = VBox(self.view, self.find_bar.Widget())
914
915 self.setWidget(self.vbox.Widget())
916
917 AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph")
918
919# Call tree window
920
921class CallTreeWindow(TreeWindowBase):
922
923 def __init__(self, glb, parent=None):
924 super(CallTreeWindow, self).__init__(parent)
925
926 self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x))
927
928 self.view = QTreeView()
929 self.view.setModel(self.model)
930
931 for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)):
932 self.view.setColumnWidth(c, w)
933
934 self.find_bar = FindBar(self, self)
935
936 self.vbox = VBox(self.view, self.find_bar.Widget())
937
938 self.setWidget(self.vbox.Widget())
939
940 AddSubWindow(glb.mainwindow.mdi_area, self, "Call Tree")
941
750# Child data item finder 942# Child data item finder
751 943
752class ChildDataItemFinder(): 944class ChildDataItemFinder():
@@ -1327,8 +1519,7 @@ class BranchModel(TreeModel):
1327 progress = Signal(object) 1519 progress = Signal(object)
1328 1520
1329 def __init__(self, glb, event_id, where_clause, parent=None): 1521 def __init__(self, glb, event_id, where_clause, parent=None):
1330 super(BranchModel, self).__init__(BranchRootItem(), parent) 1522 super(BranchModel, self).__init__(glb, parent)
1331 self.glb = glb
1332 self.event_id = event_id 1523 self.event_id = event_id
1333 self.more = True 1524 self.more = True
1334 self.populated = 0 1525 self.populated = 0
@@ -1352,6 +1543,9 @@ class BranchModel(TreeModel):
1352 self.fetcher.done.connect(self.Update) 1543 self.fetcher.done.connect(self.Update)
1353 self.fetcher.Fetch(glb_chunk_sz) 1544 self.fetcher.Fetch(glb_chunk_sz)
1354 1545
1546 def GetRoot(self):
1547 return BranchRootItem()
1548
1355 def columnCount(self, parent=None): 1549 def columnCount(self, parent=None):
1356 return 8 1550 return 8
1357 1551
@@ -1863,10 +2057,10 @@ def GetEventList(db):
1863 2057
1864# Is a table selectable 2058# Is a table selectable
1865 2059
1866def IsSelectable(db, table): 2060def IsSelectable(db, table, sql = ""):
1867 query = QSqlQuery(db) 2061 query = QSqlQuery(db)
1868 try: 2062 try:
1869 QueryExec(query, "SELECT * FROM " + table + " LIMIT 1") 2063 QueryExec(query, "SELECT * FROM " + table + " " + sql + " LIMIT 1")
1870 except: 2064 except:
1871 return False 2065 return False
1872 return True 2066 return True
@@ -2275,9 +2469,10 @@ p.c2 {
2275</style> 2469</style>
2276<p class=c1><a href=#reports>1. Reports</a></p> 2470<p class=c1><a href=#reports>1. Reports</a></p>
2277<p class=c2><a href=#callgraph>1.1 Context-Sensitive Call Graph</a></p> 2471<p class=c2><a href=#callgraph>1.1 Context-Sensitive Call Graph</a></p>
2278<p class=c2><a href=#allbranches>1.2 All branches</a></p> 2472<p class=c2><a href=#calltree>1.2 Call Tree</a></p>
2279<p class=c2><a href=#selectedbranches>1.3 Selected branches</a></p> 2473<p class=c2><a href=#allbranches>1.3 All branches</a></p>
2280<p class=c2><a href=#topcallsbyelapsedtime>1.4 Top calls by elapsed time</a></p> 2474<p class=c2><a href=#selectedbranches>1.4 Selected branches</a></p>
2475<p class=c2><a href=#topcallsbyelapsedtime>1.5 Top calls by elapsed time</a></p>
2281<p class=c1><a href=#tables>2. Tables</a></p> 2476<p class=c1><a href=#tables>2. Tables</a></p>
2282<h1 id=reports>1. Reports</h1> 2477<h1 id=reports>1. Reports</h1>
2283<h2 id=callgraph>1.1 Context-Sensitive Call Graph</h2> 2478<h2 id=callgraph>1.1 Context-Sensitive Call Graph</h2>
@@ -2313,7 +2508,10 @@ v- ls
2313<h3>Find</h3> 2508<h3>Find</h3>
2314Ctrl-F displays a Find bar which finds function names by either an exact match or a pattern match. 2509Ctrl-F displays a Find bar which finds function names by either an exact match or a pattern match.
2315The pattern matching symbols are ? for any character and * for zero or more characters. 2510The pattern matching symbols are ? for any character and * for zero or more characters.
2316<h2 id=allbranches>1.2 All branches</h2> 2511<h2 id=calltree>1.2 Call Tree</h2>
2512The Call Tree report is very similar to the Context-Sensitive Call Graph, but the data is not aggregated.
2513Also the 'Count' column, which would be always 1, is replaced by the 'Call Time'.
2514<h2 id=allbranches>1.3 All branches</h2>
2317The All branches report displays all branches in chronological order. 2515The All branches report displays all branches in chronological order.
2318Not all data is fetched immediately. More records can be fetched using the Fetch bar provided. 2516Not all data is fetched immediately. More records can be fetched using the Fetch bar provided.
2319<h3>Disassembly</h3> 2517<h3>Disassembly</h3>
@@ -2339,10 +2537,10 @@ sudo ldconfig
2339Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match. 2537Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match.
2340Refer to Python documentation for the regular expression syntax. 2538Refer to Python documentation for the regular expression syntax.
2341All columns are searched, but only currently fetched rows are searched. 2539All columns are searched, but only currently fetched rows are searched.
2342<h2 id=selectedbranches>1.3 Selected branches</h2> 2540<h2 id=selectedbranches>1.4 Selected branches</h2>
2343This is the same as the <a href=#allbranches>All branches</a> report but with the data reduced 2541This is the same as the <a href=#allbranches>All branches</a> report but with the data reduced
2344by various selection criteria. A dialog box displays available criteria which are AND'ed together. 2542by various selection criteria. A dialog box displays available criteria which are AND'ed together.
2345<h3>1.3.1 Time ranges</h3> 2543<h3>1.4.1 Time ranges</h3>
2346The time ranges hint text shows the total time range. Relative time ranges can also be entered in 2544The time ranges hint text shows the total time range. Relative time ranges can also be entered in
2347ms, us or ns. Also, negative values are relative to the end of trace. Examples: 2545ms, us or ns. Also, negative values are relative to the end of trace. Examples:
2348<pre> 2546<pre>
@@ -2353,7 +2551,7 @@ ms, us or ns. Also, negative values are relative to the end of trace. Examples:
2353 -10ms- The last 10ms 2551 -10ms- The last 10ms
2354</pre> 2552</pre>
2355N.B. Due to the granularity of timestamps, there could be no branches in any given time range. 2553N.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> 2554<h2 id=topcallsbyelapsedtime>1.5 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. 2555The 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. 2556The 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. 2557If not all data is fetched, a Fetch bar is provided. Ctrl-F displays a Find bar.
@@ -2489,6 +2687,9 @@ class MainWindow(QMainWindow):
2489 if IsSelectable(glb.db, "calls"): 2687 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)) 2688 reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self))
2491 2689
2690 if IsSelectable(glb.db, "calls", "WHERE parent_id >= 0"):
2691 reports_menu.addAction(CreateAction("Call &Tree", "Create a new window containing a call tree", self.NewCallTree, self))
2692
2492 self.EventMenu(GetEventList(glb.db), reports_menu) 2693 self.EventMenu(GetEventList(glb.db), reports_menu)
2493 2694
2494 if IsSelectable(glb.db, "calls"): 2695 if IsSelectable(glb.db, "calls"):
@@ -2549,6 +2750,9 @@ class MainWindow(QMainWindow):
2549 def NewCallGraph(self): 2750 def NewCallGraph(self):
2550 CallGraphWindow(self.glb, self) 2751 CallGraphWindow(self.glb, self)
2551 2752
2753 def NewCallTree(self):
2754 CallTreeWindow(self.glb, self)
2755
2552 def NewTopCalls(self): 2756 def NewTopCalls(self):
2553 dialog = TopCallsDialog(self.glb, self) 2757 dialog = TopCallsDialog(self.glb, self)
2554 ret = dialog.exec_() 2758 ret = dialog.exec_()
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index 3648e8b986ec..310efe5e7e23 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -58,22 +58,22 @@ def syscalls__sys_exit(event_name, context, common_cpu,
58 raw_syscalls__sys_exit(**locals()) 58 raw_syscalls__sys_exit(**locals())
59 59
60def print_error_totals(): 60def print_error_totals():
61 if for_comm is not None: 61 if for_comm is not None:
62 print("\nsyscall errors for %s:\n" % (for_comm)) 62 print("\nsyscall errors for %s:\n" % (for_comm))
63 else: 63 else:
64 print("\nsyscall errors:\n") 64 print("\nsyscall errors:\n")
65 65
66 print("%-30s %10s" % ("comm [pid]", "count")) 66 print("%-30s %10s" % ("comm [pid]", "count"))
67 print("%-30s %10s" % ("------------------------------", "----------")) 67 print("%-30s %10s" % ("------------------------------", "----------"))
68 68
69 comm_keys = syscalls.keys() 69 comm_keys = syscalls.keys()
70 for comm in comm_keys: 70 for comm in comm_keys:
71 pid_keys = syscalls[comm].keys() 71 pid_keys = syscalls[comm].keys()
72 for pid in pid_keys: 72 for pid in pid_keys:
73 print("\n%s [%d]" % (comm, pid)) 73 print("\n%s [%d]" % (comm, pid))
74 id_keys = syscalls[comm][pid].keys() 74 id_keys = syscalls[comm][pid].keys()
75 for id in id_keys: 75 for id in id_keys:
76 print(" syscall: %-16s" % syscall_name(id)) 76 print(" syscall: %-16s" % syscall_name(id))
77 ret_keys = syscalls[comm][pid][id].keys() 77 ret_keys = syscalls[comm][pid][id].keys()
78 for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True): 78 for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True):
79 print(" err = %-20s %10d" % (strerror(ret), val)) 79 print(" err = %-20s %10d" % (strerror(ret), val))
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
index 0f5cf437b602..0c4841acf75d 100644
--- a/tools/perf/scripts/python/futex-contention.py
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -10,6 +10,8 @@
10# 10#
11# Measures futex contention 11# Measures futex contention
12 12
13from __future__ import print_function
14
13import os, sys 15import os, sys
14sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 16sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
15from Util import * 17from Util import *
@@ -33,18 +35,18 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
33 35
34def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, 36def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
35 nr, ret): 37 nr, ret):
36 if thread_blocktime.has_key(tid): 38 if tid in thread_blocktime:
37 elapsed = nsecs(s, ns) - thread_blocktime[tid] 39 elapsed = nsecs(s, ns) - thread_blocktime[tid]
38 add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed) 40 add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed)
39 del thread_blocktime[tid] 41 del thread_blocktime[tid]
40 del thread_thislock[tid] 42 del thread_thislock[tid]
41 43
42def trace_begin(): 44def trace_begin():
43 print "Press control+C to stop and show the summary" 45 print("Press control+C to stop and show the summary")
44 46
45def trace_end(): 47def trace_end():
46 for (tid, lock) in lock_waits: 48 for (tid, lock) in lock_waits:
47 min, max, avg, count = lock_waits[tid, lock] 49 min, max, avg, count = lock_waits[tid, lock]
48 print "%s[%d] lock %x contended %d times, %d avg ns" % \ 50 print("%s[%d] lock %x contended %d times, %d avg ns" %
49 (process_names[tid], tid, lock, count, avg) 51 (process_names[tid], tid, lock, count, avg))
50 52
diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py
index b19172d673af..a73847c8f548 100644
--- a/tools/perf/scripts/python/intel-pt-events.py
+++ b/tools/perf/scripts/python/intel-pt-events.py
@@ -10,6 +10,8 @@
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11# more details. 11# more details.
12 12
13from __future__ import print_function
14
13import os 15import os
14import sys 16import sys
15import struct 17import struct
@@ -22,34 +24,34 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \
22#from Core import * 24#from Core import *
23 25
24def trace_begin(): 26def trace_begin():
25 print "Intel PT Power Events and PTWRITE" 27 print("Intel PT Power Events and PTWRITE")
26 28
27def trace_end(): 29def trace_end():
28 print "End" 30 print("End")
29 31
30def trace_unhandled(event_name, context, event_fields_dict): 32def trace_unhandled(event_name, context, event_fields_dict):
31 print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) 33 print(' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
32 34
33def print_ptwrite(raw_buf): 35def print_ptwrite(raw_buf):
34 data = struct.unpack_from("<IQ", raw_buf) 36 data = struct.unpack_from("<IQ", raw_buf)
35 flags = data[0] 37 flags = data[0]
36 payload = data[1] 38 payload = data[1]
37 exact_ip = flags & 1 39 exact_ip = flags & 1
38 print "IP: %u payload: %#x" % (exact_ip, payload), 40 print("IP: %u payload: %#x" % (exact_ip, payload), end=' ')
39 41
40def print_cbr(raw_buf): 42def print_cbr(raw_buf):
41 data = struct.unpack_from("<BBBBII", raw_buf) 43 data = struct.unpack_from("<BBBBII", raw_buf)
42 cbr = data[0] 44 cbr = data[0]
43 f = (data[4] + 500) / 1000 45 f = (data[4] + 500) / 1000
44 p = ((cbr * 1000 / data[2]) + 5) / 10 46 p = ((cbr * 1000 / data[2]) + 5) / 10
45 print "%3u freq: %4u MHz (%3u%%)" % (cbr, f, p), 47 print("%3u freq: %4u MHz (%3u%%)" % (cbr, f, p), end=' ')
46 48
47def print_mwait(raw_buf): 49def print_mwait(raw_buf):
48 data = struct.unpack_from("<IQ", raw_buf) 50 data = struct.unpack_from("<IQ", raw_buf)
49 payload = data[1] 51 payload = data[1]
50 hints = payload & 0xff 52 hints = payload & 0xff
51 extensions = (payload >> 32) & 0x3 53 extensions = (payload >> 32) & 0x3
52 print "hints: %#x extensions: %#x" % (hints, extensions), 54 print("hints: %#x extensions: %#x" % (hints, extensions), end=' ')
53 55
54def print_pwre(raw_buf): 56def print_pwre(raw_buf):
55 data = struct.unpack_from("<IQ", raw_buf) 57 data = struct.unpack_from("<IQ", raw_buf)
@@ -57,13 +59,14 @@ def print_pwre(raw_buf):
57 hw = (payload >> 7) & 1 59 hw = (payload >> 7) & 1
58 cstate = (payload >> 12) & 0xf 60 cstate = (payload >> 12) & 0xf
59 subcstate = (payload >> 8) & 0xf 61 subcstate = (payload >> 8) & 0xf
60 print "hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate), 62 print("hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate),
63 end=' ')
61 64
62def print_exstop(raw_buf): 65def print_exstop(raw_buf):
63 data = struct.unpack_from("<I", raw_buf) 66 data = struct.unpack_from("<I", raw_buf)
64 flags = data[0] 67 flags = data[0]
65 exact_ip = flags & 1 68 exact_ip = flags & 1
66 print "IP: %u" % (exact_ip), 69 print("IP: %u" % (exact_ip), end=' ')
67 70
68def print_pwrx(raw_buf): 71def print_pwrx(raw_buf):
69 data = struct.unpack_from("<IQ", raw_buf) 72 data = struct.unpack_from("<IQ", raw_buf)
@@ -71,36 +74,39 @@ def print_pwrx(raw_buf):
71 deepest_cstate = payload & 0xf 74 deepest_cstate = payload & 0xf
72 last_cstate = (payload >> 4) & 0xf 75 last_cstate = (payload >> 4) & 0xf
73 wake_reason = (payload >> 8) & 0xf 76 wake_reason = (payload >> 8) & 0xf
74 print "deepest cstate: %u last cstate: %u wake reason: %#x" % (deepest_cstate, last_cstate, wake_reason), 77 print("deepest cstate: %u last cstate: %u wake reason: %#x" %
78 (deepest_cstate, last_cstate, wake_reason), end=' ')
75 79
76def print_common_start(comm, sample, name): 80def print_common_start(comm, sample, name):
77 ts = sample["time"] 81 ts = sample["time"]
78 cpu = sample["cpu"] 82 cpu = sample["cpu"]
79 pid = sample["pid"] 83 pid = sample["pid"]
80 tid = sample["tid"] 84 tid = sample["tid"]
81 print "%16s %5u/%-5u [%03u] %9u.%09u %7s:" % (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), 85 print("%16s %5u/%-5u [%03u] %9u.%09u %7s:" %
86 (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name),
87 end=' ')
82 88
83def print_common_ip(sample, symbol, dso): 89def print_common_ip(sample, symbol, dso):
84 ip = sample["ip"] 90 ip = sample["ip"]
85 print "%16x %s (%s)" % (ip, symbol, dso) 91 print("%16x %s (%s)" % (ip, symbol, dso))
86 92
87def process_event(param_dict): 93def process_event(param_dict):
88 event_attr = param_dict["attr"] 94 event_attr = param_dict["attr"]
89 sample = param_dict["sample"] 95 sample = param_dict["sample"]
90 raw_buf = param_dict["raw_buf"] 96 raw_buf = param_dict["raw_buf"]
91 comm = param_dict["comm"] 97 comm = param_dict["comm"]
92 name = param_dict["ev_name"] 98 name = param_dict["ev_name"]
93 99
94 # Symbol and dso info are not always resolved 100 # Symbol and dso info are not always resolved
95 if (param_dict.has_key("dso")): 101 if "dso" in param_dict:
96 dso = param_dict["dso"] 102 dso = param_dict["dso"]
97 else: 103 else:
98 dso = "[unknown]" 104 dso = "[unknown]"
99 105
100 if (param_dict.has_key("symbol")): 106 if "symbol" in param_dict:
101 symbol = param_dict["symbol"] 107 symbol = param_dict["symbol"]
102 else: 108 else:
103 symbol = "[unknown]" 109 symbol = "[unknown]"
104 110
105 if name == "ptwrite": 111 if name == "ptwrite":
106 print_common_start(comm, sample, name) 112 print_common_start(comm, sample, name)
diff --git a/tools/perf/scripts/python/mem-phys-addr.py b/tools/perf/scripts/python/mem-phys-addr.py
index fb0bbcbfa0f0..1f332e72b9b0 100644
--- a/tools/perf/scripts/python/mem-phys-addr.py
+++ b/tools/perf/scripts/python/mem-phys-addr.py
@@ -44,12 +44,13 @@ def print_memory_type():
44 print("%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), end='') 44 print("%-40s %10s %10s\n" % ("Memory type", "count", "percentage"), end='')
45 print("%-40s %10s %10s\n" % ("----------------------------------------", 45 print("%-40s %10s %10s\n" % ("----------------------------------------",
46 "-----------", "-----------"), 46 "-----------", "-----------"),
47 end=''); 47 end='');
48 total = sum(load_mem_type_cnt.values()) 48 total = sum(load_mem_type_cnt.values())
49 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(), \
50 key = lambda kv: (kv[1], kv[0]), reverse = True): 50 key = lambda kv: (kv[1], kv[0]), reverse = True):
51 print("%-40s %10d %10.1f%%\n" % (mem_type, count, 100 * count / total), 51 print("%-40s %10d %10.1f%%\n" %
52 end='') 52 (mem_type, count, 100 * count / total),
53 end='')
53 54
54def trace_begin(): 55def trace_begin():
55 parse_iomem() 56 parse_iomem()
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index 212557a02c50..101059971738 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -7,7 +7,7 @@ import os
7import sys 7import sys
8 8
9sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 9sys.path.append(os.environ['PERF_EXEC_PATH'] + \
10 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 10 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
11 11
12from perf_trace_context import * 12from perf_trace_context import *
13from Core import * 13from Core import *
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 267bda49325d..ea0c8b90a783 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -124,14 +124,16 @@ def print_receive(hunk):
124 event = event_list[i] 124 event = event_list[i]
125 if event['event_name'] == 'napi_poll': 125 if event['event_name'] == 'napi_poll':
126 print(PF_NAPI_POLL % 126 print(PF_NAPI_POLL %
127 (diff_msec(base_t, event['event_t']), event['dev'])) 127 (diff_msec(base_t, event['event_t']),
128 event['dev']))
128 if i == len(event_list) - 1: 129 if i == len(event_list) - 1:
129 print("") 130 print("")
130 else: 131 else:
131 print(PF_JOINT) 132 print(PF_JOINT)
132 else: 133 else:
133 print(PF_NET_RECV % 134 print(PF_NET_RECV %
134 (diff_msec(base_t, event['event_t']), event['skbaddr'], 135 (diff_msec(base_t, event['event_t']),
136 event['skbaddr'],
135 event['len'])) 137 event['len']))
136 if 'comm' in event.keys(): 138 if 'comm' in event.keys():
137 print(PF_WJOINT) 139 print(PF_WJOINT)
@@ -256,7 +258,7 @@ def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, i
256 all_event_list.append(event_info) 258 all_event_list.append(event_info)
257 259
258def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, 260def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi,
259 dev_name, work=None, budget=None): 261 dev_name, work=None, budget=None):
260 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 262 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
261 napi, dev_name, work, budget) 263 napi, dev_name, work, budget)
262 all_event_list.append(event_info) 264 all_event_list.append(event_info)
@@ -353,7 +355,7 @@ def handle_irq_softirq_exit(event_info):
353 if irq_list == [] or event_list == 0: 355 if irq_list == [] or event_list == 0:
354 return 356 return
355 rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time, 357 rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time,
356 'irq_list':irq_list, 'event_list':event_list} 358 'irq_list':irq_list, 'event_list':event_list}
357 # merge information realted to a NET_RX softirq 359 # merge information realted to a NET_RX softirq
358 receive_hunk_list.append(rec_data) 360 receive_hunk_list.append(rec_data)
359 361
@@ -390,7 +392,7 @@ def handle_netif_receive_skb(event_info):
390 skbaddr, skblen, dev_name) = event_info 392 skbaddr, skblen, dev_name) = event_info
391 if cpu in net_rx_dic.keys(): 393 if cpu in net_rx_dic.keys():
392 rec_data = {'event_name':'netif_receive_skb', 394 rec_data = {'event_name':'netif_receive_skb',
393 'event_t':time, 'skbaddr':skbaddr, 'len':skblen} 395 'event_t':time, 'skbaddr':skbaddr, 'len':skblen}
394 event_list = net_rx_dic[cpu]['event_list'] 396 event_list = net_rx_dic[cpu]['event_list']
395 event_list.append(rec_data) 397 event_list.append(rec_data)
396 rx_skb_list.insert(0, rec_data) 398 rx_skb_list.insert(0, rec_data)
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 3984bf51f3c5..8196e3087c9e 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -14,10 +14,10 @@ import sys
14 14
15from collections import defaultdict 15from collections import defaultdict
16try: 16try:
17 from UserList import UserList 17 from UserList import UserList
18except ImportError: 18except ImportError:
19 # Python 3: UserList moved to the collections package 19 # Python 3: UserList moved to the collections package
20 from collections import UserList 20 from collections import UserList
21 21
22sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 22sys.path.append(os.environ['PERF_EXEC_PATH'] + \
23 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 23 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index 987ffae7c8ca..6e0278dcb092 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -13,9 +13,9 @@ from __future__ import print_function
13import os, sys, time 13import os, sys, time
14 14
15try: 15try:
16 import thread 16 import thread
17except ImportError: 17except ImportError:
18 import _thread as thread 18 import _thread as thread
19 19
20sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 20sys.path.append(os.environ['PERF_EXEC_PATH'] + \
21 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 21 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
@@ -75,11 +75,12 @@ def print_syscall_totals(interval):
75 75
76 print("%-40s %10s" % ("event", "count")) 76 print("%-40s %10s" % ("event", "count"))
77 print("%-40s %10s" % 77 print("%-40s %10s" %
78 ("----------------------------------------", 78 ("----------------------------------------",
79 "----------")) 79 "----------"))
80 80
81 for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \ 81 for id, val in sorted(syscalls.items(),
82 reverse = True): 82 key = lambda kv: (kv[1], kv[0]),
83 reverse = True):
83 try: 84 try:
84 print("%-40s %10d" % (syscall_name(id), val)) 85 print("%-40s %10d" % (syscall_name(id), val))
85 except TypeError: 86 except TypeError:
diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py
index 5e703efaddcc..b1c4def1410a 100755
--- a/tools/perf/scripts/python/stackcollapse.py
+++ b/tools/perf/scripts/python/stackcollapse.py
@@ -27,7 +27,7 @@ from collections import defaultdict
27from optparse import OptionParser, make_option 27from optparse import OptionParser, make_option
28 28
29sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 29sys.path.append(os.environ['PERF_EXEC_PATH'] + \
30 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 30 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
31 31
32from perf_trace_context import * 32from perf_trace_context import *
33from Core import * 33from Core import *
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index 42782487b0e9..f254e40c6f0f 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -39,11 +39,10 @@ def trace_end():
39 print_syscall_totals() 39 print_syscall_totals()
40 40
41def raw_syscalls__sys_enter(event_name, context, common_cpu, 41def raw_syscalls__sys_enter(event_name, context, common_cpu,
42 common_secs, common_nsecs, common_pid, common_comm, 42 common_secs, common_nsecs, common_pid, common_comm,
43 common_callchain, id, args): 43 common_callchain, id, args):
44
45 if (for_comm and common_comm != for_comm) or \ 44 if (for_comm and common_comm != for_comm) or \
46 (for_pid and common_pid != for_pid ): 45 (for_pid and common_pid != for_pid ):
47 return 46 return
48 try: 47 try:
49 syscalls[common_comm][common_pid][id] += 1 48 syscalls[common_comm][common_pid][id] += 1
@@ -51,26 +50,26 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
51 syscalls[common_comm][common_pid][id] = 1 50 syscalls[common_comm][common_pid][id] = 1
52 51
53def syscalls__sys_enter(event_name, context, common_cpu, 52def syscalls__sys_enter(event_name, context, common_cpu,
54 common_secs, common_nsecs, common_pid, common_comm, 53 common_secs, common_nsecs, common_pid, common_comm,
55 id, args): 54 id, args):
56 raw_syscalls__sys_enter(**locals()) 55 raw_syscalls__sys_enter(**locals())
57 56
58def print_syscall_totals(): 57def print_syscall_totals():
59 if for_comm is not None: 58 if for_comm is not None:
60 print("\nsyscall events for %s:\n" % (for_comm)) 59 print("\nsyscall events for %s:\n" % (for_comm))
61 else: 60 else:
62 print("\nsyscall events by comm/pid:\n") 61 print("\nsyscall events by comm/pid:\n")
63 62
64 print("%-40s %10s" % ("comm [pid]/syscalls", "count")) 63 print("%-40s %10s" % ("comm [pid]/syscalls", "count"))
65 print("%-40s %10s" % ("----------------------------------------", 64 print("%-40s %10s" % ("----------------------------------------",
66 "----------")) 65 "----------"))
67 66
68 comm_keys = syscalls.keys() 67 comm_keys = syscalls.keys()
69 for comm in comm_keys: 68 for comm in comm_keys:
70 pid_keys = syscalls[comm].keys() 69 pid_keys = syscalls[comm].keys()
71 for pid in pid_keys: 70 for pid in pid_keys:
72 print("\n%s [%d]" % (comm, pid)) 71 print("\n%s [%d]" % (comm, pid))
73 id_keys = syscalls[comm][pid].keys() 72 id_keys = syscalls[comm][pid].keys()
74 for id, val in sorted(syscalls[comm][pid].items(), \ 73 for id, val in sorted(syscalls[comm][pid].items(),
75 key = lambda kv: (kv[1], kv[0]), reverse = True): 74 key = lambda kv: (kv[1], kv[0]), reverse = True):
76 print(" %-38s %10d" % (syscall_name(id), val)) 75 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 0ebd89cfd42c..8adb95ff1664 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -36,8 +36,8 @@ def trace_end():
36 print_syscall_totals() 36 print_syscall_totals()
37 37
38def raw_syscalls__sys_enter(event_name, context, common_cpu, 38def raw_syscalls__sys_enter(event_name, context, common_cpu,
39 common_secs, common_nsecs, common_pid, common_comm, 39 common_secs, common_nsecs, common_pid, common_comm,
40 common_callchain, id, args): 40 common_callchain, id, args):
41 if for_comm is not None: 41 if for_comm is not None:
42 if common_comm != for_comm: 42 if common_comm != for_comm:
43 return 43 return
@@ -47,20 +47,19 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
47 syscalls[id] = 1 47 syscalls[id] = 1
48 48
49def syscalls__sys_enter(event_name, context, common_cpu, 49def syscalls__sys_enter(event_name, context, common_cpu,
50 common_secs, common_nsecs, common_pid, common_comm, 50 common_secs, common_nsecs, common_pid, common_comm, id, args):
51 id, args):
52 raw_syscalls__sys_enter(**locals()) 51 raw_syscalls__sys_enter(**locals())
53 52
54def print_syscall_totals(): 53def print_syscall_totals():
55 if for_comm is not None: 54 if for_comm is not None:
56 print("\nsyscall events for %s:\n" % (for_comm)) 55 print("\nsyscall events for %s:\n" % (for_comm))
57 else: 56 else:
58 print("\nsyscall events:\n") 57 print("\nsyscall events:\n")
59 58
60 print("%-40s %10s" % ("event", "count")) 59 print("%-40s %10s" % ("event", "count"))
61 print("%-40s %10s" % ("----------------------------------------", 60 print("%-40s %10s" % ("----------------------------------------",
62 "-----------")) 61 "-----------"))
63 62
64 for id, val in sorted(syscalls.items(), key = lambda kv: (kv[1], kv[0]), \ 63 for id, val in sorted(syscalls.items(),
65 reverse = True): 64 key = lambda kv: (kv[1], kv[0]), reverse = True):
66 print("%-40s %10d" % (syscall_name(id), val)) 65 print("%-40s %10d" % (syscall_name(id), val))
diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c
index d66c66315987..ea68db08b8e7 100644
--- a/tools/perf/trace/beauty/msg_flags.c
+++ b/tools/perf/trace/beauty/msg_flags.c
@@ -29,7 +29,7 @@ static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
29 return scnprintf(bf, size, "NONE"); 29 return scnprintf(bf, size, "NONE");
30#define P_MSG_FLAG(n) \ 30#define P_MSG_FLAG(n) \
31 if (flags & MSG_##n) { \ 31 if (flags & MSG_##n) { \
32 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ 32 printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \
33 flags &= ~MSG_##n; \ 33 flags &= ~MSG_##n; \
34 } 34 }
35 35
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 11a8a447a3af..5f6dbbf5d749 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -198,18 +198,18 @@ static void ins__delete(struct ins_operands *ops)
198} 198}
199 199
200static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, 200static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
201 struct ins_operands *ops) 201 struct ins_operands *ops, int max_ins_name)
202{ 202{
203 return scnprintf(bf, size, "%-6s %s", ins->name, ops->raw); 203 return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw);
204} 204}
205 205
206int ins__scnprintf(struct ins *ins, char *bf, size_t size, 206int ins__scnprintf(struct ins *ins, char *bf, size_t size,
207 struct ins_operands *ops) 207 struct ins_operands *ops, int max_ins_name)
208{ 208{
209 if (ins->ops->scnprintf) 209 if (ins->ops->scnprintf)
210 return ins->ops->scnprintf(ins, bf, size, ops); 210 return ins->ops->scnprintf(ins, bf, size, ops, max_ins_name);
211 211
212 return ins__raw_scnprintf(ins, bf, size, ops); 212 return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
213} 213}
214 214
215bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2) 215bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
@@ -273,18 +273,18 @@ indirect_call:
273} 273}
274 274
275static int call__scnprintf(struct ins *ins, char *bf, size_t size, 275static int call__scnprintf(struct ins *ins, char *bf, size_t size,
276 struct ins_operands *ops) 276 struct ins_operands *ops, int max_ins_name)
277{ 277{
278 if (ops->target.sym) 278 if (ops->target.sym)
279 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name); 279 return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
280 280
281 if (ops->target.addr == 0) 281 if (ops->target.addr == 0)
282 return ins__raw_scnprintf(ins, bf, size, ops); 282 return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
283 283
284 if (ops->target.name) 284 if (ops->target.name)
285 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name); 285 return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.name);
286 286
287 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr); 287 return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr);
288} 288}
289 289
290static struct ins_ops call_ops = { 290static struct ins_ops call_ops = {
@@ -388,15 +388,15 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s
388} 388}
389 389
390static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 390static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
391 struct ins_operands *ops) 391 struct ins_operands *ops, int max_ins_name)
392{ 392{
393 const char *c; 393 const char *c;
394 394
395 if (!ops->target.addr || ops->target.offset < 0) 395 if (!ops->target.addr || ops->target.offset < 0)
396 return ins__raw_scnprintf(ins, bf, size, ops); 396 return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
397 397
398 if (ops->target.outside && ops->target.sym != NULL) 398 if (ops->target.outside && ops->target.sym != NULL)
399 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name); 399 return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
400 400
401 c = strchr(ops->raw, ','); 401 c = strchr(ops->raw, ',');
402 c = validate_comma(c, ops); 402 c = validate_comma(c, ops);
@@ -415,7 +415,7 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
415 c++; 415 c++;
416 } 416 }
417 417
418 return scnprintf(bf, size, "%-6s %.*s%" PRIx64, 418 return scnprintf(bf, size, "%-*s %.*s%" PRIx64, max_ins_name,
419 ins->name, c ? c - ops->raw : 0, ops->raw, 419 ins->name, c ? c - ops->raw : 0, ops->raw,
420 ops->target.offset); 420 ops->target.offset);
421} 421}
@@ -483,16 +483,16 @@ out_free_ops:
483} 483}
484 484
485static int lock__scnprintf(struct ins *ins, char *bf, size_t size, 485static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
486 struct ins_operands *ops) 486 struct ins_operands *ops, int max_ins_name)
487{ 487{
488 int printed; 488 int printed;
489 489
490 if (ops->locked.ins.ops == NULL) 490 if (ops->locked.ins.ops == NULL)
491 return ins__raw_scnprintf(ins, bf, size, ops); 491 return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
492 492
493 printed = scnprintf(bf, size, "%-6s ", ins->name); 493 printed = scnprintf(bf, size, "%-*s ", max_ins_name, ins->name);
494 return printed + ins__scnprintf(&ops->locked.ins, bf + printed, 494 return printed + ins__scnprintf(&ops->locked.ins, bf + printed,
495 size - printed, ops->locked.ops); 495 size - printed, ops->locked.ops, max_ins_name);
496} 496}
497 497
498static void lock__delete(struct ins_operands *ops) 498static void lock__delete(struct ins_operands *ops)
@@ -564,9 +564,9 @@ out_free_source:
564} 564}
565 565
566static int mov__scnprintf(struct ins *ins, char *bf, size_t size, 566static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
567 struct ins_operands *ops) 567 struct ins_operands *ops, int max_ins_name)
568{ 568{
569 return scnprintf(bf, size, "%-6s %s,%s", ins->name, 569 return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
570 ops->source.name ?: ops->source.raw, 570 ops->source.name ?: ops->source.raw,
571 ops->target.name ?: ops->target.raw); 571 ops->target.name ?: ops->target.raw);
572} 572}
@@ -604,9 +604,9 @@ static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops
604} 604}
605 605
606static int dec__scnprintf(struct ins *ins, char *bf, size_t size, 606static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
607 struct ins_operands *ops) 607 struct ins_operands *ops, int max_ins_name)
608{ 608{
609 return scnprintf(bf, size, "%-6s %s", ins->name, 609 return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
610 ops->target.name ?: ops->target.raw); 610 ops->target.name ?: ops->target.raw);
611} 611}
612 612
@@ -616,9 +616,9 @@ static struct ins_ops dec_ops = {
616}; 616};
617 617
618static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size, 618static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
619 struct ins_operands *ops __maybe_unused) 619 struct ins_operands *ops __maybe_unused, int max_ins_name)
620{ 620{
621 return scnprintf(bf, size, "%-6s", "nop"); 621 return scnprintf(bf, size, "%-*s", max_ins_name, "nop");
622} 622}
623 623
624static struct ins_ops nop_ops = { 624static struct ins_ops nop_ops = {
@@ -1232,12 +1232,12 @@ void disasm_line__free(struct disasm_line *dl)
1232 annotation_line__delete(&dl->al); 1232 annotation_line__delete(&dl->al);
1233} 1233}
1234 1234
1235int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw) 1235int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name)
1236{ 1236{
1237 if (raw || !dl->ins.ops) 1237 if (raw || !dl->ins.ops)
1238 return scnprintf(bf, size, "%-6s %s", dl->ins.name, dl->ops.raw); 1238 return scnprintf(bf, size, "%-*s %s", max_ins_name, dl->ins.name, dl->ops.raw);
1239 1239
1240 return ins__scnprintf(&dl->ins, bf, size, &dl->ops); 1240 return ins__scnprintf(&dl->ins, bf, size, &dl->ops, max_ins_name);
1241} 1241}
1242 1242
1243static void annotation_line__add(struct annotation_line *al, struct list_head *head) 1243static void annotation_line__add(struct annotation_line *al, struct list_head *head)
@@ -2414,12 +2414,30 @@ static inline int width_jumps(int n)
2414 return 1; 2414 return 1;
2415} 2415}
2416 2416
2417static int annotation__max_ins_name(struct annotation *notes)
2418{
2419 int max_name = 0, len;
2420 struct annotation_line *al;
2421
2422 list_for_each_entry(al, &notes->src->source, node) {
2423 if (al->offset == -1)
2424 continue;
2425
2426 len = strlen(disasm_line(al)->ins.name);
2427 if (max_name < len)
2428 max_name = len;
2429 }
2430
2431 return max_name;
2432}
2433
2417void annotation__init_column_widths(struct annotation *notes, struct symbol *sym) 2434void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2418{ 2435{
2419 notes->widths.addr = notes->widths.target = 2436 notes->widths.addr = notes->widths.target =
2420 notes->widths.min_addr = hex_width(symbol__size(sym)); 2437 notes->widths.min_addr = hex_width(symbol__size(sym));
2421 notes->widths.max_addr = hex_width(sym->end); 2438 notes->widths.max_addr = hex_width(sym->end);
2422 notes->widths.jumps = width_jumps(notes->max_jump_sources); 2439 notes->widths.jumps = width_jumps(notes->max_jump_sources);
2440 notes->widths.max_ins_name = annotation__max_ins_name(notes);
2423} 2441}
2424 2442
2425void annotation__update_column_widths(struct annotation *notes) 2443void annotation__update_column_widths(struct annotation *notes)
@@ -2583,7 +2601,7 @@ call_like:
2583 obj__printf(obj, " "); 2601 obj__printf(obj, " ");
2584 } 2602 }
2585 2603
2586 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset); 2604 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset, notes->widths.max_ins_name);
2587} 2605}
2588 2606
2589static void ipc_coverage_string(char *bf, int size, struct annotation *notes) 2607static void ipc_coverage_string(char *bf, int size, struct annotation *notes)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 95053cab41fe..df34fe483164 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -59,14 +59,14 @@ struct ins_ops {
59 void (*free)(struct ins_operands *ops); 59 void (*free)(struct ins_operands *ops);
60 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms); 60 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms);
61 int (*scnprintf)(struct ins *ins, char *bf, size_t size, 61 int (*scnprintf)(struct ins *ins, char *bf, size_t size,
62 struct ins_operands *ops); 62 struct ins_operands *ops, int max_ins_name);
63}; 63};
64 64
65bool ins__is_jump(const struct ins *ins); 65bool ins__is_jump(const struct ins *ins);
66bool ins__is_call(const struct ins *ins); 66bool ins__is_call(const struct ins *ins);
67bool ins__is_ret(const struct ins *ins); 67bool ins__is_ret(const struct ins *ins);
68bool ins__is_lock(const struct ins *ins); 68bool ins__is_lock(const struct ins *ins);
69int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 69int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops, int max_ins_name);
70bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2); 70bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
71 71
72#define ANNOTATION__IPC_WIDTH 6 72#define ANNOTATION__IPC_WIDTH 6
@@ -219,7 +219,7 @@ int __annotation__scnprintf_samples_period(struct annotation *notes,
219 struct perf_evsel *evsel, 219 struct perf_evsel *evsel,
220 bool show_freq); 220 bool show_freq);
221 221
222int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 222int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name);
223size_t disasm__fprintf(struct list_head *head, FILE *fp); 223size_t disasm__fprintf(struct list_head *head, FILE *fp);
224void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); 224void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
225 225
@@ -289,6 +289,7 @@ struct annotation {
289 u8 target; 289 u8 target;
290 u8 min_addr; 290 u8 min_addr;
291 u8 max_addr; 291 u8 max_addr;
292 u8 max_ins_name;
292 } widths; 293 } widths;
293 bool have_cycles; 294 bool have_cycles;
294 struct annotated_source *src; 295 struct annotated_source *src;
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 267e54df511b..fb76b6b232d4 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -1918,7 +1918,8 @@ static struct dso *load_dso(const char *name)
1918 if (!map) 1918 if (!map)
1919 return NULL; 1919 return NULL;
1920 1920
1921 map__load(map); 1921 if (map__load(map) < 0)
1922 pr_err("File '%s' not found or has no symbols.\n", name);
1922 1923
1923 dso = dso__get(map->dso); 1924 dso = dso__get(map->dso);
1924 1925
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 39c0004f2886..fc361c3f8570 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -156,7 +156,7 @@ getBPFObjectFromModule(llvm::Module *Module)
156#endif 156#endif
157 if (NotAdded) { 157 if (NotAdded) {
158 llvm::errs() << "TargetMachine can't emit a file of this type\n"; 158 llvm::errs() << "TargetMachine can't emit a file of this type\n";
159 return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);; 159 return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);
160 } 160 }
161 PM.run(*Module); 161 PM.run(*Module);
162 162
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 7bd5ddeb7a41..e098e189f93e 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -237,7 +237,7 @@ static int open_file(struct perf_data *data)
237 open_file_read(data) : open_file_write(data); 237 open_file_read(data) : open_file_write(data);
238 238
239 if (fd < 0) { 239 if (fd < 0) {
240 free(data->file.path); 240 zfree(&data->file.path);
241 return -1; 241 return -1;
242 } 242 }
243 243
@@ -270,7 +270,7 @@ int perf_data__open(struct perf_data *data)
270 270
271void perf_data__close(struct perf_data *data) 271void perf_data__close(struct perf_data *data)
272{ 272{
273 free(data->file.path); 273 zfree(&data->file.path);
274 close(data->file.fd); 274 close(data->file.fd);
275} 275}
276 276
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index de9b4769d06c..d7315a00c731 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -510,18 +510,23 @@ int db_export__call_path(struct db_export *dbe, struct call_path *cp)
510 return 0; 510 return 0;
511} 511}
512 512
513int db_export__call_return(struct db_export *dbe, struct call_return *cr) 513int db_export__call_return(struct db_export *dbe, struct call_return *cr,
514 u64 *parent_db_id)
514{ 515{
515 int err; 516 int err;
516 517
517 if (cr->db_id)
518 return 0;
519
520 err = db_export__call_path(dbe, cr->cp); 518 err = db_export__call_path(dbe, cr->cp);
521 if (err) 519 if (err)
522 return err; 520 return err;
523 521
524 cr->db_id = ++dbe->call_return_last_db_id; 522 if (!cr->db_id)
523 cr->db_id = ++dbe->call_return_last_db_id;
524
525 if (parent_db_id) {
526 if (!*parent_db_id)
527 *parent_db_id = ++dbe->call_return_last_db_id;
528 cr->parent_db_id = *parent_db_id;
529 }
525 530
526 if (dbe->export_call_return) 531 if (dbe->export_call_return)
527 return dbe->export_call_return(dbe, cr); 532 return dbe->export_call_return(dbe, cr);
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
index 67bc6b8ad2d6..4e2424c89df9 100644
--- a/tools/perf/util/db-export.h
+++ b/tools/perf/util/db-export.h
@@ -104,6 +104,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
104int db_export__branch_types(struct db_export *dbe); 104int db_export__branch_types(struct db_export *dbe);
105 105
106int db_export__call_path(struct db_export *dbe, struct call_path *cp); 106int db_export__call_path(struct db_export *dbe, struct call_path *cp);
107int db_export__call_return(struct db_export *dbe, struct call_return *cr); 107int db_export__call_return(struct db_export *dbe, struct call_return *cr,
108 u64 *parent_db_id);
108 109
109#endif 110#endif
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 08cedb643ea6..ed20f4379956 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -230,18 +230,33 @@ void perf_evlist__set_leader(struct perf_evlist *evlist)
230 } 230 }
231} 231}
232 232
233void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr) 233void perf_event_attr__set_max_precise_ip(struct perf_event_attr *pattr)
234{ 234{
235 attr->precise_ip = 3; 235 struct perf_event_attr attr = {
236 .type = PERF_TYPE_HARDWARE,
237 .config = PERF_COUNT_HW_CPU_CYCLES,
238 .exclude_kernel = 1,
239 .precise_ip = 3,
240 };
236 241
237 while (attr->precise_ip != 0) { 242 event_attr_init(&attr);
238 int fd = sys_perf_event_open(attr, 0, -1, -1, 0); 243
244 /*
245 * Unnamed union member, not supported as struct member named
246 * initializer in older compilers such as gcc 4.4.7
247 */
248 attr.sample_period = 1;
249
250 while (attr.precise_ip != 0) {
251 int fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
239 if (fd != -1) { 252 if (fd != -1) {
240 close(fd); 253 close(fd);
241 break; 254 break;
242 } 255 }
243 --attr->precise_ip; 256 --attr.precise_ip;
244 } 257 }
258
259 pattr->precise_ip = attr.precise_ip;
245} 260}
246 261
247int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise) 262int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index dfe2958e6287..3bbf73e979c0 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -294,20 +294,12 @@ struct perf_evsel *perf_evsel__new_cycles(bool precise)
294 294
295 if (!precise) 295 if (!precise)
296 goto new_event; 296 goto new_event;
297 /*
298 * Unnamed union member, not supported as struct member named
299 * initializer in older compilers such as gcc 4.4.7
300 *
301 * Just for probing the precise_ip:
302 */
303 attr.sample_period = 1;
304 297
305 perf_event_attr__set_max_precise_ip(&attr); 298 perf_event_attr__set_max_precise_ip(&attr);
306 /* 299 /*
307 * Now let the usual logic to set up the perf_event_attr defaults 300 * Now let the usual logic to set up the perf_event_attr defaults
308 * to kick in when we return and before perf_evsel__open() is called. 301 * to kick in when we return and before perf_evsel__open() is called.
309 */ 302 */
310 attr.sample_period = 0;
311new_event: 303new_event:
312 evsel = perf_evsel__new(&attr); 304 evsel = perf_evsel__new(&attr);
313 if (evsel == NULL) 305 if (evsel == NULL)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 669f961316f0..f9eb95bf3938 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -396,11 +396,8 @@ static int hist_entry__init(struct hist_entry *he,
396 * adding new entries. So we need to save a copy. 396 * adding new entries. So we need to save a copy.
397 */ 397 */
398 he->branch_info = malloc(sizeof(*he->branch_info)); 398 he->branch_info = malloc(sizeof(*he->branch_info));
399 if (he->branch_info == NULL) { 399 if (he->branch_info == NULL)
400 map__zput(he->ms.map); 400 goto err;
401 free(he->stat_acc);
402 return -ENOMEM;
403 }
404 401
405 memcpy(he->branch_info, template->branch_info, 402 memcpy(he->branch_info, template->branch_info,
406 sizeof(*he->branch_info)); 403 sizeof(*he->branch_info));
@@ -419,22 +416,16 @@ static int hist_entry__init(struct hist_entry *he,
419 416
420 if (he->raw_data) { 417 if (he->raw_data) {
421 he->raw_data = memdup(he->raw_data, he->raw_size); 418 he->raw_data = memdup(he->raw_data, he->raw_size);
419 if (he->raw_data == NULL)
420 goto err_infos;
421 }
422 422
423 if (he->raw_data == NULL) { 423 if (he->srcline) {
424 map__put(he->ms.map); 424 he->srcline = strdup(he->srcline);
425 if (he->branch_info) { 425 if (he->srcline == NULL)
426 map__put(he->branch_info->from.map); 426 goto err_rawdata;
427 map__put(he->branch_info->to.map);
428 free(he->branch_info);
429 }
430 if (he->mem_info) {
431 map__put(he->mem_info->iaddr.map);
432 map__put(he->mem_info->daddr.map);
433 }
434 free(he->stat_acc);
435 return -ENOMEM;
436 }
437 } 427 }
428
438 INIT_LIST_HEAD(&he->pairs.node); 429 INIT_LIST_HEAD(&he->pairs.node);
439 thread__get(he->thread); 430 thread__get(he->thread);
440 he->hroot_in = RB_ROOT_CACHED; 431 he->hroot_in = RB_ROOT_CACHED;
@@ -444,6 +435,24 @@ static int hist_entry__init(struct hist_entry *he,
444 he->leaf = true; 435 he->leaf = true;
445 436
446 return 0; 437 return 0;
438
439err_rawdata:
440 free(he->raw_data);
441
442err_infos:
443 if (he->branch_info) {
444 map__put(he->branch_info->from.map);
445 map__put(he->branch_info->to.map);
446 free(he->branch_info);
447 }
448 if (he->mem_info) {
449 map__put(he->mem_info->iaddr.map);
450 map__put(he->mem_info->daddr.map);
451 }
452err:
453 map__zput(he->ms.map);
454 free(he->stat_acc);
455 return -ENOMEM;
447} 456}
448 457
449static void *hist_entry__zalloc(size_t size) 458static void *hist_entry__zalloc(size_t size)
@@ -606,7 +615,7 @@ __hists__add_entry(struct hists *hists,
606 .map = al->map, 615 .map = al->map,
607 .sym = al->sym, 616 .sym = al->sym,
608 }, 617 },
609 .srcline = al->srcline ? strdup(al->srcline) : NULL, 618 .srcline = (char *) al->srcline,
610 .socket = al->socket, 619 .socket = al->socket,
611 .cpu = al->cpu, 620 .cpu = al->cpu,
612 .cpumode = al->cpumode, 621 .cpumode = al->cpumode,
@@ -963,7 +972,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
963 .map = al->map, 972 .map = al->map,
964 .sym = al->sym, 973 .sym = al->sym,
965 }, 974 },
966 .srcline = al->srcline ? strdup(al->srcline) : NULL, 975 .srcline = (char *) al->srcline,
967 .parent = iter->parent, 976 .parent = iter->parent,
968 .raw_data = sample->raw_data, 977 .raw_data = sample->raw_data,
969 .raw_size = sample->raw_size, 978 .raw_size = sample->raw_size,
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 0c0180c67574..47025bc727e1 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -328,35 +328,19 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
328{ 328{
329 struct machine *machine = btsq->bts->machine; 329 struct machine *machine = btsq->bts->machine;
330 struct thread *thread; 330 struct thread *thread;
331 struct addr_location al;
332 unsigned char buf[INTEL_PT_INSN_BUF_SZ]; 331 unsigned char buf[INTEL_PT_INSN_BUF_SZ];
333 ssize_t len; 332 ssize_t len;
334 int x86_64; 333 bool x86_64;
335 uint8_t cpumode;
336 int err = -1; 334 int err = -1;
337 335
338 if (machine__kernel_ip(machine, ip))
339 cpumode = PERF_RECORD_MISC_KERNEL;
340 else
341 cpumode = PERF_RECORD_MISC_USER;
342
343 thread = machine__find_thread(machine, -1, btsq->tid); 336 thread = machine__find_thread(machine, -1, btsq->tid);
344 if (!thread) 337 if (!thread)
345 return -1; 338 return -1;
346 339
347 if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso) 340 len = thread__memcpy(thread, machine, buf, ip, INTEL_PT_INSN_BUF_SZ, &x86_64);
348 goto out_put;
349
350 len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf,
351 INTEL_PT_INSN_BUF_SZ);
352 if (len <= 0) 341 if (len <= 0)
353 goto out_put; 342 goto out_put;
354 343
355 /* Load maps to ensure dso->is_64_bit has been updated */
356 map__load(al.map);
357
358 x86_64 = al.map->dso->is_64_bit;
359
360 if (intel_pt_get_insn(buf, len, x86_64, &btsq->intel_pt_insn)) 344 if (intel_pt_get_insn(buf, len, x86_64, &btsq->intel_pt_insn))
361 goto out_put; 345 goto out_put;
362 346
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 3b497bab4324..6d288237887b 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2531,6 +2531,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2531 } 2531 }
2532 2532
2533 pt->timeless_decoding = intel_pt_timeless_decoding(pt); 2533 pt->timeless_decoding = intel_pt_timeless_decoding(pt);
2534 if (pt->timeless_decoding && !pt->tc.time_mult)
2535 pt->tc.time_mult = 1;
2534 pt->have_tsc = intel_pt_have_tsc(pt); 2536 pt->have_tsc = intel_pt_have_tsc(pt);
2535 pt->sampling_mode = false; 2537 pt->sampling_mode = false;
2536 pt->est_tsc = !pt->timeless_decoding; 2538 pt->est_tsc = !pt->timeless_decoding;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 51d437f55d18..6199a3174ab9 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -752,6 +752,19 @@ perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
752 return NULL; 752 return NULL;
753} 753}
754 754
755static int pmu_max_precise(const char *name)
756{
757 char path[PATH_MAX];
758 int max_precise = -1;
759
760 scnprintf(path, PATH_MAX,
761 "bus/event_source/devices/%s/caps/max_precise",
762 name);
763
764 sysfs__read_int(path, &max_precise);
765 return max_precise;
766}
767
755static struct perf_pmu *pmu_lookup(const char *name) 768static struct perf_pmu *pmu_lookup(const char *name)
756{ 769{
757 struct perf_pmu *pmu; 770 struct perf_pmu *pmu;
@@ -784,6 +797,7 @@ static struct perf_pmu *pmu_lookup(const char *name)
784 pmu->name = strdup(name); 797 pmu->name = strdup(name);
785 pmu->type = type; 798 pmu->type = type;
786 pmu->is_uncore = pmu_is_uncore(name); 799 pmu->is_uncore = pmu_is_uncore(name);
800 pmu->max_precise = pmu_max_precise(name);
787 pmu_add_cpu_aliases(&aliases, pmu); 801 pmu_add_cpu_aliases(&aliases, pmu);
788 802
789 INIT_LIST_HEAD(&pmu->format); 803 INIT_LIST_HEAD(&pmu->format);
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 47253c3daf55..bd9ec2704a57 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -26,6 +26,7 @@ struct perf_pmu {
26 __u32 type; 26 __u32 type;
27 bool selectable; 27 bool selectable;
28 bool is_uncore; 28 bool is_uncore;
29 int max_precise;
29 struct perf_event_attr *default_config; 30 struct perf_event_attr *default_config;
30 struct cpu_map *cpus; 31 struct cpu_map *cpus;
31 struct list_head format; /* HEAD struct perf_pmu_format -> list */ 32 struct list_head format; /* HEAD struct perf_pmu_format -> list */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 0030f9b9bf7e..a1b8d9649ca7 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -472,9 +472,12 @@ static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi,
472 strcpy(reason, "(unknown)"); 472 strcpy(reason, "(unknown)");
473 } else 473 } else
474 dso__strerror_load(dso, reason, STRERR_BUFSIZE); 474 dso__strerror_load(dso, reason, STRERR_BUFSIZE);
475 if (!silent) 475 if (!silent) {
476 pr_err("Failed to find the path for %s: %s\n", 476 if (module)
477 module ?: "kernel", reason); 477 pr_err("Module %s is not loaded, please specify its full path name.\n", module);
478 else
479 pr_err("Failed to find the path for the kernel: %s\n", reason);
480 }
478 return NULL; 481 return NULL;
479 } 482 }
480 path = dso->long_name; 483 path = dso->long_name;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 0e17db41b49b..09604c6508f0 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1173,7 +1173,7 @@ static int python_export_call_return(struct db_export *dbe,
1173 u64 comm_db_id = cr->comm ? cr->comm->db_id : 0; 1173 u64 comm_db_id = cr->comm ? cr->comm->db_id : 0;
1174 PyObject *t; 1174 PyObject *t;
1175 1175
1176 t = tuple_new(11); 1176 t = tuple_new(12);
1177 1177
1178 tuple_set_u64(t, 0, cr->db_id); 1178 tuple_set_u64(t, 0, cr->db_id);
1179 tuple_set_u64(t, 1, cr->thread->db_id); 1179 tuple_set_u64(t, 1, cr->thread->db_id);
@@ -1186,6 +1186,7 @@ static int python_export_call_return(struct db_export *dbe,
1186 tuple_set_u64(t, 8, cr->return_ref); 1186 tuple_set_u64(t, 8, cr->return_ref);
1187 tuple_set_u64(t, 9, cr->cp->parent->db_id); 1187 tuple_set_u64(t, 9, cr->cp->parent->db_id);
1188 tuple_set_s32(t, 10, cr->flags); 1188 tuple_set_s32(t, 10, cr->flags);
1189 tuple_set_u64(t, 11, cr->parent_db_id);
1189 1190
1190 call_object(tables->call_return_handler, t, "call_return_table"); 1191 call_object(tables->call_return_handler, t, "call_return_table");
1191 1192
@@ -1194,11 +1195,12 @@ static int python_export_call_return(struct db_export *dbe,
1194 return 0; 1195 return 0;
1195} 1196}
1196 1197
1197static int python_process_call_return(struct call_return *cr, void *data) 1198static int python_process_call_return(struct call_return *cr, u64 *parent_db_id,
1199 void *data)
1198{ 1200{
1199 struct db_export *dbe = data; 1201 struct db_export *dbe = data;
1200 1202
1201 return db_export__call_return(dbe, cr); 1203 return db_export__call_return(dbe, cr, parent_db_id);
1202} 1204}
1203 1205
1204static void python_process_general_event(struct perf_sample *sample, 1206static void python_process_general_event(struct perf_sample *sample,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index c764bbc91009..db643f3c2b95 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -140,7 +140,7 @@ struct perf_session *perf_session__new(struct perf_data *data,
140 140
141 if (perf_data__is_read(data)) { 141 if (perf_data__is_read(data)) {
142 if (perf_session__open(session) < 0) 142 if (perf_session__open(session) < 0)
143 goto out_close; 143 goto out_delete;
144 144
145 /* 145 /*
146 * set session attributes that are present in perf.data 146 * set session attributes that are present in perf.data
@@ -181,8 +181,6 @@ struct perf_session *perf_session__new(struct perf_data *data,
181 181
182 return session; 182 return session;
183 183
184 out_close:
185 perf_data__close(data);
186 out_delete: 184 out_delete:
187 perf_session__delete(session); 185 perf_session__delete(session);
188 out: 186 out:
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index a8b45168513c..41942c2aaa18 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -49,6 +49,7 @@ enum retpoline_state_t {
49 * @timestamp: timestamp (if known) 49 * @timestamp: timestamp (if known)
50 * @ref: external reference (e.g. db_id of sample) 50 * @ref: external reference (e.g. db_id of sample)
51 * @branch_count: the branch count when the entry was created 51 * @branch_count: the branch count when the entry was created
52 * @db_id: id used for db-export
52 * @cp: call path 53 * @cp: call path
53 * @no_call: a 'call' was not seen 54 * @no_call: a 'call' was not seen
54 * @trace_end: a 'call' but trace ended 55 * @trace_end: a 'call' but trace ended
@@ -59,6 +60,7 @@ struct thread_stack_entry {
59 u64 timestamp; 60 u64 timestamp;
60 u64 ref; 61 u64 ref;
61 u64 branch_count; 62 u64 branch_count;
63 u64 db_id;
62 struct call_path *cp; 64 struct call_path *cp;
63 bool no_call; 65 bool no_call;
64 bool trace_end; 66 bool trace_end;
@@ -280,12 +282,14 @@ static int thread_stack__call_return(struct thread *thread,
280 .comm = ts->comm, 282 .comm = ts->comm,
281 .db_id = 0, 283 .db_id = 0,
282 }; 284 };
285 u64 *parent_db_id;
283 286
284 tse = &ts->stack[idx]; 287 tse = &ts->stack[idx];
285 cr.cp = tse->cp; 288 cr.cp = tse->cp;
286 cr.call_time = tse->timestamp; 289 cr.call_time = tse->timestamp;
287 cr.return_time = timestamp; 290 cr.return_time = timestamp;
288 cr.branch_count = ts->branch_count - tse->branch_count; 291 cr.branch_count = ts->branch_count - tse->branch_count;
292 cr.db_id = tse->db_id;
289 cr.call_ref = tse->ref; 293 cr.call_ref = tse->ref;
290 cr.return_ref = ref; 294 cr.return_ref = ref;
291 if (tse->no_call) 295 if (tse->no_call)
@@ -295,7 +299,14 @@ static int thread_stack__call_return(struct thread *thread,
295 if (tse->non_call) 299 if (tse->non_call)
296 cr.flags |= CALL_RETURN_NON_CALL; 300 cr.flags |= CALL_RETURN_NON_CALL;
297 301
298 return crp->process(&cr, crp->data); 302 /*
303 * The parent db_id must be assigned before exporting the child. Note
304 * it is not possible to export the parent first because its information
305 * is not yet complete because its 'return' has not yet been processed.
306 */
307 parent_db_id = idx ? &(tse - 1)->db_id : NULL;
308
309 return crp->process(&cr, parent_db_id, crp->data);
299} 310}
300 311
301static int __thread_stack__flush(struct thread *thread, struct thread_stack *ts) 312static int __thread_stack__flush(struct thread *thread, struct thread_stack *ts)
@@ -484,7 +495,7 @@ void thread_stack__sample(struct thread *thread, int cpu,
484} 495}
485 496
486struct call_return_processor * 497struct call_return_processor *
487call_return_processor__new(int (*process)(struct call_return *cr, void *data), 498call_return_processor__new(int (*process)(struct call_return *cr, u64 *parent_db_id, void *data),
488 void *data) 499 void *data)
489{ 500{
490 struct call_return_processor *crp; 501 struct call_return_processor *crp;
@@ -537,6 +548,7 @@ static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
537 tse->no_call = no_call; 548 tse->no_call = no_call;
538 tse->trace_end = trace_end; 549 tse->trace_end = trace_end;
539 tse->non_call = false; 550 tse->non_call = false;
551 tse->db_id = 0;
540 552
541 return 0; 553 return 0;
542} 554}
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index b7c04e19ad41..9c45f947f5a9 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -55,6 +55,7 @@ enum {
55 * @call_ref: external reference to 'call' sample (e.g. db_id) 55 * @call_ref: external reference to 'call' sample (e.g. db_id)
56 * @return_ref: external reference to 'return' sample (e.g. db_id) 56 * @return_ref: external reference to 'return' sample (e.g. db_id)
57 * @db_id: id used for db-export 57 * @db_id: id used for db-export
58 * @parent_db_id: id of parent call used for db-export
58 * @flags: Call/Return flags 59 * @flags: Call/Return flags
59 */ 60 */
60struct call_return { 61struct call_return {
@@ -67,6 +68,7 @@ struct call_return {
67 u64 call_ref; 68 u64 call_ref;
68 u64 return_ref; 69 u64 return_ref;
69 u64 db_id; 70 u64 db_id;
71 u64 parent_db_id;
70 u32 flags; 72 u32 flags;
71}; 73};
72 74
@@ -79,7 +81,7 @@ struct call_return {
79 */ 81 */
80struct call_return_processor { 82struct call_return_processor {
81 struct call_path_root *cpr; 83 struct call_path_root *cpr;
82 int (*process)(struct call_return *cr, void *data); 84 int (*process)(struct call_return *cr, u64 *parent_db_id, void *data);
83 void *data; 85 void *data;
84}; 86};
85 87
@@ -93,7 +95,7 @@ void thread_stack__free(struct thread *thread);
93size_t thread_stack__depth(struct thread *thread, int cpu); 95size_t thread_stack__depth(struct thread *thread, int cpu);
94 96
95struct call_return_processor * 97struct call_return_processor *
96call_return_processor__new(int (*process)(struct call_return *cr, void *data), 98call_return_processor__new(int (*process)(struct call_return *cr, u64 *parent_db_id, void *data),
97 void *data); 99 void *data);
98void call_return_processor__free(struct call_return_processor *crp); 100void call_return_processor__free(struct call_return_processor *crp);
99int thread_stack__process(struct thread *thread, struct comm *comm, 101int thread_stack__process(struct thread *thread, struct comm *comm,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 4c179fef442d..50678d318185 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -12,6 +12,7 @@
12#include "debug.h" 12#include "debug.h"
13#include "namespaces.h" 13#include "namespaces.h"
14#include "comm.h" 14#include "comm.h"
15#include "map.h"
15#include "symbol.h" 16#include "symbol.h"
16#include "unwind.h" 17#include "unwind.h"
17 18
@@ -393,3 +394,25 @@ struct thread *thread__main_thread(struct machine *machine, struct thread *threa
393 394
394 return machine__find_thread(machine, thread->pid_, thread->pid_); 395 return machine__find_thread(machine, thread->pid_, thread->pid_);
395} 396}
397
398int thread__memcpy(struct thread *thread, struct machine *machine,
399 void *buf, u64 ip, int len, bool *is64bit)
400{
401 u8 cpumode = PERF_RECORD_MISC_USER;
402 struct addr_location al;
403 long offset;
404
405 if (machine__kernel_ip(machine, ip))
406 cpumode = PERF_RECORD_MISC_KERNEL;
407
408 if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso ||
409 al.map->dso->data.status == DSO_DATA_STATUS_ERROR ||
410 map__load(al.map) < 0)
411 return -1;
412
413 offset = al.map->map_ip(al.map, ip);
414 if (is64bit)
415 *is64bit = al.map->dso->is_64_bit;
416
417 return dso__data_read_offset(al.map->dso, machine, offset, buf, len);
418}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 8276ffeec556..cf8375c017a0 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -113,6 +113,9 @@ struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode,
113void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, 113void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
114 struct addr_location *al); 114 struct addr_location *al);
115 115
116int thread__memcpy(struct thread *thread, struct machine *machine,
117 void *buf, u64 ip, int len, bool *is64bit);
118
116static inline void *thread__priv(struct thread *thread) 119static inline void *thread__priv(struct thread *thread)
117{ 120{
118 return thread->priv; 121 return thread->priv;
diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index 6193b46050a5..0f53baec660e 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -11,6 +11,8 @@
11#include "perf.h" 11#include "perf.h"
12#include "debug.h" 12#include "debug.h"
13#include "time-utils.h" 13#include "time-utils.h"
14#include "session.h"
15#include "evlist.h"
14 16
15int parse_nsec_time(const char *str, u64 *ptime) 17int parse_nsec_time(const char *str, u64 *ptime)
16{ 18{
@@ -374,7 +376,7 @@ bool perf_time__ranges_skip_sample(struct perf_time_interval *ptime_buf,
374 struct perf_time_interval *ptime; 376 struct perf_time_interval *ptime;
375 int i; 377 int i;
376 378
377 if ((timestamp == 0) || (num == 0)) 379 if ((!ptime_buf) || (timestamp == 0) || (num == 0))
378 return false; 380 return false;
379 381
380 if (num == 1) 382 if (num == 1)
@@ -396,6 +398,53 @@ bool perf_time__ranges_skip_sample(struct perf_time_interval *ptime_buf,
396 return (i == num) ? true : false; 398 return (i == num) ? true : false;
397} 399}
398 400
401int perf_time__parse_for_ranges(const char *time_str,
402 struct perf_session *session,
403 struct perf_time_interval **ranges,
404 int *range_size, int *range_num)
405{
406 struct perf_time_interval *ptime_range;
407 int size, num, ret;
408
409 ptime_range = perf_time__range_alloc(time_str, &size);
410 if (!ptime_range)
411 return -ENOMEM;
412
413 if (perf_time__parse_str(ptime_range, time_str) != 0) {
414 if (session->evlist->first_sample_time == 0 &&
415 session->evlist->last_sample_time == 0) {
416 pr_err("HINT: no first/last sample time found in perf data.\n"
417 "Please use latest perf binary to execute 'perf record'\n"
418 "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n");
419 ret = -EINVAL;
420 goto error;
421 }
422
423 num = perf_time__percent_parse_str(
424 ptime_range, size,
425 time_str,
426 session->evlist->first_sample_time,
427 session->evlist->last_sample_time);
428
429 if (num < 0) {
430 pr_err("Invalid time string\n");
431 ret = -EINVAL;
432 goto error;
433 }
434 } else {
435 num = 1;
436 }
437
438 *range_size = size;
439 *range_num = num;
440 *ranges = ptime_range;
441 return 0;
442
443error:
444 free(ptime_range);
445 return ret;
446}
447
399int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz) 448int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
400{ 449{
401 u64 sec = timestamp / NSEC_PER_SEC; 450 u64 sec = timestamp / NSEC_PER_SEC;
diff --git a/tools/perf/util/time-utils.h b/tools/perf/util/time-utils.h
index 70b177d2b98c..b923de44e36f 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -23,6 +23,12 @@ bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp);
23bool perf_time__ranges_skip_sample(struct perf_time_interval *ptime_buf, 23bool perf_time__ranges_skip_sample(struct perf_time_interval *ptime_buf,
24 int num, u64 timestamp); 24 int num, u64 timestamp);
25 25
26struct perf_session;
27
28int perf_time__parse_for_ranges(const char *str, struct perf_session *session,
29 struct perf_time_interval **ranges,
30 int *range_size, int *range_num);
31
26int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz); 32int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
27 33
28int fetch_current_timestamp(char *buf, size_t sz); 34int fetch_current_timestamp(char *buf, size_t sz);