aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-08-04 05:02:38 -0400
committerIngo Molnar <mingo@kernel.org>2016-08-04 05:02:38 -0400
commitf282f7a0ecc3e0b8fd8532a6c3e9401534cb907c (patch)
tree93dacb43169c8339d47282d06b4eb4a8b42bcd18 /tools
parent0d87d7ec22a0879d3926faa4f4f4412a5dee1fba (diff)
parentc369e0a1a8fa6ca80e6c37c8735d9427b623ae62 (diff)
Merge tag 'perf-core-for-mingo-20160803' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: New features: - Add --sample-cpu to 'perf record', to explicitely ask for sampling the CPU (Jiri Olsa) Fixes: - Fix processing of multi byte chunks in objdump output, fixing disassemble processing for annotation on at least ARM64 (Jan Stancek) - Use SyS_epoll_wait in a BPF 'perf test' entry instead of sys_epoll_wait, that is not present in the DWARF info in vmlinux files (Arnaldo Carvalho de Melo) - Add -wno-shadow when processing files using perl headers, fixing the build on Fedora Rawhide and Arch Linux (Namhyung Kim) Infrastructure changes: - Annotate prep work to better catch and report errors related to using objdump to disassemble DSOs (Arnaldo Carvalho de Melo) - Add 'alloc', 'scnprintf' and 'and' methods for bitmap processing (Jiri Olsa) - Add nested output resorting callback in hists processing (Jiri Olsa) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/include/linux/bitmap.h37
-rw-r--r--tools/lib/bitmap.c44
-rw-r--r--tools/lib/traceevent/.gitignore1
-rw-r--r--tools/perf/Documentation/perf-record.txt3
-rw-r--r--tools/perf/Makefile.config (renamed from tools/perf/config/Makefile)0
-rw-r--r--tools/perf/Makefile.perf6
-rw-r--r--tools/perf/builtin-record.c1
-rw-r--r--tools/perf/builtin-top.c6
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Build4
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/bitmap.c53
-rw-r--r--tools/perf/tests/bpf-script-example.c4
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/code-reading.c100
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/ui/browsers/annotate.c9
-rw-r--r--tools/perf/ui/gtk/annotate.c8
-rw-r--r--tools/perf/util/annotate.c116
-rw-r--r--tools/perf/util/annotate.h22
-rw-r--r--tools/perf/util/evlist.c22
-rw-r--r--tools/perf/util/evsel.c30
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/hist.c15
-rw-r--r--tools/perf/util/hist.h4
-rw-r--r--tools/perf/util/target.c6
26 files changed, 394 insertions, 106 deletions
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..43c1c5021e4b 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -3,6 +3,7 @@
3 3
4#include <string.h> 4#include <string.h>
5#include <linux/bitops.h> 5#include <linux/bitops.h>
6#include <stdlib.h>
6 7
7#define DECLARE_BITMAP(name,bits) \ 8#define DECLARE_BITMAP(name,bits) \
8 unsigned long name[BITS_TO_LONGS(bits)] 9 unsigned long name[BITS_TO_LONGS(bits)]
@@ -10,6 +11,8 @@
10int __bitmap_weight(const unsigned long *bitmap, int bits); 11int __bitmap_weight(const unsigned long *bitmap, int bits);
11void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, 12void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
12 const unsigned long *bitmap2, int bits); 13 const unsigned long *bitmap2, int bits);
14int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
15 const unsigned long *bitmap2, unsigned int bits);
13 16
14#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) 17#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
15 18
@@ -65,4 +68,38 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
65 return (old & mask) != 0; 68 return (old & mask) != 0;
66} 69}
67 70
71/**
72 * bitmap_alloc - Allocate bitmap
73 * @nr: Bit to set
74 */
75static inline unsigned long *bitmap_alloc(int nbits)
76{
77 return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long));
78}
79
80/*
81 * bitmap_scnprintf - print bitmap list into buffer
82 * @bitmap: bitmap
83 * @nbits: size of bitmap
84 * @buf: buffer to store output
85 * @size: size of @buf
86 */
87size_t bitmap_scnprintf(unsigned long *bitmap, int nbits,
88 char *buf, size_t size);
89
90/**
91 * bitmap_and - Do logical and on bitmaps
92 * @dst: resulting bitmap
93 * @src1: operand 1
94 * @src2: operand 2
95 * @nbits: size of bitmap
96 */
97static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
98 const unsigned long *src2, unsigned int nbits)
99{
100 if (small_const_nbits(nbits))
101 return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0;
102 return __bitmap_and(dst, src1, src2, nbits);
103}
104
68#endif /* _PERF_BITOPS_H */ 105#endif /* _PERF_BITOPS_H */
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adc1111fd..38748b0e342f 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,47 @@ void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
29 for (k = 0; k < nr; k++) 29 for (k = 0; k < nr; k++)
30 dst[k] = bitmap1[k] | bitmap2[k]; 30 dst[k] = bitmap1[k] | bitmap2[k];
31} 31}
32
33size_t bitmap_scnprintf(unsigned long *bitmap, int nbits,
34 char *buf, size_t size)
35{
36 /* current bit is 'cur', most recently seen range is [rbot, rtop] */
37 int cur, rbot, rtop;
38 bool first = true;
39 size_t ret = 0;
40
41 rbot = cur = find_first_bit(bitmap, nbits);
42 while (cur < nbits) {
43 rtop = cur;
44 cur = find_next_bit(bitmap, nbits, cur + 1);
45 if (cur < nbits && cur <= rtop + 1)
46 continue;
47
48 if (!first)
49 ret += scnprintf(buf + ret, size - ret, ",");
50
51 first = false;
52
53 ret += scnprintf(buf + ret, size - ret, "%d", rbot);
54 if (rbot < rtop)
55 ret += scnprintf(buf + ret, size - ret, "-%d", rtop);
56
57 rbot = cur;
58 }
59 return ret;
60}
61
62int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
63 const unsigned long *bitmap2, unsigned int bits)
64{
65 unsigned int k;
66 unsigned int lim = bits/BITS_PER_LONG;
67 unsigned long result = 0;
68
69 for (k = 0; k < lim; k++)
70 result |= (dst[k] = bitmap1[k] & bitmap2[k]);
71 if (bits % BITS_PER_LONG)
72 result |= (dst[k] = bitmap1[k] & bitmap2[k] &
73 BITMAP_LAST_WORD_MASK(bits));
74 return result != 0;
75}
diff --git a/tools/lib/traceevent/.gitignore b/tools/lib/traceevent/.gitignore
index 3c60335fe7be..9e9f25fb1922 100644
--- a/tools/lib/traceevent/.gitignore
+++ b/tools/lib/traceevent/.gitignore
@@ -1,2 +1,3 @@
1TRACEEVENT-CFLAGS 1TRACEEVENT-CFLAGS
2libtraceevent-dynamic-list 2libtraceevent-dynamic-list
3libtraceevent.so.*
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 69966abf65d1..379a2bed07c0 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -192,6 +192,9 @@ OPTIONS
192--period:: 192--period::
193 Record the sample period. 193 Record the sample period.
194 194
195--sample-cpu::
196 Record the sample cpu.
197
195-n:: 198-n::
196--no-samples:: 199--no-samples::
197 Don't sample. 200 Don't sample.
diff --git a/tools/perf/config/Makefile b/tools/perf/Makefile.config
index 24803c58049a..24803c58049a 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/Makefile.config
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 6641abb97f0a..2d9087501633 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -161,7 +161,7 @@ TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
161BPF_DIR = $(srctree)/tools/lib/bpf/ 161BPF_DIR = $(srctree)/tools/lib/bpf/
162SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ 162SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
163 163
164# include config/Makefile by default and rule out 164# include Makefile.config by default and rule out
165# non-config cases 165# non-config cases
166config := 1 166config := 1
167 167
@@ -183,7 +183,7 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
183FEATURE_TESTS := all 183FEATURE_TESTS := all
184endif 184endif
185endif 185endif
186include config/Makefile 186include Makefile.config
187endif 187endif
188 188
189ifeq ($(config),0) 189ifeq ($(config),0)
@@ -706,7 +706,7 @@ $(INSTALL_DOC_TARGETS):
706### Cleaning rules 706### Cleaning rules
707 707
708# 708#
709# This is here, not in config/Makefile, because config/Makefile does 709# This is here, not in Makefile.config, because Makefile.config does
710# not get included for the clean target: 710# not get included for the clean target:
711# 711#
712config-clean: 712config-clean:
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8f2c16d9275f..6355902fbfc8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1434,6 +1434,7 @@ struct option __record_options[] = {
1434 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1434 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1435 "per thread counts"), 1435 "per thread counts"),
1436 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 1436 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
1437 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
1437 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 1438 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
1438 &record.opts.sample_time_set, 1439 &record.opts.sample_time_set,
1439 "Record the sample timestamps"), 1440 "Record the sample timestamps"),
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index bd108683fcb8..418ed94756d3 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -128,10 +128,14 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
128 return err; 128 return err;
129 } 129 }
130 130
131 err = symbol__annotate(sym, map, 0); 131 err = symbol__disassemble(sym, map, 0);
132 if (err == 0) { 132 if (err == 0) {
133out_assign: 133out_assign:
134 top->sym_filter_entry = he; 134 top->sym_filter_entry = he;
135 } else {
136 char msg[BUFSIZ];
137 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
138 pr_err("Couldn't annotate %s: %s\n", sym->name, msg);
135 } 139 }
136 140
137 pthread_mutex_unlock(&notes->lock); 141 pthread_mutex_unlock(&notes->lock);
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index a7e0f1497244..cb0f1356ff81 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -52,6 +52,7 @@ struct record_opts {
52 bool sample_weight; 52 bool sample_weight;
53 bool sample_time; 53 bool sample_time;
54 bool sample_time_set; 54 bool sample_time_set;
55 bool sample_cpu;
55 bool period; 56 bool period;
56 bool running_time; 57 bool running_time;
57 bool full_auxtrace; 58 bool full_auxtrace;
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build
index 928e110179cb..34faecf774ae 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Build
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Build
@@ -1,3 +1,5 @@
1libperf-y += Context.o 1libperf-y += Context.o
2 2
3CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default 3CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes
4CFLAGS_Context.o += -Wno-unused-parameter -Wno-nested-externs -Wno-undef
5CFLAGS_Context.o += -Wno-switch-default -Wno-shadow
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index cb20ae1c0d35..dc51bc570e51 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -41,6 +41,7 @@ perf-y += event-times.o
41perf-y += backward-ring-buffer.o 41perf-y += backward-ring-buffer.o
42perf-y += sdt.o 42perf-y += sdt.o
43perf-y += is_printable_array.o 43perf-y += is_printable_array.o
44perf-y += bitmap.o
44 45
45$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 46$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
46 $(call rule_mkdir) 47 $(call rule_mkdir)
diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c
new file mode 100644
index 000000000000..9abe6c13090f
--- /dev/null
+++ b/tools/perf/tests/bitmap.c
@@ -0,0 +1,53 @@
1#include <linux/compiler.h>
2#include <linux/bitmap.h>
3#include "tests.h"
4#include "cpumap.h"
5#include "debug.h"
6
7#define NBITS 100
8
9static unsigned long *get_bitmap(const char *str, int nbits)
10{
11 struct cpu_map *map = cpu_map__new(str);
12 unsigned long *bm = NULL;
13 int i;
14
15 bm = bitmap_alloc(nbits);
16
17 if (map && bm) {
18 bitmap_zero(bm, nbits);
19
20 for (i = 0; i < map->nr; i++)
21 set_bit(map->map[i], bm);
22 }
23
24 if (map)
25 cpu_map__put(map);
26 return bm;
27}
28
29static int test_bitmap(const char *str)
30{
31 unsigned long *bm = get_bitmap(str, NBITS);
32 char buf[100];
33 int ret;
34
35 bitmap_scnprintf(bm, NBITS, buf, sizeof(buf));
36 pr_debug("bitmap: %s\n", buf);
37
38 ret = !strcmp(buf, str);
39 free(bm);
40 return ret;
41}
42
43int test__bitmap_print(int subtest __maybe_unused)
44{
45 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1"));
46 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,5"));
47 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3,5,7,9,11,13,15,17,19,21-40"));
48 TEST_ASSERT_VAL("failed to convert map", test_bitmap("2-5"));
49 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37"));
50 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37"));
51 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1-10,12-20,22-30,32-40"));
52 return 0;
53}
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index e53bc91fa260..268e5f8e4aa2 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -31,8 +31,8 @@ struct bpf_map_def SEC("maps") flip_table = {
31 .max_entries = 1, 31 .max_entries = 1,
32}; 32};
33 33
34SEC("func=sys_epoll_wait") 34SEC("func=SyS_epoll_wait")
35int bpf_func__sys_epoll_wait(void *ctx) 35int bpf_func__SyS_epoll_wait(void *ctx)
36{ 36{
37 int ind =0; 37 int ind =0;
38 int *flag = bpf_map_lookup_elem(&flip_table, &ind); 38 int *flag = bpf_map_lookup_elem(&flip_table, &ind);
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 10eb30686c9c..778668a2a966 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -226,6 +226,10 @@ static struct test generic_tests[] = {
226 .func = test__is_printable_array, 226 .func = test__is_printable_array,
227 }, 227 },
228 { 228 {
229 .desc = "Test bitmap print",
230 .func = test__bitmap_print,
231 },
232 {
229 .func = NULL, 233 .func = NULL,
230 }, 234 },
231}; 235};
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 68a69a195545..2af156a8d4e5 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -33,44 +33,86 @@ static unsigned int hex(char c)
33 return c - 'A' + 10; 33 return c - 'A' + 10;
34} 34}
35 35
36static size_t read_objdump_line(const char *line, size_t line_len, void *buf, 36static size_t read_objdump_chunk(const char **line, unsigned char **buf,
37 size_t len) 37 size_t *buf_len)
38{ 38{
39 const char *p; 39 size_t bytes_read = 0;
40 size_t i, j = 0; 40 unsigned char *chunk_start = *buf;
41
42 /* Skip to a colon */
43 p = strchr(line, ':');
44 if (!p)
45 return 0;
46 i = p + 1 - line;
47 41
48 /* Read bytes */ 42 /* Read bytes */
49 while (j < len) { 43 while (*buf_len > 0) {
50 char c1, c2; 44 char c1, c2;
51 45
52 /* Skip spaces */
53 for (; i < line_len; i++) {
54 if (!isspace(line[i]))
55 break;
56 }
57 /* Get 2 hex digits */ 46 /* Get 2 hex digits */
58 if (i >= line_len || !isxdigit(line[i])) 47 c1 = *(*line)++;
48 if (!isxdigit(c1))
59 break; 49 break;
60 c1 = line[i++]; 50 c2 = *(*line)++;
61 if (i >= line_len || !isxdigit(line[i])) 51 if (!isxdigit(c2))
62 break; 52 break;
63 c2 = line[i++]; 53
64 /* Followed by a space */ 54 /* Store byte and advance buf */
65 if (i < line_len && line[i] && !isspace(line[i])) 55 **buf = (hex(c1) << 4) | hex(c2);
56 (*buf)++;
57 (*buf_len)--;
58 bytes_read++;
59
60 /* End of chunk? */
61 if (isspace(**line))
66 break; 62 break;
67 /* Store byte */
68 *(unsigned char *)buf = (hex(c1) << 4) | hex(c2);
69 buf += 1;
70 j++;
71 } 63 }
64
65 /*
66 * objdump will display raw insn as LE if code endian
67 * is LE and bytes_per_chunk > 1. In that case reverse
68 * the chunk we just read.
69 *
70 * see disassemble_bytes() at binutils/objdump.c for details
71 * how objdump chooses display endian)
72 */
73 if (bytes_read > 1 && !bigendian()) {
74 unsigned char *chunk_end = chunk_start + bytes_read - 1;
75 unsigned char tmp;
76
77 while (chunk_start < chunk_end) {
78 tmp = *chunk_start;
79 *chunk_start = *chunk_end;
80 *chunk_end = tmp;
81 chunk_start++;
82 chunk_end--;
83 }
84 }
85
86 return bytes_read;
87}
88
89static size_t read_objdump_line(const char *line, unsigned char *buf,
90 size_t buf_len)
91{
92 const char *p;
93 size_t ret, bytes_read = 0;
94
95 /* Skip to a colon */
96 p = strchr(line, ':');
97 if (!p)
98 return 0;
99 p++;
100
101 /* Skip initial spaces */
102 while (*p) {
103 if (!isspace(*p))
104 break;
105 p++;
106 }
107
108 do {
109 ret = read_objdump_chunk(&p, &buf, &buf_len);
110 bytes_read += ret;
111 p++;
112 } while (ret > 0);
113
72 /* return number of successfully read bytes */ 114 /* return number of successfully read bytes */
73 return j; 115 return bytes_read;
74} 116}
75 117
76static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr) 118static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
@@ -95,7 +137,7 @@ static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
95 } 137 }
96 138
97 /* read objdump data into temporary buffer */ 139 /* read objdump data into temporary buffer */
98 read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp)); 140 read_bytes = read_objdump_line(line, tmp, sizeof(tmp));
99 if (!read_bytes) 141 if (!read_bytes)
100 continue; 142 continue;
101 143
@@ -152,7 +194,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
152 194
153 ret = read_objdump_output(f, buf, &len, addr); 195 ret = read_objdump_output(f, buf, &len, addr);
154 if (len) { 196 if (len) {
155 pr_debug("objdump read too few bytes\n"); 197 pr_debug("objdump read too few bytes: %zd\n", len);
156 if (!ret) 198 if (!ret)
157 ret = len; 199 ret = len;
158 } 200 }
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 9bfc0e06c61a..7c196c585472 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -90,6 +90,7 @@ int test__backward_ring_buffer(int subtest);
90int test__cpu_map_print(int subtest); 90int test__cpu_map_print(int subtest);
91int test__sdt_event(int subtest); 91int test__sdt_event(int subtest);
92int test__is_printable_array(int subtest); 92int test__is_printable_array(int subtest);
93int test__bitmap_print(int subtest);
93 94
94#if defined(__arm__) || defined(__aarch64__) 95#if defined(__arm__) || defined(__aarch64__)
95#ifdef HAVE_DWARF_UNWIND_SUPPORT 96#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 29dc6d20364e..2e2d10022355 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -1026,7 +1026,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1026 .use_navkeypressed = true, 1026 .use_navkeypressed = true,
1027 }, 1027 },
1028 }; 1028 };
1029 int ret = -1; 1029 int ret = -1, err;
1030 int nr_pcnt = 1; 1030 int nr_pcnt = 1;
1031 size_t sizeof_bdl = sizeof(struct browser_disasm_line); 1031 size_t sizeof_bdl = sizeof(struct browser_disasm_line);
1032 1032
@@ -1050,8 +1050,11 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1050 (nr_pcnt - 1); 1050 (nr_pcnt - 1);
1051 } 1051 }
1052 1052
1053 if (symbol__annotate(sym, map, sizeof_bdl) < 0) { 1053 err = symbol__disassemble(sym, map, sizeof_bdl);
1054 ui__error("%s", ui_helpline__last_msg); 1054 if (err) {
1055 char msg[BUFSIZ];
1056 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
1057 ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
1055 goto out_free_offsets; 1058 goto out_free_offsets;
1056 } 1059 }
1057 1060
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index 9c7ff8d31b27..42d319927762 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -162,12 +162,16 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
162 GtkWidget *notebook; 162 GtkWidget *notebook;
163 GtkWidget *scrolled_window; 163 GtkWidget *scrolled_window;
164 GtkWidget *tab_label; 164 GtkWidget *tab_label;
165 int err;
165 166
166 if (map->dso->annotate_warned) 167 if (map->dso->annotate_warned)
167 return -1; 168 return -1;
168 169
169 if (symbol__annotate(sym, map, 0) < 0) { 170 err = symbol__disassemble(sym, map, 0);
170 ui__error("%s", ui_helpline__current); 171 if (err) {
172 char msg[BUFSIZ];
173 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
174 ui__error("Couldn't annotate %s: %s\n", sym->name, msg);
171 return -1; 175 return -1;
172 } 176 }
173 177
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index e9825fe825fd..4024d309bb00 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1123,7 +1123,46 @@ static void delete_last_nop(struct symbol *sym)
1123 } 1123 }
1124} 1124}
1125 1125
1126int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) 1126int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
1127 int errnum, char *buf, size_t buflen)
1128{
1129 struct dso *dso = map->dso;
1130
1131 BUG_ON(buflen == 0);
1132
1133 if (errnum >= 0) {
1134 str_error_r(errnum, buf, buflen);
1135 return 0;
1136 }
1137
1138 switch (errnum) {
1139 case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {
1140 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1141 char *build_id_msg = NULL;
1142
1143 if (dso->has_build_id) {
1144 build_id__sprintf(dso->build_id,
1145 sizeof(dso->build_id), bf + 15);
1146 build_id_msg = bf;
1147 }
1148 scnprintf(buf, buflen,
1149 "No vmlinux file%s\nwas found in the path.\n\n"
1150 "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1151 "Please use:\n\n"
1152 " perf buildid-cache -vu vmlinux\n\n"
1153 "or:\n\n"
1154 " --vmlinux vmlinux\n", build_id_msg ?: "");
1155 }
1156 break;
1157 default:
1158 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
1159 break;
1160 }
1161
1162 return 0;
1163}
1164
1165int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
1127{ 1166{
1128 struct dso *dso = map->dso; 1167 struct dso *dso = map->dso;
1129 char *filename = dso__build_id_filename(dso, NULL, 0); 1168 char *filename = dso__build_id_filename(dso, NULL, 0);
@@ -1134,22 +1173,20 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
1134 char symfs_filename[PATH_MAX]; 1173 char symfs_filename[PATH_MAX];
1135 struct kcore_extract kce; 1174 struct kcore_extract kce;
1136 bool delete_extract = false; 1175 bool delete_extract = false;
1176 int stdout_fd[2];
1137 int lineno = 0; 1177 int lineno = 0;
1138 int nline; 1178 int nline;
1179 pid_t pid;
1139 1180
1140 if (filename) 1181 if (filename)
1141 symbol__join_symfs(symfs_filename, filename); 1182 symbol__join_symfs(symfs_filename, filename);
1142 1183
1143 if (filename == NULL) { 1184 if (filename == NULL) {
1144 if (dso->has_build_id) { 1185 if (dso->has_build_id)
1145 pr_err("Can't annotate %s: not enough memory\n", 1186 return ENOMEM;
1146 sym->name);
1147 return -ENOMEM;
1148 }
1149 goto fallback; 1187 goto fallback;
1150 } else if (dso__is_kcore(dso)) { 1188 } else if (dso__is_kcore(dso) ||
1151 goto fallback; 1189 readlink(symfs_filename, command, sizeof(command)) < 0 ||
1152 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
1153 strstr(command, DSO__NAME_KALLSYMS) || 1190 strstr(command, DSO__NAME_KALLSYMS) ||
1154 access(symfs_filename, R_OK)) { 1191 access(symfs_filename, R_OK)) {
1155 free(filename); 1192 free(filename);
@@ -1166,27 +1203,7 @@ fallback:
1166 1203
1167 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1204 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1168 !dso__is_kcore(dso)) { 1205 !dso__is_kcore(dso)) {
1169 char bf[SBUILD_ID_SIZE + 15] = " with build id "; 1206 err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1170 char *build_id_msg = NULL;
1171
1172 if (dso->annotate_warned)
1173 goto out_free_filename;
1174
1175 if (dso->has_build_id) {
1176 build_id__sprintf(dso->build_id,
1177 sizeof(dso->build_id), bf + 15);
1178 build_id_msg = bf;
1179 }
1180 err = -ENOENT;
1181 dso->annotate_warned = 1;
1182 pr_err("Can't annotate %s:\n\n"
1183 "No vmlinux file%s\nwas found in the path.\n\n"
1184 "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1185 "Please use:\n\n"
1186 " perf buildid-cache -vu vmlinux\n\n"
1187 "or:\n\n"
1188 " --vmlinux vmlinux\n",
1189 sym->name, build_id_msg ?: "");
1190 goto out_free_filename; 1207 goto out_free_filename;
1191 } 1208 }
1192 1209
@@ -1258,9 +1275,32 @@ fallback:
1258 1275
1259 pr_debug("Executing: %s\n", command); 1276 pr_debug("Executing: %s\n", command);
1260 1277
1261 file = popen(command, "r"); 1278 err = -1;
1279 if (pipe(stdout_fd) < 0) {
1280 pr_err("Failure creating the pipe to run %s\n", command);
1281 goto out_remove_tmp;
1282 }
1283
1284 pid = fork();
1285 if (pid < 0) {
1286 pr_err("Failure forking to run %s\n", command);
1287 goto out_close_stdout;
1288 }
1289
1290 if (pid == 0) {
1291 close(stdout_fd[0]);
1292 dup2(stdout_fd[1], 1);
1293 close(stdout_fd[1]);
1294 execl("/bin/sh", "sh", "-c", command, NULL);
1295 perror(command);
1296 exit(-1);
1297 }
1298
1299 close(stdout_fd[1]);
1300
1301 file = fdopen(stdout_fd[0], "r");
1262 if (!file) { 1302 if (!file) {
1263 pr_err("Failure running %s\n", command); 1303 pr_err("Failure creating FILE stream for %s\n", command);
1264 /* 1304 /*
1265 * If we were using debug info should retry with 1305 * If we were using debug info should retry with
1266 * original binary. 1306 * original binary.
@@ -1286,9 +1326,11 @@ fallback:
1286 if (dso__is_kcore(dso)) 1326 if (dso__is_kcore(dso))
1287 delete_last_nop(sym); 1327 delete_last_nop(sym);
1288 1328
1289 pclose(file); 1329 fclose(file);
1290 1330 err = 0;
1291out_remove_tmp: 1331out_remove_tmp:
1332 close(stdout_fd[0]);
1333
1292 if (dso__needs_decompress(dso)) 1334 if (dso__needs_decompress(dso))
1293 unlink(symfs_filename); 1335 unlink(symfs_filename);
1294out_free_filename: 1336out_free_filename:
@@ -1297,6 +1339,10 @@ out_free_filename:
1297 if (free_filename) 1339 if (free_filename)
1298 free(filename); 1340 free(filename);
1299 return err; 1341 return err;
1342
1343out_close_stdout:
1344 close(stdout_fd[1]);
1345 goto out_remove_tmp;
1300} 1346}
1301 1347
1302static void insert_source_line(struct rb_root *root, struct source_line *src_line) 1348static void insert_source_line(struct rb_root *root, struct source_line *src_line)
@@ -1663,7 +1709,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1663 struct rb_root source_line = RB_ROOT; 1709 struct rb_root source_line = RB_ROOT;
1664 u64 len; 1710 u64 len;
1665 1711
1666 if (symbol__annotate(sym, map, 0) < 0) 1712 if (symbol__disassemble(sym, map, 0) < 0)
1667 return -1; 1713 return -1;
1668 1714
1669 len = symbol__size(sym); 1715 len = symbol__size(sym);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index a23084f54128..f67ccb027561 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -155,7 +155,27 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
155int symbol__alloc_hist(struct symbol *sym); 155int symbol__alloc_hist(struct symbol *sym);
156void symbol__annotate_zero_histograms(struct symbol *sym); 156void symbol__annotate_zero_histograms(struct symbol *sym);
157 157
158int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 158int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize);
159
160enum symbol_disassemble_errno {
161 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
162
163 /*
164 * Choose an arbitrary negative big number not to clash with standard
165 * errno since SUS requires the errno has distinct positive values.
166 * See 'Issue 6' in the link below.
167 *
168 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
169 */
170 __SYMBOL_ANNOTATE_ERRNO__START = -10000,
171
172 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START,
173
174 __SYMBOL_ANNOTATE_ERRNO__END,
175};
176
177int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
178 int errnum, char *buf, size_t buflen);
159 179
160int symbol__annotate_init(struct map *map, struct symbol *sym); 180int symbol__annotate_init(struct map *map, struct symbol *sym);
161int symbol__annotate_printf(struct symbol *sym, struct map *map, 181int symbol__annotate_printf(struct symbol *sym, struct map *map,
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 2a40b8e1def7..097b3ed77fdd 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -239,31 +239,13 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
239 239
240int perf_evlist__add_default(struct perf_evlist *evlist) 240int perf_evlist__add_default(struct perf_evlist *evlist)
241{ 241{
242 struct perf_event_attr attr = { 242 struct perf_evsel *evsel = perf_evsel__new_cycles();
243 .type = PERF_TYPE_HARDWARE,
244 .config = PERF_COUNT_HW_CPU_CYCLES,
245 };
246 struct perf_evsel *evsel;
247
248 event_attr_init(&attr);
249 243
250 perf_event_attr__set_max_precise_ip(&attr);
251
252 evsel = perf_evsel__new(&attr);
253 if (evsel == NULL) 244 if (evsel == NULL)
254 goto error; 245 return -ENOMEM;
255
256 /* use asprintf() because free(evsel) assumes name is allocated */
257 if (asprintf(&evsel->name, "cycles%.*s",
258 attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0)
259 goto error_free;
260 246
261 perf_evlist__add(evlist, evsel); 247 perf_evlist__add(evlist, evsel);
262 return 0; 248 return 0;
263error_free:
264 perf_evsel__delete(evsel);
265error:
266 return -ENOMEM;
267} 249}
268 250
269int perf_evlist__add_dummy(struct perf_evlist *evlist) 251int perf_evlist__add_dummy(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8c54df61fe64..d9b80ef881cd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -253,6 +253,34 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
253 return evsel; 253 return evsel;
254} 254}
255 255
256struct perf_evsel *perf_evsel__new_cycles(void)
257{
258 struct perf_event_attr attr = {
259 .type = PERF_TYPE_HARDWARE,
260 .config = PERF_COUNT_HW_CPU_CYCLES,
261 };
262 struct perf_evsel *evsel;
263
264 event_attr_init(&attr);
265
266 perf_event_attr__set_max_precise_ip(&attr);
267
268 evsel = perf_evsel__new(&attr);
269 if (evsel == NULL)
270 goto out;
271
272 /* use asprintf() because free(evsel) assumes name is allocated */
273 if (asprintf(&evsel->name, "cycles%.*s",
274 attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0)
275 goto error_free;
276out:
277 return evsel;
278error_free:
279 perf_evsel__delete(evsel);
280 evsel = NULL;
281 goto out;
282}
283
256/* 284/*
257 * Returns pointer with encoded error via <linux/err.h> interface. 285 * Returns pointer with encoded error via <linux/err.h> interface.
258 */ 286 */
@@ -854,7 +882,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
854 perf_evsel__set_sample_bit(evsel, REGS_INTR); 882 perf_evsel__set_sample_bit(evsel, REGS_INTR);
855 } 883 }
856 884
857 if (target__has_cpu(&opts->target)) 885 if (target__has_cpu(&opts->target) || opts->sample_cpu)
858 perf_evsel__set_sample_bit(evsel, CPU); 886 perf_evsel__set_sample_bit(evsel, CPU);
859 887
860 if (opts->period) 888 if (opts->period)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 8a4a6c9f1480..4d44129e050b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -175,6 +175,8 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
175 return perf_evsel__newtp_idx(sys, name, 0); 175 return perf_evsel__newtp_idx(sys, name, 0);
176} 176}
177 177
178struct perf_evsel *perf_evsel__new_cycles(void);
179
178struct event_format *event_format__new(const char *sys, const char *name); 180struct event_format *event_format__new(const char *sys, const char *name);
179 181
180void perf_evsel__init(struct perf_evsel *evsel, 182void perf_evsel__init(struct perf_evsel *evsel,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a18d142cdca3..de15dbcdcecf 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1672,7 +1672,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
1672} 1672}
1673 1673
1674static void output_resort(struct hists *hists, struct ui_progress *prog, 1674static void output_resort(struct hists *hists, struct ui_progress *prog,
1675 bool use_callchain) 1675 bool use_callchain, hists__resort_cb_t cb)
1676{ 1676{
1677 struct rb_root *root; 1677 struct rb_root *root;
1678 struct rb_node *next; 1678 struct rb_node *next;
@@ -1711,6 +1711,9 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,
1711 n = rb_entry(next, struct hist_entry, rb_node_in); 1711 n = rb_entry(next, struct hist_entry, rb_node_in);
1712 next = rb_next(&n->rb_node_in); 1712 next = rb_next(&n->rb_node_in);
1713 1713
1714 if (cb && cb(n))
1715 continue;
1716
1714 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain); 1717 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain);
1715 hists__inc_stats(hists, n); 1718 hists__inc_stats(hists, n);
1716 1719
@@ -1731,12 +1734,18 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
1731 else 1734 else
1732 use_callchain = symbol_conf.use_callchain; 1735 use_callchain = symbol_conf.use_callchain;
1733 1736
1734 output_resort(evsel__hists(evsel), prog, use_callchain); 1737 output_resort(evsel__hists(evsel), prog, use_callchain, NULL);
1735} 1738}
1736 1739
1737void hists__output_resort(struct hists *hists, struct ui_progress *prog) 1740void hists__output_resort(struct hists *hists, struct ui_progress *prog)
1738{ 1741{
1739 output_resort(hists, prog, symbol_conf.use_callchain); 1742 output_resort(hists, prog, symbol_conf.use_callchain, NULL);
1743}
1744
1745void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog,
1746 hists__resort_cb_t cb)
1747{
1748 output_resort(hists, prog, symbol_conf.use_callchain, cb);
1740} 1749}
1741 1750
1742static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd) 1751static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 49aa4fac148f..0a1edf1ab450 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -153,8 +153,12 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
153 struct perf_hpp_fmt *fmt, int printed); 153 struct perf_hpp_fmt *fmt, int printed);
154void hist_entry__delete(struct hist_entry *he); 154void hist_entry__delete(struct hist_entry *he);
155 155
156typedef int (*hists__resort_cb_t)(struct hist_entry *he);
157
156void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); 158void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog);
157void hists__output_resort(struct hists *hists, struct ui_progress *prog); 159void hists__output_resort(struct hists *hists, struct ui_progress *prog);
160void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog,
161 hists__resort_cb_t cb);
158int hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 162int hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
159 163
160void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 164void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 8cdcf4641c51..21c4d9b23c24 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -122,11 +122,7 @@ int target__strerror(struct target *target, int errnum,
122 BUG_ON(buflen == 0); 122 BUG_ON(buflen == 0);
123 123
124 if (errnum >= 0) { 124 if (errnum >= 0) {
125 const char *err = str_error_r(errnum, buf, buflen); 125 str_error_r(errnum, buf, buflen);
126
127 if (err != buf)
128 scnprintf(buf, buflen, "%s", err);
129
130 return 0; 126 return 0;
131 } 127 }
132 128