aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/alias.c3
-rw-r--r--tools/perf/util/annotate.c19
-rw-r--r--tools/perf/util/annotate.h23
-rw-r--r--tools/perf/util/build-id.c11
-rw-r--r--tools/perf/util/cache.h42
-rw-r--r--tools/perf/util/callchain.c6
-rw-r--r--tools/perf/util/cgroup.c4
-rw-r--r--tools/perf/util/config.c6
-rw-r--r--tools/perf/util/cpumap.c22
-rw-r--r--tools/perf/util/cpumap.h13
-rw-r--r--tools/perf/util/debug.c6
-rw-r--r--tools/perf/util/debug.h32
-rw-r--r--tools/perf/util/dso-test-data.c2
-rw-r--r--tools/perf/util/dwarf-aux.c2
-rw-r--r--tools/perf/util/event.c71
-rw-r--r--tools/perf/util/event.h14
-rw-r--r--tools/perf/util/evlist.c231
-rw-r--r--tools/perf/util/evlist.h51
-rw-r--r--tools/perf/util/evsel.c276
-rw-r--r--tools/perf/util/evsel.h65
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh15
-rw-r--r--tools/perf/util/header.c1063
-rw-r--r--tools/perf/util/header.h31
-rw-r--r--tools/perf/util/help.c4
-rw-r--r--tools/perf/util/hist.c775
-rw-r--r--tools/perf/util/hist.h107
-rw-r--r--tools/perf/util/include/asm/byteorder.h2
-rw-r--r--tools/perf/util/include/linux/bitops.h4
-rw-r--r--tools/perf/util/include/linux/compiler.h9
-rw-r--r--tools/perf/util/include/linux/const.h2
-rw-r--r--tools/perf/util/include/linux/kernel.h17
-rw-r--r--tools/perf/util/include/linux/magic.h12
-rw-r--r--tools/perf/util/include/linux/rbtree.h1
-rw-r--r--tools/perf/util/include/linux/rbtree_augmented.h2
-rw-r--r--tools/perf/util/include/linux/string.h2
-rw-r--r--tools/perf/util/include/linux/types.h8
-rw-r--r--tools/perf/util/intlist.c8
-rw-r--r--tools/perf/util/map.c47
-rw-r--r--tools/perf/util/map.h9
-rw-r--r--tools/perf/util/parse-events-test.c428
-rw-r--r--tools/perf/util/parse-events.c257
-rw-r--r--tools/perf/util/parse-events.h20
-rw-r--r--tools/perf/util/parse-events.l56
-rw-r--r--tools/perf/util/parse-events.y125
-rw-r--r--tools/perf/util/parse-options.c11
-rw-r--r--tools/perf/util/parse-options.h1
-rw-r--r--tools/perf/util/path.c2
-rw-r--r--tools/perf/util/perf_regs.h14
-rw-r--r--tools/perf/util/pmu.c80
-rw-r--r--tools/perf/util/pmu.h5
-rw-r--r--tools/perf/util/pmu.y6
-rw-r--r--tools/perf/util/probe-event.c69
-rw-r--r--tools/perf/util/probe-finder.c28
-rw-r--r--tools/perf/util/python.c17
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c50
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c113
-rw-r--r--tools/perf/util/session.c198
-rw-r--r--tools/perf/util/session.h12
-rw-r--r--tools/perf/util/setup.py2
-rw-r--r--tools/perf/util/sort.c31
-rw-r--r--tools/perf/util/sort.h21
-rw-r--r--tools/perf/util/stat.c57
-rw-r--r--tools/perf/util/stat.h16
-rw-r--r--tools/perf/util/string.c18
-rw-r--r--tools/perf/util/strlist.c2
-rw-r--r--tools/perf/util/symbol-elf.c841
-rw-r--r--tools/perf/util/symbol-minimal.c307
-rw-r--r--tools/perf/util/symbol.c942
-rw-r--r--tools/perf/util/symbol.h73
-rw-r--r--tools/perf/util/target.c4
-rw-r--r--tools/perf/util/thread.c1
-rw-r--r--tools/perf/util/thread.h2
-rw-r--r--tools/perf/util/top.c3
-rw-r--r--tools/perf/util/top.h1
-rw-r--r--tools/perf/util/trace-event-parse.c54
-rw-r--r--tools/perf/util/trace-event-scripting.c34
-rw-r--r--tools/perf/util/trace-event.h12
-rw-r--r--tools/perf/util/unwind.c571
-rw-r--r--tools/perf/util/unwind.h35
-rw-r--r--tools/perf/util/util.c25
-rw-r--r--tools/perf/util/util.h9
-rw-r--r--tools/perf/util/vdso.c111
-rw-r--r--tools/perf/util/vdso.h18
-rw-r--r--tools/perf/util/wrapper.c3
84 files changed, 5036 insertions, 2666 deletions
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
index b8144e80bb1e..e6d134773d0a 100644
--- a/tools/perf/util/alias.c
+++ b/tools/perf/util/alias.c
@@ -3,7 +3,8 @@
3static const char *alias_key; 3static const char *alias_key;
4static char *alias_val; 4static char *alias_val;
5 5
6static int alias_lookup_cb(const char *k, const char *v, void *cb __used) 6static int alias_lookup_cb(const char *k, const char *v,
7 void *cb __maybe_unused)
7{ 8{
8 if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) { 9 if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) {
9 if (!v) 10 if (!v)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 3a282c0057d2..f0a910371377 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -17,6 +17,7 @@
17#include <pthread.h> 17#include <pthread.h>
18 18
19const char *disassembler_style; 19const char *disassembler_style;
20const char *objdump_path;
20 21
21static struct ins *ins__find(const char *name); 22static struct ins *ins__find(const char *name);
22static int disasm_line__parse(char *line, char **namep, char **rawp); 23static int disasm_line__parse(char *line, char **namep, char **rawp);
@@ -312,8 +313,8 @@ static struct ins_ops dec_ops = {
312 .scnprintf = dec__scnprintf, 313 .scnprintf = dec__scnprintf,
313}; 314};
314 315
315static int nop__scnprintf(struct ins *ins __used, char *bf, size_t size, 316static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
316 struct ins_operands *ops __used) 317 struct ins_operands *ops __maybe_unused)
317{ 318{
318 return scnprintf(bf, size, "%-6.6s", "nop"); 319 return scnprintf(bf, size, "%-6.6s", "nop");
319} 320}
@@ -415,7 +416,7 @@ static struct ins *ins__find(const char *name)
415 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp); 416 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp);
416} 417}
417 418
418int symbol__annotate_init(struct map *map __used, struct symbol *sym) 419int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
419{ 420{
420 struct annotation *notes = symbol__annotation(sym); 421 struct annotation *notes = symbol__annotation(sym);
421 pthread_mutex_init(&notes->lock, NULL); 422 pthread_mutex_init(&notes->lock, NULL);
@@ -820,9 +821,10 @@ fallback:
820 dso, dso->long_name, sym, sym->name); 821 dso, dso->long_name, sym, sym->name);
821 822
822 snprintf(command, sizeof(command), 823 snprintf(command, sizeof(command),
823 "objdump %s%s --start-address=0x%016" PRIx64 824 "%s %s%s --start-address=0x%016" PRIx64
824 " --stop-address=0x%016" PRIx64 825 " --stop-address=0x%016" PRIx64
825 " -d %s %s -C %s|grep -v %s|expand", 826 " -d %s %s -C %s|grep -v %s|expand",
827 objdump_path ? objdump_path : "objdump",
826 disassembler_style ? "-M " : "", 828 disassembler_style ? "-M " : "",
827 disassembler_style ? disassembler_style : "", 829 disassembler_style ? disassembler_style : "",
828 map__rip_2objdump(map, sym->start), 830 map__rip_2objdump(map, sym->start),
@@ -982,7 +984,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
982 int context) 984 int context)
983{ 985{
984 struct dso *dso = map->dso; 986 struct dso *dso = map->dso;
985 const char *filename = dso->long_name, *d_filename; 987 char *filename;
988 const char *d_filename;
986 struct annotation *notes = symbol__annotation(sym); 989 struct annotation *notes = symbol__annotation(sym);
987 struct disasm_line *pos, *queue = NULL; 990 struct disasm_line *pos, *queue = NULL;
988 u64 start = map__rip_2objdump(map, sym->start); 991 u64 start = map__rip_2objdump(map, sym->start);
@@ -990,6 +993,10 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
990 int more = 0; 993 int more = 0;
991 u64 len; 994 u64 len;
992 995
996 filename = strdup(dso->long_name);
997 if (!filename)
998 return -ENOMEM;
999
993 if (full_paths) 1000 if (full_paths)
994 d_filename = filename; 1001 d_filename = filename;
995 else 1002 else
@@ -1040,6 +1047,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
1040 } 1047 }
1041 } 1048 }
1042 1049
1050 free(filename);
1051
1043 return more; 1052 return more;
1044} 1053}
1045 1054
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 78a5692dd718..39242dcee8f2 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -7,6 +7,7 @@
7#include "symbol.h" 7#include "symbol.h"
8#include <linux/list.h> 8#include <linux/list.h>
9#include <linux/rbtree.h> 9#include <linux/rbtree.h>
10#include <pthread.h>
10 11
11struct ins; 12struct ins;
12 13
@@ -125,7 +126,7 @@ int symbol__alloc_hist(struct symbol *sym);
125void symbol__annotate_zero_histograms(struct symbol *sym); 126void symbol__annotate_zero_histograms(struct symbol *sym);
126 127
127int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 128int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
128int symbol__annotate_init(struct map *map __used, struct symbol *sym); 129int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym);
129int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, 130int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
130 bool full_paths, int min_pcnt, int max_lines, 131 bool full_paths, int min_pcnt, int max_lines,
131 int context); 132 int context);
@@ -137,20 +138,22 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
137 bool print_lines, bool full_paths, int min_pcnt, 138 bool print_lines, bool full_paths, int min_pcnt,
138 int max_lines); 139 int max_lines);
139 140
140#ifdef NO_NEWT_SUPPORT 141#ifdef NEWT_SUPPORT
141static inline int symbol__tui_annotate(struct symbol *sym __used, 142int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
142 struct map *map __used, 143 void(*timer)(void *arg), void *arg, int delay_secs);
143 int evidx __used, 144#else
144 void(*timer)(void *arg) __used, 145static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
145 void *arg __used, int delay_secs __used) 146 struct map *map __maybe_unused,
147 int evidx __maybe_unused,
148 void(*timer)(void *arg) __maybe_unused,
149 void *arg __maybe_unused,
150 int delay_secs __maybe_unused)
146{ 151{
147 return 0; 152 return 0;
148} 153}
149#else
150int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
151 void(*timer)(void *arg), void *arg, int delay_secs);
152#endif 154#endif
153 155
154extern const char *disassembler_style; 156extern const char *disassembler_style;
157extern const char *objdump_path;
155 158
156#endif /* __PERF_ANNOTATE_H */ 159#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index fd9a5944b627..8e3a740ddbd4 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -16,10 +16,10 @@
16#include "session.h" 16#include "session.h"
17#include "tool.h" 17#include "tool.h"
18 18
19static int build_id__mark_dso_hit(struct perf_tool *tool __used, 19static int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
20 union perf_event *event, 20 union perf_event *event,
21 struct perf_sample *sample __used, 21 struct perf_sample *sample __maybe_unused,
22 struct perf_evsel *evsel __used, 22 struct perf_evsel *evsel __maybe_unused,
23 struct machine *machine) 23 struct machine *machine)
24{ 24{
25 struct addr_location al; 25 struct addr_location al;
@@ -41,9 +41,10 @@ static int build_id__mark_dso_hit(struct perf_tool *tool __used,
41 return 0; 41 return 0;
42} 42}
43 43
44static int perf_event__exit_del_thread(struct perf_tool *tool __used, 44static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
45 union perf_event *event, 45 union perf_event *event,
46 struct perf_sample *sample __used, 46 struct perf_sample *sample
47 __maybe_unused,
47 struct machine *machine) 48 struct machine *machine)
48{ 49{
49 struct thread *thread = machine__findnew_thread(machine, event->fork.tid); 50 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index cff18c617d13..2bd51370ad28 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -33,39 +33,41 @@ extern int pager_use_color;
33 33
34extern int use_browser; 34extern int use_browser;
35 35
36#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 36#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
37static inline void setup_browser(bool fallback_to_pager)
38{
39 if (fallback_to_pager)
40 setup_pager();
41}
42static inline void exit_browser(bool wait_for_ok __used) {}
43#else
44void setup_browser(bool fallback_to_pager); 37void setup_browser(bool fallback_to_pager);
45void exit_browser(bool wait_for_ok); 38void exit_browser(bool wait_for_ok);
46 39
47#ifdef NO_NEWT_SUPPORT 40#ifdef NEWT_SUPPORT
41int ui__init(void);
42void ui__exit(bool wait_for_ok);
43#else
48static inline int ui__init(void) 44static inline int ui__init(void)
49{ 45{
50 return -1; 46 return -1;
51} 47}
52static inline void ui__exit(bool wait_for_ok __used) {} 48static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
53#else
54int ui__init(void);
55void ui__exit(bool wait_for_ok);
56#endif 49#endif
57 50
58#ifdef NO_GTK2_SUPPORT 51#ifdef GTK2_SUPPORT
52int perf_gtk__init(void);
53void perf_gtk__exit(bool wait_for_ok);
54#else
59static inline int perf_gtk__init(void) 55static inline int perf_gtk__init(void)
60{ 56{
61 return -1; 57 return -1;
62} 58}
63static inline void perf_gtk__exit(bool wait_for_ok __used) {} 59static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
64#else
65int perf_gtk__init(void);
66void perf_gtk__exit(bool wait_for_ok);
67#endif 60#endif
68#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ 61
62#else /* NEWT_SUPPORT || GTK2_SUPPORT */
63
64static inline void setup_browser(bool fallback_to_pager)
65{
66 if (fallback_to_pager)
67 setup_pager();
68}
69static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
70#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
69 71
70char *alias_lookup(const char *alias); 72char *alias_lookup(const char *alias);
71int split_cmdline(char *cmdline, const char ***argv); 73int split_cmdline(char *cmdline, const char ***argv);
@@ -105,7 +107,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
105extern char *perf_pathdup(const char *fmt, ...) 107extern char *perf_pathdup(const char *fmt, ...)
106 __attribute__((format (printf, 1, 2))); 108 __attribute__((format (printf, 1, 2)));
107 109
108#ifdef NO_STRLCPY 110#ifndef HAVE_STRLCPY
109extern size_t strlcpy(char *dest, const char *src, size_t size); 111extern size_t strlcpy(char *dest, const char *src, size_t size);
110#endif 112#endif
111 113
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 3a6bff47614f..d3b3f5d82137 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -93,7 +93,7 @@ __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
93 */ 93 */
94static void 94static void
95sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root, 95sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
96 u64 min_hit, struct callchain_param *param __used) 96 u64 min_hit, struct callchain_param *param __maybe_unused)
97{ 97{
98 __sort_chain_flat(rb_root, &root->node, min_hit); 98 __sort_chain_flat(rb_root, &root->node, min_hit);
99} 99}
@@ -115,7 +115,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node,
115 115
116static void 116static void
117sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root, 117sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
118 u64 min_hit, struct callchain_param *param __used) 118 u64 min_hit, struct callchain_param *param __maybe_unused)
119{ 119{
120 __sort_chain_graph_abs(&chain_root->node, min_hit); 120 __sort_chain_graph_abs(&chain_root->node, min_hit);
121 rb_root->rb_node = chain_root->node.rb_root.rb_node; 121 rb_root->rb_node = chain_root->node.rb_root.rb_node;
@@ -140,7 +140,7 @@ static void __sort_chain_graph_rel(struct callchain_node *node,
140 140
141static void 141static void
142sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root, 142sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
143 u64 min_hit __used, struct callchain_param *param) 143 u64 min_hit __maybe_unused, struct callchain_param *param)
144{ 144{
145 __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0); 145 __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
146 rb_root->rb_node = chain_root->node.rb_root.rb_node; 146 rb_root->rb_node = chain_root->node.rb_root.rb_node;
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index dbe2f16b1a1a..96bbda1ddb83 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -138,8 +138,8 @@ void close_cgroup(struct cgroup_sel *cgrp)
138 } 138 }
139} 139}
140 140
141int parse_cgroups(const struct option *opt __used, const char *str, 141int parse_cgroups(const struct option *opt __maybe_unused, const char *str,
142 int unset __used) 142 int unset __maybe_unused)
143{ 143{
144 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 144 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
145 const char *p, *e, *eos = str + strlen(str); 145 const char *p, *e, *eos = str + strlen(str);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 6faa3a18bfbd..3e0fdd369ccb 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -342,13 +342,15 @@ const char *perf_config_dirname(const char *name, const char *value)
342 return value; 342 return value;
343} 343}
344 344
345static int perf_default_core_config(const char *var __used, const char *value __used) 345static int perf_default_core_config(const char *var __maybe_unused,
346 const char *value __maybe_unused)
346{ 347{
347 /* Add other config variables here. */ 348 /* Add other config variables here. */
348 return 0; 349 return 0;
349} 350}
350 351
351int perf_default_config(const char *var, const char *value, void *dummy __used) 352int perf_default_config(const char *var, const char *value,
353 void *dummy __maybe_unused)
352{ 354{
353 if (!prefixcmp(var, "core.")) 355 if (!prefixcmp(var, "core."))
354 return perf_default_core_config(var, value); 356 return perf_default_core_config(var, value);
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index adc72f09914d..2b32ffa9ebdb 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -38,24 +38,19 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
38 return cpus; 38 return cpus;
39} 39}
40 40
41static struct cpu_map *cpu_map__read_all_cpu_map(void) 41struct cpu_map *cpu_map__read(FILE *file)
42{ 42{
43 struct cpu_map *cpus = NULL; 43 struct cpu_map *cpus = NULL;
44 FILE *onlnf;
45 int nr_cpus = 0; 44 int nr_cpus = 0;
46 int *tmp_cpus = NULL, *tmp; 45 int *tmp_cpus = NULL, *tmp;
47 int max_entries = 0; 46 int max_entries = 0;
48 int n, cpu, prev; 47 int n, cpu, prev;
49 char sep; 48 char sep;
50 49
51 onlnf = fopen("/sys/devices/system/cpu/online", "r");
52 if (!onlnf)
53 return cpu_map__default_new();
54
55 sep = 0; 50 sep = 0;
56 prev = -1; 51 prev = -1;
57 for (;;) { 52 for (;;) {
58 n = fscanf(onlnf, "%u%c", &cpu, &sep); 53 n = fscanf(file, "%u%c", &cpu, &sep);
59 if (n <= 0) 54 if (n <= 0)
60 break; 55 break;
61 if (prev >= 0) { 56 if (prev >= 0) {
@@ -95,6 +90,19 @@ static struct cpu_map *cpu_map__read_all_cpu_map(void)
95 cpus = cpu_map__default_new(); 90 cpus = cpu_map__default_new();
96out_free_tmp: 91out_free_tmp:
97 free(tmp_cpus); 92 free(tmp_cpus);
93 return cpus;
94}
95
96static struct cpu_map *cpu_map__read_all_cpu_map(void)
97{
98 struct cpu_map *cpus = NULL;
99 FILE *onlnf;
100
101 onlnf = fopen("/sys/devices/system/cpu/online", "r");
102 if (!onlnf)
103 return cpu_map__default_new();
104
105 cpus = cpu_map__read(onlnf);
98 fclose(onlnf); 106 fclose(onlnf);
99 return cpus; 107 return cpus;
100} 108}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index c41518573c6a..2f68a3b8c285 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -2,6 +2,7 @@
2#define __PERF_CPUMAP_H 2#define __PERF_CPUMAP_H
3 3
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h>
5 6
6struct cpu_map { 7struct cpu_map {
7 int nr; 8 int nr;
@@ -11,7 +12,17 @@ struct cpu_map {
11struct cpu_map *cpu_map__new(const char *cpu_list); 12struct cpu_map *cpu_map__new(const char *cpu_list);
12struct cpu_map *cpu_map__dummy_new(void); 13struct cpu_map *cpu_map__dummy_new(void);
13void cpu_map__delete(struct cpu_map *map); 14void cpu_map__delete(struct cpu_map *map);
14 15struct cpu_map *cpu_map__read(FILE *file);
15size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); 16size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
16 17
18static inline int cpu_map__nr(const struct cpu_map *map)
19{
20 return map ? map->nr : 1;
21}
22
23static inline bool cpu_map__all(const struct cpu_map *map)
24{
25 return map ? map->map[0] == -1 : true;
26}
27
17#endif /* __PERF_CPUMAP_H */ 28#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 4dfe0bb3c322..03f830b48148 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -23,8 +23,10 @@ int eprintf(int level, const char *fmt, ...)
23 23
24 if (verbose >= level) { 24 if (verbose >= level) {
25 va_start(args, fmt); 25 va_start(args, fmt);
26 if (use_browser > 0) 26 if (use_browser == 1)
27 ret = ui_helpline__show_help(fmt, args); 27 ret = ui_helpline__show_help(fmt, args);
28 else if (use_browser == 2)
29 ret = perf_gtk__show_helpline(fmt, args);
28 else 30 else
29 ret = vfprintf(stderr, fmt, args); 31 ret = vfprintf(stderr, fmt, args);
30 va_end(args); 32 va_end(args);
@@ -47,7 +49,7 @@ int dump_printf(const char *fmt, ...)
47 return ret; 49 return ret;
48} 50}
49 51
50#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 52#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
51int ui__warning(const char *format, ...) 53int ui__warning(const char *format, ...)
52{ 54{
53 va_list args; 55 va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 015c91dbc096..dec98750b484 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -4,6 +4,7 @@
4 4
5#include <stdbool.h> 5#include <stdbool.h>
6#include "event.h" 6#include "event.h"
7#include "../ui/helpline.h"
7 8
8extern int verbose; 9extern int verbose;
9extern bool quiet, dump_trace; 10extern bool quiet, dump_trace;
@@ -14,38 +15,33 @@ void trace_event(union perf_event *event);
14struct ui_progress; 15struct ui_progress;
15struct perf_error_ops; 16struct perf_error_ops;
16 17
17#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 18#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
18static inline int ui_helpline__show_help(const char *format __used, va_list ap __used) 19
19{ 20#include "../ui/progress.h"
20 return 0; 21int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
21} 22#include "../ui/util.h"
22 23
23static inline void ui_progress__update(u64 curr __used, u64 total __used, 24#else
24 const char *title __used) {} 25
26static inline void ui_progress__update(u64 curr __maybe_unused,
27 u64 total __maybe_unused,
28 const char *title __maybe_unused) {}
25 29
26#define ui__error(format, arg...) ui__warning(format, ##arg) 30#define ui__error(format, arg...) ui__warning(format, ##arg)
27 31
28static inline int 32static inline int
29perf_error__register(struct perf_error_ops *eops __used) 33perf_error__register(struct perf_error_ops *eops __maybe_unused)
30{ 34{
31 return 0; 35 return 0;
32} 36}
33 37
34static inline int 38static inline int
35perf_error__unregister(struct perf_error_ops *eops __used) 39perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
36{ 40{
37 return 0; 41 return 0;
38} 42}
39 43
40#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ 44#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
41
42extern char ui_helpline__last_msg[];
43int ui_helpline__show_help(const char *format, va_list ap);
44#include "../ui/progress.h"
45int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
46#include "../ui/util.h"
47
48#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
49 45
50int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 46int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
51int ui__error_paranoid(void); 47int ui__error_paranoid(void);
diff --git a/tools/perf/util/dso-test-data.c b/tools/perf/util/dso-test-data.c
index 541cdc72c7df..c6caedeb1d6b 100644
--- a/tools/perf/util/dso-test-data.c
+++ b/tools/perf/util/dso-test-data.c
@@ -23,7 +23,7 @@ static char *test_file(int size)
23 int fd, i; 23 int fd, i;
24 unsigned char *buf; 24 unsigned char *buf;
25 25
26 fd = mkostemp(templ, O_CREAT|O_WRONLY|O_TRUNC); 26 fd = mkstemp(templ);
27 27
28 buf = malloc(size); 28 buf = malloc(size);
29 if (!buf) { 29 if (!buf) {
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index ee51e9b4dc09..3e5f5430a28a 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -804,6 +804,8 @@ int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
804 tmp = "union "; 804 tmp = "union ";
805 else if (tag == DW_TAG_structure_type) 805 else if (tag == DW_TAG_structure_type)
806 tmp = "struct "; 806 tmp = "struct ";
807 else if (tag == DW_TAG_enumeration_type)
808 tmp = "enum ";
807 /* Write a base name */ 809 /* Write a base name */
808 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type)); 810 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
809 return (ret >= len) ? -E2BIG : ret; 811 return (ret >= len) ? -E2BIG : ret;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 2a6f33cd888c..6715b1938725 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -112,7 +112,7 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
112 event->comm.header.type = PERF_RECORD_COMM; 112 event->comm.header.type = PERF_RECORD_COMM;
113 113
114 size = strlen(event->comm.comm) + 1; 114 size = strlen(event->comm.comm) + 1;
115 size = ALIGN(size, sizeof(u64)); 115 size = PERF_ALIGN(size, sizeof(u64));
116 memset(event->comm.comm + size, 0, machine->id_hdr_size); 116 memset(event->comm.comm + size, 0, machine->id_hdr_size);
117 event->comm.header.size = (sizeof(event->comm) - 117 event->comm.header.size = (sizeof(event->comm) -
118 (sizeof(event->comm.comm) - size) + 118 (sizeof(event->comm.comm) - size) +
@@ -120,7 +120,9 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
120 if (!full) { 120 if (!full) {
121 event->comm.tid = pid; 121 event->comm.tid = pid;
122 122
123 process(tool, event, &synth_sample, machine); 123 if (process(tool, event, &synth_sample, machine) != 0)
124 return -1;
125
124 goto out; 126 goto out;
125 } 127 }
126 128
@@ -143,7 +145,7 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
143 sizeof(event->comm.comm)); 145 sizeof(event->comm.comm));
144 146
145 size = strlen(event->comm.comm) + 1; 147 size = strlen(event->comm.comm) + 1;
146 size = ALIGN(size, sizeof(u64)); 148 size = PERF_ALIGN(size, sizeof(u64));
147 memset(event->comm.comm + size, 0, machine->id_hdr_size); 149 memset(event->comm.comm + size, 0, machine->id_hdr_size);
148 event->comm.header.size = (sizeof(event->comm) - 150 event->comm.header.size = (sizeof(event->comm) -
149 (sizeof(event->comm.comm) - size) + 151 (sizeof(event->comm.comm) - size) +
@@ -151,7 +153,10 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
151 153
152 event->comm.tid = pid; 154 event->comm.tid = pid;
153 155
154 process(tool, event, &synth_sample, machine); 156 if (process(tool, event, &synth_sample, machine) != 0) {
157 tgid = -1;
158 break;
159 }
155 } 160 }
156 161
157 closedir(tasks); 162 closedir(tasks);
@@ -167,6 +172,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
167{ 172{
168 char filename[PATH_MAX]; 173 char filename[PATH_MAX];
169 FILE *fp; 174 FILE *fp;
175 int rc = 0;
170 176
171 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); 177 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
172 178
@@ -222,7 +228,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
222 size = strlen(execname); 228 size = strlen(execname);
223 execname[size - 1] = '\0'; /* Remove \n */ 229 execname[size - 1] = '\0'; /* Remove \n */
224 memcpy(event->mmap.filename, execname, size); 230 memcpy(event->mmap.filename, execname, size);
225 size = ALIGN(size, sizeof(u64)); 231 size = PERF_ALIGN(size, sizeof(u64));
226 event->mmap.len -= event->mmap.start; 232 event->mmap.len -= event->mmap.start;
227 event->mmap.header.size = (sizeof(event->mmap) - 233 event->mmap.header.size = (sizeof(event->mmap) -
228 (sizeof(event->mmap.filename) - size)); 234 (sizeof(event->mmap.filename) - size));
@@ -231,18 +237,22 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
231 event->mmap.pid = tgid; 237 event->mmap.pid = tgid;
232 event->mmap.tid = pid; 238 event->mmap.tid = pid;
233 239
234 process(tool, event, &synth_sample, machine); 240 if (process(tool, event, &synth_sample, machine) != 0) {
241 rc = -1;
242 break;
243 }
235 } 244 }
236 } 245 }
237 246
238 fclose(fp); 247 fclose(fp);
239 return 0; 248 return rc;
240} 249}
241 250
242int perf_event__synthesize_modules(struct perf_tool *tool, 251int perf_event__synthesize_modules(struct perf_tool *tool,
243 perf_event__handler_t process, 252 perf_event__handler_t process,
244 struct machine *machine) 253 struct machine *machine)
245{ 254{
255 int rc = 0;
246 struct rb_node *nd; 256 struct rb_node *nd;
247 struct map_groups *kmaps = &machine->kmaps; 257 struct map_groups *kmaps = &machine->kmaps;
248 union perf_event *event = zalloc((sizeof(event->mmap) + 258 union perf_event *event = zalloc((sizeof(event->mmap) +
@@ -272,7 +282,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
272 if (pos->dso->kernel) 282 if (pos->dso->kernel)
273 continue; 283 continue;
274 284
275 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 285 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
276 event->mmap.header.type = PERF_RECORD_MMAP; 286 event->mmap.header.type = PERF_RECORD_MMAP;
277 event->mmap.header.size = (sizeof(event->mmap) - 287 event->mmap.header.size = (sizeof(event->mmap) -
278 (sizeof(event->mmap.filename) - size)); 288 (sizeof(event->mmap.filename) - size));
@@ -284,11 +294,14 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
284 294
285 memcpy(event->mmap.filename, pos->dso->long_name, 295 memcpy(event->mmap.filename, pos->dso->long_name,
286 pos->dso->long_name_len + 1); 296 pos->dso->long_name_len + 1);
287 process(tool, event, &synth_sample, machine); 297 if (process(tool, event, &synth_sample, machine) != 0) {
298 rc = -1;
299 break;
300 }
288 } 301 }
289 302
290 free(event); 303 free(event);
291 return 0; 304 return rc;
292} 305}
293 306
294static int __event__synthesize_thread(union perf_event *comm_event, 307static int __event__synthesize_thread(union perf_event *comm_event,
@@ -392,12 +405,16 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
392 if (*end) /* only interested in proper numerical dirents */ 405 if (*end) /* only interested in proper numerical dirents */
393 continue; 406 continue;
394 407
395 __event__synthesize_thread(comm_event, mmap_event, pid, 1, 408 if (__event__synthesize_thread(comm_event, mmap_event, pid, 1,
396 process, tool, machine); 409 process, tool, machine) != 0) {
410 err = -1;
411 goto out_closedir;
412 }
397 } 413 }
398 414
399 closedir(proc);
400 err = 0; 415 err = 0;
416out_closedir:
417 closedir(proc);
401out_free_mmap: 418out_free_mmap:
402 free(mmap_event); 419 free(mmap_event);
403out_free_comm: 420out_free_comm:
@@ -412,7 +429,7 @@ struct process_symbol_args {
412}; 429};
413 430
414static int find_symbol_cb(void *arg, const char *name, char type, 431static int find_symbol_cb(void *arg, const char *name, char type,
415 u64 start, u64 end __used) 432 u64 start)
416{ 433{
417 struct process_symbol_args *args = arg; 434 struct process_symbol_args *args = arg;
418 435
@@ -477,7 +494,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
477 map = machine->vmlinux_maps[MAP__FUNCTION]; 494 map = machine->vmlinux_maps[MAP__FUNCTION];
478 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 495 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
479 "%s%s", mmap_name, symbol_name) + 1; 496 "%s%s", mmap_name, symbol_name) + 1;
480 size = ALIGN(size, sizeof(u64)); 497 size = PERF_ALIGN(size, sizeof(u64));
481 event->mmap.header.type = PERF_RECORD_MMAP; 498 event->mmap.header.type = PERF_RECORD_MMAP;
482 event->mmap.header.size = (sizeof(event->mmap) - 499 event->mmap.header.size = (sizeof(event->mmap) -
483 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size); 500 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
@@ -497,9 +514,9 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
497 return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid); 514 return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid);
498} 515}
499 516
500int perf_event__process_comm(struct perf_tool *tool __used, 517int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
501 union perf_event *event, 518 union perf_event *event,
502 struct perf_sample *sample __used, 519 struct perf_sample *sample __maybe_unused,
503 struct machine *machine) 520 struct machine *machine)
504{ 521{
505 struct thread *thread = machine__findnew_thread(machine, event->comm.tid); 522 struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
@@ -515,10 +532,10 @@ int perf_event__process_comm(struct perf_tool *tool __used,
515 return 0; 532 return 0;
516} 533}
517 534
518int perf_event__process_lost(struct perf_tool *tool __used, 535int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
519 union perf_event *event, 536 union perf_event *event,
520 struct perf_sample *sample __used, 537 struct perf_sample *sample __maybe_unused,
521 struct machine *machine __used) 538 struct machine *machine __maybe_unused)
522{ 539{
523 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 540 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
524 event->lost.id, event->lost.lost); 541 event->lost.id, event->lost.lost);
@@ -538,7 +555,8 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event,
538 maps[MAP__FUNCTION]->end = ~0ULL; 555 maps[MAP__FUNCTION]->end = ~0ULL;
539} 556}
540 557
541static int perf_event__process_kernel_mmap(struct perf_tool *tool __used, 558static int perf_event__process_kernel_mmap(struct perf_tool *tool
559 __maybe_unused,
542 union perf_event *event, 560 union perf_event *event,
543 struct machine *machine) 561 struct machine *machine)
544{ 562{
@@ -640,7 +658,7 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
640 658
641int perf_event__process_mmap(struct perf_tool *tool, 659int perf_event__process_mmap(struct perf_tool *tool,
642 union perf_event *event, 660 union perf_event *event,
643 struct perf_sample *sample __used, 661 struct perf_sample *sample __maybe_unused,
644 struct machine *machine) 662 struct machine *machine)
645{ 663{
646 struct thread *thread; 664 struct thread *thread;
@@ -684,9 +702,9 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
684 event->fork.ppid, event->fork.ptid); 702 event->fork.ppid, event->fork.ptid);
685} 703}
686 704
687int perf_event__process_task(struct perf_tool *tool __used, 705int perf_event__process_task(struct perf_tool *tool __maybe_unused,
688 union perf_event *event, 706 union perf_event *event,
689 struct perf_sample *sample __used, 707 struct perf_sample *sample __maybe_unused,
690 struct machine *machine) 708 struct machine *machine)
691{ 709{
692 struct thread *thread = machine__findnew_thread(machine, event->fork.tid); 710 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
@@ -886,8 +904,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
886 al->sym = map__find_symbol(al->map, al->addr, filter); 904 al->sym = map__find_symbol(al->map, al->addr, filter);
887 } 905 }
888 906
889 if (symbol_conf.sym_list && al->sym && 907 if (symbol_conf.sym_list &&
890 !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) 908 (!al->sym || !strlist__has_entry(symbol_conf.sym_list,
909 al->sym->name)))
891 goto out_filtered; 910 goto out_filtered;
892 911
893 return 0; 912 return 0;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index d84870b06426..21b99e741a87 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -69,6 +69,16 @@ struct sample_event {
69 u64 array[]; 69 u64 array[];
70}; 70};
71 71
72struct regs_dump {
73 u64 *regs;
74};
75
76struct stack_dump {
77 u16 offset;
78 u64 size;
79 char *data;
80};
81
72struct perf_sample { 82struct perf_sample {
73 u64 ip; 83 u64 ip;
74 u32 pid, tid; 84 u32 pid, tid;
@@ -82,6 +92,8 @@ struct perf_sample {
82 void *raw_data; 92 void *raw_data;
83 struct ip_callchain *callchain; 93 struct ip_callchain *callchain;
84 struct branch_stack *branch_stack; 94 struct branch_stack *branch_stack;
95 struct regs_dump user_regs;
96 struct stack_dump user_stack;
85}; 97};
86 98
87#define BUILD_ID_SIZE 20 99#define BUILD_ID_SIZE 20
@@ -89,7 +101,7 @@ struct perf_sample {
89struct build_id_event { 101struct build_id_event {
90 struct perf_event_header header; 102 struct perf_event_header header;
91 pid_t pid; 103 pid_t pid;
92 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; 104 u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
93 char filename[]; 105 char filename[];
94}; 106};
95 107
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 9b38681add9e..186b87730396 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -57,7 +57,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist,
57 if (evlist->cpus->map[0] < 0) 57 if (evlist->cpus->map[0] < 0)
58 opts->no_inherit = true; 58 opts->no_inherit = true;
59 59
60 first = list_entry(evlist->entries.next, struct perf_evsel, node); 60 first = perf_evlist__first(evlist);
61 61
62 list_for_each_entry(evsel, &evlist->entries, node) { 62 list_for_each_entry(evsel, &evlist->entries, node) {
63 perf_evsel__config(evsel, opts, first); 63 perf_evsel__config(evsel, opts, first);
@@ -108,6 +108,25 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
108 evlist->nr_entries += nr_entries; 108 evlist->nr_entries += nr_entries;
109} 109}
110 110
111void __perf_evlist__set_leader(struct list_head *list)
112{
113 struct perf_evsel *evsel, *leader;
114
115 leader = list_entry(list->next, struct perf_evsel, node);
116 leader->leader = NULL;
117
118 list_for_each_entry(evsel, list, node) {
119 if (evsel != leader)
120 evsel->leader = leader;
121 }
122}
123
124void perf_evlist__set_leader(struct perf_evlist *evlist)
125{
126 if (evlist->nr_entries)
127 __perf_evlist__set_leader(&evlist->entries);
128}
129
111int perf_evlist__add_default(struct perf_evlist *evlist) 130int perf_evlist__add_default(struct perf_evlist *evlist)
112{ 131{
113 struct perf_event_attr attr = { 132 struct perf_event_attr attr = {
@@ -135,8 +154,8 @@ error:
135 return -ENOMEM; 154 return -ENOMEM;
136} 155}
137 156
138int perf_evlist__add_attrs(struct perf_evlist *evlist, 157static int perf_evlist__add_attrs(struct perf_evlist *evlist,
139 struct perf_event_attr *attrs, size_t nr_attrs) 158 struct perf_event_attr *attrs, size_t nr_attrs)
140{ 159{
141 struct perf_evsel *evsel, *n; 160 struct perf_evsel *evsel, *n;
142 LIST_HEAD(head); 161 LIST_HEAD(head);
@@ -170,60 +189,6 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
170 return perf_evlist__add_attrs(evlist, attrs, nr_attrs); 189 return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
171} 190}
172 191
173static int trace_event__id(const char *evname)
174{
175 char *filename, *colon;
176 int err = -1, fd;
177
178 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
179 return -1;
180
181 colon = strrchr(filename, ':');
182 if (colon != NULL)
183 *colon = '/';
184
185 fd = open(filename, O_RDONLY);
186 if (fd >= 0) {
187 char id[16];
188 if (read(fd, id, sizeof(id)) > 0)
189 err = atoi(id);
190 close(fd);
191 }
192
193 free(filename);
194 return err;
195}
196
197int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
198 const char *tracepoints[],
199 size_t nr_tracepoints)
200{
201 int err;
202 size_t i;
203 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
204
205 if (attrs == NULL)
206 return -1;
207
208 for (i = 0; i < nr_tracepoints; i++) {
209 err = trace_event__id(tracepoints[i]);
210
211 if (err < 0)
212 goto out_free_attrs;
213
214 attrs[i].type = PERF_TYPE_TRACEPOINT;
215 attrs[i].config = err;
216 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
217 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
218 attrs[i].sample_period = 1;
219 }
220
221 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
222out_free_attrs:
223 free(attrs);
224 return err;
225}
226
227struct perf_evsel * 192struct perf_evsel *
228perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 193perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
229{ 194{
@@ -238,32 +203,18 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
238 return NULL; 203 return NULL;
239} 204}
240 205
241int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, 206int perf_evlist__add_newtp(struct perf_evlist *evlist,
242 const struct perf_evsel_str_handler *assocs, 207 const char *sys, const char *name, void *handler)
243 size_t nr_assocs)
244{ 208{
245 struct perf_evsel *evsel; 209 struct perf_evsel *evsel;
246 int err;
247 size_t i;
248
249 for (i = 0; i < nr_assocs; i++) {
250 err = trace_event__id(assocs[i].name);
251 if (err < 0)
252 goto out;
253 210
254 evsel = perf_evlist__find_tracepoint_by_id(evlist, err); 211 evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
255 if (evsel == NULL) 212 if (evsel == NULL)
256 continue; 213 return -1;
257
258 err = -EEXIST;
259 if (evsel->handler.func != NULL)
260 goto out;
261 evsel->handler.func = assocs[i].handler;
262 }
263 214
264 err = 0; 215 evsel->handler.func = handler;
265out: 216 perf_evlist__add(evlist, evsel);
266 return err; 217 return 0;
267} 218}
268 219
269void perf_evlist__disable(struct perf_evlist *evlist) 220void perf_evlist__disable(struct perf_evlist *evlist)
@@ -285,7 +236,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
285 int cpu, thread; 236 int cpu, thread;
286 struct perf_evsel *pos; 237 struct perf_evsel *pos;
287 238
288 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 239 for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
289 list_for_each_entry(pos, &evlist->entries, node) { 240 list_for_each_entry(pos, &evlist->entries, node) {
290 for (thread = 0; thread < evlist->threads->nr; thread++) 241 for (thread = 0; thread < evlist->threads->nr; thread++)
291 ioctl(FD(pos, cpu, thread), 242 ioctl(FD(pos, cpu, thread),
@@ -296,7 +247,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
296 247
297static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 248static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
298{ 249{
299 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; 250 int nfds = cpu_map__nr(evlist->cpus) * evlist->threads->nr * evlist->nr_entries;
300 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 251 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
301 return evlist->pollfd != NULL ? 0 : -ENOMEM; 252 return evlist->pollfd != NULL ? 0 : -ENOMEM;
302} 253}
@@ -357,7 +308,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
357 int hash; 308 int hash;
358 309
359 if (evlist->nr_entries == 1) 310 if (evlist->nr_entries == 1)
360 return list_entry(evlist->entries.next, struct perf_evsel, node); 311 return perf_evlist__first(evlist);
361 312
362 hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 313 hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
363 head = &evlist->heads[hash]; 314 head = &evlist->heads[hash];
@@ -367,7 +318,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
367 return sid->evsel; 318 return sid->evsel;
368 319
369 if (!perf_evlist__sample_id_all(evlist)) 320 if (!perf_evlist__sample_id_all(evlist))
370 return list_entry(evlist->entries.next, struct perf_evsel, node); 321 return perf_evlist__first(evlist);
371 322
372 return NULL; 323 return NULL;
373} 324}
@@ -456,8 +407,8 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
456 407
457static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 408static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
458{ 409{
459 evlist->nr_mmaps = evlist->cpus->nr; 410 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
460 if (evlist->cpus->map[0] == -1) 411 if (cpu_map__all(evlist->cpus))
461 evlist->nr_mmaps = evlist->threads->nr; 412 evlist->nr_mmaps = evlist->threads->nr;
462 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 413 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
463 return evlist->mmap != NULL ? 0 : -ENOMEM; 414 return evlist->mmap != NULL ? 0 : -ENOMEM;
@@ -603,11 +554,11 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
603 list_for_each_entry(evsel, &evlist->entries, node) { 554 list_for_each_entry(evsel, &evlist->entries, node) {
604 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 555 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
605 evsel->sample_id == NULL && 556 evsel->sample_id == NULL &&
606 perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0) 557 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
607 return -ENOMEM; 558 return -ENOMEM;
608 } 559 }
609 560
610 if (evlist->cpus->map[0] == -1) 561 if (cpu_map__all(cpus))
611 return perf_evlist__mmap_per_thread(evlist, prot, mask); 562 return perf_evlist__mmap_per_thread(evlist, prot, mask);
612 563
613 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 564 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
@@ -647,39 +598,44 @@ void perf_evlist__delete_maps(struct perf_evlist *evlist)
647 evlist->threads = NULL; 598 evlist->threads = NULL;
648} 599}
649 600
650int perf_evlist__set_filters(struct perf_evlist *evlist) 601int perf_evlist__apply_filters(struct perf_evlist *evlist)
651{ 602{
652 const struct thread_map *threads = evlist->threads;
653 const struct cpu_map *cpus = evlist->cpus;
654 struct perf_evsel *evsel; 603 struct perf_evsel *evsel;
655 char *filter; 604 int err = 0;
656 int thread; 605 const int ncpus = cpu_map__nr(evlist->cpus),
657 int cpu; 606 nthreads = evlist->threads->nr;
658 int err;
659 int fd;
660 607
661 list_for_each_entry(evsel, &evlist->entries, node) { 608 list_for_each_entry(evsel, &evlist->entries, node) {
662 filter = evsel->filter; 609 if (evsel->filter == NULL)
663 if (!filter)
664 continue; 610 continue;
665 for (cpu = 0; cpu < cpus->nr; cpu++) { 611
666 for (thread = 0; thread < threads->nr; thread++) { 612 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter);
667 fd = FD(evsel, cpu, thread); 613 if (err)
668 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter); 614 break;
669 if (err)
670 return err;
671 }
672 }
673 } 615 }
674 616
675 return 0; 617 return err;
676} 618}
677 619
678bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) 620int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
679{ 621{
680 struct perf_evsel *pos, *first; 622 struct perf_evsel *evsel;
623 int err = 0;
624 const int ncpus = cpu_map__nr(evlist->cpus),
625 nthreads = evlist->threads->nr;
681 626
682 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); 627 list_for_each_entry(evsel, &evlist->entries, node) {
628 err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter);
629 if (err)
630 break;
631 }
632
633 return err;
634}
635
636bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
637{
638 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
683 639
684 list_for_each_entry_continue(pos, &evlist->entries, node) { 640 list_for_each_entry_continue(pos, &evlist->entries, node) {
685 if (first->attr.sample_type != pos->attr.sample_type) 641 if (first->attr.sample_type != pos->attr.sample_type)
@@ -689,23 +645,19 @@ bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist)
689 return true; 645 return true;
690} 646}
691 647
692u64 perf_evlist__sample_type(const struct perf_evlist *evlist) 648u64 perf_evlist__sample_type(struct perf_evlist *evlist)
693{ 649{
694 struct perf_evsel *first; 650 struct perf_evsel *first = perf_evlist__first(evlist);
695
696 first = list_entry(evlist->entries.next, struct perf_evsel, node);
697 return first->attr.sample_type; 651 return first->attr.sample_type;
698} 652}
699 653
700u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist) 654u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
701{ 655{
702 struct perf_evsel *first; 656 struct perf_evsel *first = perf_evlist__first(evlist);
703 struct perf_sample *data; 657 struct perf_sample *data;
704 u64 sample_type; 658 u64 sample_type;
705 u16 size = 0; 659 u16 size = 0;
706 660
707 first = list_entry(evlist->entries.next, struct perf_evsel, node);
708
709 if (!first->attr.sample_id_all) 661 if (!first->attr.sample_id_all)
710 goto out; 662 goto out;
711 663
@@ -729,11 +681,9 @@ out:
729 return size; 681 return size;
730} 682}
731 683
732bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) 684bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
733{ 685{
734 struct perf_evsel *pos, *first; 686 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
735
736 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
737 687
738 list_for_each_entry_continue(pos, &evlist->entries, node) { 688 list_for_each_entry_continue(pos, &evlist->entries, node) {
739 if (first->attr.sample_id_all != pos->attr.sample_id_all) 689 if (first->attr.sample_id_all != pos->attr.sample_id_all)
@@ -743,11 +693,9 @@ bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
743 return true; 693 return true;
744} 694}
745 695
746bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) 696bool perf_evlist__sample_id_all(struct perf_evlist *evlist)
747{ 697{
748 struct perf_evsel *first; 698 struct perf_evsel *first = perf_evlist__first(evlist);
749
750 first = list_entry(evlist->entries.next, struct perf_evsel, node);
751 return first->attr.sample_id_all; 699 return first->attr.sample_id_all;
752} 700}
753 701
@@ -757,21 +705,13 @@ void perf_evlist__set_selected(struct perf_evlist *evlist,
757 evlist->selected = evsel; 705 evlist->selected = evsel;
758} 706}
759 707
760int perf_evlist__open(struct perf_evlist *evlist, bool group) 708int perf_evlist__open(struct perf_evlist *evlist)
761{ 709{
762 struct perf_evsel *evsel, *first; 710 struct perf_evsel *evsel;
763 int err, ncpus, nthreads; 711 int err, ncpus, nthreads;
764 712
765 first = list_entry(evlist->entries.next, struct perf_evsel, node);
766
767 list_for_each_entry(evsel, &evlist->entries, node) { 713 list_for_each_entry(evsel, &evlist->entries, node) {
768 struct xyarray *group_fd = NULL; 714 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
769
770 if (group && evsel != first)
771 group_fd = first->fd;
772
773 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads,
774 group, group_fd);
775 if (err < 0) 715 if (err < 0)
776 goto out_err; 716 goto out_err;
777 } 717 }
@@ -883,8 +823,21 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
883} 823}
884 824
885int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 825int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
886 struct perf_sample *sample, bool swapped) 826 struct perf_sample *sample)
887{ 827{
888 struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node); 828 struct perf_evsel *evsel = perf_evlist__first(evlist);
889 return perf_evsel__parse_sample(e, event, sample, swapped); 829 return perf_evsel__parse_sample(evsel, event, sample);
830}
831
832size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
833{
834 struct perf_evsel *evsel;
835 size_t printed = 0;
836
837 list_for_each_entry(evsel, &evlist->entries, node) {
838 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
839 perf_evsel__name(evsel));
840 }
841
842 return printed + fprintf(fp, "\n");;
890} 843}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 528c1acd9298..56003f779e60 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -5,6 +5,7 @@
5#include <stdio.h> 5#include <stdio.h>
6#include "../perf.h" 6#include "../perf.h"
7#include "event.h" 7#include "event.h"
8#include "evsel.h"
8#include "util.h" 9#include "util.h"
9#include <unistd.h> 10#include <unistd.h>
10 11
@@ -41,8 +42,6 @@ struct perf_evsel_str_handler {
41 void *handler; 42 void *handler;
42}; 43};
43 44
44struct perf_evsel;
45
46struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 45struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
47 struct thread_map *threads); 46 struct thread_map *threads);
48void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 47void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
@@ -52,26 +51,16 @@ void perf_evlist__delete(struct perf_evlist *evlist);
52 51
53void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 52void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
54int perf_evlist__add_default(struct perf_evlist *evlist); 53int perf_evlist__add_default(struct perf_evlist *evlist);
55int perf_evlist__add_attrs(struct perf_evlist *evlist,
56 struct perf_event_attr *attrs, size_t nr_attrs);
57int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 54int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
58 struct perf_event_attr *attrs, size_t nr_attrs); 55 struct perf_event_attr *attrs, size_t nr_attrs);
59int perf_evlist__add_tracepoints(struct perf_evlist *evlist, 56
60 const char *tracepoints[], size_t nr_tracepoints);
61int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
62 const struct perf_evsel_str_handler *assocs,
63 size_t nr_assocs);
64
65#define perf_evlist__add_attrs_array(evlist, array) \
66 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
67#define perf_evlist__add_default_attrs(evlist, array) \ 57#define perf_evlist__add_default_attrs(evlist, array) \
68 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 58 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
69 59
70#define perf_evlist__add_tracepoints_array(evlist, array) \ 60int perf_evlist__add_newtp(struct perf_evlist *evlist,
71 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array)) 61 const char *sys, const char *name, void *handler);
72 62
73#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \ 63int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
75 64
76struct perf_evsel * 65struct perf_evsel *
77perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); 66perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
@@ -85,7 +74,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
85 74
86union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); 75union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
87 76
88int perf_evlist__open(struct perf_evlist *evlist, bool group); 77int perf_evlist__open(struct perf_evlist *evlist);
89 78
90void perf_evlist__config_attrs(struct perf_evlist *evlist, 79void perf_evlist__config_attrs(struct perf_evlist *evlist,
91 struct perf_record_opts *opts); 80 struct perf_record_opts *opts);
@@ -116,20 +105,34 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
116int perf_evlist__create_maps(struct perf_evlist *evlist, 105int perf_evlist__create_maps(struct perf_evlist *evlist,
117 struct perf_target *target); 106 struct perf_target *target);
118void perf_evlist__delete_maps(struct perf_evlist *evlist); 107void perf_evlist__delete_maps(struct perf_evlist *evlist);
119int perf_evlist__set_filters(struct perf_evlist *evlist); 108int perf_evlist__apply_filters(struct perf_evlist *evlist);
109
110void __perf_evlist__set_leader(struct list_head *list);
111void perf_evlist__set_leader(struct perf_evlist *evlist);
120 112
121u64 perf_evlist__sample_type(const struct perf_evlist *evlist); 113u64 perf_evlist__sample_type(struct perf_evlist *evlist);
122bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); 114bool perf_evlist__sample_id_all(struct perf_evlist *evlist);
123u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); 115u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);
124 116
125int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 117int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
126 struct perf_sample *sample, bool swapped); 118 struct perf_sample *sample);
127 119
128bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 120bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);
129bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 121bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
130 122
131void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 123void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
132 struct list_head *list, 124 struct list_head *list,
133 int nr_entries); 125 int nr_entries);
134 126
127static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
128{
129 return list_entry(evlist->entries.next, struct perf_evsel, node);
130}
131
132static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
133{
134 return list_entry(evlist->entries.prev, struct perf_evsel, node);
135}
136
137size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
135#endif /* __PERF_EVLIST_H */ 138#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2eaae140def2..618d41140abd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -8,7 +8,10 @@
8 */ 8 */
9 9
10#include <byteswap.h> 10#include <byteswap.h>
11#include <linux/bitops.h>
11#include "asm/bug.h" 12#include "asm/bug.h"
13#include "debugfs.h"
14#include "event-parse.h"
12#include "evsel.h" 15#include "evsel.h"
13#include "evlist.h" 16#include "evlist.h"
14#include "util.h" 17#include "util.h"
@@ -16,9 +19,10 @@
16#include "thread_map.h" 19#include "thread_map.h"
17#include "target.h" 20#include "target.h"
18#include "../../../include/linux/hw_breakpoint.h" 21#include "../../../include/linux/hw_breakpoint.h"
22#include "../../../include/uapi/linux/perf_event.h"
23#include "perf_regs.h"
19 24
20#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 25#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))
22 26
23static int __perf_evsel__sample_size(u64 sample_type) 27static int __perf_evsel__sample_size(u64 sample_type)
24{ 28{
@@ -66,7 +70,80 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
66 return evsel; 70 return evsel;
67} 71}
68 72
69static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { 73struct event_format *event_format__new(const char *sys, const char *name)
74{
75 int fd, n;
76 char *filename;
77 void *bf = NULL, *nbf;
78 size_t size = 0, alloc_size = 0;
79 struct event_format *format = NULL;
80
81 if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0)
82 goto out;
83
84 fd = open(filename, O_RDONLY);
85 if (fd < 0)
86 goto out_free_filename;
87
88 do {
89 if (size == alloc_size) {
90 alloc_size += BUFSIZ;
91 nbf = realloc(bf, alloc_size);
92 if (nbf == NULL)
93 goto out_free_bf;
94 bf = nbf;
95 }
96
97 n = read(fd, bf + size, BUFSIZ);
98 if (n < 0)
99 goto out_free_bf;
100 size += n;
101 } while (n > 0);
102
103 pevent_parse_format(&format, bf, size, sys);
104
105out_free_bf:
106 free(bf);
107 close(fd);
108out_free_filename:
109 free(filename);
110out:
111 return format;
112}
113
114struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx)
115{
116 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
117
118 if (evsel != NULL) {
119 struct perf_event_attr attr = {
120 .type = PERF_TYPE_TRACEPOINT,
121 .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
122 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
123 };
124
125 if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
126 goto out_free;
127
128 evsel->tp_format = event_format__new(sys, name);
129 if (evsel->tp_format == NULL)
130 goto out_free;
131
132 event_attr_init(&attr);
133 attr.config = evsel->tp_format->id;
134 attr.sample_period = 1;
135 perf_evsel__init(evsel, &attr, idx);
136 }
137
138 return evsel;
139
140out_free:
141 free(evsel->name);
142 free(evsel);
143 return NULL;
144}
145
146const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
70 "cycles", 147 "cycles",
71 "instructions", 148 "instructions",
72 "cache-references", 149 "cache-references",
@@ -129,12 +206,12 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
129 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); 206 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
130} 207}
131 208
132static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { 209const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
133 "cpu-clock", 210 "cpu-clock",
134 "task-clock", 211 "task-clock",
135 "page-faults", 212 "page-faults",
136 "context-switches", 213 "context-switches",
137 "CPU-migrations", 214 "cpu-migrations",
138 "minor-faults", 215 "minor-faults",
139 "major-faults", 216 "major-faults",
140 "alignment-faults", 217 "alignment-faults",
@@ -317,7 +394,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
317 break; 394 break;
318 395
319 default: 396 default:
320 scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); 397 scnprintf(bf, sizeof(bf), "unknown attr type: %d",
398 evsel->attr.type);
321 break; 399 break;
322 } 400 }
323 401
@@ -367,9 +445,18 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
367 attr->mmap_data = track; 445 attr->mmap_data = track;
368 } 446 }
369 447
370 if (opts->call_graph) 448 if (opts->call_graph) {
371 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 449 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
372 450
451 if (opts->call_graph == CALLCHAIN_DWARF) {
452 attr->sample_type |= PERF_SAMPLE_REGS_USER |
453 PERF_SAMPLE_STACK_USER;
454 attr->sample_regs_user = PERF_REGS_MASK;
455 attr->sample_stack_user = opts->stack_dump_size;
456 attr->exclude_callchain_user = 1;
457 }
458 }
459
373 if (perf_target__has_cpu(&opts->target)) 460 if (perf_target__has_cpu(&opts->target))
374 attr->sample_type |= PERF_SAMPLE_CPU; 461 attr->sample_type |= PERF_SAMPLE_CPU;
375 462
@@ -421,6 +508,24 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
421 return evsel->fd != NULL ? 0 : -ENOMEM; 508 return evsel->fd != NULL ? 0 : -ENOMEM;
422} 509}
423 510
511int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
512 const char *filter)
513{
514 int cpu, thread;
515
516 for (cpu = 0; cpu < ncpus; cpu++) {
517 for (thread = 0; thread < nthreads; thread++) {
518 int fd = FD(evsel, cpu, thread),
519 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);
520
521 if (err)
522 return err;
523 }
524 }
525
526 return 0;
527}
528
424int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 529int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
425{ 530{
426 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 531 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
@@ -481,6 +586,9 @@ void perf_evsel__delete(struct perf_evsel *evsel)
481{ 586{
482 perf_evsel__exit(evsel); 587 perf_evsel__exit(evsel);
483 close_cgroup(evsel->cgrp); 588 close_cgroup(evsel->cgrp);
589 free(evsel->group_name);
590 if (evsel->tp_format)
591 pevent_free_format(evsel->tp_format);
484 free(evsel->name); 592 free(evsel->name);
485 free(evsel); 593 free(evsel);
486} 594}
@@ -556,9 +664,28 @@ int __perf_evsel__read(struct perf_evsel *evsel,
556 return 0; 664 return 0;
557} 665}
558 666
667static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
668{
669 struct perf_evsel *leader = evsel->leader;
670 int fd;
671
672 if (!leader)
673 return -1;
674
675 /*
676 * Leader must be already processed/open,
677 * if not it's a bug.
678 */
679 BUG_ON(!leader->fd);
680
681 fd = FD(leader, cpu, thread);
682 BUG_ON(fd == -1);
683
684 return fd;
685}
686
559static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 687static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
560 struct thread_map *threads, bool group, 688 struct thread_map *threads)
561 struct xyarray *group_fds)
562{ 689{
563 int cpu, thread; 690 int cpu, thread;
564 unsigned long flags = 0; 691 unsigned long flags = 0;
@@ -574,13 +701,15 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
574 } 701 }
575 702
576 for (cpu = 0; cpu < cpus->nr; cpu++) { 703 for (cpu = 0; cpu < cpus->nr; cpu++) {
577 int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
578 704
579 for (thread = 0; thread < threads->nr; thread++) { 705 for (thread = 0; thread < threads->nr; thread++) {
706 int group_fd;
580 707
581 if (!evsel->cgrp) 708 if (!evsel->cgrp)
582 pid = threads->map[thread]; 709 pid = threads->map[thread];
583 710
711 group_fd = get_group_fd(evsel, cpu, thread);
712
584 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 713 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
585 pid, 714 pid,
586 cpus->map[cpu], 715 cpus->map[cpu],
@@ -589,9 +718,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
589 err = -errno; 718 err = -errno;
590 goto out_close; 719 goto out_close;
591 } 720 }
592
593 if (group && group_fd == -1)
594 group_fd = FD(evsel, cpu, thread);
595 } 721 }
596 } 722 }
597 723
@@ -635,8 +761,7 @@ static struct {
635}; 761};
636 762
637int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 763int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
638 struct thread_map *threads, bool group, 764 struct thread_map *threads)
639 struct xyarray *group_fd)
640{ 765{
641 if (cpus == NULL) { 766 if (cpus == NULL) {
642 /* Work around old compiler warnings about strict aliasing */ 767 /* Work around old compiler warnings about strict aliasing */
@@ -646,30 +771,28 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
646 if (threads == NULL) 771 if (threads == NULL)
647 threads = &empty_thread_map.map; 772 threads = &empty_thread_map.map;
648 773
649 return __perf_evsel__open(evsel, cpus, threads, group, group_fd); 774 return __perf_evsel__open(evsel, cpus, threads);
650} 775}
651 776
652int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 777int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
653 struct cpu_map *cpus, bool group, 778 struct cpu_map *cpus)
654 struct xyarray *group_fd)
655{ 779{
656 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, 780 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map);
657 group_fd);
658} 781}
659 782
660int perf_evsel__open_per_thread(struct perf_evsel *evsel, 783int perf_evsel__open_per_thread(struct perf_evsel *evsel,
661 struct thread_map *threads, bool group, 784 struct thread_map *threads)
662 struct xyarray *group_fd)
663{ 785{
664 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, 786 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
665 group_fd);
666} 787}
667 788
668static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 789static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
669 struct perf_sample *sample, 790 const union perf_event *event,
670 bool swapped) 791 struct perf_sample *sample)
671{ 792{
793 u64 type = evsel->attr.sample_type;
672 const u64 *array = event->sample.array; 794 const u64 *array = event->sample.array;
795 bool swapped = evsel->needs_swap;
673 union u64_swap u; 796 union u64_swap u;
674 797
675 array += ((event->header.size - 798 array += ((event->header.size -
@@ -730,9 +853,11 @@ static bool sample_overlap(const union perf_event *event,
730} 853}
731 854
732int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, 855int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
733 struct perf_sample *data, bool swapped) 856 struct perf_sample *data)
734{ 857{
735 u64 type = evsel->attr.sample_type; 858 u64 type = evsel->attr.sample_type;
859 u64 regs_user = evsel->attr.sample_regs_user;
860 bool swapped = evsel->needs_swap;
736 const u64 *array; 861 const u64 *array;
737 862
738 /* 863 /*
@@ -749,7 +874,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
749 if (event->header.type != PERF_RECORD_SAMPLE) { 874 if (event->header.type != PERF_RECORD_SAMPLE) {
750 if (!evsel->attr.sample_id_all) 875 if (!evsel->attr.sample_id_all)
751 return 0; 876 return 0;
752 return perf_event__parse_id_sample(event, type, data, swapped); 877 return perf_evsel__parse_id_sample(evsel, event, data);
753 } 878 }
754 879
755 array = event->sample.array; 880 array = event->sample.array;
@@ -869,6 +994,32 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
869 sz /= sizeof(u64); 994 sz /= sizeof(u64);
870 array += sz; 995 array += sz;
871 } 996 }
997
998 if (type & PERF_SAMPLE_REGS_USER) {
999 /* First u64 tells us if we have any regs in sample. */
1000 u64 avail = *array++;
1001
1002 if (avail) {
1003 data->user_regs.regs = (u64 *)array;
1004 array += hweight_long(regs_user);
1005 }
1006 }
1007
1008 if (type & PERF_SAMPLE_STACK_USER) {
1009 u64 size = *array++;
1010
1011 data->user_stack.offset = ((char *)(array - 1)
1012 - (char *) event);
1013
1014 if (!size) {
1015 data->user_stack.size = 0;
1016 } else {
1017 data->user_stack.data = (char *)array;
1018 array += size / sizeof(*array);
1019 data->user_stack.size = *array;
1020 }
1021 }
1022
872 return 0; 1023 return 0;
873} 1024}
874 1025
@@ -947,3 +1098,72 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
947 1098
948 return 0; 1099 return 0;
949} 1100}
1101
1102struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
1103{
1104 return pevent_find_field(evsel->tp_format, name);
1105}
1106
1107void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
1108 const char *name)
1109{
1110 struct format_field *field = perf_evsel__field(evsel, name);
1111 int offset;
1112
1113 if (!field)
1114 return NULL;
1115
1116 offset = field->offset;
1117
1118 if (field->flags & FIELD_IS_DYNAMIC) {
1119 offset = *(int *)(sample->raw_data + field->offset);
1120 offset &= 0xffff;
1121 }
1122
1123 return sample->raw_data + offset;
1124}
1125
1126u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
1127 const char *name)
1128{
1129 struct format_field *field = perf_evsel__field(evsel, name);
1130 void *ptr;
1131 u64 value;
1132
1133 if (!field)
1134 return 0;
1135
1136 ptr = sample->raw_data + field->offset;
1137
1138 switch (field->size) {
1139 case 1:
1140 return *(u8 *)ptr;
1141 case 2:
1142 value = *(u16 *)ptr;
1143 break;
1144 case 4:
1145 value = *(u32 *)ptr;
1146 break;
1147 case 8:
1148 value = *(u64 *)ptr;
1149 break;
1150 default:
1151 return 0;
1152 }
1153
1154 if (!evsel->needs_swap)
1155 return value;
1156
1157 switch (field->size) {
1158 case 2:
1159 return bswap_16(value);
1160 case 4:
1161 return bswap_32(value);
1162 case 8:
1163 return bswap_64(value);
1164 default:
1165 return 0;
1166 }
1167
1168 return 0;
1169}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b559929983bb..6f94d6dea00f 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -3,7 +3,7 @@
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <stdbool.h> 5#include <stdbool.h>
6#include "../../../include/linux/perf_event.h" 6#include "../../../include/uapi/linux/perf_event.h"
7#include "types.h" 7#include "types.h"
8#include "xyarray.h" 8#include "xyarray.h"
9#include "cgroup.h" 9#include "cgroup.h"
@@ -53,9 +53,10 @@ struct perf_evsel {
53 u64 *id; 53 u64 *id;
54 struct perf_counts *counts; 54 struct perf_counts *counts;
55 int idx; 55 int idx;
56 int ids; 56 u32 ids;
57 struct hists hists; 57 struct hists hists;
58 char *name; 58 char *name;
59 struct event_format *tp_format;
59 union { 60 union {
60 void *priv; 61 void *priv;
61 off_t id_offset; 62 off_t id_offset;
@@ -65,8 +66,14 @@ struct perf_evsel {
65 void *func; 66 void *func;
66 void *data; 67 void *data;
67 } handler; 68 } handler;
69 struct cpu_map *cpus;
68 unsigned int sample_size; 70 unsigned int sample_size;
69 bool supported; 71 bool supported;
72 bool needs_swap;
73 /* parse modifier helper */
74 int exclude_GH;
75 struct perf_evsel *leader;
76 char *group_name;
70}; 77};
71 78
72struct cpu_map; 79struct cpu_map;
@@ -75,6 +82,10 @@ struct perf_evlist;
75struct perf_record_opts; 82struct perf_record_opts;
76 83
77struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); 84struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
85struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx);
86
87struct event_format *event_format__new(const char *sys, const char *name);
88
78void perf_evsel__init(struct perf_evsel *evsel, 89void perf_evsel__init(struct perf_evsel *evsel,
79 struct perf_event_attr *attr, int idx); 90 struct perf_event_attr *attr, int idx);
80void perf_evsel__exit(struct perf_evsel *evsel); 91void perf_evsel__exit(struct perf_evsel *evsel);
@@ -92,8 +103,10 @@ extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
92 [PERF_EVSEL__MAX_ALIASES]; 103 [PERF_EVSEL__MAX_ALIASES];
93extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] 104extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
94 [PERF_EVSEL__MAX_ALIASES]; 105 [PERF_EVSEL__MAX_ALIASES];
95const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] 106extern const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
96 [PERF_EVSEL__MAX_ALIASES]; 107 [PERF_EVSEL__MAX_ALIASES];
108extern const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX];
109extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
97int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, 110int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
98 char *bf, size_t size); 111 char *bf, size_t size);
99const char *perf_evsel__name(struct perf_evsel *evsel); 112const char *perf_evsel__name(struct perf_evsel *evsel);
@@ -105,21 +118,46 @@ void perf_evsel__free_fd(struct perf_evsel *evsel);
105void perf_evsel__free_id(struct perf_evsel *evsel); 118void perf_evsel__free_id(struct perf_evsel *evsel);
106void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 119void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
107 120
121int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
122 const char *filter);
123
108int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 124int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
109 struct cpu_map *cpus, bool group, 125 struct cpu_map *cpus);
110 struct xyarray *group_fds);
111int perf_evsel__open_per_thread(struct perf_evsel *evsel, 126int perf_evsel__open_per_thread(struct perf_evsel *evsel,
112 struct thread_map *threads, bool group, 127 struct thread_map *threads);
113 struct xyarray *group_fds);
114int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 128int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
115 struct thread_map *threads, bool group, 129 struct thread_map *threads);
116 struct xyarray *group_fds);
117void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads); 130void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
118 131
132struct perf_sample;
133
134void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
135 const char *name);
136u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
137 const char *name);
138
139static inline char *perf_evsel__strval(struct perf_evsel *evsel,
140 struct perf_sample *sample,
141 const char *name)
142{
143 return perf_evsel__rawptr(evsel, sample, name);
144}
145
146struct format_field;
147
148struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
149
119#define perf_evsel__match(evsel, t, c) \ 150#define perf_evsel__match(evsel, t, c) \
120 (evsel->attr.type == PERF_TYPE_##t && \ 151 (evsel->attr.type == PERF_TYPE_##t && \
121 evsel->attr.config == PERF_COUNT_##c) 152 evsel->attr.config == PERF_COUNT_##c)
122 153
154static inline bool perf_evsel__match2(struct perf_evsel *e1,
155 struct perf_evsel *e2)
156{
157 return (e1->attr.type == e2->attr.type) &&
158 (e1->attr.config == e2->attr.config);
159}
160
123int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 161int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
124 int cpu, int thread, bool scale); 162 int cpu, int thread, bool scale);
125 163
@@ -181,5 +219,10 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
181void hists__init(struct hists *hists); 219void hists__init(struct hists *hists);
182 220
183int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, 221int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
184 struct perf_sample *sample, bool swapped); 222 struct perf_sample *sample);
223
224static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
225{
226 return list_entry(evsel->node.next, struct perf_evsel, node);
227}
185#endif /* __PERF_EVSEL_H */ 228#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index f06f6fd148f8..3ac38031d534 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -21,4 +21,19 @@ do
21 p 21 p
22 }' "Documentation/perf-$cmd.txt" 22 }' "Documentation/perf-$cmd.txt"
23done 23done
24
25echo "#ifdef LIBELF_SUPPORT"
26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt |
27sort |
28while read cmd
29do
30 sed -n '
31 /^NAME/,/perf-'"$cmd"'/H
32 ${
33 x
34 s/.*perf-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/
35 p
36 }' "Documentation/perf-$cmd.txt"
37done
38echo "#endif /* LIBELF_SUPPORT */"
24echo "};" 39echo "};"
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 74ea3c2f8138..7daad237dea5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -20,11 +20,14 @@
20#include "symbol.h" 20#include "symbol.h"
21#include "debug.h" 21#include "debug.h"
22#include "cpumap.h" 22#include "cpumap.h"
23#include "pmu.h"
24#include "vdso.h"
25#include "strbuf.h"
23 26
24static bool no_buildid_cache = false; 27static bool no_buildid_cache = false;
25 28
26static int event_count; 29static int trace_event_count;
27static struct perf_trace_event_type *events; 30static struct perf_trace_event_type *trace_events;
28 31
29static u32 header_argc; 32static u32 header_argc;
30static const char **header_argv; 33static const char **header_argv;
@@ -36,24 +39,24 @@ int perf_header__push_event(u64 id, const char *name)
36 if (strlen(name) > MAX_EVENT_NAME) 39 if (strlen(name) > MAX_EVENT_NAME)
37 pr_warning("Event %s will be truncated\n", name); 40 pr_warning("Event %s will be truncated\n", name);
38 41
39 nevents = realloc(events, (event_count + 1) * sizeof(*events)); 42 nevents = realloc(trace_events, (trace_event_count + 1) * sizeof(*trace_events));
40 if (nevents == NULL) 43 if (nevents == NULL)
41 return -ENOMEM; 44 return -ENOMEM;
42 events = nevents; 45 trace_events = nevents;
43 46
44 memset(&events[event_count], 0, sizeof(struct perf_trace_event_type)); 47 memset(&trace_events[trace_event_count], 0, sizeof(struct perf_trace_event_type));
45 events[event_count].event_id = id; 48 trace_events[trace_event_count].event_id = id;
46 strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1); 49 strncpy(trace_events[trace_event_count].name, name, MAX_EVENT_NAME - 1);
47 event_count++; 50 trace_event_count++;
48 return 0; 51 return 0;
49} 52}
50 53
51char *perf_header__find_event(u64 id) 54char *perf_header__find_event(u64 id)
52{ 55{
53 int i; 56 int i;
54 for (i = 0 ; i < event_count; i++) { 57 for (i = 0 ; i < trace_event_count; i++) {
55 if (events[i].event_id == id) 58 if (trace_events[i].event_id == id)
56 return events[i].name; 59 return trace_events[i].name;
57 } 60 }
58 return NULL; 61 return NULL;
59} 62}
@@ -128,7 +131,7 @@ static int do_write_string(int fd, const char *str)
128 int ret; 131 int ret;
129 132
130 olen = strlen(str) + 1; 133 olen = strlen(str) + 1;
131 len = ALIGN(olen, NAME_ALIGN); 134 len = PERF_ALIGN(olen, NAME_ALIGN);
132 135
133 /* write len, incl. \0 */ 136 /* write len, incl. \0 */
134 ret = do_write(fd, &len, sizeof(len)); 137 ret = do_write(fd, &len, sizeof(len));
@@ -206,6 +209,29 @@ perf_header__set_cmdline(int argc, const char **argv)
206 continue; \ 209 continue; \
207 else 210 else
208 211
212static int write_buildid(char *name, size_t name_len, u8 *build_id,
213 pid_t pid, u16 misc, int fd)
214{
215 int err;
216 struct build_id_event b;
217 size_t len;
218
219 len = name_len + 1;
220 len = PERF_ALIGN(len, NAME_ALIGN);
221
222 memset(&b, 0, sizeof(b));
223 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
224 b.pid = pid;
225 b.header.misc = misc;
226 b.header.size = sizeof(b) + len;
227
228 err = do_write(fd, &b, sizeof(b));
229 if (err < 0)
230 return err;
231
232 return write_padded(fd, name, name_len + 1, len);
233}
234
209static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, 235static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
210 u16 misc, int fd) 236 u16 misc, int fd)
211{ 237{
@@ -213,24 +239,23 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
213 239
214 dsos__for_each_with_build_id(pos, head) { 240 dsos__for_each_with_build_id(pos, head) {
215 int err; 241 int err;
216 struct build_id_event b; 242 char *name;
217 size_t len; 243 size_t name_len;
218 244
219 if (!pos->hit) 245 if (!pos->hit)
220 continue; 246 continue;
221 len = pos->long_name_len + 1; 247
222 len = ALIGN(len, NAME_ALIGN); 248 if (is_vdso_map(pos->short_name)) {
223 memset(&b, 0, sizeof(b)); 249 name = (char *) VDSO__MAP_NAME;
224 memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); 250 name_len = sizeof(VDSO__MAP_NAME) + 1;
225 b.pid = pid; 251 } else {
226 b.header.misc = misc; 252 name = pos->long_name;
227 b.header.size = sizeof(b) + len; 253 name_len = pos->long_name_len + 1;
228 err = do_write(fd, &b, sizeof(b)); 254 }
229 if (err < 0) 255
230 return err; 256 err = write_buildid(name, name_len, pos->build_id,
231 err = write_padded(fd, pos->long_name, 257 pid, misc, fd);
232 pos->long_name_len + 1, len); 258 if (err)
233 if (err < 0)
234 return err; 259 return err;
235 } 260 }
236 261
@@ -276,19 +301,20 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd)
276} 301}
277 302
278int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 303int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
279 const char *name, bool is_kallsyms) 304 const char *name, bool is_kallsyms, bool is_vdso)
280{ 305{
281 const size_t size = PATH_MAX; 306 const size_t size = PATH_MAX;
282 char *realname, *filename = zalloc(size), 307 char *realname, *filename = zalloc(size),
283 *linkname = zalloc(size), *targetname; 308 *linkname = zalloc(size), *targetname;
284 int len, err = -1; 309 int len, err = -1;
310 bool slash = is_kallsyms || is_vdso;
285 311
286 if (is_kallsyms) { 312 if (is_kallsyms) {
287 if (symbol_conf.kptr_restrict) { 313 if (symbol_conf.kptr_restrict) {
288 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n"); 314 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
289 return 0; 315 return 0;
290 } 316 }
291 realname = (char *)name; 317 realname = (char *) name;
292 } else 318 } else
293 realname = realpath(name, NULL); 319 realname = realpath(name, NULL);
294 320
@@ -296,7 +322,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
296 goto out_free; 322 goto out_free;
297 323
298 len = scnprintf(filename, size, "%s%s%s", 324 len = scnprintf(filename, size, "%s%s%s",
299 debugdir, is_kallsyms ? "/" : "", realname); 325 debugdir, slash ? "/" : "",
326 is_vdso ? VDSO__MAP_NAME : realname);
300 if (mkdir_p(filename, 0755)) 327 if (mkdir_p(filename, 0755))
301 goto out_free; 328 goto out_free;
302 329
@@ -332,13 +359,14 @@ out_free:
332 359
333static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 360static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
334 const char *name, const char *debugdir, 361 const char *name, const char *debugdir,
335 bool is_kallsyms) 362 bool is_kallsyms, bool is_vdso)
336{ 363{
337 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 364 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
338 365
339 build_id__sprintf(build_id, build_id_size, sbuild_id); 366 build_id__sprintf(build_id, build_id_size, sbuild_id);
340 367
341 return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms); 368 return build_id_cache__add_s(sbuild_id, debugdir, name,
369 is_kallsyms, is_vdso);
342} 370}
343 371
344int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) 372int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
@@ -382,9 +410,11 @@ out_free:
382static int dso__cache_build_id(struct dso *dso, const char *debugdir) 410static int dso__cache_build_id(struct dso *dso, const char *debugdir)
383{ 411{
384 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 412 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
413 bool is_vdso = is_vdso_map(dso->short_name);
385 414
386 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), 415 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
387 dso->long_name, debugdir, is_kallsyms); 416 dso->long_name, debugdir,
417 is_kallsyms, is_vdso);
388} 418}
389 419
390static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) 420static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
@@ -446,7 +476,7 @@ static bool perf_session__read_build_ids(struct perf_session *session, bool with
446 return ret; 476 return ret;
447} 477}
448 478
449static int write_tracing_data(int fd, struct perf_header *h __used, 479static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
450 struct perf_evlist *evlist) 480 struct perf_evlist *evlist)
451{ 481{
452 return read_tracing_data(fd, &evlist->entries); 482 return read_tracing_data(fd, &evlist->entries);
@@ -454,7 +484,7 @@ static int write_tracing_data(int fd, struct perf_header *h __used,
454 484
455 485
456static int write_build_id(int fd, struct perf_header *h, 486static int write_build_id(int fd, struct perf_header *h,
457 struct perf_evlist *evlist __used) 487 struct perf_evlist *evlist __maybe_unused)
458{ 488{
459 struct perf_session *session; 489 struct perf_session *session;
460 int err; 490 int err;
@@ -475,8 +505,8 @@ static int write_build_id(int fd, struct perf_header *h,
475 return 0; 505 return 0;
476} 506}
477 507
478static int write_hostname(int fd, struct perf_header *h __used, 508static int write_hostname(int fd, struct perf_header *h __maybe_unused,
479 struct perf_evlist *evlist __used) 509 struct perf_evlist *evlist __maybe_unused)
480{ 510{
481 struct utsname uts; 511 struct utsname uts;
482 int ret; 512 int ret;
@@ -488,8 +518,8 @@ static int write_hostname(int fd, struct perf_header *h __used,
488 return do_write_string(fd, uts.nodename); 518 return do_write_string(fd, uts.nodename);
489} 519}
490 520
491static int write_osrelease(int fd, struct perf_header *h __used, 521static int write_osrelease(int fd, struct perf_header *h __maybe_unused,
492 struct perf_evlist *evlist __used) 522 struct perf_evlist *evlist __maybe_unused)
493{ 523{
494 struct utsname uts; 524 struct utsname uts;
495 int ret; 525 int ret;
@@ -501,8 +531,8 @@ static int write_osrelease(int fd, struct perf_header *h __used,
501 return do_write_string(fd, uts.release); 531 return do_write_string(fd, uts.release);
502} 532}
503 533
504static int write_arch(int fd, struct perf_header *h __used, 534static int write_arch(int fd, struct perf_header *h __maybe_unused,
505 struct perf_evlist *evlist __used) 535 struct perf_evlist *evlist __maybe_unused)
506{ 536{
507 struct utsname uts; 537 struct utsname uts;
508 int ret; 538 int ret;
@@ -514,14 +544,14 @@ static int write_arch(int fd, struct perf_header *h __used,
514 return do_write_string(fd, uts.machine); 544 return do_write_string(fd, uts.machine);
515} 545}
516 546
517static int write_version(int fd, struct perf_header *h __used, 547static int write_version(int fd, struct perf_header *h __maybe_unused,
518 struct perf_evlist *evlist __used) 548 struct perf_evlist *evlist __maybe_unused)
519{ 549{
520 return do_write_string(fd, perf_version_string); 550 return do_write_string(fd, perf_version_string);
521} 551}
522 552
523static int write_cpudesc(int fd, struct perf_header *h __used, 553static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
524 struct perf_evlist *evlist __used) 554 struct perf_evlist *evlist __maybe_unused)
525{ 555{
526#ifndef CPUINFO_PROC 556#ifndef CPUINFO_PROC
527#define CPUINFO_PROC NULL 557#define CPUINFO_PROC NULL
@@ -579,8 +609,8 @@ done:
579 return ret; 609 return ret;
580} 610}
581 611
582static int write_nrcpus(int fd, struct perf_header *h __used, 612static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
583 struct perf_evlist *evlist __used) 613 struct perf_evlist *evlist __maybe_unused)
584{ 614{
585 long nr; 615 long nr;
586 u32 nrc, nra; 616 u32 nrc, nra;
@@ -605,15 +635,14 @@ static int write_nrcpus(int fd, struct perf_header *h __used,
605 return do_write(fd, &nra, sizeof(nra)); 635 return do_write(fd, &nra, sizeof(nra));
606} 636}
607 637
608static int write_event_desc(int fd, struct perf_header *h __used, 638static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
609 struct perf_evlist *evlist) 639 struct perf_evlist *evlist)
610{ 640{
611 struct perf_evsel *attr; 641 struct perf_evsel *evsel;
612 u32 nre = 0, nri, sz; 642 u32 nre, nri, sz;
613 int ret; 643 int ret;
614 644
615 list_for_each_entry(attr, &evlist->entries, node) 645 nre = evlist->nr_entries;
616 nre++;
617 646
618 /* 647 /*
619 * write number of events 648 * write number of events
@@ -625,14 +654,14 @@ static int write_event_desc(int fd, struct perf_header *h __used,
625 /* 654 /*
626 * size of perf_event_attr struct 655 * size of perf_event_attr struct
627 */ 656 */
628 sz = (u32)sizeof(attr->attr); 657 sz = (u32)sizeof(evsel->attr);
629 ret = do_write(fd, &sz, sizeof(sz)); 658 ret = do_write(fd, &sz, sizeof(sz));
630 if (ret < 0) 659 if (ret < 0)
631 return ret; 660 return ret;
632 661
633 list_for_each_entry(attr, &evlist->entries, node) { 662 list_for_each_entry(evsel, &evlist->entries, node) {
634 663
635 ret = do_write(fd, &attr->attr, sz); 664 ret = do_write(fd, &evsel->attr, sz);
636 if (ret < 0) 665 if (ret < 0)
637 return ret; 666 return ret;
638 /* 667 /*
@@ -642,7 +671,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
642 * copy into an nri to be independent of the 671 * copy into an nri to be independent of the
643 * type of ids, 672 * type of ids,
644 */ 673 */
645 nri = attr->ids; 674 nri = evsel->ids;
646 ret = do_write(fd, &nri, sizeof(nri)); 675 ret = do_write(fd, &nri, sizeof(nri));
647 if (ret < 0) 676 if (ret < 0)
648 return ret; 677 return ret;
@@ -650,21 +679,21 @@ static int write_event_desc(int fd, struct perf_header *h __used,
650 /* 679 /*
651 * write event string as passed on cmdline 680 * write event string as passed on cmdline
652 */ 681 */
653 ret = do_write_string(fd, perf_evsel__name(attr)); 682 ret = do_write_string(fd, perf_evsel__name(evsel));
654 if (ret < 0) 683 if (ret < 0)
655 return ret; 684 return ret;
656 /* 685 /*
657 * write unique ids for this event 686 * write unique ids for this event
658 */ 687 */
659 ret = do_write(fd, attr->id, attr->ids * sizeof(u64)); 688 ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
660 if (ret < 0) 689 if (ret < 0)
661 return ret; 690 return ret;
662 } 691 }
663 return 0; 692 return 0;
664} 693}
665 694
666static int write_cmdline(int fd, struct perf_header *h __used, 695static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
667 struct perf_evlist *evlist __used) 696 struct perf_evlist *evlist __maybe_unused)
668{ 697{
669 char buf[MAXPATHLEN]; 698 char buf[MAXPATHLEN];
670 char proc[32]; 699 char proc[32];
@@ -832,8 +861,8 @@ static struct cpu_topo *build_cpu_topology(void)
832 return tp; 861 return tp;
833} 862}
834 863
835static int write_cpu_topology(int fd, struct perf_header *h __used, 864static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
836 struct perf_evlist *evlist __used) 865 struct perf_evlist *evlist __maybe_unused)
837{ 866{
838 struct cpu_topo *tp; 867 struct cpu_topo *tp;
839 u32 i; 868 u32 i;
@@ -868,8 +897,8 @@ done:
868 897
869 898
870 899
871static int write_total_mem(int fd, struct perf_header *h __used, 900static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
872 struct perf_evlist *evlist __used) 901 struct perf_evlist *evlist __maybe_unused)
873{ 902{
874 char *buf = NULL; 903 char *buf = NULL;
875 FILE *fp; 904 FILE *fp;
@@ -954,8 +983,8 @@ done:
954 return ret; 983 return ret;
955} 984}
956 985
957static int write_numa_topology(int fd, struct perf_header *h __used, 986static int write_numa_topology(int fd, struct perf_header *h __maybe_unused,
958 struct perf_evlist *evlist __used) 987 struct perf_evlist *evlist __maybe_unused)
959{ 988{
960 char *buf = NULL; 989 char *buf = NULL;
961 size_t len = 0; 990 size_t len = 0;
@@ -1004,16 +1033,56 @@ done:
1004} 1033}
1005 1034
1006/* 1035/*
1036 * File format:
1037 *
1038 * struct pmu_mappings {
1039 * u32 pmu_num;
1040 * struct pmu_map {
1041 * u32 type;
1042 * char name[];
1043 * }[pmu_num];
1044 * };
1045 */
1046
1047static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused,
1048 struct perf_evlist *evlist __maybe_unused)
1049{
1050 struct perf_pmu *pmu = NULL;
1051 off_t offset = lseek(fd, 0, SEEK_CUR);
1052 __u32 pmu_num = 0;
1053
1054 /* write real pmu_num later */
1055 do_write(fd, &pmu_num, sizeof(pmu_num));
1056
1057 while ((pmu = perf_pmu__scan(pmu))) {
1058 if (!pmu->name)
1059 continue;
1060 pmu_num++;
1061 do_write(fd, &pmu->type, sizeof(pmu->type));
1062 do_write_string(fd, pmu->name);
1063 }
1064
1065 if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
1066 /* discard all */
1067 lseek(fd, offset, SEEK_SET);
1068 return -1;
1069 }
1070
1071 return 0;
1072}
1073
1074/*
1007 * default get_cpuid(): nothing gets recorded 1075 * default get_cpuid(): nothing gets recorded
1008 * actual implementation must be in arch/$(ARCH)/util/header.c 1076 * actual implementation must be in arch/$(ARCH)/util/header.c
1009 */ 1077 */
1010int __attribute__((weak)) get_cpuid(char *buffer __used, size_t sz __used) 1078int __attribute__ ((weak)) get_cpuid(char *buffer __maybe_unused,
1079 size_t sz __maybe_unused)
1011{ 1080{
1012 return -1; 1081 return -1;
1013} 1082}
1014 1083
1015static int write_cpuid(int fd, struct perf_header *h __used, 1084static int write_cpuid(int fd, struct perf_header *h __maybe_unused,
1016 struct perf_evlist *evlist __used) 1085 struct perf_evlist *evlist __maybe_unused)
1017{ 1086{
1018 char buffer[64]; 1087 char buffer[64];
1019 int ret; 1088 int ret;
@@ -1027,133 +1096,113 @@ write_it:
1027 return do_write_string(fd, buffer); 1096 return do_write_string(fd, buffer);
1028} 1097}
1029 1098
1030static int write_branch_stack(int fd __used, struct perf_header *h __used, 1099static int write_branch_stack(int fd __maybe_unused,
1031 struct perf_evlist *evlist __used) 1100 struct perf_header *h __maybe_unused,
1101 struct perf_evlist *evlist __maybe_unused)
1032{ 1102{
1033 return 0; 1103 return 0;
1034} 1104}
1035 1105
1036static void print_hostname(struct perf_header *ph, int fd, FILE *fp) 1106static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
1107 FILE *fp)
1037{ 1108{
1038 char *str = do_read_string(fd, ph); 1109 fprintf(fp, "# hostname : %s\n", ph->env.hostname);
1039 fprintf(fp, "# hostname : %s\n", str);
1040 free(str);
1041} 1110}
1042 1111
1043static void print_osrelease(struct perf_header *ph, int fd, FILE *fp) 1112static void print_osrelease(struct perf_header *ph, int fd __maybe_unused,
1113 FILE *fp)
1044{ 1114{
1045 char *str = do_read_string(fd, ph); 1115 fprintf(fp, "# os release : %s\n", ph->env.os_release);
1046 fprintf(fp, "# os release : %s\n", str);
1047 free(str);
1048} 1116}
1049 1117
1050static void print_arch(struct perf_header *ph, int fd, FILE *fp) 1118static void print_arch(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
1051{ 1119{
1052 char *str = do_read_string(fd, ph); 1120 fprintf(fp, "# arch : %s\n", ph->env.arch);
1053 fprintf(fp, "# arch : %s\n", str);
1054 free(str);
1055} 1121}
1056 1122
1057static void print_cpudesc(struct perf_header *ph, int fd, FILE *fp) 1123static void print_cpudesc(struct perf_header *ph, int fd __maybe_unused,
1124 FILE *fp)
1058{ 1125{
1059 char *str = do_read_string(fd, ph); 1126 fprintf(fp, "# cpudesc : %s\n", ph->env.cpu_desc);
1060 fprintf(fp, "# cpudesc : %s\n", str);
1061 free(str);
1062} 1127}
1063 1128
1064static void print_nrcpus(struct perf_header *ph, int fd, FILE *fp) 1129static void print_nrcpus(struct perf_header *ph, int fd __maybe_unused,
1130 FILE *fp)
1065{ 1131{
1066 ssize_t ret; 1132 fprintf(fp, "# nrcpus online : %u\n", ph->env.nr_cpus_online);
1067 u32 nr; 1133 fprintf(fp, "# nrcpus avail : %u\n", ph->env.nr_cpus_avail);
1068
1069 ret = read(fd, &nr, sizeof(nr));
1070 if (ret != (ssize_t)sizeof(nr))
1071 nr = -1; /* interpreted as error */
1072
1073 if (ph->needs_swap)
1074 nr = bswap_32(nr);
1075
1076 fprintf(fp, "# nrcpus online : %u\n", nr);
1077
1078 ret = read(fd, &nr, sizeof(nr));
1079 if (ret != (ssize_t)sizeof(nr))
1080 nr = -1; /* interpreted as error */
1081
1082 if (ph->needs_swap)
1083 nr = bswap_32(nr);
1084
1085 fprintf(fp, "# nrcpus avail : %u\n", nr);
1086} 1134}
1087 1135
1088static void print_version(struct perf_header *ph, int fd, FILE *fp) 1136static void print_version(struct perf_header *ph, int fd __maybe_unused,
1137 FILE *fp)
1089{ 1138{
1090 char *str = do_read_string(fd, ph); 1139 fprintf(fp, "# perf version : %s\n", ph->env.version);
1091 fprintf(fp, "# perf version : %s\n", str);
1092 free(str);
1093} 1140}
1094 1141
1095static void print_cmdline(struct perf_header *ph, int fd, FILE *fp) 1142static void print_cmdline(struct perf_header *ph, int fd __maybe_unused,
1143 FILE *fp)
1096{ 1144{
1097 ssize_t ret; 1145 int nr, i;
1098 char *str; 1146 char *str;
1099 u32 nr, i;
1100
1101 ret = read(fd, &nr, sizeof(nr));
1102 if (ret != (ssize_t)sizeof(nr))
1103 return;
1104 1147
1105 if (ph->needs_swap) 1148 nr = ph->env.nr_cmdline;
1106 nr = bswap_32(nr); 1149 str = ph->env.cmdline;
1107 1150
1108 fprintf(fp, "# cmdline : "); 1151 fprintf(fp, "# cmdline : ");
1109 1152
1110 for (i = 0; i < nr; i++) { 1153 for (i = 0; i < nr; i++) {
1111 str = do_read_string(fd, ph);
1112 fprintf(fp, "%s ", str); 1154 fprintf(fp, "%s ", str);
1113 free(str); 1155 str += strlen(str) + 1;
1114 } 1156 }
1115 fputc('\n', fp); 1157 fputc('\n', fp);
1116} 1158}
1117 1159
1118static void print_cpu_topology(struct perf_header *ph, int fd, FILE *fp) 1160static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
1161 FILE *fp)
1119{ 1162{
1120 ssize_t ret; 1163 int nr, i;
1121 u32 nr, i;
1122 char *str; 1164 char *str;
1123 1165
1124 ret = read(fd, &nr, sizeof(nr)); 1166 nr = ph->env.nr_sibling_cores;
1125 if (ret != (ssize_t)sizeof(nr)) 1167 str = ph->env.sibling_cores;
1126 return;
1127
1128 if (ph->needs_swap)
1129 nr = bswap_32(nr);
1130 1168
1131 for (i = 0; i < nr; i++) { 1169 for (i = 0; i < nr; i++) {
1132 str = do_read_string(fd, ph);
1133 fprintf(fp, "# sibling cores : %s\n", str); 1170 fprintf(fp, "# sibling cores : %s\n", str);
1134 free(str); 1171 str += strlen(str) + 1;
1135 } 1172 }
1136 1173
1137 ret = read(fd, &nr, sizeof(nr)); 1174 nr = ph->env.nr_sibling_threads;
1138 if (ret != (ssize_t)sizeof(nr)) 1175 str = ph->env.sibling_threads;
1139 return;
1140
1141 if (ph->needs_swap)
1142 nr = bswap_32(nr);
1143 1176
1144 for (i = 0; i < nr; i++) { 1177 for (i = 0; i < nr; i++) {
1145 str = do_read_string(fd, ph);
1146 fprintf(fp, "# sibling threads : %s\n", str); 1178 fprintf(fp, "# sibling threads : %s\n", str);
1147 free(str); 1179 str += strlen(str) + 1;
1148 } 1180 }
1149} 1181}
1150 1182
1151static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) 1183static void free_event_desc(struct perf_evsel *events)
1184{
1185 struct perf_evsel *evsel;
1186
1187 if (!events)
1188 return;
1189
1190 for (evsel = events; evsel->attr.size; evsel++) {
1191 if (evsel->name)
1192 free(evsel->name);
1193 if (evsel->id)
1194 free(evsel->id);
1195 }
1196
1197 free(events);
1198}
1199
1200static struct perf_evsel *
1201read_event_desc(struct perf_header *ph, int fd)
1152{ 1202{
1153 struct perf_event_attr attr; 1203 struct perf_evsel *evsel, *events = NULL;
1154 uint64_t id; 1204 u64 *id;
1155 void *buf = NULL; 1205 void *buf = NULL;
1156 char *str;
1157 u32 nre, sz, nr, i, j; 1206 u32 nre, sz, nr, i, j;
1158 ssize_t ret; 1207 ssize_t ret;
1159 size_t msz; 1208 size_t msz;
@@ -1173,18 +1222,22 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1173 if (ph->needs_swap) 1222 if (ph->needs_swap)
1174 sz = bswap_32(sz); 1223 sz = bswap_32(sz);
1175 1224
1176 memset(&attr, 0, sizeof(attr));
1177
1178 /* buffer to hold on file attr struct */ 1225 /* buffer to hold on file attr struct */
1179 buf = malloc(sz); 1226 buf = malloc(sz);
1180 if (!buf) 1227 if (!buf)
1181 goto error; 1228 goto error;
1182 1229
1183 msz = sizeof(attr); 1230 /* the last event terminates with evsel->attr.size == 0: */
1231 events = calloc(nre + 1, sizeof(*events));
1232 if (!events)
1233 goto error;
1234
1235 msz = sizeof(evsel->attr);
1184 if (sz < msz) 1236 if (sz < msz)
1185 msz = sz; 1237 msz = sz;
1186 1238
1187 for (i = 0 ; i < nre; i++) { 1239 for (i = 0, evsel = events; i < nre; evsel++, i++) {
1240 evsel->idx = i;
1188 1241
1189 /* 1242 /*
1190 * must read entire on-file attr struct to 1243 * must read entire on-file attr struct to
@@ -1197,146 +1250,188 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1197 if (ph->needs_swap) 1250 if (ph->needs_swap)
1198 perf_event__attr_swap(buf); 1251 perf_event__attr_swap(buf);
1199 1252
1200 memcpy(&attr, buf, msz); 1253 memcpy(&evsel->attr, buf, msz);
1201 1254
1202 ret = read(fd, &nr, sizeof(nr)); 1255 ret = read(fd, &nr, sizeof(nr));
1203 if (ret != (ssize_t)sizeof(nr)) 1256 if (ret != (ssize_t)sizeof(nr))
1204 goto error; 1257 goto error;
1205 1258
1206 if (ph->needs_swap) 1259 if (ph->needs_swap) {
1207 nr = bswap_32(nr); 1260 nr = bswap_32(nr);
1261 evsel->needs_swap = true;
1262 }
1208 1263
1209 str = do_read_string(fd, ph); 1264 evsel->name = do_read_string(fd, ph);
1210 fprintf(fp, "# event : name = %s, ", str); 1265
1211 free(str); 1266 if (!nr)
1267 continue;
1268
1269 id = calloc(nr, sizeof(*id));
1270 if (!id)
1271 goto error;
1272 evsel->ids = nr;
1273 evsel->id = id;
1274
1275 for (j = 0 ; j < nr; j++) {
1276 ret = read(fd, id, sizeof(*id));
1277 if (ret != (ssize_t)sizeof(*id))
1278 goto error;
1279 if (ph->needs_swap)
1280 *id = bswap_64(*id);
1281 id++;
1282 }
1283 }
1284out:
1285 if (buf)
1286 free(buf);
1287 return events;
1288error:
1289 if (events)
1290 free_event_desc(events);
1291 events = NULL;
1292 goto out;
1293}
1294
1295static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1296{
1297 struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
1298 u32 j;
1299 u64 *id;
1300
1301 if (!events) {
1302 fprintf(fp, "# event desc: not available or unable to read\n");
1303 return;
1304 }
1305
1306 for (evsel = events; evsel->attr.size; evsel++) {
1307 fprintf(fp, "# event : name = %s, ", evsel->name);
1212 1308
1213 fprintf(fp, "type = %d, config = 0x%"PRIx64 1309 fprintf(fp, "type = %d, config = 0x%"PRIx64
1214 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64, 1310 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
1215 attr.type, 1311 evsel->attr.type,
1216 (u64)attr.config, 1312 (u64)evsel->attr.config,
1217 (u64)attr.config1, 1313 (u64)evsel->attr.config1,
1218 (u64)attr.config2); 1314 (u64)evsel->attr.config2);
1219 1315
1220 fprintf(fp, ", excl_usr = %d, excl_kern = %d", 1316 fprintf(fp, ", excl_usr = %d, excl_kern = %d",
1221 attr.exclude_user, 1317 evsel->attr.exclude_user,
1222 attr.exclude_kernel); 1318 evsel->attr.exclude_kernel);
1223 1319
1224 fprintf(fp, ", excl_host = %d, excl_guest = %d", 1320 fprintf(fp, ", excl_host = %d, excl_guest = %d",
1225 attr.exclude_host, 1321 evsel->attr.exclude_host,
1226 attr.exclude_guest); 1322 evsel->attr.exclude_guest);
1227 1323
1228 fprintf(fp, ", precise_ip = %d", attr.precise_ip); 1324 fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
1229 1325
1230 if (nr) 1326 if (evsel->ids) {
1231 fprintf(fp, ", id = {"); 1327 fprintf(fp, ", id = {");
1232 1328 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
1233 for (j = 0 ; j < nr; j++) { 1329 if (j)
1234 ret = read(fd, &id, sizeof(id)); 1330 fputc(',', fp);
1235 if (ret != (ssize_t)sizeof(id)) 1331 fprintf(fp, " %"PRIu64, *id);
1236 goto error; 1332 }
1237
1238 if (ph->needs_swap)
1239 id = bswap_64(id);
1240
1241 if (j)
1242 fputc(',', fp);
1243
1244 fprintf(fp, " %"PRIu64, id);
1245 }
1246 if (nr && j == nr)
1247 fprintf(fp, " }"); 1333 fprintf(fp, " }");
1334 }
1335
1248 fputc('\n', fp); 1336 fputc('\n', fp);
1249 } 1337 }
1250 free(buf); 1338
1251 return; 1339 free_event_desc(events);
1252error:
1253 fprintf(fp, "# event desc: not available or unable to read\n");
1254} 1340}
1255 1341
1256static void print_total_mem(struct perf_header *h __used, int fd, FILE *fp) 1342static void print_total_mem(struct perf_header *ph, int fd __maybe_unused,
1343 FILE *fp)
1257{ 1344{
1258 uint64_t mem; 1345 fprintf(fp, "# total memory : %Lu kB\n", ph->env.total_mem);
1259 ssize_t ret;
1260
1261 ret = read(fd, &mem, sizeof(mem));
1262 if (ret != sizeof(mem))
1263 goto error;
1264
1265 if (h->needs_swap)
1266 mem = bswap_64(mem);
1267
1268 fprintf(fp, "# total memory : %"PRIu64" kB\n", mem);
1269 return;
1270error:
1271 fprintf(fp, "# total memory : unknown\n");
1272} 1346}
1273 1347
1274static void print_numa_topology(struct perf_header *h __used, int fd, FILE *fp) 1348static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
1349 FILE *fp)
1275{ 1350{
1276 ssize_t ret;
1277 u32 nr, c, i; 1351 u32 nr, c, i;
1278 char *str; 1352 char *str, *tmp;
1279 uint64_t mem_total, mem_free; 1353 uint64_t mem_total, mem_free;
1280 1354
1281 /* nr nodes */ 1355 /* nr nodes */
1282 ret = read(fd, &nr, sizeof(nr)); 1356 nr = ph->env.nr_numa_nodes;
1283 if (ret != (ssize_t)sizeof(nr)) 1357 str = ph->env.numa_nodes;
1284 goto error;
1285
1286 if (h->needs_swap)
1287 nr = bswap_32(nr);
1288 1358
1289 for (i = 0; i < nr; i++) { 1359 for (i = 0; i < nr; i++) {
1290
1291 /* node number */ 1360 /* node number */
1292 ret = read(fd, &c, sizeof(c)); 1361 c = strtoul(str, &tmp, 0);
1293 if (ret != (ssize_t)sizeof(c)) 1362 if (*tmp != ':')
1294 goto error; 1363 goto error;
1295 1364
1296 if (h->needs_swap) 1365 str = tmp + 1;
1297 c = bswap_32(c); 1366 mem_total = strtoull(str, &tmp, 0);
1298 1367 if (*tmp != ':')
1299 ret = read(fd, &mem_total, sizeof(u64));
1300 if (ret != sizeof(u64))
1301 goto error; 1368 goto error;
1302 1369
1303 ret = read(fd, &mem_free, sizeof(u64)); 1370 str = tmp + 1;
1304 if (ret != sizeof(u64)) 1371 mem_free = strtoull(str, &tmp, 0);
1372 if (*tmp != ':')
1305 goto error; 1373 goto error;
1306 1374
1307 if (h->needs_swap) {
1308 mem_total = bswap_64(mem_total);
1309 mem_free = bswap_64(mem_free);
1310 }
1311
1312 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," 1375 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1313 " free = %"PRIu64" kB\n", 1376 " free = %"PRIu64" kB\n",
1314 c, 1377 c, mem_total, mem_free);
1315 mem_total,
1316 mem_free);
1317 1378
1318 str = do_read_string(fd, h); 1379 str = tmp + 1;
1319 fprintf(fp, "# node%u cpu list : %s\n", c, str); 1380 fprintf(fp, "# node%u cpu list : %s\n", c, str);
1320 free(str);
1321 } 1381 }
1322 return; 1382 return;
1323error: 1383error:
1324 fprintf(fp, "# numa topology : not available\n"); 1384 fprintf(fp, "# numa topology : not available\n");
1325} 1385}
1326 1386
1327static void print_cpuid(struct perf_header *ph, int fd, FILE *fp) 1387static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
1328{ 1388{
1329 char *str = do_read_string(fd, ph); 1389 fprintf(fp, "# cpuid : %s\n", ph->env.cpuid);
1330 fprintf(fp, "# cpuid : %s\n", str);
1331 free(str);
1332} 1390}
1333 1391
1334static void print_branch_stack(struct perf_header *ph __used, int fd __used, 1392static void print_branch_stack(struct perf_header *ph __maybe_unused,
1335 FILE *fp) 1393 int fd __maybe_unused, FILE *fp)
1336{ 1394{
1337 fprintf(fp, "# contains samples with branch stack\n"); 1395 fprintf(fp, "# contains samples with branch stack\n");
1338} 1396}
1339 1397
1398static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,
1399 FILE *fp)
1400{
1401 const char *delimiter = "# pmu mappings: ";
1402 char *str, *tmp;
1403 u32 pmu_num;
1404 u32 type;
1405
1406 pmu_num = ph->env.nr_pmu_mappings;
1407 if (!pmu_num) {
1408 fprintf(fp, "# pmu mappings: not available\n");
1409 return;
1410 }
1411
1412 str = ph->env.pmu_mappings;
1413
1414 while (pmu_num) {
1415 type = strtoul(str, &tmp, 0);
1416 if (*tmp != ':')
1417 goto error;
1418
1419 str = tmp + 1;
1420 fprintf(fp, "%s%s = %" PRIu32, delimiter, str, type);
1421
1422 delimiter = ", ";
1423 str += strlen(str) + 1;
1424 pmu_num--;
1425 }
1426
1427 fprintf(fp, "\n");
1428
1429 if (!pmu_num)
1430 return;
1431error:
1432 fprintf(fp, "# pmu mappings: unable to read\n");
1433}
1434
1340static int __event_process_build_id(struct build_id_event *bev, 1435static int __event_process_build_id(struct build_id_event *bev,
1341 char *filename, 1436 char *filename,
1342 struct perf_session *session) 1437 struct perf_session *session)
@@ -1398,7 +1493,7 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1398 struct perf_session *session = container_of(header, struct perf_session, header); 1493 struct perf_session *session = container_of(header, struct perf_session, header);
1399 struct { 1494 struct {
1400 struct perf_event_header header; 1495 struct perf_event_header header;
1401 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; 1496 u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))];
1402 char filename[0]; 1497 char filename[0];
1403 } old_bev; 1498 } old_bev;
1404 struct build_id_event bev; 1499 struct build_id_event bev;
@@ -1487,28 +1582,375 @@ out:
1487 return err; 1582 return err;
1488} 1583}
1489 1584
1490static int process_tracing_data(struct perf_file_section *section __unused, 1585static int process_tracing_data(struct perf_file_section *section __maybe_unused,
1491 struct perf_header *ph __unused, 1586 struct perf_header *ph __maybe_unused,
1492 int feat __unused, int fd, void *data) 1587 int fd, void *data)
1493{ 1588{
1494 trace_report(fd, data, false); 1589 trace_report(fd, data, false);
1495 return 0; 1590 return 0;
1496} 1591}
1497 1592
1498static int process_build_id(struct perf_file_section *section, 1593static int process_build_id(struct perf_file_section *section,
1499 struct perf_header *ph, 1594 struct perf_header *ph, int fd,
1500 int feat __unused, int fd, void *data __used) 1595 void *data __maybe_unused)
1501{ 1596{
1502 if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) 1597 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1503 pr_debug("Failed to read buildids, continuing...\n"); 1598 pr_debug("Failed to read buildids, continuing...\n");
1504 return 0; 1599 return 0;
1505} 1600}
1506 1601
1602static int process_hostname(struct perf_file_section *section __maybe_unused,
1603 struct perf_header *ph, int fd,
1604 void *data __maybe_unused)
1605{
1606 ph->env.hostname = do_read_string(fd, ph);
1607 return ph->env.hostname ? 0 : -ENOMEM;
1608}
1609
1610static int process_osrelease(struct perf_file_section *section __maybe_unused,
1611 struct perf_header *ph, int fd,
1612 void *data __maybe_unused)
1613{
1614 ph->env.os_release = do_read_string(fd, ph);
1615 return ph->env.os_release ? 0 : -ENOMEM;
1616}
1617
1618static int process_version(struct perf_file_section *section __maybe_unused,
1619 struct perf_header *ph, int fd,
1620 void *data __maybe_unused)
1621{
1622 ph->env.version = do_read_string(fd, ph);
1623 return ph->env.version ? 0 : -ENOMEM;
1624}
1625
1626static int process_arch(struct perf_file_section *section __maybe_unused,
1627 struct perf_header *ph, int fd,
1628 void *data __maybe_unused)
1629{
1630 ph->env.arch = do_read_string(fd, ph);
1631 return ph->env.arch ? 0 : -ENOMEM;
1632}
1633
1634static int process_nrcpus(struct perf_file_section *section __maybe_unused,
1635 struct perf_header *ph, int fd,
1636 void *data __maybe_unused)
1637{
1638 size_t ret;
1639 u32 nr;
1640
1641 ret = read(fd, &nr, sizeof(nr));
1642 if (ret != sizeof(nr))
1643 return -1;
1644
1645 if (ph->needs_swap)
1646 nr = bswap_32(nr);
1647
1648 ph->env.nr_cpus_online = nr;
1649
1650 ret = read(fd, &nr, sizeof(nr));
1651 if (ret != sizeof(nr))
1652 return -1;
1653
1654 if (ph->needs_swap)
1655 nr = bswap_32(nr);
1656
1657 ph->env.nr_cpus_avail = nr;
1658 return 0;
1659}
1660
1661static int process_cpudesc(struct perf_file_section *section __maybe_unused,
1662 struct perf_header *ph, int fd,
1663 void *data __maybe_unused)
1664{
1665 ph->env.cpu_desc = do_read_string(fd, ph);
1666 return ph->env.cpu_desc ? 0 : -ENOMEM;
1667}
1668
1669static int process_cpuid(struct perf_file_section *section __maybe_unused,
1670 struct perf_header *ph, int fd,
1671 void *data __maybe_unused)
1672{
1673 ph->env.cpuid = do_read_string(fd, ph);
1674 return ph->env.cpuid ? 0 : -ENOMEM;
1675}
1676
1677static int process_total_mem(struct perf_file_section *section __maybe_unused,
1678 struct perf_header *ph, int fd,
1679 void *data __maybe_unused)
1680{
1681 uint64_t mem;
1682 size_t ret;
1683
1684 ret = read(fd, &mem, sizeof(mem));
1685 if (ret != sizeof(mem))
1686 return -1;
1687
1688 if (ph->needs_swap)
1689 mem = bswap_64(mem);
1690
1691 ph->env.total_mem = mem;
1692 return 0;
1693}
1694
1695static struct perf_evsel *
1696perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
1697{
1698 struct perf_evsel *evsel;
1699
1700 list_for_each_entry(evsel, &evlist->entries, node) {
1701 if (evsel->idx == idx)
1702 return evsel;
1703 }
1704
1705 return NULL;
1706}
1707
1708static void
1709perf_evlist__set_event_name(struct perf_evlist *evlist,
1710 struct perf_evsel *event)
1711{
1712 struct perf_evsel *evsel;
1713
1714 if (!event->name)
1715 return;
1716
1717 evsel = perf_evlist__find_by_index(evlist, event->idx);
1718 if (!evsel)
1719 return;
1720
1721 if (evsel->name)
1722 return;
1723
1724 evsel->name = strdup(event->name);
1725}
1726
1727static int
1728process_event_desc(struct perf_file_section *section __maybe_unused,
1729 struct perf_header *header, int fd,
1730 void *data __maybe_unused)
1731{
1732 struct perf_session *session;
1733 struct perf_evsel *evsel, *events = read_event_desc(header, fd);
1734
1735 if (!events)
1736 return 0;
1737
1738 session = container_of(header, struct perf_session, header);
1739 for (evsel = events; evsel->attr.size; evsel++)
1740 perf_evlist__set_event_name(session->evlist, evsel);
1741
1742 free_event_desc(events);
1743
1744 return 0;
1745}
1746
1747static int process_cmdline(struct perf_file_section *section __maybe_unused,
1748 struct perf_header *ph, int fd,
1749 void *data __maybe_unused)
1750{
1751 size_t ret;
1752 char *str;
1753 u32 nr, i;
1754 struct strbuf sb;
1755
1756 ret = read(fd, &nr, sizeof(nr));
1757 if (ret != sizeof(nr))
1758 return -1;
1759
1760 if (ph->needs_swap)
1761 nr = bswap_32(nr);
1762
1763 ph->env.nr_cmdline = nr;
1764 strbuf_init(&sb, 128);
1765
1766 for (i = 0; i < nr; i++) {
1767 str = do_read_string(fd, ph);
1768 if (!str)
1769 goto error;
1770
1771 /* include a NULL character at the end */
1772 strbuf_add(&sb, str, strlen(str) + 1);
1773 free(str);
1774 }
1775 ph->env.cmdline = strbuf_detach(&sb, NULL);
1776 return 0;
1777
1778error:
1779 strbuf_release(&sb);
1780 return -1;
1781}
1782
1783static int process_cpu_topology(struct perf_file_section *section __maybe_unused,
1784 struct perf_header *ph, int fd,
1785 void *data __maybe_unused)
1786{
1787 size_t ret;
1788 u32 nr, i;
1789 char *str;
1790 struct strbuf sb;
1791
1792 ret = read(fd, &nr, sizeof(nr));
1793 if (ret != sizeof(nr))
1794 return -1;
1795
1796 if (ph->needs_swap)
1797 nr = bswap_32(nr);
1798
1799 ph->env.nr_sibling_cores = nr;
1800 strbuf_init(&sb, 128);
1801
1802 for (i = 0; i < nr; i++) {
1803 str = do_read_string(fd, ph);
1804 if (!str)
1805 goto error;
1806
1807 /* include a NULL character at the end */
1808 strbuf_add(&sb, str, strlen(str) + 1);
1809 free(str);
1810 }
1811 ph->env.sibling_cores = strbuf_detach(&sb, NULL);
1812
1813 ret = read(fd, &nr, sizeof(nr));
1814 if (ret != sizeof(nr))
1815 return -1;
1816
1817 if (ph->needs_swap)
1818 nr = bswap_32(nr);
1819
1820 ph->env.nr_sibling_threads = nr;
1821
1822 for (i = 0; i < nr; i++) {
1823 str = do_read_string(fd, ph);
1824 if (!str)
1825 goto error;
1826
1827 /* include a NULL character at the end */
1828 strbuf_add(&sb, str, strlen(str) + 1);
1829 free(str);
1830 }
1831 ph->env.sibling_threads = strbuf_detach(&sb, NULL);
1832 return 0;
1833
1834error:
1835 strbuf_release(&sb);
1836 return -1;
1837}
1838
1839static int process_numa_topology(struct perf_file_section *section __maybe_unused,
1840 struct perf_header *ph, int fd,
1841 void *data __maybe_unused)
1842{
1843 size_t ret;
1844 u32 nr, node, i;
1845 char *str;
1846 uint64_t mem_total, mem_free;
1847 struct strbuf sb;
1848
1849 /* nr nodes */
1850 ret = read(fd, &nr, sizeof(nr));
1851 if (ret != sizeof(nr))
1852 goto error;
1853
1854 if (ph->needs_swap)
1855 nr = bswap_32(nr);
1856
1857 ph->env.nr_numa_nodes = nr;
1858 strbuf_init(&sb, 256);
1859
1860 for (i = 0; i < nr; i++) {
1861 /* node number */
1862 ret = read(fd, &node, sizeof(node));
1863 if (ret != sizeof(node))
1864 goto error;
1865
1866 ret = read(fd, &mem_total, sizeof(u64));
1867 if (ret != sizeof(u64))
1868 goto error;
1869
1870 ret = read(fd, &mem_free, sizeof(u64));
1871 if (ret != sizeof(u64))
1872 goto error;
1873
1874 if (ph->needs_swap) {
1875 node = bswap_32(node);
1876 mem_total = bswap_64(mem_total);
1877 mem_free = bswap_64(mem_free);
1878 }
1879
1880 strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
1881 node, mem_total, mem_free);
1882
1883 str = do_read_string(fd, ph);
1884 if (!str)
1885 goto error;
1886
1887 /* include a NULL character at the end */
1888 strbuf_add(&sb, str, strlen(str) + 1);
1889 free(str);
1890 }
1891 ph->env.numa_nodes = strbuf_detach(&sb, NULL);
1892 return 0;
1893
1894error:
1895 strbuf_release(&sb);
1896 return -1;
1897}
1898
1899static int process_pmu_mappings(struct perf_file_section *section __maybe_unused,
1900 struct perf_header *ph, int fd,
1901 void *data __maybe_unused)
1902{
1903 size_t ret;
1904 char *name;
1905 u32 pmu_num;
1906 u32 type;
1907 struct strbuf sb;
1908
1909 ret = read(fd, &pmu_num, sizeof(pmu_num));
1910 if (ret != sizeof(pmu_num))
1911 return -1;
1912
1913 if (ph->needs_swap)
1914 pmu_num = bswap_32(pmu_num);
1915
1916 if (!pmu_num) {
1917 pr_debug("pmu mappings not available\n");
1918 return 0;
1919 }
1920
1921 ph->env.nr_pmu_mappings = pmu_num;
1922 strbuf_init(&sb, 128);
1923
1924 while (pmu_num) {
1925 if (read(fd, &type, sizeof(type)) != sizeof(type))
1926 goto error;
1927 if (ph->needs_swap)
1928 type = bswap_32(type);
1929
1930 name = do_read_string(fd, ph);
1931 if (!name)
1932 goto error;
1933
1934 strbuf_addf(&sb, "%u:%s", type, name);
1935 /* include a NULL character at the end */
1936 strbuf_add(&sb, "", 1);
1937
1938 free(name);
1939 pmu_num--;
1940 }
1941 ph->env.pmu_mappings = strbuf_detach(&sb, NULL);
1942 return 0;
1943
1944error:
1945 strbuf_release(&sb);
1946 return -1;
1947}
1948
1507struct feature_ops { 1949struct feature_ops {
1508 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1950 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1509 void (*print)(struct perf_header *h, int fd, FILE *fp); 1951 void (*print)(struct perf_header *h, int fd, FILE *fp);
1510 int (*process)(struct perf_file_section *section, 1952 int (*process)(struct perf_file_section *section,
1511 struct perf_header *h, int feat, int fd, void *data); 1953 struct perf_header *h, int fd, void *data);
1512 const char *name; 1954 const char *name;
1513 bool full_only; 1955 bool full_only;
1514}; 1956};
@@ -1520,7 +1962,7 @@ struct feature_ops {
1520 .process = process_##func } 1962 .process = process_##func }
1521#define FEAT_OPF(n, func) \ 1963#define FEAT_OPF(n, func) \
1522 [n] = { .name = #n, .write = write_##func, .print = print_##func, \ 1964 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
1523 .full_only = true } 1965 .process = process_##func, .full_only = true }
1524 1966
1525/* feature_ops not implemented: */ 1967/* feature_ops not implemented: */
1526#define print_tracing_data NULL 1968#define print_tracing_data NULL
@@ -1529,19 +1971,20 @@ struct feature_ops {
1529static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 1971static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1530 FEAT_OPP(HEADER_TRACING_DATA, tracing_data), 1972 FEAT_OPP(HEADER_TRACING_DATA, tracing_data),
1531 FEAT_OPP(HEADER_BUILD_ID, build_id), 1973 FEAT_OPP(HEADER_BUILD_ID, build_id),
1532 FEAT_OPA(HEADER_HOSTNAME, hostname), 1974 FEAT_OPP(HEADER_HOSTNAME, hostname),
1533 FEAT_OPA(HEADER_OSRELEASE, osrelease), 1975 FEAT_OPP(HEADER_OSRELEASE, osrelease),
1534 FEAT_OPA(HEADER_VERSION, version), 1976 FEAT_OPP(HEADER_VERSION, version),
1535 FEAT_OPA(HEADER_ARCH, arch), 1977 FEAT_OPP(HEADER_ARCH, arch),
1536 FEAT_OPA(HEADER_NRCPUS, nrcpus), 1978 FEAT_OPP(HEADER_NRCPUS, nrcpus),
1537 FEAT_OPA(HEADER_CPUDESC, cpudesc), 1979 FEAT_OPP(HEADER_CPUDESC, cpudesc),
1538 FEAT_OPA(HEADER_CPUID, cpuid), 1980 FEAT_OPP(HEADER_CPUID, cpuid),
1539 FEAT_OPA(HEADER_TOTAL_MEM, total_mem), 1981 FEAT_OPP(HEADER_TOTAL_MEM, total_mem),
1540 FEAT_OPA(HEADER_EVENT_DESC, event_desc), 1982 FEAT_OPP(HEADER_EVENT_DESC, event_desc),
1541 FEAT_OPA(HEADER_CMDLINE, cmdline), 1983 FEAT_OPP(HEADER_CMDLINE, cmdline),
1542 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), 1984 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
1543 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), 1985 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
1544 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), 1986 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
1987 FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
1545}; 1988};
1546 1989
1547struct header_print_data { 1990struct header_print_data {
@@ -1683,17 +2126,17 @@ int perf_session__write_header(struct perf_session *session,
1683 struct perf_file_header f_header; 2126 struct perf_file_header f_header;
1684 struct perf_file_attr f_attr; 2127 struct perf_file_attr f_attr;
1685 struct perf_header *header = &session->header; 2128 struct perf_header *header = &session->header;
1686 struct perf_evsel *attr, *pair = NULL; 2129 struct perf_evsel *evsel, *pair = NULL;
1687 int err; 2130 int err;
1688 2131
1689 lseek(fd, sizeof(f_header), SEEK_SET); 2132 lseek(fd, sizeof(f_header), SEEK_SET);
1690 2133
1691 if (session->evlist != evlist) 2134 if (session->evlist != evlist)
1692 pair = list_entry(session->evlist->entries.next, struct perf_evsel, node); 2135 pair = perf_evlist__first(session->evlist);
1693 2136
1694 list_for_each_entry(attr, &evlist->entries, node) { 2137 list_for_each_entry(evsel, &evlist->entries, node) {
1695 attr->id_offset = lseek(fd, 0, SEEK_CUR); 2138 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
1696 err = do_write(fd, attr->id, attr->ids * sizeof(u64)); 2139 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
1697 if (err < 0) { 2140 if (err < 0) {
1698out_err_write: 2141out_err_write:
1699 pr_debug("failed to write perf header\n"); 2142 pr_debug("failed to write perf header\n");
@@ -1703,19 +2146,19 @@ out_err_write:
1703 err = do_write(fd, pair->id, pair->ids * sizeof(u64)); 2146 err = do_write(fd, pair->id, pair->ids * sizeof(u64));
1704 if (err < 0) 2147 if (err < 0)
1705 goto out_err_write; 2148 goto out_err_write;
1706 attr->ids += pair->ids; 2149 evsel->ids += pair->ids;
1707 pair = list_entry(pair->node.next, struct perf_evsel, node); 2150 pair = perf_evsel__next(pair);
1708 } 2151 }
1709 } 2152 }
1710 2153
1711 header->attr_offset = lseek(fd, 0, SEEK_CUR); 2154 header->attr_offset = lseek(fd, 0, SEEK_CUR);
1712 2155
1713 list_for_each_entry(attr, &evlist->entries, node) { 2156 list_for_each_entry(evsel, &evlist->entries, node) {
1714 f_attr = (struct perf_file_attr){ 2157 f_attr = (struct perf_file_attr){
1715 .attr = attr->attr, 2158 .attr = evsel->attr,
1716 .ids = { 2159 .ids = {
1717 .offset = attr->id_offset, 2160 .offset = evsel->id_offset,
1718 .size = attr->ids * sizeof(u64), 2161 .size = evsel->ids * sizeof(u64),
1719 } 2162 }
1720 }; 2163 };
1721 err = do_write(fd, &f_attr, sizeof(f_attr)); 2164 err = do_write(fd, &f_attr, sizeof(f_attr));
@@ -1726,9 +2169,9 @@ out_err_write:
1726 } 2169 }
1727 2170
1728 header->event_offset = lseek(fd, 0, SEEK_CUR); 2171 header->event_offset = lseek(fd, 0, SEEK_CUR);
1729 header->event_size = event_count * sizeof(struct perf_trace_event_type); 2172 header->event_size = trace_event_count * sizeof(struct perf_trace_event_type);
1730 if (events) { 2173 if (trace_events) {
1731 err = do_write(fd, events, header->event_size); 2174 err = do_write(fd, trace_events, header->event_size);
1732 if (err < 0) { 2175 if (err < 0) {
1733 pr_debug("failed to write perf header events\n"); 2176 pr_debug("failed to write perf header events\n");
1734 return err; 2177 return err;
@@ -1829,6 +2272,8 @@ out_free:
1829static const int attr_file_abi_sizes[] = { 2272static const int attr_file_abi_sizes[] = {
1830 [0] = PERF_ATTR_SIZE_VER0, 2273 [0] = PERF_ATTR_SIZE_VER0,
1831 [1] = PERF_ATTR_SIZE_VER1, 2274 [1] = PERF_ATTR_SIZE_VER1,
2275 [2] = PERF_ATTR_SIZE_VER2,
2276 [3] = PERF_ATTR_SIZE_VER3,
1832 0, 2277 0,
1833}; 2278};
1834 2279
@@ -2019,7 +2464,7 @@ static int perf_file_section__process(struct perf_file_section *section,
2019 if (!feat_ops[feat].process) 2464 if (!feat_ops[feat].process)
2020 return 0; 2465 return 0;
2021 2466
2022 return feat_ops[feat].process(section, ph, feat, fd, data); 2467 return feat_ops[feat].process(section, ph, fd, data);
2023} 2468}
2024 2469
2025static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 2470static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
@@ -2108,32 +2553,39 @@ static int read_attr(int fd, struct perf_header *ph,
2108 return ret <= 0 ? -1 : 0; 2553 return ret <= 0 ? -1 : 0;
2109} 2554}
2110 2555
2111static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel, 2556static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
2112 struct pevent *pevent) 2557 struct pevent *pevent)
2113{ 2558{
2114 struct event_format *event = pevent_find_event(pevent, 2559 struct event_format *event;
2115 evsel->attr.config);
2116 char bf[128]; 2560 char bf[128];
2117 2561
2562 /* already prepared */
2563 if (evsel->tp_format)
2564 return 0;
2565
2566 event = pevent_find_event(pevent, evsel->attr.config);
2118 if (event == NULL) 2567 if (event == NULL)
2119 return -1; 2568 return -1;
2120 2569
2121 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name); 2570 if (!evsel->name) {
2122 evsel->name = strdup(bf); 2571 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
2123 if (event->name == NULL) 2572 evsel->name = strdup(bf);
2124 return -1; 2573 if (evsel->name == NULL)
2574 return -1;
2575 }
2125 2576
2577 evsel->tp_format = event;
2126 return 0; 2578 return 0;
2127} 2579}
2128 2580
2129static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist, 2581static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2130 struct pevent *pevent) 2582 struct pevent *pevent)
2131{ 2583{
2132 struct perf_evsel *pos; 2584 struct perf_evsel *pos;
2133 2585
2134 list_for_each_entry(pos, &evlist->entries, node) { 2586 list_for_each_entry(pos, &evlist->entries, node) {
2135 if (pos->attr.type == PERF_TYPE_TRACEPOINT && 2587 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2136 perf_evsel__set_tracepoint_name(pos, pevent)) 2588 perf_evsel__prepare_tracepoint_event(pos, pevent))
2137 return -1; 2589 return -1;
2138 } 2590 }
2139 2591
@@ -2176,6 +2628,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
2176 2628
2177 if (evsel == NULL) 2629 if (evsel == NULL)
2178 goto out_delete_evlist; 2630 goto out_delete_evlist;
2631
2632 evsel->needs_swap = header->needs_swap;
2179 /* 2633 /*
2180 * Do it before so that if perf_evsel__alloc_id fails, this 2634 * Do it before so that if perf_evsel__alloc_id fails, this
2181 * entry gets purged too at perf_evlist__delete(). 2635 * entry gets purged too at perf_evlist__delete().
@@ -2207,13 +2661,13 @@ int perf_session__read_header(struct perf_session *session, int fd)
2207 2661
2208 if (f_header.event_types.size) { 2662 if (f_header.event_types.size) {
2209 lseek(fd, f_header.event_types.offset, SEEK_SET); 2663 lseek(fd, f_header.event_types.offset, SEEK_SET);
2210 events = malloc(f_header.event_types.size); 2664 trace_events = malloc(f_header.event_types.size);
2211 if (events == NULL) 2665 if (trace_events == NULL)
2212 return -ENOMEM; 2666 return -ENOMEM;
2213 if (perf_header__getbuffer64(header, fd, events, 2667 if (perf_header__getbuffer64(header, fd, trace_events,
2214 f_header.event_types.size)) 2668 f_header.event_types.size))
2215 goto out_errno; 2669 goto out_errno;
2216 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 2670 trace_event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
2217 } 2671 }
2218 2672
2219 perf_header__process_sections(header, fd, &session->pevent, 2673 perf_header__process_sections(header, fd, &session->pevent,
@@ -2221,7 +2675,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
2221 2675
2222 lseek(fd, header->data_offset, SEEK_SET); 2676 lseek(fd, header->data_offset, SEEK_SET);
2223 2677
2224 if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent)) 2678 if (perf_evlist__prepare_tracepoint_events(session->evlist,
2679 session->pevent))
2225 goto out_delete_evlist; 2680 goto out_delete_evlist;
2226 2681
2227 header->frozen = 1; 2682 header->frozen = 1;
@@ -2236,7 +2691,7 @@ out_delete_evlist:
2236} 2691}
2237 2692
2238int perf_event__synthesize_attr(struct perf_tool *tool, 2693int perf_event__synthesize_attr(struct perf_tool *tool,
2239 struct perf_event_attr *attr, u16 ids, u64 *id, 2694 struct perf_event_attr *attr, u32 ids, u64 *id,
2240 perf_event__handler_t process) 2695 perf_event__handler_t process)
2241{ 2696{
2242 union perf_event *ev; 2697 union perf_event *ev;
@@ -2244,7 +2699,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
2244 int err; 2699 int err;
2245 2700
2246 size = sizeof(struct perf_event_attr); 2701 size = sizeof(struct perf_event_attr);
2247 size = ALIGN(size, sizeof(u64)); 2702 size = PERF_ALIGN(size, sizeof(u64));
2248 size += sizeof(struct perf_event_header); 2703 size += sizeof(struct perf_event_header);
2249 size += ids * sizeof(u64); 2704 size += ids * sizeof(u64);
2250 2705
@@ -2257,9 +2712,12 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
2257 memcpy(ev->attr.id, id, ids * sizeof(u64)); 2712 memcpy(ev->attr.id, id, ids * sizeof(u64));
2258 2713
2259 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 2714 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
2260 ev->attr.header.size = size; 2715 ev->attr.header.size = (u16)size;
2261 2716
2262 err = process(tool, ev, NULL, NULL); 2717 if (ev->attr.header.size == size)
2718 err = process(tool, ev, NULL, NULL);
2719 else
2720 err = -E2BIG;
2263 2721
2264 free(ev); 2722 free(ev);
2265 2723
@@ -2270,12 +2728,12 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
2270 struct perf_session *session, 2728 struct perf_session *session,
2271 perf_event__handler_t process) 2729 perf_event__handler_t process)
2272{ 2730{
2273 struct perf_evsel *attr; 2731 struct perf_evsel *evsel;
2274 int err = 0; 2732 int err = 0;
2275 2733
2276 list_for_each_entry(attr, &session->evlist->entries, node) { 2734 list_for_each_entry(evsel, &session->evlist->entries, node) {
2277 err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids, 2735 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
2278 attr->id, process); 2736 evsel->id, process);
2279 if (err) { 2737 if (err) {
2280 pr_debug("failed to create perf header attribute\n"); 2738 pr_debug("failed to create perf header attribute\n");
2281 return err; 2739 return err;
@@ -2288,7 +2746,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
2288int perf_event__process_attr(union perf_event *event, 2746int perf_event__process_attr(union perf_event *event,
2289 struct perf_evlist **pevlist) 2747 struct perf_evlist **pevlist)
2290{ 2748{
2291 unsigned int i, ids, n_ids; 2749 u32 i, ids, n_ids;
2292 struct perf_evsel *evsel; 2750 struct perf_evsel *evsel;
2293 struct perf_evlist *evlist = *pevlist; 2751 struct perf_evlist *evlist = *pevlist;
2294 2752
@@ -2339,7 +2797,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool,
2339 2797
2340 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; 2798 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
2341 size = strlen(ev.event_type.event_type.name); 2799 size = strlen(ev.event_type.event_type.name);
2342 size = ALIGN(size, sizeof(u64)); 2800 size = PERF_ALIGN(size, sizeof(u64));
2343 ev.event_type.header.size = sizeof(ev.event_type) - 2801 ev.event_type.header.size = sizeof(ev.event_type) -
2344 (sizeof(ev.event_type.event_type.name) - size); 2802 (sizeof(ev.event_type.event_type.name) - size);
2345 2803
@@ -2355,8 +2813,8 @@ int perf_event__synthesize_event_types(struct perf_tool *tool,
2355 struct perf_trace_event_type *type; 2813 struct perf_trace_event_type *type;
2356 int i, err = 0; 2814 int i, err = 0;
2357 2815
2358 for (i = 0; i < event_count; i++) { 2816 for (i = 0; i < trace_event_count; i++) {
2359 type = &events[i]; 2817 type = &trace_events[i];
2360 2818
2361 err = perf_event__synthesize_event_type(tool, type->event_id, 2819 err = perf_event__synthesize_event_type(tool, type->event_id,
2362 type->name, process, 2820 type->name, process,
@@ -2370,7 +2828,7 @@ int perf_event__synthesize_event_types(struct perf_tool *tool,
2370 return err; 2828 return err;
2371} 2829}
2372 2830
2373int perf_event__process_event_type(struct perf_tool *tool __unused, 2831int perf_event__process_event_type(struct perf_tool *tool __maybe_unused,
2374 union perf_event *event) 2832 union perf_event *event)
2375{ 2833{
2376 if (perf_header__push_event(event->event_type.event_type.event_id, 2834 if (perf_header__push_event(event->event_type.event_type.event_id,
@@ -2387,7 +2845,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
2387 union perf_event ev; 2845 union perf_event ev;
2388 struct tracing_data *tdata; 2846 struct tracing_data *tdata;
2389 ssize_t size = 0, aligned_size = 0, padding; 2847 ssize_t size = 0, aligned_size = 0, padding;
2390 int err __used = 0; 2848 int err __maybe_unused = 0;
2391 2849
2392 /* 2850 /*
2393 * We are going to store the size of the data followed 2851 * We are going to store the size of the data followed
@@ -2408,7 +2866,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
2408 2866
2409 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 2867 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
2410 size = tdata->size; 2868 size = tdata->size;
2411 aligned_size = ALIGN(size, sizeof(u64)); 2869 aligned_size = PERF_ALIGN(size, sizeof(u64));
2412 padding = aligned_size - size; 2870 padding = aligned_size - size;
2413 ev.tracing_data.header.size = sizeof(ev.tracing_data); 2871 ev.tracing_data.header.size = sizeof(ev.tracing_data);
2414 ev.tracing_data.size = aligned_size; 2872 ev.tracing_data.size = aligned_size;
@@ -2439,7 +2897,7 @@ int perf_event__process_tracing_data(union perf_event *event,
2439 2897
2440 size_read = trace_report(session->fd, &session->pevent, 2898 size_read = trace_report(session->fd, &session->pevent,
2441 session->repipe); 2899 session->repipe);
2442 padding = ALIGN(size_read, sizeof(u64)) - size_read; 2900 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
2443 2901
2444 if (read(session->fd, buf, padding) < 0) 2902 if (read(session->fd, buf, padding) < 0)
2445 die("reading input file"); 2903 die("reading input file");
@@ -2452,6 +2910,9 @@ int perf_event__process_tracing_data(union perf_event *event,
2452 if (size_read + padding != size) 2910 if (size_read + padding != size)
2453 die("tracing data size mismatch"); 2911 die("tracing data size mismatch");
2454 2912
2913 perf_evlist__prepare_tracepoint_events(session->evlist,
2914 session->pevent);
2915
2455 return size_read + padding; 2916 return size_read + padding;
2456} 2917}
2457 2918
@@ -2470,7 +2931,7 @@ int perf_event__synthesize_build_id(struct perf_tool *tool,
2470 memset(&ev, 0, sizeof(ev)); 2931 memset(&ev, 0, sizeof(ev));
2471 2932
2472 len = pos->long_name_len + 1; 2933 len = pos->long_name_len + 1;
2473 len = ALIGN(len, NAME_ALIGN); 2934 len = PERF_ALIGN(len, NAME_ALIGN);
2474 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); 2935 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
2475 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; 2936 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
2476 ev.build_id.header.misc = misc; 2937 ev.build_id.header.misc = misc;
@@ -2483,7 +2944,7 @@ int perf_event__synthesize_build_id(struct perf_tool *tool,
2483 return err; 2944 return err;
2484} 2945}
2485 2946
2486int perf_event__process_build_id(struct perf_tool *tool __used, 2947int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
2487 union perf_event *event, 2948 union perf_event *event,
2488 struct perf_session *session) 2949 struct perf_session *session)
2489{ 2950{
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 2d42b3e1826f..879d215cdac9 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_HEADER_H 1#ifndef __PERF_HEADER_H
2#define __PERF_HEADER_H 2#define __PERF_HEADER_H
3 3
4#include "../../../include/linux/perf_event.h" 4#include "../../../include/uapi/linux/perf_event.h"
5#include <sys/types.h> 5#include <sys/types.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include "types.h" 7#include "types.h"
@@ -28,6 +28,7 @@ enum {
28 HEADER_CPU_TOPOLOGY, 28 HEADER_CPU_TOPOLOGY,
29 HEADER_NUMA_TOPOLOGY, 29 HEADER_NUMA_TOPOLOGY,
30 HEADER_BRANCH_STACK, 30 HEADER_BRANCH_STACK,
31 HEADER_PMU_MAPPINGS,
31 HEADER_LAST_FEATURE, 32 HEADER_LAST_FEATURE,
32 HEADER_FEAT_BITS = 256, 33 HEADER_FEAT_BITS = 256,
33}; 34};
@@ -57,6 +58,29 @@ struct perf_header;
57int perf_file_header__read(struct perf_file_header *header, 58int perf_file_header__read(struct perf_file_header *header,
58 struct perf_header *ph, int fd); 59 struct perf_header *ph, int fd);
59 60
61struct perf_session_env {
62 char *hostname;
63 char *os_release;
64 char *version;
65 char *arch;
66 int nr_cpus_online;
67 int nr_cpus_avail;
68 char *cpu_desc;
69 char *cpuid;
70 unsigned long long total_mem;
71
72 int nr_cmdline;
73 char *cmdline;
74 int nr_sibling_cores;
75 char *sibling_cores;
76 int nr_sibling_threads;
77 char *sibling_threads;
78 int nr_numa_nodes;
79 char *numa_nodes;
80 int nr_pmu_mappings;
81 char *pmu_mappings;
82};
83
60struct perf_header { 84struct perf_header {
61 int frozen; 85 int frozen;
62 bool needs_swap; 86 bool needs_swap;
@@ -66,6 +90,7 @@ struct perf_header {
66 u64 event_offset; 90 u64 event_offset;
67 u64 event_size; 91 u64 event_size;
68 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); 92 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
93 struct perf_session_env env;
69}; 94};
70 95
71struct perf_evlist; 96struct perf_evlist;
@@ -95,11 +120,11 @@ int perf_header__process_sections(struct perf_header *header, int fd,
95int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); 120int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
96 121
97int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 122int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
98 const char *name, bool is_kallsyms); 123 const char *name, bool is_kallsyms, bool is_vdso);
99int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 124int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
100 125
101int perf_event__synthesize_attr(struct perf_tool *tool, 126int perf_event__synthesize_attr(struct perf_tool *tool,
102 struct perf_event_attr *attr, u16 ids, u64 *id, 127 struct perf_event_attr *attr, u32 ids, u64 *id,
103 perf_event__handler_t process); 128 perf_event__handler_t process);
104int perf_event__synthesize_attrs(struct perf_tool *tool, 129int perf_event__synthesize_attrs(struct perf_tool *tool,
105 struct perf_session *session, 130 struct perf_session *session,
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 6f2975a00358..8b1f6e891b8a 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -3,6 +3,7 @@
3#include "exec_cmd.h" 3#include "exec_cmd.h"
4#include "levenshtein.h" 4#include "levenshtein.h"
5#include "help.h" 5#include "help.h"
6#include <termios.h>
6 7
7void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) 8void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
8{ 9{
@@ -331,7 +332,8 @@ const char *help_unknown_cmd(const char *cmd)
331 exit(1); 332 exit(1);
332} 333}
333 334
334int cmd_version(int argc __used, const char **argv __used, const char *prefix __used) 335int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused,
336 const char *prefix __maybe_unused)
335{ 337{
336 printf("perf version %s\n", perf_version_string); 338 printf("perf version %s\n", perf_version_string);
337 return 0; 339 return 0;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f247ef2789a4..277947a669b2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -45,7 +45,7 @@ bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len)
45 return false; 45 return false;
46} 46}
47 47
48static void hists__reset_col_len(struct hists *hists) 48void hists__reset_col_len(struct hists *hists)
49{ 49{
50 enum hist_column col; 50 enum hist_column col;
51 51
@@ -63,7 +63,7 @@ static void hists__set_unres_dso_col_len(struct hists *hists, int dso)
63 hists__set_col_len(hists, dso, unresolved_col_width); 63 hists__set_col_len(hists, dso, unresolved_col_width);
64} 64}
65 65
66static void hists__calc_col_len(struct hists *hists, struct hist_entry *h) 66void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
67{ 67{
68 const unsigned int unresolved_col_width = BITS_PER_LONG / 4; 68 const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
69 u16 len; 69 u16 len;
@@ -114,36 +114,68 @@ static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
114 } 114 }
115} 115}
116 116
117void hists__output_recalc_col_len(struct hists *hists, int max_rows)
118{
119 struct rb_node *next = rb_first(&hists->entries);
120 struct hist_entry *n;
121 int row = 0;
122
123 hists__reset_col_len(hists);
124
125 while (next && row++ < max_rows) {
126 n = rb_entry(next, struct hist_entry, rb_node);
127 if (!n->filtered)
128 hists__calc_col_len(hists, n);
129 next = rb_next(&n->rb_node);
130 }
131}
132
117static void hist_entry__add_cpumode_period(struct hist_entry *he, 133static void hist_entry__add_cpumode_period(struct hist_entry *he,
118 unsigned int cpumode, u64 period) 134 unsigned int cpumode, u64 period)
119{ 135{
120 switch (cpumode) { 136 switch (cpumode) {
121 case PERF_RECORD_MISC_KERNEL: 137 case PERF_RECORD_MISC_KERNEL:
122 he->period_sys += period; 138 he->stat.period_sys += period;
123 break; 139 break;
124 case PERF_RECORD_MISC_USER: 140 case PERF_RECORD_MISC_USER:
125 he->period_us += period; 141 he->stat.period_us += period;
126 break; 142 break;
127 case PERF_RECORD_MISC_GUEST_KERNEL: 143 case PERF_RECORD_MISC_GUEST_KERNEL:
128 he->period_guest_sys += period; 144 he->stat.period_guest_sys += period;
129 break; 145 break;
130 case PERF_RECORD_MISC_GUEST_USER: 146 case PERF_RECORD_MISC_GUEST_USER:
131 he->period_guest_us += period; 147 he->stat.period_guest_us += period;
132 break; 148 break;
133 default: 149 default:
134 break; 150 break;
135 } 151 }
136} 152}
137 153
154static void he_stat__add_period(struct he_stat *he_stat, u64 period)
155{
156 he_stat->period += period;
157 he_stat->nr_events += 1;
158}
159
160static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
161{
162 dest->period += src->period;
163 dest->period_sys += src->period_sys;
164 dest->period_us += src->period_us;
165 dest->period_guest_sys += src->period_guest_sys;
166 dest->period_guest_us += src->period_guest_us;
167 dest->nr_events += src->nr_events;
168}
169
138static void hist_entry__decay(struct hist_entry *he) 170static void hist_entry__decay(struct hist_entry *he)
139{ 171{
140 he->period = (he->period * 7) / 8; 172 he->stat.period = (he->stat.period * 7) / 8;
141 he->nr_events = (he->nr_events * 7) / 8; 173 he->stat.nr_events = (he->stat.nr_events * 7) / 8;
142} 174}
143 175
144static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) 176static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
145{ 177{
146 u64 prev_period = he->period; 178 u64 prev_period = he->stat.period;
147 179
148 if (prev_period == 0) 180 if (prev_period == 0)
149 return true; 181 return true;
@@ -151,9 +183,9 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
151 hist_entry__decay(he); 183 hist_entry__decay(he);
152 184
153 if (!he->filtered) 185 if (!he->filtered)
154 hists->stats.total_period -= prev_period - he->period; 186 hists->stats.total_period -= prev_period - he->stat.period;
155 187
156 return he->period == 0; 188 return he->stat.period == 0;
157} 189}
158 190
159static void __hists__decay_entries(struct hists *hists, bool zap_user, 191static void __hists__decay_entries(struct hists *hists, bool zap_user,
@@ -207,7 +239,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
207 239
208 if (he != NULL) { 240 if (he != NULL) {
209 *he = *template; 241 *he = *template;
210 he->nr_events = 1; 242
211 if (he->ms.map) 243 if (he->ms.map)
212 he->ms.map->referenced = true; 244 he->ms.map->referenced = true;
213 if (symbol_conf.use_callchain) 245 if (symbol_conf.use_callchain)
@@ -222,7 +254,7 @@ static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
222 if (!h->filtered) { 254 if (!h->filtered) {
223 hists__calc_col_len(hists, h); 255 hists__calc_col_len(hists, h);
224 ++hists->nr_entries; 256 ++hists->nr_entries;
225 hists->stats.total_period += h->period; 257 hists->stats.total_period += h->stat.period;
226 } 258 }
227} 259}
228 260
@@ -254,8 +286,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
254 cmp = hist_entry__cmp(entry, he); 286 cmp = hist_entry__cmp(entry, he);
255 287
256 if (!cmp) { 288 if (!cmp) {
257 he->period += period; 289 he_stat__add_period(&he->stat, period);
258 ++he->nr_events;
259 290
260 /* If the map of an existing hist_entry has 291 /* If the map of an existing hist_entry has
261 * become out-of-date due to an exec() or 292 * become out-of-date due to an exec() or
@@ -305,10 +336,14 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
305 .cpu = al->cpu, 336 .cpu = al->cpu,
306 .ip = bi->to.addr, 337 .ip = bi->to.addr,
307 .level = al->level, 338 .level = al->level,
308 .period = period, 339 .stat = {
340 .period = period,
341 .nr_events = 1,
342 },
309 .parent = sym_parent, 343 .parent = sym_parent,
310 .filtered = symbol__parent_filter(sym_parent), 344 .filtered = symbol__parent_filter(sym_parent),
311 .branch_info = bi, 345 .branch_info = bi,
346 .hists = self,
312 }; 347 };
313 348
314 return add_hist_entry(self, &entry, al, period); 349 return add_hist_entry(self, &entry, al, period);
@@ -327,9 +362,13 @@ struct hist_entry *__hists__add_entry(struct hists *self,
327 .cpu = al->cpu, 362 .cpu = al->cpu,
328 .ip = al->addr, 363 .ip = al->addr,
329 .level = al->level, 364 .level = al->level,
330 .period = period, 365 .stat = {
366 .period = period,
367 .nr_events = 1,
368 },
331 .parent = sym_parent, 369 .parent = sym_parent,
332 .filtered = symbol__parent_filter(sym_parent), 370 .filtered = symbol__parent_filter(sym_parent),
371 .hists = self,
333 }; 372 };
334 373
335 return add_hist_entry(self, &entry, al, period); 374 return add_hist_entry(self, &entry, al, period);
@@ -378,7 +417,7 @@ void hist_entry__free(struct hist_entry *he)
378 * collapse the histogram 417 * collapse the histogram
379 */ 418 */
380 419
381static bool hists__collapse_insert_entry(struct hists *hists __used, 420static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
382 struct rb_root *root, 421 struct rb_root *root,
383 struct hist_entry *he) 422 struct hist_entry *he)
384{ 423{
@@ -394,8 +433,8 @@ static bool hists__collapse_insert_entry(struct hists *hists __used,
394 cmp = hist_entry__collapse(iter, he); 433 cmp = hist_entry__collapse(iter, he);
395 434
396 if (!cmp) { 435 if (!cmp) {
397 iter->period += he->period; 436 he_stat__add_stat(&iter->stat, &he->stat);
398 iter->nr_events += he->nr_events; 437
399 if (symbol_conf.use_callchain) { 438 if (symbol_conf.use_callchain) {
400 callchain_cursor_reset(&callchain_cursor); 439 callchain_cursor_reset(&callchain_cursor);
401 callchain_merge(&callchain_cursor, 440 callchain_merge(&callchain_cursor,
@@ -497,7 +536,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
497 parent = *p; 536 parent = *p;
498 iter = rb_entry(parent, struct hist_entry, rb_node); 537 iter = rb_entry(parent, struct hist_entry, rb_node);
499 538
500 if (he->period > iter->period) 539 if (he->stat.period > iter->stat.period)
501 p = &(*p)->rb_left; 540 p = &(*p)->rb_left;
502 else 541 else
503 p = &(*p)->rb_right; 542 p = &(*p)->rb_right;
@@ -547,674 +586,6 @@ void hists__output_resort_threaded(struct hists *hists)
547 return __hists__output_resort(hists, true); 586 return __hists__output_resort(hists, true);
548} 587}
549 588
550static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
551{
552 int i;
553 int ret = fprintf(fp, " ");
554
555 for (i = 0; i < left_margin; i++)
556 ret += fprintf(fp, " ");
557
558 return ret;
559}
560
561static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
562 int left_margin)
563{
564 int i;
565 size_t ret = callchain__fprintf_left_margin(fp, left_margin);
566
567 for (i = 0; i < depth; i++)
568 if (depth_mask & (1 << i))
569 ret += fprintf(fp, "| ");
570 else
571 ret += fprintf(fp, " ");
572
573 ret += fprintf(fp, "\n");
574
575 return ret;
576}
577
578static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
579 int depth, int depth_mask, int period,
580 u64 total_samples, u64 hits,
581 int left_margin)
582{
583 int i;
584 size_t ret = 0;
585
586 ret += callchain__fprintf_left_margin(fp, left_margin);
587 for (i = 0; i < depth; i++) {
588 if (depth_mask & (1 << i))
589 ret += fprintf(fp, "|");
590 else
591 ret += fprintf(fp, " ");
592 if (!period && i == depth - 1) {
593 double percent;
594
595 percent = hits * 100.0 / total_samples;
596 ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
597 } else
598 ret += fprintf(fp, "%s", " ");
599 }
600 if (chain->ms.sym)
601 ret += fprintf(fp, "%s\n", chain->ms.sym->name);
602 else
603 ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
604
605 return ret;
606}
607
608static struct symbol *rem_sq_bracket;
609static struct callchain_list rem_hits;
610
611static void init_rem_hits(void)
612{
613 rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
614 if (!rem_sq_bracket) {
615 fprintf(stderr, "Not enough memory to display remaining hits\n");
616 return;
617 }
618
619 strcpy(rem_sq_bracket->name, "[...]");
620 rem_hits.ms.sym = rem_sq_bracket;
621}
622
623static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
624 u64 total_samples, int depth,
625 int depth_mask, int left_margin)
626{
627 struct rb_node *node, *next;
628 struct callchain_node *child;
629 struct callchain_list *chain;
630 int new_depth_mask = depth_mask;
631 u64 remaining;
632 size_t ret = 0;
633 int i;
634 uint entries_printed = 0;
635
636 remaining = total_samples;
637
638 node = rb_first(root);
639 while (node) {
640 u64 new_total;
641 u64 cumul;
642
643 child = rb_entry(node, struct callchain_node, rb_node);
644 cumul = callchain_cumul_hits(child);
645 remaining -= cumul;
646
647 /*
648 * The depth mask manages the output of pipes that show
649 * the depth. We don't want to keep the pipes of the current
650 * level for the last child of this depth.
651 * Except if we have remaining filtered hits. They will
652 * supersede the last child
653 */
654 next = rb_next(node);
655 if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
656 new_depth_mask &= ~(1 << (depth - 1));
657
658 /*
659 * But we keep the older depth mask for the line separator
660 * to keep the level link until we reach the last child
661 */
662 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
663 left_margin);
664 i = 0;
665 list_for_each_entry(chain, &child->val, list) {
666 ret += ipchain__fprintf_graph(fp, chain, depth,
667 new_depth_mask, i++,
668 total_samples,
669 cumul,
670 left_margin);
671 }
672
673 if (callchain_param.mode == CHAIN_GRAPH_REL)
674 new_total = child->children_hit;
675 else
676 new_total = total_samples;
677
678 ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total,
679 depth + 1,
680 new_depth_mask | (1 << depth),
681 left_margin);
682 node = next;
683 if (++entries_printed == callchain_param.print_limit)
684 break;
685 }
686
687 if (callchain_param.mode == CHAIN_GRAPH_REL &&
688 remaining && remaining != total_samples) {
689
690 if (!rem_sq_bracket)
691 return ret;
692
693 new_depth_mask &= ~(1 << (depth - 1));
694 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
695 new_depth_mask, 0, total_samples,
696 remaining, left_margin);
697 }
698
699 return ret;
700}
701
702static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
703 u64 total_samples, int left_margin)
704{
705 struct callchain_node *cnode;
706 struct callchain_list *chain;
707 u32 entries_printed = 0;
708 bool printed = false;
709 struct rb_node *node;
710 int i = 0;
711 int ret = 0;
712
713 /*
714 * If have one single callchain root, don't bother printing
715 * its percentage (100 % in fractal mode and the same percentage
716 * than the hist in graph mode). This also avoid one level of column.
717 */
718 node = rb_first(root);
719 if (node && !rb_next(node)) {
720 cnode = rb_entry(node, struct callchain_node, rb_node);
721 list_for_each_entry(chain, &cnode->val, list) {
722 /*
723 * If we sort by symbol, the first entry is the same than
724 * the symbol. No need to print it otherwise it appears as
725 * displayed twice.
726 */
727 if (!i++ && sort__first_dimension == SORT_SYM)
728 continue;
729 if (!printed) {
730 ret += callchain__fprintf_left_margin(fp, left_margin);
731 ret += fprintf(fp, "|\n");
732 ret += callchain__fprintf_left_margin(fp, left_margin);
733 ret += fprintf(fp, "---");
734 left_margin += 3;
735 printed = true;
736 } else
737 ret += callchain__fprintf_left_margin(fp, left_margin);
738
739 if (chain->ms.sym)
740 ret += fprintf(fp, " %s\n", chain->ms.sym->name);
741 else
742 ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
743
744 if (++entries_printed == callchain_param.print_limit)
745 break;
746 }
747 root = &cnode->rb_root;
748 }
749
750 ret += __callchain__fprintf_graph(fp, root, total_samples,
751 1, 1, left_margin);
752 ret += fprintf(fp, "\n");
753
754 return ret;
755}
756
757static size_t __callchain__fprintf_flat(FILE *fp,
758 struct callchain_node *self,
759 u64 total_samples)
760{
761 struct callchain_list *chain;
762 size_t ret = 0;
763
764 if (!self)
765 return 0;
766
767 ret += __callchain__fprintf_flat(fp, self->parent, total_samples);
768
769
770 list_for_each_entry(chain, &self->val, list) {
771 if (chain->ip >= PERF_CONTEXT_MAX)
772 continue;
773 if (chain->ms.sym)
774 ret += fprintf(fp, " %s\n", chain->ms.sym->name);
775 else
776 ret += fprintf(fp, " %p\n",
777 (void *)(long)chain->ip);
778 }
779
780 return ret;
781}
782
783static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self,
784 u64 total_samples)
785{
786 size_t ret = 0;
787 u32 entries_printed = 0;
788 struct rb_node *rb_node;
789 struct callchain_node *chain;
790
791 rb_node = rb_first(self);
792 while (rb_node) {
793 double percent;
794
795 chain = rb_entry(rb_node, struct callchain_node, rb_node);
796 percent = chain->hit * 100.0 / total_samples;
797
798 ret = percent_color_fprintf(fp, " %6.2f%%\n", percent);
799 ret += __callchain__fprintf_flat(fp, chain, total_samples);
800 ret += fprintf(fp, "\n");
801 if (++entries_printed == callchain_param.print_limit)
802 break;
803
804 rb_node = rb_next(rb_node);
805 }
806
807 return ret;
808}
809
810static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
811 u64 total_samples, int left_margin,
812 FILE *fp)
813{
814 switch (callchain_param.mode) {
815 case CHAIN_GRAPH_REL:
816 return callchain__fprintf_graph(fp, &he->sorted_chain, he->period,
817 left_margin);
818 break;
819 case CHAIN_GRAPH_ABS:
820 return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples,
821 left_margin);
822 break;
823 case CHAIN_FLAT:
824 return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples);
825 break;
826 case CHAIN_NONE:
827 break;
828 default:
829 pr_err("Bad callchain mode\n");
830 }
831
832 return 0;
833}
834
835void hists__output_recalc_col_len(struct hists *hists, int max_rows)
836{
837 struct rb_node *next = rb_first(&hists->entries);
838 struct hist_entry *n;
839 int row = 0;
840
841 hists__reset_col_len(hists);
842
843 while (next && row++ < max_rows) {
844 n = rb_entry(next, struct hist_entry, rb_node);
845 if (!n->filtered)
846 hists__calc_col_len(hists, n);
847 next = rb_next(&n->rb_node);
848 }
849}
850
851static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s,
852 size_t size, struct hists *pair_hists,
853 bool show_displacement, long displacement,
854 bool color, u64 total_period)
855{
856 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
857 u64 nr_events;
858 const char *sep = symbol_conf.field_sep;
859 int ret;
860
861 if (symbol_conf.exclude_other && !he->parent)
862 return 0;
863
864 if (pair_hists) {
865 period = he->pair ? he->pair->period : 0;
866 nr_events = he->pair ? he->pair->nr_events : 0;
867 total = pair_hists->stats.total_period;
868 period_sys = he->pair ? he->pair->period_sys : 0;
869 period_us = he->pair ? he->pair->period_us : 0;
870 period_guest_sys = he->pair ? he->pair->period_guest_sys : 0;
871 period_guest_us = he->pair ? he->pair->period_guest_us : 0;
872 } else {
873 period = he->period;
874 nr_events = he->nr_events;
875 total = total_period;
876 period_sys = he->period_sys;
877 period_us = he->period_us;
878 period_guest_sys = he->period_guest_sys;
879 period_guest_us = he->period_guest_us;
880 }
881
882 if (total) {
883 if (color)
884 ret = percent_color_snprintf(s, size,
885 sep ? "%.2f" : " %6.2f%%",
886 (period * 100.0) / total);
887 else
888 ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%",
889 (period * 100.0) / total);
890 if (symbol_conf.show_cpu_utilization) {
891 ret += percent_color_snprintf(s + ret, size - ret,
892 sep ? "%.2f" : " %6.2f%%",
893 (period_sys * 100.0) / total);
894 ret += percent_color_snprintf(s + ret, size - ret,
895 sep ? "%.2f" : " %6.2f%%",
896 (period_us * 100.0) / total);
897 if (perf_guest) {
898 ret += percent_color_snprintf(s + ret,
899 size - ret,
900 sep ? "%.2f" : " %6.2f%%",
901 (period_guest_sys * 100.0) /
902 total);
903 ret += percent_color_snprintf(s + ret,
904 size - ret,
905 sep ? "%.2f" : " %6.2f%%",
906 (period_guest_us * 100.0) /
907 total);
908 }
909 }
910 } else
911 ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
912
913 if (symbol_conf.show_nr_samples) {
914 if (sep)
915 ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
916 else
917 ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
918 }
919
920 if (symbol_conf.show_total_period) {
921 if (sep)
922 ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
923 else
924 ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period);
925 }
926
927 if (pair_hists) {
928 char bf[32];
929 double old_percent = 0, new_percent = 0, diff;
930
931 if (total > 0)
932 old_percent = (period * 100.0) / total;
933 if (total_period > 0)
934 new_percent = (he->period * 100.0) / total_period;
935
936 diff = new_percent - old_percent;
937
938 if (fabs(diff) >= 0.01)
939 scnprintf(bf, sizeof(bf), "%+4.2F%%", diff);
940 else
941 scnprintf(bf, sizeof(bf), " ");
942
943 if (sep)
944 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
945 else
946 ret += scnprintf(s + ret, size - ret, "%11.11s", bf);
947
948 if (show_displacement) {
949 if (displacement)
950 scnprintf(bf, sizeof(bf), "%+4ld", displacement);
951 else
952 scnprintf(bf, sizeof(bf), " ");
953
954 if (sep)
955 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
956 else
957 ret += scnprintf(s + ret, size - ret, "%6.6s", bf);
958 }
959 }
960
961 return ret;
962}
963
964int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
965 struct hists *hists)
966{
967 const char *sep = symbol_conf.field_sep;
968 struct sort_entry *se;
969 int ret = 0;
970
971 list_for_each_entry(se, &hist_entry__sort_list, list) {
972 if (se->elide)
973 continue;
974
975 ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
976 ret += se->se_snprintf(he, s + ret, size - ret,
977 hists__col_len(hists, se->se_width_idx));
978 }
979
980 return ret;
981}
982
983static int hist_entry__fprintf(struct hist_entry *he, size_t size,
984 struct hists *hists, struct hists *pair_hists,
985 bool show_displacement, long displacement,
986 u64 total_period, FILE *fp)
987{
988 char bf[512];
989 int ret;
990
991 if (size == 0 || size > sizeof(bf))
992 size = sizeof(bf);
993
994 ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
995 show_displacement, displacement,
996 true, total_period);
997 hist_entry__snprintf(he, bf + ret, size - ret, hists);
998 return fprintf(fp, "%s\n", bf);
999}
1000
1001static size_t hist_entry__fprintf_callchain(struct hist_entry *he,
1002 struct hists *hists,
1003 u64 total_period, FILE *fp)
1004{
1005 int left_margin = 0;
1006
1007 if (sort__first_dimension == SORT_COMM) {
1008 struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
1009 typeof(*se), list);
1010 left_margin = hists__col_len(hists, se->se_width_idx);
1011 left_margin -= thread__comm_len(he->thread);
1012 }
1013
1014 return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
1015}
1016
1017size_t hists__fprintf(struct hists *hists, struct hists *pair,
1018 bool show_displacement, bool show_header, int max_rows,
1019 int max_cols, FILE *fp)
1020{
1021 struct sort_entry *se;
1022 struct rb_node *nd;
1023 size_t ret = 0;
1024 u64 total_period;
1025 unsigned long position = 1;
1026 long displacement = 0;
1027 unsigned int width;
1028 const char *sep = symbol_conf.field_sep;
1029 const char *col_width = symbol_conf.col_width_list_str;
1030 int nr_rows = 0;
1031
1032 init_rem_hits();
1033
1034 if (!show_header)
1035 goto print_entries;
1036
1037 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
1038
1039 if (symbol_conf.show_cpu_utilization) {
1040 if (sep) {
1041 ret += fprintf(fp, "%csys", *sep);
1042 ret += fprintf(fp, "%cus", *sep);
1043 if (perf_guest) {
1044 ret += fprintf(fp, "%cguest sys", *sep);
1045 ret += fprintf(fp, "%cguest us", *sep);
1046 }
1047 } else {
1048 ret += fprintf(fp, " sys ");
1049 ret += fprintf(fp, " us ");
1050 if (perf_guest) {
1051 ret += fprintf(fp, " guest sys ");
1052 ret += fprintf(fp, " guest us ");
1053 }
1054 }
1055 }
1056
1057 if (symbol_conf.show_nr_samples) {
1058 if (sep)
1059 fprintf(fp, "%cSamples", *sep);
1060 else
1061 fputs(" Samples ", fp);
1062 }
1063
1064 if (symbol_conf.show_total_period) {
1065 if (sep)
1066 ret += fprintf(fp, "%cPeriod", *sep);
1067 else
1068 ret += fprintf(fp, " Period ");
1069 }
1070
1071 if (pair) {
1072 if (sep)
1073 ret += fprintf(fp, "%cDelta", *sep);
1074 else
1075 ret += fprintf(fp, " Delta ");
1076
1077 if (show_displacement) {
1078 if (sep)
1079 ret += fprintf(fp, "%cDisplacement", *sep);
1080 else
1081 ret += fprintf(fp, " Displ");
1082 }
1083 }
1084
1085 list_for_each_entry(se, &hist_entry__sort_list, list) {
1086 if (se->elide)
1087 continue;
1088 if (sep) {
1089 fprintf(fp, "%c%s", *sep, se->se_header);
1090 continue;
1091 }
1092 width = strlen(se->se_header);
1093 if (symbol_conf.col_width_list_str) {
1094 if (col_width) {
1095 hists__set_col_len(hists, se->se_width_idx,
1096 atoi(col_width));
1097 col_width = strchr(col_width, ',');
1098 if (col_width)
1099 ++col_width;
1100 }
1101 }
1102 if (!hists__new_col_len(hists, se->se_width_idx, width))
1103 width = hists__col_len(hists, se->se_width_idx);
1104 fprintf(fp, " %*s", width, se->se_header);
1105 }
1106
1107 fprintf(fp, "\n");
1108 if (max_rows && ++nr_rows >= max_rows)
1109 goto out;
1110
1111 if (sep)
1112 goto print_entries;
1113
1114 fprintf(fp, "# ........");
1115 if (symbol_conf.show_cpu_utilization)
1116 fprintf(fp, " ....... .......");
1117 if (symbol_conf.show_nr_samples)
1118 fprintf(fp, " ..........");
1119 if (symbol_conf.show_total_period)
1120 fprintf(fp, " ............");
1121 if (pair) {
1122 fprintf(fp, " ..........");
1123 if (show_displacement)
1124 fprintf(fp, " .....");
1125 }
1126 list_for_each_entry(se, &hist_entry__sort_list, list) {
1127 unsigned int i;
1128
1129 if (se->elide)
1130 continue;
1131
1132 fprintf(fp, " ");
1133 width = hists__col_len(hists, se->se_width_idx);
1134 if (width == 0)
1135 width = strlen(se->se_header);
1136 for (i = 0; i < width; i++)
1137 fprintf(fp, ".");
1138 }
1139
1140 fprintf(fp, "\n");
1141 if (max_rows && ++nr_rows >= max_rows)
1142 goto out;
1143
1144 fprintf(fp, "#\n");
1145 if (max_rows && ++nr_rows >= max_rows)
1146 goto out;
1147
1148print_entries:
1149 total_period = hists->stats.total_period;
1150
1151 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1152 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1153
1154 if (h->filtered)
1155 continue;
1156
1157 if (show_displacement) {
1158 if (h->pair != NULL)
1159 displacement = ((long)h->pair->position -
1160 (long)position);
1161 else
1162 displacement = 0;
1163 ++position;
1164 }
1165 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
1166 displacement, total_period, fp);
1167
1168 if (symbol_conf.use_callchain)
1169 ret += hist_entry__fprintf_callchain(h, hists, total_period, fp);
1170 if (max_rows && ++nr_rows >= max_rows)
1171 goto out;
1172
1173 if (h->ms.map == NULL && verbose > 1) {
1174 __map_groups__fprintf_maps(&h->thread->mg,
1175 MAP__FUNCTION, verbose, fp);
1176 fprintf(fp, "%.10s end\n", graph_dotted_line);
1177 }
1178 }
1179out:
1180 free(rem_sq_bracket);
1181
1182 return ret;
1183}
1184
1185/*
1186 * See hists__fprintf to match the column widths
1187 */
1188unsigned int hists__sort_list_width(struct hists *hists)
1189{
1190 struct sort_entry *se;
1191 int ret = 9; /* total % */
1192
1193 if (symbol_conf.show_cpu_utilization) {
1194 ret += 7; /* count_sys % */
1195 ret += 6; /* count_us % */
1196 if (perf_guest) {
1197 ret += 13; /* count_guest_sys % */
1198 ret += 12; /* count_guest_us % */
1199 }
1200 }
1201
1202 if (symbol_conf.show_nr_samples)
1203 ret += 11;
1204
1205 if (symbol_conf.show_total_period)
1206 ret += 13;
1207
1208 list_for_each_entry(se, &hist_entry__sort_list, list)
1209 if (!se->elide)
1210 ret += 2 + hists__col_len(hists, se->se_width_idx);
1211
1212 if (verbose) /* Addr + origin */
1213 ret += 3 + BITS_PER_LONG / 4;
1214
1215 return ret;
1216}
1217
1218static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, 589static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
1219 enum hist_filter filter) 590 enum hist_filter filter)
1220{ 591{
@@ -1226,8 +597,8 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
1226 if (h->ms.unfolded) 597 if (h->ms.unfolded)
1227 hists->nr_entries += h->nr_rows; 598 hists->nr_entries += h->nr_rows;
1228 h->row_offset = 0; 599 h->row_offset = 0;
1229 hists->stats.total_period += h->period; 600 hists->stats.total_period += h->stat.period;
1230 hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events; 601 hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
1231 602
1232 hists__calc_col_len(hists, h); 603 hists__calc_col_len(hists, h);
1233} 604}
@@ -1342,25 +713,3 @@ void hists__inc_nr_events(struct hists *hists, u32 type)
1342 ++hists->stats.nr_events[0]; 713 ++hists->stats.nr_events[0];
1343 ++hists->stats.nr_events[type]; 714 ++hists->stats.nr_events[type];
1344} 715}
1345
1346size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
1347{
1348 int i;
1349 size_t ret = 0;
1350
1351 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
1352 const char *name;
1353
1354 if (hists->stats.nr_events[i] == 0)
1355 continue;
1356
1357 name = perf_event__name(i);
1358 if (!strcmp(name, "UNKNOWN"))
1359 continue;
1360
1361 ret += fprintf(fp, "%16s events: %10d\n", name,
1362 hists->stats.nr_events[i]);
1363 }
1364
1365 return ret;
1366}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 0b096c27a419..66cb31fe81d2 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -75,8 +75,8 @@ struct hist_entry *__hists__add_entry(struct hists *self,
75 struct symbol *parent, u64 period); 75 struct symbol *parent, u64 period);
76int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); 76int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
77int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); 77int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
78int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, 78int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size,
79 struct hists *hists); 79 struct hists *hists);
80void hist_entry__free(struct hist_entry *); 80void hist_entry__free(struct hist_entry *);
81 81
82struct hist_entry *__hists__add_branch_entry(struct hists *self, 82struct hist_entry *__hists__add_branch_entry(struct hists *self,
@@ -98,9 +98,8 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows);
98void hists__inc_nr_events(struct hists *self, u32 type); 98void hists__inc_nr_events(struct hists *self, u32 type);
99size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); 99size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
100 100
101size_t hists__fprintf(struct hists *self, struct hists *pair, 101size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
102 bool show_displacement, bool show_header, 102 int max_cols, FILE *fp);
103 int max_rows, int max_cols, FILE *fp);
104 103
105int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); 104int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
106int hist_entry__annotate(struct hist_entry *self, size_t privsize); 105int hist_entry__annotate(struct hist_entry *self, size_t privsize);
@@ -112,55 +111,95 @@ void hists__filter_by_symbol(struct hists *hists);
112u16 hists__col_len(struct hists *self, enum hist_column col); 111u16 hists__col_len(struct hists *self, enum hist_column col);
113void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); 112void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
114bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); 113bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
114void hists__reset_col_len(struct hists *hists);
115void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
116
117struct perf_hpp {
118 char *buf;
119 size_t size;
120 const char *sep;
121 void *ptr;
122};
123
124struct perf_hpp_fmt {
125 bool cond;
126 int (*header)(struct perf_hpp *hpp);
127 int (*width)(struct perf_hpp *hpp);
128 int (*color)(struct perf_hpp *hpp, struct hist_entry *he);
129 int (*entry)(struct perf_hpp *hpp, struct hist_entry *he);
130};
131
132extern struct perf_hpp_fmt perf_hpp__format[];
133
134enum {
135 PERF_HPP__BASELINE,
136 PERF_HPP__OVERHEAD,
137 PERF_HPP__OVERHEAD_SYS,
138 PERF_HPP__OVERHEAD_US,
139 PERF_HPP__OVERHEAD_GUEST_SYS,
140 PERF_HPP__OVERHEAD_GUEST_US,
141 PERF_HPP__SAMPLES,
142 PERF_HPP__PERIOD,
143 PERF_HPP__DELTA,
144 PERF_HPP__DISPL,
145
146 PERF_HPP__MAX_INDEX
147};
148
149void perf_hpp__init(void);
150void perf_hpp__column_enable(unsigned col, bool enable);
151int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
152 bool color);
115 153
116struct perf_evlist; 154struct perf_evlist;
117 155
118#ifdef NO_NEWT_SUPPORT 156#ifdef NEWT_SUPPORT
157#include "../ui/keysyms.h"
158int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
159 void(*timer)(void *arg), void *arg, int delay_secs);
160
161int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
162 void(*timer)(void *arg), void *arg,
163 int refresh);
164#else
119static inline 165static inline
120int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used, 166int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
121 const char *help __used, 167 const char *help __maybe_unused,
122 void(*timer)(void *arg) __used, 168 void(*timer)(void *arg) __maybe_unused,
123 void *arg __used, 169 void *arg __maybe_unused,
124 int refresh __used) 170 int refresh __maybe_unused)
125{ 171{
126 return 0; 172 return 0;
127} 173}
128 174
129static inline int hist_entry__tui_annotate(struct hist_entry *self __used, 175static inline int hist_entry__tui_annotate(struct hist_entry *self
130 int evidx __used, 176 __maybe_unused,
131 void(*timer)(void *arg) __used, 177 int evidx __maybe_unused,
132 void *arg __used, 178 void(*timer)(void *arg)
133 int delay_secs __used) 179 __maybe_unused,
180 void *arg __maybe_unused,
181 int delay_secs __maybe_unused)
134{ 182{
135 return 0; 183 return 0;
136} 184}
137#define K_LEFT -1 185#define K_LEFT -1
138#define K_RIGHT -2 186#define K_RIGHT -2
139#else 187#endif
140#include "../ui/keysyms.h"
141int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
142 void(*timer)(void *arg), void *arg, int delay_secs);
143 188
144int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 189#ifdef GTK2_SUPPORT
190int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
145 void(*timer)(void *arg), void *arg, 191 void(*timer)(void *arg), void *arg,
146 int refresh); 192 int refresh);
147#endif 193#else
148
149#ifdef NO_GTK2_SUPPORT
150static inline 194static inline
151int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __used, 195int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
152 const char *help __used, 196 const char *help __maybe_unused,
153 void(*timer)(void *arg) __used, 197 void(*timer)(void *arg) __maybe_unused,
154 void *arg __used, 198 void *arg __maybe_unused,
155 int refresh __used) 199 int refresh __maybe_unused)
156{ 200{
157 return 0; 201 return 0;
158} 202}
159
160#else
161int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
162 void(*timer)(void *arg), void *arg,
163 int refresh);
164#endif 203#endif
165 204
166unsigned int hists__sort_list_width(struct hists *self); 205unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/include/asm/byteorder.h b/tools/perf/util/include/asm/byteorder.h
index b722abe3a626..2a9bdc066307 100644
--- a/tools/perf/util/include/asm/byteorder.h
+++ b/tools/perf/util/include/asm/byteorder.h
@@ -1,2 +1,2 @@
1#include <asm/types.h> 1#include <asm/types.h>
2#include "../../../../include/linux/swab.h" 2#include "../../../../include/uapi/linux/swab.h"
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index 587a230d2075..a55d8cf083c9 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -5,6 +5,10 @@
5#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <asm/hweight.h> 6#include <asm/hweight.h>
7 7
8#ifndef __WORDSIZE
9#define __WORDSIZE (__SIZEOF_LONG__ * 8)
10#endif
11
8#define BITS_PER_LONG __WORDSIZE 12#define BITS_PER_LONG __WORDSIZE
9#define BITS_PER_BYTE 8 13#define BITS_PER_BYTE 8
10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 14#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
index 547628e97f3d..96b919dae11c 100644
--- a/tools/perf/util/include/linux/compiler.h
+++ b/tools/perf/util/include/linux/compiler.h
@@ -9,6 +9,13 @@
9#define __attribute_const__ 9#define __attribute_const__
10#endif 10#endif
11 11
12#define __used __attribute__((__unused__)) 12#ifndef __maybe_unused
13#define __maybe_unused __attribute__((unused))
14#endif
15#define __packed __attribute__((__packed__))
16
17#ifndef __force
18#define __force
19#endif
13 20
14#endif 21#endif
diff --git a/tools/perf/util/include/linux/const.h b/tools/perf/util/include/linux/const.h
index 1b476c9ae649..c10a35e1afb8 100644
--- a/tools/perf/util/include/linux/const.h
+++ b/tools/perf/util/include/linux/const.h
@@ -1 +1 @@
#include "../../../../include/linux/const.h" #include "../../../../include/uapi/linux/const.h"
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index b6842c1d02a8..d8c927c868ee 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -8,8 +8,8 @@
8 8
9#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 9#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
10 10
11#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) 11#define PERF_ALIGN(x, a) __PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
12#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) 12#define __PERF_ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
13 13
14#ifndef offsetof 14#ifndef offsetof
15#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 15#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
@@ -46,9 +46,22 @@
46 _min1 < _min2 ? _min1 : _min2; }) 46 _min1 < _min2 ? _min1 : _min2; })
47#endif 47#endif
48 48
49#ifndef roundup
50#define roundup(x, y) ( \
51{ \
52 const typeof(y) __y = y; \
53 (((x) + (__y - 1)) / __y) * __y; \
54} \
55)
56#endif
57
49#ifndef BUG_ON 58#ifndef BUG_ON
59#ifdef NDEBUG
60#define BUG_ON(cond) do { if (cond) {} } while (0)
61#else
50#define BUG_ON(cond) assert(!(cond)) 62#define BUG_ON(cond) assert(!(cond))
51#endif 63#endif
64#endif
52 65
53/* 66/*
54 * Both need more care to handle endianness 67 * Both need more care to handle endianness
diff --git a/tools/perf/util/include/linux/magic.h b/tools/perf/util/include/linux/magic.h
new file mode 100644
index 000000000000..58b64ed4da12
--- /dev/null
+++ b/tools/perf/util/include/linux/magic.h
@@ -0,0 +1,12 @@
1#ifndef _PERF_LINUX_MAGIC_H_
2#define _PERF_LINUX_MAGIC_H_
3
4#ifndef DEBUGFS_MAGIC
5#define DEBUGFS_MAGIC 0x64626720
6#endif
7
8#ifndef SYSFS_MAGIC
9#define SYSFS_MAGIC 0x62656572
10#endif
11
12#endif
diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h
index 7a243a143037..2a030c5af3aa 100644
--- a/tools/perf/util/include/linux/rbtree.h
+++ b/tools/perf/util/include/linux/rbtree.h
@@ -1 +1,2 @@
1#include <stdbool.h>
1#include "../../../../include/linux/rbtree.h" 2#include "../../../../include/linux/rbtree.h"
diff --git a/tools/perf/util/include/linux/rbtree_augmented.h b/tools/perf/util/include/linux/rbtree_augmented.h
new file mode 100644
index 000000000000..9d6fcdf1788b
--- /dev/null
+++ b/tools/perf/util/include/linux/rbtree_augmented.h
@@ -0,0 +1,2 @@
1#include <stdbool.h>
2#include "../../../../include/linux/rbtree_augmented.h"
diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h
index 3b2f5900276f..6f19c548ecc0 100644
--- a/tools/perf/util/include/linux/string.h
+++ b/tools/perf/util/include/linux/string.h
@@ -1 +1,3 @@
1#include <string.h> 1#include <string.h>
2
3void *memdup(const void *src, size_t len);
diff --git a/tools/perf/util/include/linux/types.h b/tools/perf/util/include/linux/types.h
index 12de3b8112f9..eb464786c084 100644
--- a/tools/perf/util/include/linux/types.h
+++ b/tools/perf/util/include/linux/types.h
@@ -3,6 +3,14 @@
3 3
4#include <asm/types.h> 4#include <asm/types.h>
5 5
6#ifndef __bitwise
7#define __bitwise
8#endif
9
10#ifndef __le32
11typedef __u32 __bitwise __le32;
12#endif
13
6#define DECLARE_BITMAP(name,bits) \ 14#define DECLARE_BITMAP(name,bits) \
7 unsigned long name[BITS_TO_LONGS(bits)] 15 unsigned long name[BITS_TO_LONGS(bits)]
8 16
diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c
index fd530dced9cb..9d0740024ba8 100644
--- a/tools/perf/util/intlist.c
+++ b/tools/perf/util/intlist.c
@@ -11,7 +11,7 @@
11 11
12#include "intlist.h" 12#include "intlist.h"
13 13
14static struct rb_node *intlist__node_new(struct rblist *rblist __used, 14static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
15 const void *entry) 15 const void *entry)
16{ 16{
17 int i = (int)((long)entry); 17 int i = (int)((long)entry);
@@ -31,7 +31,7 @@ static void int_node__delete(struct int_node *ilist)
31 free(ilist); 31 free(ilist);
32} 32}
33 33
34static void intlist__node_delete(struct rblist *rblist __used, 34static void intlist__node_delete(struct rblist *rblist __maybe_unused,
35 struct rb_node *rb_node) 35 struct rb_node *rb_node)
36{ 36{
37 struct int_node *node = container_of(rb_node, struct int_node, rb_node); 37 struct int_node *node = container_of(rb_node, struct int_node, rb_node);
@@ -52,9 +52,9 @@ int intlist__add(struct intlist *ilist, int i)
52 return rblist__add_node(&ilist->rblist, (void *)((long)i)); 52 return rblist__add_node(&ilist->rblist, (void *)((long)i));
53} 53}
54 54
55void intlist__remove(struct intlist *ilist __used, struct int_node *node) 55void intlist__remove(struct intlist *ilist, struct int_node *node)
56{ 56{
57 int_node__delete(node); 57 rblist__remove_node(&ilist->rblist, &node->rb_node);
58} 58}
59 59
60struct int_node *intlist__find(struct intlist *ilist, int i) 60struct int_node *intlist__find(struct intlist *ilist, int i)
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index cc33486ad9e2..6109fa4d14cd 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -9,6 +9,7 @@
9#include "map.h" 9#include "map.h"
10#include "thread.h" 10#include "thread.h"
11#include "strlist.h" 11#include "strlist.h"
12#include "vdso.h"
12 13
13const char *map_type__name[MAP__NR_TYPES] = { 14const char *map_type__name[MAP__NR_TYPES] = {
14 [MAP__FUNCTION] = "Functions", 15 [MAP__FUNCTION] = "Functions",
@@ -23,7 +24,6 @@ static inline int is_anon_memory(const char *filename)
23static inline int is_no_dso_memory(const char *filename) 24static inline int is_no_dso_memory(const char *filename)
24{ 25{
25 return !strcmp(filename, "[stack]") || 26 return !strcmp(filename, "[stack]") ||
26 !strcmp(filename, "[vdso]") ||
27 !strcmp(filename, "[heap]"); 27 !strcmp(filename, "[heap]");
28} 28}
29 29
@@ -52,9 +52,10 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
52 if (self != NULL) { 52 if (self != NULL) {
53 char newfilename[PATH_MAX]; 53 char newfilename[PATH_MAX];
54 struct dso *dso; 54 struct dso *dso;
55 int anon, no_dso; 55 int anon, no_dso, vdso;
56 56
57 anon = is_anon_memory(filename); 57 anon = is_anon_memory(filename);
58 vdso = is_vdso_map(filename);
58 no_dso = is_no_dso_memory(filename); 59 no_dso = is_no_dso_memory(filename);
59 60
60 if (anon) { 61 if (anon) {
@@ -62,7 +63,12 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
62 filename = newfilename; 63 filename = newfilename;
63 } 64 }
64 65
65 dso = __dsos__findnew(dsos__list, filename); 66 if (vdso) {
67 pgoff = 0;
68 dso = vdso__dso_findnew(dsos__list);
69 } else
70 dso = __dsos__findnew(dsos__list, filename);
71
66 if (dso == NULL) 72 if (dso == NULL)
67 goto out_delete; 73 goto out_delete;
68 74
@@ -86,6 +92,25 @@ out_delete:
86 return NULL; 92 return NULL;
87} 93}
88 94
95/*
96 * Constructor variant for modules (where we know from /proc/modules where
97 * they are loaded) and for vmlinux, where only after we load all the
98 * symbols we'll know where it starts and ends.
99 */
100struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
101{
102 struct map *map = calloc(1, (sizeof(*map) +
103 (dso->kernel ? sizeof(struct kmap) : 0)));
104 if (map != NULL) {
105 /*
106 * ->end will be filled after we load all the symbols
107 */
108 map__init(map, type, start, 0, 0, dso);
109 }
110
111 return map;
112}
113
89void map__delete(struct map *self) 114void map__delete(struct map *self)
90{ 115{
91 free(self); 116 free(self);
@@ -137,6 +162,7 @@ int map__load(struct map *self, symbol_filter_t filter)
137 pr_warning(", continuing without symbols\n"); 162 pr_warning(", continuing without symbols\n");
138 return -1; 163 return -1;
139 } else if (nr == 0) { 164 } else if (nr == 0) {
165#ifdef LIBELF_SUPPORT
140 const size_t len = strlen(name); 166 const size_t len = strlen(name);
141 const size_t real_len = len - sizeof(DSO__DELETED); 167 const size_t real_len = len - sizeof(DSO__DELETED);
142 168
@@ -149,7 +175,7 @@ int map__load(struct map *self, symbol_filter_t filter)
149 pr_warning("no symbols found in %s, maybe install " 175 pr_warning("no symbols found in %s, maybe install "
150 "a debug package?\n", name); 176 "a debug package?\n", name);
151 } 177 }
152 178#endif
153 return -1; 179 return -1;
154 } 180 }
155 /* 181 /*
@@ -217,15 +243,14 @@ size_t map__fprintf(struct map *self, FILE *fp)
217 243
218size_t map__fprintf_dsoname(struct map *map, FILE *fp) 244size_t map__fprintf_dsoname(struct map *map, FILE *fp)
219{ 245{
220 const char *dsoname; 246 const char *dsoname = "[unknown]";
221 247
222 if (map && map->dso && (map->dso->name || map->dso->long_name)) { 248 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
223 if (symbol_conf.show_kernel_path && map->dso->long_name) 249 if (symbol_conf.show_kernel_path && map->dso->long_name)
224 dsoname = map->dso->long_name; 250 dsoname = map->dso->long_name;
225 else if (map->dso->name) 251 else if (map->dso->name)
226 dsoname = map->dso->name; 252 dsoname = map->dso->name;
227 } else 253 }
228 dsoname = "[unknown]";
229 254
230 return fprintf(fp, "%s", dsoname); 255 return fprintf(fp, "%s", dsoname);
231} 256}
@@ -242,14 +267,6 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
242 return addr; 267 return addr;
243} 268}
244 269
245u64 map__objdump_2ip(struct map *map, u64 addr)
246{
247 u64 ip = map->dso->adjust_symbols ?
248 addr :
249 map->unmap_ip(map, addr); /* RIP -> IP */
250 return ip;
251}
252
253void map_groups__init(struct map_groups *mg) 270void map_groups__init(struct map_groups *mg)
254{ 271{
255 int i; 272 int i;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 03a1e9b08b21..d2250fc97e25 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -96,7 +96,7 @@ static inline u64 map__unmap_ip(struct map *map, u64 ip)
96 return ip + map->start - map->pgoff; 96 return ip + map->start - map->pgoff;
97} 97}
98 98
99static inline u64 identity__map_ip(struct map *map __used, u64 ip) 99static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip)
100{ 100{
101 return ip; 101 return ip;
102} 102}
@@ -104,7 +104,6 @@ static inline u64 identity__map_ip(struct map *map __used, u64 ip)
104 104
105/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ 105/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
106u64 map__rip_2objdump(struct map *map, u64 rip); 106u64 map__rip_2objdump(struct map *map, u64 rip);
107u64 map__objdump_2ip(struct map *map, u64 addr);
108 107
109struct symbol; 108struct symbol;
110 109
@@ -115,6 +114,7 @@ void map__init(struct map *self, enum map_type type,
115struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, 114struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
116 u64 pgoff, u32 pid, char *filename, 115 u64 pgoff, u32 pid, char *filename,
117 enum map_type type); 116 enum map_type type);
117struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
118void map__delete(struct map *self); 118void map__delete(struct map *self);
119struct map *map__clone(struct map *self); 119struct map *map__clone(struct map *self);
120int map__overlap(struct map *l, struct map *r); 120int map__overlap(struct map *l, struct map *r);
@@ -157,9 +157,12 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid);
157void machine__exit(struct machine *self); 157void machine__exit(struct machine *self);
158void machine__delete(struct machine *self); 158void machine__delete(struct machine *self);
159 159
160struct perf_evsel;
161struct perf_sample;
160int machine__resolve_callchain(struct machine *machine, 162int machine__resolve_callchain(struct machine *machine,
163 struct perf_evsel *evsel,
161 struct thread *thread, 164 struct thread *thread,
162 struct ip_callchain *chain, 165 struct perf_sample *sample,
163 struct symbol **parent); 166 struct symbol **parent);
164int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, 167int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
165 u64 addr); 168 u64 addr);
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 607dd290b319..516ecd9ddd6e 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -18,8 +18,7 @@ do { \
18 18
19static int test__checkevent_tracepoint(struct perf_evlist *evlist) 19static int test__checkevent_tracepoint(struct perf_evlist *evlist)
20{ 20{
21 struct perf_evsel *evsel = list_entry(evlist->entries.next, 21 struct perf_evsel *evsel = perf_evlist__first(evlist);
22 struct perf_evsel, node);
23 22
24 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 23 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
25 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); 24 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
@@ -48,8 +47,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
48 47
49static int test__checkevent_raw(struct perf_evlist *evlist) 48static int test__checkevent_raw(struct perf_evlist *evlist)
50{ 49{
51 struct perf_evsel *evsel = list_entry(evlist->entries.next, 50 struct perf_evsel *evsel = perf_evlist__first(evlist);
52 struct perf_evsel, node);
53 51
54 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 52 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
55 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 53 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
@@ -59,8 +57,7 @@ static int test__checkevent_raw(struct perf_evlist *evlist)
59 57
60static int test__checkevent_numeric(struct perf_evlist *evlist) 58static int test__checkevent_numeric(struct perf_evlist *evlist)
61{ 59{
62 struct perf_evsel *evsel = list_entry(evlist->entries.next, 60 struct perf_evsel *evsel = perf_evlist__first(evlist);
63 struct perf_evsel, node);
64 61
65 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 62 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
66 TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); 63 TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
@@ -70,8 +67,7 @@ static int test__checkevent_numeric(struct perf_evlist *evlist)
70 67
71static int test__checkevent_symbolic_name(struct perf_evlist *evlist) 68static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
72{ 69{
73 struct perf_evsel *evsel = list_entry(evlist->entries.next, 70 struct perf_evsel *evsel = perf_evlist__first(evlist);
74 struct perf_evsel, node);
75 71
76 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 72 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
77 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); 73 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
@@ -82,8 +78,7 @@ static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
82 78
83static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist) 79static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
84{ 80{
85 struct perf_evsel *evsel = list_entry(evlist->entries.next, 81 struct perf_evsel *evsel = perf_evlist__first(evlist);
86 struct perf_evsel, node);
87 82
88 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 83 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
89 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); 84 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
@@ -100,8 +95,7 @@ static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
100 95
101static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) 96static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
102{ 97{
103 struct perf_evsel *evsel = list_entry(evlist->entries.next, 98 struct perf_evsel *evsel = perf_evlist__first(evlist);
104 struct perf_evsel, node);
105 99
106 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 100 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
107 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); 101 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
@@ -112,8 +106,7 @@ static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
112 106
113static int test__checkevent_genhw(struct perf_evlist *evlist) 107static int test__checkevent_genhw(struct perf_evlist *evlist)
114{ 108{
115 struct perf_evsel *evsel = list_entry(evlist->entries.next, 109 struct perf_evsel *evsel = perf_evlist__first(evlist);
116 struct perf_evsel, node);
117 110
118 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 111 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
119 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); 112 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type);
@@ -123,8 +116,7 @@ static int test__checkevent_genhw(struct perf_evlist *evlist)
123 116
124static int test__checkevent_breakpoint(struct perf_evlist *evlist) 117static int test__checkevent_breakpoint(struct perf_evlist *evlist)
125{ 118{
126 struct perf_evsel *evsel = list_entry(evlist->entries.next, 119 struct perf_evsel *evsel = perf_evlist__first(evlist);
127 struct perf_evsel, node);
128 120
129 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 121 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
130 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); 122 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
@@ -138,8 +130,7 @@ static int test__checkevent_breakpoint(struct perf_evlist *evlist)
138 130
139static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) 131static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
140{ 132{
141 struct perf_evsel *evsel = list_entry(evlist->entries.next, 133 struct perf_evsel *evsel = perf_evlist__first(evlist);
142 struct perf_evsel, node);
143 134
144 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 135 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
145 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); 136 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
@@ -152,8 +143,7 @@ static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
152 143
153static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) 144static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
154{ 145{
155 struct perf_evsel *evsel = list_entry(evlist->entries.next, 146 struct perf_evsel *evsel = perf_evlist__first(evlist);
156 struct perf_evsel, node);
157 147
158 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 148 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
159 TEST_ASSERT_VAL("wrong type", 149 TEST_ASSERT_VAL("wrong type",
@@ -168,8 +158,7 @@ static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
168 158
169static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) 159static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
170{ 160{
171 struct perf_evsel *evsel = list_entry(evlist->entries.next, 161 struct perf_evsel *evsel = perf_evlist__first(evlist);
172 struct perf_evsel, node);
173 162
174 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 163 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
175 TEST_ASSERT_VAL("wrong type", 164 TEST_ASSERT_VAL("wrong type",
@@ -184,8 +173,7 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
184 173
185static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) 174static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
186{ 175{
187 struct perf_evsel *evsel = list_entry(evlist->entries.next, 176 struct perf_evsel *evsel = perf_evlist__first(evlist);
188 struct perf_evsel, node);
189 177
190 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 178 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
191 TEST_ASSERT_VAL("wrong type", 179 TEST_ASSERT_VAL("wrong type",
@@ -200,8 +188,7 @@ static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
200 188
201static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) 189static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
202{ 190{
203 struct perf_evsel *evsel = list_entry(evlist->entries.next, 191 struct perf_evsel *evsel = perf_evlist__first(evlist);
204 struct perf_evsel, node);
205 192
206 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 193 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
207 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 194 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -232,8 +219,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
232 219
233static int test__checkevent_raw_modifier(struct perf_evlist *evlist) 220static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
234{ 221{
235 struct perf_evsel *evsel = list_entry(evlist->entries.next, 222 struct perf_evsel *evsel = perf_evlist__first(evlist);
236 struct perf_evsel, node);
237 223
238 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 224 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
239 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 225 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -245,8 +231,7 @@ static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
245 231
246static int test__checkevent_numeric_modifier(struct perf_evlist *evlist) 232static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
247{ 233{
248 struct perf_evsel *evsel = list_entry(evlist->entries.next, 234 struct perf_evsel *evsel = perf_evlist__first(evlist);
249 struct perf_evsel, node);
250 235
251 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 236 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
252 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 237 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -258,8 +243,7 @@ static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
258 243
259static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist) 244static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
260{ 245{
261 struct perf_evsel *evsel = list_entry(evlist->entries.next, 246 struct perf_evsel *evsel = perf_evlist__first(evlist);
262 struct perf_evsel, node);
263 247
264 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 248 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
265 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 249 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -271,8 +255,7 @@ static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
271 255
272static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist) 256static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
273{ 257{
274 struct perf_evsel *evsel = list_entry(evlist->entries.next, 258 struct perf_evsel *evsel = perf_evlist__first(evlist);
275 struct perf_evsel, node);
276 259
277 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 260 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
278 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); 261 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
@@ -282,8 +265,7 @@ static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
282 265
283static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist) 266static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
284{ 267{
285 struct perf_evsel *evsel = list_entry(evlist->entries.next, 268 struct perf_evsel *evsel = perf_evlist__first(evlist);
286 struct perf_evsel, node);
287 269
288 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); 270 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
289 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 271 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
@@ -293,8 +275,7 @@ static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
293 275
294static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist) 276static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
295{ 277{
296 struct perf_evsel *evsel = list_entry(evlist->entries.next, 278 struct perf_evsel *evsel = perf_evlist__first(evlist);
297 struct perf_evsel, node);
298 279
299 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); 280 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
300 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 281 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -306,8 +287,7 @@ static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
306 287
307static int test__checkevent_genhw_modifier(struct perf_evlist *evlist) 288static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
308{ 289{
309 struct perf_evsel *evsel = list_entry(evlist->entries.next, 290 struct perf_evsel *evsel = perf_evlist__first(evlist);
310 struct perf_evsel, node);
311 291
312 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 292 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
313 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 293 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -319,75 +299,71 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
319 299
320static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) 300static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
321{ 301{
322 struct perf_evsel *evsel = list_entry(evlist->entries.next, 302 struct perf_evsel *evsel = perf_evlist__first(evlist);
323 struct perf_evsel, node); 303
324 304
325 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); 305 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
326 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 306 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
327 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 307 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
328 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 308 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
329 TEST_ASSERT_VAL("wrong name", 309 TEST_ASSERT_VAL("wrong name",
330 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u")); 310 !strcmp(perf_evsel__name(evsel), "mem:0:u"));
331 311
332 return test__checkevent_breakpoint(evlist); 312 return test__checkevent_breakpoint(evlist);
333} 313}
334 314
335static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) 315static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
336{ 316{
337 struct perf_evsel *evsel = list_entry(evlist->entries.next, 317 struct perf_evsel *evsel = perf_evlist__first(evlist);
338 struct perf_evsel, node);
339 318
340 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 319 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
341 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 320 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
342 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 321 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
343 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 322 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
344 TEST_ASSERT_VAL("wrong name", 323 TEST_ASSERT_VAL("wrong name",
345 !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k")); 324 !strcmp(perf_evsel__name(evsel), "mem:0:x:k"));
346 325
347 return test__checkevent_breakpoint_x(evlist); 326 return test__checkevent_breakpoint_x(evlist);
348} 327}
349 328
350static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) 329static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
351{ 330{
352 struct perf_evsel *evsel = list_entry(evlist->entries.next, 331 struct perf_evsel *evsel = perf_evlist__first(evlist);
353 struct perf_evsel, node);
354 332
355 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 333 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
356 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 334 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
357 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); 335 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
358 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 336 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
359 TEST_ASSERT_VAL("wrong name", 337 TEST_ASSERT_VAL("wrong name",
360 !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp")); 338 !strcmp(perf_evsel__name(evsel), "mem:0:r:hp"));
361 339
362 return test__checkevent_breakpoint_r(evlist); 340 return test__checkevent_breakpoint_r(evlist);
363} 341}
364 342
365static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) 343static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
366{ 344{
367 struct perf_evsel *evsel = list_entry(evlist->entries.next, 345 struct perf_evsel *evsel = perf_evlist__first(evlist);
368 struct perf_evsel, node);
369 346
370 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); 347 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
371 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 348 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
372 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 349 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
373 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 350 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
374 TEST_ASSERT_VAL("wrong name", 351 TEST_ASSERT_VAL("wrong name",
375 !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up")); 352 !strcmp(perf_evsel__name(evsel), "mem:0:w:up"));
376 353
377 return test__checkevent_breakpoint_w(evlist); 354 return test__checkevent_breakpoint_w(evlist);
378} 355}
379 356
380static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) 357static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
381{ 358{
382 struct perf_evsel *evsel = list_entry(evlist->entries.next, 359 struct perf_evsel *evsel = perf_evlist__first(evlist);
383 struct perf_evsel, node);
384 360
385 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 361 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
386 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 362 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
387 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 363 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
388 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 364 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
389 TEST_ASSERT_VAL("wrong name", 365 TEST_ASSERT_VAL("wrong name",
390 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp")); 366 !strcmp(perf_evsel__name(evsel), "mem:0:rw:kp"));
391 367
392 return test__checkevent_breakpoint_rw(evlist); 368 return test__checkevent_breakpoint_rw(evlist);
393} 369}
@@ -395,8 +371,7 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
395static int test__checkevent_pmu(struct perf_evlist *evlist) 371static int test__checkevent_pmu(struct perf_evlist *evlist)
396{ 372{
397 373
398 struct perf_evsel *evsel = list_entry(evlist->entries.next, 374 struct perf_evsel *evsel = perf_evlist__first(evlist);
399 struct perf_evsel, node);
400 375
401 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); 376 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
402 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 377 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
@@ -410,12 +385,11 @@ static int test__checkevent_pmu(struct perf_evlist *evlist)
410 385
411static int test__checkevent_list(struct perf_evlist *evlist) 386static int test__checkevent_list(struct perf_evlist *evlist)
412{ 387{
413 struct perf_evsel *evsel; 388 struct perf_evsel *evsel = perf_evlist__first(evlist);
414 389
415 TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries); 390 TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
416 391
417 /* r1 */ 392 /* r1 */
418 evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
419 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 393 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
420 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); 394 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
421 TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1); 395 TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1);
@@ -426,7 +400,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)
426 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 400 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
427 401
428 /* syscalls:sys_enter_open:k */ 402 /* syscalls:sys_enter_open:k */
429 evsel = list_entry(evsel->node.next, struct perf_evsel, node); 403 evsel = perf_evsel__next(evsel);
430 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); 404 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
431 TEST_ASSERT_VAL("wrong sample_type", 405 TEST_ASSERT_VAL("wrong sample_type",
432 PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type); 406 PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
@@ -437,7 +411,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)
437 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 411 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
438 412
439 /* 1:1:hp */ 413 /* 1:1:hp */
440 evsel = list_entry(evsel->node.next, struct perf_evsel, node); 414 evsel = perf_evsel__next(evsel);
441 TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); 415 TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
442 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); 416 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
443 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 417 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
@@ -450,22 +424,21 @@ static int test__checkevent_list(struct perf_evlist *evlist)
450 424
451static int test__checkevent_pmu_name(struct perf_evlist *evlist) 425static int test__checkevent_pmu_name(struct perf_evlist *evlist)
452{ 426{
453 struct perf_evsel *evsel; 427 struct perf_evsel *evsel = perf_evlist__first(evlist);
454 428
455 /* cpu/config=1,name=krava/u */ 429 /* cpu/config=1,name=krava/u */
456 evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
457 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); 430 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
458 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 431 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
459 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); 432 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
460 TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava")); 433 TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava"));
461 434
462 /* cpu/config=2/u" */ 435 /* cpu/config=2/u" */
463 evsel = list_entry(evsel->node.next, struct perf_evsel, node); 436 evsel = perf_evsel__next(evsel);
464 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); 437 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
465 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 438 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
466 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); 439 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
467 TEST_ASSERT_VAL("wrong name", 440 TEST_ASSERT_VAL("wrong name",
468 !strcmp(perf_evsel__name(evsel), "raw 0x2:u")); 441 !strcmp(perf_evsel__name(evsel), "cpu/config=2/u"));
469 442
470 return 0; 443 return 0;
471} 444}
@@ -513,6 +486,284 @@ static int test__checkterms_simple(struct list_head *terms)
513 return 0; 486 return 0;
514} 487}
515 488
489static int test__group1(struct perf_evlist *evlist)
490{
491 struct perf_evsel *evsel, *leader;
492
493 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
494
495 /* instructions:k */
496 evsel = leader = perf_evlist__first(evlist);
497 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
498 TEST_ASSERT_VAL("wrong config",
499 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
500 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
501 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
502 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
503 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
504 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
505 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
506 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
507
508 /* cycles:upp */
509 evsel = perf_evsel__next(evsel);
510 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
511 TEST_ASSERT_VAL("wrong config",
512 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
513 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
514 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
515 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
516 /* use of precise requires exclude_guest */
517 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
518 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
519 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
520 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
521
522 return 0;
523}
524
525static int test__group2(struct perf_evlist *evlist)
526{
527 struct perf_evsel *evsel, *leader;
528
529 TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
530
531 /* faults + :ku modifier */
532 evsel = leader = perf_evlist__first(evlist);
533 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
534 TEST_ASSERT_VAL("wrong config",
535 PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
536 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
537 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
538 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
539 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
540 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
541 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
542 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
543
544 /* cache-references + :u modifier */
545 evsel = perf_evsel__next(evsel);
546 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
547 TEST_ASSERT_VAL("wrong config",
548 PERF_COUNT_HW_CACHE_REFERENCES == evsel->attr.config);
549 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
550 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
551 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
552 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
553 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
554 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
555 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
556
557 /* cycles:k */
558 evsel = perf_evsel__next(evsel);
559 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
560 TEST_ASSERT_VAL("wrong config",
561 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
562 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
563 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
564 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
565 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
566 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
567 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
568 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
569
570 return 0;
571}
572
573static int test__group3(struct perf_evlist *evlist __maybe_unused)
574{
575 struct perf_evsel *evsel, *leader;
576
577 TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
578
579 /* group1 syscalls:sys_enter_open:H */
580 evsel = leader = perf_evlist__first(evlist);
581 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
582 TEST_ASSERT_VAL("wrong sample_type",
583 PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
584 TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
585 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
586 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
587 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
588 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
589 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
590 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
591 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
592 TEST_ASSERT_VAL("wrong group name",
593 !strcmp(leader->group_name, "group1"));
594
595 /* group1 cycles:kppp */
596 evsel = perf_evsel__next(evsel);
597 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
598 TEST_ASSERT_VAL("wrong config",
599 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
600 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
601 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
602 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
603 /* use of precise requires exclude_guest */
604 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
605 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
606 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
607 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
608 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
609
610 /* group2 cycles + G modifier */
611 evsel = leader = perf_evsel__next(evsel);
612 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
613 TEST_ASSERT_VAL("wrong config",
614 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
615 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
616 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
617 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
618 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
619 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
620 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
621 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
622 TEST_ASSERT_VAL("wrong group name",
623 !strcmp(leader->group_name, "group2"));
624
625 /* group2 1:3 + G modifier */
626 evsel = perf_evsel__next(evsel);
627 TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
628 TEST_ASSERT_VAL("wrong config", 3 == evsel->attr.config);
629 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
630 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
631 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
632 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
633 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
634 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
635 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
636
637 /* instructions:u */
638 evsel = perf_evsel__next(evsel);
639 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
640 TEST_ASSERT_VAL("wrong config",
641 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
642 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
643 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
644 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
645 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
646 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
647 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
648 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
649
650 return 0;
651}
652
653static int test__group4(struct perf_evlist *evlist __maybe_unused)
654{
655 struct perf_evsel *evsel, *leader;
656
657 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
658
659 /* cycles:u + p */
660 evsel = leader = perf_evlist__first(evlist);
661 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
662 TEST_ASSERT_VAL("wrong config",
663 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
664 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
665 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
666 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
667 /* use of precise requires exclude_guest */
668 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
669 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
670 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
671 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
672 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
673
674 /* instructions:kp + p */
675 evsel = perf_evsel__next(evsel);
676 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
677 TEST_ASSERT_VAL("wrong config",
678 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
679 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
680 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
681 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
682 /* use of precise requires exclude_guest */
683 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
684 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
685 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
686 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
687
688 return 0;
689}
690
691static int test__group5(struct perf_evlist *evlist __maybe_unused)
692{
693 struct perf_evsel *evsel, *leader;
694
695 TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
696
697 /* cycles + G */
698 evsel = leader = perf_evlist__first(evlist);
699 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
700 TEST_ASSERT_VAL("wrong config",
701 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
702 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
703 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
704 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
705 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
706 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
707 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
708 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
709 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
710
711 /* instructions + G */
712 evsel = perf_evsel__next(evsel);
713 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
714 TEST_ASSERT_VAL("wrong config",
715 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
716 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
717 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
718 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
719 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
720 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
721 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
722 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
723
724 /* cycles:G */
725 evsel = leader = perf_evsel__next(evsel);
726 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
727 TEST_ASSERT_VAL("wrong config",
728 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
729 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
730 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
731 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
732 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
733 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
734 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
735 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
736 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
737
738 /* instructions:G */
739 evsel = perf_evsel__next(evsel);
740 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
741 TEST_ASSERT_VAL("wrong config",
742 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
743 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
744 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
745 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
746 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
747 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
748 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
749 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
750
751 /* cycles */
752 evsel = perf_evsel__next(evsel);
753 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
754 TEST_ASSERT_VAL("wrong config",
755 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
756 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
757 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
758 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
759 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
760 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
761 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
762 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
763
764 return 0;
765}
766
516struct test__event_st { 767struct test__event_st {
517 const char *name; 768 const char *name;
518 __u32 type; 769 __u32 type;
@@ -632,6 +883,26 @@ static struct test__event_st test__events[] = {
632 .name = "mem:0:rw:kp", 883 .name = "mem:0:rw:kp",
633 .check = test__checkevent_breakpoint_rw_modifier, 884 .check = test__checkevent_breakpoint_rw_modifier,
634 }, 885 },
886 [28] = {
887 .name = "{instructions:k,cycles:upp}",
888 .check = test__group1,
889 },
890 [29] = {
891 .name = "{faults:k,cache-references}:u,cycles:k",
892 .check = test__group2,
893 },
894 [30] = {
895 .name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u",
896 .check = test__group3,
897 },
898 [31] = {
899 .name = "{cycles:u,instructions:kp}:p",
900 .check = test__group4,
901 },
902 [32] = {
903 .name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles",
904 .check = test__group5,
905 },
635}; 906};
636 907
637static struct test__event_st test__events_pmu[] = { 908static struct test__event_st test__events_pmu[] = {
@@ -658,9 +929,6 @@ static struct test__term test__terms[] = {
658 }, 929 },
659}; 930};
660 931
661#define TEST__TERMS_CNT (sizeof(test__terms) / \
662 sizeof(struct test__term))
663
664static int test_event(struct test__event_st *e) 932static int test_event(struct test__event_st *e)
665{ 933{
666 struct perf_evlist *evlist; 934 struct perf_evlist *evlist;
@@ -685,19 +953,19 @@ static int test_event(struct test__event_st *e)
685 953
686static int test_events(struct test__event_st *events, unsigned cnt) 954static int test_events(struct test__event_st *events, unsigned cnt)
687{ 955{
688 int ret = 0; 956 int ret1, ret2 = 0;
689 unsigned i; 957 unsigned i;
690 958
691 for (i = 0; i < cnt; i++) { 959 for (i = 0; i < cnt; i++) {
692 struct test__event_st *e = &events[i]; 960 struct test__event_st *e = &events[i];
693 961
694 pr_debug("running test %d '%s'\n", i, e->name); 962 pr_debug("running test %d '%s'\n", i, e->name);
695 ret = test_event(e); 963 ret1 = test_event(e);
696 if (ret) 964 if (ret1)
697 break; 965 ret2 = ret1;
698 } 966 }
699 967
700 return ret; 968 return ret2;
701} 969}
702 970
703static int test_term(struct test__term *t) 971static int test_term(struct test__term *t)
@@ -758,13 +1026,13 @@ static int test_pmu(void)
758 1026
759int parse_events__test(void) 1027int parse_events__test(void)
760{ 1028{
761 int ret; 1029 int ret1, ret2 = 0;
762 1030
763#define TEST_EVENTS(tests) \ 1031#define TEST_EVENTS(tests) \
764do { \ 1032do { \
765 ret = test_events(tests, ARRAY_SIZE(tests)); \ 1033 ret1 = test_events(tests, ARRAY_SIZE(tests)); \
766 if (ret) \ 1034 if (!ret2) \
767 return ret; \ 1035 ret2 = ret1; \
768} while (0) 1036} while (0)
769 1037
770 TEST_EVENTS(test__events); 1038 TEST_EVENTS(test__events);
@@ -772,5 +1040,9 @@ do { \
772 if (test_pmu()) 1040 if (test_pmu())
773 TEST_EVENTS(test__events_pmu); 1041 TEST_EVENTS(test__events_pmu);
774 1042
775 return test_terms(test__terms, ARRAY_SIZE(test__terms)); 1043 ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
1044 if (!ret2)
1045 ret2 = ret1;
1046
1047 return ret2;
776} 1048}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 74a5af4d33ec..75c7b0fca6d9 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -239,8 +239,11 @@ const char *event_type(int type)
239 return "unknown"; 239 return "unknown";
240} 240}
241 241
242static int add_event(struct list_head **_list, int *idx, 242
243 struct perf_event_attr *attr, char *name) 243
244static int __add_event(struct list_head **_list, int *idx,
245 struct perf_event_attr *attr,
246 char *name, struct cpu_map *cpus)
244{ 247{
245 struct perf_evsel *evsel; 248 struct perf_evsel *evsel;
246 struct list_head *list = *_list; 249 struct list_head *list = *_list;
@@ -260,6 +263,7 @@ static int add_event(struct list_head **_list, int *idx,
260 return -ENOMEM; 263 return -ENOMEM;
261 } 264 }
262 265
266 evsel->cpus = cpus;
263 if (name) 267 if (name)
264 evsel->name = strdup(name); 268 evsel->name = strdup(name);
265 list_add_tail(&evsel->node, list); 269 list_add_tail(&evsel->node, list);
@@ -267,6 +271,12 @@ static int add_event(struct list_head **_list, int *idx,
267 return 0; 271 return 0;
268} 272}
269 273
274static int add_event(struct list_head **_list, int *idx,
275 struct perf_event_attr *attr, char *name)
276{
277 return __add_event(_list, idx, attr, name, NULL);
278}
279
270static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 280static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
271{ 281{
272 int i, j; 282 int i, j;
@@ -308,7 +318,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,
308 for (i = 0; (i < 2) && (op_result[i]); i++) { 318 for (i = 0; (i < 2) && (op_result[i]); i++) {
309 char *str = op_result[i]; 319 char *str = op_result[i];
310 320
311 snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); 321 n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str);
312 322
313 if (cache_op == -1) { 323 if (cache_op == -1) {
314 cache_op = parse_aliases(str, perf_evsel__hw_cache_op, 324 cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
@@ -346,42 +356,28 @@ int parse_events_add_cache(struct list_head **list, int *idx,
346 return add_event(list, idx, &attr, name); 356 return add_event(list, idx, &attr, name);
347} 357}
348 358
349static int add_tracepoint(struct list_head **list, int *idx, 359static int add_tracepoint(struct list_head **listp, int *idx,
350 char *sys_name, char *evt_name) 360 char *sys_name, char *evt_name)
351{ 361{
352 struct perf_event_attr attr; 362 struct perf_evsel *evsel;
353 char name[MAX_NAME_LEN]; 363 struct list_head *list = *listp;
354 char evt_path[MAXPATHLEN];
355 char id_buf[4];
356 u64 id;
357 int fd;
358
359 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
360 sys_name, evt_name);
361
362 fd = open(evt_path, O_RDONLY);
363 if (fd < 0)
364 return -1;
365 364
366 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 365 if (!list) {
367 close(fd); 366 list = malloc(sizeof(*list));
368 return -1; 367 if (!list)
368 return -ENOMEM;
369 INIT_LIST_HEAD(list);
369 } 370 }
370 371
371 close(fd); 372 evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++);
372 id = atoll(id_buf); 373 if (!evsel) {
373 374 free(list);
374 memset(&attr, 0, sizeof(attr)); 375 return -ENOMEM;
375 attr.config = id; 376 }
376 attr.type = PERF_TYPE_TRACEPOINT;
377 attr.sample_type |= PERF_SAMPLE_RAW;
378 attr.sample_type |= PERF_SAMPLE_TIME;
379 attr.sample_type |= PERF_SAMPLE_CPU;
380 attr.sample_type |= PERF_SAMPLE_PERIOD;
381 attr.sample_period = 1;
382 377
383 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name); 378 list_add_tail(&evsel->node, list);
384 return add_event(list, idx, &attr, name); 379 *listp = list;
380 return 0;
385} 381}
386 382
387static int add_tracepoint_multi(struct list_head **list, int *idx, 383static int add_tracepoint_multi(struct list_head **list, int *idx,
@@ -551,7 +547,7 @@ static int config_attr(struct perf_event_attr *attr,
551} 547}
552 548
553int parse_events_add_numeric(struct list_head **list, int *idx, 549int parse_events_add_numeric(struct list_head **list, int *idx,
554 unsigned long type, unsigned long config, 550 u32 type, u64 config,
555 struct list_head *head_config) 551 struct list_head *head_config)
556{ 552{
557 struct perf_event_attr attr; 553 struct perf_event_attr attr;
@@ -607,8 +603,23 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
607 if (perf_pmu__config(pmu, &attr, head_config)) 603 if (perf_pmu__config(pmu, &attr, head_config))
608 return -EINVAL; 604 return -EINVAL;
609 605
610 return add_event(list, idx, &attr, 606 return __add_event(list, idx, &attr, pmu_event_name(head_config),
611 pmu_event_name(head_config)); 607 pmu->cpus);
608}
609
610int parse_events__modifier_group(struct list_head *list,
611 char *event_mod)
612{
613 return parse_events__modifier_event(list, event_mod, true);
614}
615
616void parse_events__set_leader(char *name, struct list_head *list)
617{
618 struct perf_evsel *leader;
619
620 __perf_evlist__set_leader(list);
621 leader = list_entry(list->next, struct perf_evsel, node);
622 leader->group_name = name ? strdup(name) : NULL;
612} 623}
613 624
614void parse_events_update_lists(struct list_head *list_event, 625void parse_events_update_lists(struct list_head *list_event,
@@ -616,21 +627,45 @@ void parse_events_update_lists(struct list_head *list_event,
616{ 627{
617 /* 628 /*
618 * Called for single event definition. Update the 629 * Called for single event definition. Update the
619 * 'all event' list, and reinit the 'signle event' 630 * 'all event' list, and reinit the 'single event'
620 * list, for next event definition. 631 * list, for next event definition.
621 */ 632 */
622 list_splice_tail(list_event, list_all); 633 list_splice_tail(list_event, list_all);
623 free(list_event); 634 free(list_event);
624} 635}
625 636
626int parse_events_modifier(struct list_head *list, char *str) 637struct event_modifier {
638 int eu;
639 int ek;
640 int eh;
641 int eH;
642 int eG;
643 int precise;
644 int exclude_GH;
645};
646
647static int get_event_modifier(struct event_modifier *mod, char *str,
648 struct perf_evsel *evsel)
627{ 649{
628 struct perf_evsel *evsel; 650 int eu = evsel ? evsel->attr.exclude_user : 0;
629 int exclude = 0, exclude_GH = 0; 651 int ek = evsel ? evsel->attr.exclude_kernel : 0;
630 int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0; 652 int eh = evsel ? evsel->attr.exclude_hv : 0;
653 int eH = evsel ? evsel->attr.exclude_host : 0;
654 int eG = evsel ? evsel->attr.exclude_guest : 0;
655 int precise = evsel ? evsel->attr.precise_ip : 0;
631 656
632 if (str == NULL) 657 int exclude = eu | ek | eh;
633 return 0; 658 int exclude_GH = evsel ? evsel->exclude_GH : 0;
659
660 /*
661 * We are here for group and 'GH' was not set as event
662 * modifier and whatever event/group modifier override
663 * default 'GH' setup.
664 */
665 if (evsel && !exclude_GH)
666 eH = eG = 0;
667
668 memset(mod, 0, sizeof(*mod));
634 669
635 while (*str) { 670 while (*str) {
636 if (*str == 'u') { 671 if (*str == 'u') {
@@ -655,6 +690,9 @@ int parse_events_modifier(struct list_head *list, char *str)
655 eH = 0; 690 eH = 0;
656 } else if (*str == 'p') { 691 } else if (*str == 'p') {
657 precise++; 692 precise++;
693 /* use of precise requires exclude_guest */
694 if (!exclude_GH)
695 eG = 1;
658 } else 696 } else
659 break; 697 break;
660 698
@@ -674,13 +712,51 @@ int parse_events_modifier(struct list_head *list, char *str)
674 if (precise > 3) 712 if (precise > 3)
675 return -EINVAL; 713 return -EINVAL;
676 714
715 mod->eu = eu;
716 mod->ek = ek;
717 mod->eh = eh;
718 mod->eH = eH;
719 mod->eG = eG;
720 mod->precise = precise;
721 mod->exclude_GH = exclude_GH;
722 return 0;
723}
724
725int parse_events__modifier_event(struct list_head *list, char *str, bool add)
726{
727 struct perf_evsel *evsel;
728 struct event_modifier mod;
729
730 if (str == NULL)
731 return 0;
732
733 if (!add && get_event_modifier(&mod, str, NULL))
734 return -EINVAL;
735
736 list_for_each_entry(evsel, list, node) {
737
738 if (add && get_event_modifier(&mod, str, evsel))
739 return -EINVAL;
740
741 evsel->attr.exclude_user = mod.eu;
742 evsel->attr.exclude_kernel = mod.ek;
743 evsel->attr.exclude_hv = mod.eh;
744 evsel->attr.precise_ip = mod.precise;
745 evsel->attr.exclude_host = mod.eH;
746 evsel->attr.exclude_guest = mod.eG;
747 evsel->exclude_GH = mod.exclude_GH;
748 }
749
750 return 0;
751}
752
753int parse_events_name(struct list_head *list, char *name)
754{
755 struct perf_evsel *evsel;
756
677 list_for_each_entry(evsel, list, node) { 757 list_for_each_entry(evsel, list, node) {
678 evsel->attr.exclude_user = eu; 758 if (!evsel->name)
679 evsel->attr.exclude_kernel = ek; 759 evsel->name = strdup(name);
680 evsel->attr.exclude_hv = eh;
681 evsel->attr.precise_ip = precise;
682 evsel->attr.exclude_host = eH;
683 evsel->attr.exclude_guest = eG;
684 } 760 }
685 761
686 return 0; 762 return 0;
@@ -730,7 +806,8 @@ int parse_events_terms(struct list_head *terms, const char *str)
730 return ret; 806 return ret;
731} 807}
732 808
733int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) 809int parse_events(struct perf_evlist *evlist, const char *str,
810 int unset __maybe_unused)
734{ 811{
735 struct parse_events_data__events data = { 812 struct parse_events_data__events data = {
736 .list = LIST_HEAD_INIT(data.list), 813 .list = LIST_HEAD_INIT(data.list),
@@ -756,20 +833,20 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
756} 833}
757 834
758int parse_events_option(const struct option *opt, const char *str, 835int parse_events_option(const struct option *opt, const char *str,
759 int unset __used) 836 int unset __maybe_unused)
760{ 837{
761 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 838 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
762 return parse_events(evlist, str, unset); 839 return parse_events(evlist, str, unset);
763} 840}
764 841
765int parse_filter(const struct option *opt, const char *str, 842int parse_filter(const struct option *opt, const char *str,
766 int unset __used) 843 int unset __maybe_unused)
767{ 844{
768 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 845 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
769 struct perf_evsel *last = NULL; 846 struct perf_evsel *last = NULL;
770 847
771 if (evlist->nr_entries > 0) 848 if (evlist->nr_entries > 0)
772 last = list_entry(evlist->entries.prev, struct perf_evsel, node); 849 last = perf_evlist__last(evlist);
773 850
774 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 851 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
775 fprintf(stderr, 852 fprintf(stderr,
@@ -799,7 +876,8 @@ static const char * const event_type_descriptors[] = {
799 * Print the events from <debugfs_mount_point>/tracing/events 876 * Print the events from <debugfs_mount_point>/tracing/events
800 */ 877 */
801 878
802void print_tracepoint_events(const char *subsys_glob, const char *event_glob) 879void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
880 bool name_only)
803{ 881{
804 DIR *sys_dir, *evt_dir; 882 DIR *sys_dir, *evt_dir;
805 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 883 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
@@ -829,6 +907,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
829 !strglobmatch(evt_dirent.d_name, event_glob)) 907 !strglobmatch(evt_dirent.d_name, event_glob))
830 continue; 908 continue;
831 909
910 if (name_only) {
911 printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
912 continue;
913 }
914
832 snprintf(evt_path, MAXPATHLEN, "%s:%s", 915 snprintf(evt_path, MAXPATHLEN, "%s:%s",
833 sys_dirent.d_name, evt_dirent.d_name); 916 sys_dirent.d_name, evt_dirent.d_name);
834 printf(" %-50s [%s]\n", evt_path, 917 printf(" %-50s [%s]\n", evt_path,
@@ -906,7 +989,7 @@ void print_events_type(u8 type)
906 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); 989 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
907} 990}
908 991
909int print_hwcache_events(const char *event_glob) 992int print_hwcache_events(const char *event_glob, bool name_only)
910{ 993{
911 unsigned int type, op, i, printed = 0; 994 unsigned int type, op, i, printed = 0;
912 char name[64]; 995 char name[64];
@@ -923,8 +1006,11 @@ int print_hwcache_events(const char *event_glob)
923 if (event_glob != NULL && !strglobmatch(name, event_glob)) 1006 if (event_glob != NULL && !strglobmatch(name, event_glob))
924 continue; 1007 continue;
925 1008
926 printf(" %-50s [%s]\n", name, 1009 if (name_only)
927 event_type_descriptors[PERF_TYPE_HW_CACHE]); 1010 printf("%s ", name);
1011 else
1012 printf(" %-50s [%s]\n", name,
1013 event_type_descriptors[PERF_TYPE_HW_CACHE]);
928 ++printed; 1014 ++printed;
929 } 1015 }
930 } 1016 }
@@ -934,7 +1020,8 @@ int print_hwcache_events(const char *event_glob)
934} 1020}
935 1021
936static void print_symbol_events(const char *event_glob, unsigned type, 1022static void print_symbol_events(const char *event_glob, unsigned type,
937 struct event_symbol *syms, unsigned max) 1023 struct event_symbol *syms, unsigned max,
1024 bool name_only)
938{ 1025{
939 unsigned i, printed = 0; 1026 unsigned i, printed = 0;
940 char name[MAX_NAME_LEN]; 1027 char name[MAX_NAME_LEN];
@@ -946,6 +1033,11 @@ static void print_symbol_events(const char *event_glob, unsigned type,
946 (syms->alias && strglobmatch(syms->alias, event_glob)))) 1033 (syms->alias && strglobmatch(syms->alias, event_glob))))
947 continue; 1034 continue;
948 1035
1036 if (name_only) {
1037 printf("%s ", syms->symbol);
1038 continue;
1039 }
1040
949 if (strlen(syms->alias)) 1041 if (strlen(syms->alias))
950 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 1042 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
951 else 1043 else
@@ -963,39 +1055,42 @@ static void print_symbol_events(const char *event_glob, unsigned type,
963/* 1055/*
964 * Print the help text for the event symbols: 1056 * Print the help text for the event symbols:
965 */ 1057 */
966void print_events(const char *event_glob) 1058void print_events(const char *event_glob, bool name_only)
967{ 1059{
968 1060 if (!name_only) {
969 printf("\n"); 1061 printf("\n");
970 printf("List of pre-defined events (to be used in -e):\n"); 1062 printf("List of pre-defined events (to be used in -e):\n");
1063 }
971 1064
972 print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 1065 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
973 event_symbols_hw, PERF_COUNT_HW_MAX); 1066 event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
974 1067
975 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, 1068 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
976 event_symbols_sw, PERF_COUNT_SW_MAX); 1069 event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
977 1070
978 print_hwcache_events(event_glob); 1071 print_hwcache_events(event_glob, name_only);
979 1072
980 if (event_glob != NULL) 1073 if (event_glob != NULL)
981 return; 1074 return;
982 1075
983 printf("\n"); 1076 if (!name_only) {
984 printf(" %-50s [%s]\n", 1077 printf("\n");
985 "rNNN", 1078 printf(" %-50s [%s]\n",
986 event_type_descriptors[PERF_TYPE_RAW]); 1079 "rNNN",
987 printf(" %-50s [%s]\n", 1080 event_type_descriptors[PERF_TYPE_RAW]);
988 "cpu/t1=v1[,t2=v2,t3 ...]/modifier", 1081 printf(" %-50s [%s]\n",
989 event_type_descriptors[PERF_TYPE_RAW]); 1082 "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
990 printf(" (see 'perf list --help' on how to encode it)\n"); 1083 event_type_descriptors[PERF_TYPE_RAW]);
991 printf("\n"); 1084 printf(" (see 'perf list --help' on how to encode it)\n");
992 1085 printf("\n");
993 printf(" %-50s [%s]\n", 1086
994 "mem:<addr>[:access]", 1087 printf(" %-50s [%s]\n",
1088 "mem:<addr>[:access]",
995 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1089 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
996 printf("\n"); 1090 printf("\n");
1091 }
997 1092
998 print_tracepoint_events(NULL, NULL); 1093 print_tracepoint_events(NULL, NULL, name_only);
999} 1094}
1000 1095
1001int parse_events__is_hardcoded_term(struct parse_events__term *term) 1096int parse_events__is_hardcoded_term(struct parse_events__term *term)
@@ -1005,7 +1100,7 @@ int parse_events__is_hardcoded_term(struct parse_events__term *term)
1005 1100
1006static int new_term(struct parse_events__term **_term, int type_val, 1101static int new_term(struct parse_events__term **_term, int type_val,
1007 int type_term, char *config, 1102 int type_term, char *config,
1008 char *str, long num) 1103 char *str, u64 num)
1009{ 1104{
1010 struct parse_events__term *term; 1105 struct parse_events__term *term;
1011 1106
@@ -1034,7 +1129,7 @@ static int new_term(struct parse_events__term **_term, int type_val,
1034} 1129}
1035 1130
1036int parse_events__term_num(struct parse_events__term **term, 1131int parse_events__term_num(struct parse_events__term **term,
1037 int type_term, char *config, long num) 1132 int type_term, char *config, u64 num)
1038{ 1133{
1039 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, 1134 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
1040 config, NULL, num); 1135 config, NULL, num);
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ee9c218a193c..839230ceb18b 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -7,7 +7,7 @@
7#include <linux/list.h> 7#include <linux/list.h>
8#include <stdbool.h> 8#include <stdbool.h>
9#include "types.h" 9#include "types.h"
10#include "../../../include/linux/perf_event.h" 10#include "../../../include/uapi/linux/perf_event.h"
11#include "types.h" 11#include "types.h"
12 12
13struct list_head; 13struct list_head;
@@ -55,7 +55,7 @@ struct parse_events__term {
55 char *config; 55 char *config;
56 union { 56 union {
57 char *str; 57 char *str;
58 long num; 58 u64 num;
59 } val; 59 } val;
60 int type_val; 60 int type_val;
61 int type_term; 61 int type_term;
@@ -73,17 +73,19 @@ struct parse_events_data__terms {
73 73
74int parse_events__is_hardcoded_term(struct parse_events__term *term); 74int parse_events__is_hardcoded_term(struct parse_events__term *term);
75int parse_events__term_num(struct parse_events__term **_term, 75int parse_events__term_num(struct parse_events__term **_term,
76 int type_term, char *config, long num); 76 int type_term, char *config, u64 num);
77int parse_events__term_str(struct parse_events__term **_term, 77int parse_events__term_str(struct parse_events__term **_term,
78 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, 79int parse_events__term_clone(struct parse_events__term **new,
80 struct parse_events__term *term); 80 struct parse_events__term *term);
81void parse_events__free_terms(struct list_head *terms); 81void parse_events__free_terms(struct list_head *terms);
82int parse_events_modifier(struct list_head *list, char *str); 82int parse_events__modifier_event(struct list_head *list, char *str, bool add);
83int parse_events__modifier_group(struct list_head *list, char *event_mod);
84int parse_events_name(struct list_head *list, char *name);
83int parse_events_add_tracepoint(struct list_head **list, int *idx, 85int parse_events_add_tracepoint(struct list_head **list, int *idx,
84 char *sys, char *event); 86 char *sys, char *event);
85int parse_events_add_numeric(struct list_head **list, int *idx, 87int parse_events_add_numeric(struct list_head **list, int *idx,
86 unsigned long type, unsigned long config, 88 u32 type, u64 config,
87 struct list_head *head_config); 89 struct list_head *head_config);
88int parse_events_add_cache(struct list_head **list, int *idx, 90int parse_events_add_cache(struct list_head **list, int *idx,
89 char *type, char *op_result1, char *op_result2); 91 char *type, char *op_result1, char *op_result2);
@@ -91,15 +93,17 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
91 void *ptr, char *type); 93 void *ptr, char *type);
92int parse_events_add_pmu(struct list_head **list, int *idx, 94int parse_events_add_pmu(struct list_head **list, int *idx,
93 char *pmu , struct list_head *head_config); 95 char *pmu , struct list_head *head_config);
96void parse_events__set_leader(char *name, struct list_head *list);
94void parse_events_update_lists(struct list_head *list_event, 97void parse_events_update_lists(struct list_head *list_event,
95 struct list_head *list_all); 98 struct list_head *list_all);
96void parse_events_error(void *data, void *scanner, char const *msg); 99void parse_events_error(void *data, void *scanner, char const *msg);
97int parse_events__test(void); 100int parse_events__test(void);
98 101
99void print_events(const char *event_glob); 102void print_events(const char *event_glob, bool name_only);
100void print_events_type(u8 type); 103void print_events_type(u8 type);
101void print_tracepoint_events(const char *subsys_glob, const char *event_glob); 104void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
102int print_hwcache_events(const char *event_glob); 105 bool name_only);
106int print_hwcache_events(const char *event_glob, bool name_only);
103extern int is_valid_tracepoint(const char *event_string); 107extern int is_valid_tracepoint(const char *event_string);
104 108
105extern int valid_debugfs_mount(const char *debugfs); 109extern int valid_debugfs_mount(const char *debugfs);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 384ca74c6b22..c87efc12579d 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -15,10 +15,10 @@ YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
15 15
16static int __value(YYSTYPE *yylval, char *str, int base, int token) 16static int __value(YYSTYPE *yylval, char *str, int base, int token)
17{ 17{
18 long num; 18 u64 num;
19 19
20 errno = 0; 20 errno = 0;
21 num = strtoul(str, NULL, base); 21 num = strtoull(str, NULL, base);
22 if (errno) 22 if (errno)
23 return PE_ERROR; 23 return PE_ERROR;
24 24
@@ -70,6 +70,12 @@ static int term(yyscan_t scanner, int type)
70%} 70%}
71 71
72%x mem 72%x mem
73%s config
74%x event
75
76group [^,{}/]*[{][^}]*[}][^,{}/]*
77event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
78event [^,{}/]+
73 79
74num_dec [0-9]+ 80num_dec [0-9]+
75num_hex 0x[a-fA-F0-9]+ 81num_hex 0x[a-fA-F0-9]+
@@ -84,7 +90,13 @@ modifier_bp [rwx]{1,3}
84 { 90 {
85 int start_token; 91 int start_token;
86 92
87 start_token = (int) parse_events_get_extra(yyscanner); 93 start_token = parse_events_get_extra(yyscanner);
94
95 if (start_token == PE_START_TERMS)
96 BEGIN(config);
97 else if (start_token == PE_START_EVENTS)
98 BEGIN(event);
99
88 if (start_token) { 100 if (start_token) {
89 parse_events_set_extra(NULL, yyscanner); 101 parse_events_set_extra(NULL, yyscanner);
90 return start_token; 102 return start_token;
@@ -92,6 +104,26 @@ modifier_bp [rwx]{1,3}
92 } 104 }
93%} 105%}
94 106
107<event>{
108
109{group} {
110 BEGIN(INITIAL); yyless(0);
111 }
112
113{event_pmu} |
114{event} {
115 str(yyscanner, PE_EVENT_NAME);
116 BEGIN(INITIAL); yyless(0);
117 return PE_EVENT_NAME;
118 }
119
120. |
121<<EOF>> {
122 BEGIN(INITIAL); yyless(0);
123 }
124
125}
126
95cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 127cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
96stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 128stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
97stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 129stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
@@ -127,18 +159,16 @@ speculative-read|speculative-load |
127refs|Reference|ops|access | 159refs|Reference|ops|access |
128misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); } 160misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
129 161
130 /* 162<config>{
131 * These are event config hardcoded term names to be specified
132 * within xxx/.../ syntax. So far we dont clash with other names,
133 * so we can put them here directly. In case the we have a conflict
134 * in future, this needs to go into '//' condition block.
135 */
136config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } 163config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
137config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); } 164config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
138config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } 165config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
139name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } 166name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
140period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } 167period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
141branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 168branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
169, { return ','; }
170"/" { BEGIN(INITIAL); return '/'; }
171}
142 172
143mem: { BEGIN(mem); return PE_PREFIX_MEM; } 173mem: { BEGIN(mem); return PE_PREFIX_MEM; }
144r{num_raw_hex} { return raw(yyscanner); } 174r{num_raw_hex} { return raw(yyscanner); }
@@ -147,10 +177,12 @@ r{num_raw_hex} { return raw(yyscanner); }
147 177
148{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 178{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
149{name} { return str(yyscanner, PE_NAME); } 179{name} { return str(yyscanner, PE_NAME); }
150"/" { return '/'; } 180"/" { BEGIN(config); return '/'; }
151- { return '-'; } 181- { return '-'; }
152, { return ','; } 182, { BEGIN(event); return ','; }
153: { return ':'; } 183: { return ':'; }
184"{" { BEGIN(event); return '{'; }
185"}" { return '}'; }
154= { return '='; } 186= { return '='; }
155\n { } 187\n { }
156 188
@@ -175,7 +207,7 @@ r{num_raw_hex} { return raw(yyscanner); }
175 207
176%% 208%%
177 209
178int parse_events_wrap(void *scanner __used) 210int parse_events_wrap(void *scanner __maybe_unused)
179{ 211{
180 return 1; 212 return 1;
181} 213}
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 2bc5fbff2b5d..cd88209e3c58 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -27,10 +27,11 @@ do { \
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_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 29%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
30%token PE_EVENT_NAME
30%token PE_NAME 31%token PE_NAME
31%token PE_MODIFIER_EVENT PE_MODIFIER_BP 32%token PE_MODIFIER_EVENT PE_MODIFIER_BP
32%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 33%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
33%token PE_PREFIX_MEM PE_PREFIX_RAW 34%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
34%token PE_ERROR 35%token PE_ERROR
35%type <num> PE_VALUE 36%type <num> PE_VALUE
36%type <num> PE_VALUE_SYM_HW 37%type <num> PE_VALUE_SYM_HW
@@ -42,6 +43,7 @@ do { \
42%type <str> PE_NAME_CACHE_OP_RESULT 43%type <str> PE_NAME_CACHE_OP_RESULT
43%type <str> PE_MODIFIER_EVENT 44%type <str> PE_MODIFIER_EVENT
44%type <str> PE_MODIFIER_BP 45%type <str> PE_MODIFIER_BP
46%type <str> PE_EVENT_NAME
45%type <num> value_sym 47%type <num> value_sym
46%type <head> event_config 48%type <head> event_config
47%type <term> event_term 49%type <term> event_term
@@ -53,44 +55,125 @@ do { \
53%type <head> event_legacy_numeric 55%type <head> event_legacy_numeric
54%type <head> event_legacy_raw 56%type <head> event_legacy_raw
55%type <head> event_def 57%type <head> event_def
58%type <head> event_mod
59%type <head> event_name
60%type <head> event
61%type <head> events
62%type <head> group_def
63%type <head> group
64%type <head> groups
56 65
57%union 66%union
58{ 67{
59 char *str; 68 char *str;
60 unsigned long num; 69 u64 num;
61 struct list_head *head; 70 struct list_head *head;
62 struct parse_events__term *term; 71 struct parse_events__term *term;
63} 72}
64%% 73%%
65 74
66start: 75start:
67PE_START_EVENTS events 76PE_START_EVENTS start_events
68| 77|
69PE_START_TERMS terms 78PE_START_TERMS start_terms
79
80start_events: groups
81{
82 struct parse_events_data__events *data = _data;
83
84 parse_events_update_lists($1, &data->list);
85}
86
87groups:
88groups ',' group
89{
90 struct list_head *list = $1;
91 struct list_head *group = $3;
92
93 parse_events_update_lists(group, list);
94 $$ = list;
95}
96|
97groups ',' event
98{
99 struct list_head *list = $1;
100 struct list_head *event = $3;
101
102 parse_events_update_lists(event, list);
103 $$ = list;
104}
105|
106group
107|
108event
109
110group:
111group_def ':' PE_MODIFIER_EVENT
112{
113 struct list_head *list = $1;
114
115 ABORT_ON(parse_events__modifier_group(list, $3));
116 $$ = list;
117}
118|
119group_def
120
121group_def:
122PE_NAME '{' events '}'
123{
124 struct list_head *list = $3;
125
126 parse_events__set_leader($1, list);
127 $$ = list;
128}
129|
130'{' events '}'
131{
132 struct list_head *list = $2;
133
134 parse_events__set_leader(NULL, list);
135 $$ = list;
136}
70 137
71events: 138events:
72events ',' event | event 139events ',' event
140{
141 struct list_head *event = $3;
142 struct list_head *list = $1;
73 143
74event: 144 parse_events_update_lists(event, list);
75event_def PE_MODIFIER_EVENT 145 $$ = list;
146}
147|
148event
149
150event: event_mod
151
152event_mod:
153event_name PE_MODIFIER_EVENT
76{ 154{
77 struct parse_events_data__events *data = _data; 155 struct list_head *list = $1;
78 156
79 /* 157 /*
80 * Apply modifier on all events added by single event definition 158 * Apply modifier on all events added by single event definition
81 * (there could be more events added for multiple tracepoint 159 * (there could be more events added for multiple tracepoint
82 * definitions via '*?'. 160 * definitions via '*?'.
83 */ 161 */
84 ABORT_ON(parse_events_modifier($1, $2)); 162 ABORT_ON(parse_events__modifier_event(list, $2, false));
85 parse_events_update_lists($1, &data->list); 163 $$ = list;
86} 164}
87| 165|
88event_def 166event_name
89{
90 struct parse_events_data__events *data = _data;
91 167
92 parse_events_update_lists($1, &data->list); 168event_name:
169PE_EVENT_NAME event_def
170{
171 ABORT_ON(parse_events_name($2, $1));
172 free($1);
173 $$ = $2;
93} 174}
175|
176event_def
94 177
95event_def: event_pmu | 178event_def: event_pmu |
96 event_legacy_symbol | 179 event_legacy_symbol |
@@ -207,7 +290,7 @@ PE_VALUE ':' PE_VALUE
207 struct parse_events_data__events *data = _data; 290 struct parse_events_data__events *data = _data;
208 struct list_head *list = NULL; 291 struct list_head *list = NULL;
209 292
210 ABORT_ON(parse_events_add_numeric(&list, &data->idx, $1, $3, NULL)); 293 ABORT_ON(parse_events_add_numeric(&list, &data->idx, (u32)$1, $3, NULL));
211 $$ = list; 294 $$ = list;
212} 295}
213 296
@@ -222,7 +305,7 @@ PE_RAW
222 $$ = list; 305 $$ = list;
223} 306}
224 307
225terms: event_config 308start_terms: event_config
226{ 309{
227 struct parse_events_data__terms *data = _data; 310 struct parse_events_data__terms *data = _data;
228 data->terms = $1; 311 data->terms = $1;
@@ -282,7 +365,7 @@ PE_TERM '=' PE_NAME
282{ 365{
283 struct parse_events__term *term; 366 struct parse_events__term *term;
284 367
285 ABORT_ON(parse_events__term_str(&term, $1, NULL, $3)); 368 ABORT_ON(parse_events__term_str(&term, (int)$1, NULL, $3));
286 $$ = term; 369 $$ = term;
287} 370}
288| 371|
@@ -290,7 +373,7 @@ PE_TERM '=' PE_VALUE
290{ 373{
291 struct parse_events__term *term; 374 struct parse_events__term *term;
292 375
293 ABORT_ON(parse_events__term_num(&term, $1, NULL, $3)); 376 ABORT_ON(parse_events__term_num(&term, (int)$1, NULL, $3));
294 $$ = term; 377 $$ = term;
295} 378}
296| 379|
@@ -298,7 +381,7 @@ PE_TERM
298{ 381{
299 struct parse_events__term *term; 382 struct parse_events__term *term;
300 383
301 ABORT_ON(parse_events__term_num(&term, $1, NULL, 1)); 384 ABORT_ON(parse_events__term_num(&term, (int)$1, NULL, 1));
302 $$ = term; 385 $$ = term;
303} 386}
304 387
@@ -308,7 +391,7 @@ sep_slash_dc: '/' | ':' |
308 391
309%% 392%%
310 393
311void parse_events_error(void *data __used, void *scanner __used, 394void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused,
312 char const *msg __used) 395 char const *msg __maybe_unused)
313{ 396{
314} 397}
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 594f8fad5ecd..2bc9e70df7e2 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -384,6 +384,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
384 return usage_with_options_internal(usagestr, options, 1); 384 return usage_with_options_internal(usagestr, options, 1);
385 if (internal_help && !strcmp(arg + 2, "help")) 385 if (internal_help && !strcmp(arg + 2, "help"))
386 return parse_options_usage(usagestr, options); 386 return parse_options_usage(usagestr, options);
387 if (!strcmp(arg + 2, "list-opts"))
388 return PARSE_OPT_LIST;
387 switch (parse_long_opt(ctx, arg + 2, options)) { 389 switch (parse_long_opt(ctx, arg + 2, options)) {
388 case -1: 390 case -1:
389 return parse_options_usage(usagestr, options); 391 return parse_options_usage(usagestr, options);
@@ -422,6 +424,12 @@ int parse_options(int argc, const char **argv, const struct option *options,
422 exit(129); 424 exit(129);
423 case PARSE_OPT_DONE: 425 case PARSE_OPT_DONE:
424 break; 426 break;
427 case PARSE_OPT_LIST:
428 while (options->type != OPTION_END) {
429 printf("--%s ", options->long_name);
430 options++;
431 }
432 exit(130);
425 default: /* PARSE_OPT_UNKNOWN */ 433 default: /* PARSE_OPT_UNKNOWN */
426 if (ctx.argv[0][1] == '-') { 434 if (ctx.argv[0][1] == '-') {
427 error("unknown option `%s'", ctx.argv[0] + 2); 435 error("unknown option `%s'", ctx.argv[0] + 2);
@@ -557,7 +565,8 @@ int parse_options_usage(const char * const *usagestr,
557} 565}
558 566
559 567
560int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used, 568int parse_opt_verbosity_cb(const struct option *opt,
569 const char *arg __maybe_unused,
561 int unset) 570 int unset)
562{ 571{
563 int *target = opt->value; 572 int *target = opt->value;
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index abc31a1dac1a..7bb5999940ca 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -140,6 +140,7 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
140enum { 140enum {
141 PARSE_OPT_HELP = -1, 141 PARSE_OPT_HELP = -1,
142 PARSE_OPT_DONE, 142 PARSE_OPT_DONE,
143 PARSE_OPT_LIST,
143 PARSE_OPT_UNKNOWN, 144 PARSE_OPT_UNKNOWN,
144}; 145};
145 146
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index bd7497711424..a8c49548ca48 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,7 +22,7 @@ static const char *get_perf_dir(void)
22 return "."; 22 return ".";
23} 23}
24 24
25#ifdef NO_STRLCPY 25#ifndef HAVE_STRLCPY
26size_t strlcpy(char *dest, const char *src, size_t size) 26size_t strlcpy(char *dest, const char *src, size_t size)
27{ 27{
28 size_t ret = strlen(src); 28 size_t ret = strlen(src);
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
new file mode 100644
index 000000000000..5a4f2b6f3738
--- /dev/null
+++ b/tools/perf/util/perf_regs.h
@@ -0,0 +1,14 @@
1#ifndef __PERF_REGS_H
2#define __PERF_REGS_H
3
4#ifdef HAVE_PERF_REGS
5#include <perf_regs.h>
6#else
7#define PERF_REGS_MASK 0
8
9static inline const char *perf_reg_name(int id __maybe_unused)
10{
11 return NULL;
12}
13#endif /* HAVE_PERF_REGS */
14#endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 67715a42cd6d..8a2229da594f 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -9,6 +9,9 @@
9#include "util.h" 9#include "util.h"
10#include "pmu.h" 10#include "pmu.h"
11#include "parse-events.h" 11#include "parse-events.h"
12#include "cpumap.h"
13
14#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
12 15
13int perf_pmu_parse(struct list_head *list, char *name); 16int perf_pmu_parse(struct list_head *list, char *name);
14extern FILE *perf_pmu_in; 17extern FILE *perf_pmu_in;
@@ -69,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
69 return -1; 72 return -1;
70 73
71 snprintf(path, PATH_MAX, 74 snprintf(path, PATH_MAX,
72 "%s/bus/event_source/devices/%s/format", sysfs, name); 75 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
73 76
74 if (stat(path, &st) < 0) 77 if (stat(path, &st) < 0)
75 return 0; /* no error if format does not exist */ 78 return 0; /* no error if format does not exist */
@@ -206,7 +209,7 @@ static int pmu_type(char *name, __u32 *type)
206 return -1; 209 return -1;
207 210
208 snprintf(path, PATH_MAX, 211 snprintf(path, PATH_MAX,
209 "%s/bus/event_source/devices/%s/type", sysfs, name); 212 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
210 213
211 if (stat(path, &st) < 0) 214 if (stat(path, &st) < 0)
212 return -1; 215 return -1;
@@ -222,6 +225,62 @@ static int pmu_type(char *name, __u32 *type)
222 return ret; 225 return ret;
223} 226}
224 227
228/* Add all pmus in sysfs to pmu list: */
229static void pmu_read_sysfs(void)
230{
231 char path[PATH_MAX];
232 const char *sysfs;
233 DIR *dir;
234 struct dirent *dent;
235
236 sysfs = sysfs_find_mountpoint();
237 if (!sysfs)
238 return;
239
240 snprintf(path, PATH_MAX,
241 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
242
243 dir = opendir(path);
244 if (!dir)
245 return;
246
247 while ((dent = readdir(dir))) {
248 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
249 continue;
250 /* add to static LIST_HEAD(pmus): */
251 perf_pmu__find(dent->d_name);
252 }
253
254 closedir(dir);
255}
256
257static struct cpu_map *pmu_cpumask(char *name)
258{
259 struct stat st;
260 char path[PATH_MAX];
261 const char *sysfs;
262 FILE *file;
263 struct cpu_map *cpus;
264
265 sysfs = sysfs_find_mountpoint();
266 if (!sysfs)
267 return NULL;
268
269 snprintf(path, PATH_MAX,
270 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
271
272 if (stat(path, &st) < 0)
273 return NULL;
274
275 file = fopen(path, "r");
276 if (!file)
277 return NULL;
278
279 cpus = cpu_map__read(file);
280 fclose(file);
281 return cpus;
282}
283
225static struct perf_pmu *pmu_lookup(char *name) 284static struct perf_pmu *pmu_lookup(char *name)
226{ 285{
227 struct perf_pmu *pmu; 286 struct perf_pmu *pmu;
@@ -244,6 +303,8 @@ static struct perf_pmu *pmu_lookup(char *name)
244 if (!pmu) 303 if (!pmu)
245 return NULL; 304 return NULL;
246 305
306 pmu->cpus = pmu_cpumask(name);
307
247 pmu_aliases(name, &aliases); 308 pmu_aliases(name, &aliases);
248 309
249 INIT_LIST_HEAD(&pmu->format); 310 INIT_LIST_HEAD(&pmu->format);
@@ -267,6 +328,21 @@ static struct perf_pmu *pmu_find(char *name)
267 return NULL; 328 return NULL;
268} 329}
269 330
331struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
332{
333 /*
334 * pmu iterator: If pmu is NULL, we start at the begin,
335 * otherwise return the next pmu. Returns NULL on end.
336 */
337 if (!pmu) {
338 pmu_read_sysfs();
339 pmu = list_prepare_entry(pmu, &pmus, list);
340 }
341 list_for_each_entry_continue(pmu, &pmus, list)
342 return pmu;
343 return NULL;
344}
345
270struct perf_pmu *perf_pmu__find(char *name) 346struct perf_pmu *perf_pmu__find(char *name)
271{ 347{
272 struct perf_pmu *pmu; 348 struct perf_pmu *pmu;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 535f2c5258ab..39f3abac7744 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -2,7 +2,7 @@
2#define __PMU_H 2#define __PMU_H
3 3
4#include <linux/bitops.h> 4#include <linux/bitops.h>
5#include "../../../include/linux/perf_event.h" 5#include "../../../include/uapi/linux/perf_event.h"
6 6
7enum { 7enum {
8 PERF_PMU_FORMAT_VALUE_CONFIG, 8 PERF_PMU_FORMAT_VALUE_CONFIG,
@@ -28,6 +28,7 @@ struct perf_pmu__alias {
28struct perf_pmu { 28struct perf_pmu {
29 char *name; 29 char *name;
30 __u32 type; 30 __u32 type;
31 struct cpu_map *cpus;
31 struct list_head format; 32 struct list_head format;
32 struct list_head aliases; 33 struct list_head aliases;
33 struct list_head list; 34 struct list_head list;
@@ -46,5 +47,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
46 int config, unsigned long *bits); 47 int config, unsigned long *bits);
47void perf_pmu__set_format(unsigned long *bits, long from, long to); 48void perf_pmu__set_format(unsigned long *bits, long from, long to);
48 49
50struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
51
49int perf_pmu__test(void); 52int perf_pmu__test(void);
50#endif /* __PMU_H */ 53#endif /* __PMU_H */
diff --git a/tools/perf/util/pmu.y b/tools/perf/util/pmu.y
index 20ea77e93169..ec898047ebb9 100644
--- a/tools/perf/util/pmu.y
+++ b/tools/perf/util/pmu.y
@@ -86,8 +86,8 @@ PP_VALUE
86 86
87%% 87%%
88 88
89void perf_pmu_error(struct list_head *list __used, 89void perf_pmu_error(struct list_head *list __maybe_unused,
90 char *name __used, 90 char *name __maybe_unused,
91 char const *msg __used) 91 char const *msg __maybe_unused)
92{ 92{
93} 93}
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 0dda25d82d06..49a256e6e0a2 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -41,7 +41,7 @@
41#include "symbol.h" 41#include "symbol.h"
42#include "thread.h" 42#include "thread.h"
43#include "debugfs.h" 43#include "debugfs.h"
44#include "trace-event.h" /* For __unused */ 44#include "trace-event.h" /* For __maybe_unused */
45#include "probe-event.h" 45#include "probe-event.h"
46#include "probe-finder.h" 46#include "probe-finder.h"
47#include "session.h" 47#include "session.h"
@@ -647,8 +647,8 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
647} 647}
648 648
649static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 649static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
650 struct probe_trace_event **tevs __unused, 650 struct probe_trace_event **tevs __maybe_unused,
651 int max_tevs __unused, const char *target) 651 int max_tevs __maybe_unused, const char *target)
652{ 652{
653 if (perf_probe_event_need_dwarf(pev)) { 653 if (perf_probe_event_need_dwarf(pev)) {
654 pr_warning("Debuginfo-analysis is not supported.\n"); 654 pr_warning("Debuginfo-analysis is not supported.\n");
@@ -661,17 +661,18 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
661 return 0; 661 return 0;
662} 662}
663 663
664int show_line_range(struct line_range *lr __unused, const char *module __unused) 664int show_line_range(struct line_range *lr __maybe_unused,
665 const char *module __maybe_unused)
665{ 666{
666 pr_warning("Debuginfo-analysis is not supported.\n"); 667 pr_warning("Debuginfo-analysis is not supported.\n");
667 return -ENOSYS; 668 return -ENOSYS;
668} 669}
669 670
670int show_available_vars(struct perf_probe_event *pevs __unused, 671int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
671 int npevs __unused, int max_vls __unused, 672 int npevs __maybe_unused, int max_vls __maybe_unused,
672 const char *module __unused, 673 const char *module __maybe_unused,
673 struct strfilter *filter __unused, 674 struct strfilter *filter __maybe_unused,
674 bool externs __unused) 675 bool externs __maybe_unused)
675{ 676{
676 pr_warning("Debuginfo-analysis is not supported.\n"); 677 pr_warning("Debuginfo-analysis is not supported.\n");
677 return -ENOSYS; 678 return -ENOSYS;
@@ -1099,6 +1100,7 @@ static int parse_probe_trace_command(const char *cmd,
1099 struct probe_trace_point *tp = &tev->point; 1100 struct probe_trace_point *tp = &tev->point;
1100 char pr; 1101 char pr;
1101 char *p; 1102 char *p;
1103 char *argv0_str = NULL, *fmt, *fmt1_str, *fmt2_str, *fmt3_str;
1102 int ret, i, argc; 1104 int ret, i, argc;
1103 char **argv; 1105 char **argv;
1104 1106
@@ -1115,14 +1117,27 @@ static int parse_probe_trace_command(const char *cmd,
1115 } 1117 }
1116 1118
1117 /* Scan event and group name. */ 1119 /* Scan event and group name. */
1118 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", 1120 argv0_str = strdup(argv[0]);
1119 &pr, (float *)(void *)&tev->group, 1121 if (argv0_str == NULL) {
1120 (float *)(void *)&tev->event); 1122 ret = -ENOMEM;
1121 if (ret != 3) { 1123 goto out;
1124 }
1125 fmt1_str = strtok_r(argv0_str, ":", &fmt);
1126 fmt2_str = strtok_r(NULL, "/", &fmt);
1127 fmt3_str = strtok_r(NULL, " \t", &fmt);
1128 if (fmt1_str == NULL || strlen(fmt1_str) != 1 || fmt2_str == NULL
1129 || fmt3_str == NULL) {
1122 semantic_error("Failed to parse event name: %s\n", argv[0]); 1130 semantic_error("Failed to parse event name: %s\n", argv[0]);
1123 ret = -EINVAL; 1131 ret = -EINVAL;
1124 goto out; 1132 goto out;
1125 } 1133 }
1134 pr = fmt1_str[0];
1135 tev->group = strdup(fmt2_str);
1136 tev->event = strdup(fmt3_str);
1137 if (tev->group == NULL || tev->event == NULL) {
1138 ret = -ENOMEM;
1139 goto out;
1140 }
1126 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 1141 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
1127 1142
1128 tp->retprobe = (pr == 'r'); 1143 tp->retprobe = (pr == 'r');
@@ -1134,10 +1149,17 @@ static int parse_probe_trace_command(const char *cmd,
1134 p++; 1149 p++;
1135 } else 1150 } else
1136 p = argv[1]; 1151 p = argv[1];
1137 ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol, 1152 fmt1_str = strtok_r(p, "+", &fmt);
1138 &tp->offset); 1153 tp->symbol = strdup(fmt1_str);
1139 if (ret == 1) 1154 if (tp->symbol == NULL) {
1155 ret = -ENOMEM;
1156 goto out;
1157 }
1158 fmt2_str = strtok_r(NULL, "", &fmt);
1159 if (fmt2_str == NULL)
1140 tp->offset = 0; 1160 tp->offset = 0;
1161 else
1162 tp->offset = strtoul(fmt2_str, NULL, 10);
1141 1163
1142 tev->nargs = argc - 2; 1164 tev->nargs = argc - 2;
1143 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1165 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
@@ -1161,6 +1183,7 @@ static int parse_probe_trace_command(const char *cmd,
1161 } 1183 }
1162 ret = 0; 1184 ret = 0;
1163out: 1185out:
1186 free(argv0_str);
1164 argv_free(argv); 1187 argv_free(argv);
1165 return ret; 1188 return ret;
1166} 1189}
@@ -2183,7 +2206,7 @@ static struct strfilter *available_func_filter;
2183 * If a symbol corresponds to a function with global binding and 2206 * If a symbol corresponds to a function with global binding and
2184 * matches filter return 0. For all others return 1. 2207 * matches filter return 0. For all others return 1.
2185 */ 2208 */
2186static int filter_available_functions(struct map *map __unused, 2209static int filter_available_functions(struct map *map __maybe_unused,
2187 struct symbol *sym) 2210 struct symbol *sym)
2188{ 2211{
2189 if (sym->binding == STB_GLOBAL && 2212 if (sym->binding == STB_GLOBAL &&
@@ -2307,10 +2330,17 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
2307 function = NULL; 2330 function = NULL;
2308 } 2331 }
2309 if (!pev->group) { 2332 if (!pev->group) {
2310 char *ptr1, *ptr2; 2333 char *ptr1, *ptr2, *exec_copy;
2311 2334
2312 pev->group = zalloc(sizeof(char *) * 64); 2335 pev->group = zalloc(sizeof(char *) * 64);
2313 ptr1 = strdup(basename(exec)); 2336 exec_copy = strdup(exec);
2337 if (!exec_copy) {
2338 ret = -ENOMEM;
2339 pr_warning("Failed to copy exec string.\n");
2340 goto out;
2341 }
2342
2343 ptr1 = strdup(basename(exec_copy));
2314 if (ptr1) { 2344 if (ptr1) {
2315 ptr2 = strpbrk(ptr1, "-._"); 2345 ptr2 = strpbrk(ptr1, "-._");
2316 if (ptr2) 2346 if (ptr2)
@@ -2319,6 +2349,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
2319 ptr1); 2349 ptr1);
2320 free(ptr1); 2350 free(ptr1);
2321 } 2351 }
2352 free(exec_copy);
2322 } 2353 }
2323 free(pp->function); 2354 free(pp->function);
2324 pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); 2355 pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index d448984ed789..1daf5c14e751 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -207,7 +207,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
207#else 207#else
208/* With older elfutils, this just support kernel module... */ 208/* With older elfutils, this just support kernel module... */
209static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, 209static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
210 Dwarf_Addr addr __used) 210 Dwarf_Addr addr __maybe_unused)
211{ 211{
212 const char *path = kernel_get_module_path("kernel"); 212 const char *path = kernel_get_module_path("kernel");
213 213
@@ -525,8 +525,10 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
525 return -ENOENT; 525 return -ENOENT;
526 } 526 }
527 /* Verify it is a data structure */ 527 /* Verify it is a data structure */
528 if (dwarf_tag(&type) != DW_TAG_structure_type) { 528 tag = dwarf_tag(&type);
529 pr_warning("%s is not a data structure.\n", varname); 529 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
530 pr_warning("%s is not a data structure nor an union.\n",
531 varname);
530 return -EINVAL; 532 return -EINVAL;
531 } 533 }
532 534
@@ -539,8 +541,9 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
539 *ref_ptr = ref; 541 *ref_ptr = ref;
540 } else { 542 } else {
541 /* Verify it is a data structure */ 543 /* Verify it is a data structure */
542 if (tag != DW_TAG_structure_type) { 544 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
543 pr_warning("%s is not a data structure.\n", varname); 545 pr_warning("%s is not a data structure nor an union.\n",
546 varname);
544 return -EINVAL; 547 return -EINVAL;
545 } 548 }
546 if (field->name[0] == '[') { 549 if (field->name[0] == '[') {
@@ -567,10 +570,15 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
567 } 570 }
568 571
569 /* Get the offset of the field */ 572 /* Get the offset of the field */
570 ret = die_get_data_member_location(die_mem, &offs); 573 if (tag == DW_TAG_union_type) {
571 if (ret < 0) { 574 offs = 0;
572 pr_warning("Failed to get the offset of %s.\n", field->name); 575 } else {
573 return ret; 576 ret = die_get_data_member_location(die_mem, &offs);
577 if (ret < 0) {
578 pr_warning("Failed to get the offset of %s.\n",
579 field->name);
580 return ret;
581 }
574 } 582 }
575 ref->offset += (long)offs; 583 ref->offset += (long)offs;
576 584
@@ -1419,7 +1427,7 @@ static int line_range_add_line(const char *src, unsigned int lineno,
1419} 1427}
1420 1428
1421static int line_range_walk_cb(const char *fname, int lineno, 1429static int line_range_walk_cb(const char *fname, int lineno,
1422 Dwarf_Addr addr __used, 1430 Dwarf_Addr addr __maybe_unused,
1423 void *data) 1431 void *data)
1424{ 1432{
1425 struct line_finder *lf = data; 1433 struct line_finder *lf = data;
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 0688bfb6d280..9181bf212fb9 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -627,7 +627,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
627 * This will group just the fds for this single evsel, to group 627 * This will group just the fds for this single evsel, to group
628 * multiple events, use evlist.open(). 628 * multiple events, use evlist.open().
629 */ 629 */
630 if (perf_evsel__open(evsel, cpus, threads, group, NULL) < 0) { 630 if (perf_evsel__open(evsel, cpus, threads) < 0) {
631 PyErr_SetFromErrno(PyExc_OSError); 631 PyErr_SetFromErrno(PyExc_OSError);
632 return NULL; 632 return NULL;
633 } 633 }
@@ -672,7 +672,7 @@ struct pyrf_evlist {
672}; 672};
673 673
674static int pyrf_evlist__init(struct pyrf_evlist *pevlist, 674static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
675 PyObject *args, PyObject *kwargs __used) 675 PyObject *args, PyObject *kwargs __maybe_unused)
676{ 676{
677 PyObject *pcpus = NULL, *pthreads = NULL; 677 PyObject *pcpus = NULL, *pthreads = NULL;
678 struct cpu_map *cpus; 678 struct cpu_map *cpus;
@@ -733,7 +733,8 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
733} 733}
734 734
735static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, 735static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
736 PyObject *args __used, PyObject *kwargs __used) 736 PyObject *args __maybe_unused,
737 PyObject *kwargs __maybe_unused)
737{ 738{
738 struct perf_evlist *evlist = &pevlist->evlist; 739 struct perf_evlist *evlist = &pevlist->evlist;
739 PyObject *list = PyList_New(0); 740 PyObject *list = PyList_New(0);
@@ -765,7 +766,8 @@ free_list:
765 766
766 767
767static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, 768static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
768 PyObject *args, PyObject *kwargs __used) 769 PyObject *args,
770 PyObject *kwargs __maybe_unused)
769{ 771{
770 struct perf_evlist *evlist = &pevlist->evlist; 772 struct perf_evlist *evlist = &pevlist->evlist;
771 PyObject *pevsel; 773 PyObject *pevsel;
@@ -803,7 +805,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
803 if (pyevent == NULL) 805 if (pyevent == NULL)
804 return PyErr_NoMemory(); 806 return PyErr_NoMemory();
805 807
806 err = perf_evlist__parse_sample(evlist, event, &pevent->sample, false); 808 err = perf_evlist__parse_sample(evlist, event, &pevent->sample);
807 if (err) 809 if (err)
808 return PyErr_Format(PyExc_OSError, 810 return PyErr_Format(PyExc_OSError,
809 "perf: can't parse sample, err=%d", err); 811 "perf: can't parse sample, err=%d", err);
@@ -824,7 +826,10 @@ static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
824 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group)) 826 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group))
825 return NULL; 827 return NULL;
826 828
827 if (perf_evlist__open(evlist, group) < 0) { 829 if (group)
830 perf_evlist__set_leader(evlist);
831
832 if (perf_evlist__open(evlist) < 0) {
828 PyErr_SetFromErrno(PyExc_OSError); 833 PyErr_SetFromErrno(PyExc_OSError);
829 return NULL; 834 return NULL;
830 } 835 }
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 02dfa19a467f..f80605eb1855 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -25,16 +25,16 @@
25#include <ctype.h> 25#include <ctype.h>
26#include <errno.h> 26#include <errno.h>
27 27
28#include "../../perf.h"
29#include "../util.h" 28#include "../util.h"
29#include <EXTERN.h>
30#include <perl.h>
31
32#include "../../perf.h"
30#include "../thread.h" 33#include "../thread.h"
31#include "../event.h" 34#include "../event.h"
32#include "../trace-event.h" 35#include "../trace-event.h"
33#include "../evsel.h" 36#include "../evsel.h"
34 37
35#include <EXTERN.h>
36#include <perl.h>
37
38void boot_Perf__Trace__Context(pTHX_ CV *cv); 38void boot_Perf__Trace__Context(pTHX_ CV *cv);
39void boot_DynaLoader(pTHX_ CV *cv); 39void boot_DynaLoader(pTHX_ CV *cv);
40typedef PerlInterpreter * INTERP; 40typedef PerlInterpreter * INTERP;
@@ -237,16 +237,16 @@ static void define_event_symbols(struct event_format *event,
237 define_event_symbols(event, ev_name, args->next); 237 define_event_symbols(event, ev_name, args->next);
238} 238}
239 239
240static inline 240static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
241struct event_format *find_cache_event(struct pevent *pevent, int type)
242{ 241{
243 static char ev_name[256]; 242 static char ev_name[256];
244 struct event_format *event; 243 struct event_format *event;
244 int type = evsel->attr.config;
245 245
246 if (events[type]) 246 if (events[type])
247 return events[type]; 247 return events[type];
248 248
249 events[type] = event = pevent_find_event(pevent, type); 249 events[type] = event = evsel->tp_format;
250 if (!event) 250 if (!event)
251 return NULL; 251 return NULL;
252 252
@@ -257,23 +257,22 @@ struct event_format *find_cache_event(struct pevent *pevent, int type)
257 return event; 257 return event;
258} 258}
259 259
260static void perl_process_tracepoint(union perf_event *perf_event __unused, 260static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
261 struct pevent *pevent,
262 struct perf_sample *sample, 261 struct perf_sample *sample,
263 struct perf_evsel *evsel, 262 struct perf_evsel *evsel,
264 struct machine *machine __unused, 263 struct machine *machine __maybe_unused,
265 struct thread *thread) 264 struct addr_location *al)
266{ 265{
267 struct format_field *field; 266 struct format_field *field;
268 static char handler[256]; 267 static char handler[256];
269 unsigned long long val; 268 unsigned long long val;
270 unsigned long s, ns; 269 unsigned long s, ns;
271 struct event_format *event; 270 struct event_format *event;
272 int type;
273 int pid; 271 int pid;
274 int cpu = sample->cpu; 272 int cpu = sample->cpu;
275 void *data = sample->raw_data; 273 void *data = sample->raw_data;
276 unsigned long long nsecs = sample->time; 274 unsigned long long nsecs = sample->time;
275 struct thread *thread = al->thread;
277 char *comm = thread->comm; 276 char *comm = thread->comm;
278 277
279 dSP; 278 dSP;
@@ -281,13 +280,11 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused,
281 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 280 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
282 return; 281 return;
283 282
284 type = trace_parse_common_type(pevent, data); 283 event = find_cache_event(evsel);
285
286 event = find_cache_event(pevent, type);
287 if (!event) 284 if (!event)
288 die("ug! no event found for type %d", type); 285 die("ug! no event found for type %" PRIu64, evsel->attr.config);
289 286
290 pid = trace_parse_common_pid(pevent, data); 287 pid = raw_field_value(event, "common_pid", data);
291 288
292 sprintf(handler, "%s::%s", event->system, event->name); 289 sprintf(handler, "%s::%s", event->system, event->name);
293 290
@@ -320,7 +317,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused,
320 offset = field->offset; 317 offset = field->offset;
321 XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0))); 318 XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
322 } else { /* FIELD_IS_NUMERIC */ 319 } else { /* FIELD_IS_NUMERIC */
323 val = read_size(pevent, data + field->offset, 320 val = read_size(event, data + field->offset,
324 field->size); 321 field->size);
325 if (field->flags & FIELD_IS_SIGNED) { 322 if (field->flags & FIELD_IS_SIGNED) {
326 XPUSHs(sv_2mortal(newSViv(val))); 323 XPUSHs(sv_2mortal(newSViv(val)));
@@ -349,11 +346,11 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused,
349 LEAVE; 346 LEAVE;
350} 347}
351 348
352static void perl_process_event_generic(union perf_event *pevent __unused, 349static void perl_process_event_generic(union perf_event *event,
353 struct perf_sample *sample, 350 struct perf_sample *sample,
354 struct perf_evsel *evsel __unused, 351 struct perf_evsel *evsel,
355 struct machine *machine __unused, 352 struct machine *machine __maybe_unused,
356 struct thread *thread __unused) 353 struct addr_location *al __maybe_unused)
357{ 354{
358 dSP; 355 dSP;
359 356
@@ -363,7 +360,7 @@ static void perl_process_event_generic(union perf_event *pevent __unused,
363 ENTER; 360 ENTER;
364 SAVETMPS; 361 SAVETMPS;
365 PUSHMARK(SP); 362 PUSHMARK(SP);
366 XPUSHs(sv_2mortal(newSVpvn((const char *)pevent, pevent->header.size))); 363 XPUSHs(sv_2mortal(newSVpvn((const char *)event, event->header.size)));
367 XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr)))); 364 XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr))));
368 XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample)))); 365 XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample))));
369 XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size))); 366 XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size)));
@@ -376,14 +373,13 @@ static void perl_process_event_generic(union perf_event *pevent __unused,
376} 373}
377 374
378static void perl_process_event(union perf_event *event, 375static void perl_process_event(union perf_event *event,
379 struct pevent *pevent,
380 struct perf_sample *sample, 376 struct perf_sample *sample,
381 struct perf_evsel *evsel, 377 struct perf_evsel *evsel,
382 struct machine *machine, 378 struct machine *machine,
383 struct thread *thread) 379 struct addr_location *al)
384{ 380{
385 perl_process_tracepoint(event, pevent, sample, evsel, machine, thread); 381 perl_process_tracepoint(event, sample, evsel, machine, al);
386 perl_process_event_generic(event, sample, evsel, machine, thread); 382 perl_process_event_generic(event, sample, evsel, machine, al);
387} 383}
388 384
389static void run_start_sub(void) 385static void run_start_sub(void)
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ce4d1b0c3862..730c6630cba5 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -27,10 +27,12 @@
27#include <errno.h> 27#include <errno.h>
28 28
29#include "../../perf.h" 29#include "../../perf.h"
30#include "../evsel.h"
30#include "../util.h" 31#include "../util.h"
31#include "../event.h" 32#include "../event.h"
32#include "../thread.h" 33#include "../thread.h"
33#include "../trace-event.h" 34#include "../trace-event.h"
35#include "../evsel.h"
34 36
35PyMODINIT_FUNC initperf_trace_context(void); 37PyMODINIT_FUNC initperf_trace_context(void);
36 38
@@ -194,16 +196,21 @@ static void define_event_symbols(struct event_format *event,
194 define_event_symbols(event, ev_name, args->next); 196 define_event_symbols(event, ev_name, args->next);
195} 197}
196 198
197static inline 199static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
198struct event_format *find_cache_event(struct pevent *pevent, int type)
199{ 200{
200 static char ev_name[256]; 201 static char ev_name[256];
201 struct event_format *event; 202 struct event_format *event;
203 int type = evsel->attr.config;
202 204
205 /*
206 * XXX: Do we really need to cache this since now we have evsel->tp_format
207 * cached already? Need to re-read this "cache" routine that as well calls
208 * define_event_symbols() :-\
209 */
203 if (events[type]) 210 if (events[type])
204 return events[type]; 211 return events[type];
205 212
206 events[type] = event = pevent_find_event(pevent, type); 213 events[type] = event = evsel->tp_format;
207 if (!event) 214 if (!event)
208 return NULL; 215 return NULL;
209 216
@@ -214,12 +221,12 @@ struct event_format *find_cache_event(struct pevent *pevent, int type)
214 return event; 221 return event;
215} 222}
216 223
217static void python_process_event(union perf_event *perf_event __unused, 224static void python_process_tracepoint(union perf_event *perf_event
218 struct pevent *pevent, 225 __maybe_unused,
219 struct perf_sample *sample, 226 struct perf_sample *sample,
220 struct perf_evsel *evsel __unused, 227 struct perf_evsel *evsel,
221 struct machine *machine __unused, 228 struct machine *machine __maybe_unused,
222 struct thread *thread) 229 struct addr_location *al)
223{ 230{
224 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 231 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
225 static char handler_name[256]; 232 static char handler_name[256];
@@ -228,24 +235,22 @@ static void python_process_event(union perf_event *perf_event __unused,
228 unsigned long s, ns; 235 unsigned long s, ns;
229 struct event_format *event; 236 struct event_format *event;
230 unsigned n = 0; 237 unsigned n = 0;
231 int type;
232 int pid; 238 int pid;
233 int cpu = sample->cpu; 239 int cpu = sample->cpu;
234 void *data = sample->raw_data; 240 void *data = sample->raw_data;
235 unsigned long long nsecs = sample->time; 241 unsigned long long nsecs = sample->time;
242 struct thread *thread = al->thread;
236 char *comm = thread->comm; 243 char *comm = thread->comm;
237 244
238 t = PyTuple_New(MAX_FIELDS); 245 t = PyTuple_New(MAX_FIELDS);
239 if (!t) 246 if (!t)
240 Py_FatalError("couldn't create Python tuple"); 247 Py_FatalError("couldn't create Python tuple");
241 248
242 type = trace_parse_common_type(pevent, data); 249 event = find_cache_event(evsel);
243
244 event = find_cache_event(pevent, type);
245 if (!event) 250 if (!event)
246 die("ug! no event found for type %d", type); 251 die("ug! no event found for type %d", (int)evsel->attr.config);
247 252
248 pid = trace_parse_common_pid(pevent, data); 253 pid = raw_field_value(event, "common_pid", data);
249 254
250 sprintf(handler_name, "%s__%s", event->system, event->name); 255 sprintf(handler_name, "%s__%s", event->system, event->name);
251 256
@@ -290,7 +295,7 @@ static void python_process_event(union perf_event *perf_event __unused,
290 offset = field->offset; 295 offset = field->offset;
291 obj = PyString_FromString((char *)data + offset); 296 obj = PyString_FromString((char *)data + offset);
292 } else { /* FIELD_IS_NUMERIC */ 297 } else { /* FIELD_IS_NUMERIC */
293 val = read_size(pevent, data + field->offset, 298 val = read_size(event, data + field->offset,
294 field->size); 299 field->size);
295 if (field->flags & FIELD_IS_SIGNED) { 300 if (field->flags & FIELD_IS_SIGNED) {
296 if ((long long)val >= LONG_MIN && 301 if ((long long)val >= LONG_MIN &&
@@ -335,6 +340,84 @@ static void python_process_event(union perf_event *perf_event __unused,
335 Py_DECREF(t); 340 Py_DECREF(t);
336} 341}
337 342
343static void python_process_general_event(union perf_event *perf_event
344 __maybe_unused,
345 struct perf_sample *sample,
346 struct perf_evsel *evsel,
347 struct machine *machine __maybe_unused,
348 struct addr_location *al)
349{
350 PyObject *handler, *retval, *t, *dict;
351 static char handler_name[64];
352 unsigned n = 0;
353 struct thread *thread = al->thread;
354
355 /*
356 * Use the MAX_FIELDS to make the function expandable, though
357 * currently there is only one item for the tuple.
358 */
359 t = PyTuple_New(MAX_FIELDS);
360 if (!t)
361 Py_FatalError("couldn't create Python tuple");
362
363 dict = PyDict_New();
364 if (!dict)
365 Py_FatalError("couldn't create Python dictionary");
366
367 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
368
369 handler = PyDict_GetItemString(main_dict, handler_name);
370 if (!handler || !PyCallable_Check(handler))
371 goto exit;
372
373 PyDict_SetItemString(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
374 PyDict_SetItemString(dict, "attr", PyString_FromStringAndSize(
375 (const char *)&evsel->attr, sizeof(evsel->attr)));
376 PyDict_SetItemString(dict, "sample", PyString_FromStringAndSize(
377 (const char *)sample, sizeof(*sample)));
378 PyDict_SetItemString(dict, "raw_buf", PyString_FromStringAndSize(
379 (const char *)sample->raw_data, sample->raw_size));
380 PyDict_SetItemString(dict, "comm",
381 PyString_FromString(thread->comm));
382 if (al->map) {
383 PyDict_SetItemString(dict, "dso",
384 PyString_FromString(al->map->dso->name));
385 }
386 if (al->sym) {
387 PyDict_SetItemString(dict, "symbol",
388 PyString_FromString(al->sym->name));
389 }
390
391 PyTuple_SetItem(t, n++, dict);
392 if (_PyTuple_Resize(&t, n) == -1)
393 Py_FatalError("error resizing Python tuple");
394
395 retval = PyObject_CallObject(handler, t);
396 if (retval == NULL)
397 handler_call_die(handler_name);
398exit:
399 Py_DECREF(dict);
400 Py_DECREF(t);
401}
402
403static void python_process_event(union perf_event *perf_event,
404 struct perf_sample *sample,
405 struct perf_evsel *evsel,
406 struct machine *machine,
407 struct addr_location *al)
408{
409 switch (evsel->attr.type) {
410 case PERF_TYPE_TRACEPOINT:
411 python_process_tracepoint(perf_event, sample, evsel,
412 machine, al);
413 break;
414 /* Reserve for future process_hw/sw/raw APIs */
415 default:
416 python_process_general_event(perf_event, sample, evsel,
417 machine, al);
418 }
419}
420
338static int run_start_sub(void) 421static int run_start_sub(void)
339{ 422{
340 PyObject *handler, *retval; 423 PyObject *handler, *retval;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 2437fb0b463a..8cdd23239c90 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -15,6 +15,9 @@
15#include "util.h" 15#include "util.h"
16#include "cpumap.h" 16#include "cpumap.h"
17#include "event-parse.h" 17#include "event-parse.h"
18#include "perf_regs.h"
19#include "unwind.h"
20#include "vdso.h"
18 21
19static int perf_session__open(struct perf_session *self, bool force) 22static int perf_session__open(struct perf_session *self, bool force)
20{ 23{
@@ -209,6 +212,7 @@ void perf_session__delete(struct perf_session *self)
209 machine__exit(&self->host_machine); 212 machine__exit(&self->host_machine);
210 close(self->fd); 213 close(self->fd);
211 free(self); 214 free(self);
215 vdso__exit();
212} 216}
213 217
214void machine__remove_thread(struct machine *self, struct thread *th) 218void machine__remove_thread(struct machine *self, struct thread *th)
@@ -288,10 +292,11 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
288 return bi; 292 return bi;
289} 293}
290 294
291int machine__resolve_callchain(struct machine *self, 295static int machine__resolve_callchain_sample(struct machine *machine,
292 struct thread *thread, 296 struct thread *thread,
293 struct ip_callchain *chain, 297 struct ip_callchain *chain,
294 struct symbol **parent) 298 struct symbol **parent)
299
295{ 300{
296 u8 cpumode = PERF_RECORD_MISC_USER; 301 u8 cpumode = PERF_RECORD_MISC_USER;
297 unsigned int i; 302 unsigned int i;
@@ -316,11 +321,14 @@ int machine__resolve_callchain(struct machine *self,
316 if (ip >= PERF_CONTEXT_MAX) { 321 if (ip >= PERF_CONTEXT_MAX) {
317 switch (ip) { 322 switch (ip) {
318 case PERF_CONTEXT_HV: 323 case PERF_CONTEXT_HV:
319 cpumode = PERF_RECORD_MISC_HYPERVISOR; break; 324 cpumode = PERF_RECORD_MISC_HYPERVISOR;
325 break;
320 case PERF_CONTEXT_KERNEL: 326 case PERF_CONTEXT_KERNEL:
321 cpumode = PERF_RECORD_MISC_KERNEL; break; 327 cpumode = PERF_RECORD_MISC_KERNEL;
328 break;
322 case PERF_CONTEXT_USER: 329 case PERF_CONTEXT_USER:
323 cpumode = PERF_RECORD_MISC_USER; break; 330 cpumode = PERF_RECORD_MISC_USER;
331 break;
324 default: 332 default:
325 pr_debug("invalid callchain context: " 333 pr_debug("invalid callchain context: "
326 "%"PRId64"\n", (s64) ip); 334 "%"PRId64"\n", (s64) ip);
@@ -335,7 +343,7 @@ int machine__resolve_callchain(struct machine *self,
335 } 343 }
336 344
337 al.filtered = false; 345 al.filtered = false;
338 thread__find_addr_location(thread, self, cpumode, 346 thread__find_addr_location(thread, machine, cpumode,
339 MAP__FUNCTION, ip, &al, NULL); 347 MAP__FUNCTION, ip, &al, NULL);
340 if (al.sym != NULL) { 348 if (al.sym != NULL) {
341 if (sort__has_parent && !*parent && 349 if (sort__has_parent && !*parent &&
@@ -354,49 +362,92 @@ int machine__resolve_callchain(struct machine *self,
354 return 0; 362 return 0;
355} 363}
356 364
357static int process_event_synth_tracing_data_stub(union perf_event *event __used, 365static int unwind_entry(struct unwind_entry *entry, void *arg)
358 struct perf_session *session __used) 366{
367 struct callchain_cursor *cursor = arg;
368 return callchain_cursor_append(cursor, entry->ip,
369 entry->map, entry->sym);
370}
371
372int machine__resolve_callchain(struct machine *machine,
373 struct perf_evsel *evsel,
374 struct thread *thread,
375 struct perf_sample *sample,
376 struct symbol **parent)
377
378{
379 int ret;
380
381 callchain_cursor_reset(&callchain_cursor);
382
383 ret = machine__resolve_callchain_sample(machine, thread,
384 sample->callchain, parent);
385 if (ret)
386 return ret;
387
388 /* Can we do dwarf post unwind? */
389 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
390 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
391 return 0;
392
393 /* Bail out if nothing was captured. */
394 if ((!sample->user_regs.regs) ||
395 (!sample->user_stack.size))
396 return 0;
397
398 return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
399 thread, evsel->attr.sample_regs_user,
400 sample);
401
402}
403
404static int process_event_synth_tracing_data_stub(union perf_event *event
405 __maybe_unused,
406 struct perf_session *session
407 __maybe_unused)
359{ 408{
360 dump_printf(": unhandled!\n"); 409 dump_printf(": unhandled!\n");
361 return 0; 410 return 0;
362} 411}
363 412
364static int process_event_synth_attr_stub(union perf_event *event __used, 413static int process_event_synth_attr_stub(union perf_event *event __maybe_unused,
365 struct perf_evlist **pevlist __used) 414 struct perf_evlist **pevlist
415 __maybe_unused)
366{ 416{
367 dump_printf(": unhandled!\n"); 417 dump_printf(": unhandled!\n");
368 return 0; 418 return 0;
369} 419}
370 420
371static int process_event_sample_stub(struct perf_tool *tool __used, 421static int process_event_sample_stub(struct perf_tool *tool __maybe_unused,
372 union perf_event *event __used, 422 union perf_event *event __maybe_unused,
373 struct perf_sample *sample __used, 423 struct perf_sample *sample __maybe_unused,
374 struct perf_evsel *evsel __used, 424 struct perf_evsel *evsel __maybe_unused,
375 struct machine *machine __used) 425 struct machine *machine __maybe_unused)
376{ 426{
377 dump_printf(": unhandled!\n"); 427 dump_printf(": unhandled!\n");
378 return 0; 428 return 0;
379} 429}
380 430
381static int process_event_stub(struct perf_tool *tool __used, 431static int process_event_stub(struct perf_tool *tool __maybe_unused,
382 union perf_event *event __used, 432 union perf_event *event __maybe_unused,
383 struct perf_sample *sample __used, 433 struct perf_sample *sample __maybe_unused,
384 struct machine *machine __used) 434 struct machine *machine __maybe_unused)
385{ 435{
386 dump_printf(": unhandled!\n"); 436 dump_printf(": unhandled!\n");
387 return 0; 437 return 0;
388} 438}
389 439
390static int process_finished_round_stub(struct perf_tool *tool __used, 440static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
391 union perf_event *event __used, 441 union perf_event *event __maybe_unused,
392 struct perf_session *perf_session __used) 442 struct perf_session *perf_session
443 __maybe_unused)
393{ 444{
394 dump_printf(": unhandled!\n"); 445 dump_printf(": unhandled!\n");
395 return 0; 446 return 0;
396} 447}
397 448
398static int process_event_type_stub(struct perf_tool *tool __used, 449static int process_event_type_stub(struct perf_tool *tool __maybe_unused,
399 union perf_event *event __used) 450 union perf_event *event __maybe_unused)
400{ 451{
401 dump_printf(": unhandled!\n"); 452 dump_printf(": unhandled!\n");
402 return 0; 453 return 0;
@@ -473,7 +524,7 @@ static void swap_sample_id_all(union perf_event *event, void *data)
473} 524}
474 525
475static void perf_event__all64_swap(union perf_event *event, 526static void perf_event__all64_swap(union perf_event *event,
476 bool sample_id_all __used) 527 bool sample_id_all __maybe_unused)
477{ 528{
478 struct perf_event_header *hdr = &event->header; 529 struct perf_event_header *hdr = &event->header;
479 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); 530 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));
@@ -487,7 +538,7 @@ static void perf_event__comm_swap(union perf_event *event, bool sample_id_all)
487 if (sample_id_all) { 538 if (sample_id_all) {
488 void *data = &event->comm.comm; 539 void *data = &event->comm.comm;
489 540
490 data += ALIGN(strlen(data) + 1, sizeof(u64)); 541 data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
491 swap_sample_id_all(event, data); 542 swap_sample_id_all(event, data);
492 } 543 }
493} 544}
@@ -504,7 +555,7 @@ static void perf_event__mmap_swap(union perf_event *event,
504 if (sample_id_all) { 555 if (sample_id_all) {
505 void *data = &event->mmap.filename; 556 void *data = &event->mmap.filename;
506 557
507 data += ALIGN(strlen(data) + 1, sizeof(u64)); 558 data += PERF_ALIGN(strlen(data) + 1, sizeof(u64));
508 swap_sample_id_all(event, data); 559 swap_sample_id_all(event, data);
509 } 560 }
510} 561}
@@ -584,7 +635,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
584} 635}
585 636
586static void perf_event__hdr_attr_swap(union perf_event *event, 637static void perf_event__hdr_attr_swap(union perf_event *event,
587 bool sample_id_all __used) 638 bool sample_id_all __maybe_unused)
588{ 639{
589 size_t size; 640 size_t size;
590 641
@@ -596,14 +647,14 @@ static void perf_event__hdr_attr_swap(union perf_event *event,
596} 647}
597 648
598static void perf_event__event_type_swap(union perf_event *event, 649static void perf_event__event_type_swap(union perf_event *event,
599 bool sample_id_all __used) 650 bool sample_id_all __maybe_unused)
600{ 651{
601 event->event_type.event_type.event_id = 652 event->event_type.event_type.event_id =
602 bswap_64(event->event_type.event_type.event_id); 653 bswap_64(event->event_type.event_type.event_id);
603} 654}
604 655
605static void perf_event__tracing_data_swap(union perf_event *event, 656static void perf_event__tracing_data_swap(union perf_event *event,
606 bool sample_id_all __used) 657 bool sample_id_all __maybe_unused)
607{ 658{
608 event->tracing_data.size = bswap_32(event->tracing_data.size); 659 event->tracing_data.size = bswap_32(event->tracing_data.size);
609} 660}
@@ -652,7 +703,7 @@ static int perf_session_deliver_event(struct perf_session *session,
652 struct perf_tool *tool, 703 struct perf_tool *tool,
653 u64 file_offset); 704 u64 file_offset);
654 705
655static void flush_sample_queue(struct perf_session *s, 706static int flush_sample_queue(struct perf_session *s,
656 struct perf_tool *tool) 707 struct perf_tool *tool)
657{ 708{
658 struct ordered_samples *os = &s->ordered_samples; 709 struct ordered_samples *os = &s->ordered_samples;
@@ -665,19 +716,21 @@ static void flush_sample_queue(struct perf_session *s,
665 int ret; 716 int ret;
666 717
667 if (!tool->ordered_samples || !limit) 718 if (!tool->ordered_samples || !limit)
668 return; 719 return 0;
669 720
670 list_for_each_entry_safe(iter, tmp, head, list) { 721 list_for_each_entry_safe(iter, tmp, head, list) {
671 if (iter->timestamp > limit) 722 if (iter->timestamp > limit)
672 break; 723 break;
673 724
674 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample, 725 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
675 s->header.needs_swap);
676 if (ret) 726 if (ret)
677 pr_err("Can't parse sample, err = %d\n", ret); 727 pr_err("Can't parse sample, err = %d\n", ret);
678 else 728 else {
679 perf_session_deliver_event(s, iter->event, &sample, tool, 729 ret = perf_session_deliver_event(s, iter->event, &sample, tool,
680 iter->file_offset); 730 iter->file_offset);
731 if (ret)
732 return ret;
733 }
681 734
682 os->last_flush = iter->timestamp; 735 os->last_flush = iter->timestamp;
683 list_del(&iter->list); 736 list_del(&iter->list);
@@ -697,6 +750,8 @@ static void flush_sample_queue(struct perf_session *s,
697 } 750 }
698 751
699 os->nr_samples = 0; 752 os->nr_samples = 0;
753
754 return 0;
700} 755}
701 756
702/* 757/*
@@ -739,13 +794,14 @@ static void flush_sample_queue(struct perf_session *s,
739 * etc... 794 * etc...
740 */ 795 */
741static int process_finished_round(struct perf_tool *tool, 796static int process_finished_round(struct perf_tool *tool,
742 union perf_event *event __used, 797 union perf_event *event __maybe_unused,
743 struct perf_session *session) 798 struct perf_session *session)
744{ 799{
745 flush_sample_queue(session, tool); 800 int ret = flush_sample_queue(session, tool);
746 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; 801 if (!ret)
802 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
747 803
748 return 0; 804 return ret;
749} 805}
750 806
751/* The queue is ordered by time */ 807/* The queue is ordered by time */
@@ -860,6 +916,34 @@ static void branch_stack__printf(struct perf_sample *sample)
860 sample->branch_stack->entries[i].to); 916 sample->branch_stack->entries[i].to);
861} 917}
862 918
919static void regs_dump__printf(u64 mask, u64 *regs)
920{
921 unsigned rid, i = 0;
922
923 for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) {
924 u64 val = regs[i++];
925
926 printf(".... %-5s 0x%" PRIx64 "\n",
927 perf_reg_name(rid), val);
928 }
929}
930
931static void regs_user__printf(struct perf_sample *sample, u64 mask)
932{
933 struct regs_dump *user_regs = &sample->user_regs;
934
935 if (user_regs->regs) {
936 printf("... user regs: mask 0x%" PRIx64 "\n", mask);
937 regs_dump__printf(mask, user_regs->regs);
938 }
939}
940
941static void stack_user__printf(struct stack_dump *dump)
942{
943 printf("... ustack: size %" PRIu64 ", offset 0x%x\n",
944 dump->size, dump->offset);
945}
946
863static void perf_session__print_tstamp(struct perf_session *session, 947static void perf_session__print_tstamp(struct perf_session *session,
864 union perf_event *event, 948 union perf_event *event,
865 struct perf_sample *sample) 949 struct perf_sample *sample)
@@ -897,7 +981,7 @@ static void dump_event(struct perf_session *session, union perf_event *event,
897 event->header.size, perf_event__name(event->header.type)); 981 event->header.size, perf_event__name(event->header.type));
898} 982}
899 983
900static void dump_sample(struct perf_session *session, union perf_event *event, 984static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
901 struct perf_sample *sample) 985 struct perf_sample *sample)
902{ 986{
903 u64 sample_type; 987 u64 sample_type;
@@ -909,13 +993,19 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
909 event->header.misc, sample->pid, sample->tid, sample->ip, 993 event->header.misc, sample->pid, sample->tid, sample->ip,
910 sample->period, sample->addr); 994 sample->period, sample->addr);
911 995
912 sample_type = perf_evlist__sample_type(session->evlist); 996 sample_type = evsel->attr.sample_type;
913 997
914 if (sample_type & PERF_SAMPLE_CALLCHAIN) 998 if (sample_type & PERF_SAMPLE_CALLCHAIN)
915 callchain__printf(sample); 999 callchain__printf(sample);
916 1000
917 if (sample_type & PERF_SAMPLE_BRANCH_STACK) 1001 if (sample_type & PERF_SAMPLE_BRANCH_STACK)
918 branch_stack__printf(sample); 1002 branch_stack__printf(sample);
1003
1004 if (sample_type & PERF_SAMPLE_REGS_USER)
1005 regs_user__printf(sample, evsel->attr.sample_regs_user);
1006
1007 if (sample_type & PERF_SAMPLE_STACK_USER)
1008 stack_user__printf(&sample->user_stack);
919} 1009}
920 1010
921static struct machine * 1011static struct machine *
@@ -973,7 +1063,7 @@ static int perf_session_deliver_event(struct perf_session *session,
973 1063
974 switch (event->header.type) { 1064 switch (event->header.type) {
975 case PERF_RECORD_SAMPLE: 1065 case PERF_RECORD_SAMPLE:
976 dump_sample(session, event, sample); 1066 dump_sample(evsel, event, sample);
977 if (evsel == NULL) { 1067 if (evsel == NULL) {
978 ++session->hists.stats.nr_unknown_id; 1068 ++session->hists.stats.nr_unknown_id;
979 return 0; 1069 return 0;
@@ -1083,8 +1173,7 @@ static int perf_session__process_event(struct perf_session *session,
1083 /* 1173 /*
1084 * For all kernel events we get the sample data 1174 * For all kernel events we get the sample data
1085 */ 1175 */
1086 ret = perf_evlist__parse_sample(session->evlist, event, &sample, 1176 ret = perf_evlist__parse_sample(session->evlist, event, &sample);
1087 session->header.needs_swap);
1088 if (ret) 1177 if (ret)
1089 return ret; 1178 return ret;
1090 1179
@@ -1369,7 +1458,7 @@ more:
1369 err = 0; 1458 err = 0;
1370 /* do the final flush for ordered samples */ 1459 /* do the final flush for ordered samples */
1371 session->ordered_samples.next_flush = ULLONG_MAX; 1460 session->ordered_samples.next_flush = ULLONG_MAX;
1372 flush_sample_queue(session, tool); 1461 err = flush_sample_queue(session, tool);
1373out_err: 1462out_err:
1374 perf_session__warn_about_errors(session, tool); 1463 perf_session__warn_about_errors(session, tool);
1375 perf_session_free_sample_buffers(session); 1464 perf_session_free_sample_buffers(session);
@@ -1498,9 +1587,9 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1498 return NULL; 1587 return NULL;
1499} 1588}
1500 1589
1501void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 1590void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1502 struct machine *machine, int print_sym, 1591 struct perf_sample *sample, struct machine *machine,
1503 int print_dso, int print_symoffset) 1592 int print_sym, int print_dso, int print_symoffset)
1504{ 1593{
1505 struct addr_location al; 1594 struct addr_location al;
1506 struct callchain_cursor_node *node; 1595 struct callchain_cursor_node *node;
@@ -1514,8 +1603,9 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1514 1603
1515 if (symbol_conf.use_callchain && sample->callchain) { 1604 if (symbol_conf.use_callchain && sample->callchain) {
1516 1605
1517 if (machine__resolve_callchain(machine, al.thread, 1606
1518 sample->callchain, NULL) != 0) { 1607 if (machine__resolve_callchain(machine, evsel, al.thread,
1608 sample, NULL) != 0) {
1519 if (verbose) 1609 if (verbose)
1520 error("Failed to resolve callchain. Skipping\n"); 1610 error("Failed to resolve callchain. Skipping\n");
1521 return; 1611 return;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 1f7ec87db7d7..dd6426163ba6 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -7,7 +7,7 @@
7#include "symbol.h" 7#include "symbol.h"
8#include "thread.h" 8#include "thread.h"
9#include <linux/rbtree.h> 9#include <linux/rbtree.h>
10#include "../../../include/linux/perf_event.h" 10#include "../../../include/uapi/linux/perf_event.h"
11 11
12struct sample_queue; 12struct sample_queue;
13struct ip_callchain; 13struct ip_callchain;
@@ -36,9 +36,7 @@ struct perf_session {
36 struct pevent *pevent; 36 struct pevent *pevent;
37 /* 37 /*
38 * FIXME: Need to split this up further, we need global 38 * FIXME: Need to split this up further, we need global
39 * stats + per event stats. 'perf diff' also needs 39 * stats + per event stats.
40 * to properly support multiple events in a single
41 * perf.data file.
42 */ 40 */
43 struct hists hists; 41 struct hists hists;
44 int fd; 42 int fd;
@@ -129,9 +127,9 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
129struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 127struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
130 unsigned int type); 128 unsigned int type);
131 129
132void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 130void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
133 struct machine *machine, int print_sym, 131 struct perf_sample *sample, struct machine *machine,
134 int print_dso, int print_symoffset); 132 int print_sym, int print_dso, int print_symoffset);
135 133
136int perf_session__cpu_bitmap(struct perf_session *session, 134int perf_session__cpu_bitmap(struct perf_session *session,
137 const char *cpu_list, unsigned long *cpu_bitmap); 135 const char *cpu_list, unsigned long *cpu_bitmap);
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index d0f9f29cf181..73d510269784 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -23,6 +23,7 @@ cflags += getenv('CFLAGS', '').split()
23 23
24build_lib = getenv('PYTHON_EXTBUILD_LIB') 24build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP') 25build_tmp = getenv('PYTHON_EXTBUILD_TMP')
26libtraceevent = getenv('LIBTRACEEVENT')
26 27
27ext_sources = [f.strip() for f in file('util/python-ext-sources') 28ext_sources = [f.strip() for f in file('util/python-ext-sources')
28 if len(f.strip()) > 0 and f[0] != '#'] 29 if len(f.strip()) > 0 and f[0] != '#']
@@ -31,6 +32,7 @@ perf = Extension('perf',
31 sources = ext_sources, 32 sources = ext_sources,
32 include_dirs = ['util/include'], 33 include_dirs = ['util/include'],
33 extra_compile_args = cflags, 34 extra_compile_args = cflags,
35 extra_objects = [libtraceevent],
34 ) 36 )
35 37
36setup(name='perf', 38setup(name='perf',
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 0f5a0a496bc4..cfd1c0feb32d 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -8,12 +8,11 @@ const char default_sort_order[] = "comm,dso,symbol";
8const char *sort_order = default_sort_order; 8const char *sort_order = default_sort_order;
9int sort__need_collapse = 0; 9int sort__need_collapse = 0;
10int sort__has_parent = 0; 10int sort__has_parent = 0;
11int sort__has_sym = 0;
11int sort__branch_mode = -1; /* -1 = means not set */ 12int sort__branch_mode = -1; /* -1 = means not set */
12 13
13enum sort_type sort__first_dimension; 14enum sort_type sort__first_dimension;
14 15
15char * field_sep;
16
17LIST_HEAD(hist_entry__sort_list); 16LIST_HEAD(hist_entry__sort_list);
18 17
19static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) 18static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
@@ -23,11 +22,11 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
23 22
24 va_start(ap, fmt); 23 va_start(ap, fmt);
25 n = vsnprintf(bf, size, fmt, ap); 24 n = vsnprintf(bf, size, fmt, ap);
26 if (field_sep && n > 0) { 25 if (symbol_conf.field_sep && n > 0) {
27 char *sep = bf; 26 char *sep = bf;
28 27
29 while (1) { 28 while (1) {
30 sep = strchr(sep, *field_sep); 29 sep = strchr(sep, *symbol_conf.field_sep);
31 if (sep == NULL) 30 if (sep == NULL)
32 break; 31 break;
33 *sep = '.'; 32 *sep = '.';
@@ -172,7 +171,7 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
172 171
173static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, 172static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
174 u64 ip, char level, char *bf, size_t size, 173 u64 ip, char level, char *bf, size_t size,
175 unsigned int width __used) 174 unsigned int width __maybe_unused)
176{ 175{
177 size_t ret = 0; 176 size_t ret = 0;
178 177
@@ -207,7 +206,8 @@ struct sort_entry sort_dso = {
207}; 206};
208 207
209static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, 208static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
210 size_t size, unsigned int width __used) 209 size_t size,
210 unsigned int width __maybe_unused)
211{ 211{
212 return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip, 212 return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip,
213 self->level, bf, size, width); 213 self->level, bf, size, width);
@@ -250,7 +250,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
250} 250}
251 251
252static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, 252static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
253 size_t size, unsigned int width __used) 253 size_t size,
254 unsigned int width __maybe_unused)
254{ 255{
255 FILE *fp; 256 FILE *fp;
256 char cmd[PATH_MAX + 2], *path = self->srcline, *nl; 257 char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
@@ -259,6 +260,12 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
259 if (path != NULL) 260 if (path != NULL)
260 goto out_path; 261 goto out_path;
261 262
263 if (!self->ms.map)
264 goto out_ip;
265
266 if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
267 goto out_ip;
268
262 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64, 269 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
263 self->ms.map->dso->long_name, self->ip); 270 self->ms.map->dso->long_name, self->ip);
264 fp = popen(cmd, "r"); 271 fp = popen(cmd, "r");
@@ -399,7 +406,8 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
399} 406}
400 407
401static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, 408static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf,
402 size_t size, unsigned int width __used) 409 size_t size,
410 unsigned int width __maybe_unused)
403{ 411{
404 struct addr_map_symbol *from = &self->branch_info->from; 412 struct addr_map_symbol *from = &self->branch_info->from;
405 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, 413 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
@@ -408,7 +416,8 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf,
408} 416}
409 417
410static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, 418static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf,
411 size_t size, unsigned int width __used) 419 size_t size,
420 unsigned int width __maybe_unused)
412{ 421{
413 struct addr_map_symbol *to = &self->branch_info->to; 422 struct addr_map_symbol *to = &self->branch_info->to;
414 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, 423 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
@@ -509,6 +518,10 @@ int sort_dimension__add(const char *tok)
509 return -EINVAL; 518 return -EINVAL;
510 } 519 }
511 sort__has_parent = 1; 520 sort__has_parent = 1;
521 } else if (sd->entry == &sort_sym ||
522 sd->entry == &sort_sym_from ||
523 sd->entry == &sort_sym_to) {
524 sort__has_sym = 1;
512 } 525 }
513 526
514 if (sd->taken) 527 if (sd->taken)
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index e724b26acd51..5786f323b597 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -31,8 +31,8 @@ extern const char *parent_pattern;
31extern const char default_sort_order[]; 31extern const char default_sort_order[];
32extern int sort__need_collapse; 32extern int sort__need_collapse;
33extern int sort__has_parent; 33extern int sort__has_parent;
34extern int sort__has_sym;
34extern int sort__branch_mode; 35extern int sort__branch_mode;
35extern char *field_sep;
36extern struct sort_entry sort_comm; 36extern struct sort_entry sort_comm;
37extern struct sort_entry sort_dso; 37extern struct sort_entry sort_dso;
38extern struct sort_entry sort_sym; 38extern struct sort_entry sort_sym;
@@ -43,6 +43,15 @@ extern struct sort_entry sort_sym_from;
43extern struct sort_entry sort_sym_to; 43extern struct sort_entry sort_sym_to;
44extern enum sort_type sort__first_dimension; 44extern enum sort_type sort__first_dimension;
45 45
46struct he_stat {
47 u64 period;
48 u64 period_sys;
49 u64 period_us;
50 u64 period_guest_sys;
51 u64 period_guest_us;
52 u32 nr_events;
53};
54
46/** 55/**
47 * struct hist_entry - histogram entry 56 * struct hist_entry - histogram entry
48 * 57 *
@@ -52,16 +61,11 @@ extern enum sort_type sort__first_dimension;
52struct hist_entry { 61struct hist_entry {
53 struct rb_node rb_node_in; 62 struct rb_node rb_node_in;
54 struct rb_node rb_node; 63 struct rb_node rb_node;
55 u64 period; 64 struct he_stat stat;
56 u64 period_sys;
57 u64 period_us;
58 u64 period_guest_sys;
59 u64 period_guest_us;
60 struct map_symbol ms; 65 struct map_symbol ms;
61 struct thread *thread; 66 struct thread *thread;
62 u64 ip; 67 u64 ip;
63 s32 cpu; 68 s32 cpu;
64 u32 nr_events;
65 69
66 /* XXX These two should move to some tree widget lib */ 70 /* XXX These two should move to some tree widget lib */
67 u16 row_offset; 71 u16 row_offset;
@@ -73,12 +77,13 @@ struct hist_entry {
73 u8 filtered; 77 u8 filtered;
74 char *srcline; 78 char *srcline;
75 struct symbol *parent; 79 struct symbol *parent;
80 unsigned long position;
76 union { 81 union {
77 unsigned long position;
78 struct hist_entry *pair; 82 struct hist_entry *pair;
79 struct rb_root sorted_chain; 83 struct rb_root sorted_chain;
80 }; 84 };
81 struct branch_info *branch_info; 85 struct branch_info *branch_info;
86 struct hists *hists;
82 struct callchain_root callchain[0]; 87 struct callchain_root callchain[0];
83}; 88};
84 89
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
new file mode 100644
index 000000000000..23742126f47c
--- /dev/null
+++ b/tools/perf/util/stat.c
@@ -0,0 +1,57 @@
1#include <math.h>
2
3#include "stat.h"
4
5void update_stats(struct stats *stats, u64 val)
6{
7 double delta;
8
9 stats->n++;
10 delta = val - stats->mean;
11 stats->mean += delta / stats->n;
12 stats->M2 += delta*(val - stats->mean);
13}
14
15double avg_stats(struct stats *stats)
16{
17 return stats->mean;
18}
19
20/*
21 * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
22 *
23 * (\Sum n_i^2) - ((\Sum n_i)^2)/n
24 * s^2 = -------------------------------
25 * n - 1
26 *
27 * http://en.wikipedia.org/wiki/Stddev
28 *
29 * The std dev of the mean is related to the std dev by:
30 *
31 * s
32 * s_mean = -------
33 * sqrt(n)
34 *
35 */
36double stddev_stats(struct stats *stats)
37{
38 double variance, variance_mean;
39
40 if (!stats->n)
41 return 0.0;
42
43 variance = stats->M2 / (stats->n - 1);
44 variance_mean = variance / stats->n;
45
46 return sqrt(variance_mean);
47}
48
49double rel_stddev_stats(double stddev, double avg)
50{
51 double pct = 0.0;
52
53 if (avg)
54 pct = 100.0 * stddev/avg;
55
56 return pct;
57}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
new file mode 100644
index 000000000000..588367c3c767
--- /dev/null
+++ b/tools/perf/util/stat.h
@@ -0,0 +1,16 @@
1#ifndef __PERF_STATS_H
2#define __PERF_STATS_H
3
4#include "types.h"
5
6struct stats
7{
8 double n, mean, M2;
9};
10
11void update_stats(struct stats *stats, u64 val);
12double avg_stats(struct stats *stats);
13double stddev_stats(struct stats *stats);
14double rel_stddev_stats(double stddev, double avg);
15
16#endif
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 199bc4d8905d..32170590892d 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -1,5 +1,5 @@
1#include "util.h" 1#include "util.h"
2#include "string.h" 2#include "linux/string.h"
3 3
4#define K 1024LL 4#define K 1024LL
5/* 5/*
@@ -335,3 +335,19 @@ char *rtrim(char *s)
335 335
336 return s; 336 return s;
337} 337}
338
339/**
340 * memdup - duplicate region of memory
341 * @src: memory region to duplicate
342 * @len: memory region length
343 */
344void *memdup(const void *src, size_t len)
345{
346 void *p;
347
348 p = malloc(len);
349 if (p)
350 memcpy(p, src, len);
351
352 return p;
353}
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index 95856ff3dda4..155d8b7078a7 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -93,7 +93,7 @@ out:
93 93
94void strlist__remove(struct strlist *slist, struct str_node *snode) 94void strlist__remove(struct strlist *slist, struct str_node *snode)
95{ 95{
96 str_node__delete(snode, slist->dupstr); 96 rblist__remove_node(&slist->rblist, &snode->rb_node);
97} 97}
98 98
99struct str_node *strlist__find(struct strlist *slist, const char *entry) 99struct str_node *strlist__find(struct strlist *slist, const char *entry)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
new file mode 100644
index 000000000000..db0cc92cf2ea
--- /dev/null
+++ b/tools/perf/util/symbol-elf.c
@@ -0,0 +1,841 @@
1#include <libelf.h>
2#include <gelf.h>
3#include <elf.h>
4#include <fcntl.h>
5#include <stdio.h>
6#include <errno.h>
7#include <string.h>
8#include <unistd.h>
9#include <inttypes.h>
10
11#include "symbol.h"
12#include "debug.h"
13
14#ifndef NT_GNU_BUILD_ID
15#define NT_GNU_BUILD_ID 3
16#endif
17
18/**
19 * elf_symtab__for_each_symbol - iterate thru all the symbols
20 *
21 * @syms: struct elf_symtab instance to iterate
22 * @idx: uint32_t idx
23 * @sym: GElf_Sym iterator
24 */
25#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
26 for (idx = 0, gelf_getsym(syms, idx, &sym);\
27 idx < nr_syms; \
28 idx++, gelf_getsym(syms, idx, &sym))
29
30static inline uint8_t elf_sym__type(const GElf_Sym *sym)
31{
32 return GELF_ST_TYPE(sym->st_info);
33}
34
35static inline int elf_sym__is_function(const GElf_Sym *sym)
36{
37 return elf_sym__type(sym) == STT_FUNC &&
38 sym->st_name != 0 &&
39 sym->st_shndx != SHN_UNDEF;
40}
41
42static inline bool elf_sym__is_object(const GElf_Sym *sym)
43{
44 return elf_sym__type(sym) == STT_OBJECT &&
45 sym->st_name != 0 &&
46 sym->st_shndx != SHN_UNDEF;
47}
48
49static inline int elf_sym__is_label(const GElf_Sym *sym)
50{
51 return elf_sym__type(sym) == STT_NOTYPE &&
52 sym->st_name != 0 &&
53 sym->st_shndx != SHN_UNDEF &&
54 sym->st_shndx != SHN_ABS;
55}
56
57static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type)
58{
59 switch (type) {
60 case MAP__FUNCTION:
61 return elf_sym__is_function(sym);
62 case MAP__VARIABLE:
63 return elf_sym__is_object(sym);
64 default:
65 return false;
66 }
67}
68
69static inline const char *elf_sym__name(const GElf_Sym *sym,
70 const Elf_Data *symstrs)
71{
72 return symstrs->d_buf + sym->st_name;
73}
74
75static inline const char *elf_sec__name(const GElf_Shdr *shdr,
76 const Elf_Data *secstrs)
77{
78 return secstrs->d_buf + shdr->sh_name;
79}
80
81static inline int elf_sec__is_text(const GElf_Shdr *shdr,
82 const Elf_Data *secstrs)
83{
84 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
85}
86
87static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
88 const Elf_Data *secstrs)
89{
90 return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
91}
92
93static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs,
94 enum map_type type)
95{
96 switch (type) {
97 case MAP__FUNCTION:
98 return elf_sec__is_text(shdr, secstrs);
99 case MAP__VARIABLE:
100 return elf_sec__is_data(shdr, secstrs);
101 default:
102 return false;
103 }
104}
105
106static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
107{
108 Elf_Scn *sec = NULL;
109 GElf_Shdr shdr;
110 size_t cnt = 1;
111
112 while ((sec = elf_nextscn(elf, sec)) != NULL) {
113 gelf_getshdr(sec, &shdr);
114
115 if ((addr >= shdr.sh_addr) &&
116 (addr < (shdr.sh_addr + shdr.sh_size)))
117 return cnt;
118
119 ++cnt;
120 }
121
122 return -1;
123}
124
125static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
126 GElf_Shdr *shp, const char *name,
127 size_t *idx)
128{
129 Elf_Scn *sec = NULL;
130 size_t cnt = 1;
131
132 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
133 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL))
134 return NULL;
135
136 while ((sec = elf_nextscn(elf, sec)) != NULL) {
137 char *str;
138
139 gelf_getshdr(sec, shp);
140 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
141 if (!strcmp(name, str)) {
142 if (idx)
143 *idx = cnt;
144 break;
145 }
146 ++cnt;
147 }
148
149 return sec;
150}
151
152#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
153 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
154 idx < nr_entries; \
155 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
156
157#define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
158 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
159 idx < nr_entries; \
160 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
161
162/*
163 * We need to check if we have a .dynsym, so that we can handle the
164 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
165 * .dynsym or .symtab).
166 * And always look at the original dso, not at debuginfo packages, that
167 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
168 */
169int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map,
170 symbol_filter_t filter)
171{
172 uint32_t nr_rel_entries, idx;
173 GElf_Sym sym;
174 u64 plt_offset;
175 GElf_Shdr shdr_plt;
176 struct symbol *f;
177 GElf_Shdr shdr_rel_plt, shdr_dynsym;
178 Elf_Data *reldata, *syms, *symstrs;
179 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
180 size_t dynsym_idx;
181 GElf_Ehdr ehdr;
182 char sympltname[1024];
183 Elf *elf;
184 int nr = 0, symidx, err = 0;
185
186 if (!ss->dynsym)
187 return 0;
188
189 elf = ss->elf;
190 ehdr = ss->ehdr;
191
192 scn_dynsym = ss->dynsym;
193 shdr_dynsym = ss->dynshdr;
194 dynsym_idx = ss->dynsym_idx;
195
196 if (scn_dynsym == NULL)
197 goto out_elf_end;
198
199 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
200 ".rela.plt", NULL);
201 if (scn_plt_rel == NULL) {
202 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
203 ".rel.plt", NULL);
204 if (scn_plt_rel == NULL)
205 goto out_elf_end;
206 }
207
208 err = -1;
209
210 if (shdr_rel_plt.sh_link != dynsym_idx)
211 goto out_elf_end;
212
213 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
214 goto out_elf_end;
215
216 /*
217 * Fetch the relocation section to find the idxes to the GOT
218 * and the symbols in the .dynsym they refer to.
219 */
220 reldata = elf_getdata(scn_plt_rel, NULL);
221 if (reldata == NULL)
222 goto out_elf_end;
223
224 syms = elf_getdata(scn_dynsym, NULL);
225 if (syms == NULL)
226 goto out_elf_end;
227
228 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
229 if (scn_symstrs == NULL)
230 goto out_elf_end;
231
232 symstrs = elf_getdata(scn_symstrs, NULL);
233 if (symstrs == NULL)
234 goto out_elf_end;
235
236 if (symstrs->d_size == 0)
237 goto out_elf_end;
238
239 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
240 plt_offset = shdr_plt.sh_offset;
241
242 if (shdr_rel_plt.sh_type == SHT_RELA) {
243 GElf_Rela pos_mem, *pos;
244
245 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
246 nr_rel_entries) {
247 symidx = GELF_R_SYM(pos->r_info);
248 plt_offset += shdr_plt.sh_entsize;
249 gelf_getsym(syms, symidx, &sym);
250 snprintf(sympltname, sizeof(sympltname),
251 "%s@plt", elf_sym__name(&sym, symstrs));
252
253 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
254 STB_GLOBAL, sympltname);
255 if (!f)
256 goto out_elf_end;
257
258 if (filter && filter(map, f))
259 symbol__delete(f);
260 else {
261 symbols__insert(&dso->symbols[map->type], f);
262 ++nr;
263 }
264 }
265 } else if (shdr_rel_plt.sh_type == SHT_REL) {
266 GElf_Rel pos_mem, *pos;
267 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
268 nr_rel_entries) {
269 symidx = GELF_R_SYM(pos->r_info);
270 plt_offset += shdr_plt.sh_entsize;
271 gelf_getsym(syms, symidx, &sym);
272 snprintf(sympltname, sizeof(sympltname),
273 "%s@plt", elf_sym__name(&sym, symstrs));
274
275 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
276 STB_GLOBAL, sympltname);
277 if (!f)
278 goto out_elf_end;
279
280 if (filter && filter(map, f))
281 symbol__delete(f);
282 else {
283 symbols__insert(&dso->symbols[map->type], f);
284 ++nr;
285 }
286 }
287 }
288
289 err = 0;
290out_elf_end:
291 if (err == 0)
292 return nr;
293 pr_debug("%s: problems reading %s PLT info.\n",
294 __func__, dso->long_name);
295 return 0;
296}
297
298/*
299 * Align offset to 4 bytes as needed for note name and descriptor data.
300 */
301#define NOTE_ALIGN(n) (((n) + 3) & -4U)
302
303static int elf_read_build_id(Elf *elf, void *bf, size_t size)
304{
305 int err = -1;
306 GElf_Ehdr ehdr;
307 GElf_Shdr shdr;
308 Elf_Data *data;
309 Elf_Scn *sec;
310 Elf_Kind ek;
311 void *ptr;
312
313 if (size < BUILD_ID_SIZE)
314 goto out;
315
316 ek = elf_kind(elf);
317 if (ek != ELF_K_ELF)
318 goto out;
319
320 if (gelf_getehdr(elf, &ehdr) == NULL) {
321 pr_err("%s: cannot get elf header.\n", __func__);
322 goto out;
323 }
324
325 /*
326 * Check following sections for notes:
327 * '.note.gnu.build-id'
328 * '.notes'
329 * '.note' (VDSO specific)
330 */
331 do {
332 sec = elf_section_by_name(elf, &ehdr, &shdr,
333 ".note.gnu.build-id", NULL);
334 if (sec)
335 break;
336
337 sec = elf_section_by_name(elf, &ehdr, &shdr,
338 ".notes", NULL);
339 if (sec)
340 break;
341
342 sec = elf_section_by_name(elf, &ehdr, &shdr,
343 ".note", NULL);
344 if (sec)
345 break;
346
347 return err;
348
349 } while (0);
350
351 data = elf_getdata(sec, NULL);
352 if (data == NULL)
353 goto out;
354
355 ptr = data->d_buf;
356 while (ptr < (data->d_buf + data->d_size)) {
357 GElf_Nhdr *nhdr = ptr;
358 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
359 descsz = NOTE_ALIGN(nhdr->n_descsz);
360 const char *name;
361
362 ptr += sizeof(*nhdr);
363 name = ptr;
364 ptr += namesz;
365 if (nhdr->n_type == NT_GNU_BUILD_ID &&
366 nhdr->n_namesz == sizeof("GNU")) {
367 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
368 size_t sz = min(size, descsz);
369 memcpy(bf, ptr, sz);
370 memset(bf + sz, 0, size - sz);
371 err = descsz;
372 break;
373 }
374 }
375 ptr += descsz;
376 }
377
378out:
379 return err;
380}
381
382int filename__read_build_id(const char *filename, void *bf, size_t size)
383{
384 int fd, err = -1;
385 Elf *elf;
386
387 if (size < BUILD_ID_SIZE)
388 goto out;
389
390 fd = open(filename, O_RDONLY);
391 if (fd < 0)
392 goto out;
393
394 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
395 if (elf == NULL) {
396 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
397 goto out_close;
398 }
399
400 err = elf_read_build_id(elf, bf, size);
401
402 elf_end(elf);
403out_close:
404 close(fd);
405out:
406 return err;
407}
408
409int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
410{
411 int fd, err = -1;
412
413 if (size < BUILD_ID_SIZE)
414 goto out;
415
416 fd = open(filename, O_RDONLY);
417 if (fd < 0)
418 goto out;
419
420 while (1) {
421 char bf[BUFSIZ];
422 GElf_Nhdr nhdr;
423 size_t namesz, descsz;
424
425 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
426 break;
427
428 namesz = NOTE_ALIGN(nhdr.n_namesz);
429 descsz = NOTE_ALIGN(nhdr.n_descsz);
430 if (nhdr.n_type == NT_GNU_BUILD_ID &&
431 nhdr.n_namesz == sizeof("GNU")) {
432 if (read(fd, bf, namesz) != (ssize_t)namesz)
433 break;
434 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
435 size_t sz = min(descsz, size);
436 if (read(fd, build_id, sz) == (ssize_t)sz) {
437 memset(build_id + sz, 0, size - sz);
438 err = 0;
439 break;
440 }
441 } else if (read(fd, bf, descsz) != (ssize_t)descsz)
442 break;
443 } else {
444 int n = namesz + descsz;
445 if (read(fd, bf, n) != n)
446 break;
447 }
448 }
449 close(fd);
450out:
451 return err;
452}
453
454int filename__read_debuglink(const char *filename, char *debuglink,
455 size_t size)
456{
457 int fd, err = -1;
458 Elf *elf;
459 GElf_Ehdr ehdr;
460 GElf_Shdr shdr;
461 Elf_Data *data;
462 Elf_Scn *sec;
463 Elf_Kind ek;
464
465 fd = open(filename, O_RDONLY);
466 if (fd < 0)
467 goto out;
468
469 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
470 if (elf == NULL) {
471 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
472 goto out_close;
473 }
474
475 ek = elf_kind(elf);
476 if (ek != ELF_K_ELF)
477 goto out_close;
478
479 if (gelf_getehdr(elf, &ehdr) == NULL) {
480 pr_err("%s: cannot get elf header.\n", __func__);
481 goto out_close;
482 }
483
484 sec = elf_section_by_name(elf, &ehdr, &shdr,
485 ".gnu_debuglink", NULL);
486 if (sec == NULL)
487 goto out_close;
488
489 data = elf_getdata(sec, NULL);
490 if (data == NULL)
491 goto out_close;
492
493 /* the start of this section is a zero-terminated string */
494 strncpy(debuglink, data->d_buf, size);
495
496 elf_end(elf);
497
498out_close:
499 close(fd);
500out:
501 return err;
502}
503
504static int dso__swap_init(struct dso *dso, unsigned char eidata)
505{
506 static unsigned int const endian = 1;
507
508 dso->needs_swap = DSO_SWAP__NO;
509
510 switch (eidata) {
511 case ELFDATA2LSB:
512 /* We are big endian, DSO is little endian. */
513 if (*(unsigned char const *)&endian != 1)
514 dso->needs_swap = DSO_SWAP__YES;
515 break;
516
517 case ELFDATA2MSB:
518 /* We are little endian, DSO is big endian. */
519 if (*(unsigned char const *)&endian != 0)
520 dso->needs_swap = DSO_SWAP__YES;
521 break;
522
523 default:
524 pr_err("unrecognized DSO data encoding %d\n", eidata);
525 return -EINVAL;
526 }
527
528 return 0;
529}
530
531bool symsrc__possibly_runtime(struct symsrc *ss)
532{
533 return ss->dynsym || ss->opdsec;
534}
535
536bool symsrc__has_symtab(struct symsrc *ss)
537{
538 return ss->symtab != NULL;
539}
540
541void symsrc__destroy(struct symsrc *ss)
542{
543 free(ss->name);
544 elf_end(ss->elf);
545 close(ss->fd);
546}
547
548int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
549 enum dso_binary_type type)
550{
551 int err = -1;
552 GElf_Ehdr ehdr;
553 Elf *elf;
554 int fd;
555
556 fd = open(name, O_RDONLY);
557 if (fd < 0)
558 return -1;
559
560 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
561 if (elf == NULL) {
562 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
563 goto out_close;
564 }
565
566 if (gelf_getehdr(elf, &ehdr) == NULL) {
567 pr_debug("%s: cannot get elf header.\n", __func__);
568 goto out_elf_end;
569 }
570
571 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
572 goto out_elf_end;
573
574 /* Always reject images with a mismatched build-id: */
575 if (dso->has_build_id) {
576 u8 build_id[BUILD_ID_SIZE];
577
578 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
579 goto out_elf_end;
580
581 if (!dso__build_id_equal(dso, build_id))
582 goto out_elf_end;
583 }
584
585 ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab",
586 NULL);
587 if (ss->symshdr.sh_type != SHT_SYMTAB)
588 ss->symtab = NULL;
589
590 ss->dynsym_idx = 0;
591 ss->dynsym = elf_section_by_name(elf, &ehdr, &ss->dynshdr, ".dynsym",
592 &ss->dynsym_idx);
593 if (ss->dynshdr.sh_type != SHT_DYNSYM)
594 ss->dynsym = NULL;
595
596 ss->opdidx = 0;
597 ss->opdsec = elf_section_by_name(elf, &ehdr, &ss->opdshdr, ".opd",
598 &ss->opdidx);
599 if (ss->opdshdr.sh_type != SHT_PROGBITS)
600 ss->opdsec = NULL;
601
602 if (dso->kernel == DSO_TYPE_USER) {
603 GElf_Shdr shdr;
604 ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
605 elf_section_by_name(elf, &ehdr, &shdr,
606 ".gnu.prelink_undo",
607 NULL) != NULL);
608 } else {
609 ss->adjust_symbols = 0;
610 }
611
612 ss->name = strdup(name);
613 if (!ss->name)
614 goto out_elf_end;
615
616 ss->elf = elf;
617 ss->fd = fd;
618 ss->ehdr = ehdr;
619 ss->type = type;
620
621 return 0;
622
623out_elf_end:
624 elf_end(elf);
625out_close:
626 close(fd);
627 return err;
628}
629
630int dso__load_sym(struct dso *dso, struct map *map,
631 struct symsrc *syms_ss, struct symsrc *runtime_ss,
632 symbol_filter_t filter, int kmodule)
633{
634 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
635 struct map *curr_map = map;
636 struct dso *curr_dso = dso;
637 Elf_Data *symstrs, *secstrs;
638 uint32_t nr_syms;
639 int err = -1;
640 uint32_t idx;
641 GElf_Ehdr ehdr;
642 GElf_Shdr shdr;
643 Elf_Data *syms, *opddata = NULL;
644 GElf_Sym sym;
645 Elf_Scn *sec, *sec_strndx;
646 Elf *elf;
647 int nr = 0;
648
649 dso->symtab_type = syms_ss->type;
650
651 if (!syms_ss->symtab) {
652 syms_ss->symtab = syms_ss->dynsym;
653 syms_ss->symshdr = syms_ss->dynshdr;
654 }
655
656 elf = syms_ss->elf;
657 ehdr = syms_ss->ehdr;
658 sec = syms_ss->symtab;
659 shdr = syms_ss->symshdr;
660
661 if (runtime_ss->opdsec)
662 opddata = elf_rawdata(runtime_ss->opdsec, NULL);
663
664 syms = elf_getdata(sec, NULL);
665 if (syms == NULL)
666 goto out_elf_end;
667
668 sec = elf_getscn(elf, shdr.sh_link);
669 if (sec == NULL)
670 goto out_elf_end;
671
672 symstrs = elf_getdata(sec, NULL);
673 if (symstrs == NULL)
674 goto out_elf_end;
675
676 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
677 if (sec_strndx == NULL)
678 goto out_elf_end;
679
680 secstrs = elf_getdata(sec_strndx, NULL);
681 if (secstrs == NULL)
682 goto out_elf_end;
683
684 nr_syms = shdr.sh_size / shdr.sh_entsize;
685
686 memset(&sym, 0, sizeof(sym));
687 dso->adjust_symbols = runtime_ss->adjust_symbols;
688 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
689 struct symbol *f;
690 const char *elf_name = elf_sym__name(&sym, symstrs);
691 char *demangled = NULL;
692 int is_label = elf_sym__is_label(&sym);
693 const char *section_name;
694 bool used_opd = false;
695
696 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
697 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
698 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
699
700 if (!is_label && !elf_sym__is_a(&sym, map->type))
701 continue;
702
703 /* Reject ARM ELF "mapping symbols": these aren't unique and
704 * don't identify functions, so will confuse the profile
705 * output: */
706 if (ehdr.e_machine == EM_ARM) {
707 if (!strcmp(elf_name, "$a") ||
708 !strcmp(elf_name, "$d") ||
709 !strcmp(elf_name, "$t"))
710 continue;
711 }
712
713 if (runtime_ss->opdsec && sym.st_shndx == runtime_ss->opdidx) {
714 u32 offset = sym.st_value - syms_ss->opdshdr.sh_addr;
715 u64 *opd = opddata->d_buf + offset;
716 sym.st_value = DSO__SWAP(dso, u64, *opd);
717 sym.st_shndx = elf_addr_to_index(runtime_ss->elf,
718 sym.st_value);
719 used_opd = true;
720 }
721
722 sec = elf_getscn(runtime_ss->elf, sym.st_shndx);
723 if (!sec)
724 goto out_elf_end;
725
726 gelf_getshdr(sec, &shdr);
727
728 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
729 continue;
730
731 section_name = elf_sec__name(&shdr, secstrs);
732
733 /* On ARM, symbols for thumb functions have 1 added to
734 * the symbol address as a flag - remove it */
735 if ((ehdr.e_machine == EM_ARM) &&
736 (map->type == MAP__FUNCTION) &&
737 (sym.st_value & 1))
738 --sym.st_value;
739
740 if (dso->kernel != DSO_TYPE_USER || kmodule) {
741 char dso_name[PATH_MAX];
742
743 if (strcmp(section_name,
744 (curr_dso->short_name +
745 dso->short_name_len)) == 0)
746 goto new_symbol;
747
748 if (strcmp(section_name, ".text") == 0) {
749 curr_map = map;
750 curr_dso = dso;
751 goto new_symbol;
752 }
753
754 snprintf(dso_name, sizeof(dso_name),
755 "%s%s", dso->short_name, section_name);
756
757 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
758 if (curr_map == NULL) {
759 u64 start = sym.st_value;
760
761 if (kmodule)
762 start += map->start + shdr.sh_offset;
763
764 curr_dso = dso__new(dso_name);
765 if (curr_dso == NULL)
766 goto out_elf_end;
767 curr_dso->kernel = dso->kernel;
768 curr_dso->long_name = dso->long_name;
769 curr_dso->long_name_len = dso->long_name_len;
770 curr_map = map__new2(start, curr_dso,
771 map->type);
772 if (curr_map == NULL) {
773 dso__delete(curr_dso);
774 goto out_elf_end;
775 }
776 curr_map->map_ip = identity__map_ip;
777 curr_map->unmap_ip = identity__map_ip;
778 curr_dso->symtab_type = dso->symtab_type;
779 map_groups__insert(kmap->kmaps, curr_map);
780 dsos__add(&dso->node, curr_dso);
781 dso__set_loaded(curr_dso, map->type);
782 } else
783 curr_dso = curr_map->dso;
784
785 goto new_symbol;
786 }
787
788 if ((used_opd && runtime_ss->adjust_symbols)
789 || (!used_opd && syms_ss->adjust_symbols)) {
790 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
791 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
792 (u64)sym.st_value, (u64)shdr.sh_addr,
793 (u64)shdr.sh_offset);
794 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
795 }
796 /*
797 * We need to figure out if the object was created from C++ sources
798 * DWARF DW_compile_unit has this, but we don't always have access
799 * to it...
800 */
801 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
802 if (demangled != NULL)
803 elf_name = demangled;
804new_symbol:
805 f = symbol__new(sym.st_value, sym.st_size,
806 GELF_ST_BIND(sym.st_info), elf_name);
807 free(demangled);
808 if (!f)
809 goto out_elf_end;
810
811 if (filter && filter(curr_map, f))
812 symbol__delete(f);
813 else {
814 symbols__insert(&curr_dso->symbols[curr_map->type], f);
815 nr++;
816 }
817 }
818
819 /*
820 * For misannotated, zeroed, ASM function sizes.
821 */
822 if (nr > 0) {
823 symbols__fixup_duplicate(&dso->symbols[map->type]);
824 symbols__fixup_end(&dso->symbols[map->type]);
825 if (kmap) {
826 /*
827 * We need to fixup this here too because we create new
828 * maps here, for things like vsyscall sections.
829 */
830 __map_groups__fixup_end(kmap->kmaps, map->type);
831 }
832 }
833 err = nr;
834out_elf_end:
835 return err;
836}
837
838void symbol__elf_init(void)
839{
840 elf_version(EV_CURRENT);
841}
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
new file mode 100644
index 000000000000..259f8f2ea9c9
--- /dev/null
+++ b/tools/perf/util/symbol-minimal.c
@@ -0,0 +1,307 @@
1#include "symbol.h"
2
3#include <elf.h>
4#include <stdio.h>
5#include <fcntl.h>
6#include <string.h>
7#include <byteswap.h>
8#include <sys/stat.h>
9
10
11static bool check_need_swap(int file_endian)
12{
13 const int data = 1;
14 u8 *check = (u8 *)&data;
15 int host_endian;
16
17 if (check[0] == 1)
18 host_endian = ELFDATA2LSB;
19 else
20 host_endian = ELFDATA2MSB;
21
22 return host_endian != file_endian;
23}
24
25#define NOTE_ALIGN(sz) (((sz) + 3) & ~3)
26
27#define NT_GNU_BUILD_ID 3
28
29static int read_build_id(void *note_data, size_t note_len, void *bf,
30 size_t size, bool need_swap)
31{
32 struct {
33 u32 n_namesz;
34 u32 n_descsz;
35 u32 n_type;
36 } *nhdr;
37 void *ptr;
38
39 ptr = note_data;
40 while (ptr < (note_data + note_len)) {
41 const char *name;
42 size_t namesz, descsz;
43
44 nhdr = ptr;
45 if (need_swap) {
46 nhdr->n_namesz = bswap_32(nhdr->n_namesz);
47 nhdr->n_descsz = bswap_32(nhdr->n_descsz);
48 nhdr->n_type = bswap_32(nhdr->n_type);
49 }
50
51 namesz = NOTE_ALIGN(nhdr->n_namesz);
52 descsz = NOTE_ALIGN(nhdr->n_descsz);
53
54 ptr += sizeof(*nhdr);
55 name = ptr;
56 ptr += namesz;
57 if (nhdr->n_type == NT_GNU_BUILD_ID &&
58 nhdr->n_namesz == sizeof("GNU")) {
59 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
60 size_t sz = min(size, descsz);
61 memcpy(bf, ptr, sz);
62 memset(bf + sz, 0, size - sz);
63 return 0;
64 }
65 }
66 ptr += descsz;
67 }
68
69 return -1;
70}
71
72int filename__read_debuglink(const char *filename __maybe_unused,
73 char *debuglink __maybe_unused,
74 size_t size __maybe_unused)
75{
76 return -1;
77}
78
79/*
80 * Just try PT_NOTE header otherwise fails
81 */
82int filename__read_build_id(const char *filename, void *bf, size_t size)
83{
84 FILE *fp;
85 int ret = -1;
86 bool need_swap = false;
87 u8 e_ident[EI_NIDENT];
88 size_t buf_size;
89 void *buf;
90 int i;
91
92 fp = fopen(filename, "r");
93 if (fp == NULL)
94 return -1;
95
96 if (fread(e_ident, sizeof(e_ident), 1, fp) != 1)
97 goto out;
98
99 if (memcmp(e_ident, ELFMAG, SELFMAG) ||
100 e_ident[EI_VERSION] != EV_CURRENT)
101 goto out;
102
103 need_swap = check_need_swap(e_ident[EI_DATA]);
104
105 /* for simplicity */
106 fseek(fp, 0, SEEK_SET);
107
108 if (e_ident[EI_CLASS] == ELFCLASS32) {
109 Elf32_Ehdr ehdr;
110 Elf32_Phdr *phdr;
111
112 if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
113 goto out;
114
115 if (need_swap) {
116 ehdr.e_phoff = bswap_32(ehdr.e_phoff);
117 ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
118 ehdr.e_phnum = bswap_16(ehdr.e_phnum);
119 }
120
121 buf_size = ehdr.e_phentsize * ehdr.e_phnum;
122 buf = malloc(buf_size);
123 if (buf == NULL)
124 goto out;
125
126 fseek(fp, ehdr.e_phoff, SEEK_SET);
127 if (fread(buf, buf_size, 1, fp) != 1)
128 goto out_free;
129
130 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
131 void *tmp;
132
133 if (need_swap) {
134 phdr->p_type = bswap_32(phdr->p_type);
135 phdr->p_offset = bswap_32(phdr->p_offset);
136 phdr->p_filesz = bswap_32(phdr->p_filesz);
137 }
138
139 if (phdr->p_type != PT_NOTE)
140 continue;
141
142 buf_size = phdr->p_filesz;
143 tmp = realloc(buf, buf_size);
144 if (tmp == NULL)
145 goto out_free;
146
147 buf = tmp;
148 fseek(fp, phdr->p_offset, SEEK_SET);
149 if (fread(buf, buf_size, 1, fp) != 1)
150 goto out_free;
151
152 ret = read_build_id(buf, buf_size, bf, size, need_swap);
153 if (ret == 0)
154 ret = size;
155 break;
156 }
157 } else {
158 Elf64_Ehdr ehdr;
159 Elf64_Phdr *phdr;
160
161 if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
162 goto out;
163
164 if (need_swap) {
165 ehdr.e_phoff = bswap_64(ehdr.e_phoff);
166 ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
167 ehdr.e_phnum = bswap_16(ehdr.e_phnum);
168 }
169
170 buf_size = ehdr.e_phentsize * ehdr.e_phnum;
171 buf = malloc(buf_size);
172 if (buf == NULL)
173 goto out;
174
175 fseek(fp, ehdr.e_phoff, SEEK_SET);
176 if (fread(buf, buf_size, 1, fp) != 1)
177 goto out_free;
178
179 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
180 void *tmp;
181
182 if (need_swap) {
183 phdr->p_type = bswap_32(phdr->p_type);
184 phdr->p_offset = bswap_64(phdr->p_offset);
185 phdr->p_filesz = bswap_64(phdr->p_filesz);
186 }
187
188 if (phdr->p_type != PT_NOTE)
189 continue;
190
191 buf_size = phdr->p_filesz;
192 tmp = realloc(buf, buf_size);
193 if (tmp == NULL)
194 goto out_free;
195
196 buf = tmp;
197 fseek(fp, phdr->p_offset, SEEK_SET);
198 if (fread(buf, buf_size, 1, fp) != 1)
199 goto out_free;
200
201 ret = read_build_id(buf, buf_size, bf, size, need_swap);
202 if (ret == 0)
203 ret = size;
204 break;
205 }
206 }
207out_free:
208 free(buf);
209out:
210 fclose(fp);
211 return ret;
212}
213
214int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
215{
216 int fd;
217 int ret = -1;
218 struct stat stbuf;
219 size_t buf_size;
220 void *buf;
221
222 fd = open(filename, O_RDONLY);
223 if (fd < 0)
224 return -1;
225
226 if (fstat(fd, &stbuf) < 0)
227 goto out;
228
229 buf_size = stbuf.st_size;
230 buf = malloc(buf_size);
231 if (buf == NULL)
232 goto out;
233
234 if (read(fd, buf, buf_size) != (ssize_t) buf_size)
235 goto out_free;
236
237 ret = read_build_id(buf, buf_size, build_id, size, false);
238out_free:
239 free(buf);
240out:
241 close(fd);
242 return ret;
243}
244
245int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
246 const char *name,
247 enum dso_binary_type type)
248{
249 int fd = open(name, O_RDONLY);
250 if (fd < 0)
251 return -1;
252
253 ss->name = strdup(name);
254 if (!ss->name)
255 goto out_close;
256
257 ss->type = type;
258
259 return 0;
260out_close:
261 close(fd);
262 return -1;
263}
264
265bool symsrc__possibly_runtime(struct symsrc *ss __maybe_unused)
266{
267 /* Assume all sym sources could be a runtime image. */
268 return true;
269}
270
271bool symsrc__has_symtab(struct symsrc *ss __maybe_unused)
272{
273 return false;
274}
275
276void symsrc__destroy(struct symsrc *ss)
277{
278 free(ss->name);
279 close(ss->fd);
280}
281
282int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
283 struct symsrc *ss __maybe_unused,
284 struct map *map __maybe_unused,
285 symbol_filter_t filter __maybe_unused)
286{
287 return 0;
288}
289
290int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
291 struct symsrc *ss,
292 struct symsrc *runtime_ss __maybe_unused,
293 symbol_filter_t filter __maybe_unused,
294 int kmodule __maybe_unused)
295{
296 unsigned char *build_id[BUILD_ID_SIZE];
297
298 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
299 dso__set_build_id(dso, build_id);
300 return 1;
301 }
302 return 0;
303}
304
305void symbol__elf_init(void)
306{
307}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8b63b678e127..e2e8c697cffe 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,8 +15,6 @@
15#include "symbol.h" 15#include "symbol.h"
16#include "strlist.h" 16#include "strlist.h"
17 17
18#include <libelf.h>
19#include <gelf.h>
20#include <elf.h> 18#include <elf.h>
21#include <limits.h> 19#include <limits.h>
22#include <sys/utsname.h> 20#include <sys/utsname.h>
@@ -25,15 +23,7 @@
25#define KSYM_NAME_LEN 256 23#define KSYM_NAME_LEN 256
26#endif 24#endif
27 25
28#ifndef NT_GNU_BUILD_ID
29#define NT_GNU_BUILD_ID 3
30#endif
31
32static void dso_cache__free(struct rb_root *root); 26static void dso_cache__free(struct rb_root *root);
33static bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
34static int elf_read_build_id(Elf *elf, void *bf, size_t size);
35static void dsos__add(struct list_head *head, struct dso *dso);
36static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
37static int dso__load_kernel_sym(struct dso *dso, struct map *map, 27static int dso__load_kernel_sym(struct dso *dso, struct map *map,
38 symbol_filter_t filter); 28 symbol_filter_t filter);
39static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
@@ -170,7 +160,7 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
170 return SYMBOL_B; 160 return SYMBOL_B;
171} 161}
172 162
173static void symbols__fixup_duplicate(struct rb_root *symbols) 163void symbols__fixup_duplicate(struct rb_root *symbols)
174{ 164{
175 struct rb_node *nd; 165 struct rb_node *nd;
176 struct symbol *curr, *next; 166 struct symbol *curr, *next;
@@ -199,7 +189,7 @@ again:
199 } 189 }
200} 190}
201 191
202static void symbols__fixup_end(struct rb_root *symbols) 192void symbols__fixup_end(struct rb_root *symbols)
203{ 193{
204 struct rb_node *nd, *prevnd = rb_first(symbols); 194 struct rb_node *nd, *prevnd = rb_first(symbols);
205 struct symbol *curr, *prev; 195 struct symbol *curr, *prev;
@@ -222,7 +212,7 @@ static void symbols__fixup_end(struct rb_root *symbols)
222 curr->end = roundup(curr->start, 4096); 212 curr->end = roundup(curr->start, 4096);
223} 213}
224 214
225static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) 215void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
226{ 216{
227 struct map *prev, *curr; 217 struct map *prev, *curr;
228 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); 218 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]);
@@ -252,8 +242,7 @@ static void map_groups__fixup_end(struct map_groups *mg)
252 __map_groups__fixup_end(mg, i); 242 __map_groups__fixup_end(mg, i);
253} 243}
254 244
255static struct symbol *symbol__new(u64 start, u64 len, u8 binding, 245struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
256 const char *name)
257{ 246{
258 size_t namelen = strlen(name) + 1; 247 size_t namelen = strlen(name) + 1;
259 struct symbol *sym = calloc(1, (symbol_conf.priv_size + 248 struct symbol *sym = calloc(1, (symbol_conf.priv_size +
@@ -390,7 +379,7 @@ void dso__set_build_id(struct dso *dso, void *build_id)
390 dso->has_build_id = 1; 379 dso->has_build_id = 1;
391} 380}
392 381
393static void symbols__insert(struct rb_root *symbols, struct symbol *sym) 382void symbols__insert(struct rb_root *symbols, struct symbol *sym)
394{ 383{
395 struct rb_node **p = &symbols->rb_node; 384 struct rb_node **p = &symbols->rb_node;
396 struct rb_node *parent = NULL; 385 struct rb_node *parent = NULL;
@@ -574,7 +563,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
574 563
575int kallsyms__parse(const char *filename, void *arg, 564int kallsyms__parse(const char *filename, void *arg,
576 int (*process_symbol)(void *arg, const char *name, 565 int (*process_symbol)(void *arg, const char *name,
577 char type, u64 start, u64 end)) 566 char type, u64 start))
578{ 567{
579 char *line = NULL; 568 char *line = NULL;
580 size_t n; 569 size_t n;
@@ -614,13 +603,8 @@ int kallsyms__parse(const char *filename, void *arg,
614 break; 603 break;
615 } 604 }
616 605
617 /*
618 * module symbols are not sorted so we add all
619 * symbols with zero length and rely on
620 * symbols__fixup_end() to fix it up.
621 */
622 err = process_symbol(arg, symbol_name, 606 err = process_symbol(arg, symbol_name,
623 symbol_type, start, start); 607 symbol_type, start);
624 if (err) 608 if (err)
625 break; 609 break;
626 } 610 }
@@ -647,7 +631,7 @@ static u8 kallsyms2elf_type(char type)
647} 631}
648 632
649static int map__process_kallsym_symbol(void *arg, const char *name, 633static int map__process_kallsym_symbol(void *arg, const char *name,
650 char type, u64 start, u64 end) 634 char type, u64 start)
651{ 635{
652 struct symbol *sym; 636 struct symbol *sym;
653 struct process_kallsyms_args *a = arg; 637 struct process_kallsyms_args *a = arg;
@@ -656,8 +640,12 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
656 if (!symbol_type__is_a(type, a->map->type)) 640 if (!symbol_type__is_a(type, a->map->type))
657 return 0; 641 return 0;
658 642
659 sym = symbol__new(start, end - start + 1, 643 /*
660 kallsyms2elf_type(type), name); 644 * module symbols are not sorted so we add all
645 * symbols, setting length to 0, and rely on
646 * symbols__fixup_end() to fix it up.
647 */
648 sym = symbol__new(start, 0, kallsyms2elf_type(type), name);
661 if (sym == NULL) 649 if (sym == NULL)
662 return -ENOMEM; 650 return -ENOMEM;
663 /* 651 /*
@@ -904,556 +892,7 @@ out_failure:
904 return -1; 892 return -1;
905} 893}
906 894
907/** 895bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
908 * elf_symtab__for_each_symbol - iterate thru all the symbols
909 *
910 * @syms: struct elf_symtab instance to iterate
911 * @idx: uint32_t idx
912 * @sym: GElf_Sym iterator
913 */
914#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
915 for (idx = 0, gelf_getsym(syms, idx, &sym);\
916 idx < nr_syms; \
917 idx++, gelf_getsym(syms, idx, &sym))
918
919static inline uint8_t elf_sym__type(const GElf_Sym *sym)
920{
921 return GELF_ST_TYPE(sym->st_info);
922}
923
924static inline int elf_sym__is_function(const GElf_Sym *sym)
925{
926 return elf_sym__type(sym) == STT_FUNC &&
927 sym->st_name != 0 &&
928 sym->st_shndx != SHN_UNDEF;
929}
930
931static inline bool elf_sym__is_object(const GElf_Sym *sym)
932{
933 return elf_sym__type(sym) == STT_OBJECT &&
934 sym->st_name != 0 &&
935 sym->st_shndx != SHN_UNDEF;
936}
937
938static inline int elf_sym__is_label(const GElf_Sym *sym)
939{
940 return elf_sym__type(sym) == STT_NOTYPE &&
941 sym->st_name != 0 &&
942 sym->st_shndx != SHN_UNDEF &&
943 sym->st_shndx != SHN_ABS;
944}
945
946static inline const char *elf_sec__name(const GElf_Shdr *shdr,
947 const Elf_Data *secstrs)
948{
949 return secstrs->d_buf + shdr->sh_name;
950}
951
952static inline int elf_sec__is_text(const GElf_Shdr *shdr,
953 const Elf_Data *secstrs)
954{
955 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
956}
957
958static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
959 const Elf_Data *secstrs)
960{
961 return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
962}
963
964static inline const char *elf_sym__name(const GElf_Sym *sym,
965 const Elf_Data *symstrs)
966{
967 return symstrs->d_buf + sym->st_name;
968}
969
970static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
971 GElf_Shdr *shp, const char *name,
972 size_t *idx)
973{
974 Elf_Scn *sec = NULL;
975 size_t cnt = 1;
976
977 while ((sec = elf_nextscn(elf, sec)) != NULL) {
978 char *str;
979
980 gelf_getshdr(sec, shp);
981 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
982 if (!strcmp(name, str)) {
983 if (idx)
984 *idx = cnt;
985 break;
986 }
987 ++cnt;
988 }
989
990 return sec;
991}
992
993#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
994 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
995 idx < nr_entries; \
996 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
997
998#define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
999 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
1000 idx < nr_entries; \
1001 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
1002
1003/*
1004 * We need to check if we have a .dynsym, so that we can handle the
1005 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
1006 * .dynsym or .symtab).
1007 * And always look at the original dso, not at debuginfo packages, that
1008 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
1009 */
1010static int
1011dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map,
1012 symbol_filter_t filter)
1013{
1014 uint32_t nr_rel_entries, idx;
1015 GElf_Sym sym;
1016 u64 plt_offset;
1017 GElf_Shdr shdr_plt;
1018 struct symbol *f;
1019 GElf_Shdr shdr_rel_plt, shdr_dynsym;
1020 Elf_Data *reldata, *syms, *symstrs;
1021 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
1022 size_t dynsym_idx;
1023 GElf_Ehdr ehdr;
1024 char sympltname[1024];
1025 Elf *elf;
1026 int nr = 0, symidx, fd, err = 0;
1027
1028 fd = open(name, O_RDONLY);
1029 if (fd < 0)
1030 goto out;
1031
1032 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1033 if (elf == NULL)
1034 goto out_close;
1035
1036 if (gelf_getehdr(elf, &ehdr) == NULL)
1037 goto out_elf_end;
1038
1039 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
1040 ".dynsym", &dynsym_idx);
1041 if (scn_dynsym == NULL)
1042 goto out_elf_end;
1043
1044 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
1045 ".rela.plt", NULL);
1046 if (scn_plt_rel == NULL) {
1047 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
1048 ".rel.plt", NULL);
1049 if (scn_plt_rel == NULL)
1050 goto out_elf_end;
1051 }
1052
1053 err = -1;
1054
1055 if (shdr_rel_plt.sh_link != dynsym_idx)
1056 goto out_elf_end;
1057
1058 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
1059 goto out_elf_end;
1060
1061 /*
1062 * Fetch the relocation section to find the idxes to the GOT
1063 * and the symbols in the .dynsym they refer to.
1064 */
1065 reldata = elf_getdata(scn_plt_rel, NULL);
1066 if (reldata == NULL)
1067 goto out_elf_end;
1068
1069 syms = elf_getdata(scn_dynsym, NULL);
1070 if (syms == NULL)
1071 goto out_elf_end;
1072
1073 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
1074 if (scn_symstrs == NULL)
1075 goto out_elf_end;
1076
1077 symstrs = elf_getdata(scn_symstrs, NULL);
1078 if (symstrs == NULL)
1079 goto out_elf_end;
1080
1081 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
1082 plt_offset = shdr_plt.sh_offset;
1083
1084 if (shdr_rel_plt.sh_type == SHT_RELA) {
1085 GElf_Rela pos_mem, *pos;
1086
1087 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
1088 nr_rel_entries) {
1089 symidx = GELF_R_SYM(pos->r_info);
1090 plt_offset += shdr_plt.sh_entsize;
1091 gelf_getsym(syms, symidx, &sym);
1092 snprintf(sympltname, sizeof(sympltname),
1093 "%s@plt", elf_sym__name(&sym, symstrs));
1094
1095 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
1096 STB_GLOBAL, sympltname);
1097 if (!f)
1098 goto out_elf_end;
1099
1100 if (filter && filter(map, f))
1101 symbol__delete(f);
1102 else {
1103 symbols__insert(&dso->symbols[map->type], f);
1104 ++nr;
1105 }
1106 }
1107 } else if (shdr_rel_plt.sh_type == SHT_REL) {
1108 GElf_Rel pos_mem, *pos;
1109 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
1110 nr_rel_entries) {
1111 symidx = GELF_R_SYM(pos->r_info);
1112 plt_offset += shdr_plt.sh_entsize;
1113 gelf_getsym(syms, symidx, &sym);
1114 snprintf(sympltname, sizeof(sympltname),
1115 "%s@plt", elf_sym__name(&sym, symstrs));
1116
1117 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
1118 STB_GLOBAL, sympltname);
1119 if (!f)
1120 goto out_elf_end;
1121
1122 if (filter && filter(map, f))
1123 symbol__delete(f);
1124 else {
1125 symbols__insert(&dso->symbols[map->type], f);
1126 ++nr;
1127 }
1128 }
1129 }
1130
1131 err = 0;
1132out_elf_end:
1133 elf_end(elf);
1134out_close:
1135 close(fd);
1136
1137 if (err == 0)
1138 return nr;
1139out:
1140 pr_debug("%s: problems reading %s PLT info.\n",
1141 __func__, dso->long_name);
1142 return 0;
1143}
1144
1145static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type)
1146{
1147 switch (type) {
1148 case MAP__FUNCTION:
1149 return elf_sym__is_function(sym);
1150 case MAP__VARIABLE:
1151 return elf_sym__is_object(sym);
1152 default:
1153 return false;
1154 }
1155}
1156
1157static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs,
1158 enum map_type type)
1159{
1160 switch (type) {
1161 case MAP__FUNCTION:
1162 return elf_sec__is_text(shdr, secstrs);
1163 case MAP__VARIABLE:
1164 return elf_sec__is_data(shdr, secstrs);
1165 default:
1166 return false;
1167 }
1168}
1169
1170static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
1171{
1172 Elf_Scn *sec = NULL;
1173 GElf_Shdr shdr;
1174 size_t cnt = 1;
1175
1176 while ((sec = elf_nextscn(elf, sec)) != NULL) {
1177 gelf_getshdr(sec, &shdr);
1178
1179 if ((addr >= shdr.sh_addr) &&
1180 (addr < (shdr.sh_addr + shdr.sh_size)))
1181 return cnt;
1182
1183 ++cnt;
1184 }
1185
1186 return -1;
1187}
1188
1189static int dso__swap_init(struct dso *dso, unsigned char eidata)
1190{
1191 static unsigned int const endian = 1;
1192
1193 dso->needs_swap = DSO_SWAP__NO;
1194
1195 switch (eidata) {
1196 case ELFDATA2LSB:
1197 /* We are big endian, DSO is little endian. */
1198 if (*(unsigned char const *)&endian != 1)
1199 dso->needs_swap = DSO_SWAP__YES;
1200 break;
1201
1202 case ELFDATA2MSB:
1203 /* We are little endian, DSO is big endian. */
1204 if (*(unsigned char const *)&endian != 0)
1205 dso->needs_swap = DSO_SWAP__YES;
1206 break;
1207
1208 default:
1209 pr_err("unrecognized DSO data encoding %d\n", eidata);
1210 return -EINVAL;
1211 }
1212
1213 return 0;
1214}
1215
1216static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1217 int fd, symbol_filter_t filter, int kmodule,
1218 int want_symtab)
1219{
1220 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
1221 struct map *curr_map = map;
1222 struct dso *curr_dso = dso;
1223 Elf_Data *symstrs, *secstrs;
1224 uint32_t nr_syms;
1225 int err = -1;
1226 uint32_t idx;
1227 GElf_Ehdr ehdr;
1228 GElf_Shdr shdr, opdshdr;
1229 Elf_Data *syms, *opddata = NULL;
1230 GElf_Sym sym;
1231 Elf_Scn *sec, *sec_strndx, *opdsec;
1232 Elf *elf;
1233 int nr = 0;
1234 size_t opdidx = 0;
1235
1236 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1237 if (elf == NULL) {
1238 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
1239 goto out_close;
1240 }
1241
1242 if (gelf_getehdr(elf, &ehdr) == NULL) {
1243 pr_debug("%s: cannot get elf header.\n", __func__);
1244 goto out_elf_end;
1245 }
1246
1247 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
1248 goto out_elf_end;
1249
1250 /* Always reject images with a mismatched build-id: */
1251 if (dso->has_build_id) {
1252 u8 build_id[BUILD_ID_SIZE];
1253
1254 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
1255 goto out_elf_end;
1256
1257 if (!dso__build_id_equal(dso, build_id))
1258 goto out_elf_end;
1259 }
1260
1261 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
1262 if (sec == NULL) {
1263 if (want_symtab)
1264 goto out_elf_end;
1265
1266 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
1267 if (sec == NULL)
1268 goto out_elf_end;
1269 }
1270
1271 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
1272 if (opdshdr.sh_type != SHT_PROGBITS)
1273 opdsec = NULL;
1274 if (opdsec)
1275 opddata = elf_rawdata(opdsec, NULL);
1276
1277 syms = elf_getdata(sec, NULL);
1278 if (syms == NULL)
1279 goto out_elf_end;
1280
1281 sec = elf_getscn(elf, shdr.sh_link);
1282 if (sec == NULL)
1283 goto out_elf_end;
1284
1285 symstrs = elf_getdata(sec, NULL);
1286 if (symstrs == NULL)
1287 goto out_elf_end;
1288
1289 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
1290 if (sec_strndx == NULL)
1291 goto out_elf_end;
1292
1293 secstrs = elf_getdata(sec_strndx, NULL);
1294 if (secstrs == NULL)
1295 goto out_elf_end;
1296
1297 nr_syms = shdr.sh_size / shdr.sh_entsize;
1298
1299 memset(&sym, 0, sizeof(sym));
1300 if (dso->kernel == DSO_TYPE_USER) {
1301 dso->adjust_symbols = (ehdr.e_type == ET_EXEC ||
1302 elf_section_by_name(elf, &ehdr, &shdr,
1303 ".gnu.prelink_undo",
1304 NULL) != NULL);
1305 } else {
1306 dso->adjust_symbols = 0;
1307 }
1308 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
1309 struct symbol *f;
1310 const char *elf_name = elf_sym__name(&sym, symstrs);
1311 char *demangled = NULL;
1312 int is_label = elf_sym__is_label(&sym);
1313 const char *section_name;
1314
1315 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
1316 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
1317 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
1318
1319 if (!is_label && !elf_sym__is_a(&sym, map->type))
1320 continue;
1321
1322 /* Reject ARM ELF "mapping symbols": these aren't unique and
1323 * don't identify functions, so will confuse the profile
1324 * output: */
1325 if (ehdr.e_machine == EM_ARM) {
1326 if (!strcmp(elf_name, "$a") ||
1327 !strcmp(elf_name, "$d") ||
1328 !strcmp(elf_name, "$t"))
1329 continue;
1330 }
1331
1332 if (opdsec && sym.st_shndx == opdidx) {
1333 u32 offset = sym.st_value - opdshdr.sh_addr;
1334 u64 *opd = opddata->d_buf + offset;
1335 sym.st_value = DSO__SWAP(dso, u64, *opd);
1336 sym.st_shndx = elf_addr_to_index(elf, sym.st_value);
1337 }
1338
1339 sec = elf_getscn(elf, sym.st_shndx);
1340 if (!sec)
1341 goto out_elf_end;
1342
1343 gelf_getshdr(sec, &shdr);
1344
1345 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
1346 continue;
1347
1348 section_name = elf_sec__name(&shdr, secstrs);
1349
1350 /* On ARM, symbols for thumb functions have 1 added to
1351 * the symbol address as a flag - remove it */
1352 if ((ehdr.e_machine == EM_ARM) &&
1353 (map->type == MAP__FUNCTION) &&
1354 (sym.st_value & 1))
1355 --sym.st_value;
1356
1357 if (dso->kernel != DSO_TYPE_USER || kmodule) {
1358 char dso_name[PATH_MAX];
1359
1360 if (strcmp(section_name,
1361 (curr_dso->short_name +
1362 dso->short_name_len)) == 0)
1363 goto new_symbol;
1364
1365 if (strcmp(section_name, ".text") == 0) {
1366 curr_map = map;
1367 curr_dso = dso;
1368 goto new_symbol;
1369 }
1370
1371 snprintf(dso_name, sizeof(dso_name),
1372 "%s%s", dso->short_name, section_name);
1373
1374 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
1375 if (curr_map == NULL) {
1376 u64 start = sym.st_value;
1377
1378 if (kmodule)
1379 start += map->start + shdr.sh_offset;
1380
1381 curr_dso = dso__new(dso_name);
1382 if (curr_dso == NULL)
1383 goto out_elf_end;
1384 curr_dso->kernel = dso->kernel;
1385 curr_dso->long_name = dso->long_name;
1386 curr_dso->long_name_len = dso->long_name_len;
1387 curr_map = map__new2(start, curr_dso,
1388 map->type);
1389 if (curr_map == NULL) {
1390 dso__delete(curr_dso);
1391 goto out_elf_end;
1392 }
1393 curr_map->map_ip = identity__map_ip;
1394 curr_map->unmap_ip = identity__map_ip;
1395 curr_dso->symtab_type = dso->symtab_type;
1396 map_groups__insert(kmap->kmaps, curr_map);
1397 dsos__add(&dso->node, curr_dso);
1398 dso__set_loaded(curr_dso, map->type);
1399 } else
1400 curr_dso = curr_map->dso;
1401
1402 goto new_symbol;
1403 }
1404
1405 if (curr_dso->adjust_symbols) {
1406 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
1407 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
1408 (u64)sym.st_value, (u64)shdr.sh_addr,
1409 (u64)shdr.sh_offset);
1410 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
1411 }
1412 /*
1413 * We need to figure out if the object was created from C++ sources
1414 * DWARF DW_compile_unit has this, but we don't always have access
1415 * to it...
1416 */
1417 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
1418 if (demangled != NULL)
1419 elf_name = demangled;
1420new_symbol:
1421 f = symbol__new(sym.st_value, sym.st_size,
1422 GELF_ST_BIND(sym.st_info), elf_name);
1423 free(demangled);
1424 if (!f)
1425 goto out_elf_end;
1426
1427 if (filter && filter(curr_map, f))
1428 symbol__delete(f);
1429 else {
1430 symbols__insert(&curr_dso->symbols[curr_map->type], f);
1431 nr++;
1432 }
1433 }
1434
1435 /*
1436 * For misannotated, zeroed, ASM function sizes.
1437 */
1438 if (nr > 0) {
1439 symbols__fixup_duplicate(&dso->symbols[map->type]);
1440 symbols__fixup_end(&dso->symbols[map->type]);
1441 if (kmap) {
1442 /*
1443 * We need to fixup this here too because we create new
1444 * maps here, for things like vsyscall sections.
1445 */
1446 __map_groups__fixup_end(kmap->kmaps, map->type);
1447 }
1448 }
1449 err = nr;
1450out_elf_end:
1451 elf_end(elf);
1452out_close:
1453 return err;
1454}
1455
1456static bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
1457{ 896{
1458 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0; 897 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
1459} 898}
@@ -1480,216 +919,11 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1480 return have_build_id; 919 return have_build_id;
1481} 920}
1482 921
1483/*
1484 * Align offset to 4 bytes as needed for note name and descriptor data.
1485 */
1486#define NOTE_ALIGN(n) (((n) + 3) & -4U)
1487
1488static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1489{
1490 int err = -1;
1491 GElf_Ehdr ehdr;
1492 GElf_Shdr shdr;
1493 Elf_Data *data;
1494 Elf_Scn *sec;
1495 Elf_Kind ek;
1496 void *ptr;
1497
1498 if (size < BUILD_ID_SIZE)
1499 goto out;
1500
1501 ek = elf_kind(elf);
1502 if (ek != ELF_K_ELF)
1503 goto out;
1504
1505 if (gelf_getehdr(elf, &ehdr) == NULL) {
1506 pr_err("%s: cannot get elf header.\n", __func__);
1507 goto out;
1508 }
1509
1510 /*
1511 * Check following sections for notes:
1512 * '.note.gnu.build-id'
1513 * '.notes'
1514 * '.note' (VDSO specific)
1515 */
1516 do {
1517 sec = elf_section_by_name(elf, &ehdr, &shdr,
1518 ".note.gnu.build-id", NULL);
1519 if (sec)
1520 break;
1521
1522 sec = elf_section_by_name(elf, &ehdr, &shdr,
1523 ".notes", NULL);
1524 if (sec)
1525 break;
1526
1527 sec = elf_section_by_name(elf, &ehdr, &shdr,
1528 ".note", NULL);
1529 if (sec)
1530 break;
1531
1532 return err;
1533
1534 } while (0);
1535
1536 data = elf_getdata(sec, NULL);
1537 if (data == NULL)
1538 goto out;
1539
1540 ptr = data->d_buf;
1541 while (ptr < (data->d_buf + data->d_size)) {
1542 GElf_Nhdr *nhdr = ptr;
1543 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
1544 descsz = NOTE_ALIGN(nhdr->n_descsz);
1545 const char *name;
1546
1547 ptr += sizeof(*nhdr);
1548 name = ptr;
1549 ptr += namesz;
1550 if (nhdr->n_type == NT_GNU_BUILD_ID &&
1551 nhdr->n_namesz == sizeof("GNU")) {
1552 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
1553 size_t sz = min(size, descsz);
1554 memcpy(bf, ptr, sz);
1555 memset(bf + sz, 0, size - sz);
1556 err = descsz;
1557 break;
1558 }
1559 }
1560 ptr += descsz;
1561 }
1562
1563out:
1564 return err;
1565}
1566
1567int filename__read_build_id(const char *filename, void *bf, size_t size)
1568{
1569 int fd, err = -1;
1570 Elf *elf;
1571
1572 if (size < BUILD_ID_SIZE)
1573 goto out;
1574
1575 fd = open(filename, O_RDONLY);
1576 if (fd < 0)
1577 goto out;
1578
1579 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1580 if (elf == NULL) {
1581 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1582 goto out_close;
1583 }
1584
1585 err = elf_read_build_id(elf, bf, size);
1586
1587 elf_end(elf);
1588out_close:
1589 close(fd);
1590out:
1591 return err;
1592}
1593
1594int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1595{
1596 int fd, err = -1;
1597
1598 if (size < BUILD_ID_SIZE)
1599 goto out;
1600
1601 fd = open(filename, O_RDONLY);
1602 if (fd < 0)
1603 goto out;
1604
1605 while (1) {
1606 char bf[BUFSIZ];
1607 GElf_Nhdr nhdr;
1608 size_t namesz, descsz;
1609
1610 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1611 break;
1612
1613 namesz = NOTE_ALIGN(nhdr.n_namesz);
1614 descsz = NOTE_ALIGN(nhdr.n_descsz);
1615 if (nhdr.n_type == NT_GNU_BUILD_ID &&
1616 nhdr.n_namesz == sizeof("GNU")) {
1617 if (read(fd, bf, namesz) != (ssize_t)namesz)
1618 break;
1619 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1620 size_t sz = min(descsz, size);
1621 if (read(fd, build_id, sz) == (ssize_t)sz) {
1622 memset(build_id + sz, 0, size - sz);
1623 err = 0;
1624 break;
1625 }
1626 } else if (read(fd, bf, descsz) != (ssize_t)descsz)
1627 break;
1628 } else {
1629 int n = namesz + descsz;
1630 if (read(fd, bf, n) != n)
1631 break;
1632 }
1633 }
1634 close(fd);
1635out:
1636 return err;
1637}
1638
1639static int filename__read_debuglink(const char *filename,
1640 char *debuglink, size_t size)
1641{
1642 int fd, err = -1;
1643 Elf *elf;
1644 GElf_Ehdr ehdr;
1645 GElf_Shdr shdr;
1646 Elf_Data *data;
1647 Elf_Scn *sec;
1648 Elf_Kind ek;
1649
1650 fd = open(filename, O_RDONLY);
1651 if (fd < 0)
1652 goto out;
1653
1654 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1655 if (elf == NULL) {
1656 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1657 goto out_close;
1658 }
1659
1660 ek = elf_kind(elf);
1661 if (ek != ELF_K_ELF)
1662 goto out_close;
1663
1664 if (gelf_getehdr(elf, &ehdr) == NULL) {
1665 pr_err("%s: cannot get elf header.\n", __func__);
1666 goto out_close;
1667 }
1668
1669 sec = elf_section_by_name(elf, &ehdr, &shdr,
1670 ".gnu_debuglink", NULL);
1671 if (sec == NULL)
1672 goto out_close;
1673
1674 data = elf_getdata(sec, NULL);
1675 if (data == NULL)
1676 goto out_close;
1677
1678 /* the start of this section is a zero-terminated string */
1679 strncpy(debuglink, data->d_buf, size);
1680
1681 elf_end(elf);
1682
1683out_close:
1684 close(fd);
1685out:
1686 return err;
1687}
1688
1689char dso__symtab_origin(const struct dso *dso) 922char dso__symtab_origin(const struct dso *dso)
1690{ 923{
1691 static const char origin[] = { 924 static const char origin[] = {
1692 [DSO_BINARY_TYPE__KALLSYMS] = 'k', 925 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
926 [DSO_BINARY_TYPE__VMLINUX] = 'v',
1693 [DSO_BINARY_TYPE__JAVA_JIT] = 'j', 927 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
1694 [DSO_BINARY_TYPE__DEBUGLINK] = 'l', 928 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
1695 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', 929 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
@@ -1700,6 +934,7 @@ char dso__symtab_origin(const struct dso *dso)
1700 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', 934 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
1701 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', 935 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
1702 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', 936 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
937 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
1703 }; 938 };
1704 939
1705 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND) 940 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
@@ -1775,7 +1010,9 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
1775 1010
1776 default: 1011 default:
1777 case DSO_BINARY_TYPE__KALLSYMS: 1012 case DSO_BINARY_TYPE__KALLSYMS:
1013 case DSO_BINARY_TYPE__VMLINUX:
1778 case DSO_BINARY_TYPE__GUEST_KALLSYMS: 1014 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
1015 case DSO_BINARY_TYPE__GUEST_VMLINUX:
1779 case DSO_BINARY_TYPE__JAVA_JIT: 1016 case DSO_BINARY_TYPE__JAVA_JIT:
1780 case DSO_BINARY_TYPE__NOT_FOUND: 1017 case DSO_BINARY_TYPE__NOT_FOUND:
1781 ret = -1; 1018 ret = -1;
@@ -1789,11 +1026,12 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1789{ 1026{
1790 char *name; 1027 char *name;
1791 int ret = -1; 1028 int ret = -1;
1792 int fd;
1793 u_int i; 1029 u_int i;
1794 struct machine *machine; 1030 struct machine *machine;
1795 char *root_dir = (char *) ""; 1031 char *root_dir = (char *) "";
1796 int want_symtab; 1032 int ss_pos = 0;
1033 struct symsrc ss_[2];
1034 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
1797 1035
1798 dso__set_loaded(dso, map->type); 1036 dso__set_loaded(dso, map->type);
1799 1037
@@ -1835,54 +1073,69 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1835 root_dir = machine->root_dir; 1073 root_dir = machine->root_dir;
1836 1074
1837 /* Iterate over candidate debug images. 1075 /* Iterate over candidate debug images.
1838 * On the first pass, only load images if they have a full symtab. 1076 * Keep track of "interesting" ones (those which have a symtab, dynsym,
1839 * Failing that, do a second pass where we accept .dynsym also 1077 * and/or opd section) for processing.
1840 */ 1078 */
1841 want_symtab = 1;
1842restart:
1843 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) { 1079 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
1080 struct symsrc *ss = &ss_[ss_pos];
1081 bool next_slot = false;
1844 1082
1845 dso->symtab_type = binary_type_symtab[i]; 1083 enum dso_binary_type symtab_type = binary_type_symtab[i];
1846 1084
1847 if (dso__binary_type_file(dso, dso->symtab_type, 1085 if (dso__binary_type_file(dso, symtab_type,
1848 root_dir, name, PATH_MAX)) 1086 root_dir, name, PATH_MAX))
1849 continue; 1087 continue;
1850 1088
1851 /* Name is now the name of the next image to try */ 1089 /* Name is now the name of the next image to try */
1852 fd = open(name, O_RDONLY); 1090 if (symsrc__init(ss, dso, name, symtab_type) < 0)
1853 if (fd < 0)
1854 continue; 1091 continue;
1855 1092
1856 ret = dso__load_sym(dso, map, name, fd, filter, 0, 1093 if (!syms_ss && symsrc__has_symtab(ss)) {
1857 want_symtab); 1094 syms_ss = ss;
1858 close(fd); 1095 next_slot = true;
1096 }
1859 1097
1860 /* 1098 if (!runtime_ss && symsrc__possibly_runtime(ss)) {
1861 * Some people seem to have debuginfo files _WITHOUT_ debug 1099 runtime_ss = ss;
1862 * info!?!? 1100 next_slot = true;
1863 */ 1101 }
1864 if (!ret)
1865 continue;
1866 1102
1867 if (ret > 0) { 1103 if (next_slot) {
1868 int nr_plt; 1104 ss_pos++;
1869 1105
1870 nr_plt = dso__synthesize_plt_symbols(dso, name, map, filter); 1106 if (syms_ss && runtime_ss)
1871 if (nr_plt > 0) 1107 break;
1872 ret += nr_plt;
1873 break;
1874 } 1108 }
1109
1875 } 1110 }
1876 1111
1877 /* 1112 if (!runtime_ss && !syms_ss)
1878 * If we wanted a full symtab but no image had one, 1113 goto out_free;
1879 * relax our requirements and repeat the search. 1114
1880 */ 1115 if (runtime_ss && !syms_ss) {
1881 if (ret <= 0 && want_symtab) { 1116 syms_ss = runtime_ss;
1882 want_symtab = 0; 1117 }
1883 goto restart; 1118
1119 /* We'll have to hope for the best */
1120 if (!runtime_ss && syms_ss)
1121 runtime_ss = syms_ss;
1122
1123 if (syms_ss)
1124 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, 0);
1125 else
1126 ret = -1;
1127
1128 if (ret > 0) {
1129 int nr_plt;
1130
1131 nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map, filter);
1132 if (nr_plt > 0)
1133 ret += nr_plt;
1884 } 1134 }
1885 1135
1136 for (; ss_pos > 0; ss_pos--)
1137 symsrc__destroy(&ss_[ss_pos - 1]);
1138out_free:
1886 free(name); 1139 free(name);
1887 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) 1140 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL)
1888 return 0; 1141 return 0;
@@ -2030,25 +1283,6 @@ static int machine__set_modules_path(struct machine *machine)
2030 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 1283 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
2031} 1284}
2032 1285
2033/*
2034 * Constructor variant for modules (where we know from /proc/modules where
2035 * they are loaded) and for vmlinux, where only after we load all the
2036 * symbols we'll know where it starts and ends.
2037 */
2038static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
2039{
2040 struct map *map = calloc(1, (sizeof(*map) +
2041 (dso->kernel ? sizeof(struct kmap) : 0)));
2042 if (map != NULL) {
2043 /*
2044 * ->end will be filled after we load all the symbols
2045 */
2046 map__init(map, type, start, 0, 0, dso);
2047 }
2048
2049 return map;
2050}
2051
2052struct map *machine__new_module(struct machine *machine, u64 start, 1286struct map *machine__new_module(struct machine *machine, u64 start,
2053 const char *filename) 1287 const char *filename)
2054{ 1288{
@@ -2141,22 +1375,30 @@ out_failure:
2141int dso__load_vmlinux(struct dso *dso, struct map *map, 1375int dso__load_vmlinux(struct dso *dso, struct map *map,
2142 const char *vmlinux, symbol_filter_t filter) 1376 const char *vmlinux, symbol_filter_t filter)
2143{ 1377{
2144 int err = -1, fd; 1378 int err = -1;
1379 struct symsrc ss;
2145 char symfs_vmlinux[PATH_MAX]; 1380 char symfs_vmlinux[PATH_MAX];
1381 enum dso_binary_type symtab_type;
2146 1382
2147 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1383 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s",
2148 symbol_conf.symfs, vmlinux); 1384 symbol_conf.symfs, vmlinux);
2149 fd = open(symfs_vmlinux, O_RDONLY); 1385
2150 if (fd < 0) 1386 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1387 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
1388 else
1389 symtab_type = DSO_BINARY_TYPE__VMLINUX;
1390
1391 if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type))
2151 return -1; 1392 return -1;
2152 1393
2153 dso__set_long_name(dso, (char *)vmlinux); 1394 err = dso__load_sym(dso, map, &ss, &ss, filter, 0);
2154 dso__set_loaded(dso, map->type); 1395 symsrc__destroy(&ss);
2155 err = dso__load_sym(dso, map, symfs_vmlinux, fd, filter, 0, 0);
2156 close(fd);
2157 1396
2158 if (err > 0) 1397 if (err > 0) {
1398 dso__set_long_name(dso, (char *)vmlinux);
1399 dso__set_loaded(dso, map->type);
2159 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1400 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1401 }
2160 1402
2161 return err; 1403 return err;
2162} 1404}
@@ -2173,10 +1415,8 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
2173 filename = dso__build_id_filename(dso, NULL, 0); 1415 filename = dso__build_id_filename(dso, NULL, 0);
2174 if (filename != NULL) { 1416 if (filename != NULL) {
2175 err = dso__load_vmlinux(dso, map, filename, filter); 1417 err = dso__load_vmlinux(dso, map, filename, filter);
2176 if (err > 0) { 1418 if (err > 0)
2177 dso__set_long_name(dso, filename);
2178 goto out; 1419 goto out;
2179 }
2180 free(filename); 1420 free(filename);
2181 } 1421 }
2182 1422
@@ -2291,9 +1531,8 @@ do_kallsyms:
2291 free(kallsyms_allocated_filename); 1531 free(kallsyms_allocated_filename);
2292 1532
2293 if (err > 0) { 1533 if (err > 0) {
1534 dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
2294out_fixup: 1535out_fixup:
2295 if (kallsyms_filename != NULL)
2296 dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
2297 map__fixup_start(map); 1536 map__fixup_start(map);
2298 map__fixup_end(map); 1537 map__fixup_end(map);
2299 } 1538 }
@@ -2352,12 +1591,12 @@ out_try_fixup:
2352 return err; 1591 return err;
2353} 1592}
2354 1593
2355static void dsos__add(struct list_head *head, struct dso *dso) 1594void dsos__add(struct list_head *head, struct dso *dso)
2356{ 1595{
2357 list_add_tail(&dso->node, head); 1596 list_add_tail(&dso->node, head);
2358} 1597}
2359 1598
2360static struct dso *dsos__find(struct list_head *head, const char *name) 1599struct dso *dsos__find(struct list_head *head, const char *name)
2361{ 1600{
2362 struct dso *pos; 1601 struct dso *pos;
2363 1602
@@ -2516,7 +1755,7 @@ struct process_args {
2516}; 1755};
2517 1756
2518static int symbol__in_kernel(void *arg, const char *name, 1757static int symbol__in_kernel(void *arg, const char *name,
2519 char type __used, u64 start, u64 end __used) 1758 char type __maybe_unused, u64 start)
2520{ 1759{
2521 struct process_args *args = arg; 1760 struct process_args *args = arg;
2522 1761
@@ -2752,9 +1991,10 @@ int symbol__init(void)
2752 if (symbol_conf.initialized) 1991 if (symbol_conf.initialized)
2753 return 0; 1992 return 0;
2754 1993
2755 symbol_conf.priv_size = ALIGN(symbol_conf.priv_size, sizeof(u64)); 1994 symbol_conf.priv_size = PERF_ALIGN(symbol_conf.priv_size, sizeof(u64));
1995
1996 symbol__elf_init();
2756 1997
2757 elf_version(EV_CURRENT);
2758 if (symbol_conf.sort_by_name) 1998 if (symbol_conf.sort_by_name)
2759 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 1999 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
2760 sizeof(struct symbol)); 2000 sizeof(struct symbol));
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 1fe733a1e21f..8b6ef7fac745 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -10,22 +10,31 @@
10#include <linux/rbtree.h> 10#include <linux/rbtree.h>
11#include <stdio.h> 11#include <stdio.h>
12#include <byteswap.h> 12#include <byteswap.h>
13#include <libgen.h>
14
15#ifdef LIBELF_SUPPORT
16#include <libelf.h>
17#include <gelf.h>
18#include <elf.h>
19#endif
13 20
14#ifdef HAVE_CPLUS_DEMANGLE 21#ifdef HAVE_CPLUS_DEMANGLE
15extern char *cplus_demangle(const char *, int); 22extern char *cplus_demangle(const char *, int);
16 23
17static inline char *bfd_demangle(void __used *v, const char *c, int i) 24static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
18{ 25{
19 return cplus_demangle(c, i); 26 return cplus_demangle(c, i);
20} 27}
21#else 28#else
22#ifdef NO_DEMANGLE 29#ifdef NO_DEMANGLE
23static inline char *bfd_demangle(void __used *v, const char __used *c, 30static inline char *bfd_demangle(void __maybe_unused *v,
24 int __used i) 31 const char __maybe_unused *c,
32 int __maybe_unused i)
25{ 33{
26 return NULL; 34 return NULL;
27} 35}
28#else 36#else
37#define PACKAGE 'perf'
29#include <bfd.h> 38#include <bfd.h>
30#endif 39#endif
31#endif 40#endif
@@ -37,10 +46,10 @@ char *strxfrchar(char *s, char from, char to);
37 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
38 * for newer versions we can use mmap to reduce memory usage: 47 * for newer versions we can use mmap to reduce memory usage:
39 */ 48 */
40#ifdef LIBELF_NO_MMAP 49#ifdef LIBELF_MMAP
41# define PERF_ELF_C_READ_MMAP ELF_C_READ
42#else
43# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP 50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
51#else
52# define PERF_ELF_C_READ_MMAP ELF_C_READ
44#endif 53#endif
45 54
46#ifndef DMGL_PARAMS 55#ifndef DMGL_PARAMS
@@ -158,6 +167,8 @@ struct addr_location {
158enum dso_binary_type { 167enum dso_binary_type {
159 DSO_BINARY_TYPE__KALLSYMS = 0, 168 DSO_BINARY_TYPE__KALLSYMS = 0,
160 DSO_BINARY_TYPE__GUEST_KALLSYMS, 169 DSO_BINARY_TYPE__GUEST_KALLSYMS,
170 DSO_BINARY_TYPE__VMLINUX,
171 DSO_BINARY_TYPE__GUEST_VMLINUX,
161 DSO_BINARY_TYPE__JAVA_JIT, 172 DSO_BINARY_TYPE__JAVA_JIT,
162 DSO_BINARY_TYPE__DEBUGLINK, 173 DSO_BINARY_TYPE__DEBUGLINK,
163 DSO_BINARY_TYPE__BUILD_ID_CACHE, 174 DSO_BINARY_TYPE__BUILD_ID_CACHE,
@@ -217,6 +228,36 @@ struct dso {
217 char name[0]; 228 char name[0];
218}; 229};
219 230
231struct symsrc {
232 char *name;
233 int fd;
234 enum dso_binary_type type;
235
236#ifdef LIBELF_SUPPORT
237 Elf *elf;
238 GElf_Ehdr ehdr;
239
240 Elf_Scn *opdsec;
241 size_t opdidx;
242 GElf_Shdr opdshdr;
243
244 Elf_Scn *symtab;
245 GElf_Shdr symshdr;
246
247 Elf_Scn *dynsym;
248 size_t dynsym_idx;
249 GElf_Shdr dynshdr;
250
251 bool adjust_symbols;
252#endif
253};
254
255void symsrc__destroy(struct symsrc *ss);
256int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
257 enum dso_binary_type type);
258bool symsrc__has_symtab(struct symsrc *ss);
259bool symsrc__possibly_runtime(struct symsrc *ss);
260
220#define DSO__SWAP(dso, type, val) \ 261#define DSO__SWAP(dso, type, val) \
221({ \ 262({ \
222 type ____r = val; \ 263 type ____r = val; \
@@ -254,6 +295,8 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type)
254 295
255void dso__sort_by_name(struct dso *dso, enum map_type type); 296void dso__sort_by_name(struct dso *dso, enum map_type type);
256 297
298void dsos__add(struct list_head *head, struct dso *dso);
299struct dso *dsos__find(struct list_head *head, const char *name);
257struct dso *__dsos__findnew(struct list_head *head, const char *name); 300struct dso *__dsos__findnew(struct list_head *head, const char *name);
258 301
259int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 302int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
@@ -283,6 +326,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
283char dso__symtab_origin(const struct dso *dso); 326char dso__symtab_origin(const struct dso *dso);
284void dso__set_long_name(struct dso *dso, char *name); 327void dso__set_long_name(struct dso *dso, char *name);
285void dso__set_build_id(struct dso *dso, void *build_id); 328void dso__set_build_id(struct dso *dso, void *build_id);
329bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
286void dso__read_running_kernel_build_id(struct dso *dso, 330void dso__read_running_kernel_build_id(struct dso *dso,
287 struct machine *machine); 331 struct machine *machine);
288struct map *dso__new_map(const char *name); 332struct map *dso__new_map(const char *name);
@@ -297,7 +341,9 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
297int build_id__sprintf(const u8 *build_id, int len, char *bf); 341int build_id__sprintf(const u8 *build_id, int len, char *bf);
298int kallsyms__parse(const char *filename, void *arg, 342int kallsyms__parse(const char *filename, void *arg,
299 int (*process_symbol)(void *arg, const char *name, 343 int (*process_symbol)(void *arg, const char *name,
300 char type, u64 start, u64 end)); 344 char type, u64 start));
345int filename__read_debuglink(const char *filename, char *debuglink,
346 size_t size);
301 347
302void machine__destroy_kernel_maps(struct machine *machine); 348void machine__destroy_kernel_maps(struct machine *machine);
303int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); 349int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
@@ -309,6 +355,8 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
309 355
310int symbol__init(void); 356int symbol__init(void);
311void symbol__exit(void); 357void symbol__exit(void);
358void symbol__elf_init(void);
359struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
312size_t symbol__fprintf_symname_offs(const struct symbol *sym, 360size_t symbol__fprintf_symname_offs(const struct symbol *sym,
313 const struct addr_location *al, FILE *fp); 361 const struct addr_location *al, FILE *fp);
314size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 362size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
@@ -326,4 +374,15 @@ ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
326 struct machine *machine, u64 addr, 374 struct machine *machine, u64 addr,
327 u8 *data, ssize_t size); 375 u8 *data, ssize_t size);
328int dso__test_data(void); 376int dso__test_data(void);
377int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
378 struct symsrc *runtime_ss, symbol_filter_t filter,
379 int kmodule);
380int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
381 struct map *map, symbol_filter_t filter);
382
383void symbols__insert(struct rb_root *symbols, struct symbol *sym);
384void symbols__fixup_duplicate(struct rb_root *symbols);
385void symbols__fixup_end(struct rb_root *symbols);
386void __map_groups__fixup_end(struct map_groups *mg, enum map_type type);
387
329#endif /* __PERF_SYMBOL */ 388#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 051eaa68095e..065528b7563e 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -117,8 +117,8 @@ int perf_target__strerror(struct perf_target *target, int errnum,
117 117
118 if (err != buf) { 118 if (err != buf) {
119 size_t len = strlen(err); 119 size_t len = strlen(err);
120 char *c = mempcpy(buf, err, min(buflen - 1, len)); 120 memcpy(buf, err, min(buflen - 1, len));
121 *c = '\0'; 121 *(buf + min(buflen - 1, len)) = '\0';
122 } 122 }
123 123
124 return 0; 124 return 0;
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index fb4b7ea6752f..8b3e5939afb6 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm)
39 err = self->comm == NULL ? -ENOMEM : 0; 39 err = self->comm == NULL ? -ENOMEM : 0;
40 if (!err) { 40 if (!err) {
41 self->comm_set = true; 41 self->comm_set = true;
42 map_groups__flush(&self->mg);
43 } 42 }
44 return err; 43 return err;
45} 44}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 70c2c13ff679..f66610b7bacf 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -16,6 +16,8 @@ struct thread {
16 bool comm_set; 16 bool comm_set;
17 char *comm; 17 char *comm;
18 int comm_len; 18 int comm_len;
19
20 void *priv;
19}; 21};
20 22
21struct machine; 23struct machine;
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 7eeebcee291c..884dde9b9bc1 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -58,8 +58,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
58 } 58 }
59 59
60 if (top->evlist->nr_entries == 1) { 60 if (top->evlist->nr_entries == 1) {
61 struct perf_evsel *first; 61 struct perf_evsel *first = perf_evlist__first(top->evlist);
62 first = list_entry(top->evlist->entries.next, struct perf_evsel, node);
63 ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", 62 ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
64 (uint64_t)first->attr.sample_period, 63 (uint64_t)first->attr.sample_period,
65 top->freq ? "Hz" : ""); 64 top->freq ? "Hz" : "");
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 33347ca89ee4..86ff1b15059b 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -5,6 +5,7 @@
5#include "types.h" 5#include "types.h"
6#include <stddef.h> 6#include <stddef.h>
7#include <stdbool.h> 7#include <stdbool.h>
8#include <termios.h>
8 9
9struct perf_evlist; 10struct perf_evlist;
10struct perf_evsel; 11struct perf_evsel;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 0715c843c2e7..3aabcd687cd5 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -162,25 +162,16 @@ int trace_parse_common_pid(struct pevent *pevent, void *data)
162 return pevent_data_pid(pevent, &record); 162 return pevent_data_pid(pevent, &record);
163} 163}
164 164
165unsigned long long read_size(struct pevent *pevent, void *ptr, int size) 165unsigned long long read_size(struct event_format *event, void *ptr, int size)
166{ 166{
167 return pevent_read_number(pevent, ptr, size); 167 return pevent_read_number(event->pevent, ptr, size);
168} 168}
169 169
170void print_trace_event(struct pevent *pevent, int cpu, void *data, int size) 170void event_format__print(struct event_format *event,
171 int cpu, void *data, int size)
171{ 172{
172 struct event_format *event;
173 struct pevent_record record; 173 struct pevent_record record;
174 struct trace_seq s; 174 struct trace_seq s;
175 int type;
176
177 type = trace_parse_common_type(pevent, data);
178
179 event = pevent_find_event(pevent, type);
180 if (!event) {
181 warning("ug! no event found for type %d", type);
182 return;
183 }
184 175
185 memset(&record, 0, sizeof(record)); 176 memset(&record, 0, sizeof(record));
186 record.cpu = cpu; 177 record.cpu = cpu;
@@ -192,6 +183,19 @@ void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
192 trace_seq_do_printf(&s); 183 trace_seq_do_printf(&s);
193} 184}
194 185
186void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
187{
188 int type = trace_parse_common_type(pevent, data);
189 struct event_format *event = pevent_find_event(pevent, type);
190
191 if (!event) {
192 warning("ug! no event found for type %d", type);
193 return;
194 }
195
196 event_format__print(event, cpu, data, size);
197}
198
195void print_event(struct pevent *pevent, int cpu, void *data, int size, 199void print_event(struct pevent *pevent, int cpu, void *data, int size,
196 unsigned long long nsecs, char *comm) 200 unsigned long long nsecs, char *comm)
197{ 201{
@@ -217,7 +221,7 @@ void print_event(struct pevent *pevent, int cpu, void *data, int size,
217} 221}
218 222
219void parse_proc_kallsyms(struct pevent *pevent, 223void parse_proc_kallsyms(struct pevent *pevent,
220 char *file, unsigned int size __unused) 224 char *file, unsigned int size __maybe_unused)
221{ 225{
222 unsigned long long addr; 226 unsigned long long addr;
223 char *func; 227 char *func;
@@ -225,31 +229,29 @@ void parse_proc_kallsyms(struct pevent *pevent,
225 char *next = NULL; 229 char *next = NULL;
226 char *addr_str; 230 char *addr_str;
227 char *mod; 231 char *mod;
228 char ch; 232 char *fmt;
229 233
230 line = strtok_r(file, "\n", &next); 234 line = strtok_r(file, "\n", &next);
231 while (line) { 235 while (line) {
232 mod = NULL; 236 mod = NULL;
233 sscanf(line, "%as %c %as\t[%as", 237 addr_str = strtok_r(line, " ", &fmt);
234 (float *)(void *)&addr_str, /* workaround gcc warning */
235 &ch, (float *)(void *)&func, (float *)(void *)&mod);
236 addr = strtoull(addr_str, NULL, 16); 238 addr = strtoull(addr_str, NULL, 16);
237 free(addr_str); 239 /* skip character */
238 240 strtok_r(NULL, " ", &fmt);
239 /* truncate the extra ']' */ 241 func = strtok_r(NULL, "\t", &fmt);
242 mod = strtok_r(NULL, "]", &fmt);
243 /* truncate the extra '[' */
240 if (mod) 244 if (mod)
241 mod[strlen(mod) - 1] = 0; 245 mod = mod + 1;
242 246
243 pevent_register_function(pevent, func, addr, mod); 247 pevent_register_function(pevent, func, addr, mod);
244 free(func);
245 free(mod);
246 248
247 line = strtok_r(NULL, "\n", &next); 249 line = strtok_r(NULL, "\n", &next);
248 } 250 }
249} 251}
250 252
251void parse_ftrace_printk(struct pevent *pevent, 253void parse_ftrace_printk(struct pevent *pevent,
252 char *file, unsigned int size __unused) 254 char *file, unsigned int size __maybe_unused)
253{ 255{
254 unsigned long long addr; 256 unsigned long long addr;
255 char *printk; 257 char *printk;
@@ -289,7 +291,7 @@ struct event_format *trace_find_next_event(struct pevent *pevent,
289{ 291{
290 static int idx; 292 static int idx;
291 293
292 if (!pevent->events) 294 if (!pevent || !pevent->events)
293 return NULL; 295 return NULL;
294 296
295 if (!event) { 297 if (!event) {
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 474aa7a7df43..8715a1006d00 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -35,12 +35,11 @@ static int stop_script_unsupported(void)
35 return 0; 35 return 0;
36} 36}
37 37
38static void process_event_unsupported(union perf_event *event __unused, 38static void process_event_unsupported(union perf_event *event __maybe_unused,
39 struct pevent *pevent __unused, 39 struct perf_sample *sample __maybe_unused,
40 struct perf_sample *sample __unused, 40 struct perf_evsel *evsel __maybe_unused,
41 struct perf_evsel *evsel __unused, 41 struct machine *machine __maybe_unused,
42 struct machine *machine __unused, 42 struct addr_location *al __maybe_unused)
43 struct thread *thread __unused)
44{ 43{
45} 44}
46 45
@@ -53,17 +52,19 @@ static void print_python_unsupported_msg(void)
53 "\n etc.\n"); 52 "\n etc.\n");
54} 53}
55 54
56static int python_start_script_unsupported(const char *script __unused, 55static int python_start_script_unsupported(const char *script __maybe_unused,
57 int argc __unused, 56 int argc __maybe_unused,
58 const char **argv __unused) 57 const char **argv __maybe_unused)
59{ 58{
60 print_python_unsupported_msg(); 59 print_python_unsupported_msg();
61 60
62 return -1; 61 return -1;
63} 62}
64 63
65static int python_generate_script_unsupported(struct pevent *pevent __unused, 64static int python_generate_script_unsupported(struct pevent *pevent
66 const char *outfile __unused) 65 __maybe_unused,
66 const char *outfile
67 __maybe_unused)
67{ 68{
68 print_python_unsupported_msg(); 69 print_python_unsupported_msg();
69 70
@@ -115,17 +116,18 @@ static void print_perl_unsupported_msg(void)
115 "\n etc.\n"); 116 "\n etc.\n");
116} 117}
117 118
118static int perl_start_script_unsupported(const char *script __unused, 119static int perl_start_script_unsupported(const char *script __maybe_unused,
119 int argc __unused, 120 int argc __maybe_unused,
120 const char **argv __unused) 121 const char **argv __maybe_unused)
121{ 122{
122 print_perl_unsupported_msg(); 123 print_perl_unsupported_msg();
123 124
124 return -1; 125 return -1;
125} 126}
126 127
127static int perl_generate_script_unsupported(struct pevent *pevent __unused, 128static int perl_generate_script_unsupported(struct pevent *pevent
128 const char *outfile __unused) 129 __maybe_unused,
130 const char *outfile __maybe_unused)
129{ 131{
130 print_perl_unsupported_msg(); 132 print_perl_unsupported_msg();
131 133
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 8fef1d6687b7..a55fd37ffea1 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -9,7 +9,6 @@ struct machine;
9struct perf_sample; 9struct perf_sample;
10union perf_event; 10union perf_event;
11struct perf_tool; 11struct perf_tool;
12struct thread;
13 12
14extern int header_page_size_size; 13extern int header_page_size_size;
15extern int header_page_ts_size; 14extern int header_page_ts_size;
@@ -32,6 +31,8 @@ int bigendian(void);
32 31
33struct pevent *read_trace_init(int file_bigendian, int host_bigendian); 32struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
34void print_trace_event(struct pevent *pevent, int cpu, void *data, int size); 33void print_trace_event(struct pevent *pevent, int cpu, void *data, int size);
34void event_format__print(struct event_format *event,
35 int cpu, void *data, int size);
35 36
36void print_event(struct pevent *pevent, int cpu, void *data, int size, 37void print_event(struct pevent *pevent, int cpu, void *data, int size,
37 unsigned long long nsecs, char *comm); 38 unsigned long long nsecs, char *comm);
@@ -56,7 +57,7 @@ int trace_parse_common_pid(struct pevent *pevent, void *data);
56 57
57struct event_format *trace_find_next_event(struct pevent *pevent, 58struct event_format *trace_find_next_event(struct pevent *pevent,
58 struct event_format *event); 59 struct event_format *event);
59unsigned long long read_size(struct pevent *pevent, void *ptr, int size); 60unsigned long long read_size(struct event_format *event, void *ptr, int size);
60unsigned long long eval_flag(const char *flag); 61unsigned long long eval_flag(const char *flag);
61 62
62struct pevent_record *trace_read_data(struct pevent *pevent, int cpu); 63struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
@@ -74,16 +75,19 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
74void tracing_data_put(struct tracing_data *tdata); 75void tracing_data_put(struct tracing_data *tdata);
75 76
76 77
78struct addr_location;
79
80struct perf_session;
81
77struct scripting_ops { 82struct scripting_ops {
78 const char *name; 83 const char *name;
79 int (*start_script) (const char *script, int argc, const char **argv); 84 int (*start_script) (const char *script, int argc, const char **argv);
80 int (*stop_script) (void); 85 int (*stop_script) (void);
81 void (*process_event) (union perf_event *event, 86 void (*process_event) (union perf_event *event,
82 struct pevent *pevent,
83 struct perf_sample *sample, 87 struct perf_sample *sample,
84 struct perf_evsel *evsel, 88 struct perf_evsel *evsel,
85 struct machine *machine, 89 struct machine *machine,
86 struct thread *thread); 90 struct addr_location *al);
87 int (*generate_script) (struct pevent *pevent, const char *outfile); 91 int (*generate_script) (struct pevent *pevent, const char *outfile);
88}; 92};
89 93
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
new file mode 100644
index 000000000000..958723ba3d2e
--- /dev/null
+++ b/tools/perf/util/unwind.c
@@ -0,0 +1,571 @@
1/*
2 * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
3 *
4 * Lots of this code have been borrowed or heavily inspired from parts of
5 * the libunwind 0.99 code which are (amongst other contributors I may have
6 * forgotten):
7 *
8 * Copyright (C) 2002-2007 Hewlett-Packard Co
9 * Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
10 *
11 * And the bugs have been added by:
12 *
13 * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>
14 * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>
15 *
16 */
17
18#include <elf.h>
19#include <gelf.h>
20#include <fcntl.h>
21#include <string.h>
22#include <unistd.h>
23#include <sys/mman.h>
24#include <linux/list.h>
25#include <libunwind.h>
26#include <libunwind-ptrace.h>
27#include "thread.h"
28#include "session.h"
29#include "perf_regs.h"
30#include "unwind.h"
31#include "util.h"
32
33extern int
34UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
35 unw_word_t ip,
36 unw_dyn_info_t *di,
37 unw_proc_info_t *pi,
38 int need_unwind_info, void *arg);
39
40#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
41
42#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
43#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
44
45/* Pointer-encoding formats: */
46#define DW_EH_PE_omit 0xff
47#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
48#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
49#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
50#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
51#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
52
53/* Pointer-encoding application: */
54#define DW_EH_PE_absptr 0x00 /* absolute value */
55#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
56
57/*
58 * The following are not documented by LSB v1.3, yet they are used by
59 * GCC, presumably they aren't documented by LSB since they aren't
60 * used on Linux:
61 */
62#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
63#define DW_EH_PE_aligned 0x50 /* aligned pointer */
64
65/* Flags intentionaly not handled, since they're not needed:
66 * #define DW_EH_PE_indirect 0x80
67 * #define DW_EH_PE_uleb128 0x01
68 * #define DW_EH_PE_udata2 0x02
69 * #define DW_EH_PE_sleb128 0x09
70 * #define DW_EH_PE_sdata2 0x0a
71 * #define DW_EH_PE_textrel 0x20
72 * #define DW_EH_PE_datarel 0x30
73 */
74
75struct unwind_info {
76 struct perf_sample *sample;
77 struct machine *machine;
78 struct thread *thread;
79 u64 sample_uregs;
80};
81
82#define dw_read(ptr, type, end) ({ \
83 type *__p = (type *) ptr; \
84 type __v; \
85 if ((__p + 1) > (type *) end) \
86 return -EINVAL; \
87 __v = *__p++; \
88 ptr = (typeof(ptr)) __p; \
89 __v; \
90 })
91
92static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
93 u8 encoding)
94{
95 u8 *cur = *p;
96 *val = 0;
97
98 switch (encoding) {
99 case DW_EH_PE_omit:
100 *val = 0;
101 goto out;
102 case DW_EH_PE_ptr:
103 *val = dw_read(cur, unsigned long, end);
104 goto out;
105 default:
106 break;
107 }
108
109 switch (encoding & DW_EH_PE_APPL_MASK) {
110 case DW_EH_PE_absptr:
111 break;
112 case DW_EH_PE_pcrel:
113 *val = (unsigned long) cur;
114 break;
115 default:
116 return -EINVAL;
117 }
118
119 if ((encoding & 0x07) == 0x00)
120 encoding |= DW_EH_PE_udata4;
121
122 switch (encoding & DW_EH_PE_FORMAT_MASK) {
123 case DW_EH_PE_sdata4:
124 *val += dw_read(cur, s32, end);
125 break;
126 case DW_EH_PE_udata4:
127 *val += dw_read(cur, u32, end);
128 break;
129 case DW_EH_PE_sdata8:
130 *val += dw_read(cur, s64, end);
131 break;
132 case DW_EH_PE_udata8:
133 *val += dw_read(cur, u64, end);
134 break;
135 default:
136 return -EINVAL;
137 }
138
139 out:
140 *p = cur;
141 return 0;
142}
143
144#define dw_read_encoded_value(ptr, end, enc) ({ \
145 u64 __v; \
146 if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
147 return -EINVAL; \
148 } \
149 __v; \
150 })
151
152static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
153 GElf_Shdr *shp, const char *name)
154{
155 Elf_Scn *sec = NULL;
156
157 while ((sec = elf_nextscn(elf, sec)) != NULL) {
158 char *str;
159
160 gelf_getshdr(sec, shp);
161 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
162 if (!strcmp(name, str))
163 break;
164 }
165
166 return sec;
167}
168
169static u64 elf_section_offset(int fd, const char *name)
170{
171 Elf *elf;
172 GElf_Ehdr ehdr;
173 GElf_Shdr shdr;
174 u64 offset = 0;
175
176 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
177 if (elf == NULL)
178 return 0;
179
180 do {
181 if (gelf_getehdr(elf, &ehdr) == NULL)
182 break;
183
184 if (!elf_section_by_name(elf, &ehdr, &shdr, name))
185 break;
186
187 offset = shdr.sh_offset;
188 } while (0);
189
190 elf_end(elf);
191 return offset;
192}
193
194struct table_entry {
195 u32 start_ip_offset;
196 u32 fde_offset;
197};
198
199struct eh_frame_hdr {
200 unsigned char version;
201 unsigned char eh_frame_ptr_enc;
202 unsigned char fde_count_enc;
203 unsigned char table_enc;
204
205 /*
206 * The rest of the header is variable-length and consists of the
207 * following members:
208 *
209 * encoded_t eh_frame_ptr;
210 * encoded_t fde_count;
211 */
212
213 /* A single encoded pointer should not be more than 8 bytes. */
214 u64 enc[2];
215
216 /*
217 * struct {
218 * encoded_t start_ip;
219 * encoded_t fde_addr;
220 * } binary_search_table[fde_count];
221 */
222 char data[0];
223} __packed;
224
225static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
226 u64 offset, u64 *table_data, u64 *segbase,
227 u64 *fde_count)
228{
229 struct eh_frame_hdr hdr;
230 u8 *enc = (u8 *) &hdr.enc;
231 u8 *end = (u8 *) &hdr.data;
232 ssize_t r;
233
234 r = dso__data_read_offset(dso, machine, offset,
235 (u8 *) &hdr, sizeof(hdr));
236 if (r != sizeof(hdr))
237 return -EINVAL;
238
239 /* We dont need eh_frame_ptr, just skip it. */
240 dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
241
242 *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
243 *segbase = offset;
244 *table_data = (enc - (u8 *) &hdr) + offset;
245 return 0;
246}
247
248static int read_unwind_spec(struct dso *dso, struct machine *machine,
249 u64 *table_data, u64 *segbase, u64 *fde_count)
250{
251 int ret = -EINVAL, fd;
252 u64 offset;
253
254 fd = dso__data_fd(dso, machine);
255 if (fd < 0)
256 return -EINVAL;
257
258 offset = elf_section_offset(fd, ".eh_frame_hdr");
259 close(fd);
260
261 if (offset)
262 ret = unwind_spec_ehframe(dso, machine, offset,
263 table_data, segbase,
264 fde_count);
265
266 /* TODO .debug_frame check if eh_frame_hdr fails */
267 return ret;
268}
269
270static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
271{
272 struct addr_location al;
273
274 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
275 MAP__FUNCTION, ip, &al);
276 return al.map;
277}
278
279static int
280find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
281 int need_unwind_info, void *arg)
282{
283 struct unwind_info *ui = arg;
284 struct map *map;
285 unw_dyn_info_t di;
286 u64 table_data, segbase, fde_count;
287
288 map = find_map(ip, ui);
289 if (!map || !map->dso)
290 return -EINVAL;
291
292 pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
293
294 if (read_unwind_spec(map->dso, ui->machine,
295 &table_data, &segbase, &fde_count))
296 return -EINVAL;
297
298 memset(&di, 0, sizeof(di));
299 di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
300 di.start_ip = map->start;
301 di.end_ip = map->end;
302 di.u.rti.segbase = map->start + segbase;
303 di.u.rti.table_data = map->start + table_data;
304 di.u.rti.table_len = fde_count * sizeof(struct table_entry)
305 / sizeof(unw_word_t);
306 return dwarf_search_unwind_table(as, ip, &di, pi,
307 need_unwind_info, arg);
308}
309
310static int access_fpreg(unw_addr_space_t __maybe_unused as,
311 unw_regnum_t __maybe_unused num,
312 unw_fpreg_t __maybe_unused *val,
313 int __maybe_unused __write,
314 void __maybe_unused *arg)
315{
316 pr_err("unwind: access_fpreg unsupported\n");
317 return -UNW_EINVAL;
318}
319
320static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
321 unw_word_t __maybe_unused *dil_addr,
322 void __maybe_unused *arg)
323{
324 return -UNW_ENOINFO;
325}
326
327static int resume(unw_addr_space_t __maybe_unused as,
328 unw_cursor_t __maybe_unused *cu,
329 void __maybe_unused *arg)
330{
331 pr_err("unwind: resume unsupported\n");
332 return -UNW_EINVAL;
333}
334
335static int
336get_proc_name(unw_addr_space_t __maybe_unused as,
337 unw_word_t __maybe_unused addr,
338 char __maybe_unused *bufp, size_t __maybe_unused buf_len,
339 unw_word_t __maybe_unused *offp, void __maybe_unused *arg)
340{
341 pr_err("unwind: get_proc_name unsupported\n");
342 return -UNW_EINVAL;
343}
344
345static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
346 unw_word_t *data)
347{
348 struct addr_location al;
349 ssize_t size;
350
351 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
352 MAP__FUNCTION, addr, &al);
353 if (!al.map) {
354 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
355 return -1;
356 }
357
358 if (!al.map->dso)
359 return -1;
360
361 size = dso__data_read_addr(al.map->dso, al.map, ui->machine,
362 addr, (u8 *) data, sizeof(*data));
363
364 return !(size == sizeof(*data));
365}
366
367static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id,
368 u64 sample_regs)
369{
370 int i, idx = 0;
371
372 if (!(sample_regs & (1 << id)))
373 return -EINVAL;
374
375 for (i = 0; i < id; i++) {
376 if (sample_regs & (1 << i))
377 idx++;
378 }
379
380 *valp = regs->regs[idx];
381 return 0;
382}
383
384static int access_mem(unw_addr_space_t __maybe_unused as,
385 unw_word_t addr, unw_word_t *valp,
386 int __write, void *arg)
387{
388 struct unwind_info *ui = arg;
389 struct stack_dump *stack = &ui->sample->user_stack;
390 unw_word_t start, end;
391 int offset;
392 int ret;
393
394 /* Don't support write, probably not needed. */
395 if (__write || !stack || !ui->sample->user_regs.regs) {
396 *valp = 0;
397 return 0;
398 }
399
400 ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP,
401 ui->sample_uregs);
402 if (ret)
403 return ret;
404
405 end = start + stack->size;
406
407 /* Check overflow. */
408 if (addr + sizeof(unw_word_t) < addr)
409 return -EINVAL;
410
411 if (addr < start || addr + sizeof(unw_word_t) >= end) {
412 ret = access_dso_mem(ui, addr, valp);
413 if (ret) {
414 pr_debug("unwind: access_mem %p not inside range %p-%p\n",
415 (void *)addr, (void *)start, (void *)end);
416 *valp = 0;
417 return ret;
418 }
419 return 0;
420 }
421
422 offset = addr - start;
423 *valp = *(unw_word_t *)&stack->data[offset];
424 pr_debug("unwind: access_mem addr %p, val %lx, offset %d\n",
425 (void *)addr, (unsigned long)*valp, offset);
426 return 0;
427}
428
429static int access_reg(unw_addr_space_t __maybe_unused as,
430 unw_regnum_t regnum, unw_word_t *valp,
431 int __write, void *arg)
432{
433 struct unwind_info *ui = arg;
434 int id, ret;
435
436 /* Don't support write, I suspect we don't need it. */
437 if (__write) {
438 pr_err("unwind: access_reg w %d\n", regnum);
439 return 0;
440 }
441
442 if (!ui->sample->user_regs.regs) {
443 *valp = 0;
444 return 0;
445 }
446
447 id = unwind__arch_reg_id(regnum);
448 if (id < 0)
449 return -EINVAL;
450
451 ret = reg_value(valp, &ui->sample->user_regs, id, ui->sample_uregs);
452 if (ret) {
453 pr_err("unwind: can't read reg %d\n", regnum);
454 return ret;
455 }
456
457 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
458 return 0;
459}
460
461static void put_unwind_info(unw_addr_space_t __maybe_unused as,
462 unw_proc_info_t *pi __maybe_unused,
463 void *arg __maybe_unused)
464{
465 pr_debug("unwind: put_unwind_info called\n");
466}
467
468static int entry(u64 ip, struct thread *thread, struct machine *machine,
469 unwind_entry_cb_t cb, void *arg)
470{
471 struct unwind_entry e;
472 struct addr_location al;
473
474 thread__find_addr_location(thread, machine,
475 PERF_RECORD_MISC_USER,
476 MAP__FUNCTION, ip, &al, NULL);
477
478 e.ip = ip;
479 e.map = al.map;
480 e.sym = al.sym;
481
482 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
483 al.sym ? al.sym->name : "''",
484 ip,
485 al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
486
487 return cb(&e, arg);
488}
489
490static void display_error(int err)
491{
492 switch (err) {
493 case UNW_EINVAL:
494 pr_err("unwind: Only supports local.\n");
495 break;
496 case UNW_EUNSPEC:
497 pr_err("unwind: Unspecified error.\n");
498 break;
499 case UNW_EBADREG:
500 pr_err("unwind: Register unavailable.\n");
501 break;
502 default:
503 break;
504 }
505}
506
507static unw_accessors_t accessors = {
508 .find_proc_info = find_proc_info,
509 .put_unwind_info = put_unwind_info,
510 .get_dyn_info_list_addr = get_dyn_info_list_addr,
511 .access_mem = access_mem,
512 .access_reg = access_reg,
513 .access_fpreg = access_fpreg,
514 .resume = resume,
515 .get_proc_name = get_proc_name,
516};
517
518static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
519 void *arg)
520{
521 unw_addr_space_t addr_space;
522 unw_cursor_t c;
523 int ret;
524
525 addr_space = unw_create_addr_space(&accessors, 0);
526 if (!addr_space) {
527 pr_err("unwind: Can't create unwind address space.\n");
528 return -ENOMEM;
529 }
530
531 ret = unw_init_remote(&c, addr_space, ui);
532 if (ret)
533 display_error(ret);
534
535 while (!ret && (unw_step(&c) > 0)) {
536 unw_word_t ip;
537
538 unw_get_reg(&c, UNW_REG_IP, &ip);
539 ret = entry(ip, ui->thread, ui->machine, cb, arg);
540 }
541
542 unw_destroy_addr_space(addr_space);
543 return ret;
544}
545
546int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
547 struct machine *machine, struct thread *thread,
548 u64 sample_uregs, struct perf_sample *data)
549{
550 unw_word_t ip;
551 struct unwind_info ui = {
552 .sample = data,
553 .sample_uregs = sample_uregs,
554 .thread = thread,
555 .machine = machine,
556 };
557 int ret;
558
559 if (!data->user_regs.regs)
560 return -EINVAL;
561
562 ret = reg_value(&ip, &data->user_regs, PERF_REG_IP, sample_uregs);
563 if (ret)
564 return ret;
565
566 ret = entry(ip, thread, machine, cb, arg);
567 if (ret)
568 return -ENOMEM;
569
570 return get_entries(&ui, cb, arg);
571}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
new file mode 100644
index 000000000000..cb6bc503a792
--- /dev/null
+++ b/tools/perf/util/unwind.h
@@ -0,0 +1,35 @@
1#ifndef __UNWIND_H
2#define __UNWIND_H
3
4#include "types.h"
5#include "event.h"
6#include "symbol.h"
7
8struct unwind_entry {
9 struct map *map;
10 struct symbol *sym;
11 u64 ip;
12};
13
14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
15
16#ifdef LIBUNWIND_SUPPORT
17int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
18 struct machine *machine,
19 struct thread *thread,
20 u64 sample_uregs,
21 struct perf_sample *data);
22int unwind__arch_reg_id(int regnum);
23#else
24static inline int
25unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
26 void *arg __maybe_unused,
27 struct machine *machine __maybe_unused,
28 struct thread *thread __maybe_unused,
29 u64 sample_uregs __maybe_unused,
30 struct perf_sample *data __maybe_unused)
31{
32 return 0;
33}
34#endif /* LIBUNWIND_SUPPORT */
35#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index d03599fbe78b..99664598bc1a 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,6 +1,11 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include <sys/mman.h> 3#include <sys/mman.h>
4#ifdef BACKTRACE_SUPPORT
5#include <execinfo.h>
6#endif
7#include <stdio.h>
8#include <stdlib.h>
4 9
5/* 10/*
6 * XXX We need to find a better place for these things... 11 * XXX We need to find a better place for these things...
@@ -158,3 +163,23 @@ size_t hex_width(u64 v)
158 163
159 return n; 164 return n;
160} 165}
166
167/* Obtain a backtrace and print it to stdout. */
168#ifdef BACKTRACE_SUPPORT
169void dump_stack(void)
170{
171 void *array[16];
172 size_t size = backtrace(array, ARRAY_SIZE(array));
173 char **strings = backtrace_symbols(array, size);
174 size_t i;
175
176 printf("Obtained %zd stack frames.\n", size);
177
178 for (i = 0; i < size; i++)
179 printf("%s\n", strings[i]);
180
181 free(strings);
182}
183#else
184void dump_stack(void) {}
185#endif
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b13c7331eaf8..70fa70b535b2 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -69,13 +69,8 @@
69#include <sys/poll.h> 69#include <sys/poll.h>
70#include <sys/socket.h> 70#include <sys/socket.h>
71#include <sys/ioctl.h> 71#include <sys/ioctl.h>
72#include <sys/select.h>
73#include <netinet/in.h>
74#include <netinet/tcp.h>
75#include <arpa/inet.h>
76#include <netdb.h>
77#include <inttypes.h> 72#include <inttypes.h>
78#include "../../../include/linux/magic.h" 73#include <linux/magic.h>
79#include "types.h" 74#include "types.h"
80#include <sys/ttydefaults.h> 75#include <sys/ttydefaults.h>
81 76
@@ -266,4 +261,6 @@ size_t hex_width(u64 v);
266 261
267char *rtrim(char *s); 262char *rtrim(char *s);
268 263
264void dump_stack(void);
265
269#endif 266#endif
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
new file mode 100644
index 000000000000..e60951fcdb12
--- /dev/null
+++ b/tools/perf/util/vdso.c
@@ -0,0 +1,111 @@
1
2#include <unistd.h>
3#include <stdio.h>
4#include <string.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <stdlib.h>
9#include <linux/kernel.h>
10
11#include "vdso.h"
12#include "util.h"
13#include "symbol.h"
14#include "linux/string.h"
15
16static bool vdso_found;
17static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";
18
19static int find_vdso_map(void **start, void **end)
20{
21 FILE *maps;
22 char line[128];
23 int found = 0;
24
25 maps = fopen("/proc/self/maps", "r");
26 if (!maps) {
27 pr_err("vdso: cannot open maps\n");
28 return -1;
29 }
30
31 while (!found && fgets(line, sizeof(line), maps)) {
32 int m = -1;
33
34 /* We care only about private r-x mappings. */
35 if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
36 start, end, &m))
37 continue;
38 if (m < 0)
39 continue;
40
41 if (!strncmp(&line[m], VDSO__MAP_NAME,
42 sizeof(VDSO__MAP_NAME) - 1))
43 found = 1;
44 }
45
46 fclose(maps);
47 return !found;
48}
49
50static char *get_file(void)
51{
52 char *vdso = NULL;
53 char *buf = NULL;
54 void *start, *end;
55 size_t size;
56 int fd;
57
58 if (vdso_found)
59 return vdso_file;
60
61 if (find_vdso_map(&start, &end))
62 return NULL;
63
64 size = end - start;
65
66 buf = memdup(start, size);
67 if (!buf)
68 return NULL;
69
70 fd = mkstemp(vdso_file);
71 if (fd < 0)
72 goto out;
73
74 if (size == (size_t) write(fd, buf, size))
75 vdso = vdso_file;
76
77 close(fd);
78
79 out:
80 free(buf);
81
82 vdso_found = (vdso != NULL);
83 return vdso;
84}
85
86void vdso__exit(void)
87{
88 if (vdso_found)
89 unlink(vdso_file);
90}
91
92struct dso *vdso__dso_findnew(struct list_head *head)
93{
94 struct dso *dso = dsos__find(head, VDSO__MAP_NAME);
95
96 if (!dso) {
97 char *file;
98
99 file = get_file();
100 if (!file)
101 return NULL;
102
103 dso = dso__new(VDSO__MAP_NAME);
104 if (dso != NULL) {
105 dsos__add(head, dso);
106 dso__set_long_name(dso, file);
107 }
108 }
109
110 return dso;
111}
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h
new file mode 100644
index 000000000000..0f76e7caf6f8
--- /dev/null
+++ b/tools/perf/util/vdso.h
@@ -0,0 +1,18 @@
1#ifndef __PERF_VDSO__
2#define __PERF_VDSO__
3
4#include <linux/types.h>
5#include <string.h>
6#include <stdbool.h>
7
8#define VDSO__MAP_NAME "[vdso]"
9
10static inline bool is_vdso_map(const char *filename)
11{
12 return !strcmp(filename, VDSO__MAP_NAME);
13}
14
15struct dso *vdso__dso_findnew(struct list_head *head);
16void vdso__exit(void);
17
18#endif /* __PERF_VDSO__ */
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
index 73e900edb5a2..19f15b650703 100644
--- a/tools/perf/util/wrapper.c
+++ b/tools/perf/util/wrapper.c
@@ -7,7 +7,8 @@
7 * There's no pack memory to release - but stay close to the Git 7 * There's no pack memory to release - but stay close to the Git
8 * version so wrap this away: 8 * version so wrap this away:
9 */ 9 */
10static inline void release_pack_memory(size_t size __used, int flag __used) 10static inline void release_pack_memory(size_t size __maybe_unused,
11 int flag __maybe_unused)
11{ 12{
12} 13}
13 14