aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-07-06 04:17:40 -0400
committerIngo Molnar <mingo@kernel.org>2012-07-06 04:22:46 -0400
commit387ef4e24af4ae43a7961ba6eec749488da99535 (patch)
treebdd6995a544bce7401562afbd70ffd27e2b5a083 /tools/perf/util
parent6a67943a18c264d5f3df436da38edb3e59adc905 (diff)
parent81e9b994bb20716d1f6c47e048e4ae4a43de2f83 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
perf/core improvements and fixes: - Preparatory patches to use hw events in PMU syntax, from Jiri Olsa - Remaining backport of trace-cmd's libparseevent, from Namhyung Kim - Fix libtraceevent 'clean' make target, from Namhyung Kim - Teach ctags about libtraceevent error codes, from Namhyung Kim - Fix libtraceevent dependency files usage, from Namhyung Kim - Support hex number pretty printing in libtraceevent, fixing kvm output, from Namhyung Kim - Kill some die() usage in libtraceevent, from Namhyung Kim - Improve support for hw breakpoints parsing/pretty printing/testing, from Jiri Olsa - Clarify perf bench option naming, from Hitoshi Mitake - Look for ".note" ELF notes too, used in the kernel vdso, from Jiri Olsa - Fix internal PMU list usage, removing leak, from Robert Richter Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/evsel.c30
-rw-r--r--tools/perf/util/include/linux/kernel.h10
-rw-r--r--tools/perf/util/parse-events-test.c76
-rw-r--r--tools/perf/util/parse-events.c194
-rw-r--r--tools/perf/util/parse-events.l5
-rw-r--r--tools/perf/util/parse-events.y15
-rw-r--r--tools/perf/util/pmu.c3
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c4
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/symbol.c29
10 files changed, 275 insertions, 95 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3d1f6968f17..e8177136486 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,6 +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/hw_breakpoint.h"
18 19
19#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))
20#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))
@@ -152,6 +153,31 @@ static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
152 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); 153 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
153} 154}
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
155const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] 181const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
156 [PERF_EVSEL__MAX_ALIASES] = { 182 [PERF_EVSEL__MAX_ALIASES] = {
157 { "L1-dcache", "l1-d", "l1d", "L1-data", }, 183 { "L1-dcache", "l1-d", "l1d", "L1-data", },
@@ -285,6 +311,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
285 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint"); 311 scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
286 break; 312 break;
287 313
314 case PERF_TYPE_BREAKPOINT:
315 perf_evsel__bp_name(evsel, bf, sizeof(bf));
316 break;
317
288 default: 318 default:
289 scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); 319 scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
290 break; 320 break;
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index 1eb804fd3fb..b6842c1d02a 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/parse-events-test.c b/tools/perf/util/parse-events-test.c
index a0f61a2a683..1b997d2b89c 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
@@ -585,10 +624,16 @@ static struct test__event_st test__events[] = {
585 .name = "instructions:H", 624 .name = "instructions:H",
586 .check = test__checkevent_exclude_guest_modifier, 625 .check = test__checkevent_exclude_guest_modifier,
587 }, 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 },
588}; 635};
589 636
590#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
591
592static struct test__event_st test__events_pmu[] = { 637static struct test__event_st test__events_pmu[] = {
593 [0] = { 638 [0] = {
594 .name = "cpu/config=10,config1,config2=3,period=1000/u", 639 .name = "cpu/config=10,config1,config2=3,period=1000/u",
@@ -600,9 +645,6 @@ static struct test__event_st test__events_pmu[] = {
600 }, 645 },
601}; 646};
602 647
603#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \
604 sizeof(struct test__event_st))
605
606struct test__term { 648struct test__term {
607 const char *str; 649 const char *str;
608 __u32 type; 650 __u32 type;
@@ -718,21 +760,17 @@ int parse_events__test(void)
718{ 760{
719 int ret; 761 int ret;
720 762
721 do { 763#define TEST_EVENTS(tests) \
722 ret = test_events(test__events, TEST__EVENTS_CNT); 764do { \
723 if (ret) 765 ret = test_events(tests, ARRAY_SIZE(tests)); \
724 break; 766 if (ret) \
725 767 return ret; \
726 if (test_pmu()) { 768} while (0)
727 ret = test_events(test__events_pmu,
728 TEST__EVENTS_PMU_CNT);
729 if (ret)
730 break;
731 }
732 769
733 ret = test_terms(test__terms, TEST__TERMS_CNT); 770 TEST_EVENTS(test__events);
734 771
735 } while (0); 772 if (test_pmu())
773 TEST_EVENTS(test__events_pmu);
736 774
737 return ret; 775 return test_terms(test__terms, ARRAY_SIZE(test__terms));
738} 776}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 0cc27da30dd..1aa721d7c10 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -19,8 +19,6 @@
19#define MAX_NAME_LEN 100 19#define MAX_NAME_LEN 100
20 20
21struct event_symbol { 21struct event_symbol {
22 u8 type;
23 u64 config;
24 const char *symbol; 22 const char *symbol;
25 const char *alias; 23 const char *alias;
26}; 24};
@@ -30,30 +28,86 @@ extern int parse_events_debug;
30#endif 28#endif
31int parse_events_parse(void *data, void *scanner); 29int parse_events_parse(void *data, void *scanner);
32 30
33#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 31static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
34#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 32 [PERF_COUNT_HW_CPU_CYCLES] = {
35 33 .symbol = "cpu-cycles",
36static struct event_symbol event_symbols[] = { 34 .alias = "cycles",
37 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 35 },
38 { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" }, 36 [PERF_COUNT_HW_INSTRUCTIONS] = {
39 { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" }, 37 .symbol = "instructions",
40 { CHW(INSTRUCTIONS), "instructions", "" }, 38 .alias = "",
41 { CHW(CACHE_REFERENCES), "cache-references", "" }, 39 },
42 { CHW(CACHE_MISSES), "cache-misses", "" }, 40 [PERF_COUNT_HW_CACHE_REFERENCES] = {
43 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 41 .symbol = "cache-references",
44 { CHW(BRANCH_MISSES), "branch-misses", "" }, 42 .alias = "",
45 { CHW(BUS_CYCLES), "bus-cycles", "" }, 43 },
46 { CHW(REF_CPU_CYCLES), "ref-cycles", "" }, 44 [PERF_COUNT_HW_CACHE_MISSES] = {
47 45 .symbol = "cache-misses",
48 { CSW(CPU_CLOCK), "cpu-clock", "" }, 46 .alias = "",
49 { CSW(TASK_CLOCK), "task-clock", "" }, 47 },
50 { CSW(PAGE_FAULTS), "page-faults", "faults" }, 48 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
51 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 49 .symbol = "branch-instructions",
52 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 50 .alias = "branches",
53 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 51 },
54 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 52 [PERF_COUNT_HW_BRANCH_MISSES] = {
55 { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, 53 .symbol = "branch-misses",
56 { 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 },
57}; 111};
58 112
59#define __PERF_EVENT_FIELD(config, name) \ 113#define __PERF_EVENT_FIELD(config, name) \
@@ -383,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
383 if (!type || !type[i]) 437 if (!type || !type[i])
384 break; 438 break;
385 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
386 switch (type[i]) { 448 switch (type[i]) {
387 case 'r': 449 case 'r':
388 attr->bp_type |= HW_BREAKPOINT_R; 450 CHECK_SET_TYPE(HW_BREAKPOINT_R);
389 break; 451 break;
390 case 'w': 452 case 'w':
391 attr->bp_type |= HW_BREAKPOINT_W; 453 CHECK_SET_TYPE(HW_BREAKPOINT_W);
392 break; 454 break;
393 case 'x': 455 case 'x':
394 attr->bp_type |= HW_BREAKPOINT_X; 456 CHECK_SET_TYPE(HW_BREAKPOINT_X);
395 break; 457 break;
396 default: 458 default:
397 return -EINVAL; 459 return -EINVAL;
398 } 460 }
399 } 461 }
400 462
463#undef CHECK_SET_TYPE
464
401 if (!attr->bp_type) /* Default */ 465 if (!attr->bp_type) /* Default */
402 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 466 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
403 467
@@ -408,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
408 void *ptr, char *type) 472 void *ptr, char *type)
409{ 473{
410 struct perf_event_attr attr; 474 struct perf_event_attr attr;
411 char name[MAX_NAME_LEN];
412 475
413 memset(&attr, 0, sizeof(attr)); 476 memset(&attr, 0, sizeof(attr));
414 attr.bp_addr = (unsigned long) ptr; 477 attr.bp_addr = (unsigned long) ptr;
@@ -427,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
427 490
428 attr.type = PERF_TYPE_BREAKPOINT; 491 attr.type = PERF_TYPE_BREAKPOINT;
429 492
430 snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw"); 493 return add_event(list, idx, &attr, NULL);
431 return add_event(list, idx, &attr, name);
432} 494}
433 495
434static int config_term(struct perf_event_attr *attr, 496static int config_term(struct perf_event_attr *attr,
@@ -816,16 +878,13 @@ int is_valid_tracepoint(const char *event_string)
816 return 0; 878 return 0;
817} 879}
818 880
819void print_events_type(u8 type) 881static void __print_events_type(u8 type, struct event_symbol *syms,
882 unsigned max)
820{ 883{
821 struct event_symbol *syms = event_symbols;
822 unsigned int i;
823 char name[64]; 884 char name[64];
885 unsigned i;
824 886
825 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 887 for (i = 0; i < max ; i++, syms++) {
826 if (type != syms->type)
827 continue;
828
829 if (strlen(syms->alias)) 888 if (strlen(syms->alias))
830 snprintf(name, sizeof(name), "%s OR %s", 889 snprintf(name, sizeof(name), "%s OR %s",
831 syms->symbol, syms->alias); 890 syms->symbol, syms->alias);
@@ -837,6 +896,14 @@ void print_events_type(u8 type)
837 } 896 }
838} 897}
839 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
840int print_hwcache_events(const char *event_glob) 907int print_hwcache_events(const char *event_glob)
841{ 908{
842 unsigned int type, op, i, printed = 0; 909 unsigned int type, op, i, printed = 0;
@@ -864,26 +931,13 @@ int print_hwcache_events(const char *event_glob)
864 return printed; 931 return printed;
865} 932}
866 933
867/* 934static void print_symbol_events(const char *event_glob, unsigned type,
868 * Print the help text for the event symbols: 935 struct event_symbol *syms, unsigned max)
869 */
870void print_events(const char *event_glob)
871{ 936{
872 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; 937 unsigned i, printed = 0;
873 struct event_symbol *syms = event_symbols;
874 char name[MAX_NAME_LEN]; 938 char name[MAX_NAME_LEN];
875 939
876 printf("\n"); 940 for (i = 0; i < max; i++, syms++) {
877 printf("List of pre-defined events (to be used in -e):\n");
878
879 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
880 type = syms->type;
881
882 if (type != prev_type && printed) {
883 printf("\n");
884 printed = 0;
885 ntypes_printed++;
886 }
887 941
888 if (event_glob != NULL && 942 if (event_glob != NULL &&
889 !(strglobmatch(syms->symbol, event_glob) || 943 !(strglobmatch(syms->symbol, event_glob) ||
@@ -894,17 +948,31 @@ void print_events(const char *event_glob)
894 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);
895 else 949 else
896 strncpy(name, syms->symbol, MAX_NAME_LEN); 950 strncpy(name, syms->symbol, MAX_NAME_LEN);
897 printf(" %-50s [%s]\n", name,
898 event_type_descriptors[type]);
899 951
900 prev_type = type; 952 printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
901 ++printed; 953
954 printed++;
902 } 955 }
903 956
904 if (ntypes_printed) { 957 if (printed)
905 printed = 0;
906 printf("\n"); 958 printf("\n");
907 } 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
908 print_hwcache_events(event_glob); 976 print_hwcache_events(event_glob);
909 977
910 if (event_glob != NULL) 978 if (event_glob != NULL)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 488362e1413..384ca74c6b2 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -56,7 +56,7 @@ static int sym(yyscan_t scanner, int type, int config)
56 YYSTYPE *yylval = parse_events_get_lval(scanner); 56 YYSTYPE *yylval = parse_events_get_lval(scanner);
57 57
58 yylval->num = (type << 16) + config; 58 yylval->num = (type << 16) + config;
59 return PE_VALUE_SYM; 59 return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
60} 60}
61 61
62static int term(yyscan_t scanner, int type) 62static int term(yyscan_t scanner, int type)
@@ -76,7 +76,7 @@ num_hex 0x[a-fA-F0-9]+
76num_raw_hex [a-fA-F0-9]+ 76num_raw_hex [a-fA-F0-9]+
77name [a-zA-Z_*?][a-zA-Z0-9_*?]* 77name [a-zA-Z_*?][a-zA-Z0-9_*?]*
78modifier_event [ukhpGH]{1,8} 78modifier_event [ukhpGH]{1,8}
79modifier_bp [rwx] 79modifier_bp [rwx]{1,3}
80 80
81%% 81%%
82 82
@@ -152,6 +152,7 @@ r{num_raw_hex} { return raw(yyscanner); }
152, { return ','; } 152, { return ','; }
153: { return ':'; } 153: { return ':'; }
154= { return '='; } 154= { return '='; }
155\n { }
155 156
156<mem>{ 157<mem>{
157{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } 158{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 9525c455d27..2bc5fbff2b5 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -26,14 +26,15 @@ do { \
26%} 26%}
27 27
28%token PE_START_EVENTS PE_START_TERMS 28%token PE_START_EVENTS PE_START_TERMS
29%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM 29%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
30%token PE_NAME 30%token PE_NAME
31%token PE_MODIFIER_EVENT PE_MODIFIER_BP 31%token PE_MODIFIER_EVENT PE_MODIFIER_BP
32%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 32%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
33%token PE_PREFIX_MEM PE_PREFIX_RAW 33%token PE_PREFIX_MEM PE_PREFIX_RAW
34%token PE_ERROR 34%token PE_ERROR
35%type <num> PE_VALUE 35%type <num> PE_VALUE
36%type <num> PE_VALUE_SYM 36%type <num> PE_VALUE_SYM_HW
37%type <num> PE_VALUE_SYM_SW
37%type <num> PE_RAW 38%type <num> PE_RAW
38%type <num> PE_TERM 39%type <num> PE_TERM
39%type <str> PE_NAME 40%type <str> PE_NAME
@@ -41,6 +42,7 @@ do { \
41%type <str> PE_NAME_CACHE_OP_RESULT 42%type <str> PE_NAME_CACHE_OP_RESULT
42%type <str> PE_MODIFIER_EVENT 43%type <str> PE_MODIFIER_EVENT
43%type <str> PE_MODIFIER_BP 44%type <str> PE_MODIFIER_BP
45%type <num> value_sym
44%type <head> event_config 46%type <head> event_config
45%type <term> event_term 47%type <term> event_term
46%type <head> event_pmu 48%type <head> event_pmu
@@ -109,8 +111,13 @@ PE_NAME '/' event_config '/'
109 $$ = list; 111 $$ = list;
110} 112}
111 113
114value_sym:
115PE_VALUE_SYM_HW
116|
117PE_VALUE_SYM_SW
118
112event_legacy_symbol: 119event_legacy_symbol:
113PE_VALUE_SYM '/' event_config '/' 120value_sym '/' event_config '/'
114{ 121{
115 struct parse_events_data__events *data = _data; 122 struct parse_events_data__events *data = _data;
116 struct list_head *list = NULL; 123 struct list_head *list = NULL;
@@ -123,7 +130,7 @@ PE_VALUE_SYM '/' event_config '/'
123 $$ = list; 130 $$ = list;
124} 131}
125| 132|
126PE_VALUE_SYM sep_slash_dc 133value_sym sep_slash_dc
127{ 134{
128 struct parse_events_data__events *data = _data; 135 struct parse_events_data__events *data = _data;
129 struct list_head *list = NULL; 136 struct list_head *list = NULL;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 74d0948ec36..67715a42cd6 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;
@@ -252,6 +252,7 @@ static struct perf_pmu *pmu_lookup(char *name)
252 list_splice(&aliases, &pmu->aliases); 252 list_splice(&aliases, &pmu->aliases);
253 pmu->name = strdup(name); 253 pmu->name = strdup(name);
254 pmu->type = type; 254 pmu->type = type;
255 list_add_tail(&pmu->list, &pmus);
255 return pmu; 256 return pmu;
256} 257}
257 258
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b3620fe1276..02dfa19a467 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:
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index a8ca2f8179a..ce4d1b0c386 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:
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 994f4ffdcd0..50958bbeb26 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)