aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt2
-rw-r--r--tools/perf/Documentation/perf-list.txt13
-rw-r--r--tools/perf/Documentation/perf-mem.txt9
-rw-r--r--tools/perf/Documentation/perf-record.txt19
-rw-r--r--tools/perf/Documentation/perf-script.txt28
-rw-r--r--tools/perf/Documentation/perf-stat.txt20
-rw-r--r--tools/perf/MANIFEST6
-rw-r--r--tools/perf/Makefile.perf11
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c19
-rw-r--r--tools/perf/bench/futex.h13
-rw-r--r--tools/perf/bench/sched-pipe.c2
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-buildid-cache.c4
-rw-r--r--tools/perf/builtin-diff.c254
-rw-r--r--tools/perf/builtin-inject.c5
-rw-r--r--tools/perf/builtin-list.c13
-rw-r--r--tools/perf/builtin-mem.c131
-rw-r--r--tools/perf/builtin-record.c70
-rw-r--r--tools/perf/builtin-report.c40
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-top.c7
-rw-r--r--tools/perf/builtin-trace.c106
-rw-r--r--tools/perf/config/Makefile8
-rw-r--r--tools/perf/config/Makefile.arch26
-rw-r--r--tools/perf/config/feature-checks/Makefile4
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c14
-rw-r--r--tools/perf/perf-sys.h1
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.c5
-rw-r--r--tools/perf/tests/attr.py1
-rw-r--r--tools/perf/tests/dwarf-unwind.c36
-rw-r--r--tools/perf/tests/hists_cumulate.c68
-rw-r--r--tools/perf/tests/hists_filter.c2
-rw-r--r--tools/perf/tests/hists_output.c12
-rw-r--r--tools/perf/tests/make1
-rw-r--r--tools/perf/tests/parse-events.c60
-rw-r--r--tools/perf/tests/sample-parsing.c2
-rw-r--r--tools/perf/ui/browsers/annotate.c3
-rw-r--r--tools/perf/ui/browsers/hists.c2
-rw-r--r--tools/perf/ui/hist.c15
-rw-r--r--tools/perf/ui/progress.h4
-rw-r--r--tools/perf/ui/tui/helpline.c3
-rw-r--r--tools/perf/ui/tui/setup.c29
-rw-r--r--tools/perf/util/annotate.c20
-rw-r--r--tools/perf/util/annotate.h8
-rw-r--r--tools/perf/util/cache.h2
-rw-r--r--tools/perf/util/callchain.c30
-rw-r--r--tools/perf/util/callchain.h2
-rw-r--r--tools/perf/util/color.c126
-rw-r--r--tools/perf/util/color.h2
-rw-r--r--tools/perf/util/dso.c6
-rw-r--r--tools/perf/util/dso.h1
-rw-r--r--tools/perf/util/evlist.c27
-rw-r--r--tools/perf/util/evlist.h1
-rw-r--r--tools/perf/util/evsel.c4
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/hist.c66
-rw-r--r--tools/perf/util/hist.h13
-rw-r--r--tools/perf/util/hweight.c31
-rw-r--r--tools/perf/util/include/asm/hweight.h8
-rw-r--r--tools/perf/util/machine.c4
-rw-r--r--tools/perf/util/map.h16
-rw-r--r--tools/perf/util/parse-events.c27
-rw-r--r--tools/perf/util/parse-events.h3
-rw-r--r--tools/perf/util/parse-events.l1
-rw-r--r--tools/perf/util/parse-events.y26
-rw-r--r--tools/perf/util/parse-options.c2
-rw-r--r--tools/perf/util/pmu.c102
-rw-r--r--tools/perf/util/probe-event.c44
-rw-r--r--tools/perf/util/probe-finder.c18
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/python.c2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c2
-rw-r--r--tools/perf/util/session.c8
-rw-r--r--tools/perf/util/session.h3
-rw-r--r--tools/perf/util/sort.c37
-rw-r--r--tools/perf/util/symbol-elf.c13
-rw-r--r--tools/perf/util/symbol.c33
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/unwind-libunwind.c59
80 files changed, 1187 insertions, 642 deletions
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index fd77d81ea748..0294c57b1f5e 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -38,7 +38,7 @@ OPTIONS
38--remove=:: 38--remove=::
39 Remove specified file from the cache. 39 Remove specified file from the cache.
40-M:: 40-M::
41--missing=:: 41--missing=::
42 List missing build ids in the cache for the specified file. 42 List missing build ids in the cache for the specified file.
43-u:: 43-u::
44--update:: 44--update::
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index cbb4f743d921..3e2aec94f806 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -89,6 +89,19 @@ raw encoding of 0x1A8 can be used:
89You should refer to the processor specific documentation for getting these 89You should refer to the processor specific documentation for getting these
90details. Some of them are referenced in the SEE ALSO section below. 90details. Some of them are referenced in the SEE ALSO section below.
91 91
92PARAMETERIZED EVENTS
93--------------------
94
95Some pmu events listed by 'perf-list' will be displayed with '?' in them. For
96example:
97
98 hv_gpci/dtbp_ptitc,phys_processor_idx=?/
99
100This means that when provided as an event, a value for '?' must
101also be supplied. For example:
102
103 perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...
104
92OPTIONS 105OPTIONS
93------- 106-------
94 107
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 1d78a4064da4..43310d8661fe 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -12,11 +12,12 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15"perf mem -t <TYPE> record" runs a command and gathers memory operation data 15"perf mem record" runs a command and gathers memory operation data
16from it, into perf.data. Perf record options are accepted and are passed through. 16from it, into perf.data. Perf record options are accepted and are passed through.
17 17
18"perf mem -t <TYPE> report" displays the result. It invokes perf report with the 18"perf mem report" displays the result. It invokes perf report with the
19right set of options to display a memory access profile. 19right set of options to display a memory access profile. By default, loads
20and stores are sampled. Use the -t option to limit to loads or stores.
20 21
21Note that on Intel systems the memory latency reported is the use-latency, 22Note that on Intel systems the memory latency reported is the use-latency,
22not the pure load (or store latency). Use latency includes any pipeline 23not the pure load (or store latency). Use latency includes any pipeline
@@ -29,7 +30,7 @@ OPTIONS
29 30
30-t:: 31-t::
31--type=:: 32--type=::
32 Select the memory operation type: load or store (default: load) 33 Select the memory operation type: load or store (default: load,store)
33 34
34-D:: 35-D::
35--dump-raw-samples=:: 36--dump-raw-samples=::
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index af9a54ece024..31e977459c51 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -33,12 +33,27 @@ OPTIONS
33 - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a 33 - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
34 hexadecimal event descriptor. 34 hexadecimal event descriptor.
35 35
36 - a hardware breakpoint event in the form of '\mem:addr[:access]' 36 - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where
37 'param1', 'param2', etc are defined as formats for the PMU in
38 /sys/bus/event_sources/devices/<pmu>/format/*.
39
40 - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/'
41
42 where M, N, K are numbers (in decimal, hex, octal format). Acceptable
43 values for each of 'config', 'config1' and 'config2' are defined by
44 corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/*
45 param1 and param2 are defined as formats for the PMU in:
46 /sys/bus/event_sources/devices/<pmu>/format/*
47
48 - a hardware breakpoint event in the form of '\mem:addr[/len][:access]'
37 where addr is the address in memory you want to break in. 49 where addr is the address in memory you want to break in.
38 Access is the memory access type (read, write, execute) it can 50 Access is the memory access type (read, write, execute) it can
39 be passed as follows: '\mem:addr[:[r][w][x]]'. 51 be passed as follows: '\mem:addr[:[r][w][x]]'. len is the range,
52 number of bytes from specified addr, which the breakpoint will cover.
40 If you want to profile read-write accesses in 0x1000, just set 53 If you want to profile read-write accesses in 0x1000, just set
41 'mem:0x1000:rw'. 54 'mem:0x1000:rw'.
55 If you want to profile write accesses in [0x1000~1008), just set
56 'mem:0x1000/8:w'.
42 57
43--filter=<filter>:: 58--filter=<filter>::
44 Event filter. 59 Event filter.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 21494806c0ab..a21eec05bc42 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -125,46 +125,46 @@ OPTIONS
125 is equivalent to: 125 is equivalent to:
126 126
127 perf script -f trace:<fields> -f sw:<fields> -f hw:<fields> 127 perf script -f trace:<fields> -f sw:<fields> -f hw:<fields>
128 128
129 i.e., the specified fields apply to all event types if the type string 129 i.e., the specified fields apply to all event types if the type string
130 is not given. 130 is not given.
131 131
132 The arguments are processed in the order received. A later usage can 132 The arguments are processed in the order received. A later usage can
133 reset a prior request. e.g.: 133 reset a prior request. e.g.:
134 134
135 -f trace: -f comm,tid,time,ip,sym 135 -f trace: -f comm,tid,time,ip,sym
136 136
137 The first -f suppresses trace events (field list is ""), but then the 137 The first -f suppresses trace events (field list is ""), but then the
138 second invocation sets the fields to comm,tid,time,ip,sym. In this case a 138 second invocation sets the fields to comm,tid,time,ip,sym. In this case a
139 warning is given to the user: 139 warning is given to the user:
140 140
141 "Overriding previous field request for all events." 141 "Overriding previous field request for all events."
142 142
143 Alternatively, consider the order: 143 Alternatively, consider the order:
144 144
145 -f comm,tid,time,ip,sym -f trace: 145 -f comm,tid,time,ip,sym -f trace:
146 146
147 The first -f sets the fields for all events and the second -f 147 The first -f sets the fields for all events and the second -f
148 suppresses trace events. The user is given a warning message about 148 suppresses trace events. The user is given a warning message about
149 the override, and the result of the above is that only S/W and H/W 149 the override, and the result of the above is that only S/W and H/W
150 events are displayed with the given fields. 150 events are displayed with the given fields.
151 151
152 For the 'wildcard' option if a user selected field is invalid for an 152 For the 'wildcard' option if a user selected field is invalid for an
153 event type, a message is displayed to the user that the option is 153 event type, a message is displayed to the user that the option is
154 ignored for that type. For example: 154 ignored for that type. For example:
155 155
156 $ perf script -f comm,tid,trace 156 $ perf script -f comm,tid,trace
157 'trace' not valid for hardware events. Ignoring. 157 'trace' not valid for hardware events. Ignoring.
158 'trace' not valid for software events. Ignoring. 158 'trace' not valid for software events. Ignoring.
159 159
160 Alternatively, if the type is given an invalid field is specified it 160 Alternatively, if the type is given an invalid field is specified it
161 is an error. For example: 161 is an error. For example:
162 162
163 perf script -v -f sw:comm,tid,trace 163 perf script -v -f sw:comm,tid,trace
164 'trace' not valid for software events. 164 'trace' not valid for software events.
165 165
166 At this point usage is displayed, and perf-script exits. 166 At this point usage is displayed, and perf-script exits.
167 167
168 Finally, a user may not set fields to none for all event types. 168 Finally, a user may not set fields to none for all event types.
169 i.e., -f "" is not allowed. 169 i.e., -f "" is not allowed.
170 170
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 29ee857c09c6..04e150d83e7d 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -25,10 +25,22 @@ OPTIONS
25 25
26-e:: 26-e::
27--event=:: 27--event=::
28 Select the PMU event. Selection can be a symbolic event name 28 Select the PMU event. Selection can be:
29 (use 'perf list' to list all events) or a raw PMU 29
30 event (eventsel+umask) in the form of rNNN where NNN is a 30 - a symbolic event name (use 'perf list' to list all events)
31 hexadecimal event descriptor. 31
32 - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
33 hexadecimal event descriptor.
34
35 - a symbolically formed event like 'pmu/param1=0x3,param2/' where
36 param1 and param2 are defined as formats for the PMU in
37 /sys/bus/event_sources/devices/<pmu>/format/*
38
39 - a symbolically formed event like 'pmu/config=M,config1=N,config2=K/'
40 where M, N, K are numbers (in decimal, hex, octal format).
41 Acceptable values for each of 'config', 'config1' and 'config2'
42 parameters are defined by corresponding entries in
43 /sys/bus/event_sources/devices/<pmu>/format/*
32 44
33-i:: 45-i::
34--no-inherit:: 46--no-inherit::
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 83e2887f91a3..fbbfdc39271d 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -6,12 +6,15 @@ tools/lib/symbol/kallsyms.c
6tools/lib/symbol/kallsyms.h 6tools/lib/symbol/kallsyms.h
7tools/lib/util/find_next_bit.c 7tools/lib/util/find_next_bit.c
8tools/include/asm/bug.h 8tools/include/asm/bug.h
9tools/include/asm-generic/bitops/arch_hweight.h
9tools/include/asm-generic/bitops/atomic.h 10tools/include/asm-generic/bitops/atomic.h
11tools/include/asm-generic/bitops/const_hweight.h
10tools/include/asm-generic/bitops/__ffs.h 12tools/include/asm-generic/bitops/__ffs.h
11tools/include/asm-generic/bitops/__fls.h 13tools/include/asm-generic/bitops/__fls.h
12tools/include/asm-generic/bitops/find.h 14tools/include/asm-generic/bitops/find.h
13tools/include/asm-generic/bitops/fls64.h 15tools/include/asm-generic/bitops/fls64.h
14tools/include/asm-generic/bitops/fls.h 16tools/include/asm-generic/bitops/fls.h
17tools/include/asm-generic/bitops/hweight.h
15tools/include/asm-generic/bitops.h 18tools/include/asm-generic/bitops.h
16tools/include/linux/bitops.h 19tools/include/linux/bitops.h
17tools/include/linux/compiler.h 20tools/include/linux/compiler.h
@@ -19,6 +22,8 @@ tools/include/linux/export.h
19tools/include/linux/hash.h 22tools/include/linux/hash.h
20tools/include/linux/log2.h 23tools/include/linux/log2.h
21tools/include/linux/types.h 24tools/include/linux/types.h
25include/asm-generic/bitops/arch_hweight.h
26include/asm-generic/bitops/const_hweight.h
22include/asm-generic/bitops/fls64.h 27include/asm-generic/bitops/fls64.h
23include/asm-generic/bitops/__fls.h 28include/asm-generic/bitops/__fls.h
24include/asm-generic/bitops/fls.h 29include/asm-generic/bitops/fls.h
@@ -29,6 +34,7 @@ include/linux/list.h
29include/linux/hash.h 34include/linux/hash.h
30include/linux/stringify.h 35include/linux/stringify.h
31lib/find_next_bit.c 36lib/find_next_bit.c
37lib/hweight.c
32lib/rbtree.c 38lib/rbtree.c
33include/linux/swab.h 39include/linux/swab.h
34arch/*/include/asm/unistd*.h 40arch/*/include/asm/unistd*.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 67a03a825b3c..aa6a50447c32 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -232,12 +232,15 @@ LIB_H += ../include/linux/hash.h
232LIB_H += ../../include/linux/stringify.h 232LIB_H += ../../include/linux/stringify.h
233LIB_H += util/include/linux/bitmap.h 233LIB_H += util/include/linux/bitmap.h
234LIB_H += ../include/linux/bitops.h 234LIB_H += ../include/linux/bitops.h
235LIB_H += ../include/asm-generic/bitops/arch_hweight.h
235LIB_H += ../include/asm-generic/bitops/atomic.h 236LIB_H += ../include/asm-generic/bitops/atomic.h
237LIB_H += ../include/asm-generic/bitops/const_hweight.h
236LIB_H += ../include/asm-generic/bitops/find.h 238LIB_H += ../include/asm-generic/bitops/find.h
237LIB_H += ../include/asm-generic/bitops/fls64.h 239LIB_H += ../include/asm-generic/bitops/fls64.h
238LIB_H += ../include/asm-generic/bitops/fls.h 240LIB_H += ../include/asm-generic/bitops/fls.h
239LIB_H += ../include/asm-generic/bitops/__ffs.h 241LIB_H += ../include/asm-generic/bitops/__ffs.h
240LIB_H += ../include/asm-generic/bitops/__fls.h 242LIB_H += ../include/asm-generic/bitops/__fls.h
243LIB_H += ../include/asm-generic/bitops/hweight.h
241LIB_H += ../include/asm-generic/bitops.h 244LIB_H += ../include/asm-generic/bitops.h
242LIB_H += ../include/linux/compiler.h 245LIB_H += ../include/linux/compiler.h
243LIB_H += ../include/linux/log2.h 246LIB_H += ../include/linux/log2.h
@@ -255,7 +258,6 @@ LIB_H += util/include/linux/linkage.h
255LIB_H += util/include/asm/asm-offsets.h 258LIB_H += util/include/asm/asm-offsets.h
256LIB_H += ../include/asm/bug.h 259LIB_H += ../include/asm/bug.h
257LIB_H += util/include/asm/byteorder.h 260LIB_H += util/include/asm/byteorder.h
258LIB_H += util/include/asm/hweight.h
259LIB_H += util/include/asm/swab.h 261LIB_H += util/include/asm/swab.h
260LIB_H += util/include/asm/system.h 262LIB_H += util/include/asm/system.h
261LIB_H += util/include/asm/uaccess.h 263LIB_H += util/include/asm/uaccess.h
@@ -462,10 +464,12 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
462# Benchmark modules 464# Benchmark modules
463BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o 465BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
464BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o 466BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
465ifeq ($(RAW_ARCH),x86_64) 467ifeq ($(ARCH), x86)
468ifeq ($(IS_64_BIT), 1)
466BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o 469BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
467BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o 470BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
468endif 471endif
472endif
469BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 473BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
470BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o 474BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
471BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o 475BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
@@ -743,6 +747,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
743$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 747$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
744 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 748 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
745 749
750$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS
751 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
752
746$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS 753$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS
747 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 754 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
748 755
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index 3bb50eac5542..0c370f81e002 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -103,7 +103,7 @@ static Dwarf_Frame *get_eh_frame(Dwfl_Module *mod, Dwarf_Addr pc)
103 return NULL; 103 return NULL;
104 } 104 }
105 105
106 result = dwarf_cfi_addrframe(cfi, pc, &frame); 106 result = dwarf_cfi_addrframe(cfi, pc-bias, &frame);
107 if (result) { 107 if (result) {
108 pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); 108 pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
109 return NULL; 109 return NULL;
@@ -128,7 +128,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
128 return NULL; 128 return NULL;
129 } 129 }
130 130
131 result = dwarf_cfi_addrframe(cfi, pc, &frame); 131 result = dwarf_cfi_addrframe(cfi, pc-bias, &frame);
132 if (result) { 132 if (result) {
133 pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1)); 133 pr_debug("%s(): %s\n", __func__, dwfl_errmsg(-1));
134 return NULL; 134 return NULL;
@@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
145 * yet used) 145 * yet used)
146 * -1 in case of errors 146 * -1 in case of errors
147 */ 147 */
148static int check_return_addr(struct dso *dso, Dwarf_Addr pc) 148static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc)
149{ 149{
150 int rc = -1; 150 int rc = -1;
151 Dwfl *dwfl; 151 Dwfl *dwfl;
@@ -155,6 +155,7 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
155 Dwarf_Addr start = pc; 155 Dwarf_Addr start = pc;
156 Dwarf_Addr end = pc; 156 Dwarf_Addr end = pc;
157 bool signalp; 157 bool signalp;
158 const char *exec_file = dso->long_name;
158 159
159 dwfl = dso->dwfl; 160 dwfl = dso->dwfl;
160 161
@@ -165,8 +166,10 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
165 return -1; 166 return -1;
166 } 167 }
167 168
168 if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) { 169 mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1,
169 pr_debug("dwfl_report_offline() failed %s\n", 170 map_start, false);
171 if (!mod) {
172 pr_debug("dwfl_report_elf() failed %s\n",
170 dwarf_errmsg(-1)); 173 dwarf_errmsg(-1));
171 /* 174 /*
172 * We normally cache the DWARF debug info and never 175 * We normally cache the DWARF debug info and never
@@ -256,10 +259,10 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
256 return skip_slot; 259 return skip_slot;
257 } 260 }
258 261
259 rc = check_return_addr(dso, ip); 262 rc = check_return_addr(dso, al.map->start, ip);
260 263
261 pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n", 264 pr_debug("[DSO %s, sym %s, ip 0x%" PRIx64 "] rc %d\n",
262 dso->long_name, chain->nr, ip, rc); 265 dso->long_name, al.sym->name, ip, rc);
263 266
264 if (rc == 0) { 267 if (rc == 0) {
265 /* 268 /*
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index 71f2844cf97f..7ed22ff1e1ac 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -68,4 +68,17 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
68 val, opflags); 68 val, opflags);
69} 69}
70 70
71#ifndef HAVE_PTHREAD_ATTR_SETAFFINITY_NP
72#include <pthread.h>
73static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr,
74 size_t cpusetsize,
75 cpu_set_t *cpuset)
76{
77 attr = attr;
78 cpusetsize = cpusetsize;
79 cpuset = cpuset;
80 return 0;
81}
82#endif
83
71#endif /* _FUTEX_H */ 84#endif /* _FUTEX_H */
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 07a8d7646a15..005cc283790c 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -19,12 +19,12 @@
19#include <stdlib.h> 19#include <stdlib.h>
20#include <signal.h> 20#include <signal.h>
21#include <sys/wait.h> 21#include <sys/wait.h>
22#include <linux/unistd.h>
23#include <string.h> 22#include <string.h>
24#include <errno.h> 23#include <errno.h>
25#include <assert.h> 24#include <assert.h>
26#include <sys/time.h> 25#include <sys/time.h>
27#include <sys/types.h> 26#include <sys/types.h>
27#include <sys/syscall.h>
28 28
29#include <pthread.h> 29#include <pthread.h>
30 30
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index e7417fe97a97..747f86103599 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -232,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
232 if (nr_samples > 0) { 232 if (nr_samples > 0) {
233 total_nr_samples += nr_samples; 233 total_nr_samples += nr_samples;
234 hists__collapse_resort(hists, NULL); 234 hists__collapse_resort(hists, NULL);
235 hists__output_resort(hists); 235 hists__output_resort(hists, NULL);
236 236
237 if (symbol_conf.event_group && 237 if (symbol_conf.event_group &&
238 !perf_evsel__is_group_leader(pos)) 238 !perf_evsel__is_group_leader(pos))
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 77d5cae54c6a..50e6b66aea1f 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -236,10 +236,10 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
236 if (errno == ENOENT) 236 if (errno == ENOENT)
237 return false; 237 return false;
238 238
239 pr_warning("Problems with %s file, consider removing it from the cache\n", 239 pr_warning("Problems with %s file, consider removing it from the cache\n",
240 filename); 240 filename);
241 } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) { 241 } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) {
242 pr_warning("Problems with %s file, consider removing it from the cache\n", 242 pr_warning("Problems with %s file, consider removing it from the cache\n",
243 filename); 243 filename);
244 } 244 }
245 245
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 1ce425d101a9..74aada554b12 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -390,6 +390,15 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
390 } 390 }
391} 391}
392 392
393static struct data__file *fmt_to_data_file(struct perf_hpp_fmt *fmt)
394{
395 struct diff_hpp_fmt *dfmt = container_of(fmt, struct diff_hpp_fmt, fmt);
396 void *ptr = dfmt - dfmt->idx;
397 struct data__file *d = container_of(ptr, struct data__file, fmt);
398
399 return d;
400}
401
393static struct hist_entry* 402static struct hist_entry*
394get_pair_data(struct hist_entry *he, struct data__file *d) 403get_pair_data(struct hist_entry *he, struct data__file *d)
395{ 404{
@@ -407,8 +416,7 @@ get_pair_data(struct hist_entry *he, struct data__file *d)
407static struct hist_entry* 416static struct hist_entry*
408get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt) 417get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
409{ 418{
410 void *ptr = dfmt - dfmt->idx; 419 struct data__file *d = fmt_to_data_file(&dfmt->fmt);
411 struct data__file *d = container_of(ptr, struct data__file, fmt);
412 420
413 return get_pair_data(he, d); 421 return get_pair_data(he, d);
414} 422}
@@ -430,7 +438,7 @@ static void hists__baseline_only(struct hists *hists)
430 next = rb_next(&he->rb_node_in); 438 next = rb_next(&he->rb_node_in);
431 if (!hist_entry__next_pair(he)) { 439 if (!hist_entry__next_pair(he)) {
432 rb_erase(&he->rb_node_in, root); 440 rb_erase(&he->rb_node_in, root);
433 hist_entry__free(he); 441 hist_entry__delete(he);
434 } 442 }
435 } 443 }
436} 444}
@@ -448,26 +456,30 @@ static void hists__precompute(struct hists *hists)
448 next = rb_first(root); 456 next = rb_first(root);
449 while (next != NULL) { 457 while (next != NULL) {
450 struct hist_entry *he, *pair; 458 struct hist_entry *he, *pair;
459 struct data__file *d;
460 int i;
451 461
452 he = rb_entry(next, struct hist_entry, rb_node_in); 462 he = rb_entry(next, struct hist_entry, rb_node_in);
453 next = rb_next(&he->rb_node_in); 463 next = rb_next(&he->rb_node_in);
454 464
455 pair = get_pair_data(he, &data__files[sort_compute]); 465 data__for_each_file_new(i, d) {
456 if (!pair) 466 pair = get_pair_data(he, d);
457 continue; 467 if (!pair)
468 continue;
458 469
459 switch (compute) { 470 switch (compute) {
460 case COMPUTE_DELTA: 471 case COMPUTE_DELTA:
461 compute_delta(he, pair); 472 compute_delta(he, pair);
462 break; 473 break;
463 case COMPUTE_RATIO: 474 case COMPUTE_RATIO:
464 compute_ratio(he, pair); 475 compute_ratio(he, pair);
465 break; 476 break;
466 case COMPUTE_WEIGHTED_DIFF: 477 case COMPUTE_WEIGHTED_DIFF:
467 compute_wdiff(he, pair); 478 compute_wdiff(he, pair);
468 break; 479 break;
469 default: 480 default:
470 BUG_ON(1); 481 BUG_ON(1);
482 }
471 } 483 }
472 } 484 }
473} 485}
@@ -517,7 +529,7 @@ __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
517 529
518static int64_t 530static int64_t
519hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, 531hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
520 int c) 532 int c, int sort_idx)
521{ 533{
522 bool pairs_left = hist_entry__has_pairs(left); 534 bool pairs_left = hist_entry__has_pairs(left);
523 bool pairs_right = hist_entry__has_pairs(right); 535 bool pairs_right = hist_entry__has_pairs(right);
@@ -529,8 +541,8 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
529 if (!pairs_left || !pairs_right) 541 if (!pairs_left || !pairs_right)
530 return pairs_left ? -1 : 1; 542 return pairs_left ? -1 : 1;
531 543
532 p_left = get_pair_data(left, &data__files[sort_compute]); 544 p_left = get_pair_data(left, &data__files[sort_idx]);
533 p_right = get_pair_data(right, &data__files[sort_compute]); 545 p_right = get_pair_data(right, &data__files[sort_idx]);
534 546
535 if (!p_left && !p_right) 547 if (!p_left && !p_right)
536 return 0; 548 return 0;
@@ -545,55 +557,103 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
545 return __hist_entry__cmp_compute(p_left, p_right, c); 557 return __hist_entry__cmp_compute(p_left, p_right, c);
546} 558}
547 559
548static void insert_hist_entry_by_compute(struct rb_root *root, 560static int64_t
549 struct hist_entry *he, 561hist_entry__cmp_compute_idx(struct hist_entry *left, struct hist_entry *right,
550 int c) 562 int c, int sort_idx)
551{ 563{
552 struct rb_node **p = &root->rb_node; 564 struct hist_entry *p_right, *p_left;
553 struct rb_node *parent = NULL; 565
554 struct hist_entry *iter; 566 p_left = get_pair_data(left, &data__files[sort_idx]);
555 567 p_right = get_pair_data(right, &data__files[sort_idx]);
556 while (*p != NULL) { 568
557 parent = *p; 569 if (!p_left && !p_right)
558 iter = rb_entry(parent, struct hist_entry, rb_node); 570 return 0;
559 if (hist_entry__cmp_compute(he, iter, c) < 0) 571
560 p = &(*p)->rb_left; 572 if (!p_left || !p_right)
561 else 573 return p_left ? -1 : 1;
562 p = &(*p)->rb_right; 574
575 if (c != COMPUTE_DELTA) {
576 /*
577 * The delta can be computed without the baseline, but
578 * others are not. Put those entries which have no
579 * values below.
580 */
581 if (left->dummy && right->dummy)
582 return 0;
583
584 if (left->dummy || right->dummy)
585 return left->dummy ? 1 : -1;
563 } 586 }
564 587
565 rb_link_node(&he->rb_node, parent, p); 588 return __hist_entry__cmp_compute(p_left, p_right, c);
566 rb_insert_color(&he->rb_node, root);
567} 589}
568 590
569static void hists__compute_resort(struct hists *hists) 591static int64_t
592hist_entry__cmp_nop(struct perf_hpp_fmt *fmt __maybe_unused,
593 struct hist_entry *left __maybe_unused,
594 struct hist_entry *right __maybe_unused)
570{ 595{
571 struct rb_root *root; 596 return 0;
572 struct rb_node *next; 597}
573 598
574 if (sort__need_collapse) 599static int64_t
575 root = &hists->entries_collapsed; 600hist_entry__cmp_baseline(struct perf_hpp_fmt *fmt __maybe_unused,
576 else 601 struct hist_entry *left, struct hist_entry *right)
577 root = hists->entries_in; 602{
603 if (left->stat.period == right->stat.period)
604 return 0;
605 return left->stat.period > right->stat.period ? 1 : -1;
606}
578 607
579 hists->entries = RB_ROOT; 608static int64_t
580 next = rb_first(root); 609hist_entry__cmp_delta(struct perf_hpp_fmt *fmt,
610 struct hist_entry *left, struct hist_entry *right)
611{
612 struct data__file *d = fmt_to_data_file(fmt);
581 613
582 hists__reset_stats(hists); 614 return hist_entry__cmp_compute(right, left, COMPUTE_DELTA, d->idx);
583 hists__reset_col_len(hists); 615}
584 616
585 while (next != NULL) { 617static int64_t
586 struct hist_entry *he; 618hist_entry__cmp_ratio(struct perf_hpp_fmt *fmt,
619 struct hist_entry *left, struct hist_entry *right)
620{
621 struct data__file *d = fmt_to_data_file(fmt);
587 622
588 he = rb_entry(next, struct hist_entry, rb_node_in); 623 return hist_entry__cmp_compute(right, left, COMPUTE_RATIO, d->idx);
589 next = rb_next(&he->rb_node_in); 624}
625
626static int64_t
627hist_entry__cmp_wdiff(struct perf_hpp_fmt *fmt,
628 struct hist_entry *left, struct hist_entry *right)
629{
630 struct data__file *d = fmt_to_data_file(fmt);
590 631
591 insert_hist_entry_by_compute(&hists->entries, he, compute); 632 return hist_entry__cmp_compute(right, left, COMPUTE_WEIGHTED_DIFF, d->idx);
592 hists__inc_stats(hists, he); 633}
593 634
594 if (!he->filtered) 635static int64_t
595 hists__calc_col_len(hists, he); 636hist_entry__cmp_delta_idx(struct perf_hpp_fmt *fmt __maybe_unused,
596 } 637 struct hist_entry *left, struct hist_entry *right)
638{
639 return hist_entry__cmp_compute_idx(right, left, COMPUTE_DELTA,
640 sort_compute);
641}
642
643static int64_t
644hist_entry__cmp_ratio_idx(struct perf_hpp_fmt *fmt __maybe_unused,
645 struct hist_entry *left, struct hist_entry *right)
646{
647 return hist_entry__cmp_compute_idx(right, left, COMPUTE_RATIO,
648 sort_compute);
649}
650
651static int64_t
652hist_entry__cmp_wdiff_idx(struct perf_hpp_fmt *fmt __maybe_unused,
653 struct hist_entry *left, struct hist_entry *right)
654{
655 return hist_entry__cmp_compute_idx(right, left, COMPUTE_WEIGHTED_DIFF,
656 sort_compute);
597} 657}
598 658
599static void hists__process(struct hists *hists) 659static void hists__process(struct hists *hists)
@@ -601,12 +661,8 @@ static void hists__process(struct hists *hists)
601 if (show_baseline_only) 661 if (show_baseline_only)
602 hists__baseline_only(hists); 662 hists__baseline_only(hists);
603 663
604 if (sort_compute) { 664 hists__precompute(hists);
605 hists__precompute(hists); 665 hists__output_resort(hists, NULL);
606 hists__compute_resort(hists);
607 } else {
608 hists__output_resort(hists);
609 }
610 666
611 hists__fprintf(hists, true, 0, 0, 0, stdout); 667 hists__fprintf(hists, true, 0, 0, 0, stdout);
612} 668}
@@ -805,7 +861,7 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
805 char pfmt[20] = " "; 861 char pfmt[20] = " ";
806 862
807 if (!pair) 863 if (!pair)
808 goto dummy_print; 864 goto no_print;
809 865
810 switch (comparison_method) { 866 switch (comparison_method) {
811 case COMPUTE_DELTA: 867 case COMPUTE_DELTA:
@@ -814,8 +870,6 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
814 else 870 else
815 diff = compute_delta(he, pair); 871 diff = compute_delta(he, pair);
816 872
817 if (fabs(diff) < 0.01)
818 goto dummy_print;
819 scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1); 873 scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1);
820 return percent_color_snprintf(hpp->buf, hpp->size, 874 return percent_color_snprintf(hpp->buf, hpp->size,
821 pfmt, diff); 875 pfmt, diff);
@@ -847,6 +901,9 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
847 } 901 }
848dummy_print: 902dummy_print:
849 return scnprintf(hpp->buf, hpp->size, "%*s", 903 return scnprintf(hpp->buf, hpp->size, "%*s",
904 dfmt->header_width, "N/A");
905no_print:
906 return scnprintf(hpp->buf, hpp->size, "%*s",
850 dfmt->header_width, pfmt); 907 dfmt->header_width, pfmt);
851} 908}
852 909
@@ -896,14 +953,15 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
896 else 953 else
897 diff = compute_delta(he, pair); 954 diff = compute_delta(he, pair);
898 955
899 if (fabs(diff) >= 0.01) 956 scnprintf(buf, size, "%+4.2F%%", diff);
900 scnprintf(buf, size, "%+4.2F%%", diff);
901 break; 957 break;
902 958
903 case PERF_HPP_DIFF__RATIO: 959 case PERF_HPP_DIFF__RATIO:
904 /* No point for ratio number if we are dummy.. */ 960 /* No point for ratio number if we are dummy.. */
905 if (he->dummy) 961 if (he->dummy) {
962 scnprintf(buf, size, "N/A");
906 break; 963 break;
964 }
907 965
908 if (pair->diff.computed) 966 if (pair->diff.computed)
909 ratio = pair->diff.period_ratio; 967 ratio = pair->diff.period_ratio;
@@ -916,8 +974,10 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
916 974
917 case PERF_HPP_DIFF__WEIGHTED_DIFF: 975 case PERF_HPP_DIFF__WEIGHTED_DIFF:
918 /* No point for wdiff number if we are dummy.. */ 976 /* No point for wdiff number if we are dummy.. */
919 if (he->dummy) 977 if (he->dummy) {
978 scnprintf(buf, size, "N/A");
920 break; 979 break;
980 }
921 981
922 if (pair->diff.computed) 982 if (pair->diff.computed)
923 wdiff = pair->diff.wdiff; 983 wdiff = pair->diff.wdiff;
@@ -1038,32 +1098,41 @@ static void data__hpp_register(struct data__file *d, int idx)
1038 fmt->header = hpp__header; 1098 fmt->header = hpp__header;
1039 fmt->width = hpp__width; 1099 fmt->width = hpp__width;
1040 fmt->entry = hpp__entry_global; 1100 fmt->entry = hpp__entry_global;
1101 fmt->cmp = hist_entry__cmp_nop;
1102 fmt->collapse = hist_entry__cmp_nop;
1041 1103
1042 /* TODO more colors */ 1104 /* TODO more colors */
1043 switch (idx) { 1105 switch (idx) {
1044 case PERF_HPP_DIFF__BASELINE: 1106 case PERF_HPP_DIFF__BASELINE:
1045 fmt->color = hpp__color_baseline; 1107 fmt->color = hpp__color_baseline;
1108 fmt->sort = hist_entry__cmp_baseline;
1046 break; 1109 break;
1047 case PERF_HPP_DIFF__DELTA: 1110 case PERF_HPP_DIFF__DELTA:
1048 fmt->color = hpp__color_delta; 1111 fmt->color = hpp__color_delta;
1112 fmt->sort = hist_entry__cmp_delta;
1049 break; 1113 break;
1050 case PERF_HPP_DIFF__RATIO: 1114 case PERF_HPP_DIFF__RATIO:
1051 fmt->color = hpp__color_ratio; 1115 fmt->color = hpp__color_ratio;
1116 fmt->sort = hist_entry__cmp_ratio;
1052 break; 1117 break;
1053 case PERF_HPP_DIFF__WEIGHTED_DIFF: 1118 case PERF_HPP_DIFF__WEIGHTED_DIFF:
1054 fmt->color = hpp__color_wdiff; 1119 fmt->color = hpp__color_wdiff;
1120 fmt->sort = hist_entry__cmp_wdiff;
1055 break; 1121 break;
1056 default: 1122 default:
1123 fmt->sort = hist_entry__cmp_nop;
1057 break; 1124 break;
1058 } 1125 }
1059 1126
1060 init_header(d, dfmt); 1127 init_header(d, dfmt);
1061 perf_hpp__column_register(fmt); 1128 perf_hpp__column_register(fmt);
1129 perf_hpp__register_sort_field(fmt);
1062} 1130}
1063 1131
1064static void ui_init(void) 1132static int ui_init(void)
1065{ 1133{
1066 struct data__file *d; 1134 struct data__file *d;
1135 struct perf_hpp_fmt *fmt;
1067 int i; 1136 int i;
1068 1137
1069 data__for_each_file(i, d) { 1138 data__for_each_file(i, d) {
@@ -1093,6 +1162,46 @@ static void ui_init(void)
1093 data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD : 1162 data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD :
1094 PERF_HPP_DIFF__PERIOD_BASELINE); 1163 PERF_HPP_DIFF__PERIOD_BASELINE);
1095 } 1164 }
1165
1166 if (!sort_compute)
1167 return 0;
1168
1169 /*
1170 * Prepend an fmt to sort on columns at 'sort_compute' first.
1171 * This fmt is added only to the sort list but not to the
1172 * output fields list.
1173 *
1174 * Note that this column (data) can be compared twice - one
1175 * for this 'sort_compute' fmt and another for the normal
1176 * diff_hpp_fmt. But it shouldn't a problem as most entries
1177 * will be sorted out by first try or baseline and comparing
1178 * is not a costly operation.
1179 */
1180 fmt = zalloc(sizeof(*fmt));
1181 if (fmt == NULL) {
1182 pr_err("Memory allocation failed\n");
1183 return -1;
1184 }
1185
1186 fmt->cmp = hist_entry__cmp_nop;
1187 fmt->collapse = hist_entry__cmp_nop;
1188
1189 switch (compute) {
1190 case COMPUTE_DELTA:
1191 fmt->sort = hist_entry__cmp_delta_idx;
1192 break;
1193 case COMPUTE_RATIO:
1194 fmt->sort = hist_entry__cmp_ratio_idx;
1195 break;
1196 case COMPUTE_WEIGHTED_DIFF:
1197 fmt->sort = hist_entry__cmp_wdiff_idx;
1198 break;
1199 default:
1200 BUG_ON(1);
1201 }
1202
1203 list_add(&fmt->sort_list, &perf_hpp__sort_list);
1204 return 0;
1096} 1205}
1097 1206
1098static int data_init(int argc, const char **argv) 1207static int data_init(int argc, const char **argv)
@@ -1158,7 +1267,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1158 if (data_init(argc, argv) < 0) 1267 if (data_init(argc, argv) < 0)
1159 return -1; 1268 return -1;
1160 1269
1161 ui_init(); 1270 if (ui_init() < 0)
1271 return -1;
1162 1272
1163 sort__mode = SORT_MODE__DIFF; 1273 sort__mode = SORT_MODE__DIFF;
1164 1274
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 84df2deed988..a13641e066f5 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -343,6 +343,7 @@ static int __cmd_inject(struct perf_inject *inject)
343 int ret = -EINVAL; 343 int ret = -EINVAL;
344 struct perf_session *session = inject->session; 344 struct perf_session *session = inject->session;
345 struct perf_data_file *file_out = &inject->output; 345 struct perf_data_file *file_out = &inject->output;
346 int fd = perf_data_file__fd(file_out);
346 347
347 signal(SIGINT, sig_handler); 348 signal(SIGINT, sig_handler);
348 349
@@ -376,7 +377,7 @@ static int __cmd_inject(struct perf_inject *inject)
376 } 377 }
377 378
378 if (!file_out->is_pipe) 379 if (!file_out->is_pipe)
379 lseek(file_out->fd, session->header.data_offset, SEEK_SET); 380 lseek(fd, session->header.data_offset, SEEK_SET);
380 381
381 ret = perf_session__process_events(session, &inject->tool); 382 ret = perf_session__process_events(session, &inject->tool);
382 383
@@ -385,7 +386,7 @@ static int __cmd_inject(struct perf_inject *inject)
385 perf_header__set_feat(&session->header, 386 perf_header__set_feat(&session->header,
386 HEADER_BUILD_ID); 387 HEADER_BUILD_ID);
387 session->header.data_size = inject->bytes_written; 388 session->header.data_size = inject->bytes_written;
388 perf_session__write_header(session, session->evlist, file_out->fd, true); 389 perf_session__write_header(session, session->evlist, fd, true);
389 } 390 }
390 391
391 return ret; 392 return ret;
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 011195e38f21..198f3c3aff95 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -19,7 +19,9 @@
19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
20{ 20{
21 int i; 21 int i;
22 const struct option list_options[] = { 22 bool raw_dump = false;
23 struct option list_options[] = {
24 OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"),
23 OPT_END() 25 OPT_END()
24 }; 26 };
25 const char * const list_usage[] = { 27 const char * const list_usage[] = {
@@ -27,11 +29,18 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
27 NULL 29 NULL
28 }; 30 };
29 31
32 set_option_flag(list_options, 0, "raw-dump", PARSE_OPT_HIDDEN);
33
30 argc = parse_options(argc, argv, list_options, list_usage, 34 argc = parse_options(argc, argv, list_options, list_usage,
31 PARSE_OPT_STOP_AT_NON_OPTION); 35 PARSE_OPT_STOP_AT_NON_OPTION);
32 36
33 setup_pager(); 37 setup_pager();
34 38
39 if (raw_dump) {
40 print_events(NULL, true);
41 return 0;
42 }
43
35 if (argc == 0) { 44 if (argc == 0) {
36 print_events(NULL, false); 45 print_events(NULL, false);
37 return 0; 46 return 0;
@@ -53,8 +62,6 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
53 print_hwcache_events(NULL, false); 62 print_hwcache_events(NULL, false);
54 else if (strcmp(argv[i], "pmu") == 0) 63 else if (strcmp(argv[i], "pmu") == 0)
55 print_pmu_events(NULL, false); 64 print_pmu_events(NULL, false);
56 else if (strcmp(argv[i], "--raw-dump") == 0)
57 print_events(NULL, true);
58 else { 65 else {
59 char *sep = strchr(argv[i], ':'), *s; 66 char *sep = strchr(argv[i], ':'), *s;
60 int sep_idx; 67 int sep_idx;
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 24db6ffe2957..9b5663950a4d 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -7,44 +7,47 @@
7#include "util/session.h" 7#include "util/session.h"
8#include "util/data.h" 8#include "util/data.h"
9 9
10#define MEM_OPERATION_LOAD "load" 10#define MEM_OPERATION_LOAD 0x1
11#define MEM_OPERATION_STORE "store" 11#define MEM_OPERATION_STORE 0x2
12
13static const char *mem_operation = MEM_OPERATION_LOAD;
14 12
15struct perf_mem { 13struct perf_mem {
16 struct perf_tool tool; 14 struct perf_tool tool;
17 char const *input_name; 15 char const *input_name;
18 bool hide_unresolved; 16 bool hide_unresolved;
19 bool dump_raw; 17 bool dump_raw;
18 int operation;
20 const char *cpu_list; 19 const char *cpu_list;
21 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 20 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
22}; 21};
23 22
24static int __cmd_record(int argc, const char **argv) 23static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
25{ 24{
26 int rec_argc, i = 0, j; 25 int rec_argc, i = 0, j;
27 const char **rec_argv; 26 const char **rec_argv;
28 char event[64];
29 int ret; 27 int ret;
30 28
31 rec_argc = argc + 4; 29 rec_argc = argc + 7; /* max number of arguments */
32 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 30 rec_argv = calloc(rec_argc + 1, sizeof(char *));
33 if (!rec_argv) 31 if (!rec_argv)
34 return -1; 32 return -1;
35 33
36 rec_argv[i++] = strdup("record"); 34 rec_argv[i++] = "record";
37 if (!strcmp(mem_operation, MEM_OPERATION_LOAD))
38 rec_argv[i++] = strdup("-W");
39 rec_argv[i++] = strdup("-d");
40 rec_argv[i++] = strdup("-e");
41 35
42 if (strcmp(mem_operation, MEM_OPERATION_LOAD)) 36 if (mem->operation & MEM_OPERATION_LOAD)
43 sprintf(event, "cpu/mem-stores/pp"); 37 rec_argv[i++] = "-W";
44 else 38
45 sprintf(event, "cpu/mem-loads/pp"); 39 rec_argv[i++] = "-d";
40
41 if (mem->operation & MEM_OPERATION_LOAD) {
42 rec_argv[i++] = "-e";
43 rec_argv[i++] = "cpu/mem-loads/pp";
44 }
45
46 if (mem->operation & MEM_OPERATION_STORE) {
47 rec_argv[i++] = "-e";
48 rec_argv[i++] = "cpu/mem-stores/pp";
49 }
46 50
47 rec_argv[i++] = strdup(event);
48 for (j = 1; j < argc; j++, i++) 51 for (j = 1; j < argc; j++, i++)
49 rec_argv[i] = argv[j]; 52 rec_argv[i] = argv[j];
50 53
@@ -162,17 +165,17 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
162 if (!rep_argv) 165 if (!rep_argv)
163 return -1; 166 return -1;
164 167
165 rep_argv[i++] = strdup("report"); 168 rep_argv[i++] = "report";
166 rep_argv[i++] = strdup("--mem-mode"); 169 rep_argv[i++] = "--mem-mode";
167 rep_argv[i++] = strdup("-n"); /* display number of samples */ 170 rep_argv[i++] = "-n"; /* display number of samples */
168 171
169 /* 172 /*
170 * there is no weight (cost) associated with stores, so don't print 173 * there is no weight (cost) associated with stores, so don't print
171 * the column 174 * the column
172 */ 175 */
173 if (strcmp(mem_operation, MEM_OPERATION_LOAD)) 176 if (!(mem->operation & MEM_OPERATION_LOAD))
174 rep_argv[i++] = strdup("--sort=mem,sym,dso,symbol_daddr," 177 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
175 "dso_daddr,tlb,locked"); 178 "dso_daddr,tlb,locked";
176 179
177 for (j = 1; j < argc; j++, i++) 180 for (j = 1; j < argc; j++, i++)
178 rep_argv[i] = argv[j]; 181 rep_argv[i] = argv[j];
@@ -182,6 +185,75 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
182 return ret; 185 return ret;
183} 186}
184 187
188struct mem_mode {
189 const char *name;
190 int mode;
191};
192
193#define MEM_OPT(n, m) \
194 { .name = n, .mode = (m) }
195
196#define MEM_END { .name = NULL }
197
198static const struct mem_mode mem_modes[]={
199 MEM_OPT("load", MEM_OPERATION_LOAD),
200 MEM_OPT("store", MEM_OPERATION_STORE),
201 MEM_END
202};
203
204static int
205parse_mem_ops(const struct option *opt, const char *str, int unset)
206{
207 int *mode = (int *)opt->value;
208 const struct mem_mode *m;
209 char *s, *os = NULL, *p;
210 int ret = -1;
211
212 if (unset)
213 return 0;
214
215 /* str may be NULL in case no arg is passed to -t */
216 if (str) {
217 /* because str is read-only */
218 s = os = strdup(str);
219 if (!s)
220 return -1;
221
222 /* reset mode */
223 *mode = 0;
224
225 for (;;) {
226 p = strchr(s, ',');
227 if (p)
228 *p = '\0';
229
230 for (m = mem_modes; m->name; m++) {
231 if (!strcasecmp(s, m->name))
232 break;
233 }
234 if (!m->name) {
235 fprintf(stderr, "unknown sampling op %s,"
236 " check man page\n", s);
237 goto error;
238 }
239
240 *mode |= m->mode;
241
242 if (!p)
243 break;
244
245 s = p + 1;
246 }
247 }
248 ret = 0;
249
250 if (*mode == 0)
251 *mode = MEM_OPERATION_LOAD;
252error:
253 free(os);
254 return ret;
255}
256
185int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) 257int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
186{ 258{
187 struct stat st; 259 struct stat st;
@@ -197,10 +269,15 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
197 .ordered_events = true, 269 .ordered_events = true,
198 }, 270 },
199 .input_name = "perf.data", 271 .input_name = "perf.data",
272 /*
273 * default to both load an store sampling
274 */
275 .operation = MEM_OPERATION_LOAD | MEM_OPERATION_STORE,
200 }; 276 };
201 const struct option mem_options[] = { 277 const struct option mem_options[] = {
202 OPT_STRING('t', "type", &mem_operation, 278 OPT_CALLBACK('t', "type", &mem.operation,
203 "type", "memory operations(load/store)"), 279 "type", "memory operations(load,store) Default load,store",
280 parse_mem_ops),
204 OPT_BOOLEAN('D', "dump-raw-samples", &mem.dump_raw, 281 OPT_BOOLEAN('D', "dump-raw-samples", &mem.dump_raw,
205 "dump raw samples in ASCII"), 282 "dump raw samples in ASCII"),
206 OPT_BOOLEAN('U', "hide-unresolved", &mem.hide_unresolved, 283 OPT_BOOLEAN('U', "hide-unresolved", &mem.hide_unresolved,
@@ -225,7 +302,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
225 argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, 302 argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
226 mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); 303 mem_usage, PARSE_OPT_STOP_AT_NON_OPTION);
227 304
228 if (!argc || !(strncmp(argv[0], "rec", 3) || mem_operation)) 305 if (!argc || !(strncmp(argv[0], "rec", 3) || mem.operation))
229 usage_with_options(mem_usage, mem_options); 306 usage_with_options(mem_usage, mem_options);
230 307
231 if (!mem.input_name || !strlen(mem.input_name)) { 308 if (!mem.input_name || !strlen(mem.input_name)) {
@@ -236,7 +313,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
236 } 313 }
237 314
238 if (!strncmp(argv[0], "rec", 3)) 315 if (!strncmp(argv[0], "rec", 3))
239 return __cmd_record(argc, argv); 316 return __cmd_record(argc, argv, &mem);
240 else if (!strncmp(argv[0], "rep", 3)) 317 else if (!strncmp(argv[0], "rep", 3))
241 return report_events(argc, argv, &mem); 318 return report_events(argc, argv, &mem);
242 else 319 else
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8648c6d3003d..404ab3434052 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -190,16 +190,30 @@ out:
190 return rc; 190 return rc;
191} 191}
192 192
193static int process_sample_event(struct perf_tool *tool,
194 union perf_event *event,
195 struct perf_sample *sample,
196 struct perf_evsel *evsel,
197 struct machine *machine)
198{
199 struct record *rec = container_of(tool, struct record, tool);
200
201 rec->samples++;
202
203 return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
204}
205
193static int process_buildids(struct record *rec) 206static int process_buildids(struct record *rec)
194{ 207{
195 struct perf_data_file *file = &rec->file; 208 struct perf_data_file *file = &rec->file;
196 struct perf_session *session = rec->session; 209 struct perf_session *session = rec->session;
197 u64 start = session->header.data_offset;
198 210
199 u64 size = lseek(file->fd, 0, SEEK_CUR); 211 u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
200 if (size == 0) 212 if (size == 0)
201 return 0; 213 return 0;
202 214
215 file->size = size;
216
203 /* 217 /*
204 * During this process, it'll load kernel map and replace the 218 * During this process, it'll load kernel map and replace the
205 * dso->long_name to a real pathname it found. In this case 219 * dso->long_name to a real pathname it found. In this case
@@ -211,9 +225,7 @@ static int process_buildids(struct record *rec)
211 */ 225 */
212 symbol_conf.ignore_vmlinux_buildid = true; 226 symbol_conf.ignore_vmlinux_buildid = true;
213 227
214 return __perf_session__process_events(session, start, 228 return perf_session__process_events(session, &rec->tool);
215 size - start,
216 size, &build_id__mark_dso_hit_ops);
217} 229}
218 230
219static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 231static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
@@ -322,6 +334,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
322 struct perf_data_file *file = &rec->file; 334 struct perf_data_file *file = &rec->file;
323 struct perf_session *session; 335 struct perf_session *session;
324 bool disabled = false, draining = false; 336 bool disabled = false, draining = false;
337 int fd;
325 338
326 rec->progname = argv[0]; 339 rec->progname = argv[0];
327 340
@@ -336,6 +349,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
336 return -1; 349 return -1;
337 } 350 }
338 351
352 fd = perf_data_file__fd(file);
339 rec->session = session; 353 rec->session = session;
340 354
341 record__init_features(rec); 355 record__init_features(rec);
@@ -360,12 +374,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
360 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 374 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
361 375
362 if (file->is_pipe) { 376 if (file->is_pipe) {
363 err = perf_header__write_pipe(file->fd); 377 err = perf_header__write_pipe(fd);
364 if (err < 0) 378 if (err < 0)
365 goto out_child; 379 goto out_child;
366 } else { 380 } else {
367 err = perf_session__write_header(session, rec->evlist, 381 err = perf_session__write_header(session, rec->evlist, fd, false);
368 file->fd, false);
369 if (err < 0) 382 if (err < 0)
370 goto out_child; 383 goto out_child;
371 } 384 }
@@ -397,7 +410,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
397 * return this more properly and also 410 * return this more properly and also
398 * propagate errors that now are calling die() 411 * propagate errors that now are calling die()
399 */ 412 */
400 err = perf_event__synthesize_tracing_data(tool, file->fd, rec->evlist, 413 err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist,
401 process_synthesized_event); 414 process_synthesized_event);
402 if (err <= 0) { 415 if (err <= 0) {
403 pr_err("Couldn't record tracing data.\n"); 416 pr_err("Couldn't record tracing data.\n");
@@ -504,19 +517,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
504 goto out_child; 517 goto out_child;
505 } 518 }
506 519
507 if (!quiet) { 520 if (!quiet)
508 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 521 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
509 522
510 /*
511 * Approximate RIP event size: 24 bytes.
512 */
513 fprintf(stderr,
514 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
515 (double)rec->bytes_written / 1024.0 / 1024.0,
516 file->path,
517 rec->bytes_written / 24);
518 }
519
520out_child: 523out_child:
521 if (forks) { 524 if (forks) {
522 int exit_status; 525 int exit_status;
@@ -535,13 +538,29 @@ out_child:
535 } else 538 } else
536 status = err; 539 status = err;
537 540
541 /* this will be recalculated during process_buildids() */
542 rec->samples = 0;
543
538 if (!err && !file->is_pipe) { 544 if (!err && !file->is_pipe) {
539 rec->session->header.data_size += rec->bytes_written; 545 rec->session->header.data_size += rec->bytes_written;
540 546
541 if (!rec->no_buildid) 547 if (!rec->no_buildid)
542 process_buildids(rec); 548 process_buildids(rec);
543 perf_session__write_header(rec->session, rec->evlist, 549 perf_session__write_header(rec->session, rec->evlist, fd, true);
544 file->fd, true); 550 }
551
552 if (!err && !quiet) {
553 char samples[128];
554
555 if (rec->samples)
556 scnprintf(samples, sizeof(samples),
557 " (%" PRIu64 " samples)", rec->samples);
558 else
559 samples[0] = '\0';
560
561 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n",
562 perf_data_file__size(file) / 1024.0 / 1024.0,
563 file->path, samples);
545 } 564 }
546 565
547out_delete_session: 566out_delete_session:
@@ -720,6 +739,13 @@ static struct record record = {
720 .default_per_cpu = true, 739 .default_per_cpu = true,
721 }, 740 },
722 }, 741 },
742 .tool = {
743 .sample = process_sample_event,
744 .fork = perf_event__process_fork,
745 .comm = perf_event__process_comm,
746 .mmap = perf_event__process_mmap,
747 .mmap2 = perf_event__process_mmap2,
748 },
723}; 749};
724 750
725#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 751#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 39367609c707..2f91094e228b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -86,17 +86,6 @@ static int report__config(const char *var, const char *value, void *cb)
86 return perf_default_config(var, value, cb); 86 return perf_default_config(var, value, cb);
87} 87}
88 88
89static void report__inc_stats(struct report *rep, struct hist_entry *he)
90{
91 /*
92 * The @he is either of a newly created one or an existing one
93 * merging current sample. We only want to count a new one so
94 * checking ->nr_events being 1.
95 */
96 if (he->stat.nr_events == 1)
97 rep->nr_entries++;
98}
99
100static int hist_iter__report_callback(struct hist_entry_iter *iter, 89static int hist_iter__report_callback(struct hist_entry_iter *iter,
101 struct addr_location *al, bool single, 90 struct addr_location *al, bool single,
102 void *arg) 91 void *arg)
@@ -108,8 +97,6 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
108 struct mem_info *mi; 97 struct mem_info *mi;
109 struct branch_info *bi; 98 struct branch_info *bi;
110 99
111 report__inc_stats(rep, he);
112
113 if (!ui__has_annotation()) 100 if (!ui__has_annotation())
114 return 0; 101 return 0;
115 102
@@ -457,6 +444,19 @@ static void report__collapse_hists(struct report *rep)
457 ui_progress__finish(); 444 ui_progress__finish();
458} 445}
459 446
447static void report__output_resort(struct report *rep)
448{
449 struct ui_progress prog;
450 struct perf_evsel *pos;
451
452 ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
453
454 evlist__for_each(rep->session->evlist, pos)
455 hists__output_resort(evsel__hists(pos), &prog);
456
457 ui_progress__finish();
458}
459
460static int __cmd_report(struct report *rep) 460static int __cmd_report(struct report *rep)
461{ 461{
462 int ret; 462 int ret;
@@ -486,6 +486,9 @@ static int __cmd_report(struct report *rep)
486 486
487 report__warn_kptr_restrict(rep); 487 report__warn_kptr_restrict(rep);
488 488
489 evlist__for_each(session->evlist, pos)
490 rep->nr_entries += evsel__hists(pos)->nr_entries;
491
489 if (use_browser == 0) { 492 if (use_browser == 0) {
490 if (verbose > 3) 493 if (verbose > 3)
491 perf_session__fprintf(session, stdout); 494 perf_session__fprintf(session, stdout);
@@ -505,13 +508,20 @@ static int __cmd_report(struct report *rep)
505 if (session_done()) 508 if (session_done())
506 return 0; 509 return 0;
507 510
511 /*
512 * recalculate number of entries after collapsing since it
513 * might be changed during the collapse phase.
514 */
515 rep->nr_entries = 0;
516 evlist__for_each(session->evlist, pos)
517 rep->nr_entries += evsel__hists(pos)->nr_entries;
518
508 if (rep->nr_entries == 0) { 519 if (rep->nr_entries == 0) {
509 ui__error("The %s file has no samples!\n", file->path); 520 ui__error("The %s file has no samples!\n", file->path);
510 return 0; 521 return 0;
511 } 522 }
512 523
513 evlist__for_each(session->evlist, pos) 524 report__output_resort(rep);
514 hists__output_resort(evsel__hists(pos));
515 525
516 return report__browse_hists(rep); 526 return report__browse_hists(rep);
517} 527}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 891086376381..e598e4e98170 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1730,7 +1730,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1730 "detailed run - start a lot of events"), 1730 "detailed run - start a lot of events"),
1731 OPT_BOOLEAN('S', "sync", &sync_run, 1731 OPT_BOOLEAN('S', "sync", &sync_run,
1732 "call sync() before starting a run"), 1732 "call sync() before starting a run"),
1733 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 1733 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1734 "print large numbers with thousands\' separators", 1734 "print large numbers with thousands\' separators",
1735 stat__set_big_num), 1735 stat__set_big_num),
1736 OPT_STRING('C', "cpu", &target.cpu_list, "cpu", 1736 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 0aa7747ff139..c4c7eac69de4 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -66,7 +66,6 @@
66#include <sys/utsname.h> 66#include <sys/utsname.h>
67#include <sys/mman.h> 67#include <sys/mman.h>
68 68
69#include <linux/unistd.h>
70#include <linux/types.h> 69#include <linux/types.h>
71 70
72static volatile int done; 71static volatile int done;
@@ -166,7 +165,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
166 err ? "[unknown]" : uts.release, perf_version_string); 165 err ? "[unknown]" : uts.release, perf_version_string);
167 if (use_browser <= 0) 166 if (use_browser <= 0)
168 sleep(5); 167 sleep(5);
169 168
170 map->erange_warned = true; 169 map->erange_warned = true;
171} 170}
172 171
@@ -285,7 +284,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
285 } 284 }
286 285
287 hists__collapse_resort(hists, NULL); 286 hists__collapse_resort(hists, NULL);
288 hists__output_resort(hists); 287 hists__output_resort(hists, NULL);
289 288
290 hists__output_recalc_col_len(hists, top->print_entries - printed); 289 hists__output_recalc_col_len(hists, top->print_entries - printed);
291 putchar('\n'); 290 putchar('\n');
@@ -554,7 +553,7 @@ static void perf_top__sort_new_samples(void *arg)
554 } 553 }
555 554
556 hists__collapse_resort(hists, NULL); 555 hists__collapse_resort(hists, NULL);
557 hists__output_resort(hists); 556 hists__output_resort(hists, NULL);
558} 557}
559 558
560static void *display_thread_tui(void *arg) 559static void *display_thread_tui(void *arg)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index badfabc6a01f..7e935f1083ec 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -929,66 +929,66 @@ static struct syscall_fmt {
929 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 929 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
930 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, 930 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
931 { .name = "close", .errmsg = true, 931 { .name = "close", .errmsg = true,
932 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 932 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
933 { .name = "connect", .errmsg = true, }, 933 { .name = "connect", .errmsg = true, },
934 { .name = "dup", .errmsg = true, 934 { .name = "dup", .errmsg = true,
935 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 935 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
936 { .name = "dup2", .errmsg = true, 936 { .name = "dup2", .errmsg = true,
937 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 937 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
938 { .name = "dup3", .errmsg = true, 938 { .name = "dup3", .errmsg = true,
939 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 939 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
940 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, 940 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
941 { .name = "eventfd2", .errmsg = true, 941 { .name = "eventfd2", .errmsg = true,
942 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, 942 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
943 { .name = "faccessat", .errmsg = true, 943 { .name = "faccessat", .errmsg = true,
944 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 944 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
945 { .name = "fadvise64", .errmsg = true, 945 { .name = "fadvise64", .errmsg = true,
946 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 946 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
947 { .name = "fallocate", .errmsg = true, 947 { .name = "fallocate", .errmsg = true,
948 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 948 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
949 { .name = "fchdir", .errmsg = true, 949 { .name = "fchdir", .errmsg = true,
950 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 950 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
951 { .name = "fchmod", .errmsg = true, 951 { .name = "fchmod", .errmsg = true,
952 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 952 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
953 { .name = "fchmodat", .errmsg = true, 953 { .name = "fchmodat", .errmsg = true,
954 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 954 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
955 { .name = "fchown", .errmsg = true, 955 { .name = "fchown", .errmsg = true,
956 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 956 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
957 { .name = "fchownat", .errmsg = true, 957 { .name = "fchownat", .errmsg = true,
958 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 958 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
959 { .name = "fcntl", .errmsg = true, 959 { .name = "fcntl", .errmsg = true,
960 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 960 .arg_scnprintf = { [0] = SCA_FD, /* fd */
961 [1] = SCA_STRARRAY, /* cmd */ }, 961 [1] = SCA_STRARRAY, /* cmd */ },
962 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, 962 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
963 { .name = "fdatasync", .errmsg = true, 963 { .name = "fdatasync", .errmsg = true,
964 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 964 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
965 { .name = "flock", .errmsg = true, 965 { .name = "flock", .errmsg = true,
966 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 966 .arg_scnprintf = { [0] = SCA_FD, /* fd */
967 [1] = SCA_FLOCK, /* cmd */ }, }, 967 [1] = SCA_FLOCK, /* cmd */ }, },
968 { .name = "fsetxattr", .errmsg = true, 968 { .name = "fsetxattr", .errmsg = true,
969 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 969 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
970 { .name = "fstat", .errmsg = true, .alias = "newfstat", 970 { .name = "fstat", .errmsg = true, .alias = "newfstat",
971 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 971 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
972 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", 972 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
973 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 973 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
974 { .name = "fstatfs", .errmsg = true, 974 { .name = "fstatfs", .errmsg = true,
975 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 975 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
976 { .name = "fsync", .errmsg = true, 976 { .name = "fsync", .errmsg = true,
977 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 977 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
978 { .name = "ftruncate", .errmsg = true, 978 { .name = "ftruncate", .errmsg = true,
979 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 979 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
980 { .name = "futex", .errmsg = true, 980 { .name = "futex", .errmsg = true,
981 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, 981 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
982 { .name = "futimesat", .errmsg = true, 982 { .name = "futimesat", .errmsg = true,
983 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 983 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
984 { .name = "getdents", .errmsg = true, 984 { .name = "getdents", .errmsg = true,
985 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 985 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
986 { .name = "getdents64", .errmsg = true, 986 { .name = "getdents64", .errmsg = true,
987 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 987 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
988 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 988 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
989 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 989 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
990 { .name = "ioctl", .errmsg = true, 990 { .name = "ioctl", .errmsg = true,
991 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 991 .arg_scnprintf = { [0] = SCA_FD, /* fd */
992#if defined(__i386__) || defined(__x86_64__) 992#if defined(__i386__) || defined(__x86_64__)
993/* 993/*
994 * FIXME: Make this available to all arches. 994 * FIXME: Make this available to all arches.
@@ -1002,7 +1002,7 @@ static struct syscall_fmt {
1002 { .name = "kill", .errmsg = true, 1002 { .name = "kill", .errmsg = true,
1003 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 1003 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1004 { .name = "linkat", .errmsg = true, 1004 { .name = "linkat", .errmsg = true,
1005 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1005 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1006 { .name = "lseek", .errmsg = true, 1006 { .name = "lseek", .errmsg = true,
1007 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 1007 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1008 [2] = SCA_STRARRAY, /* whence */ }, 1008 [2] = SCA_STRARRAY, /* whence */ },
@@ -1012,9 +1012,9 @@ static struct syscall_fmt {
1012 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 1012 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1013 [2] = SCA_MADV_BHV, /* behavior */ }, }, 1013 [2] = SCA_MADV_BHV, /* behavior */ }, },
1014 { .name = "mkdirat", .errmsg = true, 1014 { .name = "mkdirat", .errmsg = true,
1015 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1015 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1016 { .name = "mknodat", .errmsg = true, 1016 { .name = "mknodat", .errmsg = true,
1017 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1017 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1018 { .name = "mlock", .errmsg = true, 1018 { .name = "mlock", .errmsg = true,
1019 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1019 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1020 { .name = "mlockall", .errmsg = true, 1020 { .name = "mlockall", .errmsg = true,
@@ -1036,9 +1036,9 @@ static struct syscall_fmt {
1036 { .name = "munmap", .errmsg = true, 1036 { .name = "munmap", .errmsg = true,
1037 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1037 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1038 { .name = "name_to_handle_at", .errmsg = true, 1038 { .name = "name_to_handle_at", .errmsg = true,
1039 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1039 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1040 { .name = "newfstatat", .errmsg = true, 1040 { .name = "newfstatat", .errmsg = true,
1041 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1041 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1042 { .name = "open", .errmsg = true, 1042 { .name = "open", .errmsg = true,
1043 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, 1043 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
1044 { .name = "open_by_handle_at", .errmsg = true, 1044 { .name = "open_by_handle_at", .errmsg = true,
@@ -1052,20 +1052,20 @@ static struct syscall_fmt {
1052 { .name = "poll", .errmsg = true, .timeout = true, }, 1052 { .name = "poll", .errmsg = true, .timeout = true, },
1053 { .name = "ppoll", .errmsg = true, .timeout = true, }, 1053 { .name = "ppoll", .errmsg = true, .timeout = true, },
1054 { .name = "pread", .errmsg = true, .alias = "pread64", 1054 { .name = "pread", .errmsg = true, .alias = "pread64",
1055 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1055 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1056 { .name = "preadv", .errmsg = true, .alias = "pread", 1056 { .name = "preadv", .errmsg = true, .alias = "pread",
1057 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1057 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1058 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, 1058 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
1059 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", 1059 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
1060 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1060 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1061 { .name = "pwritev", .errmsg = true, 1061 { .name = "pwritev", .errmsg = true,
1062 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1062 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1063 { .name = "read", .errmsg = true, 1063 { .name = "read", .errmsg = true,
1064 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1064 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1065 { .name = "readlinkat", .errmsg = true, 1065 { .name = "readlinkat", .errmsg = true,
1066 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1066 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1067 { .name = "readv", .errmsg = true, 1067 { .name = "readv", .errmsg = true,
1068 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1068 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1069 { .name = "recvfrom", .errmsg = true, 1069 { .name = "recvfrom", .errmsg = true,
1070 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 1070 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1071 { .name = "recvmmsg", .errmsg = true, 1071 { .name = "recvmmsg", .errmsg = true,
@@ -1073,7 +1073,7 @@ static struct syscall_fmt {
1073 { .name = "recvmsg", .errmsg = true, 1073 { .name = "recvmsg", .errmsg = true,
1074 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, 1074 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1075 { .name = "renameat", .errmsg = true, 1075 { .name = "renameat", .errmsg = true,
1076 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1076 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1077 { .name = "rt_sigaction", .errmsg = true, 1077 { .name = "rt_sigaction", .errmsg = true,
1078 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, 1078 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
1079 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, 1079 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
@@ -1091,7 +1091,7 @@ static struct syscall_fmt {
1091 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 1091 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1092 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 1092 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1093 { .name = "shutdown", .errmsg = true, 1093 { .name = "shutdown", .errmsg = true,
1094 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1094 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1095 { .name = "socket", .errmsg = true, 1095 { .name = "socket", .errmsg = true,
1096 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 1096 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1097 [1] = SCA_SK_TYPE, /* type */ }, 1097 [1] = SCA_SK_TYPE, /* type */ },
@@ -1102,7 +1102,7 @@ static struct syscall_fmt {
1102 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 1102 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1103 { .name = "stat", .errmsg = true, .alias = "newstat", }, 1103 { .name = "stat", .errmsg = true, .alias = "newstat", },
1104 { .name = "symlinkat", .errmsg = true, 1104 { .name = "symlinkat", .errmsg = true,
1105 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1105 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1106 { .name = "tgkill", .errmsg = true, 1106 { .name = "tgkill", .errmsg = true,
1107 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 1107 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1108 { .name = "tkill", .errmsg = true, 1108 { .name = "tkill", .errmsg = true,
@@ -1113,9 +1113,9 @@ static struct syscall_fmt {
1113 { .name = "utimensat", .errmsg = true, 1113 { .name = "utimensat", .errmsg = true,
1114 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, }, 1114 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
1115 { .name = "write", .errmsg = true, 1115 { .name = "write", .errmsg = true,
1116 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1116 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1117 { .name = "writev", .errmsg = true, 1117 { .name = "writev", .errmsg = true,
1118 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1118 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1119}; 1119};
1120 1120
1121static int syscall_fmt__cmp(const void *name, const void *fmtp) 1121static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -1191,7 +1191,7 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
1191 1191
1192 if (thread__priv(thread) == NULL) 1192 if (thread__priv(thread) == NULL)
1193 thread__set_priv(thread, thread_trace__new()); 1193 thread__set_priv(thread, thread_trace__new());
1194 1194
1195 if (thread__priv(thread) == NULL) 1195 if (thread__priv(thread) == NULL)
1196 goto fail; 1196 goto fail;
1197 1197
@@ -2056,23 +2056,24 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2056 if (trace->trace_syscalls && 2056 if (trace->trace_syscalls &&
2057 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, 2057 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
2058 trace__sys_exit)) 2058 trace__sys_exit))
2059 goto out_error_tp; 2059 goto out_error_raw_syscalls;
2060 2060
2061 if (trace->trace_syscalls) 2061 if (trace->trace_syscalls)
2062 perf_evlist__add_vfs_getname(evlist); 2062 perf_evlist__add_vfs_getname(evlist);
2063 2063
2064 if ((trace->trace_pgfaults & TRACE_PFMAJ) && 2064 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
2065 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) 2065 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
2066 goto out_error_tp; 2066 goto out_error_mem;
2067 }
2067 2068
2068 if ((trace->trace_pgfaults & TRACE_PFMIN) && 2069 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2069 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN)) 2070 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
2070 goto out_error_tp; 2071 goto out_error_mem;
2071 2072
2072 if (trace->sched && 2073 if (trace->sched &&
2073 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 2074 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2074 trace__sched_stat_runtime)) 2075 trace__sched_stat_runtime))
2075 goto out_error_tp; 2076 goto out_error_sched_stat_runtime;
2076 2077
2077 err = perf_evlist__create_maps(evlist, &trace->opts.target); 2078 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2078 if (err < 0) { 2079 if (err < 0) {
@@ -2202,8 +2203,12 @@ out:
2202{ 2203{
2203 char errbuf[BUFSIZ]; 2204 char errbuf[BUFSIZ];
2204 2205
2205out_error_tp: 2206out_error_sched_stat_runtime:
2206 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf)); 2207 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
2208 goto out_error;
2209
2210out_error_raw_syscalls:
2211 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
2207 goto out_error; 2212 goto out_error;
2208 2213
2209out_error_mmap: 2214out_error_mmap:
@@ -2217,6 +2222,9 @@ out_error:
2217 fprintf(trace->output, "%s\n", errbuf); 2222 fprintf(trace->output, "%s\n", errbuf);
2218 goto out_delete_evlist; 2223 goto out_delete_evlist;
2219} 2224}
2225out_error_mem:
2226 fprintf(trace->output, "Not enough memory to run!\n");
2227 goto out_delete_evlist;
2220} 2228}
2221 2229
2222static int trace__replay(struct trace *trace) 2230static int trace__replay(struct trace *trace)
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5d4b039fe1ed..cc224080b525 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -20,7 +20,7 @@ NO_PERF_REGS := 1
20 20
21# Additional ARCH settings for x86 21# Additional ARCH settings for x86
22ifeq ($(ARCH),x86) 22ifeq ($(ARCH),x86)
23 ifeq (${IS_X86_64}, 1) 23 ifeq (${IS_64_BIT}, 1)
24 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT 24 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
25 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 25 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
26 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 26 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
@@ -198,6 +198,7 @@ CORE_FEATURE_TESTS = \
198 libpython-version \ 198 libpython-version \
199 libslang \ 199 libslang \
200 libunwind \ 200 libunwind \
201 pthread-attr-setaffinity-np \
201 stackprotector-all \ 202 stackprotector-all \
202 timerfd \ 203 timerfd \
203 libdw-dwarf-unwind \ 204 libdw-dwarf-unwind \
@@ -226,6 +227,7 @@ VF_FEATURE_TESTS = \
226 libelf-getphdrnum \ 227 libelf-getphdrnum \
227 libelf-mmap \ 228 libelf-mmap \
228 libpython-version \ 229 libpython-version \
230 pthread-attr-setaffinity-np \
229 stackprotector-all \ 231 stackprotector-all \
230 timerfd \ 232 timerfd \
231 libunwind-debug-frame \ 233 libunwind-debug-frame \
@@ -301,6 +303,10 @@ ifeq ($(feature-sync-compare-and-swap), 1)
301 CFLAGS += -DHAVE_SYNC_COMPARE_AND_SWAP_SUPPORT 303 CFLAGS += -DHAVE_SYNC_COMPARE_AND_SWAP_SUPPORT
302endif 304endif
303 305
306ifeq ($(feature-pthread-attr-setaffinity-np), 1)
307 CFLAGS += -DHAVE_PTHREAD_ATTR_SETAFFINITY_NP
308endif
309
304ifndef NO_BIONIC 310ifndef NO_BIONIC
305 $(call feature_check,bionic) 311 $(call feature_check,bionic)
306 ifeq ($(feature-bionic), 1) 312 ifeq ($(feature-bionic), 1)
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
index 851cd0172a76..ff95a68741d1 100644
--- a/tools/perf/config/Makefile.arch
+++ b/tools/perf/config/Makefile.arch
@@ -1,7 +1,7 @@
1 1
2uname_M := $(shell uname -m 2>/dev/null || echo not) 2uname_M := $(shell uname -m 2>/dev/null || echo not)
3 3
4ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ 4RAW_ARCH := $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
5 -e s/arm.*/arm/ -e s/sa110/arm/ \ 5 -e s/arm.*/arm/ -e s/sa110/arm/ \
6 -e s/s390x/s390/ -e s/parisc64/parisc/ \ 6 -e s/s390x/s390/ -e s/parisc64/parisc/ \
7 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ 7 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
@@ -9,23 +9,23 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
9 -e s/tile.*/tile/ ) 9 -e s/tile.*/tile/ )
10 10
11# Additional ARCH settings for x86 11# Additional ARCH settings for x86
12ifeq ($(ARCH),i386) 12ifeq ($(RAW_ARCH),i386)
13 override ARCH := x86 13 ARCH ?= x86
14endif 14endif
15 15
16ifeq ($(ARCH),x86_64) 16ifeq ($(RAW_ARCH),x86_64)
17 override ARCH := x86 17 ARCH ?= x86
18 IS_X86_64 := 0 18
19 ifeq (, $(findstring m32,$(CFLAGS))) 19 ifneq (, $(findstring m32,$(CFLAGS)))
20 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) 20 RAW_ARCH := x86_32
21 RAW_ARCH := x86_64
22 endif 21 endif
23endif 22endif
24 23
25ifeq (${IS_X86_64}, 1) 24ARCH ?= $(RAW_ARCH)
25
26LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
27ifeq ($(LP64), 1)
26 IS_64_BIT := 1 28 IS_64_BIT := 1
27else ifeq ($(ARCH),x86)
28 IS_64_BIT := 0
29else 29else
30 IS_64_BIT := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) 30 IS_64_BIT := 0
31endif 31endif
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 53f19b5dbc37..42ac05aaf8ac 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -25,6 +25,7 @@ FILES= \
25 test-libslang.bin \ 25 test-libslang.bin \
26 test-libunwind.bin \ 26 test-libunwind.bin \
27 test-libunwind-debug-frame.bin \ 27 test-libunwind-debug-frame.bin \
28 test-pthread-attr-setaffinity-np.bin \
28 test-stackprotector-all.bin \ 29 test-stackprotector-all.bin \
29 test-timerfd.bin \ 30 test-timerfd.bin \
30 test-libdw-dwarf-unwind.bin \ 31 test-libdw-dwarf-unwind.bin \
@@ -47,6 +48,9 @@ test-all.bin:
47test-hello.bin: 48test-hello.bin:
48 $(BUILD) 49 $(BUILD)
49 50
51test-pthread-attr-setaffinity-np.bin:
52 $(BUILD) -Werror -lpthread
53
50test-stackprotector-all.bin: 54test-stackprotector-all.bin:
51 $(BUILD) -Werror -fstack-protector-all 55 $(BUILD) -Werror -fstack-protector-all
52 56
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index 652e0098eba6..6d4d09323922 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -97,6 +97,10 @@
97# include "test-zlib.c" 97# include "test-zlib.c"
98#undef main 98#undef main
99 99
100#define main main_test_pthread_attr_setaffinity_np
101# include "test-pthread_attr_setaffinity_np.c"
102#undef main
103
100int main(int argc, char *argv[]) 104int main(int argc, char *argv[])
101{ 105{
102 main_test_libpython(); 106 main_test_libpython();
@@ -121,6 +125,7 @@ int main(int argc, char *argv[])
121 main_test_libdw_dwarf_unwind(); 125 main_test_libdw_dwarf_unwind();
122 main_test_sync_compare_and_swap(argc, argv); 126 main_test_sync_compare_and_swap(argc, argv);
123 main_test_zlib(); 127 main_test_zlib();
128 main_test_pthread_attr_setaffinity_np();
124 129
125 return 0; 130 return 0;
126} 131}
diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
new file mode 100644
index 000000000000..0a0d3ecb4e8a
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
@@ -0,0 +1,14 @@
1#include <stdint.h>
2#include <pthread.h>
3
4int main(void)
5{
6 int ret = 0;
7 pthread_attr_t thread_attr;
8
9 pthread_attr_init(&thread_attr);
10 /* don't care abt exact args, just the API itself in libpthread */
11 ret = pthread_attr_setaffinity_np(&thread_attr, 0, NULL);
12
13 return ret;
14}
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index a3b13d7dc1d4..6ef68165c9db 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -6,7 +6,6 @@
6#include <sys/syscall.h> 6#include <sys/syscall.h>
7#include <linux/types.h> 7#include <linux/types.h>
8#include <linux/perf_event.h> 8#include <linux/perf_event.h>
9#include <asm/unistd.h>
10 9
11#if defined(__i386__) 10#if defined(__i386__)
12#define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 11#define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
index 790ceba6ad3f..28431d1bbcf5 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
@@ -5,7 +5,10 @@
5 * ANY CHANGES MADE HERE WILL BE LOST! 5 * ANY CHANGES MADE HERE WILL BE LOST!
6 * 6 *
7 */ 7 */
8 8#include <stdbool.h>
9#ifndef HAS_BOOL
10# define HAS_BOOL 1
11#endif
9#line 1 "Context.xs" 12#line 1 "Context.xs"
10/* 13/*
11 * Context.xs. XS interfaces for perf script. 14 * Context.xs. XS interfaces for perf script.
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index c9b4b6269b51..1091bd47adfd 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -104,7 +104,6 @@ class Event(dict):
104 continue 104 continue
105 if not self.compare_data(self[t], other[t]): 105 if not self.compare_data(self[t], other[t]):
106 log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) 106 log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
107
108 107
109# Test file description needs to have following sections: 108# Test file description needs to have following sections:
110# [config] 109# [config]
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index ab28cca2cb97..0bf06bec68c7 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -11,6 +11,9 @@
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h" 12#include "callchain.h"
13 13
14/* For bsearch. We try to unwind functions in shared object. */
15#include <stdlib.h>
16
14static int mmap_handler(struct perf_tool *tool __maybe_unused, 17static int mmap_handler(struct perf_tool *tool __maybe_unused,
15 union perf_event *event, 18 union perf_event *event,
16 struct perf_sample *sample __maybe_unused, 19 struct perf_sample *sample __maybe_unused,
@@ -28,7 +31,7 @@ static int init_live_machine(struct machine *machine)
28 mmap_handler, machine, true); 31 mmap_handler, machine, true);
29} 32}
30 33
31#define MAX_STACK 6 34#define MAX_STACK 8
32 35
33static int unwind_entry(struct unwind_entry *entry, void *arg) 36static int unwind_entry(struct unwind_entry *entry, void *arg)
34{ 37{
@@ -37,6 +40,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
37 static const char *funcs[MAX_STACK] = { 40 static const char *funcs[MAX_STACK] = {
38 "test__arch_unwind_sample", 41 "test__arch_unwind_sample",
39 "unwind_thread", 42 "unwind_thread",
43 "compare",
44 "bsearch",
40 "krava_3", 45 "krava_3",
41 "krava_2", 46 "krava_2",
42 "krava_1", 47 "krava_1",
@@ -88,10 +93,37 @@ static int unwind_thread(struct thread *thread)
88 return err; 93 return err;
89} 94}
90 95
96static int global_unwind_retval = -INT_MAX;
97
98__attribute__ ((noinline))
99static int compare(void *p1, void *p2)
100{
101 /* Any possible value should be 'thread' */
102 struct thread *thread = *(struct thread **)p1;
103
104 if (global_unwind_retval == -INT_MAX)
105 global_unwind_retval = unwind_thread(thread);
106
107 return p1 - p2;
108}
109
91__attribute__ ((noinline)) 110__attribute__ ((noinline))
92static int krava_3(struct thread *thread) 111static int krava_3(struct thread *thread)
93{ 112{
94 return unwind_thread(thread); 113 struct thread *array[2] = {thread, thread};
114 void *fp = &bsearch;
115 /*
116 * make _bsearch a volatile function pointer to
117 * prevent potential optimization, which may expand
118 * bsearch and call compare directly from this function,
119 * instead of libc shared object.
120 */
121 void *(*volatile _bsearch)(void *, void *, size_t,
122 size_t, int (*)(void *, void *));
123
124 _bsearch = fp;
125 _bsearch(array, &thread, 2, sizeof(struct thread **), compare);
126 return global_unwind_retval;
95} 127}
96 128
97__attribute__ ((noinline)) 129__attribute__ ((noinline))
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 614d5c4978ab..18619966454c 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -140,7 +140,7 @@ static void del_hist_entries(struct hists *hists)
140 he = rb_entry(node, struct hist_entry, rb_node); 140 he = rb_entry(node, struct hist_entry, rb_node);
141 rb_erase(node, root_out); 141 rb_erase(node, root_out);
142 rb_erase(&he->rb_node_in, root_in); 142 rb_erase(&he->rb_node_in, root_in);
143 hist_entry__free(he); 143 hist_entry__delete(he);
144 } 144 }
145} 145}
146 146
@@ -187,7 +187,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec
187 * function since TEST_ASSERT_VAL() returns in case of failure. 187 * function since TEST_ASSERT_VAL() returns in case of failure.
188 */ 188 */
189 hists__collapse_resort(hists, NULL); 189 hists__collapse_resort(hists, NULL);
190 hists__output_resort(hists); 190 hists__output_resort(hists, NULL);
191 191
192 if (verbose > 2) { 192 if (verbose > 2) {
193 pr_info("use callchain: %d, cumulate callchain: %d\n", 193 pr_info("use callchain: %d, cumulate callchain: %d\n",
@@ -454,12 +454,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
454 * 30.00% 10.00% perf perf [.] cmd_record 454 * 30.00% 10.00% perf perf [.] cmd_record
455 * 20.00% 0.00% bash libc [.] malloc 455 * 20.00% 0.00% bash libc [.] malloc
456 * 10.00% 10.00% bash [kernel] [k] page_fault 456 * 10.00% 10.00% bash [kernel] [k] page_fault
457 * 10.00% 10.00% perf [kernel] [k] schedule 457 * 10.00% 10.00% bash bash [.] xmalloc
458 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
459 * 10.00% 10.00% perf [kernel] [k] page_fault 458 * 10.00% 10.00% perf [kernel] [k] page_fault
460 * 10.00% 10.00% perf libc [.] free
461 * 10.00% 10.00% perf libc [.] malloc 459 * 10.00% 10.00% perf libc [.] malloc
462 * 10.00% 10.00% bash bash [.] xmalloc 460 * 10.00% 10.00% perf [kernel] [k] schedule
461 * 10.00% 10.00% perf libc [.] free
462 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
463 */ 463 */
464 struct result expected[] = { 464 struct result expected[] = {
465 { 7000, 2000, "perf", "perf", "main" }, 465 { 7000, 2000, "perf", "perf", "main" },
@@ -468,12 +468,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
468 { 3000, 1000, "perf", "perf", "cmd_record" }, 468 { 3000, 1000, "perf", "perf", "cmd_record" },
469 { 2000, 0, "bash", "libc", "malloc" }, 469 { 2000, 0, "bash", "libc", "malloc" },
470 { 1000, 1000, "bash", "[kernel]", "page_fault" }, 470 { 1000, 1000, "bash", "[kernel]", "page_fault" },
471 { 1000, 1000, "perf", "[kernel]", "schedule" }, 471 { 1000, 1000, "bash", "bash", "xmalloc" },
472 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
473 { 1000, 1000, "perf", "[kernel]", "page_fault" }, 472 { 1000, 1000, "perf", "[kernel]", "page_fault" },
473 { 1000, 1000, "perf", "[kernel]", "schedule" },
474 { 1000, 1000, "perf", "libc", "free" }, 474 { 1000, 1000, "perf", "libc", "free" },
475 { 1000, 1000, "perf", "libc", "malloc" }, 475 { 1000, 1000, "perf", "libc", "malloc" },
476 { 1000, 1000, "bash", "bash", "xmalloc" }, 476 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
477 }; 477 };
478 478
479 symbol_conf.use_callchain = false; 479 symbol_conf.use_callchain = false;
@@ -537,10 +537,13 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
537 * malloc 537 * malloc
538 * main 538 * main
539 * 539 *
540 * 10.00% 10.00% perf [kernel] [k] schedule 540 * 10.00% 10.00% bash bash [.] xmalloc
541 * | 541 * |
542 * --- schedule 542 * --- xmalloc
543 * run_command 543 * malloc
544 * xmalloc <--- NOTE: there's a cycle
545 * malloc
546 * xmalloc
544 * main 547 * main
545 * 548 *
546 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open 549 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
@@ -556,6 +559,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
556 * run_command 559 * run_command
557 * main 560 * main
558 * 561 *
562 * 10.00% 10.00% perf [kernel] [k] schedule
563 * |
564 * --- schedule
565 * run_command
566 * main
567 *
559 * 10.00% 10.00% perf libc [.] free 568 * 10.00% 10.00% perf libc [.] free
560 * | 569 * |
561 * --- free 570 * --- free
@@ -570,15 +579,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
570 * run_command 579 * run_command
571 * main 580 * main
572 * 581 *
573 * 10.00% 10.00% bash bash [.] xmalloc
574 * |
575 * --- xmalloc
576 * malloc
577 * xmalloc <--- NOTE: there's a cycle
578 * malloc
579 * xmalloc
580 * main
581 *
582 */ 582 */
583 struct result expected[] = { 583 struct result expected[] = {
584 { 7000, 2000, "perf", "perf", "main" }, 584 { 7000, 2000, "perf", "perf", "main" },
@@ -587,12 +587,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
587 { 3000, 1000, "perf", "perf", "cmd_record" }, 587 { 3000, 1000, "perf", "perf", "cmd_record" },
588 { 2000, 0, "bash", "libc", "malloc" }, 588 { 2000, 0, "bash", "libc", "malloc" },
589 { 1000, 1000, "bash", "[kernel]", "page_fault" }, 589 { 1000, 1000, "bash", "[kernel]", "page_fault" },
590 { 1000, 1000, "perf", "[kernel]", "schedule" }, 590 { 1000, 1000, "bash", "bash", "xmalloc" },
591 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, 591 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
592 { 1000, 1000, "perf", "[kernel]", "page_fault" }, 592 { 1000, 1000, "perf", "[kernel]", "page_fault" },
593 { 1000, 1000, "perf", "[kernel]", "schedule" },
593 { 1000, 1000, "perf", "libc", "free" }, 594 { 1000, 1000, "perf", "libc", "free" },
594 { 1000, 1000, "perf", "libc", "malloc" }, 595 { 1000, 1000, "perf", "libc", "malloc" },
595 { 1000, 1000, "bash", "bash", "xmalloc" },
596 }; 596 };
597 struct callchain_result expected_callchain[] = { 597 struct callchain_result expected_callchain[] = {
598 { 598 {
@@ -622,9 +622,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
622 { "bash", "main" }, }, 622 { "bash", "main" }, },
623 }, 623 },
624 { 624 {
625 3, { { "[kernel]", "schedule" }, 625 6, { { "bash", "xmalloc" },
626 { "perf", "run_command" }, 626 { "libc", "malloc" },
627 { "perf", "main" }, }, 627 { "bash", "xmalloc" },
628 { "libc", "malloc" },
629 { "bash", "xmalloc" },
630 { "bash", "main" }, },
628 }, 631 },
629 { 632 {
630 3, { { "[kernel]", "sys_perf_event_open" }, 633 3, { { "[kernel]", "sys_perf_event_open" },
@@ -638,6 +641,11 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
638 { "perf", "main" }, }, 641 { "perf", "main" }, },
639 }, 642 },
640 { 643 {
644 3, { { "[kernel]", "schedule" },
645 { "perf", "run_command" },
646 { "perf", "main" }, },
647 },
648 {
641 4, { { "libc", "free" }, 649 4, { { "libc", "free" },
642 { "perf", "cmd_record" }, 650 { "perf", "cmd_record" },
643 { "perf", "run_command" }, 651 { "perf", "run_command" },
@@ -649,14 +657,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
649 { "perf", "run_command" }, 657 { "perf", "run_command" },
650 { "perf", "main" }, }, 658 { "perf", "main" }, },
651 }, 659 },
652 {
653 6, { { "bash", "xmalloc" },
654 { "libc", "malloc" },
655 { "bash", "xmalloc" },
656 { "libc", "malloc" },
657 { "bash", "xmalloc" },
658 { "bash", "main" }, },
659 },
660 }; 660 };
661 661
662 symbol_conf.use_callchain = true; 662 symbol_conf.use_callchain = true;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 74f257a81265..59e53db7914c 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -138,7 +138,7 @@ int test__hists_filter(void)
138 struct hists *hists = evsel__hists(evsel); 138 struct hists *hists = evsel__hists(evsel);
139 139
140 hists__collapse_resort(hists, NULL); 140 hists__collapse_resort(hists, NULL);
141 hists__output_resort(hists); 141 hists__output_resort(hists, NULL);
142 142
143 if (verbose > 2) { 143 if (verbose > 2) {
144 pr_info("Normal histogram\n"); 144 pr_info("Normal histogram\n");
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index a748f2be1222..b52c9faea224 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -106,7 +106,7 @@ static void del_hist_entries(struct hists *hists)
106 he = rb_entry(node, struct hist_entry, rb_node); 106 he = rb_entry(node, struct hist_entry, rb_node);
107 rb_erase(node, root_out); 107 rb_erase(node, root_out);
108 rb_erase(&he->rb_node_in, root_in); 108 rb_erase(&he->rb_node_in, root_in);
109 hist_entry__free(he); 109 hist_entry__delete(he);
110 } 110 }
111} 111}
112 112
@@ -152,7 +152,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
152 goto out; 152 goto out;
153 153
154 hists__collapse_resort(hists, NULL); 154 hists__collapse_resort(hists, NULL);
155 hists__output_resort(hists); 155 hists__output_resort(hists, NULL);
156 156
157 if (verbose > 2) { 157 if (verbose > 2) {
158 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 158 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
@@ -252,7 +252,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
252 goto out; 252 goto out;
253 253
254 hists__collapse_resort(hists, NULL); 254 hists__collapse_resort(hists, NULL);
255 hists__output_resort(hists); 255 hists__output_resort(hists, NULL);
256 256
257 if (verbose > 2) { 257 if (verbose > 2) {
258 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 258 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
@@ -306,7 +306,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
306 goto out; 306 goto out;
307 307
308 hists__collapse_resort(hists, NULL); 308 hists__collapse_resort(hists, NULL);
309 hists__output_resort(hists); 309 hists__output_resort(hists, NULL);
310 310
311 if (verbose > 2) { 311 if (verbose > 2) {
312 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 312 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
@@ -384,7 +384,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
384 goto out; 384 goto out;
385 385
386 hists__collapse_resort(hists, NULL); 386 hists__collapse_resort(hists, NULL);
387 hists__output_resort(hists); 387 hists__output_resort(hists, NULL);
388 388
389 if (verbose > 2) { 389 if (verbose > 2) {
390 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 390 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
@@ -487,7 +487,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)
487 goto out; 487 goto out;
488 488
489 hists__collapse_resort(hists, NULL); 489 hists__collapse_resort(hists, NULL);
490 hists__output_resort(hists); 490 hists__output_resort(hists, NULL);
491 491
492 if (verbose > 2) { 492 if (verbose > 2) {
493 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 493 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 69a71ff84e01..75709d2b17b4 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -222,7 +222,6 @@ tarpkg:
222 @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \ 222 @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \
223 echo "- $@: $$cmd" && echo $$cmd > $@ && \ 223 echo "- $@: $$cmd" && echo $$cmd > $@ && \
224 ( eval $$cmd ) >> $@ 2>&1 224 ( eval $$cmd ) >> $@ 2>&1
225
226 225
227all: $(run) $(run_O) tarpkg 226all: $(run) $(run_O) tarpkg
228 @echo OK 227 @echo OK
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 7f2f51f93619..1cdab0ce00e2 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1145,6 +1145,49 @@ static int test__pinned_group(struct perf_evlist *evlist)
1145 return 0; 1145 return 0;
1146} 1146}
1147 1147
1148static int test__checkevent_breakpoint_len(struct perf_evlist *evlist)
1149{
1150 struct perf_evsel *evsel = perf_evlist__first(evlist);
1151
1152 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
1153 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
1154 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
1155 TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
1156 evsel->attr.bp_type);
1157 TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_1 ==
1158 evsel->attr.bp_len);
1159
1160 return 0;
1161}
1162
1163static int test__checkevent_breakpoint_len_w(struct perf_evlist *evlist)
1164{
1165 struct perf_evsel *evsel = perf_evlist__first(evlist);
1166
1167 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
1168 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
1169 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
1170 TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W ==
1171 evsel->attr.bp_type);
1172 TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_2 ==
1173 evsel->attr.bp_len);
1174
1175 return 0;
1176}
1177
1178static int
1179test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist)
1180{
1181 struct perf_evsel *evsel = perf_evlist__first(evlist);
1182
1183 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
1184 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
1185 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
1186 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
1187
1188 return test__checkevent_breakpoint_rw(evlist);
1189}
1190
1148static int count_tracepoints(void) 1191static int count_tracepoints(void)
1149{ 1192{
1150 char events_path[PATH_MAX]; 1193 char events_path[PATH_MAX];
@@ -1420,6 +1463,21 @@ static struct evlist_test test__events[] = {
1420 .check = test__pinned_group, 1463 .check = test__pinned_group,
1421 .id = 41, 1464 .id = 41,
1422 }, 1465 },
1466 {
1467 .name = "mem:0/1",
1468 .check = test__checkevent_breakpoint_len,
1469 .id = 42,
1470 },
1471 {
1472 .name = "mem:0/2:w",
1473 .check = test__checkevent_breakpoint_len_w,
1474 .id = 43,
1475 },
1476 {
1477 .name = "mem:0/4:rw:u",
1478 .check = test__checkevent_breakpoint_len_rw_modifier,
1479 .id = 44
1480 },
1423#if defined(__s390x__) 1481#if defined(__s390x__)
1424 { 1482 {
1425 .name = "kvm-s390:kvm_s390_create_vm", 1483 .name = "kvm-s390:kvm_s390_create_vm",
@@ -1471,7 +1529,7 @@ static int test_event(struct evlist_test *e)
1471 } else { 1529 } else {
1472 ret = e->check(evlist); 1530 ret = e->check(evlist);
1473 } 1531 }
1474 1532
1475 perf_evlist__delete(evlist); 1533 perf_evlist__delete(evlist);
1476 1534
1477 return ret; 1535 return ret;
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 4908c648a597..30c02181e78b 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -110,7 +110,7 @@ static bool samples_same(const struct perf_sample *s1,
110 110
111 if (type & PERF_SAMPLE_STACK_USER) { 111 if (type & PERF_SAMPLE_STACK_USER) {
112 COMP(user_stack.size); 112 COMP(user_stack.size);
113 if (memcmp(s1->user_stack.data, s1->user_stack.data, 113 if (memcmp(s1->user_stack.data, s2->user_stack.data,
114 s1->user_stack.size)) { 114 s1->user_stack.size)) {
115 pr_debug("Samples differ at 'user_stack'\n"); 115 pr_debug("Samples differ at 'user_stack'\n");
116 return false; 116 return false;
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 1e0a2fd80115..9d32e3c0cfee 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -517,7 +517,7 @@ static bool annotate_browser__jump(struct annotate_browser *browser)
517 } 517 }
518 518
519 annotate_browser__set_top(browser, dl, idx); 519 annotate_browser__set_top(browser, dl, idx);
520 520
521 return true; 521 return true;
522} 522}
523 523
@@ -867,7 +867,6 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser
867 867
868 ++browser->nr_jumps; 868 ++browser->nr_jumps;
869 } 869 }
870
871} 870}
872 871
873static inline int width_jumps(int n) 872static inline int width_jumps(int n)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index e6bb04b5b09b..788506eef567 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -550,7 +550,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
550 bool need_percent; 550 bool need_percent;
551 551
552 node = rb_first(root); 552 node = rb_first(root);
553 need_percent = !!rb_next(node); 553 need_percent = node && rb_next(node);
554 554
555 while (node) { 555 while (node) {
556 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 556 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index dc0d095f318c..25d608394d74 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -204,6 +204,9 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
204 if (ret) 204 if (ret)
205 return ret; 205 return ret;
206 206
207 if (a->thread != b->thread || !symbol_conf.use_callchain)
208 return 0;
209
207 ret = b->callchain->max_depth - a->callchain->max_depth; 210 ret = b->callchain->max_depth - a->callchain->max_depth;
208 } 211 }
209 return ret; 212 return ret;
@@ -282,7 +285,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
282} 285}
283 286
284#define __HPP_SORT_FN(_type, _field) \ 287#define __HPP_SORT_FN(_type, _field) \
285static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ 288static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
289 struct hist_entry *a, struct hist_entry *b) \
286{ \ 290{ \
287 return __hpp__sort(a, b, he_get_##_field); \ 291 return __hpp__sort(a, b, he_get_##_field); \
288} 292}
@@ -309,7 +313,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
309} 313}
310 314
311#define __HPP_SORT_ACC_FN(_type, _field) \ 315#define __HPP_SORT_ACC_FN(_type, _field) \
312static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ 316static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
317 struct hist_entry *a, struct hist_entry *b) \
313{ \ 318{ \
314 return __hpp__sort_acc(a, b, he_get_acc_##_field); \ 319 return __hpp__sort_acc(a, b, he_get_acc_##_field); \
315} 320}
@@ -328,7 +333,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
328} 333}
329 334
330#define __HPP_SORT_RAW_FN(_type, _field) \ 335#define __HPP_SORT_RAW_FN(_type, _field) \
331static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ 336static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
337 struct hist_entry *a, struct hist_entry *b) \
332{ \ 338{ \
333 return __hpp__sort(a, b, he_get_raw_##_field); \ 339 return __hpp__sort(a, b, he_get_raw_##_field); \
334} 340}
@@ -358,7 +364,8 @@ HPP_PERCENT_ACC_FNS(overhead_acc, period)
358HPP_RAW_FNS(samples, nr_events) 364HPP_RAW_FNS(samples, nr_events)
359HPP_RAW_FNS(period, period) 365HPP_RAW_FNS(period, period)
360 366
361static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused, 367static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
368 struct hist_entry *a __maybe_unused,
362 struct hist_entry *b __maybe_unused) 369 struct hist_entry *b __maybe_unused)
363{ 370{
364 return 0; 371 return 0;
diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h
index f34f89eb607c..717d39d3052b 100644
--- a/tools/perf/ui/progress.h
+++ b/tools/perf/ui/progress.h
@@ -4,12 +4,12 @@
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6void ui_progress__finish(void); 6void ui_progress__finish(void);
7 7
8struct ui_progress { 8struct ui_progress {
9 const char *title; 9 const char *title;
10 u64 curr, next, step, total; 10 u64 curr, next, step, total;
11}; 11};
12 12
13void ui_progress__init(struct ui_progress *p, u64 total, const char *title); 13void ui_progress__init(struct ui_progress *p, u64 total, const char *title);
14void ui_progress__update(struct ui_progress *p, u64 adv); 14void ui_progress__update(struct ui_progress *p, u64 adv);
15 15
diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c
index 1c8b9afd5d6e..88f5143a5981 100644
--- a/tools/perf/ui/tui/helpline.c
+++ b/tools/perf/ui/tui/helpline.c
@@ -9,6 +9,7 @@
9#include "../libslang.h" 9#include "../libslang.h"
10 10
11char ui_helpline__last_msg[1024]; 11char ui_helpline__last_msg[1024];
12bool tui_helpline__set;
12 13
13static void tui_helpline__pop(void) 14static void tui_helpline__pop(void)
14{ 15{
@@ -35,6 +36,8 @@ static int tui_helpline__show(const char *format, va_list ap)
35 sizeof(ui_helpline__last_msg) - backlog, format, ap); 36 sizeof(ui_helpline__last_msg) - backlog, format, ap);
36 backlog += ret; 37 backlog += ret;
37 38
39 tui_helpline__set = true;
40
38 if (ui_helpline__last_msg[backlog - 1] == '\n') { 41 if (ui_helpline__last_msg[backlog - 1] == '\n') {
39 ui_helpline__puts(ui_helpline__last_msg); 42 ui_helpline__puts(ui_helpline__last_msg);
40 SLsmg_refresh(); 43 SLsmg_refresh();
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 2f612562978c..b77e1d771363 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -1,5 +1,8 @@
1#include <signal.h> 1#include <signal.h>
2#include <stdbool.h> 2#include <stdbool.h>
3#ifdef HAVE_BACKTRACE_SUPPORT
4#include <execinfo.h>
5#endif
3 6
4#include "../../util/cache.h" 7#include "../../util/cache.h"
5#include "../../util/debug.h" 8#include "../../util/debug.h"
@@ -14,6 +17,7 @@
14static volatile int ui__need_resize; 17static volatile int ui__need_resize;
15 18
16extern struct perf_error_ops perf_tui_eops; 19extern struct perf_error_ops perf_tui_eops;
20extern bool tui_helpline__set;
17 21
18extern void hist_browser__init_hpp(void); 22extern void hist_browser__init_hpp(void);
19 23
@@ -88,6 +92,25 @@ int ui__getch(int delay_secs)
88 return SLkp_getkey(); 92 return SLkp_getkey();
89} 93}
90 94
95#ifdef HAVE_BACKTRACE_SUPPORT
96static void ui__signal_backtrace(int sig)
97{
98 void *stackdump[32];
99 size_t size;
100
101 ui__exit(false);
102 psignal(sig, "perf");
103
104 printf("-------- backtrace --------\n");
105 size = backtrace(stackdump, ARRAY_SIZE(stackdump));
106 backtrace_symbols_fd(stackdump, size, STDOUT_FILENO);
107
108 exit(0);
109}
110#else
111# define ui__signal_backtrace ui__signal
112#endif
113
91static void ui__signal(int sig) 114static void ui__signal(int sig)
92{ 115{
93 ui__exit(false); 116 ui__exit(false);
@@ -122,8 +145,8 @@ int ui__init(void)
122 ui_browser__init(); 145 ui_browser__init();
123 tui_progress__init(); 146 tui_progress__init();
124 147
125 signal(SIGSEGV, ui__signal); 148 signal(SIGSEGV, ui__signal_backtrace);
126 signal(SIGFPE, ui__signal); 149 signal(SIGFPE, ui__signal_backtrace);
127 signal(SIGINT, ui__signal); 150 signal(SIGINT, ui__signal);
128 signal(SIGQUIT, ui__signal); 151 signal(SIGQUIT, ui__signal);
129 signal(SIGTERM, ui__signal); 152 signal(SIGTERM, ui__signal);
@@ -137,7 +160,7 @@ out:
137 160
138void ui__exit(bool wait_for_ok) 161void ui__exit(bool wait_for_ok)
139{ 162{
140 if (wait_for_ok) 163 if (wait_for_ok && tui_helpline__set)
141 ui__question_window("Fatal Error", 164 ui__question_window("Fatal Error",
142 ui_helpline__last_msg, 165 ui_helpline__last_msg,
143 "Press any key...", 0); 166 "Press any key...", 0);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 79999ceaf2be..61bf9128e1f2 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -177,14 +177,17 @@ static int lock__parse(struct ins_operands *ops)
177 goto out_free_ops; 177 goto out_free_ops;
178 178
179 ops->locked.ins = ins__find(name); 179 ops->locked.ins = ins__find(name);
180 free(name);
181
180 if (ops->locked.ins == NULL) 182 if (ops->locked.ins == NULL)
181 goto out_free_ops; 183 goto out_free_ops;
182 184
183 if (!ops->locked.ins->ops) 185 if (!ops->locked.ins->ops)
184 return 0; 186 return 0;
185 187
186 if (ops->locked.ins->ops->parse) 188 if (ops->locked.ins->ops->parse &&
187 ops->locked.ins->ops->parse(ops->locked.ops); 189 ops->locked.ins->ops->parse(ops->locked.ops) < 0)
190 goto out_free_ops;
188 191
189 return 0; 192 return 0;
190 193
@@ -208,6 +211,13 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
208 211
209static void lock__delete(struct ins_operands *ops) 212static void lock__delete(struct ins_operands *ops)
210{ 213{
214 struct ins *ins = ops->locked.ins;
215
216 if (ins && ins->ops->free)
217 ins->ops->free(ops->locked.ops);
218 else
219 ins__delete(ops->locked.ops);
220
211 zfree(&ops->locked.ops); 221 zfree(&ops->locked.ops);
212 zfree(&ops->target.raw); 222 zfree(&ops->target.raw);
213 zfree(&ops->target.name); 223 zfree(&ops->target.name);
@@ -229,7 +239,7 @@ static int mov__parse(struct ins_operands *ops)
229 *s = '\0'; 239 *s = '\0';
230 ops->source.raw = strdup(ops->raw); 240 ops->source.raw = strdup(ops->raw);
231 *s = ','; 241 *s = ',';
232 242
233 if (ops->source.raw == NULL) 243 if (ops->source.raw == NULL)
234 return -1; 244 return -1;
235 245
@@ -531,8 +541,8 @@ static void disasm_line__init_ins(struct disasm_line *dl)
531 if (!dl->ins->ops) 541 if (!dl->ins->ops)
532 return; 542 return;
533 543
534 if (dl->ins->ops->parse) 544 if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops) < 0)
535 dl->ins->ops->parse(&dl->ops); 545 dl->ins = NULL;
536} 546}
537 547
538static int disasm_line__parse(char *line, char **namep, char **rawp) 548static int disasm_line__parse(char *line, char **namep, char **rawp)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 0784a9420528..cadbdc90a5cb 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -116,11 +116,6 @@ struct annotation {
116 struct annotated_source *src; 116 struct annotated_source *src;
117}; 117};
118 118
119struct sannotation {
120 struct annotation annotation;
121 struct symbol symbol;
122};
123
124static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) 119static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
125{ 120{
126 return (((void *)&notes->src->histograms) + 121 return (((void *)&notes->src->histograms) +
@@ -129,8 +124,7 @@ static inline struct sym_hist *annotation__histogram(struct annotation *notes, i
129 124
130static inline struct annotation *symbol__annotation(struct symbol *sym) 125static inline struct annotation *symbol__annotation(struct symbol *sym)
131{ 126{
132 struct sannotation *a = container_of(sym, struct sannotation, symbol); 127 return (void *)sym - symbol_conf.priv_size;
133 return &a->annotation;
134} 128}
135 129
136int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx); 130int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx);
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 5cf9e1b5989d..d04d770d90f6 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -71,7 +71,9 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
71extern char *perf_pathdup(const char *fmt, ...) 71extern char *perf_pathdup(const char *fmt, ...)
72 __attribute__((format (printf, 1, 2))); 72 __attribute__((format (printf, 1, 2)));
73 73
74#ifndef __UCLIBC__
74/* Matches the libc/libbsd function attribute so we declare this unconditionally: */ 75/* Matches the libc/libbsd function attribute so we declare this unconditionally: */
75extern size_t strlcpy(char *dest, const char *src, size_t size); 76extern size_t strlcpy(char *dest, const char *src, size_t size);
77#endif
76 78
77#endif /* __PERF_CACHE_H */ 79#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 64b377e591e4..14e7a123d43b 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -841,3 +841,33 @@ char *callchain_list__sym_name(struct callchain_list *cl,
841 841
842 return bf; 842 return bf;
843} 843}
844
845static void free_callchain_node(struct callchain_node *node)
846{
847 struct callchain_list *list, *tmp;
848 struct callchain_node *child;
849 struct rb_node *n;
850
851 list_for_each_entry_safe(list, tmp, &node->val, list) {
852 list_del(&list->list);
853 free(list);
854 }
855
856 n = rb_first(&node->rb_root_in);
857 while (n) {
858 child = container_of(n, struct callchain_node, rb_node_in);
859 n = rb_next(n);
860 rb_erase(&child->rb_node_in, &node->rb_root_in);
861
862 free_callchain_node(child);
863 free(child);
864 }
865}
866
867void free_callchain(struct callchain_root *root)
868{
869 if (!symbol_conf.use_callchain)
870 return;
871
872 free_callchain_node(&root->node);
873}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index dbc08cf5f970..c0ec1acc38e4 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -198,4 +198,6 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
198char *callchain_list__sym_name(struct callchain_list *cl, 198char *callchain_list__sym_name(struct callchain_list *cl,
199 char *bf, size_t bfsize, bool show_dso); 199 char *bf, size_t bfsize, bool show_dso);
200 200
201void free_callchain(struct callchain_root *root);
202
201#endif /* __PERF_CALLCHAIN_H */ 203#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index f4654183d391..55355b3d4f85 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -5,132 +5,6 @@
5 5
6int perf_use_color_default = -1; 6int perf_use_color_default = -1;
7 7
8static int parse_color(const char *name, int len)
9{
10 static const char * const color_names[] = {
11 "normal", "black", "red", "green", "yellow",
12 "blue", "magenta", "cyan", "white"
13 };
14 char *end;
15 int i;
16
17 for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) {
18 const char *str = color_names[i];
19 if (!strncasecmp(name, str, len) && !str[len])
20 return i - 1;
21 }
22 i = strtol(name, &end, 10);
23 if (end - name == len && i >= -1 && i <= 255)
24 return i;
25 return -2;
26}
27
28static int parse_attr(const char *name, int len)
29{
30 static const int attr_values[] = { 1, 2, 4, 5, 7 };
31 static const char * const attr_names[] = {
32 "bold", "dim", "ul", "blink", "reverse"
33 };
34 unsigned int i;
35
36 for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
37 const char *str = attr_names[i];
38 if (!strncasecmp(name, str, len) && !str[len])
39 return attr_values[i];
40 }
41 return -1;
42}
43
44void color_parse(const char *value, const char *var, char *dst)
45{
46 color_parse_mem(value, strlen(value), var, dst);
47}
48
49void color_parse_mem(const char *value, int value_len, const char *var,
50 char *dst)
51{
52 const char *ptr = value;
53 int len = value_len;
54 int attr = -1;
55 int fg = -2;
56 int bg = -2;
57
58 if (!strncasecmp(value, "reset", len)) {
59 strcpy(dst, PERF_COLOR_RESET);
60 return;
61 }
62
63 /* [fg [bg]] [attr] */
64 while (len > 0) {
65 const char *word = ptr;
66 int val, wordlen = 0;
67
68 while (len > 0 && !isspace(word[wordlen])) {
69 wordlen++;
70 len--;
71 }
72
73 ptr = word + wordlen;
74 while (len > 0 && isspace(*ptr)) {
75 ptr++;
76 len--;
77 }
78
79 val = parse_color(word, wordlen);
80 if (val >= -1) {
81 if (fg == -2) {
82 fg = val;
83 continue;
84 }
85 if (bg == -2) {
86 bg = val;
87 continue;
88 }
89 goto bad;
90 }
91 val = parse_attr(word, wordlen);
92 if (val < 0 || attr != -1)
93 goto bad;
94 attr = val;
95 }
96
97 if (attr >= 0 || fg >= 0 || bg >= 0) {
98 int sep = 0;
99
100 *dst++ = '\033';
101 *dst++ = '[';
102 if (attr >= 0) {
103 *dst++ = '0' + attr;
104 sep++;
105 }
106 if (fg >= 0) {
107 if (sep++)
108 *dst++ = ';';
109 if (fg < 8) {
110 *dst++ = '3';
111 *dst++ = '0' + fg;
112 } else {
113 dst += sprintf(dst, "38;5;%d", fg);
114 }
115 }
116 if (bg >= 0) {
117 if (sep++)
118 *dst++ = ';';
119 if (bg < 8) {
120 *dst++ = '4';
121 *dst++ = '0' + bg;
122 } else {
123 dst += sprintf(dst, "48;5;%d", bg);
124 }
125 }
126 *dst++ = 'm';
127 }
128 *dst = 0;
129 return;
130bad:
131 die("bad color value '%.*s' for variable '%s'", value_len, value, var);
132}
133
134int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty) 8int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty)
135{ 9{
136 if (value) { 10 if (value) {
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 0a594b8a0c26..38146f922c54 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -30,8 +30,6 @@ extern int perf_use_color_default;
30int perf_color_default_config(const char *var, const char *value, void *cb); 30int perf_color_default_config(const char *var, const char *value, void *cb);
31 31
32int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty); 32int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty);
33void color_parse(const char *value, const char *var, char *dst);
34void color_parse_mem(const char *value, int len, const char *var, char *dst);
35int color_vsnprintf(char *bf, size_t size, const char *color, 33int color_vsnprintf(char *bf, size_t size, const char *color,
36 const char *fmt, va_list args); 34 const char *fmt, va_list args);
37int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); 35int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args);
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 45be944d450a..c2f7d3b90966 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -532,12 +532,8 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
532 break; 532 break;
533 533
534 cache_offset = offset & DSO__DATA_CACHE_MASK; 534 cache_offset = offset & DSO__DATA_CACHE_MASK;
535 ret = -EINVAL;
536 535
537 if (-1 == lseek(dso->data.fd, cache_offset, SEEK_SET)) 536 ret = pread(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE, cache_offset);
538 break;
539
540 ret = read(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE);
541 if (ret <= 0) 537 if (ret <= 0)
542 break; 538 break;
543 539
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 3782c82c6e44..ced92841ff97 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -139,6 +139,7 @@ struct dso {
139 u32 status_seen; 139 u32 status_seen;
140 size_t file_size; 140 size_t file_size;
141 struct list_head open_entry; 141 struct list_head open_entry;
142 u64 frame_offset;
142 } data; 143 } data;
143 144
144 union { /* Tool specific area */ 145 union { /* Tool specific area */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index cbab1fb77b1d..28b8ce86bf12 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1436,33 +1436,6 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
1436 return printed + fprintf(fp, "\n"); 1436 return printed + fprintf(fp, "\n");
1437} 1437}
1438 1438
1439int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused,
1440 int err, char *buf, size_t size)
1441{
1442 char sbuf[128];
1443
1444 switch (err) {
1445 case ENOENT:
1446 scnprintf(buf, size, "%s",
1447 "Error:\tUnable to find debugfs\n"
1448 "Hint:\tWas your kernel was compiled with debugfs support?\n"
1449 "Hint:\tIs the debugfs filesystem mounted?\n"
1450 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
1451 break;
1452 case EACCES:
1453 scnprintf(buf, size,
1454 "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n"
1455 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
1456 debugfs_mountpoint, debugfs_mountpoint);
1457 break;
1458 default:
1459 scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
1460 break;
1461 }
1462
1463 return 0;
1464}
1465
1466int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, 1439int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1467 int err, char *buf, size_t size) 1440 int err, char *buf, size_t size)
1468{ 1441{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 0ba93f67ab94..c94a9e03ecf1 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -183,7 +183,6 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
183 183
184size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); 184size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
185 185
186int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size);
187int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); 186int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
188int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); 187int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
189 188
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1e90c8557ede..ea51a90e20a0 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -709,6 +709,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
709 if (opts->sample_weight) 709 if (opts->sample_weight)
710 perf_evsel__set_sample_bit(evsel, WEIGHT); 710 perf_evsel__set_sample_bit(evsel, WEIGHT);
711 711
712 attr->task = track;
712 attr->mmap = track; 713 attr->mmap = track;
713 attr->mmap2 = track && !perf_missing_features.mmap2; 714 attr->mmap2 = track && !perf_missing_features.mmap2;
714 attr->comm = track; 715 attr->comm = track;
@@ -797,6 +798,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
797 798
798int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 799int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
799{ 800{
801 if (ncpus == 0 || nthreads == 0)
802 return 0;
803
800 if (evsel->system_wide) 804 if (evsel->system_wide)
801 nthreads = 1; 805 nthreads = 1;
802 806
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index b20e40c74468..1f407f7352a7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2237,6 +2237,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2237 * - unique number to identify actual perf.data files 2237 * - unique number to identify actual perf.data files
2238 * - encode endianness of file 2238 * - encode endianness of file
2239 */ 2239 */
2240 ph->version = PERF_HEADER_VERSION_2;
2240 2241
2241 /* check magic number with one endianness */ 2242 /* check magic number with one endianness */
2242 if (magic == __perf_magic2) 2243 if (magic == __perf_magic2)
@@ -2247,7 +2248,6 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2247 return -1; 2248 return -1;
2248 2249
2249 ph->needs_swap = true; 2250 ph->needs_swap = true;
2250 ph->version = PERF_HEADER_VERSION_2;
2251 2251
2252 return 0; 2252 return 0;
2253} 2253}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 6e88b9e395df..70b48a65064c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -6,6 +6,7 @@
6#include "evlist.h" 6#include "evlist.h"
7#include "evsel.h" 7#include "evsel.h"
8#include "annotate.h" 8#include "annotate.h"
9#include "ui/progress.h"
9#include <math.h> 10#include <math.h>
10 11
11static bool hists__filter_entry_by_dso(struct hists *hists, 12static bool hists__filter_entry_by_dso(struct hists *hists,
@@ -240,6 +241,20 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
240 return he->stat.period == 0; 241 return he->stat.period == 0;
241} 242}
242 243
244static void hists__delete_entry(struct hists *hists, struct hist_entry *he)
245{
246 rb_erase(&he->rb_node, &hists->entries);
247
248 if (sort__need_collapse)
249 rb_erase(&he->rb_node_in, &hists->entries_collapsed);
250
251 --hists->nr_entries;
252 if (!he->filtered)
253 --hists->nr_non_filtered_entries;
254
255 hist_entry__delete(he);
256}
257
243void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel) 258void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
244{ 259{
245 struct rb_node *next = rb_first(&hists->entries); 260 struct rb_node *next = rb_first(&hists->entries);
@@ -257,16 +272,7 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
257 (zap_kernel && n->level != '.') || 272 (zap_kernel && n->level != '.') ||
258 hists__decay_entry(hists, n)) && 273 hists__decay_entry(hists, n)) &&
259 !n->used) { 274 !n->used) {
260 rb_erase(&n->rb_node, &hists->entries); 275 hists__delete_entry(hists, n);
261
262 if (sort__need_collapse)
263 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
264
265 --hists->nr_entries;
266 if (!n->filtered)
267 --hists->nr_non_filtered_entries;
268
269 hist_entry__free(n);
270 } 276 }
271 } 277 }
272} 278}
@@ -280,16 +286,7 @@ void hists__delete_entries(struct hists *hists)
280 n = rb_entry(next, struct hist_entry, rb_node); 286 n = rb_entry(next, struct hist_entry, rb_node);
281 next = rb_next(&n->rb_node); 287 next = rb_next(&n->rb_node);
282 288
283 rb_erase(&n->rb_node, &hists->entries); 289 hists__delete_entry(hists, n);
284
285 if (sort__need_collapse)
286 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
287
288 --hists->nr_entries;
289 if (!n->filtered)
290 --hists->nr_non_filtered_entries;
291
292 hist_entry__free(n);
293 } 290 }
294} 291}
295 292
@@ -303,7 +300,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
303 size_t callchain_size = 0; 300 size_t callchain_size = 0;
304 struct hist_entry *he; 301 struct hist_entry *he;
305 302
306 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) 303 if (symbol_conf.use_callchain)
307 callchain_size = sizeof(struct callchain_root); 304 callchain_size = sizeof(struct callchain_root);
308 305
309 he = zalloc(sizeof(*he) + callchain_size); 306 he = zalloc(sizeof(*he) + callchain_size);
@@ -432,6 +429,8 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
432 if (!he) 429 if (!he)
433 return NULL; 430 return NULL;
434 431
432 hists->nr_entries++;
433
435 rb_link_node(&he->rb_node_in, parent, p); 434 rb_link_node(&he->rb_node_in, parent, p);
436 rb_insert_color(&he->rb_node_in, hists->entries_in); 435 rb_insert_color(&he->rb_node_in, hists->entries_in);
437out: 436out:
@@ -736,7 +735,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
736 iter->he = he; 735 iter->he = he;
737 he_cache[iter->curr++] = he; 736 he_cache[iter->curr++] = he;
738 737
739 callchain_append(he->callchain, &callchain_cursor, sample->period); 738 hist_entry__append_callchain(he, sample);
740 739
741 /* 740 /*
742 * We need to re-initialize the cursor since callchain_append() 741 * We need to re-initialize the cursor since callchain_append()
@@ -809,7 +808,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
809 iter->he = he; 808 iter->he = he;
810 he_cache[iter->curr++] = he; 809 he_cache[iter->curr++] = he;
811 810
812 callchain_append(he->callchain, &cursor, sample->period); 811 if (symbol_conf.use_callchain)
812 callchain_append(he->callchain, &cursor, sample->period);
813 return 0; 813 return 0;
814} 814}
815 815
@@ -913,7 +913,7 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
913 if (perf_hpp__should_skip(fmt)) 913 if (perf_hpp__should_skip(fmt))
914 continue; 914 continue;
915 915
916 cmp = fmt->cmp(left, right); 916 cmp = fmt->cmp(fmt, left, right);
917 if (cmp) 917 if (cmp)
918 break; 918 break;
919 } 919 }
@@ -931,7 +931,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
931 if (perf_hpp__should_skip(fmt)) 931 if (perf_hpp__should_skip(fmt))
932 continue; 932 continue;
933 933
934 cmp = fmt->collapse(left, right); 934 cmp = fmt->collapse(fmt, left, right);
935 if (cmp) 935 if (cmp)
936 break; 936 break;
937 } 937 }
@@ -939,12 +939,13 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
939 return cmp; 939 return cmp;
940} 940}
941 941
942void hist_entry__free(struct hist_entry *he) 942void hist_entry__delete(struct hist_entry *he)
943{ 943{
944 zfree(&he->branch_info); 944 zfree(&he->branch_info);
945 zfree(&he->mem_info); 945 zfree(&he->mem_info);
946 zfree(&he->stat_acc); 946 zfree(&he->stat_acc);
947 free_srcline(he->srcline); 947 free_srcline(he->srcline);
948 free_callchain(he->callchain);
948 free(he); 949 free(he);
949} 950}
950 951
@@ -978,7 +979,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
978 iter->callchain, 979 iter->callchain,
979 he->callchain); 980 he->callchain);
980 } 981 }
981 hist_entry__free(he); 982 hist_entry__delete(he);
982 return false; 983 return false;
983 } 984 }
984 985
@@ -987,6 +988,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
987 else 988 else
988 p = &(*p)->rb_right; 989 p = &(*p)->rb_right;
989 } 990 }
991 hists->nr_entries++;
990 992
991 rb_link_node(&he->rb_node_in, parent, p); 993 rb_link_node(&he->rb_node_in, parent, p);
992 rb_insert_color(&he->rb_node_in, root); 994 rb_insert_color(&he->rb_node_in, root);
@@ -1024,7 +1026,10 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
1024 if (!sort__need_collapse) 1026 if (!sort__need_collapse)
1025 return; 1027 return;
1026 1028
1029 hists->nr_entries = 0;
1030
1027 root = hists__get_rotate_entries_in(hists); 1031 root = hists__get_rotate_entries_in(hists);
1032
1028 next = rb_first(root); 1033 next = rb_first(root);
1029 1034
1030 while (next) { 1035 while (next) {
@@ -1056,7 +1061,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
1056 if (perf_hpp__should_skip(fmt)) 1061 if (perf_hpp__should_skip(fmt))
1057 continue; 1062 continue;
1058 1063
1059 cmp = fmt->sort(a, b); 1064 cmp = fmt->sort(fmt, a, b);
1060 if (cmp) 1065 if (cmp)
1061 break; 1066 break;
1062 } 1067 }
@@ -1119,7 +1124,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
1119 rb_insert_color(&he->rb_node, entries); 1124 rb_insert_color(&he->rb_node, entries);
1120} 1125}
1121 1126
1122void hists__output_resort(struct hists *hists) 1127void hists__output_resort(struct hists *hists, struct ui_progress *prog)
1123{ 1128{
1124 struct rb_root *root; 1129 struct rb_root *root;
1125 struct rb_node *next; 1130 struct rb_node *next;
@@ -1148,6 +1153,9 @@ void hists__output_resort(struct hists *hists)
1148 1153
1149 if (!n->filtered) 1154 if (!n->filtered)
1150 hists__calc_col_len(hists, n); 1155 hists__calc_col_len(hists, n);
1156
1157 if (prog)
1158 ui_progress__update(prog, 1);
1151 } 1159 }
1152} 1160}
1153 1161
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index d0ef9a19a744..2b690d028907 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -119,9 +119,9 @@ int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
119int hist_entry__transaction_len(void); 119int hist_entry__transaction_len(void);
120int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, 120int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
121 struct hists *hists); 121 struct hists *hists);
122void hist_entry__free(struct hist_entry *); 122void hist_entry__delete(struct hist_entry *he);
123 123
124void hists__output_resort(struct hists *hists); 124void hists__output_resort(struct hists *hists, struct ui_progress *prog);
125void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 125void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
126 126
127void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 127void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
@@ -195,9 +195,12 @@ struct perf_hpp_fmt {
195 struct hist_entry *he); 195 struct hist_entry *he);
196 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 196 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
197 struct hist_entry *he); 197 struct hist_entry *he);
198 int64_t (*cmp)(struct hist_entry *a, struct hist_entry *b); 198 int64_t (*cmp)(struct perf_hpp_fmt *fmt,
199 int64_t (*collapse)(struct hist_entry *a, struct hist_entry *b); 199 struct hist_entry *a, struct hist_entry *b);
200 int64_t (*sort)(struct hist_entry *a, struct hist_entry *b); 200 int64_t (*collapse)(struct perf_hpp_fmt *fmt,
201 struct hist_entry *a, struct hist_entry *b);
202 int64_t (*sort)(struct perf_hpp_fmt *fmt,
203 struct hist_entry *a, struct hist_entry *b);
201 204
202 struct list_head list; 205 struct list_head list;
203 struct list_head sort_list; 206 struct list_head sort_list;
diff --git a/tools/perf/util/hweight.c b/tools/perf/util/hweight.c
deleted file mode 100644
index 5c1d0d099f0d..000000000000
--- a/tools/perf/util/hweight.c
+++ /dev/null
@@ -1,31 +0,0 @@
1#include <linux/bitops.h>
2
3/**
4 * hweightN - returns the hamming weight of a N-bit word
5 * @x: the word to weigh
6 *
7 * The Hamming Weight of a number is the total number of bits set in it.
8 */
9
10unsigned int hweight32(unsigned int w)
11{
12 unsigned int res = w - ((w >> 1) & 0x55555555);
13 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
14 res = (res + (res >> 4)) & 0x0F0F0F0F;
15 res = res + (res >> 8);
16 return (res + (res >> 16)) & 0x000000FF;
17}
18
19unsigned long hweight64(__u64 w)
20{
21#if BITS_PER_LONG == 32
22 return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
23#elif BITS_PER_LONG == 64
24 __u64 res = w - ((w >> 1) & 0x5555555555555555ul);
25 res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
26 res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
27 res = res + (res >> 8);
28 res = res + (res >> 16);
29 return (res + (res >> 32)) & 0x00000000000000FFul;
30#endif
31}
diff --git a/tools/perf/util/include/asm/hweight.h b/tools/perf/util/include/asm/hweight.h
deleted file mode 100644
index 36cf26d434a5..000000000000
--- a/tools/perf/util/include/asm/hweight.h
+++ /dev/null
@@ -1,8 +0,0 @@
1#ifndef PERF_HWEIGHT_H
2#define PERF_HWEIGHT_H
3
4#include <linux/types.h>
5unsigned int hweight32(unsigned int w);
6unsigned long hweight64(__u64 w);
7
8#endif /* PERF_HWEIGHT_H */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 94de3e48b490..1bca3a9f2b16 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -389,7 +389,6 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
389 if (th != NULL) { 389 if (th != NULL) {
390 rb_link_node(&th->rb_node, parent, p); 390 rb_link_node(&th->rb_node, parent, p);
391 rb_insert_color(&th->rb_node, &machine->threads); 391 rb_insert_color(&th->rb_node, &machine->threads);
392 machine->last_match = th;
393 392
394 /* 393 /*
395 * We have to initialize map_groups separately 394 * We have to initialize map_groups separately
@@ -400,9 +399,12 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
400 * leader and that would screwed the rb tree. 399 * leader and that would screwed the rb tree.
401 */ 400 */
402 if (thread__init_map_groups(th, machine)) { 401 if (thread__init_map_groups(th, machine)) {
402 rb_erase(&th->rb_node, &machine->threads);
403 thread__delete(th); 403 thread__delete(th);
404 return NULL; 404 return NULL;
405 } 405 }
406
407 machine->last_match = th;
406 } 408 }
407 409
408 return th; 410 return th;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 6951a9d42339..0e42438b1e59 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -116,6 +116,22 @@ struct thread;
116#define map__for_each_symbol(map, pos, n) \ 116#define map__for_each_symbol(map, pos, n) \
117 dso__for_each_symbol(map->dso, pos, n, map->type) 117 dso__for_each_symbol(map->dso, pos, n, map->type)
118 118
119/* map__for_each_symbol_with_name - iterate over the symbols in the given map
120 * that have the given name
121 *
122 * @map: the 'struct map *' in which symbols itereated
123 * @sym_name: the symbol name
124 * @pos: the 'struct symbol *' to use as a loop cursor
125 * @filter: to use when loading the DSO
126 */
127#define __map__for_each_symbol_by_name(map, sym_name, pos, filter) \
128 for (pos = map__find_symbol_by_name(map, sym_name, filter); \
129 pos && strcmp(pos->name, sym_name) == 0; \
130 pos = symbol__next_by_name(pos))
131
132#define map__for_each_symbol_by_name(map, sym_name, pos) \
133 __map__for_each_symbol_by_name(map, sym_name, (pos), NULL)
134
119typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); 135typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
120 136
121void map__init(struct map *map, enum map_type type, 137void map__init(struct map *map, enum map_type type,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 77b43fe43d55..7f8ec6ce2823 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -526,7 +526,7 @@ do { \
526} 526}
527 527
528int parse_events_add_breakpoint(struct list_head *list, int *idx, 528int parse_events_add_breakpoint(struct list_head *list, int *idx,
529 void *ptr, char *type) 529 void *ptr, char *type, u64 len)
530{ 530{
531 struct perf_event_attr attr; 531 struct perf_event_attr attr;
532 532
@@ -536,14 +536,15 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
536 if (parse_breakpoint_type(type, &attr)) 536 if (parse_breakpoint_type(type, &attr))
537 return -EINVAL; 537 return -EINVAL;
538 538
539 /* 539 /* Provide some defaults if len is not specified */
540 * We should find a nice way to override the access length 540 if (!len) {
541 * Provide some defaults for now 541 if (attr.bp_type == HW_BREAKPOINT_X)
542 */ 542 len = sizeof(long);
543 if (attr.bp_type == HW_BREAKPOINT_X) 543 else
544 attr.bp_len = sizeof(long); 544 len = HW_BREAKPOINT_LEN_4;
545 else 545 }
546 attr.bp_len = HW_BREAKPOINT_LEN_4; 546
547 attr.bp_len = len;
547 548
548 attr.type = PERF_TYPE_BREAKPOINT; 549 attr.type = PERF_TYPE_BREAKPOINT;
549 attr.sample_period = 1; 550 attr.sample_period = 1;
@@ -1121,7 +1122,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1121 return; 1122 return;
1122 1123
1123 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1124 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
1124 if (subsys_glob != NULL && 1125 if (subsys_glob != NULL &&
1125 !strglobmatch(sys_dirent.d_name, subsys_glob)) 1126 !strglobmatch(sys_dirent.d_name, subsys_glob))
1126 continue; 1127 continue;
1127 1128
@@ -1132,7 +1133,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1132 continue; 1133 continue;
1133 1134
1134 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 1135 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
1135 if (event_glob != NULL && 1136 if (event_glob != NULL &&
1136 !strglobmatch(evt_dirent.d_name, event_glob)) 1137 !strglobmatch(evt_dirent.d_name, event_glob))
1137 continue; 1138 continue;
1138 1139
@@ -1305,7 +1306,7 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1305 1306
1306 for (i = 0; i < max; i++, syms++) { 1307 for (i = 0; i < max; i++, syms++) {
1307 1308
1308 if (event_glob != NULL && 1309 if (event_glob != NULL &&
1309 !(strglobmatch(syms->symbol, event_glob) || 1310 !(strglobmatch(syms->symbol, event_glob) ||
1310 (syms->alias && strglobmatch(syms->alias, event_glob)))) 1311 (syms->alias && strglobmatch(syms->alias, event_glob))))
1311 continue; 1312 continue;
@@ -1366,7 +1367,7 @@ void print_events(const char *event_glob, bool name_only)
1366 printf("\n"); 1367 printf("\n");
1367 1368
1368 printf(" %-50s [%s]\n", 1369 printf(" %-50s [%s]\n",
1369 "mem:<addr>[:access]", 1370 "mem:<addr>[/len][:access]",
1370 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1371 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
1371 printf("\n"); 1372 printf("\n");
1372 } 1373 }
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index db2cf78ff0f3..ff6e1fa4111e 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,6 +71,7 @@ struct parse_events_term {
71 int type_val; 71 int type_val;
72 int type_term; 72 int type_term;
73 struct list_head list; 73 struct list_head list;
74 bool used;
74}; 75};
75 76
76struct parse_events_evlist { 77struct parse_events_evlist {
@@ -104,7 +105,7 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
104int parse_events_add_cache(struct list_head *list, int *idx, 105int parse_events_add_cache(struct list_head *list, int *idx,
105 char *type, char *op_result1, char *op_result2); 106 char *type, char *op_result1, char *op_result2);
106int parse_events_add_breakpoint(struct list_head *list, int *idx, 107int parse_events_add_breakpoint(struct list_head *list, int *idx,
107 void *ptr, char *type); 108 void *ptr, char *type, u64 len);
108int parse_events_add_pmu(struct list_head *list, int *idx, 109int parse_events_add_pmu(struct list_head *list, int *idx,
109 char *pmu , struct list_head *head_config); 110 char *pmu , struct list_head *head_config);
110enum perf_pmu_event_symbol_type 111enum perf_pmu_event_symbol_type
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 906630bbf8eb..94eacb6c1ef7 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -159,6 +159,7 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
159<mem>{ 159<mem>{
160{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } 160{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
161: { return ':'; } 161: { return ':'; }
162"/" { return '/'; }
162{num_dec} { return value(yyscanner, 10); } 163{num_dec} { return value(yyscanner, 10); }
163{num_hex} { return value(yyscanner, 16); } 164{num_hex} { return value(yyscanner, 16); }
164 /* 165 /*
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 93c4c9fbc922..72def077dbbf 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -326,6 +326,28 @@ PE_NAME_CACHE_TYPE
326} 326}
327 327
328event_legacy_mem: 328event_legacy_mem:
329PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
330{
331 struct parse_events_evlist *data = _data;
332 struct list_head *list;
333
334 ALLOC_LIST(list);
335 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
336 (void *) $2, $6, $4));
337 $$ = list;
338}
339|
340PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
341{
342 struct parse_events_evlist *data = _data;
343 struct list_head *list;
344
345 ALLOC_LIST(list);
346 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
347 (void *) $2, NULL, $4));
348 $$ = list;
349}
350|
329PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 351PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
330{ 352{
331 struct parse_events_evlist *data = _data; 353 struct parse_events_evlist *data = _data;
@@ -333,7 +355,7 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
333 355
334 ALLOC_LIST(list); 356 ALLOC_LIST(list);
335 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 357 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
336 (void *) $2, $4)); 358 (void *) $2, $4, 0));
337 $$ = list; 359 $$ = list;
338} 360}
339| 361|
@@ -344,7 +366,7 @@ PE_PREFIX_MEM PE_VALUE sep_dc
344 366
345 ALLOC_LIST(list); 367 ALLOC_LIST(list);
346 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 368 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
347 (void *) $2, NULL)); 369 (void *) $2, NULL, 0));
348 $$ = list; 370 $$ = list;
349} 371}
350 372
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index f62dee7bd924..4a015f77e2b5 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -46,7 +46,7 @@ static int get_value(struct parse_opt_ctx_t *p,
46 return opterror(opt, "is not usable", flags); 46 return opterror(opt, "is not usable", flags);
47 47
48 if (opt->flags & PARSE_OPT_EXCLUSIVE) { 48 if (opt->flags & PARSE_OPT_EXCLUSIVE) {
49 if (p->excl_opt) { 49 if (p->excl_opt && p->excl_opt != opt) {
50 char msg[128]; 50 char msg[128];
51 51
52 if (((flags & OPT_SHORT) && p->excl_opt->short_name) || 52 if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 5c9c4947cfb4..48411674da0f 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -551,31 +551,68 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
551} 551}
552 552
553/* 553/*
554 * Term is a string term, and might be a param-term. Try to look up it's value
555 * in the remaining terms.
556 * - We have a term like "base-or-format-term=param-term",
557 * - We need to find the value supplied for "param-term" (with param-term named
558 * in a config string) later on in the term list.
559 */
560static int pmu_resolve_param_term(struct parse_events_term *term,
561 struct list_head *head_terms,
562 __u64 *value)
563{
564 struct parse_events_term *t;
565
566 list_for_each_entry(t, head_terms, list) {
567 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
568 if (!strcmp(t->config, term->config)) {
569 t->used = true;
570 *value = t->val.num;
571 return 0;
572 }
573 }
574 }
575
576 if (verbose)
577 printf("Required parameter '%s' not specified\n", term->config);
578
579 return -1;
580}
581
582/*
554 * Setup one of config[12] attr members based on the 583 * Setup one of config[12] attr members based on the
555 * user input data - term parameter. 584 * user input data - term parameter.
556 */ 585 */
557static int pmu_config_term(struct list_head *formats, 586static int pmu_config_term(struct list_head *formats,
558 struct perf_event_attr *attr, 587 struct perf_event_attr *attr,
559 struct parse_events_term *term, 588 struct parse_events_term *term,
589 struct list_head *head_terms,
560 bool zero) 590 bool zero)
561{ 591{
562 struct perf_pmu_format *format; 592 struct perf_pmu_format *format;
563 __u64 *vp; 593 __u64 *vp;
594 __u64 val;
595
596 /*
597 * If this is a parameter we've already used for parameterized-eval,
598 * skip it in normal eval.
599 */
600 if (term->used)
601 return 0;
564 602
565 /* 603 /*
566 * Support only for hardcoded and numnerial terms.
567 * Hardcoded terms should be already in, so nothing 604 * Hardcoded terms should be already in, so nothing
568 * to be done for them. 605 * to be done for them.
569 */ 606 */
570 if (parse_events__is_hardcoded_term(term)) 607 if (parse_events__is_hardcoded_term(term))
571 return 0; 608 return 0;
572 609
573 if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
574 return -EINVAL;
575
576 format = pmu_find_format(formats, term->config); 610 format = pmu_find_format(formats, term->config);
577 if (!format) 611 if (!format) {
612 if (verbose)
613 printf("Invalid event/parameter '%s'\n", term->config);
578 return -EINVAL; 614 return -EINVAL;
615 }
579 616
580 switch (format->value) { 617 switch (format->value) {
581 case PERF_PMU_FORMAT_VALUE_CONFIG: 618 case PERF_PMU_FORMAT_VALUE_CONFIG:
@@ -592,11 +629,25 @@ static int pmu_config_term(struct list_head *formats,
592 } 629 }
593 630
594 /* 631 /*
595 * XXX If we ever decide to go with string values for 632 * Either directly use a numeric term, or try to translate string terms
596 * non-hardcoded terms, here's the place to translate 633 * using event parameters.
597 * them into value.
598 */ 634 */
599 pmu_format_value(format->bits, term->val.num, vp, zero); 635 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
636 val = term->val.num;
637 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
638 if (strcmp(term->val.str, "?")) {
639 if (verbose)
640 pr_info("Invalid sysfs entry %s=%s\n",
641 term->config, term->val.str);
642 return -EINVAL;
643 }
644
645 if (pmu_resolve_param_term(term, head_terms, &val))
646 return -EINVAL;
647 } else
648 return -EINVAL;
649
650 pmu_format_value(format->bits, val, vp, zero);
600 return 0; 651 return 0;
601} 652}
602 653
@@ -607,9 +658,10 @@ int perf_pmu__config_terms(struct list_head *formats,
607{ 658{
608 struct parse_events_term *term; 659 struct parse_events_term *term;
609 660
610 list_for_each_entry(term, head_terms, list) 661 list_for_each_entry(term, head_terms, list) {
611 if (pmu_config_term(formats, attr, term, zero)) 662 if (pmu_config_term(formats, attr, term, head_terms, zero))
612 return -EINVAL; 663 return -EINVAL;
664 }
613 665
614 return 0; 666 return 0;
615} 667}
@@ -767,10 +819,36 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)
767 set_bit(b, bits); 819 set_bit(b, bits);
768} 820}
769 821
822static int sub_non_neg(int a, int b)
823{
824 if (b > a)
825 return 0;
826 return a - b;
827}
828
770static char *format_alias(char *buf, int len, struct perf_pmu *pmu, 829static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
771 struct perf_pmu_alias *alias) 830 struct perf_pmu_alias *alias)
772{ 831{
773 snprintf(buf, len, "%s/%s/", pmu->name, alias->name); 832 struct parse_events_term *term;
833 int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
834
835 list_for_each_entry(term, &alias->terms, list) {
836 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
837 used += snprintf(buf + used, sub_non_neg(len, used),
838 ",%s=%s", term->config,
839 term->val.str);
840 }
841
842 if (sub_non_neg(len, used) > 0) {
843 buf[used] = '/';
844 used++;
845 }
846 if (sub_non_neg(len, used) > 0) {
847 buf[used] = '\0';
848 used++;
849 } else
850 buf[len - 1] = '\0';
851
774 return buf; 852 return buf;
775} 853}
776 854
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 28eb1417cb2a..919937eb0be2 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -446,7 +446,7 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
446 } 446 }
447 447
448 for (i = 0; i < ntevs; i++) { 448 for (i = 0; i < ntevs; i++) {
449 if (tevs[i].point.address) { 449 if (tevs[i].point.address && !tevs[i].point.retprobe) {
450 tmp = strdup(reloc_sym->name); 450 tmp = strdup(reloc_sym->name);
451 if (!tmp) 451 if (!tmp)
452 return -ENOMEM; 452 return -ENOMEM;
@@ -495,9 +495,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
495 } 495 }
496 496
497 if (ntevs == 0) { /* No error but failed to find probe point. */ 497 if (ntevs == 0) { /* No error but failed to find probe point. */
498 pr_warning("Probe point '%s' not found.\n", 498 pr_warning("Probe point '%s' not found in debuginfo.\n",
499 synthesize_perf_probe_point(&pev->point)); 499 synthesize_perf_probe_point(&pev->point));
500 return -ENOENT; 500 if (need_dwarf)
501 return -ENOENT;
502 return 0;
501 } 503 }
502 /* Error path : ntevs < 0 */ 504 /* Error path : ntevs < 0 */
503 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 505 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
@@ -2050,9 +2052,11 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2050 pr_debug("Writing event: %s\n", buf); 2052 pr_debug("Writing event: %s\n", buf);
2051 if (!probe_event_dry_run) { 2053 if (!probe_event_dry_run) {
2052 ret = write(fd, buf, strlen(buf)); 2054 ret = write(fd, buf, strlen(buf));
2053 if (ret <= 0) 2055 if (ret <= 0) {
2056 ret = -errno;
2054 pr_warning("Failed to write event: %s\n", 2057 pr_warning("Failed to write event: %s\n",
2055 strerror_r(errno, sbuf, sizeof(sbuf))); 2058 strerror_r(errno, sbuf, sizeof(sbuf)));
2059 }
2056 } 2060 }
2057 free(buf); 2061 free(buf);
2058 return ret; 2062 return ret;
@@ -2189,18 +2193,17 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2189 return ret; 2193 return ret;
2190} 2194}
2191 2195
2192static char *looking_function_name; 2196static int find_probe_functions(struct map *map, char *name)
2193static int num_matched_functions;
2194
2195static int probe_function_filter(struct map *map __maybe_unused,
2196 struct symbol *sym)
2197{ 2197{
2198 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && 2198 int found = 0;
2199 strcmp(looking_function_name, sym->name) == 0) { 2199 struct symbol *sym;
2200 num_matched_functions++; 2200
2201 return 0; 2201 map__for_each_symbol_by_name(map, name, sym) {
2202 if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL)
2203 found++;
2202 } 2204 }
2203 return 1; 2205
2206 return found;
2204} 2207}
2205 2208
2206#define strdup_or_goto(str, label) \ 2209#define strdup_or_goto(str, label) \
@@ -2218,10 +2221,10 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2218 struct kmap *kmap = NULL; 2221 struct kmap *kmap = NULL;
2219 struct ref_reloc_sym *reloc_sym = NULL; 2222 struct ref_reloc_sym *reloc_sym = NULL;
2220 struct symbol *sym; 2223 struct symbol *sym;
2221 struct rb_node *nd;
2222 struct probe_trace_event *tev; 2224 struct probe_trace_event *tev;
2223 struct perf_probe_point *pp = &pev->point; 2225 struct perf_probe_point *pp = &pev->point;
2224 struct probe_trace_point *tp; 2226 struct probe_trace_point *tp;
2227 int num_matched_functions;
2225 int ret, i; 2228 int ret, i;
2226 2229
2227 /* Init maps of given executable or kernel */ 2230 /* Init maps of given executable or kernel */
@@ -2238,10 +2241,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2238 * Load matched symbols: Since the different local symbols may have 2241 * Load matched symbols: Since the different local symbols may have
2239 * same name but different addresses, this lists all the symbols. 2242 * same name but different addresses, this lists all the symbols.
2240 */ 2243 */
2241 num_matched_functions = 0; 2244 num_matched_functions = find_probe_functions(map, pp->function);
2242 looking_function_name = pp->function; 2245 if (num_matched_functions == 0) {
2243 ret = map__load(map, probe_function_filter);
2244 if (ret || num_matched_functions == 0) {
2245 pr_err("Failed to find symbol %s in %s\n", pp->function, 2246 pr_err("Failed to find symbol %s in %s\n", pp->function,
2246 target ? : "kernel"); 2247 target ? : "kernel");
2247 ret = -ENOENT; 2248 ret = -ENOENT;
@@ -2253,7 +2254,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2253 goto out; 2254 goto out;
2254 } 2255 }
2255 2256
2256 if (!pev->uprobes) { 2257 if (!pev->uprobes && !pp->retprobe) {
2257 kmap = map__kmap(map); 2258 kmap = map__kmap(map);
2258 reloc_sym = kmap->ref_reloc_sym; 2259 reloc_sym = kmap->ref_reloc_sym;
2259 if (!reloc_sym) { 2260 if (!reloc_sym) {
@@ -2271,7 +2272,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2271 } 2272 }
2272 2273
2273 ret = 0; 2274 ret = 0;
2274 map__for_each_symbol(map, sym, nd) { 2275
2276 map__for_each_symbol_by_name(map, pp->function, sym) {
2275 tev = (*tevs) + ret; 2277 tev = (*tevs) + ret;
2276 tp = &tev->point; 2278 tp = &tev->point;
2277 if (ret == num_matched_functions) { 2279 if (ret == num_matched_functions) {
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index c7918f83b300..b5247d777f0e 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -989,8 +989,24 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
989 int ret = 0; 989 int ret = 0;
990 990
991#if _ELFUTILS_PREREQ(0, 142) 991#if _ELFUTILS_PREREQ(0, 142)
992 Elf *elf;
993 GElf_Ehdr ehdr;
994 GElf_Shdr shdr;
995
992 /* Get the call frame information from this dwarf */ 996 /* Get the call frame information from this dwarf */
993 pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg)); 997 elf = dwarf_getelf(dbg->dbg);
998 if (elf == NULL)
999 return -EINVAL;
1000
1001 if (gelf_getehdr(elf, &ehdr) == NULL)
1002 return -EINVAL;
1003
1004 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1005 shdr.sh_type == SHT_PROGBITS) {
1006 pf->cfi = dwarf_getcfi_elf(elf);
1007 } else {
1008 pf->cfi = dwarf_getcfi(dbg->dbg);
1009 }
994#endif 1010#endif
995 1011
996 off = 0; 1012 off = 0;
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 16a475a7d492..6c6a6953fa93 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,7 +10,7 @@ util/ctype.c
10util/evlist.c 10util/evlist.c
11util/evsel.c 11util/evsel.c
12util/cpumap.c 12util/cpumap.c
13util/hweight.c 13../../lib/hweight.c
14util/thread_map.c 14util/thread_map.c
15util/util.c 15util/util.c
16util/xyarray.c 16util/xyarray.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 3dda85ca50c1..d906d0ad5d40 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -768,7 +768,7 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
768 Py_DECREF(file); 768 Py_DECREF(file);
769 goto free_list; 769 goto free_list;
770 } 770 }
771 771
772 Py_DECREF(file); 772 Py_DECREF(file);
773 } 773 }
774 774
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index d808a328f4dc..0c815a40a6e8 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -89,7 +89,7 @@ static void handler_call_die(const char *handler_name)
89 89
90/* 90/*
91 * Insert val into into the dictionary and decrement the reference counter. 91 * Insert val into into the dictionary and decrement the reference counter.
92 * This is necessary for dictionaries since PyDict_SetItemString() does not 92 * This is necessary for dictionaries since PyDict_SetItemString() does not
93 * steal a reference, as opposed to PyTuple_SetItem(). 93 * steal a reference, as opposed to PyTuple_SetItem().
94 */ 94 */
95static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val) 95static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5f0e05a76c05..0baf75f12b7c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -274,7 +274,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
274 if (tool->id_index == NULL) 274 if (tool->id_index == NULL)
275 tool->id_index = process_id_index_stub; 275 tool->id_index = process_id_index_stub;
276} 276}
277 277
278static void swap_sample_id_all(union perf_event *event, void *data) 278static void swap_sample_id_all(union perf_event *event, void *data)
279{ 279{
280 void *end = (void *) event + event->header.size; 280 void *end = (void *) event + event->header.size;
@@ -1251,9 +1251,9 @@ fetch_mmaped_event(struct perf_session *session,
1251#define NUM_MMAPS 128 1251#define NUM_MMAPS 128
1252#endif 1252#endif
1253 1253
1254int __perf_session__process_events(struct perf_session *session, 1254static int __perf_session__process_events(struct perf_session *session,
1255 u64 data_offset, u64 data_size, 1255 u64 data_offset, u64 data_size,
1256 u64 file_size, struct perf_tool *tool) 1256 u64 file_size, struct perf_tool *tool)
1257{ 1257{
1258 int fd = perf_data_file__fd(session->file); 1258 int fd = perf_data_file__fd(session->file);
1259 u64 head, page_offset, file_offset, file_pos, size; 1259 u64 head, page_offset, file_offset, file_pos, size;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index dc26ebf60fe4..6d663dc76404 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -49,9 +49,6 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
49 union perf_event **event_ptr, 49 union perf_event **event_ptr,
50 struct perf_sample *sample); 50 struct perf_sample *sample);
51 51
52int __perf_session__process_events(struct perf_session *session,
53 u64 data_offset, u64 data_size, u64 size,
54 struct perf_tool *tool);
55int perf_session__process_events(struct perf_session *session, 52int perf_session__process_events(struct perf_session *session,
56 struct perf_tool *tool); 53 struct perf_tool *tool);
57 54
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 9139dda9f9a3..7a39c1ed8d37 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1304,6 +1304,37 @@ static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1304 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); 1304 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1305} 1305}
1306 1306
1307static int64_t __sort__hpp_cmp(struct perf_hpp_fmt *fmt,
1308 struct hist_entry *a, struct hist_entry *b)
1309{
1310 struct hpp_sort_entry *hse;
1311
1312 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1313 return hse->se->se_cmp(a, b);
1314}
1315
1316static int64_t __sort__hpp_collapse(struct perf_hpp_fmt *fmt,
1317 struct hist_entry *a, struct hist_entry *b)
1318{
1319 struct hpp_sort_entry *hse;
1320 int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
1321
1322 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1323 collapse_fn = hse->se->se_collapse ?: hse->se->se_cmp;
1324 return collapse_fn(a, b);
1325}
1326
1327static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt,
1328 struct hist_entry *a, struct hist_entry *b)
1329{
1330 struct hpp_sort_entry *hse;
1331 int64_t (*sort_fn)(struct hist_entry *, struct hist_entry *);
1332
1333 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1334 sort_fn = hse->se->se_sort ?: hse->se->se_cmp;
1335 return sort_fn(a, b);
1336}
1337
1307static struct hpp_sort_entry * 1338static struct hpp_sort_entry *
1308__sort_dimension__alloc_hpp(struct sort_dimension *sd) 1339__sort_dimension__alloc_hpp(struct sort_dimension *sd)
1309{ 1340{
@@ -1322,9 +1353,9 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1322 hse->hpp.entry = __sort__hpp_entry; 1353 hse->hpp.entry = __sort__hpp_entry;
1323 hse->hpp.color = NULL; 1354 hse->hpp.color = NULL;
1324 1355
1325 hse->hpp.cmp = sd->entry->se_cmp; 1356 hse->hpp.cmp = __sort__hpp_cmp;
1326 hse->hpp.collapse = sd->entry->se_collapse ? : sd->entry->se_cmp; 1357 hse->hpp.collapse = __sort__hpp_collapse;
1327 hse->hpp.sort = sd->entry->se_sort ? : hse->hpp.collapse; 1358 hse->hpp.sort = __sort__hpp_sort;
1328 1359
1329 INIT_LIST_HEAD(&hse->hpp.list); 1360 INIT_LIST_HEAD(&hse->hpp.list);
1330 INIT_LIST_HEAD(&hse->hpp.sort_list); 1361 INIT_LIST_HEAD(&hse->hpp.sort_list);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 06fcd1bf98b6..b24f9d8727a8 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -574,13 +574,16 @@ static int decompress_kmodule(struct dso *dso, const char *name,
574 const char *ext = strrchr(name, '.'); 574 const char *ext = strrchr(name, '.');
575 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; 575 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
576 576
577 if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && 577 if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
578 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) || 578 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP &&
579 type != dso->symtab_type) 579 type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
580 return -1; 580 return -1;
581 581
582 if (!ext || !is_supported_compression(ext + 1)) 582 if (!ext || !is_supported_compression(ext + 1)) {
583 return -1; 583 ext = strrchr(dso->name, '.');
584 if (!ext || !is_supported_compression(ext + 1))
585 return -1;
586 }
584 587
585 fd = mkstemp(tmpbuf); 588 fd = mkstemp(tmpbuf);
586 if (fd < 0) 589 if (fd < 0)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c24c5b83156c..a69066865a55 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -396,6 +396,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
396 const char *name) 396 const char *name)
397{ 397{
398 struct rb_node *n; 398 struct rb_node *n;
399 struct symbol_name_rb_node *s;
399 400
400 if (symbols == NULL) 401 if (symbols == NULL)
401 return NULL; 402 return NULL;
@@ -403,7 +404,6 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
403 n = symbols->rb_node; 404 n = symbols->rb_node;
404 405
405 while (n) { 406 while (n) {
406 struct symbol_name_rb_node *s;
407 int cmp; 407 int cmp;
408 408
409 s = rb_entry(n, struct symbol_name_rb_node, rb_node); 409 s = rb_entry(n, struct symbol_name_rb_node, rb_node);
@@ -414,10 +414,24 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
414 else if (cmp > 0) 414 else if (cmp > 0)
415 n = n->rb_right; 415 n = n->rb_right;
416 else 416 else
417 return &s->sym; 417 break;
418 } 418 }
419 419
420 return NULL; 420 if (n == NULL)
421 return NULL;
422
423 /* return first symbol that has same name (if any) */
424 for (n = rb_prev(n); n; n = rb_prev(n)) {
425 struct symbol_name_rb_node *tmp;
426
427 tmp = rb_entry(n, struct symbol_name_rb_node, rb_node);
428 if (strcmp(tmp->sym.name, s->sym.name))
429 break;
430
431 s = tmp;
432 }
433
434 return &s->sym;
421} 435}
422 436
423struct symbol *dso__find_symbol(struct dso *dso, 437struct symbol *dso__find_symbol(struct dso *dso,
@@ -436,6 +450,17 @@ struct symbol *dso__next_symbol(struct symbol *sym)
436 return symbols__next(sym); 450 return symbols__next(sym);
437} 451}
438 452
453struct symbol *symbol__next_by_name(struct symbol *sym)
454{
455 struct symbol_name_rb_node *s = container_of(sym, struct symbol_name_rb_node, sym);
456 struct rb_node *n = rb_next(&s->rb_node);
457
458 return n ? &rb_entry(n, struct symbol_name_rb_node, rb_node)->sym : NULL;
459}
460
461 /*
462 * Teturns first symbol that matched with @name.
463 */
439struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 464struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
440 const char *name) 465 const char *name)
441{ 466{
@@ -660,7 +685,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
660 struct machine *machine = kmaps->machine; 685 struct machine *machine = kmaps->machine;
661 struct map *curr_map = map; 686 struct map *curr_map = map;
662 struct symbol *pos; 687 struct symbol *pos;
663 int count = 0, moved = 0; 688 int count = 0, moved = 0;
664 struct rb_root *root = &dso->symbols[map->type]; 689 struct rb_root *root = &dso->symbols[map->type];
665 struct rb_node *next = rb_first(root); 690 struct rb_node *next = rb_first(root);
666 int kernel_range = 0; 691 int kernel_range = 0;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 9d602e9c6f59..1650dcb3a67b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -231,6 +231,7 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
231 u64 addr); 231 u64 addr);
232struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 232struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
233 const char *name); 233 const char *name);
234struct symbol *symbol__next_by_name(struct symbol *sym);
234 235
235struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); 236struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
236struct symbol *dso__next_symbol(struct symbol *sym); 237struct symbol *dso__next_symbol(struct symbol *sym);
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 371219a6daf1..e3c40a520a25 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -185,6 +185,28 @@ static u64 elf_section_offset(int fd, const char *name)
185 return offset; 185 return offset;
186} 186}
187 187
188#ifndef NO_LIBUNWIND_DEBUG_FRAME
189static int elf_is_exec(int fd, const char *name)
190{
191 Elf *elf;
192 GElf_Ehdr ehdr;
193 int retval = 0;
194
195 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
196 if (elf == NULL)
197 return 0;
198 if (gelf_getehdr(elf, &ehdr) == NULL)
199 goto out;
200
201 retval = (ehdr.e_type == ET_EXEC);
202
203out:
204 elf_end(elf);
205 pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);
206 return retval;
207}
208#endif
209
188struct table_entry { 210struct table_entry {
189 u32 start_ip_offset; 211 u32 start_ip_offset;
190 u32 fde_offset; 212 u32 fde_offset;
@@ -244,14 +266,17 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
244 u64 *fde_count) 266 u64 *fde_count)
245{ 267{
246 int ret = -EINVAL, fd; 268 int ret = -EINVAL, fd;
247 u64 offset; 269 u64 offset = dso->data.frame_offset;
248 270
249 fd = dso__data_fd(dso, machine); 271 if (offset == 0) {
250 if (fd < 0) 272 fd = dso__data_fd(dso, machine);
251 return -EINVAL; 273 if (fd < 0)
274 return -EINVAL;
252 275
253 /* Check the .eh_frame section for unwinding info */ 276 /* Check the .eh_frame section for unwinding info */
254 offset = elf_section_offset(fd, ".eh_frame_hdr"); 277 offset = elf_section_offset(fd, ".eh_frame_hdr");
278 dso->data.frame_offset = offset;
279 }
255 280
256 if (offset) 281 if (offset)
257 ret = unwind_spec_ehframe(dso, machine, offset, 282 ret = unwind_spec_ehframe(dso, machine, offset,
@@ -265,14 +290,20 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
265static int read_unwind_spec_debug_frame(struct dso *dso, 290static int read_unwind_spec_debug_frame(struct dso *dso,
266 struct machine *machine, u64 *offset) 291 struct machine *machine, u64 *offset)
267{ 292{
268 int fd = dso__data_fd(dso, machine); 293 int fd;
294 u64 ofs = dso->data.frame_offset;
269 295
270 if (fd < 0) 296 if (ofs == 0) {
271 return -EINVAL; 297 fd = dso__data_fd(dso, machine);
298 if (fd < 0)
299 return -EINVAL;
272 300
273 /* Check the .debug_frame section for unwinding info */ 301 /* Check the .debug_frame section for unwinding info */
274 *offset = elf_section_offset(fd, ".debug_frame"); 302 ofs = elf_section_offset(fd, ".debug_frame");
303 dso->data.frame_offset = ofs;
304 }
275 305
306 *offset = ofs;
276 if (*offset) 307 if (*offset)
277 return 0; 308 return 0;
278 309
@@ -322,8 +353,12 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
322#ifndef NO_LIBUNWIND_DEBUG_FRAME 353#ifndef NO_LIBUNWIND_DEBUG_FRAME
323 /* Check the .debug_frame section for unwinding info */ 354 /* Check the .debug_frame section for unwinding info */
324 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { 355 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
356 int fd = dso__data_fd(map->dso, ui->machine);
357 int is_exec = elf_is_exec(fd, map->dso->name);
358 unw_word_t base = is_exec ? 0 : map->start;
359
325 memset(&di, 0, sizeof(di)); 360 memset(&di, 0, sizeof(di));
326 if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, 361 if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name,
327 map->start, map->end)) 362 map->start, map->end))
328 return dwarf_search_unwind_table(as, ip, &di, pi, 363 return dwarf_search_unwind_table(as, ip, &di, pi,
329 need_unwind_info, arg); 364 need_unwind_info, arg);