aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-09-03 02:26:33 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-09-03 02:26:33 -0400
commitc50e86ce7c2961a41f2f7aa6e4fd6c99229ba205 (patch)
tree4ea36009719bd8fc523239fe1bdccb90f0dce3ae /tools/perf
parent14d33d384693eb6083396199de516fdef320f7af (diff)
parent4cbe5a555fa58a79b6ecbb6c531b8bab0650778d (diff)
Merge tag 'v3.6-rc4'
Merge 3.6-rc4 to get latest OMAP and device tree fixes.
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/Makefile19
-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.c8
-rw-r--r--tools/perf/builtin-report.c17
-rw-r--r--tools/perf/builtin-sched.c38
-rw-r--r--tools/perf/builtin-script.c106
-rw-r--r--tools/perf/builtin-stat.c20
-rw-r--r--tools/perf/builtin-test.c25
-rw-r--r--tools/perf/builtin-top.c37
-rw-r--r--tools/perf/config/feature-tests.mak13
-rw-r--r--tools/perf/ui/browsers/annotate.c4
-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
-rw-r--r--tools/perf/util/annotate.c15
-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/event.h3
-rw-r--r--tools/perf/util/evlist.c13
-rw-r--r--tools/perf/util/evlist.h6
-rw-r--r--tools/perf/util/evsel.c238
-rw-r--r--tools/perf/util/evsel.h25
-rw-r--r--tools/perf/util/header.c86
-rw-r--r--tools/perf/util/hist.c7
-rw-r--r--tools/perf/util/hist.h1
-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/intlist.c101
-rw-r--r--tools/perf/util/intlist.h75
-rw-r--r--tools/perf/util/map.c64
-rw-r--r--tools/perf/util/map.h3
-rw-r--r--tools/perf/util/parse-events-test.c191
-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/parse-options.c3
-rw-r--r--tools/perf/util/pmu.c169
-rw-r--r--tools/perf/util/pmu.h11
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/python.c6
-rw-r--r--tools/perf/util/rblist.c107
-rw-r--r--tools/perf/util/rblist.h47
-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.c128
-rw-r--r--tools/perf/util/session.h39
-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/strlist.c130
-rw-r--r--tools/perf/util/strlist.h11
-rw-r--r--tools/perf/util/symbol.c523
-rw-r--r--tools/perf/util/symbol.h53
-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
76 files changed, 3615 insertions, 1256 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/Makefile b/tools/perf/Makefile
index 0eee64cfe9a0..35655c3a7b7a 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
@@ -319,6 +319,8 @@ LIB_H += $(ARCH_INCLUDE)
319LIB_H += util/cgroup.h 319LIB_H += util/cgroup.h
320LIB_H += $(TRACE_EVENT_DIR)event-parse.h 320LIB_H += $(TRACE_EVENT_DIR)event-parse.h
321LIB_H += util/target.h 321LIB_H += util/target.h
322LIB_H += util/rblist.h
323LIB_H += util/intlist.h
322 324
323LIB_OBJS += $(OUTPUT)util/abspath.o 325LIB_OBJS += $(OUTPUT)util/abspath.o
324LIB_OBJS += $(OUTPUT)util/alias.o 326LIB_OBJS += $(OUTPUT)util/alias.o
@@ -354,6 +356,7 @@ LIB_OBJS += $(OUTPUT)util/usage.o
354LIB_OBJS += $(OUTPUT)util/wrapper.o 356LIB_OBJS += $(OUTPUT)util/wrapper.o
355LIB_OBJS += $(OUTPUT)util/sigchain.o 357LIB_OBJS += $(OUTPUT)util/sigchain.o
356LIB_OBJS += $(OUTPUT)util/symbol.o 358LIB_OBJS += $(OUTPUT)util/symbol.o
359LIB_OBJS += $(OUTPUT)util/dso-test-data.o
357LIB_OBJS += $(OUTPUT)util/color.o 360LIB_OBJS += $(OUTPUT)util/color.o
358LIB_OBJS += $(OUTPUT)util/pager.o 361LIB_OBJS += $(OUTPUT)util/pager.o
359LIB_OBJS += $(OUTPUT)util/header.o 362LIB_OBJS += $(OUTPUT)util/header.o
@@ -382,6 +385,8 @@ LIB_OBJS += $(OUTPUT)util/xyarray.o
382LIB_OBJS += $(OUTPUT)util/cpumap.o 385LIB_OBJS += $(OUTPUT)util/cpumap.o
383LIB_OBJS += $(OUTPUT)util/cgroup.o 386LIB_OBJS += $(OUTPUT)util/cgroup.o
384LIB_OBJS += $(OUTPUT)util/target.o 387LIB_OBJS += $(OUTPUT)util/target.o
388LIB_OBJS += $(OUTPUT)util/rblist.o
389LIB_OBJS += $(OUTPUT)util/intlist.o
385 390
386BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 391BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
387 392
@@ -503,6 +508,7 @@ else
503 LIB_OBJS += $(OUTPUT)ui/progress.o 508 LIB_OBJS += $(OUTPUT)ui/progress.o
504 LIB_OBJS += $(OUTPUT)ui/util.o 509 LIB_OBJS += $(OUTPUT)ui/util.o
505 LIB_OBJS += $(OUTPUT)ui/tui/setup.o 510 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
511 LIB_OBJS += $(OUTPUT)ui/tui/util.o
506 LIB_H += ui/browser.h 512 LIB_H += ui/browser.h
507 LIB_H += ui/browsers/map.h 513 LIB_H += ui/browsers/map.h
508 LIB_H += ui/helpline.h 514 LIB_H += ui/helpline.h
@@ -522,13 +528,18 @@ else
522 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 528 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
523 BASIC_CFLAGS += -DNO_GTK2_SUPPORT 529 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
524 else 530 else
531 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
532 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
533 endif
525 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0) 534 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
526 EXTLIBS += $(shell pkg-config --libs gtk+-2.0) 535 EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
527 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o 536 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
528 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o 537 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
538 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
529 # Make sure that it'd be included only once. 539 # Make sure that it'd be included only once.
530 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),) 540 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
531 LIB_OBJS += $(OUTPUT)ui/setup.o 541 LIB_OBJS += $(OUTPUT)ui/setup.o
542 LIB_OBJS += $(OUTPUT)ui/util.o
532 endif 543 endif
533 endif 544 endif
534endif 545endif
@@ -797,6 +808,9 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
797$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 808$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
798 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 809 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
799 810
811$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
812 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $<
813
800$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS 814$(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 $< 815 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
802 816
@@ -973,7 +987,8 @@ clean:
973 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* 987 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
974 $(MAKE) -C Documentation/ clean 988 $(MAKE) -C Documentation/ clean
975 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS 989 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
976 $(RM) $(OUTPUT)util/*-{bison,flex}* 990 $(RM) $(OUTPUT)util/*-bison*
991 $(RM) $(OUTPUT)util/*-flex*
977 $(python-clean) 992 $(python-clean)
978 993
979.PHONY: all install clean strip $(LIBTRACEEVENT) 994.PHONY: all install clean strip $(LIBTRACEEVENT)
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..4db6e1ba54e3 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
@@ -313,7 +313,7 @@ try_again:
313 } 313 }
314 } 314 }
315 315
316 perf_session__update_sample_type(session); 316 perf_session__set_id_hdr_size(session);
317} 317}
318 318
319static int process_buildids(struct perf_record *rec) 319static int process_buildids(struct perf_record *rec)
@@ -844,8 +844,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
844 struct perf_record *rec = &record; 844 struct perf_record *rec = &record;
845 char errbuf[BUFSIZ]; 845 char errbuf[BUFSIZ];
846 846
847 perf_header__set_cmdline(argc, argv);
848
849 evsel_list = perf_evlist__new(NULL, NULL); 847 evsel_list = perf_evlist__new(NULL, NULL);
850 if (evsel_list == NULL) 848 if (evsel_list == NULL)
851 return -ENOMEM; 849 return -ENOMEM;
@@ -916,7 +914,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
916 usage_with_options(record_usage, record_options); 914 usage_with_options(record_usage, record_options);
917 915
918 list_for_each_entry(pos, &evsel_list->entries, node) { 916 list_for_each_entry(pos, &evsel_list->entries, node) {
919 if (perf_header__push_event(pos->attr.config, event_name(pos))) 917 if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
920 goto out_free_fd; 918 goto out_free_fd;
921 } 919 }
922 920
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 25249f76329d..7c88a243b5db 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;
@@ -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,19 @@ 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;
252 u64 sample_type = perf_evlist__sample_type(self->evlist);
251 253
252 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { 254 if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
253 if (sort__has_parent) { 255 if (sort__has_parent) {
254 ui__error("Selected --sort parent, but no " 256 ui__error("Selected --sort parent, but no "
255 "callchain data. Did you call " 257 "callchain data. Did you call "
@@ -272,7 +274,8 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
272 } 274 }
273 275
274 if (sort__branch_mode == 1) { 276 if (sort__branch_mode == 1) {
275 if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) { 277 if (!self->fd_pipe &&
278 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
276 ui__error("Selected -b but no branch data. " 279 ui__error("Selected -b but no branch data. "
277 "Did you call perf record without -b?\n"); 280 "Did you call perf record without -b?\n");
278 return -1; 281 return -1;
@@ -314,7 +317,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
314 317
315 list_for_each_entry(pos, &evlist->entries, node) { 318 list_for_each_entry(pos, &evlist->entries, node) {
316 struct hists *hists = &pos->hists; 319 struct hists *hists = &pos->hists;
317 const char *evname = event_name(pos); 320 const char *evname = perf_evsel__name(pos);
318 321
319 hists__fprintf_nr_sample_events(hists, evname, stdout); 322 hists__fprintf_nr_sample_events(hists, evname, stdout);
320 hists__fprintf(hists, NULL, false, true, 0, 0, stdout); 323 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 262589991ea4..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",
@@ -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..1d592f5cbea9 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -478,7 +478,6 @@ static int test__basic_mmap(void)
478 unsigned int nr_events[nsyscalls], 478 unsigned int nr_events[nsyscalls],
479 expected_nr_events[nsyscalls], i, j; 479 expected_nr_events[nsyscalls], i, j;
480 struct perf_evsel *evsels[nsyscalls], *evsel; 480 struct perf_evsel *evsels[nsyscalls], *evsel;
481 int sample_size = __perf_evsel__sample_size(attr.sample_type);
482 481
483 for (i = 0; i < nsyscalls; ++i) { 482 for (i = 0; i < nsyscalls; ++i) {
484 char name[64]; 483 char name[64];
@@ -563,8 +562,7 @@ static int test__basic_mmap(void)
563 goto out_munmap; 562 goto out_munmap;
564 } 563 }
565 564
566 err = perf_event__parse_sample(event, attr.sample_type, sample_size, 565 err = perf_evlist__parse_sample(evlist, event, &sample, false);
567 false, &sample, false);
568 if (err) { 566 if (err) {
569 pr_err("Can't parse sample, err = %d\n", err); 567 pr_err("Can't parse sample, err = %d\n", err);
570 goto out_munmap; 568 goto out_munmap;
@@ -583,7 +581,7 @@ static int test__basic_mmap(void)
583 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 581 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
584 pr_debug("expected %d %s events, got %d\n", 582 pr_debug("expected %d %s events, got %d\n",
585 expected_nr_events[evsel->idx], 583 expected_nr_events[evsel->idx],
586 event_name(evsel), nr_events[evsel->idx]); 584 perf_evsel__name(evsel), nr_events[evsel->idx]);
587 goto out_munmap; 585 goto out_munmap;
588 } 586 }
589 } 587 }
@@ -661,12 +659,12 @@ static int test__PERF_RECORD(void)
661 const char *cmd = "sleep"; 659 const char *cmd = "sleep";
662 const char *argv[] = { cmd, "1", NULL, }; 660 const char *argv[] = { cmd, "1", NULL, };
663 char *bname; 661 char *bname;
664 u64 sample_type, prev_time = 0; 662 u64 prev_time = 0;
665 bool found_cmd_mmap = false, 663 bool found_cmd_mmap = false,
666 found_libc_mmap = false, 664 found_libc_mmap = false,
667 found_vdso_mmap = false, 665 found_vdso_mmap = false,
668 found_ld_mmap = false; 666 found_ld_mmap = false;
669 int err = -1, errs = 0, i, wakeups = 0, sample_size; 667 int err = -1, errs = 0, i, wakeups = 0;
670 u32 cpu; 668 u32 cpu;
671 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; 669 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
672 670
@@ -757,13 +755,6 @@ static int test__PERF_RECORD(void)
757 } 755 }
758 756
759 /* 757 /*
760 * We'll need these two to parse the PERF_SAMPLE_* fields in each
761 * event.
762 */
763 sample_type = perf_evlist__sample_type(evlist);
764 sample_size = __perf_evsel__sample_size(sample_type);
765
766 /*
767 * Now that all is properly set up, enable the events, they will 758 * Now that all is properly set up, enable the events, they will
768 * count just on workload.pid, which will start... 759 * count just on workload.pid, which will start...
769 */ 760 */
@@ -788,9 +779,7 @@ static int test__PERF_RECORD(void)
788 if (type < PERF_RECORD_MAX) 779 if (type < PERF_RECORD_MAX)
789 nr_events[type]++; 780 nr_events[type]++;
790 781
791 err = perf_event__parse_sample(event, sample_type, 782 err = perf_evlist__parse_sample(evlist, event, &sample, false);
792 sample_size, true,
793 &sample, false);
794 if (err < 0) { 783 if (err < 0) {
795 if (verbose) 784 if (verbose)
796 perf_event__fprintf(event, stderr); 785 perf_event__fprintf(event, stderr);
@@ -1142,6 +1131,10 @@ static struct test {
1142 .func = test__perf_pmu, 1131 .func = test__perf_pmu,
1143 }, 1132 },
1144 { 1133 {
1134 .desc = "Test dso data interface",
1135 .func = dso__test_data,
1136 },
1137 {
1145 .func = NULL, 1138 .func = NULL,
1146 }, 1139 },
1147}; 1140};
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 6bb0277b7dfe..68cd61ef6ac5 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -38,6 +38,7 @@
38#include "util/cpumap.h" 38#include "util/cpumap.h"
39#include "util/xyarray.h" 39#include "util/xyarray.h"
40#include "util/sort.h" 40#include "util/sort.h"
41#include "util/intlist.h"
41 42
42#include "util/debug.h" 43#include "util/debug.h"
43 44
@@ -125,7 +126,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
125 /* 126 /*
126 * We can't annotate with just /proc/kallsyms 127 * We can't annotate with just /proc/kallsyms
127 */ 128 */
128 if (map->dso->symtab_type == SYMTAB__KALLSYMS) { 129 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
129 pr_err("Can't annotate %s: No vmlinux file was found in the " 130 pr_err("Can't annotate %s: No vmlinux file was found in the "
130 "path\n", sym->name); 131 "path\n", sym->name);
131 sleep(1); 132 sleep(1);
@@ -245,7 +246,7 @@ static void perf_top__show_details(struct perf_top *top)
245 if (notes->src == NULL) 246 if (notes->src == NULL)
246 goto out_unlock; 247 goto out_unlock;
247 248
248 printf("Showing %s for %s\n", event_name(top->sym_evsel), symbol->name); 249 printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
249 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter); 250 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
250 251
251 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx, 252 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
@@ -408,7 +409,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); 409 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries);
409 410
410 if (top->evlist->nr_entries > 1) 411 if (top->evlist->nr_entries > 1)
411 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top->sym_evsel)); 412 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", perf_evsel__name(top->sym_evsel));
412 413
413 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter); 414 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter);
414 415
@@ -503,13 +504,13 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
503 fprintf(stderr, "\nAvailable events:"); 504 fprintf(stderr, "\nAvailable events:");
504 505
505 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node) 506 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)); 507 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
507 508
508 prompt_integer(&counter, "Enter details event counter"); 509 prompt_integer(&counter, "Enter details event counter");
509 510
510 if (counter >= top->evlist->nr_entries) { 511 if (counter >= top->evlist->nr_entries) {
511 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node); 512 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)); 513 fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel));
513 sleep(1); 514 sleep(1);
514 break; 515 break;
515 } 516 }
@@ -706,8 +707,16 @@ static void perf_event__process_sample(struct perf_tool *tool,
706 int err; 707 int err;
707 708
708 if (!machine && perf_guest) { 709 if (!machine && perf_guest) {
709 pr_err("Can't find guest [%d]'s kernel information\n", 710 static struct intlist *seen;
710 event->ip.pid); 711
712 if (!seen)
713 seen = intlist__new();
714
715 if (!intlist__has_entry(seen, event->ip.pid)) {
716 pr_err("Can't find guest [%d]'s kernel information\n",
717 event->ip.pid);
718 intlist__add(seen, event->ip.pid);
719 }
711 return; 720 return;
712 } 721 }
713 722
@@ -774,7 +783,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
774 783
775 if ((sort__has_parent || symbol_conf.use_callchain) && 784 if ((sort__has_parent || symbol_conf.use_callchain) &&
776 sample->callchain) { 785 sample->callchain) {
777 err = machine__resolve_callchain(machine, evsel, al.thread, 786 err = machine__resolve_callchain(machine, al.thread,
778 sample->callchain, &parent); 787 sample->callchain, &parent);
779 if (err) 788 if (err)
780 return; 789 return;
@@ -811,7 +820,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
811 int ret; 820 int ret;
812 821
813 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { 822 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
814 ret = perf_session__parse_sample(session, event, &sample); 823 ret = perf_evlist__parse_sample(top->evlist, event, &sample, false);
815 if (ret) { 824 if (ret) {
816 pr_err("Can't parse sample, err = %d\n", ret); 825 pr_err("Can't parse sample, err = %d\n", ret);
817 continue; 826 continue;
@@ -943,8 +952,10 @@ try_again:
943 * based cpu-clock-tick sw counter, which 952 * based cpu-clock-tick sw counter, which
944 * is always available even if no PMU support: 953 * is always available even if no PMU support:
945 */ 954 */
946 if (attr->type == PERF_TYPE_HARDWARE && 955 if ((err == ENOENT || err == ENXIO) &&
947 attr->config == PERF_COUNT_HW_CPU_CYCLES) { 956 (attr->type == PERF_TYPE_HARDWARE) &&
957 (attr->config == PERF_COUNT_HW_CPU_CYCLES)) {
958
948 if (verbose) 959 if (verbose)
949 ui__warning("Cycles event not supported,\n" 960 ui__warning("Cycles event not supported,\n"
950 "trying to fall back to cpu-clock-ticks\n"); 961 "trying to fall back to cpu-clock-ticks\n");
@@ -960,7 +971,7 @@ try_again:
960 971
961 if (err == ENOENT) { 972 if (err == ENOENT) {
962 ui__error("The %s event is not supported.\n", 973 ui__error("The %s event is not supported.\n",
963 event_name(counter)); 974 perf_evsel__name(counter));
964 goto out_err; 975 goto out_err;
965 } else if (err == EMFILE) { 976 } else if (err == EMFILE) {
966 ui__error("Too many events are opened.\n" 977 ui__error("Too many events are opened.\n"
@@ -1032,7 +1043,7 @@ static int __cmd_top(struct perf_top *top)
1032 &top->session->host_machine); 1043 &top->session->host_machine);
1033 perf_top__start_counters(top); 1044 perf_top__start_counters(top);
1034 top->session->evlist = top->evlist; 1045 top->session->evlist = top->evlist;
1035 perf_session__update_sample_type(top->session); 1046 perf_session__set_id_hdr_size(top->session);
1036 1047
1037 /* Wait for a minimal set of events before starting the snapshot */ 1048 /* Wait for a minimal set of events before starting the snapshot */
1038 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 1049 poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
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/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 34b1c46eaf42..67a2703e666a 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -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/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/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/event.h b/tools/perf/util/event.h
index 1b197280c621..d84870b06426 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -197,9 +197,6 @@ int perf_event__preprocess_sample(const union perf_event *self,
197 197
198const char *perf_event__name(unsigned int id); 198const char *perf_event__name(unsigned int id);
199 199
200int perf_event__parse_sample(const union perf_event *event, u64 type,
201 int sample_size, bool sample_id_all,
202 struct perf_sample *sample, bool swapped);
203int perf_event__synthesize_sample(union perf_event *event, u64 type, 200int perf_event__synthesize_sample(union perf_event *event, u64 type,
204 const struct perf_sample *sample, 201 const struct perf_sample *sample,
205 bool swapped); 202 bool swapped);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 7400fb3fc50c..9b38681add9e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -214,7 +214,7 @@ int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
214 attrs[i].type = PERF_TYPE_TRACEPOINT; 214 attrs[i].type = PERF_TYPE_TRACEPOINT;
215 attrs[i].config = err; 215 attrs[i].config = err;
216 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | 216 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
217 PERF_SAMPLE_CPU); 217 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
218 attrs[i].sample_period = 1; 218 attrs[i].sample_period = 1;
219 } 219 }
220 220
@@ -224,8 +224,8 @@ out_free_attrs:
224 return err; 224 return err;
225} 225}
226 226
227static struct perf_evsel * 227struct perf_evsel *
228 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 228perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
229{ 229{
230 struct perf_evsel *evsel; 230 struct perf_evsel *evsel;
231 231
@@ -881,3 +881,10 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
881 881
882 return 0; 882 return 0;
883} 883}
884
885int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
886 struct perf_sample *sample, bool swapped)
887{
888 struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node);
889 return perf_evsel__parse_sample(e, event, sample, swapped);
890}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 989bee9624c2..528c1acd9298 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -73,6 +73,9 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
73#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \ 73#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array)) 74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
75 75
76struct perf_evsel *
77perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
78
76void 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,
77 int cpu, int thread, u64 id); 80 int cpu, int thread, u64 id);
78 81
@@ -119,6 +122,9 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
119bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); 122bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
120u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); 123u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
121 124
125int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
126 struct perf_sample *sample, bool swapped);
127
122bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 128bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
123bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 129bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
124 130
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9f6cebd798ee..2eaae140def2 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,12 +15,12 @@
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))
22 22
23int __perf_evsel__sample_size(u64 sample_type) 23static int __perf_evsel__sample_size(u64 sample_type)
24{ 24{
25 u64 mask = sample_type & PERF_SAMPLE_MASK; 25 u64 mask = sample_type & PERF_SAMPLE_MASK;
26 int size = 0; 26 int size = 0;
@@ -53,6 +53,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
53 evsel->attr = *attr; 53 evsel->attr = *attr;
54 INIT_LIST_HEAD(&evsel->node); 54 INIT_LIST_HEAD(&evsel->node);
55 hists__init(&evsel->hists); 55 hists__init(&evsel->hists);
56 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
56} 57}
57 58
58struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) 59struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
@@ -78,7 +79,7 @@ static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
78 "ref-cycles", 79 "ref-cycles",
79}; 80};
80 81
81const char *__perf_evsel__hw_name(u64 config) 82static const char *__perf_evsel__hw_name(u64 config)
82{ 83{
83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) 84 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
84 return perf_evsel__hw_names[config]; 85 return perf_evsel__hw_names[config];
@@ -86,16 +87,15 @@ const char *__perf_evsel__hw_name(u64 config)
86 return "unknown-hardware"; 87 return "unknown-hardware";
87} 88}
88 89
89static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) 90static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
90{ 91{
91 int colon = 0; 92 int colon = 0, r = 0;
92 struct perf_event_attr *attr = &evsel->attr; 93 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; 94 bool exclude_guest_default = false;
95 95
96#define MOD_PRINT(context, mod) do { \ 96#define MOD_PRINT(context, mod) do { \
97 if (!attr->exclude_##context) { \ 97 if (!attr->exclude_##context) { \
98 if (!colon) colon = r++; \ 98 if (!colon) colon = ++r; \
99 r += scnprintf(bf + r, size - r, "%c", mod); \ 99 r += scnprintf(bf + r, size - r, "%c", mod); \
100 } } while(0) 100 } } while(0)
101 101
@@ -108,7 +108,7 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
108 108
109 if (attr->precise_ip) { 109 if (attr->precise_ip) {
110 if (!colon) 110 if (!colon)
111 colon = r++; 111 colon = ++r;
112 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); 112 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
113 exclude_guest_default = true; 113 exclude_guest_default = true;
114 } 114 }
@@ -119,39 +119,211 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
119 } 119 }
120#undef MOD_PRINT 120#undef MOD_PRINT
121 if (colon) 121 if (colon)
122 bf[colon] = ':'; 122 bf[colon - 1] = ':';
123 return r;
124}
125
126static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
127{
128 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
129 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
130}
131
132static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
133 "cpu-clock",
134 "task-clock",
135 "page-faults",
136 "context-switches",
137 "CPU-migrations",
138 "minor-faults",
139 "major-faults",
140 "alignment-faults",
141 "emulation-faults",
142};
143
144static const char *__perf_evsel__sw_name(u64 config)
145{
146 if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
147 return perf_evsel__sw_names[config];
148 return "unknown-software";
149}
150
151static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
152{
153 int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
154 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
155}
156
157static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
158{
159 int r;
160
161 r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
162
163 if (type & HW_BREAKPOINT_R)
164 r += scnprintf(bf + r, size - r, "r");
165
166 if (type & HW_BREAKPOINT_W)
167 r += scnprintf(bf + r, size - r, "w");
168
169 if (type & HW_BREAKPOINT_X)
170 r += scnprintf(bf + r, size - r, "x");
171
123 return r; 172 return r;
124} 173}
125 174
126int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size) 175static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
127{ 176{
128 int ret; 177 struct perf_event_attr *attr = &evsel->attr;
178 int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
179 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
180}
181
182const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
183 [PERF_EVSEL__MAX_ALIASES] = {
184 { "L1-dcache", "l1-d", "l1d", "L1-data", },
185 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
186 { "LLC", "L2", },
187 { "dTLB", "d-tlb", "Data-TLB", },
188 { "iTLB", "i-tlb", "Instruction-TLB", },
189 { "branch", "branches", "bpu", "btb", "bpc", },
190 { "node", },
191};
192
193const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
194 [PERF_EVSEL__MAX_ALIASES] = {
195 { "load", "loads", "read", },
196 { "store", "stores", "write", },
197 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
198};
199
200const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
201 [PERF_EVSEL__MAX_ALIASES] = {
202 { "refs", "Reference", "ops", "access", },
203 { "misses", "miss", },
204};
205
206#define C(x) PERF_COUNT_HW_CACHE_##x
207#define CACHE_READ (1 << C(OP_READ))
208#define CACHE_WRITE (1 << C(OP_WRITE))
209#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
210#define COP(x) (1 << x)
211
212/*
213 * cache operartion stat
214 * L1I : Read and prefetch only
215 * ITLB and BPU : Read-only
216 */
217static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
218 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
219 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
220 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
221 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
222 [C(ITLB)] = (CACHE_READ),
223 [C(BPU)] = (CACHE_READ),
224 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
225};
226
227bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
228{
229 if (perf_evsel__hw_cache_stat[type] & COP(op))
230 return true; /* valid */
231 else
232 return false; /* invalid */
233}
234
235int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
236 char *bf, size_t size)
237{
238 if (result) {
239 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
240 perf_evsel__hw_cache_op[op][0],
241 perf_evsel__hw_cache_result[result][0]);
242 }
243
244 return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
245 perf_evsel__hw_cache_op[op][1]);
246}
247
248static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
249{
250 u8 op, result, type = (config >> 0) & 0xff;
251 const char *err = "unknown-ext-hardware-cache-type";
252
253 if (type > PERF_COUNT_HW_CACHE_MAX)
254 goto out_err;
255
256 op = (config >> 8) & 0xff;
257 err = "unknown-ext-hardware-cache-op";
258 if (op > PERF_COUNT_HW_CACHE_OP_MAX)
259 goto out_err;
260
261 result = (config >> 16) & 0xff;
262 err = "unknown-ext-hardware-cache-result";
263 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
264 goto out_err;
265
266 err = "invalid-cache";
267 if (!perf_evsel__is_cache_op_valid(type, op))
268 goto out_err;
269
270 return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
271out_err:
272 return scnprintf(bf, size, "%s", err);
273}
274
275static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
276{
277 int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
278 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
279}
280
281static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
282{
283 int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
284 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
285}
286
287const char *perf_evsel__name(struct perf_evsel *evsel)
288{
289 char bf[128];
290
291 if (evsel->name)
292 return evsel->name;
129 293
130 switch (evsel->attr.type) { 294 switch (evsel->attr.type) {
131 case PERF_TYPE_RAW: 295 case PERF_TYPE_RAW:
132 ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); 296 perf_evsel__raw_name(evsel, bf, sizeof(bf));
133 break; 297 break;
134 298
135 case PERF_TYPE_HARDWARE: 299 case PERF_TYPE_HARDWARE:
136 ret = perf_evsel__hw_name(evsel, bf, size); 300 perf_evsel__hw_name(evsel, bf, sizeof(bf));
301 break;
302
303 case PERF_TYPE_HW_CACHE:
304 perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
137 break; 305 break;
306
307 case PERF_TYPE_SOFTWARE:
308 perf_evsel__sw_name(evsel, bf, sizeof(bf));
309 break;
310
311 case PERF_TYPE_TRACEPOINT:
312 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
313 break;
314
315 case PERF_TYPE_BREAKPOINT:
316 perf_evsel__bp_name(evsel, bf, sizeof(bf));
317 break;
318
138 default: 319 default:
139 /* 320 scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
140 * FIXME 321 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 } 322 }
153 323
154 return ret; 324 evsel->name = strdup(bf);
325
326 return evsel->name ?: "unknown";
155} 327}
156 328
157void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, 329void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
@@ -557,10 +729,10 @@ static bool sample_overlap(const union perf_event *event,
557 return false; 729 return false;
558} 730}
559 731
560int perf_event__parse_sample(const union perf_event *event, u64 type, 732int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
561 int sample_size, bool sample_id_all,
562 struct perf_sample *data, bool swapped) 733 struct perf_sample *data, bool swapped)
563{ 734{
735 u64 type = evsel->attr.sample_type;
564 const u64 *array; 736 const u64 *array;
565 737
566 /* 738 /*
@@ -575,14 +747,14 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
575 data->period = 1; 747 data->period = 1;
576 748
577 if (event->header.type != PERF_RECORD_SAMPLE) { 749 if (event->header.type != PERF_RECORD_SAMPLE) {
578 if (!sample_id_all) 750 if (!evsel->attr.sample_id_all)
579 return 0; 751 return 0;
580 return perf_event__parse_id_sample(event, type, data, swapped); 752 return perf_event__parse_id_sample(event, type, data, swapped);
581 } 753 }
582 754
583 array = event->sample.array; 755 array = event->sample.array;
584 756
585 if (sample_size + sizeof(event->header) > event->header.size) 757 if (evsel->sample_size + sizeof(event->header) > event->header.size)
586 return -EFAULT; 758 return -EFAULT;
587 759
588 if (type & PERF_SAMPLE_IP) { 760 if (type & PERF_SAMPLE_IP) {
@@ -724,7 +896,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
724 u.val32[1] = sample->tid; 896 u.val32[1] = sample->tid;
725 if (swapped) { 897 if (swapped) {
726 /* 898 /*
727 * Inverse of what is done in perf_event__parse_sample 899 * Inverse of what is done in perf_evsel__parse_sample
728 */ 900 */
729 u.val32[0] = bswap_32(u.val32[0]); 901 u.val32[0] = bswap_32(u.val32[0]);
730 u.val32[1] = bswap_32(u.val32[1]); 902 u.val32[1] = bswap_32(u.val32[1]);
@@ -759,7 +931,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
759 u.val32[0] = sample->cpu; 931 u.val32[0] = sample->cpu;
760 if (swapped) { 932 if (swapped) {
761 /* 933 /*
762 * Inverse of what is done in perf_event__parse_sample 934 * Inverse of what is done in perf_evsel__parse_sample
763 */ 935 */
764 u.val32[0] = bswap_32(u.val32[0]); 936 u.val32[0] = bswap_32(u.val32[0]);
765 u.val64 = bswap_64(u.val64); 937 u.val64 = bswap_64(u.val64);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4ba8b564e6f4..b559929983bb 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -65,6 +65,7 @@ struct perf_evsel {
65 void *func; 65 void *func;
66 void *data; 66 void *data;
67 } handler; 67 } handler;
68 unsigned int sample_size;
68 bool supported; 69 bool supported;
69}; 70};
70 71
@@ -83,8 +84,19 @@ void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts, 84 struct perf_record_opts *opts,
84 struct perf_evsel *first); 85 struct perf_evsel *first);
85 86
86const char* __perf_evsel__hw_name(u64 config); 87bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
87int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size); 88
89#define PERF_EVSEL__MAX_ALIASES 8
90
91extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
92 [PERF_EVSEL__MAX_ALIASES];
93extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
94 [PERF_EVSEL__MAX_ALIASES];
95const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
96 [PERF_EVSEL__MAX_ALIASES];
97int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
98 char *bf, size_t size);
99const char *perf_evsel__name(struct perf_evsel *evsel);
88 100
89int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 101int 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); 102int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
@@ -166,13 +178,8 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
166 return __perf_evsel__read(evsel, ncpus, nthreads, true); 178 return __perf_evsel__read(evsel, ncpus, nthreads, true);
167} 179}
168 180
169int __perf_evsel__sample_size(u64 sample_type);
170
171static inline int perf_evsel__sample_size(struct perf_evsel *evsel)
172{
173 return __perf_evsel__sample_size(evsel->attr.sample_type);
174}
175
176void hists__init(struct hists *hists); 181void hists__init(struct hists *hists);
177 182
183int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
184 struct perf_sample *sample, bool swapped);
178#endif /* __PERF_EVSEL_H */ 185#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 2dd5edf161b7..74ea3c2f8138 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -174,6 +174,15 @@ perf_header__set_cmdline(int argc, const char **argv)
174{ 174{
175 int i; 175 int i;
176 176
177 /*
178 * If header_argv has already been set, do not override it.
179 * This allows a command to set the cmdline, parse args and
180 * then call another builtin function that implements a
181 * command -- e.g, cmd_kvm calling cmd_record.
182 */
183 if (header_argv)
184 return 0;
185
177 header_argc = (u32)argc; 186 header_argc = (u32)argc;
178 187
179 /* do not include NULL termination */ 188 /* do not include NULL termination */
@@ -641,7 +650,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
641 /* 650 /*
642 * write event string as passed on cmdline 651 * write event string as passed on cmdline
643 */ 652 */
644 ret = do_write_string(fd, event_name(attr)); 653 ret = do_write_string(fd, perf_evsel__name(attr));
645 if (ret < 0) 654 if (ret < 0)
646 return ret; 655 return ret;
647 /* 656 /*
@@ -1212,6 +1221,12 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1212 attr.exclude_user, 1221 attr.exclude_user,
1213 attr.exclude_kernel); 1222 attr.exclude_kernel);
1214 1223
1224 fprintf(fp, ", excl_host = %d, excl_guest = %d",
1225 attr.exclude_host,
1226 attr.exclude_guest);
1227
1228 fprintf(fp, ", precise_ip = %d", attr.precise_ip);
1229
1215 if (nr) 1230 if (nr)
1216 fprintf(fp, ", id = {"); 1231 fprintf(fp, ", id = {");
1217 1232
@@ -1474,15 +1489,15 @@ out:
1474 1489
1475static int process_tracing_data(struct perf_file_section *section __unused, 1490static int process_tracing_data(struct perf_file_section *section __unused,
1476 struct perf_header *ph __unused, 1491 struct perf_header *ph __unused,
1477 int feat __unused, int fd) 1492 int feat __unused, int fd, void *data)
1478{ 1493{
1479 trace_report(fd, false); 1494 trace_report(fd, data, false);
1480 return 0; 1495 return 0;
1481} 1496}
1482 1497
1483static int process_build_id(struct perf_file_section *section, 1498static int process_build_id(struct perf_file_section *section,
1484 struct perf_header *ph, 1499 struct perf_header *ph,
1485 int feat __unused, int fd) 1500 int feat __unused, int fd, void *data __used)
1486{ 1501{
1487 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1502 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1488 pr_debug("Failed to read buildids, continuing...\n"); 1503 pr_debug("Failed to read buildids, continuing...\n");
@@ -1493,7 +1508,7 @@ struct feature_ops {
1493 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1508 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1494 void (*print)(struct perf_header *h, int fd, FILE *fp); 1509 void (*print)(struct perf_header *h, int fd, FILE *fp);
1495 int (*process)(struct perf_file_section *section, 1510 int (*process)(struct perf_file_section *section,
1496 struct perf_header *h, int feat, int fd); 1511 struct perf_header *h, int feat, int fd, void *data);
1497 const char *name; 1512 const char *name;
1498 bool full_only; 1513 bool full_only;
1499}; 1514};
@@ -1942,7 +1957,6 @@ int perf_file_header__read(struct perf_file_header *header,
1942 else 1957 else
1943 return -1; 1958 return -1;
1944 } else if (ph->needs_swap) { 1959 } else if (ph->needs_swap) {
1945 unsigned int i;
1946 /* 1960 /*
1947 * feature bitmap is declared as an array of unsigned longs -- 1961 * feature bitmap is declared as an array of unsigned longs --
1948 * not good since its size can differ between the host that 1962 * not good since its size can differ between the host that
@@ -1958,14 +1972,17 @@ int perf_file_header__read(struct perf_file_header *header,
1958 * file), punt and fallback to the original behavior -- 1972 * file), punt and fallback to the original behavior --
1959 * clearing all feature bits and setting buildid. 1973 * clearing all feature bits and setting buildid.
1960 */ 1974 */
1961 for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) 1975 mem_bswap_64(&header->adds_features,
1962 header->adds_features[i] = bswap_64(header->adds_features[i]); 1976 BITS_TO_U64(HEADER_FEAT_BITS));
1963 1977
1964 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { 1978 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
1965 for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) { 1979 /* unswap as u64 */
1966 header->adds_features[i] = bswap_64(header->adds_features[i]); 1980 mem_bswap_64(&header->adds_features,
1967 header->adds_features[i] = bswap_32(header->adds_features[i]); 1981 BITS_TO_U64(HEADER_FEAT_BITS));
1968 } 1982
1983 /* unswap as u32 */
1984 mem_bswap_32(&header->adds_features,
1985 BITS_TO_U32(HEADER_FEAT_BITS));
1969 } 1986 }
1970 1987
1971 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { 1988 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
@@ -1986,7 +2003,7 @@ int perf_file_header__read(struct perf_file_header *header,
1986 2003
1987static int perf_file_section__process(struct perf_file_section *section, 2004static int perf_file_section__process(struct perf_file_section *section,
1988 struct perf_header *ph, 2005 struct perf_header *ph,
1989 int feat, int fd, void *data __used) 2006 int feat, int fd, void *data)
1990{ 2007{
1991 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 2008 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
1992 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 2009 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2002,7 +2019,7 @@ static int perf_file_section__process(struct perf_file_section *section,
2002 if (!feat_ops[feat].process) 2019 if (!feat_ops[feat].process)
2003 return 0; 2020 return 0;
2004 2021
2005 return feat_ops[feat].process(section, ph, feat, fd); 2022 return feat_ops[feat].process(section, ph, feat, fd, data);
2006} 2023}
2007 2024
2008static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 2025static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
@@ -2091,6 +2108,38 @@ static int read_attr(int fd, struct perf_header *ph,
2091 return ret <= 0 ? -1 : 0; 2108 return ret <= 0 ? -1 : 0;
2092} 2109}
2093 2110
2111static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel,
2112 struct pevent *pevent)
2113{
2114 struct event_format *event = pevent_find_event(pevent,
2115 evsel->attr.config);
2116 char bf[128];
2117
2118 if (event == NULL)
2119 return -1;
2120
2121 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
2122 evsel->name = strdup(bf);
2123 if (event->name == NULL)
2124 return -1;
2125
2126 return 0;
2127}
2128
2129static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist,
2130 struct pevent *pevent)
2131{
2132 struct perf_evsel *pos;
2133
2134 list_for_each_entry(pos, &evlist->entries, node) {
2135 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2136 perf_evsel__set_tracepoint_name(pos, pevent))
2137 return -1;
2138 }
2139
2140 return 0;
2141}
2142
2094int perf_session__read_header(struct perf_session *session, int fd) 2143int perf_session__read_header(struct perf_session *session, int fd)
2095{ 2144{
2096 struct perf_header *header = &session->header; 2145 struct perf_header *header = &session->header;
@@ -2167,11 +2216,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); 2216 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
2168 } 2217 }
2169 2218
2170 perf_header__process_sections(header, fd, NULL, 2219 perf_header__process_sections(header, fd, &session->pevent,
2171 perf_file_section__process); 2220 perf_file_section__process);
2172 2221
2173 lseek(fd, header->data_offset, SEEK_SET); 2222 lseek(fd, header->data_offset, SEEK_SET);
2174 2223
2224 if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent))
2225 goto out_delete_evlist;
2226
2175 header->frozen = 1; 2227 header->frozen = 1;
2176 return 0; 2228 return 0;
2177out_errno: 2229out_errno:
@@ -2385,8 +2437,8 @@ int perf_event__process_tracing_data(union perf_event *event,
2385 lseek(session->fd, offset + sizeof(struct tracing_data_event), 2437 lseek(session->fd, offset + sizeof(struct tracing_data_event),
2386 SEEK_SET); 2438 SEEK_SET);
2387 2439
2388 size_read = trace_report(session->fd, session->repipe); 2440 size_read = trace_report(session->fd, &session->pevent,
2389 2441 session->repipe);
2390 padding = ALIGN(size_read, sizeof(u64)) - size_read; 2442 padding = ALIGN(size_read, sizeof(u64)) - size_read;
2391 2443
2392 if (read(session->fd, buf, padding) < 0) 2444 if (read(session->fd, buf, padding) < 0)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 514e2a4b367d..f247ef2789a4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -708,7 +708,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
708 bool printed = false; 708 bool printed = false;
709 struct rb_node *node; 709 struct rb_node *node;
710 int i = 0; 710 int i = 0;
711 int ret; 711 int ret = 0;
712 712
713 /* 713 /*
714 * If have one single callchain root, don't bother printing 714 * If have one single callchain root, don't bother printing
@@ -747,8 +747,11 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
747 root = &cnode->rb_root; 747 root = &cnode->rb_root;
748 } 748 }
749 749
750 return __callchain__fprintf_graph(fp, root, total_samples, 750 ret += __callchain__fprintf_graph(fp, root, total_samples,
751 1, 1, left_margin); 751 1, 1, left_margin);
752 ret += fprintf(fp, "\n");
753
754 return ret;
752} 755}
753 756
754static 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 34bb556d6219..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
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/intlist.c b/tools/perf/util/intlist.c
new file mode 100644
index 000000000000..fd530dced9cb
--- /dev/null
+++ b/tools/perf/util/intlist.c
@@ -0,0 +1,101 @@
1/*
2 * Based on intlist.c by:
3 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
4 *
5 * Licensed under the GPLv2.
6 */
7
8#include <errno.h>
9#include <stdlib.h>
10#include <linux/compiler.h>
11
12#include "intlist.h"
13
14static struct rb_node *intlist__node_new(struct rblist *rblist __used,
15 const void *entry)
16{
17 int i = (int)((long)entry);
18 struct rb_node *rc = NULL;
19 struct int_node *node = malloc(sizeof(*node));
20
21 if (node != NULL) {
22 node->i = i;
23 rc = &node->rb_node;
24 }
25
26 return rc;
27}
28
29static void int_node__delete(struct int_node *ilist)
30{
31 free(ilist);
32}
33
34static void intlist__node_delete(struct rblist *rblist __used,
35 struct rb_node *rb_node)
36{
37 struct int_node *node = container_of(rb_node, struct int_node, rb_node);
38
39 int_node__delete(node);
40}
41
42static int intlist__node_cmp(struct rb_node *rb_node, const void *entry)
43{
44 int i = (int)((long)entry);
45 struct int_node *node = container_of(rb_node, struct int_node, rb_node);
46
47 return node->i - i;
48}
49
50int intlist__add(struct intlist *ilist, int i)
51{
52 return rblist__add_node(&ilist->rblist, (void *)((long)i));
53}
54
55void intlist__remove(struct intlist *ilist __used, struct int_node *node)
56{
57 int_node__delete(node);
58}
59
60struct int_node *intlist__find(struct intlist *ilist, int i)
61{
62 struct int_node *node = NULL;
63 struct rb_node *rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
64
65 if (rb_node)
66 node = container_of(rb_node, struct int_node, rb_node);
67
68 return node;
69}
70
71struct intlist *intlist__new(void)
72{
73 struct intlist *ilist = malloc(sizeof(*ilist));
74
75 if (ilist != NULL) {
76 rblist__init(&ilist->rblist);
77 ilist->rblist.node_cmp = intlist__node_cmp;
78 ilist->rblist.node_new = intlist__node_new;
79 ilist->rblist.node_delete = intlist__node_delete;
80 }
81
82 return ilist;
83}
84
85void intlist__delete(struct intlist *ilist)
86{
87 if (ilist != NULL)
88 rblist__delete(&ilist->rblist);
89}
90
91struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx)
92{
93 struct int_node *node = NULL;
94 struct rb_node *rb_node;
95
96 rb_node = rblist__entry(&ilist->rblist, idx);
97 if (rb_node)
98 node = container_of(rb_node, struct int_node, rb_node);
99
100 return node;
101}
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h
new file mode 100644
index 000000000000..6d63ab90db50
--- /dev/null
+++ b/tools/perf/util/intlist.h
@@ -0,0 +1,75 @@
1#ifndef __PERF_INTLIST_H
2#define __PERF_INTLIST_H
3
4#include <linux/rbtree.h>
5#include <stdbool.h>
6
7#include "rblist.h"
8
9struct int_node {
10 struct rb_node rb_node;
11 int i;
12};
13
14struct intlist {
15 struct rblist rblist;
16};
17
18struct intlist *intlist__new(void);
19void intlist__delete(struct intlist *ilist);
20
21void intlist__remove(struct intlist *ilist, struct int_node *in);
22int intlist__add(struct intlist *ilist, int i);
23
24struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx);
25struct int_node *intlist__find(struct intlist *ilist, int i);
26
27static inline bool intlist__has_entry(struct intlist *ilist, int i)
28{
29 return intlist__find(ilist, i) != NULL;
30}
31
32static inline bool intlist__empty(const struct intlist *ilist)
33{
34 return rblist__empty(&ilist->rblist);
35}
36
37static inline unsigned int intlist__nr_entries(const struct intlist *ilist)
38{
39 return rblist__nr_entries(&ilist->rblist);
40}
41
42/* For intlist iteration */
43static inline struct int_node *intlist__first(struct intlist *ilist)
44{
45 struct rb_node *rn = rb_first(&ilist->rblist.entries);
46 return rn ? rb_entry(rn, struct int_node, rb_node) : NULL;
47}
48static inline struct int_node *intlist__next(struct int_node *in)
49{
50 struct rb_node *rn;
51 if (!in)
52 return NULL;
53 rn = rb_next(&in->rb_node);
54 return rn ? rb_entry(rn, struct int_node, rb_node) : NULL;
55}
56
57/**
58 * intlist_for_each - iterate over a intlist
59 * @pos: the &struct int_node to use as a loop cursor.
60 * @ilist: the &struct intlist for loop.
61 */
62#define intlist__for_each(pos, ilist) \
63 for (pos = intlist__first(ilist); pos; pos = intlist__next(pos))
64
65/**
66 * intlist_for_each_safe - iterate over a intlist safe against removal of
67 * int_node
68 * @pos: the &struct int_node to use as a loop cursor.
69 * @n: another &struct int_node to use as temporary storage.
70 * @ilist: the &struct intlist for loop.
71 */
72#define intlist__for_each_safe(pos, n, ilist) \
73 for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\
74 pos = n, n = intlist__next(n))
75#endif /* __PERF_INTLIST_H */
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/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 76b98e2a587d..127d648cc548 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -13,6 +13,9 @@ do { \
13 } \ 13 } \
14} while (0) 14} while (0)
15 15
16#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
17 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
18
16static int test__checkevent_tracepoint(struct perf_evlist *evlist) 19static int test__checkevent_tracepoint(struct perf_evlist *evlist)
17{ 20{
18 struct perf_evsel *evsel = list_entry(evlist->entries.next, 21 struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -21,8 +24,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist)
21 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 24 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
22 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); 25 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
23 TEST_ASSERT_VAL("wrong sample_type", 26 TEST_ASSERT_VAL("wrong sample_type",
24 (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == 27 PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
25 evsel->attr.sample_type);
26 TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); 28 TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
27 return 0; 29 return 0;
28} 30}
@@ -37,8 +39,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
37 TEST_ASSERT_VAL("wrong type", 39 TEST_ASSERT_VAL("wrong type",
38 PERF_TYPE_TRACEPOINT == evsel->attr.type); 40 PERF_TYPE_TRACEPOINT == evsel->attr.type);
39 TEST_ASSERT_VAL("wrong sample_type", 41 TEST_ASSERT_VAL("wrong sample_type",
40 (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) 42 PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
41 == evsel->attr.sample_type);
42 TEST_ASSERT_VAL("wrong sample_period", 43 TEST_ASSERT_VAL("wrong sample_period",
43 1 == evsel->attr.sample_period); 44 1 == evsel->attr.sample_period);
44 } 45 }
@@ -181,6 +182,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
181 return 0; 182 return 0;
182} 183}
183 184
185static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
186{
187 struct perf_evsel *evsel = list_entry(evlist->entries.next,
188 struct perf_evsel, node);
189
190 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
191 TEST_ASSERT_VAL("wrong type",
192 PERF_TYPE_BREAKPOINT == evsel->attr.type);
193 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
194 TEST_ASSERT_VAL("wrong bp_type",
195 (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
196 TEST_ASSERT_VAL("wrong bp_len",
197 HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
198 return 0;
199}
200
184static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) 201static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
185{ 202{
186 struct perf_evsel *evsel = list_entry(evlist->entries.next, 203 struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -309,6 +326,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
309 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 326 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
310 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 327 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
311 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 328 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
329 TEST_ASSERT_VAL("wrong name",
330 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
312 331
313 return test__checkevent_breakpoint(evlist); 332 return test__checkevent_breakpoint(evlist);
314} 333}
@@ -322,6 +341,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
322 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 341 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
323 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 342 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
324 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 343 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
344 TEST_ASSERT_VAL("wrong name",
345 !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
325 346
326 return test__checkevent_breakpoint_x(evlist); 347 return test__checkevent_breakpoint_x(evlist);
327} 348}
@@ -335,6 +356,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
335 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 356 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
336 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); 357 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
337 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 358 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
359 TEST_ASSERT_VAL("wrong name",
360 !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
338 361
339 return test__checkevent_breakpoint_r(evlist); 362 return test__checkevent_breakpoint_r(evlist);
340} 363}
@@ -348,10 +371,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
348 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 371 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
349 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 372 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
350 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 373 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
374 TEST_ASSERT_VAL("wrong name",
375 !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
351 376
352 return test__checkevent_breakpoint_w(evlist); 377 return test__checkevent_breakpoint_w(evlist);
353} 378}
354 379
380static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
381{
382 struct perf_evsel *evsel = list_entry(evlist->entries.next,
383 struct perf_evsel, node);
384
385 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
386 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
387 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
388 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
389 TEST_ASSERT_VAL("wrong name",
390 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
391
392 return test__checkevent_breakpoint_rw(evlist);
393}
394
355static int test__checkevent_pmu(struct perf_evlist *evlist) 395static int test__checkevent_pmu(struct perf_evlist *evlist)
356{ 396{
357 397
@@ -389,8 +429,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)
389 evsel = list_entry(evsel->node.next, struct perf_evsel, node); 429 evsel = list_entry(evsel->node.next, struct perf_evsel, node);
390 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); 430 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
391 TEST_ASSERT_VAL("wrong sample_type", 431 TEST_ASSERT_VAL("wrong sample_type",
392 (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == 432 PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
393 evsel->attr.sample_type);
394 TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); 433 TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
395 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 434 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
396 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 435 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -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};
561 653
562static int test(struct test__event_st *e) 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))
663
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/parse-options.c b/tools/perf/util/parse-options.c
index 99d02aa57dbf..594f8fad5ecd 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -1,6 +1,7 @@
1#include "util.h" 1#include "util.h"
2#include "parse-options.h" 2#include "parse-options.h"
3#include "cache.h" 3#include "cache.h"
4#include "header.h"
4 5
5#define OPT_SHORT 1 6#define OPT_SHORT 1
6#define OPT_UNSET 2 7#define OPT_UNSET 2
@@ -413,6 +414,8 @@ int parse_options(int argc, const char **argv, const struct option *options,
413{ 414{
414 struct parse_opt_ctx_t ctx; 415 struct parse_opt_ctx_t ctx;
415 416
417 perf_header__set_cmdline(argc, argv);
418
416 parse_options_start(&ctx, argc, argv, flags); 419 parse_options_start(&ctx, argc, argv, flags);
417 switch (parse_options_step(&ctx, options, usagestr)) { 420 switch (parse_options_step(&ctx, options, usagestr)) {
418 case PARSE_OPT_HELP: 421 case PARSE_OPT_HELP:
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/python-ext-sources b/tools/perf/util/python-ext-sources
index 2884e67ee625..213362850abd 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,10 +10,12 @@ util/ctype.c
10util/evlist.c 10util/evlist.c
11util/evsel.c 11util/evsel.c
12util/cpumap.c 12util/cpumap.c
13util/hweight.c
13util/thread_map.c 14util/thread_map.c
14util/util.c 15util/util.c
15util/xyarray.c 16util/xyarray.c
16util/cgroup.c 17util/cgroup.c
17util/debugfs.c 18util/debugfs.c
19util/rblist.c
18util/strlist.c 20util/strlist.c
19../../lib/rbtree.c 21../../lib/rbtree.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index e03b58a48424..0688bfb6d280 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -797,17 +797,13 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
797 797
798 event = perf_evlist__mmap_read(evlist, cpu); 798 event = perf_evlist__mmap_read(evlist, cpu);
799 if (event != NULL) { 799 if (event != NULL) {
800 struct perf_evsel *first;
801 PyObject *pyevent = pyrf_event__new(event); 800 PyObject *pyevent = pyrf_event__new(event);
802 struct pyrf_event *pevent = (struct pyrf_event *)pyevent; 801 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
803 802
804 if (pyevent == NULL) 803 if (pyevent == NULL)
805 return PyErr_NoMemory(); 804 return PyErr_NoMemory();
806 805
807 first = list_entry(evlist->entries.next, struct perf_evsel, node); 806 err = perf_evlist__parse_sample(evlist, event, &pevent->sample, false);
808 err = perf_event__parse_sample(event, first->attr.sample_type,
809 perf_evsel__sample_size(first),
810 sample_id_all, &pevent->sample, false);
811 if (err) 807 if (err)
812 return PyErr_Format(PyExc_OSError, 808 return PyErr_Format(PyExc_OSError,
813 "perf: can't parse sample, err=%d", err); 809 "perf: can't parse sample, err=%d", err);
diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c
new file mode 100644
index 000000000000..0171fb611004
--- /dev/null
+++ b/tools/perf/util/rblist.c
@@ -0,0 +1,107 @@
1/*
2 * Based on strlist.c by:
3 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
4 *
5 * Licensed under the GPLv2.
6 */
7
8#include <errno.h>
9#include <stdio.h>
10#include <stdlib.h>
11
12#include "rblist.h"
13
14int rblist__add_node(struct rblist *rblist, const void *new_entry)
15{
16 struct rb_node **p = &rblist->entries.rb_node;
17 struct rb_node *parent = NULL, *new_node;
18
19 while (*p != NULL) {
20 int rc;
21
22 parent = *p;
23
24 rc = rblist->node_cmp(parent, new_entry);
25 if (rc > 0)
26 p = &(*p)->rb_left;
27 else if (rc < 0)
28 p = &(*p)->rb_right;
29 else
30 return -EEXIST;
31 }
32
33 new_node = rblist->node_new(rblist, new_entry);
34 if (new_node == NULL)
35 return -ENOMEM;
36
37 rb_link_node(new_node, parent, p);
38 rb_insert_color(new_node, &rblist->entries);
39 ++rblist->nr_entries;
40
41 return 0;
42}
43
44void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node)
45{
46 rb_erase(rb_node, &rblist->entries);
47 rblist->node_delete(rblist, rb_node);
48}
49
50struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
51{
52 struct rb_node **p = &rblist->entries.rb_node;
53 struct rb_node *parent = NULL;
54
55 while (*p != NULL) {
56 int rc;
57
58 parent = *p;
59
60 rc = rblist->node_cmp(parent, entry);
61 if (rc > 0)
62 p = &(*p)->rb_left;
63 else if (rc < 0)
64 p = &(*p)->rb_right;
65 else
66 return parent;
67 }
68
69 return NULL;
70}
71
72void rblist__init(struct rblist *rblist)
73{
74 if (rblist != NULL) {
75 rblist->entries = RB_ROOT;
76 rblist->nr_entries = 0;
77 }
78
79 return;
80}
81
82void rblist__delete(struct rblist *rblist)
83{
84 if (rblist != NULL) {
85 struct rb_node *pos, *next = rb_first(&rblist->entries);
86
87 while (next) {
88 pos = next;
89 next = rb_next(pos);
90 rb_erase(pos, &rblist->entries);
91 rblist->node_delete(rblist, pos);
92 }
93 free(rblist);
94 }
95}
96
97struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx)
98{
99 struct rb_node *node;
100
101 for (node = rb_first(&rblist->entries); node; node = rb_next(node)) {
102 if (!idx--)
103 return node;
104 }
105
106 return NULL;
107}
diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h
new file mode 100644
index 000000000000..6d0cae5ae83d
--- /dev/null
+++ b/tools/perf/util/rblist.h
@@ -0,0 +1,47 @@
1#ifndef __PERF_RBLIST_H
2#define __PERF_RBLIST_H
3
4#include <linux/rbtree.h>
5#include <stdbool.h>
6
7/*
8 * create node structs of the form:
9 * struct my_node {
10 * struct rb_node rb_node;
11 * ... my data ...
12 * };
13 *
14 * create list structs of the form:
15 * struct mylist {
16 * struct rblist rblist;
17 * ... my data ...
18 * };
19 */
20
21struct rblist {
22 struct rb_root entries;
23 unsigned int nr_entries;
24
25 int (*node_cmp)(struct rb_node *rbn, const void *entry);
26 struct rb_node *(*node_new)(struct rblist *rlist, const void *new_entry);
27 void (*node_delete)(struct rblist *rblist, struct rb_node *rb_node);
28};
29
30void rblist__init(struct rblist *rblist);
31void rblist__delete(struct rblist *rblist);
32int rblist__add_node(struct rblist *rblist, const void *new_entry);
33void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node);
34struct rb_node *rblist__find(struct rblist *rblist, const void *entry);
35struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx);
36
37static inline bool rblist__empty(const struct rblist *rblist)
38{
39 return rblist->nr_entries == 0;
40}
41
42static inline unsigned int rblist__nr_entries(const struct rblist *rblist)
43{
44 return rblist->nr_entries;
45}
46
47#endif /* __PERF_RBLIST_H */
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 2600916efa83..2437fb0b463a 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{
@@ -79,13 +80,12 @@ out_close:
79 return -1; 80 return -1;
80} 81}
81 82
82void perf_session__update_sample_type(struct perf_session *self) 83void perf_session__set_id_hdr_size(struct perf_session *session)
83{ 84{
84 self->sample_type = perf_evlist__sample_type(self->evlist); 85 u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist);
85 self->sample_size = __perf_evsel__sample_size(self->sample_type); 86
86 self->sample_id_all = perf_evlist__sample_id_all(self->evlist); 87 session->host_machine.id_hdr_size = id_hdr_size;
87 self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); 88 machines__set_id_hdr_size(&session->machines, id_hdr_size);
88 self->host_machine.id_hdr_size = self->id_hdr_size;
89} 89}
90 90
91int perf_session__create_kernel_maps(struct perf_session *self) 91int perf_session__create_kernel_maps(struct perf_session *self)
@@ -145,7 +145,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
145 if (mode == O_RDONLY) { 145 if (mode == O_RDONLY) {
146 if (perf_session__open(self, force) < 0) 146 if (perf_session__open(self, force) < 0)
147 goto out_delete; 147 goto out_delete;
148 perf_session__update_sample_type(self); 148 perf_session__set_id_hdr_size(self);
149 } else if (mode == O_WRONLY) { 149 } else if (mode == O_WRONLY) {
150 /* 150 /*
151 * In O_RDONLY mode this will be performed when reading the 151 * In O_RDONLY mode this will be performed when reading the
@@ -156,7 +156,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
156 } 156 }
157 157
158 if (tool && tool->ordering_requires_timestamps && 158 if (tool && tool->ordering_requires_timestamps &&
159 tool->ordered_samples && !self->sample_id_all) { 159 tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) {
160 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 160 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
161 tool->ordered_samples = false; 161 tool->ordered_samples = false;
162 } 162 }
@@ -289,7 +289,6 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
289} 289}
290 290
291int machine__resolve_callchain(struct machine *self, 291int machine__resolve_callchain(struct machine *self,
292 struct perf_evsel *evsel __used,
293 struct thread *thread, 292 struct thread *thread,
294 struct ip_callchain *chain, 293 struct ip_callchain *chain,
295 struct symbol **parent) 294 struct symbol **parent)
@@ -442,6 +441,16 @@ static void perf_tool__fill_defaults(struct perf_tool *tool)
442 tool->finished_round = process_finished_round_stub; 441 tool->finished_round = process_finished_round_stub;
443 } 442 }
444} 443}
444
445void mem_bswap_32(void *src, int byte_size)
446{
447 u32 *m = src;
448 while (byte_size > 0) {
449 *m = bswap_32(*m);
450 byte_size -= sizeof(u32);
451 ++m;
452 }
453}
445 454
446void mem_bswap_64(void *src, int byte_size) 455void mem_bswap_64(void *src, int byte_size)
447{ 456{
@@ -662,7 +671,8 @@ static void flush_sample_queue(struct perf_session *s,
662 if (iter->timestamp > limit) 671 if (iter->timestamp > limit)
663 break; 672 break;
664 673
665 ret = perf_session__parse_sample(s, iter->event, &sample); 674 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample,
675 s->header.needs_swap);
666 if (ret) 676 if (ret)
667 pr_err("Can't parse sample, err = %d\n", ret); 677 pr_err("Can't parse sample, err = %d\n", ret);
668 else 678 else
@@ -854,16 +864,18 @@ static void perf_session__print_tstamp(struct perf_session *session,
854 union perf_event *event, 864 union perf_event *event,
855 struct perf_sample *sample) 865 struct perf_sample *sample)
856{ 866{
867 u64 sample_type = perf_evlist__sample_type(session->evlist);
868
857 if (event->header.type != PERF_RECORD_SAMPLE && 869 if (event->header.type != PERF_RECORD_SAMPLE &&
858 !session->sample_id_all) { 870 !perf_evlist__sample_id_all(session->evlist)) {
859 fputs("-1 -1 ", stdout); 871 fputs("-1 -1 ", stdout);
860 return; 872 return;
861 } 873 }
862 874
863 if ((session->sample_type & PERF_SAMPLE_CPU)) 875 if ((sample_type & PERF_SAMPLE_CPU))
864 printf("%u ", sample->cpu); 876 printf("%u ", sample->cpu);
865 877
866 if (session->sample_type & PERF_SAMPLE_TIME) 878 if (sample_type & PERF_SAMPLE_TIME)
867 printf("%" PRIu64 " ", sample->time); 879 printf("%" PRIu64 " ", sample->time);
868} 880}
869 881
@@ -888,6 +900,8 @@ static void dump_event(struct perf_session *session, union perf_event *event,
888static void dump_sample(struct perf_session *session, union perf_event *event, 900static void dump_sample(struct perf_session *session, union perf_event *event,
889 struct perf_sample *sample) 901 struct perf_sample *sample)
890{ 902{
903 u64 sample_type;
904
891 if (!dump_trace) 905 if (!dump_trace)
892 return; 906 return;
893 907
@@ -895,10 +909,12 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
895 event->header.misc, sample->pid, sample->tid, sample->ip, 909 event->header.misc, sample->pid, sample->tid, sample->ip,
896 sample->period, sample->addr); 910 sample->period, sample->addr);
897 911
898 if (session->sample_type & PERF_SAMPLE_CALLCHAIN) 912 sample_type = perf_evlist__sample_type(session->evlist);
913
914 if (sample_type & PERF_SAMPLE_CALLCHAIN)
899 callchain__printf(sample); 915 callchain__printf(sample);
900 916
901 if (session->sample_type & PERF_SAMPLE_BRANCH_STACK) 917 if (sample_type & PERF_SAMPLE_BRANCH_STACK)
902 branch_stack__printf(sample); 918 branch_stack__printf(sample);
903} 919}
904 920
@@ -908,7 +924,9 @@ static struct machine *
908{ 924{
909 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 925 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
910 926
911 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 927 if (perf_guest &&
928 ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
929 (cpumode == PERF_RECORD_MISC_GUEST_USER))) {
912 u32 pid; 930 u32 pid;
913 931
914 if (event->header.type == PERF_RECORD_MMAP) 932 if (event->header.type == PERF_RECORD_MMAP)
@@ -916,7 +934,7 @@ static struct machine *
916 else 934 else
917 pid = event->ip.pid; 935 pid = event->ip.pid;
918 936
919 return perf_session__find_machine(session, pid); 937 return perf_session__findnew_machine(session, pid);
920 } 938 }
921 939
922 return perf_session__find_host_machine(session); 940 return perf_session__find_host_machine(session);
@@ -993,7 +1011,7 @@ static int perf_session__preprocess_sample(struct perf_session *session,
993 union perf_event *event, struct perf_sample *sample) 1011 union perf_event *event, struct perf_sample *sample)
994{ 1012{
995 if (event->header.type != PERF_RECORD_SAMPLE || 1013 if (event->header.type != PERF_RECORD_SAMPLE ||
996 !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) 1014 !(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_CALLCHAIN))
997 return 0; 1015 return 0;
998 1016
999 if (!ip_callchain__valid(sample->callchain, event)) { 1017 if (!ip_callchain__valid(sample->callchain, event)) {
@@ -1017,7 +1035,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
1017 case PERF_RECORD_HEADER_ATTR: 1035 case PERF_RECORD_HEADER_ATTR:
1018 err = tool->attr(event, &session->evlist); 1036 err = tool->attr(event, &session->evlist);
1019 if (err == 0) 1037 if (err == 0)
1020 perf_session__update_sample_type(session); 1038 perf_session__set_id_hdr_size(session);
1021 return err; 1039 return err;
1022 case PERF_RECORD_HEADER_EVENT_TYPE: 1040 case PERF_RECORD_HEADER_EVENT_TYPE:
1023 return tool->event_type(tool, event); 1041 return tool->event_type(tool, event);
@@ -1052,7 +1070,7 @@ static int perf_session__process_event(struct perf_session *session,
1052 int ret; 1070 int ret;
1053 1071
1054 if (session->header.needs_swap) 1072 if (session->header.needs_swap)
1055 event_swap(event, session->sample_id_all); 1073 event_swap(event, perf_evlist__sample_id_all(session->evlist));
1056 1074
1057 if (event->header.type >= PERF_RECORD_HEADER_MAX) 1075 if (event->header.type >= PERF_RECORD_HEADER_MAX)
1058 return -EINVAL; 1076 return -EINVAL;
@@ -1065,7 +1083,8 @@ static int perf_session__process_event(struct perf_session *session,
1065 /* 1083 /*
1066 * For all kernel events we get the sample data 1084 * For all kernel events we get the sample data
1067 */ 1085 */
1068 ret = perf_session__parse_sample(session, event, &sample); 1086 ret = perf_evlist__parse_sample(session->evlist, event, &sample,
1087 session->header.needs_swap);
1069 if (ret) 1088 if (ret)
1070 return ret; 1089 return ret;
1071 1090
@@ -1376,9 +1395,9 @@ int perf_session__process_events(struct perf_session *self,
1376 return err; 1395 return err;
1377} 1396}
1378 1397
1379bool perf_session__has_traces(struct perf_session *self, const char *msg) 1398bool perf_session__has_traces(struct perf_session *session, const char *msg)
1380{ 1399{
1381 if (!(self->sample_type & PERF_SAMPLE_RAW)) { 1400 if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) {
1382 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); 1401 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
1383 return false; 1402 return false;
1384 } 1403 }
@@ -1439,7 +1458,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1439 ret += hists__fprintf_nr_events(&session->hists, fp); 1458 ret += hists__fprintf_nr_events(&session->hists, fp);
1440 1459
1441 list_for_each_entry(pos, &session->evlist->entries, node) { 1460 list_for_each_entry(pos, &session->evlist->entries, node) {
1442 ret += fprintf(fp, "%s stats:\n", event_name(pos)); 1461 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1443 ret += hists__fprintf_nr_events(&pos->hists, fp); 1462 ret += hists__fprintf_nr_events(&pos->hists, fp);
1444 } 1463 }
1445 1464
@@ -1480,8 +1499,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1480} 1499}
1481 1500
1482void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 1501void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1483 struct machine *machine, struct perf_evsel *evsel, 1502 struct machine *machine, int print_sym,
1484 int print_sym, int print_dso, int print_symoffset) 1503 int print_dso, int print_symoffset)
1485{ 1504{
1486 struct addr_location al; 1505 struct addr_location al;
1487 struct callchain_cursor_node *node; 1506 struct callchain_cursor_node *node;
@@ -1495,7 +1514,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1495 1514
1496 if (symbol_conf.use_callchain && sample->callchain) { 1515 if (symbol_conf.use_callchain && sample->callchain) {
1497 1516
1498 if (machine__resolve_callchain(machine, evsel, al.thread, 1517 if (machine__resolve_callchain(machine, al.thread,
1499 sample->callchain, NULL) != 0) { 1518 sample->callchain, NULL) != 0) {
1500 if (verbose) 1519 if (verbose)
1501 error("Failed to resolve callchain. Skipping\n"); 1520 error("Failed to resolve callchain. Skipping\n");
@@ -1601,3 +1620,58 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
1601 perf_header__fprintf_info(session, fp, full); 1620 perf_header__fprintf_info(session, fp, full);
1602 fprintf(fp, "# ========\n#\n"); 1621 fprintf(fp, "# ========\n#\n");
1603} 1622}
1623
1624
1625int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1626 const struct perf_evsel_str_handler *assocs,
1627 size_t nr_assocs)
1628{
1629 struct perf_evlist *evlist = session->evlist;
1630 struct event_format *format;
1631 struct perf_evsel *evsel;
1632 char *tracepoint, *name;
1633 size_t i;
1634 int err;
1635
1636 for (i = 0; i < nr_assocs; i++) {
1637 err = -ENOMEM;
1638 tracepoint = strdup(assocs[i].name);
1639 if (tracepoint == NULL)
1640 goto out;
1641
1642 err = -ENOENT;
1643 name = strchr(tracepoint, ':');
1644 if (name == NULL)
1645 goto out_free;
1646
1647 *name++ = '\0';
1648 format = pevent_find_event_by_name(session->pevent,
1649 tracepoint, name);
1650 if (format == NULL) {
1651 /*
1652 * Adding a handler for an event not in the session,
1653 * just ignore it.
1654 */
1655 goto next;
1656 }
1657
1658 evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id);
1659 if (evsel == NULL)
1660 goto next;
1661
1662 err = -EEXIST;
1663 if (evsel->handler.func != NULL)
1664 goto out_free;
1665 evsel->handler.func = assocs[i].handler;
1666next:
1667 free(tracepoint);
1668 }
1669
1670 err = 0;
1671out:
1672 return err;
1673
1674out_free:
1675 free(tracepoint);
1676 goto out;
1677}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 7a5434c00565..1f7ec87db7d7 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
@@ -40,13 +41,9 @@ struct perf_session {
40 * perf.data file. 41 * perf.data file.
41 */ 42 */
42 struct hists hists; 43 struct hists hists;
43 u64 sample_type;
44 int sample_size;
45 int fd; 44 int fd;
46 bool fd_pipe; 45 bool fd_pipe;
47 bool repipe; 46 bool repipe;
48 bool sample_id_all;
49 u16 id_hdr_size;
50 int cwdlen; 47 int cwdlen;
51 char *cwd; 48 char *cwd;
52 struct ordered_samples ordered_samples; 49 struct ordered_samples ordered_samples;
@@ -80,11 +77,12 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
80bool perf_session__has_traces(struct perf_session *self, const char *msg); 77bool perf_session__has_traces(struct perf_session *self, const char *msg);
81 78
82void mem_bswap_64(void *src, int byte_size); 79void mem_bswap_64(void *src, int byte_size);
80void mem_bswap_32(void *src, int byte_size);
83void perf_event__attr_swap(struct perf_event_attr *attr); 81void perf_event__attr_swap(struct perf_event_attr *attr);
84 82
85int perf_session__create_kernel_maps(struct perf_session *self); 83int perf_session__create_kernel_maps(struct perf_session *self);
86 84
87void perf_session__update_sample_type(struct perf_session *self); 85void perf_session__set_id_hdr_size(struct perf_session *session);
88void perf_session__remove_thread(struct perf_session *self, struct thread *th); 86void perf_session__remove_thread(struct perf_session *self, struct thread *th);
89 87
90static inline 88static inline
@@ -128,33 +126,24 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
128 126
129size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); 127size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
130 128
131static inline int perf_session__parse_sample(struct perf_session *session,
132 const union perf_event *event,
133 struct perf_sample *sample)
134{
135 return perf_event__parse_sample(event, session->sample_type,
136 session->sample_size,
137 session->sample_id_all, sample,
138 session->header.needs_swap);
139}
140
141static inline int perf_session__synthesize_sample(struct perf_session *session,
142 union perf_event *event,
143 const struct perf_sample *sample)
144{
145 return perf_event__synthesize_sample(event, session->sample_type,
146 sample, session->header.needs_swap);
147}
148
149struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 129struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
150 unsigned int type); 130 unsigned int type);
151 131
152void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 132void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
153 struct machine *machine, struct perf_evsel *evsel, 133 struct machine *machine, int print_sym,
154 int print_sym, int print_dso, int print_symoffset); 134 int print_dso, int print_symoffset);
155 135
156int perf_session__cpu_bitmap(struct perf_session *session, 136int perf_session__cpu_bitmap(struct perf_session *session,
157 const char *cpu_list, unsigned long *cpu_bitmap); 137 const char *cpu_list, unsigned long *cpu_bitmap);
158 138
159void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full); 139void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full);
140
141struct perf_evsel_str_handler;
142
143int __perf_session__set_tracepoints_handlers(struct perf_session *session,
144 const struct perf_evsel_str_handler *assocs,
145 size_t nr_assocs);
146
147#define perf_session__set_tracepoints_handlers(session, array) \
148 __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array))
160#endif /* __PERF_SESSION_H */ 149#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/strlist.c b/tools/perf/util/strlist.c
index 6783a2043555..95856ff3dda4 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -10,23 +10,28 @@
10#include <stdlib.h> 10#include <stdlib.h>
11#include <string.h> 11#include <string.h>
12 12
13static struct str_node *str_node__new(const char *s, bool dupstr) 13static
14struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry)
14{ 15{
15 struct str_node *self = malloc(sizeof(*self)); 16 const char *s = entry;
17 struct rb_node *rc = NULL;
18 struct strlist *strlist = container_of(rblist, struct strlist, rblist);
19 struct str_node *snode = malloc(sizeof(*snode));
16 20
17 if (self != NULL) { 21 if (snode != NULL) {
18 if (dupstr) { 22 if (strlist->dupstr) {
19 s = strdup(s); 23 s = strdup(s);
20 if (s == NULL) 24 if (s == NULL)
21 goto out_delete; 25 goto out_delete;
22 } 26 }
23 self->s = s; 27 snode->s = s;
28 rc = &snode->rb_node;
24 } 29 }
25 30
26 return self; 31 return rc;
27 32
28out_delete: 33out_delete:
29 free(self); 34 free(snode);
30 return NULL; 35 return NULL;
31} 36}
32 37
@@ -37,36 +42,26 @@ static void str_node__delete(struct str_node *self, bool dupstr)
37 free(self); 42 free(self);
38} 43}
39 44
40int strlist__add(struct strlist *self, const char *new_entry) 45static
46void strlist__node_delete(struct rblist *rblist, struct rb_node *rb_node)
41{ 47{
42 struct rb_node **p = &self->entries.rb_node; 48 struct strlist *slist = container_of(rblist, struct strlist, rblist);
43 struct rb_node *parent = NULL; 49 struct str_node *snode = container_of(rb_node, struct str_node, rb_node);
44 struct str_node *sn;
45
46 while (*p != NULL) {
47 int rc;
48
49 parent = *p;
50 sn = rb_entry(parent, struct str_node, rb_node);
51 rc = strcmp(sn->s, new_entry);
52
53 if (rc > 0)
54 p = &(*p)->rb_left;
55 else if (rc < 0)
56 p = &(*p)->rb_right;
57 else
58 return -EEXIST;
59 }
60 50
61 sn = str_node__new(new_entry, self->dupstr); 51 str_node__delete(snode, slist->dupstr);
62 if (sn == NULL) 52}
63 return -ENOMEM;
64 53
65 rb_link_node(&sn->rb_node, parent, p); 54static int strlist__node_cmp(struct rb_node *rb_node, const void *entry)
66 rb_insert_color(&sn->rb_node, &self->entries); 55{
67 ++self->nr_entries; 56 const char *str = entry;
57 struct str_node *snode = container_of(rb_node, struct str_node, rb_node);
58
59 return strcmp(snode->s, str);
60}
68 61
69 return 0; 62int strlist__add(struct strlist *self, const char *new_entry)
63{
64 return rblist__add_node(&self->rblist, new_entry);
70} 65}
71 66
72int strlist__load(struct strlist *self, const char *filename) 67int strlist__load(struct strlist *self, const char *filename)
@@ -96,34 +91,20 @@ out:
96 return err; 91 return err;
97} 92}
98 93
99void strlist__remove(struct strlist *self, struct str_node *sn) 94void strlist__remove(struct strlist *slist, struct str_node *snode)
100{ 95{
101 rb_erase(&sn->rb_node, &self->entries); 96 str_node__delete(snode, slist->dupstr);
102 str_node__delete(sn, self->dupstr);
103} 97}
104 98
105struct str_node *strlist__find(struct strlist *self, const char *entry) 99struct str_node *strlist__find(struct strlist *slist, const char *entry)
106{ 100{
107 struct rb_node **p = &self->entries.rb_node; 101 struct str_node *snode = NULL;
108 struct rb_node *parent = NULL; 102 struct rb_node *rb_node = rblist__find(&slist->rblist, entry);
109
110 while (*p != NULL) {
111 struct str_node *sn;
112 int rc;
113
114 parent = *p;
115 sn = rb_entry(parent, struct str_node, rb_node);
116 rc = strcmp(sn->s, entry);
117
118 if (rc > 0)
119 p = &(*p)->rb_left;
120 else if (rc < 0)
121 p = &(*p)->rb_right;
122 else
123 return sn;
124 }
125 103
126 return NULL; 104 if (rb_node)
105 snode = container_of(rb_node, struct str_node, rb_node);
106
107 return snode;
127} 108}
128 109
129static int strlist__parse_list_entry(struct strlist *self, const char *s) 110static int strlist__parse_list_entry(struct strlist *self, const char *s)
@@ -156,9 +137,12 @@ struct strlist *strlist__new(bool dupstr, const char *slist)
156 struct strlist *self = malloc(sizeof(*self)); 137 struct strlist *self = malloc(sizeof(*self));
157 138
158 if (self != NULL) { 139 if (self != NULL) {
159 self->entries = RB_ROOT; 140 rblist__init(&self->rblist);
141 self->rblist.node_cmp = strlist__node_cmp;
142 self->rblist.node_new = strlist__node_new;
143 self->rblist.node_delete = strlist__node_delete;
144
160 self->dupstr = dupstr; 145 self->dupstr = dupstr;
161 self->nr_entries = 0;
162 if (slist && strlist__parse_list(self, slist) != 0) 146 if (slist && strlist__parse_list(self, slist) != 0)
163 goto out_error; 147 goto out_error;
164 } 148 }
@@ -171,30 +155,18 @@ out_error:
171 155
172void strlist__delete(struct strlist *self) 156void strlist__delete(struct strlist *self)
173{ 157{
174 if (self != NULL) { 158 if (self != NULL)
175 struct str_node *pos; 159 rblist__delete(&self->rblist);
176 struct rb_node *next = rb_first(&self->entries);
177
178 while (next) {
179 pos = rb_entry(next, struct str_node, rb_node);
180 next = rb_next(&pos->rb_node);
181 strlist__remove(self, pos);
182 }
183 self->entries = RB_ROOT;
184 free(self);
185 }
186} 160}
187 161
188struct str_node *strlist__entry(const struct strlist *self, unsigned int idx) 162struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx)
189{ 163{
190 struct rb_node *nd; 164 struct str_node *snode = NULL;
165 struct rb_node *rb_node;
191 166
192 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { 167 rb_node = rblist__entry(&slist->rblist, idx);
193 struct str_node *pos = rb_entry(nd, struct str_node, rb_node); 168 if (rb_node)
169 snode = container_of(rb_node, struct str_node, rb_node);
194 170
195 if (!idx--) 171 return snode;
196 return pos;
197 }
198
199 return NULL;
200} 172}
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 3ba839007d2c..dd9f922ec67c 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -4,14 +4,15 @@
4#include <linux/rbtree.h> 4#include <linux/rbtree.h>
5#include <stdbool.h> 5#include <stdbool.h>
6 6
7#include "rblist.h"
8
7struct str_node { 9struct str_node {
8 struct rb_node rb_node; 10 struct rb_node rb_node;
9 const char *s; 11 const char *s;
10}; 12};
11 13
12struct strlist { 14struct strlist {
13 struct rb_root entries; 15 struct rblist rblist;
14 unsigned int nr_entries;
15 bool dupstr; 16 bool dupstr;
16}; 17};
17 18
@@ -32,18 +33,18 @@ static inline bool strlist__has_entry(struct strlist *self, const char *entry)
32 33
33static inline bool strlist__empty(const struct strlist *self) 34static inline bool strlist__empty(const struct strlist *self)
34{ 35{
35 return self->nr_entries == 0; 36 return rblist__empty(&self->rblist);
36} 37}
37 38
38static inline unsigned int strlist__nr_entries(const struct strlist *self) 39static inline unsigned int strlist__nr_entries(const struct strlist *self)
39{ 40{
40 return self->nr_entries; 41 return rblist__nr_entries(&self->rblist);
41} 42}
42 43
43/* For strlist iteration */ 44/* For strlist iteration */
44static inline struct str_node *strlist__first(struct strlist *self) 45static inline struct str_node *strlist__first(struct strlist *self)
45{ 46{
46 struct rb_node *rn = rb_first(&self->entries); 47 struct rb_node *rn = rb_first(&self->rblist.entries);
47 return rn ? rb_entry(rn, struct str_node, rb_node) : NULL; 48 return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;
48} 49}
49static inline struct str_node *strlist__next(struct str_node *sn) 50static inline struct str_node *strlist__next(struct str_node *sn)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 3e2e5ea0f03f..8b63b678e127 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 ARRAY_SIZE(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 ARRAY_SIZE(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,7 +344,9 @@ 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;
@@ -352,6 +380,7 @@ void dso__delete(struct dso *dso)
352 free((char *)dso->short_name); 380 free((char *)dso->short_name);
353 if (dso->lname_alloc) 381 if (dso->lname_alloc)
354 free(dso->long_name); 382 free(dso->long_name);
383 dso_cache__free(&dso->cache);
355 free(dso); 384 free(dso);
356} 385}
357 386
@@ -806,9 +835,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
806 symbols__fixup_end(&dso->symbols[map->type]); 835 symbols__fixup_end(&dso->symbols[map->type]);
807 836
808 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 837 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
809 dso->symtab_type = SYMTAB__GUEST_KALLSYMS; 838 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
810 else 839 else
811 dso->symtab_type = SYMTAB__KALLSYMS; 840 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
812 841
813 return dso__split_kallsyms(dso, map, filter); 842 return dso__split_kallsyms(dso, map, filter);
814} 843}
@@ -1478,14 +1507,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1478 goto out; 1507 goto out;
1479 } 1508 }
1480 1509
1481 sec = elf_section_by_name(elf, &ehdr, &shdr, 1510 /*
1482 ".note.gnu.build-id", NULL); 1511 * Check following sections for notes:
1483 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
1484 sec = elf_section_by_name(elf, &ehdr, &shdr, 1522 sec = elf_section_by_name(elf, &ehdr, &shdr,
1485 ".notes", NULL); 1523 ".notes", NULL);
1486 if (sec == NULL) 1524 if (sec)
1487 goto out; 1525 break;
1488 } 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);
1489 1535
1490 data = elf_getdata(sec, NULL); 1536 data = elf_getdata(sec, NULL);
1491 if (data == NULL) 1537 if (data == NULL)
@@ -1590,34 +1636,163 @@ out:
1590 return err; 1636 return err;
1591} 1637}
1592 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
1593char dso__symtab_origin(const struct dso *dso) 1689char dso__symtab_origin(const struct dso *dso)
1594{ 1690{
1595 static const char origin[] = { 1691 static const char origin[] = {
1596 [SYMTAB__KALLSYMS] = 'k', 1692 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
1597 [SYMTAB__JAVA_JIT] = 'j', 1693 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
1598 [SYMTAB__BUILD_ID_CACHE] = 'B', 1694 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
1599 [SYMTAB__FEDORA_DEBUGINFO] = 'f', 1695 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
1600 [SYMTAB__UBUNTU_DEBUGINFO] = 'u', 1696 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
1601 [SYMTAB__BUILDID_DEBUGINFO] = 'b', 1697 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
1602 [SYMTAB__SYSTEM_PATH_DSO] = 'd', 1698 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
1603 [SYMTAB__SYSTEM_PATH_KMODULE] = 'K', 1699 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
1604 [SYMTAB__GUEST_KALLSYMS] = 'g', 1700 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
1605 [SYMTAB__GUEST_KMODULE] = 'G', 1701 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
1702 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
1606 }; 1703 };
1607 1704
1608 if (dso == NULL || dso->symtab_type == SYMTAB__NOT_FOUND) 1705 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
1609 return '!'; 1706 return '!';
1610 return origin[dso->symtab_type]; 1707 return origin[dso->symtab_type];
1611} 1708}
1612 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
1613int 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)
1614{ 1789{
1615 int size = PATH_MAX;
1616 char *name; 1790 char *name;
1617 int ret = -1; 1791 int ret = -1;
1618 int fd; 1792 int fd;
1793 u_int i;
1619 struct machine *machine; 1794 struct machine *machine;
1620 const char *root_dir; 1795 char *root_dir = (char *) "";
1621 int want_symtab; 1796 int want_symtab;
1622 1797
1623 dso__set_loaded(dso, map->type); 1798 dso__set_loaded(dso, map->type);
@@ -1632,7 +1807,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1632 else 1807 else
1633 machine = NULL; 1808 machine = NULL;
1634 1809
1635 name = malloc(size); 1810 name = malloc(PATH_MAX);
1636 if (!name) 1811 if (!name)
1637 return -1; 1812 return -1;
1638 1813
@@ -1651,69 +1826,27 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1651 } 1826 }
1652 1827
1653 ret = dso__load_perf_map(dso, map, filter); 1828 ret = dso__load_perf_map(dso, map, filter);
1654 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : 1829 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1655 SYMTAB__NOT_FOUND; 1830 DSO_BINARY_TYPE__NOT_FOUND;
1656 return ret; 1831 return ret;
1657 } 1832 }
1658 1833
1834 if (machine)
1835 root_dir = machine->root_dir;
1836
1659 /* Iterate over candidate debug images. 1837 /* Iterate over candidate debug images.
1660 * 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.
1661 * Failing that, do a second pass where we accept .dynsym also 1839 * Failing that, do a second pass where we accept .dynsym also
1662 */ 1840 */
1663 want_symtab = 1; 1841 want_symtab = 1;
1664restart: 1842restart:
1665 for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE; 1843 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
1666 dso->symtab_type != SYMTAB__NOT_FOUND;
1667 dso->symtab_type++) {
1668 switch (dso->symtab_type) {
1669 case SYMTAB__BUILD_ID_CACHE:
1670 /* skip the locally configured cache if a symfs is given */
1671 if (symbol_conf.symfs[0] ||
1672 (dso__build_id_filename(dso, name, size) == NULL)) {
1673 continue;
1674 }
1675 break;
1676 case SYMTAB__FEDORA_DEBUGINFO:
1677 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1678 symbol_conf.symfs, dso->long_name);
1679 break;
1680 case SYMTAB__UBUNTU_DEBUGINFO:
1681 snprintf(name, size, "%s/usr/lib/debug%s",
1682 symbol_conf.symfs, dso->long_name);
1683 break;
1684 case SYMTAB__BUILDID_DEBUGINFO: {
1685 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1686
1687 if (!dso->has_build_id)
1688 continue;
1689 1844
1690 build_id__sprintf(dso->build_id, 1845 dso->symtab_type = binary_type_symtab[i];
1691 sizeof(dso->build_id),
1692 build_id_hex);
1693 snprintf(name, size,
1694 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1695 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1696 }
1697 break;
1698 case SYMTAB__SYSTEM_PATH_DSO:
1699 snprintf(name, size, "%s%s",
1700 symbol_conf.symfs, dso->long_name);
1701 break;
1702 case SYMTAB__GUEST_KMODULE:
1703 if (map->groups && machine)
1704 root_dir = machine->root_dir;
1705 else
1706 root_dir = "";
1707 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1708 root_dir, dso->long_name);
1709 break;
1710 1846
1711 case SYMTAB__SYSTEM_PATH_KMODULE: 1847 if (dso__binary_type_file(dso, dso->symtab_type,
1712 snprintf(name, size, "%s%s", symbol_conf.symfs, 1848 root_dir, name, PATH_MAX))
1713 dso->long_name); 1849 continue;
1714 break;
1715 default:;
1716 }
1717 1850
1718 /* Name is now the name of the next image to try */ 1851 /* Name is now the name of the next image to try */
1719 fd = open(name, O_RDONLY); 1852 fd = open(name, O_RDONLY);
@@ -1930,9 +2063,9 @@ struct map *machine__new_module(struct machine *machine, u64 start,
1930 return NULL; 2063 return NULL;
1931 2064
1932 if (machine__is_host(machine)) 2065 if (machine__is_host(machine))
1933 dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE; 2066 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
1934 else 2067 else
1935 dso->symtab_type = SYMTAB__GUEST_KMODULE; 2068 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
1936 map_groups__insert(&machine->kmaps, map); 2069 map_groups__insert(&machine->kmaps, map);
1937 return map; 2070 return map;
1938} 2071}
@@ -2484,8 +2617,15 @@ int machine__create_kernel_maps(struct machine *machine)
2484 __machine__create_kernel_maps(machine, kernel) < 0) 2617 __machine__create_kernel_maps(machine, kernel) < 0)
2485 return -1; 2618 return -1;
2486 2619
2487 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) 2620 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
2488 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
2489 /* 2629 /*
2490 * 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:
2491 */ 2631 */
@@ -2735,6 +2875,7 @@ int machines__create_guest_kernel_maps(struct rb_root *machines)
2735 int i, items = 0; 2875 int i, items = 0;
2736 char path[PATH_MAX]; 2876 char path[PATH_MAX];
2737 pid_t pid; 2877 pid_t pid;
2878 char *endp;
2738 2879
2739 if (symbol_conf.default_guest_vmlinux_name || 2880 if (symbol_conf.default_guest_vmlinux_name ||
2740 symbol_conf.default_guest_modules || 2881 symbol_conf.default_guest_modules ||
@@ -2751,7 +2892,14 @@ int machines__create_guest_kernel_maps(struct rb_root *machines)
2751 /* Filter out . and .. */ 2892 /* Filter out . and .. */
2752 continue; 2893 continue;
2753 } 2894 }
2754 pid = atoi(namelist[i]->d_name); 2895 pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
2896 if ((*endp != '\0') ||
2897 (endp == namelist[i]->d_name) ||
2898 (errno == ERANGE)) {
2899 pr_debug("invalid directory (%s). Skipping.\n",
2900 namelist[i]->d_name);
2901 continue;
2902 }
2755 sprintf(path, "%s/%s/proc/kallsyms", 2903 sprintf(path, "%s/%s/proc/kallsyms",
2756 symbol_conf.guestmount, 2904 symbol_conf.guestmount,
2757 namelist[i]->d_name); 2905 namelist[i]->d_name);
@@ -2825,3 +2973,218 @@ struct map *dso__new_map(const char *name)
2825 2973
2826 return map; 2974 return map;
2827} 2975}
2976
2977static int open_dso(struct dso *dso, struct machine *machine)
2978{
2979 char *root_dir = (char *) "";
2980 char *name;
2981 int fd;
2982
2983 name = malloc(PATH_MAX);
2984 if (!name)
2985 return -ENOMEM;
2986
2987 if (machine)
2988 root_dir = machine->root_dir;
2989
2990 if (dso__binary_type_file(dso, dso->data_type,
2991 root_dir, name, PATH_MAX)) {
2992 free(name);
2993 return -EINVAL;
2994 }
2995
2996 fd = open(name, O_RDONLY);
2997 free(name);
2998 return fd;
2999}
3000
3001int dso__data_fd(struct dso *dso, struct machine *machine)
3002{
3003 int i = 0;
3004
3005 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
3006 return open_dso(dso, machine);
3007
3008 do {
3009 int fd;
3010
3011 dso->data_type = binary_type_data[i++];
3012
3013 fd = open_dso(dso, machine);
3014 if (fd >= 0)
3015 return fd;
3016
3017 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
3018
3019 return -EINVAL;
3020}
3021
3022static void
3023dso_cache__free(struct rb_root *root)
3024{
3025 struct rb_node *next = rb_first(root);
3026
3027 while (next) {
3028 struct dso_cache *cache;
3029
3030 cache = rb_entry(next, struct dso_cache, rb_node);
3031 next = rb_next(&cache->rb_node);
3032 rb_erase(&cache->rb_node, root);
3033 free(cache);
3034 }
3035}
3036
3037static struct dso_cache*
3038dso_cache__find(struct rb_root *root, u64 offset)
3039{
3040 struct rb_node **p = &root->rb_node;
3041 struct rb_node *parent = NULL;
3042 struct dso_cache *cache;
3043
3044 while (*p != NULL) {
3045 u64 end;
3046
3047 parent = *p;
3048 cache = rb_entry(parent, struct dso_cache, rb_node);
3049 end = cache->offset + DSO__DATA_CACHE_SIZE;
3050
3051 if (offset < cache->offset)
3052 p = &(*p)->rb_left;
3053 else if (offset >= end)
3054 p = &(*p)->rb_right;
3055 else
3056 return cache;
3057 }
3058 return NULL;
3059}
3060
3061static void
3062dso_cache__insert(struct rb_root *root, struct dso_cache *new)
3063{
3064 struct rb_node **p = &root->rb_node;
3065 struct rb_node *parent = NULL;
3066 struct dso_cache *cache;
3067 u64 offset = new->offset;
3068
3069 while (*p != NULL) {
3070 u64 end;
3071
3072 parent = *p;
3073 cache = rb_entry(parent, struct dso_cache, rb_node);
3074 end = cache->offset + DSO__DATA_CACHE_SIZE;
3075
3076 if (offset < cache->offset)
3077 p = &(*p)->rb_left;
3078 else if (offset >= end)
3079 p = &(*p)->rb_right;
3080 }
3081
3082 rb_link_node(&new->rb_node, parent, p);
3083 rb_insert_color(&new->rb_node, root);
3084}
3085
3086static ssize_t
3087dso_cache__memcpy(struct dso_cache *cache, u64 offset,
3088 u8 *data, u64 size)
3089{
3090 u64 cache_offset = offset - cache->offset;
3091 u64 cache_size = min(cache->size - cache_offset, size);
3092
3093 memcpy(data, cache->data + cache_offset, cache_size);
3094 return cache_size;
3095}
3096
3097static ssize_t
3098dso_cache__read(struct dso *dso, struct machine *machine,
3099 u64 offset, u8 *data, ssize_t size)
3100{
3101 struct dso_cache *cache;
3102 ssize_t ret;
3103 int fd;
3104
3105 fd = dso__data_fd(dso, machine);
3106 if (fd < 0)
3107 return -1;
3108
3109 do {
3110 u64 cache_offset;
3111
3112 ret = -ENOMEM;
3113
3114 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
3115 if (!cache)
3116 break;
3117
3118 cache_offset = offset & DSO__DATA_CACHE_MASK;
3119 ret = -EINVAL;
3120
3121 if (-1 == lseek(fd, cache_offset, SEEK_SET))
3122 break;
3123
3124 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
3125 if (ret <= 0)
3126 break;
3127
3128 cache->offset = cache_offset;
3129 cache->size = ret;
3130 dso_cache__insert(&dso->cache, cache);
3131
3132 ret = dso_cache__memcpy(cache, offset, data, size);
3133
3134 } while (0);
3135
3136 if (ret <= 0)
3137 free(cache);
3138
3139 close(fd);
3140 return ret;
3141}
3142
3143static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
3144 u64 offset, u8 *data, ssize_t size)
3145{
3146 struct dso_cache *cache;
3147
3148 cache = dso_cache__find(&dso->cache, offset);
3149 if (cache)
3150 return dso_cache__memcpy(cache, offset, data, size);
3151 else
3152 return dso_cache__read(dso, machine, offset, data, size);
3153}
3154
3155ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
3156 u64 offset, u8 *data, ssize_t size)
3157{
3158 ssize_t r = 0;
3159 u8 *p = data;
3160
3161 do {
3162 ssize_t ret;
3163
3164 ret = dso_cache_read(dso, machine, offset, p, size);
3165 if (ret < 0)
3166 return ret;
3167
3168 /* Reached EOF, return what we have. */
3169 if (!ret)
3170 break;
3171
3172 BUG_ON(ret > size);
3173
3174 r += ret;
3175 p += ret;
3176 offset += ret;
3177 size -= ret;
3178
3179 } while (size);
3180
3181 return r;
3182}
3183
3184ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
3185 struct machine *machine, u64 addr,
3186 u8 *data, ssize_t size)
3187{
3188 u64 offset = map->map_ip(map, addr);
3189 return dso__data_read_offset(dso, machine, offset, data, size);
3190}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index af0752b1aca1..1fe733a1e21f 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -155,6 +155,21 @@ struct addr_location {
155 s32 cpu; 155 s32 cpu;
156}; 156};
157 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
158enum dso_kernel_type { 173enum dso_kernel_type {
159 DSO_TYPE_USER = 0, 174 DSO_TYPE_USER = 0,
160 DSO_TYPE_KERNEL, 175 DSO_TYPE_KERNEL,
@@ -167,19 +182,31 @@ enum dso_swap_type {
167 DSO_SWAP__YES, 182 DSO_SWAP__YES,
168}; 183};
169 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
170struct dso { 195struct dso {
171 struct list_head node; 196 struct list_head node;
172 struct rb_root symbols[MAP__NR_TYPES]; 197 struct rb_root symbols[MAP__NR_TYPES];
173 struct rb_root symbol_names[MAP__NR_TYPES]; 198 struct rb_root symbol_names[MAP__NR_TYPES];
199 struct rb_root cache;
174 enum dso_kernel_type kernel; 200 enum dso_kernel_type kernel;
175 enum dso_swap_type needs_swap; 201 enum dso_swap_type needs_swap;
202 enum dso_binary_type symtab_type;
203 enum dso_binary_type data_type;
176 u8 adjust_symbols:1; 204 u8 adjust_symbols:1;
177 u8 has_build_id:1; 205 u8 has_build_id:1;
178 u8 hit:1; 206 u8 hit:1;
179 u8 annotate_warned:1; 207 u8 annotate_warned:1;
180 u8 sname_alloc:1; 208 u8 sname_alloc:1;
181 u8 lname_alloc:1; 209 u8 lname_alloc:1;
182 unsigned char symtab_type;
183 u8 sorted_by_name; 210 u8 sorted_by_name;
184 u8 loaded; 211 u8 loaded;
185 u8 build_id[BUILD_ID_SIZE]; 212 u8 build_id[BUILD_ID_SIZE];
@@ -253,20 +280,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
253 enum map_type type, FILE *fp); 280 enum map_type type, FILE *fp);
254size_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);
255 282
256enum symtab_type {
257 SYMTAB__KALLSYMS = 0,
258 SYMTAB__GUEST_KALLSYMS,
259 SYMTAB__JAVA_JIT,
260 SYMTAB__BUILD_ID_CACHE,
261 SYMTAB__FEDORA_DEBUGINFO,
262 SYMTAB__UBUNTU_DEBUGINFO,
263 SYMTAB__BUILDID_DEBUGINFO,
264 SYMTAB__SYSTEM_PATH_DSO,
265 SYMTAB__GUEST_KMODULE,
266 SYMTAB__SYSTEM_PATH_KMODULE,
267 SYMTAB__NOT_FOUND,
268};
269
270char dso__symtab_origin(const struct dso *dso); 283char dso__symtab_origin(const struct dso *dso);
271void dso__set_long_name(struct dso *dso, char *name); 284void dso__set_long_name(struct dso *dso, char *name);
272void dso__set_build_id(struct dso *dso, void *build_id); 285void dso__set_build_id(struct dso *dso, void *build_id);
@@ -303,4 +316,14 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type);
303 316
304size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 317size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
305 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);
306#endif /* __PERF_SYMBOL */ 329#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 1064d5b148ad..051eaa68095e 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