aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-bench.txt78
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt2
-rw-r--r--tools/perf/MANIFEST2
-rw-r--r--tools/perf/Makefile12
-rw-r--r--tools/perf/bench/mem-memcpy.c84
-rw-r--r--tools/perf/bench/mem-memset.c88
-rw-r--r--tools/perf/builtin-bench.c4
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-kmem.c37
-rw-r--r--tools/perf/builtin-lock.c4
-rw-r--r--tools/perf/builtin-record.c4
-rw-r--r--tools/perf/builtin-report.c20
-rw-r--r--tools/perf/builtin-sched.c38
-rw-r--r--tools/perf/builtin-script.c106
-rw-r--r--tools/perf/builtin-stat.c28
-rw-r--r--tools/perf/builtin-test.c6
-rw-r--r--tools/perf/builtin-top.c16
-rw-r--r--tools/perf/config/feature-tests.mak13
-rw-r--r--tools/perf/design.txt7
-rw-r--r--tools/perf/ui/browsers/annotate.c6
-rw-r--r--tools/perf/ui/browsers/hists.c210
-rw-r--r--tools/perf/ui/gtk/browser.c69
-rw-r--r--tools/perf/ui/gtk/gtk.h31
-rw-r--r--tools/perf/ui/gtk/setup.c5
-rw-r--r--tools/perf/ui/gtk/util.c129
-rw-r--r--tools/perf/ui/tui/setup.c6
-rw-r--r--tools/perf/ui/tui/util.c243
-rw-r--r--tools/perf/ui/util.c277
-rw-r--r--tools/perf/ui/util.h9
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN2
-rw-r--r--tools/perf/util/annotate.c15
-rw-r--r--tools/perf/util/callchain.c2
-rw-r--r--tools/perf/util/callchain.h2
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debug.h23
-rw-r--r--tools/perf/util/dso-test-data.c153
-rw-r--r--tools/perf/util/evlist.c23
-rw-r--r--tools/perf/util/evlist.h7
-rw-r--r--tools/perf/util/evsel.c252
-rw-r--r--tools/perf/util/evsel.h15
-rw-r--r--tools/perf/util/header.c77
-rw-r--r--tools/perf/util/hist.c14
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/include/linux/bitops.h2
-rw-r--r--tools/perf/util/include/linux/kernel.h10
-rw-r--r--tools/perf/util/map.c64
-rw-r--r--tools/perf/util/map.h3
-rw-r--r--tools/perf/util/pager.c4
-rw-r--r--tools/perf/util/parse-events-test.c179
-rw-r--r--tools/perf/util/parse-events.c472
-rw-r--r--tools/perf/util/parse-events.h17
-rw-r--r--tools/perf/util/parse-events.l134
-rw-r--r--tools/perf/util/parse-events.y86
-rw-r--r--tools/perf/util/pmu.c169
-rw-r--r--tools/perf/util/pmu.h11
-rw-r--r--tools/perf/util/probe-event.c8
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c32
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c25
-rw-r--r--tools/perf/util/session.c177
-rw-r--r--tools/perf/util/session.h15
-rw-r--r--tools/perf/util/sort.c49
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/string.c22
-rw-r--r--tools/perf/util/symbol.c551
-rw-r--r--tools/perf/util/symbol.h83
-rw-r--r--tools/perf/util/target.c11
-rw-r--r--tools/perf/util/top.c2
-rw-r--r--tools/perf/util/trace-event-parse.c61
-rw-r--r--tools/perf/util/trace-event-read.c97
-rw-r--r--tools/perf/util/trace-event-scripting.c7
-rw-r--r--tools/perf/util/trace-event.h38
-rw-r--r--tools/perf/util/util.h2
73 files changed, 3332 insertions, 1129 deletions
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt
index a3dbadb26ef5..7065cd6fbdfc 100644
--- a/tools/perf/Documentation/perf-bench.txt
+++ b/tools/perf/Documentation/perf-bench.txt
@@ -12,7 +12,7 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This 'perf bench' command is general framework for benchmark suites. 15This 'perf bench' command is a general framework for benchmark suites.
16 16
17COMMON OPTIONS 17COMMON OPTIONS
18-------------- 18--------------
@@ -45,14 +45,20 @@ SUBSYSTEM
45'sched':: 45'sched'::
46 Scheduler and IPC mechanisms. 46 Scheduler and IPC mechanisms.
47 47
48'mem'::
49 Memory access performance.
50
51'all'::
52 All benchmark subsystems.
53
48SUITES FOR 'sched' 54SUITES FOR 'sched'
49~~~~~~~~~~~~~~~~~~ 55~~~~~~~~~~~~~~~~~~
50*messaging*:: 56*messaging*::
51Suite for evaluating performance of scheduler and IPC mechanisms. 57Suite for evaluating performance of scheduler and IPC mechanisms.
52Based on hackbench by Rusty Russell. 58Based on hackbench by Rusty Russell.
53 59
54Options of *pipe* 60Options of *messaging*
55^^^^^^^^^^^^^^^^^ 61^^^^^^^^^^^^^^^^^^^^^^
56-p:: 62-p::
57--pipe:: 63--pipe::
58Use pipe() instead of socketpair() 64Use pipe() instead of socketpair()
@@ -115,6 +121,72 @@ Example of *pipe*
115 59004 ops/sec 121 59004 ops/sec
116--------------------- 122---------------------
117 123
124SUITES FOR 'mem'
125~~~~~~~~~~~~~~~~
126*memcpy*::
127Suite for evaluating performance of simple memory copy in various ways.
128
129Options of *memcpy*
130^^^^^^^^^^^^^^^^^^^
131-l::
132--length::
133Specify length of memory to copy (default: 1MB).
134Available units are B, KB, MB, GB and TB (case insensitive).
135
136-r::
137--routine::
138Specify routine to copy (default: default).
139Available routines are depend on the architecture.
140On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported.
141
142-i::
143--iterations::
144Repeat memcpy invocation this number of times.
145
146-c::
147--cycle::
148Use perf's cpu-cycles event instead of gettimeofday syscall.
149
150-o::
151--only-prefault::
152Show only the result with page faults before memcpy.
153
154-n::
155--no-prefault::
156Show only the result without page faults before memcpy.
157
158*memset*::
159Suite for evaluating performance of simple memory set in various ways.
160
161Options of *memset*
162^^^^^^^^^^^^^^^^^^^
163-l::
164--length::
165Specify length of memory to set (default: 1MB).
166Available units are B, KB, MB, GB and TB (case insensitive).
167
168-r::
169--routine::
170Specify routine to set (default: default).
171Available routines are depend on the architecture.
172On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported.
173
174-i::
175--iterations::
176Repeat memset invocation this number of times.
177
178-c::
179--cycle::
180Use perf's cpu-cycles event instead of gettimeofday syscall.
181
182-o::
183--only-prefault::
184Show only the result with page faults before memset.
185
186-n::
187--no-prefault::
188Show only the result without page faults before memset.
189
118SEE ALSO 190SEE ALSO
119-------- 191--------
120linkperf:perf[1] 192linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 2d89f02719b5..495210a612c4 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -57,7 +57,7 @@ OPTIONS
57 57
58-s:: 58-s::
59--sort=:: 59--sort=::
60 Sort by key(s): pid, comm, dso, symbol, parent. 60 Sort by key(s): pid, comm, dso, symbol, parent, srcline.
61 61
62-p:: 62-p::
63--parent=<regex>:: 63--parent=<regex>::
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 4a5680cb242e..5b80d84d6b4a 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -112,7 +112,7 @@ Default is to monitor all CPUS.
112 112
113-s:: 113-s::
114--sort:: 114--sort::
115 Sort by key(s): pid, comm, dso, symbol, parent 115 Sort by key(s): pid, comm, dso, symbol, parent, srcline.
116 116
117-n:: 117-n::
118--show-nr-samples:: 118--show-nr-samples::
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 5476bc0a1eac..b4b572e8c100 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,4 +1,6 @@
1tools/perf 1tools/perf
2tools/scripts
3tools/lib/traceevent
2include/linux/const.h 4include/linux/const.h
3include/linux/perf_event.h 5include/linux/perf_event.h
4include/linux/rbtree.h 6include/linux/rbtree.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 0eee64cfe9a0..77f124fe57ad 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -155,7 +155,7 @@ endif
155 155
156### --- END CONFIGURATION SECTION --- 156### --- END CONFIGURATION SECTION ---
157 157
158BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 158BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
159BASIC_LDFLAGS = 159BASIC_LDFLAGS =
160 160
161# Guard against environment variables 161# Guard against environment variables
@@ -354,6 +354,7 @@ LIB_OBJS += $(OUTPUT)util/usage.o
354LIB_OBJS += $(OUTPUT)util/wrapper.o 354LIB_OBJS += $(OUTPUT)util/wrapper.o
355LIB_OBJS += $(OUTPUT)util/sigchain.o 355LIB_OBJS += $(OUTPUT)util/sigchain.o
356LIB_OBJS += $(OUTPUT)util/symbol.o 356LIB_OBJS += $(OUTPUT)util/symbol.o
357LIB_OBJS += $(OUTPUT)util/dso-test-data.o
357LIB_OBJS += $(OUTPUT)util/color.o 358LIB_OBJS += $(OUTPUT)util/color.o
358LIB_OBJS += $(OUTPUT)util/pager.o 359LIB_OBJS += $(OUTPUT)util/pager.o
359LIB_OBJS += $(OUTPUT)util/header.o 360LIB_OBJS += $(OUTPUT)util/header.o
@@ -503,6 +504,7 @@ else
503 LIB_OBJS += $(OUTPUT)ui/progress.o 504 LIB_OBJS += $(OUTPUT)ui/progress.o
504 LIB_OBJS += $(OUTPUT)ui/util.o 505 LIB_OBJS += $(OUTPUT)ui/util.o
505 LIB_OBJS += $(OUTPUT)ui/tui/setup.o 506 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
507 LIB_OBJS += $(OUTPUT)ui/tui/util.o
506 LIB_H += ui/browser.h 508 LIB_H += ui/browser.h
507 LIB_H += ui/browsers/map.h 509 LIB_H += ui/browsers/map.h
508 LIB_H += ui/helpline.h 510 LIB_H += ui/helpline.h
@@ -522,13 +524,18 @@ else
522 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 524 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
523 BASIC_CFLAGS += -DNO_GTK2_SUPPORT 525 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
524 else 526 else
527 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
528 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
529 endif
525 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0) 530 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
526 EXTLIBS += $(shell pkg-config --libs gtk+-2.0) 531 EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
527 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o 532 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
528 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o 533 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
534 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
529 # Make sure that it'd be included only once. 535 # Make sure that it'd be included only once.
530 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),) 536 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
531 LIB_OBJS += $(OUTPUT)ui/setup.o 537 LIB_OBJS += $(OUTPUT)ui/setup.o
538 LIB_OBJS += $(OUTPUT)ui/util.o
532 endif 539 endif
533 endif 540 endif
534endif 541endif
@@ -797,6 +804,9 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
797$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 804$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
798 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 805 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
799 806
807$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
808 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $<
809
800$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS 810$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
801 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< 811 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
802 812
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 71557225bf92..02dad5d3359b 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -24,21 +24,21 @@
24static const char *length_str = "1MB"; 24static const char *length_str = "1MB";
25static const char *routine = "default"; 25static const char *routine = "default";
26static int iterations = 1; 26static int iterations = 1;
27static bool use_clock; 27static bool use_cycle;
28static int clock_fd; 28static int cycle_fd;
29static bool only_prefault; 29static bool only_prefault;
30static bool no_prefault; 30static bool no_prefault;
31 31
32static const struct option options[] = { 32static const struct option options[] = {
33 OPT_STRING('l', "length", &length_str, "1MB", 33 OPT_STRING('l', "length", &length_str, "1MB",
34 "Specify length of memory to copy. " 34 "Specify length of memory to copy. "
35 "available unit: B, MB, GB (upper and lower)"), 35 "Available units: B, KB, MB, GB and TB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default", 36 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"), 37 "Specify routine to copy"),
38 OPT_INTEGER('i', "iterations", &iterations, 38 OPT_INTEGER('i', "iterations", &iterations,
39 "repeat memcpy() invocation this number of times"), 39 "repeat memcpy() invocation this number of times"),
40 OPT_BOOLEAN('c', "clock", &use_clock, 40 OPT_BOOLEAN('c', "cycle", &use_cycle,
41 "Use CPU clock for measuring"), 41 "Use cycles event instead of gettimeofday() for measuring"),
42 OPT_BOOLEAN('o', "only-prefault", &only_prefault, 42 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
43 "Show only the result with page faults before memcpy()"), 43 "Show only the result with page faults before memcpy()"),
44 OPT_BOOLEAN('n', "no-prefault", &no_prefault, 44 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
@@ -76,27 +76,27 @@ static const char * const bench_mem_memcpy_usage[] = {
76 NULL 76 NULL
77}; 77};
78 78
79static struct perf_event_attr clock_attr = { 79static struct perf_event_attr cycle_attr = {
80 .type = PERF_TYPE_HARDWARE, 80 .type = PERF_TYPE_HARDWARE,
81 .config = PERF_COUNT_HW_CPU_CYCLES 81 .config = PERF_COUNT_HW_CPU_CYCLES
82}; 82};
83 83
84static void init_clock(void) 84static void init_cycle(void)
85{ 85{
86 clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); 86 cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
87 87
88 if (clock_fd < 0 && errno == ENOSYS) 88 if (cycle_fd < 0 && errno == ENOSYS)
89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
90 else 90 else
91 BUG_ON(clock_fd < 0); 91 BUG_ON(cycle_fd < 0);
92} 92}
93 93
94static u64 get_clock(void) 94static u64 get_cycle(void)
95{ 95{
96 int ret; 96 int ret;
97 u64 clk; 97 u64 clk;
98 98
99 ret = read(clock_fd, &clk, sizeof(u64)); 99 ret = read(cycle_fd, &clk, sizeof(u64));
100 BUG_ON(ret != sizeof(u64)); 100 BUG_ON(ret != sizeof(u64));
101 101
102 return clk; 102 return clk;
@@ -119,9 +119,9 @@ static void alloc_mem(void **dst, void **src, size_t length)
119 die("memory allocation failed - maybe length is too large?\n"); 119 die("memory allocation failed - maybe length is too large?\n");
120} 120}
121 121
122static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault) 122static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
123{ 123{
124 u64 clock_start = 0ULL, clock_end = 0ULL; 124 u64 cycle_start = 0ULL, cycle_end = 0ULL;
125 void *src = NULL, *dst = NULL; 125 void *src = NULL, *dst = NULL;
126 int i; 126 int i;
127 127
@@ -130,14 +130,14 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
130 if (prefault) 130 if (prefault)
131 fn(dst, src, len); 131 fn(dst, src, len);
132 132
133 clock_start = get_clock(); 133 cycle_start = get_cycle();
134 for (i = 0; i < iterations; ++i) 134 for (i = 0; i < iterations; ++i)
135 fn(dst, src, len); 135 fn(dst, src, len);
136 clock_end = get_clock(); 136 cycle_end = get_cycle();
137 137
138 free(src); 138 free(src);
139 free(dst); 139 free(dst);
140 return clock_end - clock_start; 140 return cycle_end - cycle_start;
141} 141}
142 142
143static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) 143static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
@@ -182,17 +182,17 @@ int bench_mem_memcpy(int argc, const char **argv,
182 int i; 182 int i;
183 size_t len; 183 size_t len;
184 double result_bps[2]; 184 double result_bps[2];
185 u64 result_clock[2]; 185 u64 result_cycle[2];
186 186
187 argc = parse_options(argc, argv, options, 187 argc = parse_options(argc, argv, options,
188 bench_mem_memcpy_usage, 0); 188 bench_mem_memcpy_usage, 0);
189 189
190 if (use_clock) 190 if (use_cycle)
191 init_clock(); 191 init_cycle();
192 192
193 len = (size_t)perf_atoll((char *)length_str); 193 len = (size_t)perf_atoll((char *)length_str);
194 194
195 result_clock[0] = result_clock[1] = 0ULL; 195 result_cycle[0] = result_cycle[1] = 0ULL;
196 result_bps[0] = result_bps[1] = 0.0; 196 result_bps[0] = result_bps[1] = 0.0;
197 197
198 if ((s64)len <= 0) { 198 if ((s64)len <= 0) {
@@ -223,11 +223,11 @@ int bench_mem_memcpy(int argc, const char **argv,
223 223
224 if (!only_prefault && !no_prefault) { 224 if (!only_prefault && !no_prefault) {
225 /* show both of results */ 225 /* show both of results */
226 if (use_clock) { 226 if (use_cycle) {
227 result_clock[0] = 227 result_cycle[0] =
228 do_memcpy_clock(routines[i].fn, len, false); 228 do_memcpy_cycle(routines[i].fn, len, false);
229 result_clock[1] = 229 result_cycle[1] =
230 do_memcpy_clock(routines[i].fn, len, true); 230 do_memcpy_cycle(routines[i].fn, len, true);
231 } else { 231 } else {
232 result_bps[0] = 232 result_bps[0] =
233 do_memcpy_gettimeofday(routines[i].fn, 233 do_memcpy_gettimeofday(routines[i].fn,
@@ -237,9 +237,9 @@ int bench_mem_memcpy(int argc, const char **argv,
237 len, true); 237 len, true);
238 } 238 }
239 } else { 239 } else {
240 if (use_clock) { 240 if (use_cycle) {
241 result_clock[pf] = 241 result_cycle[pf] =
242 do_memcpy_clock(routines[i].fn, 242 do_memcpy_cycle(routines[i].fn,
243 len, only_prefault); 243 len, only_prefault);
244 } else { 244 } else {
245 result_bps[pf] = 245 result_bps[pf] =
@@ -251,12 +251,12 @@ int bench_mem_memcpy(int argc, const char **argv,
251 switch (bench_format) { 251 switch (bench_format) {
252 case BENCH_FORMAT_DEFAULT: 252 case BENCH_FORMAT_DEFAULT:
253 if (!only_prefault && !no_prefault) { 253 if (!only_prefault && !no_prefault) {
254 if (use_clock) { 254 if (use_cycle) {
255 printf(" %14lf Clock/Byte\n", 255 printf(" %14lf Cycle/Byte\n",
256 (double)result_clock[0] 256 (double)result_cycle[0]
257 / (double)len); 257 / (double)len);
258 printf(" %14lf Clock/Byte (with prefault)\n", 258 printf(" %14lf Cycle/Byte (with prefault)\n",
259 (double)result_clock[1] 259 (double)result_cycle[1]
260 / (double)len); 260 / (double)len);
261 } else { 261 } else {
262 print_bps(result_bps[0]); 262 print_bps(result_bps[0]);
@@ -265,9 +265,9 @@ int bench_mem_memcpy(int argc, const char **argv,
265 printf(" (with prefault)\n"); 265 printf(" (with prefault)\n");
266 } 266 }
267 } else { 267 } else {
268 if (use_clock) { 268 if (use_cycle) {
269 printf(" %14lf Clock/Byte", 269 printf(" %14lf Cycle/Byte",
270 (double)result_clock[pf] 270 (double)result_cycle[pf]
271 / (double)len); 271 / (double)len);
272 } else 272 } else
273 print_bps(result_bps[pf]); 273 print_bps(result_bps[pf]);
@@ -277,17 +277,17 @@ int bench_mem_memcpy(int argc, const char **argv,
277 break; 277 break;
278 case BENCH_FORMAT_SIMPLE: 278 case BENCH_FORMAT_SIMPLE:
279 if (!only_prefault && !no_prefault) { 279 if (!only_prefault && !no_prefault) {
280 if (use_clock) { 280 if (use_cycle) {
281 printf("%lf %lf\n", 281 printf("%lf %lf\n",
282 (double)result_clock[0] / (double)len, 282 (double)result_cycle[0] / (double)len,
283 (double)result_clock[1] / (double)len); 283 (double)result_cycle[1] / (double)len);
284 } else { 284 } else {
285 printf("%lf %lf\n", 285 printf("%lf %lf\n",
286 result_bps[0], result_bps[1]); 286 result_bps[0], result_bps[1]);
287 } 287 }
288 } else { 288 } else {
289 if (use_clock) { 289 if (use_cycle) {
290 printf("%lf\n", (double)result_clock[pf] 290 printf("%lf\n", (double)result_cycle[pf]
291 / (double)len); 291 / (double)len);
292 } else 292 } else
293 printf("%lf\n", result_bps[pf]); 293 printf("%lf\n", result_bps[pf]);
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
index e9079185bd72..350cc9557265 100644
--- a/tools/perf/bench/mem-memset.c
+++ b/tools/perf/bench/mem-memset.c
@@ -24,21 +24,21 @@
24static const char *length_str = "1MB"; 24static const char *length_str = "1MB";
25static const char *routine = "default"; 25static const char *routine = "default";
26static int iterations = 1; 26static int iterations = 1;
27static bool use_clock; 27static bool use_cycle;
28static int clock_fd; 28static int cycle_fd;
29static bool only_prefault; 29static bool only_prefault;
30static bool no_prefault; 30static bool no_prefault;
31 31
32static const struct option options[] = { 32static const struct option options[] = {
33 OPT_STRING('l', "length", &length_str, "1MB", 33 OPT_STRING('l', "length", &length_str, "1MB",
34 "Specify length of memory to copy. " 34 "Specify length of memory to set. "
35 "available unit: B, MB, GB (upper and lower)"), 35 "Available units: B, KB, MB, GB and TB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default", 36 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"), 37 "Specify routine to set"),
38 OPT_INTEGER('i', "iterations", &iterations, 38 OPT_INTEGER('i', "iterations", &iterations,
39 "repeat memset() invocation this number of times"), 39 "repeat memset() invocation this number of times"),
40 OPT_BOOLEAN('c', "clock", &use_clock, 40 OPT_BOOLEAN('c', "cycle", &use_cycle,
41 "Use CPU clock for measuring"), 41 "Use cycles event instead of gettimeofday() for measuring"),
42 OPT_BOOLEAN('o', "only-prefault", &only_prefault, 42 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
43 "Show only the result with page faults before memset()"), 43 "Show only the result with page faults before memset()"),
44 OPT_BOOLEAN('n', "no-prefault", &no_prefault, 44 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
@@ -76,27 +76,27 @@ static const char * const bench_mem_memset_usage[] = {
76 NULL 76 NULL
77}; 77};
78 78
79static struct perf_event_attr clock_attr = { 79static struct perf_event_attr cycle_attr = {
80 .type = PERF_TYPE_HARDWARE, 80 .type = PERF_TYPE_HARDWARE,
81 .config = PERF_COUNT_HW_CPU_CYCLES 81 .config = PERF_COUNT_HW_CPU_CYCLES
82}; 82};
83 83
84static void init_clock(void) 84static void init_cycle(void)
85{ 85{
86 clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); 86 cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
87 87
88 if (clock_fd < 0 && errno == ENOSYS) 88 if (cycle_fd < 0 && errno == ENOSYS)
89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 89 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
90 else 90 else
91 BUG_ON(clock_fd < 0); 91 BUG_ON(cycle_fd < 0);
92} 92}
93 93
94static u64 get_clock(void) 94static u64 get_cycle(void)
95{ 95{
96 int ret; 96 int ret;
97 u64 clk; 97 u64 clk;
98 98
99 ret = read(clock_fd, &clk, sizeof(u64)); 99 ret = read(cycle_fd, &clk, sizeof(u64));
100 BUG_ON(ret != sizeof(u64)); 100 BUG_ON(ret != sizeof(u64));
101 101
102 return clk; 102 return clk;
@@ -115,9 +115,9 @@ static void alloc_mem(void **dst, size_t length)
115 die("memory allocation failed - maybe length is too large?\n"); 115 die("memory allocation failed - maybe length is too large?\n");
116} 116}
117 117
118static u64 do_memset_clock(memset_t fn, size_t len, bool prefault) 118static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault)
119{ 119{
120 u64 clock_start = 0ULL, clock_end = 0ULL; 120 u64 cycle_start = 0ULL, cycle_end = 0ULL;
121 void *dst = NULL; 121 void *dst = NULL;
122 int i; 122 int i;
123 123
@@ -126,13 +126,13 @@ static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
126 if (prefault) 126 if (prefault)
127 fn(dst, -1, len); 127 fn(dst, -1, len);
128 128
129 clock_start = get_clock(); 129 cycle_start = get_cycle();
130 for (i = 0; i < iterations; ++i) 130 for (i = 0; i < iterations; ++i)
131 fn(dst, i, len); 131 fn(dst, i, len);
132 clock_end = get_clock(); 132 cycle_end = get_cycle();
133 133
134 free(dst); 134 free(dst);
135 return clock_end - clock_start; 135 return cycle_end - cycle_start;
136} 136}
137 137
138static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) 138static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
@@ -176,17 +176,17 @@ int bench_mem_memset(int argc, const char **argv,
176 int i; 176 int i;
177 size_t len; 177 size_t len;
178 double result_bps[2]; 178 double result_bps[2];
179 u64 result_clock[2]; 179 u64 result_cycle[2];
180 180
181 argc = parse_options(argc, argv, options, 181 argc = parse_options(argc, argv, options,
182 bench_mem_memset_usage, 0); 182 bench_mem_memset_usage, 0);
183 183
184 if (use_clock) 184 if (use_cycle)
185 init_clock(); 185 init_cycle();
186 186
187 len = (size_t)perf_atoll((char *)length_str); 187 len = (size_t)perf_atoll((char *)length_str);
188 188
189 result_clock[0] = result_clock[1] = 0ULL; 189 result_cycle[0] = result_cycle[1] = 0ULL;
190 result_bps[0] = result_bps[1] = 0.0; 190 result_bps[0] = result_bps[1] = 0.0;
191 191
192 if ((s64)len <= 0) { 192 if ((s64)len <= 0) {
@@ -217,11 +217,11 @@ int bench_mem_memset(int argc, const char **argv,
217 217
218 if (!only_prefault && !no_prefault) { 218 if (!only_prefault && !no_prefault) {
219 /* show both of results */ 219 /* show both of results */
220 if (use_clock) { 220 if (use_cycle) {
221 result_clock[0] = 221 result_cycle[0] =
222 do_memset_clock(routines[i].fn, len, false); 222 do_memset_cycle(routines[i].fn, len, false);
223 result_clock[1] = 223 result_cycle[1] =
224 do_memset_clock(routines[i].fn, len, true); 224 do_memset_cycle(routines[i].fn, len, true);
225 } else { 225 } else {
226 result_bps[0] = 226 result_bps[0] =
227 do_memset_gettimeofday(routines[i].fn, 227 do_memset_gettimeofday(routines[i].fn,
@@ -231,9 +231,9 @@ int bench_mem_memset(int argc, const char **argv,
231 len, true); 231 len, true);
232 } 232 }
233 } else { 233 } else {
234 if (use_clock) { 234 if (use_cycle) {
235 result_clock[pf] = 235 result_cycle[pf] =
236 do_memset_clock(routines[i].fn, 236 do_memset_cycle(routines[i].fn,
237 len, only_prefault); 237 len, only_prefault);
238 } else { 238 } else {
239 result_bps[pf] = 239 result_bps[pf] =
@@ -245,12 +245,12 @@ int bench_mem_memset(int argc, const char **argv,
245 switch (bench_format) { 245 switch (bench_format) {
246 case BENCH_FORMAT_DEFAULT: 246 case BENCH_FORMAT_DEFAULT:
247 if (!only_prefault && !no_prefault) { 247 if (!only_prefault && !no_prefault) {
248 if (use_clock) { 248 if (use_cycle) {
249 printf(" %14lf Clock/Byte\n", 249 printf(" %14lf Cycle/Byte\n",
250 (double)result_clock[0] 250 (double)result_cycle[0]
251 / (double)len); 251 / (double)len);
252 printf(" %14lf Clock/Byte (with prefault)\n ", 252 printf(" %14lf Cycle/Byte (with prefault)\n ",
253 (double)result_clock[1] 253 (double)result_cycle[1]
254 / (double)len); 254 / (double)len);
255 } else { 255 } else {
256 print_bps(result_bps[0]); 256 print_bps(result_bps[0]);
@@ -259,9 +259,9 @@ int bench_mem_memset(int argc, const char **argv,
259 printf(" (with prefault)\n"); 259 printf(" (with prefault)\n");
260 } 260 }
261 } else { 261 } else {
262 if (use_clock) { 262 if (use_cycle) {
263 printf(" %14lf Clock/Byte", 263 printf(" %14lf Cycle/Byte",
264 (double)result_clock[pf] 264 (double)result_cycle[pf]
265 / (double)len); 265 / (double)len);
266 } else 266 } else
267 print_bps(result_bps[pf]); 267 print_bps(result_bps[pf]);
@@ -271,17 +271,17 @@ int bench_mem_memset(int argc, const char **argv,
271 break; 271 break;
272 case BENCH_FORMAT_SIMPLE: 272 case BENCH_FORMAT_SIMPLE:
273 if (!only_prefault && !no_prefault) { 273 if (!only_prefault && !no_prefault) {
274 if (use_clock) { 274 if (use_cycle) {
275 printf("%lf %lf\n", 275 printf("%lf %lf\n",
276 (double)result_clock[0] / (double)len, 276 (double)result_cycle[0] / (double)len,
277 (double)result_clock[1] / (double)len); 277 (double)result_cycle[1] / (double)len);
278 } else { 278 } else {
279 printf("%lf %lf\n", 279 printf("%lf %lf\n",
280 result_bps[0], result_bps[1]); 280 result_bps[0], result_bps[1]);
281 } 281 }
282 } else { 282 } else {
283 if (use_clock) { 283 if (use_cycle) {
284 printf("%lf\n", (double)result_clock[pf] 284 printf("%lf\n", (double)result_cycle[pf]
285 / (double)len); 285 / (double)len);
286 } else 286 } else
287 printf("%lf\n", result_bps[pf]); 287 printf("%lf\n", result_bps[pf]);
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index b0e74ab2d7a2..1f3100216448 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -33,7 +33,7 @@ struct bench_suite {
33}; 33};
34 \ 34 \
35/* sentinel: easy for help */ 35/* sentinel: easy for help */
36#define suite_all { "all", "test all suite (pseudo suite)", NULL } 36#define suite_all { "all", "Test all benchmark suites", NULL }
37 37
38static struct bench_suite sched_suites[] = { 38static struct bench_suite sched_suites[] = {
39 { "messaging", 39 { "messaging",
@@ -75,7 +75,7 @@ static struct bench_subsys subsystems[] = {
75 "memory access performance", 75 "memory access performance",
76 mem_suites }, 76 mem_suites },
77 { "all", /* sentinel: easy for help */ 77 { "all", /* sentinel: easy for help */
78 "test all subsystem (pseudo subsystem)", 78 "all benchmark subsystem",
79 NULL }, 79 NULL },
80 { NULL, 80 { NULL,
81 NULL, 81 NULL,
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index acd78dc28341..0dd5a058f766 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -60,7 +60,7 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
60 list_for_each_entry(pos, &session->evlist->entries, node) { 60 list_for_each_entry(pos, &session->evlist->entries, node) {
61 bool first = true; 61 bool first = true;
62 62
63 printf("%s", event_name(pos)); 63 printf("%s", perf_evsel__name(pos));
64 64
65 if (details->verbose || details->freq) { 65 if (details->verbose || details->freq) {
66 comma_printf(&first, " sample_freq=%" PRIu64, 66 comma_printf(&first, " sample_freq=%" PRIu64,
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 547af48deb4f..ce35015f2dc6 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -57,6 +57,11 @@ static unsigned long nr_allocs, nr_cross_allocs;
57 57
58#define PATH_SYS_NODE "/sys/devices/system/node" 58#define PATH_SYS_NODE "/sys/devices/system/node"
59 59
60struct perf_kmem {
61 struct perf_tool tool;
62 struct perf_session *session;
63};
64
60static void init_cpunode_map(void) 65static void init_cpunode_map(void)
61{ 66{
62 FILE *fp; 67 FILE *fp;
@@ -278,14 +283,16 @@ static void process_free_event(void *data,
278 s_alloc->alloc_cpu = -1; 283 s_alloc->alloc_cpu = -1;
279} 284}
280 285
281static void process_raw_event(union perf_event *raw_event __used, void *data, 286static void process_raw_event(struct perf_tool *tool,
287 union perf_event *raw_event __used, void *data,
282 int cpu, u64 timestamp, struct thread *thread) 288 int cpu, u64 timestamp, struct thread *thread)
283{ 289{
290 struct perf_kmem *kmem = container_of(tool, struct perf_kmem, tool);
284 struct event_format *event; 291 struct event_format *event;
285 int type; 292 int type;
286 293
287 type = trace_parse_common_type(data); 294 type = trace_parse_common_type(kmem->session->pevent, data);
288 event = trace_find_event(type); 295 event = pevent_find_event(kmem->session->pevent, type);
289 296
290 if (!strcmp(event->name, "kmalloc") || 297 if (!strcmp(event->name, "kmalloc") ||
291 !strcmp(event->name, "kmem_cache_alloc")) { 298 !strcmp(event->name, "kmem_cache_alloc")) {
@@ -306,7 +313,7 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
306 } 313 }
307} 314}
308 315
309static int process_sample_event(struct perf_tool *tool __used, 316static int process_sample_event(struct perf_tool *tool,
310 union perf_event *event, 317 union perf_event *event,
311 struct perf_sample *sample, 318 struct perf_sample *sample,
312 struct perf_evsel *evsel __used, 319 struct perf_evsel *evsel __used,
@@ -322,16 +329,18 @@ static int process_sample_event(struct perf_tool *tool __used,
322 329
323 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 330 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
324 331
325 process_raw_event(event, sample->raw_data, sample->cpu, 332 process_raw_event(tool, event, sample->raw_data, sample->cpu,
326 sample->time, thread); 333 sample->time, thread);
327 334
328 return 0; 335 return 0;
329} 336}
330 337
331static struct perf_tool perf_kmem = { 338static struct perf_kmem perf_kmem = {
332 .sample = process_sample_event, 339 .tool = {
333 .comm = perf_event__process_comm, 340 .sample = process_sample_event,
334 .ordered_samples = true, 341 .comm = perf_event__process_comm,
342 .ordered_samples = true,
343 },
335}; 344};
336 345
337static double fragmentation(unsigned long n_req, unsigned long n_alloc) 346static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -486,11 +495,15 @@ static void sort_result(void)
486static int __cmd_kmem(void) 495static int __cmd_kmem(void)
487{ 496{
488 int err = -EINVAL; 497 int err = -EINVAL;
489 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 498 struct perf_session *session;
490 0, false, &perf_kmem); 499
500 session = perf_session__new(input_name, O_RDONLY, 0, false,
501 &perf_kmem.tool);
491 if (session == NULL) 502 if (session == NULL)
492 return -ENOMEM; 503 return -ENOMEM;
493 504
505 perf_kmem.session = session;
506
494 if (perf_session__create_kernel_maps(session) < 0) 507 if (perf_session__create_kernel_maps(session) < 0)
495 goto out_delete; 508 goto out_delete;
496 509
@@ -498,7 +511,7 @@ static int __cmd_kmem(void)
498 goto out_delete; 511 goto out_delete;
499 512
500 setup_pager(); 513 setup_pager();
501 err = perf_session__process_events(session, &perf_kmem); 514 err = perf_session__process_events(session, &perf_kmem.tool);
502 if (err != 0) 515 if (err != 0)
503 goto out_delete; 516 goto out_delete;
504 sort_result(); 517 sort_result();
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index fd53319de20d..b3c428548868 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -724,8 +724,8 @@ process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
724 struct event_format *event; 724 struct event_format *event;
725 int type; 725 int type;
726 726
727 type = trace_parse_common_type(data); 727 type = trace_parse_common_type(session->pevent, data);
728 event = trace_find_event(type); 728 event = pevent_find_event(session->pevent, type);
729 729
730 if (!strcmp(event->name, "lock_acquire")) 730 if (!strcmp(event->name, "lock_acquire"))
731 process_lock_acquire_event(data, event, cpu, timestamp, thread); 731 process_lock_acquire_event(data, event, cpu, timestamp, thread);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f95840d04e4c..f5a6452931e6 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -265,7 +265,7 @@ try_again:
265 265
266 if (err == ENOENT) { 266 if (err == ENOENT) {
267 ui__error("The %s event is not supported.\n", 267 ui__error("The %s event is not supported.\n",
268 event_name(pos)); 268 perf_evsel__name(pos));
269 exit(EXIT_FAILURE); 269 exit(EXIT_FAILURE);
270 } 270 }
271 271
@@ -916,7 +916,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
916 usage_with_options(record_usage, record_options); 916 usage_with_options(record_usage, record_options);
917 917
918 list_for_each_entry(pos, &evsel_list->entries, node) { 918 list_for_each_entry(pos, &evsel_list->entries, node) {
919 if (perf_header__push_event(pos->attr.config, event_name(pos))) 919 if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
920 goto out_free_fd; 920 goto out_free_fd;
921 } 921 }
922 922
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8c767c6bca91..69b1c1185159 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -69,7 +69,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
69 69
70 if ((sort__has_parent || symbol_conf.use_callchain) 70 if ((sort__has_parent || symbol_conf.use_callchain)
71 && sample->callchain) { 71 && sample->callchain) {
72 err = machine__resolve_callchain(machine, evsel, al->thread, 72 err = machine__resolve_callchain(machine, al->thread,
73 sample->callchain, &parent); 73 sample->callchain, &parent);
74 if (err) 74 if (err)
75 return err; 75 return err;
@@ -140,7 +140,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
140 struct hist_entry *he; 140 struct hist_entry *he;
141 141
142 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { 142 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
143 err = machine__resolve_callchain(machine, evsel, al->thread, 143 err = machine__resolve_callchain(machine, al->thread,
144 sample->callchain, &parent); 144 sample->callchain, &parent);
145 if (err) 145 if (err)
146 return err; 146 return err;
@@ -152,7 +152,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
152 152
153 if (symbol_conf.use_callchain) { 153 if (symbol_conf.use_callchain) {
154 err = callchain_append(he->callchain, 154 err = callchain_append(he->callchain,
155 &evsel->hists.callchain_cursor, 155 &callchain_cursor,
156 sample->period); 156 sample->period);
157 if (err) 157 if (err)
158 return err; 158 return err;
@@ -162,7 +162,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
162 * so we don't allocated the extra space needed because the stdio 162 * so we don't allocated the extra space needed because the stdio
163 * code will not use it. 163 * code will not use it.
164 */ 164 */
165 if (al->sym != NULL && use_browser > 0) { 165 if (he->ms.sym != NULL && use_browser > 0) {
166 struct annotation *notes = symbol__annotation(he->ms.sym); 166 struct annotation *notes = symbol__annotation(he->ms.sym);
167 167
168 assert(evsel != NULL); 168 assert(evsel != NULL);
@@ -230,7 +230,7 @@ static int process_read_event(struct perf_tool *tool,
230 struct perf_report *rep = container_of(tool, struct perf_report, tool); 230 struct perf_report *rep = container_of(tool, struct perf_report, tool);
231 231
232 if (rep->show_threads) { 232 if (rep->show_threads) {
233 const char *name = evsel ? event_name(evsel) : "unknown"; 233 const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
234 perf_read_values_add_value(&rep->show_threads_values, 234 perf_read_values_add_value(&rep->show_threads_values,
235 event->read.pid, event->read.tid, 235 event->read.pid, event->read.tid,
236 event->read.id, 236 event->read.id,
@@ -239,17 +239,18 @@ static int process_read_event(struct perf_tool *tool,
239 } 239 }
240 240
241 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid, 241 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
242 evsel ? event_name(evsel) : "FAIL", 242 evsel ? perf_evsel__name(evsel) : "FAIL",
243 event->read.value); 243 event->read.value);
244 244
245 return 0; 245 return 0;
246} 246}
247 247
248/* For pipe mode, sample_type is not currently set */
248static int perf_report__setup_sample_type(struct perf_report *rep) 249static int perf_report__setup_sample_type(struct perf_report *rep)
249{ 250{
250 struct perf_session *self = rep->session; 251 struct perf_session *self = rep->session;
251 252
252 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { 253 if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
253 if (sort__has_parent) { 254 if (sort__has_parent) {
254 ui__error("Selected --sort parent, but no " 255 ui__error("Selected --sort parent, but no "
255 "callchain data. Did you call " 256 "callchain data. Did you call "
@@ -272,7 +273,8 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
272 } 273 }
273 274
274 if (sort__branch_mode == 1) { 275 if (sort__branch_mode == 1) {
275 if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) { 276 if (!self->fd_pipe &&
277 !(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
276 ui__error("Selected -b but no branch data. " 278 ui__error("Selected -b but no branch data. "
277 "Did you call perf record without -b?\n"); 279 "Did you call perf record without -b?\n");
278 return -1; 280 return -1;
@@ -314,7 +316,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
314 316
315 list_for_each_entry(pos, &evlist->entries, node) { 317 list_for_each_entry(pos, &evlist->entries, node) {
316 struct hists *hists = &pos->hists; 318 struct hists *hists = &pos->hists;
317 const char *evname = event_name(pos); 319 const char *evname = perf_evsel__name(pos);
318 320
319 hists__fprintf_nr_sample_events(hists, evname, stdout); 321 hists__fprintf_nr_sample_events(hists, evname, stdout);
320 hists__fprintf(hists, NULL, false, true, 0, 0, stdout); 322 hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index b125e07eb399..7a9ad2b1ee76 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -43,6 +43,11 @@ static u64 sleep_measurement_overhead;
43 43
44static unsigned long nr_tasks; 44static unsigned long nr_tasks;
45 45
46struct perf_sched {
47 struct perf_tool tool;
48 struct perf_session *session;
49};
50
46struct sched_atom; 51struct sched_atom;
47 52
48struct task_desc { 53struct task_desc {
@@ -1597,11 +1602,13 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1597 struct perf_evsel *evsel, 1602 struct perf_evsel *evsel,
1598 struct machine *machine) 1603 struct machine *machine)
1599{ 1604{
1605 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1606 struct pevent *pevent = sched->session->pevent;
1600 struct thread *thread = machine__findnew_thread(machine, sample->pid); 1607 struct thread *thread = machine__findnew_thread(machine, sample->pid);
1601 1608
1602 if (thread == NULL) { 1609 if (thread == NULL) {
1603 pr_debug("problem processing %s event, skipping it.\n", 1610 pr_debug("problem processing %s event, skipping it.\n",
1604 evsel->name); 1611 perf_evsel__name(evsel));
1605 return -1; 1612 return -1;
1606 } 1613 }
1607 1614
@@ -1612,7 +1619,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1612 tracepoint_handler f = evsel->handler.func; 1619 tracepoint_handler f = evsel->handler.func;
1613 1620
1614 if (evsel->handler.data == NULL) 1621 if (evsel->handler.data == NULL)
1615 evsel->handler.data = trace_find_event(evsel->attr.config); 1622 evsel->handler.data = pevent_find_event(pevent,
1623 evsel->attr.config);
1616 1624
1617 f(tool, evsel->handler.data, sample, machine, thread); 1625 f(tool, evsel->handler.data, sample, machine, thread);
1618 } 1626 }
@@ -1620,12 +1628,14 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1620 return 0; 1628 return 0;
1621} 1629}
1622 1630
1623static struct perf_tool perf_sched = { 1631static struct perf_sched perf_sched = {
1624 .sample = perf_sched__process_tracepoint_sample, 1632 .tool = {
1625 .comm = perf_event__process_comm, 1633 .sample = perf_sched__process_tracepoint_sample,
1626 .lost = perf_event__process_lost, 1634 .comm = perf_event__process_comm,
1627 .fork = perf_event__process_task, 1635 .lost = perf_event__process_lost,
1628 .ordered_samples = true, 1636 .fork = perf_event__process_task,
1637 .ordered_samples = true,
1638 },
1629}; 1639};
1630 1640
1631static void read_events(bool destroy, struct perf_session **psession) 1641static void read_events(bool destroy, struct perf_session **psession)
@@ -1640,16 +1650,20 @@ static void read_events(bool destroy, struct perf_session **psession)
1640 { "sched:sched_process_exit", process_sched_exit_event, }, 1650 { "sched:sched_process_exit", process_sched_exit_event, },
1641 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1651 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1642 }; 1652 };
1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 1653 struct perf_session *session;
1644 0, false, &perf_sched); 1654
1655 session = perf_session__new(input_name, O_RDONLY, 0, false,
1656 &perf_sched.tool);
1645 if (session == NULL) 1657 if (session == NULL)
1646 die("No Memory"); 1658 die("No Memory");
1647 1659
1648 err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers); 1660 perf_sched.session = session;
1661
1662 err = perf_session__set_tracepoints_handlers(session, handlers);
1649 assert(err == 0); 1663 assert(err == 0);
1650 1664
1651 if (perf_session__has_traces(session, "record -R")) { 1665 if (perf_session__has_traces(session, "record -R")) {
1652 err = perf_session__process_events(session, &perf_sched); 1666 err = perf_session__process_events(session, &perf_sched.tool);
1653 if (err) 1667 if (err)
1654 die("Failed to process events, error %d", err); 1668 die("Failed to process events, error %d", err);
1655 1669
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 8e395a538eb9..1e60ab70b2b1 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -28,6 +28,11 @@ static bool system_wide;
28static const char *cpu_list; 28static const char *cpu_list;
29static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 29static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
30 30
31struct perf_script {
32 struct perf_tool tool;
33 struct perf_session *session;
34};
35
31enum perf_output_field { 36enum perf_output_field {
32 PERF_OUTPUT_COMM = 1U << 0, 37 PERF_OUTPUT_COMM = 1U << 0,
33 PERF_OUTPUT_TID = 1U << 1, 38 PERF_OUTPUT_TID = 1U << 1,
@@ -137,10 +142,11 @@ static const char *output_field2str(enum perf_output_field field)
137 142
138#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) 143#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
139 144
140static int perf_event_attr__check_stype(struct perf_event_attr *attr, 145static int perf_evsel__check_stype(struct perf_evsel *evsel,
141 u64 sample_type, const char *sample_msg, 146 u64 sample_type, const char *sample_msg,
142 enum perf_output_field field) 147 enum perf_output_field field)
143{ 148{
149 struct perf_event_attr *attr = &evsel->attr;
144 int type = attr->type; 150 int type = attr->type;
145 const char *evname; 151 const char *evname;
146 152
@@ -148,7 +154,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
148 return 0; 154 return 0;
149 155
150 if (output[type].user_set) { 156 if (output[type].user_set) {
151 evname = __event_name(attr->type, attr->config); 157 evname = perf_evsel__name(evsel);
152 pr_err("Samples for '%s' event do not have %s attribute set. " 158 pr_err("Samples for '%s' event do not have %s attribute set. "
153 "Cannot print '%s' field.\n", 159 "Cannot print '%s' field.\n",
154 evname, sample_msg, output_field2str(field)); 160 evname, sample_msg, output_field2str(field));
@@ -157,7 +163,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
157 163
158 /* user did not ask for it explicitly so remove from the default list */ 164 /* user did not ask for it explicitly so remove from the default list */
159 output[type].fields &= ~field; 165 output[type].fields &= ~field;
160 evname = __event_name(attr->type, attr->config); 166 evname = perf_evsel__name(evsel);
161 pr_debug("Samples for '%s' event do not have %s attribute set. " 167 pr_debug("Samples for '%s' event do not have %s attribute set. "
162 "Skipping '%s' field.\n", 168 "Skipping '%s' field.\n",
163 evname, sample_msg, output_field2str(field)); 169 evname, sample_msg, output_field2str(field));
@@ -175,8 +181,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
175 return -EINVAL; 181 return -EINVAL;
176 182
177 if (PRINT_FIELD(IP)) { 183 if (PRINT_FIELD(IP)) {
178 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", 184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
179 PERF_OUTPUT_IP)) 185 PERF_OUTPUT_IP))
180 return -EINVAL; 186 return -EINVAL;
181 187
182 if (!no_callchain && 188 if (!no_callchain &&
@@ -185,8 +191,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
185 } 191 }
186 192
187 if (PRINT_FIELD(ADDR) && 193 if (PRINT_FIELD(ADDR) &&
188 perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR", 194 perf_evsel__check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
189 PERF_OUTPUT_ADDR)) 195 PERF_OUTPUT_ADDR))
190 return -EINVAL; 196 return -EINVAL;
191 197
192 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 198 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
@@ -208,18 +214,18 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
208 } 214 }
209 215
210 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 216 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
211 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", 217 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
212 PERF_OUTPUT_TID|PERF_OUTPUT_PID)) 218 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
213 return -EINVAL; 219 return -EINVAL;
214 220
215 if (PRINT_FIELD(TIME) && 221 if (PRINT_FIELD(TIME) &&
216 perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME", 222 perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
217 PERF_OUTPUT_TIME)) 223 PERF_OUTPUT_TIME))
218 return -EINVAL; 224 return -EINVAL;
219 225
220 if (PRINT_FIELD(CPU) && 226 if (PRINT_FIELD(CPU) &&
221 perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU", 227 perf_evsel__check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
222 PERF_OUTPUT_CPU)) 228 PERF_OUTPUT_CPU))
223 return -EINVAL; 229 return -EINVAL;
224 230
225 return 0; 231 return 0;
@@ -256,11 +262,13 @@ static int perf_session__check_output_opt(struct perf_session *session)
256 return 0; 262 return 0;
257} 263}
258 264
259static void print_sample_start(struct perf_sample *sample, 265static void print_sample_start(struct pevent *pevent,
266 struct perf_sample *sample,
260 struct thread *thread, 267 struct thread *thread,
261 struct perf_event_attr *attr) 268 struct perf_evsel *evsel)
262{ 269{
263 int type; 270 int type;
271 struct perf_event_attr *attr = &evsel->attr;
264 struct event_format *event; 272 struct event_format *event;
265 const char *evname = NULL; 273 const char *evname = NULL;
266 unsigned long secs; 274 unsigned long secs;
@@ -300,12 +308,18 @@ static void print_sample_start(struct perf_sample *sample,
300 308
301 if (PRINT_FIELD(EVNAME)) { 309 if (PRINT_FIELD(EVNAME)) {
302 if (attr->type == PERF_TYPE_TRACEPOINT) { 310 if (attr->type == PERF_TYPE_TRACEPOINT) {
303 type = trace_parse_common_type(sample->raw_data); 311 /*
304 event = trace_find_event(type); 312 * XXX Do we really need this here?
313 * perf_evlist__set_tracepoint_names should have done
314 * this already
315 */
316 type = trace_parse_common_type(pevent,
317 sample->raw_data);
318 event = pevent_find_event(pevent, type);
305 if (event) 319 if (event)
306 evname = event->name; 320 evname = event->name;
307 } else 321 } else
308 evname = __event_name(attr->type, attr->config); 322 evname = perf_evsel__name(evsel);
309 323
310 printf("%s: ", evname ? evname : "[unknown]"); 324 printf("%s: ", evname ? evname : "[unknown]");
311 } 325 }
@@ -387,7 +401,7 @@ static void print_sample_bts(union perf_event *event,
387 printf(" "); 401 printf(" ");
388 else 402 else
389 printf("\n"); 403 printf("\n");
390 perf_event__print_ip(event, sample, machine, evsel, 404 perf_event__print_ip(event, sample, machine,
391 PRINT_FIELD(SYM), PRINT_FIELD(DSO), 405 PRINT_FIELD(SYM), PRINT_FIELD(DSO),
392 PRINT_FIELD(SYMOFFSET)); 406 PRINT_FIELD(SYMOFFSET));
393 } 407 }
@@ -402,6 +416,7 @@ static void print_sample_bts(union perf_event *event,
402} 416}
403 417
404static void process_event(union perf_event *event __unused, 418static void process_event(union perf_event *event __unused,
419 struct pevent *pevent,
405 struct perf_sample *sample, 420 struct perf_sample *sample,
406 struct perf_evsel *evsel, 421 struct perf_evsel *evsel,
407 struct machine *machine, 422 struct machine *machine,
@@ -412,7 +427,7 @@ static void process_event(union perf_event *event __unused,
412 if (output[attr->type].fields == 0) 427 if (output[attr->type].fields == 0)
413 return; 428 return;
414 429
415 print_sample_start(sample, thread, attr); 430 print_sample_start(pevent, sample, thread, evsel);
416 431
417 if (is_bts_event(attr)) { 432 if (is_bts_event(attr)) {
418 print_sample_bts(event, sample, evsel, machine, thread); 433 print_sample_bts(event, sample, evsel, machine, thread);
@@ -420,7 +435,7 @@ static void process_event(union perf_event *event __unused,
420 } 435 }
421 436
422 if (PRINT_FIELD(TRACE)) 437 if (PRINT_FIELD(TRACE))
423 print_trace_event(sample->cpu, sample->raw_data, 438 print_trace_event(pevent, sample->cpu, sample->raw_data,
424 sample->raw_size); 439 sample->raw_size);
425 440
426 if (PRINT_FIELD(ADDR)) 441 if (PRINT_FIELD(ADDR))
@@ -431,7 +446,7 @@ static void process_event(union perf_event *event __unused,
431 printf(" "); 446 printf(" ");
432 else 447 else
433 printf("\n"); 448 printf("\n");
434 perf_event__print_ip(event, sample, machine, evsel, 449 perf_event__print_ip(event, sample, machine,
435 PRINT_FIELD(SYM), PRINT_FIELD(DSO), 450 PRINT_FIELD(SYM), PRINT_FIELD(DSO),
436 PRINT_FIELD(SYMOFFSET)); 451 PRINT_FIELD(SYMOFFSET));
437 } 452 }
@@ -451,7 +466,8 @@ static int default_stop_script(void)
451 return 0; 466 return 0;
452} 467}
453 468
454static int default_generate_script(const char *outfile __unused) 469static int default_generate_script(struct pevent *pevent __unused,
470 const char *outfile __unused)
455{ 471{
456 return 0; 472 return 0;
457} 473}
@@ -489,6 +505,7 @@ static int process_sample_event(struct perf_tool *tool __used,
489 struct machine *machine) 505 struct machine *machine)
490{ 506{
491 struct addr_location al; 507 struct addr_location al;
508 struct perf_script *scr = container_of(tool, struct perf_script, tool);
492 struct thread *thread = machine__findnew_thread(machine, event->ip.tid); 509 struct thread *thread = machine__findnew_thread(machine, event->ip.tid);
493 510
494 if (thread == NULL) { 511 if (thread == NULL) {
@@ -520,24 +537,27 @@ static int process_sample_event(struct perf_tool *tool __used,
520 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 537 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
521 return 0; 538 return 0;
522 539
523 scripting_ops->process_event(event, sample, evsel, machine, thread); 540 scripting_ops->process_event(event, scr->session->pevent,
541 sample, evsel, machine, thread);
524 542
525 evsel->hists.stats.total_period += sample->period; 543 evsel->hists.stats.total_period += sample->period;
526 return 0; 544 return 0;
527} 545}
528 546
529static struct perf_tool perf_script = { 547static struct perf_script perf_script = {
530 .sample = process_sample_event, 548 .tool = {
531 .mmap = perf_event__process_mmap, 549 .sample = process_sample_event,
532 .comm = perf_event__process_comm, 550 .mmap = perf_event__process_mmap,
533 .exit = perf_event__process_task, 551 .comm = perf_event__process_comm,
534 .fork = perf_event__process_task, 552 .exit = perf_event__process_task,
535 .attr = perf_event__process_attr, 553 .fork = perf_event__process_task,
536 .event_type = perf_event__process_event_type, 554 .attr = perf_event__process_attr,
537 .tracing_data = perf_event__process_tracing_data, 555 .event_type = perf_event__process_event_type,
538 .build_id = perf_event__process_build_id, 556 .tracing_data = perf_event__process_tracing_data,
539 .ordered_samples = true, 557 .build_id = perf_event__process_build_id,
540 .ordering_requires_timestamps = true, 558 .ordered_samples = true,
559 .ordering_requires_timestamps = true,
560 },
541}; 561};
542 562
543extern volatile int session_done; 563extern volatile int session_done;
@@ -553,7 +573,7 @@ static int __cmd_script(struct perf_session *session)
553 573
554 signal(SIGINT, sig_handler); 574 signal(SIGINT, sig_handler);
555 575
556 ret = perf_session__process_events(session, &perf_script); 576 ret = perf_session__process_events(session, &perf_script.tool);
557 577
558 if (debug_mode) 578 if (debug_mode)
559 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 579 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1335,10 +1355,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1335 if (!script_name) 1355 if (!script_name)
1336 setup_pager(); 1356 setup_pager();
1337 1357
1338 session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_script); 1358 session = perf_session__new(input_name, O_RDONLY, 0, false,
1359 &perf_script.tool);
1339 if (session == NULL) 1360 if (session == NULL)
1340 return -ENOMEM; 1361 return -ENOMEM;
1341 1362
1363 perf_script.session = session;
1364
1342 if (cpu_list) { 1365 if (cpu_list) {
1343 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1366 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
1344 return -1; 1367 return -1;
@@ -1384,7 +1407,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1384 return -1; 1407 return -1;
1385 } 1408 }
1386 1409
1387 err = scripting_ops->generate_script("perf-script"); 1410 err = scripting_ops->generate_script(session->pevent,
1411 "perf-script");
1388 goto out; 1412 goto out;
1389 } 1413 }
1390 1414
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 62ae30d34fa6..861f0aec77ae 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -391,7 +391,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
391 391
392 if (verbose) { 392 if (verbose) {
393 fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 393 fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
394 event_name(counter), count[0], count[1], count[2]); 394 perf_evsel__name(counter), count[0], count[1], count[2]);
395 } 395 }
396 396
397 /* 397 /*
@@ -496,7 +496,7 @@ static int run_perf_stat(int argc __used, const char **argv)
496 errno == ENXIO) { 496 errno == ENXIO) {
497 if (verbose) 497 if (verbose)
498 ui__warning("%s event is not supported by the kernel.\n", 498 ui__warning("%s event is not supported by the kernel.\n",
499 event_name(counter)); 499 perf_evsel__name(counter));
500 counter->supported = false; 500 counter->supported = false;
501 continue; 501 continue;
502 } 502 }
@@ -594,7 +594,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
594 csv_output ? 0 : -4, 594 csv_output ? 0 : -4,
595 evsel_list->cpus->map[cpu], csv_sep); 595 evsel_list->cpus->map[cpu], csv_sep);
596 596
597 fprintf(output, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 597 fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
598 598
599 if (evsel->cgrp) 599 if (evsel->cgrp)
600 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 600 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -792,7 +792,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
792 else 792 else
793 cpu = 0; 793 cpu = 0;
794 794
795 fprintf(output, fmt, cpustr, avg, csv_sep, event_name(evsel)); 795 fprintf(output, fmt, cpustr, avg, csv_sep, perf_evsel__name(evsel));
796 796
797 if (evsel->cgrp) 797 if (evsel->cgrp)
798 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 798 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -908,7 +908,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
908 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 908 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
909 csv_sep, 909 csv_sep,
910 csv_output ? 0 : -24, 910 csv_output ? 0 : -24,
911 event_name(counter)); 911 perf_evsel__name(counter));
912 912
913 if (counter->cgrp) 913 if (counter->cgrp)
914 fprintf(output, "%s%s", csv_sep, counter->cgrp->name); 914 fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
@@ -961,7 +961,7 @@ static void print_counter(struct perf_evsel *counter)
961 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 961 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
962 csv_sep, 962 csv_sep,
963 csv_output ? 0 : -24, 963 csv_output ? 0 : -24,
964 event_name(counter)); 964 perf_evsel__name(counter));
965 965
966 if (counter->cgrp) 966 if (counter->cgrp)
967 fprintf(output, "%s%s", 967 fprintf(output, "%s%s",
@@ -1129,7 +1129,7 @@ static int add_default_attributes(void)
1129 return 0; 1129 return 0;
1130 1130
1131 if (!evsel_list->nr_entries) { 1131 if (!evsel_list->nr_entries) {
1132 if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0) 1132 if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0)
1133 return -1; 1133 return -1;
1134 } 1134 }
1135 1135
@@ -1139,21 +1139,21 @@ static int add_default_attributes(void)
1139 return 0; 1139 return 0;
1140 1140
1141 /* Append detailed run extra attributes: */ 1141 /* Append detailed run extra attributes: */
1142 if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0) 1142 if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0)
1143 return -1; 1143 return -1;
1144 1144
1145 if (detailed_run < 2) 1145 if (detailed_run < 2)
1146 return 0; 1146 return 0;
1147 1147
1148 /* Append very detailed run extra attributes: */ 1148 /* Append very detailed run extra attributes: */
1149 if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0) 1149 if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0)
1150 return -1; 1150 return -1;
1151 1151
1152 if (detailed_run < 3) 1152 if (detailed_run < 3)
1153 return 0; 1153 return 0;
1154 1154
1155 /* Append very, very detailed run extra attributes: */ 1155 /* Append very, very detailed run extra attributes: */
1156 return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs); 1156 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1157} 1157}
1158 1158
1159int cmd_stat(int argc, const char **argv, const char *prefix __used) 1159int cmd_stat(int argc, const char **argv, const char *prefix __used)
@@ -1179,6 +1179,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1179 fprintf(stderr, "cannot use both --output and --log-fd\n"); 1179 fprintf(stderr, "cannot use both --output and --log-fd\n");
1180 usage_with_options(stat_usage, options); 1180 usage_with_options(stat_usage, options);
1181 } 1181 }
1182
1183 if (output_fd < 0) {
1184 fprintf(stderr, "argument to --log-fd must be a > 0\n");
1185 usage_with_options(stat_usage, options);
1186 }
1187
1182 if (!output) { 1188 if (!output) {
1183 struct timespec tm; 1189 struct timespec tm;
1184 mode = append_file ? "a" : "w"; 1190 mode = append_file ? "a" : "w";
@@ -1190,7 +1196,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1190 } 1196 }
1191 clock_gettime(CLOCK_REALTIME, &tm); 1197 clock_gettime(CLOCK_REALTIME, &tm);
1192 fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); 1198 fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
1193 } else if (output_fd != 2) { 1199 } else if (output_fd > 0) {
1194 mode = append_file ? "a" : "w"; 1200 mode = append_file ? "a" : "w";
1195 output = fdopen(output_fd, mode); 1201 output = fdopen(output_fd, mode);
1196 if (!output) { 1202 if (!output) {
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 5a8727c08757..d909eb74a0eb 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -583,7 +583,7 @@ static int test__basic_mmap(void)
583 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 583 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
584 pr_debug("expected %d %s events, got %d\n", 584 pr_debug("expected %d %s events, got %d\n",
585 expected_nr_events[evsel->idx], 585 expected_nr_events[evsel->idx],
586 event_name(evsel), nr_events[evsel->idx]); 586 perf_evsel__name(evsel), nr_events[evsel->idx]);
587 goto out_munmap; 587 goto out_munmap;
588 } 588 }
589 } 589 }
@@ -1142,6 +1142,10 @@ static struct test {
1142 .func = test__perf_pmu, 1142 .func = test__perf_pmu,
1143 }, 1143 },
1144 { 1144 {
1145 .desc = "Test dso data interface",
1146 .func = dso__test_data,
1147 },
1148 {
1145 .func = NULL, 1149 .func = NULL,
1146 }, 1150 },
1147}; 1151};
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 871b540293e1..35e86c6df713 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -125,7 +125,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
125 /* 125 /*
126 * We can't annotate with just /proc/kallsyms 126 * We can't annotate with just /proc/kallsyms
127 */ 127 */
128 if (map->dso->symtab_type == SYMTAB__KALLSYMS) { 128 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
129 pr_err("Can't annotate %s: No vmlinux file was found in the " 129 pr_err("Can't annotate %s: No vmlinux file was found in the "
130 "path\n", sym->name); 130 "path\n", sym->name);
131 sleep(1); 131 sleep(1);
@@ -245,7 +245,7 @@ static void perf_top__show_details(struct perf_top *top)
245 if (notes->src == NULL) 245 if (notes->src == NULL)
246 goto out_unlock; 246 goto out_unlock;
247 247
248 printf("Showing %s for %s\n", event_name(top->sym_evsel), symbol->name); 248 printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
249 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter); 249 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
250 250
251 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx, 251 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
@@ -408,7 +408,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)
408 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries); 408 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries);
409 409
410 if (top->evlist->nr_entries > 1) 410 if (top->evlist->nr_entries > 1)
411 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top->sym_evsel)); 411 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", perf_evsel__name(top->sym_evsel));
412 412
413 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter); 413 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter);
414 414
@@ -503,13 +503,13 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
503 fprintf(stderr, "\nAvailable events:"); 503 fprintf(stderr, "\nAvailable events:");
504 504
505 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node) 505 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
506 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, event_name(top->sym_evsel)); 506 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
507 507
508 prompt_integer(&counter, "Enter details event counter"); 508 prompt_integer(&counter, "Enter details event counter");
509 509
510 if (counter >= top->evlist->nr_entries) { 510 if (counter >= top->evlist->nr_entries) {
511 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node); 511 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
512 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top->sym_evsel)); 512 fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel));
513 sleep(1); 513 sleep(1);
514 break; 514 break;
515 } 515 }
@@ -774,7 +774,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
774 774
775 if ((sort__has_parent || symbol_conf.use_callchain) && 775 if ((sort__has_parent || symbol_conf.use_callchain) &&
776 sample->callchain) { 776 sample->callchain) {
777 err = machine__resolve_callchain(machine, evsel, al.thread, 777 err = machine__resolve_callchain(machine, al.thread,
778 sample->callchain, &parent); 778 sample->callchain, &parent);
779 if (err) 779 if (err)
780 return; 780 return;
@@ -787,7 +787,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
787 } 787 }
788 788
789 if (symbol_conf.use_callchain) { 789 if (symbol_conf.use_callchain) {
790 err = callchain_append(he->callchain, &evsel->hists.callchain_cursor, 790 err = callchain_append(he->callchain, &callchain_cursor,
791 sample->period); 791 sample->period);
792 if (err) 792 if (err)
793 return; 793 return;
@@ -960,7 +960,7 @@ try_again:
960 960
961 if (err == ENOENT) { 961 if (err == ENOENT) {
962 ui__error("The %s event is not supported.\n", 962 ui__error("The %s event is not supported.\n",
963 event_name(counter)); 963 perf_evsel__name(counter));
964 goto out_err; 964 goto out_err;
965 } else if (err == EMFILE) { 965 } else if (err == EMFILE) {
966 ui__error("Too many events are opened.\n" 966 ui__error("Too many events are opened.\n"
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index d9084e03ce56..6c18785a6417 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -78,6 +78,19 @@ int main(int argc, char *argv[])
78 return 0; 78 return 0;
79} 79}
80endef 80endef
81
82define SOURCE_GTK2_INFOBAR
83#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
84#include <gtk/gtk.h>
85#pragma GCC diagnostic error \"-Wstrict-prototypes\"
86
87int main(void)
88{
89 gtk_info_bar_new();
90
91 return 0;
92}
93endef
81endif 94endif
82 95
83ifndef NO_LIBPERL 96ifndef NO_LIBPERL
diff --git a/tools/perf/design.txt b/tools/perf/design.txt
index bd0bb1b1279b..67e5d0cace85 100644
--- a/tools/perf/design.txt
+++ b/tools/perf/design.txt
@@ -409,14 +409,15 @@ Counters can be enabled and disabled in two ways: via ioctl and via
409prctl. When a counter is disabled, it doesn't count or generate 409prctl. When a counter is disabled, it doesn't count or generate
410events but does continue to exist and maintain its count value. 410events but does continue to exist and maintain its count value.
411 411
412An individual counter or counter group can be enabled with 412An individual counter can be enabled with
413 413
414 ioctl(fd, PERF_EVENT_IOC_ENABLE); 414 ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
415 415
416or disabled with 416or disabled with
417 417
418 ioctl(fd, PERF_EVENT_IOC_DISABLE); 418 ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
419 419
420For a counter group, pass PERF_IOC_FLAG_GROUP as the third argument.
420Enabling or disabling the leader of a group enables or disables the 421Enabling or disabling the leader of a group enables or disables the
421whole group; that is, while the group leader is disabled, none of the 422whole group; that is, while the group leader is disabled, none of the
422counters in the group will count. Enabling or disabling a member of a 423counters in the group will count. Enabling or disabling a member of a
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 4deea6aaf927..67a2703e666a 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -668,7 +668,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
668 "q/ESC/CTRL+C Exit\n\n" 668 "q/ESC/CTRL+C Exit\n\n"
669 "-> Go to target\n" 669 "-> Go to target\n"
670 "<- Exit\n" 670 "<- Exit\n"
671 "h Cycle thru hottest instructions\n" 671 "H Cycle thru hottest instructions\n"
672 "j Toggle showing jump to target arrows\n" 672 "j Toggle showing jump to target arrows\n"
673 "J Toggle showing number of jump sources on targets\n" 673 "J Toggle showing number of jump sources on targets\n"
674 "n Search next string\n" 674 "n Search next string\n"
@@ -814,7 +814,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
814{ 814{
815 struct disasm_line *pos, *n; 815 struct disasm_line *pos, *n;
816 struct annotation *notes; 816 struct annotation *notes;
817 const size_t size = symbol__size(sym); 817 size_t size;
818 struct map_symbol ms = { 818 struct map_symbol ms = {
819 .map = map, 819 .map = map,
820 .sym = sym, 820 .sym = sym,
@@ -834,6 +834,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
834 if (sym == NULL) 834 if (sym == NULL)
835 return -1; 835 return -1;
836 836
837 size = symbol__size(sym);
838
837 if (map->dso->annotate_warned) 839 if (map->dso->annotate_warned)
838 return -1; 840 return -1;
839 841
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 53f6697d014e..413bd62eedb1 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -23,6 +23,7 @@ struct hist_browser {
23 struct hists *hists; 23 struct hists *hists;
24 struct hist_entry *he_selection; 24 struct hist_entry *he_selection;
25 struct map_symbol *selection; 25 struct map_symbol *selection;
26 int print_seq;
26 bool has_symbols; 27 bool has_symbols;
27}; 28};
28 29
@@ -800,6 +801,196 @@ do_offset:
800 } 801 }
801} 802}
802 803
804static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
805 struct callchain_node *chain_node,
806 u64 total, int level,
807 FILE *fp)
808{
809 struct rb_node *node;
810 int offset = level * LEVEL_OFFSET_STEP;
811 u64 new_total, remaining;
812 int printed = 0;
813
814 if (callchain_param.mode == CHAIN_GRAPH_REL)
815 new_total = chain_node->children_hit;
816 else
817 new_total = total;
818
819 remaining = new_total;
820 node = rb_first(&chain_node->rb_root);
821 while (node) {
822 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
823 struct rb_node *next = rb_next(node);
824 u64 cumul = callchain_cumul_hits(child);
825 struct callchain_list *chain;
826 char folded_sign = ' ';
827 int first = true;
828 int extra_offset = 0;
829
830 remaining -= cumul;
831
832 list_for_each_entry(chain, &child->val, list) {
833 char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str;
834 const char *str;
835 bool was_first = first;
836
837 if (first)
838 first = false;
839 else
840 extra_offset = LEVEL_OFFSET_STEP;
841
842 folded_sign = callchain_list__folded(chain);
843
844 alloc_str = NULL;
845 str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
846 if (was_first) {
847 double percent = cumul * 100.0 / new_total;
848
849 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
850 str = "Not enough memory!";
851 else
852 str = alloc_str;
853 }
854
855 printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
856 free(alloc_str);
857 if (folded_sign == '+')
858 break;
859 }
860
861 if (folded_sign == '-') {
862 const int new_level = level + (extra_offset ? 2 : 1);
863 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
864 new_level, fp);
865 }
866
867 node = next;
868 }
869
870 return printed;
871}
872
873static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
874 struct callchain_node *node,
875 int level, FILE *fp)
876{
877 struct callchain_list *chain;
878 int offset = level * LEVEL_OFFSET_STEP;
879 char folded_sign = ' ';
880 int printed = 0;
881
882 list_for_each_entry(chain, &node->val, list) {
883 char ipstr[BITS_PER_LONG / 4 + 1], *s;
884
885 folded_sign = callchain_list__folded(chain);
886 s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
887 printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
888 }
889
890 if (folded_sign == '-')
891 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
892 browser->hists->stats.total_period,
893 level + 1, fp);
894 return printed;
895}
896
897static int hist_browser__fprintf_callchain(struct hist_browser *browser,
898 struct rb_root *chain, int level, FILE *fp)
899{
900 struct rb_node *nd;
901 int printed = 0;
902
903 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
904 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
905
906 printed += hist_browser__fprintf_callchain_node(browser, node, level, fp);
907 }
908
909 return printed;
910}
911
912static int hist_browser__fprintf_entry(struct hist_browser *browser,
913 struct hist_entry *he, FILE *fp)
914{
915 char s[8192];
916 double percent;
917 int printed = 0;
918 char folded_sign = ' ';
919
920 if (symbol_conf.use_callchain)
921 folded_sign = hist_entry__folded(he);
922
923 hist_entry__snprintf(he, s, sizeof(s), browser->hists);
924 percent = (he->period * 100.0) / browser->hists->stats.total_period;
925
926 if (symbol_conf.use_callchain)
927 printed += fprintf(fp, "%c ", folded_sign);
928
929 printed += fprintf(fp, " %5.2f%%", percent);
930
931 if (symbol_conf.show_nr_samples)
932 printed += fprintf(fp, " %11u", he->nr_events);
933
934 if (symbol_conf.show_total_period)
935 printed += fprintf(fp, " %12" PRIu64, he->period);
936
937 printed += fprintf(fp, "%s\n", rtrim(s));
938
939 if (folded_sign == '-')
940 printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp);
941
942 return printed;
943}
944
945static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp)
946{
947 struct rb_node *nd = hists__filter_entries(rb_first(browser->b.entries));
948 int printed = 0;
949
950 while (nd) {
951 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
952
953 printed += hist_browser__fprintf_entry(browser, h, fp);
954 nd = hists__filter_entries(rb_next(nd));
955 }
956
957 return printed;
958}
959
960static int hist_browser__dump(struct hist_browser *browser)
961{
962 char filename[64];
963 FILE *fp;
964
965 while (1) {
966 scnprintf(filename, sizeof(filename), "perf.hist.%d", browser->print_seq);
967 if (access(filename, F_OK))
968 break;
969 /*
970 * XXX: Just an arbitrary lazy upper limit
971 */
972 if (++browser->print_seq == 8192) {
973 ui_helpline__fpush("Too many perf.hist.N files, nothing written!");
974 return -1;
975 }
976 }
977
978 fp = fopen(filename, "w");
979 if (fp == NULL) {
980 char bf[64];
981 const char *err = strerror_r(errno, bf, sizeof(bf));
982 ui_helpline__fpush("Couldn't write to %s: %s", filename, err);
983 return -1;
984 }
985
986 ++browser->print_seq;
987 hist_browser__fprintf(browser, fp);
988 fclose(fp);
989 ui_helpline__fpush("%s written!", filename);
990
991 return 0;
992}
993
803static struct hist_browser *hist_browser__new(struct hists *hists) 994static struct hist_browser *hist_browser__new(struct hists *hists)
804{ 995{
805 struct hist_browser *browser = zalloc(sizeof(*browser)); 996 struct hist_browser *browser = zalloc(sizeof(*browser));
@@ -937,6 +1128,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
937 browser->selection->map->dso->annotate_warned) 1128 browser->selection->map->dso->annotate_warned)
938 continue; 1129 continue;
939 goto do_annotate; 1130 goto do_annotate;
1131 case 'P':
1132 hist_browser__dump(browser);
1133 continue;
940 case 'd': 1134 case 'd':
941 goto zoom_dso; 1135 goto zoom_dso;
942 case 't': 1136 case 't':
@@ -969,6 +1163,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
969 "E Expand all callchains\n" 1163 "E Expand all callchains\n"
970 "d Zoom into current DSO\n" 1164 "d Zoom into current DSO\n"
971 "t Zoom into current Thread\n" 1165 "t Zoom into current Thread\n"
1166 "P Print histograms to perf.hist.N\n"
972 "/ Filter symbol by name"); 1167 "/ Filter symbol by name");
973 continue; 1168 continue;
974 case K_ENTER: 1169 case K_ENTER:
@@ -1172,7 +1367,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1172 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); 1367 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
1173 bool current_entry = ui_browser__is_current_entry(browser, row); 1368 bool current_entry = ui_browser__is_current_entry(browser, row);
1174 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1369 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
1175 const char *ev_name = event_name(evsel); 1370 const char *ev_name = perf_evsel__name(evsel);
1176 char bf[256], unit; 1371 char bf[256], unit;
1177 const char *warn = " "; 1372 const char *warn = " ";
1178 size_t printed; 1373 size_t printed;
@@ -1240,7 +1435,7 @@ browse_hists:
1240 */ 1435 */
1241 if (timer) 1436 if (timer)
1242 timer(arg); 1437 timer(arg);
1243 ev_name = event_name(pos); 1438 ev_name = perf_evsel__name(pos);
1244 key = perf_evsel__hists_browse(pos, nr_events, help, 1439 key = perf_evsel__hists_browse(pos, nr_events, help,
1245 ev_name, true, timer, 1440 ev_name, true, timer,
1246 arg, delay_secs); 1441 arg, delay_secs);
@@ -1309,17 +1504,11 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1309 ui_helpline__push("Press ESC to exit"); 1504 ui_helpline__push("Press ESC to exit");
1310 1505
1311 list_for_each_entry(pos, &evlist->entries, node) { 1506 list_for_each_entry(pos, &evlist->entries, node) {
1312 const char *ev_name = event_name(pos); 1507 const char *ev_name = perf_evsel__name(pos);
1313 size_t line_len = strlen(ev_name) + 7; 1508 size_t line_len = strlen(ev_name) + 7;
1314 1509
1315 if (menu.b.width < line_len) 1510 if (menu.b.width < line_len)
1316 menu.b.width = line_len; 1511 menu.b.width = line_len;
1317 /*
1318 * Cache the evsel name, tracepoints have a _high_ cost per
1319 * event_name() call.
1320 */
1321 if (pos->name == NULL)
1322 pos->name = strdup(ev_name);
1323 } 1512 }
1324 1513
1325 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer, 1514 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer,
@@ -1330,11 +1519,10 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
1330 void(*timer)(void *arg), void *arg, 1519 void(*timer)(void *arg), void *arg,
1331 int delay_secs) 1520 int delay_secs)
1332{ 1521{
1333
1334 if (evlist->nr_entries == 1) { 1522 if (evlist->nr_entries == 1) {
1335 struct perf_evsel *first = list_entry(evlist->entries.next, 1523 struct perf_evsel *first = list_entry(evlist->entries.next,
1336 struct perf_evsel, node); 1524 struct perf_evsel, node);
1337 const char *ev_name = event_name(first); 1525 const char *ev_name = perf_evsel__name(first);
1338 return perf_evsel__hists_browse(first, evlist->nr_entries, help, 1526 return perf_evsel__hists_browse(first, evlist->nr_entries, help,
1339 ev_name, false, timer, arg, 1527 ev_name, false, timer, arg,
1340 delay_secs); 1528 delay_secs);
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 0656c381a89c..ec12e0b4ded6 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -11,8 +11,8 @@
11 11
12static void perf_gtk__signal(int sig) 12static void perf_gtk__signal(int sig)
13{ 13{
14 perf_gtk__exit(false);
14 psignal(sig, "perf"); 15 psignal(sig, "perf");
15 gtk_main_quit();
16} 16}
17 17
18static void perf_gtk__resize_window(GtkWidget *window) 18static void perf_gtk__resize_window(GtkWidget *window)
@@ -122,13 +122,59 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
122 gtk_container_add(GTK_CONTAINER(window), view); 122 gtk_container_add(GTK_CONTAINER(window), view);
123} 123}
124 124
125#ifdef HAVE_GTK_INFO_BAR
126static GtkWidget *perf_gtk__setup_info_bar(void)
127{
128 GtkWidget *info_bar;
129 GtkWidget *label;
130 GtkWidget *content_area;
131
132 info_bar = gtk_info_bar_new();
133 gtk_widget_set_no_show_all(info_bar, TRUE);
134
135 label = gtk_label_new("");
136 gtk_widget_show(label);
137
138 content_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(info_bar));
139 gtk_container_add(GTK_CONTAINER(content_area), label);
140
141 gtk_info_bar_add_button(GTK_INFO_BAR(info_bar), GTK_STOCK_OK,
142 GTK_RESPONSE_OK);
143 g_signal_connect(info_bar, "response",
144 G_CALLBACK(gtk_widget_hide), NULL);
145
146 pgctx->info_bar = info_bar;
147 pgctx->message_label = label;
148
149 return info_bar;
150}
151#endif
152
153static GtkWidget *perf_gtk__setup_statusbar(void)
154{
155 GtkWidget *stbar;
156 unsigned ctxid;
157
158 stbar = gtk_statusbar_new();
159
160 ctxid = gtk_statusbar_get_context_id(GTK_STATUSBAR(stbar),
161 "perf report");
162 pgctx->statbar = stbar;
163 pgctx->statbar_ctx_id = ctxid;
164
165 return stbar;
166}
167
125int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, 168int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
126 const char *help __used, 169 const char *help __used,
127 void (*timer) (void *arg)__used, 170 void (*timer) (void *arg)__used,
128 void *arg __used, int delay_secs __used) 171 void *arg __used, int delay_secs __used)
129{ 172{
130 struct perf_evsel *pos; 173 struct perf_evsel *pos;
174 GtkWidget *vbox;
131 GtkWidget *notebook; 175 GtkWidget *notebook;
176 GtkWidget *info_bar;
177 GtkWidget *statbar;
132 GtkWidget *window; 178 GtkWidget *window;
133 179
134 signal(SIGSEGV, perf_gtk__signal); 180 signal(SIGSEGV, perf_gtk__signal);
@@ -143,11 +189,17 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
143 189
144 g_signal_connect(window, "delete_event", gtk_main_quit, NULL); 190 g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
145 191
192 pgctx = perf_gtk__activate_context(window);
193 if (!pgctx)
194 return -1;
195
196 vbox = gtk_vbox_new(FALSE, 0);
197
146 notebook = gtk_notebook_new(); 198 notebook = gtk_notebook_new();
147 199
148 list_for_each_entry(pos, &evlist->entries, node) { 200 list_for_each_entry(pos, &evlist->entries, node) {
149 struct hists *hists = &pos->hists; 201 struct hists *hists = &pos->hists;
150 const char *evname = event_name(pos); 202 const char *evname = perf_evsel__name(pos);
151 GtkWidget *scrolled_window; 203 GtkWidget *scrolled_window;
152 GtkWidget *tab_label; 204 GtkWidget *tab_label;
153 205
@@ -164,7 +216,16 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
164 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label); 216 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
165 } 217 }
166 218
167 gtk_container_add(GTK_CONTAINER(window), notebook); 219 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
220
221 info_bar = perf_gtk__setup_info_bar();
222 if (info_bar)
223 gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
224
225 statbar = perf_gtk__setup_statusbar();
226 gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
227
228 gtk_container_add(GTK_CONTAINER(window), vbox);
168 229
169 gtk_widget_show_all(window); 230 gtk_widget_show_all(window);
170 231
@@ -174,5 +235,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
174 235
175 gtk_main(); 236 gtk_main();
176 237
238 perf_gtk__deactivate_context(&pgctx);
239
177 return 0; 240 return 0;
178} 241}
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 75177ee04032..a4d0f2b4a2dc 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -1,8 +1,39 @@
1#ifndef _PERF_GTK_H_ 1#ifndef _PERF_GTK_H_
2#define _PERF_GTK_H_ 1 2#define _PERF_GTK_H_ 1
3 3
4#include <stdbool.h>
5
4#pragma GCC diagnostic ignored "-Wstrict-prototypes" 6#pragma GCC diagnostic ignored "-Wstrict-prototypes"
5#include <gtk/gtk.h> 7#include <gtk/gtk.h>
6#pragma GCC diagnostic error "-Wstrict-prototypes" 8#pragma GCC diagnostic error "-Wstrict-prototypes"
7 9
10
11struct perf_gtk_context {
12 GtkWidget *main_window;
13
14#ifdef HAVE_GTK_INFO_BAR
15 GtkWidget *info_bar;
16 GtkWidget *message_label;
17#endif
18 GtkWidget *statbar;
19 guint statbar_ctx_id;
20};
21
22extern struct perf_gtk_context *pgctx;
23
24static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
25{
26 return ctx && ctx->main_window;
27}
28
29struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window);
30int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);
31
32#ifndef HAVE_GTK_INFO_BAR
33static inline GtkWidget *perf_gtk__setup_info_bar(void)
34{
35 return NULL;
36}
37#endif
38
8#endif /* _PERF_GTK_H_ */ 39#endif /* _PERF_GTK_H_ */
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 829529957766..92879ce61e2f 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -1,12 +1,17 @@
1#include "gtk.h" 1#include "gtk.h"
2#include "../../util/cache.h" 2#include "../../util/cache.h"
3#include "../../util/debug.h"
4
5extern struct perf_error_ops perf_gtk_eops;
3 6
4int perf_gtk__init(void) 7int perf_gtk__init(void)
5{ 8{
9 perf_error__register(&perf_gtk_eops);
6 return gtk_init_check(NULL, NULL) ? 0 : -1; 10 return gtk_init_check(NULL, NULL) ? 0 : -1;
7} 11}
8 12
9void perf_gtk__exit(bool wait_for_ok __used) 13void perf_gtk__exit(bool wait_for_ok __used)
10{ 14{
15 perf_error__unregister(&perf_gtk_eops);
11 gtk_main_quit(); 16 gtk_main_quit();
12} 17}
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
new file mode 100644
index 000000000000..0ead373c0dfb
--- /dev/null
+++ b/tools/perf/ui/gtk/util.c
@@ -0,0 +1,129 @@
1#include "../util.h"
2#include "../../util/debug.h"
3#include "gtk.h"
4
5#include <string.h>
6
7
8struct perf_gtk_context *pgctx;
9
10struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window)
11{
12 struct perf_gtk_context *ctx;
13
14 ctx = malloc(sizeof(*pgctx));
15 if (ctx)
16 ctx->main_window = window;
17
18 return ctx;
19}
20
21int perf_gtk__deactivate_context(struct perf_gtk_context **ctx)
22{
23 if (!perf_gtk__is_active_context(*ctx))
24 return -1;
25
26 free(*ctx);
27 *ctx = NULL;
28 return 0;
29}
30
31static int perf_gtk__error(const char *format, va_list args)
32{
33 char *msg;
34 GtkWidget *dialog;
35
36 if (!perf_gtk__is_active_context(pgctx) ||
37 vasprintf(&msg, format, args) < 0) {
38 fprintf(stderr, "Error:\n");
39 vfprintf(stderr, format, args);
40 fprintf(stderr, "\n");
41 return -1;
42 }
43
44 dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(pgctx->main_window),
45 GTK_DIALOG_DESTROY_WITH_PARENT,
46 GTK_MESSAGE_ERROR,
47 GTK_BUTTONS_CLOSE,
48 "<b>Error</b>\n\n%s", msg);
49 gtk_dialog_run(GTK_DIALOG(dialog));
50
51 gtk_widget_destroy(dialog);
52 free(msg);
53 return 0;
54}
55
56#ifdef HAVE_GTK_INFO_BAR
57static int perf_gtk__warning_info_bar(const char *format, va_list args)
58{
59 char *msg;
60
61 if (!perf_gtk__is_active_context(pgctx) ||
62 vasprintf(&msg, format, args) < 0) {
63 fprintf(stderr, "Warning:\n");
64 vfprintf(stderr, format, args);
65 fprintf(stderr, "\n");
66 return -1;
67 }
68
69 gtk_label_set_text(GTK_LABEL(pgctx->message_label), msg);
70 gtk_info_bar_set_message_type(GTK_INFO_BAR(pgctx->info_bar),
71 GTK_MESSAGE_WARNING);
72 gtk_widget_show(pgctx->info_bar);
73
74 free(msg);
75 return 0;
76}
77#else
78static int perf_gtk__warning_statusbar(const char *format, va_list args)
79{
80 char *msg, *p;
81
82 if (!perf_gtk__is_active_context(pgctx) ||
83 vasprintf(&msg, format, args) < 0) {
84 fprintf(stderr, "Warning:\n");
85 vfprintf(stderr, format, args);
86 fprintf(stderr, "\n");
87 return -1;
88 }
89
90 gtk_statusbar_pop(GTK_STATUSBAR(pgctx->statbar),
91 pgctx->statbar_ctx_id);
92
93 /* Only first line can be displayed */
94 p = strchr(msg, '\n');
95 if (p)
96 *p = '\0';
97
98 gtk_statusbar_push(GTK_STATUSBAR(pgctx->statbar),
99 pgctx->statbar_ctx_id, msg);
100
101 free(msg);
102 return 0;
103}
104#endif
105
106struct perf_error_ops perf_gtk_eops = {
107 .error = perf_gtk__error,
108#ifdef HAVE_GTK_INFO_BAR
109 .warning = perf_gtk__warning_info_bar,
110#else
111 .warning = perf_gtk__warning_statusbar,
112#endif
113};
114
115/*
116 * FIXME: Functions below should be implemented properly.
117 * For now, just add stubs for NO_NEWT=1 build.
118 */
119#ifdef NO_NEWT_SUPPORT
120int ui_helpline__show_help(const char *format __used, va_list ap __used)
121{
122 return 0;
123}
124
125void ui_progress__update(u64 curr __used, u64 total __used,
126 const char *title __used)
127{
128}
129#endif
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index d33e943ac434..e813c1d17346 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -15,6 +15,8 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
15 15
16static volatile int ui__need_resize; 16static volatile int ui__need_resize;
17 17
18extern struct perf_error_ops perf_tui_eops;
19
18void ui__refresh_dimensions(bool force) 20void ui__refresh_dimensions(bool force)
19{ 21{
20 if (force || ui__need_resize) { 22 if (force || ui__need_resize) {
@@ -122,6 +124,8 @@ int ui__init(void)
122 signal(SIGINT, ui__signal); 124 signal(SIGINT, ui__signal);
123 signal(SIGQUIT, ui__signal); 125 signal(SIGQUIT, ui__signal);
124 signal(SIGTERM, ui__signal); 126 signal(SIGTERM, ui__signal);
127
128 perf_error__register(&perf_tui_eops);
125out: 129out:
126 return err; 130 return err;
127} 131}
@@ -137,4 +141,6 @@ void ui__exit(bool wait_for_ok)
137 SLsmg_refresh(); 141 SLsmg_refresh();
138 SLsmg_reset_smg(); 142 SLsmg_reset_smg();
139 SLang_reset_tty(); 143 SLang_reset_tty();
144
145 perf_error__unregister(&perf_tui_eops);
140} 146}
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
new file mode 100644
index 000000000000..092902e30cee
--- /dev/null
+++ b/tools/perf/ui/tui/util.c
@@ -0,0 +1,243 @@
1#include "../../util/util.h"
2#include <signal.h>
3#include <stdbool.h>
4#include <string.h>
5#include <sys/ttydefaults.h>
6
7#include "../../util/cache.h"
8#include "../../util/debug.h"
9#include "../browser.h"
10#include "../keysyms.h"
11#include "../helpline.h"
12#include "../ui.h"
13#include "../util.h"
14#include "../libslang.h"
15
16static void ui_browser__argv_write(struct ui_browser *browser,
17 void *entry, int row)
18{
19 char **arg = entry;
20 bool current_entry = ui_browser__is_current_entry(browser, row);
21
22 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
23 HE_COLORSET_NORMAL);
24 slsmg_write_nstring(*arg, browser->width);
25}
26
27static int popup_menu__run(struct ui_browser *menu)
28{
29 int key;
30
31 if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
32 return -1;
33
34 while (1) {
35 key = ui_browser__run(menu, 0);
36
37 switch (key) {
38 case K_RIGHT:
39 case K_ENTER:
40 key = menu->index;
41 break;
42 case K_LEFT:
43 case K_ESC:
44 case 'q':
45 case CTRL('c'):
46 key = -1;
47 break;
48 default:
49 continue;
50 }
51
52 break;
53 }
54
55 ui_browser__hide(menu);
56 return key;
57}
58
59int ui__popup_menu(int argc, char * const argv[])
60{
61 struct ui_browser menu = {
62 .entries = (void *)argv,
63 .refresh = ui_browser__argv_refresh,
64 .seek = ui_browser__argv_seek,
65 .write = ui_browser__argv_write,
66 .nr_entries = argc,
67 };
68
69 return popup_menu__run(&menu);
70}
71
72int ui_browser__input_window(const char *title, const char *text, char *input,
73 const char *exit_msg, int delay_secs)
74{
75 int x, y, len, key;
76 int max_len = 60, nr_lines = 0;
77 static char buf[50];
78 const char *t;
79
80 t = text;
81 while (1) {
82 const char *sep = strchr(t, '\n');
83
84 if (sep == NULL)
85 sep = strchr(t, '\0');
86 len = sep - t;
87 if (max_len < len)
88 max_len = len;
89 ++nr_lines;
90 if (*sep == '\0')
91 break;
92 t = sep + 1;
93 }
94
95 max_len += 2;
96 nr_lines += 8;
97 y = SLtt_Screen_Rows / 2 - nr_lines / 2;
98 x = SLtt_Screen_Cols / 2 - max_len / 2;
99
100 SLsmg_set_color(0);
101 SLsmg_draw_box(y, x++, nr_lines, max_len);
102 if (title) {
103 SLsmg_gotorc(y, x + 1);
104 SLsmg_write_string((char *)title);
105 }
106 SLsmg_gotorc(++y, x);
107 nr_lines -= 7;
108 max_len -= 2;
109 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
110 nr_lines, max_len, 1);
111 y += nr_lines;
112 len = 5;
113 while (len--) {
114 SLsmg_gotorc(y + len - 1, x);
115 SLsmg_write_nstring((char *)" ", max_len);
116 }
117 SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
118
119 SLsmg_gotorc(y + 3, x);
120 SLsmg_write_nstring((char *)exit_msg, max_len);
121 SLsmg_refresh();
122
123 x += 2;
124 len = 0;
125 key = ui__getch(delay_secs);
126 while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
127 if (key == K_BKSPC) {
128 if (len == 0)
129 goto next_key;
130 SLsmg_gotorc(y, x + --len);
131 SLsmg_write_char(' ');
132 } else {
133 buf[len] = key;
134 SLsmg_gotorc(y, x + len++);
135 SLsmg_write_char(key);
136 }
137 SLsmg_refresh();
138
139 /* XXX more graceful overflow handling needed */
140 if (len == sizeof(buf) - 1) {
141 ui_helpline__push("maximum size of symbol name reached!");
142 key = K_ENTER;
143 break;
144 }
145next_key:
146 key = ui__getch(delay_secs);
147 }
148
149 buf[len] = '\0';
150 strncpy(input, buf, len+1);
151 return key;
152}
153
154int ui__question_window(const char *title, const char *text,
155 const char *exit_msg, int delay_secs)
156{
157 int x, y;
158 int max_len = 0, nr_lines = 0;
159 const char *t;
160
161 t = text;
162 while (1) {
163 const char *sep = strchr(t, '\n');
164 int len;
165
166 if (sep == NULL)
167 sep = strchr(t, '\0');
168 len = sep - t;
169 if (max_len < len)
170 max_len = len;
171 ++nr_lines;
172 if (*sep == '\0')
173 break;
174 t = sep + 1;
175 }
176
177 max_len += 2;
178 nr_lines += 4;
179 y = SLtt_Screen_Rows / 2 - nr_lines / 2,
180 x = SLtt_Screen_Cols / 2 - max_len / 2;
181
182 SLsmg_set_color(0);
183 SLsmg_draw_box(y, x++, nr_lines, max_len);
184 if (title) {
185 SLsmg_gotorc(y, x + 1);
186 SLsmg_write_string((char *)title);
187 }
188 SLsmg_gotorc(++y, x);
189 nr_lines -= 2;
190 max_len -= 2;
191 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
192 nr_lines, max_len, 1);
193 SLsmg_gotorc(y + nr_lines - 2, x);
194 SLsmg_write_nstring((char *)" ", max_len);
195 SLsmg_gotorc(y + nr_lines - 1, x);
196 SLsmg_write_nstring((char *)exit_msg, max_len);
197 SLsmg_refresh();
198 return ui__getch(delay_secs);
199}
200
201int ui__help_window(const char *text)
202{
203 return ui__question_window("Help", text, "Press any key...", 0);
204}
205
206int ui__dialog_yesno(const char *msg)
207{
208 return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
209}
210
211static int __ui__warning(const char *title, const char *format, va_list args)
212{
213 char *s;
214
215 if (vasprintf(&s, format, args) > 0) {
216 int key;
217
218 pthread_mutex_lock(&ui__lock);
219 key = ui__question_window(title, s, "Press any key...", 0);
220 pthread_mutex_unlock(&ui__lock);
221 free(s);
222 return key;
223 }
224
225 fprintf(stderr, "%s\n", title);
226 vfprintf(stderr, format, args);
227 return K_ESC;
228}
229
230static int perf_tui__error(const char *format, va_list args)
231{
232 return __ui__warning("Error:", format, args);
233}
234
235static int perf_tui__warning(const char *format, va_list args)
236{
237 return __ui__warning("Warning:", format, args);
238}
239
240struct perf_error_ops perf_tui_eops = {
241 .error = perf_tui__error,
242 .warning = perf_tui__warning,
243};
diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c
index ad4374a16bb0..4f989774c8c6 100644
--- a/tools/perf/ui/util.c
+++ b/tools/perf/ui/util.c
@@ -1,250 +1,85 @@
1#include "../util.h"
2#include <signal.h>
3#include <stdbool.h>
4#include <string.h>
5#include <sys/ttydefaults.h>
6
7#include "../cache.h"
8#include "../debug.h"
9#include "browser.h"
10#include "keysyms.h"
11#include "helpline.h"
12#include "ui.h"
13#include "util.h" 1#include "util.h"
14#include "libslang.h" 2#include "../debug.h"
15
16static void ui_browser__argv_write(struct ui_browser *browser,
17 void *entry, int row)
18{
19 char **arg = entry;
20 bool current_entry = ui_browser__is_current_entry(browser, row);
21
22 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
23 HE_COLORSET_NORMAL);
24 slsmg_write_nstring(*arg, browser->width);
25}
26
27static int popup_menu__run(struct ui_browser *menu)
28{
29 int key;
30
31 if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
32 return -1;
33 3
34 while (1) {
35 key = ui_browser__run(menu, 0);
36
37 switch (key) {
38 case K_RIGHT:
39 case K_ENTER:
40 key = menu->index;
41 break;
42 case K_LEFT:
43 case K_ESC:
44 case 'q':
45 case CTRL('c'):
46 key = -1;
47 break;
48 default:
49 continue;
50 }
51
52 break;
53 }
54
55 ui_browser__hide(menu);
56 return key;
57}
58 4
59int ui__popup_menu(int argc, char * const argv[]) 5/*
6 * Default error logging functions
7 */
8static int perf_stdio__error(const char *format, va_list args)
60{ 9{
61 struct ui_browser menu = { 10 fprintf(stderr, "Error:\n");
62 .entries = (void *)argv, 11 vfprintf(stderr, format, args);
63 .refresh = ui_browser__argv_refresh, 12 return 0;
64 .seek = ui_browser__argv_seek,
65 .write = ui_browser__argv_write,
66 .nr_entries = argc,
67 };
68
69 return popup_menu__run(&menu);
70} 13}
71 14
72int ui_browser__input_window(const char *title, const char *text, char *input, 15static int perf_stdio__warning(const char *format, va_list args)
73 const char *exit_msg, int delay_secs)
74{ 16{
75 int x, y, len, key; 17 fprintf(stderr, "Warning:\n");
76 int max_len = 60, nr_lines = 0; 18 vfprintf(stderr, format, args);
77 static char buf[50]; 19 return 0;
78 const char *t;
79
80 t = text;
81 while (1) {
82 const char *sep = strchr(t, '\n');
83
84 if (sep == NULL)
85 sep = strchr(t, '\0');
86 len = sep - t;
87 if (max_len < len)
88 max_len = len;
89 ++nr_lines;
90 if (*sep == '\0')
91 break;
92 t = sep + 1;
93 }
94
95 max_len += 2;
96 nr_lines += 8;
97 y = SLtt_Screen_Rows / 2 - nr_lines / 2;
98 x = SLtt_Screen_Cols / 2 - max_len / 2;
99
100 SLsmg_set_color(0);
101 SLsmg_draw_box(y, x++, nr_lines, max_len);
102 if (title) {
103 SLsmg_gotorc(y, x + 1);
104 SLsmg_write_string((char *)title);
105 }
106 SLsmg_gotorc(++y, x);
107 nr_lines -= 7;
108 max_len -= 2;
109 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
110 nr_lines, max_len, 1);
111 y += nr_lines;
112 len = 5;
113 while (len--) {
114 SLsmg_gotorc(y + len - 1, x);
115 SLsmg_write_nstring((char *)" ", max_len);
116 }
117 SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
118
119 SLsmg_gotorc(y + 3, x);
120 SLsmg_write_nstring((char *)exit_msg, max_len);
121 SLsmg_refresh();
122
123 x += 2;
124 len = 0;
125 key = ui__getch(delay_secs);
126 while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
127 if (key == K_BKSPC) {
128 if (len == 0)
129 goto next_key;
130 SLsmg_gotorc(y, x + --len);
131 SLsmg_write_char(' ');
132 } else {
133 buf[len] = key;
134 SLsmg_gotorc(y, x + len++);
135 SLsmg_write_char(key);
136 }
137 SLsmg_refresh();
138
139 /* XXX more graceful overflow handling needed */
140 if (len == sizeof(buf) - 1) {
141 ui_helpline__push("maximum size of symbol name reached!");
142 key = K_ENTER;
143 break;
144 }
145next_key:
146 key = ui__getch(delay_secs);
147 }
148
149 buf[len] = '\0';
150 strncpy(input, buf, len+1);
151 return key;
152} 20}
153 21
154int ui__question_window(const char *title, const char *text, 22static struct perf_error_ops default_eops =
155 const char *exit_msg, int delay_secs)
156{ 23{
157 int x, y; 24 .error = perf_stdio__error,
158 int max_len = 0, nr_lines = 0; 25 .warning = perf_stdio__warning,
159 const char *t; 26};
160
161 t = text;
162 while (1) {
163 const char *sep = strchr(t, '\n');
164 int len;
165
166 if (sep == NULL)
167 sep = strchr(t, '\0');
168 len = sep - t;
169 if (max_len < len)
170 max_len = len;
171 ++nr_lines;
172 if (*sep == '\0')
173 break;
174 t = sep + 1;
175 }
176
177 max_len += 2;
178 nr_lines += 4;
179 y = SLtt_Screen_Rows / 2 - nr_lines / 2,
180 x = SLtt_Screen_Cols / 2 - max_len / 2;
181
182 SLsmg_set_color(0);
183 SLsmg_draw_box(y, x++, nr_lines, max_len);
184 if (title) {
185 SLsmg_gotorc(y, x + 1);
186 SLsmg_write_string((char *)title);
187 }
188 SLsmg_gotorc(++y, x);
189 nr_lines -= 2;
190 max_len -= 2;
191 SLsmg_write_wrapped_string((unsigned char *)text, y, x,
192 nr_lines, max_len, 1);
193 SLsmg_gotorc(y + nr_lines - 2, x);
194 SLsmg_write_nstring((char *)" ", max_len);
195 SLsmg_gotorc(y + nr_lines - 1, x);
196 SLsmg_write_nstring((char *)exit_msg, max_len);
197 SLsmg_refresh();
198 return ui__getch(delay_secs);
199}
200 27
201int ui__help_window(const char *text) 28static struct perf_error_ops *perf_eops = &default_eops;
202{
203 return ui__question_window("Help", text, "Press any key...", 0);
204}
205 29
206int ui__dialog_yesno(const char *msg)
207{
208 return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
209}
210 30
211int __ui__warning(const char *title, const char *format, va_list args) 31int ui__error(const char *format, ...)
212{ 32{
213 char *s; 33 int ret;
214 34 va_list args;
215 if (use_browser > 0 && vasprintf(&s, format, args) > 0) {
216 int key;
217 35
218 pthread_mutex_lock(&ui__lock); 36 va_start(args, format);
219 key = ui__question_window(title, s, "Press any key...", 0); 37 ret = perf_eops->error(format, args);
220 pthread_mutex_unlock(&ui__lock); 38 va_end(args);
221 free(s);
222 return key;
223 }
224 39
225 fprintf(stderr, "%s:\n", title); 40 return ret;
226 vfprintf(stderr, format, args);
227 return K_ESC;
228} 41}
229 42
230int ui__warning(const char *format, ...) 43int ui__warning(const char *format, ...)
231{ 44{
232 int key; 45 int ret;
233 va_list args; 46 va_list args;
234 47
235 va_start(args, format); 48 va_start(args, format);
236 key = __ui__warning("Warning", format, args); 49 ret = perf_eops->warning(format, args);
237 va_end(args); 50 va_end(args);
238 return key; 51
52 return ret;
239} 53}
240 54
241int ui__error(const char *format, ...) 55
56/**
57 * perf_error__register - Register error logging functions
58 * @eops: The pointer to error logging function struct
59 *
60 * Register UI-specific error logging functions. Before calling this,
61 * other logging functions should be unregistered, if any.
62 */
63int perf_error__register(struct perf_error_ops *eops)
242{ 64{
243 int key; 65 if (perf_eops != &default_eops)
244 va_list args; 66 return -1;
245 67
246 va_start(args, format); 68 perf_eops = eops;
247 key = __ui__warning("Error", format, args); 69 return 0;
248 va_end(args); 70}
249 return key; 71
72/**
73 * perf_error__unregister - Unregister error logging functions
74 * @eops: The pointer to error logging function struct
75 *
76 * Unregister already registered error logging functions.
77 */
78int perf_error__unregister(struct perf_error_ops *eops)
79{
80 if (perf_eops != eops)
81 return -1;
82
83 perf_eops = &default_eops;
84 return 0;
250} 85}
diff --git a/tools/perf/ui/util.h b/tools/perf/ui/util.h
index 2d1738bd71c8..361f08c52d37 100644
--- a/tools/perf/ui/util.h
+++ b/tools/perf/ui/util.h
@@ -9,6 +9,13 @@ int ui__help_window(const char *text);
9int ui__dialog_yesno(const char *msg); 9int ui__dialog_yesno(const char *msg);
10int ui__question_window(const char *title, const char *text, 10int ui__question_window(const char *title, const char *text,
11 const char *exit_msg, int delay_secs); 11 const char *exit_msg, int delay_secs);
12int __ui__warning(const char *title, const char *format, va_list args); 12
13struct perf_error_ops {
14 int (*error)(const char *format, va_list args);
15 int (*warning)(const char *format, va_list args);
16};
17
18int perf_error__register(struct perf_error_ops *eops);
19int perf_error__unregister(struct perf_error_ops *eops);
13 20
14#endif /* _PERF_UI_UTIL_H_ */ 21#endif /* _PERF_UI_UTIL_H_ */
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index ad73300f7bac..95264f304179 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -12,7 +12,7 @@ LF='
12# First check if there is a .git to get the version from git describe 12# First check if there is a .git to get the version from git describe
13# otherwise try to get the version from the kernel makefile 13# otherwise try to get the version from the kernel makefile
14if test -d ../../.git -o -f ../../.git && 14if test -d ../../.git -o -f ../../.git &&
15 VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && 15 VN=$(git describe --match 'v[0-9].[0-9]*' --abbrev=4 HEAD 2>/dev/null) &&
16 case "$VN" in 16 case "$VN" in
17 *$LF*) (exit 1) ;; 17 *$LF*) (exit 1) ;;
18 v[0-9]*) 18 v[0-9]*)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 8069dfb5ba77..3a282c0057d2 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -426,7 +426,18 @@ int symbol__alloc_hist(struct symbol *sym)
426{ 426{
427 struct annotation *notes = symbol__annotation(sym); 427 struct annotation *notes = symbol__annotation(sym);
428 const size_t size = symbol__size(sym); 428 const size_t size = symbol__size(sym);
429 size_t sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); 429 size_t sizeof_sym_hist;
430
431 /* Check for overflow when calculating sizeof_sym_hist */
432 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64))
433 return -1;
434
435 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64));
436
437 /* Check for overflow in zalloc argument */
438 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
439 / symbol_conf.nr_events)
440 return -1;
430 441
431 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); 442 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
432 if (notes->src == NULL) 443 if (notes->src == NULL)
@@ -777,7 +788,7 @@ fallback:
777 free_filename = false; 788 free_filename = false;
778 } 789 }
779 790
780 if (dso->symtab_type == SYMTAB__KALLSYMS) { 791 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
781 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 792 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
782 char *build_id_msg = NULL; 793 char *build_id_msg = NULL;
783 794
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 9f7106a8d9a4..3a6bff47614f 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -18,6 +18,8 @@
18#include "util.h" 18#include "util.h"
19#include "callchain.h" 19#include "callchain.h"
20 20
21__thread struct callchain_cursor callchain_cursor;
22
21bool ip_callchain__valid(struct ip_callchain *chain, 23bool ip_callchain__valid(struct ip_callchain *chain,
22 const union perf_event *event) 24 const union perf_event *event)
23{ 25{
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 7f9c0f1ae3a9..3bdb407f9cd9 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -76,6 +76,8 @@ struct callchain_cursor {
76 struct callchain_cursor_node *curr; 76 struct callchain_cursor_node *curr;
77}; 77};
78 78
79extern __thread struct callchain_cursor callchain_cursor;
80
79static inline void callchain_init(struct callchain_root *root) 81static inline void callchain_init(struct callchain_root *root)
80{ 82{
81 INIT_LIST_HEAD(&root->node.siblings); 83 INIT_LIST_HEAD(&root->node.siblings);
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index efb1fce259a4..4dfe0bb3c322 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -47,7 +47,7 @@ int dump_printf(const char *fmt, ...)
47 return ret; 47 return ret;
48} 48}
49 49
50#ifdef NO_NEWT_SUPPORT 50#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
51int ui__warning(const char *format, ...) 51int ui__warning(const char *format, ...)
52{ 52{
53 va_list args; 53 va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 6bebe7f0a20c..015c91dbc096 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -12,8 +12,9 @@ int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
12void trace_event(union perf_event *event); 12void trace_event(union perf_event *event);
13 13
14struct ui_progress; 14struct ui_progress;
15struct perf_error_ops;
15 16
16#ifdef NO_NEWT_SUPPORT 17#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
17static inline int ui_helpline__show_help(const char *format __used, va_list ap __used) 18static inline int ui_helpline__show_help(const char *format __used, va_list ap __used)
18{ 19{
19 return 0; 20 return 0;
@@ -23,12 +24,28 @@ static inline void ui_progress__update(u64 curr __used, u64 total __used,
23 const char *title __used) {} 24 const char *title __used) {}
24 25
25#define ui__error(format, arg...) ui__warning(format, ##arg) 26#define ui__error(format, arg...) ui__warning(format, ##arg)
26#else 27
28static inline int
29perf_error__register(struct perf_error_ops *eops __used)
30{
31 return 0;
32}
33
34static inline int
35perf_error__unregister(struct perf_error_ops *eops __used)
36{
37 return 0;
38}
39
40#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
41
27extern char ui_helpline__last_msg[]; 42extern char ui_helpline__last_msg[];
28int ui_helpline__show_help(const char *format, va_list ap); 43int ui_helpline__show_help(const char *format, va_list ap);
29#include "../ui/progress.h" 44#include "../ui/progress.h"
30int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 45int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
31#endif 46#include "../ui/util.h"
47
48#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
32 49
33int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 50int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
34int ui__error_paranoid(void); 51int ui__error_paranoid(void);
diff --git a/tools/perf/util/dso-test-data.c b/tools/perf/util/dso-test-data.c
new file mode 100644
index 000000000000..541cdc72c7df
--- /dev/null
+++ b/tools/perf/util/dso-test-data.c
@@ -0,0 +1,153 @@
1#include "util.h"
2
3#include <stdlib.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <fcntl.h>
7#include <string.h>
8
9#include "symbol.h"
10
11#define TEST_ASSERT_VAL(text, cond) \
12do { \
13 if (!(cond)) { \
14 pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
15 return -1; \
16 } \
17} while (0)
18
19static char *test_file(int size)
20{
21 static char buf_templ[] = "/tmp/test-XXXXXX";
22 char *templ = buf_templ;
23 int fd, i;
24 unsigned char *buf;
25
26 fd = mkostemp(templ, O_CREAT|O_WRONLY|O_TRUNC);
27
28 buf = malloc(size);
29 if (!buf) {
30 close(fd);
31 return NULL;
32 }
33
34 for (i = 0; i < size; i++)
35 buf[i] = (unsigned char) ((int) i % 10);
36
37 if (size != write(fd, buf, size))
38 templ = NULL;
39
40 close(fd);
41 return templ;
42}
43
44#define TEST_FILE_SIZE (DSO__DATA_CACHE_SIZE * 20)
45
46struct test_data_offset {
47 off_t offset;
48 u8 data[10];
49 int size;
50};
51
52struct test_data_offset offsets[] = {
53 /* Fill first cache page. */
54 {
55 .offset = 10,
56 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
57 .size = 10,
58 },
59 /* Read first cache page. */
60 {
61 .offset = 10,
62 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
63 .size = 10,
64 },
65 /* Fill cache boundary pages. */
66 {
67 .offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10,
68 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
69 .size = 10,
70 },
71 /* Read cache boundary pages. */
72 {
73 .offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10,
74 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
75 .size = 10,
76 },
77 /* Fill final cache page. */
78 {
79 .offset = TEST_FILE_SIZE - 10,
80 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
81 .size = 10,
82 },
83 /* Read final cache page. */
84 {
85 .offset = TEST_FILE_SIZE - 10,
86 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
87 .size = 10,
88 },
89 /* Read final cache page. */
90 {
91 .offset = TEST_FILE_SIZE - 3,
92 .data = { 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 },
93 .size = 3,
94 },
95};
96
97int dso__test_data(void)
98{
99 struct machine machine;
100 struct dso *dso;
101 char *file = test_file(TEST_FILE_SIZE);
102 size_t i;
103
104 TEST_ASSERT_VAL("No test file", file);
105
106 memset(&machine, 0, sizeof(machine));
107
108 dso = dso__new((const char *)file);
109
110 /* Basic 10 bytes tests. */
111 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
112 struct test_data_offset *data = &offsets[i];
113 ssize_t size;
114 u8 buf[10];
115
116 memset(buf, 0, 10);
117 size = dso__data_read_offset(dso, &machine, data->offset,
118 buf, 10);
119
120 TEST_ASSERT_VAL("Wrong size", size == data->size);
121 TEST_ASSERT_VAL("Wrong data", !memcmp(buf, data->data, 10));
122 }
123
124 /* Read cross multiple cache pages. */
125 {
126 ssize_t size;
127 int c;
128 u8 *buf;
129
130 buf = malloc(TEST_FILE_SIZE);
131 TEST_ASSERT_VAL("ENOMEM\n", buf);
132
133 /* First iteration to fill caches, second one to read them. */
134 for (c = 0; c < 2; c++) {
135 memset(buf, 0, TEST_FILE_SIZE);
136 size = dso__data_read_offset(dso, &machine, 10,
137 buf, TEST_FILE_SIZE);
138
139 TEST_ASSERT_VAL("Wrong size",
140 size == (TEST_FILE_SIZE - 10));
141
142 for (i = 0; i < (size_t)size; i++)
143 TEST_ASSERT_VAL("Wrong data",
144 buf[i] == (i % 10));
145 }
146
147 free(buf);
148 }
149
150 dso__delete(dso);
151 unlink(file);
152 return 0;
153}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 4ac5f5ae4ce9..3edfd3483816 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -159,6 +159,17 @@ out_delete_partial_list:
159 return -1; 159 return -1;
160} 160}
161 161
162int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
163 struct perf_event_attr *attrs, size_t nr_attrs)
164{
165 size_t i;
166
167 for (i = 0; i < nr_attrs; i++)
168 event_attr_init(attrs + i);
169
170 return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
171}
172
162static int trace_event__id(const char *evname) 173static int trace_event__id(const char *evname)
163{ 174{
164 char *filename, *colon; 175 char *filename, *colon;
@@ -203,7 +214,7 @@ int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
203 attrs[i].type = PERF_TYPE_TRACEPOINT; 214 attrs[i].type = PERF_TYPE_TRACEPOINT;
204 attrs[i].config = err; 215 attrs[i].config = err;
205 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | 216 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
206 PERF_SAMPLE_CPU); 217 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
207 attrs[i].sample_period = 1; 218 attrs[i].sample_period = 1;
208 } 219 }
209 220
@@ -213,8 +224,8 @@ out_free_attrs:
213 return err; 224 return err;
214} 225}
215 226
216static struct perf_evsel * 227struct perf_evsel *
217 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 228perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
218{ 229{
219 struct perf_evsel *evsel; 230 struct perf_evsel *evsel;
220 231
@@ -263,7 +274,8 @@ void perf_evlist__disable(struct perf_evlist *evlist)
263 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 274 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
264 list_for_each_entry(pos, &evlist->entries, node) { 275 list_for_each_entry(pos, &evlist->entries, node) {
265 for (thread = 0; thread < evlist->threads->nr; thread++) 276 for (thread = 0; thread < evlist->threads->nr; thread++)
266 ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_DISABLE); 277 ioctl(FD(pos, cpu, thread),
278 PERF_EVENT_IOC_DISABLE, 0);
267 } 279 }
268 } 280 }
269} 281}
@@ -276,7 +288,8 @@ void perf_evlist__enable(struct perf_evlist *evlist)
276 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 288 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
277 list_for_each_entry(pos, &evlist->entries, node) { 289 list_for_each_entry(pos, &evlist->entries, node) {
278 for (thread = 0; thread < evlist->threads->nr; thread++) 290 for (thread = 0; thread < evlist->threads->nr; thread++)
279 ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_ENABLE); 291 ioctl(FD(pos, cpu, thread),
292 PERF_EVENT_IOC_ENABLE, 0);
280 } 293 }
281 } 294 }
282} 295}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 58abb63ac13a..40d4d3cdced0 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -54,6 +54,8 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
54int perf_evlist__add_default(struct perf_evlist *evlist); 54int perf_evlist__add_default(struct perf_evlist *evlist);
55int perf_evlist__add_attrs(struct perf_evlist *evlist, 55int perf_evlist__add_attrs(struct perf_evlist *evlist,
56 struct perf_event_attr *attrs, size_t nr_attrs); 56 struct perf_event_attr *attrs, size_t nr_attrs);
57int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
58 struct perf_event_attr *attrs, size_t nr_attrs);
57int perf_evlist__add_tracepoints(struct perf_evlist *evlist, 59int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
58 const char *tracepoints[], size_t nr_tracepoints); 60 const char *tracepoints[], size_t nr_tracepoints);
59int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, 61int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
@@ -62,6 +64,8 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
62 64
63#define perf_evlist__add_attrs_array(evlist, array) \ 65#define perf_evlist__add_attrs_array(evlist, array) \
64 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array)) 66 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
67#define perf_evlist__add_default_attrs(evlist, array) \
68 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
65 69
66#define perf_evlist__add_tracepoints_array(evlist, array) \ 70#define perf_evlist__add_tracepoints_array(evlist, array) \
67 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array)) 71 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
@@ -69,6 +73,9 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
69#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \ 73#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
70 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array)) 74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
71 75
76struct perf_evsel *
77perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
78
72void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 79void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
73 int cpu, int thread, u64 id); 80 int cpu, int thread, u64 id);
74 81
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 91d19138f3ec..e81771364867 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,7 +15,7 @@
15#include "cpumap.h" 15#include "cpumap.h"
16#include "thread_map.h" 16#include "thread_map.h"
17#include "target.h" 17#include "target.h"
18#include "../../include/linux/perf_event.h" 18#include "../../../include/linux/hw_breakpoint.h"
19 19
20#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 20#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
21#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) 21#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -78,7 +78,7 @@ static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
78 "ref-cycles", 78 "ref-cycles",
79}; 79};
80 80
81const char *__perf_evsel__hw_name(u64 config) 81static const char *__perf_evsel__hw_name(u64 config)
82{ 82{
83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) 83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
84 return perf_evsel__hw_names[config]; 84 return perf_evsel__hw_names[config];
@@ -86,16 +86,15 @@ const char *__perf_evsel__hw_name(u64 config)
86 return "unknown-hardware"; 86 return "unknown-hardware";
87} 87}
88 88
89static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) 89static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
90{ 90{
91 int colon = 0; 91 int colon = 0, r = 0;
92 struct perf_event_attr *attr = &evsel->attr; 92 struct perf_event_attr *attr = &evsel->attr;
93 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config));
94 bool exclude_guest_default = false; 93 bool exclude_guest_default = false;
95 94
96#define MOD_PRINT(context, mod) do { \ 95#define MOD_PRINT(context, mod) do { \
97 if (!attr->exclude_##context) { \ 96 if (!attr->exclude_##context) { \
98 if (!colon) colon = r++; \ 97 if (!colon) colon = ++r; \
99 r += scnprintf(bf + r, size - r, "%c", mod); \ 98 r += scnprintf(bf + r, size - r, "%c", mod); \
100 } } while(0) 99 } } while(0)
101 100
@@ -108,7 +107,7 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
108 107
109 if (attr->precise_ip) { 108 if (attr->precise_ip) {
110 if (!colon) 109 if (!colon)
111 colon = r++; 110 colon = ++r;
112 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); 111 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
113 exclude_guest_default = true; 112 exclude_guest_default = true;
114 } 113 }
@@ -119,39 +118,211 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
119 } 118 }
120#undef MOD_PRINT 119#undef MOD_PRINT
121 if (colon) 120 if (colon)
122 bf[colon] = ':'; 121 bf[colon - 1] = ':';
122 return r;
123}
124
125static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
126{
127 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
128 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
129}
130
131static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
132 "cpu-clock",
133 "task-clock",
134 "page-faults",
135 "context-switches",
136 "CPU-migrations",
137 "minor-faults",
138 "major-faults",
139 "alignment-faults",
140 "emulation-faults",
141};
142
143static const char *__perf_evsel__sw_name(u64 config)
144{
145 if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
146 return perf_evsel__sw_names[config];
147 return "unknown-software";
148}
149
150static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
151{
152 int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
153 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
154}
155
156static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
157{
158 int r;
159
160 r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
161
162 if (type & HW_BREAKPOINT_R)
163 r += scnprintf(bf + r, size - r, "r");
164
165 if (type & HW_BREAKPOINT_W)
166 r += scnprintf(bf + r, size - r, "w");
167
168 if (type & HW_BREAKPOINT_X)
169 r += scnprintf(bf + r, size - r, "x");
170
123 return r; 171 return r;
124} 172}
125 173
126int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size) 174static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
127{ 175{
128 int ret; 176 struct perf_event_attr *attr = &evsel->attr;
177 int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
178 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
179}
180
181const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
182 [PERF_EVSEL__MAX_ALIASES] = {
183 { "L1-dcache", "l1-d", "l1d", "L1-data", },
184 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
185 { "LLC", "L2", },
186 { "dTLB", "d-tlb", "Data-TLB", },
187 { "iTLB", "i-tlb", "Instruction-TLB", },
188 { "branch", "branches", "bpu", "btb", "bpc", },
189 { "node", },
190};
191
192const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
193 [PERF_EVSEL__MAX_ALIASES] = {
194 { "load", "loads", "read", },
195 { "store", "stores", "write", },
196 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
197};
198
199const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
200 [PERF_EVSEL__MAX_ALIASES] = {
201 { "refs", "Reference", "ops", "access", },
202 { "misses", "miss", },
203};
204
205#define C(x) PERF_COUNT_HW_CACHE_##x
206#define CACHE_READ (1 << C(OP_READ))
207#define CACHE_WRITE (1 << C(OP_WRITE))
208#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
209#define COP(x) (1 << x)
210
211/*
212 * cache operartion stat
213 * L1I : Read and prefetch only
214 * ITLB and BPU : Read-only
215 */
216static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
217 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
218 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
219 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
220 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
221 [C(ITLB)] = (CACHE_READ),
222 [C(BPU)] = (CACHE_READ),
223 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
224};
225
226bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
227{
228 if (perf_evsel__hw_cache_stat[type] & COP(op))
229 return true; /* valid */
230 else
231 return false; /* invalid */
232}
233
234int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
235 char *bf, size_t size)
236{
237 if (result) {
238 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
239 perf_evsel__hw_cache_op[op][0],
240 perf_evsel__hw_cache_result[result][0]);
241 }
242
243 return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
244 perf_evsel__hw_cache_op[op][1]);
245}
246
247static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
248{
249 u8 op, result, type = (config >> 0) & 0xff;
250 const char *err = "unknown-ext-hardware-cache-type";
251
252 if (type > PERF_COUNT_HW_CACHE_MAX)
253 goto out_err;
254
255 op = (config >> 8) & 0xff;
256 err = "unknown-ext-hardware-cache-op";
257 if (op > PERF_COUNT_HW_CACHE_OP_MAX)
258 goto out_err;
259
260 result = (config >> 16) & 0xff;
261 err = "unknown-ext-hardware-cache-result";
262 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
263 goto out_err;
264
265 err = "invalid-cache";
266 if (!perf_evsel__is_cache_op_valid(type, op))
267 goto out_err;
268
269 return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
270out_err:
271 return scnprintf(bf, size, "%s", err);
272}
273
274static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
275{
276 int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
277 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
278}
279
280static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
281{
282 int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
283 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
284}
285
286const char *perf_evsel__name(struct perf_evsel *evsel)
287{
288 char bf[128];
289
290 if (evsel->name)
291 return evsel->name;
129 292
130 switch (evsel->attr.type) { 293 switch (evsel->attr.type) {
131 case PERF_TYPE_RAW: 294 case PERF_TYPE_RAW:
132 ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); 295 perf_evsel__raw_name(evsel, bf, sizeof(bf));
133 break; 296 break;
134 297
135 case PERF_TYPE_HARDWARE: 298 case PERF_TYPE_HARDWARE:
136 ret = perf_evsel__hw_name(evsel, bf, size); 299 perf_evsel__hw_name(evsel, bf, sizeof(bf));
300 break;
301
302 case PERF_TYPE_HW_CACHE:
303 perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
304 break;
305
306 case PERF_TYPE_SOFTWARE:
307 perf_evsel__sw_name(evsel, bf, sizeof(bf));
308 break;
309
310 case PERF_TYPE_TRACEPOINT:
311 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
137 break; 312 break;
313
314 case PERF_TYPE_BREAKPOINT:
315 perf_evsel__bp_name(evsel, bf, sizeof(bf));
316 break;
317
138 default: 318 default:
139 /* 319 scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
140 * FIXME 320 break;
141 *
142 * This is the minimal perf_evsel__name so that we can
143 * reconstruct event names taking into account event modifiers.
144 *
145 * The old event_name uses it now for raw anr hw events, so that
146 * we don't drag all the parsing stuff into the python binding.
147 *
148 * On the next devel cycle the rest of the event naming will be
149 * brought here.
150 */
151 return 0;
152 } 321 }
153 322
154 return ret; 323 evsel->name = strdup(bf);
324
325 return evsel->name ?: "unknown";
155} 326}
156 327
157void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, 328void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
@@ -494,16 +665,24 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel,
494} 665}
495 666
496static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 667static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
497 struct perf_sample *sample) 668 struct perf_sample *sample,
669 bool swapped)
498{ 670{
499 const u64 *array = event->sample.array; 671 const u64 *array = event->sample.array;
672 union u64_swap u;
500 673
501 array += ((event->header.size - 674 array += ((event->header.size -
502 sizeof(event->header)) / sizeof(u64)) - 1; 675 sizeof(event->header)) / sizeof(u64)) - 1;
503 676
504 if (type & PERF_SAMPLE_CPU) { 677 if (type & PERF_SAMPLE_CPU) {
505 u32 *p = (u32 *)array; 678 u.val64 = *array;
506 sample->cpu = *p; 679 if (swapped) {
680 /* undo swap of u64, then swap on individual u32s */
681 u.val64 = bswap_64(u.val64);
682 u.val32[0] = bswap_32(u.val32[0]);
683 }
684
685 sample->cpu = u.val32[0];
507 array--; 686 array--;
508 } 687 }
509 688
@@ -523,9 +702,16 @@ static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
523 } 702 }
524 703
525 if (type & PERF_SAMPLE_TID) { 704 if (type & PERF_SAMPLE_TID) {
526 u32 *p = (u32 *)array; 705 u.val64 = *array;
527 sample->pid = p[0]; 706 if (swapped) {
528 sample->tid = p[1]; 707 /* undo swap of u64, then swap on individual u32s */
708 u.val64 = bswap_64(u.val64);
709 u.val32[0] = bswap_32(u.val32[0]);
710 u.val32[1] = bswap_32(u.val32[1]);
711 }
712
713 sample->pid = u.val32[0];
714 sample->tid = u.val32[1];
529 } 715 }
530 716
531 return 0; 717 return 0;
@@ -562,7 +748,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
562 if (event->header.type != PERF_RECORD_SAMPLE) { 748 if (event->header.type != PERF_RECORD_SAMPLE) {
563 if (!sample_id_all) 749 if (!sample_id_all)
564 return 0; 750 return 0;
565 return perf_event__parse_id_sample(event, type, data); 751 return perf_event__parse_id_sample(event, type, data, swapped);
566 } 752 }
567 753
568 array = event->sample.array; 754 array = event->sample.array;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4ba8b564e6f4..67cc5033d192 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -83,8 +83,19 @@ void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts, 83 struct perf_record_opts *opts,
84 struct perf_evsel *first); 84 struct perf_evsel *first);
85 85
86const char* __perf_evsel__hw_name(u64 config); 86bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
87int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size); 87
88#define PERF_EVSEL__MAX_ALIASES 8
89
90extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
91 [PERF_EVSEL__MAX_ALIASES];
92extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
93 [PERF_EVSEL__MAX_ALIASES];
94const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
95 [PERF_EVSEL__MAX_ALIASES];
96int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
97 char *bf, size_t size);
98const char *perf_evsel__name(struct perf_evsel *evsel);
88 99
89int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 100int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
90int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 101int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 2dd5edf161b7..3a6d20443330 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -641,7 +641,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
641 /* 641 /*
642 * write event string as passed on cmdline 642 * write event string as passed on cmdline
643 */ 643 */
644 ret = do_write_string(fd, event_name(attr)); 644 ret = do_write_string(fd, perf_evsel__name(attr));
645 if (ret < 0) 645 if (ret < 0)
646 return ret; 646 return ret;
647 /* 647 /*
@@ -1212,6 +1212,12 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1212 attr.exclude_user, 1212 attr.exclude_user,
1213 attr.exclude_kernel); 1213 attr.exclude_kernel);
1214 1214
1215 fprintf(fp, ", excl_host = %d, excl_guest = %d",
1216 attr.exclude_host,
1217 attr.exclude_guest);
1218
1219 fprintf(fp, ", precise_ip = %d", attr.precise_ip);
1220
1215 if (nr) 1221 if (nr)
1216 fprintf(fp, ", id = {"); 1222 fprintf(fp, ", id = {");
1217 1223
@@ -1474,15 +1480,15 @@ out:
1474 1480
1475static int process_tracing_data(struct perf_file_section *section __unused, 1481static int process_tracing_data(struct perf_file_section *section __unused,
1476 struct perf_header *ph __unused, 1482 struct perf_header *ph __unused,
1477 int feat __unused, int fd) 1483 int feat __unused, int fd, void *data)
1478{ 1484{
1479 trace_report(fd, false); 1485 trace_report(fd, data, false);
1480 return 0; 1486 return 0;
1481} 1487}
1482 1488
1483static int process_build_id(struct perf_file_section *section, 1489static int process_build_id(struct perf_file_section *section,
1484 struct perf_header *ph, 1490 struct perf_header *ph,
1485 int feat __unused, int fd) 1491 int feat __unused, int fd, void *data __used)
1486{ 1492{
1487 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1493 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1488 pr_debug("Failed to read buildids, continuing...\n"); 1494 pr_debug("Failed to read buildids, continuing...\n");
@@ -1493,7 +1499,7 @@ struct feature_ops {
1493 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1499 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1494 void (*print)(struct perf_header *h, int fd, FILE *fp); 1500 void (*print)(struct perf_header *h, int fd, FILE *fp);
1495 int (*process)(struct perf_file_section *section, 1501 int (*process)(struct perf_file_section *section,
1496 struct perf_header *h, int feat, int fd); 1502 struct perf_header *h, int feat, int fd, void *data);
1497 const char *name; 1503 const char *name;
1498 bool full_only; 1504 bool full_only;
1499}; 1505};
@@ -1942,7 +1948,6 @@ int perf_file_header__read(struct perf_file_header *header,
1942 else 1948 else
1943 return -1; 1949 return -1;
1944 } else if (ph->needs_swap) { 1950 } else if (ph->needs_swap) {
1945 unsigned int i;
1946 /* 1951 /*
1947 * feature bitmap is declared as an array of unsigned longs -- 1952 * feature bitmap is declared as an array of unsigned longs --
1948 * not good since its size can differ between the host that 1953 * not good since its size can differ between the host that
@@ -1958,14 +1963,17 @@ int perf_file_header__read(struct perf_file_header *header,
1958 * file), punt and fallback to the original behavior -- 1963 * file), punt and fallback to the original behavior --
1959 * clearing all feature bits and setting buildid. 1964 * clearing all feature bits and setting buildid.
1960 */ 1965 */
1961 for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) 1966 mem_bswap_64(&header->adds_features,
1962 header->adds_features[i] = bswap_64(header->adds_features[i]); 1967 BITS_TO_U64(HEADER_FEAT_BITS));
1963 1968
1964 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { 1969 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
1965 for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) { 1970 /* unswap as u64 */
1966 header->adds_features[i] = bswap_64(header->adds_features[i]); 1971 mem_bswap_64(&header->adds_features,
1967 header->adds_features[i] = bswap_32(header->adds_features[i]); 1972 BITS_TO_U64(HEADER_FEAT_BITS));
1968 } 1973
1974 /* unswap as u32 */
1975 mem_bswap_32(&header->adds_features,
1976 BITS_TO_U32(HEADER_FEAT_BITS));
1969 } 1977 }
1970 1978
1971 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { 1979 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
@@ -1986,7 +1994,7 @@ int perf_file_header__read(struct perf_file_header *header,
1986 1994
1987static int perf_file_section__process(struct perf_file_section *section, 1995static int perf_file_section__process(struct perf_file_section *section,
1988 struct perf_header *ph, 1996 struct perf_header *ph,
1989 int feat, int fd, void *data __used) 1997 int feat, int fd, void *data)
1990{ 1998{
1991 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 1999 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
1992 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 2000 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2002,7 +2010,7 @@ static int perf_file_section__process(struct perf_file_section *section,
2002 if (!feat_ops[feat].process) 2010 if (!feat_ops[feat].process)
2003 return 0; 2011 return 0;
2004 2012
2005 return feat_ops[feat].process(section, ph, feat, fd); 2013 return feat_ops[feat].process(section, ph, feat, fd, data);
2006} 2014}
2007 2015
2008static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 2016static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
@@ -2091,6 +2099,38 @@ static int read_attr(int fd, struct perf_header *ph,
2091 return ret <= 0 ? -1 : 0; 2099 return ret <= 0 ? -1 : 0;
2092} 2100}
2093 2101
2102static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel,
2103 struct pevent *pevent)
2104{
2105 struct event_format *event = pevent_find_event(pevent,
2106 evsel->attr.config);
2107 char bf[128];
2108
2109 if (event == NULL)
2110 return -1;
2111
2112 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
2113 evsel->name = strdup(bf);
2114 if (event->name == NULL)
2115 return -1;
2116
2117 return 0;
2118}
2119
2120static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist,
2121 struct pevent *pevent)
2122{
2123 struct perf_evsel *pos;
2124
2125 list_for_each_entry(pos, &evlist->entries, node) {
2126 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2127 perf_evsel__set_tracepoint_name(pos, pevent))
2128 return -1;
2129 }
2130
2131 return 0;
2132}
2133
2094int perf_session__read_header(struct perf_session *session, int fd) 2134int perf_session__read_header(struct perf_session *session, int fd)
2095{ 2135{
2096 struct perf_header *header = &session->header; 2136 struct perf_header *header = &session->header;
@@ -2167,11 +2207,14 @@ int perf_session__read_header(struct perf_session *session, int fd)
2167 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 2207 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
2168 } 2208 }
2169 2209
2170 perf_header__process_sections(header, fd, NULL, 2210 perf_header__process_sections(header, fd, &session->pevent,
2171 perf_file_section__process); 2211 perf_file_section__process);
2172 2212
2173 lseek(fd, header->data_offset, SEEK_SET); 2213 lseek(fd, header->data_offset, SEEK_SET);
2174 2214
2215 if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent))
2216 goto out_delete_evlist;
2217
2175 header->frozen = 1; 2218 header->frozen = 1;
2176 return 0; 2219 return 0;
2177out_errno: 2220out_errno:
@@ -2385,8 +2428,8 @@ int perf_event__process_tracing_data(union perf_event *event,
2385 lseek(session->fd, offset + sizeof(struct tracing_data_event), 2428 lseek(session->fd, offset + sizeof(struct tracing_data_event),
2386 SEEK_SET); 2429 SEEK_SET);
2387 2430
2388 size_read = trace_report(session->fd, session->repipe); 2431 size_read = trace_report(session->fd, &session->pevent,
2389 2432 session->repipe);
2390 padding = ALIGN(size_read, sizeof(u64)) - size_read; 2433 padding = ALIGN(size_read, sizeof(u64)) - size_read;
2391 2434
2392 if (read(session->fd, buf, padding) < 0) 2435 if (read(session->fd, buf, padding) < 0)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 1293b5ebea4d..f247ef2789a4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -378,7 +378,7 @@ void hist_entry__free(struct hist_entry *he)
378 * collapse the histogram 378 * collapse the histogram
379 */ 379 */
380 380
381static bool hists__collapse_insert_entry(struct hists *hists, 381static bool hists__collapse_insert_entry(struct hists *hists __used,
382 struct rb_root *root, 382 struct rb_root *root,
383 struct hist_entry *he) 383 struct hist_entry *he)
384{ 384{
@@ -397,8 +397,9 @@ static bool hists__collapse_insert_entry(struct hists *hists,
397 iter->period += he->period; 397 iter->period += he->period;
398 iter->nr_events += he->nr_events; 398 iter->nr_events += he->nr_events;
399 if (symbol_conf.use_callchain) { 399 if (symbol_conf.use_callchain) {
400 callchain_cursor_reset(&hists->callchain_cursor); 400 callchain_cursor_reset(&callchain_cursor);
401 callchain_merge(&hists->callchain_cursor, iter->callchain, 401 callchain_merge(&callchain_cursor,
402 iter->callchain,
402 he->callchain); 403 he->callchain);
403 } 404 }
404 hist_entry__free(he); 405 hist_entry__free(he);
@@ -707,7 +708,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
707 bool printed = false; 708 bool printed = false;
708 struct rb_node *node; 709 struct rb_node *node;
709 int i = 0; 710 int i = 0;
710 int ret; 711 int ret = 0;
711 712
712 /* 713 /*
713 * If have one single callchain root, don't bother printing 714 * If have one single callchain root, don't bother printing
@@ -746,8 +747,11 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
746 root = &cnode->rb_root; 747 root = &cnode->rb_root;
747 } 748 }
748 749
749 return __callchain__fprintf_graph(fp, root, total_samples, 750 ret += __callchain__fprintf_graph(fp, root, total_samples,
750 1, 1, left_margin); 751 1, 1, left_margin);
752 ret += fprintf(fp, "\n");
753
754 return ret;
751} 755}
752 756
753static size_t __callchain__fprintf_flat(FILE *fp, 757static size_t __callchain__fprintf_flat(FILE *fp,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index cfc64e293f90..0b096c27a419 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -47,6 +47,7 @@ enum hist_column {
47 HISTC_SYMBOL_TO, 47 HISTC_SYMBOL_TO,
48 HISTC_DSO_FROM, 48 HISTC_DSO_FROM,
49 HISTC_DSO_TO, 49 HISTC_DSO_TO,
50 HISTC_SRCLINE,
50 HISTC_NR_COLS, /* Last entry */ 51 HISTC_NR_COLS, /* Last entry */
51}; 52};
52 53
@@ -67,8 +68,6 @@ struct hists {
67 struct events_stats stats; 68 struct events_stats stats;
68 u64 event_stream; 69 u64 event_stream;
69 u16 col_len[HISTC_NR_COLS]; 70 u16 col_len[HISTC_NR_COLS];
70 /* Best would be to reuse the session callchain cursor */
71 struct callchain_cursor callchain_cursor;
72}; 71};
73 72
74struct hist_entry *__hists__add_entry(struct hists *self, 73struct hist_entry *__hists__add_entry(struct hists *self,
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index f1584833bd22..587a230d2075 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -8,6 +8,8 @@
8#define BITS_PER_LONG __WORDSIZE 8#define BITS_PER_LONG __WORDSIZE
9#define BITS_PER_BYTE 8 9#define BITS_PER_BYTE 8
10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
11#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
12#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
11 13
12#define for_each_set_bit(bit, addr, size) \ 14#define for_each_set_bit(bit, addr, size) \
13 for ((bit) = find_first_bit((addr), (size)); \ 15 for ((bit) = find_first_bit((addr), (size)); \
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index 1eb804fd3fbf..b6842c1d02a8 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -108,4 +108,14 @@ int eprintf(int level,
108#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 108#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
109#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 109#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
110 110
111/*
112 * This looks more complex than it should be. But we need to
113 * get the type for the ~ right in round_down (it needs to be
114 * as wide as the result!), and we want to evaluate the macro
115 * arguments just once each.
116 */
117#define __round_mask(x, y) ((__typeof__(x))((y)-1))
118#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
119#define round_down(x, y) ((x) & ~__round_mask(x, y))
120
111#endif 121#endif
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 35ae56864e4f..cc33486ad9e2 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -7,6 +7,8 @@
7#include <stdio.h> 7#include <stdio.h>
8#include <unistd.h> 8#include <unistd.h>
9#include "map.h" 9#include "map.h"
10#include "thread.h"
11#include "strlist.h"
10 12
11const char *map_type__name[MAP__NR_TYPES] = { 13const char *map_type__name[MAP__NR_TYPES] = {
12 [MAP__FUNCTION] = "Functions", 14 [MAP__FUNCTION] = "Functions",
@@ -585,7 +587,21 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid)
585 self->kmaps.machine = self; 587 self->kmaps.machine = self;
586 self->pid = pid; 588 self->pid = pid;
587 self->root_dir = strdup(root_dir); 589 self->root_dir = strdup(root_dir);
588 return self->root_dir == NULL ? -ENOMEM : 0; 590 if (self->root_dir == NULL)
591 return -ENOMEM;
592
593 if (pid != HOST_KERNEL_ID) {
594 struct thread *thread = machine__findnew_thread(self, pid);
595 char comm[64];
596
597 if (thread == NULL)
598 return -ENOMEM;
599
600 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
601 thread__set_comm(thread, comm);
602 }
603
604 return 0;
589} 605}
590 606
591static void dsos__delete(struct list_head *self) 607static void dsos__delete(struct list_head *self)
@@ -669,25 +685,34 @@ struct machine *machines__find(struct rb_root *self, pid_t pid)
669struct machine *machines__findnew(struct rb_root *self, pid_t pid) 685struct machine *machines__findnew(struct rb_root *self, pid_t pid)
670{ 686{
671 char path[PATH_MAX]; 687 char path[PATH_MAX];
672 const char *root_dir; 688 const char *root_dir = "";
673 struct machine *machine = machines__find(self, pid); 689 struct machine *machine = machines__find(self, pid);
674 690
675 if (!machine || machine->pid != pid) { 691 if (machine && (machine->pid == pid))
676 if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) 692 goto out;
677 root_dir = ""; 693
678 else { 694 if ((pid != HOST_KERNEL_ID) &&
679 if (!symbol_conf.guestmount) 695 (pid != DEFAULT_GUEST_KERNEL_ID) &&
680 goto out; 696 (symbol_conf.guestmount)) {
681 sprintf(path, "%s/%d", symbol_conf.guestmount, pid); 697 sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
682 if (access(path, R_OK)) { 698 if (access(path, R_OK)) {
699 static struct strlist *seen;
700
701 if (!seen)
702 seen = strlist__new(true, NULL);
703
704 if (!strlist__has_entry(seen, path)) {
683 pr_err("Can't access file %s\n", path); 705 pr_err("Can't access file %s\n", path);
684 goto out; 706 strlist__add(seen, path);
685 } 707 }
686 root_dir = path; 708 machine = NULL;
709 goto out;
687 } 710 }
688 machine = machines__add(self, pid, root_dir); 711 root_dir = path;
689 } 712 }
690 713
714 machine = machines__add(self, pid, root_dir);
715
691out: 716out:
692 return machine; 717 return machine;
693} 718}
@@ -713,3 +738,16 @@ char *machine__mmap_name(struct machine *self, char *bf, size_t size)
713 738
714 return bf; 739 return bf;
715} 740}
741
742void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size)
743{
744 struct rb_node *node;
745 struct machine *machine;
746
747 for (node = rb_first(machines); node; node = rb_next(node)) {
748 machine = rb_entry(node, struct machine, rb_node);
749 machine->id_hdr_size = id_hdr_size;
750 }
751
752 return;
753}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 81371bad4ef0..03a1e9b08b21 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -151,13 +151,14 @@ struct machine *machines__add(struct rb_root *self, pid_t pid,
151struct machine *machines__find_host(struct rb_root *self); 151struct machine *machines__find_host(struct rb_root *self);
152struct machine *machines__find(struct rb_root *self, pid_t pid); 152struct machine *machines__find(struct rb_root *self, pid_t pid);
153struct machine *machines__findnew(struct rb_root *self, pid_t pid); 153struct machine *machines__findnew(struct rb_root *self, pid_t pid);
154void machines__set_id_hdr_size(struct rb_root *self, u16 id_hdr_size);
154char *machine__mmap_name(struct machine *self, char *bf, size_t size); 155char *machine__mmap_name(struct machine *self, char *bf, size_t size);
155int machine__init(struct machine *self, const char *root_dir, pid_t pid); 156int machine__init(struct machine *self, const char *root_dir, pid_t pid);
156void machine__exit(struct machine *self); 157void machine__exit(struct machine *self);
157void machine__delete(struct machine *self); 158void machine__delete(struct machine *self);
158 159
159int machine__resolve_callchain(struct machine *machine, 160int machine__resolve_callchain(struct machine *machine,
160 struct perf_evsel *evsel, struct thread *thread, 161 struct thread *thread,
161 struct ip_callchain *chain, 162 struct ip_callchain *chain,
162 struct symbol **parent); 163 struct symbol **parent);
163int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, 164int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c
index 1915de20dcac..3322b8446e89 100644
--- a/tools/perf/util/pager.c
+++ b/tools/perf/util/pager.c
@@ -57,6 +57,10 @@ void setup_pager(void)
57 } 57 }
58 if (!pager) 58 if (!pager)
59 pager = getenv("PAGER"); 59 pager = getenv("PAGER");
60 if (!pager) {
61 if (!access("/usr/bin/pager", X_OK))
62 pager = "/usr/bin/pager";
63 }
60 if (!pager) 64 if (!pager)
61 pager = "less"; 65 pager = "less";
62 else if (!*pager || !strcmp(pager, "cat")) 66 else if (!*pager || !strcmp(pager, "cat"))
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 76b98e2a587d..1b997d2b89ce 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
181 return 0; 181 return 0;
182} 182}
183 183
184static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
185{
186 struct perf_evsel *evsel = list_entry(evlist->entries.next,
187 struct perf_evsel, node);
188
189 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
190 TEST_ASSERT_VAL("wrong type",
191 PERF_TYPE_BREAKPOINT == evsel->attr.type);
192 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
193 TEST_ASSERT_VAL("wrong bp_type",
194 (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
195 TEST_ASSERT_VAL("wrong bp_len",
196 HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
197 return 0;
198}
199
184static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) 200static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
185{ 201{
186 struct perf_evsel *evsel = list_entry(evlist->entries.next, 202 struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
309 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 325 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
310 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 326 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
311 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 327 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
328 TEST_ASSERT_VAL("wrong name",
329 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
312 330
313 return test__checkevent_breakpoint(evlist); 331 return test__checkevent_breakpoint(evlist);
314} 332}
@@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
322 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 340 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
323 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 341 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
324 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 342 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
343 TEST_ASSERT_VAL("wrong name",
344 !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
325 345
326 return test__checkevent_breakpoint_x(evlist); 346 return test__checkevent_breakpoint_x(evlist);
327} 347}
@@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
335 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 355 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
336 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); 356 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
337 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 357 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
358 TEST_ASSERT_VAL("wrong name",
359 !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
338 360
339 return test__checkevent_breakpoint_r(evlist); 361 return test__checkevent_breakpoint_r(evlist);
340} 362}
@@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
348 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 370 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
349 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 371 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
350 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 372 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
373 TEST_ASSERT_VAL("wrong name",
374 !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
351 375
352 return test__checkevent_breakpoint_w(evlist); 376 return test__checkevent_breakpoint_w(evlist);
353} 377}
354 378
379static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
380{
381 struct perf_evsel *evsel = list_entry(evlist->entries.next,
382 struct perf_evsel, node);
383
384 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
385 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
386 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
387 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
388 TEST_ASSERT_VAL("wrong name",
389 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
390
391 return test__checkevent_breakpoint_rw(evlist);
392}
393
355static int test__checkevent_pmu(struct perf_evlist *evlist) 394static int test__checkevent_pmu(struct perf_evlist *evlist)
356{ 395{
357 396
@@ -413,19 +452,63 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
413{ 452{
414 struct perf_evsel *evsel; 453 struct perf_evsel *evsel;
415 454
416 /* cpu/config=1,name=krava1/u */ 455 /* cpu/config=1,name=krava/u */
417 evsel = list_entry(evlist->entries.next, struct perf_evsel, node); 456 evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
418 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); 457 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
419 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 458 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
420 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); 459 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
421 TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "krava")); 460 TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava"));
422 461
423 /* cpu/config=2/" */ 462 /* cpu/config=2/u" */
424 evsel = list_entry(evsel->node.next, struct perf_evsel, node); 463 evsel = list_entry(evsel->node.next, struct perf_evsel, node);
425 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); 464 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
426 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 465 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
427 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); 466 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
428 TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "raw 0x2")); 467 TEST_ASSERT_VAL("wrong name",
468 !strcmp(perf_evsel__name(evsel), "raw 0x2:u"));
469
470 return 0;
471}
472
473static int test__checkterms_simple(struct list_head *terms)
474{
475 struct parse_events__term *term;
476
477 /* config=10 */
478 term = list_entry(terms->next, struct parse_events__term, list);
479 TEST_ASSERT_VAL("wrong type term",
480 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG);
481 TEST_ASSERT_VAL("wrong type val",
482 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
483 TEST_ASSERT_VAL("wrong val", term->val.num == 10);
484 TEST_ASSERT_VAL("wrong config", !term->config);
485
486 /* config1 */
487 term = list_entry(term->list.next, struct parse_events__term, list);
488 TEST_ASSERT_VAL("wrong type term",
489 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1);
490 TEST_ASSERT_VAL("wrong type val",
491 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
492 TEST_ASSERT_VAL("wrong val", term->val.num == 1);
493 TEST_ASSERT_VAL("wrong config", !term->config);
494
495 /* config2=3 */
496 term = list_entry(term->list.next, struct parse_events__term, list);
497 TEST_ASSERT_VAL("wrong type term",
498 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2);
499 TEST_ASSERT_VAL("wrong type val",
500 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
501 TEST_ASSERT_VAL("wrong val", term->val.num == 3);
502 TEST_ASSERT_VAL("wrong config", !term->config);
503
504 /* umask=1*/
505 term = list_entry(term->list.next, struct parse_events__term, list);
506 TEST_ASSERT_VAL("wrong type term",
507 term->type_term == PARSE_EVENTS__TERM_TYPE_USER);
508 TEST_ASSERT_VAL("wrong type val",
509 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
510 TEST_ASSERT_VAL("wrong val", term->val.num == 1);
511 TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "umask"));
429 512
430 return 0; 513 return 0;
431} 514}
@@ -541,10 +624,16 @@ static struct test__event_st test__events[] = {
541 .name = "instructions:H", 624 .name = "instructions:H",
542 .check = test__checkevent_exclude_guest_modifier, 625 .check = test__checkevent_exclude_guest_modifier,
543 }, 626 },
627 [26] = {
628 .name = "mem:0:rw",
629 .check = test__checkevent_breakpoint_rw,
630 },
631 [27] = {
632 .name = "mem:0:rw:kp",
633 .check = test__checkevent_breakpoint_rw_modifier,
634 },
544}; 635};
545 636
546#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
547
548static struct test__event_st test__events_pmu[] = { 637static struct test__event_st test__events_pmu[] = {
549 [0] = { 638 [0] = {
550 .name = "cpu/config=10,config1,config2=3,period=1000/u", 639 .name = "cpu/config=10,config1,config2=3,period=1000/u",
@@ -556,10 +645,23 @@ static struct test__event_st test__events_pmu[] = {
556 }, 645 },
557}; 646};
558 647
559#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \ 648struct test__term {
560 sizeof(struct test__event_st)) 649 const char *str;
650 __u32 type;
651 int (*check)(struct list_head *terms);
652};
653
654static struct test__term test__terms[] = {
655 [0] = {
656 .str = "config=10,config1,config2=3,umask=1",
657 .check = test__checkterms_simple,
658 },
659};
660
661#define TEST__TERMS_CNT (sizeof(test__terms) / \
662 sizeof(struct test__term))
561 663
562static int test(struct test__event_st *e) 664static int test_event(struct test__event_st *e)
563{ 665{
564 struct perf_evlist *evlist; 666 struct perf_evlist *evlist;
565 int ret; 667 int ret;
@@ -590,7 +692,48 @@ static int test_events(struct test__event_st *events, unsigned cnt)
590 struct test__event_st *e = &events[i]; 692 struct test__event_st *e = &events[i];
591 693
592 pr_debug("running test %d '%s'\n", i, e->name); 694 pr_debug("running test %d '%s'\n", i, e->name);
593 ret = test(e); 695 ret = test_event(e);
696 if (ret)
697 break;
698 }
699
700 return ret;
701}
702
703static int test_term(struct test__term *t)
704{
705 struct list_head *terms;
706 int ret;
707
708 terms = malloc(sizeof(*terms));
709 if (!terms)
710 return -ENOMEM;
711
712 INIT_LIST_HEAD(terms);
713
714 ret = parse_events_terms(terms, t->str);
715 if (ret) {
716 pr_debug("failed to parse terms '%s', err %d\n",
717 t->str , ret);
718 return ret;
719 }
720
721 ret = t->check(terms);
722 parse_events__free_terms(terms);
723
724 return ret;
725}
726
727static int test_terms(struct test__term *terms, unsigned cnt)
728{
729 int ret = 0;
730 unsigned i;
731
732 for (i = 0; i < cnt; i++) {
733 struct test__term *t = &terms[i];
734
735 pr_debug("running test %d '%s'\n", i, t->str);
736 ret = test_term(t);
594 if (ret) 737 if (ret)
595 break; 738 break;
596 } 739 }
@@ -617,9 +760,17 @@ int parse_events__test(void)
617{ 760{
618 int ret; 761 int ret;
619 762
620 ret = test_events(test__events, TEST__EVENTS_CNT); 763#define TEST_EVENTS(tests) \
621 if (!ret && test_pmu()) 764do { \
622 ret = test_events(test__events_pmu, TEST__EVENTS_PMU_CNT); 765 ret = test_events(tests, ARRAY_SIZE(tests)); \
766 if (ret) \
767 return ret; \
768} while (0)
623 769
624 return ret; 770 TEST_EVENTS(test__events);
771
772 if (test_pmu())
773 TEST_EVENTS(test__events_pmu);
774
775 return test_terms(test__terms, ARRAY_SIZE(test__terms));
625} 776}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 05dbc8b3c767..74a5af4d33ec 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -11,14 +11,14 @@
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debugfs.h" 13#include "debugfs.h"
14#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int
14#include "parse-events-flex.h" 16#include "parse-events-flex.h"
15#include "pmu.h" 17#include "pmu.h"
16 18
17#define MAX_NAME_LEN 100 19#define MAX_NAME_LEN 100
18 20
19struct event_symbol { 21struct event_symbol {
20 u8 type;
21 u64 config;
22 const char *symbol; 22 const char *symbol;
23 const char *alias; 23 const char *alias;
24}; 24};
@@ -26,32 +26,88 @@ struct event_symbol {
26#ifdef PARSER_DEBUG 26#ifdef PARSER_DEBUG
27extern int parse_events_debug; 27extern int parse_events_debug;
28#endif 28#endif
29int parse_events_parse(struct list_head *list, int *idx); 29int parse_events_parse(void *data, void *scanner);
30 30
31#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 31static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
32#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 32 [PERF_COUNT_HW_CPU_CYCLES] = {
33 33 .symbol = "cpu-cycles",
34static struct event_symbol event_symbols[] = { 34 .alias = "cycles",
35 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 35 },
36 { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" }, 36 [PERF_COUNT_HW_INSTRUCTIONS] = {
37 { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" }, 37 .symbol = "instructions",
38 { CHW(INSTRUCTIONS), "instructions", "" }, 38 .alias = "",
39 { CHW(CACHE_REFERENCES), "cache-references", "" }, 39 },
40 { CHW(CACHE_MISSES), "cache-misses", "" }, 40 [PERF_COUNT_HW_CACHE_REFERENCES] = {
41 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 41 .symbol = "cache-references",
42 { CHW(BRANCH_MISSES), "branch-misses", "" }, 42 .alias = "",
43 { CHW(BUS_CYCLES), "bus-cycles", "" }, 43 },
44 { CHW(REF_CPU_CYCLES), "ref-cycles", "" }, 44 [PERF_COUNT_HW_CACHE_MISSES] = {
45 45 .symbol = "cache-misses",
46 { CSW(CPU_CLOCK), "cpu-clock", "" }, 46 .alias = "",
47 { CSW(TASK_CLOCK), "task-clock", "" }, 47 },
48 { CSW(PAGE_FAULTS), "page-faults", "faults" }, 48 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
49 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 49 .symbol = "branch-instructions",
50 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 50 .alias = "branches",
51 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 51 },
52 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 52 [PERF_COUNT_HW_BRANCH_MISSES] = {
53 { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, 53 .symbol = "branch-misses",
54 { CSW(EMULATION_FAULTS), "emulation-faults", "" }, 54 .alias = "",
55 },
56 [PERF_COUNT_HW_BUS_CYCLES] = {
57 .symbol = "bus-cycles",
58 .alias = "",
59 },
60 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
61 .symbol = "stalled-cycles-frontend",
62 .alias = "idle-cycles-frontend",
63 },
64 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
65 .symbol = "stalled-cycles-backend",
66 .alias = "idle-cycles-backend",
67 },
68 [PERF_COUNT_HW_REF_CPU_CYCLES] = {
69 .symbol = "ref-cycles",
70 .alias = "",
71 },
72};
73
74static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
75 [PERF_COUNT_SW_CPU_CLOCK] = {
76 .symbol = "cpu-clock",
77 .alias = "",
78 },
79 [PERF_COUNT_SW_TASK_CLOCK] = {
80 .symbol = "task-clock",
81 .alias = "",
82 },
83 [PERF_COUNT_SW_PAGE_FAULTS] = {
84 .symbol = "page-faults",
85 .alias = "faults",
86 },
87 [PERF_COUNT_SW_CONTEXT_SWITCHES] = {
88 .symbol = "context-switches",
89 .alias = "cs",
90 },
91 [PERF_COUNT_SW_CPU_MIGRATIONS] = {
92 .symbol = "cpu-migrations",
93 .alias = "migrations",
94 },
95 [PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
96 .symbol = "minor-faults",
97 .alias = "",
98 },
99 [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
100 .symbol = "major-faults",
101 .alias = "",
102 },
103 [PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
104 .symbol = "alignment-faults",
105 .alias = "",
106 },
107 [PERF_COUNT_SW_EMULATION_FAULTS] = {
108 .symbol = "emulation-faults",
109 .alias = "",
110 },
55}; 111};
56 112
57#define __PERF_EVENT_FIELD(config, name) \ 113#define __PERF_EVENT_FIELD(config, name) \
@@ -62,63 +118,6 @@ static struct event_symbol event_symbols[] = {
62#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 118#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
63#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 119#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
64 120
65static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
66 "cpu-clock",
67 "task-clock",
68 "page-faults",
69 "context-switches",
70 "CPU-migrations",
71 "minor-faults",
72 "major-faults",
73 "alignment-faults",
74 "emulation-faults",
75};
76
77#define MAX_ALIASES 8
78
79static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
80 { "L1-dcache", "l1-d", "l1d", "L1-data", },
81 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
82 { "LLC", "L2", },
83 { "dTLB", "d-tlb", "Data-TLB", },
84 { "iTLB", "i-tlb", "Instruction-TLB", },
85 { "branch", "branches", "bpu", "btb", "bpc", },
86 { "node", },
87};
88
89static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
90 { "load", "loads", "read", },
91 { "store", "stores", "write", },
92 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
93};
94
95static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
96 [MAX_ALIASES] = {
97 { "refs", "Reference", "ops", "access", },
98 { "misses", "miss", },
99};
100
101#define C(x) PERF_COUNT_HW_CACHE_##x
102#define CACHE_READ (1 << C(OP_READ))
103#define CACHE_WRITE (1 << C(OP_WRITE))
104#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
105#define COP(x) (1 << x)
106
107/*
108 * cache operartion stat
109 * L1I : Read and prefetch only
110 * ITLB and BPU : Read-only
111 */
112static unsigned long hw_cache_stat[C(MAX)] = {
113 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
114 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
115 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
116 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
117 [C(ITLB)] = (CACHE_READ),
118 [C(BPU)] = (CACHE_READ),
119 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
120};
121
122#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 121#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \
123 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ 122 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
124 if (sys_dirent.d_type == DT_DIR && \ 123 if (sys_dirent.d_type == DT_DIR && \
@@ -218,48 +217,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
218 return NULL; 217 return NULL;
219} 218}
220 219
221#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
222static const char *tracepoint_id_to_name(u64 config)
223{
224 static char buf[TP_PATH_LEN];
225 struct tracepoint_path *path;
226
227 path = tracepoint_id_to_path(config);
228 if (path) {
229 snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
230 free(path->name);
231 free(path->system);
232 free(path);
233 } else
234 snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
235
236 return buf;
237}
238
239static int is_cache_op_valid(u8 cache_type, u8 cache_op)
240{
241 if (hw_cache_stat[cache_type] & COP(cache_op))
242 return 1; /* valid */
243 else
244 return 0; /* invalid */
245}
246
247static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
248{
249 static char name[50];
250
251 if (cache_result) {
252 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
253 hw_cache_op[cache_op][0],
254 hw_cache_result[cache_result][0]);
255 } else {
256 sprintf(name, "%s-%s", hw_cache[cache_type][0],
257 hw_cache_op[cache_op][1]);
258 }
259
260 return name;
261}
262
263const char *event_type(int type) 220const char *event_type(int type)
264{ 221{
265 switch (type) { 222 switch (type) {
@@ -282,76 +239,6 @@ const char *event_type(int type)
282 return "unknown"; 239 return "unknown";
283} 240}
284 241
285const char *event_name(struct perf_evsel *evsel)
286{
287 u64 config = evsel->attr.config;
288 int type = evsel->attr.type;
289
290 if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) {
291 /*
292 * XXX minimal fix, see comment on perf_evsen__name, this static buffer
293 * will go away together with event_name in the next devel cycle.
294 */
295 static char bf[128];
296 perf_evsel__name(evsel, bf, sizeof(bf));
297 return bf;
298 }
299
300 if (evsel->name)
301 return evsel->name;
302
303 return __event_name(type, config);
304}
305
306const char *__event_name(int type, u64 config)
307{
308 static char buf[32];
309
310 if (type == PERF_TYPE_RAW) {
311 sprintf(buf, "raw 0x%" PRIx64, config);
312 return buf;
313 }
314
315 switch (type) {
316 case PERF_TYPE_HARDWARE:
317 return __perf_evsel__hw_name(config);
318
319 case PERF_TYPE_HW_CACHE: {
320 u8 cache_type, cache_op, cache_result;
321
322 cache_type = (config >> 0) & 0xff;
323 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
324 return "unknown-ext-hardware-cache-type";
325
326 cache_op = (config >> 8) & 0xff;
327 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
328 return "unknown-ext-hardware-cache-op";
329
330 cache_result = (config >> 16) & 0xff;
331 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
332 return "unknown-ext-hardware-cache-result";
333
334 if (!is_cache_op_valid(cache_type, cache_op))
335 return "invalid-cache";
336
337 return event_cache_name(cache_type, cache_op, cache_result);
338 }
339
340 case PERF_TYPE_SOFTWARE:
341 if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
342 return sw_event_names[config];
343 return "unknown-software";
344
345 case PERF_TYPE_TRACEPOINT:
346 return tracepoint_id_to_name(config);
347
348 default:
349 break;
350 }
351
352 return "unknown";
353}
354
355static int add_event(struct list_head **_list, int *idx, 242static int add_event(struct list_head **_list, int *idx,
356 struct perf_event_attr *attr, char *name) 243 struct perf_event_attr *attr, char *name)
357{ 244{
@@ -373,19 +260,20 @@ static int add_event(struct list_head **_list, int *idx,
373 return -ENOMEM; 260 return -ENOMEM;
374 } 261 }
375 262
376 evsel->name = strdup(name); 263 if (name)
264 evsel->name = strdup(name);
377 list_add_tail(&evsel->node, list); 265 list_add_tail(&evsel->node, list);
378 *_list = list; 266 *_list = list;
379 return 0; 267 return 0;
380} 268}
381 269
382static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size) 270static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
383{ 271{
384 int i, j; 272 int i, j;
385 int n, longest = -1; 273 int n, longest = -1;
386 274
387 for (i = 0; i < size; i++) { 275 for (i = 0; i < size; i++) {
388 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 276 for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) {
389 n = strlen(names[i][j]); 277 n = strlen(names[i][j]);
390 if (n > longest && !strncasecmp(str, names[i][j], n)) 278 if (n > longest && !strncasecmp(str, names[i][j], n))
391 longest = n; 279 longest = n;
@@ -410,7 +298,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,
410 * No fallback - if we cannot get a clear cache type 298 * No fallback - if we cannot get a clear cache type
411 * then bail out: 299 * then bail out:
412 */ 300 */
413 cache_type = parse_aliases(type, hw_cache, 301 cache_type = parse_aliases(type, perf_evsel__hw_cache,
414 PERF_COUNT_HW_CACHE_MAX); 302 PERF_COUNT_HW_CACHE_MAX);
415 if (cache_type == -1) 303 if (cache_type == -1)
416 return -EINVAL; 304 return -EINVAL;
@@ -423,18 +311,18 @@ int parse_events_add_cache(struct list_head **list, int *idx,
423 snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); 311 snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);
424 312
425 if (cache_op == -1) { 313 if (cache_op == -1) {
426 cache_op = parse_aliases(str, hw_cache_op, 314 cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
427 PERF_COUNT_HW_CACHE_OP_MAX); 315 PERF_COUNT_HW_CACHE_OP_MAX);
428 if (cache_op >= 0) { 316 if (cache_op >= 0) {
429 if (!is_cache_op_valid(cache_type, cache_op)) 317 if (!perf_evsel__is_cache_op_valid(cache_type, cache_op))
430 return -EINVAL; 318 return -EINVAL;
431 continue; 319 continue;
432 } 320 }
433 } 321 }
434 322
435 if (cache_result == -1) { 323 if (cache_result == -1) {
436 cache_result = parse_aliases(str, hw_cache_result, 324 cache_result = parse_aliases(str, perf_evsel__hw_cache_result,
437 PERF_COUNT_HW_CACHE_RESULT_MAX); 325 PERF_COUNT_HW_CACHE_RESULT_MAX);
438 if (cache_result >= 0) 326 if (cache_result >= 0)
439 continue; 327 continue;
440 } 328 }
@@ -489,6 +377,7 @@ static int add_tracepoint(struct list_head **list, int *idx,
489 attr.sample_type |= PERF_SAMPLE_RAW; 377 attr.sample_type |= PERF_SAMPLE_RAW;
490 attr.sample_type |= PERF_SAMPLE_TIME; 378 attr.sample_type |= PERF_SAMPLE_TIME;
491 attr.sample_type |= PERF_SAMPLE_CPU; 379 attr.sample_type |= PERF_SAMPLE_CPU;
380 attr.sample_type |= PERF_SAMPLE_PERIOD;
492 attr.sample_period = 1; 381 attr.sample_period = 1;
493 382
494 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name); 383 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name);
@@ -549,21 +438,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
549 if (!type || !type[i]) 438 if (!type || !type[i])
550 break; 439 break;
551 440
441#define CHECK_SET_TYPE(bit) \
442do { \
443 if (attr->bp_type & bit) \
444 return -EINVAL; \
445 else \
446 attr->bp_type |= bit; \
447} while (0)
448
552 switch (type[i]) { 449 switch (type[i]) {
553 case 'r': 450 case 'r':
554 attr->bp_type |= HW_BREAKPOINT_R; 451 CHECK_SET_TYPE(HW_BREAKPOINT_R);
555 break; 452 break;
556 case 'w': 453 case 'w':
557 attr->bp_type |= HW_BREAKPOINT_W; 454 CHECK_SET_TYPE(HW_BREAKPOINT_W);
558 break; 455 break;
559 case 'x': 456 case 'x':
560 attr->bp_type |= HW_BREAKPOINT_X; 457 CHECK_SET_TYPE(HW_BREAKPOINT_X);
561 break; 458 break;
562 default: 459 default:
563 return -EINVAL; 460 return -EINVAL;
564 } 461 }
565 } 462 }
566 463
464#undef CHECK_SET_TYPE
465
567 if (!attr->bp_type) /* Default */ 466 if (!attr->bp_type) /* Default */
568 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 467 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
569 468
@@ -574,7 +473,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
574 void *ptr, char *type) 473 void *ptr, char *type)
575{ 474{
576 struct perf_event_attr attr; 475 struct perf_event_attr attr;
577 char name[MAX_NAME_LEN];
578 476
579 memset(&attr, 0, sizeof(attr)); 477 memset(&attr, 0, sizeof(attr));
580 attr.bp_addr = (unsigned long) ptr; 478 attr.bp_addr = (unsigned long) ptr;
@@ -592,9 +490,9 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
592 attr.bp_len = HW_BREAKPOINT_LEN_4; 490 attr.bp_len = HW_BREAKPOINT_LEN_4;
593 491
594 attr.type = PERF_TYPE_BREAKPOINT; 492 attr.type = PERF_TYPE_BREAKPOINT;
493 attr.sample_period = 1;
595 494
596 snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw"); 495 return add_event(list, idx, &attr, NULL);
597 return add_event(list, idx, &attr, name);
598} 496}
599 497
600static int config_term(struct perf_event_attr *attr, 498static int config_term(struct perf_event_attr *attr,
@@ -666,8 +564,7 @@ int parse_events_add_numeric(struct list_head **list, int *idx,
666 config_attr(&attr, head_config, 1)) 564 config_attr(&attr, head_config, 1))
667 return -EINVAL; 565 return -EINVAL;
668 566
669 return add_event(list, idx, &attr, 567 return add_event(list, idx, &attr, NULL);
670 (char *) __event_name(type, config));
671} 568}
672 569
673static int parse_events__is_name_term(struct parse_events__term *term) 570static int parse_events__is_name_term(struct parse_events__term *term)
@@ -675,8 +572,7 @@ static int parse_events__is_name_term(struct parse_events__term *term)
675 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME; 572 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
676} 573}
677 574
678static char *pmu_event_name(struct perf_event_attr *attr, 575static char *pmu_event_name(struct list_head *head_terms)
679 struct list_head *head_terms)
680{ 576{
681 struct parse_events__term *term; 577 struct parse_events__term *term;
682 578
@@ -684,7 +580,7 @@ static char *pmu_event_name(struct perf_event_attr *attr,
684 if (parse_events__is_name_term(term)) 580 if (parse_events__is_name_term(term))
685 return term->val.str; 581 return term->val.str;
686 582
687 return (char *) __event_name(PERF_TYPE_RAW, attr->config); 583 return NULL;
688} 584}
689 585
690int parse_events_add_pmu(struct list_head **list, int *idx, 586int parse_events_add_pmu(struct list_head **list, int *idx,
@@ -699,6 +595,9 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
699 595
700 memset(&attr, 0, sizeof(attr)); 596 memset(&attr, 0, sizeof(attr));
701 597
598 if (perf_pmu__check_alias(pmu, head_config))
599 return -EINVAL;
600
702 /* 601 /*
703 * Configure hardcoded terms first, no need to check 602 * Configure hardcoded terms first, no need to check
704 * return value when called with fail == 0 ;) 603 * return value when called with fail == 0 ;)
@@ -709,7 +608,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
709 return -EINVAL; 608 return -EINVAL;
710 609
711 return add_event(list, idx, &attr, 610 return add_event(list, idx, &attr,
712 pmu_event_name(&attr, head_config)); 611 pmu_event_name(head_config));
713} 612}
714 613
715void parse_events_update_lists(struct list_head *list_event, 614void parse_events_update_lists(struct list_head *list_event,
@@ -787,27 +686,62 @@ int parse_events_modifier(struct list_head *list, char *str)
787 return 0; 686 return 0;
788} 687}
789 688
790int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) 689static int parse_events__scanner(const char *str, void *data, int start_token)
791{ 690{
792 LIST_HEAD(list);
793 LIST_HEAD(list_tmp);
794 YY_BUFFER_STATE buffer; 691 YY_BUFFER_STATE buffer;
795 int ret, idx = evlist->nr_entries; 692 void *scanner;
693 int ret;
694
695 ret = parse_events_lex_init_extra(start_token, &scanner);
696 if (ret)
697 return ret;
796 698
797 buffer = parse_events__scan_string(str); 699 buffer = parse_events__scan_string(str, scanner);
798 700
799#ifdef PARSER_DEBUG 701#ifdef PARSER_DEBUG
800 parse_events_debug = 1; 702 parse_events_debug = 1;
801#endif 703#endif
802 ret = parse_events_parse(&list, &idx); 704 ret = parse_events_parse(data, scanner);
803 705
804 parse_events__flush_buffer(buffer); 706 parse_events__flush_buffer(buffer, scanner);
805 parse_events__delete_buffer(buffer); 707 parse_events__delete_buffer(buffer, scanner);
806 parse_events_lex_destroy(); 708 parse_events_lex_destroy(scanner);
709 return ret;
710}
711
712/*
713 * parse event config string, return a list of event terms.
714 */
715int parse_events_terms(struct list_head *terms, const char *str)
716{
717 struct parse_events_data__terms data = {
718 .terms = NULL,
719 };
720 int ret;
807 721
722 ret = parse_events__scanner(str, &data, PE_START_TERMS);
808 if (!ret) { 723 if (!ret) {
809 int entries = idx - evlist->nr_entries; 724 list_splice(data.terms, terms);
810 perf_evlist__splice_list_tail(evlist, &list, entries); 725 free(data.terms);
726 return 0;
727 }
728
729 parse_events__free_terms(data.terms);
730 return ret;
731}
732
733int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
734{
735 struct parse_events_data__events data = {
736 .list = LIST_HEAD_INIT(data.list),
737 .idx = evlist->nr_entries,
738 };
739 int ret;
740
741 ret = parse_events__scanner(str, &data, PE_START_EVENTS);
742 if (!ret) {
743 int entries = data.idx - evlist->nr_entries;
744 perf_evlist__splice_list_tail(evlist, &data.list, entries);
811 return 0; 745 return 0;
812 } 746 }
813 747
@@ -946,16 +880,13 @@ int is_valid_tracepoint(const char *event_string)
946 return 0; 880 return 0;
947} 881}
948 882
949void print_events_type(u8 type) 883static void __print_events_type(u8 type, struct event_symbol *syms,
884 unsigned max)
950{ 885{
951 struct event_symbol *syms = event_symbols;
952 unsigned int i;
953 char name[64]; 886 char name[64];
887 unsigned i;
954 888
955 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 889 for (i = 0; i < max ; i++, syms++) {
956 if (type != syms->type)
957 continue;
958
959 if (strlen(syms->alias)) 890 if (strlen(syms->alias))
960 snprintf(name, sizeof(name), "%s OR %s", 891 snprintf(name, sizeof(name), "%s OR %s",
961 syms->symbol, syms->alias); 892 syms->symbol, syms->alias);
@@ -967,19 +898,28 @@ void print_events_type(u8 type)
967 } 898 }
968} 899}
969 900
901void print_events_type(u8 type)
902{
903 if (type == PERF_TYPE_SOFTWARE)
904 __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
905 else
906 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
907}
908
970int print_hwcache_events(const char *event_glob) 909int print_hwcache_events(const char *event_glob)
971{ 910{
972 unsigned int type, op, i, printed = 0; 911 unsigned int type, op, i, printed = 0;
912 char name[64];
973 913
974 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 914 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
975 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 915 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
976 /* skip invalid cache type */ 916 /* skip invalid cache type */
977 if (!is_cache_op_valid(type, op)) 917 if (!perf_evsel__is_cache_op_valid(type, op))
978 continue; 918 continue;
979 919
980 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 920 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
981 char *name = event_cache_name(type, op, i); 921 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
982 922 name, sizeof(name));
983 if (event_glob != NULL && !strglobmatch(name, event_glob)) 923 if (event_glob != NULL && !strglobmatch(name, event_glob))
984 continue; 924 continue;
985 925
@@ -993,26 +933,13 @@ int print_hwcache_events(const char *event_glob)
993 return printed; 933 return printed;
994} 934}
995 935
996/* 936static void print_symbol_events(const char *event_glob, unsigned type,
997 * Print the help text for the event symbols: 937 struct event_symbol *syms, unsigned max)
998 */
999void print_events(const char *event_glob)
1000{ 938{
1001 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; 939 unsigned i, printed = 0;
1002 struct event_symbol *syms = event_symbols;
1003 char name[MAX_NAME_LEN]; 940 char name[MAX_NAME_LEN];
1004 941
1005 printf("\n"); 942 for (i = 0; i < max; i++, syms++) {
1006 printf("List of pre-defined events (to be used in -e):\n");
1007
1008 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
1009 type = syms->type;
1010
1011 if (type != prev_type && printed) {
1012 printf("\n");
1013 printed = 0;
1014 ntypes_printed++;
1015 }
1016 943
1017 if (event_glob != NULL && 944 if (event_glob != NULL &&
1018 !(strglobmatch(syms->symbol, event_glob) || 945 !(strglobmatch(syms->symbol, event_glob) ||
@@ -1023,17 +950,31 @@ void print_events(const char *event_glob)
1023 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 950 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
1024 else 951 else
1025 strncpy(name, syms->symbol, MAX_NAME_LEN); 952 strncpy(name, syms->symbol, MAX_NAME_LEN);
1026 printf(" %-50s [%s]\n", name,
1027 event_type_descriptors[type]);
1028 953
1029 prev_type = type; 954 printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
1030 ++printed; 955
956 printed++;
1031 } 957 }
1032 958
1033 if (ntypes_printed) { 959 if (printed)
1034 printed = 0;
1035 printf("\n"); 960 printf("\n");
1036 } 961}
962
963/*
964 * Print the help text for the event symbols:
965 */
966void print_events(const char *event_glob)
967{
968
969 printf("\n");
970 printf("List of pre-defined events (to be used in -e):\n");
971
972 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
973 event_symbols_hw, PERF_COUNT_HW_MAX);
974
975 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
976 event_symbols_sw, PERF_COUNT_SW_MAX);
977
1037 print_hwcache_events(event_glob); 978 print_hwcache_events(event_glob);
1038 979
1039 if (event_glob != NULL) 980 if (event_glob != NULL)
@@ -1106,6 +1047,13 @@ int parse_events__term_str(struct parse_events__term **term,
1106 config, str, 0); 1047 config, str, 0);
1107} 1048}
1108 1049
1050int parse_events__term_clone(struct parse_events__term **new,
1051 struct parse_events__term *term)
1052{
1053 return new_term(new, term->type_val, term->type_term, term->config,
1054 term->val.str, term->val.num);
1055}
1056
1109void parse_events__free_terms(struct list_head *terms) 1057void parse_events__free_terms(struct list_head *terms)
1110{ 1058{
1111 struct parse_events__term *term, *h; 1059 struct parse_events__term *term, *h;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 8cac57ab4ee6..ee9c218a193c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -26,13 +26,12 @@ extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
26extern bool have_tracepoints(struct list_head *evlist); 26extern bool have_tracepoints(struct list_head *evlist);
27 27
28const char *event_type(int type); 28const char *event_type(int type);
29const char *event_name(struct perf_evsel *event);
30extern const char *__event_name(int type, u64 config);
31 29
32extern int parse_events_option(const struct option *opt, const char *str, 30extern int parse_events_option(const struct option *opt, const char *str,
33 int unset); 31 int unset);
34extern int parse_events(struct perf_evlist *evlist, const char *str, 32extern int parse_events(struct perf_evlist *evlist, const char *str,
35 int unset); 33 int unset);
34extern int parse_events_terms(struct list_head *terms, const char *str);
36extern int parse_filter(const struct option *opt, const char *str, int unset); 35extern int parse_filter(const struct option *opt, const char *str, int unset);
37 36
38#define EVENTS_HELP_MAX (128*1024) 37#define EVENTS_HELP_MAX (128*1024)
@@ -63,11 +62,22 @@ struct parse_events__term {
63 struct list_head list; 62 struct list_head list;
64}; 63};
65 64
65struct parse_events_data__events {
66 struct list_head list;
67 int idx;
68};
69
70struct parse_events_data__terms {
71 struct list_head *terms;
72};
73
66int parse_events__is_hardcoded_term(struct parse_events__term *term); 74int parse_events__is_hardcoded_term(struct parse_events__term *term);
67int parse_events__term_num(struct parse_events__term **_term, 75int parse_events__term_num(struct parse_events__term **_term,
68 int type_term, char *config, long num); 76 int type_term, char *config, long num);
69int parse_events__term_str(struct parse_events__term **_term, 77int parse_events__term_str(struct parse_events__term **_term,
70 int type_term, char *config, char *str); 78 int type_term, char *config, char *str);
79int parse_events__term_clone(struct parse_events__term **new,
80 struct parse_events__term *term);
71void parse_events__free_terms(struct list_head *terms); 81void parse_events__free_terms(struct list_head *terms);
72int parse_events_modifier(struct list_head *list, char *str); 82int parse_events_modifier(struct list_head *list, char *str);
73int parse_events_add_tracepoint(struct list_head **list, int *idx, 83int parse_events_add_tracepoint(struct list_head **list, int *idx,
@@ -83,8 +93,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
83 char *pmu , struct list_head *head_config); 93 char *pmu , struct list_head *head_config);
84void parse_events_update_lists(struct list_head *list_event, 94void parse_events_update_lists(struct list_head *list_event,
85 struct list_head *list_all); 95 struct list_head *list_all);
86void parse_events_error(struct list_head *list_all, 96void parse_events_error(void *data, void *scanner, char const *msg);
87 int *idx, char const *msg);
88int parse_events__test(void); 97int parse_events__test(void);
89 98
90void print_events(const char *event_glob); 99void print_events(const char *event_glob);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 618a8e788399..384ca74c6b22 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -1,4 +1,6 @@
1 1
2%option reentrant
3%option bison-bridge
2%option prefix="parse_events_" 4%option prefix="parse_events_"
3%option stack 5%option stack
4 6
@@ -8,7 +10,10 @@
8#include "parse-events-bison.h" 10#include "parse-events-bison.h"
9#include "parse-events.h" 11#include "parse-events.h"
10 12
11static int __value(char *str, int base, int token) 13char *parse_events_get_text(yyscan_t yyscanner);
14YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
15
16static int __value(YYSTYPE *yylval, char *str, int base, int token)
12{ 17{
13 long num; 18 long num;
14 19
@@ -17,35 +22,48 @@ static int __value(char *str, int base, int token)
17 if (errno) 22 if (errno)
18 return PE_ERROR; 23 return PE_ERROR;
19 24
20 parse_events_lval.num = num; 25 yylval->num = num;
21 return token; 26 return token;
22} 27}
23 28
24static int value(int base) 29static int value(yyscan_t scanner, int base)
25{ 30{
26 return __value(parse_events_text, base, PE_VALUE); 31 YYSTYPE *yylval = parse_events_get_lval(scanner);
32 char *text = parse_events_get_text(scanner);
33
34 return __value(yylval, text, base, PE_VALUE);
27} 35}
28 36
29static int raw(void) 37static int raw(yyscan_t scanner)
30{ 38{
31 return __value(parse_events_text + 1, 16, PE_RAW); 39 YYSTYPE *yylval = parse_events_get_lval(scanner);
40 char *text = parse_events_get_text(scanner);
41
42 return __value(yylval, text + 1, 16, PE_RAW);
32} 43}
33 44
34static int str(int token) 45static int str(yyscan_t scanner, int token)
35{ 46{
36 parse_events_lval.str = strdup(parse_events_text); 47 YYSTYPE *yylval = parse_events_get_lval(scanner);
48 char *text = parse_events_get_text(scanner);
49
50 yylval->str = strdup(text);
37 return token; 51 return token;
38} 52}
39 53
40static int sym(int type, int config) 54static int sym(yyscan_t scanner, int type, int config)
41{ 55{
42 parse_events_lval.num = (type << 16) + config; 56 YYSTYPE *yylval = parse_events_get_lval(scanner);
43 return PE_VALUE_SYM; 57
58 yylval->num = (type << 16) + config;
59 return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
44} 60}
45 61
46static int term(int type) 62static int term(yyscan_t scanner, int type)
47{ 63{
48 parse_events_lval.num = type; 64 YYSTYPE *yylval = parse_events_get_lval(scanner);
65
66 yylval->num = type;
49 return PE_TERM; 67 return PE_TERM;
50} 68}
51 69
@@ -58,28 +76,41 @@ num_hex 0x[a-fA-F0-9]+
58num_raw_hex [a-fA-F0-9]+ 76num_raw_hex [a-fA-F0-9]+
59name [a-zA-Z_*?][a-zA-Z0-9_*?]* 77name [a-zA-Z_*?][a-zA-Z0-9_*?]*
60modifier_event [ukhpGH]{1,8} 78modifier_event [ukhpGH]{1,8}
61modifier_bp [rwx] 79modifier_bp [rwx]{1,3}
62 80
63%% 81%%
64cpu-cycles|cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 82
65stalled-cycles-frontend|idle-cycles-frontend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 83%{
66stalled-cycles-backend|idle-cycles-backend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 84 {
67instructions { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); } 85 int start_token;
68cache-references { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); } 86
69cache-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); } 87 start_token = (int) parse_events_get_extra(yyscanner);
70branch-instructions|branches { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } 88 if (start_token) {
71branch-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); } 89 parse_events_set_extra(NULL, yyscanner);
72bus-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); } 90 return start_token;
73ref-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); } 91 }
74cpu-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); } 92 }
75task-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); } 93%}
76page-faults|faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); } 94
77minor-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); } 95cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
78major-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); } 96stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
79context-switches|cs { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); } 97stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
80cpu-migrations|migrations { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); } 98instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
81alignment-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } 99cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
82emulation-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 100cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
101branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
102branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
103bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
104ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
105cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
106task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
107page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
108minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
109major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
110context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
111cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
112alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
113emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
83 114
84L1-dcache|l1-d|l1d|L1-data | 115L1-dcache|l1-d|l1d|L1-data |
85L1-icache|l1-i|l1i|L1-instruction | 116L1-icache|l1-i|l1i|L1-instruction |
@@ -87,14 +118,14 @@ LLC|L2 |
87dTLB|d-tlb|Data-TLB | 118dTLB|d-tlb|Data-TLB |
88iTLB|i-tlb|Instruction-TLB | 119iTLB|i-tlb|Instruction-TLB |
89branch|branches|bpu|btb|bpc | 120branch|branches|bpu|btb|bpc |
90node { return str(PE_NAME_CACHE_TYPE); } 121node { return str(yyscanner, PE_NAME_CACHE_TYPE); }
91 122
92load|loads|read | 123load|loads|read |
93store|stores|write | 124store|stores|write |
94prefetch|prefetches | 125prefetch|prefetches |
95speculative-read|speculative-load | 126speculative-read|speculative-load |
96refs|Reference|ops|access | 127refs|Reference|ops|access |
97misses|miss { return str(PE_NAME_CACHE_OP_RESULT); } 128misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
98 129
99 /* 130 /*
100 * These are event config hardcoded term names to be specified 131 * These are event config hardcoded term names to be specified
@@ -102,38 +133,39 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
102 * so we can put them here directly. In case the we have a conflict 133 * so we can put them here directly. In case the we have a conflict
103 * in future, this needs to go into '//' condition block. 134 * in future, this needs to go into '//' condition block.
104 */ 135 */
105config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); } 136config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
106config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); } 137config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
107config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); } 138config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
108name { return term(PARSE_EVENTS__TERM_TYPE_NAME); } 139name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
109period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } 140period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
110branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 141branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
111 142
112mem: { BEGIN(mem); return PE_PREFIX_MEM; } 143mem: { BEGIN(mem); return PE_PREFIX_MEM; }
113r{num_raw_hex} { return raw(); } 144r{num_raw_hex} { return raw(yyscanner); }
114{num_dec} { return value(10); } 145{num_dec} { return value(yyscanner, 10); }
115{num_hex} { return value(16); } 146{num_hex} { return value(yyscanner, 16); }
116 147
117{modifier_event} { return str(PE_MODIFIER_EVENT); } 148{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
118{name} { return str(PE_NAME); } 149{name} { return str(yyscanner, PE_NAME); }
119"/" { return '/'; } 150"/" { return '/'; }
120- { return '-'; } 151- { return '-'; }
121, { return ','; } 152, { return ','; }
122: { return ':'; } 153: { return ':'; }
123= { return '='; } 154= { return '='; }
155\n { }
124 156
125<mem>{ 157<mem>{
126{modifier_bp} { return str(PE_MODIFIER_BP); } 158{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
127: { return ':'; } 159: { return ':'; }
128{num_dec} { return value(10); } 160{num_dec} { return value(yyscanner, 10); }
129{num_hex} { return value(16); } 161{num_hex} { return value(yyscanner, 16); }
130 /* 162 /*
131 * We need to separate 'mem:' scanner part, in order to get specific 163 * We need to separate 'mem:' scanner part, in order to get specific
132 * modifier bits parsed out. Otherwise we would need to handle PE_NAME 164 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
133 * and we'd need to parse it manually. During the escape from <mem> 165 * and we'd need to parse it manually. During the escape from <mem>
134 * state we need to put the escaping char back, so we dont miss it. 166 * state we need to put the escaping char back, so we dont miss it.
135 */ 167 */
136. { unput(*parse_events_text); BEGIN(INITIAL); } 168. { unput(*yytext); BEGIN(INITIAL); }
137 /* 169 /*
138 * We destroy the scanner after reaching EOF, 170 * We destroy the scanner after reaching EOF,
139 * but anyway just to be sure get back to INIT state. 171 * but anyway just to be sure get back to INIT state.
@@ -143,7 +175,7 @@ r{num_raw_hex} { return raw(); }
143 175
144%% 176%%
145 177
146int parse_events_wrap(void) 178int parse_events_wrap(void *scanner __used)
147{ 179{
148 return 1; 180 return 1;
149} 181}
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 362cc59332ae..2bc5fbff2b5d 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -1,7 +1,8 @@
1 1%pure-parser
2%name-prefix "parse_events_" 2%name-prefix "parse_events_"
3%parse-param {struct list_head *list_all} 3%parse-param {void *_data}
4%parse-param {int *idx} 4%parse-param {void *scanner}
5%lex-param {void* scanner}
5 6
6%{ 7%{
7 8
@@ -12,8 +13,9 @@
12#include "types.h" 13#include "types.h"
13#include "util.h" 14#include "util.h"
14#include "parse-events.h" 15#include "parse-events.h"
16#include "parse-events-bison.h"
15 17
16extern int parse_events_lex (void); 18extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
17 19
18#define ABORT_ON(val) \ 20#define ABORT_ON(val) \
19do { \ 21do { \
@@ -23,14 +25,16 @@ do { \
23 25
24%} 26%}
25 27
26%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM 28%token PE_START_EVENTS PE_START_TERMS
29%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
27%token PE_NAME 30%token PE_NAME
28%token PE_MODIFIER_EVENT PE_MODIFIER_BP 31%token PE_MODIFIER_EVENT PE_MODIFIER_BP
29%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 32%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
30%token PE_PREFIX_MEM PE_PREFIX_RAW 33%token PE_PREFIX_MEM PE_PREFIX_RAW
31%token PE_ERROR 34%token PE_ERROR
32%type <num> PE_VALUE 35%type <num> PE_VALUE
33%type <num> PE_VALUE_SYM 36%type <num> PE_VALUE_SYM_HW
37%type <num> PE_VALUE_SYM_SW
34%type <num> PE_RAW 38%type <num> PE_RAW
35%type <num> PE_TERM 39%type <num> PE_TERM
36%type <str> PE_NAME 40%type <str> PE_NAME
@@ -38,6 +42,7 @@ do { \
38%type <str> PE_NAME_CACHE_OP_RESULT 42%type <str> PE_NAME_CACHE_OP_RESULT
39%type <str> PE_MODIFIER_EVENT 43%type <str> PE_MODIFIER_EVENT
40%type <str> PE_MODIFIER_BP 44%type <str> PE_MODIFIER_BP
45%type <num> value_sym
41%type <head> event_config 46%type <head> event_config
42%type <term> event_term 47%type <term> event_term
43%type <head> event_pmu 48%type <head> event_pmu
@@ -58,24 +63,33 @@ do { \
58} 63}
59%% 64%%
60 65
66start:
67PE_START_EVENTS events
68|
69PE_START_TERMS terms
70
61events: 71events:
62events ',' event | event 72events ',' event | event
63 73
64event: 74event:
65event_def PE_MODIFIER_EVENT 75event_def PE_MODIFIER_EVENT
66{ 76{
77 struct parse_events_data__events *data = _data;
78
67 /* 79 /*
68 * Apply modifier on all events added by single event definition 80 * Apply modifier on all events added by single event definition
69 * (there could be more events added for multiple tracepoint 81 * (there could be more events added for multiple tracepoint
70 * definitions via '*?'. 82 * definitions via '*?'.
71 */ 83 */
72 ABORT_ON(parse_events_modifier($1, $2)); 84 ABORT_ON(parse_events_modifier($1, $2));
73 parse_events_update_lists($1, list_all); 85 parse_events_update_lists($1, &data->list);
74} 86}
75| 87|
76event_def 88event_def
77{ 89{
78 parse_events_update_lists($1, list_all); 90 struct parse_events_data__events *data = _data;
91
92 parse_events_update_lists($1, &data->list);
79} 93}
80 94
81event_def: event_pmu | 95event_def: event_pmu |
@@ -89,104 +103,131 @@ event_def: event_pmu |
89event_pmu: 103event_pmu:
90PE_NAME '/' event_config '/' 104PE_NAME '/' event_config '/'
91{ 105{
106 struct parse_events_data__events *data = _data;
92 struct list_head *list = NULL; 107 struct list_head *list = NULL;
93 108
94 ABORT_ON(parse_events_add_pmu(&list, idx, $1, $3)); 109 ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3));
95 parse_events__free_terms($3); 110 parse_events__free_terms($3);
96 $$ = list; 111 $$ = list;
97} 112}
98 113
114value_sym:
115PE_VALUE_SYM_HW
116|
117PE_VALUE_SYM_SW
118
99event_legacy_symbol: 119event_legacy_symbol:
100PE_VALUE_SYM '/' event_config '/' 120value_sym '/' event_config '/'
101{ 121{
122 struct parse_events_data__events *data = _data;
102 struct list_head *list = NULL; 123 struct list_head *list = NULL;
103 int type = $1 >> 16; 124 int type = $1 >> 16;
104 int config = $1 & 255; 125 int config = $1 & 255;
105 126
106 ABORT_ON(parse_events_add_numeric(&list, idx, type, config, $3)); 127 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
128 type, config, $3));
107 parse_events__free_terms($3); 129 parse_events__free_terms($3);
108 $$ = list; 130 $$ = list;
109} 131}
110| 132|
111PE_VALUE_SYM sep_slash_dc 133value_sym sep_slash_dc
112{ 134{
135 struct parse_events_data__events *data = _data;
113 struct list_head *list = NULL; 136 struct list_head *list = NULL;
114 int type = $1 >> 16; 137 int type = $1 >> 16;
115 int config = $1 & 255; 138 int config = $1 & 255;
116 139
117 ABORT_ON(parse_events_add_numeric(&list, idx, type, config, NULL)); 140 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
141 type, config, NULL));
118 $$ = list; 142 $$ = list;
119} 143}
120 144
121event_legacy_cache: 145event_legacy_cache:
122PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 146PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
123{ 147{
148 struct parse_events_data__events *data = _data;
124 struct list_head *list = NULL; 149 struct list_head *list = NULL;
125 150
126 ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, $5)); 151 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5));
127 $$ = list; 152 $$ = list;
128} 153}
129| 154|
130PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 155PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
131{ 156{
157 struct parse_events_data__events *data = _data;
132 struct list_head *list = NULL; 158 struct list_head *list = NULL;
133 159
134 ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, NULL)); 160 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL));
135 $$ = list; 161 $$ = list;
136} 162}
137| 163|
138PE_NAME_CACHE_TYPE 164PE_NAME_CACHE_TYPE
139{ 165{
166 struct parse_events_data__events *data = _data;
140 struct list_head *list = NULL; 167 struct list_head *list = NULL;
141 168
142 ABORT_ON(parse_events_add_cache(&list, idx, $1, NULL, NULL)); 169 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL));
143 $$ = list; 170 $$ = list;
144} 171}
145 172
146event_legacy_mem: 173event_legacy_mem:
147PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 174PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
148{ 175{
176 struct parse_events_data__events *data = _data;
149 struct list_head *list = NULL; 177 struct list_head *list = NULL;
150 178
151 ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, $4)); 179 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
180 (void *) $2, $4));
152 $$ = list; 181 $$ = list;
153} 182}
154| 183|
155PE_PREFIX_MEM PE_VALUE sep_dc 184PE_PREFIX_MEM PE_VALUE sep_dc
156{ 185{
186 struct parse_events_data__events *data = _data;
157 struct list_head *list = NULL; 187 struct list_head *list = NULL;
158 188
159 ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, NULL)); 189 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
190 (void *) $2, NULL));
160 $$ = list; 191 $$ = list;
161} 192}
162 193
163event_legacy_tracepoint: 194event_legacy_tracepoint:
164PE_NAME ':' PE_NAME 195PE_NAME ':' PE_NAME
165{ 196{
197 struct parse_events_data__events *data = _data;
166 struct list_head *list = NULL; 198 struct list_head *list = NULL;
167 199
168 ABORT_ON(parse_events_add_tracepoint(&list, idx, $1, $3)); 200 ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3));
169 $$ = list; 201 $$ = list;
170} 202}
171 203
172event_legacy_numeric: 204event_legacy_numeric:
173PE_VALUE ':' PE_VALUE 205PE_VALUE ':' PE_VALUE
174{ 206{
207 struct parse_events_data__events *data = _data;
175 struct list_head *list = NULL; 208 struct list_head *list = NULL;
176 209
177 ABORT_ON(parse_events_add_numeric(&list, idx, $1, $3, NULL)); 210 ABORT_ON(parse_events_add_numeric(&list, &data->idx, $1, $3, NULL));
178 $$ = list; 211 $$ = list;
179} 212}
180 213
181event_legacy_raw: 214event_legacy_raw:
182PE_RAW 215PE_RAW
183{ 216{
217 struct parse_events_data__events *data = _data;
184 struct list_head *list = NULL; 218 struct list_head *list = NULL;
185 219
186 ABORT_ON(parse_events_add_numeric(&list, idx, PERF_TYPE_RAW, $1, NULL)); 220 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
221 PERF_TYPE_RAW, $1, NULL));
187 $$ = list; 222 $$ = list;
188} 223}
189 224
225terms: event_config
226{
227 struct parse_events_data__terms *data = _data;
228 data->terms = $1;
229}
230
190event_config: 231event_config:
191event_config ',' event_term 232event_config ',' event_term
192{ 233{
@@ -267,8 +308,7 @@ sep_slash_dc: '/' | ':' |
267 308
268%% 309%%
269 310
270void parse_events_error(struct list_head *list_all __used, 311void parse_events_error(void *data __used, void *scanner __used,
271 int *idx __used,
272 char const *msg __used) 312 char const *msg __used)
273{ 313{
274} 314}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index a119a5371699..67715a42cd6d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
72 "%s/bus/event_source/devices/%s/format", sysfs, name); 72 "%s/bus/event_source/devices/%s/format", sysfs, name);
73 73
74 if (stat(path, &st) < 0) 74 if (stat(path, &st) < 0)
75 return -1; 75 return 0; /* no error if format does not exist */
76 76
77 if (pmu_format_parse(path, format)) 77 if (pmu_format_parse(path, format))
78 return -1; 78 return -1;
@@ -80,6 +80,114 @@ static int pmu_format(char *name, struct list_head *format)
80 return 0; 80 return 0;
81} 81}
82 82
83static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
84{
85 struct perf_pmu__alias *alias;
86 char buf[256];
87 int ret;
88
89 ret = fread(buf, 1, sizeof(buf), file);
90 if (ret == 0)
91 return -EINVAL;
92 buf[ret] = 0;
93
94 alias = malloc(sizeof(*alias));
95 if (!alias)
96 return -ENOMEM;
97
98 INIT_LIST_HEAD(&alias->terms);
99 ret = parse_events_terms(&alias->terms, buf);
100 if (ret) {
101 free(alias);
102 return ret;
103 }
104
105 alias->name = strdup(name);
106 list_add_tail(&alias->list, list);
107 return 0;
108}
109
110/*
111 * Process all the sysfs attributes located under the directory
112 * specified in 'dir' parameter.
113 */
114static int pmu_aliases_parse(char *dir, struct list_head *head)
115{
116 struct dirent *evt_ent;
117 DIR *event_dir;
118 int ret = 0;
119
120 event_dir = opendir(dir);
121 if (!event_dir)
122 return -EINVAL;
123
124 while (!ret && (evt_ent = readdir(event_dir))) {
125 char path[PATH_MAX];
126 char *name = evt_ent->d_name;
127 FILE *file;
128
129 if (!strcmp(name, ".") || !strcmp(name, ".."))
130 continue;
131
132 snprintf(path, PATH_MAX, "%s/%s", dir, name);
133
134 ret = -EINVAL;
135 file = fopen(path, "r");
136 if (!file)
137 break;
138 ret = perf_pmu__new_alias(head, name, file);
139 fclose(file);
140 }
141
142 closedir(event_dir);
143 return ret;
144}
145
146/*
147 * Reading the pmu event aliases definition, which should be located at:
148 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
149 */
150static int pmu_aliases(char *name, struct list_head *head)
151{
152 struct stat st;
153 char path[PATH_MAX];
154 const char *sysfs;
155
156 sysfs = sysfs_find_mountpoint();
157 if (!sysfs)
158 return -1;
159
160 snprintf(path, PATH_MAX,
161 "%s/bus/event_source/devices/%s/events", sysfs, name);
162
163 if (stat(path, &st) < 0)
164 return -1;
165
166 if (pmu_aliases_parse(path, head))
167 return -1;
168
169 return 0;
170}
171
172static int pmu_alias_terms(struct perf_pmu__alias *alias,
173 struct list_head *terms)
174{
175 struct parse_events__term *term, *clone;
176 LIST_HEAD(list);
177 int ret;
178
179 list_for_each_entry(term, &alias->terms, list) {
180 ret = parse_events__term_clone(&clone, term);
181 if (ret) {
182 parse_events__free_terms(&list);
183 return ret;
184 }
185 list_add_tail(&clone->list, &list);
186 }
187 list_splice(&list, terms);
188 return 0;
189}
190
83/* 191/*
84 * Reading/parsing the default pmu type value, which should be 192 * Reading/parsing the default pmu type value, which should be
85 * located at: 193 * located at:
@@ -118,6 +226,7 @@ static struct perf_pmu *pmu_lookup(char *name)
118{ 226{
119 struct perf_pmu *pmu; 227 struct perf_pmu *pmu;
120 LIST_HEAD(format); 228 LIST_HEAD(format);
229 LIST_HEAD(aliases);
121 __u32 type; 230 __u32 type;
122 231
123 /* 232 /*
@@ -135,10 +244,15 @@ static struct perf_pmu *pmu_lookup(char *name)
135 if (!pmu) 244 if (!pmu)
136 return NULL; 245 return NULL;
137 246
247 pmu_aliases(name, &aliases);
248
138 INIT_LIST_HEAD(&pmu->format); 249 INIT_LIST_HEAD(&pmu->format);
250 INIT_LIST_HEAD(&pmu->aliases);
139 list_splice(&format, &pmu->format); 251 list_splice(&format, &pmu->format);
252 list_splice(&aliases, &pmu->aliases);
140 pmu->name = strdup(name); 253 pmu->name = strdup(name);
141 pmu->type = type; 254 pmu->type = type;
255 list_add_tail(&pmu->list, &pmus);
142 return pmu; 256 return pmu;
143} 257}
144 258
@@ -279,6 +393,59 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
279 return pmu_config(&pmu->format, attr, head_terms); 393 return pmu_config(&pmu->format, attr, head_terms);
280} 394}
281 395
396static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
397 struct parse_events__term *term)
398{
399 struct perf_pmu__alias *alias;
400 char *name;
401
402 if (parse_events__is_hardcoded_term(term))
403 return NULL;
404
405 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
406 if (term->val.num != 1)
407 return NULL;
408 if (pmu_find_format(&pmu->format, term->config))
409 return NULL;
410 name = term->config;
411 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
412 if (strcasecmp(term->config, "event"))
413 return NULL;
414 name = term->val.str;
415 } else {
416 return NULL;
417 }
418
419 list_for_each_entry(alias, &pmu->aliases, list) {
420 if (!strcasecmp(alias->name, name))
421 return alias;
422 }
423 return NULL;
424}
425
426/*
427 * Find alias in the terms list and replace it with the terms
428 * defined for the alias
429 */
430int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
431{
432 struct parse_events__term *term, *h;
433 struct perf_pmu__alias *alias;
434 int ret;
435
436 list_for_each_entry_safe(term, h, head_terms, list) {
437 alias = pmu_find_alias(pmu, term);
438 if (!alias)
439 continue;
440 ret = pmu_alias_terms(alias, &term->list);
441 if (ret)
442 return ret;
443 list_del(&term->list);
444 free(term);
445 }
446 return 0;
447}
448
282int perf_pmu__new_format(struct list_head *list, char *name, 449int perf_pmu__new_format(struct list_head *list, char *name,
283 int config, unsigned long *bits) 450 int config, unsigned long *bits)
284{ 451{
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 68c0db965e1f..535f2c5258ab 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -19,17 +19,26 @@ struct perf_pmu__format {
19 struct list_head list; 19 struct list_head list;
20}; 20};
21 21
22struct perf_pmu__alias {
23 char *name;
24 struct list_head terms;
25 struct list_head list;
26};
27
22struct perf_pmu { 28struct perf_pmu {
23 char *name; 29 char *name;
24 __u32 type; 30 __u32 type;
25 struct list_head format; 31 struct list_head format;
32 struct list_head aliases;
26 struct list_head list; 33 struct list_head list;
27}; 34};
28 35
29struct perf_pmu *perf_pmu__find(char *name); 36struct perf_pmu *perf_pmu__find(char *name);
30int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 37int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
31 struct list_head *head_terms); 38 struct list_head *head_terms);
32 39int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
40struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
41 struct list_head *head_terms);
33int perf_pmu_wrap(void); 42int perf_pmu_wrap(void);
34void perf_pmu_error(struct list_head *list, char *name, char const *msg); 43void perf_pmu_error(struct list_head *list, char *name, char const *msg);
35 44
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 59dccc98b554..0dda25d82d06 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2164,16 +2164,12 @@ int del_perf_probe_events(struct strlist *dellist)
2164 2164
2165error: 2165error:
2166 if (kfd >= 0) { 2166 if (kfd >= 0) {
2167 if (namelist) 2167 strlist__delete(namelist);
2168 strlist__delete(namelist);
2169
2170 close(kfd); 2168 close(kfd);
2171 } 2169 }
2172 2170
2173 if (ufd >= 0) { 2171 if (ufd >= 0) {
2174 if (unamelist) 2172 strlist__delete(unamelist);
2175 strlist__delete(unamelist);
2176
2177 close(ufd); 2173 close(ufd);
2178 } 2174 }
2179 2175
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 4c1b3d72a1d2..02dfa19a467f 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -209,6 +209,10 @@ static void define_event_symbols(struct event_format *event,
209 define_symbolic_values(args->symbol.symbols, ev_name, 209 define_symbolic_values(args->symbol.symbols, ev_name,
210 cur_field_name); 210 cur_field_name);
211 break; 211 break;
212 case PRINT_HEX:
213 define_event_symbols(event, ev_name, args->hex.field);
214 define_event_symbols(event, ev_name, args->hex.size);
215 break;
212 case PRINT_BSTRING: 216 case PRINT_BSTRING:
213 case PRINT_DYNAMIC_ARRAY: 217 case PRINT_DYNAMIC_ARRAY:
214 case PRINT_STRING: 218 case PRINT_STRING:
@@ -233,7 +237,8 @@ static void define_event_symbols(struct event_format *event,
233 define_event_symbols(event, ev_name, args->next); 237 define_event_symbols(event, ev_name, args->next);
234} 238}
235 239
236static inline struct event_format *find_cache_event(int type) 240static inline
241struct event_format *find_cache_event(struct pevent *pevent, int type)
237{ 242{
238 static char ev_name[256]; 243 static char ev_name[256];
239 struct event_format *event; 244 struct event_format *event;
@@ -241,7 +246,7 @@ static inline struct event_format *find_cache_event(int type)
241 if (events[type]) 246 if (events[type])
242 return events[type]; 247 return events[type];
243 248
244 events[type] = event = trace_find_event(type); 249 events[type] = event = pevent_find_event(pevent, type);
245 if (!event) 250 if (!event)
246 return NULL; 251 return NULL;
247 252
@@ -252,7 +257,8 @@ static inline struct event_format *find_cache_event(int type)
252 return event; 257 return event;
253} 258}
254 259
255static void perl_process_tracepoint(union perf_event *pevent __unused, 260static void perl_process_tracepoint(union perf_event *perf_event __unused,
261 struct pevent *pevent,
256 struct perf_sample *sample, 262 struct perf_sample *sample,
257 struct perf_evsel *evsel, 263 struct perf_evsel *evsel,
258 struct machine *machine __unused, 264 struct machine *machine __unused,
@@ -275,13 +281,13 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
275 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 281 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
276 return; 282 return;
277 283
278 type = trace_parse_common_type(data); 284 type = trace_parse_common_type(pevent, data);
279 285
280 event = find_cache_event(type); 286 event = find_cache_event(pevent, type);
281 if (!event) 287 if (!event)
282 die("ug! no event found for type %d", type); 288 die("ug! no event found for type %d", type);
283 289
284 pid = trace_parse_common_pid(data); 290 pid = trace_parse_common_pid(pevent, data);
285 291
286 sprintf(handler, "%s::%s", event->system, event->name); 292 sprintf(handler, "%s::%s", event->system, event->name);
287 293
@@ -314,7 +320,8 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
314 offset = field->offset; 320 offset = field->offset;
315 XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0))); 321 XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
316 } else { /* FIELD_IS_NUMERIC */ 322 } else { /* FIELD_IS_NUMERIC */
317 val = read_size(data + field->offset, field->size); 323 val = read_size(pevent, data + field->offset,
324 field->size);
318 if (field->flags & FIELD_IS_SIGNED) { 325 if (field->flags & FIELD_IS_SIGNED) {
319 XPUSHs(sv_2mortal(newSViv(val))); 326 XPUSHs(sv_2mortal(newSViv(val)));
320 } else { 327 } else {
@@ -368,14 +375,15 @@ static void perl_process_event_generic(union perf_event *pevent __unused,
368 LEAVE; 375 LEAVE;
369} 376}
370 377
371static void perl_process_event(union perf_event *pevent, 378static void perl_process_event(union perf_event *event,
379 struct pevent *pevent,
372 struct perf_sample *sample, 380 struct perf_sample *sample,
373 struct perf_evsel *evsel, 381 struct perf_evsel *evsel,
374 struct machine *machine, 382 struct machine *machine,
375 struct thread *thread) 383 struct thread *thread)
376{ 384{
377 perl_process_tracepoint(pevent, sample, evsel, machine, thread); 385 perl_process_tracepoint(event, pevent, sample, evsel, machine, thread);
378 perl_process_event_generic(pevent, sample, evsel, machine, thread); 386 perl_process_event_generic(event, sample, evsel, machine, thread);
379} 387}
380 388
381static void run_start_sub(void) 389static void run_start_sub(void)
@@ -448,7 +456,7 @@ static int perl_stop_script(void)
448 return 0; 456 return 0;
449} 457}
450 458
451static int perl_generate_script(const char *outfile) 459static int perl_generate_script(struct pevent *pevent, const char *outfile)
452{ 460{
453 struct event_format *event = NULL; 461 struct event_format *event = NULL;
454 struct format_field *f; 462 struct format_field *f;
@@ -495,7 +503,7 @@ static int perl_generate_script(const char *outfile)
495 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n"); 503 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
496 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n"); 504 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n");
497 505
498 while ((event = trace_find_next_event(event))) { 506 while ((event = trace_find_next_event(pevent, event))) {
499 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name); 507 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
500 fprintf(ofp, "\tmy ("); 508 fprintf(ofp, "\tmy (");
501 509
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index acb9795286c4..ce4d1b0c3862 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -166,6 +166,10 @@ static void define_event_symbols(struct event_format *event,
166 define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, 166 define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
167 cur_field_name); 167 cur_field_name);
168 break; 168 break;
169 case PRINT_HEX:
170 define_event_symbols(event, ev_name, args->hex.field);
171 define_event_symbols(event, ev_name, args->hex.size);
172 break;
169 case PRINT_STRING: 173 case PRINT_STRING:
170 break; 174 break;
171 case PRINT_TYPE: 175 case PRINT_TYPE:
@@ -190,7 +194,8 @@ static void define_event_symbols(struct event_format *event,
190 define_event_symbols(event, ev_name, args->next); 194 define_event_symbols(event, ev_name, args->next);
191} 195}
192 196
193static inline struct event_format *find_cache_event(int type) 197static inline
198struct event_format *find_cache_event(struct pevent *pevent, int type)
194{ 199{
195 static char ev_name[256]; 200 static char ev_name[256];
196 struct event_format *event; 201 struct event_format *event;
@@ -198,7 +203,7 @@ static inline struct event_format *find_cache_event(int type)
198 if (events[type]) 203 if (events[type])
199 return events[type]; 204 return events[type];
200 205
201 events[type] = event = trace_find_event(type); 206 events[type] = event = pevent_find_event(pevent, type);
202 if (!event) 207 if (!event)
203 return NULL; 208 return NULL;
204 209
@@ -209,7 +214,8 @@ static inline struct event_format *find_cache_event(int type)
209 return event; 214 return event;
210} 215}
211 216
212static void python_process_event(union perf_event *pevent __unused, 217static void python_process_event(union perf_event *perf_event __unused,
218 struct pevent *pevent,
213 struct perf_sample *sample, 219 struct perf_sample *sample,
214 struct perf_evsel *evsel __unused, 220 struct perf_evsel *evsel __unused,
215 struct machine *machine __unused, 221 struct machine *machine __unused,
@@ -233,13 +239,13 @@ static void python_process_event(union perf_event *pevent __unused,
233 if (!t) 239 if (!t)
234 Py_FatalError("couldn't create Python tuple"); 240 Py_FatalError("couldn't create Python tuple");
235 241
236 type = trace_parse_common_type(data); 242 type = trace_parse_common_type(pevent, data);
237 243
238 event = find_cache_event(type); 244 event = find_cache_event(pevent, type);
239 if (!event) 245 if (!event)
240 die("ug! no event found for type %d", type); 246 die("ug! no event found for type %d", type);
241 247
242 pid = trace_parse_common_pid(data); 248 pid = trace_parse_common_pid(pevent, data);
243 249
244 sprintf(handler_name, "%s__%s", event->system, event->name); 250 sprintf(handler_name, "%s__%s", event->system, event->name);
245 251
@@ -284,7 +290,8 @@ static void python_process_event(union perf_event *pevent __unused,
284 offset = field->offset; 290 offset = field->offset;
285 obj = PyString_FromString((char *)data + offset); 291 obj = PyString_FromString((char *)data + offset);
286 } else { /* FIELD_IS_NUMERIC */ 292 } else { /* FIELD_IS_NUMERIC */
287 val = read_size(data + field->offset, field->size); 293 val = read_size(pevent, data + field->offset,
294 field->size);
288 if (field->flags & FIELD_IS_SIGNED) { 295 if (field->flags & FIELD_IS_SIGNED) {
289 if ((long long)val >= LONG_MIN && 296 if ((long long)val >= LONG_MIN &&
290 (long long)val <= LONG_MAX) 297 (long long)val <= LONG_MAX)
@@ -438,7 +445,7 @@ out:
438 return err; 445 return err;
439} 446}
440 447
441static int python_generate_script(const char *outfile) 448static int python_generate_script(struct pevent *pevent, const char *outfile)
442{ 449{
443 struct event_format *event = NULL; 450 struct event_format *event = NULL;
444 struct format_field *f; 451 struct format_field *f;
@@ -487,7 +494,7 @@ static int python_generate_script(const char *outfile)
487 fprintf(ofp, "def trace_end():\n"); 494 fprintf(ofp, "def trace_end():\n");
488 fprintf(ofp, "\tprint \"in trace_end\"\n\n"); 495 fprintf(ofp, "\tprint \"in trace_end\"\n\n");
489 496
490 while ((event = trace_find_next_event(event))) { 497 while ((event = trace_find_next_event(pevent, event))) {
491 fprintf(ofp, "def %s__%s(", event->system, event->name); 498 fprintf(ofp, "def %s__%s(", event->system, event->name);
492 fprintf(ofp, "event_name, "); 499 fprintf(ofp, "event_name, ");
493 fprintf(ofp, "context, "); 500 fprintf(ofp, "context, ");
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 93d355d27109..8e4f0755d2aa 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,7 @@
14#include "sort.h" 14#include "sort.h"
15#include "util.h" 15#include "util.h"
16#include "cpumap.h" 16#include "cpumap.h"
17#include "event-parse.h"
17 18
18static int perf_session__open(struct perf_session *self, bool force) 19static int perf_session__open(struct perf_session *self, bool force)
19{ 20{
@@ -86,6 +87,7 @@ void perf_session__update_sample_type(struct perf_session *self)
86 self->sample_id_all = perf_evlist__sample_id_all(self->evlist); 87 self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
87 self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); 88 self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
88 self->host_machine.id_hdr_size = self->id_hdr_size; 89 self->host_machine.id_hdr_size = self->id_hdr_size;
90 machines__set_id_hdr_size(&self->machines, self->id_hdr_size);
89} 91}
90 92
91int perf_session__create_kernel_maps(struct perf_session *self) 93int perf_session__create_kernel_maps(struct perf_session *self)
@@ -288,7 +290,7 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
288 return bi; 290 return bi;
289} 291}
290 292
291int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, 293int machine__resolve_callchain(struct machine *self,
292 struct thread *thread, 294 struct thread *thread,
293 struct ip_callchain *chain, 295 struct ip_callchain *chain,
294 struct symbol **parent) 296 struct symbol **parent)
@@ -297,7 +299,12 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
297 unsigned int i; 299 unsigned int i;
298 int err; 300 int err;
299 301
300 callchain_cursor_reset(&evsel->hists.callchain_cursor); 302 callchain_cursor_reset(&callchain_cursor);
303
304 if (chain->nr > PERF_MAX_STACK_DEPTH) {
305 pr_warning("corrupted callchain. skipping...\n");
306 return 0;
307 }
301 308
302 for (i = 0; i < chain->nr; i++) { 309 for (i = 0; i < chain->nr; i++) {
303 u64 ip; 310 u64 ip;
@@ -317,7 +324,14 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
317 case PERF_CONTEXT_USER: 324 case PERF_CONTEXT_USER:
318 cpumode = PERF_RECORD_MISC_USER; break; 325 cpumode = PERF_RECORD_MISC_USER; break;
319 default: 326 default:
320 break; 327 pr_debug("invalid callchain context: "
328 "%"PRId64"\n", (s64) ip);
329 /*
330 * It seems the callchain is corrupted.
331 * Discard all.
332 */
333 callchain_cursor_reset(&callchain_cursor);
334 return 0;
321 } 335 }
322 continue; 336 continue;
323 } 337 }
@@ -333,7 +347,7 @@ int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
333 break; 347 break;
334 } 348 }
335 349
336 err = callchain_cursor_append(&evsel->hists.callchain_cursor, 350 err = callchain_cursor_append(&callchain_cursor,
337 ip, al.map, al.sym); 351 ip, al.map, al.sym);
338 if (err) 352 if (err)
339 return err; 353 return err;
@@ -429,6 +443,16 @@ static void perf_tool__fill_defaults(struct perf_tool *tool)
429 tool->finished_round = process_finished_round_stub; 443 tool->finished_round = process_finished_round_stub;
430 } 444 }
431} 445}
446
447void mem_bswap_32(void *src, int byte_size)
448{
449 u32 *m = src;
450 while (byte_size > 0) {
451 *m = bswap_32(*m);
452 byte_size -= sizeof(u32);
453 ++m;
454 }
455}
432 456
433void mem_bswap_64(void *src, int byte_size) 457void mem_bswap_64(void *src, int byte_size)
434{ 458{
@@ -441,37 +465,65 @@ void mem_bswap_64(void *src, int byte_size)
441 } 465 }
442} 466}
443 467
444static void perf_event__all64_swap(union perf_event *event) 468static void swap_sample_id_all(union perf_event *event, void *data)
469{
470 void *end = (void *) event + event->header.size;
471 int size = end - data;
472
473 BUG_ON(size % sizeof(u64));
474 mem_bswap_64(data, size);
475}
476
477static void perf_event__all64_swap(union perf_event *event,
478 bool sample_id_all __used)
445{ 479{
446 struct perf_event_header *hdr = &event->header; 480 struct perf_event_header *hdr = &event->header;
447 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); 481 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));
448} 482}
449 483
450static void perf_event__comm_swap(union perf_event *event) 484static void perf_event__comm_swap(union perf_event *event, bool sample_id_all)
451{ 485{
452 event->comm.pid = bswap_32(event->comm.pid); 486 event->comm.pid = bswap_32(event->comm.pid);
453 event->comm.tid = bswap_32(event->comm.tid); 487 event->comm.tid = bswap_32(event->comm.tid);
488
489 if (sample_id_all) {
490 void *data = &event->comm.comm;
491
492 data += ALIGN(strlen(data) + 1, sizeof(u64));
493 swap_sample_id_all(event, data);
494 }
454} 495}
455 496
456static void perf_event__mmap_swap(union perf_event *event) 497static void perf_event__mmap_swap(union perf_event *event,
498 bool sample_id_all)
457{ 499{
458 event->mmap.pid = bswap_32(event->mmap.pid); 500 event->mmap.pid = bswap_32(event->mmap.pid);
459 event->mmap.tid = bswap_32(event->mmap.tid); 501 event->mmap.tid = bswap_32(event->mmap.tid);
460 event->mmap.start = bswap_64(event->mmap.start); 502 event->mmap.start = bswap_64(event->mmap.start);
461 event->mmap.len = bswap_64(event->mmap.len); 503 event->mmap.len = bswap_64(event->mmap.len);
462 event->mmap.pgoff = bswap_64(event->mmap.pgoff); 504 event->mmap.pgoff = bswap_64(event->mmap.pgoff);
505
506 if (sample_id_all) {
507 void *data = &event->mmap.filename;
508
509 data += ALIGN(strlen(data) + 1, sizeof(u64));
510 swap_sample_id_all(event, data);
511 }
463} 512}
464 513
465static void perf_event__task_swap(union perf_event *event) 514static void perf_event__task_swap(union perf_event *event, bool sample_id_all)
466{ 515{
467 event->fork.pid = bswap_32(event->fork.pid); 516 event->fork.pid = bswap_32(event->fork.pid);
468 event->fork.tid = bswap_32(event->fork.tid); 517 event->fork.tid = bswap_32(event->fork.tid);
469 event->fork.ppid = bswap_32(event->fork.ppid); 518 event->fork.ppid = bswap_32(event->fork.ppid);
470 event->fork.ptid = bswap_32(event->fork.ptid); 519 event->fork.ptid = bswap_32(event->fork.ptid);
471 event->fork.time = bswap_64(event->fork.time); 520 event->fork.time = bswap_64(event->fork.time);
521
522 if (sample_id_all)
523 swap_sample_id_all(event, &event->fork + 1);
472} 524}
473 525
474static void perf_event__read_swap(union perf_event *event) 526static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
475{ 527{
476 event->read.pid = bswap_32(event->read.pid); 528 event->read.pid = bswap_32(event->read.pid);
477 event->read.tid = bswap_32(event->read.tid); 529 event->read.tid = bswap_32(event->read.tid);
@@ -479,6 +531,9 @@ static void perf_event__read_swap(union perf_event *event)
479 event->read.time_enabled = bswap_64(event->read.time_enabled); 531 event->read.time_enabled = bswap_64(event->read.time_enabled);
480 event->read.time_running = bswap_64(event->read.time_running); 532 event->read.time_running = bswap_64(event->read.time_running);
481 event->read.id = bswap_64(event->read.id); 533 event->read.id = bswap_64(event->read.id);
534
535 if (sample_id_all)
536 swap_sample_id_all(event, &event->read + 1);
482} 537}
483 538
484static u8 revbyte(u8 b) 539static u8 revbyte(u8 b)
@@ -530,7 +585,8 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
530 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); 585 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
531} 586}
532 587
533static void perf_event__hdr_attr_swap(union perf_event *event) 588static void perf_event__hdr_attr_swap(union perf_event *event,
589 bool sample_id_all __used)
534{ 590{
535 size_t size; 591 size_t size;
536 592
@@ -541,18 +597,21 @@ static void perf_event__hdr_attr_swap(union perf_event *event)
541 mem_bswap_64(event->attr.id, size); 597 mem_bswap_64(event->attr.id, size);
542} 598}
543 599
544static void perf_event__event_type_swap(union perf_event *event) 600static void perf_event__event_type_swap(union perf_event *event,
601 bool sample_id_all __used)
545{ 602{
546 event->event_type.event_type.event_id = 603 event->event_type.event_type.event_id =
547 bswap_64(event->event_type.event_type.event_id); 604 bswap_64(event->event_type.event_type.event_id);
548} 605}
549 606
550static void perf_event__tracing_data_swap(union perf_event *event) 607static void perf_event__tracing_data_swap(union perf_event *event,
608 bool sample_id_all __used)
551{ 609{
552 event->tracing_data.size = bswap_32(event->tracing_data.size); 610 event->tracing_data.size = bswap_32(event->tracing_data.size);
553} 611}
554 612
555typedef void (*perf_event__swap_op)(union perf_event *event); 613typedef void (*perf_event__swap_op)(union perf_event *event,
614 bool sample_id_all);
556 615
557static perf_event__swap_op perf_event__swap_ops[] = { 616static perf_event__swap_op perf_event__swap_ops[] = {
558 [PERF_RECORD_MMAP] = perf_event__mmap_swap, 617 [PERF_RECORD_MMAP] = perf_event__mmap_swap,
@@ -860,7 +919,9 @@ static struct machine *
860{ 919{
861 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 920 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
862 921
863 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 922 if (perf_guest &&
923 ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
924 (cpumode == PERF_RECORD_MISC_GUEST_USER))) {
864 u32 pid; 925 u32 pid;
865 926
866 if (event->header.type == PERF_RECORD_MMAP) 927 if (event->header.type == PERF_RECORD_MMAP)
@@ -868,7 +929,7 @@ static struct machine *
868 else 929 else
869 pid = event->ip.pid; 930 pid = event->ip.pid;
870 931
871 return perf_session__find_machine(session, pid); 932 return perf_session__findnew_machine(session, pid);
872 } 933 }
873 934
874 return perf_session__find_host_machine(session); 935 return perf_session__find_host_machine(session);
@@ -986,6 +1047,15 @@ static int perf_session__process_user_event(struct perf_session *session, union
986 } 1047 }
987} 1048}
988 1049
1050static void event_swap(union perf_event *event, bool sample_id_all)
1051{
1052 perf_event__swap_op swap;
1053
1054 swap = perf_event__swap_ops[event->header.type];
1055 if (swap)
1056 swap(event, sample_id_all);
1057}
1058
989static int perf_session__process_event(struct perf_session *session, 1059static int perf_session__process_event(struct perf_session *session,
990 union perf_event *event, 1060 union perf_event *event,
991 struct perf_tool *tool, 1061 struct perf_tool *tool,
@@ -994,9 +1064,8 @@ static int perf_session__process_event(struct perf_session *session,
994 struct perf_sample sample; 1064 struct perf_sample sample;
995 int ret; 1065 int ret;
996 1066
997 if (session->header.needs_swap && 1067 if (session->header.needs_swap)
998 perf_event__swap_ops[event->header.type]) 1068 event_swap(event, session->sample_id_all);
999 perf_event__swap_ops[event->header.type](event);
1000 1069
1001 if (event->header.type >= PERF_RECORD_HEADER_MAX) 1070 if (event->header.type >= PERF_RECORD_HEADER_MAX)
1002 return -EINVAL; 1071 return -EINVAL;
@@ -1383,7 +1452,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1383 ret += hists__fprintf_nr_events(&session->hists, fp); 1452 ret += hists__fprintf_nr_events(&session->hists, fp);
1384 1453
1385 list_for_each_entry(pos, &session->evlist->entries, node) { 1454 list_for_each_entry(pos, &session->evlist->entries, node) {
1386 ret += fprintf(fp, "%s stats:\n", event_name(pos)); 1455 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1387 ret += hists__fprintf_nr_events(&pos->hists, fp); 1456 ret += hists__fprintf_nr_events(&pos->hists, fp);
1388 } 1457 }
1389 1458
@@ -1424,11 +1493,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1424} 1493}
1425 1494
1426void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 1495void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1427 struct machine *machine, struct perf_evsel *evsel, 1496 struct machine *machine, int print_sym,
1428 int print_sym, int print_dso, int print_symoffset) 1497 int print_dso, int print_symoffset)
1429{ 1498{
1430 struct addr_location al; 1499 struct addr_location al;
1431 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
1432 struct callchain_cursor_node *node; 1500 struct callchain_cursor_node *node;
1433 1501
1434 if (perf_event__preprocess_sample(event, machine, &al, sample, 1502 if (perf_event__preprocess_sample(event, machine, &al, sample,
@@ -1440,16 +1508,16 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1440 1508
1441 if (symbol_conf.use_callchain && sample->callchain) { 1509 if (symbol_conf.use_callchain && sample->callchain) {
1442 1510
1443 if (machine__resolve_callchain(machine, evsel, al.thread, 1511 if (machine__resolve_callchain(machine, al.thread,
1444 sample->callchain, NULL) != 0) { 1512 sample->callchain, NULL) != 0) {
1445 if (verbose) 1513 if (verbose)
1446 error("Failed to resolve callchain. Skipping\n"); 1514 error("Failed to resolve callchain. Skipping\n");
1447 return; 1515 return;
1448 } 1516 }
1449 callchain_cursor_commit(cursor); 1517 callchain_cursor_commit(&callchain_cursor);
1450 1518
1451 while (1) { 1519 while (1) {
1452 node = callchain_cursor_current(cursor); 1520 node = callchain_cursor_current(&callchain_cursor);
1453 if (!node) 1521 if (!node)
1454 break; 1522 break;
1455 1523
@@ -1460,12 +1528,12 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1460 } 1528 }
1461 if (print_dso) { 1529 if (print_dso) {
1462 printf(" ("); 1530 printf(" (");
1463 map__fprintf_dsoname(al.map, stdout); 1531 map__fprintf_dsoname(node->map, stdout);
1464 printf(")"); 1532 printf(")");
1465 } 1533 }
1466 printf("\n"); 1534 printf("\n");
1467 1535
1468 callchain_cursor_advance(cursor); 1536 callchain_cursor_advance(&callchain_cursor);
1469 } 1537 }
1470 1538
1471 } else { 1539 } else {
@@ -1546,3 +1614,58 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
1546 perf_header__fprintf_info(session, fp, full); 1614 perf_header__fprintf_info(session, fp, full);
1547 fprintf(fp, "# ========\n#\n"); 1615 fprintf(fp, "# ========\n#\n");
1548} 1616}
1617
1618
1619int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1620 const struct perf_evsel_str_handler *assocs,
1621 size_t nr_assocs)
1622{
1623 struct perf_evlist *evlist = session->evlist;
1624 struct event_format *format;
1625 struct perf_evsel *evsel;
1626 char *tracepoint, *name;
1627 size_t i;
1628 int err;
1629
1630 for (i = 0; i < nr_assocs; i++) {
1631 err = -ENOMEM;
1632 tracepoint = strdup(assocs[i].name);
1633 if (tracepoint == NULL)
1634 goto out;
1635
1636 err = -ENOENT;
1637 name = strchr(tracepoint, ':');
1638 if (name == NULL)
1639 goto out_free;
1640
1641 *name++ = '\0';
1642 format = pevent_find_event_by_name(session->pevent,
1643 tracepoint, name);
1644 if (format == NULL) {
1645 /*
1646 * Adding a handler for an event not in the session,
1647 * just ignore it.
1648 */
1649 goto next;
1650 }
1651
1652 evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id);
1653 if (evsel == NULL)
1654 goto next;
1655
1656 err = -EEXIST;
1657 if (evsel->handler.func != NULL)
1658 goto out_free;
1659 evsel->handler.func = assocs[i].handler;
1660next:
1661 free(tracepoint);
1662 }
1663
1664 err = 0;
1665out:
1666 return err;
1667
1668out_free:
1669 free(tracepoint);
1670 goto out;
1671}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 7a5434c00565..7c435bde6eb0 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -33,6 +33,7 @@ struct perf_session {
33 struct machine host_machine; 33 struct machine host_machine;
34 struct rb_root machines; 34 struct rb_root machines;
35 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
36 struct pevent *pevent;
36 /* 37 /*
37 * FIXME: Need to split this up further, we need global 38 * FIXME: Need to split this up further, we need global
38 * stats + per event stats. 'perf diff' also needs 39 * stats + per event stats. 'perf diff' also needs
@@ -80,6 +81,7 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
80bool perf_session__has_traces(struct perf_session *self, const char *msg); 81bool perf_session__has_traces(struct perf_session *self, const char *msg);
81 82
82void mem_bswap_64(void *src, int byte_size); 83void mem_bswap_64(void *src, int byte_size);
84void mem_bswap_32(void *src, int byte_size);
83void perf_event__attr_swap(struct perf_event_attr *attr); 85void perf_event__attr_swap(struct perf_event_attr *attr);
84 86
85int perf_session__create_kernel_maps(struct perf_session *self); 87int perf_session__create_kernel_maps(struct perf_session *self);
@@ -150,11 +152,20 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
150 unsigned int type); 152 unsigned int type);
151 153
152void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 154void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
153 struct machine *machine, struct perf_evsel *evsel, 155 struct machine *machine, int print_sym,
154 int print_sym, int print_dso, int print_symoffset); 156 int print_dso, int print_symoffset);
155 157
156int perf_session__cpu_bitmap(struct perf_session *session, 158int perf_session__cpu_bitmap(struct perf_session *session,
157 const char *cpu_list, unsigned long *cpu_bitmap); 159 const char *cpu_list, unsigned long *cpu_bitmap);
158 160
159void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full); 161void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full);
162
163struct perf_evsel_str_handler;
164
165int __perf_session__set_tracepoints_handlers(struct perf_session *session,
166 const struct perf_evsel_str_handler *assocs,
167 size_t nr_assocs);
168
169#define perf_session__set_tracepoints_handlers(session, array) \
170 __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array))
160#endif /* __PERF_SESSION_H */ 171#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index a27237430c5f..0f5a0a496bc4 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -241,6 +241,54 @@ struct sort_entry sort_sym = {
241 .se_width_idx = HISTC_SYMBOL, 241 .se_width_idx = HISTC_SYMBOL,
242}; 242};
243 243
244/* --sort srcline */
245
246static int64_t
247sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
248{
249 return (int64_t)(right->ip - left->ip);
250}
251
252static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
253 size_t size, unsigned int width __used)
254{
255 FILE *fp;
256 char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
257 size_t line_len;
258
259 if (path != NULL)
260 goto out_path;
261
262 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
263 self->ms.map->dso->long_name, self->ip);
264 fp = popen(cmd, "r");
265 if (!fp)
266 goto out_ip;
267
268 if (getline(&path, &line_len, fp) < 0 || !line_len)
269 goto out_ip;
270 fclose(fp);
271 self->srcline = strdup(path);
272 if (self->srcline == NULL)
273 goto out_ip;
274
275 nl = strchr(self->srcline, '\n');
276 if (nl != NULL)
277 *nl = '\0';
278 path = self->srcline;
279out_path:
280 return repsep_snprintf(bf, size, "%s", path);
281out_ip:
282 return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
283}
284
285struct sort_entry sort_srcline = {
286 .se_header = "Source:Line",
287 .se_cmp = sort__srcline_cmp,
288 .se_snprintf = hist_entry__srcline_snprintf,
289 .se_width_idx = HISTC_SRCLINE,
290};
291
244/* --sort parent */ 292/* --sort parent */
245 293
246static int64_t 294static int64_t
@@ -439,6 +487,7 @@ static struct sort_dimension sort_dimensions[] = {
439 DIM(SORT_PARENT, "parent", sort_parent), 487 DIM(SORT_PARENT, "parent", sort_parent),
440 DIM(SORT_CPU, "cpu", sort_cpu), 488 DIM(SORT_CPU, "cpu", sort_cpu),
441 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), 489 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
490 DIM(SORT_SRCLINE, "srcline", sort_srcline),
442}; 491};
443 492
444int sort_dimension__add(const char *tok) 493int sort_dimension__add(const char *tok)
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 472aa5a63a58..e724b26acd51 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -71,6 +71,7 @@ struct hist_entry {
71 char level; 71 char level;
72 bool used; 72 bool used;
73 u8 filtered; 73 u8 filtered;
74 char *srcline;
74 struct symbol *parent; 75 struct symbol *parent;
75 union { 76 union {
76 unsigned long position; 77 unsigned long position;
@@ -93,6 +94,7 @@ enum sort_type {
93 SORT_SYM_FROM, 94 SORT_SYM_FROM,
94 SORT_SYM_TO, 95 SORT_SYM_TO,
95 SORT_MISPREDICT, 96 SORT_MISPREDICT,
97 SORT_SRCLINE,
96}; 98};
97 99
98/* 100/*
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index d5836382ff2c..199bc4d8905d 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -313,3 +313,25 @@ int strtailcmp(const char *s1, const char *s2)
313 return 0; 313 return 0;
314} 314}
315 315
316/**
317 * rtrim - Removes trailing whitespace from @s.
318 * @s: The string to be stripped.
319 *
320 * Note that the first trailing whitespace is replaced with a %NUL-terminator
321 * in the given string @s. Returns @s.
322 */
323char *rtrim(char *s)
324{
325 size_t size = strlen(s);
326 char *end;
327
328 if (!size)
329 return s;
330
331 end = s + size - 1;
332 while (end >= s && isspace(*end))
333 end--;
334 *(end + 1) = '\0';
335
336 return s;
337}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e2ba8858f3e1..fdad4eeeb429 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -29,6 +29,7 @@
29#define NT_GNU_BUILD_ID 3 29#define NT_GNU_BUILD_ID 3
30#endif 30#endif
31 31
32static void dso_cache__free(struct rb_root *root);
32static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); 33static bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
33static int elf_read_build_id(Elf *elf, void *bf, size_t size); 34static int elf_read_build_id(Elf *elf, void *bf, size_t size);
34static void dsos__add(struct list_head *head, struct dso *dso); 35static void dsos__add(struct list_head *head, struct dso *dso);
@@ -48,6 +49,31 @@ struct symbol_conf symbol_conf = {
48 .symfs = "", 49 .symfs = "",
49}; 50};
50 51
52static enum dso_binary_type binary_type_symtab[] = {
53 DSO_BINARY_TYPE__KALLSYMS,
54 DSO_BINARY_TYPE__GUEST_KALLSYMS,
55 DSO_BINARY_TYPE__JAVA_JIT,
56 DSO_BINARY_TYPE__DEBUGLINK,
57 DSO_BINARY_TYPE__BUILD_ID_CACHE,
58 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
59 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
60 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
61 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
62 DSO_BINARY_TYPE__GUEST_KMODULE,
63 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
64 DSO_BINARY_TYPE__NOT_FOUND,
65};
66
67#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab)
68
69static enum dso_binary_type binary_type_data[] = {
70 DSO_BINARY_TYPE__BUILD_ID_CACHE,
71 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
72 DSO_BINARY_TYPE__NOT_FOUND,
73};
74
75#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data)
76
51int dso__name_len(const struct dso *dso) 77int dso__name_len(const struct dso *dso)
52{ 78{
53 if (!dso) 79 if (!dso)
@@ -318,11 +344,14 @@ struct dso *dso__new(const char *name)
318 dso__set_short_name(dso, dso->name); 344 dso__set_short_name(dso, dso->name);
319 for (i = 0; i < MAP__NR_TYPES; ++i) 345 for (i = 0; i < MAP__NR_TYPES; ++i)
320 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 346 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
321 dso->symtab_type = SYMTAB__NOT_FOUND; 347 dso->cache = RB_ROOT;
348 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
349 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
322 dso->loaded = 0; 350 dso->loaded = 0;
323 dso->sorted_by_name = 0; 351 dso->sorted_by_name = 0;
324 dso->has_build_id = 0; 352 dso->has_build_id = 0;
325 dso->kernel = DSO_TYPE_USER; 353 dso->kernel = DSO_TYPE_USER;
354 dso->needs_swap = DSO_SWAP__UNSET;
326 INIT_LIST_HEAD(&dso->node); 355 INIT_LIST_HEAD(&dso->node);
327 } 356 }
328 357
@@ -351,6 +380,7 @@ void dso__delete(struct dso *dso)
351 free((char *)dso->short_name); 380 free((char *)dso->short_name);
352 if (dso->lname_alloc) 381 if (dso->lname_alloc)
353 free(dso->long_name); 382 free(dso->long_name);
383 dso_cache__free(&dso->cache);
354 free(dso); 384 free(dso);
355} 385}
356 386
@@ -805,9 +835,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
805 symbols__fixup_end(&dso->symbols[map->type]); 835 symbols__fixup_end(&dso->symbols[map->type]);
806 836
807 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 837 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
808 dso->symtab_type = SYMTAB__GUEST_KALLSYMS; 838 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
809 else 839 else
810 dso->symtab_type = SYMTAB__KALLSYMS; 840 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
811 841
812 return dso__split_kallsyms(dso, map, filter); 842 return dso__split_kallsyms(dso, map, filter);
813} 843}
@@ -1156,6 +1186,33 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
1156 return -1; 1186 return -1;
1157} 1187}
1158 1188
1189static int dso__swap_init(struct dso *dso, unsigned char eidata)
1190{
1191 static unsigned int const endian = 1;
1192
1193 dso->needs_swap = DSO_SWAP__NO;
1194
1195 switch (eidata) {
1196 case ELFDATA2LSB:
1197 /* We are big endian, DSO is little endian. */
1198 if (*(unsigned char const *)&endian != 1)
1199 dso->needs_swap = DSO_SWAP__YES;
1200 break;
1201
1202 case ELFDATA2MSB:
1203 /* We are little endian, DSO is big endian. */
1204 if (*(unsigned char const *)&endian != 0)
1205 dso->needs_swap = DSO_SWAP__YES;
1206 break;
1207
1208 default:
1209 pr_err("unrecognized DSO data encoding %d\n", eidata);
1210 return -EINVAL;
1211 }
1212
1213 return 0;
1214}
1215
1159static int dso__load_sym(struct dso *dso, struct map *map, const char *name, 1216static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1160 int fd, symbol_filter_t filter, int kmodule, 1217 int fd, symbol_filter_t filter, int kmodule,
1161 int want_symtab) 1218 int want_symtab)
@@ -1187,6 +1244,9 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1187 goto out_elf_end; 1244 goto out_elf_end;
1188 } 1245 }
1189 1246
1247 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
1248 goto out_elf_end;
1249
1190 /* Always reject images with a mismatched build-id: */ 1250 /* Always reject images with a mismatched build-id: */
1191 if (dso->has_build_id) { 1251 if (dso->has_build_id) {
1192 u8 build_id[BUILD_ID_SIZE]; 1252 u8 build_id[BUILD_ID_SIZE];
@@ -1272,7 +1332,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1272 if (opdsec && sym.st_shndx == opdidx) { 1332 if (opdsec && sym.st_shndx == opdidx) {
1273 u32 offset = sym.st_value - opdshdr.sh_addr; 1333 u32 offset = sym.st_value - opdshdr.sh_addr;
1274 u64 *opd = opddata->d_buf + offset; 1334 u64 *opd = opddata->d_buf + offset;
1275 sym.st_value = *opd; 1335 sym.st_value = DSO__SWAP(dso, u64, *opd);
1276 sym.st_shndx = elf_addr_to_index(elf, sym.st_value); 1336 sym.st_shndx = elf_addr_to_index(elf, sym.st_value);
1277 } 1337 }
1278 1338
@@ -1447,14 +1507,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1447 goto out; 1507 goto out;
1448 } 1508 }
1449 1509
1450 sec = elf_section_by_name(elf, &ehdr, &shdr, 1510 /*
1451 ".note.gnu.build-id", NULL); 1511 * Check following sections for notes:
1452 if (sec == NULL) { 1512 * '.note.gnu.build-id'
1513 * '.notes'
1514 * '.note' (VDSO specific)
1515 */
1516 do {
1517 sec = elf_section_by_name(elf, &ehdr, &shdr,
1518 ".note.gnu.build-id", NULL);
1519 if (sec)
1520 break;
1521
1453 sec = elf_section_by_name(elf, &ehdr, &shdr, 1522 sec = elf_section_by_name(elf, &ehdr, &shdr,
1454 ".notes", NULL); 1523 ".notes", NULL);
1455 if (sec == NULL) 1524 if (sec)
1456 goto out; 1525 break;
1457 } 1526
1527 sec = elf_section_by_name(elf, &ehdr, &shdr,
1528 ".note", NULL);
1529 if (sec)
1530 break;
1531
1532 return err;
1533
1534 } while (0);
1458 1535
1459 data = elf_getdata(sec, NULL); 1536 data = elf_getdata(sec, NULL);
1460 if (data == NULL) 1537 if (data == NULL)
@@ -1559,34 +1636,163 @@ out:
1559 return err; 1636 return err;
1560} 1637}
1561 1638
1639static int filename__read_debuglink(const char *filename,
1640 char *debuglink, size_t size)
1641{
1642 int fd, err = -1;
1643 Elf *elf;
1644 GElf_Ehdr ehdr;
1645 GElf_Shdr shdr;
1646 Elf_Data *data;
1647 Elf_Scn *sec;
1648 Elf_Kind ek;
1649
1650 fd = open(filename, O_RDONLY);
1651 if (fd < 0)
1652 goto out;
1653
1654 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1655 if (elf == NULL) {
1656 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1657 goto out_close;
1658 }
1659
1660 ek = elf_kind(elf);
1661 if (ek != ELF_K_ELF)
1662 goto out_close;
1663
1664 if (gelf_getehdr(elf, &ehdr) == NULL) {
1665 pr_err("%s: cannot get elf header.\n", __func__);
1666 goto out_close;
1667 }
1668
1669 sec = elf_section_by_name(elf, &ehdr, &shdr,
1670 ".gnu_debuglink", NULL);
1671 if (sec == NULL)
1672 goto out_close;
1673
1674 data = elf_getdata(sec, NULL);
1675 if (data == NULL)
1676 goto out_close;
1677
1678 /* the start of this section is a zero-terminated string */
1679 strncpy(debuglink, data->d_buf, size);
1680
1681 elf_end(elf);
1682
1683out_close:
1684 close(fd);
1685out:
1686 return err;
1687}
1688
1562char dso__symtab_origin(const struct dso *dso) 1689char dso__symtab_origin(const struct dso *dso)
1563{ 1690{
1564 static const char origin[] = { 1691 static const char origin[] = {
1565 [SYMTAB__KALLSYMS] = 'k', 1692 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
1566 [SYMTAB__JAVA_JIT] = 'j', 1693 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
1567 [SYMTAB__BUILD_ID_CACHE] = 'B', 1694 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
1568 [SYMTAB__FEDORA_DEBUGINFO] = 'f', 1695 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
1569 [SYMTAB__UBUNTU_DEBUGINFO] = 'u', 1696 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
1570 [SYMTAB__BUILDID_DEBUGINFO] = 'b', 1697 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
1571 [SYMTAB__SYSTEM_PATH_DSO] = 'd', 1698 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
1572 [SYMTAB__SYSTEM_PATH_KMODULE] = 'K', 1699 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
1573 [SYMTAB__GUEST_KALLSYMS] = 'g', 1700 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
1574 [SYMTAB__GUEST_KMODULE] = 'G', 1701 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
1702 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
1575 }; 1703 };
1576 1704
1577 if (dso == NULL || dso->symtab_type == SYMTAB__NOT_FOUND) 1705 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
1578 return '!'; 1706 return '!';
1579 return origin[dso->symtab_type]; 1707 return origin[dso->symtab_type];
1580} 1708}
1581 1709
1710int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
1711 char *root_dir, char *file, size_t size)
1712{
1713 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1714 int ret = 0;
1715
1716 switch (type) {
1717 case DSO_BINARY_TYPE__DEBUGLINK: {
1718 char *debuglink;
1719
1720 strncpy(file, dso->long_name, size);
1721 debuglink = file + dso->long_name_len;
1722 while (debuglink != file && *debuglink != '/')
1723 debuglink--;
1724 if (*debuglink == '/')
1725 debuglink++;
1726 filename__read_debuglink(dso->long_name, debuglink,
1727 size - (debuglink - file));
1728 }
1729 break;
1730 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
1731 /* skip the locally configured cache if a symfs is given */
1732 if (symbol_conf.symfs[0] ||
1733 (dso__build_id_filename(dso, file, size) == NULL))
1734 ret = -1;
1735 break;
1736
1737 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
1738 snprintf(file, size, "%s/usr/lib/debug%s.debug",
1739 symbol_conf.symfs, dso->long_name);
1740 break;
1741
1742 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
1743 snprintf(file, size, "%s/usr/lib/debug%s",
1744 symbol_conf.symfs, dso->long_name);
1745 break;
1746
1747 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
1748 if (!dso->has_build_id) {
1749 ret = -1;
1750 break;
1751 }
1752
1753 build_id__sprintf(dso->build_id,
1754 sizeof(dso->build_id),
1755 build_id_hex);
1756 snprintf(file, size,
1757 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1758 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1759 break;
1760
1761 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
1762 snprintf(file, size, "%s%s",
1763 symbol_conf.symfs, dso->long_name);
1764 break;
1765
1766 case DSO_BINARY_TYPE__GUEST_KMODULE:
1767 snprintf(file, size, "%s%s%s", symbol_conf.symfs,
1768 root_dir, dso->long_name);
1769 break;
1770
1771 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1772 snprintf(file, size, "%s%s", symbol_conf.symfs,
1773 dso->long_name);
1774 break;
1775
1776 default:
1777 case DSO_BINARY_TYPE__KALLSYMS:
1778 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
1779 case DSO_BINARY_TYPE__JAVA_JIT:
1780 case DSO_BINARY_TYPE__NOT_FOUND:
1781 ret = -1;
1782 break;
1783 }
1784
1785 return ret;
1786}
1787
1582int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 1788int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1583{ 1789{
1584 int size = PATH_MAX;
1585 char *name; 1790 char *name;
1586 int ret = -1; 1791 int ret = -1;
1587 int fd; 1792 int fd;
1793 u_int i;
1588 struct machine *machine; 1794 struct machine *machine;
1589 const char *root_dir; 1795 char *root_dir = (char *) "";
1590 int want_symtab; 1796 int want_symtab;
1591 1797
1592 dso__set_loaded(dso, map->type); 1798 dso__set_loaded(dso, map->type);
@@ -1601,7 +1807,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1601 else 1807 else
1602 machine = NULL; 1808 machine = NULL;
1603 1809
1604 name = malloc(size); 1810 name = malloc(PATH_MAX);
1605 if (!name) 1811 if (!name)
1606 return -1; 1812 return -1;
1607 1813
@@ -1620,69 +1826,27 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1620 } 1826 }
1621 1827
1622 ret = dso__load_perf_map(dso, map, filter); 1828 ret = dso__load_perf_map(dso, map, filter);
1623 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : 1829 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1624 SYMTAB__NOT_FOUND; 1830 DSO_BINARY_TYPE__NOT_FOUND;
1625 return ret; 1831 return ret;
1626 } 1832 }
1627 1833
1834 if (machine)
1835 root_dir = machine->root_dir;
1836
1628 /* Iterate over candidate debug images. 1837 /* Iterate over candidate debug images.
1629 * On the first pass, only load images if they have a full symtab. 1838 * On the first pass, only load images if they have a full symtab.
1630 * Failing that, do a second pass where we accept .dynsym also 1839 * Failing that, do a second pass where we accept .dynsym also
1631 */ 1840 */
1632 want_symtab = 1; 1841 want_symtab = 1;
1633restart: 1842restart:
1634 for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE; 1843 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
1635 dso->symtab_type != SYMTAB__NOT_FOUND;
1636 dso->symtab_type++) {
1637 switch (dso->symtab_type) {
1638 case SYMTAB__BUILD_ID_CACHE:
1639 /* skip the locally configured cache if a symfs is given */
1640 if (symbol_conf.symfs[0] ||
1641 (dso__build_id_filename(dso, name, size) == NULL)) {
1642 continue;
1643 }
1644 break;
1645 case SYMTAB__FEDORA_DEBUGINFO:
1646 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1647 symbol_conf.symfs, dso->long_name);
1648 break;
1649 case SYMTAB__UBUNTU_DEBUGINFO:
1650 snprintf(name, size, "%s/usr/lib/debug%s",
1651 symbol_conf.symfs, dso->long_name);
1652 break;
1653 case SYMTAB__BUILDID_DEBUGINFO: {
1654 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1655 1844
1656 if (!dso->has_build_id) 1845 dso->symtab_type = binary_type_symtab[i];
1657 continue;
1658 1846
1659 build_id__sprintf(dso->build_id, 1847 if (dso__binary_type_file(dso, dso->symtab_type,
1660 sizeof(dso->build_id), 1848 root_dir, name, PATH_MAX))
1661 build_id_hex); 1849 continue;
1662 snprintf(name, size,
1663 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1664 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1665 }
1666 break;
1667 case SYMTAB__SYSTEM_PATH_DSO:
1668 snprintf(name, size, "%s%s",
1669 symbol_conf.symfs, dso->long_name);
1670 break;
1671 case SYMTAB__GUEST_KMODULE:
1672 if (map->groups && machine)
1673 root_dir = machine->root_dir;
1674 else
1675 root_dir = "";
1676 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1677 root_dir, dso->long_name);
1678 break;
1679
1680 case SYMTAB__SYSTEM_PATH_KMODULE:
1681 snprintf(name, size, "%s%s", symbol_conf.symfs,
1682 dso->long_name);
1683 break;
1684 default:;
1685 }
1686 1850
1687 /* Name is now the name of the next image to try */ 1851 /* Name is now the name of the next image to try */
1688 fd = open(name, O_RDONLY); 1852 fd = open(name, O_RDONLY);
@@ -1899,9 +2063,9 @@ struct map *machine__new_module(struct machine *machine, u64 start,
1899 return NULL; 2063 return NULL;
1900 2064
1901 if (machine__is_host(machine)) 2065 if (machine__is_host(machine))
1902 dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE; 2066 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
1903 else 2067 else
1904 dso->symtab_type = SYMTAB__GUEST_KMODULE; 2068 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
1905 map_groups__insert(&machine->kmaps, map); 2069 map_groups__insert(&machine->kmaps, map);
1906 return map; 2070 return map;
1907} 2071}
@@ -2453,8 +2617,15 @@ int machine__create_kernel_maps(struct machine *machine)
2453 __machine__create_kernel_maps(machine, kernel) < 0) 2617 __machine__create_kernel_maps(machine, kernel) < 0)
2454 return -1; 2618 return -1;
2455 2619
2456 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) 2620 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
2457 pr_debug("Problems creating module maps, continuing anyway...\n"); 2621 if (machine__is_host(machine))
2622 pr_debug("Problems creating module maps, "
2623 "continuing anyway...\n");
2624 else
2625 pr_debug("Problems creating module maps for guest %d, "
2626 "continuing anyway...\n", machine->pid);
2627 }
2628
2458 /* 2629 /*
2459 * Now that we have all the maps created, just set the ->end of them: 2630 * Now that we have all the maps created, just set the ->end of them:
2460 */ 2631 */
@@ -2786,8 +2957,226 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
2786 2957
2787struct map *dso__new_map(const char *name) 2958struct map *dso__new_map(const char *name)
2788{ 2959{
2960 struct map *map = NULL;
2789 struct dso *dso = dso__new(name); 2961 struct dso *dso = dso__new(name);
2790 struct map *map = map__new2(0, dso, MAP__FUNCTION); 2962
2963 if (dso)
2964 map = map__new2(0, dso, MAP__FUNCTION);
2791 2965
2792 return map; 2966 return map;
2793} 2967}
2968
2969static int open_dso(struct dso *dso, struct machine *machine)
2970{
2971 char *root_dir = (char *) "";
2972 char *name;
2973 int fd;
2974
2975 name = malloc(PATH_MAX);
2976 if (!name)
2977 return -ENOMEM;
2978
2979 if (machine)
2980 root_dir = machine->root_dir;
2981
2982 if (dso__binary_type_file(dso, dso->data_type,
2983 root_dir, name, PATH_MAX)) {
2984 free(name);
2985 return -EINVAL;
2986 }
2987
2988 fd = open(name, O_RDONLY);
2989 free(name);
2990 return fd;
2991}
2992
2993int dso__data_fd(struct dso *dso, struct machine *machine)
2994{
2995 int i = 0;
2996
2997 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
2998 return open_dso(dso, machine);
2999
3000 do {
3001 int fd;
3002
3003 dso->data_type = binary_type_data[i++];
3004
3005 fd = open_dso(dso, machine);
3006 if (fd >= 0)
3007 return fd;
3008
3009 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
3010
3011 return -EINVAL;
3012}
3013
3014static void
3015dso_cache__free(struct rb_root *root)
3016{
3017 struct rb_node *next = rb_first(root);
3018
3019 while (next) {
3020 struct dso_cache *cache;
3021
3022 cache = rb_entry(next, struct dso_cache, rb_node);
3023 next = rb_next(&cache->rb_node);
3024 rb_erase(&cache->rb_node, root);
3025 free(cache);
3026 }
3027}
3028
3029static struct dso_cache*
3030dso_cache__find(struct rb_root *root, u64 offset)
3031{
3032 struct rb_node **p = &root->rb_node;
3033 struct rb_node *parent = NULL;
3034 struct dso_cache *cache;
3035
3036 while (*p != NULL) {
3037 u64 end;
3038
3039 parent = *p;
3040 cache = rb_entry(parent, struct dso_cache, rb_node);
3041 end = cache->offset + DSO__DATA_CACHE_SIZE;
3042
3043 if (offset < cache->offset)
3044 p = &(*p)->rb_left;
3045 else if (offset >= end)
3046 p = &(*p)->rb_right;
3047 else
3048 return cache;
3049 }
3050 return NULL;
3051}
3052
3053static void
3054dso_cache__insert(struct rb_root *root, struct dso_cache *new)
3055{
3056 struct rb_node **p = &root->rb_node;
3057 struct rb_node *parent = NULL;
3058 struct dso_cache *cache;
3059 u64 offset = new->offset;
3060
3061 while (*p != NULL) {
3062 u64 end;
3063
3064 parent = *p;
3065 cache = rb_entry(parent, struct dso_cache, rb_node);
3066 end = cache->offset + DSO__DATA_CACHE_SIZE;
3067
3068 if (offset < cache->offset)
3069 p = &(*p)->rb_left;
3070 else if (offset >= end)
3071 p = &(*p)->rb_right;
3072 }
3073
3074 rb_link_node(&new->rb_node, parent, p);
3075 rb_insert_color(&new->rb_node, root);
3076}
3077
3078static ssize_t
3079dso_cache__memcpy(struct dso_cache *cache, u64 offset,
3080 u8 *data, u64 size)
3081{
3082 u64 cache_offset = offset - cache->offset;
3083 u64 cache_size = min(cache->size - cache_offset, size);
3084
3085 memcpy(data, cache->data + cache_offset, cache_size);
3086 return cache_size;
3087}
3088
3089static ssize_t
3090dso_cache__read(struct dso *dso, struct machine *machine,
3091 u64 offset, u8 *data, ssize_t size)
3092{
3093 struct dso_cache *cache;
3094 ssize_t ret;
3095 int fd;
3096
3097 fd = dso__data_fd(dso, machine);
3098 if (fd < 0)
3099 return -1;
3100
3101 do {
3102 u64 cache_offset;
3103
3104 ret = -ENOMEM;
3105
3106 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
3107 if (!cache)
3108 break;
3109
3110 cache_offset = offset & DSO__DATA_CACHE_MASK;
3111 ret = -EINVAL;
3112
3113 if (-1 == lseek(fd, cache_offset, SEEK_SET))
3114 break;
3115
3116 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
3117 if (ret <= 0)
3118 break;
3119
3120 cache->offset = cache_offset;
3121 cache->size = ret;
3122 dso_cache__insert(&dso->cache, cache);
3123
3124 ret = dso_cache__memcpy(cache, offset, data, size);
3125
3126 } while (0);
3127
3128 if (ret <= 0)
3129 free(cache);
3130
3131 close(fd);
3132 return ret;
3133}
3134
3135static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
3136 u64 offset, u8 *data, ssize_t size)
3137{
3138 struct dso_cache *cache;
3139
3140 cache = dso_cache__find(&dso->cache, offset);
3141 if (cache)
3142 return dso_cache__memcpy(cache, offset, data, size);
3143 else
3144 return dso_cache__read(dso, machine, offset, data, size);
3145}
3146
3147ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
3148 u64 offset, u8 *data, ssize_t size)
3149{
3150 ssize_t r = 0;
3151 u8 *p = data;
3152
3153 do {
3154 ssize_t ret;
3155
3156 ret = dso_cache_read(dso, machine, offset, p, size);
3157 if (ret < 0)
3158 return ret;
3159
3160 /* Reached EOF, return what we have. */
3161 if (!ret)
3162 break;
3163
3164 BUG_ON(ret > size);
3165
3166 r += ret;
3167 p += ret;
3168 offset += ret;
3169 size -= ret;
3170
3171 } while (size);
3172
3173 return r;
3174}
3175
3176ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
3177 struct machine *machine, u64 addr,
3178 u8 *data, ssize_t size)
3179{
3180 u64 offset = map->map_ip(map, addr);
3181 return dso__data_read_offset(dso, machine, offset, data, size);
3182}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5649d63798cb..1fe733a1e21f 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -9,6 +9,7 @@
9#include <linux/list.h> 9#include <linux/list.h>
10#include <linux/rbtree.h> 10#include <linux/rbtree.h>
11#include <stdio.h> 11#include <stdio.h>
12#include <byteswap.h>
12 13
13#ifdef HAVE_CPLUS_DEMANGLE 14#ifdef HAVE_CPLUS_DEMANGLE
14extern char *cplus_demangle(const char *, int); 15extern char *cplus_demangle(const char *, int);
@@ -154,24 +155,58 @@ struct addr_location {
154 s32 cpu; 155 s32 cpu;
155}; 156};
156 157
158enum dso_binary_type {
159 DSO_BINARY_TYPE__KALLSYMS = 0,
160 DSO_BINARY_TYPE__GUEST_KALLSYMS,
161 DSO_BINARY_TYPE__JAVA_JIT,
162 DSO_BINARY_TYPE__DEBUGLINK,
163 DSO_BINARY_TYPE__BUILD_ID_CACHE,
164 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
165 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
166 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
167 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
168 DSO_BINARY_TYPE__GUEST_KMODULE,
169 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
170 DSO_BINARY_TYPE__NOT_FOUND,
171};
172
157enum dso_kernel_type { 173enum dso_kernel_type {
158 DSO_TYPE_USER = 0, 174 DSO_TYPE_USER = 0,
159 DSO_TYPE_KERNEL, 175 DSO_TYPE_KERNEL,
160 DSO_TYPE_GUEST_KERNEL 176 DSO_TYPE_GUEST_KERNEL
161}; 177};
162 178
179enum dso_swap_type {
180 DSO_SWAP__UNSET,
181 DSO_SWAP__NO,
182 DSO_SWAP__YES,
183};
184
185#define DSO__DATA_CACHE_SIZE 4096
186#define DSO__DATA_CACHE_MASK ~(DSO__DATA_CACHE_SIZE - 1)
187
188struct dso_cache {
189 struct rb_node rb_node;
190 u64 offset;
191 u64 size;
192 char data[0];
193};
194
163struct dso { 195struct dso {
164 struct list_head node; 196 struct list_head node;
165 struct rb_root symbols[MAP__NR_TYPES]; 197 struct rb_root symbols[MAP__NR_TYPES];
166 struct rb_root symbol_names[MAP__NR_TYPES]; 198 struct rb_root symbol_names[MAP__NR_TYPES];
199 struct rb_root cache;
167 enum dso_kernel_type kernel; 200 enum dso_kernel_type kernel;
201 enum dso_swap_type needs_swap;
202 enum dso_binary_type symtab_type;
203 enum dso_binary_type data_type;
168 u8 adjust_symbols:1; 204 u8 adjust_symbols:1;
169 u8 has_build_id:1; 205 u8 has_build_id:1;
170 u8 hit:1; 206 u8 hit:1;
171 u8 annotate_warned:1; 207 u8 annotate_warned:1;
172 u8 sname_alloc:1; 208 u8 sname_alloc:1;
173 u8 lname_alloc:1; 209 u8 lname_alloc:1;
174 unsigned char symtab_type;
175 u8 sorted_by_name; 210 u8 sorted_by_name;
176 u8 loaded; 211 u8 loaded;
177 u8 build_id[BUILD_ID_SIZE]; 212 u8 build_id[BUILD_ID_SIZE];
@@ -182,6 +217,28 @@ struct dso {
182 char name[0]; 217 char name[0];
183}; 218};
184 219
220#define DSO__SWAP(dso, type, val) \
221({ \
222 type ____r = val; \
223 BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \
224 if (dso->needs_swap == DSO_SWAP__YES) { \
225 switch (sizeof(____r)) { \
226 case 2: \
227 ____r = bswap_16(val); \
228 break; \
229 case 4: \
230 ____r = bswap_32(val); \
231 break; \
232 case 8: \
233 ____r = bswap_64(val); \
234 break; \
235 default: \
236 BUG_ON(1); \
237 } \
238 } \
239 ____r; \
240})
241
185struct dso *dso__new(const char *name); 242struct dso *dso__new(const char *name);
186void dso__delete(struct dso *dso); 243void dso__delete(struct dso *dso);
187 244
@@ -223,20 +280,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
223 enum map_type type, FILE *fp); 280 enum map_type type, FILE *fp);
224size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); 281size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
225 282
226enum symtab_type {
227 SYMTAB__KALLSYMS = 0,
228 SYMTAB__GUEST_KALLSYMS,
229 SYMTAB__JAVA_JIT,
230 SYMTAB__BUILD_ID_CACHE,
231 SYMTAB__FEDORA_DEBUGINFO,
232 SYMTAB__UBUNTU_DEBUGINFO,
233 SYMTAB__BUILDID_DEBUGINFO,
234 SYMTAB__SYSTEM_PATH_DSO,
235 SYMTAB__GUEST_KMODULE,
236 SYMTAB__SYSTEM_PATH_KMODULE,
237 SYMTAB__NOT_FOUND,
238};
239
240char dso__symtab_origin(const struct dso *dso); 283char dso__symtab_origin(const struct dso *dso);
241void dso__set_long_name(struct dso *dso, char *name); 284void dso__set_long_name(struct dso *dso, char *name);
242void dso__set_build_id(struct dso *dso, void *build_id); 285void dso__set_build_id(struct dso *dso, void *build_id);
@@ -273,4 +316,14 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type);
273 316
274size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 317size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
275 318
319int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
320 char *root_dir, char *file, size_t size);
321
322int dso__data_fd(struct dso *dso, struct machine *machine);
323ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
324 u64 offset, u8 *data, ssize_t size);
325ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
326 struct machine *machine, u64 addr,
327 u8 *data, ssize_t size);
328int dso__test_data(void);
276#endif /* __PERF_SYMBOL */ 329#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 1064d5b148ad..3f59c496e64c 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -110,8 +110,17 @@ int perf_target__strerror(struct perf_target *target, int errnum,
110 int idx; 110 int idx;
111 const char *msg; 111 const char *msg;
112 112
113 BUG_ON(buflen > 0);
114
113 if (errnum >= 0) { 115 if (errnum >= 0) {
114 strerror_r(errnum, buf, buflen); 116 const char *err = strerror_r(errnum, buf, buflen);
117
118 if (err != buf) {
119 size_t len = strlen(err);
120 char *c = mempcpy(buf, err, min(buflen - 1, len));
121 *c = '\0';
122 }
123
115 return 0; 124 return 0;
116 } 125 }
117 126
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index abe0e8e95068..7eeebcee291c 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -65,7 +65,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
65 top->freq ? "Hz" : ""); 65 top->freq ? "Hz" : "");
66 } 66 }
67 67
68 ret += SNPRINTF(bf + ret, size - ret, "%s", event_name(top->sym_evsel)); 68 ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel));
69 69
70 ret += SNPRINTF(bf + ret, size - ret, "], "); 70 ret += SNPRINTF(bf + ret, size - ret, "], ");
71 71
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index df2fddbf0cd2..0715c843c2e7 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -32,29 +32,25 @@ int header_page_size_size;
32int header_page_ts_size; 32int header_page_ts_size;
33int header_page_data_offset; 33int header_page_data_offset;
34 34
35struct pevent *perf_pevent;
36static struct pevent *pevent;
37
38bool latency_format; 35bool latency_format;
39 36
40int read_trace_init(int file_bigendian, int host_bigendian) 37struct pevent *read_trace_init(int file_bigendian, int host_bigendian)
41{ 38{
42 if (pevent) 39 struct pevent *pevent = pevent_alloc();
43 return 0;
44
45 perf_pevent = pevent_alloc();
46 pevent = perf_pevent;
47 40
48 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); 41 if (pevent != NULL) {
49 pevent_set_file_bigendian(pevent, file_bigendian); 42 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
50 pevent_set_host_bigendian(pevent, host_bigendian); 43 pevent_set_file_bigendian(pevent, file_bigendian);
44 pevent_set_host_bigendian(pevent, host_bigendian);
45 }
51 46
52 return 0; 47 return pevent;
53} 48}
54 49
55static int get_common_field(struct scripting_context *context, 50static int get_common_field(struct scripting_context *context,
56 int *offset, int *size, const char *type) 51 int *offset, int *size, const char *type)
57{ 52{
53 struct pevent *pevent = context->pevent;
58 struct event_format *event; 54 struct event_format *event;
59 struct format_field *field; 55 struct format_field *field;
60 56
@@ -150,7 +146,7 @@ void *raw_field_ptr(struct event_format *event, const char *name, void *data)
150 return data + field->offset; 146 return data + field->offset;
151} 147}
152 148
153int trace_parse_common_type(void *data) 149int trace_parse_common_type(struct pevent *pevent, void *data)
154{ 150{
155 struct pevent_record record; 151 struct pevent_record record;
156 152
@@ -158,7 +154,7 @@ int trace_parse_common_type(void *data)
158 return pevent_data_type(pevent, &record); 154 return pevent_data_type(pevent, &record);
159} 155}
160 156
161int trace_parse_common_pid(void *data) 157int trace_parse_common_pid(struct pevent *pevent, void *data)
162{ 158{
163 struct pevent_record record; 159 struct pevent_record record;
164 160
@@ -166,27 +162,21 @@ int trace_parse_common_pid(void *data)
166 return pevent_data_pid(pevent, &record); 162 return pevent_data_pid(pevent, &record);
167} 163}
168 164
169unsigned long long read_size(void *ptr, int size) 165unsigned long long read_size(struct pevent *pevent, void *ptr, int size)
170{ 166{
171 return pevent_read_number(pevent, ptr, size); 167 return pevent_read_number(pevent, ptr, size);
172} 168}
173 169
174struct event_format *trace_find_event(int type) 170void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
175{
176 return pevent_find_event(pevent, type);
177}
178
179
180void print_trace_event(int cpu, void *data, int size)
181{ 171{
182 struct event_format *event; 172 struct event_format *event;
183 struct pevent_record record; 173 struct pevent_record record;
184 struct trace_seq s; 174 struct trace_seq s;
185 int type; 175 int type;
186 176
187 type = trace_parse_common_type(data); 177 type = trace_parse_common_type(pevent, data);
188 178
189 event = trace_find_event(type); 179 event = pevent_find_event(pevent, type);
190 if (!event) { 180 if (!event) {
191 warning("ug! no event found for type %d", type); 181 warning("ug! no event found for type %d", type);
192 return; 182 return;
@@ -198,13 +188,12 @@ void print_trace_event(int cpu, void *data, int size)
198 record.data = data; 188 record.data = data;
199 189
200 trace_seq_init(&s); 190 trace_seq_init(&s);
201 pevent_print_event(pevent, &s, &record); 191 pevent_event_info(&s, event, &record);
202 trace_seq_do_printf(&s); 192 trace_seq_do_printf(&s);
203 printf("\n");
204} 193}
205 194
206void print_event(int cpu, void *data, int size, unsigned long long nsecs, 195void print_event(struct pevent *pevent, int cpu, void *data, int size,
207 char *comm) 196 unsigned long long nsecs, char *comm)
208{ 197{
209 struct pevent_record record; 198 struct pevent_record record;
210 struct trace_seq s; 199 struct trace_seq s;
@@ -227,7 +216,8 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
227 printf("\n"); 216 printf("\n");
228} 217}
229 218
230void parse_proc_kallsyms(char *file, unsigned int size __unused) 219void parse_proc_kallsyms(struct pevent *pevent,
220 char *file, unsigned int size __unused)
231{ 221{
232 unsigned long long addr; 222 unsigned long long addr;
233 char *func; 223 char *func;
@@ -258,7 +248,8 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused)
258 } 248 }
259} 249}
260 250
261void parse_ftrace_printk(char *file, unsigned int size __unused) 251void parse_ftrace_printk(struct pevent *pevent,
252 char *file, unsigned int size __unused)
262{ 253{
263 unsigned long long addr; 254 unsigned long long addr;
264 char *printk; 255 char *printk;
@@ -282,17 +273,19 @@ void parse_ftrace_printk(char *file, unsigned int size __unused)
282 } 273 }
283} 274}
284 275
285int parse_ftrace_file(char *buf, unsigned long size) 276int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size)
286{ 277{
287 return pevent_parse_event(pevent, buf, size, "ftrace"); 278 return pevent_parse_event(pevent, buf, size, "ftrace");
288} 279}
289 280
290int parse_event_file(char *buf, unsigned long size, char *sys) 281int parse_event_file(struct pevent *pevent,
282 char *buf, unsigned long size, char *sys)
291{ 283{
292 return pevent_parse_event(pevent, buf, size, sys); 284 return pevent_parse_event(pevent, buf, size, sys);
293} 285}
294 286
295struct event_format *trace_find_next_event(struct event_format *event) 287struct event_format *trace_find_next_event(struct pevent *pevent,
288 struct event_format *event)
296{ 289{
297 static int idx; 290 static int idx;
298 291
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index f097e0dd6c5c..719ed74a8565 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -114,20 +114,20 @@ static void skip(int size)
114 }; 114 };
115} 115}
116 116
117static unsigned int read4(void) 117static unsigned int read4(struct pevent *pevent)
118{ 118{
119 unsigned int data; 119 unsigned int data;
120 120
121 read_or_die(&data, 4); 121 read_or_die(&data, 4);
122 return __data2host4(perf_pevent, data); 122 return __data2host4(pevent, data);
123} 123}
124 124
125static unsigned long long read8(void) 125static unsigned long long read8(struct pevent *pevent)
126{ 126{
127 unsigned long long data; 127 unsigned long long data;
128 128
129 read_or_die(&data, 8); 129 read_or_die(&data, 8);
130 return __data2host8(perf_pevent, data); 130 return __data2host8(pevent, data);
131} 131}
132 132
133static char *read_string(void) 133static char *read_string(void)
@@ -168,12 +168,12 @@ static char *read_string(void)
168 return str; 168 return str;
169} 169}
170 170
171static void read_proc_kallsyms(void) 171static void read_proc_kallsyms(struct pevent *pevent)
172{ 172{
173 unsigned int size; 173 unsigned int size;
174 char *buf; 174 char *buf;
175 175
176 size = read4(); 176 size = read4(pevent);
177 if (!size) 177 if (!size)
178 return; 178 return;
179 179
@@ -181,29 +181,29 @@ static void read_proc_kallsyms(void)
181 read_or_die(buf, size); 181 read_or_die(buf, size);
182 buf[size] = '\0'; 182 buf[size] = '\0';
183 183
184 parse_proc_kallsyms(buf, size); 184 parse_proc_kallsyms(pevent, buf, size);
185 185
186 free(buf); 186 free(buf);
187} 187}
188 188
189static void read_ftrace_printk(void) 189static void read_ftrace_printk(struct pevent *pevent)
190{ 190{
191 unsigned int size; 191 unsigned int size;
192 char *buf; 192 char *buf;
193 193
194 size = read4(); 194 size = read4(pevent);
195 if (!size) 195 if (!size)
196 return; 196 return;
197 197
198 buf = malloc_or_die(size); 198 buf = malloc_or_die(size);
199 read_or_die(buf, size); 199 read_or_die(buf, size);
200 200
201 parse_ftrace_printk(buf, size); 201 parse_ftrace_printk(pevent, buf, size);
202 202
203 free(buf); 203 free(buf);
204} 204}
205 205
206static void read_header_files(void) 206static void read_header_files(struct pevent *pevent)
207{ 207{
208 unsigned long long size; 208 unsigned long long size;
209 char *header_event; 209 char *header_event;
@@ -214,7 +214,7 @@ static void read_header_files(void)
214 if (memcmp(buf, "header_page", 12) != 0) 214 if (memcmp(buf, "header_page", 12) != 0)
215 die("did not read header page"); 215 die("did not read header page");
216 216
217 size = read8(); 217 size = read8(pevent);
218 skip(size); 218 skip(size);
219 219
220 /* 220 /*
@@ -227,47 +227,48 @@ static void read_header_files(void)
227 if (memcmp(buf, "header_event", 13) != 0) 227 if (memcmp(buf, "header_event", 13) != 0)
228 die("did not read header event"); 228 die("did not read header event");
229 229
230 size = read8(); 230 size = read8(pevent);
231 header_event = malloc_or_die(size); 231 header_event = malloc_or_die(size);
232 read_or_die(header_event, size); 232 read_or_die(header_event, size);
233 free(header_event); 233 free(header_event);
234} 234}
235 235
236static void read_ftrace_file(unsigned long long size) 236static void read_ftrace_file(struct pevent *pevent, unsigned long long size)
237{ 237{
238 char *buf; 238 char *buf;
239 239
240 buf = malloc_or_die(size); 240 buf = malloc_or_die(size);
241 read_or_die(buf, size); 241 read_or_die(buf, size);
242 parse_ftrace_file(buf, size); 242 parse_ftrace_file(pevent, buf, size);
243 free(buf); 243 free(buf);
244} 244}
245 245
246static void read_event_file(char *sys, unsigned long long size) 246static void read_event_file(struct pevent *pevent, char *sys,
247 unsigned long long size)
247{ 248{
248 char *buf; 249 char *buf;
249 250
250 buf = malloc_or_die(size); 251 buf = malloc_or_die(size);
251 read_or_die(buf, size); 252 read_or_die(buf, size);
252 parse_event_file(buf, size, sys); 253 parse_event_file(pevent, buf, size, sys);
253 free(buf); 254 free(buf);
254} 255}
255 256
256static void read_ftrace_files(void) 257static void read_ftrace_files(struct pevent *pevent)
257{ 258{
258 unsigned long long size; 259 unsigned long long size;
259 int count; 260 int count;
260 int i; 261 int i;
261 262
262 count = read4(); 263 count = read4(pevent);
263 264
264 for (i = 0; i < count; i++) { 265 for (i = 0; i < count; i++) {
265 size = read8(); 266 size = read8(pevent);
266 read_ftrace_file(size); 267 read_ftrace_file(pevent, size);
267 } 268 }
268} 269}
269 270
270static void read_event_files(void) 271static void read_event_files(struct pevent *pevent)
271{ 272{
272 unsigned long long size; 273 unsigned long long size;
273 char *sys; 274 char *sys;
@@ -275,15 +276,15 @@ static void read_event_files(void)
275 int count; 276 int count;
276 int i,x; 277 int i,x;
277 278
278 systems = read4(); 279 systems = read4(pevent);
279 280
280 for (i = 0; i < systems; i++) { 281 for (i = 0; i < systems; i++) {
281 sys = read_string(); 282 sys = read_string();
282 283
283 count = read4(); 284 count = read4(pevent);
284 for (x=0; x < count; x++) { 285 for (x=0; x < count; x++) {
285 size = read8(); 286 size = read8(pevent);
286 read_event_file(sys, size); 287 read_event_file(pevent, sys, size);
287 } 288 }
288 } 289 }
289} 290}
@@ -377,7 +378,7 @@ static int calc_index(void *ptr, int cpu)
377 return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page; 378 return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
378} 379}
379 380
380struct pevent_record *trace_peek_data(int cpu) 381struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu)
381{ 382{
382 struct pevent_record *data; 383 struct pevent_record *data;
383 void *page = cpu_data[cpu].page; 384 void *page = cpu_data[cpu].page;
@@ -399,15 +400,15 @@ struct pevent_record *trace_peek_data(int cpu)
399 /* FIXME: handle header page */ 400 /* FIXME: handle header page */
400 if (header_page_ts_size != 8) 401 if (header_page_ts_size != 8)
401 die("expected a long long type for timestamp"); 402 die("expected a long long type for timestamp");
402 cpu_data[cpu].timestamp = data2host8(perf_pevent, ptr); 403 cpu_data[cpu].timestamp = data2host8(pevent, ptr);
403 ptr += 8; 404 ptr += 8;
404 switch (header_page_size_size) { 405 switch (header_page_size_size) {
405 case 4: 406 case 4:
406 cpu_data[cpu].page_size = data2host4(perf_pevent, ptr); 407 cpu_data[cpu].page_size = data2host4(pevent, ptr);
407 ptr += 4; 408 ptr += 4;
408 break; 409 break;
409 case 8: 410 case 8:
410 cpu_data[cpu].page_size = data2host8(perf_pevent, ptr); 411 cpu_data[cpu].page_size = data2host8(pevent, ptr);
411 ptr += 8; 412 ptr += 8;
412 break; 413 break;
413 default: 414 default:
@@ -421,10 +422,10 @@ read_again:
421 422
422 if (idx >= cpu_data[cpu].page_size) { 423 if (idx >= cpu_data[cpu].page_size) {
423 get_next_page(cpu); 424 get_next_page(cpu);
424 return trace_peek_data(cpu); 425 return trace_peek_data(pevent, cpu);
425 } 426 }
426 427
427 type_len_ts = data2host4(perf_pevent, ptr); 428 type_len_ts = data2host4(pevent, ptr);
428 ptr += 4; 429 ptr += 4;
429 430
430 type_len = type_len4host(type_len_ts); 431 type_len = type_len4host(type_len_ts);
@@ -434,14 +435,14 @@ read_again:
434 case RINGBUF_TYPE_PADDING: 435 case RINGBUF_TYPE_PADDING:
435 if (!delta) 436 if (!delta)
436 die("error, hit unexpected end of page"); 437 die("error, hit unexpected end of page");
437 length = data2host4(perf_pevent, ptr); 438 length = data2host4(pevent, ptr);
438 ptr += 4; 439 ptr += 4;
439 length *= 4; 440 length *= 4;
440 ptr += length; 441 ptr += length;
441 goto read_again; 442 goto read_again;
442 443
443 case RINGBUF_TYPE_TIME_EXTEND: 444 case RINGBUF_TYPE_TIME_EXTEND:
444 extend = data2host4(perf_pevent, ptr); 445 extend = data2host4(pevent, ptr);
445 ptr += 4; 446 ptr += 4;
446 extend <<= TS_SHIFT; 447 extend <<= TS_SHIFT;
447 extend += delta; 448 extend += delta;
@@ -452,7 +453,7 @@ read_again:
452 ptr += 12; 453 ptr += 12;
453 break; 454 break;
454 case 0: 455 case 0:
455 length = data2host4(perf_pevent, ptr); 456 length = data2host4(pevent, ptr);
456 ptr += 4; 457 ptr += 4;
457 die("here! length=%d", length); 458 die("here! length=%d", length);
458 break; 459 break;
@@ -477,17 +478,17 @@ read_again:
477 return data; 478 return data;
478} 479}
479 480
480struct pevent_record *trace_read_data(int cpu) 481struct pevent_record *trace_read_data(struct pevent *pevent, int cpu)
481{ 482{
482 struct pevent_record *data; 483 struct pevent_record *data;
483 484
484 data = trace_peek_data(cpu); 485 data = trace_peek_data(pevent, cpu);
485 cpu_data[cpu].next = NULL; 486 cpu_data[cpu].next = NULL;
486 487
487 return data; 488 return data;
488} 489}
489 490
490ssize_t trace_report(int fd, bool __repipe) 491ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
491{ 492{
492 char buf[BUFSIZ]; 493 char buf[BUFSIZ];
493 char test[] = { 23, 8, 68 }; 494 char test[] = { 23, 8, 68 };
@@ -519,30 +520,32 @@ ssize_t trace_report(int fd, bool __repipe)
519 file_bigendian = buf[0]; 520 file_bigendian = buf[0];
520 host_bigendian = bigendian(); 521 host_bigendian = bigendian();
521 522
522 read_trace_init(file_bigendian, host_bigendian); 523 *ppevent = read_trace_init(file_bigendian, host_bigendian);
524 if (*ppevent == NULL)
525 die("read_trace_init failed");
523 526
524 read_or_die(buf, 1); 527 read_or_die(buf, 1);
525 long_size = buf[0]; 528 long_size = buf[0];
526 529
527 page_size = read4(); 530 page_size = read4(*ppevent);
528 531
529 read_header_files(); 532 read_header_files(*ppevent);
530 533
531 read_ftrace_files(); 534 read_ftrace_files(*ppevent);
532 read_event_files(); 535 read_event_files(*ppevent);
533 read_proc_kallsyms(); 536 read_proc_kallsyms(*ppevent);
534 read_ftrace_printk(); 537 read_ftrace_printk(*ppevent);
535 538
536 size = calc_data_size - 1; 539 size = calc_data_size - 1;
537 calc_data_size = 0; 540 calc_data_size = 0;
538 repipe = false; 541 repipe = false;
539 542
540 if (show_funcs) { 543 if (show_funcs) {
541 pevent_print_funcs(perf_pevent); 544 pevent_print_funcs(*ppevent);
542 return size; 545 return size;
543 } 546 }
544 if (show_printk) { 547 if (show_printk) {
545 pevent_print_printk(perf_pevent); 548 pevent_print_printk(*ppevent);
546 return size; 549 return size;
547 } 550 }
548 551
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 18ae6c1831d3..474aa7a7df43 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -36,6 +36,7 @@ static int stop_script_unsupported(void)
36} 36}
37 37
38static void process_event_unsupported(union perf_event *event __unused, 38static void process_event_unsupported(union perf_event *event __unused,
39 struct pevent *pevent __unused,
39 struct perf_sample *sample __unused, 40 struct perf_sample *sample __unused,
40 struct perf_evsel *evsel __unused, 41 struct perf_evsel *evsel __unused,
41 struct machine *machine __unused, 42 struct machine *machine __unused,
@@ -61,7 +62,8 @@ static int python_start_script_unsupported(const char *script __unused,
61 return -1; 62 return -1;
62} 63}
63 64
64static int python_generate_script_unsupported(const char *outfile __unused) 65static int python_generate_script_unsupported(struct pevent *pevent __unused,
66 const char *outfile __unused)
65{ 67{
66 print_python_unsupported_msg(); 68 print_python_unsupported_msg();
67 69
@@ -122,7 +124,8 @@ static int perl_start_script_unsupported(const char *script __unused,
122 return -1; 124 return -1;
123} 125}
124 126
125static int perl_generate_script_unsupported(const char *outfile __unused) 127static int perl_generate_script_unsupported(struct pevent *pevent __unused,
128 const char *outfile __unused)
126{ 129{
127 print_perl_unsupported_msg(); 130 print_perl_unsupported_msg();
128 131
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 639852ac1117..8fef1d6687b7 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -8,6 +8,7 @@
8struct machine; 8struct machine;
9struct perf_sample; 9struct perf_sample;
10union perf_event; 10union perf_event;
11struct perf_tool;
11struct thread; 12struct thread;
12 13
13extern int header_page_size_size; 14extern int header_page_size_size;
@@ -29,35 +30,36 @@ enum {
29 30
30int bigendian(void); 31int bigendian(void);
31 32
32int read_trace_init(int file_bigendian, int host_bigendian); 33struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
33void print_trace_event(int cpu, void *data, int size); 34void print_trace_event(struct pevent *pevent, int cpu, void *data, int size);
34 35
35void print_event(int cpu, void *data, int size, unsigned long long nsecs, 36void print_event(struct pevent *pevent, int cpu, void *data, int size,
36 char *comm); 37 unsigned long long nsecs, char *comm);
37 38
38int parse_ftrace_file(char *buf, unsigned long size); 39int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size);
39int parse_event_file(char *buf, unsigned long size, char *sys); 40int parse_event_file(struct pevent *pevent,
41 char *buf, unsigned long size, char *sys);
40 42
41struct pevent_record *trace_peek_data(int cpu); 43struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu);
42struct event_format *trace_find_event(int type);
43 44
44unsigned long long 45unsigned long long
45raw_field_value(struct event_format *event, const char *name, void *data); 46raw_field_value(struct event_format *event, const char *name, void *data);
46void *raw_field_ptr(struct event_format *event, const char *name, void *data); 47void *raw_field_ptr(struct event_format *event, const char *name, void *data);
47 48
48void parse_proc_kallsyms(char *file, unsigned int size __unused); 49void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
49void parse_ftrace_printk(char *file, unsigned int size __unused); 50void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
50 51
51ssize_t trace_report(int fd, bool repipe); 52ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
52 53
53int trace_parse_common_type(void *data); 54int trace_parse_common_type(struct pevent *pevent, void *data);
54int trace_parse_common_pid(void *data); 55int trace_parse_common_pid(struct pevent *pevent, void *data);
55 56
56struct event_format *trace_find_next_event(struct event_format *event); 57struct event_format *trace_find_next_event(struct pevent *pevent,
57unsigned long long read_size(void *ptr, int size); 58 struct event_format *event);
59unsigned long long read_size(struct pevent *pevent, void *ptr, int size);
58unsigned long long eval_flag(const char *flag); 60unsigned long long eval_flag(const char *flag);
59 61
60struct pevent_record *trace_read_data(int cpu); 62struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
61int read_tracing_data(int fd, struct list_head *pattrs); 63int read_tracing_data(int fd, struct list_head *pattrs);
62 64
63struct tracing_data { 65struct tracing_data {
@@ -77,11 +79,12 @@ struct scripting_ops {
77 int (*start_script) (const char *script, int argc, const char **argv); 79 int (*start_script) (const char *script, int argc, const char **argv);
78 int (*stop_script) (void); 80 int (*stop_script) (void);
79 void (*process_event) (union perf_event *event, 81 void (*process_event) (union perf_event *event,
82 struct pevent *pevent,
80 struct perf_sample *sample, 83 struct perf_sample *sample,
81 struct perf_evsel *evsel, 84 struct perf_evsel *evsel,
82 struct machine *machine, 85 struct machine *machine,
83 struct thread *thread); 86 struct thread *thread);
84 int (*generate_script) (const char *outfile); 87 int (*generate_script) (struct pevent *pevent, const char *outfile);
85}; 88};
86 89
87int script_spec_register(const char *spec, struct scripting_ops *ops); 90int script_spec_register(const char *spec, struct scripting_ops *ops);
@@ -90,6 +93,7 @@ void setup_perl_scripting(void);
90void setup_python_scripting(void); 93void setup_python_scripting(void);
91 94
92struct scripting_context { 95struct scripting_context {
96 struct pevent *pevent;
93 void *event_data; 97 void *event_data;
94}; 98};
95 99
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 2daaedb83d84..b13c7331eaf8 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -264,4 +264,6 @@ bool is_power_of_2(unsigned long n)
264 264
265size_t hex_width(u64 v); 265size_t hex_width(u64 v);
266 266
267char *rtrim(char *s);
268
267#endif 269#endif