aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 13:28:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 13:28:49 -0400
commit7e92daaefa68e5ef1e1732e45231e73adbb724e7 (patch)
tree8e7f8ac9d82654df4c65939c6682f95510e22977 /tools/perf/util
parent7a68294278ae714ce2632a54f0f46916dca64f56 (diff)
parent1d787d37c8ff6612b8151c6dff15bfa7347bcbdf (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf update from Ingo Molnar: "Lots of changes in this cycle as well, with hundreds of commits from over 30 contributors. Most of the activity was on the tooling side. Higher level changes: - New 'perf kvm' analysis tool, from Xiao Guangrong. - New 'perf trace' system-wide tracing tool - uprobes fixes + cleanups from Oleg Nesterov. - Lots of patches to make perf build on Android out of box, from Irina Tirdea - Extend ftrace function tracing utility to be more dynamic for its users. It allows for data passing to the callback functions, as well as reading regs as if a breakpoint were to trigger at function entry. The main goal of this patch series was to allow kprobes to use ftrace as an optimized probe point when a probe is placed on an ftrace nop. With lots of help from Masami Hiramatsu, and going through lots of iterations, we finally came up with a good solution. - Add cpumask for uncore pmu, use it in 'stat', from Yan, Zheng. - Various tracing updates from Steve Rostedt - Clean up and improve 'perf sched' performance by elliminating lots of needless calls to libtraceevent. - Event group parsing support, from Jiri Olsa - UI/gtk refactorings and improvements from Namhyung Kim - Add support for non-tracepoint events in perf script python, from Feng Tang - Add --symbols to 'script', similar to the one in 'report', from Feng Tang. Infrastructure enhancements and fixes: - Convert the trace builtins to use the growing evsel/evlist tracepoint infrastructure, removing several open coded constructs like switch like series of strcmp to dispatch events, etc. Basically what had already been showcased in 'perf sched'. - Add evsel constructor for tracepoints, that uses libtraceevent just to parse the /format events file, use it in a new 'perf test' to make sure the libtraceevent format parsing regressions can be more readily caught. - Some strange errors were happening in some builds, but not on the next, reported by several people, problem was some parser related files, generated during the build, didn't had proper make deps, fix from Eric Sandeen. - Introduce struct and cache information about the environment where a perf.data file was captured, from Namhyung Kim. - Fix handling of unresolved samples when --symbols is used in 'report', from Feng Tang. - Add union member access support to 'probe', from Hyeoncheol Lee. - Fixups to die() removal, from Namhyung Kim. - Render fixes for the TUI, from Namhyung Kim. - Don't enable annotation in non symbolic view, from Namhyung Kim. - Fix pipe mode in 'report', from Namhyung Kim. - Move related stats code from stat to util/, will be used by the 'stat' kvm tool, from Xiao Guangrong. - Remove die()/exit() calls from several tools. - Resolve vdso callchains, from Jiri Olsa - Don't pass const char pointers to basename, so that we can unconditionally use libgen.h and thus avoid ifdef BIONIC lines, from David Ahern - Refactor hist formatting so that it can be reused with the GTK browser, From Namhyung Kim - Fix build for another rbtree.c change, from Adrian Hunter. - Make 'perf diff' command work with evsel hists, from Jiri Olsa. - Use the only field_sep var that is set up: symbol_conf.field_sep, fix from Jiri Olsa. - .gitignore compiled python binaries, from Namhyung Kim. - Get rid of die() in more libtraceevent places, from Namhyung Kim. - Rename libtraceevent 'private' struct member to 'priv' so that it works in C++, from Steven Rostedt - Remove lots of exit()/die() calls from tools so that the main perf exit routine can take place, from David Ahern - Fix x86 build on x86-64, from David Ahern. - {int,str,rb}list fixes from Suzuki K Poulose - perf.data header fixes from Namhyung Kim - Allow user to indicate objdump path, needed in cross environments, from Maciek Borzecki - Fix hardware cache event name generation, fix from Jiri Olsa - Add round trip test for sw, hw and cache event names, catching the problem Jiri fixed, after Jiri's patch, the test passes successfully. - Clean target should do clean for lib/traceevent too, fix from David Ahern - Check the right variable for allocation failure, fix from Namhyung Kim - Set up evsel->tp_format regardless of evsel->name being set already, fix from Namhyung Kim - Oprofile fixes from Robert Richter. - Remove perf_event_attr needless version inflation, from Jiri Olsa - Introduce libtraceevent strerror like error reporting facility, from Namhyung Kim - Add pmu mappings to perf.data header and use event names from cmd line, from Robert Richter - Fix include order for bison/flex-generated C files, from Ben Hutchings - Build fixes and documentation corrections from David Ahern - Assorted cleanups from Robert Richter - Let O= makes handle relative paths, from Steven Rostedt - perf script python fixes, from Feng Tang. - Initial bash completion support, from Frederic Weisbecker - Allow building without libelf, from Namhyung Kim. - Support DWARF CFI based unwind to have callchains when %bp based unwinding is not possible, from Jiri Olsa. - Symbol resolution fixes, while fixing support PPC64 files with an .opt ELF section was the end goal, several fixes for code that handles all architectures and cleanups are included, from Cody Schafer. - Assorted fixes for Documentation and build in 32 bit, from Robert Richter - Cache the libtraceevent event_format associated to each evsel early, so that we avoid relookups, i.e. calling pevent_find_event repeatedly when processing tracepoint events. [ This is to reduce the surface contact with libtraceevents and make clear what is that the perf tools needs from that lib: so far parsing the common and per event fields. ] - Don't stop the build if the audit libraries are not installed, fix from Namhyung Kim. - Fix bfd.h/libbfd detection with recent binutils, from Markus Trippelsdorf. - Improve warning message when libunwind devel packages not present, from Jiri Olsa" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (282 commits) perf trace: Add aliases for some syscalls perf probe: Print an enum type variable in "enum variable-name" format when showing accessible variables perf tools: Check libaudit availability for perf-trace builtin perf hists: Add missing period_* fields when collapsing a hist entry perf trace: New tool perf evsel: Export the event_format constructor perf evsel: Introduce rawptr() method perf tools: Use perf_evsel__newtp in the event parser perf evsel: The tracepoint constructor should store sys:name perf evlist: Introduce set_filter() method perf evlist: Renane set_filters method to apply_filters perf test: Add test to check we correctly parse and match syscall open parms perf evsel: Handle endianity in intval method perf evsel: Know if byte swap is needed perf tools: Allow handling a NULL cpu_map as meaning "all cpus" perf evsel: Improve tracepoint constructor setup tools lib traceevent: Fix error path on pevent_parse_event perf test: Fix build failure trace: Move trace event enable from fs_initcall to core_initcall tracing: Add an option for disabling markers ...
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.h15
-rw-r--r--tools/perf/util/build-id.c11
-rw-r--r--tools/perf/util/cache.h6
-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.c4
-rw-r--r--tools/perf/util/debug.h17
-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.c143
-rw-r--r--tools/perf/util/evlist.h35
-rw-r--r--tools/perf/util/evsel.c276
-rw-r--r--tools/perf/util/evsel.h63
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh15
-rw-r--r--tools/perf/util/header.c1063
-rw-r--r--tools/perf/util/header.h29
-rw-r--r--tools/perf/util/help.c4
-rw-r--r--tools/perf/util/hist.c721
-rw-r--r--tools/perf/util/hist.h75
-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/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/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.c424
-rw-r--r--tools/perf/util/parse-events.c254
-rw-r--r--tools/perf/util/parse-events.h18
-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.c3
-rw-r--r--tools/perf/util/perf_regs.h14
-rw-r--r--tools/perf/util/pmu.c80
-rw-r--r--tools/perf/util/pmu.h3
-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.h10
-rw-r--r--tools/perf/util/sort.c25
-rw-r--r--tools/perf/util/sort.h2
-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.h67
-rw-r--r--tools/perf/util/target.c4
-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
77 files changed, 4892 insertions, 2491 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..9b5b21e7b032 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);
@@ -138,11 +139,12 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
138 int max_lines); 139 int max_lines);
139 140
140#ifdef NO_NEWT_SUPPORT 141#ifdef NO_NEWT_SUPPORT
141static inline int symbol__tui_annotate(struct symbol *sym __used, 142static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
142 struct map *map __used, 143 struct map *map __maybe_unused,
143 int evidx __used, 144 int evidx __maybe_unused,
144 void(*timer)(void *arg) __used, 145 void(*timer)(void *arg) __maybe_unused,
145 void *arg __used, int delay_secs __used) 146 void *arg __maybe_unused,
147 int delay_secs __maybe_unused)
146{ 148{
147 return 0; 149 return 0;
148} 150}
@@ -152,5 +154,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
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..ab1769426541 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -39,7 +39,7 @@ static inline void setup_browser(bool fallback_to_pager)
39 if (fallback_to_pager) 39 if (fallback_to_pager)
40 setup_pager(); 40 setup_pager();
41} 41}
42static inline void exit_browser(bool wait_for_ok __used) {} 42static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
43#else 43#else
44void setup_browser(bool fallback_to_pager); 44void setup_browser(bool fallback_to_pager);
45void exit_browser(bool wait_for_ok); 45void exit_browser(bool wait_for_ok);
@@ -49,7 +49,7 @@ static inline int ui__init(void)
49{ 49{
50 return -1; 50 return -1;
51} 51}
52static inline void ui__exit(bool wait_for_ok __used) {} 52static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
53#else 53#else
54int ui__init(void); 54int ui__init(void);
55void ui__exit(bool wait_for_ok); 55void ui__exit(bool wait_for_ok);
@@ -60,7 +60,7 @@ static inline int perf_gtk__init(void)
60{ 60{
61 return -1; 61 return -1;
62} 62}
63static inline void perf_gtk__exit(bool wait_for_ok __used) {} 63static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
64#else 64#else
65int perf_gtk__init(void); 65int perf_gtk__init(void);
66void perf_gtk__exit(bool wait_for_ok); 66void perf_gtk__exit(bool wait_for_ok);
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..66eb3828ceb5 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);
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 015c91dbc096..bb2e7d1007ab 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;
@@ -15,32 +16,26 @@ struct 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(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
18static inline int ui_helpline__show_help(const char *format __used, va_list ap __used) 19static inline void ui_progress__update(u64 curr __maybe_unused,
19{ 20 u64 total __maybe_unused,
20 return 0; 21 const char *title __maybe_unused) {}
21}
22
23static inline void ui_progress__update(u64 curr __used, u64 total __used,
24 const char *title __used) {}
25 22
26#define ui__error(format, arg...) ui__warning(format, ##arg) 23#define ui__error(format, arg...) ui__warning(format, ##arg)
27 24
28static inline int 25static inline int
29perf_error__register(struct perf_error_ops *eops __used) 26perf_error__register(struct perf_error_ops *eops __maybe_unused)
30{ 27{
31 return 0; 28 return 0;
32} 29}
33 30
34static inline int 31static inline int
35perf_error__unregister(struct perf_error_ops *eops __used) 32perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
36{ 33{
37 return 0; 34 return 0;
38} 35}
39 36
40#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ 37#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
41 38
42extern char ui_helpline__last_msg[];
43int ui_helpline__show_help(const char *format, va_list ap);
44#include "../ui/progress.h" 39#include "../ui/progress.h"
45int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 40int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
46#include "../ui/util.h" 41#include "../ui/util.h"
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..ae89686102f4 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 = {
@@ -285,7 +304,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
285 int cpu, thread; 304 int cpu, thread;
286 struct perf_evsel *pos; 305 struct perf_evsel *pos;
287 306
288 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 307 for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
289 list_for_each_entry(pos, &evlist->entries, node) { 308 list_for_each_entry(pos, &evlist->entries, node) {
290 for (thread = 0; thread < evlist->threads->nr; thread++) 309 for (thread = 0; thread < evlist->threads->nr; thread++)
291 ioctl(FD(pos, cpu, thread), 310 ioctl(FD(pos, cpu, thread),
@@ -296,7 +315,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
296 315
297static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 316static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
298{ 317{
299 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; 318 int nfds = cpu_map__nr(evlist->cpus) * evlist->threads->nr * evlist->nr_entries;
300 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 319 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
301 return evlist->pollfd != NULL ? 0 : -ENOMEM; 320 return evlist->pollfd != NULL ? 0 : -ENOMEM;
302} 321}
@@ -357,7 +376,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
357 int hash; 376 int hash;
358 377
359 if (evlist->nr_entries == 1) 378 if (evlist->nr_entries == 1)
360 return list_entry(evlist->entries.next, struct perf_evsel, node); 379 return perf_evlist__first(evlist);
361 380
362 hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 381 hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
363 head = &evlist->heads[hash]; 382 head = &evlist->heads[hash];
@@ -367,7 +386,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
367 return sid->evsel; 386 return sid->evsel;
368 387
369 if (!perf_evlist__sample_id_all(evlist)) 388 if (!perf_evlist__sample_id_all(evlist))
370 return list_entry(evlist->entries.next, struct perf_evsel, node); 389 return perf_evlist__first(evlist);
371 390
372 return NULL; 391 return NULL;
373} 392}
@@ -456,8 +475,8 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
456 475
457static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 476static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
458{ 477{
459 evlist->nr_mmaps = evlist->cpus->nr; 478 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
460 if (evlist->cpus->map[0] == -1) 479 if (cpu_map__all(evlist->cpus))
461 evlist->nr_mmaps = evlist->threads->nr; 480 evlist->nr_mmaps = evlist->threads->nr;
462 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 481 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
463 return evlist->mmap != NULL ? 0 : -ENOMEM; 482 return evlist->mmap != NULL ? 0 : -ENOMEM;
@@ -603,11 +622,11 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
603 list_for_each_entry(evsel, &evlist->entries, node) { 622 list_for_each_entry(evsel, &evlist->entries, node) {
604 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 623 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
605 evsel->sample_id == NULL && 624 evsel->sample_id == NULL &&
606 perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0) 625 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
607 return -ENOMEM; 626 return -ENOMEM;
608 } 627 }
609 628
610 if (evlist->cpus->map[0] == -1) 629 if (cpu_map__all(cpus))
611 return perf_evlist__mmap_per_thread(evlist, prot, mask); 630 return perf_evlist__mmap_per_thread(evlist, prot, mask);
612 631
613 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 632 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
@@ -647,39 +666,44 @@ void perf_evlist__delete_maps(struct perf_evlist *evlist)
647 evlist->threads = NULL; 666 evlist->threads = NULL;
648} 667}
649 668
650int perf_evlist__set_filters(struct perf_evlist *evlist) 669int perf_evlist__apply_filters(struct perf_evlist *evlist)
651{ 670{
652 const struct thread_map *threads = evlist->threads;
653 const struct cpu_map *cpus = evlist->cpus;
654 struct perf_evsel *evsel; 671 struct perf_evsel *evsel;
655 char *filter; 672 int err = 0;
656 int thread; 673 const int ncpus = cpu_map__nr(evlist->cpus),
657 int cpu; 674 nthreads = evlist->threads->nr;
658 int err;
659 int fd;
660 675
661 list_for_each_entry(evsel, &evlist->entries, node) { 676 list_for_each_entry(evsel, &evlist->entries, node) {
662 filter = evsel->filter; 677 if (evsel->filter == NULL)
663 if (!filter)
664 continue; 678 continue;
665 for (cpu = 0; cpu < cpus->nr; cpu++) { 679
666 for (thread = 0; thread < threads->nr; thread++) { 680 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter);
667 fd = FD(evsel, cpu, thread); 681 if (err)
668 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter); 682 break;
669 if (err)
670 return err;
671 }
672 }
673 } 683 }
674 684
675 return 0; 685 return err;
676} 686}
677 687
678bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) 688int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
679{ 689{
680 struct perf_evsel *pos, *first; 690 struct perf_evsel *evsel;
691 int err = 0;
692 const int ncpus = cpu_map__nr(evlist->cpus),
693 nthreads = evlist->threads->nr;
694
695 list_for_each_entry(evsel, &evlist->entries, node) {
696 err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter);
697 if (err)
698 break;
699 }
700
701 return err;
702}
681 703
682 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); 704bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
705{
706 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
683 707
684 list_for_each_entry_continue(pos, &evlist->entries, node) { 708 list_for_each_entry_continue(pos, &evlist->entries, node) {
685 if (first->attr.sample_type != pos->attr.sample_type) 709 if (first->attr.sample_type != pos->attr.sample_type)
@@ -689,23 +713,19 @@ bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist)
689 return true; 713 return true;
690} 714}
691 715
692u64 perf_evlist__sample_type(const struct perf_evlist *evlist) 716u64 perf_evlist__sample_type(struct perf_evlist *evlist)
693{ 717{
694 struct perf_evsel *first; 718 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; 719 return first->attr.sample_type;
698} 720}
699 721
700u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist) 722u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
701{ 723{
702 struct perf_evsel *first; 724 struct perf_evsel *first = perf_evlist__first(evlist);
703 struct perf_sample *data; 725 struct perf_sample *data;
704 u64 sample_type; 726 u64 sample_type;
705 u16 size = 0; 727 u16 size = 0;
706 728
707 first = list_entry(evlist->entries.next, struct perf_evsel, node);
708
709 if (!first->attr.sample_id_all) 729 if (!first->attr.sample_id_all)
710 goto out; 730 goto out;
711 731
@@ -729,11 +749,9 @@ out:
729 return size; 749 return size;
730} 750}
731 751
732bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) 752bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
733{ 753{
734 struct perf_evsel *pos, *first; 754 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
735
736 pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
737 755
738 list_for_each_entry_continue(pos, &evlist->entries, node) { 756 list_for_each_entry_continue(pos, &evlist->entries, node) {
739 if (first->attr.sample_id_all != pos->attr.sample_id_all) 757 if (first->attr.sample_id_all != pos->attr.sample_id_all)
@@ -743,11 +761,9 @@ bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
743 return true; 761 return true;
744} 762}
745 763
746bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) 764bool perf_evlist__sample_id_all(struct perf_evlist *evlist)
747{ 765{
748 struct perf_evsel *first; 766 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; 767 return first->attr.sample_id_all;
752} 768}
753 769
@@ -757,21 +773,13 @@ void perf_evlist__set_selected(struct perf_evlist *evlist,
757 evlist->selected = evsel; 773 evlist->selected = evsel;
758} 774}
759 775
760int perf_evlist__open(struct perf_evlist *evlist, bool group) 776int perf_evlist__open(struct perf_evlist *evlist)
761{ 777{
762 struct perf_evsel *evsel, *first; 778 struct perf_evsel *evsel;
763 int err, ncpus, nthreads; 779 int err, ncpus, nthreads;
764 780
765 first = list_entry(evlist->entries.next, struct perf_evsel, node);
766
767 list_for_each_entry(evsel, &evlist->entries, node) { 781 list_for_each_entry(evsel, &evlist->entries, node) {
768 struct xyarray *group_fd = NULL; 782 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) 783 if (err < 0)
776 goto out_err; 784 goto out_err;
777 } 785 }
@@ -883,8 +891,21 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
883} 891}
884 892
885int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 893int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
886 struct perf_sample *sample, bool swapped) 894 struct perf_sample *sample)
895{
896 struct perf_evsel *evsel = perf_evlist__first(evlist);
897 return perf_evsel__parse_sample(evsel, event, sample);
898}
899
900size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
887{ 901{
888 struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node); 902 struct perf_evsel *evsel;
889 return perf_evsel__parse_sample(e, event, sample, swapped); 903 size_t printed = 0;
904
905 list_for_each_entry(evsel, &evlist->entries, node) {
906 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
907 perf_evsel__name(evsel));
908 }
909
910 return printed + fprintf(fp, "\n");;
890} 911}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 528c1acd9298..3f1fb66be022 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,
@@ -73,6 +72,8 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
73#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \ 72#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
74 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array)) 73 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
75 74
75int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
76
76struct perf_evsel * 77struct perf_evsel *
77perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); 78perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
78 79
@@ -85,7 +86,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
85 86
86union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); 87union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
87 88
88int perf_evlist__open(struct perf_evlist *evlist, bool group); 89int perf_evlist__open(struct perf_evlist *evlist);
89 90
90void perf_evlist__config_attrs(struct perf_evlist *evlist, 91void perf_evlist__config_attrs(struct perf_evlist *evlist,
91 struct perf_record_opts *opts); 92 struct perf_record_opts *opts);
@@ -116,20 +117,34 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
116int perf_evlist__create_maps(struct perf_evlist *evlist, 117int perf_evlist__create_maps(struct perf_evlist *evlist,
117 struct perf_target *target); 118 struct perf_target *target);
118void perf_evlist__delete_maps(struct perf_evlist *evlist); 119void perf_evlist__delete_maps(struct perf_evlist *evlist);
119int perf_evlist__set_filters(struct perf_evlist *evlist); 120int perf_evlist__apply_filters(struct perf_evlist *evlist);
121
122void __perf_evlist__set_leader(struct list_head *list);
123void perf_evlist__set_leader(struct perf_evlist *evlist);
120 124
121u64 perf_evlist__sample_type(const struct perf_evlist *evlist); 125u64 perf_evlist__sample_type(struct perf_evlist *evlist);
122bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); 126bool perf_evlist__sample_id_all(struct perf_evlist *evlist);
123u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); 127u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);
124 128
125int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, 129int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
126 struct perf_sample *sample, bool swapped); 130 struct perf_sample *sample);
127 131
128bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 132bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);
129bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 133bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
130 134
131void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 135void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
132 struct list_head *list, 136 struct list_head *list,
133 int nr_entries); 137 int nr_entries);
134 138
139static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
140{
141 return list_entry(evlist->entries.next, struct perf_evsel, node);
142}
143
144static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
145{
146 return list_entry(evlist->entries.prev, struct perf_evsel, node);
147}
148
149size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
135#endif /* __PERF_EVLIST_H */ 150#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2eaae140def2..ffdd94e9c9c3 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/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..3ead0d59c03d 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.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..389590c1ad21 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 "#ifndef NO_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 /* NO_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..99bdd3abce59 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.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..236bc9d98ff2 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,6 +114,22 @@ 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{
@@ -378,7 +394,7 @@ void hist_entry__free(struct hist_entry *he)
378 * collapse the histogram 394 * collapse the histogram
379 */ 395 */
380 396
381static bool hists__collapse_insert_entry(struct hists *hists __used, 397static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
382 struct rb_root *root, 398 struct rb_root *root,
383 struct hist_entry *he) 399 struct hist_entry *he)
384{ 400{
@@ -394,8 +410,13 @@ static bool hists__collapse_insert_entry(struct hists *hists __used,
394 cmp = hist_entry__collapse(iter, he); 410 cmp = hist_entry__collapse(iter, he);
395 411
396 if (!cmp) { 412 if (!cmp) {
397 iter->period += he->period; 413 iter->period += he->period;
398 iter->nr_events += he->nr_events; 414 iter->period_sys += he->period_sys;
415 iter->period_us += he->period_us;
416 iter->period_guest_sys += he->period_guest_sys;
417 iter->period_guest_us += he->period_guest_us;
418 iter->nr_events += he->nr_events;
419
399 if (symbol_conf.use_callchain) { 420 if (symbol_conf.use_callchain) {
400 callchain_cursor_reset(&callchain_cursor); 421 callchain_cursor_reset(&callchain_cursor);
401 callchain_merge(&callchain_cursor, 422 callchain_merge(&callchain_cursor,
@@ -547,674 +568,6 @@ void hists__output_resort_threaded(struct hists *hists)
547 return __hists__output_resort(hists, true); 568 return __hists__output_resort(hists, true);
548} 569}
549 570
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, 571static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
1219 enum hist_filter filter) 572 enum hist_filter filter)
1220{ 573{
@@ -1342,25 +695,3 @@ void hists__inc_nr_events(struct hists *hists, u32 type)
1342 ++hists->stats.nr_events[0]; 695 ++hists->stats.nr_events[0];
1343 ++hists->stats.nr_events[type]; 696 ++hists->stats.nr_events[type];
1344} 697}
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..f011ad4756e8 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,
@@ -112,25 +112,66 @@ void hists__filter_by_symbol(struct hists *hists);
112u16 hists__col_len(struct hists *self, enum hist_column col); 112u16 hists__col_len(struct hists *self, enum hist_column col);
113void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); 113void 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); 114bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
115void hists__reset_col_len(struct hists *hists);
116void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
117
118struct perf_hpp {
119 char *buf;
120 size_t size;
121 u64 total_period;
122 const char *sep;
123 long displacement;
124 void *ptr;
125};
126
127struct perf_hpp_fmt {
128 bool cond;
129 int (*header)(struct perf_hpp *hpp);
130 int (*width)(struct perf_hpp *hpp);
131 int (*color)(struct perf_hpp *hpp, struct hist_entry *he);
132 int (*entry)(struct perf_hpp *hpp, struct hist_entry *he);
133};
134
135extern struct perf_hpp_fmt perf_hpp__format[];
136
137enum {
138 PERF_HPP__OVERHEAD,
139 PERF_HPP__OVERHEAD_SYS,
140 PERF_HPP__OVERHEAD_US,
141 PERF_HPP__OVERHEAD_GUEST_SYS,
142 PERF_HPP__OVERHEAD_GUEST_US,
143 PERF_HPP__SAMPLES,
144 PERF_HPP__PERIOD,
145 PERF_HPP__DELTA,
146 PERF_HPP__DISPL,
147
148 PERF_HPP__MAX_INDEX
149};
150
151void perf_hpp__init(bool need_pair, bool show_displacement);
152int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
153 bool color);
115 154
116struct perf_evlist; 155struct perf_evlist;
117 156
118#ifdef NO_NEWT_SUPPORT 157#ifdef NO_NEWT_SUPPORT
119static inline 158static inline
120int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used, 159int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
121 const char *help __used, 160 const char *help __maybe_unused,
122 void(*timer)(void *arg) __used, 161 void(*timer)(void *arg) __maybe_unused,
123 void *arg __used, 162 void *arg __maybe_unused,
124 int refresh __used) 163 int refresh __maybe_unused)
125{ 164{
126 return 0; 165 return 0;
127} 166}
128 167
129static inline int hist_entry__tui_annotate(struct hist_entry *self __used, 168static inline int hist_entry__tui_annotate(struct hist_entry *self
130 int evidx __used, 169 __maybe_unused,
131 void(*timer)(void *arg) __used, 170 int evidx __maybe_unused,
132 void *arg __used, 171 void(*timer)(void *arg)
133 int delay_secs __used) 172 __maybe_unused,
173 void *arg __maybe_unused,
174 int delay_secs __maybe_unused)
134{ 175{
135 return 0; 176 return 0;
136} 177}
@@ -148,11 +189,11 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
148 189
149#ifdef NO_GTK2_SUPPORT 190#ifdef NO_GTK2_SUPPORT
150static inline 191static inline
151int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __used, 192int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
152 const char *help __used, 193 const char *help __maybe_unused,
153 void(*timer)(void *arg) __used, 194 void(*timer)(void *arg) __maybe_unused,
154 void *arg __used, 195 void *arg __maybe_unused,
155 int refresh __used) 196 int refresh __maybe_unused)
156{ 197{
157 return 0; 198 return 0;
158} 199}
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/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/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..ead5316b3f89 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#ifndef NO_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..28c18d1d52c3 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,280 @@ 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 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
517 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
518 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
519 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
520
521 return 0;
522}
523
524static int test__group2(struct perf_evlist *evlist)
525{
526 struct perf_evsel *evsel, *leader;
527
528 TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
529
530 /* faults + :ku modifier */
531 evsel = leader = perf_evlist__first(evlist);
532 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
533 TEST_ASSERT_VAL("wrong config",
534 PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
535 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
536 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
537 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
538 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
539 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
540 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
541 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
542
543 /* cache-references + :u modifier */
544 evsel = perf_evsel__next(evsel);
545 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
546 TEST_ASSERT_VAL("wrong config",
547 PERF_COUNT_HW_CACHE_REFERENCES == evsel->attr.config);
548 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
549 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
550 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
551 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
552 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
553 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
554 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
555
556 /* cycles:k */
557 evsel = perf_evsel__next(evsel);
558 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
559 TEST_ASSERT_VAL("wrong config",
560 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
561 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
562 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
563 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
564 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
565 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
566 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
567 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
568
569 return 0;
570}
571
572static int test__group3(struct perf_evlist *evlist __maybe_unused)
573{
574 struct perf_evsel *evsel, *leader;
575
576 TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
577
578 /* group1 syscalls:sys_enter_open:H */
579 evsel = leader = perf_evlist__first(evlist);
580 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
581 TEST_ASSERT_VAL("wrong sample_type",
582 PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
583 TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
584 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
585 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
586 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
587 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
588 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
589 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
590 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
591 TEST_ASSERT_VAL("wrong group name",
592 !strcmp(leader->group_name, "group1"));
593
594 /* group1 cycles:kppp */
595 evsel = perf_evsel__next(evsel);
596 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
597 TEST_ASSERT_VAL("wrong config",
598 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
599 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
600 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
601 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
602 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
603 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
604 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
605 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
606 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
607
608 /* group2 cycles + G modifier */
609 evsel = leader = perf_evsel__next(evsel);
610 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
611 TEST_ASSERT_VAL("wrong config",
612 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
613 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
614 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
615 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
616 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
617 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
618 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
619 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
620 TEST_ASSERT_VAL("wrong group name",
621 !strcmp(leader->group_name, "group2"));
622
623 /* group2 1:3 + G modifier */
624 evsel = perf_evsel__next(evsel);
625 TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
626 TEST_ASSERT_VAL("wrong config", 3 == evsel->attr.config);
627 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
628 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
629 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
630 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
631 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
632 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
633 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
634
635 /* instructions:u */
636 evsel = perf_evsel__next(evsel);
637 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
638 TEST_ASSERT_VAL("wrong config",
639 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
640 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
641 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
642 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
643 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
644 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
645 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
646 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
647
648 return 0;
649}
650
651static int test__group4(struct perf_evlist *evlist __maybe_unused)
652{
653 struct perf_evsel *evsel, *leader;
654
655 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
656
657 /* cycles:u + p */
658 evsel = leader = perf_evlist__first(evlist);
659 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
660 TEST_ASSERT_VAL("wrong config",
661 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
662 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
663 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
664 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
665 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
666 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
667 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
668 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
669 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
670
671 /* instructions:kp + p */
672 evsel = perf_evsel__next(evsel);
673 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
674 TEST_ASSERT_VAL("wrong config",
675 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
676 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
677 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
678 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
679 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
680 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
681 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
682 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
683
684 return 0;
685}
686
687static int test__group5(struct perf_evlist *evlist __maybe_unused)
688{
689 struct perf_evsel *evsel, *leader;
690
691 TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
692
693 /* cycles + G */
694 evsel = leader = perf_evlist__first(evlist);
695 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
696 TEST_ASSERT_VAL("wrong config",
697 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
698 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
699 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
700 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
701 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
702 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
703 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
704 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
705 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
706
707 /* instructions + G */
708 evsel = perf_evsel__next(evsel);
709 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
710 TEST_ASSERT_VAL("wrong config",
711 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
712 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
713 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
714 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
715 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
716 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
717 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
718 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
719
720 /* cycles:G */
721 evsel = leader = perf_evsel__next(evsel);
722 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
723 TEST_ASSERT_VAL("wrong config",
724 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
725 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
726 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
727 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
728 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
729 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
730 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
731 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
732 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
733
734 /* instructions:G */
735 evsel = perf_evsel__next(evsel);
736 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
737 TEST_ASSERT_VAL("wrong config",
738 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
739 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
740 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
741 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
742 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
743 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
744 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
745 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
746
747 /* cycles */
748 evsel = perf_evsel__next(evsel);
749 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
750 TEST_ASSERT_VAL("wrong config",
751 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
752 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
753 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
754 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
755 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
756 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
757 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
758 TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
759
760 return 0;
761}
762
516struct test__event_st { 763struct test__event_st {
517 const char *name; 764 const char *name;
518 __u32 type; 765 __u32 type;
@@ -632,6 +879,26 @@ static struct test__event_st test__events[] = {
632 .name = "mem:0:rw:kp", 879 .name = "mem:0:rw:kp",
633 .check = test__checkevent_breakpoint_rw_modifier, 880 .check = test__checkevent_breakpoint_rw_modifier,
634 }, 881 },
882 [28] = {
883 .name = "{instructions:k,cycles:upp}",
884 .check = test__group1,
885 },
886 [29] = {
887 .name = "{faults:k,cache-references}:u,cycles:k",
888 .check = test__group2,
889 },
890 [30] = {
891 .name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u",
892 .check = test__group3,
893 },
894 [31] = {
895 .name = "{cycles:u,instructions:kp}:p",
896 .check = test__group4,
897 },
898 [32] = {
899 .name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles",
900 .check = test__group5,
901 },
635}; 902};
636 903
637static struct test__event_st test__events_pmu[] = { 904static struct test__event_st test__events_pmu[] = {
@@ -658,9 +925,6 @@ static struct test__term test__terms[] = {
658 }, 925 },
659}; 926};
660 927
661#define TEST__TERMS_CNT (sizeof(test__terms) / \
662 sizeof(struct test__term))
663
664static int test_event(struct test__event_st *e) 928static int test_event(struct test__event_st *e)
665{ 929{
666 struct perf_evlist *evlist; 930 struct perf_evlist *evlist;
@@ -685,19 +949,19 @@ static int test_event(struct test__event_st *e)
685 949
686static int test_events(struct test__event_st *events, unsigned cnt) 950static int test_events(struct test__event_st *events, unsigned cnt)
687{ 951{
688 int ret = 0; 952 int ret1, ret2 = 0;
689 unsigned i; 953 unsigned i;
690 954
691 for (i = 0; i < cnt; i++) { 955 for (i = 0; i < cnt; i++) {
692 struct test__event_st *e = &events[i]; 956 struct test__event_st *e = &events[i];
693 957
694 pr_debug("running test %d '%s'\n", i, e->name); 958 pr_debug("running test %d '%s'\n", i, e->name);
695 ret = test_event(e); 959 ret1 = test_event(e);
696 if (ret) 960 if (ret1)
697 break; 961 ret2 = ret1;
698 } 962 }
699 963
700 return ret; 964 return ret2;
701} 965}
702 966
703static int test_term(struct test__term *t) 967static int test_term(struct test__term *t)
@@ -758,13 +1022,13 @@ static int test_pmu(void)
758 1022
759int parse_events__test(void) 1023int parse_events__test(void)
760{ 1024{
761 int ret; 1025 int ret1, ret2 = 0;
762 1026
763#define TEST_EVENTS(tests) \ 1027#define TEST_EVENTS(tests) \
764do { \ 1028do { \
765 ret = test_events(tests, ARRAY_SIZE(tests)); \ 1029 ret1 = test_events(tests, ARRAY_SIZE(tests)); \
766 if (ret) \ 1030 if (!ret2) \
767 return ret; \ 1031 ret2 = ret1; \
768} while (0) 1032} while (0)
769 1033
770 TEST_EVENTS(test__events); 1034 TEST_EVENTS(test__events);
@@ -772,5 +1036,9 @@ do { \
772 if (test_pmu()) 1036 if (test_pmu())
773 TEST_EVENTS(test__events_pmu); 1037 TEST_EVENTS(test__events_pmu);
774 1038
775 return test_terms(test__terms, ARRAY_SIZE(test__terms)); 1039 ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
1040 if (!ret2)
1041 ret2 = ret1;
1042
1043 return ret2;
776} 1044}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 74a5af4d33ec..aed38e4b9dfa 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') {
@@ -674,13 +709,51 @@ int parse_events_modifier(struct list_head *list, char *str)
674 if (precise > 3) 709 if (precise > 3)
675 return -EINVAL; 710 return -EINVAL;
676 711
712 mod->eu = eu;
713 mod->ek = ek;
714 mod->eh = eh;
715 mod->eH = eH;
716 mod->eG = eG;
717 mod->precise = precise;
718 mod->exclude_GH = exclude_GH;
719 return 0;
720}
721
722int parse_events__modifier_event(struct list_head *list, char *str, bool add)
723{
724 struct perf_evsel *evsel;
725 struct event_modifier mod;
726
727 if (str == NULL)
728 return 0;
729
730 if (!add && get_event_modifier(&mod, str, NULL))
731 return -EINVAL;
732
677 list_for_each_entry(evsel, list, node) { 733 list_for_each_entry(evsel, list, node) {
678 evsel->attr.exclude_user = eu; 734
679 evsel->attr.exclude_kernel = ek; 735 if (add && get_event_modifier(&mod, str, evsel))
680 evsel->attr.exclude_hv = eh; 736 return -EINVAL;
681 evsel->attr.precise_ip = precise; 737
682 evsel->attr.exclude_host = eH; 738 evsel->attr.exclude_user = mod.eu;
683 evsel->attr.exclude_guest = eG; 739 evsel->attr.exclude_kernel = mod.ek;
740 evsel->attr.exclude_hv = mod.eh;
741 evsel->attr.precise_ip = mod.precise;
742 evsel->attr.exclude_host = mod.eH;
743 evsel->attr.exclude_guest = mod.eG;
744 evsel->exclude_GH = mod.exclude_GH;
745 }
746
747 return 0;
748}
749
750int parse_events_name(struct list_head *list, char *name)
751{
752 struct perf_evsel *evsel;
753
754 list_for_each_entry(evsel, list, node) {
755 if (!evsel->name)
756 evsel->name = strdup(name);
684 } 757 }
685 758
686 return 0; 759 return 0;
@@ -730,7 +803,8 @@ int parse_events_terms(struct list_head *terms, const char *str)
730 return ret; 803 return ret;
731} 804}
732 805
733int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) 806int parse_events(struct perf_evlist *evlist, const char *str,
807 int unset __maybe_unused)
734{ 808{
735 struct parse_events_data__events data = { 809 struct parse_events_data__events data = {
736 .list = LIST_HEAD_INIT(data.list), 810 .list = LIST_HEAD_INIT(data.list),
@@ -756,20 +830,20 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
756} 830}
757 831
758int parse_events_option(const struct option *opt, const char *str, 832int parse_events_option(const struct option *opt, const char *str,
759 int unset __used) 833 int unset __maybe_unused)
760{ 834{
761 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 835 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
762 return parse_events(evlist, str, unset); 836 return parse_events(evlist, str, unset);
763} 837}
764 838
765int parse_filter(const struct option *opt, const char *str, 839int parse_filter(const struct option *opt, const char *str,
766 int unset __used) 840 int unset __maybe_unused)
767{ 841{
768 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 842 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
769 struct perf_evsel *last = NULL; 843 struct perf_evsel *last = NULL;
770 844
771 if (evlist->nr_entries > 0) 845 if (evlist->nr_entries > 0)
772 last = list_entry(evlist->entries.prev, struct perf_evsel, node); 846 last = perf_evlist__last(evlist);
773 847
774 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 848 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
775 fprintf(stderr, 849 fprintf(stderr,
@@ -799,7 +873,8 @@ static const char * const event_type_descriptors[] = {
799 * Print the events from <debugfs_mount_point>/tracing/events 873 * Print the events from <debugfs_mount_point>/tracing/events
800 */ 874 */
801 875
802void print_tracepoint_events(const char *subsys_glob, const char *event_glob) 876void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
877 bool name_only)
803{ 878{
804 DIR *sys_dir, *evt_dir; 879 DIR *sys_dir, *evt_dir;
805 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 880 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
@@ -829,6 +904,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
829 !strglobmatch(evt_dirent.d_name, event_glob)) 904 !strglobmatch(evt_dirent.d_name, event_glob))
830 continue; 905 continue;
831 906
907 if (name_only) {
908 printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
909 continue;
910 }
911
832 snprintf(evt_path, MAXPATHLEN, "%s:%s", 912 snprintf(evt_path, MAXPATHLEN, "%s:%s",
833 sys_dirent.d_name, evt_dirent.d_name); 913 sys_dirent.d_name, evt_dirent.d_name);
834 printf(" %-50s [%s]\n", evt_path, 914 printf(" %-50s [%s]\n", evt_path,
@@ -906,7 +986,7 @@ void print_events_type(u8 type)
906 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); 986 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
907} 987}
908 988
909int print_hwcache_events(const char *event_glob) 989int print_hwcache_events(const char *event_glob, bool name_only)
910{ 990{
911 unsigned int type, op, i, printed = 0; 991 unsigned int type, op, i, printed = 0;
912 char name[64]; 992 char name[64];
@@ -923,8 +1003,11 @@ int print_hwcache_events(const char *event_glob)
923 if (event_glob != NULL && !strglobmatch(name, event_glob)) 1003 if (event_glob != NULL && !strglobmatch(name, event_glob))
924 continue; 1004 continue;
925 1005
926 printf(" %-50s [%s]\n", name, 1006 if (name_only)
927 event_type_descriptors[PERF_TYPE_HW_CACHE]); 1007 printf("%s ", name);
1008 else
1009 printf(" %-50s [%s]\n", name,
1010 event_type_descriptors[PERF_TYPE_HW_CACHE]);
928 ++printed; 1011 ++printed;
929 } 1012 }
930 } 1013 }
@@ -934,7 +1017,8 @@ int print_hwcache_events(const char *event_glob)
934} 1017}
935 1018
936static void print_symbol_events(const char *event_glob, unsigned type, 1019static void print_symbol_events(const char *event_glob, unsigned type,
937 struct event_symbol *syms, unsigned max) 1020 struct event_symbol *syms, unsigned max,
1021 bool name_only)
938{ 1022{
939 unsigned i, printed = 0; 1023 unsigned i, printed = 0;
940 char name[MAX_NAME_LEN]; 1024 char name[MAX_NAME_LEN];
@@ -946,6 +1030,11 @@ static void print_symbol_events(const char *event_glob, unsigned type,
946 (syms->alias && strglobmatch(syms->alias, event_glob)))) 1030 (syms->alias && strglobmatch(syms->alias, event_glob))))
947 continue; 1031 continue;
948 1032
1033 if (name_only) {
1034 printf("%s ", syms->symbol);
1035 continue;
1036 }
1037
949 if (strlen(syms->alias)) 1038 if (strlen(syms->alias))
950 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 1039 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
951 else 1040 else
@@ -963,39 +1052,42 @@ static void print_symbol_events(const char *event_glob, unsigned type,
963/* 1052/*
964 * Print the help text for the event symbols: 1053 * Print the help text for the event symbols:
965 */ 1054 */
966void print_events(const char *event_glob) 1055void print_events(const char *event_glob, bool name_only)
967{ 1056{
968 1057 if (!name_only) {
969 printf("\n"); 1058 printf("\n");
970 printf("List of pre-defined events (to be used in -e):\n"); 1059 printf("List of pre-defined events (to be used in -e):\n");
1060 }
971 1061
972 print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 1062 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
973 event_symbols_hw, PERF_COUNT_HW_MAX); 1063 event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
974 1064
975 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, 1065 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
976 event_symbols_sw, PERF_COUNT_SW_MAX); 1066 event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
977 1067
978 print_hwcache_events(event_glob); 1068 print_hwcache_events(event_glob, name_only);
979 1069
980 if (event_glob != NULL) 1070 if (event_glob != NULL)
981 return; 1071 return;
982 1072
983 printf("\n"); 1073 if (!name_only) {
984 printf(" %-50s [%s]\n", 1074 printf("\n");
985 "rNNN", 1075 printf(" %-50s [%s]\n",
986 event_type_descriptors[PERF_TYPE_RAW]); 1076 "rNNN",
987 printf(" %-50s [%s]\n", 1077 event_type_descriptors[PERF_TYPE_RAW]);
988 "cpu/t1=v1[,t2=v2,t3 ...]/modifier", 1078 printf(" %-50s [%s]\n",
989 event_type_descriptors[PERF_TYPE_RAW]); 1079 "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
990 printf(" (see 'perf list --help' on how to encode it)\n"); 1080 event_type_descriptors[PERF_TYPE_RAW]);
991 printf("\n"); 1081 printf(" (see 'perf list --help' on how to encode it)\n");
992 1082 printf("\n");
993 printf(" %-50s [%s]\n", 1083
994 "mem:<addr>[:access]", 1084 printf(" %-50s [%s]\n",
1085 "mem:<addr>[:access]",
995 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1086 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
996 printf("\n"); 1087 printf("\n");
1088 }
997 1089
998 print_tracepoint_events(NULL, NULL); 1090 print_tracepoint_events(NULL, NULL, name_only);
999} 1091}
1000 1092
1001int parse_events__is_hardcoded_term(struct parse_events__term *term) 1093int parse_events__is_hardcoded_term(struct parse_events__term *term)
@@ -1005,7 +1097,7 @@ int parse_events__is_hardcoded_term(struct parse_events__term *term)
1005 1097
1006static int new_term(struct parse_events__term **_term, int type_val, 1098static int new_term(struct parse_events__term **_term, int type_val,
1007 int type_term, char *config, 1099 int type_term, char *config,
1008 char *str, long num) 1100 char *str, u64 num)
1009{ 1101{
1010 struct parse_events__term *term; 1102 struct parse_events__term *term;
1011 1103
@@ -1034,7 +1126,7 @@ static int new_term(struct parse_events__term **_term, int type_val,
1034} 1126}
1035 1127
1036int parse_events__term_num(struct parse_events__term **term, 1128int parse_events__term_num(struct parse_events__term **term,
1037 int type_term, char *config, long num) 1129 int type_term, char *config, u64 num)
1038{ 1130{
1039 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, 1131 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
1040 config, NULL, num); 1132 config, NULL, num);
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ee9c218a193c..c356e443448d 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -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..443fc116512b 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -557,7 +557,8 @@ int parse_options_usage(const char * const *usagestr,
557} 557}
558 558
559 559
560int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used, 560int parse_opt_verbosity_cb(const struct option *opt,
561 const char *arg __maybe_unused,
561 int unset) 562 int unset)
562{ 563{
563 int *target = opt->value; 564 int *target = opt->value;
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
new file mode 100644
index 000000000000..316dbe7f86ed
--- /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#ifndef NO_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 /* NO_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..53c7794fc4be 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -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..aab414fbb64b 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -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/sort.c b/tools/perf/util/sort.c
index 0f5a0a496bc4..b5b1b9211960 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;
@@ -399,7 +400,8 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
399} 400}
400 401
401static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, 402static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf,
402 size_t size, unsigned int width __used) 403 size_t size,
404 unsigned int width __maybe_unused)
403{ 405{
404 struct addr_map_symbol *from = &self->branch_info->from; 406 struct addr_map_symbol *from = &self->branch_info->from;
405 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, 407 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
@@ -408,7 +410,8 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf,
408} 410}
409 411
410static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, 412static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf,
411 size_t size, unsigned int width __used) 413 size_t size,
414 unsigned int width __maybe_unused)
412{ 415{
413 struct addr_map_symbol *to = &self->branch_info->to; 416 struct addr_map_symbol *to = &self->branch_info->to;
414 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, 417 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
@@ -509,6 +512,10 @@ int sort_dimension__add(const char *tok)
509 return -EINVAL; 512 return -EINVAL;
510 } 513 }
511 sort__has_parent = 1; 514 sort__has_parent = 1;
515 } else if (sd->entry == &sort_sym ||
516 sd->entry == &sort_sym_from ||
517 sd->entry == &sort_sym_to) {
518 sort__has_sym = 1;
512 } 519 }
513 520
514 if (sd->taken) 521 if (sd->taken)
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index e724b26acd51..12d634792de5 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;
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..b441b07172b7 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#ifndef NO_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
@@ -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#ifndef NO_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.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..a78c8b303bb5
--- /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#ifndef NO_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 /* NO_LIBUNWIND_SUPPORT */
35#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index d03599fbe78b..2055cf38041c 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#ifndef NO_BACKTRACE
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#ifndef NO_BACKTRACE
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