aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debug.h23
-rw-r--r--tools/perf/util/evlist.c4
-rw-r--r--tools/perf/util/evlist.h3
-rw-r--r--tools/perf/util/evsel.c227
-rw-r--r--tools/perf/util/evsel.h15
-rw-r--r--tools/perf/util/header.c33
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/include/linux/kernel.h10
-rw-r--r--tools/perf/util/map.c29
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/parse-events-test.c179
-rw-r--r--tools/perf/util/parse-events.c470
-rw-r--r--tools/perf/util/parse-events.h17
-rw-r--r--tools/perf/util/parse-events.l134
-rw-r--r--tools/perf/util/parse-events.y86
-rw-r--r--tools/perf/util/pmu.c169
-rw-r--r--tools/perf/util/pmu.h11
-rw-r--r--tools/perf/util/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.c67
-rw-r--r--tools/perf/util/session.h14
-rw-r--r--tools/perf/util/sort.c49
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/string.c22
-rw-r--r--tools/perf/util/symbol.c94
-rw-r--r--tools/perf/util/symbol.h1
-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
33 files changed, 1369 insertions, 559 deletions
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/evlist.c b/tools/perf/util/evlist.c
index 7400fb3fc50c..f74e9560350e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -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
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 989bee9624c2..40d4d3cdced0 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
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9f6cebd798ee..e81771364867 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,7 +15,7 @@
15#include "cpumap.h" 15#include "cpumap.h"
16#include "thread_map.h" 16#include "thread_map.h"
17#include "target.h" 17#include "target.h"
18#include "../../include/linux/perf_event.h" 18#include "../../../include/linux/hw_breakpoint.h"
19 19
20#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 20#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
21#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) 21#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -78,7 +78,7 @@ static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
78 "ref-cycles", 78 "ref-cycles",
79}; 79};
80 80
81const char *__perf_evsel__hw_name(u64 config) 81static const char *__perf_evsel__hw_name(u64 config)
82{ 82{
83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) 83 if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
84 return perf_evsel__hw_names[config]; 84 return perf_evsel__hw_names[config];
@@ -86,16 +86,15 @@ const char *__perf_evsel__hw_name(u64 config)
86 return "unknown-hardware"; 86 return "unknown-hardware";
87} 87}
88 88
89static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) 89static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
90{ 90{
91 int colon = 0; 91 int colon = 0, r = 0;
92 struct perf_event_attr *attr = &evsel->attr; 92 struct perf_event_attr *attr = &evsel->attr;
93 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config));
94 bool exclude_guest_default = false; 93 bool exclude_guest_default = false;
95 94
96#define MOD_PRINT(context, mod) do { \ 95#define MOD_PRINT(context, mod) do { \
97 if (!attr->exclude_##context) { \ 96 if (!attr->exclude_##context) { \
98 if (!colon) colon = r++; \ 97 if (!colon) colon = ++r; \
99 r += scnprintf(bf + r, size - r, "%c", mod); \ 98 r += scnprintf(bf + r, size - r, "%c", mod); \
100 } } while(0) 99 } } while(0)
101 100
@@ -108,7 +107,7 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
108 107
109 if (attr->precise_ip) { 108 if (attr->precise_ip) {
110 if (!colon) 109 if (!colon)
111 colon = r++; 110 colon = ++r;
112 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); 111 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
113 exclude_guest_default = true; 112 exclude_guest_default = true;
114 } 113 }
@@ -119,39 +118,211 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
119 } 118 }
120#undef MOD_PRINT 119#undef MOD_PRINT
121 if (colon) 120 if (colon)
122 bf[colon] = ':'; 121 bf[colon - 1] = ':';
123 return r; 122 return r;
124} 123}
125 124
126int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size) 125static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
126{
127 int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
128 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
129}
130
131static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
132 "cpu-clock",
133 "task-clock",
134 "page-faults",
135 "context-switches",
136 "CPU-migrations",
137 "minor-faults",
138 "major-faults",
139 "alignment-faults",
140 "emulation-faults",
141};
142
143static const char *__perf_evsel__sw_name(u64 config)
127{ 144{
128 int ret; 145 if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
146 return perf_evsel__sw_names[config];
147 return "unknown-software";
148}
149
150static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
151{
152 int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
153 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
154}
155
156static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
157{
158 int r;
159
160 r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
161
162 if (type & HW_BREAKPOINT_R)
163 r += scnprintf(bf + r, size - r, "r");
164
165 if (type & HW_BREAKPOINT_W)
166 r += scnprintf(bf + r, size - r, "w");
167
168 if (type & HW_BREAKPOINT_X)
169 r += scnprintf(bf + r, size - r, "x");
170
171 return r;
172}
173
174static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
175{
176 struct perf_event_attr *attr = &evsel->attr;
177 int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
178 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
179}
180
181const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
182 [PERF_EVSEL__MAX_ALIASES] = {
183 { "L1-dcache", "l1-d", "l1d", "L1-data", },
184 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
185 { "LLC", "L2", },
186 { "dTLB", "d-tlb", "Data-TLB", },
187 { "iTLB", "i-tlb", "Instruction-TLB", },
188 { "branch", "branches", "bpu", "btb", "bpc", },
189 { "node", },
190};
191
192const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
193 [PERF_EVSEL__MAX_ALIASES] = {
194 { "load", "loads", "read", },
195 { "store", "stores", "write", },
196 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
197};
198
199const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
200 [PERF_EVSEL__MAX_ALIASES] = {
201 { "refs", "Reference", "ops", "access", },
202 { "misses", "miss", },
203};
204
205#define C(x) PERF_COUNT_HW_CACHE_##x
206#define CACHE_READ (1 << C(OP_READ))
207#define CACHE_WRITE (1 << C(OP_WRITE))
208#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
209#define COP(x) (1 << x)
210
211/*
212 * cache operartion stat
213 * L1I : Read and prefetch only
214 * ITLB and BPU : Read-only
215 */
216static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
217 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
218 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
219 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
220 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
221 [C(ITLB)] = (CACHE_READ),
222 [C(BPU)] = (CACHE_READ),
223 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
224};
225
226bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
227{
228 if (perf_evsel__hw_cache_stat[type] & COP(op))
229 return true; /* valid */
230 else
231 return false; /* invalid */
232}
233
234int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
235 char *bf, size_t size)
236{
237 if (result) {
238 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
239 perf_evsel__hw_cache_op[op][0],
240 perf_evsel__hw_cache_result[result][0]);
241 }
242
243 return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
244 perf_evsel__hw_cache_op[op][1]);
245}
246
247static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
248{
249 u8 op, result, type = (config >> 0) & 0xff;
250 const char *err = "unknown-ext-hardware-cache-type";
251
252 if (type > PERF_COUNT_HW_CACHE_MAX)
253 goto out_err;
254
255 op = (config >> 8) & 0xff;
256 err = "unknown-ext-hardware-cache-op";
257 if (op > PERF_COUNT_HW_CACHE_OP_MAX)
258 goto out_err;
259
260 result = (config >> 16) & 0xff;
261 err = "unknown-ext-hardware-cache-result";
262 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
263 goto out_err;
264
265 err = "invalid-cache";
266 if (!perf_evsel__is_cache_op_valid(type, op))
267 goto out_err;
268
269 return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
270out_err:
271 return scnprintf(bf, size, "%s", err);
272}
273
274static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
275{
276 int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
277 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
278}
279
280static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
281{
282 int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
283 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
284}
285
286const char *perf_evsel__name(struct perf_evsel *evsel)
287{
288 char bf[128];
289
290 if (evsel->name)
291 return evsel->name;
129 292
130 switch (evsel->attr.type) { 293 switch (evsel->attr.type) {
131 case PERF_TYPE_RAW: 294 case PERF_TYPE_RAW:
132 ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); 295 perf_evsel__raw_name(evsel, bf, sizeof(bf));
133 break; 296 break;
134 297
135 case PERF_TYPE_HARDWARE: 298 case PERF_TYPE_HARDWARE:
136 ret = perf_evsel__hw_name(evsel, bf, size); 299 perf_evsel__hw_name(evsel, bf, sizeof(bf));
300 break;
301
302 case PERF_TYPE_HW_CACHE:
303 perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
304 break;
305
306 case PERF_TYPE_SOFTWARE:
307 perf_evsel__sw_name(evsel, bf, sizeof(bf));
137 break; 308 break;
309
310 case PERF_TYPE_TRACEPOINT:
311 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
312 break;
313
314 case PERF_TYPE_BREAKPOINT:
315 perf_evsel__bp_name(evsel, bf, sizeof(bf));
316 break;
317
138 default: 318 default:
139 /* 319 scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
140 * FIXME 320 break;
141 * 321 }
142 * This is the minimal perf_evsel__name so that we can 322
143 * reconstruct event names taking into account event modifiers. 323 evsel->name = strdup(bf);
144 * 324
145 * The old event_name uses it now for raw anr hw events, so that 325 return evsel->name ?: "unknown";
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 }
153
154 return ret;
155} 326}
156 327
157void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, 328void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4ba8b564e6f4..67cc5033d192 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -83,8 +83,19 @@ void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts, 83 struct perf_record_opts *opts,
84 struct perf_evsel *first); 84 struct perf_evsel *first);
85 85
86const char* __perf_evsel__hw_name(u64 config); 86bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
87int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size); 87
88#define PERF_EVSEL__MAX_ALIASES 8
89
90extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
91 [PERF_EVSEL__MAX_ALIASES];
92extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
93 [PERF_EVSEL__MAX_ALIASES];
94const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
95 [PERF_EVSEL__MAX_ALIASES];
96int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
97 char *bf, size_t size);
98const char *perf_evsel__name(struct perf_evsel *evsel);
88 99
89int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 100int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
90int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 101int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e909d43cf542..5a47aba46759 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -641,7 +641,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
641 /* 641 /*
642 * write event string as passed on cmdline 642 * write event string as passed on cmdline
643 */ 643 */
644 ret = do_write_string(fd, event_name(attr)); 644 ret = do_write_string(fd, perf_evsel__name(attr));
645 if (ret < 0) 645 if (ret < 0)
646 return ret; 646 return ret;
647 /* 647 /*
@@ -1474,15 +1474,15 @@ out:
1474 1474
1475static int process_tracing_data(struct perf_file_section *section __unused, 1475static int process_tracing_data(struct perf_file_section *section __unused,
1476 struct perf_header *ph __unused, 1476 struct perf_header *ph __unused,
1477 int feat __unused, int fd) 1477 int feat __unused, int fd, void *data)
1478{ 1478{
1479 trace_report(fd, false); 1479 trace_report(fd, data, false);
1480 return 0; 1480 return 0;
1481} 1481}
1482 1482
1483static int process_build_id(struct perf_file_section *section, 1483static int process_build_id(struct perf_file_section *section,
1484 struct perf_header *ph, 1484 struct perf_header *ph,
1485 int feat __unused, int fd) 1485 int feat __unused, int fd, void *data __used)
1486{ 1486{
1487 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1487 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1488 pr_debug("Failed to read buildids, continuing...\n"); 1488 pr_debug("Failed to read buildids, continuing...\n");
@@ -1493,7 +1493,7 @@ struct feature_ops {
1493 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1493 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1494 void (*print)(struct perf_header *h, int fd, FILE *fp); 1494 void (*print)(struct perf_header *h, int fd, FILE *fp);
1495 int (*process)(struct perf_file_section *section, 1495 int (*process)(struct perf_file_section *section,
1496 struct perf_header *h, int feat, int fd); 1496 struct perf_header *h, int feat, int fd, void *data);
1497 const char *name; 1497 const char *name;
1498 bool full_only; 1498 bool full_only;
1499}; 1499};
@@ -1988,7 +1988,7 @@ int perf_file_header__read(struct perf_file_header *header,
1988 1988
1989static int perf_file_section__process(struct perf_file_section *section, 1989static int perf_file_section__process(struct perf_file_section *section,
1990 struct perf_header *ph, 1990 struct perf_header *ph,
1991 int feat, int fd, void *data __used) 1991 int feat, int fd, void *data)
1992{ 1992{
1993 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) { 1993 if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
1994 pr_debug("Failed to lseek to %" PRIu64 " offset for feature " 1994 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2004,7 +2004,7 @@ static int perf_file_section__process(struct perf_file_section *section,
2004 if (!feat_ops[feat].process) 2004 if (!feat_ops[feat].process)
2005 return 0; 2005 return 0;
2006 2006
2007 return feat_ops[feat].process(section, ph, feat, fd); 2007 return feat_ops[feat].process(section, ph, feat, fd, data);
2008} 2008}
2009 2009
2010static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 2010static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
@@ -2093,9 +2093,11 @@ static int read_attr(int fd, struct perf_header *ph,
2093 return ret <= 0 ? -1 : 0; 2093 return ret <= 0 ? -1 : 0;
2094} 2094}
2095 2095
2096static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel) 2096static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel,
2097 struct pevent *pevent)
2097{ 2098{
2098 struct event_format *event = trace_find_event(evsel->attr.config); 2099 struct event_format *event = pevent_find_event(pevent,
2100 evsel->attr.config);
2099 char bf[128]; 2101 char bf[128];
2100 2102
2101 if (event == NULL) 2103 if (event == NULL)
@@ -2109,13 +2111,14 @@ static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel)
2109 return 0; 2111 return 0;
2110} 2112}
2111 2113
2112static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist) 2114static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist,
2115 struct pevent *pevent)
2113{ 2116{
2114 struct perf_evsel *pos; 2117 struct perf_evsel *pos;
2115 2118
2116 list_for_each_entry(pos, &evlist->entries, node) { 2119 list_for_each_entry(pos, &evlist->entries, node) {
2117 if (pos->attr.type == PERF_TYPE_TRACEPOINT && 2120 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2118 perf_evsel__set_tracepoint_name(pos)) 2121 perf_evsel__set_tracepoint_name(pos, pevent))
2119 return -1; 2122 return -1;
2120 } 2123 }
2121 2124
@@ -2198,12 +2201,12 @@ int perf_session__read_header(struct perf_session *session, int fd)
2198 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 2201 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
2199 } 2202 }
2200 2203
2201 perf_header__process_sections(header, fd, NULL, 2204 perf_header__process_sections(header, fd, &session->pevent,
2202 perf_file_section__process); 2205 perf_file_section__process);
2203 2206
2204 lseek(fd, header->data_offset, SEEK_SET); 2207 lseek(fd, header->data_offset, SEEK_SET);
2205 2208
2206 if (perf_evlist__set_tracepoint_names(session->evlist)) 2209 if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent))
2207 goto out_delete_evlist; 2210 goto out_delete_evlist;
2208 2211
2209 header->frozen = 1; 2212 header->frozen = 1;
@@ -2419,8 +2422,8 @@ int perf_event__process_tracing_data(union perf_event *event,
2419 lseek(session->fd, offset + sizeof(struct tracing_data_event), 2422 lseek(session->fd, offset + sizeof(struct tracing_data_event),
2420 SEEK_SET); 2423 SEEK_SET);
2421 2424
2422 size_read = trace_report(session->fd, session->repipe); 2425 size_read = trace_report(session->fd, &session->pevent,
2423 2426 session->repipe);
2424 padding = ALIGN(size_read, sizeof(u64)) - size_read; 2427 padding = ALIGN(size_read, sizeof(u64)) - size_read;
2425 2428
2426 if (read(session->fd, buf, padding) < 0) 2429 if (read(session->fd, buf, padding) < 0)
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/kernel.h b/tools/perf/util/include/linux/kernel.h
index 1eb804fd3fbf..b6842c1d02a8 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -108,4 +108,14 @@ int eprintf(int level,
108#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 108#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
109#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 109#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
110 110
111/*
112 * This looks more complex than it should be. But we need to
113 * get the type for the ~ right in round_down (it needs to be
114 * as wide as the result!), and we want to evaluate the macro
115 * arguments just once each.
116 */
117#define __round_mask(x, y) ((__typeof__(x))((y)-1))
118#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
119#define round_down(x, y) ((x) & ~__round_mask(x, y))
120
111#endif 121#endif
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 35ae56864e4f..a1f4e3669142 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -669,25 +669,26 @@ struct machine *machines__find(struct rb_root *self, pid_t pid)
669struct machine *machines__findnew(struct rb_root *self, pid_t pid) 669struct machine *machines__findnew(struct rb_root *self, pid_t pid)
670{ 670{
671 char path[PATH_MAX]; 671 char path[PATH_MAX];
672 const char *root_dir; 672 const char *root_dir = "";
673 struct machine *machine = machines__find(self, pid); 673 struct machine *machine = machines__find(self, pid);
674 674
675 if (!machine || machine->pid != pid) { 675 if (machine && (machine->pid == pid))
676 if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) 676 goto out;
677 root_dir = ""; 677
678 else { 678 if ((pid != HOST_KERNEL_ID) &&
679 if (!symbol_conf.guestmount) 679 (pid != DEFAULT_GUEST_KERNEL_ID) &&
680 goto out; 680 (symbol_conf.guestmount)) {
681 sprintf(path, "%s/%d", symbol_conf.guestmount, pid); 681 sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
682 if (access(path, R_OK)) { 682 if (access(path, R_OK)) {
683 pr_err("Can't access file %s\n", path); 683 pr_err("Can't access file %s\n", path);
684 goto out; 684 machine = NULL;
685 } 685 goto out;
686 root_dir = path;
687 } 686 }
688 machine = machines__add(self, pid, root_dir); 687 root_dir = path;
689 } 688 }
690 689
690 machine = machines__add(self, pid, root_dir);
691
691out: 692out:
692 return machine; 693 return machine;
693} 694}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 81371bad4ef0..c14c665d9a25 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -157,7 +157,7 @@ void machine__exit(struct machine *self);
157void machine__delete(struct machine *self); 157void machine__delete(struct machine *self);
158 158
159int machine__resolve_callchain(struct machine *machine, 159int machine__resolve_callchain(struct machine *machine,
160 struct perf_evsel *evsel, struct thread *thread, 160 struct thread *thread,
161 struct ip_callchain *chain, 161 struct ip_callchain *chain,
162 struct symbol **parent); 162 struct symbol **parent);
163int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, 163int 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..1b997d2b89ce 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
181 return 0; 181 return 0;
182} 182}
183 183
184static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
185{
186 struct perf_evsel *evsel = list_entry(evlist->entries.next,
187 struct perf_evsel, node);
188
189 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
190 TEST_ASSERT_VAL("wrong type",
191 PERF_TYPE_BREAKPOINT == evsel->attr.type);
192 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
193 TEST_ASSERT_VAL("wrong bp_type",
194 (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
195 TEST_ASSERT_VAL("wrong bp_len",
196 HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
197 return 0;
198}
199
184static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) 200static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
185{ 201{
186 struct perf_evsel *evsel = list_entry(evlist->entries.next, 202 struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
309 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 325 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
310 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 326 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
311 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 327 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
328 TEST_ASSERT_VAL("wrong name",
329 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
312 330
313 return test__checkevent_breakpoint(evlist); 331 return test__checkevent_breakpoint(evlist);
314} 332}
@@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
322 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 340 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
323 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 341 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
324 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 342 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
343 TEST_ASSERT_VAL("wrong name",
344 !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
325 345
326 return test__checkevent_breakpoint_x(evlist); 346 return test__checkevent_breakpoint_x(evlist);
327} 347}
@@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
335 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 355 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
336 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); 356 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
337 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 357 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
358 TEST_ASSERT_VAL("wrong name",
359 !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
338 360
339 return test__checkevent_breakpoint_r(evlist); 361 return test__checkevent_breakpoint_r(evlist);
340} 362}
@@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
348 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 370 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
349 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 371 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
350 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 372 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
373 TEST_ASSERT_VAL("wrong name",
374 !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
351 375
352 return test__checkevent_breakpoint_w(evlist); 376 return test__checkevent_breakpoint_w(evlist);
353} 377}
354 378
379static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
380{
381 struct perf_evsel *evsel = list_entry(evlist->entries.next,
382 struct perf_evsel, node);
383
384 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
385 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
386 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
387 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
388 TEST_ASSERT_VAL("wrong name",
389 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
390
391 return test__checkevent_breakpoint_rw(evlist);
392}
393
355static int test__checkevent_pmu(struct perf_evlist *evlist) 394static int test__checkevent_pmu(struct perf_evlist *evlist)
356{ 395{
357 396
@@ -413,19 +452,63 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
413{ 452{
414 struct perf_evsel *evsel; 453 struct perf_evsel *evsel;
415 454
416 /* cpu/config=1,name=krava1/u */ 455 /* cpu/config=1,name=krava/u */
417 evsel = list_entry(evlist->entries.next, struct perf_evsel, node); 456 evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
418 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); 457 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
419 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 458 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
420 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); 459 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
421 TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "krava")); 460 TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava"));
422 461
423 /* cpu/config=2/" */ 462 /* cpu/config=2/u" */
424 evsel = list_entry(evsel->node.next, struct perf_evsel, node); 463 evsel = list_entry(evsel->node.next, struct perf_evsel, node);
425 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); 464 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
426 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 465 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
427 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); 466 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
428 TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "raw 0x2")); 467 TEST_ASSERT_VAL("wrong name",
468 !strcmp(perf_evsel__name(evsel), "raw 0x2:u"));
469
470 return 0;
471}
472
473static int test__checkterms_simple(struct list_head *terms)
474{
475 struct parse_events__term *term;
476
477 /* config=10 */
478 term = list_entry(terms->next, struct parse_events__term, list);
479 TEST_ASSERT_VAL("wrong type term",
480 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG);
481 TEST_ASSERT_VAL("wrong type val",
482 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
483 TEST_ASSERT_VAL("wrong val", term->val.num == 10);
484 TEST_ASSERT_VAL("wrong config", !term->config);
485
486 /* config1 */
487 term = list_entry(term->list.next, struct parse_events__term, list);
488 TEST_ASSERT_VAL("wrong type term",
489 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1);
490 TEST_ASSERT_VAL("wrong type val",
491 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
492 TEST_ASSERT_VAL("wrong val", term->val.num == 1);
493 TEST_ASSERT_VAL("wrong config", !term->config);
494
495 /* config2=3 */
496 term = list_entry(term->list.next, struct parse_events__term, list);
497 TEST_ASSERT_VAL("wrong type term",
498 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2);
499 TEST_ASSERT_VAL("wrong type val",
500 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
501 TEST_ASSERT_VAL("wrong val", term->val.num == 3);
502 TEST_ASSERT_VAL("wrong config", !term->config);
503
504 /* umask=1*/
505 term = list_entry(term->list.next, struct parse_events__term, list);
506 TEST_ASSERT_VAL("wrong type term",
507 term->type_term == PARSE_EVENTS__TERM_TYPE_USER);
508 TEST_ASSERT_VAL("wrong type val",
509 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
510 TEST_ASSERT_VAL("wrong val", term->val.num == 1);
511 TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "umask"));
429 512
430 return 0; 513 return 0;
431} 514}
@@ -541,10 +624,16 @@ static struct test__event_st test__events[] = {
541 .name = "instructions:H", 624 .name = "instructions:H",
542 .check = test__checkevent_exclude_guest_modifier, 625 .check = test__checkevent_exclude_guest_modifier,
543 }, 626 },
627 [26] = {
628 .name = "mem:0:rw",
629 .check = test__checkevent_breakpoint_rw,
630 },
631 [27] = {
632 .name = "mem:0:rw:kp",
633 .check = test__checkevent_breakpoint_rw_modifier,
634 },
544}; 635};
545 636
546#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
547
548static struct test__event_st test__events_pmu[] = { 637static struct test__event_st test__events_pmu[] = {
549 [0] = { 638 [0] = {
550 .name = "cpu/config=10,config1,config2=3,period=1000/u", 639 .name = "cpu/config=10,config1,config2=3,period=1000/u",
@@ -556,10 +645,23 @@ static struct test__event_st test__events_pmu[] = {
556 }, 645 },
557}; 646};
558 647
559#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \ 648struct test__term {
560 sizeof(struct test__event_st)) 649 const char *str;
650 __u32 type;
651 int (*check)(struct list_head *terms);
652};
653
654static struct test__term test__terms[] = {
655 [0] = {
656 .str = "config=10,config1,config2=3,umask=1",
657 .check = test__checkterms_simple,
658 },
659};
660
661#define TEST__TERMS_CNT (sizeof(test__terms) / \
662 sizeof(struct test__term))
561 663
562static int test(struct test__event_st *e) 664static int test_event(struct test__event_st *e)
563{ 665{
564 struct perf_evlist *evlist; 666 struct perf_evlist *evlist;
565 int ret; 667 int ret;
@@ -590,7 +692,48 @@ static int test_events(struct test__event_st *events, unsigned cnt)
590 struct test__event_st *e = &events[i]; 692 struct test__event_st *e = &events[i];
591 693
592 pr_debug("running test %d '%s'\n", i, e->name); 694 pr_debug("running test %d '%s'\n", i, e->name);
593 ret = test(e); 695 ret = test_event(e);
696 if (ret)
697 break;
698 }
699
700 return ret;
701}
702
703static int test_term(struct test__term *t)
704{
705 struct list_head *terms;
706 int ret;
707
708 terms = malloc(sizeof(*terms));
709 if (!terms)
710 return -ENOMEM;
711
712 INIT_LIST_HEAD(terms);
713
714 ret = parse_events_terms(terms, t->str);
715 if (ret) {
716 pr_debug("failed to parse terms '%s', err %d\n",
717 t->str , ret);
718 return ret;
719 }
720
721 ret = t->check(terms);
722 parse_events__free_terms(terms);
723
724 return ret;
725}
726
727static int test_terms(struct test__term *terms, unsigned cnt)
728{
729 int ret = 0;
730 unsigned i;
731
732 for (i = 0; i < cnt; i++) {
733 struct test__term *t = &terms[i];
734
735 pr_debug("running test %d '%s'\n", i, t->str);
736 ret = test_term(t);
594 if (ret) 737 if (ret)
595 break; 738 break;
596 } 739 }
@@ -617,9 +760,17 @@ int parse_events__test(void)
617{ 760{
618 int ret; 761 int ret;
619 762
620 ret = test_events(test__events, TEST__EVENTS_CNT); 763#define TEST_EVENTS(tests) \
621 if (!ret && test_pmu()) 764do { \
622 ret = test_events(test__events_pmu, TEST__EVENTS_PMU_CNT); 765 ret = test_events(tests, ARRAY_SIZE(tests)); \
766 if (ret) \
767 return ret; \
768} while (0)
623 769
624 return ret; 770 TEST_EVENTS(test__events);
771
772 if (test_pmu())
773 TEST_EVENTS(test__events_pmu);
774
775 return test_terms(test__terms, ARRAY_SIZE(test__terms));
625} 776}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 05dbc8b3c767..1aa721d7c10f 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 }
@@ -549,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
549 if (!type || !type[i]) 437 if (!type || !type[i])
550 break; 438 break;
551 439
440#define CHECK_SET_TYPE(bit) \
441do { \
442 if (attr->bp_type & bit) \
443 return -EINVAL; \
444 else \
445 attr->bp_type |= bit; \
446} while (0)
447
552 switch (type[i]) { 448 switch (type[i]) {
553 case 'r': 449 case 'r':
554 attr->bp_type |= HW_BREAKPOINT_R; 450 CHECK_SET_TYPE(HW_BREAKPOINT_R);
555 break; 451 break;
556 case 'w': 452 case 'w':
557 attr->bp_type |= HW_BREAKPOINT_W; 453 CHECK_SET_TYPE(HW_BREAKPOINT_W);
558 break; 454 break;
559 case 'x': 455 case 'x':
560 attr->bp_type |= HW_BREAKPOINT_X; 456 CHECK_SET_TYPE(HW_BREAKPOINT_X);
561 break; 457 break;
562 default: 458 default:
563 return -EINVAL; 459 return -EINVAL;
564 } 460 }
565 } 461 }
566 462
463#undef CHECK_SET_TYPE
464
567 if (!attr->bp_type) /* Default */ 465 if (!attr->bp_type) /* Default */
568 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 466 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
569 467
@@ -574,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
574 void *ptr, char *type) 472 void *ptr, char *type)
575{ 473{
576 struct perf_event_attr attr; 474 struct perf_event_attr attr;
577 char name[MAX_NAME_LEN];
578 475
579 memset(&attr, 0, sizeof(attr)); 476 memset(&attr, 0, sizeof(attr));
580 attr.bp_addr = (unsigned long) ptr; 477 attr.bp_addr = (unsigned long) ptr;
@@ -593,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
593 490
594 attr.type = PERF_TYPE_BREAKPOINT; 491 attr.type = PERF_TYPE_BREAKPOINT;
595 492
596 snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw"); 493 return add_event(list, idx, &attr, NULL);
597 return add_event(list, idx, &attr, name);
598} 494}
599 495
600static int config_term(struct perf_event_attr *attr, 496static int config_term(struct perf_event_attr *attr,
@@ -666,8 +562,7 @@ int parse_events_add_numeric(struct list_head **list, int *idx,
666 config_attr(&attr, head_config, 1)) 562 config_attr(&attr, head_config, 1))
667 return -EINVAL; 563 return -EINVAL;
668 564
669 return add_event(list, idx, &attr, 565 return add_event(list, idx, &attr, NULL);
670 (char *) __event_name(type, config));
671} 566}
672 567
673static int parse_events__is_name_term(struct parse_events__term *term) 568static int parse_events__is_name_term(struct parse_events__term *term)
@@ -675,8 +570,7 @@ static int parse_events__is_name_term(struct parse_events__term *term)
675 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME; 570 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
676} 571}
677 572
678static char *pmu_event_name(struct perf_event_attr *attr, 573static char *pmu_event_name(struct list_head *head_terms)
679 struct list_head *head_terms)
680{ 574{
681 struct parse_events__term *term; 575 struct parse_events__term *term;
682 576
@@ -684,7 +578,7 @@ static char *pmu_event_name(struct perf_event_attr *attr,
684 if (parse_events__is_name_term(term)) 578 if (parse_events__is_name_term(term))
685 return term->val.str; 579 return term->val.str;
686 580
687 return (char *) __event_name(PERF_TYPE_RAW, attr->config); 581 return NULL;
688} 582}
689 583
690int parse_events_add_pmu(struct list_head **list, int *idx, 584int parse_events_add_pmu(struct list_head **list, int *idx,
@@ -699,6 +593,9 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
699 593
700 memset(&attr, 0, sizeof(attr)); 594 memset(&attr, 0, sizeof(attr));
701 595
596 if (perf_pmu__check_alias(pmu, head_config))
597 return -EINVAL;
598
702 /* 599 /*
703 * Configure hardcoded terms first, no need to check 600 * Configure hardcoded terms first, no need to check
704 * return value when called with fail == 0 ;) 601 * return value when called with fail == 0 ;)
@@ -709,7 +606,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
709 return -EINVAL; 606 return -EINVAL;
710 607
711 return add_event(list, idx, &attr, 608 return add_event(list, idx, &attr,
712 pmu_event_name(&attr, head_config)); 609 pmu_event_name(head_config));
713} 610}
714 611
715void parse_events_update_lists(struct list_head *list_event, 612void parse_events_update_lists(struct list_head *list_event,
@@ -787,27 +684,62 @@ int parse_events_modifier(struct list_head *list, char *str)
787 return 0; 684 return 0;
788} 685}
789 686
790int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) 687static int parse_events__scanner(const char *str, void *data, int start_token)
791{ 688{
792 LIST_HEAD(list);
793 LIST_HEAD(list_tmp);
794 YY_BUFFER_STATE buffer; 689 YY_BUFFER_STATE buffer;
795 int ret, idx = evlist->nr_entries; 690 void *scanner;
691 int ret;
692
693 ret = parse_events_lex_init_extra(start_token, &scanner);
694 if (ret)
695 return ret;
796 696
797 buffer = parse_events__scan_string(str); 697 buffer = parse_events__scan_string(str, scanner);
798 698
799#ifdef PARSER_DEBUG 699#ifdef PARSER_DEBUG
800 parse_events_debug = 1; 700 parse_events_debug = 1;
801#endif 701#endif
802 ret = parse_events_parse(&list, &idx); 702 ret = parse_events_parse(data, scanner);
803 703
804 parse_events__flush_buffer(buffer); 704 parse_events__flush_buffer(buffer, scanner);
805 parse_events__delete_buffer(buffer); 705 parse_events__delete_buffer(buffer, scanner);
806 parse_events_lex_destroy(); 706 parse_events_lex_destroy(scanner);
707 return ret;
708}
709
710/*
711 * parse event config string, return a list of event terms.
712 */
713int parse_events_terms(struct list_head *terms, const char *str)
714{
715 struct parse_events_data__terms data = {
716 .terms = NULL,
717 };
718 int ret;
807 719
720 ret = parse_events__scanner(str, &data, PE_START_TERMS);
808 if (!ret) { 721 if (!ret) {
809 int entries = idx - evlist->nr_entries; 722 list_splice(data.terms, terms);
810 perf_evlist__splice_list_tail(evlist, &list, entries); 723 free(data.terms);
724 return 0;
725 }
726
727 parse_events__free_terms(data.terms);
728 return ret;
729}
730
731int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
732{
733 struct parse_events_data__events data = {
734 .list = LIST_HEAD_INIT(data.list),
735 .idx = evlist->nr_entries,
736 };
737 int ret;
738
739 ret = parse_events__scanner(str, &data, PE_START_EVENTS);
740 if (!ret) {
741 int entries = data.idx - evlist->nr_entries;
742 perf_evlist__splice_list_tail(evlist, &data.list, entries);
811 return 0; 743 return 0;
812 } 744 }
813 745
@@ -946,16 +878,13 @@ int is_valid_tracepoint(const char *event_string)
946 return 0; 878 return 0;
947} 879}
948 880
949void print_events_type(u8 type) 881static void __print_events_type(u8 type, struct event_symbol *syms,
882 unsigned max)
950{ 883{
951 struct event_symbol *syms = event_symbols;
952 unsigned int i;
953 char name[64]; 884 char name[64];
885 unsigned i;
954 886
955 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 887 for (i = 0; i < max ; i++, syms++) {
956 if (type != syms->type)
957 continue;
958
959 if (strlen(syms->alias)) 888 if (strlen(syms->alias))
960 snprintf(name, sizeof(name), "%s OR %s", 889 snprintf(name, sizeof(name), "%s OR %s",
961 syms->symbol, syms->alias); 890 syms->symbol, syms->alias);
@@ -967,19 +896,28 @@ void print_events_type(u8 type)
967 } 896 }
968} 897}
969 898
899void print_events_type(u8 type)
900{
901 if (type == PERF_TYPE_SOFTWARE)
902 __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
903 else
904 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
905}
906
970int print_hwcache_events(const char *event_glob) 907int print_hwcache_events(const char *event_glob)
971{ 908{
972 unsigned int type, op, i, printed = 0; 909 unsigned int type, op, i, printed = 0;
910 char name[64];
973 911
974 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 912 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
975 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 913 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
976 /* skip invalid cache type */ 914 /* skip invalid cache type */
977 if (!is_cache_op_valid(type, op)) 915 if (!perf_evsel__is_cache_op_valid(type, op))
978 continue; 916 continue;
979 917
980 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 918 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
981 char *name = event_cache_name(type, op, i); 919 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
982 920 name, sizeof(name));
983 if (event_glob != NULL && !strglobmatch(name, event_glob)) 921 if (event_glob != NULL && !strglobmatch(name, event_glob))
984 continue; 922 continue;
985 923
@@ -993,26 +931,13 @@ int print_hwcache_events(const char *event_glob)
993 return printed; 931 return printed;
994} 932}
995 933
996/* 934static void print_symbol_events(const char *event_glob, unsigned type,
997 * Print the help text for the event symbols: 935 struct event_symbol *syms, unsigned max)
998 */
999void print_events(const char *event_glob)
1000{ 936{
1001 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; 937 unsigned i, printed = 0;
1002 struct event_symbol *syms = event_symbols;
1003 char name[MAX_NAME_LEN]; 938 char name[MAX_NAME_LEN];
1004 939
1005 printf("\n"); 940 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 941
1017 if (event_glob != NULL && 942 if (event_glob != NULL &&
1018 !(strglobmatch(syms->symbol, event_glob) || 943 !(strglobmatch(syms->symbol, event_glob) ||
@@ -1023,17 +948,31 @@ void print_events(const char *event_glob)
1023 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 948 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
1024 else 949 else
1025 strncpy(name, syms->symbol, MAX_NAME_LEN); 950 strncpy(name, syms->symbol, MAX_NAME_LEN);
1026 printf(" %-50s [%s]\n", name,
1027 event_type_descriptors[type]);
1028 951
1029 prev_type = type; 952 printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
1030 ++printed; 953
954 printed++;
1031 } 955 }
1032 956
1033 if (ntypes_printed) { 957 if (printed)
1034 printed = 0;
1035 printf("\n"); 958 printf("\n");
1036 } 959}
960
961/*
962 * Print the help text for the event symbols:
963 */
964void print_events(const char *event_glob)
965{
966
967 printf("\n");
968 printf("List of pre-defined events (to be used in -e):\n");
969
970 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
971 event_symbols_hw, PERF_COUNT_HW_MAX);
972
973 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
974 event_symbols_sw, PERF_COUNT_SW_MAX);
975
1037 print_hwcache_events(event_glob); 976 print_hwcache_events(event_glob);
1038 977
1039 if (event_glob != NULL) 978 if (event_glob != NULL)
@@ -1106,6 +1045,13 @@ int parse_events__term_str(struct parse_events__term **term,
1106 config, str, 0); 1045 config, str, 0);
1107} 1046}
1108 1047
1048int parse_events__term_clone(struct parse_events__term **new,
1049 struct parse_events__term *term)
1050{
1051 return new_term(new, term->type_val, term->type_term, term->config,
1052 term->val.str, term->val.num);
1053}
1054
1109void parse_events__free_terms(struct list_head *terms) 1055void parse_events__free_terms(struct list_head *terms)
1110{ 1056{
1111 struct parse_events__term *term, *h; 1057 struct parse_events__term *term, *h;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 8cac57ab4ee6..ee9c218a193c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -26,13 +26,12 @@ extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
26extern bool have_tracepoints(struct list_head *evlist); 26extern bool have_tracepoints(struct list_head *evlist);
27 27
28const char *event_type(int type); 28const char *event_type(int type);
29const char *event_name(struct perf_evsel *event);
30extern const char *__event_name(int type, u64 config);
31 29
32extern int parse_events_option(const struct option *opt, const char *str, 30extern int parse_events_option(const struct option *opt, const char *str,
33 int unset); 31 int unset);
34extern int parse_events(struct perf_evlist *evlist, const char *str, 32extern int parse_events(struct perf_evlist *evlist, const char *str,
35 int unset); 33 int unset);
34extern int parse_events_terms(struct list_head *terms, const char *str);
36extern int parse_filter(const struct option *opt, const char *str, int unset); 35extern int parse_filter(const struct option *opt, const char *str, int unset);
37 36
38#define EVENTS_HELP_MAX (128*1024) 37#define EVENTS_HELP_MAX (128*1024)
@@ -63,11 +62,22 @@ struct parse_events__term {
63 struct list_head list; 62 struct list_head list;
64}; 63};
65 64
65struct parse_events_data__events {
66 struct list_head list;
67 int idx;
68};
69
70struct parse_events_data__terms {
71 struct list_head *terms;
72};
73
66int parse_events__is_hardcoded_term(struct parse_events__term *term); 74int parse_events__is_hardcoded_term(struct parse_events__term *term);
67int parse_events__term_num(struct parse_events__term **_term, 75int parse_events__term_num(struct parse_events__term **_term,
68 int type_term, char *config, long num); 76 int type_term, char *config, long num);
69int parse_events__term_str(struct parse_events__term **_term, 77int parse_events__term_str(struct parse_events__term **_term,
70 int type_term, char *config, char *str); 78 int type_term, char *config, char *str);
79int parse_events__term_clone(struct parse_events__term **new,
80 struct parse_events__term *term);
71void parse_events__free_terms(struct list_head *terms); 81void parse_events__free_terms(struct list_head *terms);
72int parse_events_modifier(struct list_head *list, char *str); 82int parse_events_modifier(struct list_head *list, char *str);
73int parse_events_add_tracepoint(struct list_head **list, int *idx, 83int parse_events_add_tracepoint(struct list_head **list, int *idx,
@@ -83,8 +93,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
83 char *pmu , struct list_head *head_config); 93 char *pmu , struct list_head *head_config);
84void parse_events_update_lists(struct list_head *list_event, 94void parse_events_update_lists(struct list_head *list_event,
85 struct list_head *list_all); 95 struct list_head *list_all);
86void parse_events_error(struct list_head *list_all, 96void parse_events_error(void *data, void *scanner, char const *msg);
87 int *idx, char const *msg);
88int parse_events__test(void); 97int parse_events__test(void);
89 98
90void print_events(const char *event_glob); 99void print_events(const char *event_glob);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 618a8e788399..384ca74c6b22 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -1,4 +1,6 @@
1 1
2%option reentrant
3%option bison-bridge
2%option prefix="parse_events_" 4%option prefix="parse_events_"
3%option stack 5%option stack
4 6
@@ -8,7 +10,10 @@
8#include "parse-events-bison.h" 10#include "parse-events-bison.h"
9#include "parse-events.h" 11#include "parse-events.h"
10 12
11static int __value(char *str, int base, int token) 13char *parse_events_get_text(yyscan_t yyscanner);
14YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
15
16static int __value(YYSTYPE *yylval, char *str, int base, int token)
12{ 17{
13 long num; 18 long num;
14 19
@@ -17,35 +22,48 @@ static int __value(char *str, int base, int token)
17 if (errno) 22 if (errno)
18 return PE_ERROR; 23 return PE_ERROR;
19 24
20 parse_events_lval.num = num; 25 yylval->num = num;
21 return token; 26 return token;
22} 27}
23 28
24static int value(int base) 29static int value(yyscan_t scanner, int base)
25{ 30{
26 return __value(parse_events_text, base, PE_VALUE); 31 YYSTYPE *yylval = parse_events_get_lval(scanner);
32 char *text = parse_events_get_text(scanner);
33
34 return __value(yylval, text, base, PE_VALUE);
27} 35}
28 36
29static int raw(void) 37static int raw(yyscan_t scanner)
30{ 38{
31 return __value(parse_events_text + 1, 16, PE_RAW); 39 YYSTYPE *yylval = parse_events_get_lval(scanner);
40 char *text = parse_events_get_text(scanner);
41
42 return __value(yylval, text + 1, 16, PE_RAW);
32} 43}
33 44
34static int str(int token) 45static int str(yyscan_t scanner, int token)
35{ 46{
36 parse_events_lval.str = strdup(parse_events_text); 47 YYSTYPE *yylval = parse_events_get_lval(scanner);
48 char *text = parse_events_get_text(scanner);
49
50 yylval->str = strdup(text);
37 return token; 51 return token;
38} 52}
39 53
40static int sym(int type, int config) 54static int sym(yyscan_t scanner, int type, int config)
41{ 55{
42 parse_events_lval.num = (type << 16) + config; 56 YYSTYPE *yylval = parse_events_get_lval(scanner);
43 return PE_VALUE_SYM; 57
58 yylval->num = (type << 16) + config;
59 return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
44} 60}
45 61
46static int term(int type) 62static int term(yyscan_t scanner, int type)
47{ 63{
48 parse_events_lval.num = type; 64 YYSTYPE *yylval = parse_events_get_lval(scanner);
65
66 yylval->num = type;
49 return PE_TERM; 67 return PE_TERM;
50} 68}
51 69
@@ -58,28 +76,41 @@ num_hex 0x[a-fA-F0-9]+
58num_raw_hex [a-fA-F0-9]+ 76num_raw_hex [a-fA-F0-9]+
59name [a-zA-Z_*?][a-zA-Z0-9_*?]* 77name [a-zA-Z_*?][a-zA-Z0-9_*?]*
60modifier_event [ukhpGH]{1,8} 78modifier_event [ukhpGH]{1,8}
61modifier_bp [rwx] 79modifier_bp [rwx]{1,3}
62 80
63%% 81%%
64cpu-cycles|cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 82
65stalled-cycles-frontend|idle-cycles-frontend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 83%{
66stalled-cycles-backend|idle-cycles-backend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 84 {
67instructions { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); } 85 int start_token;
68cache-references { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); } 86
69cache-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); } 87 start_token = (int) parse_events_get_extra(yyscanner);
70branch-instructions|branches { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } 88 if (start_token) {
71branch-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); } 89 parse_events_set_extra(NULL, yyscanner);
72bus-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); } 90 return start_token;
73ref-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); } 91 }
74cpu-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); } 92 }
75task-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); } 93%}
76page-faults|faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); } 94
77minor-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); } 95cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
78major-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); } 96stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
79context-switches|cs { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); } 97stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
80cpu-migrations|migrations { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); } 98instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
81alignment-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } 99cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
82emulation-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 100cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
101branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
102branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
103bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
104ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
105cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
106task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
107page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
108minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
109major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
110context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
111cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
112alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
113emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
83 114
84L1-dcache|l1-d|l1d|L1-data | 115L1-dcache|l1-d|l1d|L1-data |
85L1-icache|l1-i|l1i|L1-instruction | 116L1-icache|l1-i|l1i|L1-instruction |
@@ -87,14 +118,14 @@ LLC|L2 |
87dTLB|d-tlb|Data-TLB | 118dTLB|d-tlb|Data-TLB |
88iTLB|i-tlb|Instruction-TLB | 119iTLB|i-tlb|Instruction-TLB |
89branch|branches|bpu|btb|bpc | 120branch|branches|bpu|btb|bpc |
90node { return str(PE_NAME_CACHE_TYPE); } 121node { return str(yyscanner, PE_NAME_CACHE_TYPE); }
91 122
92load|loads|read | 123load|loads|read |
93store|stores|write | 124store|stores|write |
94prefetch|prefetches | 125prefetch|prefetches |
95speculative-read|speculative-load | 126speculative-read|speculative-load |
96refs|Reference|ops|access | 127refs|Reference|ops|access |
97misses|miss { return str(PE_NAME_CACHE_OP_RESULT); } 128misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
98 129
99 /* 130 /*
100 * These are event config hardcoded term names to be specified 131 * These are event config hardcoded term names to be specified
@@ -102,38 +133,39 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
102 * so we can put them here directly. In case the we have a conflict 133 * so we can put them here directly. In case the we have a conflict
103 * in future, this needs to go into '//' condition block. 134 * in future, this needs to go into '//' condition block.
104 */ 135 */
105config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); } 136config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
106config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); } 137config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
107config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); } 138config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
108name { return term(PARSE_EVENTS__TERM_TYPE_NAME); } 139name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
109period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } 140period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
110branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 141branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
111 142
112mem: { BEGIN(mem); return PE_PREFIX_MEM; } 143mem: { BEGIN(mem); return PE_PREFIX_MEM; }
113r{num_raw_hex} { return raw(); } 144r{num_raw_hex} { return raw(yyscanner); }
114{num_dec} { return value(10); } 145{num_dec} { return value(yyscanner, 10); }
115{num_hex} { return value(16); } 146{num_hex} { return value(yyscanner, 16); }
116 147
117{modifier_event} { return str(PE_MODIFIER_EVENT); } 148{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
118{name} { return str(PE_NAME); } 149{name} { return str(yyscanner, PE_NAME); }
119"/" { return '/'; } 150"/" { return '/'; }
120- { return '-'; } 151- { return '-'; }
121, { return ','; } 152, { return ','; }
122: { return ':'; } 153: { return ':'; }
123= { return '='; } 154= { return '='; }
155\n { }
124 156
125<mem>{ 157<mem>{
126{modifier_bp} { return str(PE_MODIFIER_BP); } 158{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
127: { return ':'; } 159: { return ':'; }
128{num_dec} { return value(10); } 160{num_dec} { return value(yyscanner, 10); }
129{num_hex} { return value(16); } 161{num_hex} { return value(yyscanner, 16); }
130 /* 162 /*
131 * We need to separate 'mem:' scanner part, in order to get specific 163 * We need to separate 'mem:' scanner part, in order to get specific
132 * modifier bits parsed out. Otherwise we would need to handle PE_NAME 164 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
133 * and we'd need to parse it manually. During the escape from <mem> 165 * and we'd need to parse it manually. During the escape from <mem>
134 * state we need to put the escaping char back, so we dont miss it. 166 * state we need to put the escaping char back, so we dont miss it.
135 */ 167 */
136. { unput(*parse_events_text); BEGIN(INITIAL); } 168. { unput(*yytext); BEGIN(INITIAL); }
137 /* 169 /*
138 * We destroy the scanner after reaching EOF, 170 * We destroy the scanner after reaching EOF,
139 * but anyway just to be sure get back to INIT state. 171 * but anyway just to be sure get back to INIT state.
@@ -143,7 +175,7 @@ r{num_raw_hex} { return raw(); }
143 175
144%% 176%%
145 177
146int parse_events_wrap(void) 178int parse_events_wrap(void *scanner __used)
147{ 179{
148 return 1; 180 return 1;
149} 181}
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 362cc59332ae..2bc5fbff2b5d 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -1,7 +1,8 @@
1 1%pure-parser
2%name-prefix "parse_events_" 2%name-prefix "parse_events_"
3%parse-param {struct list_head *list_all} 3%parse-param {void *_data}
4%parse-param {int *idx} 4%parse-param {void *scanner}
5%lex-param {void* scanner}
5 6
6%{ 7%{
7 8
@@ -12,8 +13,9 @@
12#include "types.h" 13#include "types.h"
13#include "util.h" 14#include "util.h"
14#include "parse-events.h" 15#include "parse-events.h"
16#include "parse-events-bison.h"
15 17
16extern int parse_events_lex (void); 18extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
17 19
18#define ABORT_ON(val) \ 20#define ABORT_ON(val) \
19do { \ 21do { \
@@ -23,14 +25,16 @@ do { \
23 25
24%} 26%}
25 27
26%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM 28%token PE_START_EVENTS PE_START_TERMS
29%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
27%token PE_NAME 30%token PE_NAME
28%token PE_MODIFIER_EVENT PE_MODIFIER_BP 31%token PE_MODIFIER_EVENT PE_MODIFIER_BP
29%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 32%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
30%token PE_PREFIX_MEM PE_PREFIX_RAW 33%token PE_PREFIX_MEM PE_PREFIX_RAW
31%token PE_ERROR 34%token PE_ERROR
32%type <num> PE_VALUE 35%type <num> PE_VALUE
33%type <num> PE_VALUE_SYM 36%type <num> PE_VALUE_SYM_HW
37%type <num> PE_VALUE_SYM_SW
34%type <num> PE_RAW 38%type <num> PE_RAW
35%type <num> PE_TERM 39%type <num> PE_TERM
36%type <str> PE_NAME 40%type <str> PE_NAME
@@ -38,6 +42,7 @@ do { \
38%type <str> PE_NAME_CACHE_OP_RESULT 42%type <str> PE_NAME_CACHE_OP_RESULT
39%type <str> PE_MODIFIER_EVENT 43%type <str> PE_MODIFIER_EVENT
40%type <str> PE_MODIFIER_BP 44%type <str> PE_MODIFIER_BP
45%type <num> value_sym
41%type <head> event_config 46%type <head> event_config
42%type <term> event_term 47%type <term> event_term
43%type <head> event_pmu 48%type <head> event_pmu
@@ -58,24 +63,33 @@ do { \
58} 63}
59%% 64%%
60 65
66start:
67PE_START_EVENTS events
68|
69PE_START_TERMS terms
70
61events: 71events:
62events ',' event | event 72events ',' event | event
63 73
64event: 74event:
65event_def PE_MODIFIER_EVENT 75event_def PE_MODIFIER_EVENT
66{ 76{
77 struct parse_events_data__events *data = _data;
78
67 /* 79 /*
68 * Apply modifier on all events added by single event definition 80 * Apply modifier on all events added by single event definition
69 * (there could be more events added for multiple tracepoint 81 * (there could be more events added for multiple tracepoint
70 * definitions via '*?'. 82 * definitions via '*?'.
71 */ 83 */
72 ABORT_ON(parse_events_modifier($1, $2)); 84 ABORT_ON(parse_events_modifier($1, $2));
73 parse_events_update_lists($1, list_all); 85 parse_events_update_lists($1, &data->list);
74} 86}
75| 87|
76event_def 88event_def
77{ 89{
78 parse_events_update_lists($1, list_all); 90 struct parse_events_data__events *data = _data;
91
92 parse_events_update_lists($1, &data->list);
79} 93}
80 94
81event_def: event_pmu | 95event_def: event_pmu |
@@ -89,104 +103,131 @@ event_def: event_pmu |
89event_pmu: 103event_pmu:
90PE_NAME '/' event_config '/' 104PE_NAME '/' event_config '/'
91{ 105{
106 struct parse_events_data__events *data = _data;
92 struct list_head *list = NULL; 107 struct list_head *list = NULL;
93 108
94 ABORT_ON(parse_events_add_pmu(&list, idx, $1, $3)); 109 ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3));
95 parse_events__free_terms($3); 110 parse_events__free_terms($3);
96 $$ = list; 111 $$ = list;
97} 112}
98 113
114value_sym:
115PE_VALUE_SYM_HW
116|
117PE_VALUE_SYM_SW
118
99event_legacy_symbol: 119event_legacy_symbol:
100PE_VALUE_SYM '/' event_config '/' 120value_sym '/' event_config '/'
101{ 121{
122 struct parse_events_data__events *data = _data;
102 struct list_head *list = NULL; 123 struct list_head *list = NULL;
103 int type = $1 >> 16; 124 int type = $1 >> 16;
104 int config = $1 & 255; 125 int config = $1 & 255;
105 126
106 ABORT_ON(parse_events_add_numeric(&list, idx, type, config, $3)); 127 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
128 type, config, $3));
107 parse_events__free_terms($3); 129 parse_events__free_terms($3);
108 $$ = list; 130 $$ = list;
109} 131}
110| 132|
111PE_VALUE_SYM sep_slash_dc 133value_sym sep_slash_dc
112{ 134{
135 struct parse_events_data__events *data = _data;
113 struct list_head *list = NULL; 136 struct list_head *list = NULL;
114 int type = $1 >> 16; 137 int type = $1 >> 16;
115 int config = $1 & 255; 138 int config = $1 & 255;
116 139
117 ABORT_ON(parse_events_add_numeric(&list, idx, type, config, NULL)); 140 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
141 type, config, NULL));
118 $$ = list; 142 $$ = list;
119} 143}
120 144
121event_legacy_cache: 145event_legacy_cache:
122PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 146PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
123{ 147{
148 struct parse_events_data__events *data = _data;
124 struct list_head *list = NULL; 149 struct list_head *list = NULL;
125 150
126 ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, $5)); 151 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5));
127 $$ = list; 152 $$ = list;
128} 153}
129| 154|
130PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 155PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
131{ 156{
157 struct parse_events_data__events *data = _data;
132 struct list_head *list = NULL; 158 struct list_head *list = NULL;
133 159
134 ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, NULL)); 160 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL));
135 $$ = list; 161 $$ = list;
136} 162}
137| 163|
138PE_NAME_CACHE_TYPE 164PE_NAME_CACHE_TYPE
139{ 165{
166 struct parse_events_data__events *data = _data;
140 struct list_head *list = NULL; 167 struct list_head *list = NULL;
141 168
142 ABORT_ON(parse_events_add_cache(&list, idx, $1, NULL, NULL)); 169 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL));
143 $$ = list; 170 $$ = list;
144} 171}
145 172
146event_legacy_mem: 173event_legacy_mem:
147PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 174PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
148{ 175{
176 struct parse_events_data__events *data = _data;
149 struct list_head *list = NULL; 177 struct list_head *list = NULL;
150 178
151 ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, $4)); 179 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
180 (void *) $2, $4));
152 $$ = list; 181 $$ = list;
153} 182}
154| 183|
155PE_PREFIX_MEM PE_VALUE sep_dc 184PE_PREFIX_MEM PE_VALUE sep_dc
156{ 185{
186 struct parse_events_data__events *data = _data;
157 struct list_head *list = NULL; 187 struct list_head *list = NULL;
158 188
159 ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, NULL)); 189 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
190 (void *) $2, NULL));
160 $$ = list; 191 $$ = list;
161} 192}
162 193
163event_legacy_tracepoint: 194event_legacy_tracepoint:
164PE_NAME ':' PE_NAME 195PE_NAME ':' PE_NAME
165{ 196{
197 struct parse_events_data__events *data = _data;
166 struct list_head *list = NULL; 198 struct list_head *list = NULL;
167 199
168 ABORT_ON(parse_events_add_tracepoint(&list, idx, $1, $3)); 200 ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3));
169 $$ = list; 201 $$ = list;
170} 202}
171 203
172event_legacy_numeric: 204event_legacy_numeric:
173PE_VALUE ':' PE_VALUE 205PE_VALUE ':' PE_VALUE
174{ 206{
207 struct parse_events_data__events *data = _data;
175 struct list_head *list = NULL; 208 struct list_head *list = NULL;
176 209
177 ABORT_ON(parse_events_add_numeric(&list, idx, $1, $3, NULL)); 210 ABORT_ON(parse_events_add_numeric(&list, &data->idx, $1, $3, NULL));
178 $$ = list; 211 $$ = list;
179} 212}
180 213
181event_legacy_raw: 214event_legacy_raw:
182PE_RAW 215PE_RAW
183{ 216{
217 struct parse_events_data__events *data = _data;
184 struct list_head *list = NULL; 218 struct list_head *list = NULL;
185 219
186 ABORT_ON(parse_events_add_numeric(&list, idx, PERF_TYPE_RAW, $1, NULL)); 220 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
221 PERF_TYPE_RAW, $1, NULL));
187 $$ = list; 222 $$ = list;
188} 223}
189 224
225terms: event_config
226{
227 struct parse_events_data__terms *data = _data;
228 data->terms = $1;
229}
230
190event_config: 231event_config:
191event_config ',' event_term 232event_config ',' event_term
192{ 233{
@@ -267,8 +308,7 @@ sep_slash_dc: '/' | ':' |
267 308
268%% 309%%
269 310
270void parse_events_error(struct list_head *list_all __used, 311void parse_events_error(void *data __used, void *scanner __used,
271 int *idx __used,
272 char const *msg __used) 312 char const *msg __used)
273{ 313{
274} 314}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index a119a5371699..67715a42cd6d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
72 "%s/bus/event_source/devices/%s/format", sysfs, name); 72 "%s/bus/event_source/devices/%s/format", sysfs, name);
73 73
74 if (stat(path, &st) < 0) 74 if (stat(path, &st) < 0)
75 return -1; 75 return 0; /* no error if format does not exist */
76 76
77 if (pmu_format_parse(path, format)) 77 if (pmu_format_parse(path, format))
78 return -1; 78 return -1;
@@ -80,6 +80,114 @@ static int pmu_format(char *name, struct list_head *format)
80 return 0; 80 return 0;
81} 81}
82 82
83static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
84{
85 struct perf_pmu__alias *alias;
86 char buf[256];
87 int ret;
88
89 ret = fread(buf, 1, sizeof(buf), file);
90 if (ret == 0)
91 return -EINVAL;
92 buf[ret] = 0;
93
94 alias = malloc(sizeof(*alias));
95 if (!alias)
96 return -ENOMEM;
97
98 INIT_LIST_HEAD(&alias->terms);
99 ret = parse_events_terms(&alias->terms, buf);
100 if (ret) {
101 free(alias);
102 return ret;
103 }
104
105 alias->name = strdup(name);
106 list_add_tail(&alias->list, list);
107 return 0;
108}
109
110/*
111 * Process all the sysfs attributes located under the directory
112 * specified in 'dir' parameter.
113 */
114static int pmu_aliases_parse(char *dir, struct list_head *head)
115{
116 struct dirent *evt_ent;
117 DIR *event_dir;
118 int ret = 0;
119
120 event_dir = opendir(dir);
121 if (!event_dir)
122 return -EINVAL;
123
124 while (!ret && (evt_ent = readdir(event_dir))) {
125 char path[PATH_MAX];
126 char *name = evt_ent->d_name;
127 FILE *file;
128
129 if (!strcmp(name, ".") || !strcmp(name, ".."))
130 continue;
131
132 snprintf(path, PATH_MAX, "%s/%s", dir, name);
133
134 ret = -EINVAL;
135 file = fopen(path, "r");
136 if (!file)
137 break;
138 ret = perf_pmu__new_alias(head, name, file);
139 fclose(file);
140 }
141
142 closedir(event_dir);
143 return ret;
144}
145
146/*
147 * Reading the pmu event aliases definition, which should be located at:
148 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
149 */
150static int pmu_aliases(char *name, struct list_head *head)
151{
152 struct stat st;
153 char path[PATH_MAX];
154 const char *sysfs;
155
156 sysfs = sysfs_find_mountpoint();
157 if (!sysfs)
158 return -1;
159
160 snprintf(path, PATH_MAX,
161 "%s/bus/event_source/devices/%s/events", sysfs, name);
162
163 if (stat(path, &st) < 0)
164 return -1;
165
166 if (pmu_aliases_parse(path, head))
167 return -1;
168
169 return 0;
170}
171
172static int pmu_alias_terms(struct perf_pmu__alias *alias,
173 struct list_head *terms)
174{
175 struct parse_events__term *term, *clone;
176 LIST_HEAD(list);
177 int ret;
178
179 list_for_each_entry(term, &alias->terms, list) {
180 ret = parse_events__term_clone(&clone, term);
181 if (ret) {
182 parse_events__free_terms(&list);
183 return ret;
184 }
185 list_add_tail(&clone->list, &list);
186 }
187 list_splice(&list, terms);
188 return 0;
189}
190
83/* 191/*
84 * Reading/parsing the default pmu type value, which should be 192 * Reading/parsing the default pmu type value, which should be
85 * located at: 193 * located at:
@@ -118,6 +226,7 @@ static struct perf_pmu *pmu_lookup(char *name)
118{ 226{
119 struct perf_pmu *pmu; 227 struct perf_pmu *pmu;
120 LIST_HEAD(format); 228 LIST_HEAD(format);
229 LIST_HEAD(aliases);
121 __u32 type; 230 __u32 type;
122 231
123 /* 232 /*
@@ -135,10 +244,15 @@ static struct perf_pmu *pmu_lookup(char *name)
135 if (!pmu) 244 if (!pmu)
136 return NULL; 245 return NULL;
137 246
247 pmu_aliases(name, &aliases);
248
138 INIT_LIST_HEAD(&pmu->format); 249 INIT_LIST_HEAD(&pmu->format);
250 INIT_LIST_HEAD(&pmu->aliases);
139 list_splice(&format, &pmu->format); 251 list_splice(&format, &pmu->format);
252 list_splice(&aliases, &pmu->aliases);
140 pmu->name = strdup(name); 253 pmu->name = strdup(name);
141 pmu->type = type; 254 pmu->type = type;
255 list_add_tail(&pmu->list, &pmus);
142 return pmu; 256 return pmu;
143} 257}
144 258
@@ -279,6 +393,59 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
279 return pmu_config(&pmu->format, attr, head_terms); 393 return pmu_config(&pmu->format, attr, head_terms);
280} 394}
281 395
396static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
397 struct parse_events__term *term)
398{
399 struct perf_pmu__alias *alias;
400 char *name;
401
402 if (parse_events__is_hardcoded_term(term))
403 return NULL;
404
405 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
406 if (term->val.num != 1)
407 return NULL;
408 if (pmu_find_format(&pmu->format, term->config))
409 return NULL;
410 name = term->config;
411 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
412 if (strcasecmp(term->config, "event"))
413 return NULL;
414 name = term->val.str;
415 } else {
416 return NULL;
417 }
418
419 list_for_each_entry(alias, &pmu->aliases, list) {
420 if (!strcasecmp(alias->name, name))
421 return alias;
422 }
423 return NULL;
424}
425
426/*
427 * Find alias in the terms list and replace it with the terms
428 * defined for the alias
429 */
430int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
431{
432 struct parse_events__term *term, *h;
433 struct perf_pmu__alias *alias;
434 int ret;
435
436 list_for_each_entry_safe(term, h, head_terms, list) {
437 alias = pmu_find_alias(pmu, term);
438 if (!alias)
439 continue;
440 ret = pmu_alias_terms(alias, &term->list);
441 if (ret)
442 return ret;
443 list_del(&term->list);
444 free(term);
445 }
446 return 0;
447}
448
282int perf_pmu__new_format(struct list_head *list, char *name, 449int perf_pmu__new_format(struct list_head *list, char *name,
283 int config, unsigned long *bits) 450 int config, unsigned long *bits)
284{ 451{
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 68c0db965e1f..535f2c5258ab 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -19,17 +19,26 @@ struct perf_pmu__format {
19 struct list_head list; 19 struct list_head list;
20}; 20};
21 21
22struct perf_pmu__alias {
23 char *name;
24 struct list_head terms;
25 struct list_head list;
26};
27
22struct perf_pmu { 28struct perf_pmu {
23 char *name; 29 char *name;
24 __u32 type; 30 __u32 type;
25 struct list_head format; 31 struct list_head format;
32 struct list_head aliases;
26 struct list_head list; 33 struct list_head list;
27}; 34};
28 35
29struct perf_pmu *perf_pmu__find(char *name); 36struct perf_pmu *perf_pmu__find(char *name);
30int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 37int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
31 struct list_head *head_terms); 38 struct list_head *head_terms);
32 39int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
40struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
41 struct list_head *head_terms);
33int perf_pmu_wrap(void); 42int perf_pmu_wrap(void);
34void perf_pmu_error(struct list_head *list, char *name, char const *msg); 43void perf_pmu_error(struct list_head *list, char *name, char const *msg);
35 44
diff --git a/tools/perf/util/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 c3e399bcf18d..8e485592ca20 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{
@@ -289,7 +290,6 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
289} 290}
290 291
291int machine__resolve_callchain(struct machine *self, 292int machine__resolve_callchain(struct machine *self,
292 struct perf_evsel *evsel __used,
293 struct thread *thread, 293 struct thread *thread,
294 struct ip_callchain *chain, 294 struct ip_callchain *chain,
295 struct symbol **parent) 295 struct symbol **parent)
@@ -926,7 +926,7 @@ static struct machine *
926 else 926 else
927 pid = event->ip.pid; 927 pid = event->ip.pid;
928 928
929 return perf_session__find_machine(session, pid); 929 return perf_session__findnew_machine(session, pid);
930 } 930 }
931 931
932 return perf_session__find_host_machine(session); 932 return perf_session__find_host_machine(session);
@@ -1449,7 +1449,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1449 ret += hists__fprintf_nr_events(&session->hists, fp); 1449 ret += hists__fprintf_nr_events(&session->hists, fp);
1450 1450
1451 list_for_each_entry(pos, &session->evlist->entries, node) { 1451 list_for_each_entry(pos, &session->evlist->entries, node) {
1452 ret += fprintf(fp, "%s stats:\n", event_name(pos)); 1452 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1453 ret += hists__fprintf_nr_events(&pos->hists, fp); 1453 ret += hists__fprintf_nr_events(&pos->hists, fp);
1454 } 1454 }
1455 1455
@@ -1490,8 +1490,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1490} 1490}
1491 1491
1492void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 1492void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1493 struct machine *machine, struct perf_evsel *evsel, 1493 struct machine *machine, int print_sym,
1494 int print_sym, int print_dso, int print_symoffset) 1494 int print_dso, int print_symoffset)
1495{ 1495{
1496 struct addr_location al; 1496 struct addr_location al;
1497 struct callchain_cursor_node *node; 1497 struct callchain_cursor_node *node;
@@ -1505,7 +1505,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1505 1505
1506 if (symbol_conf.use_callchain && sample->callchain) { 1506 if (symbol_conf.use_callchain && sample->callchain) {
1507 1507
1508 if (machine__resolve_callchain(machine, evsel, al.thread, 1508 if (machine__resolve_callchain(machine, al.thread,
1509 sample->callchain, NULL) != 0) { 1509 sample->callchain, NULL) != 0) {
1510 if (verbose) 1510 if (verbose)
1511 error("Failed to resolve callchain. Skipping\n"); 1511 error("Failed to resolve callchain. Skipping\n");
@@ -1611,3 +1611,58 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
1611 perf_header__fprintf_info(session, fp, full); 1611 perf_header__fprintf_info(session, fp, full);
1612 fprintf(fp, "# ========\n#\n"); 1612 fprintf(fp, "# ========\n#\n");
1613} 1613}
1614
1615
1616int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1617 const struct perf_evsel_str_handler *assocs,
1618 size_t nr_assocs)
1619{
1620 struct perf_evlist *evlist = session->evlist;
1621 struct event_format *format;
1622 struct perf_evsel *evsel;
1623 char *tracepoint, *name;
1624 size_t i;
1625 int err;
1626
1627 for (i = 0; i < nr_assocs; i++) {
1628 err = -ENOMEM;
1629 tracepoint = strdup(assocs[i].name);
1630 if (tracepoint == NULL)
1631 goto out;
1632
1633 err = -ENOENT;
1634 name = strchr(tracepoint, ':');
1635 if (name == NULL)
1636 goto out_free;
1637
1638 *name++ = '\0';
1639 format = pevent_find_event_by_name(session->pevent,
1640 tracepoint, name);
1641 if (format == NULL) {
1642 /*
1643 * Adding a handler for an event not in the session,
1644 * just ignore it.
1645 */
1646 goto next;
1647 }
1648
1649 evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id);
1650 if (evsel == NULL)
1651 goto next;
1652
1653 err = -EEXIST;
1654 if (evsel->handler.func != NULL)
1655 goto out_free;
1656 evsel->handler.func = assocs[i].handler;
1657next:
1658 free(tracepoint);
1659 }
1660
1661 err = 0;
1662out:
1663 return err;
1664
1665out_free:
1666 free(tracepoint);
1667 goto out;
1668}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0c702e3f0a36..7c435bde6eb0 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -33,6 +33,7 @@ struct perf_session {
33 struct machine host_machine; 33 struct machine host_machine;
34 struct rb_root machines; 34 struct rb_root machines;
35 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
36 struct pevent *pevent;
36 /* 37 /*
37 * FIXME: Need to split this up further, we need global 38 * FIXME: Need to split this up further, we need global
38 * stats + per event stats. 'perf diff' also needs 39 * stats + per event stats. 'perf diff' also needs
@@ -151,11 +152,20 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
151 unsigned int type); 152 unsigned int type);
152 153
153void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 154void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
154 struct machine *machine, struct perf_evsel *evsel, 155 struct machine *machine, int print_sym,
155 int print_sym, int print_dso, int print_symoffset); 156 int print_dso, int print_symoffset);
156 157
157int perf_session__cpu_bitmap(struct perf_session *session, 158int perf_session__cpu_bitmap(struct perf_session *session,
158 const char *cpu_list, unsigned long *cpu_bitmap); 159 const char *cpu_list, unsigned long *cpu_bitmap);
159 160
160void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full); 161void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full);
162
163struct perf_evsel_str_handler;
164
165int __perf_session__set_tracepoints_handlers(struct perf_session *session,
166 const struct perf_evsel_str_handler *assocs,
167 size_t nr_assocs);
168
169#define perf_session__set_tracepoints_handlers(session, array) \
170 __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array))
161#endif /* __PERF_SESSION_H */ 171#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index a27237430c5f..0f5a0a496bc4 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -241,6 +241,54 @@ struct sort_entry sort_sym = {
241 .se_width_idx = HISTC_SYMBOL, 241 .se_width_idx = HISTC_SYMBOL,
242}; 242};
243 243
244/* --sort srcline */
245
246static int64_t
247sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
248{
249 return (int64_t)(right->ip - left->ip);
250}
251
252static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
253 size_t size, unsigned int width __used)
254{
255 FILE *fp;
256 char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
257 size_t line_len;
258
259 if (path != NULL)
260 goto out_path;
261
262 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
263 self->ms.map->dso->long_name, self->ip);
264 fp = popen(cmd, "r");
265 if (!fp)
266 goto out_ip;
267
268 if (getline(&path, &line_len, fp) < 0 || !line_len)
269 goto out_ip;
270 fclose(fp);
271 self->srcline = strdup(path);
272 if (self->srcline == NULL)
273 goto out_ip;
274
275 nl = strchr(self->srcline, '\n');
276 if (nl != NULL)
277 *nl = '\0';
278 path = self->srcline;
279out_path:
280 return repsep_snprintf(bf, size, "%s", path);
281out_ip:
282 return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
283}
284
285struct sort_entry sort_srcline = {
286 .se_header = "Source:Line",
287 .se_cmp = sort__srcline_cmp,
288 .se_snprintf = hist_entry__srcline_snprintf,
289 .se_width_idx = HISTC_SRCLINE,
290};
291
244/* --sort parent */ 292/* --sort parent */
245 293
246static int64_t 294static int64_t
@@ -439,6 +487,7 @@ static struct sort_dimension sort_dimensions[] = {
439 DIM(SORT_PARENT, "parent", sort_parent), 487 DIM(SORT_PARENT, "parent", sort_parent),
440 DIM(SORT_CPU, "cpu", sort_cpu), 488 DIM(SORT_CPU, "cpu", sort_cpu),
441 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), 489 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
490 DIM(SORT_SRCLINE, "srcline", sort_srcline),
442}; 491};
443 492
444int sort_dimension__add(const char *tok) 493int sort_dimension__add(const char *tok)
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 472aa5a63a58..e724b26acd51 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -71,6 +71,7 @@ struct hist_entry {
71 char level; 71 char level;
72 bool used; 72 bool used;
73 u8 filtered; 73 u8 filtered;
74 char *srcline;
74 struct symbol *parent; 75 struct symbol *parent;
75 union { 76 union {
76 unsigned long position; 77 unsigned long position;
@@ -93,6 +94,7 @@ enum sort_type {
93 SORT_SYM_FROM, 94 SORT_SYM_FROM,
94 SORT_SYM_TO, 95 SORT_SYM_TO,
95 SORT_MISPREDICT, 96 SORT_MISPREDICT,
97 SORT_SRCLINE,
96}; 98};
97 99
98/* 100/*
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index d5836382ff2c..199bc4d8905d 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -313,3 +313,25 @@ int strtailcmp(const char *s1, const char *s2)
313 return 0; 313 return 0;
314} 314}
315 315
316/**
317 * rtrim - Removes trailing whitespace from @s.
318 * @s: The string to be stripped.
319 *
320 * Note that the first trailing whitespace is replaced with a %NUL-terminator
321 * in the given string @s. Returns @s.
322 */
323char *rtrim(char *s)
324{
325 size_t size = strlen(s);
326 char *end;
327
328 if (!size)
329 return s;
330
331 end = s + size - 1;
332 while (end >= s && isspace(*end))
333 end--;
334 *(end + 1) = '\0';
335
336 return s;
337}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 3e2e5ea0f03f..50958bbeb26a 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1478,14 +1478,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1478 goto out; 1478 goto out;
1479 } 1479 }
1480 1480
1481 sec = elf_section_by_name(elf, &ehdr, &shdr, 1481 /*
1482 ".note.gnu.build-id", NULL); 1482 * Check following sections for notes:
1483 if (sec == NULL) { 1483 * '.note.gnu.build-id'
1484 * '.notes'
1485 * '.note' (VDSO specific)
1486 */
1487 do {
1488 sec = elf_section_by_name(elf, &ehdr, &shdr,
1489 ".note.gnu.build-id", NULL);
1490 if (sec)
1491 break;
1492
1484 sec = elf_section_by_name(elf, &ehdr, &shdr, 1493 sec = elf_section_by_name(elf, &ehdr, &shdr,
1485 ".notes", NULL); 1494 ".notes", NULL);
1486 if (sec == NULL) 1495 if (sec)
1487 goto out; 1496 break;
1488 } 1497
1498 sec = elf_section_by_name(elf, &ehdr, &shdr,
1499 ".note", NULL);
1500 if (sec)
1501 break;
1502
1503 return err;
1504
1505 } while (0);
1489 1506
1490 data = elf_getdata(sec, NULL); 1507 data = elf_getdata(sec, NULL);
1491 if (data == NULL) 1508 if (data == NULL)
@@ -1590,11 +1607,62 @@ out:
1590 return err; 1607 return err;
1591} 1608}
1592 1609
1610static int filename__read_debuglink(const char *filename,
1611 char *debuglink, size_t size)
1612{
1613 int fd, err = -1;
1614 Elf *elf;
1615 GElf_Ehdr ehdr;
1616 GElf_Shdr shdr;
1617 Elf_Data *data;
1618 Elf_Scn *sec;
1619 Elf_Kind ek;
1620
1621 fd = open(filename, O_RDONLY);
1622 if (fd < 0)
1623 goto out;
1624
1625 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1626 if (elf == NULL) {
1627 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1628 goto out_close;
1629 }
1630
1631 ek = elf_kind(elf);
1632 if (ek != ELF_K_ELF)
1633 goto out_close;
1634
1635 if (gelf_getehdr(elf, &ehdr) == NULL) {
1636 pr_err("%s: cannot get elf header.\n", __func__);
1637 goto out_close;
1638 }
1639
1640 sec = elf_section_by_name(elf, &ehdr, &shdr,
1641 ".gnu_debuglink", NULL);
1642 if (sec == NULL)
1643 goto out_close;
1644
1645 data = elf_getdata(sec, NULL);
1646 if (data == NULL)
1647 goto out_close;
1648
1649 /* the start of this section is a zero-terminated string */
1650 strncpy(debuglink, data->d_buf, size);
1651
1652 elf_end(elf);
1653
1654out_close:
1655 close(fd);
1656out:
1657 return err;
1658}
1659
1593char dso__symtab_origin(const struct dso *dso) 1660char dso__symtab_origin(const struct dso *dso)
1594{ 1661{
1595 static const char origin[] = { 1662 static const char origin[] = {
1596 [SYMTAB__KALLSYMS] = 'k', 1663 [SYMTAB__KALLSYMS] = 'k',
1597 [SYMTAB__JAVA_JIT] = 'j', 1664 [SYMTAB__JAVA_JIT] = 'j',
1665 [SYMTAB__DEBUGLINK] = 'l',
1598 [SYMTAB__BUILD_ID_CACHE] = 'B', 1666 [SYMTAB__BUILD_ID_CACHE] = 'B',
1599 [SYMTAB__FEDORA_DEBUGINFO] = 'f', 1667 [SYMTAB__FEDORA_DEBUGINFO] = 'f',
1600 [SYMTAB__UBUNTU_DEBUGINFO] = 'u', 1668 [SYMTAB__UBUNTU_DEBUGINFO] = 'u',
@@ -1662,10 +1730,22 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1662 */ 1730 */
1663 want_symtab = 1; 1731 want_symtab = 1;
1664restart: 1732restart:
1665 for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE; 1733 for (dso->symtab_type = SYMTAB__DEBUGLINK;
1666 dso->symtab_type != SYMTAB__NOT_FOUND; 1734 dso->symtab_type != SYMTAB__NOT_FOUND;
1667 dso->symtab_type++) { 1735 dso->symtab_type++) {
1668 switch (dso->symtab_type) { 1736 switch (dso->symtab_type) {
1737 case SYMTAB__DEBUGLINK: {
1738 char *debuglink;
1739 strncpy(name, dso->long_name, size);
1740 debuglink = name + dso->long_name_len;
1741 while (debuglink != name && *debuglink != '/')
1742 debuglink--;
1743 if (*debuglink == '/')
1744 debuglink++;
1745 filename__read_debuglink(dso->long_name, debuglink,
1746 size - (debuglink - name));
1747 }
1748 break;
1669 case SYMTAB__BUILD_ID_CACHE: 1749 case SYMTAB__BUILD_ID_CACHE:
1670 /* skip the locally configured cache if a symfs is given */ 1750 /* skip the locally configured cache if a symfs is given */
1671 if (symbol_conf.symfs[0] || 1751 if (symbol_conf.symfs[0] ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index af0752b1aca1..a884b99017f0 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -257,6 +257,7 @@ enum symtab_type {
257 SYMTAB__KALLSYMS = 0, 257 SYMTAB__KALLSYMS = 0,
258 SYMTAB__GUEST_KALLSYMS, 258 SYMTAB__GUEST_KALLSYMS,
259 SYMTAB__JAVA_JIT, 259 SYMTAB__JAVA_JIT,
260 SYMTAB__DEBUGLINK,
260 SYMTAB__BUILD_ID_CACHE, 261 SYMTAB__BUILD_ID_CACHE,
261 SYMTAB__FEDORA_DEBUGINFO, 262 SYMTAB__FEDORA_DEBUGINFO,
262 SYMTAB__UBUNTU_DEBUGINFO, 263 SYMTAB__UBUNTU_DEBUGINFO,
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