aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Documentation/Makefile4
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt3
-rw-r--r--tools/perf/Documentation/perf-diff.txt4
-rw-r--r--tools/perf/Documentation/perf-top.txt2
-rw-r--r--tools/perf/Makefile51
-rw-r--r--tools/perf/builtin-buildid-cache.c48
-rw-r--r--tools/perf/builtin-buildid-list.c21
-rw-r--r--tools/perf/builtin-diff.c121
-rw-r--r--tools/perf/builtin-evlist.c81
-rw-r--r--tools/perf/builtin-record.c40
-rw-r--r--tools/perf/builtin-report.c1
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-top.c207
-rw-r--r--tools/perf/builtin-trace.c2
-rw-r--r--tools/perf/tests/attr/base-record2
-rw-r--r--tools/perf/tests/attr/test-record-group2
-rw-r--r--tools/perf/tests/attr/test-record-group12
-rw-r--r--tools/perf/tests/mmap-basic.c40
-rw-r--r--tools/perf/tests/open-syscall-all-cpus.c18
-rw-r--r--tools/perf/tests/open-syscall.c17
-rw-r--r--tools/perf/tests/parse-events.c20
-rw-r--r--tools/perf/tests/perf-record.c8
-rw-r--r--tools/perf/tests/tests.h3
-rw-r--r--tools/perf/tests/util.c30
-rw-r--r--tools/perf/ui/browsers/hists.c20
-rw-r--r--tools/perf/ui/gtk/browser.c30
-rw-r--r--tools/perf/ui/gtk/helpline.c23
-rw-r--r--tools/perf/ui/helpline.c12
-rw-r--r--tools/perf/ui/helpline.h22
-rw-r--r--tools/perf/ui/hist.c170
-rw-r--r--tools/perf/ui/setup.c1
-rw-r--r--tools/perf/ui/stdio/hist.c17
-rw-r--r--tools/perf/ui/tui/helpline.c29
-rw-r--r--tools/perf/ui/util.c10
-rw-r--r--tools/perf/util/callchain.h5
-rw-r--r--tools/perf/util/debug.c28
-rw-r--r--tools/perf/util/debug.h33
-rw-r--r--tools/perf/util/dso.c6
-rw-r--r--tools/perf/util/dso.h2
-rw-r--r--tools/perf/util/evlist.c17
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c186
-rw-r--r--tools/perf/util/evsel.h25
-rw-r--r--tools/perf/util/hist.c4
-rw-r--r--tools/perf/util/hist.h22
-rw-r--r--tools/perf/util/machine.c742
-rw-r--r--tools/perf/util/machine.h11
-rw-r--r--tools/perf/util/session.c256
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/sort.h5
-rw-r--r--tools/perf/util/symbol-elf.c11
-rw-r--r--tools/perf/util/symbol.c522
-rw-r--r--tools/perf/util/symbol.h4
-rw-r--r--tools/perf/util/thread.c20
-rw-r--r--tools/perf/util/thread.h1
-rw-r--r--tools/perf/util/top.c22
-rw-r--r--tools/perf/util/top.h8
57 files changed, 1483 insertions, 1519 deletions
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index ef6d22e879eb..eb30044a922a 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -222,10 +222,14 @@ install-pdf: pdf
222#install-html: html 222#install-html: html
223# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) 223# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
224 224
225ifneq ($(MAKECMDGOALS),clean)
226ifneq ($(MAKECMDGOALS),tags)
225$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 227$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
226 $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE 228 $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE
227 229
228-include $(OUTPUT)PERF-VERSION-FILE 230-include $(OUTPUT)PERF-VERSION-FILE
231endif
232endif
229 233
230# 234#
231# Determine "include::" file references in asciidoc files. 235# Determine "include::" file references in asciidoc files.
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index c1057701a7dc..8e798baae0fd 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -24,6 +24,9 @@ OPTIONS
24-r:: 24-r::
25--remove=:: 25--remove=::
26 Remove specified file from the cache. 26 Remove specified file from the cache.
27-M::
28--missing=::
29 List missing build ids in the cache for the specified file.
27-v:: 30-v::
28--verbose:: 31--verbose::
29 Be more verbose. 32 Be more verbose.
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 194f37d635df..5b3123d5721f 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -22,10 +22,6 @@ specified perf.data files.
22 22
23OPTIONS 23OPTIONS
24------- 24-------
25-M::
26--displacement::
27 Show position displacement relative to baseline.
28
29-D:: 25-D::
30--dump-raw-trace:: 26--dump-raw-trace::
31 Dump raw trace in ASCII. 27 Dump raw trace in ASCII.
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 5b80d84d6b4a..a414bc95fd52 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -60,7 +60,7 @@ Default is to monitor all CPUS.
60 60
61-i:: 61-i::
62--inherit:: 62--inherit::
63 Child tasks inherit counters, only makes sens with -p option. 63 Child tasks do not inherit counters.
64 64
65-k <path>:: 65-k <path>::
66--vmlinux=<path>:: 66--vmlinux=<path>::
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 8ab05e543ef4..2cbaad83a6e2 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -153,6 +153,8 @@ INSTALL = install
153# explicitly what architecture to check for. Fix this up for yours.. 153# explicitly what architecture to check for. Fix this up for yours..
154SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 154SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
155 155
156ifneq ($(MAKECMDGOALS),clean)
157ifneq ($(MAKECMDGOALS),tags)
156-include config/feature-tests.mak 158-include config/feature-tests.mak
157 159
158ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) 160ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
@@ -206,6 +208,8 @@ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y)
206 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS)) 208 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
207 BASIC_CFLAGS += -I. 209 BASIC_CFLAGS += -I.
208endif 210endif
211endif # MAKECMDGOALS != tags
212endif # MAKECMDGOALS != clean
209 213
210# Guard against environment variables 214# Guard against environment variables
211BUILTIN_OBJS = 215BUILTIN_OBJS =
@@ -230,11 +234,19 @@ endif
230LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 234LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
231TE_LIB := -L$(TE_PATH) -ltraceevent 235TE_LIB := -L$(TE_PATH) -ltraceevent
232 236
237export LIBTRACEEVENT
238
239# python extension build directories
240PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
241PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
242PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
243export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
244
245python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
246
233PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 247PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
234PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py 248PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
235 249
236export LIBTRACEEVENT
237
238$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 250$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
239 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 251 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
240 --quiet build_ext; \ 252 --quiet build_ext; \
@@ -378,8 +390,11 @@ LIB_H += util/rblist.h
378LIB_H += util/intlist.h 390LIB_H += util/intlist.h
379LIB_H += util/perf_regs.h 391LIB_H += util/perf_regs.h
380LIB_H += util/unwind.h 392LIB_H += util/unwind.h
381LIB_H += ui/helpline.h
382LIB_H += util/vdso.h 393LIB_H += util/vdso.h
394LIB_H += ui/helpline.h
395LIB_H += ui/progress.h
396LIB_H += ui/util.h
397LIB_H += ui/ui.h
383 398
384LIB_OBJS += $(OUTPUT)util/abspath.o 399LIB_OBJS += $(OUTPUT)util/abspath.o
385LIB_OBJS += $(OUTPUT)util/alias.o 400LIB_OBJS += $(OUTPUT)util/alias.o
@@ -453,6 +468,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
453LIB_OBJS += $(OUTPUT)ui/setup.o 468LIB_OBJS += $(OUTPUT)ui/setup.o
454LIB_OBJS += $(OUTPUT)ui/helpline.o 469LIB_OBJS += $(OUTPUT)ui/helpline.o
455LIB_OBJS += $(OUTPUT)ui/progress.o 470LIB_OBJS += $(OUTPUT)ui/progress.o
471LIB_OBJS += $(OUTPUT)ui/util.o
456LIB_OBJS += $(OUTPUT)ui/hist.o 472LIB_OBJS += $(OUTPUT)ui/hist.o
457LIB_OBJS += $(OUTPUT)ui/stdio/hist.o 473LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
458 474
@@ -471,7 +487,6 @@ LIB_OBJS += $(OUTPUT)tests/rdpmc.o
471LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o 487LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
472LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o 488LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
473LIB_OBJS += $(OUTPUT)tests/pmu.o 489LIB_OBJS += $(OUTPUT)tests/pmu.o
474LIB_OBJS += $(OUTPUT)tests/util.o
475 490
476BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 491BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
477BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 492BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -510,6 +525,8 @@ PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
510# 525#
511# Platform specific tweaks 526# Platform specific tweaks
512# 527#
528ifneq ($(MAKECMDGOALS),clean)
529ifneq ($(MAKECMDGOALS),tags)
513 530
514# We choose to avoid "if .. else if .. else .. endif endif" 531# We choose to avoid "if .. else if .. else .. endif endif"
515# because maintaining the nesting to match is a pain. If 532# because maintaining the nesting to match is a pain. If
@@ -646,7 +663,6 @@ ifndef NO_NEWT
646 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o 663 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
647 LIB_OBJS += $(OUTPUT)ui/browsers/map.o 664 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
648 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o 665 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
649 LIB_OBJS += $(OUTPUT)ui/util.o
650 LIB_OBJS += $(OUTPUT)ui/tui/setup.o 666 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
651 LIB_OBJS += $(OUTPUT)ui/tui/util.o 667 LIB_OBJS += $(OUTPUT)ui/tui/util.o
652 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o 668 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
@@ -655,9 +671,6 @@ ifndef NO_NEWT
655 LIB_H += ui/browsers/map.h 671 LIB_H += ui/browsers/map.h
656 LIB_H += ui/keysyms.h 672 LIB_H += ui/keysyms.h
657 LIB_H += ui/libslang.h 673 LIB_H += ui/libslang.h
658 LIB_H += ui/progress.h
659 LIB_H += ui/util.h
660 LIB_H += ui/ui.h
661 endif 674 endif
662endif 675endif
663 676
@@ -677,10 +690,6 @@ ifndef NO_GTK2
677 LIB_OBJS += $(OUTPUT)ui/gtk/util.o 690 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
678 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o 691 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
679 LIB_OBJS += $(OUTPUT)ui/gtk/progress.o 692 LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
680 # Make sure that it'd be included only once.
681 ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
682 LIB_OBJS += $(OUTPUT)ui/util.o
683 endif
684 endif 693 endif
685endif 694endif
686 695
@@ -707,7 +716,7 @@ disable-python = $(eval $(disable-python_code))
707define disable-python_code 716define disable-python_code
708 BASIC_CFLAGS += -DNO_LIBPYTHON 717 BASIC_CFLAGS += -DNO_LIBPYTHON
709 $(if $(1),$(warning No $(1) was found)) 718 $(if $(1),$(warning No $(1) was found))
710 $(warning Python support won't be built) 719 $(warning Python support will not be built)
711endef 720endef
712 721
713override PYTHON := \ 722override PYTHON := \
@@ -715,19 +724,10 @@ override PYTHON := \
715 724
716ifndef PYTHON 725ifndef PYTHON
717 $(call disable-python,python interpreter) 726 $(call disable-python,python interpreter)
718 python-clean :=
719else 727else
720 728
721 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 729 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
722 730
723 # python extension build directories
724 PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
725 PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
726 PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
727 export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
728
729 python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
730
731 ifdef NO_LIBPYTHON 731 ifdef NO_LIBPYTHON
732 $(call disable-python) 732 $(call disable-python)
733 else 733 else
@@ -843,6 +843,9 @@ ifdef ASCIIDOC8
843 export ASCIIDOC8 843 export ASCIIDOC8
844endif 844endif
845 845
846endif # MAKECMDGOALS != tags
847endif # MAKECMDGOALS != clean
848
846# Shell quote (do not use $(call) to accommodate ancient setups); 849# Shell quote (do not use $(call) to accommodate ancient setups);
847 850
848ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) 851ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
@@ -1099,7 +1102,7 @@ perfexec_instdir = $(prefix)/$(perfexecdir)
1099endif 1102endif
1100perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 1103perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
1101 1104
1102install: all try-install-man 1105install-bin: all
1103 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 1106 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
1104 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)' 1107 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
1105 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' 1108 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
@@ -1120,6 +1123,8 @@ install: all try-install-man
1120 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' 1123 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
1121 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' 1124 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
1122 1125
1126install: install-bin try-install-man
1127
1123install-python_ext: 1128install-python_ext:
1124 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' 1129 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
1125 1130
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index fae8b250b2ca..a336014e0286 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -14,6 +14,7 @@
14#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/strlist.h" 15#include "util/strlist.h"
16#include "util/build-id.h" 16#include "util/build-id.h"
17#include "util/session.h"
17#include "util/symbol.h" 18#include "util/symbol.h"
18 19
19static int build_id_cache__add_file(const char *filename, const char *debugdir) 20static int build_id_cache__add_file(const char *filename, const char *debugdir)
@@ -58,19 +59,59 @@ static int build_id_cache__remove_file(const char *filename,
58 return err; 59 return err;
59} 60}
60 61
62static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
63{
64 char filename[PATH_MAX];
65 u8 build_id[BUILD_ID_SIZE];
66
67 if (dso__build_id_filename(dso, filename, sizeof(filename)) &&
68 filename__read_build_id(filename, build_id,
69 sizeof(build_id)) != sizeof(build_id)) {
70 if (errno == ENOENT)
71 return false;
72
73 pr_warning("Problems with %s file, consider removing it from the cache\n",
74 filename);
75 } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) {
76 pr_warning("Problems with %s file, consider removing it from the cache\n",
77 filename);
78 }
79
80 return true;
81}
82
83static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp)
84{
85 struct perf_session *session = perf_session__new(filename, O_RDONLY,
86 force, false, NULL);
87 if (session == NULL)
88 return -1;
89
90 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
91 perf_session__delete(session);
92
93 return 0;
94}
95
61int cmd_buildid_cache(int argc, const char **argv, 96int cmd_buildid_cache(int argc, const char **argv,
62 const char *prefix __maybe_unused) 97 const char *prefix __maybe_unused)
63{ 98{
64 struct strlist *list; 99 struct strlist *list;
65 struct str_node *pos; 100 struct str_node *pos;
101 int ret = 0;
102 bool force = false;
66 char debugdir[PATH_MAX]; 103 char debugdir[PATH_MAX];
67 char const *add_name_list_str = NULL, 104 char const *add_name_list_str = NULL,
68 *remove_name_list_str = NULL; 105 *remove_name_list_str = NULL,
106 *missing_filename = NULL;
69 const struct option buildid_cache_options[] = { 107 const struct option buildid_cache_options[] = {
70 OPT_STRING('a', "add", &add_name_list_str, 108 OPT_STRING('a', "add", &add_name_list_str,
71 "file list", "file(s) to add"), 109 "file list", "file(s) to add"),
72 OPT_STRING('r', "remove", &remove_name_list_str, "file list", 110 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
73 "file(s) to remove"), 111 "file(s) to remove"),
112 OPT_STRING('M', "missing", &missing_filename, "file",
113 "to find missing build ids in the cache"),
114 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
74 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 115 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
75 OPT_END() 116 OPT_END()
76 }; 117 };
@@ -125,5 +166,8 @@ int cmd_buildid_cache(int argc, const char **argv,
125 } 166 }
126 } 167 }
127 168
128 return 0; 169 if (missing_filename)
170 ret = build_id_cache__fprintf_missing(missing_filename, force, stdout);
171
172 return ret;
129} 173}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index a82d99fec83e..e74366a13218 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -44,23 +44,26 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
44 return fprintf(fp, "%s\n", sbuild_id); 44 return fprintf(fp, "%s\n", sbuild_id);
45} 45}
46 46
47static bool dso__skip_buildid(struct dso *dso, int with_hits)
48{
49 return with_hits && !dso->hit;
50}
51
47static int perf_session__list_build_ids(bool force, bool with_hits) 52static int perf_session__list_build_ids(bool force, bool with_hits)
48{ 53{
49 struct perf_session *session; 54 struct perf_session *session;
50 55
51 symbol__elf_init(); 56 symbol__elf_init();
52
53 session = perf_session__new(input_name, O_RDONLY, force, false,
54 &build_id__mark_dso_hit_ops);
55 if (session == NULL)
56 return -1;
57
58 /* 57 /*
59 * See if this is an ELF file first: 58 * See if this is an ELF file first:
60 */ 59 */
61 if (filename__fprintf_build_id(session->filename, stdout)) 60 if (filename__fprintf_build_id(input_name, stdout))
62 goto out; 61 goto out;
63 62
63 session = perf_session__new(input_name, O_RDONLY, force, false,
64 &build_id__mark_dso_hit_ops);
65 if (session == NULL)
66 return -1;
64 /* 67 /*
65 * in pipe-mode, the only way to get the buildids is to parse 68 * in pipe-mode, the only way to get the buildids is to parse
66 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID 69 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
@@ -68,9 +71,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
68 if (with_hits || session->fd_pipe) 71 if (with_hits || session->fd_pipe)
69 perf_session__process_events(session, &build_id__mark_dso_hit_ops); 72 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
70 73
71 perf_session__fprintf_dsos_buildid(session, stdout, with_hits); 74 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
72out:
73 perf_session__delete(session); 75 perf_session__delete(session);
76out:
74 return 0; 77 return 0;
75} 78}
76 79
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 93b852f8a5d5..b2e7d39f099b 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -23,7 +23,6 @@ static char const *input_old = "perf.data.old",
23 *input_new = "perf.data"; 23 *input_new = "perf.data";
24static char diff__default_sort_order[] = "dso,symbol"; 24static char diff__default_sort_order[] = "dso,symbol";
25static bool force; 25static bool force;
26static bool show_displacement;
27static bool show_period; 26static bool show_period;
28static bool show_formula; 27static bool show_formula;
29static bool show_baseline_only; 28static bool show_baseline_only;
@@ -146,58 +145,47 @@ static int setup_compute(const struct option *opt, const char *str,
146 return -EINVAL; 145 return -EINVAL;
147} 146}
148 147
149static double get_period_percent(struct hist_entry *he, u64 period) 148double perf_diff__period_percent(struct hist_entry *he, u64 period)
150{ 149{
151 u64 total = he->hists->stats.total_period; 150 u64 total = he->hists->stats.total_period;
152 return (period * 100.0) / total; 151 return (period * 100.0) / total;
153} 152}
154 153
155double perf_diff__compute_delta(struct hist_entry *he) 154double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair)
156{ 155{
157 struct hist_entry *pair = hist_entry__next_pair(he); 156 double new_percent = perf_diff__period_percent(he, he->stat.period);
158 double new_percent = get_period_percent(he, he->stat.period); 157 double old_percent = perf_diff__period_percent(pair, pair->stat.period);
159 double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
160 158
161 he->diff.period_ratio_delta = new_percent - old_percent; 159 he->diff.period_ratio_delta = new_percent - old_percent;
162 he->diff.computed = true; 160 he->diff.computed = true;
163 return he->diff.period_ratio_delta; 161 return he->diff.period_ratio_delta;
164} 162}
165 163
166double perf_diff__compute_ratio(struct hist_entry *he) 164double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair)
167{ 165{
168 struct hist_entry *pair = hist_entry__next_pair(he);
169 double new_period = he->stat.period; 166 double new_period = he->stat.period;
170 double old_period = pair ? pair->stat.period : 0; 167 double old_period = pair->stat.period;
171 168
172 he->diff.computed = true; 169 he->diff.computed = true;
173 he->diff.period_ratio = pair ? (new_period / old_period) : 0; 170 he->diff.period_ratio = new_period / old_period;
174 return he->diff.period_ratio; 171 return he->diff.period_ratio;
175} 172}
176 173
177s64 perf_diff__compute_wdiff(struct hist_entry *he) 174s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
178{ 175{
179 struct hist_entry *pair = hist_entry__next_pair(he);
180 u64 new_period = he->stat.period; 176 u64 new_period = he->stat.period;
181 u64 old_period = pair ? pair->stat.period : 0; 177 u64 old_period = pair->stat.period;
182 178
183 he->diff.computed = true; 179 he->diff.computed = true;
184 180 he->diff.wdiff = new_period * compute_wdiff_w2 -
185 if (!pair) 181 old_period * compute_wdiff_w1;
186 he->diff.wdiff = 0;
187 else
188 he->diff.wdiff = new_period * compute_wdiff_w2 -
189 old_period * compute_wdiff_w1;
190 182
191 return he->diff.wdiff; 183 return he->diff.wdiff;
192} 184}
193 185
194static int formula_delta(struct hist_entry *he, char *buf, size_t size) 186static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
187 char *buf, size_t size)
195{ 188{
196 struct hist_entry *pair = hist_entry__next_pair(he);
197
198 if (!pair)
199 return -1;
200
201 return scnprintf(buf, size, 189 return scnprintf(buf, size,
202 "(%" PRIu64 " * 100 / %" PRIu64 ") - " 190 "(%" PRIu64 " * 100 / %" PRIu64 ") - "
203 "(%" PRIu64 " * 100 / %" PRIu64 ")", 191 "(%" PRIu64 " * 100 / %" PRIu64 ")",
@@ -205,41 +193,36 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size)
205 pair->stat.period, pair->hists->stats.total_period); 193 pair->stat.period, pair->hists->stats.total_period);
206} 194}
207 195
208static int formula_ratio(struct hist_entry *he, char *buf, size_t size) 196static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
197 char *buf, size_t size)
209{ 198{
210 struct hist_entry *pair = hist_entry__next_pair(he);
211 double new_period = he->stat.period; 199 double new_period = he->stat.period;
212 double old_period = pair ? pair->stat.period : 0; 200 double old_period = pair->stat.period;
213
214 if (!pair)
215 return -1;
216 201
217 return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period); 202 return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
218} 203}
219 204
220static int formula_wdiff(struct hist_entry *he, char *buf, size_t size) 205static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair,
206 char *buf, size_t size)
221{ 207{
222 struct hist_entry *pair = hist_entry__next_pair(he);
223 u64 new_period = he->stat.period; 208 u64 new_period = he->stat.period;
224 u64 old_period = pair ? pair->stat.period : 0; 209 u64 old_period = pair->stat.period;
225
226 if (!pair)
227 return -1;
228 210
229 return scnprintf(buf, size, 211 return scnprintf(buf, size,
230 "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")", 212 "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
231 new_period, compute_wdiff_w2, old_period, compute_wdiff_w1); 213 new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
232} 214}
233 215
234int perf_diff__formula(char *buf, size_t size, struct hist_entry *he) 216int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
217 char *buf, size_t size)
235{ 218{
236 switch (compute) { 219 switch (compute) {
237 case COMPUTE_DELTA: 220 case COMPUTE_DELTA:
238 return formula_delta(he, buf, size); 221 return formula_delta(he, pair, buf, size);
239 case COMPUTE_RATIO: 222 case COMPUTE_RATIO:
240 return formula_ratio(he, buf, size); 223 return formula_ratio(he, pair, buf, size);
241 case COMPUTE_WEIGHTED_DIFF: 224 case COMPUTE_WEIGHTED_DIFF:
242 return formula_wdiff(he, buf, size); 225 return formula_wdiff(he, pair, buf, size);
243 default: 226 default:
244 BUG_ON(1); 227 BUG_ON(1);
245 } 228 }
@@ -312,9 +295,8 @@ static void insert_hist_entry_by_name(struct rb_root *root,
312 rb_insert_color(&he->rb_node, root); 295 rb_insert_color(&he->rb_node, root);
313} 296}
314 297
315static void hists__name_resort(struct hists *self, bool sort) 298static void hists__name_resort(struct hists *self)
316{ 299{
317 unsigned long position = 1;
318 struct rb_root tmp = RB_ROOT; 300 struct rb_root tmp = RB_ROOT;
319 struct rb_node *next = rb_first(&self->entries); 301 struct rb_node *next = rb_first(&self->entries);
320 302
@@ -322,16 +304,12 @@ static void hists__name_resort(struct hists *self, bool sort)
322 struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); 304 struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
323 305
324 next = rb_next(&n->rb_node); 306 next = rb_next(&n->rb_node);
325 n->position = position++;
326 307
327 if (sort) { 308 rb_erase(&n->rb_node, &self->entries);
328 rb_erase(&n->rb_node, &self->entries); 309 insert_hist_entry_by_name(&tmp, n);
329 insert_hist_entry_by_name(&tmp, n);
330 }
331 } 310 }
332 311
333 if (sort) 312 self->entries = tmp;
334 self->entries = tmp;
335} 313}
336 314
337static struct perf_evsel *evsel_match(struct perf_evsel *evsel, 315static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
@@ -355,12 +333,8 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
355 333
356 hists__output_resort(hists); 334 hists__output_resort(hists);
357 335
358 /* 336 if (name)
359 * The hists__name_resort only sets possition 337 hists__name_resort(hists);
360 * if name is false.
361 */
362 if (name || ((!name) && show_displacement))
363 hists__name_resort(hists, name);
364 } 338 }
365} 339}
366 340
@@ -385,18 +359,21 @@ static void hists__precompute(struct hists *hists)
385 359
386 while (next != NULL) { 360 while (next != NULL) {
387 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); 361 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
362 struct hist_entry *pair = hist_entry__next_pair(he);
388 363
389 next = rb_next(&he->rb_node); 364 next = rb_next(&he->rb_node);
365 if (!pair)
366 continue;
390 367
391 switch (compute) { 368 switch (compute) {
392 case COMPUTE_DELTA: 369 case COMPUTE_DELTA:
393 perf_diff__compute_delta(he); 370 perf_diff__compute_delta(he, pair);
394 break; 371 break;
395 case COMPUTE_RATIO: 372 case COMPUTE_RATIO:
396 perf_diff__compute_ratio(he); 373 perf_diff__compute_ratio(he, pair);
397 break; 374 break;
398 case COMPUTE_WEIGHTED_DIFF: 375 case COMPUTE_WEIGHTED_DIFF:
399 perf_diff__compute_wdiff(he); 376 perf_diff__compute_wdiff(he, pair);
400 break; 377 break;
401 default: 378 default:
402 BUG_ON(1); 379 BUG_ON(1);
@@ -562,8 +539,6 @@ static const char * const diff_usage[] = {
562static const struct option options[] = { 539static const struct option options[] = {
563 OPT_INCR('v', "verbose", &verbose, 540 OPT_INCR('v', "verbose", &verbose,
564 "be more verbose (show symbol address, etc)"), 541 "be more verbose (show symbol address, etc)"),
565 OPT_BOOLEAN('M', "displacement", &show_displacement,
566 "Show position displacement relative to baseline"),
567 OPT_BOOLEAN('b', "baseline-only", &show_baseline_only, 542 OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
568 "Show only items with match in baseline"), 543 "Show only items with match in baseline"),
569 OPT_CALLBACK('c', "compute", &compute, 544 OPT_CALLBACK('c', "compute", &compute,
@@ -597,40 +572,32 @@ static const struct option options[] = {
597 572
598static void ui_init(void) 573static void ui_init(void)
599{ 574{
600 perf_hpp__init();
601
602 /* No overhead column. */
603 perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
604
605 /* 575 /*
606 * Display baseline/delta/ratio/displacement/ 576 * Display baseline/delta/ratio
607 * formula/periods columns. 577 * formula/periods columns.
608 */ 578 */
609 perf_hpp__column_enable(PERF_HPP__BASELINE, true); 579 perf_hpp__column_enable(PERF_HPP__BASELINE);
610 580
611 switch (compute) { 581 switch (compute) {
612 case COMPUTE_DELTA: 582 case COMPUTE_DELTA:
613 perf_hpp__column_enable(PERF_HPP__DELTA, true); 583 perf_hpp__column_enable(PERF_HPP__DELTA);
614 break; 584 break;
615 case COMPUTE_RATIO: 585 case COMPUTE_RATIO:
616 perf_hpp__column_enable(PERF_HPP__RATIO, true); 586 perf_hpp__column_enable(PERF_HPP__RATIO);
617 break; 587 break;
618 case COMPUTE_WEIGHTED_DIFF: 588 case COMPUTE_WEIGHTED_DIFF:
619 perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true); 589 perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF);
620 break; 590 break;
621 default: 591 default:
622 BUG_ON(1); 592 BUG_ON(1);
623 }; 593 };
624 594
625 if (show_displacement)
626 perf_hpp__column_enable(PERF_HPP__DISPL, true);
627
628 if (show_formula) 595 if (show_formula)
629 perf_hpp__column_enable(PERF_HPP__FORMULA, true); 596 perf_hpp__column_enable(PERF_HPP__FORMULA);
630 597
631 if (show_period) { 598 if (show_period) {
632 perf_hpp__column_enable(PERF_HPP__PERIOD, true); 599 perf_hpp__column_enable(PERF_HPP__PERIOD);
633 perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true); 600 perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE);
634 } 601 }
635} 602}
636 603
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index c20f1dcfb7e2..1312a5e03ec7 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -15,39 +15,6 @@
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16#include "util/session.h" 16#include "util/session.h"
17 17
18struct perf_attr_details {
19 bool freq;
20 bool verbose;
21};
22
23static int comma_printf(bool *first, const char *fmt, ...)
24{
25 va_list args;
26 int ret = 0;
27
28 if (!*first) {
29 ret += printf(",");
30 } else {
31 ret += printf(":");
32 *first = false;
33 }
34
35 va_start(args, fmt);
36 ret += vprintf(fmt, args);
37 va_end(args);
38 return ret;
39}
40
41static int __if_print(bool *first, const char *field, u64 value)
42{
43 if (value == 0)
44 return 0;
45
46 return comma_printf(first, " %s: %" PRIu64, field, value);
47}
48
49#define if_print(field) __if_print(&first, #field, pos->attr.field)
50
51static int __cmd_evlist(const char *file_name, struct perf_attr_details *details) 18static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
52{ 19{
53 struct perf_session *session; 20 struct perf_session *session;
@@ -57,52 +24,8 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
57 if (session == NULL) 24 if (session == NULL)
58 return -ENOMEM; 25 return -ENOMEM;
59 26
60 list_for_each_entry(pos, &session->evlist->entries, node) { 27 list_for_each_entry(pos, &session->evlist->entries, node)
61 bool first = true; 28 perf_evsel__fprintf(pos, details, stdout);
62
63 printf("%s", perf_evsel__name(pos));
64
65 if (details->verbose || details->freq) {
66 comma_printf(&first, " sample_freq=%" PRIu64,
67 (u64)pos->attr.sample_freq);
68 }
69
70 if (details->verbose) {
71 if_print(type);
72 if_print(config);
73 if_print(config1);
74 if_print(config2);
75 if_print(size);
76 if_print(sample_type);
77 if_print(read_format);
78 if_print(disabled);
79 if_print(inherit);
80 if_print(pinned);
81 if_print(exclusive);
82 if_print(exclude_user);
83 if_print(exclude_kernel);
84 if_print(exclude_hv);
85 if_print(exclude_idle);
86 if_print(mmap);
87 if_print(comm);
88 if_print(freq);
89 if_print(inherit_stat);
90 if_print(enable_on_exec);
91 if_print(task);
92 if_print(watermark);
93 if_print(precise_ip);
94 if_print(mmap_data);
95 if_print(sample_id_all);
96 if_print(exclude_host);
97 if_print(exclude_guest);
98 if_print(__reserved_1);
99 if_print(wakeup_events);
100 if_print(bp_type);
101 if_print(branch_sample_type);
102 }
103
104 putchar('\n');
105 }
106 29
107 perf_session__delete(session); 30 perf_session__delete(session);
108 return 0; 31 return 0;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f3151d3c70ce..028de726b832 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -230,14 +230,7 @@ static int perf_record__open(struct perf_record *rec)
230 struct perf_record_opts *opts = &rec->opts; 230 struct perf_record_opts *opts = &rec->opts;
231 int rc = 0; 231 int rc = 0;
232 232
233 /* 233 perf_evlist__config(evlist, opts);
234 * Set the evsel leader links before we configure attributes,
235 * since some might depend on this info.
236 */
237 if (opts->group)
238 perf_evlist__set_leader(evlist);
239
240 perf_evlist__config_attrs(evlist, opts);
241 234
242 list_for_each_entry(pos, &evlist->entries, node) { 235 list_for_each_entry(pos, &evlist->entries, node) {
243 struct perf_event_attr *attr = &pos->attr; 236 struct perf_event_attr *attr = &pos->attr;
@@ -286,7 +279,7 @@ try_again:
286 */ 279 */
287 opts->sample_id_all_missing = true; 280 opts->sample_id_all_missing = true;
288 if (!opts->sample_time && !opts->raw_samples && !time_needed) 281 if (!opts->sample_time && !opts->raw_samples && !time_needed)
289 attr->sample_type &= ~PERF_SAMPLE_TIME; 282 perf_evsel__reset_sample_bit(pos, TIME);
290 283
291 goto retry_sample_id; 284 goto retry_sample_id;
292 } 285 }
@@ -875,11 +868,10 @@ static int get_stack_size(char *str, unsigned long *_size)
875} 868}
876#endif /* LIBUNWIND_SUPPORT */ 869#endif /* LIBUNWIND_SUPPORT */
877 870
878static int 871int record_parse_callchain_opt(const struct option *opt,
879parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, 872 const char *arg, int unset)
880 int unset)
881{ 873{
882 struct perf_record *rec = (struct perf_record *)opt->value; 874 struct perf_record_opts *opts = opt->value;
883 char *tok, *name, *saveptr = NULL; 875 char *tok, *name, *saveptr = NULL;
884 char *buf; 876 char *buf;
885 int ret = -1; 877 int ret = -1;
@@ -905,7 +897,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
905 /* Framepointer style */ 897 /* Framepointer style */
906 if (!strncmp(name, "fp", sizeof("fp"))) { 898 if (!strncmp(name, "fp", sizeof("fp"))) {
907 if (!strtok_r(NULL, ",", &saveptr)) { 899 if (!strtok_r(NULL, ",", &saveptr)) {
908 rec->opts.call_graph = CALLCHAIN_FP; 900 opts->call_graph = CALLCHAIN_FP;
909 ret = 0; 901 ret = 0;
910 } else 902 } else
911 pr_err("callchain: No more arguments " 903 pr_err("callchain: No more arguments "
@@ -918,20 +910,20 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
918 const unsigned long default_stack_dump_size = 8192; 910 const unsigned long default_stack_dump_size = 8192;
919 911
920 ret = 0; 912 ret = 0;
921 rec->opts.call_graph = CALLCHAIN_DWARF; 913 opts->call_graph = CALLCHAIN_DWARF;
922 rec->opts.stack_dump_size = default_stack_dump_size; 914 opts->stack_dump_size = default_stack_dump_size;
923 915
924 tok = strtok_r(NULL, ",", &saveptr); 916 tok = strtok_r(NULL, ",", &saveptr);
925 if (tok) { 917 if (tok) {
926 unsigned long size = 0; 918 unsigned long size = 0;
927 919
928 ret = get_stack_size(tok, &size); 920 ret = get_stack_size(tok, &size);
929 rec->opts.stack_dump_size = size; 921 opts->stack_dump_size = size;
930 } 922 }
931 923
932 if (!ret) 924 if (!ret)
933 pr_debug("callchain: stack dump size %d\n", 925 pr_debug("callchain: stack dump size %d\n",
934 rec->opts.stack_dump_size); 926 opts->stack_dump_size);
935#endif /* LIBUNWIND_SUPPORT */ 927#endif /* LIBUNWIND_SUPPORT */
936 } else { 928 } else {
937 pr_err("callchain: Unknown -g option " 929 pr_err("callchain: Unknown -g option "
@@ -944,7 +936,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
944 free(buf); 936 free(buf);
945 937
946 if (!ret) 938 if (!ret)
947 pr_debug("callchain: type %d\n", rec->opts.call_graph); 939 pr_debug("callchain: type %d\n", opts->call_graph);
948 940
949 return ret; 941 return ret;
950} 942}
@@ -982,9 +974,9 @@ static struct perf_record record = {
982#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " 974#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
983 975
984#ifdef LIBUNWIND_SUPPORT 976#ifdef LIBUNWIND_SUPPORT
985static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 977const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
986#else 978#else
987static const char callchain_help[] = CALLCHAIN_HELP "[fp]"; 979const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
988#endif 980#endif
989 981
990/* 982/*
@@ -1028,9 +1020,9 @@ const struct option record_options[] = {
1028 "number of mmap data pages"), 1020 "number of mmap data pages"),
1029 OPT_BOOLEAN(0, "group", &record.opts.group, 1021 OPT_BOOLEAN(0, "group", &record.opts.group,
1030 "put the counters into a counter group"), 1022 "put the counters into a counter group"),
1031 OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]", 1023 OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
1032 callchain_help, &parse_callchain_opt, 1024 "mode[,dump_size]", record_callchain_help,
1033 "fp"), 1025 &record_parse_callchain_opt, "fp"),
1034 OPT_INCR('v', "verbose", &verbose, 1026 OPT_INCR('v', "verbose", &verbose,
1035 "be more verbose (show counter open errors, etc)"), 1027 "be more verbose (show counter open errors, etc)"),
1036 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1028 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index fc251005dd3d..5134acf1c39a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -692,6 +692,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
692 setup_browser(true); 692 setup_browser(true);
693 else { 693 else {
694 use_browser = 0; 694 use_browser = 0;
695 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
695 perf_hpp__init(); 696 perf_hpp__init();
696 } 697 }
697 698
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c247faca7127..c12655af2b88 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -153,7 +153,7 @@ retry:
153 } 153 }
154 154
155 if (!perf_target__has_task(&target) && 155 if (!perf_target__has_task(&target) &&
156 !perf_evsel__is_group_member(evsel)) { 156 perf_evsel__is_group_leader(evsel)) {
157 attr->disabled = 1; 157 attr->disabled = 1;
158 attr->enable_on_exec = 1; 158 attr->enable_on_exec = 1;
159 } 159 }
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9ff3950cd4b..b7d2ea62dbc6 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -596,7 +596,7 @@ static void *display_thread_tui(void *arg)
596 * via --uid. 596 * via --uid.
597 */ 597 */
598 list_for_each_entry(pos, &top->evlist->entries, node) 598 list_for_each_entry(pos, &top->evlist->entries, node)
599 pos->hists.uid_filter_str = top->target.uid_str; 599 pos->hists.uid_filter_str = top->record_opts.target.uid_str;
600 600
601 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, 601 perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
602 &top->session->header.env); 602 &top->session->header.env);
@@ -727,7 +727,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
727 } 727 }
728 728
729 if (!machine) { 729 if (!machine) {
730 pr_err("%u unprocessable samples recorded.", 730 pr_err("%u unprocessable samples recorded.\n",
731 top->session->hists.stats.nr_unprocessable_samples++); 731 top->session->hists.stats.nr_unprocessable_samples++);
732 return; 732 return;
733 } 733 }
@@ -894,35 +894,13 @@ static void perf_top__start_counters(struct perf_top *top)
894{ 894{
895 struct perf_evsel *counter; 895 struct perf_evsel *counter;
896 struct perf_evlist *evlist = top->evlist; 896 struct perf_evlist *evlist = top->evlist;
897 struct perf_record_opts *opts = &top->record_opts;
897 898
898 if (top->group) 899 perf_evlist__config(evlist, opts);
899 perf_evlist__set_leader(evlist);
900 900
901 list_for_each_entry(counter, &evlist->entries, node) { 901 list_for_each_entry(counter, &evlist->entries, node) {
902 struct perf_event_attr *attr = &counter->attr; 902 struct perf_event_attr *attr = &counter->attr;
903 903
904 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
905
906 if (top->freq) {
907 attr->sample_type |= PERF_SAMPLE_PERIOD;
908 attr->freq = 1;
909 attr->sample_freq = top->freq;
910 }
911
912 if (evlist->nr_entries > 1) {
913 attr->sample_type |= PERF_SAMPLE_ID;
914 attr->read_format |= PERF_FORMAT_ID;
915 }
916
917 if (perf_target__has_cpu(&top->target))
918 attr->sample_type |= PERF_SAMPLE_CPU;
919
920 if (symbol_conf.use_callchain)
921 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
922
923 attr->mmap = 1;
924 attr->comm = 1;
925 attr->inherit = top->inherit;
926fallback_missing_features: 904fallback_missing_features:
927 if (top->exclude_guest_missing) 905 if (top->exclude_guest_missing)
928 attr->exclude_guest = attr->exclude_host = 0; 906 attr->exclude_guest = attr->exclude_host = 0;
@@ -996,7 +974,7 @@ try_again:
996 } 974 }
997 } 975 }
998 976
999 if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) { 977 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
1000 ui__error("Failed to mmap with %d (%s)\n", 978 ui__error("Failed to mmap with %d (%s)\n",
1001 errno, strerror(errno)); 979 errno, strerror(errno));
1002 goto out_err; 980 goto out_err;
@@ -1016,7 +994,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
1016 ui__error("Selected -g but \"sym\" not present in --sort/-s."); 994 ui__error("Selected -g but \"sym\" not present in --sort/-s.");
1017 return -EINVAL; 995 return -EINVAL;
1018 } 996 }
1019 } else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) { 997 } else if (callchain_param.mode != CHAIN_NONE) {
1020 if (callchain_register_param(&callchain_param) < 0) { 998 if (callchain_register_param(&callchain_param) < 0) {
1021 ui__error("Can't register callchain params.\n"); 999 ui__error("Can't register callchain params.\n");
1022 return -EINVAL; 1000 return -EINVAL;
@@ -1028,6 +1006,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
1028 1006
1029static int __cmd_top(struct perf_top *top) 1007static int __cmd_top(struct perf_top *top)
1030{ 1008{
1009 struct perf_record_opts *opts = &top->record_opts;
1031 pthread_t thread; 1010 pthread_t thread;
1032 int ret; 1011 int ret;
1033 /* 1012 /*
@@ -1042,7 +1021,7 @@ static int __cmd_top(struct perf_top *top)
1042 if (ret) 1021 if (ret)
1043 goto out_delete; 1022 goto out_delete;
1044 1023
1045 if (perf_target__has_task(&top->target)) 1024 if (perf_target__has_task(&opts->target))
1046 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 1025 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
1047 perf_event__process, 1026 perf_event__process,
1048 &top->session->host_machine); 1027 &top->session->host_machine);
@@ -1053,6 +1032,17 @@ static int __cmd_top(struct perf_top *top)
1053 top->session->evlist = top->evlist; 1032 top->session->evlist = top->evlist;
1054 perf_session__set_id_hdr_size(top->session); 1033 perf_session__set_id_hdr_size(top->session);
1055 1034
1035 /*
1036 * When perf is starting the traced process, all the events (apart from
1037 * group members) have enable_on_exec=1 set, so don't spoil it by
1038 * prematurely enabling them.
1039 *
1040 * XXX 'top' still doesn't start workloads like record, trace, but should,
1041 * so leave the check here.
1042 */
1043 if (!perf_target__none(&opts->target))
1044 perf_evlist__enable(top->evlist);
1045
1056 /* Wait for a minimal set of events before starting the snapshot */ 1046 /* Wait for a minimal set of events before starting the snapshot */
1057 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 1047 poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
1058 1048
@@ -1093,116 +1083,56 @@ out_delete:
1093static int 1083static int
1094parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1084parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1095{ 1085{
1096 struct perf_top *top = (struct perf_top *)opt->value;
1097 char *tok, *tok2;
1098 char *endptr;
1099
1100 /* 1086 /*
1101 * --no-call-graph 1087 * --no-call-graph
1102 */ 1088 */
1103 if (unset) { 1089 if (unset)
1104 top->dont_use_callchains = true;
1105 return 0; 1090 return 0;
1106 }
1107 1091
1108 symbol_conf.use_callchain = true; 1092 symbol_conf.use_callchain = true;
1109 1093
1110 if (!arg) 1094 return record_parse_callchain_opt(opt, arg, unset);
1111 return 0;
1112
1113 tok = strtok((char *)arg, ",");
1114 if (!tok)
1115 return -1;
1116
1117 /* get the output mode */
1118 if (!strncmp(tok, "graph", strlen(arg)))
1119 callchain_param.mode = CHAIN_GRAPH_ABS;
1120
1121 else if (!strncmp(tok, "flat", strlen(arg)))
1122 callchain_param.mode = CHAIN_FLAT;
1123
1124 else if (!strncmp(tok, "fractal", strlen(arg)))
1125 callchain_param.mode = CHAIN_GRAPH_REL;
1126
1127 else if (!strncmp(tok, "none", strlen(arg))) {
1128 callchain_param.mode = CHAIN_NONE;
1129 symbol_conf.use_callchain = false;
1130
1131 return 0;
1132 } else
1133 return -1;
1134
1135 /* get the min percentage */
1136 tok = strtok(NULL, ",");
1137 if (!tok)
1138 goto setup;
1139
1140 callchain_param.min_percent = strtod(tok, &endptr);
1141 if (tok == endptr)
1142 return -1;
1143
1144 /* get the print limit */
1145 tok2 = strtok(NULL, ",");
1146 if (!tok2)
1147 goto setup;
1148
1149 if (tok2[0] != 'c') {
1150 callchain_param.print_limit = strtod(tok2, &endptr);
1151 tok2 = strtok(NULL, ",");
1152 if (!tok2)
1153 goto setup;
1154 }
1155
1156 /* get the call chain order */
1157 if (!strcmp(tok2, "caller"))
1158 callchain_param.order = ORDER_CALLER;
1159 else if (!strcmp(tok2, "callee"))
1160 callchain_param.order = ORDER_CALLEE;
1161 else
1162 return -1;
1163setup:
1164 if (callchain_register_param(&callchain_param) < 0) {
1165 fprintf(stderr, "Can't register callchain params\n");
1166 return -1;
1167 }
1168 return 0;
1169} 1095}
1170 1096
1171int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1097int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1172{ 1098{
1173 struct perf_evsel *pos;
1174 int status; 1099 int status;
1175 char errbuf[BUFSIZ]; 1100 char errbuf[BUFSIZ];
1176 struct perf_top top = { 1101 struct perf_top top = {
1177 .count_filter = 5, 1102 .count_filter = 5,
1178 .delay_secs = 2, 1103 .delay_secs = 2,
1179 .freq = 4000, /* 4 KHz */ 1104 .record_opts = {
1180 .mmap_pages = 128, 1105 .mmap_pages = UINT_MAX,
1181 .sym_pcnt_filter = 5, 1106 .user_freq = UINT_MAX,
1182 .target = { 1107 .user_interval = ULLONG_MAX,
1183 .uses_mmap = true, 1108 .freq = 4000, /* 4 KHz */
1109 .target = {
1110 .uses_mmap = true,
1111 },
1184 }, 1112 },
1113 .sym_pcnt_filter = 5,
1185 }; 1114 };
1186 char callchain_default_opt[] = "fractal,0.5,callee"; 1115 struct perf_record_opts *opts = &top.record_opts;
1116 struct perf_target *target = &opts->target;
1187 const struct option options[] = { 1117 const struct option options[] = {
1188 OPT_CALLBACK('e', "event", &top.evlist, "event", 1118 OPT_CALLBACK('e', "event", &top.evlist, "event",
1189 "event selector. use 'perf list' to list available events", 1119 "event selector. use 'perf list' to list available events",
1190 parse_events_option), 1120 parse_events_option),
1191 OPT_INTEGER('c', "count", &top.default_interval, 1121 OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
1192 "event period to sample"), 1122 OPT_STRING('p', "pid", &target->pid, "pid",
1193 OPT_STRING('p', "pid", &top.target.pid, "pid",
1194 "profile events on existing process id"), 1123 "profile events on existing process id"),
1195 OPT_STRING('t', "tid", &top.target.tid, "tid", 1124 OPT_STRING('t', "tid", &target->tid, "tid",
1196 "profile events on existing thread id"), 1125 "profile events on existing thread id"),
1197 OPT_BOOLEAN('a', "all-cpus", &top.target.system_wide, 1126 OPT_BOOLEAN('a', "all-cpus", &target->system_wide,
1198 "system-wide collection from all CPUs"), 1127 "system-wide collection from all CPUs"),
1199 OPT_STRING('C', "cpu", &top.target.cpu_list, "cpu", 1128 OPT_STRING('C', "cpu", &target->cpu_list, "cpu",
1200 "list of cpus to monitor"), 1129 "list of cpus to monitor"),
1201 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1130 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1202 "file", "vmlinux pathname"), 1131 "file", "vmlinux pathname"),
1203 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1132 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1204 "hide kernel symbols"), 1133 "hide kernel symbols"),
1205 OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"), 1134 OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages,
1135 "number of mmap data pages"),
1206 OPT_INTEGER('r', "realtime", &top.realtime_prio, 1136 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1207 "collect data with this RT SCHED_FIFO priority"), 1137 "collect data with this RT SCHED_FIFO priority"),
1208 OPT_INTEGER('d', "delay", &top.delay_secs, 1138 OPT_INTEGER('d', "delay", &top.delay_secs,
@@ -1211,16 +1141,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1211 "dump the symbol table used for profiling"), 1141 "dump the symbol table used for profiling"),
1212 OPT_INTEGER('f', "count-filter", &top.count_filter, 1142 OPT_INTEGER('f', "count-filter", &top.count_filter,
1213 "only display functions with more events than this"), 1143 "only display functions with more events than this"),
1214 OPT_BOOLEAN('g', "group", &top.group, 1144 OPT_BOOLEAN('g', "group", &opts->group,
1215 "put the counters into a counter group"), 1145 "put the counters into a counter group"),
1216 OPT_BOOLEAN('i', "inherit", &top.inherit, 1146 OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
1217 "child tasks inherit counters"), 1147 "child tasks do not inherit counters"),
1218 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name", 1148 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
1219 "symbol to annotate"), 1149 "symbol to annotate"),
1220 OPT_BOOLEAN('z', "zero", &top.zero, 1150 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
1221 "zero history across updates"), 1151 OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"),
1222 OPT_INTEGER('F', "freq", &top.freq,
1223 "profile at this frequency"),
1224 OPT_INTEGER('E', "entries", &top.print_entries, 1152 OPT_INTEGER('E', "entries", &top.print_entries,
1225 "display this many functions"), 1153 "display this many functions"),
1226 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1154 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
@@ -1233,10 +1161,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1233 "sort by key(s): pid, comm, dso, symbol, parent"), 1161 "sort by key(s): pid, comm, dso, symbol, parent"),
1234 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1162 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1235 "Show a column with the number of samples"), 1163 "Show a column with the number of samples"),
1236 OPT_CALLBACK_DEFAULT('G', "call-graph", &top, "output_type,min_percent, call_order", 1164 OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
1237 "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. " 1165 "mode[,dump_size]", record_callchain_help,
1238 "Default: fractal,0.5,callee", &parse_callchain_opt, 1166 &parse_callchain_opt, "fp"),
1239 callchain_default_opt),
1240 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 1167 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1241 "Show a column with the sum of periods"), 1168 "Show a column with the sum of periods"),
1242 OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 1169 OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -1251,7 +1178,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1251 "Display raw encoding of assembly instructions (default)"), 1178 "Display raw encoding of assembly instructions (default)"),
1252 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1179 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1253 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1180 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1254 OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"), 1181 OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
1255 OPT_END() 1182 OPT_END()
1256 }; 1183 };
1257 const char * const top_usage[] = { 1184 const char * const top_usage[] = {
@@ -1281,27 +1208,27 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1281 1208
1282 setup_browser(false); 1209 setup_browser(false);
1283 1210
1284 status = perf_target__validate(&top.target); 1211 status = perf_target__validate(target);
1285 if (status) { 1212 if (status) {
1286 perf_target__strerror(&top.target, status, errbuf, BUFSIZ); 1213 perf_target__strerror(target, status, errbuf, BUFSIZ);
1287 ui__warning("%s", errbuf); 1214 ui__warning("%s", errbuf);
1288 } 1215 }
1289 1216
1290 status = perf_target__parse_uid(&top.target); 1217 status = perf_target__parse_uid(target);
1291 if (status) { 1218 if (status) {
1292 int saved_errno = errno; 1219 int saved_errno = errno;
1293 1220
1294 perf_target__strerror(&top.target, status, errbuf, BUFSIZ); 1221 perf_target__strerror(target, status, errbuf, BUFSIZ);
1295 ui__error("%s", errbuf); 1222 ui__error("%s", errbuf);
1296 1223
1297 status = -saved_errno; 1224 status = -saved_errno;
1298 goto out_delete_evlist; 1225 goto out_delete_evlist;
1299 } 1226 }
1300 1227
1301 if (perf_target__none(&top.target)) 1228 if (perf_target__none(target))
1302 top.target.system_wide = true; 1229 target->system_wide = true;
1303 1230
1304 if (perf_evlist__create_maps(top.evlist, &top.target) < 0) 1231 if (perf_evlist__create_maps(top.evlist, target) < 0)
1305 usage_with_options(top_usage, options); 1232 usage_with_options(top_usage, options);
1306 1233
1307 if (!top.evlist->nr_entries && 1234 if (!top.evlist->nr_entries &&
@@ -1315,24 +1242,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1315 if (top.delay_secs < 1) 1242 if (top.delay_secs < 1)
1316 top.delay_secs = 1; 1243 top.delay_secs = 1;
1317 1244
1245 if (opts->user_interval != ULLONG_MAX)
1246 opts->default_interval = opts->user_interval;
1247 if (opts->user_freq != UINT_MAX)
1248 opts->freq = opts->user_freq;
1249
1318 /* 1250 /*
1319 * User specified count overrides default frequency. 1251 * User specified count overrides default frequency.
1320 */ 1252 */
1321 if (top.default_interval) 1253 if (opts->default_interval)
1322 top.freq = 0; 1254 opts->freq = 0;
1323 else if (top.freq) { 1255 else if (opts->freq) {
1324 top.default_interval = top.freq; 1256 opts->default_interval = opts->freq;
1325 } else { 1257 } else {
1326 ui__error("frequency and count are zero, aborting\n"); 1258 ui__error("frequency and count are zero, aborting\n");
1327 exit(EXIT_FAILURE); 1259 status = -EINVAL;
1328 } 1260 goto out_delete_evlist;
1329
1330 list_for_each_entry(pos, &top.evlist->entries, node) {
1331 /*
1332 * Fill in the ones not specifically initialized via -c:
1333 */
1334 if (!pos->attr.sample_period)
1335 pos->attr.sample_period = top.default_interval;
1336 } 1261 }
1337 1262
1338 top.sym_evsel = perf_evlist__first(top.evlist); 1263 top.sym_evsel = perf_evlist__first(top.evlist);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 7932ffa29889..d222d7fc7e96 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -455,7 +455,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
455 goto out_delete_evlist; 455 goto out_delete_evlist;
456 } 456 }
457 457
458 perf_evlist__config_attrs(evlist, &trace->opts); 458 perf_evlist__config(evlist, &trace->opts);
459 459
460 signal(SIGCHLD, sig_handler); 460 signal(SIGCHLD, sig_handler);
461 signal(SIGINT, sig_handler); 461 signal(SIGINT, sig_handler);
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index f1485d8e6a0b..5bc3880f7be5 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -7,7 +7,7 @@ size=96
7config=0 7config=0
8sample_period=4000 8sample_period=4000
9sample_type=263 9sample_type=263
10read_format=7 10read_format=0
11disabled=1 11disabled=1
12inherit=1 12inherit=1
13pinned=0 13pinned=0
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group
index a6599e9a19d3..57739cacdb2a 100644
--- a/tools/perf/tests/attr/test-record-group
+++ b/tools/perf/tests/attr/test-record-group
@@ -6,12 +6,14 @@ args = --group -e cycles,instructions kill >/dev/null 2>&1
6fd=1 6fd=1
7group_fd=-1 7group_fd=-1
8sample_type=327 8sample_type=327
9read_format=4
9 10
10[event-2:base-record] 11[event-2:base-record]
11fd=2 12fd=2
12group_fd=1 13group_fd=1
13config=1 14config=1
14sample_type=327 15sample_type=327
16read_format=4
15mmap=0 17mmap=0
16comm=0 18comm=0
17enable_on_exec=0 19enable_on_exec=0
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index 5a8359da38af..4d688a13fd2f 100644
--- a/tools/perf/tests/attr/test-record-group1
+++ b/tools/perf/tests/attr/test-record-group1
@@ -6,6 +6,7 @@ args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1
6fd=1 6fd=1
7group_fd=-1 7group_fd=-1
8sample_type=327 8sample_type=327
9read_format=4
9 10
10[event-2:base-record] 11[event-2:base-record]
11fd=2 12fd=2
@@ -13,6 +14,7 @@ group_fd=1
13type=0 14type=0
14config=1 15config=1
15sample_type=327 16sample_type=327
17read_format=4
16mmap=0 18mmap=0
17comm=0 19comm=0
18enable_on_exec=0 20enable_on_exec=0
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index e1746811e14b..cdd50755af51 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -22,36 +22,16 @@ int test__basic_mmap(void)
22 struct thread_map *threads; 22 struct thread_map *threads;
23 struct cpu_map *cpus; 23 struct cpu_map *cpus;
24 struct perf_evlist *evlist; 24 struct perf_evlist *evlist;
25 struct perf_event_attr attr = {
26 .type = PERF_TYPE_TRACEPOINT,
27 .read_format = PERF_FORMAT_ID,
28 .sample_type = PERF_SAMPLE_ID,
29 .watermark = 0,
30 };
31 cpu_set_t cpu_set; 25 cpu_set_t cpu_set;
32 const char *syscall_names[] = { "getsid", "getppid", "getpgrp", 26 const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
33 "getpgid", }; 27 "getpgid", };
34 pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp, 28 pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
35 (void*)getpgid }; 29 (void*)getpgid };
36#define nsyscalls ARRAY_SIZE(syscall_names) 30#define nsyscalls ARRAY_SIZE(syscall_names)
37 int ids[nsyscalls];
38 unsigned int nr_events[nsyscalls], 31 unsigned int nr_events[nsyscalls],
39 expected_nr_events[nsyscalls], i, j; 32 expected_nr_events[nsyscalls], i, j;
40 struct perf_evsel *evsels[nsyscalls], *evsel; 33 struct perf_evsel *evsels[nsyscalls], *evsel;
41 34
42 for (i = 0; i < nsyscalls; ++i) {
43 char name[64];
44
45 snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
46 ids[i] = trace_event__id(name);
47 if (ids[i] < 0) {
48 pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
49 return -1;
50 }
51 nr_events[i] = 0;
52 expected_nr_events[i] = random() % 257;
53 }
54
55 threads = thread_map__new(-1, getpid(), UINT_MAX); 35 threads = thread_map__new(-1, getpid(), UINT_MAX);
56 if (threads == NULL) { 36 if (threads == NULL) {
57 pr_debug("thread_map__new\n"); 37 pr_debug("thread_map__new\n");
@@ -79,18 +59,19 @@ int test__basic_mmap(void)
79 goto out_free_cpus; 59 goto out_free_cpus;
80 } 60 }
81 61
82 /* anonymous union fields, can't be initialized above */
83 attr.wakeup_events = 1;
84 attr.sample_period = 1;
85
86 for (i = 0; i < nsyscalls; ++i) { 62 for (i = 0; i < nsyscalls; ++i) {
87 attr.config = ids[i]; 63 char name[64];
88 evsels[i] = perf_evsel__new(&attr, i); 64
65 snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
66 evsels[i] = perf_evsel__newtp("syscalls", name, i);
89 if (evsels[i] == NULL) { 67 if (evsels[i] == NULL) {
90 pr_debug("perf_evsel__new\n"); 68 pr_debug("perf_evsel__new\n");
91 goto out_free_evlist; 69 goto out_free_evlist;
92 } 70 }
93 71
72 evsels[i]->attr.wakeup_events = 1;
73 perf_evsel__set_sample_id(evsels[i]);
74
94 perf_evlist__add(evlist, evsels[i]); 75 perf_evlist__add(evlist, evsels[i]);
95 76
96 if (perf_evsel__open(evsels[i], cpus, threads) < 0) { 77 if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
@@ -99,6 +80,9 @@ int test__basic_mmap(void)
99 strerror(errno)); 80 strerror(errno));
100 goto out_close_fd; 81 goto out_close_fd;
101 } 82 }
83
84 nr_events[i] = 0;
85 expected_nr_events[i] = 1 + rand() % 127;
102 } 86 }
103 87
104 if (perf_evlist__mmap(evlist, 128, true) < 0) { 88 if (perf_evlist__mmap(evlist, 128, true) < 0) {
@@ -128,6 +112,7 @@ int test__basic_mmap(void)
128 goto out_munmap; 112 goto out_munmap;
129 } 113 }
130 114
115 err = -1;
131 evsel = perf_evlist__id2evsel(evlist, sample.id); 116 evsel = perf_evlist__id2evsel(evlist, sample.id);
132 if (evsel == NULL) { 117 if (evsel == NULL) {
133 pr_debug("event with id %" PRIu64 118 pr_debug("event with id %" PRIu64
@@ -137,16 +122,17 @@ int test__basic_mmap(void)
137 nr_events[evsel->idx]++; 122 nr_events[evsel->idx]++;
138 } 123 }
139 124
125 err = 0;
140 list_for_each_entry(evsel, &evlist->entries, node) { 126 list_for_each_entry(evsel, &evlist->entries, node) {
141 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 127 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
142 pr_debug("expected %d %s events, got %d\n", 128 pr_debug("expected %d %s events, got %d\n",
143 expected_nr_events[evsel->idx], 129 expected_nr_events[evsel->idx],
144 perf_evsel__name(evsel), nr_events[evsel->idx]); 130 perf_evsel__name(evsel), nr_events[evsel->idx]);
131 err = -1;
145 goto out_munmap; 132 goto out_munmap;
146 } 133 }
147 } 134 }
148 135
149 err = 0;
150out_munmap: 136out_munmap:
151 perf_evlist__munmap(evlist); 137 perf_evlist__munmap(evlist);
152out_close_fd: 138out_close_fd:
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
index 31072aba0d54..9b920a0cce79 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -7,20 +7,12 @@
7int test__open_syscall_event_on_all_cpus(void) 7int test__open_syscall_event_on_all_cpus(void)
8{ 8{
9 int err = -1, fd, cpu; 9 int err = -1, fd, cpu;
10 struct thread_map *threads;
11 struct cpu_map *cpus; 10 struct cpu_map *cpus;
12 struct perf_evsel *evsel; 11 struct perf_evsel *evsel;
13 struct perf_event_attr attr;
14 unsigned int nr_open_calls = 111, i; 12 unsigned int nr_open_calls = 111, i;
15 cpu_set_t cpu_set; 13 cpu_set_t cpu_set;
16 int id = trace_event__id("sys_enter_open"); 14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
17 15
18 if (id < 0) {
19 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
20 return -1;
21 }
22
23 threads = thread_map__new(-1, getpid(), UINT_MAX);
24 if (threads == NULL) { 16 if (threads == NULL) {
25 pr_debug("thread_map__new\n"); 17 pr_debug("thread_map__new\n");
26 return -1; 18 return -1;
@@ -32,15 +24,11 @@ int test__open_syscall_event_on_all_cpus(void)
32 goto out_thread_map_delete; 24 goto out_thread_map_delete;
33 } 25 }
34 26
35
36 CPU_ZERO(&cpu_set); 27 CPU_ZERO(&cpu_set);
37 28
38 memset(&attr, 0, sizeof(attr)); 29 evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
39 attr.type = PERF_TYPE_TRACEPOINT;
40 attr.config = id;
41 evsel = perf_evsel__new(&attr, 0);
42 if (evsel == NULL) { 30 if (evsel == NULL) {
43 pr_debug("perf_evsel__new\n"); 31 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
44 goto out_thread_map_delete; 32 goto out_thread_map_delete;
45 } 33 }
46 34
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
index 98be8b518b4f..befc0671f95d 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/open-syscall.c
@@ -6,29 +6,18 @@
6int test__open_syscall_event(void) 6int test__open_syscall_event(void)
7{ 7{
8 int err = -1, fd; 8 int err = -1, fd;
9 struct thread_map *threads;
10 struct perf_evsel *evsel; 9 struct perf_evsel *evsel;
11 struct perf_event_attr attr;
12 unsigned int nr_open_calls = 111, i; 10 unsigned int nr_open_calls = 111, i;
13 int id = trace_event__id("sys_enter_open"); 11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
14 12
15 if (id < 0) {
16 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
17 return -1;
18 }
19
20 threads = thread_map__new(-1, getpid(), UINT_MAX);
21 if (threads == NULL) { 13 if (threads == NULL) {
22 pr_debug("thread_map__new\n"); 14 pr_debug("thread_map__new\n");
23 return -1; 15 return -1;
24 } 16 }
25 17
26 memset(&attr, 0, sizeof(attr)); 18 evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
27 attr.type = PERF_TYPE_TRACEPOINT;
28 attr.config = id;
29 evsel = perf_evsel__new(&attr, 0);
30 if (evsel == NULL) { 19 if (evsel == NULL) {
31 pr_debug("perf_evsel__new\n"); 20 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
32 goto out_thread_map_delete; 21 goto out_thread_map_delete;
33 } 22 }
34 23
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 32ee478905eb..294ffddfbf42 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -521,7 +521,7 @@ static int test__group1(struct perf_evlist *evlist)
521 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 521 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
522 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 522 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
523 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 523 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
524 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 524 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
525 525
526 /* cycles:upp */ 526 /* cycles:upp */
527 evsel = perf_evsel__next(evsel); 527 evsel = perf_evsel__next(evsel);
@@ -557,7 +557,7 @@ static int test__group2(struct perf_evlist *evlist)
557 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 557 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
558 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 558 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
559 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 559 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
560 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 560 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
561 561
562 /* cache-references + :u modifier */ 562 /* cache-references + :u modifier */
563 evsel = perf_evsel__next(evsel); 563 evsel = perf_evsel__next(evsel);
@@ -583,7 +583,7 @@ static int test__group2(struct perf_evlist *evlist)
583 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 583 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
584 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 584 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
585 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 585 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
586 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 586 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
587 587
588 return 0; 588 return 0;
589} 589}
@@ -606,7 +606,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
606 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); 606 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
607 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 607 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
608 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 608 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
609 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 609 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
610 TEST_ASSERT_VAL("wrong group name", 610 TEST_ASSERT_VAL("wrong group name",
611 !strcmp(leader->group_name, "group1")); 611 !strcmp(leader->group_name, "group1"));
612 612
@@ -636,7 +636,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
636 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 636 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
637 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); 637 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
638 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 638 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
639 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 639 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
640 TEST_ASSERT_VAL("wrong group name", 640 TEST_ASSERT_VAL("wrong group name",
641 !strcmp(leader->group_name, "group2")); 641 !strcmp(leader->group_name, "group2"));
642 642
@@ -663,7 +663,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
663 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 663 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
664 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 664 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
665 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 665 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
666 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 666 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
667 667
668 return 0; 668 return 0;
669} 669}
@@ -687,7 +687,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
687 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 687 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
688 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); 688 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
689 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 689 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
690 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 690 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
691 691
692 /* instructions:kp + p */ 692 /* instructions:kp + p */
693 evsel = perf_evsel__next(evsel); 693 evsel = perf_evsel__next(evsel);
@@ -724,7 +724,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
724 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); 724 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
725 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 725 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
726 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 726 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
727 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 727 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
728 728
729 /* instructions + G */ 729 /* instructions + G */
730 evsel = perf_evsel__next(evsel); 730 evsel = perf_evsel__next(evsel);
@@ -751,7 +751,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
751 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); 751 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
752 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 752 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
753 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 753 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
754 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 754 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
755 755
756 /* instructions:G */ 756 /* instructions:G */
757 evsel = perf_evsel__next(evsel); 757 evsel = perf_evsel__next(evsel);
@@ -777,7 +777,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
777 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); 777 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
778 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 778 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
779 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 779 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
780 TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); 780 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
781 781
782 return 0; 782 return 0;
783} 783}
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 70e0d4421df8..6ea66cf6791b 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -103,10 +103,10 @@ int test__PERF_RECORD(void)
103 * Config the evsels, setting attr->comm on the first one, etc. 103 * Config the evsels, setting attr->comm on the first one, etc.
104 */ 104 */
105 evsel = perf_evlist__first(evlist); 105 evsel = perf_evlist__first(evlist);
106 evsel->attr.sample_type |= PERF_SAMPLE_CPU; 106 perf_evsel__set_sample_bit(evsel, CPU);
107 evsel->attr.sample_type |= PERF_SAMPLE_TID; 107 perf_evsel__set_sample_bit(evsel, TID);
108 evsel->attr.sample_type |= PERF_SAMPLE_TIME; 108 perf_evsel__set_sample_bit(evsel, TIME);
109 perf_evlist__config_attrs(evlist, &opts); 109 perf_evlist__config(evlist, &opts);
110 110
111 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); 111 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
112 if (err < 0) { 112 if (err < 0) {
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index fc121edab016..0fd94657960e 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -16,7 +16,4 @@ int test__attr(void);
16int test__dso_data(void); 16int test__dso_data(void);
17int test__parse_events(void); 17int test__parse_events(void);
18 18
19/* Util */
20int trace_event__id(const char *evname);
21
22#endif /* TESTS_H */ 19#endif /* TESTS_H */
diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c
deleted file mode 100644
index 748f2e8f6961..000000000000
--- a/tools/perf/tests/util.c
+++ /dev/null
@@ -1,30 +0,0 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <fcntl.h>
7#include "tests.h"
8#include "debugfs.h"
9
10int trace_event__id(const char *evname)
11{
12 char *filename;
13 int err = -1, fd;
14
15 if (asprintf(&filename,
16 "%s/syscalls/%s/id",
17 tracing_events_path, evname) < 0)
18 return -1;
19
20 fd = open(filename, O_RDONLY);
21 if (fd >= 0) {
22 char id[16];
23 if (read(fd, id, sizeof(id)) > 0)
24 err = atoi(id);
25 close(fd);
26 }
27
28 free(filename);
29 return err;
30}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index ccc4bd161420..57b82c26cd05 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -587,6 +587,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
587 587
588void hist_browser__init_hpp(void) 588void hist_browser__init_hpp(void)
589{ 589{
590 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
591
590 perf_hpp__init(); 592 perf_hpp__init();
591 593
592 perf_hpp__format[PERF_HPP__OVERHEAD].color = 594 perf_hpp__format[PERF_HPP__OVERHEAD].color =
@@ -607,12 +609,13 @@ static int hist_browser__show_entry(struct hist_browser *browser,
607{ 609{
608 char s[256]; 610 char s[256];
609 double percent; 611 double percent;
610 int i, printed = 0; 612 int printed = 0;
611 int width = browser->b.width; 613 int width = browser->b.width;
612 char folded_sign = ' '; 614 char folded_sign = ' ';
613 bool current_entry = ui_browser__is_current_entry(&browser->b, row); 615 bool current_entry = ui_browser__is_current_entry(&browser->b, row);
614 off_t row_offset = entry->row_offset; 616 off_t row_offset = entry->row_offset;
615 bool first = true; 617 bool first = true;
618 struct perf_hpp_fmt *fmt;
616 619
617 if (current_entry) { 620 if (current_entry) {
618 browser->he_selection = entry; 621 browser->he_selection = entry;
@@ -629,12 +632,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
629 .buf = s, 632 .buf = s,
630 .size = sizeof(s), 633 .size = sizeof(s),
631 }; 634 };
635 int i = 0;
632 636
633 ui_browser__gotorc(&browser->b, row, 0); 637 ui_browser__gotorc(&browser->b, row, 0);
634 638
635 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 639 perf_hpp__for_each_format(fmt) {
636 if (!perf_hpp__format[i].cond)
637 continue;
638 640
639 if (!first) { 641 if (!first) {
640 slsmg_printf(" "); 642 slsmg_printf(" ");
@@ -642,14 +644,14 @@ static int hist_browser__show_entry(struct hist_browser *browser,
642 } 644 }
643 first = false; 645 first = false;
644 646
645 if (perf_hpp__format[i].color) { 647 if (fmt->color) {
646 hpp.ptr = &percent; 648 hpp.ptr = &percent;
647 /* It will set percent for us. See HPP__COLOR_FN above. */ 649 /* It will set percent for us. See HPP__COLOR_FN above. */
648 width -= perf_hpp__format[i].color(&hpp, entry); 650 width -= fmt->color(&hpp, entry);
649 651
650 ui_browser__set_percent_color(&browser->b, percent, current_entry); 652 ui_browser__set_percent_color(&browser->b, percent, current_entry);
651 653
652 if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) { 654 if (!i && symbol_conf.use_callchain) {
653 slsmg_printf("%c ", folded_sign); 655 slsmg_printf("%c ", folded_sign);
654 width -= 2; 656 width -= 2;
655 } 657 }
@@ -659,9 +661,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
659 if (!current_entry || !browser->b.navkeypressed) 661 if (!current_entry || !browser->b.navkeypressed)
660 ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); 662 ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL);
661 } else { 663 } else {
662 width -= perf_hpp__format[i].entry(&hpp, entry); 664 width -= fmt->entry(&hpp, entry);
663 slsmg_printf("%s", s); 665 slsmg_printf("%s", s);
664 } 666 }
667
668 i++;
665 } 669 }
666 670
667 /* The scroll bar isn't being used */ 671 /* The scroll bar isn't being used */
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 253b6219a39e..e59ba337f494 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -74,6 +74,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
74 74
75void perf_gtk__init_hpp(void) 75void perf_gtk__init_hpp(void)
76{ 76{
77 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
78
77 perf_hpp__init(); 79 perf_hpp__init();
78 80
79 perf_hpp__format[PERF_HPP__OVERHEAD].color = 81 perf_hpp__format[PERF_HPP__OVERHEAD].color =
@@ -90,13 +92,14 @@ void perf_gtk__init_hpp(void)
90 92
91static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) 93static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
92{ 94{
95 struct perf_hpp_fmt *fmt;
93 GType col_types[MAX_COLUMNS]; 96 GType col_types[MAX_COLUMNS];
94 GtkCellRenderer *renderer; 97 GtkCellRenderer *renderer;
95 struct sort_entry *se; 98 struct sort_entry *se;
96 GtkListStore *store; 99 GtkListStore *store;
97 struct rb_node *nd; 100 struct rb_node *nd;
98 GtkWidget *view; 101 GtkWidget *view;
99 int i, col_idx; 102 int col_idx;
100 int nr_cols; 103 int nr_cols;
101 char s[512]; 104 char s[512];
102 105
@@ -107,12 +110,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
107 110
108 nr_cols = 0; 111 nr_cols = 0;
109 112
110 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 113 perf_hpp__for_each_format(fmt)
111 if (!perf_hpp__format[i].cond)
112 continue;
113
114 col_types[nr_cols++] = G_TYPE_STRING; 114 col_types[nr_cols++] = G_TYPE_STRING;
115 }
116 115
117 list_for_each_entry(se, &hist_entry__sort_list, list) { 116 list_for_each_entry(se, &hist_entry__sort_list, list) {
118 if (se->elide) 117 if (se->elide)
@@ -129,12 +128,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
129 128
130 col_idx = 0; 129 col_idx = 0;
131 130
132 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 131 perf_hpp__for_each_format(fmt) {
133 if (!perf_hpp__format[i].cond) 132 fmt->header(&hpp);
134 continue;
135
136 perf_hpp__format[i].header(&hpp);
137
138 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), 133 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
139 -1, s, 134 -1, s,
140 renderer, "markup", 135 renderer, "markup",
@@ -166,14 +161,11 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
166 161
167 col_idx = 0; 162 col_idx = 0;
168 163
169 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 164 perf_hpp__for_each_format(fmt) {
170 if (!perf_hpp__format[i].cond) 165 if (fmt->color)
171 continue; 166 fmt->color(&hpp, h);
172
173 if (perf_hpp__format[i].color)
174 perf_hpp__format[i].color(&hpp, h);
175 else 167 else
176 perf_hpp__format[i].entry(&hpp, h); 168 fmt->entry(&hpp, h);
177 169
178 gtk_list_store_set(store, &iter, col_idx++, s, -1); 170 gtk_list_store_set(store, &iter, col_idx++, s, -1);
179 } 171 }
diff --git a/tools/perf/ui/gtk/helpline.c b/tools/perf/ui/gtk/helpline.c
index 5db4432ff12a..3388cbd12186 100644
--- a/tools/perf/ui/gtk/helpline.c
+++ b/tools/perf/ui/gtk/helpline.c
@@ -24,17 +24,7 @@ static void gtk_helpline_push(const char *msg)
24 pgctx->statbar_ctx_id, msg); 24 pgctx->statbar_ctx_id, msg);
25} 25}
26 26
27static struct ui_helpline gtk_helpline_fns = { 27static int gtk_helpline_show(const char *fmt, va_list ap)
28 .pop = gtk_helpline_pop,
29 .push = gtk_helpline_push,
30};
31
32void perf_gtk__init_helpline(void)
33{
34 helpline_fns = &gtk_helpline_fns;
35}
36
37int perf_gtk__show_helpline(const char *fmt, va_list ap)
38{ 28{
39 int ret; 29 int ret;
40 char *ptr; 30 char *ptr;
@@ -54,3 +44,14 @@ int perf_gtk__show_helpline(const char *fmt, va_list ap)
54 44
55 return ret; 45 return ret;
56} 46}
47
48static struct ui_helpline gtk_helpline_fns = {
49 .pop = gtk_helpline_pop,
50 .push = gtk_helpline_push,
51 .show = gtk_helpline_show,
52};
53
54void perf_gtk__init_helpline(void)
55{
56 helpline_fns = &gtk_helpline_fns;
57}
diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c
index a49bcf3c190b..700fb3cfa1c7 100644
--- a/tools/perf/ui/helpline.c
+++ b/tools/perf/ui/helpline.c
@@ -16,9 +16,16 @@ static void nop_helpline__push(const char *msg __maybe_unused)
16{ 16{
17} 17}
18 18
19static int nop_helpline__show(const char *fmt __maybe_unused,
20 va_list ap __maybe_unused)
21{
22 return 0;
23}
24
19static struct ui_helpline default_helpline_fns = { 25static struct ui_helpline default_helpline_fns = {
20 .pop = nop_helpline__pop, 26 .pop = nop_helpline__pop,
21 .push = nop_helpline__push, 27 .push = nop_helpline__push,
28 .show = nop_helpline__show,
22}; 29};
23 30
24struct ui_helpline *helpline_fns = &default_helpline_fns; 31struct ui_helpline *helpline_fns = &default_helpline_fns;
@@ -59,3 +66,8 @@ void ui_helpline__puts(const char *msg)
59 ui_helpline__pop(); 66 ui_helpline__pop();
60 ui_helpline__push(msg); 67 ui_helpline__push(msg);
61} 68}
69
70int ui_helpline__vshow(const char *fmt, va_list ap)
71{
72 return helpline_fns->show(fmt, ap);
73}
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index baa28a4d16b9..46181f4fc07e 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -9,6 +9,7 @@
9struct ui_helpline { 9struct ui_helpline {
10 void (*pop)(void); 10 void (*pop)(void);
11 void (*push)(const char *msg); 11 void (*push)(const char *msg);
12 int (*show)(const char *fmt, va_list ap);
12}; 13};
13 14
14extern struct ui_helpline *helpline_fns; 15extern struct ui_helpline *helpline_fns;
@@ -20,28 +21,9 @@ void ui_helpline__push(const char *msg);
20void ui_helpline__vpush(const char *fmt, va_list ap); 21void ui_helpline__vpush(const char *fmt, va_list ap);
21void ui_helpline__fpush(const char *fmt, ...); 22void ui_helpline__fpush(const char *fmt, ...);
22void ui_helpline__puts(const char *msg); 23void ui_helpline__puts(const char *msg);
24int ui_helpline__vshow(const char *fmt, va_list ap);
23 25
24extern char ui_helpline__current[512]; 26extern char ui_helpline__current[512];
25
26#ifdef NEWT_SUPPORT
27extern char ui_helpline__last_msg[]; 27extern char ui_helpline__last_msg[];
28int ui_helpline__show_help(const char *format, va_list ap);
29#else
30static inline int ui_helpline__show_help(const char *format __maybe_unused,
31 va_list ap __maybe_unused)
32{
33 return 0;
34}
35#endif /* NEWT_SUPPORT */
36
37#ifdef GTK2_SUPPORT
38int perf_gtk__show_helpline(const char *format, va_list ap);
39#else
40static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
41 va_list ap __maybe_unused)
42{
43 return 0;
44}
45#endif /* GTK2_SUPPORT */
46 28
47#endif /* _PERF_UI_HELPLINE_H_ */ 29#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index aa84130024d5..1889c12ca81f 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -268,14 +268,18 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
268 268
269static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) 269static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
270{ 270{
271 struct hist_entry *pair = hist_entry__next_pair(he);
271 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; 272 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
272 char buf[32] = " "; 273 char buf[32] = " ";
273 double diff; 274 double diff = 0.0;
274 275
275 if (he->diff.computed) 276 if (pair) {
276 diff = he->diff.period_ratio_delta; 277 if (he->diff.computed)
277 else 278 diff = he->diff.period_ratio_delta;
278 diff = perf_diff__compute_delta(he); 279 else
280 diff = perf_diff__compute_delta(he, pair);
281 } else
282 diff = perf_diff__period_percent(he, he->stat.period);
279 283
280 if (fabs(diff) >= 0.01) 284 if (fabs(diff) >= 0.01)
281 scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); 285 scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
@@ -297,14 +301,17 @@ static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)
297 301
298static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he) 302static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
299{ 303{
304 struct hist_entry *pair = hist_entry__next_pair(he);
300 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; 305 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
301 char buf[32] = " "; 306 char buf[32] = " ";
302 double ratio; 307 double ratio = 0.0;
303 308
304 if (he->diff.computed) 309 if (pair) {
305 ratio = he->diff.period_ratio; 310 if (he->diff.computed)
306 else 311 ratio = he->diff.period_ratio;
307 ratio = perf_diff__compute_ratio(he); 312 else
313 ratio = perf_diff__compute_ratio(he, pair);
314 }
308 315
309 if (ratio > 0.0) 316 if (ratio > 0.0)
310 scnprintf(buf, sizeof(buf), "%+14.6F", ratio); 317 scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
@@ -326,14 +333,17 @@ static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)
326 333
327static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he) 334static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
328{ 335{
336 struct hist_entry *pair = hist_entry__next_pair(he);
329 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; 337 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
330 char buf[32] = " "; 338 char buf[32] = " ";
331 s64 wdiff; 339 s64 wdiff = 0;
332 340
333 if (he->diff.computed) 341 if (pair) {
334 wdiff = he->diff.wdiff; 342 if (he->diff.computed)
335 else 343 wdiff = he->diff.wdiff;
336 wdiff = perf_diff__compute_wdiff(he); 344 else
345 wdiff = perf_diff__compute_wdiff(he, pair);
346 }
337 347
338 if (wdiff != 0) 348 if (wdiff != 0)
339 scnprintf(buf, sizeof(buf), "%14ld", wdiff); 349 scnprintf(buf, sizeof(buf), "%14ld", wdiff);
@@ -341,30 +351,6 @@ static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
341 return scnprintf(hpp->buf, hpp->size, fmt, buf); 351 return scnprintf(hpp->buf, hpp->size, fmt, buf);
342} 352}
343 353
344static int hpp__header_displ(struct perf_hpp *hpp)
345{
346 return scnprintf(hpp->buf, hpp->size, "Displ.");
347}
348
349static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
350{
351 return 6;
352}
353
354static int hpp__entry_displ(struct perf_hpp *hpp,
355 struct hist_entry *he)
356{
357 struct hist_entry *pair = hist_entry__next_pair(he);
358 long displacement = pair ? pair->position - he->position : 0;
359 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
360 char buf[32] = " ";
361
362 if (displacement)
363 scnprintf(buf, sizeof(buf), "%+4ld", displacement);
364
365 return scnprintf(hpp->buf, hpp->size, fmt, buf);
366}
367
368static int hpp__header_formula(struct perf_hpp *hpp) 354static int hpp__header_formula(struct perf_hpp *hpp)
369{ 355{
370 const char *fmt = symbol_conf.field_sep ? "%s" : "%70s"; 356 const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
@@ -379,67 +365,80 @@ static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)
379 365
380static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he) 366static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
381{ 367{
368 struct hist_entry *pair = hist_entry__next_pair(he);
382 const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s"; 369 const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
383 char buf[96] = " "; 370 char buf[96] = " ";
384 371
385 perf_diff__formula(buf, sizeof(buf), he); 372 if (pair)
373 perf_diff__formula(he, pair, buf, sizeof(buf));
374
386 return scnprintf(hpp->buf, hpp->size, fmt, buf); 375 return scnprintf(hpp->buf, hpp->size, fmt, buf);
387} 376}
388 377
389#define HPP__COLOR_PRINT_FNS(_name) \ 378#define HPP__COLOR_PRINT_FNS(_name) \
390 .header = hpp__header_ ## _name, \ 379 { \
391 .width = hpp__width_ ## _name, \ 380 .header = hpp__header_ ## _name, \
392 .color = hpp__color_ ## _name, \ 381 .width = hpp__width_ ## _name, \
393 .entry = hpp__entry_ ## _name 382 .color = hpp__color_ ## _name, \
383 .entry = hpp__entry_ ## _name \
384 }
394 385
395#define HPP__PRINT_FNS(_name) \ 386#define HPP__PRINT_FNS(_name) \
396 .header = hpp__header_ ## _name, \ 387 { \
397 .width = hpp__width_ ## _name, \ 388 .header = hpp__header_ ## _name, \
398 .entry = hpp__entry_ ## _name 389 .width = hpp__width_ ## _name, \
390 .entry = hpp__entry_ ## _name \
391 }
399 392
400struct perf_hpp_fmt perf_hpp__format[] = { 393struct perf_hpp_fmt perf_hpp__format[] = {
401 { .cond = false, HPP__COLOR_PRINT_FNS(baseline) }, 394 HPP__COLOR_PRINT_FNS(baseline),
402 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, 395 HPP__COLOR_PRINT_FNS(overhead),
403 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, 396 HPP__COLOR_PRINT_FNS(overhead_sys),
404 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, 397 HPP__COLOR_PRINT_FNS(overhead_us),
405 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) }, 398 HPP__COLOR_PRINT_FNS(overhead_guest_sys),
406 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) }, 399 HPP__COLOR_PRINT_FNS(overhead_guest_us),
407 { .cond = false, HPP__PRINT_FNS(samples) }, 400 HPP__PRINT_FNS(samples),
408 { .cond = false, HPP__PRINT_FNS(period) }, 401 HPP__PRINT_FNS(period),
409 { .cond = false, HPP__PRINT_FNS(period_baseline) }, 402 HPP__PRINT_FNS(period_baseline),
410 { .cond = false, HPP__PRINT_FNS(delta) }, 403 HPP__PRINT_FNS(delta),
411 { .cond = false, HPP__PRINT_FNS(ratio) }, 404 HPP__PRINT_FNS(ratio),
412 { .cond = false, HPP__PRINT_FNS(wdiff) }, 405 HPP__PRINT_FNS(wdiff),
413 { .cond = false, HPP__PRINT_FNS(displ) }, 406 HPP__PRINT_FNS(formula)
414 { .cond = false, HPP__PRINT_FNS(formula) }
415}; 407};
416 408
409LIST_HEAD(perf_hpp__list);
410
417#undef HPP__COLOR_PRINT_FNS 411#undef HPP__COLOR_PRINT_FNS
418#undef HPP__PRINT_FNS 412#undef HPP__PRINT_FNS
419 413
420void perf_hpp__init(void) 414void perf_hpp__init(void)
421{ 415{
422 if (symbol_conf.show_cpu_utilization) { 416 if (symbol_conf.show_cpu_utilization) {
423 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; 417 perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS);
424 perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true; 418 perf_hpp__column_enable(PERF_HPP__OVERHEAD_US);
425 419
426 if (perf_guest) { 420 if (perf_guest) {
427 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true; 421 perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_SYS);
428 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true; 422 perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_US);
429 } 423 }
430 } 424 }
431 425
432 if (symbol_conf.show_nr_samples) 426 if (symbol_conf.show_nr_samples)
433 perf_hpp__format[PERF_HPP__SAMPLES].cond = true; 427 perf_hpp__column_enable(PERF_HPP__SAMPLES);
434 428
435 if (symbol_conf.show_total_period) 429 if (symbol_conf.show_total_period)
436 perf_hpp__format[PERF_HPP__PERIOD].cond = true; 430 perf_hpp__column_enable(PERF_HPP__PERIOD);
431}
432
433void perf_hpp__column_register(struct perf_hpp_fmt *format)
434{
435 list_add_tail(&format->list, &perf_hpp__list);
437} 436}
438 437
439void perf_hpp__column_enable(unsigned col, bool enable) 438void perf_hpp__column_enable(unsigned col)
440{ 439{
441 BUG_ON(col >= PERF_HPP__MAX_INDEX); 440 BUG_ON(col >= PERF_HPP__MAX_INDEX);
442 perf_hpp__format[col].cond = enable; 441 perf_hpp__column_register(&perf_hpp__format[col]);
443} 442}
444 443
445static inline void advance_hpp(struct perf_hpp *hpp, int inc) 444static inline void advance_hpp(struct perf_hpp *hpp, int inc)
@@ -452,27 +451,29 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
452 bool color) 451 bool color)
453{ 452{
454 const char *sep = symbol_conf.field_sep; 453 const char *sep = symbol_conf.field_sep;
454 struct perf_hpp_fmt *fmt;
455 char *start = hpp->buf; 455 char *start = hpp->buf;
456 int i, ret; 456 int ret;
457 bool first = true; 457 bool first = true;
458 458
459 if (symbol_conf.exclude_other && !he->parent) 459 if (symbol_conf.exclude_other && !he->parent)
460 return 0; 460 return 0;
461 461
462 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 462 perf_hpp__for_each_format(fmt) {
463 if (!perf_hpp__format[i].cond) 463 /*
464 continue; 464 * If there's no field_sep, we still need
465 465 * to display initial ' '.
466 */
466 if (!sep || !first) { 467 if (!sep || !first) {
467 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); 468 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
468 advance_hpp(hpp, ret); 469 advance_hpp(hpp, ret);
470 } else
469 first = false; 471 first = false;
470 }
471 472
472 if (color && perf_hpp__format[i].color) 473 if (color && fmt->color)
473 ret = perf_hpp__format[i].color(hpp, he); 474 ret = fmt->color(hpp, he);
474 else 475 else
475 ret = perf_hpp__format[i].entry(hpp, he); 476 ret = fmt->entry(hpp, he);
476 477
477 advance_hpp(hpp, ret); 478 advance_hpp(hpp, ret);
478 } 479 }
@@ -504,16 +505,15 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
504 */ 505 */
505unsigned int hists__sort_list_width(struct hists *hists) 506unsigned int hists__sort_list_width(struct hists *hists)
506{ 507{
508 struct perf_hpp_fmt *fmt;
507 struct sort_entry *se; 509 struct sort_entry *se;
508 int i, ret = 0; 510 int i = 0, ret = 0;
509 511
510 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 512 perf_hpp__for_each_format(fmt) {
511 if (!perf_hpp__format[i].cond)
512 continue;
513 if (i) 513 if (i)
514 ret += 2; 514 ret += 2;
515 515
516 ret += perf_hpp__format[i].width(NULL); 516 ret += fmt->width(NULL);
517 } 517 }
518 518
519 list_for_each_entry(se, &hist_entry__sort_list, list) 519 list_for_each_entry(se, &hist_entry__sort_list, list)
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index ebb4cc107876..166f13df3134 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -30,6 +30,7 @@ void setup_browser(bool fallback_to_pager)
30 if (fallback_to_pager) 30 if (fallback_to_pager)
31 setup_pager(); 31 setup_pager();
32 32
33 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
33 perf_hpp__init(); 34 perf_hpp__init();
34 break; 35 break;
35 } 36 }
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index f0ee204f99bb..0eae3b2c32f2 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -335,13 +335,14 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
335size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 335size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
336 int max_cols, FILE *fp) 336 int max_cols, FILE *fp)
337{ 337{
338 struct perf_hpp_fmt *fmt;
338 struct sort_entry *se; 339 struct sort_entry *se;
339 struct rb_node *nd; 340 struct rb_node *nd;
340 size_t ret = 0; 341 size_t ret = 0;
341 unsigned int width; 342 unsigned int width;
342 const char *sep = symbol_conf.field_sep; 343 const char *sep = symbol_conf.field_sep;
343 const char *col_width = symbol_conf.col_width_list_str; 344 const char *col_width = symbol_conf.col_width_list_str;
344 int idx, nr_rows = 0; 345 int nr_rows = 0;
345 char bf[96]; 346 char bf[96];
346 struct perf_hpp dummy_hpp = { 347 struct perf_hpp dummy_hpp = {
347 .buf = bf, 348 .buf = bf,
@@ -355,16 +356,14 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
355 goto print_entries; 356 goto print_entries;
356 357
357 fprintf(fp, "# "); 358 fprintf(fp, "# ");
358 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
359 if (!perf_hpp__format[idx].cond)
360 continue;
361 359
360 perf_hpp__for_each_format(fmt) {
362 if (!first) 361 if (!first)
363 fprintf(fp, "%s", sep ?: " "); 362 fprintf(fp, "%s", sep ?: " ");
364 else 363 else
365 first = false; 364 first = false;
366 365
367 perf_hpp__format[idx].header(&dummy_hpp); 366 fmt->header(&dummy_hpp);
368 fprintf(fp, "%s", bf); 367 fprintf(fp, "%s", bf);
369 } 368 }
370 369
@@ -400,18 +399,16 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
400 first = true; 399 first = true;
401 400
402 fprintf(fp, "# "); 401 fprintf(fp, "# ");
403 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
404 unsigned int i;
405 402
406 if (!perf_hpp__format[idx].cond) 403 perf_hpp__for_each_format(fmt) {
407 continue; 404 unsigned int i;
408 405
409 if (!first) 406 if (!first)
410 fprintf(fp, "%s", sep ?: " "); 407 fprintf(fp, "%s", sep ?: " ");
411 else 408 else
412 first = false; 409 first = false;
413 410
414 width = perf_hpp__format[idx].width(&dummy_hpp); 411 width = fmt->width(&dummy_hpp);
415 for (i = 0; i < width; i++) 412 for (i = 0; i < width; i++)
416 fprintf(fp, "."); 413 fprintf(fp, ".");
417 } 414 }
diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c
index 2884d2f41e33..1c8b9afd5d6e 100644
--- a/tools/perf/ui/tui/helpline.c
+++ b/tools/perf/ui/tui/helpline.c
@@ -8,6 +8,8 @@
8#include "../ui.h" 8#include "../ui.h"
9#include "../libslang.h" 9#include "../libslang.h"
10 10
11char ui_helpline__last_msg[1024];
12
11static void tui_helpline__pop(void) 13static void tui_helpline__pop(void)
12{ 14{
13} 15}
@@ -23,20 +25,7 @@ static void tui_helpline__push(const char *msg)
23 strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0'; 25 strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0';
24} 26}
25 27
26struct ui_helpline tui_helpline_fns = { 28static int tui_helpline__show(const char *format, va_list ap)
27 .pop = tui_helpline__pop,
28 .push = tui_helpline__push,
29};
30
31void ui_helpline__init(void)
32{
33 helpline_fns = &tui_helpline_fns;
34 ui_helpline__puts(" ");
35}
36
37char ui_helpline__last_msg[1024];
38
39int ui_helpline__show_help(const char *format, va_list ap)
40{ 29{
41 int ret; 30 int ret;
42 static int backlog; 31 static int backlog;
@@ -55,3 +44,15 @@ int ui_helpline__show_help(const char *format, va_list ap)
55 44
56 return ret; 45 return ret;
57} 46}
47
48struct ui_helpline tui_helpline_fns = {
49 .pop = tui_helpline__pop,
50 .push = tui_helpline__push,
51 .show = tui_helpline__show,
52};
53
54void ui_helpline__init(void)
55{
56 helpline_fns = &tui_helpline_fns;
57 ui_helpline__puts(" ");
58}
diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c
index 4f989774c8c6..3014a7cd5271 100644
--- a/tools/perf/ui/util.c
+++ b/tools/perf/ui/util.c
@@ -52,6 +52,16 @@ int ui__warning(const char *format, ...)
52 return ret; 52 return ret;
53} 53}
54 54
55int ui__error_paranoid(void)
56{
57 return ui__error("Permission error - are you root?\n"
58 "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
59 " -1 - Not paranoid at all\n"
60 " 0 - Disallow raw tracepoint access for unpriv\n"
61 " 1 - Disallow cpu events for unpriv\n"
62 " 2 - Disallow kernel profiling for unpriv\n");
63}
64
55 65
56/** 66/**
57 * perf_error__register - Register error logging functions 67 * perf_error__register - Register error logging functions
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index eb340571e7d6..3ee9f67d5af0 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -143,4 +143,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
143 cursor->curr = cursor->curr->next; 143 cursor->curr = cursor->curr->next;
144 cursor->pos++; 144 cursor->pos++;
145} 145}
146
147struct option;
148
149int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
150extern const char record_callchain_help[];
146#endif /* __PERF_CALLCHAIN_H */ 151#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 03f830b48148..399e74c34c1a 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -23,10 +23,8 @@ 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 == 1) 26 if (use_browser >= 1)
27 ret = ui_helpline__show_help(fmt, args); 27 ui_helpline__vshow(fmt, args);
28 else if (use_browser == 2)
29 ret = perf_gtk__show_helpline(fmt, args);
30 else 28 else
31 ret = vfprintf(stderr, fmt, args); 29 ret = vfprintf(stderr, fmt, args);
32 va_end(args); 30 va_end(args);
@@ -49,28 +47,6 @@ int dump_printf(const char *fmt, ...)
49 return ret; 47 return ret;
50} 48}
51 49
52#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
53int ui__warning(const char *format, ...)
54{
55 va_list args;
56
57 va_start(args, format);
58 vfprintf(stderr, format, args);
59 va_end(args);
60 return 0;
61}
62#endif
63
64int ui__error_paranoid(void)
65{
66 return ui__error("Permission error - are you root?\n"
67 "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
68 " -1 - Not paranoid at all\n"
69 " 0 - Disallow raw tracepoint access for unpriv\n"
70 " 1 - Disallow cpu events for unpriv\n"
71 " 2 - Disallow kernel profiling for unpriv\n");
72}
73
74void trace_event(union perf_event *event) 50void trace_event(union perf_event *event)
75{ 51{
76 unsigned char *raw_event = (void *)event; 52 unsigned char *raw_event = (void *)event;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 83e8d234af6b..6e2667fb8211 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -5,6 +5,8 @@
5#include <stdbool.h> 5#include <stdbool.h>
6#include "event.h" 6#include "event.h"
7#include "../ui/helpline.h" 7#include "../ui/helpline.h"
8#include "../ui/progress.h"
9#include "../ui/util.h"
8 10
9extern int verbose; 11extern int verbose;
10extern bool quiet, dump_trace; 12extern bool quiet, dump_trace;
@@ -12,38 +14,7 @@ extern bool quiet, dump_trace;
12int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 14int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
13void trace_event(union perf_event *event); 15void trace_event(union perf_event *event);
14 16
15struct ui_progress;
16struct perf_error_ops;
17
18#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
19
20#include "../ui/progress.h"
21int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 17int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
22#include "../ui/util.h"
23
24#else
25
26static inline void ui_progress__update(u64 curr __maybe_unused,
27 u64 total __maybe_unused,
28 const char *title __maybe_unused) {}
29static inline void ui_progress__finish(void) {}
30
31#define ui__error(format, arg...) ui__warning(format, ##arg)
32
33static inline int
34perf_error__register(struct perf_error_ops *eops __maybe_unused)
35{
36 return 0;
37}
38
39static inline int
40perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
41{
42 return 0;
43}
44
45#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
46
47int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 18int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
48int ui__error_paranoid(void); 19int ui__error_paranoid(void);
49 20
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index d6d9a465acdb..6f7d5a9d6b05 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -539,13 +539,13 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name)
539} 539}
540 540
541size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 541size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
542 bool with_hits) 542 bool (skip)(struct dso *dso, int parm), int parm)
543{ 543{
544 struct dso *pos; 544 struct dso *pos;
545 size_t ret = 0; 545 size_t ret = 0;
546 546
547 list_for_each_entry(pos, head, node) { 547 list_for_each_entry(pos, head, node) {
548 if (with_hits && !pos->hit) 548 if (skip && skip(pos, parm))
549 continue; 549 continue;
550 ret += dso__fprintf_buildid(pos, fp); 550 ret += dso__fprintf_buildid(pos, fp);
551 ret += fprintf(fp, " %s\n", pos->long_name); 551 ret += fprintf(fp, " %s\n", pos->long_name);
@@ -583,7 +583,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
583 if (dso->short_name != dso->long_name) 583 if (dso->short_name != dso->long_name)
584 ret += fprintf(fp, "%s, ", dso->long_name); 584 ret += fprintf(fp, "%s, ", dso->long_name);
585 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type], 585 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
586 dso->loaded ? "" : "NOT "); 586 dso__loaded(dso, type) ? "" : "NOT ");
587 ret += dso__fprintf_buildid(dso, fp); 587 ret += dso__fprintf_buildid(dso, fp);
588 ret += fprintf(fp, ")\n"); 588 ret += fprintf(fp, ")\n");
589 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) { 589 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index e03276940b99..450199ab51b5 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -138,7 +138,7 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name);
138bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 138bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
139 139
140size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 140size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
141 bool with_hits); 141 bool (skip)(struct dso *dso, int parm), int parm);
142size_t __dsos__fprintf(struct list_head *head, FILE *fp); 142size_t __dsos__fprintf(struct list_head *head, FILE *fp);
143 143
144size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); 144size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 705293489e3c..dc8aee97a488 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -49,10 +49,16 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
49 return evlist; 49 return evlist;
50} 50}
51 51
52void perf_evlist__config_attrs(struct perf_evlist *evlist, 52void perf_evlist__config(struct perf_evlist *evlist,
53 struct perf_record_opts *opts) 53 struct perf_record_opts *opts)
54{ 54{
55 struct perf_evsel *evsel; 55 struct perf_evsel *evsel;
56 /*
57 * Set the evsel leader links before we configure attributes,
58 * since some might depend on this info.
59 */
60 if (opts->group)
61 perf_evlist__set_leader(evlist);
56 62
57 if (evlist->cpus->map[0] < 0) 63 if (evlist->cpus->map[0] < 0)
58 opts->no_inherit = true; 64 opts->no_inherit = true;
@@ -61,7 +67,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist,
61 perf_evsel__config(evsel, opts); 67 perf_evsel__config(evsel, opts);
62 68
63 if (evlist->nr_entries > 1) 69 if (evlist->nr_entries > 1)
64 evsel->attr.sample_type |= PERF_SAMPLE_ID; 70 perf_evsel__set_sample_id(evsel);
65 } 71 }
66} 72}
67 73
@@ -111,7 +117,6 @@ void __perf_evlist__set_leader(struct list_head *list)
111 struct perf_evsel *evsel, *leader; 117 struct perf_evsel *evsel, *leader;
112 118
113 leader = list_entry(list->next, struct perf_evsel, node); 119 leader = list_entry(list->next, struct perf_evsel, node);
114 leader->leader = NULL;
115 120
116 list_for_each_entry(evsel, list, node) { 121 list_for_each_entry(evsel, list, node) {
117 if (evsel != leader) 122 if (evsel != leader)
@@ -222,7 +227,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
222 227
223 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 228 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
224 list_for_each_entry(pos, &evlist->entries, node) { 229 list_for_each_entry(pos, &evlist->entries, node) {
225 if (perf_evsel__is_group_member(pos)) 230 if (!perf_evsel__is_group_leader(pos))
226 continue; 231 continue;
227 for (thread = 0; thread < evlist->threads->nr; thread++) 232 for (thread = 0; thread < evlist->threads->nr; thread++)
228 ioctl(FD(pos, cpu, thread), 233 ioctl(FD(pos, cpu, thread),
@@ -238,7 +243,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
238 243
239 for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) { 244 for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
240 list_for_each_entry(pos, &evlist->entries, node) { 245 list_for_each_entry(pos, &evlist->entries, node) {
241 if (perf_evsel__is_group_member(pos)) 246 if (!perf_evsel__is_group_leader(pos))
242 continue; 247 continue;
243 for (thread = 0; thread < evlist->threads->nr; thread++) 248 for (thread = 0; thread < evlist->threads->nr; thread++)
244 ioctl(FD(pos, cpu, thread), 249 ioctl(FD(pos, cpu, thread),
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 56003f779e60..457e2350d21d 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -76,8 +76,8 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
76 76
77int perf_evlist__open(struct perf_evlist *evlist); 77int perf_evlist__open(struct perf_evlist *evlist);
78 78
79void perf_evlist__config_attrs(struct perf_evlist *evlist, 79void perf_evlist__config(struct perf_evlist *evlist,
80 struct perf_record_opts *opts); 80 struct perf_record_opts *opts);
81 81
82int perf_evlist__prepare_workload(struct perf_evlist *evlist, 82int perf_evlist__prepare_workload(struct perf_evlist *evlist,
83 struct perf_record_opts *opts, 83 struct perf_record_opts *opts,
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1b16dd1edc8e..7a2a3dc3ff03 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -50,11 +50,36 @@ void hists__init(struct hists *hists)
50 pthread_mutex_init(&hists->lock, NULL); 50 pthread_mutex_init(&hists->lock, NULL);
51} 51}
52 52
53void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
54 enum perf_event_sample_format bit)
55{
56 if (!(evsel->attr.sample_type & bit)) {
57 evsel->attr.sample_type |= bit;
58 evsel->sample_size += sizeof(u64);
59 }
60}
61
62void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
63 enum perf_event_sample_format bit)
64{
65 if (evsel->attr.sample_type & bit) {
66 evsel->attr.sample_type &= ~bit;
67 evsel->sample_size -= sizeof(u64);
68 }
69}
70
71void perf_evsel__set_sample_id(struct perf_evsel *evsel)
72{
73 perf_evsel__set_sample_bit(evsel, ID);
74 evsel->attr.read_format |= PERF_FORMAT_ID;
75}
76
53void perf_evsel__init(struct perf_evsel *evsel, 77void perf_evsel__init(struct perf_evsel *evsel,
54 struct perf_event_attr *attr, int idx) 78 struct perf_event_attr *attr, int idx)
55{ 79{
56 evsel->idx = idx; 80 evsel->idx = idx;
57 evsel->attr = *attr; 81 evsel->attr = *attr;
82 evsel->leader = evsel;
58 INIT_LIST_HEAD(&evsel->node); 83 INIT_LIST_HEAD(&evsel->node);
59 hists__init(&evsel->hists); 84 hists__init(&evsel->hists);
60 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); 85 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
@@ -440,11 +465,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
440 465
441 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 466 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
442 attr->inherit = !opts->no_inherit; 467 attr->inherit = !opts->no_inherit;
443 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
444 PERF_FORMAT_TOTAL_TIME_RUNNING |
445 PERF_FORMAT_ID;
446 468
447 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 469 perf_evsel__set_sample_bit(evsel, IP);
470 perf_evsel__set_sample_bit(evsel, TID);
448 471
449 /* 472 /*
450 * We default some events to a 1 default interval. But keep 473 * We default some events to a 1 default interval. But keep
@@ -453,7 +476,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
453 if (!attr->sample_period || (opts->user_freq != UINT_MAX && 476 if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
454 opts->user_interval != ULLONG_MAX)) { 477 opts->user_interval != ULLONG_MAX)) {
455 if (opts->freq) { 478 if (opts->freq) {
456 attr->sample_type |= PERF_SAMPLE_PERIOD; 479 perf_evsel__set_sample_bit(evsel, PERIOD);
457 attr->freq = 1; 480 attr->freq = 1;
458 attr->sample_freq = opts->freq; 481 attr->sample_freq = opts->freq;
459 } else { 482 } else {
@@ -468,16 +491,16 @@ void perf_evsel__config(struct perf_evsel *evsel,
468 attr->inherit_stat = 1; 491 attr->inherit_stat = 1;
469 492
470 if (opts->sample_address) { 493 if (opts->sample_address) {
471 attr->sample_type |= PERF_SAMPLE_ADDR; 494 perf_evsel__set_sample_bit(evsel, ADDR);
472 attr->mmap_data = track; 495 attr->mmap_data = track;
473 } 496 }
474 497
475 if (opts->call_graph) { 498 if (opts->call_graph) {
476 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 499 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
477 500
478 if (opts->call_graph == CALLCHAIN_DWARF) { 501 if (opts->call_graph == CALLCHAIN_DWARF) {
479 attr->sample_type |= PERF_SAMPLE_REGS_USER | 502 perf_evsel__set_sample_bit(evsel, REGS_USER);
480 PERF_SAMPLE_STACK_USER; 503 perf_evsel__set_sample_bit(evsel, STACK_USER);
481 attr->sample_regs_user = PERF_REGS_MASK; 504 attr->sample_regs_user = PERF_REGS_MASK;
482 attr->sample_stack_user = opts->stack_dump_size; 505 attr->sample_stack_user = opts->stack_dump_size;
483 attr->exclude_callchain_user = 1; 506 attr->exclude_callchain_user = 1;
@@ -485,20 +508,20 @@ void perf_evsel__config(struct perf_evsel *evsel,
485 } 508 }
486 509
487 if (perf_target__has_cpu(&opts->target)) 510 if (perf_target__has_cpu(&opts->target))
488 attr->sample_type |= PERF_SAMPLE_CPU; 511 perf_evsel__set_sample_bit(evsel, CPU);
489 512
490 if (opts->period) 513 if (opts->period)
491 attr->sample_type |= PERF_SAMPLE_PERIOD; 514 perf_evsel__set_sample_bit(evsel, PERIOD);
492 515
493 if (!opts->sample_id_all_missing && 516 if (!opts->sample_id_all_missing &&
494 (opts->sample_time || !opts->no_inherit || 517 (opts->sample_time || !opts->no_inherit ||
495 perf_target__has_cpu(&opts->target))) 518 perf_target__has_cpu(&opts->target)))
496 attr->sample_type |= PERF_SAMPLE_TIME; 519 perf_evsel__set_sample_bit(evsel, TIME);
497 520
498 if (opts->raw_samples) { 521 if (opts->raw_samples) {
499 attr->sample_type |= PERF_SAMPLE_TIME; 522 perf_evsel__set_sample_bit(evsel, TIME);
500 attr->sample_type |= PERF_SAMPLE_RAW; 523 perf_evsel__set_sample_bit(evsel, RAW);
501 attr->sample_type |= PERF_SAMPLE_CPU; 524 perf_evsel__set_sample_bit(evsel, CPU);
502 } 525 }
503 526
504 if (opts->no_delay) { 527 if (opts->no_delay) {
@@ -506,7 +529,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
506 attr->wakeup_events = 1; 529 attr->wakeup_events = 1;
507 } 530 }
508 if (opts->branch_stack) { 531 if (opts->branch_stack) {
509 attr->sample_type |= PERF_SAMPLE_BRANCH_STACK; 532 perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
510 attr->branch_sample_type = opts->branch_stack; 533 attr->branch_sample_type = opts->branch_stack;
511 } 534 }
512 535
@@ -519,14 +542,14 @@ void perf_evsel__config(struct perf_evsel *evsel,
519 * Disabling only independent events or group leaders, 542 * Disabling only independent events or group leaders,
520 * keeping group members enabled. 543 * keeping group members enabled.
521 */ 544 */
522 if (!perf_evsel__is_group_member(evsel)) 545 if (perf_evsel__is_group_leader(evsel))
523 attr->disabled = 1; 546 attr->disabled = 1;
524 547
525 /* 548 /*
526 * Setting enable_on_exec for independent events and 549 * Setting enable_on_exec for independent events and
527 * group leaders for traced executed by perf. 550 * group leaders for traced executed by perf.
528 */ 551 */
529 if (perf_target__none(&opts->target) && !perf_evsel__is_group_member(evsel)) 552 if (perf_target__none(&opts->target) && perf_evsel__is_group_leader(evsel))
530 attr->enable_on_exec = 1; 553 attr->enable_on_exec = 1;
531} 554}
532 555
@@ -707,7 +730,7 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
707 struct perf_evsel *leader = evsel->leader; 730 struct perf_evsel *leader = evsel->leader;
708 int fd; 731 int fd;
709 732
710 if (!perf_evsel__is_group_member(evsel)) 733 if (perf_evsel__is_group_leader(evsel))
711 return -1; 734 return -1;
712 735
713 /* 736 /*
@@ -1205,3 +1228,128 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
1205 1228
1206 return 0; 1229 return 0;
1207} 1230}
1231
1232static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
1233{
1234 va_list args;
1235 int ret = 0;
1236
1237 if (!*first) {
1238 ret += fprintf(fp, ",");
1239 } else {
1240 ret += fprintf(fp, ":");
1241 *first = false;
1242 }
1243
1244 va_start(args, fmt);
1245 ret += vfprintf(fp, fmt, args);
1246 va_end(args);
1247 return ret;
1248}
1249
1250static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value)
1251{
1252 if (value == 0)
1253 return 0;
1254
1255 return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
1256}
1257
1258#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
1259
1260struct bit_names {
1261 int bit;
1262 const char *name;
1263};
1264
1265static int bits__fprintf(FILE *fp, const char *field, u64 value,
1266 struct bit_names *bits, bool *first)
1267{
1268 int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
1269 bool first_bit = true;
1270
1271 do {
1272 if (value & bits[i].bit) {
1273 printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
1274 first_bit = false;
1275 }
1276 } while (bits[++i].name != NULL);
1277
1278 return printed;
1279}
1280
1281static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
1282{
1283#define bit_name(n) { PERF_SAMPLE_##n, #n }
1284 struct bit_names bits[] = {
1285 bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
1286 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1287 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1288 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1289 { .name = NULL, }
1290 };
1291#undef bit_name
1292 return bits__fprintf(fp, "sample_type", value, bits, first);
1293}
1294
1295static int read_format__fprintf(FILE *fp, bool *first, u64 value)
1296{
1297#define bit_name(n) { PERF_FORMAT_##n, #n }
1298 struct bit_names bits[] = {
1299 bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
1300 bit_name(ID), bit_name(GROUP),
1301 { .name = NULL, }
1302 };
1303#undef bit_name
1304 return bits__fprintf(fp, "read_format", value, bits, first);
1305}
1306
1307int perf_evsel__fprintf(struct perf_evsel *evsel,
1308 struct perf_attr_details *details, FILE *fp)
1309{
1310 bool first = true;
1311 int printed = fprintf(fp, "%s", perf_evsel__name(evsel));
1312
1313 if (details->verbose || details->freq) {
1314 printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
1315 (u64)evsel->attr.sample_freq);
1316 }
1317
1318 if (details->verbose) {
1319 if_print(type);
1320 if_print(config);
1321 if_print(config1);
1322 if_print(config2);
1323 if_print(size);
1324 printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
1325 if (evsel->attr.read_format)
1326 printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
1327 if_print(disabled);
1328 if_print(inherit);
1329 if_print(pinned);
1330 if_print(exclusive);
1331 if_print(exclude_user);
1332 if_print(exclude_kernel);
1333 if_print(exclude_hv);
1334 if_print(exclude_idle);
1335 if_print(mmap);
1336 if_print(comm);
1337 if_print(freq);
1338 if_print(inherit_stat);
1339 if_print(enable_on_exec);
1340 if_print(task);
1341 if_print(watermark);
1342 if_print(precise_ip);
1343 if_print(mmap_data);
1344 if_print(sample_id_all);
1345 if_print(exclude_host);
1346 if_print(exclude_guest);
1347 if_print(__reserved_1);
1348 if_print(wakeup_events);
1349 if_print(bp_type);
1350 if_print(branch_sample_type);
1351 }
1352
1353 fputc('\n', fp);
1354 return ++printed;
1355}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 3d2b8017438c..9cb8a0215711 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -118,6 +118,19 @@ void perf_evsel__free_fd(struct perf_evsel *evsel);
118void perf_evsel__free_id(struct perf_evsel *evsel); 118void perf_evsel__free_id(struct perf_evsel *evsel);
119void 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);
120 120
121void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
122 enum perf_event_sample_format bit);
123void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
124 enum perf_event_sample_format bit);
125
126#define perf_evsel__set_sample_bit(evsel, bit) \
127 __perf_evsel__set_sample_bit(evsel, PERF_SAMPLE_##bit)
128
129#define perf_evsel__reset_sample_bit(evsel, bit) \
130 __perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit)
131
132void perf_evsel__set_sample_id(struct perf_evsel *evsel);
133
121int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 134int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
122 const char *filter); 135 const char *filter);
123 136
@@ -226,8 +239,16 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
226 return list_entry(evsel->node.next, struct perf_evsel, node); 239 return list_entry(evsel->node.next, struct perf_evsel, node);
227} 240}
228 241
229static inline bool perf_evsel__is_group_member(const struct perf_evsel *evsel) 242static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel)
230{ 243{
231 return evsel->leader != NULL; 244 return evsel->leader == evsel;
232} 245}
246
247struct perf_attr_details {
248 bool freq;
249 bool verbose;
250};
251
252int perf_evsel__fprintf(struct perf_evsel *evsel,
253 struct perf_attr_details *details, FILE *fp);
233#endif /* __PERF_EVSEL_H */ 254#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cb17e2a8c6ed..82df1b26f0d4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -785,7 +785,7 @@ void hists__match(struct hists *leader, struct hists *other)
785 pair = hists__find_entry(other, pos); 785 pair = hists__find_entry(other, pos);
786 786
787 if (pair) 787 if (pair)
788 hist__entry_add_pair(pos, pair); 788 hist_entry__add_pair(pair, pos);
789 } 789 }
790} 790}
791 791
@@ -806,7 +806,7 @@ int hists__link(struct hists *leader, struct hists *other)
806 pair = hists__add_dummy_entry(leader, pos); 806 pair = hists__add_dummy_entry(leader, pos);
807 if (pair == NULL) 807 if (pair == NULL)
808 return -1; 808 return -1;
809 hist__entry_add_pair(pair, pos); 809 hist_entry__add_pair(pos, pair);
810 } 810 }
811 } 811 }
812 812
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8b091a51e4a2..5b3b0075be64 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -126,13 +126,19 @@ struct perf_hpp {
126}; 126};
127 127
128struct perf_hpp_fmt { 128struct perf_hpp_fmt {
129 bool cond;
130 int (*header)(struct perf_hpp *hpp); 129 int (*header)(struct perf_hpp *hpp);
131 int (*width)(struct perf_hpp *hpp); 130 int (*width)(struct perf_hpp *hpp);
132 int (*color)(struct perf_hpp *hpp, struct hist_entry *he); 131 int (*color)(struct perf_hpp *hpp, struct hist_entry *he);
133 int (*entry)(struct perf_hpp *hpp, struct hist_entry *he); 132 int (*entry)(struct perf_hpp *hpp, struct hist_entry *he);
133
134 struct list_head list;
134}; 135};
135 136
137extern struct list_head perf_hpp__list;
138
139#define perf_hpp__for_each_format(format) \
140 list_for_each_entry(format, &perf_hpp__list, list)
141
136extern struct perf_hpp_fmt perf_hpp__format[]; 142extern struct perf_hpp_fmt perf_hpp__format[];
137 143
138enum { 144enum {
@@ -148,14 +154,14 @@ enum {
148 PERF_HPP__DELTA, 154 PERF_HPP__DELTA,
149 PERF_HPP__RATIO, 155 PERF_HPP__RATIO,
150 PERF_HPP__WEIGHTED_DIFF, 156 PERF_HPP__WEIGHTED_DIFF,
151 PERF_HPP__DISPL,
152 PERF_HPP__FORMULA, 157 PERF_HPP__FORMULA,
153 158
154 PERF_HPP__MAX_INDEX 159 PERF_HPP__MAX_INDEX
155}; 160};
156 161
157void perf_hpp__init(void); 162void perf_hpp__init(void);
158void perf_hpp__column_enable(unsigned col, bool enable); 163void perf_hpp__column_register(struct perf_hpp_fmt *format);
164void perf_hpp__column_enable(unsigned col);
159int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, 165int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
160 bool color); 166 bool color);
161 167
@@ -219,8 +225,10 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
219 225
220unsigned int hists__sort_list_width(struct hists *self); 226unsigned int hists__sort_list_width(struct hists *self);
221 227
222double perf_diff__compute_delta(struct hist_entry *he); 228double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair);
223double perf_diff__compute_ratio(struct hist_entry *he); 229double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair);
224s64 perf_diff__compute_wdiff(struct hist_entry *he); 230s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair);
225int perf_diff__formula(char *buf, size_t size, struct hist_entry *he); 231int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
232 char *buf, size_t size);
233double perf_diff__period_percent(struct hist_entry *he, u64 period);
226#endif /* __PERF_HIST_H */ 234#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 1f09d0581e6b..71fa90391fe4 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1,10 +1,15 @@
1#include "callchain.h"
1#include "debug.h" 2#include "debug.h"
2#include "event.h" 3#include "event.h"
4#include "evsel.h"
5#include "hist.h"
3#include "machine.h" 6#include "machine.h"
4#include "map.h" 7#include "map.h"
8#include "sort.h"
5#include "strlist.h" 9#include "strlist.h"
6#include "thread.h" 10#include "thread.h"
7#include <stdbool.h> 11#include <stdbool.h>
12#include "unwind.h"
8 13
9int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 14int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
10{ 15{
@@ -48,6 +53,29 @@ static void dsos__delete(struct list_head *dsos)
48 } 53 }
49} 54}
50 55
56void machine__delete_dead_threads(struct machine *machine)
57{
58 struct thread *n, *t;
59
60 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
61 list_del(&t->node);
62 thread__delete(t);
63 }
64}
65
66void machine__delete_threads(struct machine *machine)
67{
68 struct rb_node *nd = rb_first(&machine->threads);
69
70 while (nd) {
71 struct thread *t = rb_entry(nd, struct thread, rb_node);
72
73 rb_erase(&t->rb_node, &machine->threads);
74 nd = rb_next(nd);
75 thread__delete(t);
76 }
77}
78
51void machine__exit(struct machine *machine) 79void machine__exit(struct machine *machine)
52{ 80{
53 map_groups__exit(&machine->kmaps); 81 map_groups__exit(&machine->kmaps);
@@ -264,6 +292,534 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
264 return 0; 292 return 0;
265} 293}
266 294
295struct map *machine__new_module(struct machine *machine, u64 start,
296 const char *filename)
297{
298 struct map *map;
299 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
300
301 if (dso == NULL)
302 return NULL;
303
304 map = map__new2(start, dso, MAP__FUNCTION);
305 if (map == NULL)
306 return NULL;
307
308 if (machine__is_host(machine))
309 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
310 else
311 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
312 map_groups__insert(&machine->kmaps, map);
313 return map;
314}
315
316size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
317{
318 struct rb_node *nd;
319 size_t ret = 0;
320
321 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
322 struct machine *pos = rb_entry(nd, struct machine, rb_node);
323 ret += __dsos__fprintf(&pos->kernel_dsos, fp);
324 ret += __dsos__fprintf(&pos->user_dsos, fp);
325 }
326
327 return ret;
328}
329
330size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
331 bool (skip)(struct dso *dso, int parm), int parm)
332{
333 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) +
334 __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm);
335}
336
337size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
338 bool (skip)(struct dso *dso, int parm), int parm)
339{
340 struct rb_node *nd;
341 size_t ret = 0;
342
343 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
344 struct machine *pos = rb_entry(nd, struct machine, rb_node);
345 ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm);
346 }
347 return ret;
348}
349
350size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
351{
352 int i;
353 size_t printed = 0;
354 struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
355
356 if (kdso->has_build_id) {
357 char filename[PATH_MAX];
358 if (dso__build_id_filename(kdso, filename, sizeof(filename)))
359 printed += fprintf(fp, "[0] %s\n", filename);
360 }
361
362 for (i = 0; i < vmlinux_path__nr_entries; ++i)
363 printed += fprintf(fp, "[%d] %s\n",
364 i + kdso->has_build_id, vmlinux_path[i]);
365
366 return printed;
367}
368
369size_t machine__fprintf(struct machine *machine, FILE *fp)
370{
371 size_t ret = 0;
372 struct rb_node *nd;
373
374 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
375 struct thread *pos = rb_entry(nd, struct thread, rb_node);
376
377 ret += thread__fprintf(pos, fp);
378 }
379
380 return ret;
381}
382
383static struct dso *machine__get_kernel(struct machine *machine)
384{
385 const char *vmlinux_name = NULL;
386 struct dso *kernel;
387
388 if (machine__is_host(machine)) {
389 vmlinux_name = symbol_conf.vmlinux_name;
390 if (!vmlinux_name)
391 vmlinux_name = "[kernel.kallsyms]";
392
393 kernel = dso__kernel_findnew(machine, vmlinux_name,
394 "[kernel]",
395 DSO_TYPE_KERNEL);
396 } else {
397 char bf[PATH_MAX];
398
399 if (machine__is_default_guest(machine))
400 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
401 if (!vmlinux_name)
402 vmlinux_name = machine__mmap_name(machine, bf,
403 sizeof(bf));
404
405 kernel = dso__kernel_findnew(machine, vmlinux_name,
406 "[guest.kernel]",
407 DSO_TYPE_GUEST_KERNEL);
408 }
409
410 if (kernel != NULL && (!kernel->has_build_id))
411 dso__read_running_kernel_build_id(kernel, machine);
412
413 return kernel;
414}
415
416struct process_args {
417 u64 start;
418};
419
420static int symbol__in_kernel(void *arg, const char *name,
421 char type __maybe_unused, u64 start)
422{
423 struct process_args *args = arg;
424
425 if (strchr(name, '['))
426 return 0;
427
428 args->start = start;
429 return 1;
430}
431
432/* Figure out the start address of kernel map from /proc/kallsyms */
433static u64 machine__get_kernel_start_addr(struct machine *machine)
434{
435 const char *filename;
436 char path[PATH_MAX];
437 struct process_args args;
438
439 if (machine__is_host(machine)) {
440 filename = "/proc/kallsyms";
441 } else {
442 if (machine__is_default_guest(machine))
443 filename = (char *)symbol_conf.default_guest_kallsyms;
444 else {
445 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
446 filename = path;
447 }
448 }
449
450 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
451 return 0;
452
453 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
454 return 0;
455
456 return args.start;
457}
458
459int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
460{
461 enum map_type type;
462 u64 start = machine__get_kernel_start_addr(machine);
463
464 for (type = 0; type < MAP__NR_TYPES; ++type) {
465 struct kmap *kmap;
466
467 machine->vmlinux_maps[type] = map__new2(start, kernel, type);
468 if (machine->vmlinux_maps[type] == NULL)
469 return -1;
470
471 machine->vmlinux_maps[type]->map_ip =
472 machine->vmlinux_maps[type]->unmap_ip =
473 identity__map_ip;
474 kmap = map__kmap(machine->vmlinux_maps[type]);
475 kmap->kmaps = &machine->kmaps;
476 map_groups__insert(&machine->kmaps,
477 machine->vmlinux_maps[type]);
478 }
479
480 return 0;
481}
482
483void machine__destroy_kernel_maps(struct machine *machine)
484{
485 enum map_type type;
486
487 for (type = 0; type < MAP__NR_TYPES; ++type) {
488 struct kmap *kmap;
489
490 if (machine->vmlinux_maps[type] == NULL)
491 continue;
492
493 kmap = map__kmap(machine->vmlinux_maps[type]);
494 map_groups__remove(&machine->kmaps,
495 machine->vmlinux_maps[type]);
496 if (kmap->ref_reloc_sym) {
497 /*
498 * ref_reloc_sym is shared among all maps, so free just
499 * on one of them.
500 */
501 if (type == MAP__FUNCTION) {
502 free((char *)kmap->ref_reloc_sym->name);
503 kmap->ref_reloc_sym->name = NULL;
504 free(kmap->ref_reloc_sym);
505 }
506 kmap->ref_reloc_sym = NULL;
507 }
508
509 map__delete(machine->vmlinux_maps[type]);
510 machine->vmlinux_maps[type] = NULL;
511 }
512}
513
514int machines__create_guest_kernel_maps(struct rb_root *machines)
515{
516 int ret = 0;
517 struct dirent **namelist = NULL;
518 int i, items = 0;
519 char path[PATH_MAX];
520 pid_t pid;
521 char *endp;
522
523 if (symbol_conf.default_guest_vmlinux_name ||
524 symbol_conf.default_guest_modules ||
525 symbol_conf.default_guest_kallsyms) {
526 machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
527 }
528
529 if (symbol_conf.guestmount) {
530 items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
531 if (items <= 0)
532 return -ENOENT;
533 for (i = 0; i < items; i++) {
534 if (!isdigit(namelist[i]->d_name[0])) {
535 /* Filter out . and .. */
536 continue;
537 }
538 pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
539 if ((*endp != '\0') ||
540 (endp == namelist[i]->d_name) ||
541 (errno == ERANGE)) {
542 pr_debug("invalid directory (%s). Skipping.\n",
543 namelist[i]->d_name);
544 continue;
545 }
546 sprintf(path, "%s/%s/proc/kallsyms",
547 symbol_conf.guestmount,
548 namelist[i]->d_name);
549 ret = access(path, R_OK);
550 if (ret) {
551 pr_debug("Can't access file %s\n", path);
552 goto failure;
553 }
554 machines__create_kernel_maps(machines, pid);
555 }
556failure:
557 free(namelist);
558 }
559
560 return ret;
561}
562
563void machines__destroy_guest_kernel_maps(struct rb_root *machines)
564{
565 struct rb_node *next = rb_first(machines);
566
567 while (next) {
568 struct machine *pos = rb_entry(next, struct machine, rb_node);
569
570 next = rb_next(&pos->rb_node);
571 rb_erase(&pos->rb_node, machines);
572 machine__delete(pos);
573 }
574}
575
576int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
577{
578 struct machine *machine = machines__findnew(machines, pid);
579
580 if (machine == NULL)
581 return -1;
582
583 return machine__create_kernel_maps(machine);
584}
585
586int machine__load_kallsyms(struct machine *machine, const char *filename,
587 enum map_type type, symbol_filter_t filter)
588{
589 struct map *map = machine->vmlinux_maps[type];
590 int ret = dso__load_kallsyms(map->dso, filename, map, filter);
591
592 if (ret > 0) {
593 dso__set_loaded(map->dso, type);
594 /*
595 * Since /proc/kallsyms will have multiple sessions for the
596 * kernel, with modules between them, fixup the end of all
597 * sections.
598 */
599 __map_groups__fixup_end(&machine->kmaps, type);
600 }
601
602 return ret;
603}
604
605int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
606 symbol_filter_t filter)
607{
608 struct map *map = machine->vmlinux_maps[type];
609 int ret = dso__load_vmlinux_path(map->dso, map, filter);
610
611 if (ret > 0) {
612 dso__set_loaded(map->dso, type);
613 map__reloc_vmlinux(map);
614 }
615
616 return ret;
617}
618
619static void map_groups__fixup_end(struct map_groups *mg)
620{
621 int i;
622 for (i = 0; i < MAP__NR_TYPES; ++i)
623 __map_groups__fixup_end(mg, i);
624}
625
626static char *get_kernel_version(const char *root_dir)
627{
628 char version[PATH_MAX];
629 FILE *file;
630 char *name, *tmp;
631 const char *prefix = "Linux version ";
632
633 sprintf(version, "%s/proc/version", root_dir);
634 file = fopen(version, "r");
635 if (!file)
636 return NULL;
637
638 version[0] = '\0';
639 tmp = fgets(version, sizeof(version), file);
640 fclose(file);
641
642 name = strstr(version, prefix);
643 if (!name)
644 return NULL;
645 name += strlen(prefix);
646 tmp = strchr(name, ' ');
647 if (tmp)
648 *tmp = '\0';
649
650 return strdup(name);
651}
652
653static int map_groups__set_modules_path_dir(struct map_groups *mg,
654 const char *dir_name)
655{
656 struct dirent *dent;
657 DIR *dir = opendir(dir_name);
658 int ret = 0;
659
660 if (!dir) {
661 pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
662 return -1;
663 }
664
665 while ((dent = readdir(dir)) != NULL) {
666 char path[PATH_MAX];
667 struct stat st;
668
669 /*sshfs might return bad dent->d_type, so we have to stat*/
670 snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
671 if (stat(path, &st))
672 continue;
673
674 if (S_ISDIR(st.st_mode)) {
675 if (!strcmp(dent->d_name, ".") ||
676 !strcmp(dent->d_name, ".."))
677 continue;
678
679 ret = map_groups__set_modules_path_dir(mg, path);
680 if (ret < 0)
681 goto out;
682 } else {
683 char *dot = strrchr(dent->d_name, '.'),
684 dso_name[PATH_MAX];
685 struct map *map;
686 char *long_name;
687
688 if (dot == NULL || strcmp(dot, ".ko"))
689 continue;
690 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
691 (int)(dot - dent->d_name), dent->d_name);
692
693 strxfrchar(dso_name, '-', '_');
694 map = map_groups__find_by_name(mg, MAP__FUNCTION,
695 dso_name);
696 if (map == NULL)
697 continue;
698
699 long_name = strdup(path);
700 if (long_name == NULL) {
701 ret = -1;
702 goto out;
703 }
704 dso__set_long_name(map->dso, long_name);
705 map->dso->lname_alloc = 1;
706 dso__kernel_module_get_build_id(map->dso, "");
707 }
708 }
709
710out:
711 closedir(dir);
712 return ret;
713}
714
715static int machine__set_modules_path(struct machine *machine)
716{
717 char *version;
718 char modules_path[PATH_MAX];
719
720 version = get_kernel_version(machine->root_dir);
721 if (!version)
722 return -1;
723
724 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
725 machine->root_dir, version);
726 free(version);
727
728 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
729}
730
731static int machine__create_modules(struct machine *machine)
732{
733 char *line = NULL;
734 size_t n;
735 FILE *file;
736 struct map *map;
737 const char *modules;
738 char path[PATH_MAX];
739
740 if (machine__is_default_guest(machine))
741 modules = symbol_conf.default_guest_modules;
742 else {
743 sprintf(path, "%s/proc/modules", machine->root_dir);
744 modules = path;
745 }
746
747 if (symbol__restricted_filename(path, "/proc/modules"))
748 return -1;
749
750 file = fopen(modules, "r");
751 if (file == NULL)
752 return -1;
753
754 while (!feof(file)) {
755 char name[PATH_MAX];
756 u64 start;
757 char *sep;
758 int line_len;
759
760 line_len = getline(&line, &n, file);
761 if (line_len < 0)
762 break;
763
764 if (!line)
765 goto out_failure;
766
767 line[--line_len] = '\0'; /* \n */
768
769 sep = strrchr(line, 'x');
770 if (sep == NULL)
771 continue;
772
773 hex2u64(sep + 1, &start);
774
775 sep = strchr(line, ' ');
776 if (sep == NULL)
777 continue;
778
779 *sep = '\0';
780
781 snprintf(name, sizeof(name), "[%s]", line);
782 map = machine__new_module(machine, start, name);
783 if (map == NULL)
784 goto out_delete_line;
785 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
786 }
787
788 free(line);
789 fclose(file);
790
791 return machine__set_modules_path(machine);
792
793out_delete_line:
794 free(line);
795out_failure:
796 return -1;
797}
798
799int machine__create_kernel_maps(struct machine *machine)
800{
801 struct dso *kernel = machine__get_kernel(machine);
802
803 if (kernel == NULL ||
804 __machine__create_kernel_maps(machine, kernel) < 0)
805 return -1;
806
807 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
808 if (machine__is_host(machine))
809 pr_debug("Problems creating module maps, "
810 "continuing anyway...\n");
811 else
812 pr_debug("Problems creating module maps for guest %d, "
813 "continuing anyway...\n", machine->pid);
814 }
815
816 /*
817 * Now that we have all the maps created, just set the ->end of them:
818 */
819 map_groups__fixup_end(&machine->kmaps);
820 return 0;
821}
822
267static void machine__set_kernel_mmap_len(struct machine *machine, 823static void machine__set_kernel_mmap_len(struct machine *machine,
268 union perf_event *event) 824 union perf_event *event)
269{ 825{
@@ -462,3 +1018,189 @@ int machine__process_event(struct machine *machine, union perf_event *event)
462 1018
463 return ret; 1019 return ret;
464} 1020}
1021
1022void machine__remove_thread(struct machine *machine, struct thread *th)
1023{
1024 machine->last_match = NULL;
1025 rb_erase(&th->rb_node, &machine->threads);
1026 /*
1027 * We may have references to this thread, for instance in some hist_entry
1028 * instances, so just move them to a separate list.
1029 */
1030 list_add_tail(&th->node, &machine->dead_threads);
1031}
1032
1033static bool symbol__match_parent_regex(struct symbol *sym)
1034{
1035 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
1036 return 1;
1037
1038 return 0;
1039}
1040
1041static const u8 cpumodes[] = {
1042 PERF_RECORD_MISC_USER,
1043 PERF_RECORD_MISC_KERNEL,
1044 PERF_RECORD_MISC_GUEST_USER,
1045 PERF_RECORD_MISC_GUEST_KERNEL
1046};
1047#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
1048
1049static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1050 struct addr_map_symbol *ams,
1051 u64 ip)
1052{
1053 struct addr_location al;
1054 size_t i;
1055 u8 m;
1056
1057 memset(&al, 0, sizeof(al));
1058
1059 for (i = 0; i < NCPUMODES; i++) {
1060 m = cpumodes[i];
1061 /*
1062 * We cannot use the header.misc hint to determine whether a
1063 * branch stack address is user, kernel, guest, hypervisor.
1064 * Branches may straddle the kernel/user/hypervisor boundaries.
1065 * Thus, we have to try consecutively until we find a match
1066 * or else, the symbol is unknown
1067 */
1068 thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
1069 ip, &al, NULL);
1070 if (al.sym)
1071 goto found;
1072 }
1073found:
1074 ams->addr = ip;
1075 ams->al_addr = al.addr;
1076 ams->sym = al.sym;
1077 ams->map = al.map;
1078}
1079
1080struct branch_info *machine__resolve_bstack(struct machine *machine,
1081 struct thread *thr,
1082 struct branch_stack *bs)
1083{
1084 struct branch_info *bi;
1085 unsigned int i;
1086
1087 bi = calloc(bs->nr, sizeof(struct branch_info));
1088 if (!bi)
1089 return NULL;
1090
1091 for (i = 0; i < bs->nr; i++) {
1092 ip__resolve_ams(machine, thr, &bi[i].to, bs->entries[i].to);
1093 ip__resolve_ams(machine, thr, &bi[i].from, bs->entries[i].from);
1094 bi[i].flags = bs->entries[i].flags;
1095 }
1096 return bi;
1097}
1098
1099static int machine__resolve_callchain_sample(struct machine *machine,
1100 struct thread *thread,
1101 struct ip_callchain *chain,
1102 struct symbol **parent)
1103
1104{
1105 u8 cpumode = PERF_RECORD_MISC_USER;
1106 unsigned int i;
1107 int err;
1108
1109 callchain_cursor_reset(&callchain_cursor);
1110
1111 if (chain->nr > PERF_MAX_STACK_DEPTH) {
1112 pr_warning("corrupted callchain. skipping...\n");
1113 return 0;
1114 }
1115
1116 for (i = 0; i < chain->nr; i++) {
1117 u64 ip;
1118 struct addr_location al;
1119
1120 if (callchain_param.order == ORDER_CALLEE)
1121 ip = chain->ips[i];
1122 else
1123 ip = chain->ips[chain->nr - i - 1];
1124
1125 if (ip >= PERF_CONTEXT_MAX) {
1126 switch (ip) {
1127 case PERF_CONTEXT_HV:
1128 cpumode = PERF_RECORD_MISC_HYPERVISOR;
1129 break;
1130 case PERF_CONTEXT_KERNEL:
1131 cpumode = PERF_RECORD_MISC_KERNEL;
1132 break;
1133 case PERF_CONTEXT_USER:
1134 cpumode = PERF_RECORD_MISC_USER;
1135 break;
1136 default:
1137 pr_debug("invalid callchain context: "
1138 "%"PRId64"\n", (s64) ip);
1139 /*
1140 * It seems the callchain is corrupted.
1141 * Discard all.
1142 */
1143 callchain_cursor_reset(&callchain_cursor);
1144 return 0;
1145 }
1146 continue;
1147 }
1148
1149 al.filtered = false;
1150 thread__find_addr_location(thread, machine, cpumode,
1151 MAP__FUNCTION, ip, &al, NULL);
1152 if (al.sym != NULL) {
1153 if (sort__has_parent && !*parent &&
1154 symbol__match_parent_regex(al.sym))
1155 *parent = al.sym;
1156 if (!symbol_conf.use_callchain)
1157 break;
1158 }
1159
1160 err = callchain_cursor_append(&callchain_cursor,
1161 ip, al.map, al.sym);
1162 if (err)
1163 return err;
1164 }
1165
1166 return 0;
1167}
1168
1169static int unwind_entry(struct unwind_entry *entry, void *arg)
1170{
1171 struct callchain_cursor *cursor = arg;
1172 return callchain_cursor_append(cursor, entry->ip,
1173 entry->map, entry->sym);
1174}
1175
1176int machine__resolve_callchain(struct machine *machine,
1177 struct perf_evsel *evsel,
1178 struct thread *thread,
1179 struct perf_sample *sample,
1180 struct symbol **parent)
1181
1182{
1183 int ret;
1184
1185 callchain_cursor_reset(&callchain_cursor);
1186
1187 ret = machine__resolve_callchain_sample(machine, thread,
1188 sample->callchain, parent);
1189 if (ret)
1190 return ret;
1191
1192 /* Can we do dwarf post unwind? */
1193 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
1194 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
1195 return 0;
1196
1197 /* Bail out if nothing was captured. */
1198 if ((!sample->user_regs.regs) ||
1199 (!sample->user_stack.size))
1200 return 0;
1201
1202 return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
1203 thread, evsel->attr.sample_regs_user,
1204 sample);
1205
1206}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index b7cde7467d55..e11236878ec1 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -61,9 +61,10 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
61 61
62int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 62int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
63void machine__exit(struct machine *machine); 63void machine__exit(struct machine *machine);
64void machine__delete_dead_threads(struct machine *machine);
65void machine__delete_threads(struct machine *machine);
64void machine__delete(struct machine *machine); 66void machine__delete(struct machine *machine);
65 67
66
67struct branch_info *machine__resolve_bstack(struct machine *machine, 68struct branch_info *machine__resolve_bstack(struct machine *machine,
68 struct thread *thread, 69 struct thread *thread,
69 struct branch_stack *bs); 70 struct branch_stack *bs);
@@ -129,11 +130,11 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
129int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 130int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
130 symbol_filter_t filter); 131 symbol_filter_t filter);
131 132
132size_t machine__fprintf_dsos_buildid(struct machine *machine, 133size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
133 FILE *fp, bool with_hits); 134 bool (skip)(struct dso *dso, int parm), int parm);
134size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); 135size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
135size_t machines__fprintf_dsos_buildid(struct rb_root *machines, 136size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
136 FILE *fp, bool with_hits); 137 bool (skip)(struct dso *dso, int parm), int parm);
137 138
138void machine__destroy_kernel_maps(struct machine *machine); 139void machine__destroy_kernel_maps(struct machine *machine);
139int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); 140int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ce6f51162386..76d6e257b8a4 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,7 +16,6 @@
16#include "cpumap.h" 16#include "cpumap.h"
17#include "event-parse.h" 17#include "event-parse.h"
18#include "perf_regs.h" 18#include "perf_regs.h"
19#include "unwind.h"
20#include "vdso.h" 19#include "vdso.h"
21 20
22static int perf_session__open(struct perf_session *self, bool force) 21static int perf_session__open(struct perf_session *self, bool force)
@@ -128,15 +127,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
128 goto out; 127 goto out;
129 128
130 memcpy(self->filename, filename, len); 129 memcpy(self->filename, filename, len);
131 /*
132 * On 64bit we can mmap the data file in one go. No need for tiny mmap
133 * slices. On 32bit we use 32MB.
134 */
135#if BITS_PER_LONG == 64
136 self->mmap_window = ULLONG_MAX;
137#else
138 self->mmap_window = 32 * 1024 * 1024ULL;
139#endif
140 self->machines = RB_ROOT; 130 self->machines = RB_ROOT;
141 self->repipe = repipe; 131 self->repipe = repipe;
142 INIT_LIST_HEAD(&self->ordered_samples.samples); 132 INIT_LIST_HEAD(&self->ordered_samples.samples);
@@ -171,37 +161,30 @@ out_delete:
171 return NULL; 161 return NULL;
172} 162}
173 163
174static void machine__delete_dead_threads(struct machine *machine)
175{
176 struct thread *n, *t;
177
178 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
179 list_del(&t->node);
180 thread__delete(t);
181 }
182}
183
184static void perf_session__delete_dead_threads(struct perf_session *session) 164static void perf_session__delete_dead_threads(struct perf_session *session)
185{ 165{
186 machine__delete_dead_threads(&session->host_machine); 166 machine__delete_dead_threads(&session->host_machine);
187} 167}
188 168
189static void machine__delete_threads(struct machine *self) 169static void perf_session__delete_threads(struct perf_session *session)
190{ 170{
191 struct rb_node *nd = rb_first(&self->threads); 171 machine__delete_threads(&session->host_machine);
192
193 while (nd) {
194 struct thread *t = rb_entry(nd, struct thread, rb_node);
195
196 rb_erase(&t->rb_node, &self->threads);
197 nd = rb_next(nd);
198 thread__delete(t);
199 }
200} 172}
201 173
202static void perf_session__delete_threads(struct perf_session *session) 174static void perf_session_env__delete(struct perf_session_env *env)
203{ 175{
204 machine__delete_threads(&session->host_machine); 176 free(env->hostname);
177 free(env->os_release);
178 free(env->version);
179 free(env->arch);
180 free(env->cpu_desc);
181 free(env->cpuid);
182
183 free(env->cmdline);
184 free(env->sibling_cores);
185 free(env->sibling_threads);
186 free(env->numa_nodes);
187 free(env->pmu_mappings);
205} 188}
206 189
207void perf_session__delete(struct perf_session *self) 190void perf_session__delete(struct perf_session *self)
@@ -209,198 +192,13 @@ void perf_session__delete(struct perf_session *self)
209 perf_session__destroy_kernel_maps(self); 192 perf_session__destroy_kernel_maps(self);
210 perf_session__delete_dead_threads(self); 193 perf_session__delete_dead_threads(self);
211 perf_session__delete_threads(self); 194 perf_session__delete_threads(self);
195 perf_session_env__delete(&self->header.env);
212 machine__exit(&self->host_machine); 196 machine__exit(&self->host_machine);
213 close(self->fd); 197 close(self->fd);
214 free(self); 198 free(self);
215 vdso__exit(); 199 vdso__exit();
216} 200}
217 201
218void machine__remove_thread(struct machine *self, struct thread *th)
219{
220 self->last_match = NULL;
221 rb_erase(&th->rb_node, &self->threads);
222 /*
223 * We may have references to this thread, for instance in some hist_entry
224 * instances, so just move them to a separate list.
225 */
226 list_add_tail(&th->node, &self->dead_threads);
227}
228
229static bool symbol__match_parent_regex(struct symbol *sym)
230{
231 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
232 return 1;
233
234 return 0;
235}
236
237static const u8 cpumodes[] = {
238 PERF_RECORD_MISC_USER,
239 PERF_RECORD_MISC_KERNEL,
240 PERF_RECORD_MISC_GUEST_USER,
241 PERF_RECORD_MISC_GUEST_KERNEL
242};
243#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
244
245static void ip__resolve_ams(struct machine *self, struct thread *thread,
246 struct addr_map_symbol *ams,
247 u64 ip)
248{
249 struct addr_location al;
250 size_t i;
251 u8 m;
252
253 memset(&al, 0, sizeof(al));
254
255 for (i = 0; i < NCPUMODES; i++) {
256 m = cpumodes[i];
257 /*
258 * We cannot use the header.misc hint to determine whether a
259 * branch stack address is user, kernel, guest, hypervisor.
260 * Branches may straddle the kernel/user/hypervisor boundaries.
261 * Thus, we have to try consecutively until we find a match
262 * or else, the symbol is unknown
263 */
264 thread__find_addr_location(thread, self, m, MAP__FUNCTION,
265 ip, &al, NULL);
266 if (al.sym)
267 goto found;
268 }
269found:
270 ams->addr = ip;
271 ams->al_addr = al.addr;
272 ams->sym = al.sym;
273 ams->map = al.map;
274}
275
276struct branch_info *machine__resolve_bstack(struct machine *self,
277 struct thread *thr,
278 struct branch_stack *bs)
279{
280 struct branch_info *bi;
281 unsigned int i;
282
283 bi = calloc(bs->nr, sizeof(struct branch_info));
284 if (!bi)
285 return NULL;
286
287 for (i = 0; i < bs->nr; i++) {
288 ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to);
289 ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from);
290 bi[i].flags = bs->entries[i].flags;
291 }
292 return bi;
293}
294
295static int machine__resolve_callchain_sample(struct machine *machine,
296 struct thread *thread,
297 struct ip_callchain *chain,
298 struct symbol **parent)
299
300{
301 u8 cpumode = PERF_RECORD_MISC_USER;
302 unsigned int i;
303 int err;
304
305 callchain_cursor_reset(&callchain_cursor);
306
307 if (chain->nr > PERF_MAX_STACK_DEPTH) {
308 pr_warning("corrupted callchain. skipping...\n");
309 return 0;
310 }
311
312 for (i = 0; i < chain->nr; i++) {
313 u64 ip;
314 struct addr_location al;
315
316 if (callchain_param.order == ORDER_CALLEE)
317 ip = chain->ips[i];
318 else
319 ip = chain->ips[chain->nr - i - 1];
320
321 if (ip >= PERF_CONTEXT_MAX) {
322 switch (ip) {
323 case PERF_CONTEXT_HV:
324 cpumode = PERF_RECORD_MISC_HYPERVISOR;
325 break;
326 case PERF_CONTEXT_KERNEL:
327 cpumode = PERF_RECORD_MISC_KERNEL;
328 break;
329 case PERF_CONTEXT_USER:
330 cpumode = PERF_RECORD_MISC_USER;
331 break;
332 default:
333 pr_debug("invalid callchain context: "
334 "%"PRId64"\n", (s64) ip);
335 /*
336 * It seems the callchain is corrupted.
337 * Discard all.
338 */
339 callchain_cursor_reset(&callchain_cursor);
340 return 0;
341 }
342 continue;
343 }
344
345 al.filtered = false;
346 thread__find_addr_location(thread, machine, cpumode,
347 MAP__FUNCTION, ip, &al, NULL);
348 if (al.sym != NULL) {
349 if (sort__has_parent && !*parent &&
350 symbol__match_parent_regex(al.sym))
351 *parent = al.sym;
352 if (!symbol_conf.use_callchain)
353 break;
354 }
355
356 err = callchain_cursor_append(&callchain_cursor,
357 ip, al.map, al.sym);
358 if (err)
359 return err;
360 }
361
362 return 0;
363}
364
365static int unwind_entry(struct unwind_entry *entry, void *arg)
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 202static int process_event_synth_tracing_data_stub(union perf_event *event
405 __maybe_unused, 203 __maybe_unused,
406 struct perf_session *session 204 struct perf_session *session
@@ -1369,6 +1167,18 @@ fetch_mmaped_event(struct perf_session *session,
1369 return event; 1167 return event;
1370} 1168}
1371 1169
1170/*
1171 * On 64bit we can mmap the data file in one go. No need for tiny mmap
1172 * slices. On 32bit we use 32MB.
1173 */
1174#if BITS_PER_LONG == 64
1175#define MMAP_SIZE ULLONG_MAX
1176#define NUM_MMAPS 1
1177#else
1178#define MMAP_SIZE (32 * 1024 * 1024ULL)
1179#define NUM_MMAPS 128
1180#endif
1181
1372int __perf_session__process_events(struct perf_session *session, 1182int __perf_session__process_events(struct perf_session *session,
1373 u64 data_offset, u64 data_size, 1183 u64 data_offset, u64 data_size,
1374 u64 file_size, struct perf_tool *tool) 1184 u64 file_size, struct perf_tool *tool)
@@ -1376,7 +1186,7 @@ int __perf_session__process_events(struct perf_session *session,
1376 u64 head, page_offset, file_offset, file_pos, progress_next; 1186 u64 head, page_offset, file_offset, file_pos, progress_next;
1377 int err, mmap_prot, mmap_flags, map_idx = 0; 1187 int err, mmap_prot, mmap_flags, map_idx = 0;
1378 size_t mmap_size; 1188 size_t mmap_size;
1379 char *buf, *mmaps[8]; 1189 char *buf, *mmaps[NUM_MMAPS];
1380 union perf_event *event; 1190 union perf_event *event;
1381 uint32_t size; 1191 uint32_t size;
1382 1192
@@ -1391,7 +1201,7 @@ int __perf_session__process_events(struct perf_session *session,
1391 1201
1392 progress_next = file_size / 16; 1202 progress_next = file_size / 16;
1393 1203
1394 mmap_size = session->mmap_window; 1204 mmap_size = MMAP_SIZE;
1395 if (mmap_size > file_size) 1205 if (mmap_size > file_size)
1396 mmap_size = file_size; 1206 mmap_size = file_size;
1397 1207
@@ -1532,10 +1342,10 @@ size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp)
1532} 1342}
1533 1343
1534size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, 1344size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
1535 bool with_hits) 1345 bool (skip)(struct dso *dso, int parm), int parm)
1536{ 1346{
1537 size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits); 1347 size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, skip, parm);
1538 return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); 1348 return ret + machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm);
1539} 1349}
1540 1350
1541size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) 1351size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index cea133a6bdf1..8c2302504199 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -30,7 +30,6 @@ struct ordered_samples {
30struct perf_session { 30struct perf_session {
31 struct perf_header header; 31 struct perf_header header;
32 unsigned long size; 32 unsigned long size;
33 unsigned long mmap_window;
34 struct machine host_machine; 33 struct machine host_machine;
35 struct rb_root machines; 34 struct rb_root machines;
36 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
@@ -116,8 +115,8 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
116 115
117size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); 116size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
118 117
119size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, 118size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
120 FILE *fp, bool with_hits); 119 bool (fn)(struct dso *dso, int parm), int parm);
121 120
122size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); 121size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
123 122
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index b4e8c3ba559d..a1c0d56b6885 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -55,9 +55,6 @@ struct he_stat {
55struct hist_entry_diff { 55struct hist_entry_diff {
56 bool computed; 56 bool computed;
57 57
58 /* PERF_HPP__DISPL */
59 int displacement;
60
61 /* PERF_HPP__DELTA */ 58 /* PERF_HPP__DELTA */
62 double period_ratio_delta; 59 double period_ratio_delta;
63 60
@@ -118,7 +115,7 @@ static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he)
118 return NULL; 115 return NULL;
119} 116}
120 117
121static inline void hist__entry_add_pair(struct hist_entry *he, 118static inline void hist_entry__add_pair(struct hist_entry *he,
122 struct hist_entry *pair) 119 struct hist_entry *pair)
123{ 120{
124 list_add_tail(&he->pairs.head, &pair->pairs.node); 121 list_add_tail(&he->pairs.head, &pair->pairs.node);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index db0cc92cf2ea..f63557b59c06 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -718,6 +718,17 @@ int dso__load_sym(struct dso *dso, struct map *map,
718 sym.st_value); 718 sym.st_value);
719 used_opd = true; 719 used_opd = true;
720 } 720 }
721 /*
722 * When loading symbols in a data mapping, ABS symbols (which
723 * has a value of SHN_ABS in its st_shndx) failed at
724 * elf_getscn(). And it marks the loading as a failure so
725 * already loaded symbols cannot be fixed up.
726 *
727 * I'm not sure what should be done. Just ignore them for now.
728 * - Namhyung Kim
729 */
730 if (sym.st_shndx == SHN_ABS)
731 continue;
721 732
722 sec = elf_getscn(runtime_ss->elf, sym.st_shndx); 733 sec = elf_getscn(runtime_ss->elf, sym.st_shndx);
723 if (!sec) 734 if (!sec)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 295f8d4feedf..2960284d6ae1 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -28,8 +28,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
28 symbol_filter_t filter); 28 symbol_filter_t filter);
29static 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,
30 symbol_filter_t filter); 30 symbol_filter_t filter);
31static int vmlinux_path__nr_entries; 31int vmlinux_path__nr_entries;
32static char **vmlinux_path; 32char **vmlinux_path;
33 33
34struct symbol_conf symbol_conf = { 34struct symbol_conf symbol_conf = {
35 .exclude_other = true, 35 .exclude_other = true,
@@ -202,13 +202,6 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
202 curr->end = ~0ULL; 202 curr->end = ~0ULL;
203} 203}
204 204
205static void map_groups__fixup_end(struct map_groups *mg)
206{
207 int i;
208 for (i = 0; i < MAP__NR_TYPES; ++i)
209 __map_groups__fixup_end(mg, i);
210}
211
212struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) 205struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
213{ 206{
214 size_t namelen = strlen(name) + 1; 207 size_t namelen = strlen(name) + 1;
@@ -652,8 +645,8 @@ discard_symbol: rb_erase(&pos->rb_node, root);
652 return count + moved; 645 return count + moved;
653} 646}
654 647
655static bool symbol__restricted_filename(const char *filename, 648bool symbol__restricted_filename(const char *filename,
656 const char *restricted_filename) 649 const char *restricted_filename)
657{ 650{
658 bool restricted = false; 651 bool restricted = false;
659 652
@@ -887,200 +880,6 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
887 return NULL; 880 return NULL;
888} 881}
889 882
890static int map_groups__set_modules_path_dir(struct map_groups *mg,
891 const char *dir_name)
892{
893 struct dirent *dent;
894 DIR *dir = opendir(dir_name);
895 int ret = 0;
896
897 if (!dir) {
898 pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
899 return -1;
900 }
901
902 while ((dent = readdir(dir)) != NULL) {
903 char path[PATH_MAX];
904 struct stat st;
905
906 /*sshfs might return bad dent->d_type, so we have to stat*/
907 snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
908 if (stat(path, &st))
909 continue;
910
911 if (S_ISDIR(st.st_mode)) {
912 if (!strcmp(dent->d_name, ".") ||
913 !strcmp(dent->d_name, ".."))
914 continue;
915
916 ret = map_groups__set_modules_path_dir(mg, path);
917 if (ret < 0)
918 goto out;
919 } else {
920 char *dot = strrchr(dent->d_name, '.'),
921 dso_name[PATH_MAX];
922 struct map *map;
923 char *long_name;
924
925 if (dot == NULL || strcmp(dot, ".ko"))
926 continue;
927 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
928 (int)(dot - dent->d_name), dent->d_name);
929
930 strxfrchar(dso_name, '-', '_');
931 map = map_groups__find_by_name(mg, MAP__FUNCTION,
932 dso_name);
933 if (map == NULL)
934 continue;
935
936 long_name = strdup(path);
937 if (long_name == NULL) {
938 ret = -1;
939 goto out;
940 }
941 dso__set_long_name(map->dso, long_name);
942 map->dso->lname_alloc = 1;
943 dso__kernel_module_get_build_id(map->dso, "");
944 }
945 }
946
947out:
948 closedir(dir);
949 return ret;
950}
951
952static char *get_kernel_version(const char *root_dir)
953{
954 char version[PATH_MAX];
955 FILE *file;
956 char *name, *tmp;
957 const char *prefix = "Linux version ";
958
959 sprintf(version, "%s/proc/version", root_dir);
960 file = fopen(version, "r");
961 if (!file)
962 return NULL;
963
964 version[0] = '\0';
965 tmp = fgets(version, sizeof(version), file);
966 fclose(file);
967
968 name = strstr(version, prefix);
969 if (!name)
970 return NULL;
971 name += strlen(prefix);
972 tmp = strchr(name, ' ');
973 if (tmp)
974 *tmp = '\0';
975
976 return strdup(name);
977}
978
979static int machine__set_modules_path(struct machine *machine)
980{
981 char *version;
982 char modules_path[PATH_MAX];
983
984 version = get_kernel_version(machine->root_dir);
985 if (!version)
986 return -1;
987
988 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
989 machine->root_dir, version);
990 free(version);
991
992 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
993}
994
995struct map *machine__new_module(struct machine *machine, u64 start,
996 const char *filename)
997{
998 struct map *map;
999 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
1000
1001 if (dso == NULL)
1002 return NULL;
1003
1004 map = map__new2(start, dso, MAP__FUNCTION);
1005 if (map == NULL)
1006 return NULL;
1007
1008 if (machine__is_host(machine))
1009 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
1010 else
1011 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
1012 map_groups__insert(&machine->kmaps, map);
1013 return map;
1014}
1015
1016static int machine__create_modules(struct machine *machine)
1017{
1018 char *line = NULL;
1019 size_t n;
1020 FILE *file;
1021 struct map *map;
1022 const char *modules;
1023 char path[PATH_MAX];
1024
1025 if (machine__is_default_guest(machine))
1026 modules = symbol_conf.default_guest_modules;
1027 else {
1028 sprintf(path, "%s/proc/modules", machine->root_dir);
1029 modules = path;
1030 }
1031
1032 if (symbol__restricted_filename(path, "/proc/modules"))
1033 return -1;
1034
1035 file = fopen(modules, "r");
1036 if (file == NULL)
1037 return -1;
1038
1039 while (!feof(file)) {
1040 char name[PATH_MAX];
1041 u64 start;
1042 char *sep;
1043 int line_len;
1044
1045 line_len = getline(&line, &n, file);
1046 if (line_len < 0)
1047 break;
1048
1049 if (!line)
1050 goto out_failure;
1051
1052 line[--line_len] = '\0'; /* \n */
1053
1054 sep = strrchr(line, 'x');
1055 if (sep == NULL)
1056 continue;
1057
1058 hex2u64(sep + 1, &start);
1059
1060 sep = strchr(line, ' ');
1061 if (sep == NULL)
1062 continue;
1063
1064 *sep = '\0';
1065
1066 snprintf(name, sizeof(name), "[%s]", line);
1067 map = machine__new_module(machine, start, name);
1068 if (map == NULL)
1069 goto out_delete_line;
1070 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
1071 }
1072
1073 free(line);
1074 fclose(file);
1075
1076 return machine__set_modules_path(machine);
1077
1078out_delete_line:
1079 free(line);
1080out_failure:
1081 return -1;
1082}
1083
1084int dso__load_vmlinux(struct dso *dso, struct map *map, 883int dso__load_vmlinux(struct dso *dso, struct map *map,
1085 const char *vmlinux, symbol_filter_t filter) 884 const char *vmlinux, symbol_filter_t filter)
1086{ 885{
@@ -1300,195 +1099,6 @@ out_try_fixup:
1300 return err; 1099 return err;
1301} 1100}
1302 1101
1303size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
1304{
1305 struct rb_node *nd;
1306 size_t ret = 0;
1307
1308 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
1309 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1310 ret += __dsos__fprintf(&pos->kernel_dsos, fp);
1311 ret += __dsos__fprintf(&pos->user_dsos, fp);
1312 }
1313
1314 return ret;
1315}
1316
1317size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
1318 bool with_hits)
1319{
1320 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) +
1321 __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits);
1322}
1323
1324size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
1325 FILE *fp, bool with_hits)
1326{
1327 struct rb_node *nd;
1328 size_t ret = 0;
1329
1330 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
1331 struct machine *pos = rb_entry(nd, struct machine, rb_node);
1332 ret += machine__fprintf_dsos_buildid(pos, fp, with_hits);
1333 }
1334 return ret;
1335}
1336
1337static struct dso *machine__get_kernel(struct machine *machine)
1338{
1339 const char *vmlinux_name = NULL;
1340 struct dso *kernel;
1341
1342 if (machine__is_host(machine)) {
1343 vmlinux_name = symbol_conf.vmlinux_name;
1344 if (!vmlinux_name)
1345 vmlinux_name = "[kernel.kallsyms]";
1346
1347 kernel = dso__kernel_findnew(machine, vmlinux_name,
1348 "[kernel]",
1349 DSO_TYPE_KERNEL);
1350 } else {
1351 char bf[PATH_MAX];
1352
1353 if (machine__is_default_guest(machine))
1354 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
1355 if (!vmlinux_name)
1356 vmlinux_name = machine__mmap_name(machine, bf,
1357 sizeof(bf));
1358
1359 kernel = dso__kernel_findnew(machine, vmlinux_name,
1360 "[guest.kernel]",
1361 DSO_TYPE_GUEST_KERNEL);
1362 }
1363
1364 if (kernel != NULL && (!kernel->has_build_id))
1365 dso__read_running_kernel_build_id(kernel, machine);
1366
1367 return kernel;
1368}
1369
1370struct process_args {
1371 u64 start;
1372};
1373
1374static int symbol__in_kernel(void *arg, const char *name,
1375 char type __maybe_unused, u64 start)
1376{
1377 struct process_args *args = arg;
1378
1379 if (strchr(name, '['))
1380 return 0;
1381
1382 args->start = start;
1383 return 1;
1384}
1385
1386/* Figure out the start address of kernel map from /proc/kallsyms */
1387static u64 machine__get_kernel_start_addr(struct machine *machine)
1388{
1389 const char *filename;
1390 char path[PATH_MAX];
1391 struct process_args args;
1392
1393 if (machine__is_host(machine)) {
1394 filename = "/proc/kallsyms";
1395 } else {
1396 if (machine__is_default_guest(machine))
1397 filename = (char *)symbol_conf.default_guest_kallsyms;
1398 else {
1399 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
1400 filename = path;
1401 }
1402 }
1403
1404 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
1405 return 0;
1406
1407 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
1408 return 0;
1409
1410 return args.start;
1411}
1412
1413int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
1414{
1415 enum map_type type;
1416 u64 start = machine__get_kernel_start_addr(machine);
1417
1418 for (type = 0; type < MAP__NR_TYPES; ++type) {
1419 struct kmap *kmap;
1420
1421 machine->vmlinux_maps[type] = map__new2(start, kernel, type);
1422 if (machine->vmlinux_maps[type] == NULL)
1423 return -1;
1424
1425 machine->vmlinux_maps[type]->map_ip =
1426 machine->vmlinux_maps[type]->unmap_ip =
1427 identity__map_ip;
1428 kmap = map__kmap(machine->vmlinux_maps[type]);
1429 kmap->kmaps = &machine->kmaps;
1430 map_groups__insert(&machine->kmaps,
1431 machine->vmlinux_maps[type]);
1432 }
1433
1434 return 0;
1435}
1436
1437void machine__destroy_kernel_maps(struct machine *machine)
1438{
1439 enum map_type type;
1440
1441 for (type = 0; type < MAP__NR_TYPES; ++type) {
1442 struct kmap *kmap;
1443
1444 if (machine->vmlinux_maps[type] == NULL)
1445 continue;
1446
1447 kmap = map__kmap(machine->vmlinux_maps[type]);
1448 map_groups__remove(&machine->kmaps,
1449 machine->vmlinux_maps[type]);
1450 if (kmap->ref_reloc_sym) {
1451 /*
1452 * ref_reloc_sym is shared among all maps, so free just
1453 * on one of them.
1454 */
1455 if (type == MAP__FUNCTION) {
1456 free((char *)kmap->ref_reloc_sym->name);
1457 kmap->ref_reloc_sym->name = NULL;
1458 free(kmap->ref_reloc_sym);
1459 }
1460 kmap->ref_reloc_sym = NULL;
1461 }
1462
1463 map__delete(machine->vmlinux_maps[type]);
1464 machine->vmlinux_maps[type] = NULL;
1465 }
1466}
1467
1468int machine__create_kernel_maps(struct machine *machine)
1469{
1470 struct dso *kernel = machine__get_kernel(machine);
1471
1472 if (kernel == NULL ||
1473 __machine__create_kernel_maps(machine, kernel) < 0)
1474 return -1;
1475
1476 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
1477 if (machine__is_host(machine))
1478 pr_debug("Problems creating module maps, "
1479 "continuing anyway...\n");
1480 else
1481 pr_debug("Problems creating module maps for guest %d, "
1482 "continuing anyway...\n", machine->pid);
1483 }
1484
1485 /*
1486 * Now that we have all the maps created, just set the ->end of them:
1487 */
1488 map_groups__fixup_end(&machine->kmaps);
1489 return 0;
1490}
1491
1492static void vmlinux_path__exit(void) 1102static void vmlinux_path__exit(void)
1493{ 1103{
1494 while (--vmlinux_path__nr_entries >= 0) { 1104 while (--vmlinux_path__nr_entries >= 0) {
@@ -1549,25 +1159,6 @@ out_fail:
1549 return -1; 1159 return -1;
1550} 1160}
1551 1161
1552size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
1553{
1554 int i;
1555 size_t printed = 0;
1556 struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
1557
1558 if (kdso->has_build_id) {
1559 char filename[PATH_MAX];
1560 if (dso__build_id_filename(kdso, filename, sizeof(filename)))
1561 printed += fprintf(fp, "[0] %s\n", filename);
1562 }
1563
1564 for (i = 0; i < vmlinux_path__nr_entries; ++i)
1565 printed += fprintf(fp, "[%d] %s\n",
1566 i + kdso->has_build_id, vmlinux_path[i]);
1567
1568 return printed;
1569}
1570
1571static int setup_list(struct strlist **list, const char *list_str, 1162static int setup_list(struct strlist **list, const char *list_str,
1572 const char *list_name) 1163 const char *list_name)
1573{ 1164{
@@ -1671,108 +1262,3 @@ void symbol__exit(void)
1671 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 1262 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
1672 symbol_conf.initialized = false; 1263 symbol_conf.initialized = false;
1673} 1264}
1674
1675int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
1676{
1677 struct machine *machine = machines__findnew(machines, pid);
1678
1679 if (machine == NULL)
1680 return -1;
1681
1682 return machine__create_kernel_maps(machine);
1683}
1684
1685int machines__create_guest_kernel_maps(struct rb_root *machines)
1686{
1687 int ret = 0;
1688 struct dirent **namelist = NULL;
1689 int i, items = 0;
1690 char path[PATH_MAX];
1691 pid_t pid;
1692 char *endp;
1693
1694 if (symbol_conf.default_guest_vmlinux_name ||
1695 symbol_conf.default_guest_modules ||
1696 symbol_conf.default_guest_kallsyms) {
1697 machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
1698 }
1699
1700 if (symbol_conf.guestmount) {
1701 items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
1702 if (items <= 0)
1703 return -ENOENT;
1704 for (i = 0; i < items; i++) {
1705 if (!isdigit(namelist[i]->d_name[0])) {
1706 /* Filter out . and .. */
1707 continue;
1708 }
1709 pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
1710 if ((*endp != '\0') ||
1711 (endp == namelist[i]->d_name) ||
1712 (errno == ERANGE)) {
1713 pr_debug("invalid directory (%s). Skipping.\n",
1714 namelist[i]->d_name);
1715 continue;
1716 }
1717 sprintf(path, "%s/%s/proc/kallsyms",
1718 symbol_conf.guestmount,
1719 namelist[i]->d_name);
1720 ret = access(path, R_OK);
1721 if (ret) {
1722 pr_debug("Can't access file %s\n", path);
1723 goto failure;
1724 }
1725 machines__create_kernel_maps(machines, pid);
1726 }
1727failure:
1728 free(namelist);
1729 }
1730
1731 return ret;
1732}
1733
1734void machines__destroy_guest_kernel_maps(struct rb_root *machines)
1735{
1736 struct rb_node *next = rb_first(machines);
1737
1738 while (next) {
1739 struct machine *pos = rb_entry(next, struct machine, rb_node);
1740
1741 next = rb_next(&pos->rb_node);
1742 rb_erase(&pos->rb_node, machines);
1743 machine__delete(pos);
1744 }
1745}
1746
1747int machine__load_kallsyms(struct machine *machine, const char *filename,
1748 enum map_type type, symbol_filter_t filter)
1749{
1750 struct map *map = machine->vmlinux_maps[type];
1751 int ret = dso__load_kallsyms(map->dso, filename, map, filter);
1752
1753 if (ret > 0) {
1754 dso__set_loaded(map->dso, type);
1755 /*
1756 * Since /proc/kallsyms will have multiple sessions for the
1757 * kernel, with modules between them, fixup the end of all
1758 * sections.
1759 */
1760 __map_groups__fixup_end(&machine->kmaps, type);
1761 }
1762
1763 return ret;
1764}
1765
1766int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
1767 symbol_filter_t filter)
1768{
1769 struct map *map = machine->vmlinux_maps[type];
1770 int ret = dso__load_vmlinux_path(map->dso, map, filter);
1771
1772 if (ret > 0) {
1773 dso__set_loaded(map->dso, type);
1774 map__reloc_vmlinux(map);
1775 }
1776
1777 return ret;
1778}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index de68f98b236d..ec7b2405c377 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -120,6 +120,8 @@ struct symbol_conf {
120}; 120};
121 121
122extern struct symbol_conf symbol_conf; 122extern struct symbol_conf symbol_conf;
123extern int vmlinux_path__nr_entries;
124extern char **vmlinux_path;
123 125
124static inline void *symbol__priv(struct symbol *sym) 126static inline void *symbol__priv(struct symbol *sym)
125{ 127{
@@ -223,6 +225,8 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym,
223size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 225size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
224size_t symbol__fprintf(struct symbol *sym, FILE *fp); 226size_t symbol__fprintf(struct symbol *sym, FILE *fp);
225bool symbol_type__is_a(char symbol_type, enum map_type map_type); 227bool symbol_type__is_a(char symbol_type, enum map_type map_type);
228bool symbol__restricted_filename(const char *filename,
229 const char *restricted_filename);
226 230
227int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 231int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
228 struct symsrc *runtime_ss, symbol_filter_t filter, 232 struct symsrc *runtime_ss, symbol_filter_t filter,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index df59623ac763..632e40e5ceca 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -54,10 +54,10 @@ int thread__comm_len(struct thread *self)
54 return self->comm_len; 54 return self->comm_len;
55} 55}
56 56
57static size_t thread__fprintf(struct thread *self, FILE *fp) 57size_t thread__fprintf(struct thread *thread, FILE *fp)
58{ 58{
59 return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) + 59 return fprintf(fp, "Thread %d %s\n", thread->pid, thread->comm) +
60 map_groups__fprintf(&self->mg, verbose, fp); 60 map_groups__fprintf(&thread->mg, verbose, fp);
61} 61}
62 62
63void thread__insert_map(struct thread *self, struct map *map) 63void thread__insert_map(struct thread *self, struct map *map)
@@ -84,17 +84,3 @@ int thread__fork(struct thread *self, struct thread *parent)
84 return -ENOMEM; 84 return -ENOMEM;
85 return 0; 85 return 0;
86} 86}
87
88size_t machine__fprintf(struct machine *machine, FILE *fp)
89{
90 size_t ret = 0;
91 struct rb_node *nd;
92
93 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
94 struct thread *pos = rb_entry(nd, struct thread, rb_node);
95
96 ret += thread__fprintf(pos, fp);
97 }
98
99 return ret;
100}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index f2fa17caa7d5..5ad266403098 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -30,6 +30,7 @@ int thread__set_comm(struct thread *self, const char *comm);
30int thread__comm_len(struct thread *self); 30int thread__comm_len(struct thread *self);
31void thread__insert_map(struct thread *self, struct map *map); 31void thread__insert_map(struct thread *self, struct map *map);
32int thread__fork(struct thread *self, struct thread *parent); 32int thread__fork(struct thread *self, struct thread *parent);
33size_t thread__fprintf(struct thread *thread, FILE *fp);
33 34
34static inline struct map *thread__find_map(struct thread *self, 35static inline struct map *thread__find_map(struct thread *self,
35 enum map_type type, u64 addr) 36 enum map_type type, u64 addr)
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 884dde9b9bc1..54d37a4753c5 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -26,6 +26,8 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
26 float samples_per_sec = top->samples / top->delay_secs; 26 float samples_per_sec = top->samples / top->delay_secs;
27 float ksamples_per_sec = top->kernel_samples / top->delay_secs; 27 float ksamples_per_sec = top->kernel_samples / top->delay_secs;
28 float esamples_percent = (100.0 * top->exact_samples) / top->samples; 28 float esamples_percent = (100.0 * top->exact_samples) / top->samples;
29 struct perf_record_opts *opts = &top->record_opts;
30 struct perf_target *target = &opts->target;
29 size_t ret = 0; 31 size_t ret = 0;
30 32
31 if (!perf_guest) { 33 if (!perf_guest) {
@@ -61,31 +63,31 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
61 struct perf_evsel *first = perf_evlist__first(top->evlist); 63 struct perf_evsel *first = perf_evlist__first(top->evlist);
62 ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", 64 ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
63 (uint64_t)first->attr.sample_period, 65 (uint64_t)first->attr.sample_period,
64 top->freq ? "Hz" : ""); 66 opts->freq ? "Hz" : "");
65 } 67 }
66 68
67 ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel)); 69 ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel));
68 70
69 ret += SNPRINTF(bf + ret, size - ret, "], "); 71 ret += SNPRINTF(bf + ret, size - ret, "], ");
70 72
71 if (top->target.pid) 73 if (target->pid)
72 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s", 74 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
73 top->target.pid); 75 target->pid);
74 else if (top->target.tid) 76 else if (target->tid)
75 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s", 77 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s",
76 top->target.tid); 78 target->tid);
77 else if (top->target.uid_str != NULL) 79 else if (target->uid_str != NULL)
78 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s", 80 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
79 top->target.uid_str); 81 target->uid_str);
80 else 82 else
81 ret += SNPRINTF(bf + ret, size - ret, " (all"); 83 ret += SNPRINTF(bf + ret, size - ret, " (all");
82 84
83 if (top->target.cpu_list) 85 if (target->cpu_list)
84 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", 86 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
85 top->evlist->cpus->nr > 1 ? "s" : "", 87 top->evlist->cpus->nr > 1 ? "s" : "",
86 top->target.cpu_list); 88 target->cpu_list);
87 else { 89 else {
88 if (top->target.tid) 90 if (target->tid)
89 ret += SNPRINTF(bf + ret, size - ret, ")"); 91 ret += SNPRINTF(bf + ret, size - ret, ")");
90 else 92 else
91 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", 93 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 86ff1b15059b..927c229c2d9a 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -14,7 +14,7 @@ struct perf_session;
14struct perf_top { 14struct perf_top {
15 struct perf_tool tool; 15 struct perf_tool tool;
16 struct perf_evlist *evlist; 16 struct perf_evlist *evlist;
17 struct perf_target target; 17 struct perf_record_opts record_opts;
18 /* 18 /*
19 * Symbols will be added here in perf_event__process_sample and will 19 * Symbols will be added here in perf_event__process_sample and will
20 * get out after decayed. 20 * get out after decayed.
@@ -24,15 +24,11 @@ struct perf_top {
24 u64 exact_samples; 24 u64 exact_samples;
25 u64 guest_us_samples, guest_kernel_samples; 25 u64 guest_us_samples, guest_kernel_samples;
26 int print_entries, count_filter, delay_secs; 26 int print_entries, count_filter, delay_secs;
27 int freq;
28 bool hide_kernel_symbols, hide_user_symbols, zero; 27 bool hide_kernel_symbols, hide_user_symbols, zero;
29 bool use_tui, use_stdio; 28 bool use_tui, use_stdio;
30 bool sort_has_symbols; 29 bool sort_has_symbols;
31 bool dont_use_callchains;
32 bool kptr_restrict_warned; 30 bool kptr_restrict_warned;
33 bool vmlinux_warned; 31 bool vmlinux_warned;
34 bool inherit;
35 bool group;
36 bool sample_id_all_missing; 32 bool sample_id_all_missing;
37 bool exclude_guest_missing; 33 bool exclude_guest_missing;
38 bool dump_symtab; 34 bool dump_symtab;
@@ -40,8 +36,6 @@ struct perf_top {
40 struct perf_evsel *sym_evsel; 36 struct perf_evsel *sym_evsel;
41 struct perf_session *session; 37 struct perf_session *session;
42 struct winsize winsize; 38 struct winsize winsize;
43 unsigned int mmap_pages;
44 int default_interval;
45 int realtime_prio; 39 int realtime_prio;
46 int sym_pcnt_filter; 40 int sym_pcnt_filter;
47 const char *sym_filter; 41 const char *sym_filter;