aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/hv/hv_kvp_daemon.c29
-rw-r--r--tools/hv/hv_vss_daemon.c8
-rw-r--r--tools/lib/traceevent/Makefile18
-rw-r--r--tools/lib/traceevent/event-parse.c165
-rw-r--r--tools/lib/traceevent/event-parse.h14
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/Makefile79
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt13
-rw-r--r--tools/perf/Documentation/perf-kvm.txt4
-rw-r--r--tools/perf/Documentation/perf-lock.txt2
-rw-r--r--tools/perf/Documentation/perf-record.txt25
-rw-r--r--tools/perf/Documentation/perf-report.txt16
-rw-r--r--tools/perf/Documentation/perf-stat.txt5
-rw-r--r--tools/perf/Documentation/perf-timechart.txt15
-rw-r--r--tools/perf/Documentation/perf-top.txt33
-rw-r--r--tools/perf/Documentation/perf-trace.txt31
-rw-r--r--tools/perf/Makefile848
-rw-r--r--tools/perf/Makefile.perf892
-rw-r--r--tools/perf/arch/x86/include/perf_regs.h6
-rw-r--r--tools/perf/arch/x86/util/unwind.c4
-rw-r--r--tools/perf/bash_completion106
-rw-r--r--tools/perf/bench/mem-memcpy-arch.h2
-rw-r--r--tools/perf/bench/mem-memcpy.c2
-rw-r--r--tools/perf/bench/mem-memset-arch.h2
-rw-r--r--tools/perf/bench/mem-memset.c2
-rw-r--r--tools/perf/bench/numa.c38
-rw-r--r--tools/perf/bench/sched-pipe.c115
-rw-r--r--tools/perf/builtin-annotate.c45
-rw-r--r--tools/perf/builtin-bench.c245
-rw-r--r--tools/perf/builtin-buildid-cache.c156
-rw-r--r--tools/perf/builtin-buildid-list.c11
-rw-r--r--tools/perf/builtin-diff.c31
-rw-r--r--tools/perf/builtin-evlist.c7
-rw-r--r--tools/perf/builtin-inject.c46
-rw-r--r--tools/perf/builtin-kmem.c13
-rw-r--r--tools/perf/builtin-kvm.c37
-rw-r--r--tools/perf/builtin-list.c84
-rw-r--r--tools/perf/builtin-lock.c137
-rw-r--r--tools/perf/builtin-mem.c9
-rw-r--r--tools/perf/builtin-probe.c14
-rw-r--r--tools/perf/builtin-record.c241
-rw-r--r--tools/perf/builtin-report.c124
-rw-r--r--tools/perf/builtin-sched.c70
-rw-r--r--tools/perf/builtin-script.c127
-rw-r--r--tools/perf/builtin-stat.c211
-rw-r--r--tools/perf/builtin-timechart.c14
-rw-r--r--tools/perf/builtin-top.c94
-rw-r--r--tools/perf/builtin-trace.c1411
-rw-r--r--tools/perf/config/Makefile380
-rw-r--r--tools/perf/config/feature-checks/Makefile149
-rw-r--r--tools/perf/config/feature-checks/test-all.c115
-rw-r--r--tools/perf/config/feature-checks/test-backtrace.c13
-rw-r--r--tools/perf/config/feature-checks/test-bionic.c6
-rw-r--r--tools/perf/config/feature-checks/test-cplus-demangle.c14
-rw-r--r--tools/perf/config/feature-checks/test-dwarf.c10
-rw-r--r--tools/perf/config/feature-checks/test-fortify-source.c6
-rw-r--r--tools/perf/config/feature-checks/test-glibc.c8
-rw-r--r--tools/perf/config/feature-checks/test-gtk2-infobar.c11
-rw-r--r--tools/perf/config/feature-checks/test-gtk2.c10
-rw-r--r--tools/perf/config/feature-checks/test-hello.c6
-rw-r--r--tools/perf/config/feature-checks/test-libaudit.c10
-rw-r--r--tools/perf/config/feature-checks/test-libbfd.c15
-rw-r--r--tools/perf/config/feature-checks/test-libelf-getphdrnum.c8
-rw-r--r--tools/perf/config/feature-checks/test-libelf-mmap.c8
-rw-r--r--tools/perf/config/feature-checks/test-libelf.c8
-rw-r--r--tools/perf/config/feature-checks/test-libnuma.c9
-rw-r--r--tools/perf/config/feature-checks/test-libperl.c9
-rw-r--r--tools/perf/config/feature-checks/test-libpython-version.c10
-rw-r--r--tools/perf/config/feature-checks/test-libpython.c8
-rw-r--r--tools/perf/config/feature-checks/test-libslang.c6
-rw-r--r--tools/perf/config/feature-checks/test-libunwind-debug-frame.c16
-rw-r--r--tools/perf/config/feature-checks/test-libunwind.c27
-rw-r--r--tools/perf/config/feature-checks/test-on-exit.c16
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector-all.c6
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector.c6
-rw-r--r--tools/perf/config/feature-checks/test-timerfd.c18
-rw-r--r--tools/perf/config/feature-checks/test-volatile-register-var.c6
-rw-r--r--tools/perf/config/feature-tests.mak265
-rw-r--r--tools/perf/config/utilities.mak17
-rw-r--r--tools/perf/perf.c14
-rw-r--r--tools/perf/perf.h65
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c6
-rw-r--r--tools/perf/tests/attr/README6
-rw-r--r--tools/perf/tests/attr/test-record-graph-default2
-rw-r--r--tools/perf/tests/attr/test-record-graph-dwarf2
-rw-r--r--tools/perf/tests/attr/test-record-graph-fp2
-rw-r--r--tools/perf/tests/code-reading.c3
-rw-r--r--tools/perf/tests/dso-data.c1
-rw-r--r--tools/perf/tests/hists_link.c14
-rw-r--r--tools/perf/tests/keep-tracking.c1
-rw-r--r--tools/perf/tests/mmap-basic.c1
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c4
-rw-r--r--tools/perf/tests/parse-events.c6
-rw-r--r--tools/perf/tests/perf-record.c14
-rw-r--r--tools/perf/tests/perf-time-to-tsc.c4
-rw-r--r--tools/perf/tests/rdpmc.c2
-rw-r--r--tools/perf/tests/sample-parsing.c11
-rw-r--r--tools/perf/tests/sw-clock.c4
-rw-r--r--tools/perf/tests/task-exit.c20
-rw-r--r--tools/perf/ui/browser.h32
-rw-r--r--tools/perf/ui/browsers/annotate.c24
-rw-r--r--tools/perf/ui/browsers/hists.c12
-rw-r--r--tools/perf/ui/browsers/map.c40
-rw-r--r--tools/perf/ui/browsers/map.h2
-rw-r--r--tools/perf/ui/browsers/scripts.c8
-rw-r--r--tools/perf/ui/gtk/annotate.c13
-rw-r--r--tools/perf/ui/gtk/browser.c2
-rw-r--r--tools/perf/ui/gtk/gtk.h22
-rw-r--r--tools/perf/ui/gtk/progress.c20
-rw-r--r--tools/perf/ui/gtk/setup.c2
-rw-r--r--tools/perf/ui/gtk/util.c4
-rw-r--r--tools/perf/ui/hist.c2
-rw-r--r--tools/perf/ui/progress.c32
-rw-r--r--tools/perf/ui/progress.h19
-rw-r--r--tools/perf/ui/setup.c61
-rw-r--r--tools/perf/ui/stdio/hist.c23
-rw-r--r--tools/perf/ui/tui/progress.c15
-rw-r--r--tools/perf/ui/tui/setup.c3
-rw-r--r--tools/perf/ui/tui/tui.h6
-rw-r--r--tools/perf/ui/ui.h14
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN5
-rw-r--r--tools/perf/util/annotate.c76
-rw-r--r--tools/perf/util/annotate.h26
-rw-r--r--tools/perf/util/build-id.c6
-rw-r--r--tools/perf/util/build-id.h3
-rw-r--r--tools/perf/util/cache.h3
-rw-r--r--tools/perf/util/callchain.c147
-rw-r--r--tools/perf/util/callchain.h14
-rw-r--r--tools/perf/util/color.c11
-rw-r--r--tools/perf/util/color.h2
-rw-r--r--tools/perf/util/comm.c121
-rw-r--r--tools/perf/util/comm.h21
-rw-r--r--tools/perf/util/cpumap.c6
-rw-r--r--tools/perf/util/data.c120
-rw-r--r--tools/perf/util/data.h48
-rw-r--r--tools/perf/util/dso.c50
-rw-r--r--tools/perf/util/dso.h3
-rw-r--r--tools/perf/util/event.c40
-rw-r--r--tools/perf/util/event.h14
-rw-r--r--tools/perf/util/evlist.c262
-rw-r--r--tools/perf/util/evlist.h21
-rw-r--r--tools/perf/util/evsel.c29
-rw-r--r--tools/perf/util/evsel.h11
-rw-r--r--tools/perf/util/fs.c119
-rw-r--r--tools/perf/util/fs.h7
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh4
-rw-r--r--tools/perf/util/header.c22
-rw-r--r--tools/perf/util/hist.c95
-rw-r--r--tools/perf/util/hist.h88
-rw-r--r--tools/perf/util/include/dwarf-regs.h2
-rw-r--r--tools/perf/util/include/linux/compiler.h19
-rw-r--r--tools/perf/util/include/linux/magic.h4
-rw-r--r--tools/perf/util/intlist.c23
-rw-r--r--tools/perf/util/intlist.h2
-rw-r--r--tools/perf/util/machine.c166
-rw-r--r--tools/perf/util/machine.h29
-rw-r--r--tools/perf/util/map.c50
-rw-r--r--tools/perf/util/map.h7
-rw-r--r--tools/perf/util/parse-events.c4
-rw-r--r--tools/perf/util/parse-events.l63
-rw-r--r--tools/perf/util/parse-options.c218
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/path.c10
-rw-r--r--tools/perf/util/perf_regs.h4
-rw-r--r--tools/perf/util/pmu.c33
-rw-r--r--tools/perf/util/pmu.h1
-rw-r--r--tools/perf/util/probe-event.c5
-rw-r--r--tools/perf/util/probe-finder.c248
-rw-r--r--tools/perf/util/probe-finder.h15
-rw-r--r--tools/perf/util/pstack.h10
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/python.c10
-rw-r--r--tools/perf/util/rblist.c27
-rw-r--r--tools/perf/util/rblist.h1
-rw-r--r--tools/perf/util/record.c71
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c41
-rw-r--r--tools/perf/util/session.c278
-rw-r--r--tools/perf/util/session.h38
-rw-r--r--tools/perf/util/sort.c318
-rw-r--r--tools/perf/util/sort.h8
-rw-r--r--tools/perf/util/srcline.c265
-rw-r--r--tools/perf/util/strfilter.c72
-rw-r--r--tools/perf/util/strfilter.h12
-rw-r--r--tools/perf/util/symbol-elf.c607
-rw-r--r--tools/perf/util/symbol-minimal.c15
-rw-r--r--tools/perf/util/symbol.c449
-rw-r--r--tools/perf/util/symbol.h29
-rw-r--r--tools/perf/util/sysfs.c60
-rw-r--r--tools/perf/util/sysfs.h6
-rw-r--r--tools/perf/util/thread.c137
-rw-r--r--tools/perf/util/thread.h20
-rw-r--r--tools/perf/util/top.h1
-rw-r--r--tools/perf/util/trace-event-parse.c36
-rw-r--r--tools/perf/util/trace-event.h9
-rw-r--r--tools/perf/util/unwind.h4
-rw-r--r--tools/perf/util/util.c66
-rw-r--r--tools/perf/util/util.h26
-rw-r--r--tools/scripts/Makefile.include23
-rw-r--r--tools/testing/ktest/examples/crosstests.conf6
-rw-r--r--tools/vm/page-types.c32
201 files changed, 8607 insertions, 3691 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 8fd9ec66121c..b8d6d541d854 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -89,6 +89,7 @@ static char *processor_arch;
89static char *os_build; 89static char *os_build;
90static char *os_version; 90static char *os_version;
91static char *lic_version = "Unknown version"; 91static char *lic_version = "Unknown version";
92static char full_domain_name[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
92static struct utsname uts_buf; 93static struct utsname uts_buf;
93 94
94/* 95/*
@@ -1367,7 +1368,7 @@ setval_error:
1367} 1368}
1368 1369
1369 1370
1370static int 1371static void
1371kvp_get_domain_name(char *buffer, int length) 1372kvp_get_domain_name(char *buffer, int length)
1372{ 1373{
1373 struct addrinfo hints, *info ; 1374 struct addrinfo hints, *info ;
@@ -1381,12 +1382,12 @@ kvp_get_domain_name(char *buffer, int length)
1381 1382
1382 error = getaddrinfo(buffer, NULL, &hints, &info); 1383 error = getaddrinfo(buffer, NULL, &hints, &info);
1383 if (error != 0) { 1384 if (error != 0) {
1384 strcpy(buffer, "getaddrinfo failed\n"); 1385 snprintf(buffer, length, "getaddrinfo failed: 0x%x %s",
1385 return error; 1386 error, gai_strerror(error));
1387 return;
1386 } 1388 }
1387 strcpy(buffer, info->ai_canonname); 1389 snprintf(buffer, length, "%s", info->ai_canonname);
1388 freeaddrinfo(info); 1390 freeaddrinfo(info);
1389 return error;
1390} 1391}
1391 1392
1392static int 1393static int
@@ -1433,7 +1434,6 @@ int main(void)
1433 int pool; 1434 int pool;
1434 char *if_name; 1435 char *if_name;
1435 struct hv_kvp_ipaddr_value *kvp_ip_val; 1436 struct hv_kvp_ipaddr_value *kvp_ip_val;
1436 char *kvp_send_buffer;
1437 char *kvp_recv_buffer; 1437 char *kvp_recv_buffer;
1438 size_t kvp_recv_buffer_len; 1438 size_t kvp_recv_buffer_len;
1439 1439
@@ -1442,17 +1442,21 @@ int main(void)
1442 openlog("KVP", 0, LOG_USER); 1442 openlog("KVP", 0, LOG_USER);
1443 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); 1443 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
1444 1444
1445 kvp_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg); 1445 kvp_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg);
1446 kvp_send_buffer = calloc(1, kvp_recv_buffer_len);
1447 kvp_recv_buffer = calloc(1, kvp_recv_buffer_len); 1446 kvp_recv_buffer = calloc(1, kvp_recv_buffer_len);
1448 if (!(kvp_send_buffer && kvp_recv_buffer)) { 1447 if (!kvp_recv_buffer) {
1449 syslog(LOG_ERR, "Failed to allocate netlink buffers"); 1448 syslog(LOG_ERR, "Failed to allocate netlink buffer");
1450 exit(EXIT_FAILURE); 1449 exit(EXIT_FAILURE);
1451 } 1450 }
1452 /* 1451 /*
1453 * Retrieve OS release information. 1452 * Retrieve OS release information.
1454 */ 1453 */
1455 kvp_get_os_info(); 1454 kvp_get_os_info();
1455 /*
1456 * Cache Fully Qualified Domain Name because getaddrinfo takes an
1457 * unpredictable amount of time to finish.
1458 */
1459 kvp_get_domain_name(full_domain_name, sizeof(full_domain_name));
1456 1460
1457 if (kvp_file_init()) { 1461 if (kvp_file_init()) {
1458 syslog(LOG_ERR, "Failed to initialize the pools"); 1462 syslog(LOG_ERR, "Failed to initialize the pools");
@@ -1488,7 +1492,7 @@ int main(void)
1488 /* 1492 /*
1489 * Register ourselves with the kernel. 1493 * Register ourselves with the kernel.
1490 */ 1494 */
1491 message = (struct cn_msg *)kvp_send_buffer; 1495 message = (struct cn_msg *)kvp_recv_buffer;
1492 message->id.idx = CN_KVP_IDX; 1496 message->id.idx = CN_KVP_IDX;
1493 message->id.val = CN_KVP_VAL; 1497 message->id.val = CN_KVP_VAL;
1494 1498
@@ -1671,8 +1675,7 @@ int main(void)
1671 1675
1672 switch (hv_msg->body.kvp_enum_data.index) { 1676 switch (hv_msg->body.kvp_enum_data.index) {
1673 case FullyQualifiedDomainName: 1677 case FullyQualifiedDomainName:
1674 kvp_get_domain_name(key_value, 1678 strcpy(key_value, full_domain_name);
1675 HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1676 strcpy(key_name, "FullyQualifiedDomainName"); 1679 strcpy(key_name, "FullyQualifiedDomainName");
1677 break; 1680 break;
1678 case IntegrationServicesVersion: 1681 case IntegrationServicesVersion:
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 8611962c672c..8bcb04096eb2 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -140,7 +140,6 @@ int main(void)
140 struct cn_msg *incoming_cn_msg; 140 struct cn_msg *incoming_cn_msg;
141 int op; 141 int op;
142 struct hv_vss_msg *vss_msg; 142 struct hv_vss_msg *vss_msg;
143 char *vss_send_buffer;
144 char *vss_recv_buffer; 143 char *vss_recv_buffer;
145 size_t vss_recv_buffer_len; 144 size_t vss_recv_buffer_len;
146 145
@@ -150,10 +149,9 @@ int main(void)
150 openlog("Hyper-V VSS", 0, LOG_USER); 149 openlog("Hyper-V VSS", 0, LOG_USER);
151 syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); 150 syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
152 151
153 vss_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg); 152 vss_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg);
154 vss_send_buffer = calloc(1, vss_recv_buffer_len);
155 vss_recv_buffer = calloc(1, vss_recv_buffer_len); 153 vss_recv_buffer = calloc(1, vss_recv_buffer_len);
156 if (!(vss_send_buffer && vss_recv_buffer)) { 154 if (!vss_recv_buffer) {
157 syslog(LOG_ERR, "Failed to allocate netlink buffers"); 155 syslog(LOG_ERR, "Failed to allocate netlink buffers");
158 exit(EXIT_FAILURE); 156 exit(EXIT_FAILURE);
159 } 157 }
@@ -185,7 +183,7 @@ int main(void)
185 /* 183 /*
186 * Register ourselves with the kernel. 184 * Register ourselves with the kernel.
187 */ 185 */
188 message = (struct cn_msg *)vss_send_buffer; 186 message = (struct cn_msg *)vss_recv_buffer;
189 message->id.idx = CN_VSS_IDX; 187 message->id.idx = CN_VSS_IDX;
190 message->id.val = CN_VSS_VAL; 188 message->id.val = CN_VSS_VAL;
191 message->ack = 0; 189 message->ack = 0;
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index ca6cb779876a..fc1502098595 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -134,14 +134,14 @@ ifeq ($(VERBOSE),1)
134 print_install = 134 print_install =
135else 135else
136 Q = @ 136 Q = @
137 print_compile = echo ' CC '$(OBJ); 137 print_compile = echo ' CC '$(OBJ);
138 print_app_build = echo ' BUILD '$(OBJ); 138 print_app_build = echo ' BUILD '$(OBJ);
139 print_fpic_compile = echo ' CC FPIC '$(OBJ); 139 print_fpic_compile = echo ' CC FPIC '$(OBJ);
140 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); 140 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
141 print_plugin_obj_compile = echo ' CC PLUGIN OBJ '$(OBJ); 141 print_plugin_obj_compile = echo ' BUILD PLUGIN OBJ '$(OBJ);
142 print_plugin_build = echo ' CC PLUGI '$(OBJ); 142 print_plugin_build = echo ' BUILD PLUGIN '$(OBJ);
143 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); 143 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
144 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; 144 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
145endif 145endif
146 146
147do_fpic_compile = \ 147do_fpic_compile = \
@@ -268,7 +268,7 @@ TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
268TRACEEVENT-CFLAGS: force 268TRACEEVENT-CFLAGS: force
269 @FLAGS='$(TRACK_CFLAGS)'; \ 269 @FLAGS='$(TRACK_CFLAGS)'; \
270 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \ 270 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
271 echo 1>&2 " * new build flags or cross compiler"; \ 271 echo 1>&2 " FLAGS: * new build flags or cross compiler"; \
272 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \ 272 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
273 fi 273 fi
274 274
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index d1c2a6a4cd32..8f450adaa9c2 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -305,6 +305,11 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
305 return 0; 305 return 0;
306} 306}
307 307
308void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock)
309{
310 pevent->trace_clock = trace_clock;
311}
312
308struct func_map { 313struct func_map {
309 unsigned long long addr; 314 unsigned long long addr;
310 char *func; 315 char *func;
@@ -599,10 +604,11 @@ find_printk(struct pevent *pevent, unsigned long long addr)
599 * This registers a string by the address it was stored in the kernel. 604 * This registers a string by the address it was stored in the kernel.
600 * The @fmt passed in is duplicated. 605 * The @fmt passed in is duplicated.
601 */ 606 */
602int pevent_register_print_string(struct pevent *pevent, char *fmt, 607int pevent_register_print_string(struct pevent *pevent, const char *fmt,
603 unsigned long long addr) 608 unsigned long long addr)
604{ 609{
605 struct printk_list *item = malloc(sizeof(*item)); 610 struct printk_list *item = malloc(sizeof(*item));
611 char *p;
606 612
607 if (!item) 613 if (!item)
608 return -1; 614 return -1;
@@ -610,10 +616,21 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt,
610 item->next = pevent->printklist; 616 item->next = pevent->printklist;
611 item->addr = addr; 617 item->addr = addr;
612 618
619 /* Strip off quotes and '\n' from the end */
620 if (fmt[0] == '"')
621 fmt++;
613 item->printk = strdup(fmt); 622 item->printk = strdup(fmt);
614 if (!item->printk) 623 if (!item->printk)
615 goto out_free; 624 goto out_free;
616 625
626 p = item->printk + strlen(item->printk) - 1;
627 if (*p == '"')
628 *p = 0;
629
630 p -= 2;
631 if (strcmp(p, "\\n") == 0)
632 *p = 0;
633
617 pevent->printklist = item; 634 pevent->printklist = item;
618 pevent->printk_count++; 635 pevent->printk_count++;
619 636
@@ -3488,6 +3505,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3488 struct pevent *pevent = event->pevent; 3505 struct pevent *pevent = event->pevent;
3489 struct print_flag_sym *flag; 3506 struct print_flag_sym *flag;
3490 struct format_field *field; 3507 struct format_field *field;
3508 struct printk_map *printk;
3491 unsigned long long val, fval; 3509 unsigned long long val, fval;
3492 unsigned long addr; 3510 unsigned long addr;
3493 char *str; 3511 char *str;
@@ -3523,7 +3541,12 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3523 if (!(field->flags & FIELD_IS_ARRAY) && 3541 if (!(field->flags & FIELD_IS_ARRAY) &&
3524 field->size == pevent->long_size) { 3542 field->size == pevent->long_size) {
3525 addr = *(unsigned long *)(data + field->offset); 3543 addr = *(unsigned long *)(data + field->offset);
3526 trace_seq_printf(s, "%lx", addr); 3544 /* Check if it matches a print format */
3545 printk = find_printk(pevent, addr);
3546 if (printk)
3547 trace_seq_puts(s, printk->printk);
3548 else
3549 trace_seq_printf(s, "%lx", addr);
3527 break; 3550 break;
3528 } 3551 }
3529 str = malloc(len + 1); 3552 str = malloc(len + 1);
@@ -3565,15 +3588,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3565 } 3588 }
3566 break; 3589 break;
3567 case PRINT_HEX: 3590 case PRINT_HEX:
3568 field = arg->hex.field->field.field; 3591 if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) {
3569 if (!field) { 3592 unsigned long offset;
3570 str = arg->hex.field->field.name; 3593 offset = pevent_read_number(pevent,
3571 field = pevent_find_any_field(event, str); 3594 data + arg->hex.field->dynarray.field->offset,
3572 if (!field) 3595 arg->hex.field->dynarray.field->size);
3573 goto out_warning_field; 3596 hex = data + (offset & 0xffff);
3574 arg->hex.field->field.field = field; 3597 } else {
3598 field = arg->hex.field->field.field;
3599 if (!field) {
3600 str = arg->hex.field->field.name;
3601 field = pevent_find_any_field(event, str);
3602 if (!field)
3603 goto out_warning_field;
3604 arg->hex.field->field.field = field;
3605 }
3606 hex = data + field->offset;
3575 } 3607 }
3576 hex = data + field->offset;
3577 len = eval_num_arg(data, size, event, arg->hex.size); 3608 len = eval_num_arg(data, size, event, arg->hex.size);
3578 for (i = 0; i < len; i++) { 3609 for (i = 0; i < len; i++) {
3579 if (i) 3610 if (i)
@@ -3771,8 +3802,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3771 if (asprintf(&arg->atom.atom, "%lld", ip) < 0) 3802 if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
3772 goto out_free; 3803 goto out_free;
3773 3804
3774 /* skip the first "%pf : " */ 3805 /* skip the first "%pf: " */
3775 for (ptr = fmt + 6, bptr = data + field->offset; 3806 for (ptr = fmt + 5, bptr = data + field->offset;
3776 bptr < data + size && *ptr; ptr++) { 3807 bptr < data + size && *ptr; ptr++) {
3777 int ls = 0; 3808 int ls = 0;
3778 3809
@@ -3882,7 +3913,6 @@ get_bprint_format(void *data, int size __maybe_unused,
3882 struct format_field *field; 3913 struct format_field *field;
3883 struct printk_map *printk; 3914 struct printk_map *printk;
3884 char *format; 3915 char *format;
3885 char *p;
3886 3916
3887 field = pevent->bprint_fmt_field; 3917 field = pevent->bprint_fmt_field;
3888 3918
@@ -3899,25 +3929,13 @@ get_bprint_format(void *data, int size __maybe_unused,
3899 3929
3900 printk = find_printk(pevent, addr); 3930 printk = find_printk(pevent, addr);
3901 if (!printk) { 3931 if (!printk) {
3902 if (asprintf(&format, "%%pf : (NO FORMAT FOUND at %llx)\n", addr) < 0) 3932 if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0)
3903 return NULL; 3933 return NULL;
3904 return format; 3934 return format;
3905 } 3935 }
3906 3936
3907 p = printk->printk; 3937 if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0)
3908 /* Remove any quotes. */
3909 if (*p == '"')
3910 p++;
3911 if (asprintf(&format, "%s : %s", "%pf", p) < 0)
3912 return NULL; 3938 return NULL;
3913 /* remove ending quotes and new line since we will add one too */
3914 p = format + strlen(format) - 1;
3915 if (*p == '"')
3916 *p = 0;
3917
3918 p -= 2;
3919 if (strcmp(p, "\\n") == 0)
3920 *p = 0;
3921 3939
3922 return format; 3940 return format;
3923} 3941}
@@ -3963,7 +3981,7 @@ static int is_printable_array(char *p, unsigned int len)
3963 unsigned int i; 3981 unsigned int i;
3964 3982
3965 for (i = 0; i < len && p[i]; i++) 3983 for (i = 0; i < len && p[i]; i++)
3966 if (!isprint(p[i])) 3984 if (!isprint(p[i]) && !isspace(p[i]))
3967 return 0; 3985 return 0;
3968 return 1; 3986 return 1;
3969} 3987}
@@ -4428,11 +4446,11 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
4428{ 4446{
4429 int print_pretty = 1; 4447 int print_pretty = 1;
4430 4448
4431 if (event->pevent->print_raw) 4449 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
4432 print_event_fields(s, record->data, record->size, event); 4450 print_event_fields(s, record->data, record->size, event);
4433 else { 4451 else {
4434 4452
4435 if (event->handler) 4453 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
4436 print_pretty = event->handler(s, record, event, 4454 print_pretty = event->handler(s, record, event,
4437 event->context); 4455 event->context);
4438 4456
@@ -4443,8 +4461,21 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
4443 trace_seq_terminate(s); 4461 trace_seq_terminate(s);
4444} 4462}
4445 4463
4464static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
4465{
4466 if (!use_trace_clock)
4467 return true;
4468
4469 if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global")
4470 || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf"))
4471 return true;
4472
4473 /* trace_clock is setting in tsc or counter mode */
4474 return false;
4475}
4476
4446void pevent_print_event(struct pevent *pevent, struct trace_seq *s, 4477void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4447 struct pevent_record *record) 4478 struct pevent_record *record, bool use_trace_clock)
4448{ 4479{
4449 static const char *spaces = " "; /* 20 spaces */ 4480 static const char *spaces = " "; /* 20 spaces */
4450 struct event_format *event; 4481 struct event_format *event;
@@ -4457,9 +4488,14 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4457 int pid; 4488 int pid;
4458 int len; 4489 int len;
4459 int p; 4490 int p;
4491 bool use_usec_format;
4460 4492
4461 secs = record->ts / NSECS_PER_SEC; 4493 use_usec_format = is_timestamp_in_us(pevent->trace_clock,
4462 nsecs = record->ts - secs * NSECS_PER_SEC; 4494 use_trace_clock);
4495 if (use_usec_format) {
4496 secs = record->ts / NSECS_PER_SEC;
4497 nsecs = record->ts - secs * NSECS_PER_SEC;
4498 }
4463 4499
4464 if (record->size < 0) { 4500 if (record->size < 0) {
4465 do_warning("ug! negative record size %d", record->size); 4501 do_warning("ug! negative record size %d", record->size);
@@ -4484,15 +4520,20 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4484 } else 4520 } else
4485 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu); 4521 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
4486 4522
4487 if (pevent->flags & PEVENT_NSEC_OUTPUT) { 4523 if (use_usec_format) {
4488 usecs = nsecs; 4524 if (pevent->flags & PEVENT_NSEC_OUTPUT) {
4489 p = 9; 4525 usecs = nsecs;
4490 } else { 4526 p = 9;
4491 usecs = (nsecs + 500) / NSECS_PER_USEC; 4527 } else {
4492 p = 6; 4528 usecs = (nsecs + 500) / NSECS_PER_USEC;
4493 } 4529 p = 6;
4530 }
4494 4531
4495 trace_seq_printf(s, " %5lu.%0*lu: %s: ", secs, p, usecs, event->name); 4532 trace_seq_printf(s, " %5lu.%0*lu: %s: ",
4533 secs, p, usecs, event->name);
4534 } else
4535 trace_seq_printf(s, " %12llu: %s: ",
4536 record->ts, event->name);
4496 4537
4497 /* Space out the event names evenly. */ 4538 /* Space out the event names evenly. */
4498 len = strlen(event->name); 4539 len = strlen(event->name);
@@ -5326,6 +5367,48 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt,
5326 return -1; 5367 return -1;
5327} 5368}
5328 5369
5370/**
5371 * pevent_print_func_field - print a field and a format for function pointers
5372 * @s: The seq to print to
5373 * @fmt: The printf format to print the field with.
5374 * @event: the event that the field is for
5375 * @name: The name of the field
5376 * @record: The record with the field name.
5377 * @err: print default error if failed.
5378 *
5379 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
5380 */
5381int pevent_print_func_field(struct trace_seq *s, const char *fmt,
5382 struct event_format *event, const char *name,
5383 struct pevent_record *record, int err)
5384{
5385 struct format_field *field = pevent_find_field(event, name);
5386 struct pevent *pevent = event->pevent;
5387 unsigned long long val;
5388 struct func_map *func;
5389 char tmp[128];
5390
5391 if (!field)
5392 goto failed;
5393
5394 if (pevent_read_number_field(field, record->data, &val))
5395 goto failed;
5396
5397 func = find_func(pevent, val);
5398
5399 if (func)
5400 snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
5401 else
5402 sprintf(tmp, "0x%08llx", val);
5403
5404 return trace_seq_printf(s, fmt, tmp);
5405
5406 failed:
5407 if (err)
5408 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
5409 return -1;
5410}
5411
5329static void free_func_handle(struct pevent_function_handler *func) 5412static void free_func_handle(struct pevent_function_handler *func)
5330{ 5413{
5331 struct pevent_func_params *params; 5414 struct pevent_func_params *params;
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index c37b2026d04a..8d73d2594f65 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -20,6 +20,7 @@
20#ifndef _PARSE_EVENTS_H 20#ifndef _PARSE_EVENTS_H
21#define _PARSE_EVENTS_H 21#define _PARSE_EVENTS_H
22 22
23#include <stdbool.h>
23#include <stdarg.h> 24#include <stdarg.h>
24#include <regex.h> 25#include <regex.h>
25 26
@@ -307,6 +308,8 @@ enum {
307 EVENT_FL_ISBPRINT = 0x04, 308 EVENT_FL_ISBPRINT = 0x04,
308 EVENT_FL_ISFUNCENT = 0x10, 309 EVENT_FL_ISFUNCENT = 0x10,
309 EVENT_FL_ISFUNCRET = 0x20, 310 EVENT_FL_ISFUNCRET = 0x20,
311 EVENT_FL_NOHANDLE = 0x40,
312 EVENT_FL_PRINTRAW = 0x80,
310 313
311 EVENT_FL_FAILED = 0x80000000 314 EVENT_FL_FAILED = 0x80000000
312}; 315};
@@ -450,6 +453,8 @@ struct pevent {
450 453
451 /* cache */ 454 /* cache */
452 struct event_format *last_event; 455 struct event_format *last_event;
456
457 char *trace_clock;
453}; 458};
454 459
455static inline void pevent_set_flag(struct pevent *pevent, int flag) 460static inline void pevent_set_flag(struct pevent *pevent, int flag)
@@ -527,14 +532,15 @@ enum trace_flag_type {
527}; 532};
528 533
529int pevent_register_comm(struct pevent *pevent, const char *comm, int pid); 534int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
535void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock);
530int pevent_register_function(struct pevent *pevent, char *name, 536int pevent_register_function(struct pevent *pevent, char *name,
531 unsigned long long addr, char *mod); 537 unsigned long long addr, char *mod);
532int pevent_register_print_string(struct pevent *pevent, char *fmt, 538int pevent_register_print_string(struct pevent *pevent, const char *fmt,
533 unsigned long long addr); 539 unsigned long long addr);
534int pevent_pid_is_registered(struct pevent *pevent, int pid); 540int pevent_pid_is_registered(struct pevent *pevent, int pid);
535 541
536void pevent_print_event(struct pevent *pevent, struct trace_seq *s, 542void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
537 struct pevent_record *record); 543 struct pevent_record *record, bool use_trace_clock);
538 544
539int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size, 545int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
540 int long_size); 546 int long_size);
@@ -563,6 +569,10 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt,
563 struct event_format *event, const char *name, 569 struct event_format *event, const char *name,
564 struct pevent_record *record, int err); 570 struct pevent_record *record, int err);
565 571
572int pevent_print_func_field(struct trace_seq *s, const char *fmt,
573 struct event_format *event, const char *name,
574 struct pevent_record *record, int err);
575
566int pevent_register_event_handler(struct pevent *pevent, int id, 576int pevent_register_event_handler(struct pevent *pevent, int id,
567 const char *sys_name, const char *event_name, 577 const char *sys_name, const char *event_name,
568 pevent_event_handler_func func, void *context); 578 pevent_event_handler_func func, void *context);
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 8f8fbc227a46..782d86e961b9 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -13,6 +13,7 @@ perf*.html
13common-cmds.h 13common-cmds.h
14perf.data 14perf.data
15perf.data.old 15perf.data.old
16output.svg
16perf-archive 17perf-archive
17tags 18tags
18TAGS 19TAGS
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 5a37a7c84e69..3ba1c0b09908 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -145,16 +145,17 @@ endif
145 145
146ifneq ($(findstring $(MAKEFLAGS),s),s) 146ifneq ($(findstring $(MAKEFLAGS),s),s)
147ifneq ($(V),1) 147ifneq ($(V),1)
148 QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@; 148 QUIET_ASCIIDOC = @echo ' ASCIIDOC '$@;
149 QUIET_XMLTO = @echo ' ' XMLTO $@; 149 QUIET_XMLTO = @echo ' XMLTO '$@;
150 QUIET_DB2TEXI = @echo ' ' DB2TEXI $@; 150 QUIET_DB2TEXI = @echo ' DB2TEXI '$@;
151 QUIET_MAKEINFO = @echo ' ' MAKEINFO $@; 151 QUIET_MAKEINFO = @echo ' MAKEINFO '$@;
152 QUIET_DBLATEX = @echo ' ' DBLATEX $@; 152 QUIET_DBLATEX = @echo ' DBLATEX '$@;
153 QUIET_XSLTPROC = @echo ' ' XSLTPROC $@; 153 QUIET_XSLTPROC = @echo ' XSLTPROC '$@;
154 QUIET_GEN = @echo ' ' GEN $@; 154 QUIET_GEN = @echo ' GEN '$@;
155 QUIET_STDERR = 2> /dev/null 155 QUIET_STDERR = 2> /dev/null
156 QUIET_SUBDIR0 = +@subdir= 156 QUIET_SUBDIR0 = +@subdir=
157 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ 157 QUIET_SUBDIR1 = ;$(NO_SUBDIR) \
158 echo ' SUBDIR ' $$subdir; \
158 $(MAKE) $(PRINT_DIR) -C $$subdir 159 $(MAKE) $(PRINT_DIR) -C $$subdir
159 export V 160 export V
160endif 161endif
@@ -183,47 +184,43 @@ ifdef missing_tools
183endif 184endif
184 185
185do-install-man: man 186do-install-man: man
186 $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir) 187 $(call QUIET_INSTALL, Documentation-man) \
187# $(INSTALL) -d -m 755 $(DESTDIR)$(man5dir) 188 $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir); \
188# $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir) 189# $(INSTALL) -d -m 755 $(DESTDIR)$(man5dir); \
189 $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir) 190# $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir); \
190# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir) 191 $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir); \
191# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir) 192# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir); \
193# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
192 194
193install-man: check-man-tools man 195install-man: check-man-tools man
194 196
195try-install-man:
196ifdef missing_tools 197ifdef missing_tools
197 $(warning Please install $(missing_tools) to have the man pages installed) 198 DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed)
198else 199else
199 $(MAKE) do-install-man 200 DO_INSTALL_MAN = do-install-man
200endif 201endif
201 202
203try-install-man: $(DO_INSTALL_MAN)
204
202install-info: info 205install-info: info
203 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir) 206 $(call QUIET_INSTALL, Documentation-info) \
204 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir) 207 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir); \
208 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir); \
205 if test -r $(DESTDIR)$(infodir)/dir; then \ 209 if test -r $(DESTDIR)$(infodir)/dir; then \
206 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\ 210 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\
207 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\ 211 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\
208 else \ 212 else \
209 echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \ 213 echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \
210 fi 214 fi
211 215
212install-pdf: pdf 216install-pdf: pdf
213 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir) 217 $(call QUIET_INSTALL, Documentation-pdf) \
214 $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir) 218 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir); \
219 $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir)
215 220
216#install-html: html 221#install-html: html
217# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) 222# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
218 223
219ifneq ($(MAKECMDGOALS),clean)
220ifneq ($(MAKECMDGOALS),tags)
221$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
222 $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE
223
224-include $(OUTPUT)PERF-VERSION-FILE
225endif
226endif
227 224
228# 225#
229# Determine "include::" file references in asciidoc files. 226# Determine "include::" file references in asciidoc files.
@@ -253,15 +250,17 @@ $(OUTPUT)cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
253 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \ 250 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
254 date >$@ 251 date >$@
255 252
253CLEAN_FILES = \
254 $(MAN_XML) $(addsuffix +,$(MAN_XML)) \
255 $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \
256 $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7) \
257 $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++ \
258 $(OUTPUT)perf.info $(OUTPUT)perfman.info \
259 $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep \
260 $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt \
261 $(cmds_txt) $(OUTPUT)*.made
256clean: 262clean:
257 $(RM) $(MAN_XML) $(addsuffix +,$(MAN_XML)) 263 $(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES)
258 $(RM) $(MAN_HTML) $(addsuffix +,$(MAN_HTML))
259 $(RM) $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7)
260 $(RM) $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++
261 $(RM) $(OUTPUT)perf.info $(OUTPUT)perfman.info
262 $(RM) $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep
263 $(RM) $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt
264 $(RM) $(cmds_txt) $(OUTPUT)*.made
265 264
266$(MAN_HTML): $(OUTPUT)%.html : %.txt 265$(MAN_HTML): $(OUTPUT)%.html : %.txt
267 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 266 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
@@ -342,5 +341,3 @@ $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
342 341
343#quick-install-html: 342#quick-install-html:
344# '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir) 343# '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
345
346.PHONY: .FORCE-PERF-VERSION-FILE
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index e9a8349a7172..fd77d81ea748 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -21,6 +21,19 @@ OPTIONS
21-a:: 21-a::
22--add=:: 22--add=::
23 Add specified file to the cache. 23 Add specified file to the cache.
24-k::
25--kcore::
26 Add specified kcore file to the cache. For the current host that is
27 /proc/kcore which requires root permissions to read. Be aware that
28 running 'perf buildid-cache' as root may update root's build-id cache
29 not the user's. Use the -v option to see where the file is created.
30 Note that the copied file contains only code sections not the whole core
31 image. Note also that files "kallsyms" and "modules" must also be in the
32 same directory and are also copied. All 3 files are created with read
33 permissions for root only. kcore will not be added if there is already a
34 kcore in the cache (with the same build-id) that has the same modules at
35 the same addresses. Use the -v option to see if a copy of kcore is
36 actually made.
24-r:: 37-r::
25--remove=:: 38--remove=::
26 Remove specified file from the cache. 39 Remove specified file from the cache.
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index ac84db2d2334..6a06cefe9642 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -109,7 +109,9 @@ STAT LIVE OPTIONS
109 109
110-m:: 110-m::
111--mmap-pages=:: 111--mmap-pages=::
112 Number of mmap data pages. Must be a power of two. 112 Number of mmap data pages (must be a power of two) or size
113 specification with appended unit character - B/K/M/G. The
114 size is rounded up to have nearest pages power of two value.
113 115
114-a:: 116-a::
115--all-cpus:: 117--all-cpus::
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index c7f5f55634ac..ab25be28c9dc 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -48,7 +48,7 @@ REPORT OPTIONS
48-k:: 48-k::
49--key=<value>:: 49--key=<value>::
50 Sorting key. Possible values: acquired (default), contended, 50 Sorting key. Possible values: acquired (default), contended,
51 wait_total, wait_max, wait_min. 51 avg_wait, wait_total, wait_max, wait_min.
52 52
53INFO OPTIONS 53INFO OPTIONS
54------------ 54------------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e297b74471b8..052f7c4dc00c 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -87,11 +87,25 @@ OPTIONS
87 87
88-m:: 88-m::
89--mmap-pages=:: 89--mmap-pages=::
90 Number of mmap data pages. Must be a power of two. 90 Number of mmap data pages (must be a power of two) or size
91 specification with appended unit character - B/K/M/G. The
92 size is rounded up to have nearest pages power of two value.
91 93
92-g:: 94-g::
95 Enables call-graph (stack chain/backtrace) recording.
96
93--call-graph:: 97--call-graph::
94 Do call-graph (stack chain/backtrace) recording. 98 Setup and enable call-graph (stack chain/backtrace) recording,
99 implies -g.
100
101 Allows specifying "fp" (frame pointer) or "dwarf"
102 (DWARF's CFI - Call Frame Information) as the method to collect
103 the information used to show the call graphs.
104
105 In some systems, where binaries are build with gcc
106 --fomit-frame-pointer, using the "fp" method will produce bogus
107 call graphs, using "dwarf", if available (perf tools linked to
108 the libunwind library) should be used instead.
95 109
96-q:: 110-q::
97--quiet:: 111--quiet::
@@ -166,6 +180,9 @@ following filters are defined:
166 - u: only when the branch target is at the user level 180 - u: only when the branch target is at the user level
167 - k: only when the branch target is in the kernel 181 - k: only when the branch target is in the kernel
168 - hv: only when the target is at the hypervisor level 182 - hv: only when the target is at the hypervisor level
183 - in_tx: only when the target is in a hardware transaction
184 - no_tx: only when the target is not in a hardware transaction
185 - abort_tx: only when the target is a hardware transaction abort
169 186
170+ 187+
171The option requires at least one branch type among any, any_call, any_ret, ind_call. 188The option requires at least one branch type among any, any_call, any_ret, ind_call.
@@ -176,12 +193,14 @@ is enabled for all the sampling events. The sampled branch type is the same for
176The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k 193The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
177Note that this feature may not be available on all processors. 194Note that this feature may not be available on all processors.
178 195
179-W::
180--weight:: 196--weight::
181Enable weightened sampling. An additional weight is recorded per sample and can be 197Enable weightened sampling. An additional weight is recorded per sample and can be
182displayed with the weight and local_weight sort keys. This currently works for TSX 198displayed with the weight and local_weight sort keys. This currently works for TSX
183abort events and some memory events in precise mode on modern Intel CPUs. 199abort events and some memory events in precise mode on modern Intel CPUs.
184 200
201--transaction::
202Record transaction flags for transaction related events.
203
185SEE ALSO 204SEE ALSO
186-------- 205--------
187linkperf:perf-stat[1], linkperf:perf-list[1] 206linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 2b8097ee39d8..10a279871251 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -71,7 +71,11 @@ OPTIONS
71 entries are displayed as "[other]". 71 entries are displayed as "[other]".
72 - cpu: cpu number the task ran at the time of sample 72 - cpu: cpu number the task ran at the time of sample
73 - srcline: filename and line number executed at the time of sample. The 73 - srcline: filename and line number executed at the time of sample. The
74 DWARF debuggin info must be provided. 74 DWARF debugging info must be provided.
75 - weight: Event specific weight, e.g. memory latency or transaction
76 abort cost. This is the global weight.
77 - local_weight: Local weight version of the weight above.
78 - transaction: Transaction abort flags.
75 79
76 By default, comm, dso and symbol keys are used. 80 By default, comm, dso and symbol keys are used.
77 (i.e. --sort comm,dso,symbol) 81 (i.e. --sort comm,dso,symbol)
@@ -85,6 +89,8 @@ OPTIONS
85 - symbol_from: name of function branched from 89 - symbol_from: name of function branched from
86 - symbol_to: name of function branched to 90 - symbol_to: name of function branched to
87 - mispredict: "N" for predicted branch, "Y" for mispredicted branch 91 - mispredict: "N" for predicted branch, "Y" for mispredicted branch
92 - in_tx: branch in TSX transaction
93 - abort: TSX transaction abort.
88 94
89 And default sort keys are changed to comm, dso_from, symbol_from, dso_to 95 And default sort keys are changed to comm, dso_from, symbol_from, dso_to
90 and symbol_to, see '--branch-stack'. 96 and symbol_to, see '--branch-stack'.
@@ -135,6 +141,14 @@ OPTIONS
135 141
136 Default: fractal,0.5,callee,function. 142 Default: fractal,0.5,callee,function.
137 143
144--max-stack::
145 Set the stack depth limit when parsing the callchain, anything
146 beyond the specified depth will be ignored. This is a trade-off
147 between information loss and faster processing especially for
148 workloads that can have a very long callchain stack.
149
150 Default: 127
151
138-G:: 152-G::
139--inverted:: 153--inverted::
140 alias for inverted caller based call graph. 154 alias for inverted caller based call graph.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 73c9759005a3..80c7da6732f2 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -137,6 +137,11 @@ core number and the number of online logical processors on that physical process
137After starting the program, wait msecs before measuring. This is useful to 137After starting the program, wait msecs before measuring. This is useful to
138filter out the startup phase of the program, which is often very different. 138filter out the startup phase of the program, which is often very different.
139 139
140-T::
141--transaction::
142
143Print statistics of transactional execution if supported.
144
140EXAMPLES 145EXAMPLES
141-------- 146--------
142 147
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 1632b0efc757..3ff8bd4f0b4d 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -8,7 +8,8 @@ perf-timechart - Tool to visualize total system behavior during a workload
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf timechart' {record} 11'perf timechart' record <command>
12'perf timechart' [<options>]
12 13
13DESCRIPTION 14DESCRIPTION
14----------- 15-----------
@@ -41,6 +42,18 @@ OPTIONS
41--symfs=<directory>:: 42--symfs=<directory>::
42 Look for files with symbols relative to this directory. 43 Look for files with symbols relative to this directory.
43 44
45EXAMPLES
46--------
47
48$ perf timechart record git pull
49
50 [ perf record: Woken up 13 times to write data ]
51 [ perf record: Captured and wrote 4.253 MB perf.data (~185801 samples) ]
52
53$ perf timechart
54
55 Written 10.2 seconds of trace to output.svg.
56
44SEE ALSO 57SEE ALSO
45-------- 58--------
46linkperf:perf-record[1] 59linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 58d6598a9686..7de01dd79688 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -68,7 +68,9 @@ Default is to monitor all CPUS.
68 68
69-m <pages>:: 69-m <pages>::
70--mmap-pages=<pages>:: 70--mmap-pages=<pages>::
71 Number of mmapped data pages. 71 Number of mmap data pages (must be a power of two) or size
72 specification with appended unit character - B/K/M/G. The
73 size is rounded up to have nearest pages power of two value.
72 74
73-p <pid>:: 75-p <pid>::
74--pid=<pid>:: 76--pid=<pid>::
@@ -112,7 +114,8 @@ Default is to monitor all CPUS.
112 114
113-s:: 115-s::
114--sort:: 116--sort::
115 Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight, local_weight. 117 Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight,
118 local_weight, abort, in_tx, transaction
116 119
117-n:: 120-n::
118--show-nr-samples:: 121--show-nr-samples::
@@ -140,20 +143,20 @@ Default is to monitor all CPUS.
140--asm-raw:: 143--asm-raw::
141 Show raw instruction encoding of assembly instructions. 144 Show raw instruction encoding of assembly instructions.
142 145
143-G [type,min,order]:: 146-G::
147 Enables call-graph (stack chain/backtrace) recording.
148
144--call-graph:: 149--call-graph::
145 Display call chains using type, min percent threshold and order. 150 Setup and enable call-graph (stack chain/backtrace) recording,
146 type can be either: 151 implies -G.
147 - flat: single column, linear exposure of call chains. 152
148 - graph: use a graph tree, displaying absolute overhead rates. 153--max-stack::
149 - fractal: like graph, but displays relative rates. Each branch of 154 Set the stack depth limit when parsing the callchain, anything
150 the tree is considered as a new profiled object. 155 beyond the specified depth will be ignored. This is a trade-off
151 156 between information loss and faster processing especially for
152 order can be either: 157 workloads that can have a very long callchain stack.
153 - callee: callee based call graph. 158
154 - caller: inverted caller based call graph. 159 Default: 127
155
156 Default: fractal,0.5,callee.
157 160
158--ignore-callees=<regex>:: 161--ignore-callees=<regex>::
159 Ignore callees of the function(s) matching the given regex. 162 Ignore callees of the function(s) matching the given regex.
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index daccd2c0a48f..7b0497f95a75 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -9,6 +9,7 @@ SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf trace' 11'perf trace'
12'perf trace record'
12 13
13DESCRIPTION 14DESCRIPTION
14----------- 15-----------
@@ -16,9 +17,14 @@ This command will show the events associated with the target, initially
16syscalls, but other system events like pagefaults, task lifetime events, 17syscalls, but other system events like pagefaults, task lifetime events,
17scheduling events, etc. 18scheduling events, etc.
18 19
19Initially this is a live mode only tool, but eventually will work with 20This is a live mode tool in addition to working with perf.data files like
20perf.data files like the other tools, allowing a detached 'record' from 21the other perf tools. Files can be generated using the 'perf record' command
21analysis phases. 22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*').
23Alernatively, the 'perf trace record' can be used as a shortcut to
24automatically include the raw_syscalls events when writing events to a file.
25
26The following options apply to perf trace; options to perf trace record are
27found in the perf record man page.
22 28
23OPTIONS 29OPTIONS
24------- 30-------
@@ -59,7 +65,9 @@ OPTIONS
59 65
60-m:: 66-m::
61--mmap-pages=:: 67--mmap-pages=::
62 Number of mmap data pages. Must be a power of two. 68 Number of mmap data pages (must be a power of two) or size
69 specification with appended unit character - B/K/M/G. The
70 size is rounded up to have nearest pages power of two value.
63 71
64-C:: 72-C::
65--cpu:: 73--cpu::
@@ -78,6 +86,21 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
78--input 86--input
79 Process events from a given perf data file. 87 Process events from a given perf data file.
80 88
89-T
90--time
91 Print full timestamp rather time relative to first sample.
92
93--comm::
94 Show process COMM right beside its ID, on by default, disable with --no-comm.
95
96--summary::
97 Show a summary of syscalls by thread with min, max, and average times (in
98 msec) and relative stddev.
99
100--tool_stats::
101 Show tool stats such as number of times fd->pathname was discovered thru
102 hooking the open syscall return + vfs_getname or via reading /proc/pid/fd, etc.
103
81SEE ALSO 104SEE ALSO
82-------- 105--------
83linkperf:perf-record[1], linkperf:perf-script[1] 106linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 64c043b7a438..4835618a5608 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -1,819 +1,79 @@
1include ../scripts/Makefile.include
2
3# The default target of this Makefile is...
4all:
5
6include config/utilities.mak
7
8# Define V to have a more verbose compile.
9#
10# Define O to save output files in a separate directory.
11#
12# Define ARCH as name of target architecture if you want cross-builds.
13#
14# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
15#
16# Define NO_LIBPERL to disable perl script extension.
17#
18# Define NO_LIBPYTHON to disable python script extension.
19#
20# Define PYTHON to point to the python binary if the default
21# `python' is not correct; for example: PYTHON=python2
22#
23# Define PYTHON_CONFIG to point to the python-config binary if
24# the default `$(PYTHON)-config' is not correct.
25# 1#
26# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 2# This is a simple wrapper Makefile that calls the main Makefile.perf
3# with a -j option to do parallel builds
27# 4#
28# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72. 5# If you want to invoke the perf build in some non-standard way then
6# you can use the 'make -f Makefile.perf' method to invoke it.
29# 7#
30# Define LDFLAGS=-static to build a static binary. 8
31#
32# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
33#
34# Define NO_DWARF if you do not want debug-info analysis feature at all.
35#
36# Define WERROR=0 to disable treating any warnings as errors.
37#
38# Define NO_NEWT if you do not want TUI support. (deprecated)
39#
40# Define NO_SLANG if you do not want TUI support.
41#
42# Define NO_GTK2 if you do not want GTK+ GUI support.
43# 9#
44# Define NO_DEMANGLE if you do not want C++ symbol demangling. 10# Clear out the built-in rules GNU make defines by default (such as .o targets),
11# so that we pass through all targets to Makefile.perf:
45# 12#
46# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds) 13.SUFFIXES:
14
47# 15#
48# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf 16# We don't want to pass along options like -j:
49# backtrace post unwind.
50# 17#
51# Define NO_BACKTRACE if you do not want stack backtrace debug feature 18unexport MAKEFLAGS
19
52# 20#
53# Define NO_LIBNUMA if you do not want numa perf benchmark 21# Do a parallel build with multiple jobs, based on the number of CPUs online
22# in this system: 'make -j8' on a 8-CPU system, etc.
54# 23#
55# Define NO_LIBAUDIT if you do not want libaudit support 24# (To override it, run 'make JOBS=1' and similar.)
56# 25#
57# Define NO_LIBBIONIC if you do not want bionic support 26ifeq ($(JOBS),)
58 27 JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
59ifeq ($(srctree),) 28 ifeq ($(JOBS),)
60srctree := $(patsubst %/,%,$(dir $(shell pwd))) 29 JOBS := 1
61srctree := $(patsubst %/,%,$(dir $(srctree))) 30 endif
62#$(info Determined 'srctree' to be $(srctree))
63endif
64
65ifneq ($(objtree),)
66#$(info Determined 'objtree' to be $(objtree))
67endif
68
69ifneq ($(OUTPUT),)
70#$(info Determined 'OUTPUT' to be $(OUTPUT))
71endif
72
73$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
74 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
75
76CC = $(CROSS_COMPILE)gcc
77AR = $(CROSS_COMPILE)ar
78
79RM = rm -f
80MKDIR = mkdir
81FIND = find
82INSTALL = install
83FLEX = flex
84BISON = bison
85STRIP = strip
86
87LK_DIR = $(srctree)/tools/lib/lk/
88TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
89
90# include config/Makefile by default and rule out
91# non-config cases
92config := 1
93
94NON_CONFIG_TARGETS := clean TAGS tags cscope help
95
96ifdef MAKECMDGOALS
97ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
98 config := 0
99endif
100endif 31endif
101 32
102ifeq ($(config),1) 33#
103include config/Makefile 34# Only pass canonical directory names as the output directory:
35#
36ifneq ($(O),)
37 FULL_O := $(shell readlink -f $(O) || echo $(O))
104endif 38endif
105 39
106export prefix bindir sharedir sysconfdir 40#
107 41# Only accept the 'DEBUG' variable from the command line:
108# sparse is architecture-neutral, which means that we need to tell it 42#
109# explicitly what architecture to check for. Fix this up for yours.. 43ifeq ("$(origin DEBUG)", "command line")
110SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 44 ifeq ($(DEBUG),)
111 45 override DEBUG = 0
112# Guard against environment variables 46 else
113BUILTIN_OBJS = 47 SET_DEBUG = "DEBUG=$(DEBUG)"
114LIB_H = 48 endif
115LIB_OBJS =
116PYRF_OBJS =
117SCRIPT_SH =
118
119SCRIPT_SH += perf-archive.sh
120
121grep-libs = $(filter -l%,$(1))
122strip-libs = $(filter-out -l%,$(1))
123
124ifneq ($(OUTPUT),)
125 TE_PATH=$(OUTPUT)
126ifneq ($(subdir),)
127 LK_PATH=$(OUTPUT)/../lib/lk/
128else
129 LK_PATH=$(OUTPUT)
130endif
131else 49else
132 TE_PATH=$(TRACE_EVENT_DIR) 50 override DEBUG = 0
133 LK_PATH=$(LK_DIR)
134endif 51endif
135 52
136LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 53define print_msg
137export LIBTRACEEVENT 54 @printf ' BUILD: Doing '\''make \033[33m-j'$(JOBS)'\033[m'\'' parallel build\n'
138 55endef
139LIBLK = $(LK_PATH)liblk.a
140export LIBLK
141
142# python extension build directories
143PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
144PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
145PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
146export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
147 56
148python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 57define make
58 @$(MAKE) -f Makefile.perf --no-print-directory -j$(JOBS) O=$(FULL_O) $(SET_DEBUG) $@
59endef
149 60
150PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
151PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
152
153$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
154 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
155 --quiet build_ext; \
156 mkdir -p $(OUTPUT)python && \
157 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
158# 61#
159# No Perl scripts right now: 62# Needed if no target specified:
160# 63#
161 64all:
162SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 65 $(print_msg)
66 $(make)
163 67
164# 68#
165# Single 'perf' binary right now: 69# The clean target is not really parallel, don't print the jobs info:
166# 70#
167PROGRAMS += $(OUTPUT)perf 71clean:
168 72 $(make)
169# what 'all' will build and 'install' will install, in perfexecdir
170ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
171
172# what 'all' will build but not install in perfexecdir
173OTHER_PROGRAMS = $(OUTPUT)perf
174
175# Set paths to tools early so that they can be used for version tests.
176ifndef SHELL_PATH
177 SHELL_PATH = /bin/sh
178endif
179ifndef PERL_PATH
180 PERL_PATH = /usr/bin/perl
181endif
182
183export PERL_PATH
184
185$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
186 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
187
188$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
189 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
190
191$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
192 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
193
194$(OUTPUT)util/pmu-bison.c: util/pmu.y
195 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
196
197$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
198$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
199
200LIB_FILE=$(OUTPUT)libperf.a
201
202LIB_H += ../../include/uapi/linux/perf_event.h
203LIB_H += ../../include/linux/rbtree.h
204LIB_H += ../../include/linux/list.h
205LIB_H += ../../include/uapi/linux/const.h
206LIB_H += ../../include/linux/hash.h
207LIB_H += ../../include/linux/stringify.h
208LIB_H += util/include/linux/bitmap.h
209LIB_H += util/include/linux/bitops.h
210LIB_H += util/include/linux/compiler.h
211LIB_H += util/include/linux/const.h
212LIB_H += util/include/linux/ctype.h
213LIB_H += util/include/linux/kernel.h
214LIB_H += util/include/linux/list.h
215LIB_H += util/include/linux/export.h
216LIB_H += util/include/linux/magic.h
217LIB_H += util/include/linux/poison.h
218LIB_H += util/include/linux/prefetch.h
219LIB_H += util/include/linux/rbtree.h
220LIB_H += util/include/linux/rbtree_augmented.h
221LIB_H += util/include/linux/string.h
222LIB_H += util/include/linux/types.h
223LIB_H += util/include/linux/linkage.h
224LIB_H += util/include/asm/asm-offsets.h
225LIB_H += util/include/asm/bug.h
226LIB_H += util/include/asm/byteorder.h
227LIB_H += util/include/asm/hweight.h
228LIB_H += util/include/asm/swab.h
229LIB_H += util/include/asm/system.h
230LIB_H += util/include/asm/uaccess.h
231LIB_H += util/include/dwarf-regs.h
232LIB_H += util/include/asm/dwarf2.h
233LIB_H += util/include/asm/cpufeature.h
234LIB_H += util/include/asm/unistd_32.h
235LIB_H += util/include/asm/unistd_64.h
236LIB_H += perf.h
237LIB_H += util/annotate.h
238LIB_H += util/cache.h
239LIB_H += util/callchain.h
240LIB_H += util/build-id.h
241LIB_H += util/debug.h
242LIB_H += util/sysfs.h
243LIB_H += util/pmu.h
244LIB_H += util/event.h
245LIB_H += util/evsel.h
246LIB_H += util/evlist.h
247LIB_H += util/exec_cmd.h
248LIB_H += util/types.h
249LIB_H += util/levenshtein.h
250LIB_H += util/machine.h
251LIB_H += util/map.h
252LIB_H += util/parse-options.h
253LIB_H += util/parse-events.h
254LIB_H += util/quote.h
255LIB_H += util/util.h
256LIB_H += util/xyarray.h
257LIB_H += util/header.h
258LIB_H += util/help.h
259LIB_H += util/session.h
260LIB_H += util/strbuf.h
261LIB_H += util/strlist.h
262LIB_H += util/strfilter.h
263LIB_H += util/svghelper.h
264LIB_H += util/tool.h
265LIB_H += util/run-command.h
266LIB_H += util/sigchain.h
267LIB_H += util/dso.h
268LIB_H += util/symbol.h
269LIB_H += util/color.h
270LIB_H += util/values.h
271LIB_H += util/sort.h
272LIB_H += util/hist.h
273LIB_H += util/thread.h
274LIB_H += util/thread_map.h
275LIB_H += util/trace-event.h
276LIB_H += util/probe-finder.h
277LIB_H += util/dwarf-aux.h
278LIB_H += util/probe-event.h
279LIB_H += util/pstack.h
280LIB_H += util/cpumap.h
281LIB_H += util/top.h
282LIB_H += $(ARCH_INCLUDE)
283LIB_H += util/cgroup.h
284LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
285LIB_H += util/target.h
286LIB_H += util/rblist.h
287LIB_H += util/intlist.h
288LIB_H += util/perf_regs.h
289LIB_H += util/unwind.h
290LIB_H += util/vdso.h
291LIB_H += ui/helpline.h
292LIB_H += ui/progress.h
293LIB_H += ui/util.h
294LIB_H += ui/ui.h
295
296LIB_OBJS += $(OUTPUT)util/abspath.o
297LIB_OBJS += $(OUTPUT)util/alias.o
298LIB_OBJS += $(OUTPUT)util/annotate.o
299LIB_OBJS += $(OUTPUT)util/build-id.o
300LIB_OBJS += $(OUTPUT)util/config.o
301LIB_OBJS += $(OUTPUT)util/ctype.o
302LIB_OBJS += $(OUTPUT)util/sysfs.o
303LIB_OBJS += $(OUTPUT)util/pmu.o
304LIB_OBJS += $(OUTPUT)util/environment.o
305LIB_OBJS += $(OUTPUT)util/event.o
306LIB_OBJS += $(OUTPUT)util/evlist.o
307LIB_OBJS += $(OUTPUT)util/evsel.o
308LIB_OBJS += $(OUTPUT)util/exec_cmd.o
309LIB_OBJS += $(OUTPUT)util/help.o
310LIB_OBJS += $(OUTPUT)util/levenshtein.o
311LIB_OBJS += $(OUTPUT)util/parse-options.o
312LIB_OBJS += $(OUTPUT)util/parse-events.o
313LIB_OBJS += $(OUTPUT)util/path.o
314LIB_OBJS += $(OUTPUT)util/rbtree.o
315LIB_OBJS += $(OUTPUT)util/bitmap.o
316LIB_OBJS += $(OUTPUT)util/hweight.o
317LIB_OBJS += $(OUTPUT)util/run-command.o
318LIB_OBJS += $(OUTPUT)util/quote.o
319LIB_OBJS += $(OUTPUT)util/strbuf.o
320LIB_OBJS += $(OUTPUT)util/string.o
321LIB_OBJS += $(OUTPUT)util/strlist.o
322LIB_OBJS += $(OUTPUT)util/strfilter.o
323LIB_OBJS += $(OUTPUT)util/top.o
324LIB_OBJS += $(OUTPUT)util/usage.o
325LIB_OBJS += $(OUTPUT)util/wrapper.o
326LIB_OBJS += $(OUTPUT)util/sigchain.o
327LIB_OBJS += $(OUTPUT)util/dso.o
328LIB_OBJS += $(OUTPUT)util/symbol.o
329LIB_OBJS += $(OUTPUT)util/symbol-elf.o
330LIB_OBJS += $(OUTPUT)util/color.o
331LIB_OBJS += $(OUTPUT)util/pager.o
332LIB_OBJS += $(OUTPUT)util/header.o
333LIB_OBJS += $(OUTPUT)util/callchain.o
334LIB_OBJS += $(OUTPUT)util/values.o
335LIB_OBJS += $(OUTPUT)util/debug.o
336LIB_OBJS += $(OUTPUT)util/machine.o
337LIB_OBJS += $(OUTPUT)util/map.o
338LIB_OBJS += $(OUTPUT)util/pstack.o
339LIB_OBJS += $(OUTPUT)util/session.o
340LIB_OBJS += $(OUTPUT)util/thread.o
341LIB_OBJS += $(OUTPUT)util/thread_map.o
342LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
343LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
344LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
345LIB_OBJS += $(OUTPUT)util/pmu-flex.o
346LIB_OBJS += $(OUTPUT)util/pmu-bison.o
347LIB_OBJS += $(OUTPUT)util/trace-event-read.o
348LIB_OBJS += $(OUTPUT)util/trace-event-info.o
349LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
350LIB_OBJS += $(OUTPUT)util/svghelper.o
351LIB_OBJS += $(OUTPUT)util/sort.o
352LIB_OBJS += $(OUTPUT)util/hist.o
353LIB_OBJS += $(OUTPUT)util/probe-event.o
354LIB_OBJS += $(OUTPUT)util/util.o
355LIB_OBJS += $(OUTPUT)util/xyarray.o
356LIB_OBJS += $(OUTPUT)util/cpumap.o
357LIB_OBJS += $(OUTPUT)util/cgroup.o
358LIB_OBJS += $(OUTPUT)util/target.o
359LIB_OBJS += $(OUTPUT)util/rblist.o
360LIB_OBJS += $(OUTPUT)util/intlist.o
361LIB_OBJS += $(OUTPUT)util/vdso.o
362LIB_OBJS += $(OUTPUT)util/stat.o
363LIB_OBJS += $(OUTPUT)util/record.o
364
365LIB_OBJS += $(OUTPUT)ui/setup.o
366LIB_OBJS += $(OUTPUT)ui/helpline.o
367LIB_OBJS += $(OUTPUT)ui/progress.o
368LIB_OBJS += $(OUTPUT)ui/util.o
369LIB_OBJS += $(OUTPUT)ui/hist.o
370LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
371
372LIB_OBJS += $(OUTPUT)arch/common.o
373
374LIB_OBJS += $(OUTPUT)tests/parse-events.o
375LIB_OBJS += $(OUTPUT)tests/dso-data.o
376LIB_OBJS += $(OUTPUT)tests/attr.o
377LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
378LIB_OBJS += $(OUTPUT)tests/open-syscall.o
379LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
380LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
381LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
382LIB_OBJS += $(OUTPUT)tests/perf-record.o
383LIB_OBJS += $(OUTPUT)tests/rdpmc.o
384LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
385LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
386LIB_OBJS += $(OUTPUT)tests/pmu.o
387LIB_OBJS += $(OUTPUT)tests/hists_link.o
388LIB_OBJS += $(OUTPUT)tests/python-use.o
389LIB_OBJS += $(OUTPUT)tests/bp_signal.o
390LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
391LIB_OBJS += $(OUTPUT)tests/task-exit.o
392LIB_OBJS += $(OUTPUT)tests/sw-clock.o
393ifeq ($(ARCH),x86)
394LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
395endif
396LIB_OBJS += $(OUTPUT)tests/code-reading.o
397LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
398LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
399
400BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
401BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
402# Benchmark modules
403BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
404BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
405ifeq ($(RAW_ARCH),x86_64)
406BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
407BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
408endif
409BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
410BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
411
412BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
413BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
414BUILTIN_OBJS += $(OUTPUT)builtin-help.o
415BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
416BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
417BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
418BUILTIN_OBJS += $(OUTPUT)builtin-list.o
419BUILTIN_OBJS += $(OUTPUT)builtin-record.o
420BUILTIN_OBJS += $(OUTPUT)builtin-report.o
421BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
422BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
423BUILTIN_OBJS += $(OUTPUT)builtin-top.o
424BUILTIN_OBJS += $(OUTPUT)builtin-script.o
425BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
426BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
427BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
428BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
429BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
430BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
431BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
432
433PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
434
435# We choose to avoid "if .. else if .. else .. endif endif"
436# because maintaining the nesting to match is a pain. If
437# we had "elif" things would have been much nicer...
438
439-include arch/$(ARCH)/Makefile
440
441ifneq ($(OUTPUT),)
442 CFLAGS += -I$(OUTPUT)
443endif
444
445ifdef NO_LIBELF
446EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
447
448# Remove ELF/DWARF dependent codes
449LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
450LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
451LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
452LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
453
454BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
455
456# Use minimal symbol handling
457LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
458
459else # NO_LIBELF
460ifndef NO_DWARF
461 LIB_OBJS += $(OUTPUT)util/probe-finder.o
462 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
463endif # NO_DWARF
464endif # NO_LIBELF
465
466ifndef NO_LIBUNWIND
467 LIB_OBJS += $(OUTPUT)util/unwind.o
468endif
469LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
470
471ifndef NO_LIBAUDIT
472 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
473endif
474
475ifndef NO_SLANG
476 LIB_OBJS += $(OUTPUT)ui/browser.o
477 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
478 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
479 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
480 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
481 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
482 LIB_OBJS += $(OUTPUT)ui/tui/util.o
483 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
484 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
485 LIB_H += ui/browser.h
486 LIB_H += ui/browsers/map.h
487 LIB_H += ui/keysyms.h
488 LIB_H += ui/libslang.h
489endif
490
491ifndef NO_GTK2
492 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
493 LIB_OBJS += $(OUTPUT)ui/gtk/hists.o
494 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
495 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
496 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
497 LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
498 LIB_OBJS += $(OUTPUT)ui/gtk/annotate.o
499endif
500
501ifndef NO_LIBPERL
502 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
503 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
504endif
505
506ifndef NO_LIBPYTHON
507 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
508 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
509endif
510
511ifeq ($(NO_PERF_REGS),0)
512 ifeq ($(ARCH),x86)
513 LIB_H += arch/x86/include/perf_regs.h
514 endif
515endif
516
517ifndef NO_LIBNUMA
518 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
519endif
520
521ifdef ASCIIDOC8
522 export ASCIIDOC8
523endif
524
525LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
526
527export INSTALL SHELL_PATH
528
529### Build rules
530
531SHELL = $(SHELL_PATH)
532
533all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
534
535please_set_SHELL_PATH_to_a_more_modern_shell:
536 @$$(:)
537
538shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
539
540strip: $(PROGRAMS) $(OUTPUT)perf
541 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
542
543$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
544 $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
545 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
546 $(CFLAGS) -c $(filter %.c,$^) -o $@
547
548$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
549 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
550 $(BUILTIN_OBJS) $(LIBS) -o $@
551
552$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
553 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
554 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
555 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
556 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
557
558$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
559 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
560 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
561 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
562 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
563
564$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
565
566$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
567 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
568
569$(SCRIPTS) : % : %.sh
570 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
571
572# These can record PERF_VERSION
573$(OUTPUT)perf.o perf.spec \
574 $(SCRIPTS) \
575 : $(OUTPUT)PERF-VERSION-FILE
576
577.SUFFIXES:
578.SUFFIXES: .o .c .S .s
579
580# These two need to be here so that when O= is not used they take precedence
581# over the general rule for .o
582
583$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
584 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
585
586$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
587 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
588
589$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
590 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
591$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
592 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
593$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
594 $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
595$(OUTPUT)%.o: %.S
596 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
597$(OUTPUT)%.s: %.S
598 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
599
600$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
601 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
602 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
603 '-DPREFIX="$(prefix_SQ)"' \
604 $<
605
606$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
607 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
608 '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
609 $<
610
611$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
612 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
613 -DPYTHONPATH='"$(OUTPUT)python"' \
614 -DPYTHON='"$(PYTHON_WORD)"' \
615 $<
616
617$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
618 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
619
620$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
621 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
622
623$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
624 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
625 73
626$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 74#
627 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 75# All other targets get passed through:
628 76#
629$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 77%:
630 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 78 $(print_msg)
631 79 $(make)
632$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
633 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
634
635$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
636 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
637
638$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
639 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
640
641$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
642 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
643
644$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
645 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
646
647$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
648 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
649
650$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
651 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
652
653$(OUTPUT)perf-%: %.o $(PERFLIBS)
654 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
655
656$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
657$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
658
659# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
660# we depend the various files onto their directories.
661DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
662$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
663# In the second step, we make a rule to actually create these directories
664$(sort $(dir $(DIRECTORY_DEPS))):
665 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
666
667$(LIB_FILE): $(LIB_OBJS)
668 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
669
670# libtraceevent.a
671$(LIBTRACEEVENT):
672 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a
673
674$(LIBTRACEEVENT)-clean:
675 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
676
677# if subdir is set, we've been called from above so target has been built
678# already
679$(LIBLK):
680ifeq ($(subdir),)
681 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
682endif
683
684$(LIBLK)-clean:
685ifeq ($(subdir),)
686 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
687endif
688
689help:
690 @echo 'Perf make targets:'
691 @echo ' doc - make *all* documentation (see below)'
692 @echo ' man - make manpage documentation (access with man <foo>)'
693 @echo ' html - make html documentation'
694 @echo ' info - make GNU info documentation (access with info <foo>)'
695 @echo ' pdf - make pdf documentation'
696 @echo ' TAGS - use etags to make tag information for source browsing'
697 @echo ' tags - use ctags to make tag information for source browsing'
698 @echo ' cscope - use cscope to make interactive browsing database'
699 @echo ''
700 @echo 'Perf install targets:'
701 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed'
702 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular'
703 @echo ' path like make prefix=/usr/local install install-doc'
704 @echo ' install - install compiled binaries'
705 @echo ' install-doc - install *all* documentation'
706 @echo ' install-man - install manpage documentation'
707 @echo ' install-html - install html documentation'
708 @echo ' install-info - install GNU info documentation'
709 @echo ' install-pdf - install pdf documentation'
710 @echo ''
711 @echo ' quick-install-doc - alias for quick-install-man'
712 @echo ' quick-install-man - install the documentation quickly'
713 @echo ' quick-install-html - install the html documentation quickly'
714 @echo ''
715 @echo 'Perf maintainer targets:'
716 @echo ' clean - clean all binary objects and build output'
717
718
719DOC_TARGETS := doc man html info pdf
720
721INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
722INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
723
724# 'make doc' should call 'make -C Documentation all'
725$(DOC_TARGETS):
726 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
727
728TAGS:
729 $(RM) TAGS
730 $(FIND) . -name '*.[hcS]' -print | xargs etags -a
731
732tags:
733 $(RM) tags
734 $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
735
736cscope:
737 $(RM) cscope*
738 $(FIND) . -name '*.[hcS]' -print | xargs cscope -b
739
740### Detect prefix changes
741TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
742 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
743
744$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
745 @FLAGS='$(TRACK_CFLAGS)'; \
746 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
747 echo 1>&2 " * new build flags or prefix"; \
748 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
749 fi
750
751### Testing rules
752
753# GNU make supports exporting all variables by "export" without parameters.
754# However, the environment gets quite big, and some programs have problems
755# with that.
756
757check: $(OUTPUT)common-cmds.h
758 if sparse; \
759 then \
760 for i in *.c */*.c; \
761 do \
762 sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
763 done; \
764 else \
765 exit 1; \
766 fi
767
768### Installation rules
769
770install-bin: all
771 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
772 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
773 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
774 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
775ifndef NO_LIBPERL
776 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
777 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
778 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
779 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
780 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
781endif
782ifndef NO_LIBPYTHON
783 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
784 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
785 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
786 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
787 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
788endif
789 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'
790 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
791 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
792 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
793 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
794 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
795
796install: install-bin try-install-man
797
798install-python_ext:
799 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
800
801# 'make install-doc' should call 'make -C Documentation install'
802$(INSTALL_DOC_TARGETS):
803 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
804
805### Cleaning rules
806
807clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean
808 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
809 $(RM) $(ALL_PROGRAMS) perf
810 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
811 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
812 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
813 $(RM) $(OUTPUT)util/*-bison*
814 $(RM) $(OUTPUT)util/*-flex*
815 $(python-clean)
816
817.PHONY: all install clean strip $(LIBTRACEEVENT) $(LIBLK)
818.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
819.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
new file mode 100644
index 000000000000..7fc8f179cae7
--- /dev/null
+++ b/tools/perf/Makefile.perf
@@ -0,0 +1,892 @@
1include ../scripts/Makefile.include
2
3# The default target of this Makefile is...
4all:
5
6include config/utilities.mak
7
8# Define V to have a more verbose compile.
9#
10# Define O to save output files in a separate directory.
11#
12# Define ARCH as name of target architecture if you want cross-builds.
13#
14# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
15#
16# Define NO_LIBPERL to disable perl script extension.
17#
18# Define NO_LIBPYTHON to disable python script extension.
19#
20# Define PYTHON to point to the python binary if the default
21# `python' is not correct; for example: PYTHON=python2
22#
23# Define PYTHON_CONFIG to point to the python-config binary if
24# the default `$(PYTHON)-config' is not correct.
25#
26# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
27#
28# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
29#
30# Define LDFLAGS=-static to build a static binary.
31#
32# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
33#
34# Define NO_DWARF if you do not want debug-info analysis feature at all.
35#
36# Define WERROR=0 to disable treating any warnings as errors.
37#
38# Define NO_NEWT if you do not want TUI support. (deprecated)
39#
40# Define NO_SLANG if you do not want TUI support.
41#
42# Define NO_GTK2 if you do not want GTK+ GUI support.
43#
44# Define NO_DEMANGLE if you do not want C++ symbol demangling.
45#
46# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds)
47#
48# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
49# backtrace post unwind.
50#
51# Define NO_BACKTRACE if you do not want stack backtrace debug feature
52#
53# Define NO_LIBNUMA if you do not want numa perf benchmark
54#
55# Define NO_LIBAUDIT if you do not want libaudit support
56#
57# Define NO_LIBBIONIC if you do not want bionic support
58
59ifeq ($(srctree),)
60srctree := $(patsubst %/,%,$(dir $(shell pwd)))
61srctree := $(patsubst %/,%,$(dir $(srctree)))
62#$(info Determined 'srctree' to be $(srctree))
63endif
64
65ifneq ($(objtree),)
66#$(info Determined 'objtree' to be $(objtree))
67endif
68
69ifneq ($(OUTPUT),)
70#$(info Determined 'OUTPUT' to be $(OUTPUT))
71endif
72
73$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
74 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
75 @touch $(OUTPUT)PERF-VERSION-FILE
76
77CC = $(CROSS_COMPILE)gcc
78AR = $(CROSS_COMPILE)ar
79
80RM = rm -f
81LN = ln -f
82MKDIR = mkdir
83FIND = find
84INSTALL = install
85FLEX = flex
86BISON = bison
87STRIP = strip
88
89LK_DIR = $(srctree)/tools/lib/lk/
90TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
91
92# include config/Makefile by default and rule out
93# non-config cases
94config := 1
95
96NON_CONFIG_TARGETS := clean TAGS tags cscope help
97
98ifdef MAKECMDGOALS
99ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
100 config := 0
101endif
102endif
103
104ifeq ($(config),1)
105include config/Makefile
106endif
107
108export prefix bindir sharedir sysconfdir
109
110# sparse is architecture-neutral, which means that we need to tell it
111# explicitly what architecture to check for. Fix this up for yours..
112SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
113
114# Guard against environment variables
115BUILTIN_OBJS =
116LIB_H =
117LIB_OBJS =
118GTK_OBJS =
119PYRF_OBJS =
120SCRIPT_SH =
121
122SCRIPT_SH += perf-archive.sh
123
124grep-libs = $(filter -l%,$(1))
125strip-libs = $(filter-out -l%,$(1))
126
127ifneq ($(OUTPUT),)
128 TE_PATH=$(OUTPUT)
129ifneq ($(subdir),)
130 LK_PATH=$(OUTPUT)/../lib/lk/
131else
132 LK_PATH=$(OUTPUT)
133endif
134else
135 TE_PATH=$(TRACE_EVENT_DIR)
136 LK_PATH=$(LK_DIR)
137endif
138
139LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
140export LIBTRACEEVENT
141
142LIBLK = $(LK_PATH)liblk.a
143export LIBLK
144
145# python extension build directories
146PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
147PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
148PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
149export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
150
151python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
152
153PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
154PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
155
156$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
157 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
158 --quiet build_ext; \
159 mkdir -p $(OUTPUT)python && \
160 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
161#
162# No Perl scripts right now:
163#
164
165SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
166
167#
168# Single 'perf' binary right now:
169#
170PROGRAMS += $(OUTPUT)perf
171
172# what 'all' will build and 'install' will install, in perfexecdir
173ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
174
175# what 'all' will build but not install in perfexecdir
176OTHER_PROGRAMS = $(OUTPUT)perf
177
178# Set paths to tools early so that they can be used for version tests.
179ifndef SHELL_PATH
180 SHELL_PATH = /bin/sh
181endif
182ifndef PERL_PATH
183 PERL_PATH = /usr/bin/perl
184endif
185
186export PERL_PATH
187
188$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
189 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
190
191$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
192 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
193
194$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
195 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
196
197$(OUTPUT)util/pmu-bison.c: util/pmu.y
198 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
199
200$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
201$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
202
203LIB_FILE=$(OUTPUT)libperf.a
204
205LIB_H += ../../include/uapi/linux/perf_event.h
206LIB_H += ../../include/linux/rbtree.h
207LIB_H += ../../include/linux/list.h
208LIB_H += ../../include/uapi/linux/const.h
209LIB_H += ../../include/linux/hash.h
210LIB_H += ../../include/linux/stringify.h
211LIB_H += util/include/linux/bitmap.h
212LIB_H += util/include/linux/bitops.h
213LIB_H += util/include/linux/compiler.h
214LIB_H += util/include/linux/const.h
215LIB_H += util/include/linux/ctype.h
216LIB_H += util/include/linux/kernel.h
217LIB_H += util/include/linux/list.h
218LIB_H += util/include/linux/export.h
219LIB_H += util/include/linux/magic.h
220LIB_H += util/include/linux/poison.h
221LIB_H += util/include/linux/prefetch.h
222LIB_H += util/include/linux/rbtree.h
223LIB_H += util/include/linux/rbtree_augmented.h
224LIB_H += util/include/linux/string.h
225LIB_H += util/include/linux/types.h
226LIB_H += util/include/linux/linkage.h
227LIB_H += util/include/asm/asm-offsets.h
228LIB_H += util/include/asm/bug.h
229LIB_H += util/include/asm/byteorder.h
230LIB_H += util/include/asm/hweight.h
231LIB_H += util/include/asm/swab.h
232LIB_H += util/include/asm/system.h
233LIB_H += util/include/asm/uaccess.h
234LIB_H += util/include/dwarf-regs.h
235LIB_H += util/include/asm/dwarf2.h
236LIB_H += util/include/asm/cpufeature.h
237LIB_H += util/include/asm/unistd_32.h
238LIB_H += util/include/asm/unistd_64.h
239LIB_H += perf.h
240LIB_H += util/annotate.h
241LIB_H += util/cache.h
242LIB_H += util/callchain.h
243LIB_H += util/build-id.h
244LIB_H += util/debug.h
245LIB_H += util/fs.h
246LIB_H += util/pmu.h
247LIB_H += util/event.h
248LIB_H += util/evsel.h
249LIB_H += util/evlist.h
250LIB_H += util/exec_cmd.h
251LIB_H += util/types.h
252LIB_H += util/levenshtein.h
253LIB_H += util/machine.h
254LIB_H += util/map.h
255LIB_H += util/parse-options.h
256LIB_H += util/parse-events.h
257LIB_H += util/quote.h
258LIB_H += util/util.h
259LIB_H += util/xyarray.h
260LIB_H += util/header.h
261LIB_H += util/help.h
262LIB_H += util/session.h
263LIB_H += util/strbuf.h
264LIB_H += util/strlist.h
265LIB_H += util/strfilter.h
266LIB_H += util/svghelper.h
267LIB_H += util/tool.h
268LIB_H += util/run-command.h
269LIB_H += util/sigchain.h
270LIB_H += util/dso.h
271LIB_H += util/symbol.h
272LIB_H += util/color.h
273LIB_H += util/values.h
274LIB_H += util/sort.h
275LIB_H += util/hist.h
276LIB_H += util/comm.h
277LIB_H += util/thread.h
278LIB_H += util/thread_map.h
279LIB_H += util/trace-event.h
280LIB_H += util/probe-finder.h
281LIB_H += util/dwarf-aux.h
282LIB_H += util/probe-event.h
283LIB_H += util/pstack.h
284LIB_H += util/cpumap.h
285LIB_H += util/top.h
286LIB_H += $(ARCH_INCLUDE)
287LIB_H += util/cgroup.h
288LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
289LIB_H += util/target.h
290LIB_H += util/rblist.h
291LIB_H += util/intlist.h
292LIB_H += util/perf_regs.h
293LIB_H += util/unwind.h
294LIB_H += util/vdso.h
295LIB_H += ui/helpline.h
296LIB_H += ui/progress.h
297LIB_H += ui/util.h
298LIB_H += ui/ui.h
299LIB_H += util/data.h
300
301LIB_OBJS += $(OUTPUT)util/abspath.o
302LIB_OBJS += $(OUTPUT)util/alias.o
303LIB_OBJS += $(OUTPUT)util/annotate.o
304LIB_OBJS += $(OUTPUT)util/build-id.o
305LIB_OBJS += $(OUTPUT)util/config.o
306LIB_OBJS += $(OUTPUT)util/ctype.o
307LIB_OBJS += $(OUTPUT)util/fs.o
308LIB_OBJS += $(OUTPUT)util/pmu.o
309LIB_OBJS += $(OUTPUT)util/environment.o
310LIB_OBJS += $(OUTPUT)util/event.o
311LIB_OBJS += $(OUTPUT)util/evlist.o
312LIB_OBJS += $(OUTPUT)util/evsel.o
313LIB_OBJS += $(OUTPUT)util/exec_cmd.o
314LIB_OBJS += $(OUTPUT)util/help.o
315LIB_OBJS += $(OUTPUT)util/levenshtein.o
316LIB_OBJS += $(OUTPUT)util/parse-options.o
317LIB_OBJS += $(OUTPUT)util/parse-events.o
318LIB_OBJS += $(OUTPUT)util/path.o
319LIB_OBJS += $(OUTPUT)util/rbtree.o
320LIB_OBJS += $(OUTPUT)util/bitmap.o
321LIB_OBJS += $(OUTPUT)util/hweight.o
322LIB_OBJS += $(OUTPUT)util/run-command.o
323LIB_OBJS += $(OUTPUT)util/quote.o
324LIB_OBJS += $(OUTPUT)util/strbuf.o
325LIB_OBJS += $(OUTPUT)util/string.o
326LIB_OBJS += $(OUTPUT)util/strlist.o
327LIB_OBJS += $(OUTPUT)util/strfilter.o
328LIB_OBJS += $(OUTPUT)util/top.o
329LIB_OBJS += $(OUTPUT)util/usage.o
330LIB_OBJS += $(OUTPUT)util/wrapper.o
331LIB_OBJS += $(OUTPUT)util/sigchain.o
332LIB_OBJS += $(OUTPUT)util/dso.o
333LIB_OBJS += $(OUTPUT)util/symbol.o
334LIB_OBJS += $(OUTPUT)util/symbol-elf.o
335LIB_OBJS += $(OUTPUT)util/color.o
336LIB_OBJS += $(OUTPUT)util/pager.o
337LIB_OBJS += $(OUTPUT)util/header.o
338LIB_OBJS += $(OUTPUT)util/callchain.o
339LIB_OBJS += $(OUTPUT)util/values.o
340LIB_OBJS += $(OUTPUT)util/debug.o
341LIB_OBJS += $(OUTPUT)util/machine.o
342LIB_OBJS += $(OUTPUT)util/map.o
343LIB_OBJS += $(OUTPUT)util/pstack.o
344LIB_OBJS += $(OUTPUT)util/session.o
345LIB_OBJS += $(OUTPUT)util/comm.o
346LIB_OBJS += $(OUTPUT)util/thread.o
347LIB_OBJS += $(OUTPUT)util/thread_map.o
348LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
349LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
350LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
351LIB_OBJS += $(OUTPUT)util/pmu-flex.o
352LIB_OBJS += $(OUTPUT)util/pmu-bison.o
353LIB_OBJS += $(OUTPUT)util/trace-event-read.o
354LIB_OBJS += $(OUTPUT)util/trace-event-info.o
355LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
356LIB_OBJS += $(OUTPUT)util/svghelper.o
357LIB_OBJS += $(OUTPUT)util/sort.o
358LIB_OBJS += $(OUTPUT)util/hist.o
359LIB_OBJS += $(OUTPUT)util/probe-event.o
360LIB_OBJS += $(OUTPUT)util/util.o
361LIB_OBJS += $(OUTPUT)util/xyarray.o
362LIB_OBJS += $(OUTPUT)util/cpumap.o
363LIB_OBJS += $(OUTPUT)util/cgroup.o
364LIB_OBJS += $(OUTPUT)util/target.o
365LIB_OBJS += $(OUTPUT)util/rblist.o
366LIB_OBJS += $(OUTPUT)util/intlist.o
367LIB_OBJS += $(OUTPUT)util/vdso.o
368LIB_OBJS += $(OUTPUT)util/stat.o
369LIB_OBJS += $(OUTPUT)util/record.o
370LIB_OBJS += $(OUTPUT)util/srcline.o
371LIB_OBJS += $(OUTPUT)util/data.o
372
373LIB_OBJS += $(OUTPUT)ui/setup.o
374LIB_OBJS += $(OUTPUT)ui/helpline.o
375LIB_OBJS += $(OUTPUT)ui/progress.o
376LIB_OBJS += $(OUTPUT)ui/util.o
377LIB_OBJS += $(OUTPUT)ui/hist.o
378LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
379
380LIB_OBJS += $(OUTPUT)arch/common.o
381
382LIB_OBJS += $(OUTPUT)tests/parse-events.o
383LIB_OBJS += $(OUTPUT)tests/dso-data.o
384LIB_OBJS += $(OUTPUT)tests/attr.o
385LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
386LIB_OBJS += $(OUTPUT)tests/open-syscall.o
387LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
388LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
389LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
390LIB_OBJS += $(OUTPUT)tests/perf-record.o
391LIB_OBJS += $(OUTPUT)tests/rdpmc.o
392LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
393LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
394LIB_OBJS += $(OUTPUT)tests/pmu.o
395LIB_OBJS += $(OUTPUT)tests/hists_link.o
396LIB_OBJS += $(OUTPUT)tests/python-use.o
397LIB_OBJS += $(OUTPUT)tests/bp_signal.o
398LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
399LIB_OBJS += $(OUTPUT)tests/task-exit.o
400LIB_OBJS += $(OUTPUT)tests/sw-clock.o
401ifeq ($(ARCH),x86)
402LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
403endif
404LIB_OBJS += $(OUTPUT)tests/code-reading.o
405LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
406LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
407
408BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
409BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
410# Benchmark modules
411BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
412BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
413ifeq ($(RAW_ARCH),x86_64)
414BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
415BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
416endif
417BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
418BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
419
420BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
421BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
422BUILTIN_OBJS += $(OUTPUT)builtin-help.o
423BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
424BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
425BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
426BUILTIN_OBJS += $(OUTPUT)builtin-list.o
427BUILTIN_OBJS += $(OUTPUT)builtin-record.o
428BUILTIN_OBJS += $(OUTPUT)builtin-report.o
429BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
430BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
431BUILTIN_OBJS += $(OUTPUT)builtin-top.o
432BUILTIN_OBJS += $(OUTPUT)builtin-script.o
433BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
434BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
435BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
436BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
437BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
438BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
439BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
440
441PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
442
443# We choose to avoid "if .. else if .. else .. endif endif"
444# because maintaining the nesting to match is a pain. If
445# we had "elif" things would have been much nicer...
446
447-include arch/$(ARCH)/Makefile
448
449ifneq ($(OUTPUT),)
450 CFLAGS += -I$(OUTPUT)
451endif
452
453ifdef NO_LIBELF
454EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
455
456# Remove ELF/DWARF dependent codes
457LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
458LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
459LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
460LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
461
462BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
463
464# Use minimal symbol handling
465LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
466
467else # NO_LIBELF
468ifndef NO_DWARF
469 LIB_OBJS += $(OUTPUT)util/probe-finder.o
470 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
471endif # NO_DWARF
472endif # NO_LIBELF
473
474ifndef NO_LIBUNWIND
475 LIB_OBJS += $(OUTPUT)util/unwind.o
476endif
477LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
478
479ifndef NO_LIBAUDIT
480 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
481endif
482
483ifndef NO_SLANG
484 LIB_OBJS += $(OUTPUT)ui/browser.o
485 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
486 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
487 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
488 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
489 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
490 LIB_OBJS += $(OUTPUT)ui/tui/util.o
491 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
492 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
493 LIB_H += ui/tui/tui.h
494 LIB_H += ui/browser.h
495 LIB_H += ui/browsers/map.h
496 LIB_H += ui/keysyms.h
497 LIB_H += ui/libslang.h
498endif
499
500ifndef NO_GTK2
501 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
502
503 GTK_OBJS += $(OUTPUT)ui/gtk/browser.o
504 GTK_OBJS += $(OUTPUT)ui/gtk/hists.o
505 GTK_OBJS += $(OUTPUT)ui/gtk/setup.o
506 GTK_OBJS += $(OUTPUT)ui/gtk/util.o
507 GTK_OBJS += $(OUTPUT)ui/gtk/helpline.o
508 GTK_OBJS += $(OUTPUT)ui/gtk/progress.o
509 GTK_OBJS += $(OUTPUT)ui/gtk/annotate.o
510
511install-gtk: $(OUTPUT)libperf-gtk.so
512 $(call QUIET_INSTALL, 'GTK UI') \
513 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
514 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
515endif
516
517ifndef NO_LIBPERL
518 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
519 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
520endif
521
522ifndef NO_LIBPYTHON
523 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
524 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
525endif
526
527ifeq ($(NO_PERF_REGS),0)
528 ifeq ($(ARCH),x86)
529 LIB_H += arch/x86/include/perf_regs.h
530 endif
531endif
532
533ifndef NO_LIBNUMA
534 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
535endif
536
537ifdef ASCIIDOC8
538 export ASCIIDOC8
539endif
540
541LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
542
543export INSTALL SHELL_PATH
544
545### Build rules
546
547SHELL = $(SHELL_PATH)
548
549all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
550
551please_set_SHELL_PATH_to_a_more_modern_shell:
552 @$$(:)
553
554shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
555
556strip: $(PROGRAMS) $(OUTPUT)perf
557 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
558
559$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
560 $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
561 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
562 $(CFLAGS) -c $(filter %.c,$^) -o $@
563
564$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
565 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
566 $(BUILTIN_OBJS) $(LIBS) -o $@
567
568$(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H)
569 $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $<
570
571$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS)
572 $(QUIET_LINK)$(CC) -o $@ -shared $(ALL_LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
573
574$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
575 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
576 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
577 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
578 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
579
580$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
581 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
582 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
583 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
584 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
585
586$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
587
588$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
589 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
590
591$(SCRIPTS) : % : %.sh
592 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
593
594# These can record PERF_VERSION
595$(OUTPUT)perf.o perf.spec \
596 $(SCRIPTS) \
597 : $(OUTPUT)PERF-VERSION-FILE
598
599.SUFFIXES:
600
601#
602# If a target does not match any of the later rules then prefix it by $(OUTPUT)
603# This makes targets like 'make O=/tmp/perf perf.o' work in a natural way.
604#
605ifneq ($(OUTPUT),)
606%.o: $(OUTPUT)%.o
607 @echo " # Redirected target $@ => $(OUTPUT)$@"
608util/%.o: $(OUTPUT)util/%.o
609 @echo " # Redirected target $@ => $(OUTPUT)$@"
610bench/%.o: $(OUTPUT)bench/%.o
611 @echo " # Redirected target $@ => $(OUTPUT)$@"
612tests/%.o: $(OUTPUT)tests/%.o
613 @echo " # Redirected target $@ => $(OUTPUT)$@"
614endif
615
616# These two need to be here so that when O= is not used they take precedence
617# over the general rule for .o
618
619$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
620 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
621
622$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
623 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
624
625$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
626 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
627$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
628 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
629$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
630 $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
631$(OUTPUT)%.o: %.S
632 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
633$(OUTPUT)%.s: %.S
634 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
635
636$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
637 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
638 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
639 '-DPREFIX="$(prefix_SQ)"' \
640 $<
641
642$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
643 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
644 '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
645 $<
646
647$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
648 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
649 -DPYTHONPATH='"$(OUTPUT)python"' \
650 -DPYTHON='"$(PYTHON_WORD)"' \
651 $<
652
653$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
654 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
655
656$(OUTPUT)ui/setup.o: ui/setup.c $(OUTPUT)PERF-CFLAGS
657 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DLIBDIR='"$(libdir_SQ)"' $<
658
659$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
660 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
661
662$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
663 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
664
665$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
666 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
667
668$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
669 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
670
671$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
672 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
673
674$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
675 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
676
677$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
678 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
679
680$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
681 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
682
683$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
684 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
685
686$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
687 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
688
689$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
690 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
691
692$(OUTPUT)perf-%: %.o $(PERFLIBS)
693 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
694
695$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
696$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
697
698# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
699# we depend the various files onto their directories.
700DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
701DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
702$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
703# In the second step, we make a rule to actually create these directories
704$(sort $(dir $(DIRECTORY_DEPS))):
705 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
706
707$(LIB_FILE): $(LIB_OBJS)
708 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
709
710# libtraceevent.a
711TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
712
713$(LIBTRACEEVENT): $(TE_SOURCES)
714 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) CFLAGS="-g -Wall $(EXTRA_CFLAGS)" libtraceevent.a
715
716$(LIBTRACEEVENT)-clean:
717 $(call QUIET_CLEAN, libtraceevent)
718 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
719
720LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch])
721
722# if subdir is set, we've been called from above so target has been built
723# already
724$(LIBLK): $(LIBLK_SOURCES)
725ifeq ($(subdir),)
726 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
727endif
728
729$(LIBLK)-clean:
730ifeq ($(subdir),)
731 $(call QUIET_CLEAN, liblk)
732 @$(MAKE) -C $(LK_DIR) O=$(OUTPUT) clean >/dev/null
733endif
734
735help:
736 @echo 'Perf make targets:'
737 @echo ' doc - make *all* documentation (see below)'
738 @echo ' man - make manpage documentation (access with man <foo>)'
739 @echo ' html - make html documentation'
740 @echo ' info - make GNU info documentation (access with info <foo>)'
741 @echo ' pdf - make pdf documentation'
742 @echo ' TAGS - use etags to make tag information for source browsing'
743 @echo ' tags - use ctags to make tag information for source browsing'
744 @echo ' cscope - use cscope to make interactive browsing database'
745 @echo ''
746 @echo 'Perf install targets:'
747 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed'
748 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular'
749 @echo ' path like make prefix=/usr/local install install-doc'
750 @echo ' install - install compiled binaries'
751 @echo ' install-doc - install *all* documentation'
752 @echo ' install-man - install manpage documentation'
753 @echo ' install-html - install html documentation'
754 @echo ' install-info - install GNU info documentation'
755 @echo ' install-pdf - install pdf documentation'
756 @echo ''
757 @echo ' quick-install-doc - alias for quick-install-man'
758 @echo ' quick-install-man - install the documentation quickly'
759 @echo ' quick-install-html - install the html documentation quickly'
760 @echo ''
761 @echo 'Perf maintainer targets:'
762 @echo ' clean - clean all binary objects and build output'
763
764
765DOC_TARGETS := doc man html info pdf
766
767INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
768INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
769
770# 'make doc' should call 'make -C Documentation all'
771$(DOC_TARGETS):
772 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
773
774TAGS:
775 $(RM) TAGS
776 $(FIND) . -name '*.[hcS]' -print | xargs etags -a
777
778tags:
779 $(RM) tags
780 $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
781
782cscope:
783 $(RM) cscope*
784 $(FIND) . -name '*.[hcS]' -print | xargs cscope -b
785
786### Detect prefix changes
787TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
788 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
789
790$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
791 @FLAGS='$(TRACK_CFLAGS)'; \
792 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
793 echo 1>&2 " FLAGS: * new build flags or prefix"; \
794 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
795 fi
796
797### Testing rules
798
799# GNU make supports exporting all variables by "export" without parameters.
800# However, the environment gets quite big, and some programs have problems
801# with that.
802
803check: $(OUTPUT)common-cmds.h
804 if sparse; \
805 then \
806 for i in *.c */*.c; \
807 do \
808 sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
809 done; \
810 else \
811 exit 1; \
812 fi
813
814### Installation rules
815
816install-gtk:
817
818install-bin: all install-gtk
819 $(call QUIET_INSTALL, binaries) \
820 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
821 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
822 $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'
823 $(call QUIET_INSTALL, libexec) \
824 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
825 $(call QUIET_INSTALL, perf-archive) \
826 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
827ifndef NO_LIBPERL
828 $(call QUIET_INSTALL, perl-scripts) \
829 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
830 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
831 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'; \
832 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'; \
833 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
834endif
835ifndef NO_LIBPYTHON
836 $(call QUIET_INSTALL, python-scripts) \
837 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
838 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'; \
839 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
840 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
841 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
842endif
843 $(call QUIET_INSTALL, bash_completion-script) \
844 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
845 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
846 $(call QUIET_INSTALL, tests) \
847 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
848 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
849 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
850 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
851
852install: install-bin try-install-man
853
854install-python_ext:
855 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
856
857# 'make install-doc' should call 'make -C Documentation install'
858$(INSTALL_DOC_TARGETS):
859 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
860
861### Cleaning rules
862
863#
864# This is here, not in config/Makefile, because config/Makefile does
865# not get included for the clean target:
866#
867config-clean:
868 $(call QUIET_CLEAN, config)
869 @$(MAKE) -C config/feature-checks clean >/dev/null
870
871clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean config-clean
872 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
873 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
874 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
875 $(call QUIET_CLEAN, Documentation)
876 @$(MAKE) -C Documentation O=$(OUTPUT) clean >/dev/null
877 $(python-clean)
878
879#
880# Trick: if ../../.git does not exist - we are building out of tree for example,
881# then force version regeneration:
882#
883ifeq ($(wildcard ../../.git/HEAD),)
884 GIT-HEAD-PHONY = ../../.git/HEAD
885else
886 GIT-HEAD-PHONY =
887endif
888
889.PHONY: all install clean config-clean strip install-gtk
890.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
891.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope .FORCE-PERF-CFLAGS
892
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h
index 7fcdcdbee917..e84ca76aae77 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -5,7 +5,7 @@
5#include "../../util/types.h" 5#include "../../util/types.h"
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8#ifndef ARCH_X86_64 8#ifndef HAVE_ARCH_X86_64_SUPPORT
9#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) 9#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
10#else 10#else
11#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ 11#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
@@ -52,7 +52,7 @@ static inline const char *perf_reg_name(int id)
52 return "FS"; 52 return "FS";
53 case PERF_REG_X86_GS: 53 case PERF_REG_X86_GS:
54 return "GS"; 54 return "GS";
55#ifdef ARCH_X86_64 55#ifdef HAVE_ARCH_X86_64_SUPPORT
56 case PERF_REG_X86_R8: 56 case PERF_REG_X86_R8:
57 return "R8"; 57 return "R8";
58 case PERF_REG_X86_R9: 58 case PERF_REG_X86_R9:
@@ -69,7 +69,7 @@ static inline const char *perf_reg_name(int id)
69 return "R14"; 69 return "R14";
70 case PERF_REG_X86_R15: 70 case PERF_REG_X86_R15:
71 return "R15"; 71 return "R15";
72#endif /* ARCH_X86_64 */ 72#endif /* HAVE_ARCH_X86_64_SUPPORT */
73 default: 73 default:
74 return NULL; 74 return NULL;
75 } 75 }
diff --git a/tools/perf/arch/x86/util/unwind.c b/tools/perf/arch/x86/util/unwind.c
index 78d956eff96f..456a88cf5b37 100644
--- a/tools/perf/arch/x86/util/unwind.c
+++ b/tools/perf/arch/x86/util/unwind.c
@@ -4,7 +4,7 @@
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6 6
7#ifdef ARCH_X86_64 7#ifdef HAVE_ARCH_X86_64_SUPPORT
8int unwind__arch_reg_id(int regnum) 8int unwind__arch_reg_id(int regnum)
9{ 9{
10 int id; 10 int id;
@@ -108,4 +108,4 @@ int unwind__arch_reg_id(int regnum)
108 108
109 return id; 109 return id;
110} 110}
111#endif /* ARCH_X86_64 */ 111#endif /* HAVE_ARCH_X86_64_SUPPORT */
diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 56e6a12aab59..62e157db2e2b 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -1,17 +1,87 @@
1# perf completion 1# perf completion
2 2
3function_exists() 3# Taken from git.git's completion script.
4__my_reassemble_comp_words_by_ref()
4{ 5{
5 declare -F $1 > /dev/null 6 local exclude i j first
6 return $? 7 # Which word separators to exclude?
8 exclude="${1//[^$COMP_WORDBREAKS]}"
9 cword_=$COMP_CWORD
10 if [ -z "$exclude" ]; then
11 words_=("${COMP_WORDS[@]}")
12 return
13 fi
14 # List of word completion separators has shrunk;
15 # re-assemble words to complete.
16 for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
17 # Append each nonempty word consisting of just
18 # word separator characters to the current word.
19 first=t
20 while
21 [ $i -gt 0 ] &&
22 [ -n "${COMP_WORDS[$i]}" ] &&
23 # word consists of excluded word separators
24 [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
25 do
26 # Attach to the previous token,
27 # unless the previous token is the command name.
28 if [ $j -ge 2 ] && [ -n "$first" ]; then
29 ((j--))
30 fi
31 first=
32 words_[$j]=${words_[j]}${COMP_WORDS[i]}
33 if [ $i = $COMP_CWORD ]; then
34 cword_=$j
35 fi
36 if (($i < ${#COMP_WORDS[@]} - 1)); then
37 ((i++))
38 else
39 # Done.
40 return
41 fi
42 done
43 words_[$j]=${words_[j]}${COMP_WORDS[i]}
44 if [ $i = $COMP_CWORD ]; then
45 cword_=$j
46 fi
47 done
7} 48}
8 49
9function_exists __ltrim_colon_completions || 50type _get_comp_words_by_ref &>/dev/null ||
51_get_comp_words_by_ref()
52{
53 local exclude cur_ words_ cword_
54 if [ "$1" = "-n" ]; then
55 exclude=$2
56 shift 2
57 fi
58 __my_reassemble_comp_words_by_ref "$exclude"
59 cur_=${words_[cword_]}
60 while [ $# -gt 0 ]; do
61 case "$1" in
62 cur)
63 cur=$cur_
64 ;;
65 prev)
66 prev=${words_[$cword_-1]}
67 ;;
68 words)
69 words=("${words_[@]}")
70 ;;
71 cword)
72 cword=$cword_
73 ;;
74 esac
75 shift
76 done
77}
78
79type __ltrim_colon_completions &>/dev/null ||
10__ltrim_colon_completions() 80__ltrim_colon_completions()
11{ 81{
12 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then 82 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
13 # Remove colon-word prefix from COMPREPLY items 83 # Remove colon-word prefix from COMPREPLY items
14 local colon_word=${1%${1##*:}} 84 local colon_word=${1%"${1##*:}"}
15 local i=${#COMPREPLY[*]} 85 local i=${#COMPREPLY[*]}
16 while [[ $((--i)) -ge 0 ]]; do 86 while [[ $((--i)) -ge 0 ]]; do
17 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} 87 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
@@ -19,23 +89,18 @@ __ltrim_colon_completions()
19 fi 89 fi
20} 90}
21 91
22have perf && 92type perf &>/dev/null &&
23_perf() 93_perf()
24{ 94{
25 local cur prev cmd 95 local cur words cword prev cmd
26 96
27 COMPREPLY=() 97 COMPREPLY=()
28 if function_exists _get_comp_words_by_ref; then 98 _get_comp_words_by_ref -n =: cur words cword prev
29 _get_comp_words_by_ref -n : cur prev
30 else
31 cur=$(_get_cword :)
32 prev=${COMP_WORDS[COMP_CWORD-1]}
33 fi
34 99
35 cmd=${COMP_WORDS[0]} 100 cmd=${words[0]}
36 101
37 # List perf subcommands or long options 102 # List perf subcommands or long options
38 if [ $COMP_CWORD -eq 1 ]; then 103 if [ $cword -eq 1 ]; then
39 if [[ $cur == --* ]]; then 104 if [[ $cur == --* ]]; then
40 COMPREPLY=( $( compgen -W '--help --version \ 105 COMPREPLY=( $( compgen -W '--help --version \
41 --exec-path --html-path --paginate --no-pager \ 106 --exec-path --html-path --paginate --no-pager \
@@ -45,18 +110,17 @@ _perf()
45 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) 110 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
46 fi 111 fi
47 # List possible events for -e option 112 # List possible events for -e option
48 elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then 113 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
49 evts=$($cmd list --raw-dump) 114 evts=$($cmd list --raw-dump)
50 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) ) 115 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
51 __ltrim_colon_completions $cur 116 __ltrim_colon_completions $cur
52 # List long option names 117 # List long option names
53 elif [[ $cur == --* ]]; then 118 elif [[ $cur == --* ]]; then
54 subcmd=${COMP_WORDS[1]} 119 subcmd=${words[1]}
55 opts=$($cmd $subcmd --list-opts) 120 opts=$($cmd $subcmd --list-opts)
56 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) ) 121 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
57 # Fall down to list regular files
58 else
59 _filedir
60 fi 122 fi
61} && 123} &&
62complete -F _perf perf 124
125complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
126 || complete -o default -o nospace -F _perf perf
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h
index a72e36cb5394..57b4ed871459 100644
--- a/tools/perf/bench/mem-memcpy-arch.h
+++ b/tools/perf/bench/mem-memcpy-arch.h
@@ -1,5 +1,5 @@
1 1
2#ifdef ARCH_X86_64 2#ifdef HAVE_ARCH_X86_64_SUPPORT
3 3
4#define MEMCPY_FN(fn, name, desc) \ 4#define MEMCPY_FN(fn, name, desc) \
5 extern void *fn(void *, const void *, size_t); 5 extern void *fn(void *, const void *, size_t);
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 8cdca43016b2..5ce71d3b72cf 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -58,7 +58,7 @@ struct routine routines[] = {
58 { "default", 58 { "default",
59 "Default memcpy() provided by glibc", 59 "Default memcpy() provided by glibc",
60 memcpy }, 60 memcpy },
61#ifdef ARCH_X86_64 61#ifdef HAVE_ARCH_X86_64_SUPPORT
62 62
63#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, 63#define MEMCPY_FN(fn, name, desc) { name, desc, fn },
64#include "mem-memcpy-x86-64-asm-def.h" 64#include "mem-memcpy-x86-64-asm-def.h"
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h
index a040fa77665b..633800cb0dcb 100644
--- a/tools/perf/bench/mem-memset-arch.h
+++ b/tools/perf/bench/mem-memset-arch.h
@@ -1,5 +1,5 @@
1 1
2#ifdef ARCH_X86_64 2#ifdef HAVE_ARCH_X86_64_SUPPORT
3 3
4#define MEMSET_FN(fn, name, desc) \ 4#define MEMSET_FN(fn, name, desc) \
5 extern void *fn(void *, int, size_t); 5 extern void *fn(void *, int, size_t);
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
index 4a2f12081964..9af79d2b18e5 100644
--- a/tools/perf/bench/mem-memset.c
+++ b/tools/perf/bench/mem-memset.c
@@ -58,7 +58,7 @@ static const struct routine routines[] = {
58 { "default", 58 { "default",
59 "Default memset() provided by glibc", 59 "Default memset() provided by glibc",
60 memset }, 60 memset },
61#ifdef ARCH_X86_64 61#ifdef HAVE_ARCH_X86_64_SUPPORT
62 62
63#define MEMSET_FN(fn, name, desc) { name, desc, fn }, 63#define MEMSET_FN(fn, name, desc) { name, desc, fn },
64#include "mem-memset-x86-64-asm-def.h" 64#include "mem-memset-x86-64-asm-def.h"
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 30d1c3225b46..d4c83c60b9b2 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -429,14 +429,14 @@ static int parse_cpu_list(const char *arg)
429 return 0; 429 return 0;
430} 430}
431 431
432static void parse_setup_cpu_list(void) 432static int parse_setup_cpu_list(void)
433{ 433{
434 struct thread_data *td; 434 struct thread_data *td;
435 char *str0, *str; 435 char *str0, *str;
436 int t; 436 int t;
437 437
438 if (!g->p.cpu_list_str) 438 if (!g->p.cpu_list_str)
439 return; 439 return 0;
440 440
441 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks); 441 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
442 442
@@ -500,8 +500,12 @@ static void parse_setup_cpu_list(void)
500 500
501 dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul); 501 dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul);
502 502
503 BUG_ON(bind_cpu_0 < 0 || bind_cpu_0 >= g->p.nr_cpus); 503 if (bind_cpu_0 >= g->p.nr_cpus || bind_cpu_1 >= g->p.nr_cpus) {
504 BUG_ON(bind_cpu_1 < 0 || bind_cpu_1 >= g->p.nr_cpus); 504 printf("\nTest not applicable, system has only %d CPUs.\n", g->p.nr_cpus);
505 return -1;
506 }
507
508 BUG_ON(bind_cpu_0 < 0 || bind_cpu_1 < 0);
505 BUG_ON(bind_cpu_0 > bind_cpu_1); 509 BUG_ON(bind_cpu_0 > bind_cpu_1);
506 510
507 for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) { 511 for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) {
@@ -541,6 +545,7 @@ out:
541 printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t); 545 printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
542 546
543 free(str0); 547 free(str0);
548 return 0;
544} 549}
545 550
546static int parse_cpus_opt(const struct option *opt __maybe_unused, 551static int parse_cpus_opt(const struct option *opt __maybe_unused,
@@ -561,14 +566,14 @@ static int parse_node_list(const char *arg)
561 return 0; 566 return 0;
562} 567}
563 568
564static void parse_setup_node_list(void) 569static int parse_setup_node_list(void)
565{ 570{
566 struct thread_data *td; 571 struct thread_data *td;
567 char *str0, *str; 572 char *str0, *str;
568 int t; 573 int t;
569 574
570 if (!g->p.node_list_str) 575 if (!g->p.node_list_str)
571 return; 576 return 0;
572 577
573 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks); 578 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
574 579
@@ -619,8 +624,12 @@ static void parse_setup_node_list(void)
619 624
620 dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step); 625 dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step);
621 626
622 BUG_ON(bind_node_0 < 0 || bind_node_0 >= g->p.nr_nodes); 627 if (bind_node_0 >= g->p.nr_nodes || bind_node_1 >= g->p.nr_nodes) {
623 BUG_ON(bind_node_1 < 0 || bind_node_1 >= g->p.nr_nodes); 628 printf("\nTest not applicable, system has only %d nodes.\n", g->p.nr_nodes);
629 return -1;
630 }
631
632 BUG_ON(bind_node_0 < 0 || bind_node_1 < 0);
624 BUG_ON(bind_node_0 > bind_node_1); 633 BUG_ON(bind_node_0 > bind_node_1);
625 634
626 for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) { 635 for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) {
@@ -651,6 +660,7 @@ out:
651 printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t); 660 printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
652 661
653 free(str0); 662 free(str0);
663 return 0;
654} 664}
655 665
656static int parse_nodes_opt(const struct option *opt __maybe_unused, 666static int parse_nodes_opt(const struct option *opt __maybe_unused,
@@ -1110,7 +1120,7 @@ static void *worker_thread(void *__tdata)
1110 /* Check whether our max runtime timed out: */ 1120 /* Check whether our max runtime timed out: */
1111 if (g->p.nr_secs) { 1121 if (g->p.nr_secs) {
1112 timersub(&stop, &start0, &diff); 1122 timersub(&stop, &start0, &diff);
1113 if (diff.tv_sec >= g->p.nr_secs) { 1123 if ((u32)diff.tv_sec >= g->p.nr_secs) {
1114 g->stop_work = true; 1124 g->stop_work = true;
1115 break; 1125 break;
1116 } 1126 }
@@ -1157,7 +1167,7 @@ static void *worker_thread(void *__tdata)
1157 runtime_ns_max += diff.tv_usec * 1000; 1167 runtime_ns_max += diff.tv_usec * 1000;
1158 1168
1159 if (details >= 0) { 1169 if (details >= 0) {
1160 printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016lx]\n", 1170 printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016"PRIx64"]\n",
1161 process_nr, thread_nr, runtime_ns_max / bytes_done, val); 1171 process_nr, thread_nr, runtime_ns_max / bytes_done, val);
1162 } 1172 }
1163 fflush(stdout); 1173 fflush(stdout);
@@ -1356,8 +1366,8 @@ static int init(void)
1356 init_thread_data(); 1366 init_thread_data();
1357 1367
1358 tprintf("#\n"); 1368 tprintf("#\n");
1359 parse_setup_cpu_list(); 1369 if (parse_setup_cpu_list() || parse_setup_node_list())
1360 parse_setup_node_list(); 1370 return -1;
1361 tprintf("#\n"); 1371 tprintf("#\n");
1362 1372
1363 print_summary(); 1373 print_summary();
@@ -1600,7 +1610,6 @@ static int run_bench_numa(const char *name, const char **argv)
1600 return 0; 1610 return 0;
1601 1611
1602err: 1612err:
1603 usage_with_options(numa_usage, options);
1604 return -1; 1613 return -1;
1605} 1614}
1606 1615
@@ -1701,8 +1710,7 @@ static int bench_all(void)
1701 BUG_ON(ret < 0); 1710 BUG_ON(ret < 0);
1702 1711
1703 for (i = 0; i < nr; i++) { 1712 for (i = 0; i < nr; i++) {
1704 if (run_bench_numa(tests[i][0], tests[i] + 1)) 1713 run_bench_numa(tests[i][0], tests[i] + 1);
1705 return -1;
1706 } 1714 }
1707 1715
1708 printf("\n"); 1716 printf("\n");
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 69cfba8d4c6c..07a8d7646a15 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -7,9 +7,7 @@
7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com> 7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com>
8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c 8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
10 *
11 */ 10 */
12
13#include "../perf.h" 11#include "../perf.h"
14#include "../util/util.h" 12#include "../util/util.h"
15#include "../util/parse-options.h" 13#include "../util/parse-options.h"
@@ -28,12 +26,24 @@
28#include <sys/time.h> 26#include <sys/time.h>
29#include <sys/types.h> 27#include <sys/types.h>
30 28
29#include <pthread.h>
30
31struct thread_data {
32 int nr;
33 int pipe_read;
34 int pipe_write;
35 pthread_t pthread;
36};
37
31#define LOOPS_DEFAULT 1000000 38#define LOOPS_DEFAULT 1000000
32static int loops = LOOPS_DEFAULT; 39static int loops = LOOPS_DEFAULT;
40
41/* Use processes by default: */
42static bool threaded;
33 43
34static const struct option options[] = { 44static const struct option options[] = {
35 OPT_INTEGER('l', "loop", &loops, 45 OPT_INTEGER('l', "loop", &loops, "Specify number of loops"),
36 "Specify number of loops"), 46 OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"),
37 OPT_END() 47 OPT_END()
38}; 48};
39 49
@@ -42,13 +52,37 @@ static const char * const bench_sched_pipe_usage[] = {
42 NULL 52 NULL
43}; 53};
44 54
45int bench_sched_pipe(int argc, const char **argv, 55static void *worker_thread(void *__tdata)
46 const char *prefix __maybe_unused)
47{ 56{
48 int pipe_1[2], pipe_2[2]; 57 struct thread_data *td = __tdata;
49 int m = 0, i; 58 int m = 0, i;
59 int ret;
60
61 for (i = 0; i < loops; i++) {
62 if (!td->nr) {
63 ret = read(td->pipe_read, &m, sizeof(int));
64 BUG_ON(ret != sizeof(int));
65 ret = write(td->pipe_write, &m, sizeof(int));
66 BUG_ON(ret != sizeof(int));
67 } else {
68 ret = write(td->pipe_write, &m, sizeof(int));
69 BUG_ON(ret != sizeof(int));
70 ret = read(td->pipe_read, &m, sizeof(int));
71 BUG_ON(ret != sizeof(int));
72 }
73 }
74
75 return NULL;
76}
77
78int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unused)
79{
80 struct thread_data threads[2], *td;
81 int pipe_1[2], pipe_2[2];
50 struct timeval start, stop, diff; 82 struct timeval start, stop, diff;
51 unsigned long long result_usec = 0; 83 unsigned long long result_usec = 0;
84 int nr_threads = 2;
85 int t;
52 86
53 /* 87 /*
54 * why does "ret" exist? 88 * why does "ret" exist?
@@ -58,43 +92,66 @@ int bench_sched_pipe(int argc, const char **argv,
58 int __maybe_unused ret, wait_stat; 92 int __maybe_unused ret, wait_stat;
59 pid_t pid, retpid __maybe_unused; 93 pid_t pid, retpid __maybe_unused;
60 94
61 argc = parse_options(argc, argv, options, 95 argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0);
62 bench_sched_pipe_usage, 0);
63 96
64 BUG_ON(pipe(pipe_1)); 97 BUG_ON(pipe(pipe_1));
65 BUG_ON(pipe(pipe_2)); 98 BUG_ON(pipe(pipe_2));
66 99
67 pid = fork();
68 assert(pid >= 0);
69
70 gettimeofday(&start, NULL); 100 gettimeofday(&start, NULL);
71 101
72 if (!pid) { 102 for (t = 0; t < nr_threads; t++) {
73 for (i = 0; i < loops; i++) { 103 td = threads + t;
74 ret = read(pipe_1[0], &m, sizeof(int)); 104
75 ret = write(pipe_2[1], &m, sizeof(int)); 105 td->nr = t;
76 } 106
77 } else { 107 if (t == 0) {
78 for (i = 0; i < loops; i++) { 108 td->pipe_read = pipe_1[0];
79 ret = write(pipe_1[1], &m, sizeof(int)); 109 td->pipe_write = pipe_2[1];
80 ret = read(pipe_2[0], &m, sizeof(int)); 110 } else {
111 td->pipe_write = pipe_1[1];
112 td->pipe_read = pipe_2[0];
81 } 113 }
82 } 114 }
83 115
84 gettimeofday(&stop, NULL);
85 timersub(&stop, &start, &diff);
86 116
87 if (pid) { 117 if (threaded) {
118
119 for (t = 0; t < nr_threads; t++) {
120 td = threads + t;
121
122 ret = pthread_create(&td->pthread, NULL, worker_thread, td);
123 BUG_ON(ret);
124 }
125
126 for (t = 0; t < nr_threads; t++) {
127 td = threads + t;
128
129 ret = pthread_join(td->pthread, NULL);
130 BUG_ON(ret);
131 }
132
133 } else {
134 pid = fork();
135 assert(pid >= 0);
136
137 if (!pid) {
138 worker_thread(threads + 0);
139 exit(0);
140 } else {
141 worker_thread(threads + 1);
142 }
143
88 retpid = waitpid(pid, &wait_stat, 0); 144 retpid = waitpid(pid, &wait_stat, 0);
89 assert((retpid == pid) && WIFEXITED(wait_stat)); 145 assert((retpid == pid) && WIFEXITED(wait_stat));
90 } else {
91 exit(0);
92 } 146 }
93 147
148 gettimeofday(&stop, NULL);
149 timersub(&stop, &start, &diff);
150
94 switch (bench_format) { 151 switch (bench_format) {
95 case BENCH_FORMAT_DEFAULT: 152 case BENCH_FORMAT_DEFAULT:
96 printf("# Executed %d pipe operations between two tasks\n\n", 153 printf("# Executed %d pipe operations between two %s\n\n",
97 loops); 154 loops, threaded ? "threads" : "processes");
98 155
99 result_usec = diff.tv_sec * 1000000; 156 result_usec = diff.tv_sec * 1000000;
100 result_usec += diff.tv_usec; 157 result_usec += diff.tv_usec;
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 5ebd0c3b71b6..4087ab19823c 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -28,8 +28,10 @@
28#include "util/hist.h" 28#include "util/hist.h"
29#include "util/session.h" 29#include "util/session.h"
30#include "util/tool.h" 30#include "util/tool.h"
31#include "util/data.h"
31#include "arch/common.h" 32#include "arch/common.h"
32 33
34#include <dlfcn.h>
33#include <linux/bitmap.h> 35#include <linux/bitmap.h>
34 36
35struct perf_annotate { 37struct perf_annotate {
@@ -63,7 +65,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
63 return 0; 65 return 0;
64 } 66 }
65 67
66 he = __hists__add_entry(&evsel->hists, al, NULL, 1, 1); 68 he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0);
67 if (he == NULL) 69 if (he == NULL)
68 return -ENOMEM; 70 return -ENOMEM;
69 71
@@ -116,11 +118,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
116 ann->print_line, ann->full_paths, 0, 0); 118 ann->print_line, ann->full_paths, 0, 0);
117} 119}
118 120
119static void hists__find_annotations(struct hists *self, 121static void hists__find_annotations(struct hists *hists,
120 struct perf_evsel *evsel, 122 struct perf_evsel *evsel,
121 struct perf_annotate *ann) 123 struct perf_annotate *ann)
122{ 124{
123 struct rb_node *nd = rb_first(&self->entries), *next; 125 struct rb_node *nd = rb_first(&hists->entries), *next;
124 int key = K_RIGHT; 126 int key = K_RIGHT;
125 127
126 while (nd) { 128 while (nd) {
@@ -142,8 +144,18 @@ find_next:
142 144
143 if (use_browser == 2) { 145 if (use_browser == 2) {
144 int ret; 146 int ret;
147 int (*annotate)(struct hist_entry *he,
148 struct perf_evsel *evsel,
149 struct hist_browser_timer *hbt);
150
151 annotate = dlsym(perf_gtk_handle,
152 "hist_entry__gtk_annotate");
153 if (annotate == NULL) {
154 ui__error("GTK browser not found!\n");
155 return;
156 }
145 157
146 ret = hist_entry__gtk_annotate(he, evsel, NULL); 158 ret = annotate(he, evsel, NULL);
147 if (!ret || !ann->skip_missing) 159 if (!ret || !ann->skip_missing)
148 return; 160 return;
149 161
@@ -188,9 +200,13 @@ static int __cmd_annotate(struct perf_annotate *ann)
188 struct perf_session *session; 200 struct perf_session *session;
189 struct perf_evsel *pos; 201 struct perf_evsel *pos;
190 u64 total_nr_samples; 202 u64 total_nr_samples;
203 struct perf_data_file file = {
204 .path = input_name,
205 .mode = PERF_DATA_MODE_READ,
206 .force = ann->force,
207 };
191 208
192 session = perf_session__new(input_name, O_RDONLY, 209 session = perf_session__new(&file, false, &ann->tool);
193 ann->force, false, &ann->tool);
194 if (session == NULL) 210 if (session == NULL)
195 return -ENOMEM; 211 return -ENOMEM;
196 212
@@ -231,7 +247,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
231 247
232 if (nr_samples > 0) { 248 if (nr_samples > 0) {
233 total_nr_samples += nr_samples; 249 total_nr_samples += nr_samples;
234 hists__collapse_resort(hists); 250 hists__collapse_resort(hists, NULL);
235 hists__output_resort(hists); 251 hists__output_resort(hists);
236 252
237 if (symbol_conf.event_group && 253 if (symbol_conf.event_group &&
@@ -243,12 +259,21 @@ static int __cmd_annotate(struct perf_annotate *ann)
243 } 259 }
244 260
245 if (total_nr_samples == 0) { 261 if (total_nr_samples == 0) {
246 ui__error("The %s file has no samples!\n", session->filename); 262 ui__error("The %s file has no samples!\n", file.path);
247 goto out_delete; 263 goto out_delete;
248 } 264 }
249 265
250 if (use_browser == 2) 266 if (use_browser == 2) {
251 perf_gtk__show_annotations(); 267 void (*show_annotations)(void);
268
269 show_annotations = dlsym(perf_gtk_handle,
270 "perf_gtk__show_annotations");
271 if (show_annotations == NULL) {
272 ui__error("GTK browser not found!\n");
273 goto out_delete;
274 }
275 show_annotations();
276 }
252 277
253out_delete: 278out_delete:
254 /* 279 /*
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 77298bf892b8..e47f90cc7b98 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -1,21 +1,18 @@
1/* 1/*
2 *
3 * builtin-bench.c 2 * builtin-bench.c
4 * 3 *
5 * General benchmarking subsystem provided by perf 4 * General benchmarking collections provided by perf
6 * 5 *
7 * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 6 * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
8 *
9 */ 7 */
10 8
11/* 9/*
10 * Available benchmark collection list:
12 * 11 *
13 * Available subsystem list: 12 * sched ... scheduler and IPC performance
14 * sched ... scheduler and IPC mechanism
15 * mem ... memory access performance 13 * mem ... memory access performance
16 * 14 * numa ... NUMA scheduling and MM performance
17 */ 15 */
18
19#include "perf.h" 16#include "perf.h"
20#include "util/util.h" 17#include "util/util.h"
21#include "util/parse-options.h" 18#include "util/parse-options.h"
@@ -25,112 +22,92 @@
25#include <stdio.h> 22#include <stdio.h>
26#include <stdlib.h> 23#include <stdlib.h>
27#include <string.h> 24#include <string.h>
25#include <sys/prctl.h>
28 26
29struct bench_suite { 27typedef int (*bench_fn_t)(int argc, const char **argv, const char *prefix);
30 const char *name; 28
31 const char *summary; 29struct bench {
32 int (*fn)(int, const char **, const char *); 30 const char *name;
31 const char *summary;
32 bench_fn_t fn;
33}; 33};
34 \ 34
35/* sentinel: easy for help */ 35#ifdef HAVE_LIBNUMA_SUPPORT
36#define suite_all { "all", "Test all benchmark suites", NULL } 36static struct bench numa_benchmarks[] = {
37 37 { "mem", "Benchmark for NUMA workloads", bench_numa },
38#ifdef LIBNUMA_SUPPORT 38 { "all", "Test all NUMA benchmarks", NULL },
39static struct bench_suite numa_suites[] = { 39 { NULL, NULL, NULL }
40 { "mem",
41 "Benchmark for NUMA workloads",
42 bench_numa },
43 suite_all,
44 { NULL,
45 NULL,
46 NULL }
47}; 40};
48#endif 41#endif
49 42
50static struct bench_suite sched_suites[] = { 43static struct bench sched_benchmarks[] = {
51 { "messaging", 44 { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging },
52 "Benchmark for scheduler and IPC mechanisms", 45 { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe },
53 bench_sched_messaging }, 46 { "all", "Test all scheduler benchmarks", NULL },
54 { "pipe", 47 { NULL, NULL, NULL }
55 "Flood of communication over pipe() between two processes",
56 bench_sched_pipe },
57 suite_all,
58 { NULL,
59 NULL,
60 NULL }
61}; 48};
62 49
63static struct bench_suite mem_suites[] = { 50static struct bench mem_benchmarks[] = {
64 { "memcpy", 51 { "memcpy", "Benchmark for memcpy()", bench_mem_memcpy },
65 "Simple memory copy in various ways", 52 { "memset", "Benchmark for memset() tests", bench_mem_memset },
66 bench_mem_memcpy }, 53 { "all", "Test all memory benchmarks", NULL },
67 { "memset", 54 { NULL, NULL, NULL }
68 "Simple memory set in various ways",
69 bench_mem_memset },
70 suite_all,
71 { NULL,
72 NULL,
73 NULL }
74}; 55};
75 56
76struct bench_subsys { 57struct collection {
77 const char *name; 58 const char *name;
78 const char *summary; 59 const char *summary;
79 struct bench_suite *suites; 60 struct bench *benchmarks;
80}; 61};
81 62
82static struct bench_subsys subsystems[] = { 63static struct collection collections[] = {
83#ifdef LIBNUMA_SUPPORT 64 { "sched", "Scheduler and IPC benchmarks", sched_benchmarks },
84 { "numa", 65 { "mem", "Memory access benchmarks", mem_benchmarks },
85 "NUMA scheduling and MM behavior", 66#ifdef HAVE_LIBNUMA_SUPPORT
86 numa_suites }, 67 { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks },
87#endif 68#endif
88 { "sched", 69 { "all", "All benchmarks", NULL },
89 "scheduler and IPC mechanism", 70 { NULL, NULL, NULL }
90 sched_suites },
91 { "mem",
92 "memory access performance",
93 mem_suites },
94 { "all", /* sentinel: easy for help */
95 "all benchmark subsystem",
96 NULL },
97 { NULL,
98 NULL,
99 NULL }
100}; 71};
101 72
102static void dump_suites(int subsys_index) 73/* Iterate over all benchmark collections: */
74#define for_each_collection(coll) \
75 for (coll = collections; coll->name; coll++)
76
77/* Iterate over all benchmarks within a collection: */
78#define for_each_bench(coll, bench) \
79 for (bench = coll->benchmarks; bench->name; bench++)
80
81static void dump_benchmarks(struct collection *coll)
103{ 82{
104 int i; 83 struct bench *bench;
105 84
106 printf("# List of available suites for %s...\n\n", 85 printf("\n # List of available benchmarks for collection '%s':\n\n", coll->name);
107 subsystems[subsys_index].name);
108 86
109 for (i = 0; subsystems[subsys_index].suites[i].name; i++) 87 for_each_bench(coll, bench)
110 printf("%14s: %s\n", 88 printf("%14s: %s\n", bench->name, bench->summary);
111 subsystems[subsys_index].suites[i].name,
112 subsystems[subsys_index].suites[i].summary);
113 89
114 printf("\n"); 90 printf("\n");
115 return;
116} 91}
117 92
118static const char *bench_format_str; 93static const char *bench_format_str;
94
95/* Output/formatting style, exported to benchmark modules: */
119int bench_format = BENCH_FORMAT_DEFAULT; 96int bench_format = BENCH_FORMAT_DEFAULT;
120 97
121static const struct option bench_options[] = { 98static const struct option bench_options[] = {
122 OPT_STRING('f', "format", &bench_format_str, "default", 99 OPT_STRING('f', "format", &bench_format_str, "default", "Specify format style"),
123 "Specify format style"),
124 OPT_END() 100 OPT_END()
125}; 101};
126 102
127static const char * const bench_usage[] = { 103static const char * const bench_usage[] = {
128 "perf bench [<common options>] <subsystem> <suite> [<options>]", 104 "perf bench [<common options>] <collection> <benchmark> [<options>]",
129 NULL 105 NULL
130}; 106};
131 107
132static void print_usage(void) 108static void print_usage(void)
133{ 109{
110 struct collection *coll;
134 int i; 111 int i;
135 112
136 printf("Usage: \n"); 113 printf("Usage: \n");
@@ -138,11 +115,10 @@ static void print_usage(void)
138 printf("\t%s\n", bench_usage[i]); 115 printf("\t%s\n", bench_usage[i]);
139 printf("\n"); 116 printf("\n");
140 117
141 printf("# List of available subsystems...\n\n"); 118 printf(" # List of all available benchmark collections:\n\n");
142 119
143 for (i = 0; subsystems[i].name; i++) 120 for_each_collection(coll)
144 printf("%14s: %s\n", 121 printf("%14s: %s\n", coll->name, coll->summary);
145 subsystems[i].name, subsystems[i].summary);
146 printf("\n"); 122 printf("\n");
147} 123}
148 124
@@ -159,44 +135,74 @@ static int bench_str2int(const char *str)
159 return BENCH_FORMAT_UNKNOWN; 135 return BENCH_FORMAT_UNKNOWN;
160} 136}
161 137
162static void all_suite(struct bench_subsys *subsys) /* FROM HERE */ 138/*
139 * Run a specific benchmark but first rename the running task's ->comm[]
140 * to something meaningful:
141 */
142static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn,
143 int argc, const char **argv, const char *prefix)
163{ 144{
164 int i; 145 int size;
146 char *name;
147 int ret;
148
149 size = strlen(coll_name) + 1 + strlen(bench_name) + 1;
150
151 name = zalloc(size);
152 BUG_ON(!name);
153
154 scnprintf(name, size, "%s-%s", coll_name, bench_name);
155
156 prctl(PR_SET_NAME, name);
157 argv[0] = name;
158
159 ret = fn(argc, argv, prefix);
160
161 free(name);
162
163 return ret;
164}
165
166static void run_collection(struct collection *coll)
167{
168 struct bench *bench;
165 const char *argv[2]; 169 const char *argv[2];
166 struct bench_suite *suites = subsys->suites;
167 170
168 argv[1] = NULL; 171 argv[1] = NULL;
169 /* 172 /*
170 * TODO: 173 * TODO:
171 * preparing preset parameters for 174 *
175 * Preparing preset parameters for
172 * embedded, ordinary PC, HPC, etc... 176 * embedded, ordinary PC, HPC, etc...
173 * will be helpful 177 * would be helpful.
174 */ 178 */
175 for (i = 0; suites[i].fn; i++) { 179 for_each_bench(coll, bench) {
176 printf("# Running %s/%s benchmark...\n", 180 if (!bench->fn)
177 subsys->name, 181 break;
178 suites[i].name); 182 printf("# Running %s/%s benchmark...\n", coll->name, bench->name);
179 fflush(stdout); 183 fflush(stdout);
180 184
181 argv[1] = suites[i].name; 185 argv[1] = bench->name;
182 suites[i].fn(1, argv, NULL); 186 run_bench(coll->name, bench->name, bench->fn, 1, argv, NULL);
183 printf("\n"); 187 printf("\n");
184 } 188 }
185} 189}
186 190
187static void all_subsystem(void) 191static void run_all_collections(void)
188{ 192{
189 int i; 193 struct collection *coll;
190 for (i = 0; subsystems[i].suites; i++) 194
191 all_suite(&subsystems[i]); 195 for_each_collection(coll)
196 run_collection(coll);
192} 197}
193 198
194int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) 199int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
195{ 200{
196 int i, j, status = 0; 201 struct collection *coll;
202 int ret = 0;
197 203
198 if (argc < 2) { 204 if (argc < 2) {
199 /* No subsystem specified. */ 205 /* No collection specified. */
200 print_usage(); 206 print_usage();
201 goto end; 207 goto end;
202 } 208 }
@@ -206,7 +212,7 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
206 212
207 bench_format = bench_str2int(bench_format_str); 213 bench_format = bench_str2int(bench_format_str);
208 if (bench_format == BENCH_FORMAT_UNKNOWN) { 214 if (bench_format == BENCH_FORMAT_UNKNOWN) {
209 printf("Unknown format descriptor:%s\n", bench_format_str); 215 printf("Unknown format descriptor: '%s'\n", bench_format_str);
210 goto end; 216 goto end;
211 } 217 }
212 218
@@ -216,52 +222,51 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
216 } 222 }
217 223
218 if (!strcmp(argv[0], "all")) { 224 if (!strcmp(argv[0], "all")) {
219 all_subsystem(); 225 run_all_collections();
220 goto end; 226 goto end;
221 } 227 }
222 228
223 for (i = 0; subsystems[i].name; i++) { 229 for_each_collection(coll) {
224 if (strcmp(subsystems[i].name, argv[0])) 230 struct bench *bench;
231
232 if (strcmp(coll->name, argv[0]))
225 continue; 233 continue;
226 234
227 if (argc < 2) { 235 if (argc < 2) {
228 /* No suite specified. */ 236 /* No bench specified. */
229 dump_suites(i); 237 dump_benchmarks(coll);
230 goto end; 238 goto end;
231 } 239 }
232 240
233 if (!strcmp(argv[1], "all")) { 241 if (!strcmp(argv[1], "all")) {
234 all_suite(&subsystems[i]); 242 run_collection(coll);
235 goto end; 243 goto end;
236 } 244 }
237 245
238 for (j = 0; subsystems[i].suites[j].name; j++) { 246 for_each_bench(coll, bench) {
239 if (strcmp(subsystems[i].suites[j].name, argv[1])) 247 if (strcmp(bench->name, argv[1]))
240 continue; 248 continue;
241 249
242 if (bench_format == BENCH_FORMAT_DEFAULT) 250 if (bench_format == BENCH_FORMAT_DEFAULT)
243 printf("# Running %s/%s benchmark...\n", 251 printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name);
244 subsystems[i].name,
245 subsystems[i].suites[j].name);
246 fflush(stdout); 252 fflush(stdout);
247 status = subsystems[i].suites[j].fn(argc - 1, 253 ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1, prefix);
248 argv + 1, prefix);
249 goto end; 254 goto end;
250 } 255 }
251 256
252 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 257 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
253 dump_suites(i); 258 dump_benchmarks(coll);
254 goto end; 259 goto end;
255 } 260 }
256 261
257 printf("Unknown suite:%s for %s\n", argv[1], argv[0]); 262 printf("Unknown benchmark: '%s' for collection '%s'\n", argv[1], argv[0]);
258 status = 1; 263 ret = 1;
259 goto end; 264 goto end;
260 } 265 }
261 266
262 printf("Unknown subsystem:%s\n", argv[0]); 267 printf("Unknown collection: '%s'\n", argv[0]);
263 status = 1; 268 ret = 1;
264 269
265end: 270end:
266 return status; 271 return ret;
267} 272}
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index c96c8fa38243..cfede86161d8 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -6,6 +6,11 @@
6 * Copyright (C) 2010, Red Hat Inc. 6 * Copyright (C) 2010, Red Hat Inc.
7 * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com> 7 * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
8 */ 8 */
9#include <sys/types.h>
10#include <sys/time.h>
11#include <time.h>
12#include <dirent.h>
13#include <unistd.h>
9#include "builtin.h" 14#include "builtin.h"
10#include "perf.h" 15#include "perf.h"
11#include "util/cache.h" 16#include "util/cache.h"
@@ -17,6 +22,140 @@
17#include "util/session.h" 22#include "util/session.h"
18#include "util/symbol.h" 23#include "util/symbol.h"
19 24
25static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
26{
27 char root_dir[PATH_MAX];
28 char notes[PATH_MAX];
29 u8 build_id[BUILD_ID_SIZE];
30 char *p;
31
32 strlcpy(root_dir, proc_dir, sizeof(root_dir));
33
34 p = strrchr(root_dir, '/');
35 if (!p)
36 return -1;
37 *p = '\0';
38
39 scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir);
40
41 if (sysfs__read_build_id(notes, build_id, sizeof(build_id)))
42 return -1;
43
44 build_id__sprintf(build_id, sizeof(build_id), sbuildid);
45
46 return 0;
47}
48
49static int build_id_cache__kcore_dir(char *dir, size_t sz)
50{
51 struct timeval tv;
52 struct tm tm;
53 char dt[32];
54
55 if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
56 return -1;
57
58 if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
59 return -1;
60
61 scnprintf(dir, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
62
63 return 0;
64}
65
66static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
67 size_t to_dir_sz)
68{
69 char from[PATH_MAX];
70 char to[PATH_MAX];
71 struct dirent *dent;
72 int ret = -1;
73 DIR *d;
74
75 d = opendir(to_dir);
76 if (!d)
77 return -1;
78
79 scnprintf(from, sizeof(from), "%s/modules", from_dir);
80
81 while (1) {
82 dent = readdir(d);
83 if (!dent)
84 break;
85 if (dent->d_type != DT_DIR)
86 continue;
87 scnprintf(to, sizeof(to), "%s/%s/modules", to_dir,
88 dent->d_name);
89 if (!compare_proc_modules(from, to)) {
90 scnprintf(to, sizeof(to), "%s/%s", to_dir,
91 dent->d_name);
92 strlcpy(to_dir, to, to_dir_sz);
93 ret = 0;
94 break;
95 }
96 }
97
98 closedir(d);
99
100 return ret;
101}
102
103static int build_id_cache__add_kcore(const char *filename, const char *debugdir)
104{
105 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
106 char from_dir[PATH_MAX], to_dir[PATH_MAX];
107 char *p;
108
109 strlcpy(from_dir, filename, sizeof(from_dir));
110
111 p = strrchr(from_dir, '/');
112 if (!p || strcmp(p + 1, "kcore"))
113 return -1;
114 *p = '\0';
115
116 if (build_id_cache__kcore_buildid(from_dir, sbuildid))
117 return -1;
118
119 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
120 debugdir, sbuildid);
121
122 if (!build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
123 pr_debug("same kcore found in %s\n", to_dir);
124 return 0;
125 }
126
127 if (build_id_cache__kcore_dir(dir, sizeof(dir)))
128 return -1;
129
130 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
131 debugdir, sbuildid, dir);
132
133 if (mkdir_p(to_dir, 0755))
134 return -1;
135
136 if (kcore_copy(from_dir, to_dir)) {
137 /* Remove YYYYmmddHHMMSShh directory */
138 if (!rmdir(to_dir)) {
139 p = strrchr(to_dir, '/');
140 if (p)
141 *p = '\0';
142 /* Try to remove buildid directory */
143 if (!rmdir(to_dir)) {
144 p = strrchr(to_dir, '/');
145 if (p)
146 *p = '\0';
147 /* Try to remove [kernel.kcore] directory */
148 rmdir(to_dir);
149 }
150 }
151 return -1;
152 }
153
154 pr_debug("kcore added to build-id cache directory %s\n", to_dir);
155
156 return 0;
157}
158
20static int build_id_cache__add_file(const char *filename, const char *debugdir) 159static int build_id_cache__add_file(const char *filename, const char *debugdir)
21{ 160{
22 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 161 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -82,8 +221,12 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
82 221
83static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) 222static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp)
84{ 223{
85 struct perf_session *session = perf_session__new(filename, O_RDONLY, 224 struct perf_data_file file = {
86 force, false, NULL); 225 .path = filename,
226 .mode = PERF_DATA_MODE_READ,
227 .force = force,
228 };
229 struct perf_session *session = perf_session__new(&file, false, NULL);
87 if (session == NULL) 230 if (session == NULL)
88 return -1; 231 return -1;
89 232
@@ -130,11 +273,14 @@ int cmd_buildid_cache(int argc, const char **argv,
130 char const *add_name_list_str = NULL, 273 char const *add_name_list_str = NULL,
131 *remove_name_list_str = NULL, 274 *remove_name_list_str = NULL,
132 *missing_filename = NULL, 275 *missing_filename = NULL,
133 *update_name_list_str = NULL; 276 *update_name_list_str = NULL,
277 *kcore_filename;
134 278
135 const struct option buildid_cache_options[] = { 279 const struct option buildid_cache_options[] = {
136 OPT_STRING('a', "add", &add_name_list_str, 280 OPT_STRING('a', "add", &add_name_list_str,
137 "file list", "file(s) to add"), 281 "file list", "file(s) to add"),
282 OPT_STRING('k', "kcore", &kcore_filename,
283 "file", "kcore file to add"),
138 OPT_STRING('r', "remove", &remove_name_list_str, "file list", 284 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
139 "file(s) to remove"), 285 "file(s) to remove"),
140 OPT_STRING('M', "missing", &missing_filename, "file", 286 OPT_STRING('M', "missing", &missing_filename, "file",
@@ -217,5 +363,9 @@ int cmd_buildid_cache(int argc, const char **argv,
217 } 363 }
218 } 364 }
219 365
366 if (kcore_filename &&
367 build_id_cache__add_kcore(kcore_filename, debugdir))
368 pr_warning("Couldn't add %s\n", kcore_filename);
369
220 return ret; 370 return ret;
221} 371}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index e74366a13218..ed3873b3e238 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -15,6 +15,7 @@
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16#include "util/session.h" 16#include "util/session.h"
17#include "util/symbol.h" 17#include "util/symbol.h"
18#include "util/data.h"
18 19
19static int sysfs__fprintf_build_id(FILE *fp) 20static int sysfs__fprintf_build_id(FILE *fp)
20{ 21{
@@ -52,6 +53,11 @@ static bool dso__skip_buildid(struct dso *dso, int with_hits)
52static int perf_session__list_build_ids(bool force, bool with_hits) 53static int perf_session__list_build_ids(bool force, bool with_hits)
53{ 54{
54 struct perf_session *session; 55 struct perf_session *session;
56 struct perf_data_file file = {
57 .path = input_name,
58 .mode = PERF_DATA_MODE_READ,
59 .force = force,
60 };
55 61
56 symbol__elf_init(); 62 symbol__elf_init();
57 /* 63 /*
@@ -60,15 +66,14 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
60 if (filename__fprintf_build_id(input_name, stdout)) 66 if (filename__fprintf_build_id(input_name, stdout))
61 goto out; 67 goto out;
62 68
63 session = perf_session__new(input_name, O_RDONLY, force, false, 69 session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops);
64 &build_id__mark_dso_hit_ops);
65 if (session == NULL) 70 if (session == NULL)
66 return -1; 71 return -1;
67 /* 72 /*
68 * in pipe-mode, the only way to get the buildids is to parse 73 * in pipe-mode, the only way to get the buildids is to parse
69 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID 74 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
70 */ 75 */
71 if (with_hits || session->fd_pipe) 76 if (with_hits || perf_data_file__is_pipe(&file))
72 perf_session__process_events(session, &build_id__mark_dso_hit_ops); 77 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
73 78
74 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); 79 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index f28799e94f2a..3b67ea2444bd 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -16,6 +16,7 @@
16#include "util/sort.h" 16#include "util/sort.h"
17#include "util/symbol.h" 17#include "util/symbol.h"
18#include "util/util.h" 18#include "util/util.h"
19#include "util/data.h"
19 20
20#include <stdlib.h> 21#include <stdlib.h>
21#include <math.h> 22#include <math.h>
@@ -42,7 +43,7 @@ struct diff_hpp_fmt {
42 43
43struct data__file { 44struct data__file {
44 struct perf_session *session; 45 struct perf_session *session;
45 const char *file; 46 struct perf_data_file file;
46 int idx; 47 int idx;
47 struct hists *hists; 48 struct hists *hists;
48 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; 49 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX];
@@ -302,11 +303,12 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
302 return -1; 303 return -1;
303} 304}
304 305
305static int hists__add_entry(struct hists *self, 306static int hists__add_entry(struct hists *hists,
306 struct addr_location *al, u64 period, 307 struct addr_location *al, u64 period,
307 u64 weight) 308 u64 weight, u64 transaction)
308{ 309{
309 if (__hists__add_entry(self, al, NULL, period, weight) != NULL) 310 if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight,
311 transaction) != NULL)
310 return 0; 312 return 0;
311 return -ENOMEM; 313 return -ENOMEM;
312} 314}
@@ -328,7 +330,8 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
328 if (al.filtered) 330 if (al.filtered)
329 return 0; 331 return 0;
330 332
331 if (hists__add_entry(&evsel->hists, &al, sample->period, sample->weight)) { 333 if (hists__add_entry(&evsel->hists, &al, sample->period,
334 sample->weight, sample->transaction)) {
332 pr_warning("problem incrementing symbol period, skipping event\n"); 335 pr_warning("problem incrementing symbol period, skipping event\n");
333 return -1; 336 return -1;
334 } 337 }
@@ -367,7 +370,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
367 list_for_each_entry(evsel, &evlist->entries, node) { 370 list_for_each_entry(evsel, &evlist->entries, node) {
368 struct hists *hists = &evsel->hists; 371 struct hists *hists = &evsel->hists;
369 372
370 hists__collapse_resort(hists); 373 hists__collapse_resort(hists, NULL);
371 } 374 }
372} 375}
373 376
@@ -599,7 +602,7 @@ static void data__fprintf(void)
599 602
600 data__for_each_file(i, d) 603 data__for_each_file(i, d)
601 fprintf(stdout, "# [%d] %s %s\n", 604 fprintf(stdout, "# [%d] %s %s\n",
602 d->idx, d->file, 605 d->idx, d->file.path,
603 !d->idx ? "(Baseline)" : ""); 606 !d->idx ? "(Baseline)" : "");
604 607
605 fprintf(stdout, "#\n"); 608 fprintf(stdout, "#\n");
@@ -661,17 +664,16 @@ static int __cmd_diff(void)
661 int ret = -EINVAL, i; 664 int ret = -EINVAL, i;
662 665
663 data__for_each_file(i, d) { 666 data__for_each_file(i, d) {
664 d->session = perf_session__new(d->file, O_RDONLY, force, 667 d->session = perf_session__new(&d->file, false, &tool);
665 false, &tool);
666 if (!d->session) { 668 if (!d->session) {
667 pr_err("Failed to open %s\n", d->file); 669 pr_err("Failed to open %s\n", d->file.path);
668 ret = -ENOMEM; 670 ret = -ENOMEM;
669 goto out_delete; 671 goto out_delete;
670 } 672 }
671 673
672 ret = perf_session__process_events(d->session, &tool); 674 ret = perf_session__process_events(d->session, &tool);
673 if (ret) { 675 if (ret) {
674 pr_err("Failed to process %s\n", d->file); 676 pr_err("Failed to process %s\n", d->file.path);
675 goto out_delete; 677 goto out_delete;
676 } 678 }
677 679
@@ -1014,7 +1016,12 @@ static int data_init(int argc, const char **argv)
1014 return -ENOMEM; 1016 return -ENOMEM;
1015 1017
1016 data__for_each_file(i, d) { 1018 data__for_each_file(i, d) {
1017 d->file = use_default ? defaults[i] : argv[i]; 1019 struct perf_data_file *file = &d->file;
1020
1021 file->path = use_default ? defaults[i] : argv[i];
1022 file->mode = PERF_DATA_MODE_READ,
1023 file->force = force,
1024
1018 d->idx = i; 1025 d->idx = i;
1019 } 1026 }
1020 1027
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 05bd9dfe875c..20b0f12763b0 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -14,13 +14,18 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16#include "util/session.h" 16#include "util/session.h"
17#include "util/data.h"
17 18
18static int __cmd_evlist(const char *file_name, struct perf_attr_details *details) 19static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
19{ 20{
20 struct perf_session *session; 21 struct perf_session *session;
21 struct perf_evsel *pos; 22 struct perf_evsel *pos;
23 struct perf_data_file file = {
24 .path = file_name,
25 .mode = PERF_DATA_MODE_READ,
26 };
22 27
23 session = perf_session__new(file_name, O_RDONLY, 0, false, NULL); 28 session = perf_session__new(&file, 0, NULL);
24 if (session == NULL) 29 if (session == NULL)
25 return -ENOMEM; 30 return -ENOMEM;
26 31
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index afe377b2884f..6a2508589460 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -15,6 +15,7 @@
15#include "util/tool.h" 15#include "util/tool.h"
16#include "util/debug.h" 16#include "util/debug.h"
17#include "util/build-id.h" 17#include "util/build-id.h"
18#include "util/data.h"
18 19
19#include "util/parse-options.h" 20#include "util/parse-options.h"
20 21
@@ -71,12 +72,17 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
71 union perf_event *event, 72 union perf_event *event,
72 struct perf_evlist **pevlist) 73 struct perf_evlist **pevlist)
73{ 74{
75 struct perf_inject *inject = container_of(tool, struct perf_inject,
76 tool);
74 int ret; 77 int ret;
75 78
76 ret = perf_event__process_attr(tool, event, pevlist); 79 ret = perf_event__process_attr(tool, event, pevlist);
77 if (ret) 80 if (ret)
78 return ret; 81 return ret;
79 82
83 if (!inject->pipe_output)
84 return 0;
85
80 return perf_event__repipe_synth(tool, event); 86 return perf_event__repipe_synth(tool, event);
81} 87}
82 88
@@ -100,8 +106,8 @@ static int perf_event__repipe_sample(struct perf_tool *tool,
100 struct perf_evsel *evsel, 106 struct perf_evsel *evsel,
101 struct machine *machine) 107 struct machine *machine)
102{ 108{
103 if (evsel->handler.func) { 109 if (evsel->handler) {
104 inject_handler f = evsel->handler.func; 110 inject_handler f = evsel->handler;
105 return f(tool, event, sample, evsel, machine); 111 return f(tool, event, sample, evsel, machine);
106 } 112 }
107 113
@@ -161,38 +167,38 @@ static int perf_event__repipe_tracing_data(struct perf_tool *tool,
161 return err; 167 return err;
162} 168}
163 169
164static int dso__read_build_id(struct dso *self) 170static int dso__read_build_id(struct dso *dso)
165{ 171{
166 if (self->has_build_id) 172 if (dso->has_build_id)
167 return 0; 173 return 0;
168 174
169 if (filename__read_build_id(self->long_name, self->build_id, 175 if (filename__read_build_id(dso->long_name, dso->build_id,
170 sizeof(self->build_id)) > 0) { 176 sizeof(dso->build_id)) > 0) {
171 self->has_build_id = true; 177 dso->has_build_id = true;
172 return 0; 178 return 0;
173 } 179 }
174 180
175 return -1; 181 return -1;
176} 182}
177 183
178static int dso__inject_build_id(struct dso *self, struct perf_tool *tool, 184static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool,
179 struct machine *machine) 185 struct machine *machine)
180{ 186{
181 u16 misc = PERF_RECORD_MISC_USER; 187 u16 misc = PERF_RECORD_MISC_USER;
182 int err; 188 int err;
183 189
184 if (dso__read_build_id(self) < 0) { 190 if (dso__read_build_id(dso) < 0) {
185 pr_debug("no build_id found for %s\n", self->long_name); 191 pr_debug("no build_id found for %s\n", dso->long_name);
186 return -1; 192 return -1;
187 } 193 }
188 194
189 if (self->kernel) 195 if (dso->kernel)
190 misc = PERF_RECORD_MISC_KERNEL; 196 misc = PERF_RECORD_MISC_KERNEL;
191 197
192 err = perf_event__synthesize_build_id(tool, self, misc, perf_event__repipe, 198 err = perf_event__synthesize_build_id(tool, dso, misc, perf_event__repipe,
193 machine); 199 machine);
194 if (err) { 200 if (err) {
195 pr_err("Can't synthesize build_id event for %s\n", self->long_name); 201 pr_err("Can't synthesize build_id event for %s\n", dso->long_name);
196 return -1; 202 return -1;
197 } 203 }
198 204
@@ -231,7 +237,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
231 * account this as unresolved. 237 * account this as unresolved.
232 */ 238 */
233 } else { 239 } else {
234#ifdef LIBELF_SUPPORT 240#ifdef HAVE_LIBELF_SUPPORT
235 pr_warning("no symbols found in %s, maybe " 241 pr_warning("no symbols found in %s, maybe "
236 "install a debug package?\n", 242 "install a debug package?\n",
237 al.map->dso->long_name); 243 al.map->dso->long_name);
@@ -345,6 +351,10 @@ static int __cmd_inject(struct perf_inject *inject)
345{ 351{
346 struct perf_session *session; 352 struct perf_session *session;
347 int ret = -EINVAL; 353 int ret = -EINVAL;
354 struct perf_data_file file = {
355 .path = inject->input_name,
356 .mode = PERF_DATA_MODE_READ,
357 };
348 358
349 signal(SIGINT, sig_handler); 359 signal(SIGINT, sig_handler);
350 360
@@ -355,7 +365,7 @@ static int __cmd_inject(struct perf_inject *inject)
355 inject->tool.tracing_data = perf_event__repipe_tracing_data; 365 inject->tool.tracing_data = perf_event__repipe_tracing_data;
356 } 366 }
357 367
358 session = perf_session__new(inject->input_name, O_RDONLY, false, true, &inject->tool); 368 session = perf_session__new(&file, true, &inject->tool);
359 if (session == NULL) 369 if (session == NULL)
360 return -ENOMEM; 370 return -ENOMEM;
361 371
@@ -373,11 +383,11 @@ static int __cmd_inject(struct perf_inject *inject)
373 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID")) 383 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID"))
374 return -EINVAL; 384 return -EINVAL;
375 385
376 evsel->handler.func = perf_inject__sched_switch; 386 evsel->handler = perf_inject__sched_switch;
377 } else if (!strcmp(name, "sched:sched_process_exit")) 387 } else if (!strcmp(name, "sched:sched_process_exit"))
378 evsel->handler.func = perf_inject__sched_process_exit; 388 evsel->handler = perf_inject__sched_process_exit;
379 else if (!strncmp(name, "sched:sched_stat_", 17)) 389 else if (!strncmp(name, "sched:sched_stat_", 17))
380 evsel->handler.func = perf_inject__sched_stat; 390 evsel->handler = perf_inject__sched_stat;
381 } 391 }
382 } 392 }
383 393
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 9b5f077fee5b..929462aa4943 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -13,6 +13,7 @@
13 13
14#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/trace-event.h" 15#include "util/trace-event.h"
16#include "util/data.h"
16 17
17#include "util/debug.h" 18#include "util/debug.h"
18 19
@@ -314,10 +315,10 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
314 return -1; 315 return -1;
315 } 316 }
316 317
317 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid); 318 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
318 319
319 if (evsel->handler.func != NULL) { 320 if (evsel->handler != NULL) {
320 tracepoint_handler f = evsel->handler.func; 321 tracepoint_handler f = evsel->handler;
321 return f(evsel, sample); 322 return f(evsel, sample);
322 } 323 }
323 324
@@ -486,8 +487,12 @@ static int __cmd_kmem(void)
486 { "kmem:kfree", perf_evsel__process_free_event, }, 487 { "kmem:kfree", perf_evsel__process_free_event, },
487 { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, 488 { "kmem:kmem_cache_free", perf_evsel__process_free_event, },
488 }; 489 };
490 struct perf_data_file file = {
491 .path = input_name,
492 .mode = PERF_DATA_MODE_READ,
493 };
489 494
490 session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_kmem); 495 session = perf_session__new(&file, false, &perf_kmem);
491 if (session == NULL) 496 if (session == NULL)
492 return -ENOMEM; 497 return -ENOMEM;
493 498
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 935d52216c89..cd9f92078aba 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -17,9 +17,12 @@
17#include "util/tool.h" 17#include "util/tool.h"
18#include "util/stat.h" 18#include "util/stat.h"
19#include "util/top.h" 19#include "util/top.h"
20#include "util/data.h"
20 21
21#include <sys/prctl.h> 22#include <sys/prctl.h>
23#ifdef HAVE_TIMERFD_SUPPORT
22#include <sys/timerfd.h> 24#include <sys/timerfd.h>
25#endif
23 26
24#include <termios.h> 27#include <termios.h>
25#include <semaphore.h> 28#include <semaphore.h>
@@ -336,6 +339,7 @@ static void init_kvm_event_record(struct perf_kvm_stat *kvm)
336 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]); 339 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
337} 340}
338 341
342#ifdef HAVE_TIMERFD_SUPPORT
339static void clear_events_cache_stats(struct list_head *kvm_events_cache) 343static void clear_events_cache_stats(struct list_head *kvm_events_cache)
340{ 344{
341 struct list_head *head; 345 struct list_head *head;
@@ -357,6 +361,7 @@ static void clear_events_cache_stats(struct list_head *kvm_events_cache)
357 } 361 }
358 } 362 }
359} 363}
364#endif
360 365
361static int kvm_events_hash_fn(u64 key) 366static int kvm_events_hash_fn(u64 key)
362{ 367{
@@ -782,6 +787,7 @@ static void print_result(struct perf_kvm_stat *kvm)
782 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events); 787 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
783} 788}
784 789
790#ifdef HAVE_TIMERFD_SUPPORT
785static int process_lost_event(struct perf_tool *tool, 791static int process_lost_event(struct perf_tool *tool,
786 union perf_event *event __maybe_unused, 792 union perf_event *event __maybe_unused,
787 struct perf_sample *sample __maybe_unused, 793 struct perf_sample *sample __maybe_unused,
@@ -792,6 +798,7 @@ static int process_lost_event(struct perf_tool *tool,
792 kvm->lost_events++; 798 kvm->lost_events++;
793 return 0; 799 return 0;
794} 800}
801#endif
795 802
796static bool skip_sample(struct perf_kvm_stat *kvm, 803static bool skip_sample(struct perf_kvm_stat *kvm,
797 struct perf_sample *sample) 804 struct perf_sample *sample)
@@ -871,6 +878,7 @@ static bool verify_vcpu(int vcpu)
871 return true; 878 return true;
872} 879}
873 880
881#ifdef HAVE_TIMERFD_SUPPORT
874/* keeping the max events to a modest level to keep 882/* keeping the max events to a modest level to keep
875 * the processing of samples per mmap smooth. 883 * the processing of samples per mmap smooth.
876 */ 884 */
@@ -888,11 +896,18 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
888 while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) { 896 while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
889 err = perf_evlist__parse_sample(kvm->evlist, event, &sample); 897 err = perf_evlist__parse_sample(kvm->evlist, event, &sample);
890 if (err) { 898 if (err) {
899 perf_evlist__mmap_consume(kvm->evlist, idx);
891 pr_err("Failed to parse sample\n"); 900 pr_err("Failed to parse sample\n");
892 return -1; 901 return -1;
893 } 902 }
894 903
895 err = perf_session_queue_event(kvm->session, event, &sample, 0); 904 err = perf_session_queue_event(kvm->session, event, &sample, 0);
905 /*
906 * FIXME: Here we can't consume the event, as perf_session_queue_event will
907 * point to it, and it'll get possibly overwritten by the kernel.
908 */
909 perf_evlist__mmap_consume(kvm->evlist, idx);
910
896 if (err) { 911 if (err) {
897 pr_err("Failed to enqueue sample: %d\n", err); 912 pr_err("Failed to enqueue sample: %d\n", err);
898 return -1; 913 return -1;
@@ -1205,6 +1220,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1205out: 1220out:
1206 return rc; 1221 return rc;
1207} 1222}
1223#endif
1208 1224
1209static int read_events(struct perf_kvm_stat *kvm) 1225static int read_events(struct perf_kvm_stat *kvm)
1210{ 1226{
@@ -1215,10 +1231,13 @@ static int read_events(struct perf_kvm_stat *kvm)
1215 .comm = perf_event__process_comm, 1231 .comm = perf_event__process_comm,
1216 .ordered_samples = true, 1232 .ordered_samples = true,
1217 }; 1233 };
1234 struct perf_data_file file = {
1235 .path = input_name,
1236 .mode = PERF_DATA_MODE_READ,
1237 };
1218 1238
1219 kvm->tool = eops; 1239 kvm->tool = eops;
1220 kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false, 1240 kvm->session = perf_session__new(&file, false, &kvm->tool);
1221 &kvm->tool);
1222 if (!kvm->session) { 1241 if (!kvm->session) {
1223 pr_err("Initializing perf session failed\n"); 1242 pr_err("Initializing perf session failed\n");
1224 return -EINVAL; 1243 return -EINVAL;
@@ -1368,6 +1387,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1368 return kvm_events_report_vcpu(kvm); 1387 return kvm_events_report_vcpu(kvm);
1369} 1388}
1370 1389
1390#ifdef HAVE_TIMERFD_SUPPORT
1371static struct perf_evlist *kvm_live_event_list(void) 1391static struct perf_evlist *kvm_live_event_list(void)
1372{ 1392{
1373 struct perf_evlist *evlist; 1393 struct perf_evlist *evlist;
@@ -1426,8 +1446,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1426 const struct option live_options[] = { 1446 const struct option live_options[] = {
1427 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", 1447 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1428 "record events on existing process id"), 1448 "record events on existing process id"),
1429 OPT_UINTEGER('m', "mmap-pages", &kvm->opts.mmap_pages, 1449 OPT_CALLBACK('m', "mmap-pages", &kvm->opts.mmap_pages, "pages",
1430 "number of mmap data pages"), 1450 "number of mmap data pages",
1451 perf_evlist__parse_mmap_pages),
1431 OPT_INCR('v', "verbose", &verbose, 1452 OPT_INCR('v', "verbose", &verbose,
1432 "be more verbose (show counter open errors, etc)"), 1453 "be more verbose (show counter open errors, etc)"),
1433 OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide, 1454 OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide,
@@ -1449,6 +1470,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1449 "perf kvm stat live [<options>]", 1470 "perf kvm stat live [<options>]",
1450 NULL 1471 NULL
1451 }; 1472 };
1473 struct perf_data_file file = {
1474 .mode = PERF_DATA_MODE_WRITE,
1475 };
1452 1476
1453 1477
1454 /* event handling */ 1478 /* event handling */
@@ -1513,7 +1537,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1513 /* 1537 /*
1514 * perf session 1538 * perf session
1515 */ 1539 */
1516 kvm->session = perf_session__new(NULL, O_WRONLY, false, false, &kvm->tool); 1540 kvm->session = perf_session__new(&file, false, &kvm->tool);
1517 if (kvm->session == NULL) { 1541 if (kvm->session == NULL) {
1518 err = -ENOMEM; 1542 err = -ENOMEM;
1519 goto out; 1543 goto out;
@@ -1551,6 +1575,7 @@ out:
1551 1575
1552 return err; 1576 return err;
1553} 1577}
1578#endif
1554 1579
1555static void print_kvm_stat_usage(void) 1580static void print_kvm_stat_usage(void)
1556{ 1581{
@@ -1589,8 +1614,10 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
1589 if (!strncmp(argv[1], "rep", 3)) 1614 if (!strncmp(argv[1], "rep", 3))
1590 return kvm_events_report(&kvm, argc - 1 , argv + 1); 1615 return kvm_events_report(&kvm, argc - 1 , argv + 1);
1591 1616
1617#ifdef HAVE_TIMERFD_SUPPORT
1592 if (!strncmp(argv[1], "live", 4)) 1618 if (!strncmp(argv[1], "live", 4))
1593 return kvm_events_live(&kvm, argc - 1 , argv + 1); 1619 return kvm_events_live(&kvm, argc - 1 , argv + 1);
1620#endif
1594 1621
1595perf_stat: 1622perf_stat:
1596 return cmd_stat(argc, argv, NULL); 1623 return cmd_stat(argc, argv, NULL);
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index e79f423cc302..011195e38f21 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -14,51 +14,63 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/cache.h" 15#include "util/cache.h"
16#include "util/pmu.h" 16#include "util/pmu.h"
17#include "util/parse-options.h"
17 18
18int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
19{ 20{
21 int i;
22 const struct option list_options[] = {
23 OPT_END()
24 };
25 const char * const list_usage[] = {
26 "perf list [hw|sw|cache|tracepoint|pmu|event_glob]",
27 NULL
28 };
29
30 argc = parse_options(argc, argv, list_options, list_usage,
31 PARSE_OPT_STOP_AT_NON_OPTION);
32
20 setup_pager(); 33 setup_pager();
21 34
22 if (argc == 1) 35 if (argc == 0) {
23 print_events(NULL, false); 36 print_events(NULL, false);
24 else { 37 return 0;
25 int i; 38 }
26
27 for (i = 1; i < argc; ++i) {
28 if (i > 2)
29 putchar('\n');
30 if (strncmp(argv[i], "tracepoint", 10) == 0)
31 print_tracepoint_events(NULL, NULL, false);
32 else if (strcmp(argv[i], "hw") == 0 ||
33 strcmp(argv[i], "hardware") == 0)
34 print_events_type(PERF_TYPE_HARDWARE);
35 else if (strcmp(argv[i], "sw") == 0 ||
36 strcmp(argv[i], "software") == 0)
37 print_events_type(PERF_TYPE_SOFTWARE);
38 else if (strcmp(argv[i], "cache") == 0 ||
39 strcmp(argv[i], "hwcache") == 0)
40 print_hwcache_events(NULL, false);
41 else if (strcmp(argv[i], "pmu") == 0)
42 print_pmu_events(NULL, false);
43 else if (strcmp(argv[i], "--raw-dump") == 0)
44 print_events(NULL, true);
45 else {
46 char *sep = strchr(argv[i], ':'), *s;
47 int sep_idx;
48 39
49 if (sep == NULL) { 40 for (i = 0; i < argc; ++i) {
50 print_events(argv[i], false); 41 if (i)
51 continue; 42 putchar('\n');
52 } 43 if (strncmp(argv[i], "tracepoint", 10) == 0)
53 sep_idx = sep - argv[i]; 44 print_tracepoint_events(NULL, NULL, false);
54 s = strdup(argv[i]); 45 else if (strcmp(argv[i], "hw") == 0 ||
55 if (s == NULL) 46 strcmp(argv[i], "hardware") == 0)
56 return -1; 47 print_events_type(PERF_TYPE_HARDWARE);
48 else if (strcmp(argv[i], "sw") == 0 ||
49 strcmp(argv[i], "software") == 0)
50 print_events_type(PERF_TYPE_SOFTWARE);
51 else if (strcmp(argv[i], "cache") == 0 ||
52 strcmp(argv[i], "hwcache") == 0)
53 print_hwcache_events(NULL, false);
54 else if (strcmp(argv[i], "pmu") == 0)
55 print_pmu_events(NULL, false);
56 else if (strcmp(argv[i], "--raw-dump") == 0)
57 print_events(NULL, true);
58 else {
59 char *sep = strchr(argv[i], ':'), *s;
60 int sep_idx;
57 61
58 s[sep_idx] = '\0'; 62 if (sep == NULL) {
59 print_tracepoint_events(s, s + sep_idx + 1, false); 63 print_events(argv[i], false);
60 free(s); 64 continue;
61 } 65 }
66 sep_idx = sep - argv[i];
67 s = strdup(argv[i]);
68 if (s == NULL)
69 return -1;
70
71 s[sep_idx] = '\0';
72 print_tracepoint_events(s, s + sep_idx + 1, false);
73 free(s);
62 } 74 }
63 } 75 }
64 return 0; 76 return 0;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ee33ba2f05dd..c852c7a85d32 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -15,6 +15,7 @@
15#include "util/debug.h" 15#include "util/debug.h"
16#include "util/session.h" 16#include "util/session.h"
17#include "util/tool.h" 17#include "util/tool.h"
18#include "util/data.h"
18 19
19#include <sys/types.h> 20#include <sys/types.h>
20#include <sys/prctl.h> 21#include <sys/prctl.h>
@@ -56,7 +57,9 @@ struct lock_stat {
56 57
57 unsigned int nr_readlock; 58 unsigned int nr_readlock;
58 unsigned int nr_trylock; 59 unsigned int nr_trylock;
60
59 /* these times are in nano sec. */ 61 /* these times are in nano sec. */
62 u64 avg_wait_time;
60 u64 wait_time_total; 63 u64 wait_time_total;
61 u64 wait_time_min; 64 u64 wait_time_min;
62 u64 wait_time_max; 65 u64 wait_time_max;
@@ -208,6 +211,7 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid)
208 211
209SINGLE_KEY(nr_acquired) 212SINGLE_KEY(nr_acquired)
210SINGLE_KEY(nr_contended) 213SINGLE_KEY(nr_contended)
214SINGLE_KEY(avg_wait_time)
211SINGLE_KEY(wait_time_total) 215SINGLE_KEY(wait_time_total)
212SINGLE_KEY(wait_time_max) 216SINGLE_KEY(wait_time_max)
213 217
@@ -244,6 +248,7 @@ static struct rb_root result; /* place to store sorted data */
244struct lock_key keys[] = { 248struct lock_key keys[] = {
245 DEF_KEY_LOCK(acquired, nr_acquired), 249 DEF_KEY_LOCK(acquired, nr_acquired),
246 DEF_KEY_LOCK(contended, nr_contended), 250 DEF_KEY_LOCK(contended, nr_contended),
251 DEF_KEY_LOCK(avg_wait, avg_wait_time),
247 DEF_KEY_LOCK(wait_total, wait_time_total), 252 DEF_KEY_LOCK(wait_total, wait_time_total),
248 DEF_KEY_LOCK(wait_min, wait_time_min), 253 DEF_KEY_LOCK(wait_min, wait_time_min),
249 DEF_KEY_LOCK(wait_max, wait_time_max), 254 DEF_KEY_LOCK(wait_max, wait_time_max),
@@ -321,10 +326,12 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name)
321 326
322 new->addr = addr; 327 new->addr = addr;
323 new->name = zalloc(sizeof(char) * strlen(name) + 1); 328 new->name = zalloc(sizeof(char) * strlen(name) + 1);
324 if (!new->name) 329 if (!new->name) {
330 free(new);
325 goto alloc_failed; 331 goto alloc_failed;
326 strcpy(new->name, name); 332 }
327 333
334 strcpy(new->name, name);
328 new->wait_time_min = ULLONG_MAX; 335 new->wait_time_min = ULLONG_MAX;
329 336
330 list_add(&new->hash_entry, entry); 337 list_add(&new->hash_entry, entry);
@@ -400,17 +407,17 @@ static int report_lock_acquire_event(struct perf_evsel *evsel,
400 407
401 ls = lock_stat_findnew(addr, name); 408 ls = lock_stat_findnew(addr, name);
402 if (!ls) 409 if (!ls)
403 return -1; 410 return -ENOMEM;
404 if (ls->discard) 411 if (ls->discard)
405 return 0; 412 return 0;
406 413
407 ts = thread_stat_findnew(sample->tid); 414 ts = thread_stat_findnew(sample->tid);
408 if (!ts) 415 if (!ts)
409 return -1; 416 return -ENOMEM;
410 417
411 seq = get_seq(ts, addr); 418 seq = get_seq(ts, addr);
412 if (!seq) 419 if (!seq)
413 return -1; 420 return -ENOMEM;
414 421
415 switch (seq->state) { 422 switch (seq->state) {
416 case SEQ_STATE_UNINITIALIZED: 423 case SEQ_STATE_UNINITIALIZED:
@@ -446,7 +453,6 @@ broken:
446 list_del(&seq->list); 453 list_del(&seq->list);
447 free(seq); 454 free(seq);
448 goto end; 455 goto end;
449 break;
450 default: 456 default:
451 BUG_ON("Unknown state of lock sequence found!\n"); 457 BUG_ON("Unknown state of lock sequence found!\n");
452 break; 458 break;
@@ -473,17 +479,17 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
473 479
474 ls = lock_stat_findnew(addr, name); 480 ls = lock_stat_findnew(addr, name);
475 if (!ls) 481 if (!ls)
476 return -1; 482 return -ENOMEM;
477 if (ls->discard) 483 if (ls->discard)
478 return 0; 484 return 0;
479 485
480 ts = thread_stat_findnew(sample->tid); 486 ts = thread_stat_findnew(sample->tid);
481 if (!ts) 487 if (!ts)
482 return -1; 488 return -ENOMEM;
483 489
484 seq = get_seq(ts, addr); 490 seq = get_seq(ts, addr);
485 if (!seq) 491 if (!seq)
486 return -1; 492 return -ENOMEM;
487 493
488 switch (seq->state) { 494 switch (seq->state) {
489 case SEQ_STATE_UNINITIALIZED: 495 case SEQ_STATE_UNINITIALIZED:
@@ -508,8 +514,6 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
508 list_del(&seq->list); 514 list_del(&seq->list);
509 free(seq); 515 free(seq);
510 goto end; 516 goto end;
511 break;
512
513 default: 517 default:
514 BUG_ON("Unknown state of lock sequence found!\n"); 518 BUG_ON("Unknown state of lock sequence found!\n");
515 break; 519 break;
@@ -517,6 +521,7 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
517 521
518 seq->state = SEQ_STATE_ACQUIRED; 522 seq->state = SEQ_STATE_ACQUIRED;
519 ls->nr_acquired++; 523 ls->nr_acquired++;
524 ls->avg_wait_time = ls->nr_contended ? ls->wait_time_total/ls->nr_contended : 0;
520 seq->prev_event_time = sample->time; 525 seq->prev_event_time = sample->time;
521end: 526end:
522 return 0; 527 return 0;
@@ -536,17 +541,17 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
536 541
537 ls = lock_stat_findnew(addr, name); 542 ls = lock_stat_findnew(addr, name);
538 if (!ls) 543 if (!ls)
539 return -1; 544 return -ENOMEM;
540 if (ls->discard) 545 if (ls->discard)
541 return 0; 546 return 0;
542 547
543 ts = thread_stat_findnew(sample->tid); 548 ts = thread_stat_findnew(sample->tid);
544 if (!ts) 549 if (!ts)
545 return -1; 550 return -ENOMEM;
546 551
547 seq = get_seq(ts, addr); 552 seq = get_seq(ts, addr);
548 if (!seq) 553 if (!seq)
549 return -1; 554 return -ENOMEM;
550 555
551 switch (seq->state) { 556 switch (seq->state) {
552 case SEQ_STATE_UNINITIALIZED: 557 case SEQ_STATE_UNINITIALIZED:
@@ -564,7 +569,6 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
564 list_del(&seq->list); 569 list_del(&seq->list);
565 free(seq); 570 free(seq);
566 goto end; 571 goto end;
567 break;
568 default: 572 default:
569 BUG_ON("Unknown state of lock sequence found!\n"); 573 BUG_ON("Unknown state of lock sequence found!\n");
570 break; 574 break;
@@ -572,6 +576,7 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
572 576
573 seq->state = SEQ_STATE_CONTENDED; 577 seq->state = SEQ_STATE_CONTENDED;
574 ls->nr_contended++; 578 ls->nr_contended++;
579 ls->avg_wait_time = ls->wait_time_total/ls->nr_contended;
575 seq->prev_event_time = sample->time; 580 seq->prev_event_time = sample->time;
576end: 581end:
577 return 0; 582 return 0;
@@ -591,22 +596,21 @@ static int report_lock_release_event(struct perf_evsel *evsel,
591 596
592 ls = lock_stat_findnew(addr, name); 597 ls = lock_stat_findnew(addr, name);
593 if (!ls) 598 if (!ls)
594 return -1; 599 return -ENOMEM;
595 if (ls->discard) 600 if (ls->discard)
596 return 0; 601 return 0;
597 602
598 ts = thread_stat_findnew(sample->tid); 603 ts = thread_stat_findnew(sample->tid);
599 if (!ts) 604 if (!ts)
600 return -1; 605 return -ENOMEM;
601 606
602 seq = get_seq(ts, addr); 607 seq = get_seq(ts, addr);
603 if (!seq) 608 if (!seq)
604 return -1; 609 return -ENOMEM;
605 610
606 switch (seq->state) { 611 switch (seq->state) {
607 case SEQ_STATE_UNINITIALIZED: 612 case SEQ_STATE_UNINITIALIZED:
608 goto end; 613 goto end;
609 break;
610 case SEQ_STATE_ACQUIRED: 614 case SEQ_STATE_ACQUIRED:
611 break; 615 break;
612 case SEQ_STATE_READ_ACQUIRED: 616 case SEQ_STATE_READ_ACQUIRED:
@@ -624,7 +628,6 @@ static int report_lock_release_event(struct perf_evsel *evsel,
624 ls->discard = 1; 628 ls->discard = 1;
625 bad_hist[BROKEN_RELEASE]++; 629 bad_hist[BROKEN_RELEASE]++;
626 goto free_seq; 630 goto free_seq;
627 break;
628 default: 631 default:
629 BUG_ON("Unknown state of lock sequence found!\n"); 632 BUG_ON("Unknown state of lock sequence found!\n");
630 break; 633 break;
@@ -690,7 +693,7 @@ static void print_bad_events(int bad, int total)
690 693
691 pr_info("\n=== output for debug===\n\n"); 694 pr_info("\n=== output for debug===\n\n");
692 pr_info("bad: %d, total: %d\n", bad, total); 695 pr_info("bad: %d, total: %d\n", bad, total);
693 pr_info("bad rate: %f %%\n", (double)bad / (double)total * 100); 696 pr_info("bad rate: %.2f %%\n", (double)bad / (double)total * 100);
694 pr_info("histogram of events caused bad sequence\n"); 697 pr_info("histogram of events caused bad sequence\n");
695 for (i = 0; i < BROKEN_MAX; i++) 698 for (i = 0; i < BROKEN_MAX; i++)
696 pr_info(" %10s: %d\n", name[i], bad_hist[i]); 699 pr_info(" %10s: %d\n", name[i], bad_hist[i]);
@@ -707,6 +710,7 @@ static void print_result(void)
707 pr_info("%10s ", "acquired"); 710 pr_info("%10s ", "acquired");
708 pr_info("%10s ", "contended"); 711 pr_info("%10s ", "contended");
709 712
713 pr_info("%15s ", "avg wait (ns)");
710 pr_info("%15s ", "total wait (ns)"); 714 pr_info("%15s ", "total wait (ns)");
711 pr_info("%15s ", "max wait (ns)"); 715 pr_info("%15s ", "max wait (ns)");
712 pr_info("%15s ", "min wait (ns)"); 716 pr_info("%15s ", "min wait (ns)");
@@ -738,6 +742,7 @@ static void print_result(void)
738 pr_info("%10u ", st->nr_acquired); 742 pr_info("%10u ", st->nr_acquired);
739 pr_info("%10u ", st->nr_contended); 743 pr_info("%10u ", st->nr_contended);
740 744
745 pr_info("%15" PRIu64 " ", st->avg_wait_time);
741 pr_info("%15" PRIu64 " ", st->wait_time_total); 746 pr_info("%15" PRIu64 " ", st->wait_time_total);
742 pr_info("%15" PRIu64 " ", st->wait_time_max); 747 pr_info("%15" PRIu64 " ", st->wait_time_max);
743 pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ? 748 pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ?
@@ -762,7 +767,7 @@ static void dump_threads(void)
762 while (node) { 767 while (node) {
763 st = container_of(node, struct thread_stat, rb); 768 st = container_of(node, struct thread_stat, rb);
764 t = perf_session__findnew(session, st->tid); 769 t = perf_session__findnew(session, st->tid);
765 pr_info("%10d: %s\n", st->tid, t->comm); 770 pr_info("%10d: %s\n", st->tid, thread__comm_str(t));
766 node = rb_next(node); 771 node = rb_next(node);
767 }; 772 };
768} 773}
@@ -814,14 +819,26 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
814 return -1; 819 return -1;
815 } 820 }
816 821
817 if (evsel->handler.func != NULL) { 822 if (evsel->handler != NULL) {
818 tracepoint_handler f = evsel->handler.func; 823 tracepoint_handler f = evsel->handler;
819 return f(evsel, sample); 824 return f(evsel, sample);
820 } 825 }
821 826
822 return 0; 827 return 0;
823} 828}
824 829
830static void sort_result(void)
831{
832 unsigned int i;
833 struct lock_stat *st;
834
835 for (i = 0; i < LOCKHASH_SIZE; i++) {
836 list_for_each_entry(st, &lockhash_table[i], hash_entry) {
837 insert_to_result(st, compare);
838 }
839 }
840}
841
825static const struct perf_evsel_str_handler lock_tracepoints[] = { 842static const struct perf_evsel_str_handler lock_tracepoints[] = {
826 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */ 843 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */
827 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ 844 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
@@ -829,51 +846,51 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
829 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */ 846 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */
830}; 847};
831 848
832static int read_events(void) 849static int __cmd_report(bool display_info)
833{ 850{
851 int err = -EINVAL;
834 struct perf_tool eops = { 852 struct perf_tool eops = {
835 .sample = process_sample_event, 853 .sample = process_sample_event,
836 .comm = perf_event__process_comm, 854 .comm = perf_event__process_comm,
837 .ordered_samples = true, 855 .ordered_samples = true,
838 }; 856 };
839 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); 857 struct perf_data_file file = {
858 .path = input_name,
859 .mode = PERF_DATA_MODE_READ,
860 };
861
862 session = perf_session__new(&file, false, &eops);
840 if (!session) { 863 if (!session) {
841 pr_err("Initializing perf session failed\n"); 864 pr_err("Initializing perf session failed\n");
842 return -1; 865 return -ENOMEM;
843 } 866 }
844 867
868 if (!perf_session__has_traces(session, "lock record"))
869 goto out_delete;
870
845 if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) { 871 if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) {
846 pr_err("Initializing perf session tracepoint handlers failed\n"); 872 pr_err("Initializing perf session tracepoint handlers failed\n");
847 return -1; 873 goto out_delete;
848 } 874 }
849 875
850 return perf_session__process_events(session, &eops); 876 if (select_key())
851} 877 goto out_delete;
852
853static void sort_result(void)
854{
855 unsigned int i;
856 struct lock_stat *st;
857 878
858 for (i = 0; i < LOCKHASH_SIZE; i++) { 879 err = perf_session__process_events(session, &eops);
859 list_for_each_entry(st, &lockhash_table[i], hash_entry) { 880 if (err)
860 insert_to_result(st, compare); 881 goto out_delete;
861 }
862 }
863}
864 882
865static int __cmd_report(void)
866{
867 setup_pager(); 883 setup_pager();
884 if (display_info) /* used for info subcommand */
885 err = dump_info();
886 else {
887 sort_result();
888 print_result();
889 }
868 890
869 if ((select_key() != 0) || 891out_delete:
870 (read_events() != 0)) 892 perf_session__delete(session);
871 return -1; 893 return err;
872
873 sort_result();
874 print_result();
875
876 return 0;
877} 894}
878 895
879static int __cmd_record(int argc, const char **argv) 896static int __cmd_record(int argc, const char **argv)
@@ -881,7 +898,7 @@ static int __cmd_record(int argc, const char **argv)
881 const char *record_args[] = { 898 const char *record_args[] = {
882 "record", "-R", "-m", "1024", "-c", "1", 899 "record", "-R", "-m", "1024", "-c", "1",
883 }; 900 };
884 unsigned int rec_argc, i, j; 901 unsigned int rec_argc, i, j, ret;
885 const char **rec_argv; 902 const char **rec_argv;
886 903
887 for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) { 904 for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) {
@@ -898,7 +915,7 @@ static int __cmd_record(int argc, const char **argv)
898 rec_argc += 2 * ARRAY_SIZE(lock_tracepoints); 915 rec_argc += 2 * ARRAY_SIZE(lock_tracepoints);
899 916
900 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 917 rec_argv = calloc(rec_argc + 1, sizeof(char *));
901 if (rec_argv == NULL) 918 if (!rec_argv)
902 return -ENOMEM; 919 return -ENOMEM;
903 920
904 for (i = 0; i < ARRAY_SIZE(record_args); i++) 921 for (i = 0; i < ARRAY_SIZE(record_args); i++)
@@ -914,7 +931,9 @@ static int __cmd_record(int argc, const char **argv)
914 931
915 BUG_ON(i != rec_argc); 932 BUG_ON(i != rec_argc);
916 933
917 return cmd_record(i, rec_argv, NULL); 934 ret = cmd_record(i, rec_argv, NULL);
935 free(rec_argv);
936 return ret;
918} 937}
919 938
920int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) 939int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
@@ -934,7 +953,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
934 }; 953 };
935 const struct option report_options[] = { 954 const struct option report_options[] = {
936 OPT_STRING('k', "key", &sort_key, "acquired", 955 OPT_STRING('k', "key", &sort_key, "acquired",
937 "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"), 956 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
938 /* TODO: type */ 957 /* TODO: type */
939 OPT_END() 958 OPT_END()
940 }; 959 };
@@ -972,7 +991,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
972 if (argc) 991 if (argc)
973 usage_with_options(report_usage, report_options); 992 usage_with_options(report_usage, report_options);
974 } 993 }
975 __cmd_report(); 994 rc = __cmd_report(false);
976 } else if (!strcmp(argv[0], "script")) { 995 } else if (!strcmp(argv[0], "script")) {
977 /* Aliased to 'perf script' */ 996 /* Aliased to 'perf script' */
978 return cmd_script(argc, argv, prefix); 997 return cmd_script(argc, argv, prefix);
@@ -985,11 +1004,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
985 } 1004 }
986 /* recycling report_lock_ops */ 1005 /* recycling report_lock_ops */
987 trace_handler = &report_lock_ops; 1006 trace_handler = &report_lock_ops;
988 setup_pager(); 1007 rc = __cmd_report(true);
989 if (read_events() != 0)
990 rc = -1;
991 else
992 rc = dump_info();
993 } else { 1008 } else {
994 usage_with_options(lock_usage, lock_options); 1009 usage_with_options(lock_usage, lock_options);
995 } 1010 }
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 253133a6251d..31c00f186da1 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -5,6 +5,7 @@
5#include "util/trace-event.h" 5#include "util/trace-event.h"
6#include "util/tool.h" 6#include "util/tool.h"
7#include "util/session.h" 7#include "util/session.h"
8#include "util/data.h"
8 9
9#define MEM_OPERATION_LOAD "load" 10#define MEM_OPERATION_LOAD "load"
10#define MEM_OPERATION_STORE "store" 11#define MEM_OPERATION_STORE "store"
@@ -119,10 +120,14 @@ static int process_sample_event(struct perf_tool *tool,
119 120
120static int report_raw_events(struct perf_mem *mem) 121static int report_raw_events(struct perf_mem *mem)
121{ 122{
123 struct perf_data_file file = {
124 .path = input_name,
125 .mode = PERF_DATA_MODE_READ,
126 };
122 int err = -EINVAL; 127 int err = -EINVAL;
123 int ret; 128 int ret;
124 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 129 struct perf_session *session = perf_session__new(&file, false,
125 0, false, &mem->tool); 130 &mem->tool);
126 131
127 if (session == NULL) 132 if (session == NULL)
128 return -ENOMEM; 133 return -ENOMEM;
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index e8a66f9a6715..89acc17cf2a0 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -173,7 +173,7 @@ static int opt_set_target(const struct option *opt, const char *str,
173 if (str && !params.target) { 173 if (str && !params.target) {
174 if (!strcmp(opt->long_name, "exec")) 174 if (!strcmp(opt->long_name, "exec"))
175 params.uprobes = true; 175 params.uprobes = true;
176#ifdef DWARF_SUPPORT 176#ifdef HAVE_DWARF_SUPPORT
177 else if (!strcmp(opt->long_name, "module")) 177 else if (!strcmp(opt->long_name, "module"))
178 params.uprobes = false; 178 params.uprobes = false;
179#endif 179#endif
@@ -187,7 +187,7 @@ static int opt_set_target(const struct option *opt, const char *str,
187 return ret; 187 return ret;
188} 188}
189 189
190#ifdef DWARF_SUPPORT 190#ifdef HAVE_DWARF_SUPPORT
191static int opt_show_lines(const struct option *opt __maybe_unused, 191static int opt_show_lines(const struct option *opt __maybe_unused,
192 const char *str, int unset __maybe_unused) 192 const char *str, int unset __maybe_unused)
193{ 193{
@@ -257,7 +257,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
257 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 257 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
258 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 258 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
259 "perf probe --list", 259 "perf probe --list",
260#ifdef DWARF_SUPPORT 260#ifdef HAVE_DWARF_SUPPORT
261 "perf probe [<options>] --line 'LINEDESC'", 261 "perf probe [<options>] --line 'LINEDESC'",
262 "perf probe [<options>] --vars 'PROBEPOINT'", 262 "perf probe [<options>] --vars 'PROBEPOINT'",
263#endif 263#endif
@@ -271,7 +271,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
271 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 271 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
272 opt_del_probe_event), 272 opt_del_probe_event),
273 OPT_CALLBACK('a', "add", NULL, 273 OPT_CALLBACK('a', "add", NULL,
274#ifdef DWARF_SUPPORT 274#ifdef HAVE_DWARF_SUPPORT
275 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" 275 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
276 " [[NAME=]ARG ...]", 276 " [[NAME=]ARG ...]",
277#else 277#else
@@ -283,7 +283,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
283 "\t\tFUNC:\tFunction name\n" 283 "\t\tFUNC:\tFunction name\n"
284 "\t\tOFF:\tOffset from function entry (in byte)\n" 284 "\t\tOFF:\tOffset from function entry (in byte)\n"
285 "\t\t%return:\tPut the probe at function return\n" 285 "\t\t%return:\tPut the probe at function return\n"
286#ifdef DWARF_SUPPORT 286#ifdef HAVE_DWARF_SUPPORT
287 "\t\tSRC:\tSource code path\n" 287 "\t\tSRC:\tSource code path\n"
288 "\t\tRL:\tRelative line number from function entry.\n" 288 "\t\tRL:\tRelative line number from function entry.\n"
289 "\t\tAL:\tAbsolute line number in file.\n" 289 "\t\tAL:\tAbsolute line number in file.\n"
@@ -296,7 +296,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
296 opt_add_probe_event), 296 opt_add_probe_event),
297 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events" 297 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
298 " with existing name"), 298 " with existing name"),
299#ifdef DWARF_SUPPORT 299#ifdef HAVE_DWARF_SUPPORT
300 OPT_CALLBACK('L', "line", NULL, 300 OPT_CALLBACK('L', "line", NULL,
301 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", 301 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
302 "Show source code lines.", opt_show_lines), 302 "Show source code lines.", opt_show_lines),
@@ -408,7 +408,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
408 return ret; 408 return ret;
409 } 409 }
410 410
411#ifdef DWARF_SUPPORT 411#ifdef HAVE_DWARF_SUPPORT
412 if (params.show_lines && !params.uprobes) { 412 if (params.show_lines && !params.uprobes) {
413 if (params.mod_events) { 413 if (params.mod_events) {
414 pr_err(" Error: Don't use --line with" 414 pr_err(" Error: Don't use --line with"
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a41ac41546c9..15280b5e5574 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -24,12 +24,13 @@
24#include "util/symbol.h" 24#include "util/symbol.h"
25#include "util/cpumap.h" 25#include "util/cpumap.h"
26#include "util/thread_map.h" 26#include "util/thread_map.h"
27#include "util/data.h"
27 28
28#include <unistd.h> 29#include <unistd.h>
29#include <sched.h> 30#include <sched.h>
30#include <sys/mman.h> 31#include <sys/mman.h>
31 32
32#ifndef HAVE_ON_EXIT 33#ifndef HAVE_ON_EXIT_SUPPORT
33#ifndef ATEXIT_MAX 34#ifndef ATEXIT_MAX
34#define ATEXIT_MAX 32 35#define ATEXIT_MAX 32
35#endif 36#endif
@@ -65,31 +66,25 @@ struct perf_record {
65 struct perf_tool tool; 66 struct perf_tool tool;
66 struct perf_record_opts opts; 67 struct perf_record_opts opts;
67 u64 bytes_written; 68 u64 bytes_written;
68 const char *output_name; 69 struct perf_data_file file;
69 struct perf_evlist *evlist; 70 struct perf_evlist *evlist;
70 struct perf_session *session; 71 struct perf_session *session;
71 const char *progname; 72 const char *progname;
72 int output;
73 unsigned int page_size;
74 int realtime_prio; 73 int realtime_prio;
75 bool no_buildid; 74 bool no_buildid;
76 bool no_buildid_cache; 75 bool no_buildid_cache;
77 long samples; 76 long samples;
78 off_t post_processing_offset;
79}; 77};
80 78
81static void advance_output(struct perf_record *rec, size_t size)
82{
83 rec->bytes_written += size;
84}
85
86static int write_output(struct perf_record *rec, void *buf, size_t size) 79static int write_output(struct perf_record *rec, void *buf, size_t size)
87{ 80{
81 struct perf_data_file *file = &rec->file;
82
88 while (size) { 83 while (size) {
89 int ret = write(rec->output, buf, size); 84 int ret = write(file->fd, buf, size);
90 85
91 if (ret < 0) { 86 if (ret < 0) {
92 pr_err("failed to write\n"); 87 pr_err("failed to write perf data, error: %m\n");
93 return -1; 88 return -1;
94 } 89 }
95 90
@@ -119,7 +114,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
119{ 114{
120 unsigned int head = perf_mmap__read_head(md); 115 unsigned int head = perf_mmap__read_head(md);
121 unsigned int old = md->prev; 116 unsigned int old = md->prev;
122 unsigned char *data = md->base + rec->page_size; 117 unsigned char *data = md->base + page_size;
123 unsigned long size; 118 unsigned long size;
124 void *buf; 119 void *buf;
125 int rc = 0; 120 int rc = 0;
@@ -234,10 +229,6 @@ try_again:
234 "or try again with a smaller value of -m/--mmap_pages.\n" 229 "or try again with a smaller value of -m/--mmap_pages.\n"
235 "(current value: %d)\n", opts->mmap_pages); 230 "(current value: %d)\n", opts->mmap_pages);
236 rc = -errno; 231 rc = -errno;
237 } else if (!is_power_of_2(opts->mmap_pages) &&
238 (opts->mmap_pages != UINT_MAX)) {
239 pr_err("--mmap_pages/-m value must be a power of two.");
240 rc = -EINVAL;
241 } else { 232 } else {
242 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 233 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
243 rc = -errno; 234 rc = -errno;
@@ -253,31 +244,34 @@ out:
253 244
254static int process_buildids(struct perf_record *rec) 245static int process_buildids(struct perf_record *rec)
255{ 246{
256 u64 size = lseek(rec->output, 0, SEEK_CUR); 247 struct perf_data_file *file = &rec->file;
248 struct perf_session *session = rec->session;
249 u64 start = session->header.data_offset;
257 250
251 u64 size = lseek(file->fd, 0, SEEK_CUR);
258 if (size == 0) 252 if (size == 0)
259 return 0; 253 return 0;
260 254
261 rec->session->fd = rec->output; 255 return __perf_session__process_events(session, start,
262 return __perf_session__process_events(rec->session, rec->post_processing_offset, 256 size - start,
263 size - rec->post_processing_offset,
264 size, &build_id__mark_dso_hit_ops); 257 size, &build_id__mark_dso_hit_ops);
265} 258}
266 259
267static void perf_record__exit(int status, void *arg) 260static void perf_record__exit(int status, void *arg)
268{ 261{
269 struct perf_record *rec = arg; 262 struct perf_record *rec = arg;
263 struct perf_data_file *file = &rec->file;
270 264
271 if (status != 0) 265 if (status != 0)
272 return; 266 return;
273 267
274 if (!rec->opts.pipe_output) { 268 if (!file->is_pipe) {
275 rec->session->header.data_size += rec->bytes_written; 269 rec->session->header.data_size += rec->bytes_written;
276 270
277 if (!rec->no_buildid) 271 if (!rec->no_buildid)
278 process_buildids(rec); 272 process_buildids(rec);
279 perf_session__write_header(rec->session, rec->evlist, 273 perf_session__write_header(rec->session, rec->evlist,
280 rec->output, true); 274 file->fd, true);
281 perf_session__delete(rec->session); 275 perf_session__delete(rec->session);
282 perf_evlist__delete(rec->evlist); 276 perf_evlist__delete(rec->evlist);
283 symbol__exit(); 277 symbol__exit();
@@ -343,64 +337,47 @@ out:
343 return rc; 337 return rc;
344} 338}
345 339
340static void perf_record__init_features(struct perf_record *rec)
341{
342 struct perf_evlist *evsel_list = rec->evlist;
343 struct perf_session *session = rec->session;
344 int feat;
345
346 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
347 perf_header__set_feat(&session->header, feat);
348
349 if (rec->no_buildid)
350 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
351
352 if (!have_tracepoints(&evsel_list->entries))
353 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
354
355 if (!rec->opts.branch_stack)
356 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
357}
358
346static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 359static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
347{ 360{
348 struct stat st; 361 int err;
349 int flags;
350 int err, output, feat;
351 unsigned long waking = 0; 362 unsigned long waking = 0;
352 const bool forks = argc > 0; 363 const bool forks = argc > 0;
353 struct machine *machine; 364 struct machine *machine;
354 struct perf_tool *tool = &rec->tool; 365 struct perf_tool *tool = &rec->tool;
355 struct perf_record_opts *opts = &rec->opts; 366 struct perf_record_opts *opts = &rec->opts;
356 struct perf_evlist *evsel_list = rec->evlist; 367 struct perf_evlist *evsel_list = rec->evlist;
357 const char *output_name = rec->output_name; 368 struct perf_data_file *file = &rec->file;
358 struct perf_session *session; 369 struct perf_session *session;
359 bool disabled = false; 370 bool disabled = false;
360 371
361 rec->progname = argv[0]; 372 rec->progname = argv[0];
362 373
363 rec->page_size = sysconf(_SC_PAGE_SIZE);
364
365 on_exit(perf_record__sig_exit, rec); 374 on_exit(perf_record__sig_exit, rec);
366 signal(SIGCHLD, sig_handler); 375 signal(SIGCHLD, sig_handler);
367 signal(SIGINT, sig_handler); 376 signal(SIGINT, sig_handler);
368 signal(SIGUSR1, sig_handler); 377 signal(SIGUSR1, sig_handler);
369 signal(SIGTERM, sig_handler); 378 signal(SIGTERM, sig_handler);
370 379
371 if (!output_name) { 380 session = perf_session__new(file, false, NULL);
372 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
373 opts->pipe_output = true;
374 else
375 rec->output_name = output_name = "perf.data";
376 }
377 if (output_name) {
378 if (!strcmp(output_name, "-"))
379 opts->pipe_output = true;
380 else if (!stat(output_name, &st) && st.st_size) {
381 char oldname[PATH_MAX];
382 snprintf(oldname, sizeof(oldname), "%s.old",
383 output_name);
384 unlink(oldname);
385 rename(output_name, oldname);
386 }
387 }
388
389 flags = O_CREAT|O_RDWR|O_TRUNC;
390
391 if (opts->pipe_output)
392 output = STDOUT_FILENO;
393 else
394 output = open(output_name, flags, S_IRUSR | S_IWUSR);
395 if (output < 0) {
396 perror("failed to create output file");
397 return -1;
398 }
399
400 rec->output = output;
401
402 session = perf_session__new(output_name, O_WRONLY,
403 true, false, NULL);
404 if (session == NULL) { 381 if (session == NULL) {
405 pr_err("Not enough memory for reading perf file header\n"); 382 pr_err("Not enough memory for reading perf file header\n");
406 return -1; 383 return -1;
@@ -408,21 +385,11 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
408 385
409 rec->session = session; 386 rec->session = session;
410 387
411 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 388 perf_record__init_features(rec);
412 perf_header__set_feat(&session->header, feat);
413
414 if (rec->no_buildid)
415 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
416
417 if (!have_tracepoints(&evsel_list->entries))
418 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
419
420 if (!rec->opts.branch_stack)
421 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
422 389
423 if (forks) { 390 if (forks) {
424 err = perf_evlist__prepare_workload(evsel_list, &opts->target, 391 err = perf_evlist__prepare_workload(evsel_list, &opts->target,
425 argv, opts->pipe_output, 392 argv, file->is_pipe,
426 true); 393 true);
427 if (err < 0) { 394 if (err < 0) {
428 pr_err("Couldn't run the workload!\n"); 395 pr_err("Couldn't run the workload!\n");
@@ -443,13 +410,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
443 */ 410 */
444 on_exit(perf_record__exit, rec); 411 on_exit(perf_record__exit, rec);
445 412
446 if (opts->pipe_output) { 413 if (file->is_pipe) {
447 err = perf_header__write_pipe(output); 414 err = perf_header__write_pipe(file->fd);
448 if (err < 0) 415 if (err < 0)
449 goto out_delete_session; 416 goto out_delete_session;
450 } else { 417 } else {
451 err = perf_session__write_header(session, evsel_list, 418 err = perf_session__write_header(session, evsel_list,
452 output, false); 419 file->fd, false);
453 if (err < 0) 420 if (err < 0)
454 goto out_delete_session; 421 goto out_delete_session;
455 } 422 }
@@ -462,11 +429,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
462 goto out_delete_session; 429 goto out_delete_session;
463 } 430 }
464 431
465 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
466
467 machine = &session->machines.host; 432 machine = &session->machines.host;
468 433
469 if (opts->pipe_output) { 434 if (file->is_pipe) {
470 err = perf_event__synthesize_attrs(tool, session, 435 err = perf_event__synthesize_attrs(tool, session,
471 process_synthesized_event); 436 process_synthesized_event);
472 if (err < 0) { 437 if (err < 0) {
@@ -483,13 +448,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
483 * return this more properly and also 448 * return this more properly and also
484 * propagate errors that now are calling die() 449 * propagate errors that now are calling die()
485 */ 450 */
486 err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 451 err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list,
487 process_synthesized_event); 452 process_synthesized_event);
488 if (err <= 0) { 453 if (err <= 0) {
489 pr_err("Couldn't record tracing data.\n"); 454 pr_err("Couldn't record tracing data.\n");
490 goto out_delete_session; 455 goto out_delete_session;
491 } 456 }
492 advance_output(rec, err); 457 rec->bytes_written += err;
493 } 458 }
494 } 459 }
495 460
@@ -590,7 +555,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
590 fprintf(stderr, 555 fprintf(stderr,
591 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 556 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
592 (double)rec->bytes_written / 1024.0 / 1024.0, 557 (double)rec->bytes_written / 1024.0 / 1024.0,
593 output_name, 558 file->path,
594 rec->bytes_written / 24); 559 rec->bytes_written / 24);
595 560
596 return 0; 561 return 0;
@@ -618,6 +583,9 @@ static const struct branch_mode branch_modes[] = {
618 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 583 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
619 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 584 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
620 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 585 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
586 BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
587 BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
588 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
621 BRANCH_END 589 BRANCH_END
622}; 590};
623 591
@@ -684,7 +652,7 @@ error:
684 return ret; 652 return ret;
685} 653}
686 654
687#ifdef LIBUNWIND_SUPPORT 655#ifdef HAVE_LIBUNWIND_SUPPORT
688static int get_stack_size(char *str, unsigned long *_size) 656static int get_stack_size(char *str, unsigned long *_size)
689{ 657{
690 char *endptr; 658 char *endptr;
@@ -710,23 +678,14 @@ static int get_stack_size(char *str, unsigned long *_size)
710 max_size, str); 678 max_size, str);
711 return -1; 679 return -1;
712} 680}
713#endif /* LIBUNWIND_SUPPORT */ 681#endif /* HAVE_LIBUNWIND_SUPPORT */
714 682
715int record_parse_callchain_opt(const struct option *opt, 683int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
716 const char *arg, int unset)
717{ 684{
718 struct perf_record_opts *opts = opt->value;
719 char *tok, *name, *saveptr = NULL; 685 char *tok, *name, *saveptr = NULL;
720 char *buf; 686 char *buf;
721 int ret = -1; 687 int ret = -1;
722 688
723 /* --no-call-graph */
724 if (unset)
725 return 0;
726
727 /* We specified default option if none is provided. */
728 BUG_ON(!arg);
729
730 /* We need buffer that we know we can write to. */ 689 /* We need buffer that we know we can write to. */
731 buf = malloc(strlen(arg) + 1); 690 buf = malloc(strlen(arg) + 1);
732 if (!buf) 691 if (!buf)
@@ -748,7 +707,7 @@ int record_parse_callchain_opt(const struct option *opt,
748 "needed for -g fp\n"); 707 "needed for -g fp\n");
749 break; 708 break;
750 709
751#ifdef LIBUNWIND_SUPPORT 710#ifdef HAVE_LIBUNWIND_SUPPORT
752 /* Dwarf style */ 711 /* Dwarf style */
753 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 712 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
754 const unsigned long default_stack_dump_size = 8192; 713 const unsigned long default_stack_dump_size = 8192;
@@ -764,13 +723,9 @@ int record_parse_callchain_opt(const struct option *opt,
764 ret = get_stack_size(tok, &size); 723 ret = get_stack_size(tok, &size);
765 opts->stack_dump_size = size; 724 opts->stack_dump_size = size;
766 } 725 }
767 726#endif /* HAVE_LIBUNWIND_SUPPORT */
768 if (!ret)
769 pr_debug("callchain: stack dump size %d\n",
770 opts->stack_dump_size);
771#endif /* LIBUNWIND_SUPPORT */
772 } else { 727 } else {
773 pr_err("callchain: Unknown -g option " 728 pr_err("callchain: Unknown --call-graph option "
774 "value: %s\n", arg); 729 "value: %s\n", arg);
775 break; 730 break;
776 } 731 }
@@ -778,13 +733,52 @@ int record_parse_callchain_opt(const struct option *opt,
778 } while (0); 733 } while (0);
779 734
780 free(buf); 735 free(buf);
736 return ret;
737}
738
739static void callchain_debug(struct perf_record_opts *opts)
740{
741 pr_debug("callchain: type %d\n", opts->call_graph);
742
743 if (opts->call_graph == CALLCHAIN_DWARF)
744 pr_debug("callchain: stack dump size %d\n",
745 opts->stack_dump_size);
746}
781 747
748int record_parse_callchain_opt(const struct option *opt,
749 const char *arg,
750 int unset)
751{
752 struct perf_record_opts *opts = opt->value;
753 int ret;
754
755 /* --no-call-graph */
756 if (unset) {
757 opts->call_graph = CALLCHAIN_NONE;
758 pr_debug("callchain: disabled\n");
759 return 0;
760 }
761
762 ret = record_parse_callchain(arg, opts);
782 if (!ret) 763 if (!ret)
783 pr_debug("callchain: type %d\n", opts->call_graph); 764 callchain_debug(opts);
784 765
785 return ret; 766 return ret;
786} 767}
787 768
769int record_callchain_opt(const struct option *opt,
770 const char *arg __maybe_unused,
771 int unset __maybe_unused)
772{
773 struct perf_record_opts *opts = opt->value;
774
775 if (opts->call_graph == CALLCHAIN_NONE)
776 opts->call_graph = CALLCHAIN_FP;
777
778 callchain_debug(opts);
779 return 0;
780}
781
788static const char * const record_usage[] = { 782static const char * const record_usage[] = {
789 "perf record [<options>] [<command>]", 783 "perf record [<options>] [<command>]",
790 "perf record [<options>] -- <command> [<options>]", 784 "perf record [<options>] -- <command> [<options>]",
@@ -813,12 +807,12 @@ static struct perf_record record = {
813 }, 807 },
814}; 808};
815 809
816#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " 810#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
817 811
818#ifdef LIBUNWIND_SUPPORT 812#ifdef HAVE_LIBUNWIND_SUPPORT
819const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 813const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
820#else 814#else
821const char record_callchain_help[] = CALLCHAIN_HELP "[fp]"; 815const char record_callchain_help[] = CALLCHAIN_HELP "fp";
822#endif 816#endif
823 817
824/* 818/*
@@ -849,18 +843,22 @@ const struct option record_options[] = {
849 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 843 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
850 "list of cpus to monitor"), 844 "list of cpus to monitor"),
851 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 845 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
852 OPT_STRING('o', "output", &record.output_name, "file", 846 OPT_STRING('o', "output", &record.file.path, "file",
853 "output file name"), 847 "output file name"),
854 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 848 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
855 "child tasks do not inherit counters"), 849 "child tasks do not inherit counters"),
856 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 850 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
857 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 851 OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
858 "number of mmap data pages"), 852 "number of mmap data pages",
853 perf_evlist__parse_mmap_pages),
859 OPT_BOOLEAN(0, "group", &record.opts.group, 854 OPT_BOOLEAN(0, "group", &record.opts.group,
860 "put the counters into a counter group"), 855 "put the counters into a counter group"),
861 OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts, 856 OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
862 "mode[,dump_size]", record_callchain_help, 857 NULL, "enables call-graph recording" ,
863 &record_parse_callchain_opt, "fp"), 858 &record_callchain_opt),
859 OPT_CALLBACK(0, "call-graph", &record.opts,
860 "mode[,dump_size]", record_callchain_help,
861 &record_parse_callchain_opt),
864 OPT_INCR('v', "verbose", &verbose, 862 OPT_INCR('v', "verbose", &verbose,
865 "be more verbose (show counter open errors, etc)"), 863 "be more verbose (show counter open errors, etc)"),
866 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 864 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
@@ -891,6 +889,8 @@ const struct option record_options[] = {
891 parse_branch_stack), 889 parse_branch_stack),
892 OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 890 OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
893 "sample by weight (on special events only)"), 891 "sample by weight (on special events only)"),
892 OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
893 "sample transaction flags (special events only)"),
894 OPT_END() 894 OPT_END()
895}; 895};
896 896
@@ -960,20 +960,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
960 if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 960 if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
961 usage_with_options(record_usage, record_options); 961 usage_with_options(record_usage, record_options);
962 962
963 if (rec->opts.user_interval != ULLONG_MAX) 963 if (perf_record_opts__config(&rec->opts)) {
964 rec->opts.default_interval = rec->opts.user_interval;
965 if (rec->opts.user_freq != UINT_MAX)
966 rec->opts.freq = rec->opts.user_freq;
967
968 /*
969 * User specified count overrides default frequency.
970 */
971 if (rec->opts.default_interval)
972 rec->opts.freq = 0;
973 else if (rec->opts.freq) {
974 rec->opts.default_interval = rec->opts.freq;
975 } else {
976 ui__error("frequency and count are zero, aborting\n");
977 err = -EINVAL; 964 err = -EINVAL;
978 goto out_free_fd; 965 goto out_free_fd;
979 } 966 }
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 72eae7498c09..8cf8e66ba594 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,8 +33,10 @@
33#include "util/thread.h" 33#include "util/thread.h"
34#include "util/sort.h" 34#include "util/sort.h"
35#include "util/hist.h" 35#include "util/hist.h"
36#include "util/data.h"
36#include "arch/common.h" 37#include "arch/common.h"
37 38
39#include <dlfcn.h>
38#include <linux/bitmap.h> 40#include <linux/bitmap.h>
39 41
40struct perf_report { 42struct perf_report {
@@ -47,6 +49,7 @@ struct perf_report {
47 bool show_threads; 49 bool show_threads;
48 bool inverted_callchain; 50 bool inverted_callchain;
49 bool mem_mode; 51 bool mem_mode;
52 int max_stack;
50 struct perf_read_values show_threads_values; 53 struct perf_read_values show_threads_values;
51 const char *pretty_printing_style; 54 const char *pretty_printing_style;
52 const char *cpu_list; 55 const char *cpu_list;
@@ -88,7 +91,8 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
88 if ((sort__has_parent || symbol_conf.use_callchain) && 91 if ((sort__has_parent || symbol_conf.use_callchain) &&
89 sample->callchain) { 92 sample->callchain) {
90 err = machine__resolve_callchain(machine, evsel, al->thread, 93 err = machine__resolve_callchain(machine, evsel, al->thread,
91 sample, &parent, al); 94 sample, &parent, al,
95 rep->max_stack);
92 if (err) 96 if (err)
93 return err; 97 return err;
94 } 98 }
@@ -111,7 +115,8 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
111 * and this is indirectly achieved by passing period=weight here 115 * and this is indirectly achieved by passing period=weight here
112 * and the he_stat__add_period() function. 116 * and the he_stat__add_period() function.
113 */ 117 */
114 he = __hists__add_mem_entry(&evsel->hists, al, parent, mi, cost, cost); 118 he = __hists__add_entry(&evsel->hists, al, parent, NULL, mi,
119 cost, cost, 0);
115 if (!he) 120 if (!he)
116 return -ENOMEM; 121 return -ENOMEM;
117 122
@@ -179,7 +184,8 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
179 if ((sort__has_parent || symbol_conf.use_callchain) 184 if ((sort__has_parent || symbol_conf.use_callchain)
180 && sample->callchain) { 185 && sample->callchain) {
181 err = machine__resolve_callchain(machine, evsel, al->thread, 186 err = machine__resolve_callchain(machine, evsel, al->thread,
182 sample, &parent, al); 187 sample, &parent, al,
188 rep->max_stack);
183 if (err) 189 if (err)
184 return err; 190 return err;
185 } 191 }
@@ -195,12 +201,16 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
195 201
196 err = -ENOMEM; 202 err = -ENOMEM;
197 203
204 /* overwrite the 'al' to branch-to info */
205 al->map = bi[i].to.map;
206 al->sym = bi[i].to.sym;
207 al->addr = bi[i].to.addr;
198 /* 208 /*
199 * The report shows the percentage of total branches captured 209 * The report shows the percentage of total branches captured
200 * and not events sampled. Thus we use a pseudo period of 1. 210 * and not events sampled. Thus we use a pseudo period of 1.
201 */ 211 */
202 he = __hists__add_branch_entry(&evsel->hists, al, parent, 212 he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
203 &bi[i], 1, 1); 213 1, 1, 0);
204 if (he) { 214 if (he) {
205 struct annotation *notes; 215 struct annotation *notes;
206 bx = he->branch_info; 216 bx = he->branch_info;
@@ -242,24 +252,28 @@ out:
242 return err; 252 return err;
243} 253}
244 254
245static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, 255static int perf_evsel__add_hist_entry(struct perf_tool *tool,
256 struct perf_evsel *evsel,
246 struct addr_location *al, 257 struct addr_location *al,
247 struct perf_sample *sample, 258 struct perf_sample *sample,
248 struct machine *machine) 259 struct machine *machine)
249{ 260{
261 struct perf_report *rep = container_of(tool, struct perf_report, tool);
250 struct symbol *parent = NULL; 262 struct symbol *parent = NULL;
251 int err = 0; 263 int err = 0;
252 struct hist_entry *he; 264 struct hist_entry *he;
253 265
254 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { 266 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
255 err = machine__resolve_callchain(machine, evsel, al->thread, 267 err = machine__resolve_callchain(machine, evsel, al->thread,
256 sample, &parent, al); 268 sample, &parent, al,
269 rep->max_stack);
257 if (err) 270 if (err)
258 return err; 271 return err;
259 } 272 }
260 273
261 he = __hists__add_entry(&evsel->hists, al, parent, sample->period, 274 he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
262 sample->weight); 275 sample->period, sample->weight,
276 sample->transaction);
263 if (he == NULL) 277 if (he == NULL)
264 return -ENOMEM; 278 return -ENOMEM;
265 279
@@ -330,7 +344,8 @@ static int process_sample_event(struct perf_tool *tool,
330 if (al.map != NULL) 344 if (al.map != NULL)
331 al.map->dso->hit = 1; 345 al.map->dso->hit = 1;
332 346
333 ret = perf_evsel__add_hist_entry(evsel, &al, sample, machine); 347 ret = perf_evsel__add_hist_entry(tool, evsel, &al, sample,
348 machine);
334 if (ret < 0) 349 if (ret < 0)
335 pr_debug("problem incrementing symbol period, skipping event\n"); 350 pr_debug("problem incrementing symbol period, skipping event\n");
336 } 351 }
@@ -364,10 +379,11 @@ static int process_read_event(struct perf_tool *tool,
364/* For pipe mode, sample_type is not currently set */ 379/* For pipe mode, sample_type is not currently set */
365static int perf_report__setup_sample_type(struct perf_report *rep) 380static int perf_report__setup_sample_type(struct perf_report *rep)
366{ 381{
367 struct perf_session *self = rep->session; 382 struct perf_session *session = rep->session;
368 u64 sample_type = perf_evlist__combined_sample_type(self->evlist); 383 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
384 bool is_pipe = perf_data_file__is_pipe(session->file);
369 385
370 if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 386 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
371 if (sort__has_parent) { 387 if (sort__has_parent) {
372 ui__error("Selected --sort parent, but no " 388 ui__error("Selected --sort parent, but no "
373 "callchain data. Did you call " 389 "callchain data. Did you call "
@@ -390,7 +406,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
390 } 406 }
391 407
392 if (sort__mode == SORT_MODE__BRANCH) { 408 if (sort__mode == SORT_MODE__BRANCH) {
393 if (!self->fd_pipe && 409 if (!is_pipe &&
394 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) { 410 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
395 ui__error("Selected -b but no branch data. " 411 ui__error("Selected -b but no branch data. "
396 "Did you call perf record without -b?\n"); 412 "Did you call perf record without -b?\n");
@@ -407,14 +423,14 @@ static void sig_handler(int sig __maybe_unused)
407} 423}
408 424
409static size_t hists__fprintf_nr_sample_events(struct perf_report *rep, 425static size_t hists__fprintf_nr_sample_events(struct perf_report *rep,
410 struct hists *self, 426 struct hists *hists,
411 const char *evname, FILE *fp) 427 const char *evname, FILE *fp)
412{ 428{
413 size_t ret; 429 size_t ret;
414 char unit; 430 char unit;
415 unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE]; 431 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
416 u64 nr_events = self->stats.total_period; 432 u64 nr_events = hists->stats.total_period;
417 struct perf_evsel *evsel = hists_to_evsel(self); 433 struct perf_evsel *evsel = hists_to_evsel(hists);
418 char buf[512]; 434 char buf[512];
419 size_t size = sizeof(buf); 435 size_t size = sizeof(buf);
420 436
@@ -486,6 +502,8 @@ static int __cmd_report(struct perf_report *rep)
486 struct map *kernel_map; 502 struct map *kernel_map;
487 struct kmap *kernel_kmap; 503 struct kmap *kernel_kmap;
488 const char *help = "For a higher level overview, try: perf report --sort comm,dso"; 504 const char *help = "For a higher level overview, try: perf report --sort comm,dso";
505 struct ui_progress prog;
506 struct perf_data_file *file = session->file;
489 507
490 signal(SIGINT, sig_handler); 508 signal(SIGINT, sig_handler);
491 509
@@ -547,13 +565,19 @@ static int __cmd_report(struct perf_report *rep)
547 } 565 }
548 566
549 nr_samples = 0; 567 nr_samples = 0;
568 list_for_each_entry(pos, &session->evlist->entries, node)
569 nr_samples += pos->hists.nr_entries;
570
571 ui_progress__init(&prog, nr_samples, "Merging related events...");
572
573 nr_samples = 0;
550 list_for_each_entry(pos, &session->evlist->entries, node) { 574 list_for_each_entry(pos, &session->evlist->entries, node) {
551 struct hists *hists = &pos->hists; 575 struct hists *hists = &pos->hists;
552 576
553 if (pos->idx == 0) 577 if (pos->idx == 0)
554 hists->symbol_filter_str = rep->symbol_filter_str; 578 hists->symbol_filter_str = rep->symbol_filter_str;
555 579
556 hists__collapse_resort(hists); 580 hists__collapse_resort(hists, &prog);
557 nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE]; 581 nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
558 582
559 /* Non-group events are considered as leader */ 583 /* Non-group events are considered as leader */
@@ -565,12 +589,13 @@ static int __cmd_report(struct perf_report *rep)
565 hists__link(leader_hists, hists); 589 hists__link(leader_hists, hists);
566 } 590 }
567 } 591 }
592 ui_progress__finish();
568 593
569 if (session_done()) 594 if (session_done())
570 return 0; 595 return 0;
571 596
572 if (nr_samples == 0) { 597 if (nr_samples == 0) {
573 ui__error("The %s file has no samples!\n", session->filename); 598 ui__error("The %s file has no samples!\n", file->path);
574 return 0; 599 return 0;
575 } 600 }
576 601
@@ -591,8 +616,19 @@ static int __cmd_report(struct perf_report *rep)
591 ret = 0; 616 ret = 0;
592 617
593 } else if (use_browser == 2) { 618 } else if (use_browser == 2) {
594 perf_evlist__gtk_browse_hists(session->evlist, help, 619 int (*hist_browser)(struct perf_evlist *,
595 NULL, rep->min_percent); 620 const char *,
621 struct hist_browser_timer *,
622 float min_pcnt);
623
624 hist_browser = dlsym(perf_gtk_handle,
625 "perf_evlist__gtk_browse_hists");
626 if (hist_browser == NULL) {
627 ui__error("GTK browser not found!\n");
628 return ret;
629 }
630 hist_browser(session->evlist, help, NULL,
631 rep->min_percent);
596 } 632 }
597 } else 633 } else
598 perf_evlist__tty_browse_hists(session->evlist, rep, help); 634 perf_evlist__tty_browse_hists(session->evlist, rep, help);
@@ -757,6 +793,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
757 .ordered_samples = true, 793 .ordered_samples = true,
758 .ordering_requires_timestamps = true, 794 .ordering_requires_timestamps = true,
759 }, 795 },
796 .max_stack = PERF_MAX_STACK_DEPTH,
760 .pretty_printing_style = "normal", 797 .pretty_printing_style = "normal",
761 }; 798 };
762 const struct option options[] = { 799 const struct option options[] = {
@@ -787,7 +824,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
787 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," 824 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
788 " dso_to, dso_from, symbol_to, symbol_from, mispredict," 825 " dso_to, dso_from, symbol_to, symbol_from, mispredict,"
789 " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, " 826 " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, "
790 "snoop, locked"), 827 "snoop, locked, abort, in_tx, transaction"),
791 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 828 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
792 "Show sample percentage for different cpu modes"), 829 "Show sample percentage for different cpu modes"),
793 OPT_STRING('p', "parent", &parent_pattern, "regex", 830 OPT_STRING('p', "parent", &parent_pattern, "regex",
@@ -797,6 +834,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
797 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order", 834 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
798 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). " 835 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
799 "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt), 836 "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt),
837 OPT_INTEGER(0, "max-stack", &report.max_stack,
838 "Set the maximum stack depth when parsing the callchain, "
839 "anything beyond the specified depth will be ignored. "
840 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
800 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, 841 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
801 "alias for inverted call graph"), 842 "alias for inverted call graph"),
802 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 843 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
@@ -845,6 +886,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
845 "Don't show entries under that percent", parse_percent_limit), 886 "Don't show entries under that percent", parse_percent_limit),
846 OPT_END() 887 OPT_END()
847 }; 888 };
889 struct perf_data_file file = {
890 .mode = PERF_DATA_MODE_READ,
891 };
848 892
849 perf_config(perf_report_config, &report); 893 perf_config(perf_report_config, &report);
850 894
@@ -867,16 +911,11 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
867 input_name = "perf.data"; 911 input_name = "perf.data";
868 } 912 }
869 913
870 if (strcmp(input_name, "-") != 0) 914 file.path = input_name;
871 setup_browser(true); 915 file.force = report.force;
872 else {
873 use_browser = 0;
874 perf_hpp__init();
875 }
876 916
877repeat: 917repeat:
878 session = perf_session__new(input_name, O_RDONLY, 918 session = perf_session__new(&file, false, &report.tool);
879 report.force, false, &report.tool);
880 if (session == NULL) 919 if (session == NULL)
881 return -ENOMEM; 920 return -ENOMEM;
882 921
@@ -914,8 +953,22 @@ repeat:
914 sort_order = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; 953 sort_order = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
915 } 954 }
916 955
917 if (setup_sorting() < 0) 956 if (setup_sorting() < 0) {
918 usage_with_options(report_usage, options); 957 parse_options_usage(report_usage, options, "s", 1);
958 goto error;
959 }
960
961 if (parent_pattern != default_parent_pattern) {
962 if (sort_dimension__add("parent") < 0)
963 goto error;
964 }
965
966 if (strcmp(input_name, "-") != 0)
967 setup_browser(true);
968 else {
969 use_browser = 0;
970 perf_hpp__init();
971 }
919 972
920 /* 973 /*
921 * Only in the TUI browser we are doing integrated annotation, 974 * Only in the TUI browser we are doing integrated annotation,
@@ -946,11 +999,6 @@ repeat:
946 if (symbol__init() < 0) 999 if (symbol__init() < 0)
947 goto error; 1000 goto error;
948 1001
949 if (parent_pattern != default_parent_pattern) {
950 if (sort_dimension__add("parent") < 0)
951 goto error;
952 }
953
954 if (argc) { 1002 if (argc) {
955 /* 1003 /*
956 * Special case: if there's an argument left then assume that 1004 * Special case: if there's an argument left then assume that
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index d8c51b2f263f..0f3c65518a2c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -737,12 +737,12 @@ static int replay_fork_event(struct perf_sched *sched,
737 737
738 if (verbose) { 738 if (verbose) {
739 printf("fork event\n"); 739 printf("fork event\n");
740 printf("... parent: %s/%d\n", parent->comm, parent->tid); 740 printf("... parent: %s/%d\n", thread__comm_str(parent), parent->tid);
741 printf("... child: %s/%d\n", child->comm, child->tid); 741 printf("... child: %s/%d\n", thread__comm_str(child), child->tid);
742 } 742 }
743 743
744 register_pid(sched, parent->tid, parent->comm); 744 register_pid(sched, parent->tid, thread__comm_str(parent));
745 register_pid(sched, child->tid, child->comm); 745 register_pid(sched, child->tid, thread__comm_str(child));
746 return 0; 746 return 0;
747} 747}
748 748
@@ -1077,7 +1077,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,
1077 if (!atoms) { 1077 if (!atoms) {
1078 if (thread_atoms_insert(sched, migrant)) 1078 if (thread_atoms_insert(sched, migrant))
1079 return -1; 1079 return -1;
1080 register_pid(sched, migrant->tid, migrant->comm); 1080 register_pid(sched, migrant->tid, thread__comm_str(migrant));
1081 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1081 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1082 if (!atoms) { 1082 if (!atoms) {
1083 pr_err("migration-event: Internal tree error"); 1083 pr_err("migration-event: Internal tree error");
@@ -1111,13 +1111,13 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1111 /* 1111 /*
1112 * Ignore idle threads: 1112 * Ignore idle threads:
1113 */ 1113 */
1114 if (!strcmp(work_list->thread->comm, "swapper")) 1114 if (!strcmp(thread__comm_str(work_list->thread), "swapper"))
1115 return; 1115 return;
1116 1116
1117 sched->all_runtime += work_list->total_runtime; 1117 sched->all_runtime += work_list->total_runtime;
1118 sched->all_count += work_list->nb_atoms; 1118 sched->all_count += work_list->nb_atoms;
1119 1119
1120 ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->tid); 1120 ret = printf(" %s:%d ", thread__comm_str(work_list->thread), work_list->thread->tid);
1121 1121
1122 for (i = 0; i < 24 - ret; i++) 1122 for (i = 0; i < 24 - ret; i++)
1123 printf(" "); 1123 printf(" ");
@@ -1334,7 +1334,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1334 printf(" %12.6f secs ", (double)timestamp/1e9); 1334 printf(" %12.6f secs ", (double)timestamp/1e9);
1335 if (new_shortname) { 1335 if (new_shortname) {
1336 printf("%s => %s:%d\n", 1336 printf("%s => %s:%d\n",
1337 sched_in->shortname, sched_in->comm, sched_in->tid); 1337 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid);
1338 } else { 1338 } else {
1339 printf("\n"); 1339 printf("\n");
1340 } 1340 }
@@ -1427,8 +1427,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1427 evsel->hists.stats.total_period += sample->period; 1427 evsel->hists.stats.total_period += sample->period;
1428 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 1428 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
1429 1429
1430 if (evsel->handler.func != NULL) { 1430 if (evsel->handler != NULL) {
1431 tracepoint_handler f = evsel->handler.func; 1431 tracepoint_handler f = evsel->handler;
1432 err = f(tool, evsel, sample, machine); 1432 err = f(tool, evsel, sample, machine);
1433 } 1433 }
1434 1434
@@ -1446,8 +1446,12 @@ static int perf_sched__read_events(struct perf_sched *sched,
1446 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1446 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1447 }; 1447 };
1448 struct perf_session *session; 1448 struct perf_session *session;
1449 struct perf_data_file file = {
1450 .path = input_name,
1451 .mode = PERF_DATA_MODE_READ,
1452 };
1449 1453
1450 session = perf_session__new(input_name, O_RDONLY, 0, false, &sched->tool); 1454 session = perf_session__new(&file, false, &sched->tool);
1451 if (session == NULL) { 1455 if (session == NULL) {
1452 pr_debug("No Memory for session\n"); 1456 pr_debug("No Memory for session\n");
1453 return -1; 1457 return -1;
@@ -1651,29 +1655,27 @@ static int __cmd_record(int argc, const char **argv)
1651 return cmd_record(i, rec_argv, NULL); 1655 return cmd_record(i, rec_argv, NULL);
1652} 1656}
1653 1657
1654static const char default_sort_order[] = "avg, max, switch, runtime";
1655static struct perf_sched sched = {
1656 .tool = {
1657 .sample = perf_sched__process_tracepoint_sample,
1658 .comm = perf_event__process_comm,
1659 .lost = perf_event__process_lost,
1660 .fork = perf_sched__process_fork_event,
1661 .ordered_samples = true,
1662 },
1663 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1664 .sort_list = LIST_HEAD_INIT(sched.sort_list),
1665 .start_work_mutex = PTHREAD_MUTEX_INITIALIZER,
1666 .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
1667 .curr_pid = { [0 ... MAX_CPUS - 1] = -1 },
1668 .sort_order = default_sort_order,
1669 .replay_repeat = 10,
1670 .profile_cpu = -1,
1671 .next_shortname1 = 'A',
1672 .next_shortname2 = '0',
1673};
1674
1675int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) 1658int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1676{ 1659{
1660 const char default_sort_order[] = "avg, max, switch, runtime";
1661 struct perf_sched sched = {
1662 .tool = {
1663 .sample = perf_sched__process_tracepoint_sample,
1664 .comm = perf_event__process_comm,
1665 .lost = perf_event__process_lost,
1666 .fork = perf_sched__process_fork_event,
1667 .ordered_samples = true,
1668 },
1669 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1670 .sort_list = LIST_HEAD_INIT(sched.sort_list),
1671 .start_work_mutex = PTHREAD_MUTEX_INITIALIZER,
1672 .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
1673 .sort_order = default_sort_order,
1674 .replay_repeat = 10,
1675 .profile_cpu = -1,
1676 .next_shortname1 = 'A',
1677 .next_shortname2 = '0',
1678 };
1677 const struct option latency_options[] = { 1679 const struct option latency_options[] = {
1678 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", 1680 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
1679 "sort by key(s): runtime, switch, avg, max"), 1681 "sort by key(s): runtime, switch, avg, max"),
@@ -1729,6 +1731,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1729 .switch_event = replay_switch_event, 1731 .switch_event = replay_switch_event,
1730 .fork_event = replay_fork_event, 1732 .fork_event = replay_fork_event,
1731 }; 1733 };
1734 unsigned int i;
1735
1736 for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++)
1737 sched.curr_pid[i] = -1;
1732 1738
1733 argc = parse_options(argc, argv, sched_options, sched_usage, 1739 argc = parse_options(argc, argv, sched_options, sched_usage,
1734 PARSE_OPT_STOP_AT_NON_OPTION); 1740 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9c333ff3dfeb..baf17989a216 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -15,6 +15,7 @@
15#include "util/evlist.h" 15#include "util/evlist.h"
16#include "util/evsel.h" 16#include "util/evsel.h"
17#include "util/sort.h" 17#include "util/sort.h"
18#include "util/data.h"
18#include <linux/bitmap.h> 19#include <linux/bitmap.h>
19 20
20static char const *script_name; 21static char const *script_name;
@@ -228,6 +229,24 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
228 return 0; 229 return 0;
229} 230}
230 231
232static void set_print_ip_opts(struct perf_event_attr *attr)
233{
234 unsigned int type = attr->type;
235
236 output[type].print_ip_opts = 0;
237 if (PRINT_FIELD(IP))
238 output[type].print_ip_opts |= PRINT_IP_OPT_IP;
239
240 if (PRINT_FIELD(SYM))
241 output[type].print_ip_opts |= PRINT_IP_OPT_SYM;
242
243 if (PRINT_FIELD(DSO))
244 output[type].print_ip_opts |= PRINT_IP_OPT_DSO;
245
246 if (PRINT_FIELD(SYMOFFSET))
247 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
248}
249
231/* 250/*
232 * verify all user requested events exist and the samples 251 * verify all user requested events exist and the samples
233 * have the expected data 252 * have the expected data
@@ -236,7 +255,6 @@ static int perf_session__check_output_opt(struct perf_session *session)
236{ 255{
237 int j; 256 int j;
238 struct perf_evsel *evsel; 257 struct perf_evsel *evsel;
239 struct perf_event_attr *attr;
240 258
241 for (j = 0; j < PERF_TYPE_MAX; ++j) { 259 for (j = 0; j < PERF_TYPE_MAX; ++j) {
242 evsel = perf_session__find_first_evtype(session, j); 260 evsel = perf_session__find_first_evtype(session, j);
@@ -259,20 +277,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
259 if (evsel == NULL) 277 if (evsel == NULL)
260 continue; 278 continue;
261 279
262 attr = &evsel->attr; 280 set_print_ip_opts(&evsel->attr);
263
264 output[j].print_ip_opts = 0;
265 if (PRINT_FIELD(IP))
266 output[j].print_ip_opts |= PRINT_IP_OPT_IP;
267
268 if (PRINT_FIELD(SYM))
269 output[j].print_ip_opts |= PRINT_IP_OPT_SYM;
270
271 if (PRINT_FIELD(DSO))
272 output[j].print_ip_opts |= PRINT_IP_OPT_DSO;
273
274 if (PRINT_FIELD(SYMOFFSET))
275 output[j].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
276 } 281 }
277 282
278 return 0; 283 return 0;
@@ -290,11 +295,11 @@ static void print_sample_start(struct perf_sample *sample,
290 295
291 if (PRINT_FIELD(COMM)) { 296 if (PRINT_FIELD(COMM)) {
292 if (latency_format) 297 if (latency_format)
293 printf("%8.8s ", thread->comm); 298 printf("%8.8s ", thread__comm_str(thread));
294 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) 299 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
295 printf("%s ", thread->comm); 300 printf("%s ", thread__comm_str(thread));
296 else 301 else
297 printf("%16s ", thread->comm); 302 printf("%16s ", thread__comm_str(thread));
298 } 303 }
299 304
300 if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) 305 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
@@ -409,7 +414,9 @@ static void print_sample_bts(union perf_event *event,
409 printf(" => "); 414 printf(" => ");
410 415
411 /* print branch_to information */ 416 /* print branch_to information */
412 if (PRINT_FIELD(ADDR)) 417 if (PRINT_FIELD(ADDR) ||
418 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
419 !output[attr->type].user_set))
413 print_sample_addr(event, sample, machine, thread, attr); 420 print_sample_addr(event, sample, machine, thread, attr);
414 421
415 printf("\n"); 422 printf("\n");
@@ -539,32 +546,51 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
539 return 0; 546 return 0;
540} 547}
541 548
542static struct perf_tool perf_script = { 549struct perf_script {
543 .sample = process_sample_event, 550 struct perf_tool tool;
544 .mmap = perf_event__process_mmap, 551 struct perf_session *session;
545 .mmap2 = perf_event__process_mmap2,
546 .comm = perf_event__process_comm,
547 .exit = perf_event__process_exit,
548 .fork = perf_event__process_fork,
549 .attr = perf_event__process_attr,
550 .tracing_data = perf_event__process_tracing_data,
551 .build_id = perf_event__process_build_id,
552 .ordered_samples = true,
553 .ordering_requires_timestamps = true,
554}; 552};
555 553
554static int process_attr(struct perf_tool *tool, union perf_event *event,
555 struct perf_evlist **pevlist)
556{
557 struct perf_script *scr = container_of(tool, struct perf_script, tool);
558 struct perf_evlist *evlist;
559 struct perf_evsel *evsel, *pos;
560 int err;
561
562 err = perf_event__process_attr(tool, event, pevlist);
563 if (err)
564 return err;
565
566 evlist = *pevlist;
567 evsel = perf_evlist__last(*pevlist);
568
569 if (evsel->attr.type >= PERF_TYPE_MAX)
570 return 0;
571
572 list_for_each_entry(pos, &evlist->entries, node) {
573 if (pos->attr.type == evsel->attr.type && pos != evsel)
574 return 0;
575 }
576
577 set_print_ip_opts(&evsel->attr);
578
579 return perf_evsel__check_attr(evsel, scr->session);
580}
581
556static void sig_handler(int sig __maybe_unused) 582static void sig_handler(int sig __maybe_unused)
557{ 583{
558 session_done = 1; 584 session_done = 1;
559} 585}
560 586
561static int __cmd_script(struct perf_session *session) 587static int __cmd_script(struct perf_script *script)
562{ 588{
563 int ret; 589 int ret;
564 590
565 signal(SIGINT, sig_handler); 591 signal(SIGINT, sig_handler);
566 592
567 ret = perf_session__process_events(session, &perf_script); 593 ret = perf_session__process_events(script->session, &script->tool);
568 594
569 if (debug_mode) 595 if (debug_mode)
570 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 596 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1113,10 +1139,14 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
1113 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; 1139 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
1114 DIR *scripts_dir, *lang_dir; 1140 DIR *scripts_dir, *lang_dir;
1115 struct perf_session *session; 1141 struct perf_session *session;
1142 struct perf_data_file file = {
1143 .path = input_name,
1144 .mode = PERF_DATA_MODE_READ,
1145 };
1116 char *temp; 1146 char *temp;
1117 int i = 0; 1147 int i = 0;
1118 1148
1119 session = perf_session__new(input_name, O_RDONLY, 0, false, NULL); 1149 session = perf_session__new(&file, false, NULL);
1120 if (!session) 1150 if (!session)
1121 return -1; 1151 return -1;
1122 1152
@@ -1266,6 +1296,21 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1266 char *script_path = NULL; 1296 char *script_path = NULL;
1267 const char **__argv; 1297 const char **__argv;
1268 int i, j, err; 1298 int i, j, err;
1299 struct perf_script script = {
1300 .tool = {
1301 .sample = process_sample_event,
1302 .mmap = perf_event__process_mmap,
1303 .mmap2 = perf_event__process_mmap2,
1304 .comm = perf_event__process_comm,
1305 .exit = perf_event__process_exit,
1306 .fork = perf_event__process_fork,
1307 .attr = process_attr,
1308 .tracing_data = perf_event__process_tracing_data,
1309 .build_id = perf_event__process_build_id,
1310 .ordered_samples = true,
1311 .ordering_requires_timestamps = true,
1312 },
1313 };
1269 const struct option options[] = { 1314 const struct option options[] = {
1270 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1315 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1271 "dump raw trace in ASCII"), 1316 "dump raw trace in ASCII"),
@@ -1317,12 +1362,17 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1317 "perf script [<options>] <top-script> [script-args]", 1362 "perf script [<options>] <top-script> [script-args]",
1318 NULL 1363 NULL
1319 }; 1364 };
1365 struct perf_data_file file = {
1366 .mode = PERF_DATA_MODE_READ,
1367 };
1320 1368
1321 setup_scripting(); 1369 setup_scripting();
1322 1370
1323 argc = parse_options(argc, argv, options, script_usage, 1371 argc = parse_options(argc, argv, options, script_usage,
1324 PARSE_OPT_STOP_AT_NON_OPTION); 1372 PARSE_OPT_STOP_AT_NON_OPTION);
1325 1373
1374 file.path = input_name;
1375
1326 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 1376 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
1327 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 1377 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
1328 if (!rec_script_path) 1378 if (!rec_script_path)
@@ -1486,11 +1536,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1486 if (!script_name) 1536 if (!script_name)
1487 setup_pager(); 1537 setup_pager();
1488 1538
1489 session = perf_session__new(input_name, O_RDONLY, 0, false, 1539 session = perf_session__new(&file, false, &script.tool);
1490 &perf_script);
1491 if (session == NULL) 1540 if (session == NULL)
1492 return -ENOMEM; 1541 return -ENOMEM;
1493 1542
1543 script.session = session;
1544
1494 if (cpu_list) { 1545 if (cpu_list) {
1495 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1546 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
1496 return -1; 1547 return -1;
@@ -1514,7 +1565,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1514 return -1; 1565 return -1;
1515 } 1566 }
1516 1567
1517 input = open(session->filename, O_RDONLY); /* input_name */ 1568 input = open(file.path, O_RDONLY); /* input_name */
1518 if (input < 0) { 1569 if (input < 0) {
1519 perror("failed to open file"); 1570 perror("failed to open file");
1520 return -1; 1571 return -1;
@@ -1554,7 +1605,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1554 if (err < 0) 1605 if (err < 0)
1555 goto out; 1606 goto out;
1556 1607
1557 err = __cmd_script(session); 1608 err = __cmd_script(&script);
1558 1609
1559 perf_session__delete(session); 1610 perf_session__delete(session);
1560 cleanup_scripting(); 1611 cleanup_scripting();
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 5098f144b92d..0fc1c941a73c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -46,6 +46,7 @@
46#include "util/util.h" 46#include "util/util.h"
47#include "util/parse-options.h" 47#include "util/parse-options.h"
48#include "util/parse-events.h" 48#include "util/parse-events.h"
49#include "util/pmu.h"
49#include "util/event.h" 50#include "util/event.h"
50#include "util/evlist.h" 51#include "util/evlist.h"
51#include "util/evsel.h" 52#include "util/evsel.h"
@@ -70,6 +71,41 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix);
70static void print_counter(struct perf_evsel *counter, char *prefix); 71static void print_counter(struct perf_evsel *counter, char *prefix);
71static void print_aggr(char *prefix); 72static void print_aggr(char *prefix);
72 73
74/* Default events used for perf stat -T */
75static const char * const transaction_attrs[] = {
76 "task-clock",
77 "{"
78 "instructions,"
79 "cycles,"
80 "cpu/cycles-t/,"
81 "cpu/tx-start/,"
82 "cpu/el-start/,"
83 "cpu/cycles-ct/"
84 "}"
85};
86
87/* More limited version when the CPU does not have all events. */
88static const char * const transaction_limited_attrs[] = {
89 "task-clock",
90 "{"
91 "instructions,"
92 "cycles,"
93 "cpu/cycles-t/,"
94 "cpu/tx-start/"
95 "}"
96};
97
98/* must match transaction_attrs and the beginning limited_attrs */
99enum {
100 T_TASK_CLOCK,
101 T_INSTRUCTIONS,
102 T_CYCLES,
103 T_CYCLES_IN_TX,
104 T_TRANSACTION_START,
105 T_ELISION_START,
106 T_CYCLES_IN_TX_CP,
107};
108
73static struct perf_evlist *evsel_list; 109static struct perf_evlist *evsel_list;
74 110
75static struct perf_target target = { 111static struct perf_target target = {
@@ -90,6 +126,7 @@ static enum aggr_mode aggr_mode = AGGR_GLOBAL;
90static volatile pid_t child_pid = -1; 126static volatile pid_t child_pid = -1;
91static bool null_run = false; 127static bool null_run = false;
92static int detailed_run = 0; 128static int detailed_run = 0;
129static bool transaction_run;
93static bool big_num = true; 130static bool big_num = true;
94static int big_num_opt = -1; 131static int big_num_opt = -1;
95static const char *csv_sep = NULL; 132static const char *csv_sep = NULL;
@@ -214,7 +251,10 @@ static struct stats runtime_l1_icache_stats[MAX_NR_CPUS];
214static struct stats runtime_ll_cache_stats[MAX_NR_CPUS]; 251static struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
215static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS]; 252static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
216static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; 253static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
254static struct stats runtime_cycles_in_tx_stats[MAX_NR_CPUS];
217static struct stats walltime_nsecs_stats; 255static struct stats walltime_nsecs_stats;
256static struct stats runtime_transaction_stats[MAX_NR_CPUS];
257static struct stats runtime_elision_stats[MAX_NR_CPUS];
218 258
219static void perf_stat__reset_stats(struct perf_evlist *evlist) 259static void perf_stat__reset_stats(struct perf_evlist *evlist)
220{ 260{
@@ -236,6 +276,11 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)
236 memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats)); 276 memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats));
237 memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats)); 277 memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats));
238 memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats)); 278 memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats));
279 memset(runtime_cycles_in_tx_stats, 0,
280 sizeof(runtime_cycles_in_tx_stats));
281 memset(runtime_transaction_stats, 0,
282 sizeof(runtime_transaction_stats));
283 memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
239 memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); 284 memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
240} 285}
241 286
@@ -274,6 +319,29 @@ static inline int nsec_counter(struct perf_evsel *evsel)
274 return 0; 319 return 0;
275} 320}
276 321
322static struct perf_evsel *nth_evsel(int n)
323{
324 static struct perf_evsel **array;
325 static int array_len;
326 struct perf_evsel *ev;
327 int j;
328
329 /* Assumes this only called when evsel_list does not change anymore. */
330 if (!array) {
331 list_for_each_entry(ev, &evsel_list->entries, node)
332 array_len++;
333 array = malloc(array_len * sizeof(void *));
334 if (!array)
335 exit(ENOMEM);
336 j = 0;
337 list_for_each_entry(ev, &evsel_list->entries, node)
338 array[j++] = ev;
339 }
340 if (n < array_len)
341 return array[n];
342 return NULL;
343}
344
277/* 345/*
278 * Update various tracking values we maintain to print 346 * Update various tracking values we maintain to print
279 * more semantic information such as miss/hit ratios, 347 * more semantic information such as miss/hit ratios,
@@ -285,6 +353,15 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
285 update_stats(&runtime_nsecs_stats[0], count[0]); 353 update_stats(&runtime_nsecs_stats[0], count[0]);
286 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 354 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
287 update_stats(&runtime_cycles_stats[0], count[0]); 355 update_stats(&runtime_cycles_stats[0], count[0]);
356 else if (transaction_run &&
357 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
358 update_stats(&runtime_cycles_in_tx_stats[0], count[0]);
359 else if (transaction_run &&
360 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
361 update_stats(&runtime_transaction_stats[0], count[0]);
362 else if (transaction_run &&
363 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
364 update_stats(&runtime_elision_stats[0], count[0]);
288 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 365 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
289 update_stats(&runtime_stalled_cycles_front_stats[0], count[0]); 366 update_stats(&runtime_stalled_cycles_front_stats[0], count[0]);
290 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 367 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
@@ -629,10 +706,13 @@ static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
629{ 706{
630 double msecs = avg / 1e6; 707 double msecs = avg / 1e6;
631 const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s"; 708 const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s";
709 char name[25];
632 710
633 aggr_printout(evsel, cpu, nr); 711 aggr_printout(evsel, cpu, nr);
634 712
635 fprintf(output, fmt, msecs, csv_sep, perf_evsel__name(evsel)); 713 scnprintf(name, sizeof(name), "%s%s",
714 perf_evsel__name(evsel), csv_output ? "" : " (msec)");
715 fprintf(output, fmt, msecs, csv_sep, name);
636 716
637 if (evsel->cgrp) 717 if (evsel->cgrp)
638 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 718 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -828,7 +908,7 @@ static void print_ll_cache_misses(int cpu,
828 908
829static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 909static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
830{ 910{
831 double total, ratio = 0.0; 911 double total, ratio = 0.0, total2;
832 const char *fmt; 912 const char *fmt;
833 913
834 if (csv_output) 914 if (csv_output)
@@ -853,11 +933,10 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
853 933
854 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 934 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
855 total = avg_stats(&runtime_cycles_stats[cpu]); 935 total = avg_stats(&runtime_cycles_stats[cpu]);
856 if (total) 936 if (total) {
857 ratio = avg / total; 937 ratio = avg / total;
858 938 fprintf(output, " # %5.2f insns per cycle ", ratio);
859 fprintf(output, " # %5.2f insns per cycle ", ratio); 939 }
860
861 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 940 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
862 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 941 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
863 942
@@ -920,10 +999,47 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
920 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 999 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
921 total = avg_stats(&runtime_nsecs_stats[cpu]); 1000 total = avg_stats(&runtime_nsecs_stats[cpu]);
922 1001
1002 if (total) {
1003 ratio = avg / total;
1004 fprintf(output, " # %8.3f GHz ", ratio);
1005 }
1006 } else if (transaction_run &&
1007 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
1008 total = avg_stats(&runtime_cycles_stats[cpu]);
1009 if (total)
1010 fprintf(output,
1011 " # %5.2f%% transactional cycles ",
1012 100.0 * (avg / total));
1013 } else if (transaction_run &&
1014 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX_CP))) {
1015 total = avg_stats(&runtime_cycles_stats[cpu]);
1016 total2 = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1017 if (total2 < avg)
1018 total2 = avg;
1019 if (total)
1020 fprintf(output,
1021 " # %5.2f%% aborted cycles ",
1022 100.0 * ((total2-avg) / total));
1023 } else if (transaction_run &&
1024 perf_evsel__cmp(evsel, nth_evsel(T_TRANSACTION_START)) &&
1025 avg > 0 &&
1026 runtime_cycles_in_tx_stats[cpu].n != 0) {
1027 total = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1028
923 if (total) 1029 if (total)
924 ratio = 1.0 * avg / total; 1030 ratio = total / avg;
925 1031
926 fprintf(output, " # %8.3f GHz ", ratio); 1032 fprintf(output, " # %8.0f cycles / transaction ", ratio);
1033 } else if (transaction_run &&
1034 perf_evsel__cmp(evsel, nth_evsel(T_ELISION_START)) &&
1035 avg > 0 &&
1036 runtime_cycles_in_tx_stats[cpu].n != 0) {
1037 total = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1038
1039 if (total)
1040 ratio = total / avg;
1041
1042 fprintf(output, " # %8.0f cycles / elision ", ratio);
927 } else if (runtime_nsecs_stats[cpu].n != 0) { 1043 } else if (runtime_nsecs_stats[cpu].n != 0) {
928 char unit = 'M'; 1044 char unit = 'M';
929 1045
@@ -1116,7 +1232,11 @@ static void print_stat(int argc, const char **argv)
1116 if (!csv_output) { 1232 if (!csv_output) {
1117 fprintf(output, "\n"); 1233 fprintf(output, "\n");
1118 fprintf(output, " Performance counter stats for "); 1234 fprintf(output, " Performance counter stats for ");
1119 if (!perf_target__has_task(&target)) { 1235 if (target.system_wide)
1236 fprintf(output, "\'system wide");
1237 else if (target.cpu_list)
1238 fprintf(output, "\'CPU(s) %s", target.cpu_list);
1239 else if (!perf_target__has_task(&target)) {
1120 fprintf(output, "\'%s", argv[0]); 1240 fprintf(output, "\'%s", argv[0]);
1121 for (i = 1; i < argc; i++) 1241 for (i = 1; i < argc; i++)
1122 fprintf(output, " %s", argv[i]); 1242 fprintf(output, " %s", argv[i]);
@@ -1237,6 +1357,16 @@ static int perf_stat_init_aggr_mode(void)
1237 return 0; 1357 return 0;
1238} 1358}
1239 1359
1360static int setup_events(const char * const *attrs, unsigned len)
1361{
1362 unsigned i;
1363
1364 for (i = 0; i < len; i++) {
1365 if (parse_events(evsel_list, attrs[i]))
1366 return -1;
1367 }
1368 return 0;
1369}
1240 1370
1241/* 1371/*
1242 * Add default attributes, if there were no attributes specified or 1372 * Add default attributes, if there were no attributes specified or
@@ -1355,6 +1485,22 @@ static int add_default_attributes(void)
1355 if (null_run) 1485 if (null_run)
1356 return 0; 1486 return 0;
1357 1487
1488 if (transaction_run) {
1489 int err;
1490 if (pmu_have_event("cpu", "cycles-ct") &&
1491 pmu_have_event("cpu", "el-start"))
1492 err = setup_events(transaction_attrs,
1493 ARRAY_SIZE(transaction_attrs));
1494 else
1495 err = setup_events(transaction_limited_attrs,
1496 ARRAY_SIZE(transaction_limited_attrs));
1497 if (err < 0) {
1498 fprintf(stderr, "Cannot set up transaction events\n");
1499 return -1;
1500 }
1501 return 0;
1502 }
1503
1358 if (!evsel_list->nr_entries) { 1504 if (!evsel_list->nr_entries) {
1359 if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0) 1505 if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0)
1360 return -1; 1506 return -1;
@@ -1389,6 +1535,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1389 int output_fd = 0; 1535 int output_fd = 0;
1390 const char *output_name = NULL; 1536 const char *output_name = NULL;
1391 const struct option options[] = { 1537 const struct option options[] = {
1538 OPT_BOOLEAN('T', "transaction", &transaction_run,
1539 "hardware transaction statistics"),
1392 OPT_CALLBACK('e', "event", &evsel_list, "event", 1540 OPT_CALLBACK('e', "event", &evsel_list, "event",
1393 "event selector. use 'perf list' to list available events", 1541 "event selector. use 'perf list' to list available events",
1394 parse_events_option), 1542 parse_events_option),
@@ -1448,7 +1596,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1448 "perf stat [<options>] [<command>]", 1596 "perf stat [<options>] [<command>]",
1449 NULL 1597 NULL
1450 }; 1598 };
1451 int status = -ENOMEM, run_idx; 1599 int status = -EINVAL, run_idx;
1452 const char *mode; 1600 const char *mode;
1453 1601
1454 setlocale(LC_ALL, ""); 1602 setlocale(LC_ALL, "");
@@ -1466,12 +1614,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1466 1614
1467 if (output_name && output_fd) { 1615 if (output_name && output_fd) {
1468 fprintf(stderr, "cannot use both --output and --log-fd\n"); 1616 fprintf(stderr, "cannot use both --output and --log-fd\n");
1469 usage_with_options(stat_usage, options); 1617 parse_options_usage(stat_usage, options, "o", 1);
1618 parse_options_usage(NULL, options, "log-fd", 0);
1619 goto out;
1470 } 1620 }
1471 1621
1472 if (output_fd < 0) { 1622 if (output_fd < 0) {
1473 fprintf(stderr, "argument to --log-fd must be a > 0\n"); 1623 fprintf(stderr, "argument to --log-fd must be a > 0\n");
1474 usage_with_options(stat_usage, options); 1624 parse_options_usage(stat_usage, options, "log-fd", 0);
1625 goto out;
1475 } 1626 }
1476 1627
1477 if (!output) { 1628 if (!output) {
@@ -1508,16 +1659,21 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1508 /* User explicitly passed -B? */ 1659 /* User explicitly passed -B? */
1509 if (big_num_opt == 1) { 1660 if (big_num_opt == 1) {
1510 fprintf(stderr, "-B option not supported with -x\n"); 1661 fprintf(stderr, "-B option not supported with -x\n");
1511 usage_with_options(stat_usage, options); 1662 parse_options_usage(stat_usage, options, "B", 1);
1663 parse_options_usage(NULL, options, "x", 1);
1664 goto out;
1512 } else /* Nope, so disable big number formatting */ 1665 } else /* Nope, so disable big number formatting */
1513 big_num = false; 1666 big_num = false;
1514 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1667 } else if (big_num_opt == 0) /* User passed --no-big-num */
1515 big_num = false; 1668 big_num = false;
1516 1669
1517 if (!argc && !perf_target__has_task(&target)) 1670 if (!argc && perf_target__none(&target))
1518 usage_with_options(stat_usage, options); 1671 usage_with_options(stat_usage, options);
1672
1519 if (run_count < 0) { 1673 if (run_count < 0) {
1520 usage_with_options(stat_usage, options); 1674 pr_err("Run count must be a positive number\n");
1675 parse_options_usage(stat_usage, options, "r", 1);
1676 goto out;
1521 } else if (run_count == 0) { 1677 } else if (run_count == 0) {
1522 forever = true; 1678 forever = true;
1523 run_count = 1; 1679 run_count = 1;
@@ -1529,8 +1685,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1529 fprintf(stderr, "both cgroup and no-aggregation " 1685 fprintf(stderr, "both cgroup and no-aggregation "
1530 "modes only available in system-wide mode\n"); 1686 "modes only available in system-wide mode\n");
1531 1687
1532 usage_with_options(stat_usage, options); 1688 parse_options_usage(stat_usage, options, "G", 1);
1533 return -1; 1689 parse_options_usage(NULL, options, "A", 1);
1690 parse_options_usage(NULL, options, "a", 1);
1691 goto out;
1534 } 1692 }
1535 1693
1536 if (add_default_attributes()) 1694 if (add_default_attributes())
@@ -1539,25 +1697,28 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1539 perf_target__validate(&target); 1697 perf_target__validate(&target);
1540 1698
1541 if (perf_evlist__create_maps(evsel_list, &target) < 0) { 1699 if (perf_evlist__create_maps(evsel_list, &target) < 0) {
1542 if (perf_target__has_task(&target)) 1700 if (perf_target__has_task(&target)) {
1543 pr_err("Problems finding threads of monitor\n"); 1701 pr_err("Problems finding threads of monitor\n");
1544 if (perf_target__has_cpu(&target)) 1702 parse_options_usage(stat_usage, options, "p", 1);
1703 parse_options_usage(NULL, options, "t", 1);
1704 } else if (perf_target__has_cpu(&target)) {
1545 perror("failed to parse CPUs map"); 1705 perror("failed to parse CPUs map");
1546 1706 parse_options_usage(stat_usage, options, "C", 1);
1547 usage_with_options(stat_usage, options); 1707 parse_options_usage(NULL, options, "a", 1);
1548 return -1; 1708 }
1709 goto out;
1549 } 1710 }
1550 if (interval && interval < 100) { 1711 if (interval && interval < 100) {
1551 pr_err("print interval must be >= 100ms\n"); 1712 pr_err("print interval must be >= 100ms\n");
1552 usage_with_options(stat_usage, options); 1713 parse_options_usage(stat_usage, options, "I", 1);
1553 return -1; 1714 goto out_free_maps;
1554 } 1715 }
1555 1716
1556 if (perf_evlist__alloc_stats(evsel_list, interval)) 1717 if (perf_evlist__alloc_stats(evsel_list, interval))
1557 goto out_free_maps; 1718 goto out_free_maps;
1558 1719
1559 if (perf_stat_init_aggr_mode()) 1720 if (perf_stat_init_aggr_mode())
1560 goto out; 1721 goto out_free_maps;
1561 1722
1562 /* 1723 /*
1563 * We dont want to block the signals - that would cause 1724 * We dont want to block the signals - that would cause
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index c2e02319347a..41c9bde2fb67 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -36,6 +36,7 @@
36#include "util/session.h" 36#include "util/session.h"
37#include "util/svghelper.h" 37#include "util/svghelper.h"
38#include "util/tool.h" 38#include "util/tool.h"
39#include "util/data.h"
39 40
40#define SUPPORT_OLD_POWER_EVENTS 1 41#define SUPPORT_OLD_POWER_EVENTS 1
41#define PWR_EVENT_EXIT -1 42#define PWR_EVENT_EXIT -1
@@ -482,8 +483,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
482 if (sample->cpu > numcpus) 483 if (sample->cpu > numcpus)
483 numcpus = sample->cpu; 484 numcpus = sample->cpu;
484 485
485 if (evsel->handler.func != NULL) { 486 if (evsel->handler != NULL) {
486 tracepoint_handler f = evsel->handler.func; 487 tracepoint_handler f = evsel->handler;
487 return f(evsel, sample); 488 return f(evsel, sample);
488 } 489 }
489 490
@@ -990,8 +991,13 @@ static int __cmd_timechart(const char *output_name)
990 { "power:power_frequency", process_sample_power_frequency }, 991 { "power:power_frequency", process_sample_power_frequency },
991#endif 992#endif
992 }; 993 };
993 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 994 struct perf_data_file file = {
994 0, false, &perf_timechart); 995 .path = input_name,
996 .mode = PERF_DATA_MODE_READ,
997 };
998
999 struct perf_session *session = perf_session__new(&file, false,
1000 &perf_timechart);
995 int ret = -EINVAL; 1001 int ret = -EINVAL;
996 1002
997 if (session == NULL) 1003 if (session == NULL)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 212214162bb2..9acca8856ccb 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -246,10 +246,10 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
246 struct hist_entry *he; 246 struct hist_entry *he;
247 247
248 pthread_mutex_lock(&evsel->hists.lock); 248 pthread_mutex_lock(&evsel->hists.lock);
249 he = __hists__add_entry(&evsel->hists, al, NULL, sample->period, 249 he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL,
250 sample->weight); 250 sample->period, sample->weight,
251 sample->transaction);
251 pthread_mutex_unlock(&evsel->hists.lock); 252 pthread_mutex_unlock(&evsel->hists.lock);
252
253 if (he == NULL) 253 if (he == NULL)
254 return NULL; 254 return NULL;
255 255
@@ -287,7 +287,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
287 return; 287 return;
288 } 288 }
289 289
290 hists__collapse_resort(&top->sym_evsel->hists); 290 hists__collapse_resort(&top->sym_evsel->hists, NULL);
291 hists__output_resort(&top->sym_evsel->hists); 291 hists__output_resort(&top->sym_evsel->hists);
292 hists__decay_entries(&top->sym_evsel->hists, 292 hists__decay_entries(&top->sym_evsel->hists,
293 top->hide_user_symbols, 293 top->hide_user_symbols,
@@ -553,7 +553,7 @@ static void perf_top__sort_new_samples(void *arg)
553 if (t->evlist->selected != NULL) 553 if (t->evlist->selected != NULL)
554 t->sym_evsel = t->evlist->selected; 554 t->sym_evsel = t->evlist->selected;
555 555
556 hists__collapse_resort(&t->sym_evsel->hists); 556 hists__collapse_resort(&t->sym_evsel->hists, NULL);
557 hists__output_resort(&t->sym_evsel->hists); 557 hists__output_resort(&t->sym_evsel->hists);
558 hists__decay_entries(&t->sym_evsel->hists, 558 hists__decay_entries(&t->sym_evsel->hists,
559 t->hide_user_symbols, 559 t->hide_user_symbols,
@@ -771,7 +771,8 @@ static void perf_event__process_sample(struct perf_tool *tool,
771 sample->callchain) { 771 sample->callchain) {
772 err = machine__resolve_callchain(machine, evsel, 772 err = machine__resolve_callchain(machine, evsel,
773 al.thread, sample, 773 al.thread, sample,
774 &parent, &al); 774 &parent, &al,
775 top->max_stack);
775 if (err) 776 if (err)
776 return; 777 return;
777 } 778 }
@@ -810,7 +811,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
810 ret = perf_evlist__parse_sample(top->evlist, event, &sample); 811 ret = perf_evlist__parse_sample(top->evlist, event, &sample);
811 if (ret) { 812 if (ret) {
812 pr_err("Can't parse sample, err = %d\n", ret); 813 pr_err("Can't parse sample, err = %d\n", ret);
813 continue; 814 goto next_event;
814 } 815 }
815 816
816 evsel = perf_evlist__id2evsel(session->evlist, sample.id); 817 evsel = perf_evlist__id2evsel(session->evlist, sample.id);
@@ -825,13 +826,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
825 case PERF_RECORD_MISC_USER: 826 case PERF_RECORD_MISC_USER:
826 ++top->us_samples; 827 ++top->us_samples;
827 if (top->hide_user_symbols) 828 if (top->hide_user_symbols)
828 continue; 829 goto next_event;
829 machine = &session->machines.host; 830 machine = &session->machines.host;
830 break; 831 break;
831 case PERF_RECORD_MISC_KERNEL: 832 case PERF_RECORD_MISC_KERNEL:
832 ++top->kernel_samples; 833 ++top->kernel_samples;
833 if (top->hide_kernel_symbols) 834 if (top->hide_kernel_symbols)
834 continue; 835 goto next_event;
835 machine = &session->machines.host; 836 machine = &session->machines.host;
836 break; 837 break;
837 case PERF_RECORD_MISC_GUEST_KERNEL: 838 case PERF_RECORD_MISC_GUEST_KERNEL:
@@ -847,7 +848,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
847 */ 848 */
848 /* Fall thru */ 849 /* Fall thru */
849 default: 850 default:
850 continue; 851 goto next_event;
851 } 852 }
852 853
853 854
@@ -856,9 +857,11 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
856 &sample, machine); 857 &sample, machine);
857 } else if (event->header.type < PERF_RECORD_MAX) { 858 } else if (event->header.type < PERF_RECORD_MAX) {
858 hists__inc_nr_events(&evsel->hists, event->header.type); 859 hists__inc_nr_events(&evsel->hists, event->header.type);
859 machine__process_event(machine, event); 860 machine__process_event(machine, event, &sample);
860 } else 861 } else
861 ++session->stats.nr_unknown_events; 862 ++session->stats.nr_unknown_events;
863next_event:
864 perf_evlist__mmap_consume(top->evlist, idx);
862 } 865 }
863} 866}
864 867
@@ -930,11 +933,8 @@ static int __cmd_top(struct perf_top *top)
930 struct perf_record_opts *opts = &top->record_opts; 933 struct perf_record_opts *opts = &top->record_opts;
931 pthread_t thread; 934 pthread_t thread;
932 int ret; 935 int ret;
933 /* 936
934 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 937 top->session = perf_session__new(NULL, false, NULL);
935 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
936 */
937 top->session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
938 if (top->session == NULL) 938 if (top->session == NULL)
939 return -ENOMEM; 939 return -ENOMEM;
940 940
@@ -1016,16 +1016,16 @@ out_delete:
1016} 1016}
1017 1017
1018static int 1018static int
1019parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1019callchain_opt(const struct option *opt, const char *arg, int unset)
1020{ 1020{
1021 /*
1022 * --no-call-graph
1023 */
1024 if (unset)
1025 return 0;
1026
1027 symbol_conf.use_callchain = true; 1021 symbol_conf.use_callchain = true;
1022 return record_callchain_opt(opt, arg, unset);
1023}
1028 1024
1025static int
1026parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1027{
1028 symbol_conf.use_callchain = true;
1029 return record_parse_callchain_opt(opt, arg, unset); 1029 return record_parse_callchain_opt(opt, arg, unset);
1030} 1030}
1031 1031
@@ -1041,7 +1041,7 @@ parse_percent_limit(const struct option *opt, const char *arg,
1041 1041
1042int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1042int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1043{ 1043{
1044 int status; 1044 int status = -1;
1045 char errbuf[BUFSIZ]; 1045 char errbuf[BUFSIZ];
1046 struct perf_top top = { 1046 struct perf_top top = {
1047 .count_filter = 5, 1047 .count_filter = 5,
@@ -1051,10 +1051,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1051 .user_freq = UINT_MAX, 1051 .user_freq = UINT_MAX,
1052 .user_interval = ULLONG_MAX, 1052 .user_interval = ULLONG_MAX,
1053 .freq = 4000, /* 4 KHz */ 1053 .freq = 4000, /* 4 KHz */
1054 .target = { 1054 .target = {
1055 .uses_mmap = true, 1055 .uses_mmap = true,
1056 }, 1056 },
1057 }, 1057 },
1058 .max_stack = PERF_MAX_STACK_DEPTH,
1058 .sym_pcnt_filter = 5, 1059 .sym_pcnt_filter = 5,
1059 }; 1060 };
1060 struct perf_record_opts *opts = &top.record_opts; 1061 struct perf_record_opts *opts = &top.record_opts;
@@ -1074,10 +1075,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1074 "list of cpus to monitor"), 1075 "list of cpus to monitor"),
1075 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1076 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1076 "file", "vmlinux pathname"), 1077 "file", "vmlinux pathname"),
1078 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
1079 "don't load vmlinux even if found"),
1077 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1080 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1078 "hide kernel symbols"), 1081 "hide kernel symbols"),
1079 OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages, 1082 OPT_CALLBACK('m', "mmap-pages", &opts->mmap_pages, "pages",
1080 "number of mmap data pages"), 1083 "number of mmap data pages",
1084 perf_evlist__parse_mmap_pages),
1081 OPT_INTEGER('r', "realtime", &top.realtime_prio, 1085 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1082 "collect data with this RT SCHED_FIFO priority"), 1086 "collect data with this RT SCHED_FIFO priority"),
1083 OPT_INTEGER('d', "delay", &top.delay_secs, 1087 OPT_INTEGER('d', "delay", &top.delay_secs,
@@ -1103,12 +1107,19 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1103 OPT_INCR('v', "verbose", &verbose, 1107 OPT_INCR('v', "verbose", &verbose,
1104 "be more verbose (show counter open errors, etc)"), 1108 "be more verbose (show counter open errors, etc)"),
1105 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1109 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1106 "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"), 1110 "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight,"
1111 " abort, in_tx, transaction"),
1107 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1112 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1108 "Show a column with the number of samples"), 1113 "Show a column with the number of samples"),
1109 OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, 1114 OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts,
1110 "mode[,dump_size]", record_callchain_help, 1115 NULL, "enables call-graph recording",
1111 &parse_callchain_opt, "fp"), 1116 &callchain_opt),
1117 OPT_CALLBACK(0, "call-graph", &top.record_opts,
1118 "mode[,dump_size]", record_callchain_help,
1119 &parse_callchain_opt),
1120 OPT_INTEGER(0, "max-stack", &top.max_stack,
1121 "Set the maximum stack depth when parsing the callchain. "
1122 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
1112 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 1123 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
1113 "ignore callees of these functions in call graphs", 1124 "ignore callees of these functions in call graphs",
1114 report_parse_ignore_callees_opt), 1125 report_parse_ignore_callees_opt),
@@ -1149,8 +1160,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1149 if (sort_order == default_sort_order) 1160 if (sort_order == default_sort_order)
1150 sort_order = "dso,symbol"; 1161 sort_order = "dso,symbol";
1151 1162
1152 if (setup_sorting() < 0) 1163 if (setup_sorting() < 0) {
1153 usage_with_options(top_usage, options); 1164 parse_options_usage(top_usage, options, "s", 1);
1165 goto out_delete_evlist;
1166 }
1154 1167
1155 /* display thread wants entries to be collapsed in a different tree */ 1168 /* display thread wants entries to be collapsed in a different tree */
1156 sort__need_collapse = 1; 1169 sort__need_collapse = 1;
@@ -1196,20 +1209,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1196 if (top.delay_secs < 1) 1209 if (top.delay_secs < 1)
1197 top.delay_secs = 1; 1210 top.delay_secs = 1;
1198 1211
1199 if (opts->user_interval != ULLONG_MAX) 1212 if (perf_record_opts__config(opts)) {
1200 opts->default_interval = opts->user_interval;
1201 if (opts->user_freq != UINT_MAX)
1202 opts->freq = opts->user_freq;
1203
1204 /*
1205 * User specified count overrides default frequency.
1206 */
1207 if (opts->default_interval)
1208 opts->freq = 0;
1209 else if (opts->freq) {
1210 opts->default_interval = opts->freq;
1211 } else {
1212 ui__error("frequency and count are zero, aborting\n");
1213 status = -EINVAL; 1213 status = -EINVAL;
1214 goto out_delete_maps; 1214 goto out_delete_maps;
1215 } 1215 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 71aa3e35406b..329b7832b5da 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -10,9 +10,11 @@
10#include "util/strlist.h" 10#include "util/strlist.h"
11#include "util/intlist.h" 11#include "util/intlist.h"
12#include "util/thread_map.h" 12#include "util/thread_map.h"
13#include "util/stat.h"
13 14
14#include <libaudit.h> 15#include <libaudit.h>
15#include <stdlib.h> 16#include <stdlib.h>
17#include <sys/eventfd.h>
16#include <sys/mman.h> 18#include <sys/mman.h>
17#include <linux/futex.h> 19#include <linux/futex.h>
18 20
@@ -33,49 +35,279 @@
33# define MADV_UNMERGEABLE 13 35# define MADV_UNMERGEABLE 13
34#endif 36#endif
35 37
36static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, 38struct tp_field {
37 unsigned long arg, 39 int offset;
38 u8 arg_idx __maybe_unused, 40 union {
39 u8 *arg_mask __maybe_unused) 41 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
42 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
43 };
44};
45
46#define TP_UINT_FIELD(bits) \
47static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
48{ \
49 return *(u##bits *)(sample->raw_data + field->offset); \
50}
51
52TP_UINT_FIELD(8);
53TP_UINT_FIELD(16);
54TP_UINT_FIELD(32);
55TP_UINT_FIELD(64);
56
57#define TP_UINT_FIELD__SWAPPED(bits) \
58static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
59{ \
60 u##bits value = *(u##bits *)(sample->raw_data + field->offset); \
61 return bswap_##bits(value);\
62}
63
64TP_UINT_FIELD__SWAPPED(16);
65TP_UINT_FIELD__SWAPPED(32);
66TP_UINT_FIELD__SWAPPED(64);
67
68static int tp_field__init_uint(struct tp_field *field,
69 struct format_field *format_field,
70 bool needs_swap)
40{ 71{
41 return scnprintf(bf, size, "%#lx", arg); 72 field->offset = format_field->offset;
73
74 switch (format_field->size) {
75 case 1:
76 field->integer = tp_field__u8;
77 break;
78 case 2:
79 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
80 break;
81 case 4:
82 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
83 break;
84 case 8:
85 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
86 break;
87 default:
88 return -1;
89 }
90
91 return 0;
42} 92}
43 93
44#define SCA_HEX syscall_arg__scnprintf_hex 94static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
95{
96 return sample->raw_data + field->offset;
97}
98
99static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
100{
101 field->offset = format_field->offset;
102 field->pointer = tp_field__ptr;
103 return 0;
104}
45 105
46static size_t syscall_arg__scnprintf_whence(char *bf, size_t size, 106struct syscall_tp {
47 unsigned long arg, 107 struct tp_field id;
48 u8 arg_idx __maybe_unused, 108 union {
49 u8 *arg_mask __maybe_unused) 109 struct tp_field args, ret;
110 };
111};
112
113static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
114 struct tp_field *field,
115 const char *name)
50{ 116{
51 int whence = arg; 117 struct format_field *format_field = perf_evsel__field(evsel, name);
52 118
53 switch (whence) { 119 if (format_field == NULL)
54#define P_WHENCE(n) case SEEK_##n: return scnprintf(bf, size, #n) 120 return -1;
55 P_WHENCE(SET); 121
56 P_WHENCE(CUR); 122 return tp_field__init_uint(field, format_field, evsel->needs_swap);
57 P_WHENCE(END); 123}
58#ifdef SEEK_DATA 124
59 P_WHENCE(DATA); 125#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
60#endif 126 ({ struct syscall_tp *sc = evsel->priv;\
61#ifdef SEEK_HOLE 127 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
62 P_WHENCE(HOLE); 128
63#endif 129static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
64#undef P_WHENCE 130 struct tp_field *field,
65 default: break; 131 const char *name)
132{
133 struct format_field *format_field = perf_evsel__field(evsel, name);
134
135 if (format_field == NULL)
136 return -1;
137
138 return tp_field__init_ptr(field, format_field);
139}
140
141#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
142 ({ struct syscall_tp *sc = evsel->priv;\
143 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
144
145static void perf_evsel__delete_priv(struct perf_evsel *evsel)
146{
147 free(evsel->priv);
148 evsel->priv = NULL;
149 perf_evsel__delete(evsel);
150}
151
152static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction,
153 void *handler, int idx)
154{
155 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction, idx);
156
157 if (evsel) {
158 evsel->priv = malloc(sizeof(struct syscall_tp));
159
160 if (evsel->priv == NULL)
161 goto out_delete;
162
163 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
164 goto out_delete;
165
166 evsel->handler = handler;
66 } 167 }
67 168
68 return scnprintf(bf, size, "%#x", whence); 169 return evsel;
170
171out_delete:
172 perf_evsel__delete_priv(evsel);
173 return NULL;
69} 174}
70 175
71#define SCA_WHENCE syscall_arg__scnprintf_whence 176#define perf_evsel__sc_tp_uint(evsel, name, sample) \
177 ({ struct syscall_tp *fields = evsel->priv; \
178 fields->name.integer(&fields->name, sample); })
179
180#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
181 ({ struct syscall_tp *fields = evsel->priv; \
182 fields->name.pointer(&fields->name, sample); })
183
184static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist,
185 void *sys_enter_handler,
186 void *sys_exit_handler)
187{
188 int ret = -1;
189 int idx = evlist->nr_entries;
190 struct perf_evsel *sys_enter, *sys_exit;
191
192 sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler, idx++);
193 if (sys_enter == NULL)
194 goto out;
195
196 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
197 goto out_delete_sys_enter;
198
199 sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler, idx++);
200 if (sys_exit == NULL)
201 goto out_delete_sys_enter;
202
203 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
204 goto out_delete_sys_exit;
205
206 perf_evlist__add(evlist, sys_enter);
207 perf_evlist__add(evlist, sys_exit);
208
209 ret = 0;
210out:
211 return ret;
212
213out_delete_sys_exit:
214 perf_evsel__delete_priv(sys_exit);
215out_delete_sys_enter:
216 perf_evsel__delete_priv(sys_enter);
217 goto out;
218}
219
220
221struct syscall_arg {
222 unsigned long val;
223 struct thread *thread;
224 struct trace *trace;
225 void *parm;
226 u8 idx;
227 u8 mask;
228};
229
230struct strarray {
231 int offset;
232 int nr_entries;
233 const char **entries;
234};
235
236#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
237 .nr_entries = ARRAY_SIZE(array), \
238 .entries = array, \
239}
240
241#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
242 .offset = off, \
243 .nr_entries = ARRAY_SIZE(array), \
244 .entries = array, \
245}
246
247static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
248 const char *intfmt,
249 struct syscall_arg *arg)
250{
251 struct strarray *sa = arg->parm;
252 int idx = arg->val - sa->offset;
253
254 if (idx < 0 || idx >= sa->nr_entries)
255 return scnprintf(bf, size, intfmt, arg->val);
256
257 return scnprintf(bf, size, "%s", sa->entries[idx]);
258}
259
260static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
261 struct syscall_arg *arg)
262{
263 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
264}
265
266#define SCA_STRARRAY syscall_arg__scnprintf_strarray
267
268static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
269 struct syscall_arg *arg)
270{
271 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
272}
273
274#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
275
276static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
277 struct syscall_arg *arg);
278
279#define SCA_FD syscall_arg__scnprintf_fd
280
281static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
282 struct syscall_arg *arg)
283{
284 int fd = arg->val;
285
286 if (fd == AT_FDCWD)
287 return scnprintf(bf, size, "CWD");
288
289 return syscall_arg__scnprintf_fd(bf, size, arg);
290}
291
292#define SCA_FDAT syscall_arg__scnprintf_fd_at
293
294static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
295 struct syscall_arg *arg);
296
297#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
298
299static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
300 struct syscall_arg *arg)
301{
302 return scnprintf(bf, size, "%#lx", arg->val);
303}
304
305#define SCA_HEX syscall_arg__scnprintf_hex
72 306
73static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 307static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
74 unsigned long arg, 308 struct syscall_arg *arg)
75 u8 arg_idx __maybe_unused,
76 u8 *arg_mask __maybe_unused)
77{ 309{
78 int printed = 0, prot = arg; 310 int printed = 0, prot = arg->val;
79 311
80 if (prot == PROT_NONE) 312 if (prot == PROT_NONE)
81 return scnprintf(bf, size, "NONE"); 313 return scnprintf(bf, size, "NONE");
@@ -104,10 +336,9 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
104#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot 336#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
105 337
106static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, 338static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
107 unsigned long arg, u8 arg_idx __maybe_unused, 339 struct syscall_arg *arg)
108 u8 *arg_mask __maybe_unused)
109{ 340{
110 int printed = 0, flags = arg; 341 int printed = 0, flags = arg->val;
111 342
112#define P_MMAP_FLAG(n) \ 343#define P_MMAP_FLAG(n) \
113 if (flags & MAP_##n) { \ 344 if (flags & MAP_##n) { \
@@ -148,10 +379,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
148#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 379#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
149 380
150static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 381static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
151 unsigned long arg, u8 arg_idx __maybe_unused, 382 struct syscall_arg *arg)
152 u8 *arg_mask __maybe_unused)
153{ 383{
154 int behavior = arg; 384 int behavior = arg->val;
155 385
156 switch (behavior) { 386 switch (behavior) {
157#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n) 387#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
@@ -190,8 +420,38 @@ static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
190 420
191#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior 421#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
192 422
193static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned long arg, 423static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
194 u8 arg_idx __maybe_unused, u8 *arg_mask) 424 struct syscall_arg *arg)
425{
426 int printed = 0, op = arg->val;
427
428 if (op == 0)
429 return scnprintf(bf, size, "NONE");
430#define P_CMD(cmd) \
431 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
432 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
433 op &= ~LOCK_##cmd; \
434 }
435
436 P_CMD(SH);
437 P_CMD(EX);
438 P_CMD(NB);
439 P_CMD(UN);
440 P_CMD(MAND);
441 P_CMD(RW);
442 P_CMD(READ);
443 P_CMD(WRITE);
444#undef P_OP
445
446 if (op)
447 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
448
449 return printed;
450}
451
452#define SCA_FLOCK syscall_arg__scnprintf_flock
453
454static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
195{ 455{
196 enum syscall_futex_args { 456 enum syscall_futex_args {
197 SCF_UADDR = (1 << 0), 457 SCF_UADDR = (1 << 0),
@@ -201,24 +461,24 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned lo
201 SCF_UADDR2 = (1 << 4), 461 SCF_UADDR2 = (1 << 4),
202 SCF_VAL3 = (1 << 5), 462 SCF_VAL3 = (1 << 5),
203 }; 463 };
204 int op = arg; 464 int op = arg->val;
205 int cmd = op & FUTEX_CMD_MASK; 465 int cmd = op & FUTEX_CMD_MASK;
206 size_t printed = 0; 466 size_t printed = 0;
207 467
208 switch (cmd) { 468 switch (cmd) {
209#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n); 469#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
210 P_FUTEX_OP(WAIT); *arg_mask |= SCF_VAL3|SCF_UADDR2; break; 470 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
211 P_FUTEX_OP(WAKE); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 471 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
212 P_FUTEX_OP(FD); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 472 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
213 P_FUTEX_OP(REQUEUE); *arg_mask |= SCF_VAL3|SCF_TIMEOUT; break; 473 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
214 P_FUTEX_OP(CMP_REQUEUE); *arg_mask |= SCF_TIMEOUT; break; 474 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
215 P_FUTEX_OP(CMP_REQUEUE_PI); *arg_mask |= SCF_TIMEOUT; break; 475 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
216 P_FUTEX_OP(WAKE_OP); break; 476 P_FUTEX_OP(WAKE_OP); break;
217 P_FUTEX_OP(LOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 477 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
218 P_FUTEX_OP(UNLOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 478 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
219 P_FUTEX_OP(TRYLOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2; break; 479 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
220 P_FUTEX_OP(WAIT_BITSET); *arg_mask |= SCF_UADDR2; break; 480 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
221 P_FUTEX_OP(WAKE_BITSET); *arg_mask |= SCF_UADDR2; break; 481 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
222 P_FUTEX_OP(WAIT_REQUEUE_PI); break; 482 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
223 default: printed = scnprintf(bf, size, "%#x", cmd); break; 483 default: printed = scnprintf(bf, size, "%#x", cmd); break;
224 } 484 }
@@ -234,14 +494,194 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned lo
234 494
235#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op 495#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
236 496
497static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
498static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
499
500static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
501static DEFINE_STRARRAY(itimers);
502
503static const char *whences[] = { "SET", "CUR", "END",
504#ifdef SEEK_DATA
505"DATA",
506#endif
507#ifdef SEEK_HOLE
508"HOLE",
509#endif
510};
511static DEFINE_STRARRAY(whences);
512
513static const char *fcntl_cmds[] = {
514 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
515 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
516 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
517 "F_GETOWNER_UIDS",
518};
519static DEFINE_STRARRAY(fcntl_cmds);
520
521static const char *rlimit_resources[] = {
522 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
523 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
524 "RTTIME",
525};
526static DEFINE_STRARRAY(rlimit_resources);
527
528static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
529static DEFINE_STRARRAY(sighow);
530
531static const char *clockid[] = {
532 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
533 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
534};
535static DEFINE_STRARRAY(clockid);
536
537static const char *socket_families[] = {
538 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
539 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
540 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
541 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
542 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
543 "ALG", "NFC", "VSOCK",
544};
545static DEFINE_STRARRAY(socket_families);
546
547#ifndef SOCK_TYPE_MASK
548#define SOCK_TYPE_MASK 0xf
549#endif
550
551static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
552 struct syscall_arg *arg)
553{
554 size_t printed;
555 int type = arg->val,
556 flags = type & ~SOCK_TYPE_MASK;
557
558 type &= SOCK_TYPE_MASK;
559 /*
560 * Can't use a strarray, MIPS may override for ABI reasons.
561 */
562 switch (type) {
563#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
564 P_SK_TYPE(STREAM);
565 P_SK_TYPE(DGRAM);
566 P_SK_TYPE(RAW);
567 P_SK_TYPE(RDM);
568 P_SK_TYPE(SEQPACKET);
569 P_SK_TYPE(DCCP);
570 P_SK_TYPE(PACKET);
571#undef P_SK_TYPE
572 default:
573 printed = scnprintf(bf, size, "%#x", type);
574 }
575
576#define P_SK_FLAG(n) \
577 if (flags & SOCK_##n) { \
578 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
579 flags &= ~SOCK_##n; \
580 }
581
582 P_SK_FLAG(CLOEXEC);
583 P_SK_FLAG(NONBLOCK);
584#undef P_SK_FLAG
585
586 if (flags)
587 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
588
589 return printed;
590}
591
592#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
593
594#ifndef MSG_PROBE
595#define MSG_PROBE 0x10
596#endif
597#ifndef MSG_WAITFORONE
598#define MSG_WAITFORONE 0x10000
599#endif
600#ifndef MSG_SENDPAGE_NOTLAST
601#define MSG_SENDPAGE_NOTLAST 0x20000
602#endif
603#ifndef MSG_FASTOPEN
604#define MSG_FASTOPEN 0x20000000
605#endif
606
607static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
608 struct syscall_arg *arg)
609{
610 int printed = 0, flags = arg->val;
611
612 if (flags == 0)
613 return scnprintf(bf, size, "NONE");
614#define P_MSG_FLAG(n) \
615 if (flags & MSG_##n) { \
616 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
617 flags &= ~MSG_##n; \
618 }
619
620 P_MSG_FLAG(OOB);
621 P_MSG_FLAG(PEEK);
622 P_MSG_FLAG(DONTROUTE);
623 P_MSG_FLAG(TRYHARD);
624 P_MSG_FLAG(CTRUNC);
625 P_MSG_FLAG(PROBE);
626 P_MSG_FLAG(TRUNC);
627 P_MSG_FLAG(DONTWAIT);
628 P_MSG_FLAG(EOR);
629 P_MSG_FLAG(WAITALL);
630 P_MSG_FLAG(FIN);
631 P_MSG_FLAG(SYN);
632 P_MSG_FLAG(CONFIRM);
633 P_MSG_FLAG(RST);
634 P_MSG_FLAG(ERRQUEUE);
635 P_MSG_FLAG(NOSIGNAL);
636 P_MSG_FLAG(MORE);
637 P_MSG_FLAG(WAITFORONE);
638 P_MSG_FLAG(SENDPAGE_NOTLAST);
639 P_MSG_FLAG(FASTOPEN);
640 P_MSG_FLAG(CMSG_CLOEXEC);
641#undef P_MSG_FLAG
642
643 if (flags)
644 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
645
646 return printed;
647}
648
649#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
650
651static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
652 struct syscall_arg *arg)
653{
654 size_t printed = 0;
655 int mode = arg->val;
656
657 if (mode == F_OK) /* 0 */
658 return scnprintf(bf, size, "F");
659#define P_MODE(n) \
660 if (mode & n##_OK) { \
661 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
662 mode &= ~n##_OK; \
663 }
664
665 P_MODE(R);
666 P_MODE(W);
667 P_MODE(X);
668#undef P_MODE
669
670 if (mode)
671 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
672
673 return printed;
674}
675
676#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
677
237static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, 678static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
238 unsigned long arg, 679 struct syscall_arg *arg)
239 u8 arg_idx, u8 *arg_mask)
240{ 680{
241 int printed = 0, flags = arg; 681 int printed = 0, flags = arg->val;
242 682
243 if (!(flags & O_CREAT)) 683 if (!(flags & O_CREAT))
244 *arg_mask |= 1 << (arg_idx + 1); /* Mask the mode parm */ 684 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
245 685
246 if (flags == 0) 686 if (flags == 0)
247 return scnprintf(bf, size, "RDONLY"); 687 return scnprintf(bf, size, "RDONLY");
@@ -291,32 +731,225 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
291 731
292#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags 732#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
293 733
734static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
735 struct syscall_arg *arg)
736{
737 int printed = 0, flags = arg->val;
738
739 if (flags == 0)
740 return scnprintf(bf, size, "NONE");
741#define P_FLAG(n) \
742 if (flags & EFD_##n) { \
743 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
744 flags &= ~EFD_##n; \
745 }
746
747 P_FLAG(SEMAPHORE);
748 P_FLAG(CLOEXEC);
749 P_FLAG(NONBLOCK);
750#undef P_FLAG
751
752 if (flags)
753 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
754
755 return printed;
756}
757
758#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
759
760static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
761 struct syscall_arg *arg)
762{
763 int printed = 0, flags = arg->val;
764
765#define P_FLAG(n) \
766 if (flags & O_##n) { \
767 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
768 flags &= ~O_##n; \
769 }
770
771 P_FLAG(CLOEXEC);
772 P_FLAG(NONBLOCK);
773#undef P_FLAG
774
775 if (flags)
776 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
777
778 return printed;
779}
780
781#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
782
783static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
784{
785 int sig = arg->val;
786
787 switch (sig) {
788#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
789 P_SIGNUM(HUP);
790 P_SIGNUM(INT);
791 P_SIGNUM(QUIT);
792 P_SIGNUM(ILL);
793 P_SIGNUM(TRAP);
794 P_SIGNUM(ABRT);
795 P_SIGNUM(BUS);
796 P_SIGNUM(FPE);
797 P_SIGNUM(KILL);
798 P_SIGNUM(USR1);
799 P_SIGNUM(SEGV);
800 P_SIGNUM(USR2);
801 P_SIGNUM(PIPE);
802 P_SIGNUM(ALRM);
803 P_SIGNUM(TERM);
804 P_SIGNUM(STKFLT);
805 P_SIGNUM(CHLD);
806 P_SIGNUM(CONT);
807 P_SIGNUM(STOP);
808 P_SIGNUM(TSTP);
809 P_SIGNUM(TTIN);
810 P_SIGNUM(TTOU);
811 P_SIGNUM(URG);
812 P_SIGNUM(XCPU);
813 P_SIGNUM(XFSZ);
814 P_SIGNUM(VTALRM);
815 P_SIGNUM(PROF);
816 P_SIGNUM(WINCH);
817 P_SIGNUM(IO);
818 P_SIGNUM(PWR);
819 P_SIGNUM(SYS);
820 default: break;
821 }
822
823 return scnprintf(bf, size, "%#x", sig);
824}
825
826#define SCA_SIGNUM syscall_arg__scnprintf_signum
827
828#define TCGETS 0x5401
829
830static const char *tioctls[] = {
831 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
832 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
833 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
834 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
835 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
836 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
837 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
838 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
839 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
840 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
841 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
842 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
843 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
844 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
845 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
846};
847
848static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
849
850#define STRARRAY(arg, name, array) \
851 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
852 .arg_parm = { [arg] = &strarray__##array, }
853
294static struct syscall_fmt { 854static struct syscall_fmt {
295 const char *name; 855 const char *name;
296 const char *alias; 856 const char *alias;
297 size_t (*arg_scnprintf[6])(char *bf, size_t size, unsigned long arg, u8 arg_idx, u8 *arg_mask); 857 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
858 void *arg_parm[6];
298 bool errmsg; 859 bool errmsg;
299 bool timeout; 860 bool timeout;
300 bool hexret; 861 bool hexret;
301} syscall_fmts[] = { 862} syscall_fmts[] = {
302 { .name = "access", .errmsg = true, }, 863 { .name = "access", .errmsg = true,
864 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
303 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 865 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
304 { .name = "brk", .hexret = true, 866 { .name = "brk", .hexret = true,
305 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 867 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
306 { .name = "mmap", .hexret = true, }, 868 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
869 { .name = "close", .errmsg = true,
870 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
307 { .name = "connect", .errmsg = true, }, 871 { .name = "connect", .errmsg = true, },
308 { .name = "fstat", .errmsg = true, .alias = "newfstat", }, 872 { .name = "dup", .errmsg = true,
309 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, 873 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
874 { .name = "dup2", .errmsg = true,
875 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
876 { .name = "dup3", .errmsg = true,
877 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
878 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
879 { .name = "eventfd2", .errmsg = true,
880 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
881 { .name = "faccessat", .errmsg = true,
882 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
883 { .name = "fadvise64", .errmsg = true,
884 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
885 { .name = "fallocate", .errmsg = true,
886 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
887 { .name = "fchdir", .errmsg = true,
888 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
889 { .name = "fchmod", .errmsg = true,
890 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
891 { .name = "fchmodat", .errmsg = true,
892 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
893 { .name = "fchown", .errmsg = true,
894 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
895 { .name = "fchownat", .errmsg = true,
896 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
897 { .name = "fcntl", .errmsg = true,
898 .arg_scnprintf = { [0] = SCA_FD, /* fd */
899 [1] = SCA_STRARRAY, /* cmd */ },
900 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
901 { .name = "fdatasync", .errmsg = true,
902 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
903 { .name = "flock", .errmsg = true,
904 .arg_scnprintf = { [0] = SCA_FD, /* fd */
905 [1] = SCA_FLOCK, /* cmd */ }, },
906 { .name = "fsetxattr", .errmsg = true,
907 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
908 { .name = "fstat", .errmsg = true, .alias = "newfstat",
909 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
910 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
911 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
912 { .name = "fstatfs", .errmsg = true,
913 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
914 { .name = "fsync", .errmsg = true,
915 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
916 { .name = "ftruncate", .errmsg = true,
917 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
310 { .name = "futex", .errmsg = true, 918 { .name = "futex", .errmsg = true,
311 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, 919 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
920 { .name = "futimesat", .errmsg = true,
921 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
922 { .name = "getdents", .errmsg = true,
923 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
924 { .name = "getdents64", .errmsg = true,
925 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
926 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
927 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
312 { .name = "ioctl", .errmsg = true, 928 { .name = "ioctl", .errmsg = true,
313 .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, }, 929 .arg_scnprintf = { [0] = SCA_FD, /* fd */
930 [1] = SCA_STRHEXARRAY, /* cmd */
931 [2] = SCA_HEX, /* arg */ },
932 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
933 { .name = "kill", .errmsg = true,
934 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
935 { .name = "linkat", .errmsg = true,
936 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
314 { .name = "lseek", .errmsg = true, 937 { .name = "lseek", .errmsg = true,
315 .arg_scnprintf = { [2] = SCA_WHENCE, /* whence */ }, }, 938 .arg_scnprintf = { [0] = SCA_FD, /* fd */
939 [2] = SCA_STRARRAY, /* whence */ },
940 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
316 { .name = "lstat", .errmsg = true, .alias = "newlstat", }, 941 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
317 { .name = "madvise", .errmsg = true, 942 { .name = "madvise", .errmsg = true,
318 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 943 .arg_scnprintf = { [0] = SCA_HEX, /* start */
319 [2] = SCA_MADV_BHV, /* behavior */ }, }, 944 [2] = SCA_MADV_BHV, /* behavior */ }, },
945 { .name = "mkdirat", .errmsg = true,
946 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
947 { .name = "mknodat", .errmsg = true,
948 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
949 { .name = "mlock", .errmsg = true,
950 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
951 { .name = "mlockall", .errmsg = true,
952 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
320 { .name = "mmap", .hexret = true, 953 { .name = "mmap", .hexret = true,
321 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 954 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
322 [2] = SCA_MMAP_PROT, /* prot */ 955 [2] = SCA_MMAP_PROT, /* prot */
@@ -327,24 +960,91 @@ static struct syscall_fmt {
327 { .name = "mremap", .hexret = true, 960 { .name = "mremap", .hexret = true,
328 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 961 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
329 [4] = SCA_HEX, /* new_addr */ }, }, 962 [4] = SCA_HEX, /* new_addr */ }, },
963 { .name = "munlock", .errmsg = true,
964 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
330 { .name = "munmap", .errmsg = true, 965 { .name = "munmap", .errmsg = true,
331 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 966 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
967 { .name = "name_to_handle_at", .errmsg = true,
968 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
969 { .name = "newfstatat", .errmsg = true,
970 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
332 { .name = "open", .errmsg = true, 971 { .name = "open", .errmsg = true,
333 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, 972 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
334 { .name = "open_by_handle_at", .errmsg = true, 973 { .name = "open_by_handle_at", .errmsg = true,
335 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 974 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
975 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
336 { .name = "openat", .errmsg = true, 976 { .name = "openat", .errmsg = true,
337 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 977 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
978 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
979 { .name = "pipe2", .errmsg = true,
980 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
338 { .name = "poll", .errmsg = true, .timeout = true, }, 981 { .name = "poll", .errmsg = true, .timeout = true, },
339 { .name = "ppoll", .errmsg = true, .timeout = true, }, 982 { .name = "ppoll", .errmsg = true, .timeout = true, },
340 { .name = "pread", .errmsg = true, .alias = "pread64", }, 983 { .name = "pread", .errmsg = true, .alias = "pread64",
341 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, 984 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
342 { .name = "read", .errmsg = true, }, 985 { .name = "preadv", .errmsg = true, .alias = "pread",
343 { .name = "recvfrom", .errmsg = true, }, 986 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
987 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
988 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
989 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
990 { .name = "pwritev", .errmsg = true,
991 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
992 { .name = "read", .errmsg = true,
993 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
994 { .name = "readlinkat", .errmsg = true,
995 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
996 { .name = "readv", .errmsg = true,
997 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
998 { .name = "recvfrom", .errmsg = true,
999 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1000 { .name = "recvmmsg", .errmsg = true,
1001 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1002 { .name = "recvmsg", .errmsg = true,
1003 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1004 { .name = "renameat", .errmsg = true,
1005 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1006 { .name = "rt_sigaction", .errmsg = true,
1007 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
1008 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
1009 { .name = "rt_sigqueueinfo", .errmsg = true,
1010 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1011 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1012 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
344 { .name = "select", .errmsg = true, .timeout = true, }, 1013 { .name = "select", .errmsg = true, .timeout = true, },
345 { .name = "socket", .errmsg = true, }, 1014 { .name = "sendmmsg", .errmsg = true,
1015 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1016 { .name = "sendmsg", .errmsg = true,
1017 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1018 { .name = "sendto", .errmsg = true,
1019 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1020 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1021 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1022 { .name = "shutdown", .errmsg = true,
1023 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1024 { .name = "socket", .errmsg = true,
1025 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1026 [1] = SCA_SK_TYPE, /* type */ },
1027 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1028 { .name = "socketpair", .errmsg = true,
1029 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1030 [1] = SCA_SK_TYPE, /* type */ },
1031 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
346 { .name = "stat", .errmsg = true, .alias = "newstat", }, 1032 { .name = "stat", .errmsg = true, .alias = "newstat", },
1033 { .name = "symlinkat", .errmsg = true,
1034 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1035 { .name = "tgkill", .errmsg = true,
1036 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1037 { .name = "tkill", .errmsg = true,
1038 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
347 { .name = "uname", .errmsg = true, .alias = "newuname", }, 1039 { .name = "uname", .errmsg = true, .alias = "newuname", },
1040 { .name = "unlinkat", .errmsg = true,
1041 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1042 { .name = "utimensat", .errmsg = true,
1043 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
1044 { .name = "write", .errmsg = true,
1045 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1046 { .name = "writev", .errmsg = true,
1047 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
348}; 1048};
349 1049
350static int syscall_fmt__cmp(const void *name, const void *fmtp) 1050static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -364,8 +1064,8 @@ struct syscall {
364 const char *name; 1064 const char *name;
365 bool filtered; 1065 bool filtered;
366 struct syscall_fmt *fmt; 1066 struct syscall_fmt *fmt;
367 size_t (**arg_scnprintf)(char *bf, size_t size, 1067 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
368 unsigned long arg, u8 arg_idx, u8 *args_mask); 1068 void **arg_parm;
369}; 1069};
370 1070
371static size_t fprintf_duration(unsigned long t, FILE *fp) 1071static size_t fprintf_duration(unsigned long t, FILE *fp)
@@ -389,11 +1089,24 @@ struct thread_trace {
389 unsigned long nr_events; 1089 unsigned long nr_events;
390 char *entry_str; 1090 char *entry_str;
391 double runtime_ms; 1091 double runtime_ms;
1092 struct {
1093 int max;
1094 char **table;
1095 } paths;
1096
1097 struct intlist *syscall_stats;
392}; 1098};
393 1099
394static struct thread_trace *thread_trace__new(void) 1100static struct thread_trace *thread_trace__new(void)
395{ 1101{
396 return zalloc(sizeof(struct thread_trace)); 1102 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1103
1104 if (ttrace)
1105 ttrace->paths.max = -1;
1106
1107 ttrace->syscall_stats = intlist__new(NULL);
1108
1109 return ttrace;
397} 1110}
398 1111
399static struct thread_trace *thread__trace(struct thread *thread, FILE *fp) 1112static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
@@ -421,26 +1134,140 @@ fail:
421 1134
422struct trace { 1135struct trace {
423 struct perf_tool tool; 1136 struct perf_tool tool;
424 int audit_machine; 1137 struct {
1138 int machine;
1139 int open_id;
1140 } audit;
425 struct { 1141 struct {
426 int max; 1142 int max;
427 struct syscall *table; 1143 struct syscall *table;
428 } syscalls; 1144 } syscalls;
429 struct perf_record_opts opts; 1145 struct perf_record_opts opts;
430 struct machine host; 1146 struct machine *host;
431 u64 base_time; 1147 u64 base_time;
1148 bool full_time;
432 FILE *output; 1149 FILE *output;
433 unsigned long nr_events; 1150 unsigned long nr_events;
434 struct strlist *ev_qualifier; 1151 struct strlist *ev_qualifier;
435 bool not_ev_qualifier; 1152 bool not_ev_qualifier;
1153 bool live;
1154 const char *last_vfs_getname;
436 struct intlist *tid_list; 1155 struct intlist *tid_list;
437 struct intlist *pid_list; 1156 struct intlist *pid_list;
438 bool sched; 1157 bool sched;
439 bool multiple_threads; 1158 bool multiple_threads;
1159 bool summary;
1160 bool show_comm;
1161 bool show_tool_stats;
440 double duration_filter; 1162 double duration_filter;
441 double runtime_ms; 1163 double runtime_ms;
1164 struct {
1165 u64 vfs_getname, proc_getname;
1166 } stats;
442}; 1167};
443 1168
1169static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1170{
1171 struct thread_trace *ttrace = thread->priv;
1172
1173 if (fd > ttrace->paths.max) {
1174 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1175
1176 if (npath == NULL)
1177 return -1;
1178
1179 if (ttrace->paths.max != -1) {
1180 memset(npath + ttrace->paths.max + 1, 0,
1181 (fd - ttrace->paths.max) * sizeof(char *));
1182 } else {
1183 memset(npath, 0, (fd + 1) * sizeof(char *));
1184 }
1185
1186 ttrace->paths.table = npath;
1187 ttrace->paths.max = fd;
1188 }
1189
1190 ttrace->paths.table[fd] = strdup(pathname);
1191
1192 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1193}
1194
1195static int thread__read_fd_path(struct thread *thread, int fd)
1196{
1197 char linkname[PATH_MAX], pathname[PATH_MAX];
1198 struct stat st;
1199 int ret;
1200
1201 if (thread->pid_ == thread->tid) {
1202 scnprintf(linkname, sizeof(linkname),
1203 "/proc/%d/fd/%d", thread->pid_, fd);
1204 } else {
1205 scnprintf(linkname, sizeof(linkname),
1206 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1207 }
1208
1209 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1210 return -1;
1211
1212 ret = readlink(linkname, pathname, sizeof(pathname));
1213
1214 if (ret < 0 || ret > st.st_size)
1215 return -1;
1216
1217 pathname[ret] = '\0';
1218 return trace__set_fd_pathname(thread, fd, pathname);
1219}
1220
1221static const char *thread__fd_path(struct thread *thread, int fd,
1222 struct trace *trace)
1223{
1224 struct thread_trace *ttrace = thread->priv;
1225
1226 if (ttrace == NULL)
1227 return NULL;
1228
1229 if (fd < 0)
1230 return NULL;
1231
1232 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL))
1233 if (!trace->live)
1234 return NULL;
1235 ++trace->stats.proc_getname;
1236 if (thread__read_fd_path(thread, fd)) {
1237 return NULL;
1238 }
1239
1240 return ttrace->paths.table[fd];
1241}
1242
1243static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1244 struct syscall_arg *arg)
1245{
1246 int fd = arg->val;
1247 size_t printed = scnprintf(bf, size, "%d", fd);
1248 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
1249
1250 if (path)
1251 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1252
1253 return printed;
1254}
1255
1256static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1257 struct syscall_arg *arg)
1258{
1259 int fd = arg->val;
1260 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1261 struct thread_trace *ttrace = arg->thread->priv;
1262
1263 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
1264 free(ttrace->paths.table[fd]);
1265 ttrace->paths.table[fd] = NULL;
1266 }
1267
1268 return printed;
1269}
1270
444static bool trace__filter_duration(struct trace *trace, double t) 1271static bool trace__filter_duration(struct trace *trace, double t)
445{ 1272{
446 return t < (trace->duration_filter * NSEC_PER_MSEC); 1273 return t < (trace->duration_filter * NSEC_PER_MSEC);
@@ -454,10 +1281,12 @@ static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
454} 1281}
455 1282
456static bool done = false; 1283static bool done = false;
1284static bool interrupted = false;
457 1285
458static void sig_handler(int sig __maybe_unused) 1286static void sig_handler(int sig)
459{ 1287{
460 done = true; 1288 done = true;
1289 interrupted = sig == SIGINT;
461} 1290}
462 1291
463static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, 1292static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
@@ -466,14 +1295,17 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
466 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); 1295 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
467 printed += fprintf_duration(duration, fp); 1296 printed += fprintf_duration(duration, fp);
468 1297
469 if (trace->multiple_threads) 1298 if (trace->multiple_threads) {
1299 if (trace->show_comm)
1300 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
470 printed += fprintf(fp, "%d ", thread->tid); 1301 printed += fprintf(fp, "%d ", thread->tid);
1302 }
471 1303
472 return printed; 1304 return printed;
473} 1305}
474 1306
475static int trace__process_event(struct trace *trace, struct machine *machine, 1307static int trace__process_event(struct trace *trace, struct machine *machine,
476 union perf_event *event) 1308 union perf_event *event, struct perf_sample *sample)
477{ 1309{
478 int ret = 0; 1310 int ret = 0;
479 1311
@@ -481,9 +1313,9 @@ static int trace__process_event(struct trace *trace, struct machine *machine,
481 case PERF_RECORD_LOST: 1313 case PERF_RECORD_LOST:
482 color_fprintf(trace->output, PERF_COLOR_RED, 1314 color_fprintf(trace->output, PERF_COLOR_RED,
483 "LOST %" PRIu64 " events!\n", event->lost.lost); 1315 "LOST %" PRIu64 " events!\n", event->lost.lost);
484 ret = machine__process_lost_event(machine, event); 1316 ret = machine__process_lost_event(machine, event, sample);
485 default: 1317 default:
486 ret = machine__process_event(machine, event); 1318 ret = machine__process_event(machine, event, sample);
487 break; 1319 break;
488 } 1320 }
489 1321
@@ -492,11 +1324,11 @@ static int trace__process_event(struct trace *trace, struct machine *machine,
492 1324
493static int trace__tool_process(struct perf_tool *tool, 1325static int trace__tool_process(struct perf_tool *tool,
494 union perf_event *event, 1326 union perf_event *event,
495 struct perf_sample *sample __maybe_unused, 1327 struct perf_sample *sample,
496 struct machine *machine) 1328 struct machine *machine)
497{ 1329{
498 struct trace *trace = container_of(tool, struct trace, tool); 1330 struct trace *trace = container_of(tool, struct trace, tool);
499 return trace__process_event(trace, machine, event); 1331 return trace__process_event(trace, machine, event, sample);
500} 1332}
501 1333
502static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1334static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
@@ -506,16 +1338,17 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
506 if (err) 1338 if (err)
507 return err; 1339 return err;
508 1340
509 machine__init(&trace->host, "", HOST_KERNEL_ID); 1341 trace->host = machine__new_host();
510 machine__create_kernel_maps(&trace->host); 1342 if (trace->host == NULL)
1343 return -ENOMEM;
511 1344
512 if (perf_target__has_task(&trace->opts.target)) { 1345 if (perf_target__has_task(&trace->opts.target)) {
513 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, 1346 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
514 trace__tool_process, 1347 trace__tool_process,
515 &trace->host); 1348 trace->host);
516 } else { 1349 } else {
517 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, 1350 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
518 &trace->host); 1351 trace->host);
519 } 1352 }
520 1353
521 if (err) 1354 if (err)
@@ -533,6 +1366,9 @@ static int syscall__set_arg_fmts(struct syscall *sc)
533 if (sc->arg_scnprintf == NULL) 1366 if (sc->arg_scnprintf == NULL)
534 return -1; 1367 return -1;
535 1368
1369 if (sc->fmt)
1370 sc->arg_parm = sc->fmt->arg_parm;
1371
536 for (field = sc->tp_format->format.fields->next; field; field = field->next) { 1372 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
537 if (sc->fmt && sc->fmt->arg_scnprintf[idx]) 1373 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
538 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1374 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
@@ -548,7 +1384,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
548{ 1384{
549 char tp_name[128]; 1385 char tp_name[128];
550 struct syscall *sc; 1386 struct syscall *sc;
551 const char *name = audit_syscall_to_name(id, trace->audit_machine); 1387 const char *name = audit_syscall_to_name(id, trace->audit.machine);
552 1388
553 if (name == NULL) 1389 if (name == NULL)
554 return -1; 1390 return -1;
@@ -603,32 +1439,52 @@ static int trace__read_syscall_info(struct trace *trace, int id)
603} 1439}
604 1440
605static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1441static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
606 unsigned long *args) 1442 unsigned long *args, struct trace *trace,
1443 struct thread *thread)
607{ 1444{
608 int i = 0;
609 size_t printed = 0; 1445 size_t printed = 0;
610 1446
611 if (sc->tp_format != NULL) { 1447 if (sc->tp_format != NULL) {
612 struct format_field *field; 1448 struct format_field *field;
613 u8 mask = 0, bit = 1; 1449 u8 bit = 1;
1450 struct syscall_arg arg = {
1451 .idx = 0,
1452 .mask = 0,
1453 .trace = trace,
1454 .thread = thread,
1455 };
614 1456
615 for (field = sc->tp_format->format.fields->next; field; 1457 for (field = sc->tp_format->format.fields->next; field;
616 field = field->next, ++i, bit <<= 1) { 1458 field = field->next, ++arg.idx, bit <<= 1) {
617 if (mask & bit) 1459 if (arg.mask & bit)
1460 continue;
1461 /*
1462 * Suppress this argument if its value is zero and
1463 * and we don't have a string associated in an
1464 * strarray for it.
1465 */
1466 if (args[arg.idx] == 0 &&
1467 !(sc->arg_scnprintf &&
1468 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1469 sc->arg_parm[arg.idx]))
618 continue; 1470 continue;
619 1471
620 printed += scnprintf(bf + printed, size - printed, 1472 printed += scnprintf(bf + printed, size - printed,
621 "%s%s: ", printed ? ", " : "", field->name); 1473 "%s%s: ", printed ? ", " : "", field->name);
622 1474 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
623 if (sc->arg_scnprintf && sc->arg_scnprintf[i]) { 1475 arg.val = args[arg.idx];
624 printed += sc->arg_scnprintf[i](bf + printed, size - printed, 1476 if (sc->arg_parm)
625 args[i], i, &mask); 1477 arg.parm = sc->arg_parm[arg.idx];
1478 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1479 size - printed, &arg);
626 } else { 1480 } else {
627 printed += scnprintf(bf + printed, size - printed, 1481 printed += scnprintf(bf + printed, size - printed,
628 "%ld", args[i]); 1482 "%ld", args[arg.idx]);
629 } 1483 }
630 } 1484 }
631 } else { 1485 } else {
1486 int i = 0;
1487
632 while (i < 6) { 1488 while (i < 6) {
633 printed += scnprintf(bf + printed, size - printed, 1489 printed += scnprintf(bf + printed, size - printed,
634 "%sarg%d: %ld", 1490 "%sarg%d: %ld",
@@ -644,10 +1500,8 @@ typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
644 struct perf_sample *sample); 1500 struct perf_sample *sample);
645 1501
646static struct syscall *trace__syscall_info(struct trace *trace, 1502static struct syscall *trace__syscall_info(struct trace *trace,
647 struct perf_evsel *evsel, 1503 struct perf_evsel *evsel, int id)
648 struct perf_sample *sample)
649{ 1504{
650 int id = perf_evsel__intval(evsel, sample, "id");
651 1505
652 if (id < 0) { 1506 if (id < 0) {
653 1507
@@ -688,6 +1542,32 @@ out_cant_read:
688 return NULL; 1542 return NULL;
689} 1543}
690 1544
1545static void thread__update_stats(struct thread_trace *ttrace,
1546 int id, struct perf_sample *sample)
1547{
1548 struct int_node *inode;
1549 struct stats *stats;
1550 u64 duration = 0;
1551
1552 inode = intlist__findnew(ttrace->syscall_stats, id);
1553 if (inode == NULL)
1554 return;
1555
1556 stats = inode->priv;
1557 if (stats == NULL) {
1558 stats = malloc(sizeof(struct stats));
1559 if (stats == NULL)
1560 return;
1561 init_stats(stats);
1562 inode->priv = stats;
1563 }
1564
1565 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1566 duration = sample->time - ttrace->entry_time;
1567
1568 update_stats(stats, duration);
1569}
1570
691static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1571static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
692 struct perf_sample *sample) 1572 struct perf_sample *sample)
693{ 1573{
@@ -695,7 +1575,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
695 void *args; 1575 void *args;
696 size_t printed = 0; 1576 size_t printed = 0;
697 struct thread *thread; 1577 struct thread *thread;
698 struct syscall *sc = trace__syscall_info(trace, evsel, sample); 1578 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
1579 struct syscall *sc = trace__syscall_info(trace, evsel, id);
699 struct thread_trace *ttrace; 1580 struct thread_trace *ttrace;
700 1581
701 if (sc == NULL) 1582 if (sc == NULL)
@@ -704,18 +1585,12 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
704 if (sc->filtered) 1585 if (sc->filtered)
705 return 0; 1586 return 0;
706 1587
707 thread = machine__findnew_thread(&trace->host, sample->pid, 1588 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
708 sample->tid);
709 ttrace = thread__trace(thread, trace->output); 1589 ttrace = thread__trace(thread, trace->output);
710 if (ttrace == NULL) 1590 if (ttrace == NULL)
711 return -1; 1591 return -1;
712 1592
713 args = perf_evsel__rawptr(evsel, sample, "args"); 1593 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
714 if (args == NULL) {
715 fprintf(trace->output, "Problems reading syscall arguments\n");
716 return -1;
717 }
718
719 ttrace = thread->priv; 1594 ttrace = thread->priv;
720 1595
721 if (ttrace->entry_str == NULL) { 1596 if (ttrace->entry_str == NULL) {
@@ -728,7 +1603,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
728 msg = ttrace->entry_str; 1603 msg = ttrace->entry_str;
729 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); 1604 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
730 1605
731 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed, args); 1606 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
1607 args, trace, thread);
732 1608
733 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) { 1609 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
734 if (!trace->duration_filter) { 1610 if (!trace->duration_filter) {
@@ -747,7 +1623,8 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
747 int ret; 1623 int ret;
748 u64 duration = 0; 1624 u64 duration = 0;
749 struct thread *thread; 1625 struct thread *thread;
750 struct syscall *sc = trace__syscall_info(trace, evsel, sample); 1626 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
1627 struct syscall *sc = trace__syscall_info(trace, evsel, id);
751 struct thread_trace *ttrace; 1628 struct thread_trace *ttrace;
752 1629
753 if (sc == NULL) 1630 if (sc == NULL)
@@ -756,13 +1633,21 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
756 if (sc->filtered) 1633 if (sc->filtered)
757 return 0; 1634 return 0;
758 1635
759 thread = machine__findnew_thread(&trace->host, sample->pid, 1636 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
760 sample->tid);
761 ttrace = thread__trace(thread, trace->output); 1637 ttrace = thread__trace(thread, trace->output);
762 if (ttrace == NULL) 1638 if (ttrace == NULL)
763 return -1; 1639 return -1;
764 1640
765 ret = perf_evsel__intval(evsel, sample, "ret"); 1641 if (trace->summary)
1642 thread__update_stats(ttrace, id, sample);
1643
1644 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
1645
1646 if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
1647 trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
1648 trace->last_vfs_getname = NULL;
1649 ++trace->stats.vfs_getname;
1650 }
766 1651
767 ttrace = thread->priv; 1652 ttrace = thread->priv;
768 1653
@@ -808,12 +1693,19 @@ out:
808 return 0; 1693 return 0;
809} 1694}
810 1695
1696static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1697 struct perf_sample *sample)
1698{
1699 trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
1700 return 0;
1701}
1702
811static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel, 1703static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
812 struct perf_sample *sample) 1704 struct perf_sample *sample)
813{ 1705{
814 u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 1706 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
815 double runtime_ms = (double)runtime / NSEC_PER_MSEC; 1707 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
816 struct thread *thread = machine__findnew_thread(&trace->host, 1708 struct thread *thread = machine__findnew_thread(trace->host,
817 sample->pid, 1709 sample->pid,
818 sample->tid); 1710 sample->tid);
819 struct thread_trace *ttrace = thread__trace(thread, trace->output); 1711 struct thread_trace *ttrace = thread__trace(thread, trace->output);
@@ -856,12 +1748,12 @@ static int trace__process_sample(struct perf_tool *tool,
856 struct trace *trace = container_of(tool, struct trace, tool); 1748 struct trace *trace = container_of(tool, struct trace, tool);
857 int err = 0; 1749 int err = 0;
858 1750
859 tracepoint_handler handler = evsel->handler.func; 1751 tracepoint_handler handler = evsel->handler;
860 1752
861 if (skip_sample(trace, sample)) 1753 if (skip_sample(trace, sample))
862 return 0; 1754 return 0;
863 1755
864 if (trace->base_time == 0) 1756 if (!trace->full_time && trace->base_time == 0)
865 trace->base_time = sample->time; 1757 trace->base_time = sample->time;
866 1758
867 if (handler) 1759 if (handler)
@@ -901,6 +1793,51 @@ static int parse_target_str(struct trace *trace)
901 return 0; 1793 return 0;
902} 1794}
903 1795
1796static int trace__record(int argc, const char **argv)
1797{
1798 unsigned int rec_argc, i, j;
1799 const char **rec_argv;
1800 const char * const record_args[] = {
1801 "record",
1802 "-R",
1803 "-m", "1024",
1804 "-c", "1",
1805 "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
1806 };
1807
1808 rec_argc = ARRAY_SIZE(record_args) + argc;
1809 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1810
1811 if (rec_argv == NULL)
1812 return -ENOMEM;
1813
1814 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1815 rec_argv[i] = record_args[i];
1816
1817 for (j = 0; j < (unsigned int)argc; j++, i++)
1818 rec_argv[i] = argv[j];
1819
1820 return cmd_record(i, rec_argv, NULL);
1821}
1822
1823static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
1824
1825static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
1826{
1827 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname",
1828 evlist->nr_entries);
1829 if (evsel == NULL)
1830 return;
1831
1832 if (perf_evsel__field(evsel, "pathname") == NULL) {
1833 perf_evsel__delete(evsel);
1834 return;
1835 }
1836
1837 evsel->handler = trace__vfs_getname;
1838 perf_evlist__add(evlist, evsel);
1839}
1840
904static int trace__run(struct trace *trace, int argc, const char **argv) 1841static int trace__run(struct trace *trace, int argc, const char **argv)
905{ 1842{
906 struct perf_evlist *evlist = perf_evlist__new(); 1843 struct perf_evlist *evlist = perf_evlist__new();
@@ -909,23 +1846,22 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
909 unsigned long before; 1846 unsigned long before;
910 const bool forks = argc > 0; 1847 const bool forks = argc > 0;
911 1848
1849 trace->live = true;
1850
912 if (evlist == NULL) { 1851 if (evlist == NULL) {
913 fprintf(trace->output, "Not enough memory to run!\n"); 1852 fprintf(trace->output, "Not enough memory to run!\n");
914 goto out; 1853 goto out;
915 } 1854 }
916 1855
917 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) || 1856 if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit))
918 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) { 1857 goto out_error_tp;
919 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n"); 1858
920 goto out_delete_evlist; 1859 perf_evlist__add_vfs_getname(evlist);
921 }
922 1860
923 if (trace->sched && 1861 if (trace->sched &&
924 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 1862 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
925 trace__sched_stat_runtime)) { 1863 trace__sched_stat_runtime))
926 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n"); 1864 goto out_error_tp;
927 goto out_delete_evlist;
928 }
929 1865
930 err = perf_evlist__create_maps(evlist, &trace->opts.target); 1866 err = perf_evlist__create_maps(evlist, &trace->opts.target);
931 if (err < 0) { 1867 if (err < 0) {
@@ -954,10 +1890,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
954 } 1890 }
955 1891
956 err = perf_evlist__open(evlist); 1892 err = perf_evlist__open(evlist);
957 if (err < 0) { 1893 if (err < 0)
958 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno)); 1894 goto out_error_open;
959 goto out_delete_maps;
960 }
961 1895
962 err = perf_evlist__mmap(evlist, UINT_MAX, false); 1896 err = perf_evlist__mmap(evlist, UINT_MAX, false);
963 if (err < 0) { 1897 if (err < 0) {
@@ -987,51 +1921,65 @@ again:
987 err = perf_evlist__parse_sample(evlist, event, &sample); 1921 err = perf_evlist__parse_sample(evlist, event, &sample);
988 if (err) { 1922 if (err) {
989 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err); 1923 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
990 continue; 1924 goto next_event;
991 } 1925 }
992 1926
993 if (trace->base_time == 0) 1927 if (!trace->full_time && trace->base_time == 0)
994 trace->base_time = sample.time; 1928 trace->base_time = sample.time;
995 1929
996 if (type != PERF_RECORD_SAMPLE) { 1930 if (type != PERF_RECORD_SAMPLE) {
997 trace__process_event(trace, &trace->host, event); 1931 trace__process_event(trace, trace->host, event, &sample);
998 continue; 1932 continue;
999 } 1933 }
1000 1934
1001 evsel = perf_evlist__id2evsel(evlist, sample.id); 1935 evsel = perf_evlist__id2evsel(evlist, sample.id);
1002 if (evsel == NULL) { 1936 if (evsel == NULL) {
1003 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id); 1937 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
1004 continue; 1938 goto next_event;
1005 } 1939 }
1006 1940
1007 if (sample.raw_data == NULL) { 1941 if (sample.raw_data == NULL) {
1008 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", 1942 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
1009 perf_evsel__name(evsel), sample.tid, 1943 perf_evsel__name(evsel), sample.tid,
1010 sample.cpu, sample.raw_size); 1944 sample.cpu, sample.raw_size);
1011 continue; 1945 goto next_event;
1012 } 1946 }
1013 1947
1014 handler = evsel->handler.func; 1948 handler = evsel->handler;
1015 handler(trace, evsel, &sample); 1949 handler(trace, evsel, &sample);
1950next_event:
1951 perf_evlist__mmap_consume(evlist, i);
1016 1952
1017 if (done) 1953 if (interrupted)
1018 goto out_unmap_evlist; 1954 goto out_disable;
1019 } 1955 }
1020 } 1956 }
1021 1957
1022 if (trace->nr_events == before) { 1958 if (trace->nr_events == before) {
1023 if (done) 1959 int timeout = done ? 100 : -1;
1024 goto out_unmap_evlist;
1025 1960
1026 poll(evlist->pollfd, evlist->nr_fds, -1); 1961 if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0)
1962 goto again;
1963 } else {
1964 goto again;
1027 } 1965 }
1028 1966
1029 if (done) 1967out_disable:
1030 perf_evlist__disable(evlist); 1968 perf_evlist__disable(evlist);
1031 1969
1032 goto again; 1970 if (!err) {
1971 if (trace->summary)
1972 trace__fprintf_thread_summary(trace, trace->output);
1973
1974 if (trace->show_tool_stats) {
1975 fprintf(trace->output, "Stats:\n "
1976 " vfs_getname : %" PRIu64 "\n"
1977 " proc_getname: %" PRIu64 "\n",
1978 trace->stats.vfs_getname,
1979 trace->stats.proc_getname);
1980 }
1981 }
1033 1982
1034out_unmap_evlist:
1035 perf_evlist__munmap(evlist); 1983 perf_evlist__munmap(evlist);
1036out_close_evlist: 1984out_close_evlist:
1037 perf_evlist__close(evlist); 1985 perf_evlist__close(evlist);
@@ -1040,7 +1988,22 @@ out_delete_maps:
1040out_delete_evlist: 1988out_delete_evlist:
1041 perf_evlist__delete(evlist); 1989 perf_evlist__delete(evlist);
1042out: 1990out:
1991 trace->live = false;
1043 return err; 1992 return err;
1993{
1994 char errbuf[BUFSIZ];
1995
1996out_error_tp:
1997 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
1998 goto out_error;
1999
2000out_error_open:
2001 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2002
2003out_error:
2004 fprintf(trace->output, "%s\n", errbuf);
2005 goto out_delete_evlist;
2006}
1044} 2007}
1045 2008
1046static int trace__replay(struct trace *trace) 2009static int trace__replay(struct trace *trace)
@@ -1048,8 +2011,12 @@ static int trace__replay(struct trace *trace)
1048 const struct perf_evsel_str_handler handlers[] = { 2011 const struct perf_evsel_str_handler handlers[] = {
1049 { "raw_syscalls:sys_enter", trace__sys_enter, }, 2012 { "raw_syscalls:sys_enter", trace__sys_enter, },
1050 { "raw_syscalls:sys_exit", trace__sys_exit, }, 2013 { "raw_syscalls:sys_exit", trace__sys_exit, },
2014 { "probe:vfs_getname", trace__vfs_getname, },
2015 };
2016 struct perf_data_file file = {
2017 .path = input_name,
2018 .mode = PERF_DATA_MODE_READ,
1051 }; 2019 };
1052
1053 struct perf_session *session; 2020 struct perf_session *session;
1054 int err = -1; 2021 int err = -1;
1055 2022
@@ -1072,11 +2039,12 @@ static int trace__replay(struct trace *trace)
1072 if (symbol__init() < 0) 2039 if (symbol__init() < 0)
1073 return -1; 2040 return -1;
1074 2041
1075 session = perf_session__new(input_name, O_RDONLY, 0, false, 2042 session = perf_session__new(&file, false, &trace->tool);
1076 &trace->tool);
1077 if (session == NULL) 2043 if (session == NULL)
1078 return -ENOMEM; 2044 return -ENOMEM;
1079 2045
2046 trace->host = &session->machines.host;
2047
1080 err = perf_session__set_tracepoints_handlers(session, handlers); 2048 err = perf_session__set_tracepoints_handlers(session, handlers);
1081 if (err) 2049 if (err)
1082 goto out; 2050 goto out;
@@ -1101,6 +2069,9 @@ static int trace__replay(struct trace *trace)
1101 if (err) 2069 if (err)
1102 pr_err("Failed to process events, error %d", err); 2070 pr_err("Failed to process events, error %d", err);
1103 2071
2072 else if (trace->summary)
2073 trace__fprintf_thread_summary(trace, trace->output);
2074
1104out: 2075out:
1105 perf_session__delete(session); 2076 perf_session__delete(session);
1106 2077
@@ -1111,47 +2082,111 @@ static size_t trace__fprintf_threads_header(FILE *fp)
1111{ 2082{
1112 size_t printed; 2083 size_t printed;
1113 2084
1114 printed = fprintf(fp, "\n _____________________________________________________________________\n"); 2085 printed = fprintf(fp, "\n _____________________________________________________________________________\n");
1115 printed += fprintf(fp," __) Summary of events (__\n\n"); 2086 printed += fprintf(fp, " __) Summary of events (__\n\n");
1116 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n"); 2087 printed += fprintf(fp, " [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1117 printed += fprintf(fp," _____________________________________________________________________\n\n"); 2088 printed += fprintf(fp, " syscall count min max avg stddev\n");
2089 printed += fprintf(fp, " msec msec msec %%\n");
2090 printed += fprintf(fp, " _____________________________________________________________________________\n\n");
1118 2091
1119 return printed; 2092 return printed;
1120} 2093}
1121 2094
1122static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) 2095static size_t thread__dump_stats(struct thread_trace *ttrace,
2096 struct trace *trace, FILE *fp)
1123{ 2097{
1124 size_t printed = trace__fprintf_threads_header(fp); 2098 struct stats *stats;
1125 struct rb_node *nd; 2099 size_t printed = 0;
1126 2100 struct syscall *sc;
1127 for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) { 2101 struct int_node *inode = intlist__first(ttrace->syscall_stats);
1128 struct thread *thread = rb_entry(nd, struct thread, rb_node);
1129 struct thread_trace *ttrace = thread->priv;
1130 const char *color;
1131 double ratio;
1132
1133 if (ttrace == NULL)
1134 continue;
1135 2102
1136 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0; 2103 if (inode == NULL)
2104 return 0;
1137 2105
1138 color = PERF_COLOR_NORMAL; 2106 printed += fprintf(fp, "\n");
1139 if (ratio > 50.0) 2107
1140 color = PERF_COLOR_RED; 2108 /* each int_node is a syscall */
1141 else if (ratio > 25.0) 2109 while (inode) {
1142 color = PERF_COLOR_GREEN; 2110 stats = inode->priv;
1143 else if (ratio > 5.0) 2111 if (stats) {
1144 color = PERF_COLOR_YELLOW; 2112 double min = (double)(stats->min) / NSEC_PER_MSEC;
2113 double max = (double)(stats->max) / NSEC_PER_MSEC;
2114 double avg = avg_stats(stats);
2115 double pct;
2116 u64 n = (u64) stats->n;
2117
2118 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2119 avg /= NSEC_PER_MSEC;
2120
2121 sc = &trace->syscalls.table[inode->i];
2122 printed += fprintf(fp, "%24s %14s : ", "", sc->name);
2123 printed += fprintf(fp, "%5" PRIu64 " %8.3f %8.3f",
2124 n, min, max);
2125 printed += fprintf(fp, " %8.3f %6.2f\n", avg, pct);
2126 }
1145 2127
1146 printed += color_fprintf(fp, color, "%20s", thread->comm); 2128 inode = intlist__next(inode);
1147 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
1148 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1149 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1150 } 2129 }
1151 2130
2131 printed += fprintf(fp, "\n\n");
2132
1152 return printed; 2133 return printed;
1153} 2134}
1154 2135
2136/* struct used to pass data to per-thread function */
2137struct summary_data {
2138 FILE *fp;
2139 struct trace *trace;
2140 size_t printed;
2141};
2142
2143static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2144{
2145 struct summary_data *data = priv;
2146 FILE *fp = data->fp;
2147 size_t printed = data->printed;
2148 struct trace *trace = data->trace;
2149 struct thread_trace *ttrace = thread->priv;
2150 const char *color;
2151 double ratio;
2152
2153 if (ttrace == NULL)
2154 return 0;
2155
2156 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2157
2158 color = PERF_COLOR_NORMAL;
2159 if (ratio > 50.0)
2160 color = PERF_COLOR_RED;
2161 else if (ratio > 25.0)
2162 color = PERF_COLOR_GREEN;
2163 else if (ratio > 5.0)
2164 color = PERF_COLOR_YELLOW;
2165
2166 printed += color_fprintf(fp, color, "%20s", thread__comm_str(thread));
2167 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
2168 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
2169 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
2170 printed += thread__dump_stats(ttrace, trace, fp);
2171
2172 data->printed += printed;
2173
2174 return 0;
2175}
2176
2177static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2178{
2179 struct summary_data data = {
2180 .fp = fp,
2181 .trace = trace
2182 };
2183 data.printed = trace__fprintf_threads_header(fp);
2184
2185 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
2186
2187 return data.printed;
2188}
2189
1155static int trace__set_duration(const struct option *opt, const char *str, 2190static int trace__set_duration(const struct option *opt, const char *str,
1156 int unset __maybe_unused) 2191 int unset __maybe_unused)
1157{ 2192{
@@ -1183,10 +2218,15 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1183 const char * const trace_usage[] = { 2218 const char * const trace_usage[] = {
1184 "perf trace [<options>] [<command>]", 2219 "perf trace [<options>] [<command>]",
1185 "perf trace [<options>] -- <command> [<options>]", 2220 "perf trace [<options>] -- <command> [<options>]",
2221 "perf trace record [<options>] [<command>]",
2222 "perf trace record [<options>] -- <command> [<options>]",
1186 NULL 2223 NULL
1187 }; 2224 };
1188 struct trace trace = { 2225 struct trace trace = {
1189 .audit_machine = audit_detect_machine(), 2226 .audit = {
2227 .machine = audit_detect_machine(),
2228 .open_id = audit_name_to_syscall("open", trace.audit.machine),
2229 },
1190 .syscalls = { 2230 .syscalls = {
1191 . max = -1, 2231 . max = -1,
1192 }, 2232 },
@@ -1201,10 +2241,14 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1201 .mmap_pages = 1024, 2241 .mmap_pages = 1024,
1202 }, 2242 },
1203 .output = stdout, 2243 .output = stdout,
2244 .show_comm = true,
1204 }; 2245 };
1205 const char *output_name = NULL; 2246 const char *output_name = NULL;
1206 const char *ev_qualifier_str = NULL; 2247 const char *ev_qualifier_str = NULL;
1207 const struct option trace_options[] = { 2248 const struct option trace_options[] = {
2249 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2250 "show the thread COMM next to its id"),
2251 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
1208 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", 2252 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1209 "list of events to trace"), 2253 "list of events to trace"),
1210 OPT_STRING('o', "output", &output_name, "file", "output file name"), 2254 OPT_STRING('o', "output", &output_name, "file", "output file name"),
@@ -1219,8 +2263,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1219 "list of cpus to monitor"), 2263 "list of cpus to monitor"),
1220 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit, 2264 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
1221 "child tasks do not inherit counters"), 2265 "child tasks do not inherit counters"),
1222 OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages, 2266 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1223 "number of mmap data pages"), 2267 "number of mmap data pages",
2268 perf_evlist__parse_mmap_pages),
1224 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user", 2269 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
1225 "user to profile"), 2270 "user to profile"),
1226 OPT_CALLBACK(0, "duration", &trace, "float", 2271 OPT_CALLBACK(0, "duration", &trace, "float",
@@ -1228,11 +2273,18 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1228 trace__set_duration), 2273 trace__set_duration),
1229 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"), 2274 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
1230 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 2275 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
2276 OPT_BOOLEAN('T', "time", &trace.full_time,
2277 "Show full timestamp, not time relative to first start"),
2278 OPT_BOOLEAN(0, "summary", &trace.summary,
2279 "Show syscall summary with statistics"),
1231 OPT_END() 2280 OPT_END()
1232 }; 2281 };
1233 int err; 2282 int err;
1234 char bf[BUFSIZ]; 2283 char bf[BUFSIZ];
1235 2284
2285 if ((argc > 1) && (strcmp(argv[1], "record") == 0))
2286 return trace__record(argc-2, &argv[2]);
2287
1236 argc = parse_options(argc, argv, trace_options, trace_usage, 0); 2288 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
1237 2289
1238 if (output_name != NULL) { 2290 if (output_name != NULL) {
@@ -1280,9 +2332,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1280 else 2332 else
1281 err = trace__run(&trace, argc, argv); 2333 err = trace__run(&trace, argc, argv);
1282 2334
1283 if (trace.sched && !err)
1284 trace__fprintf_thread_summary(&trace, trace.output);
1285
1286out_close: 2335out_close:
1287 if (output_name != NULL) 2336 if (output_name != NULL)
1288 fclose(trace.output); 2337 fclose(trace.output);
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 75b93d7f7860..f5905f2b197d 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -23,11 +23,13 @@ ifeq ($(ARCH),x86_64)
23 endif 23 endif
24 ifeq (${IS_X86_64}, 1) 24 ifeq (${IS_X86_64}, 1)
25 RAW_ARCH := x86_64 25 RAW_ARCH := x86_64
26 CFLAGS += -DARCH_X86_64 26 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
27 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 27 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
28 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
29 else
30 LIBUNWIND_LIBS = -lunwind -lunwind-x86
28 endif 31 endif
29 NO_PERF_REGS := 0 32 NO_PERF_REGS := 0
30 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
31endif 33endif
32ifeq ($(ARCH),arm) 34ifeq ($(ARCH),arm)
33 NO_PERF_REGS := 0 35 NO_PERF_REGS := 0
@@ -35,7 +37,7 @@ ifeq ($(ARCH),arm)
35endif 37endif
36 38
37ifeq ($(NO_PERF_REGS),0) 39ifeq ($(NO_PERF_REGS),0)
38 CFLAGS += -DHAVE_PERF_REGS 40 CFLAGS += -DHAVE_PERF_REGS_SUPPORT
39endif 41endif
40 42
41ifeq ($(src-perf),) 43ifeq ($(src-perf),)
@@ -55,7 +57,6 @@ LIB_INCLUDE := $(srctree)/tools/lib/
55# include ARCH specific config 57# include ARCH specific config
56-include $(src-perf)/arch/$(ARCH)/Makefile 58-include $(src-perf)/arch/$(ARCH)/Makefile
57 59
58include $(src-perf)/config/feature-tests.mak
59include $(src-perf)/config/utilities.mak 60include $(src-perf)/config/utilities.mak
60 61
61ifeq ($(call get-executable,$(FLEX)),) 62ifeq ($(call get-executable,$(FLEX)),)
@@ -71,10 +72,11 @@ ifneq ($(WERROR),0)
71 CFLAGS += -Werror 72 CFLAGS += -Werror
72endif 73endif
73 74
74ifeq ("$(origin DEBUG)", "command line") 75ifndef DEBUG
75 PERF_DEBUG = $(DEBUG) 76 DEBUG := 0
76endif 77endif
77ifndef PERF_DEBUG 78
79ifeq ($(DEBUG),0)
78 CFLAGS += -O6 80 CFLAGS += -O6
79endif 81endif
80 82
@@ -93,20 +95,125 @@ CFLAGS += -std=gnu99
93 95
94EXTLIBS = -lelf -lpthread -lrt -lm -ldl 96EXTLIBS = -lelf -lpthread -lrt -lm -ldl
95 97
96ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) 98ifneq ($(OUTPUT),)
97 CFLAGS += -fstack-protector-all 99 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
100 $(shell mkdir -p $(OUTPUT_FEATURES))
98endif 101endif
99 102
100ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector,-Wstack-protector),y) 103feature_check = $(eval $(feature_check_code))
101 CFLAGS += -Wstack-protector 104define feature_check_code
105 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0)
106endef
107
108feature_set = $(eval $(feature_set_code))
109define feature_set_code
110 feature-$(1) := 1
111endef
112
113#
114# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
115#
116
117#
118# Note that this is not a complete list of all feature tests, just
119# those that are typically built on a fully configured system.
120#
121# [ Feature tests not mentioned here have to be built explicitly in
122# the rule that uses them - an example for that is the 'bionic'
123# feature check. ]
124#
125CORE_FEATURE_TESTS = \
126 backtrace \
127 dwarf \
128 fortify-source \
129 glibc \
130 gtk2 \
131 gtk2-infobar \
132 libaudit \
133 libbfd \
134 libelf \
135 libelf-getphdrnum \
136 libelf-mmap \
137 libnuma \
138 libperl \
139 libpython \
140 libpython-version \
141 libslang \
142 libunwind \
143 on-exit \
144 stackprotector \
145 stackprotector-all
146
147#
148# So here we detect whether test-all was rebuilt, to be able
149# to skip the print-out of the long features list if the file
150# existed before and after it was built:
151#
152ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all),)
153 test-all-failed := 1
154else
155 test-all-failed := 0
156endif
157
158#
159# Special fast-path for the 'all features are available' case:
160#
161$(call feature_check,all,$(MSG))
162
163#
164# Just in case the build freshly failed, make sure we print the
165# feature matrix:
166#
167ifeq ($(feature-all), 0)
168 test-all-failed := 1
169endif
170
171ifeq ($(test-all-failed),1)
172 $(info )
173 $(info Auto-detecting system features:)
174endif
175
176ifeq ($(feature-all), 1)
177 #
178 # test-all.c passed - just set all the core feature flags to 1:
179 #
180 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
181else
182 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1)
183 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
102endif 184endif
103 185
104ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var,-Wvolatile-register-var),y) 186#
105 CFLAGS += -Wvolatile-register-var 187# Print the result of the feature test:
188#
189feature_print = $(eval $(feature_print_code)) $(info $(MSG))
190
191define feature_print_code
192 ifeq ($(feature-$(1)), 1)
193 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
194 else
195 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
196 endif
197endef
198
199#
200# Only print out our features if we rebuilt the testcases or if a test failed:
201#
202ifeq ($(test-all-failed), 1)
203 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_print,$(feat)))
204 $(info )
205endif
206
207ifeq ($(feature-stackprotector-all), 1)
208 CFLAGS += -fstack-protector-all
106endif 209endif
107 210
108ifndef PERF_DEBUG 211ifeq ($(feature-stackprotector), 1)
109 ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -D_FORTIFY_SOURCE=2,-D_FORTIFY_SOURCE=2),y) 212 CFLAGS += -Wstack-protector
213endif
214
215ifeq ($(DEBUG),0)
216 ifeq ($(feature-fortify-source), 1)
110 CFLAGS += -D_FORTIFY_SOURCE=2 217 CFLAGS += -D_FORTIFY_SOURCE=2
111 endif 218 endif
112endif 219endif
@@ -132,84 +239,74 @@ CFLAGS += -I$(LIB_INCLUDE)
132CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 239CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
133 240
134ifndef NO_BIONIC 241ifndef NO_BIONIC
135ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) 242 $(call feature_check,bionic)
136 BIONIC := 1 243 ifeq ($(feature-bionic), 1)
137 EXTLIBS := $(filter-out -lrt,$(EXTLIBS)) 244 BIONIC := 1
138 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS)) 245 EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
246 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
247 endif
139endif 248endif
140endif # NO_BIONIC
141 249
142ifdef NO_LIBELF 250ifdef NO_LIBELF
143 NO_DWARF := 1 251 NO_DWARF := 1
144 NO_DEMANGLE := 1 252 NO_DEMANGLE := 1
145 NO_LIBUNWIND := 1 253 NO_LIBUNWIND := 1
146else 254else
147FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) 255 ifeq ($(feature-libelf), 0)
148ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y) 256 ifeq ($(feature-glibc), 1)
149 FLAGS_GLIBC=$(CFLAGS) $(LDFLAGS) 257 LIBC_SUPPORT := 1
150 ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC),glibc),y) 258 endif
151 LIBC_SUPPORT := 1 259 ifeq ($(BIONIC),1)
152 endif 260 LIBC_SUPPORT := 1
153 ifeq ($(BIONIC),1) 261 endif
154 LIBC_SUPPORT := 1 262 ifeq ($(LIBC_SUPPORT),1)
155 endif 263 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
156 ifeq ($(LIBC_SUPPORT),1)
157 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
158 264
159 NO_LIBELF := 1 265 NO_LIBELF := 1
160 NO_DWARF := 1 266 NO_DWARF := 1
161 NO_DEMANGLE := 1 267 NO_DEMANGLE := 1
268 else
269 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
270 endif
162 else 271 else
163 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); 272 # for linking with debug library, run like:
164 endif 273 # make DEBUG=1 LIBDW_DIR=/opt/libdw/
165else 274 ifdef LIBDW_DIR
166 # for linking with debug library, run like: 275 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
167 # make DEBUG=1 LIBDW_DIR=/opt/libdw/ 276 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
168 ifdef LIBDW_DIR 277 endif
169 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
170 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
171 endif
172 278
173 FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lz -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS) 279 ifneq ($(feature-dwarf), 1)
174 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) 280 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
175 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 281 NO_DWARF := 1
176 NO_DWARF := 1 282 endif # Dwarf support
177 endif # Dwarf support 283 endif # libelf support
178endif # SOURCE_LIBELF
179endif # NO_LIBELF 284endif # NO_LIBELF
180 285
181ifndef NO_LIBELF 286ifndef NO_LIBELF
182CFLAGS += -DLIBELF_SUPPORT 287 CFLAGS += -DHAVE_LIBELF_SUPPORT
183FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS)
184ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
185 CFLAGS += -DLIBELF_MMAP
186endif
187ifeq ($(call try-cc,$(SOURCE_ELF_GETPHDRNUM),$(FLAGS_LIBELF),-DHAVE_ELF_GETPHDRNUM),y)
188 CFLAGS += -DHAVE_ELF_GETPHDRNUM
189endif
190 288
191# include ARCH specific config 289 ifeq ($(feature-libelf-mmap), 1)
192-include $(src-perf)/arch/$(ARCH)/Makefile 290 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
291 endif
193 292
194ifndef NO_DWARF 293 ifeq ($(feature-libelf-getphdrnum), 1)
195ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 294 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
196 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 295 endif
197 NO_DWARF := 1
198else
199 CFLAGS += -DDWARF_SUPPORT $(LIBDW_CFLAGS)
200 LDFLAGS += $(LIBDW_LDFLAGS)
201 EXTLIBS += -lelf -ldw
202endif # PERF_HAVE_DWARF_REGS
203endif # NO_DWARF
204 296
205endif # NO_LIBELF 297 # include ARCH specific config
298 -include $(src-perf)/arch/$(ARCH)/Makefile
206 299
207ifndef NO_LIBELF 300 ifndef NO_DWARF
208CFLAGS += -DLIBELF_SUPPORT 301 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
209FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) 302 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
210ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y) 303 NO_DWARF := 1
211 CFLAGS += -DLIBELF_MMAP 304 else
212endif # try-cc 305 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
306 LDFLAGS += $(LIBDW_LDFLAGS)
307 EXTLIBS += -lelf -ldw
308 endif # PERF_HAVE_DWARF_REGS
309 endif # NO_DWARF
213endif # NO_LIBELF 310endif # NO_LIBELF
214 311
215ifeq ($(LIBUNWIND_LIBS),) 312ifeq ($(LIBUNWIND_LIBS),)
@@ -217,38 +314,40 @@ ifeq ($(LIBUNWIND_LIBS),)
217endif 314endif
218 315
219ifndef NO_LIBUNWIND 316ifndef NO_LIBUNWIND
220# for linking with debug library, run like: 317 #
221# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ 318 # For linking with debug library, run like:
222ifdef LIBUNWIND_DIR 319 #
223 LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include 320 # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
224 LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib 321 #
225endif 322 ifdef LIBUNWIND_DIR
323 LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include
324 LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib
325 endif
226 326
227FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(CFLAGS) $(LIBUNWIND_LDFLAGS) $(LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) 327 ifneq ($(feature-libunwind), 1)
228ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y) 328 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1);
229 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1); 329 NO_LIBUNWIND := 1
230 NO_LIBUNWIND := 1 330 else
231endif # Libunwind support 331 ifneq ($(feature-libunwind-debug-frame), 1)
232ifneq ($(call try-cc,$(SOURCE_LIBUNWIND_DEBUG_FRAME),$(FLAGS_UNWIND),libunwind debug_frame),y) 332 msg := $(warning No debug_frame support found in libunwind);
233 msg := $(warning No debug_frame support found in libunwind); 333 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
234CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME 334 endif
235endif # debug_frame support in libunwind 335 endif
236endif # NO_LIBUNWIND 336endif
237 337
238ifndef NO_LIBUNWIND 338ifndef NO_LIBUNWIND
239 CFLAGS += -DLIBUNWIND_SUPPORT 339 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
240 EXTLIBS += $(LIBUNWIND_LIBS) 340 EXTLIBS += $(LIBUNWIND_LIBS)
241 CFLAGS += $(LIBUNWIND_CFLAGS) 341 CFLAGS += $(LIBUNWIND_CFLAGS)
242 LDFLAGS += $(LIBUNWIND_LDFLAGS) 342 LDFLAGS += $(LIBUNWIND_LDFLAGS)
243endif # NO_LIBUNWIND 343endif
244 344
245ifndef NO_LIBAUDIT 345ifndef NO_LIBAUDIT
246 FLAGS_LIBAUDIT = $(CFLAGS) $(LDFLAGS) -laudit 346 ifneq ($(feature-libaudit), 1)
247 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y)
248 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev); 347 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
249 NO_LIBAUDIT := 1 348 NO_LIBAUDIT := 1
250 else 349 else
251 CFLAGS += -DLIBAUDIT_SUPPORT 350 CFLAGS += -DHAVE_LIBAUDIT_SUPPORT
252 EXTLIBS += -laudit 351 EXTLIBS += -laudit
253 endif 352 endif
254endif 353endif
@@ -258,30 +357,30 @@ ifdef NO_NEWT
258endif 357endif
259 358
260ifndef NO_SLANG 359ifndef NO_SLANG
261 FLAGS_SLANG=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -I/usr/include/slang -lslang 360 ifneq ($(feature-libslang), 1)
262 ifneq ($(call try-cc,$(SOURCE_SLANG),$(FLAGS_SLANG),libslang),y)
263 msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); 361 msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev);
264 NO_SLANG := 1 362 NO_SLANG := 1
265 else 363 else
266 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 364 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
267 CFLAGS += -I/usr/include/slang 365 CFLAGS += -I/usr/include/slang
268 CFLAGS += -DSLANG_SUPPORT 366 CFLAGS += -DHAVE_SLANG_SUPPORT
269 EXTLIBS += -lslang 367 EXTLIBS += -lslang
270 endif 368 endif
271endif 369endif
272 370
273ifndef NO_GTK2 371ifndef NO_GTK2
274 FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 372 FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
275 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2),gtk2),y) 373 ifneq ($(feature-gtk2), 1)
276 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 374 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
277 NO_GTK2 := 1 375 NO_GTK2 := 1
278 else 376 else
279 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2),-DHAVE_GTK_INFO_BAR),y) 377 ifeq ($(feature-gtk2-infobar), 1)
280 CFLAGS += -DHAVE_GTK_INFO_BAR 378 GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT
281 endif 379 endif
282 CFLAGS += -DGTK2_SUPPORT 380 CFLAGS += -DHAVE_GTK2_SUPPORT
283 CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) 381 GTK_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
284 EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) 382 GTK_LIBS := $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
383 EXTLIBS += -ldl
285 endif 384 endif
286endif 385endif
287 386
@@ -297,7 +396,7 @@ else
297 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` 396 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
298 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) 397 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
299 398
300 ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED),perl),y) 399 ifneq ($(feature-libperl), 1)
301 CFLAGS += -DNO_LIBPERL 400 CFLAGS += -DNO_LIBPERL
302 NO_LIBPERL := 1 401 NO_LIBPERL := 1
303 else 402 else
@@ -306,6 +405,13 @@ else
306 endif 405 endif
307endif 406endif
308 407
408$(call feature_check,timerfd)
409ifeq ($(feature-timerfd), 1)
410 CFLAGS += -DHAVE_TIMERFD_SUPPORT
411else
412 msg := $(warning No timerfd support. Disables 'perf kvm stat live');
413endif
414
309disable-python = $(eval $(disable-python_code)) 415disable-python = $(eval $(disable-python_code))
310define disable-python_code 416define disable-python_code
311 CFLAGS += -DNO_LIBPYTHON 417 CFLAGS += -DNO_LIBPYTHON
@@ -342,11 +448,11 @@ else
342 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 448 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
343 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 449 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
344 450
345 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED),python),y) 451 ifneq ($(feature-libpython), 1)
346 $(call disable-python,Python.h (for Python 2.x)) 452 $(call disable-python,Python.h (for Python 2.x))
347 else 453 else
348 454
349 ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED),python version),y) 455 ifneq ($(feature-libpython-version), 1)
350 $(warning Python 3 is not yet supported; please set) 456 $(warning Python 3 is not yet supported; please set)
351 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 457 $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
352 $(warning If you also have Python 2 installed, then) 458 $(warning If you also have Python 2 installed, then)
@@ -369,33 +475,30 @@ else
369 endif 475 endif
370endif 476endif
371 477
478ifeq ($(feature-libbfd), 1)
479 EXTLIBS += -lbfd
480endif
481
372ifdef NO_DEMANGLE 482ifdef NO_DEMANGLE
373 CFLAGS += -DNO_DEMANGLE 483 CFLAGS += -DNO_DEMANGLE
374else 484else
375 ifdef HAVE_CPLUS_DEMANGLE 485 ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
376 EXTLIBS += -liberty 486 EXTLIBS += -liberty
377 CFLAGS += -DHAVE_CPLUS_DEMANGLE 487 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
378 else 488 else
379 FLAGS_BFD=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd 489 ifneq ($(feature-libbfd), 1)
380 has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD),libbfd) 490 $(call feature_check,liberty)
381 ifeq ($(has_bfd),y) 491 ifeq ($(feature-liberty), 1)
382 EXTLIBS += -lbfd
383 else
384 FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty
385 has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY),liberty)
386 ifeq ($(has_bfd_iberty),y)
387 EXTLIBS += -lbfd -liberty 492 EXTLIBS += -lbfd -liberty
388 else 493 else
389 FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz 494 $(call feature_check,liberty-z)
390 has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z),libz) 495 ifeq ($(feature-liberty-z), 1)
391 ifeq ($(has_bfd_iberty_z),y)
392 EXTLIBS += -lbfd -liberty -lz 496 EXTLIBS += -lbfd -liberty -lz
393 else 497 else
394 FLAGS_CPLUS_DEMANGLE=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -liberty 498 $(call feature_check,cplus-demangle)
395 has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE),demangle) 499 ifeq ($(feature-cplus-demangle), 1)
396 ifeq ($(has_cplus_demangle),y)
397 EXTLIBS += -liberty 500 EXTLIBS += -liberty
398 CFLAGS += -DHAVE_CPLUS_DEMANGLE 501 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
399 else 502 else
400 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) 503 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling)
401 CFLAGS += -DNO_DEMANGLE 504 CFLAGS += -DNO_DEMANGLE
@@ -406,31 +509,28 @@ else
406 endif 509 endif
407endif 510endif
408 511
409ifndef NO_STRLCPY 512ifneq ($(filter -lbfd,$(EXTLIBS)),)
410 ifeq ($(call try-cc,$(SOURCE_STRLCPY),,-DHAVE_STRLCPY),y) 513 CFLAGS += -DHAVE_LIBBFD_SUPPORT
411 CFLAGS += -DHAVE_STRLCPY
412 endif
413endif 514endif
414 515
415ifndef NO_ON_EXIT 516ifndef NO_ON_EXIT
416 ifeq ($(call try-cc,$(SOURCE_ON_EXIT),,-DHAVE_ON_EXIT),y) 517 ifeq ($(feature-on-exit), 1)
417 CFLAGS += -DHAVE_ON_EXIT 518 CFLAGS += -DHAVE_ON_EXIT_SUPPORT
418 endif 519 endif
419endif 520endif
420 521
421ifndef NO_BACKTRACE 522ifndef NO_BACKTRACE
422 ifeq ($(call try-cc,$(SOURCE_BACKTRACE),,-DBACKTRACE_SUPPORT),y) 523 ifeq ($(feature-backtrace), 1)
423 CFLAGS += -DBACKTRACE_SUPPORT 524 CFLAGS += -DHAVE_BACKTRACE_SUPPORT
424 endif 525 endif
425endif 526endif
426 527
427ifndef NO_LIBNUMA 528ifndef NO_LIBNUMA
428 FLAGS_LIBNUMA = $(CFLAGS) $(LDFLAGS) -lnuma 529 ifeq ($(feature-libnuma), 0)
429 ifneq ($(call try-cc,$(SOURCE_LIBNUMA),$(FLAGS_LIBNUMA),libnuma),y)
430 msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev); 530 msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev);
431 NO_LIBNUMA := 1 531 NO_LIBNUMA := 1
432 else 532 else
433 CFLAGS += -DLIBNUMA_SUPPORT 533 CFLAGS += -DHAVE_LIBNUMA_SUPPORT
434 EXTLIBS += -lnuma 534 EXTLIBS += -lnuma
435 endif 535 endif
436endif 536endif
@@ -466,7 +566,12 @@ else
466sysconfdir = $(prefix)/etc 566sysconfdir = $(prefix)/etc
467ETC_PERFCONFIG = etc/perfconfig 567ETC_PERFCONFIG = etc/perfconfig
468endif 568endif
569ifeq ($(IS_X86_64),1)
570lib = lib64
571else
469lib = lib 572lib = lib
573endif
574libdir = $(prefix)/$(lib)
470 575
471# Shell quote (do not use $(call) to accommodate ancient setups); 576# Shell quote (do not use $(call) to accommodate ancient setups);
472ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) 577ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
@@ -479,6 +584,7 @@ template_dir_SQ = $(subst ','\'',$(template_dir))
479htmldir_SQ = $(subst ','\'',$(htmldir)) 584htmldir_SQ = $(subst ','\'',$(htmldir))
480prefix_SQ = $(subst ','\'',$(prefix)) 585prefix_SQ = $(subst ','\'',$(prefix))
481sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) 586sysconfdir_SQ = $(subst ','\'',$(sysconfdir))
587libdir_SQ = $(subst ','\'',$(libdir))
482 588
483ifneq ($(filter /%,$(firstword $(perfexecdir))),) 589ifneq ($(filter /%,$(firstword $(perfexecdir))),)
484perfexec_instdir = $(perfexecdir) 590perfexec_instdir = $(perfexecdir)
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
new file mode 100644
index 000000000000..e8e195f49a4e
--- /dev/null
+++ b/tools/perf/config/feature-checks/Makefile
@@ -0,0 +1,149 @@
1
2FILES= \
3 test-all \
4 test-backtrace \
5 test-bionic \
6 test-dwarf \
7 test-fortify-source \
8 test-glibc \
9 test-gtk2 \
10 test-gtk2-infobar \
11 test-hello \
12 test-libaudit \
13 test-libbfd \
14 test-liberty \
15 test-liberty-z \
16 test-cplus-demangle \
17 test-libelf \
18 test-libelf-getphdrnum \
19 test-libelf-mmap \
20 test-libnuma \
21 test-libperl \
22 test-libpython \
23 test-libpython-version \
24 test-libslang \
25 test-libunwind \
26 test-libunwind-debug-frame \
27 test-on-exit \
28 test-stackprotector-all \
29 test-stackprotector \
30 test-timerfd
31
32CC := $(CC) -MD
33
34all: $(FILES)
35
36BUILD = $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUTPUT)$@ $@.c
37
38###############################
39
40test-all:
41 $(BUILD) -Werror -fstack-protector -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
42
43test-hello:
44 $(BUILD)
45
46test-stackprotector-all:
47 $(BUILD) -Werror -fstack-protector-all
48
49test-stackprotector:
50 $(BUILD) -Werror -fstack-protector -Wstack-protector
51
52test-fortify-source:
53 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
54
55test-bionic:
56 $(BUILD)
57
58test-libelf:
59 $(BUILD) -lelf
60
61test-glibc:
62 $(BUILD)
63
64test-dwarf:
65 $(BUILD) -ldw
66
67test-libelf-mmap:
68 $(BUILD) -lelf
69
70test-libelf-getphdrnum:
71 $(BUILD) -lelf
72
73test-libnuma:
74 $(BUILD) -lnuma
75
76test-libunwind:
77 $(BUILD) $(LIBUNWIND_LIBS) -lelf
78
79test-libaudit:
80 $(BUILD) -laudit
81
82test-libslang:
83 $(BUILD) -I/usr/include/slang -lslang
84
85test-gtk2:
86 $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
87
88test-gtk2-infobar:
89 $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
90
91grep-libs = $(filter -l%,$(1))
92strip-libs = $(filter-out -l%,$(1))
93
94PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
95PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
96PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
97PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
98FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
99
100test-libperl:
101 $(BUILD) $(FLAGS_PERL_EMBED)
102
103override PYTHON := python
104override PYTHON_CONFIG := python-config
105
106escape-for-shell-sq = $(subst ','\'',$(1))
107shell-sq = '$(escape-for-shell-sq)'
108
109PYTHON_CONFIG_SQ = $(call shell-sq,$(PYTHON_CONFIG))
110
111PYTHON_EMBED_LDOPTS = $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
112PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
113PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
114PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
115FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
116
117test-libpython:
118 $(BUILD) $(FLAGS_PYTHON_EMBED)
119
120test-libpython-version:
121 $(BUILD) $(FLAGS_PYTHON_EMBED)
122
123test-libbfd:
124 $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
125
126test-liberty:
127 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
128
129test-liberty-z:
130 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
131
132test-cplus-demangle:
133 $(BUILD) -liberty
134
135test-on-exit:
136 $(BUILD)
137
138test-backtrace:
139 $(BUILD)
140
141test-timerfd:
142 $(BUILD)
143
144-include *.d
145
146###############################
147
148clean:
149 rm -f $(FILES) *.d
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
new file mode 100644
index 000000000000..799865b60772
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -0,0 +1,115 @@
1/*
2 * test-all.c: Try to build all the main testcases at once.
3 *
4 * A well-configured system will have all the prereqs installed, so we can speed
5 * up auto-detection on such systems.
6 */
7
8/*
9 * Quirk: Python and Perl headers cannot be in arbitrary places, so keep
10 * these 3 testcases at the top:
11 */
12#define main main_test_libpython
13# include "test-libpython.c"
14#undef main
15
16#define main main_test_libpython_version
17# include "test-libpython-version.c"
18#undef main
19
20#define main main_test_libperl
21# include "test-libperl.c"
22#undef main
23
24#define main main_test_hello
25# include "test-hello.c"
26#undef main
27
28#define main main_test_libelf
29# include "test-libelf.c"
30#undef main
31
32#define main main_test_libelf_mmap
33# include "test-libelf-mmap.c"
34#undef main
35
36#define main main_test_glibc
37# include "test-glibc.c"
38#undef main
39
40#define main main_test_dwarf
41# include "test-dwarf.c"
42#undef main
43
44#define main main_test_libelf_getphdrnum
45# include "test-libelf-getphdrnum.c"
46#undef main
47
48#define main main_test_libunwind
49# include "test-libunwind.c"
50#undef main
51
52#define main main_test_libunwind_debug_frame
53# include "test-libunwind-debug-frame.c"
54#undef main
55
56#define main main_test_libaudit
57# include "test-libaudit.c"
58#undef main
59
60#define main main_test_libslang
61# include "test-libslang.c"
62#undef main
63
64#define main main_test_gtk2
65# include "test-gtk2.c"
66#undef main
67
68#define main main_test_gtk2_infobar
69# include "test-gtk2-infobar.c"
70#undef main
71
72#define main main_test_libbfd
73# include "test-libbfd.c"
74#undef main
75
76#define main main_test_on_exit
77# include "test-on-exit.c"
78#undef main
79
80#define main main_test_backtrace
81# include "test-backtrace.c"
82#undef main
83
84#define main main_test_libnuma
85# include "test-libnuma.c"
86#undef main
87
88#define main main_test_timerfd
89# include "test-timerfd.c"
90#undef main
91
92int main(int argc, char *argv[])
93{
94 main_test_libpython();
95 main_test_libpython_version();
96 main_test_libperl();
97 main_test_hello();
98 main_test_libelf();
99 main_test_libelf_mmap();
100 main_test_glibc();
101 main_test_dwarf();
102 main_test_libelf_getphdrnum();
103 main_test_libunwind();
104 main_test_libaudit();
105 main_test_libslang();
106 main_test_gtk2(argc, argv);
107 main_test_gtk2_infobar(argc, argv);
108 main_test_libbfd();
109 main_test_on_exit();
110 main_test_backtrace();
111 main_test_libnuma();
112 main_test_timerfd();
113
114 return 0;
115}
diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/perf/config/feature-checks/test-backtrace.c
new file mode 100644
index 000000000000..7124aa1dc8fb
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-backtrace.c
@@ -0,0 +1,13 @@
1#include <execinfo.h>
2#include <stdio.h>
3
4int main(void)
5{
6 void *backtrace_fns[10];
7 size_t entries;
8
9 entries = backtrace(backtrace_fns, 10);
10 backtrace_symbols_fd(backtrace_fns, entries, 1);
11
12 return 0;
13}
diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/perf/config/feature-checks/test-bionic.c
new file mode 100644
index 000000000000..eac24e9513eb
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-bionic.c
@@ -0,0 +1,6 @@
1#include <android/api-level.h>
2
3int main(void)
4{
5 return __ANDROID_API__;
6}
diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/perf/config/feature-checks/test-cplus-demangle.c
new file mode 100644
index 000000000000..610c686e0009
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-cplus-demangle.c
@@ -0,0 +1,14 @@
1extern int printf(const char *format, ...);
2extern char *cplus_demangle(const char *, int);
3
4int main(void)
5{
6 char symbol[4096] = "FieldName__9ClassNameFd";
7 char *tmp;
8
9 tmp = cplus_demangle(symbol, 0);
10
11 printf("demangled symbol: {%s}\n", tmp);
12
13 return 0;
14}
diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/perf/config/feature-checks/test-dwarf.c
new file mode 100644
index 000000000000..3fc1801ce4a9
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-dwarf.c
@@ -0,0 +1,10 @@
1#include <dwarf.h>
2#include <elfutils/libdw.h>
3#include <elfutils/version.h>
4
5int main(void)
6{
7 Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
8
9 return (long)dbg;
10}
diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/perf/config/feature-checks/test-fortify-source.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-fortify-source.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/perf/config/feature-checks/test-glibc.c
new file mode 100644
index 000000000000..b0820345cd98
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-glibc.c
@@ -0,0 +1,8 @@
1#include <gnu/libc-version.h>
2
3int main(void)
4{
5 const char *version = gnu_get_libc_version();
6
7 return (long)version;
8}
diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/perf/config/feature-checks/test-gtk2-infobar.c
new file mode 100644
index 000000000000..397b4646d066
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-gtk2-infobar.c
@@ -0,0 +1,11 @@
1#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes"
4
5int main(int argc, char *argv[])
6{
7 gtk_init(&argc, &argv);
8 gtk_info_bar_new();
9
10 return 0;
11}
diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/perf/config/feature-checks/test-gtk2.c
new file mode 100644
index 000000000000..6bd80e509439
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-gtk2.c
@@ -0,0 +1,10 @@
1#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes"
4
5int main(int argc, char *argv[])
6{
7 gtk_init(&argc, &argv);
8
9 return 0;
10}
diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/perf/config/feature-checks/test-hello.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-hello.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/perf/config/feature-checks/test-libaudit.c
new file mode 100644
index 000000000000..afc019f08641
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libaudit.c
@@ -0,0 +1,10 @@
1#include <libaudit.h>
2
3extern int printf(const char *format, ...);
4
5int main(void)
6{
7 printf("error message: %s\n", audit_errno_to_name(0));
8
9 return audit_open();
10}
diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/perf/config/feature-checks/test-libbfd.c
new file mode 100644
index 000000000000..24059907e990
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libbfd.c
@@ -0,0 +1,15 @@
1#include <bfd.h>
2
3extern int printf(const char *format, ...);
4
5int main(void)
6{
7 char symbol[4096] = "FieldName__9ClassNameFd";
8 char *tmp;
9
10 tmp = bfd_demangle(0, symbol, 0);
11
12 printf("demangled symbol: {%s}\n", tmp);
13
14 return 0;
15}
diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
new file mode 100644
index 000000000000..d710459306c3
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 size_t dst;
6
7 return elf_getphdrnum(0, &dst);
8}
diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/perf/config/feature-checks/test-libelf-mmap.c
new file mode 100644
index 000000000000..564427d7ef18
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf-mmap.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
6
7 return (long)elf;
8}
diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/perf/config/feature-checks/test-libelf.c
new file mode 100644
index 000000000000..08db322d8957
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 Elf *elf = elf_begin(0, ELF_C_READ, 0);
6
7 return (long)elf;
8}
diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/perf/config/feature-checks/test-libnuma.c
new file mode 100644
index 000000000000..4763d9cd587d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libnuma.c
@@ -0,0 +1,9 @@
1#include <numa.h>
2#include <numaif.h>
3
4int main(void)
5{
6 numa_available();
7
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/perf/config/feature-checks/test-libperl.c
new file mode 100644
index 000000000000..8871f6a0fdb4
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libperl.c
@@ -0,0 +1,9 @@
1#include <EXTERN.h>
2#include <perl.h>
3
4int main(void)
5{
6 perl_alloc();
7
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/perf/config/feature-checks/test-libpython-version.c
new file mode 100644
index 000000000000..facea122d812
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libpython-version.c
@@ -0,0 +1,10 @@
1#include <Python.h>
2
3#if PY_VERSION_HEX >= 0x03000000
4 #error
5#endif
6
7int main(void)
8{
9 return 0;
10}
diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/perf/config/feature-checks/test-libpython.c
new file mode 100644
index 000000000000..b24b28ad6324
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libpython.c
@@ -0,0 +1,8 @@
1#include <Python.h>
2
3int main(void)
4{
5 Py_Initialize();
6
7 return 0;
8}
diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/perf/config/feature-checks/test-libslang.c
new file mode 100644
index 000000000000..22ff22ed94d1
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libslang.c
@@ -0,0 +1,6 @@
1#include <slang.h>
2
3int main(void)
4{
5 return SLsmg_init_smg();
6}
diff --git a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c b/tools/perf/config/feature-checks/test-libunwind-debug-frame.c
new file mode 100644
index 000000000000..0ef8087a104a
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libunwind-debug-frame.c
@@ -0,0 +1,16 @@
1#include <libunwind.h>
2#include <stdlib.h>
3
4extern int
5UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
6 unw_word_t ip, unw_word_t segbase,
7 const char *obj_name, unw_word_t start,
8 unw_word_t end);
9
10#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
11
12int main(void)
13{
14 dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
15 return 0;
16}
diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/perf/config/feature-checks/test-libunwind.c
new file mode 100644
index 000000000000..43b9369bcab7
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libunwind.c
@@ -0,0 +1,27 @@
1#include <libunwind.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
diff --git a/tools/perf/config/feature-checks/test-on-exit.c b/tools/perf/config/feature-checks/test-on-exit.c
new file mode 100644
index 000000000000..8e88b16e6ded
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-on-exit.c
@@ -0,0 +1,16 @@
1#include <stdio.h>
2#include <stdlib.h>
3
4static void exit_fn(int status, void *__data)
5{
6 printf("exit status: %d, data: %d\n", status, *(int *)__data);
7}
8
9static int data = 123;
10
11int main(void)
12{
13 on_exit(exit_fn, &data);
14
15 return 321;
16}
diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/perf/config/feature-checks/test-stackprotector-all.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-stackprotector-all.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-stackprotector.c b/tools/perf/config/feature-checks/test-stackprotector.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-stackprotector.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/perf/config/feature-checks/test-timerfd.c
new file mode 100644
index 000000000000..8c5c083b4d3c
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-timerfd.c
@@ -0,0 +1,18 @@
1/*
2 * test for timerfd functions used by perf-kvm-stat-live
3 */
4#include <sys/timerfd.h>
5
6int main(void)
7{
8 struct itimerspec new_value;
9
10 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
11 if (fd < 0)
12 return 1;
13
14 if (timerfd_settime(fd, 0, &new_value, NULL) != 0)
15 return 1;
16
17 return 0;
18}
diff --git a/tools/perf/config/feature-checks/test-volatile-register-var.c b/tools/perf/config/feature-checks/test-volatile-register-var.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-volatile-register-var.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
deleted file mode 100644
index 028fe997d5eb..000000000000
--- a/tools/perf/config/feature-tests.mak
+++ /dev/null
@@ -1,265 +0,0 @@
1define SOURCE_HELLO
2#include <stdio.h>
3int main(void)
4{
5 return puts(\"hi\");
6}
7endef
8
9ifndef NO_DWARF
10define SOURCE_DWARF
11#include <dwarf.h>
12#include <elfutils/libdw.h>
13#include <elfutils/version.h>
14#ifndef _ELFUTILS_PREREQ
15#error
16#endif
17
18int main(void)
19{
20 Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
21 return (long)dbg;
22}
23endef
24endif
25
26define SOURCE_LIBELF
27#include <libelf.h>
28
29int main(void)
30{
31 Elf *elf = elf_begin(0, ELF_C_READ, 0);
32 return (long)elf;
33}
34endef
35
36define SOURCE_GLIBC
37#include <gnu/libc-version.h>
38
39int main(void)
40{
41 const char *version = gnu_get_libc_version();
42 return (long)version;
43}
44endef
45
46define SOURCE_BIONIC
47#include <android/api-level.h>
48
49int main(void)
50{
51 return __ANDROID_API__;
52}
53endef
54
55define SOURCE_ELF_MMAP
56#include <libelf.h>
57int main(void)
58{
59 Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
60 return (long)elf;
61}
62endef
63
64define SOURCE_ELF_GETPHDRNUM
65#include <libelf.h>
66int main(void)
67{
68 size_t dst;
69 return elf_getphdrnum(0, &dst);
70}
71endef
72
73ifndef NO_SLANG
74define SOURCE_SLANG
75#include <slang.h>
76
77int main(void)
78{
79 return SLsmg_init_smg();
80}
81endef
82endif
83
84ifndef NO_GTK2
85define SOURCE_GTK2
86#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
87#include <gtk/gtk.h>
88#pragma GCC diagnostic error \"-Wstrict-prototypes\"
89
90int main(int argc, char *argv[])
91{
92 gtk_init(&argc, &argv);
93
94 return 0;
95}
96endef
97
98define SOURCE_GTK2_INFOBAR
99#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
100#include <gtk/gtk.h>
101#pragma GCC diagnostic error \"-Wstrict-prototypes\"
102
103int main(void)
104{
105 gtk_info_bar_new();
106
107 return 0;
108}
109endef
110endif
111
112ifndef NO_LIBPERL
113define SOURCE_PERL_EMBED
114#include <EXTERN.h>
115#include <perl.h>
116
117int main(void)
118{
119perl_alloc();
120return 0;
121}
122endef
123endif
124
125ifndef NO_LIBPYTHON
126define SOURCE_PYTHON_VERSION
127#include <Python.h>
128#if PY_VERSION_HEX >= 0x03000000
129 #error
130#endif
131int main(void)
132{
133 return 0;
134}
135endef
136define SOURCE_PYTHON_EMBED
137#include <Python.h>
138int main(void)
139{
140 Py_Initialize();
141 return 0;
142}
143endef
144endif
145
146define SOURCE_BFD
147#include <bfd.h>
148
149int main(void)
150{
151 bfd_demangle(0, 0, 0);
152 return 0;
153}
154endef
155
156define SOURCE_CPLUS_DEMANGLE
157extern char *cplus_demangle(const char *, int);
158
159int main(void)
160{
161 cplus_demangle(0, 0);
162 return 0;
163}
164endef
165
166define SOURCE_STRLCPY
167#include <stdlib.h>
168extern size_t strlcpy(char *dest, const char *src, size_t size);
169
170int main(void)
171{
172 strlcpy(NULL, NULL, 0);
173 return 0;
174}
175endef
176
177ifndef NO_LIBUNWIND
178define SOURCE_LIBUNWIND
179#include <libunwind.h>
180#include <stdlib.h>
181
182extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
183 unw_word_t ip,
184 unw_dyn_info_t *di,
185 unw_proc_info_t *pi,
186 int need_unwind_info, void *arg);
187
188#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
189
190int main(void)
191{
192 unw_addr_space_t addr_space;
193 addr_space = unw_create_addr_space(NULL, 0);
194 unw_init_remote(NULL, addr_space, NULL);
195 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
196 return 0;
197}
198endef
199
200define SOURCE_LIBUNWIND_DEBUG_FRAME
201#include <libunwind.h>
202#include <stdlib.h>
203
204extern int
205UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
206 unw_word_t ip, unw_word_t segbase,
207 const char *obj_name, unw_word_t start,
208 unw_word_t end);
209
210#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
211
212int main(void)
213{
214 dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
215 return 0;
216}
217endef
218
219endif
220
221ifndef NO_BACKTRACE
222define SOURCE_BACKTRACE
223#include <execinfo.h>
224#include <stdio.h>
225
226int main(void)
227{
228 backtrace(NULL, 0);
229 backtrace_symbols(NULL, 0);
230 return 0;
231}
232endef
233endif
234
235ifndef NO_LIBAUDIT
236define SOURCE_LIBAUDIT
237#include <libaudit.h>
238
239int main(void)
240{
241 printf(\"error message: %s\", audit_errno_to_name(0));
242 return audit_open();
243}
244endef
245endif
246
247define SOURCE_ON_EXIT
248#include <stdio.h>
249
250int main(void)
251{
252 return on_exit(NULL, NULL);
253}
254endef
255
256define SOURCE_LIBNUMA
257#include <numa.h>
258#include <numaif.h>
259
260int main(void)
261{
262 numa_available();
263 return 0;
264}
265endef
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 94d2d4f9c35d..f168debc5be2 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -179,16 +179,9 @@ _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_e
179_gea_warn = $(warning The path '$(1)' is not executable.) 179_gea_warn = $(warning The path '$(1)' is not executable.)
180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
181 181
182# try-cc 182ifneq ($(findstring $(MAKEFLAGS),s),s)
183# Usage: option = $(call try-cc, source-to-build, cc-options, msg) 183 ifneq ($(V),1)
184ifneq ($(V),1) 184 QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
185TRY_CC_OUTPUT= > /dev/null 2>&1 185 QUIET_INSTALL = @printf ' INSTALL %s\n' $1;
186 endif
186endif 187endif
187TRY_CC_MSG=echo " CHK $(3)" 1>&2;
188
189try-cc = $(shell sh -c \
190 'TMP="$(OUTPUT)$(TMPOUT).$$$$"; \
191 $(TRY_CC_MSG) \
192 echo "$(1)" | \
193 $(CC) -x c - $(2) -o "$$TMP" $(TRY_CC_OUTPUT) && echo y; \
194 rm -f "$$TMP"')
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 85e1aed95204..8b38b4e80ec2 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -49,14 +49,14 @@ static struct cmd_struct commands[] = {
49 { "version", cmd_version, 0 }, 49 { "version", cmd_version, 0 },
50 { "script", cmd_script, 0 }, 50 { "script", cmd_script, 0 },
51 { "sched", cmd_sched, 0 }, 51 { "sched", cmd_sched, 0 },
52#ifdef LIBELF_SUPPORT 52#ifdef HAVE_LIBELF_SUPPORT
53 { "probe", cmd_probe, 0 }, 53 { "probe", cmd_probe, 0 },
54#endif 54#endif
55 { "kmem", cmd_kmem, 0 }, 55 { "kmem", cmd_kmem, 0 },
56 { "lock", cmd_lock, 0 }, 56 { "lock", cmd_lock, 0 },
57 { "kvm", cmd_kvm, 0 }, 57 { "kvm", cmd_kvm, 0 },
58 { "test", cmd_test, 0 }, 58 { "test", cmd_test, 0 },
59#ifdef LIBAUDIT_SUPPORT 59#ifdef HAVE_LIBAUDIT_SUPPORT
60 { "trace", cmd_trace, 0 }, 60 { "trace", cmd_trace, 0 },
61#endif 61#endif
62 { "inject", cmd_inject, 0 }, 62 { "inject", cmd_inject, 0 },
@@ -456,6 +456,7 @@ int main(int argc, const char **argv)
456{ 456{
457 const char *cmd; 457 const char *cmd;
458 458
459 /* The page_size is placed in util object. */
459 page_size = sysconf(_SC_PAGE_SIZE); 460 page_size = sysconf(_SC_PAGE_SIZE);
460 461
461 cmd = perf_extract_argv0_path(argv[0]); 462 cmd = perf_extract_argv0_path(argv[0]);
@@ -480,7 +481,14 @@ int main(int argc, const char **argv)
480 fprintf(stderr, "cannot handle %s internally", cmd); 481 fprintf(stderr, "cannot handle %s internally", cmd);
481 goto out; 482 goto out;
482 } 483 }
483 484#ifdef HAVE_LIBAUDIT_SUPPORT
485 if (!prefixcmp(cmd, "trace")) {
486 set_buildid_dir();
487 setup_path();
488 argv[0] = "trace";
489 return cmd_trace(argc, argv, NULL);
490 }
491#endif
484 /* Look for flags.. */ 492 /* Look for flags.. */
485 argv++; 493 argv++;
486 argc--; 494 argc--;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cf20187eee0a..6a587e84fdfe 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -4,6 +4,8 @@
4#include <asm/unistd.h> 4#include <asm/unistd.h>
5 5
6#if defined(__i386__) 6#if defined(__i386__)
7#define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
8#define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
7#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 9#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
8#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 10#define cpu_relax() asm volatile("rep; nop" ::: "memory");
9#define CPUINFO_PROC "model name" 11#define CPUINFO_PROC "model name"
@@ -13,6 +15,8 @@
13#endif 15#endif
14 16
15#if defined(__x86_64__) 17#if defined(__x86_64__)
18#define mb() asm volatile("mfence" ::: "memory")
19#define wmb() asm volatile("sfence" ::: "memory")
16#define rmb() asm volatile("lfence" ::: "memory") 20#define rmb() asm volatile("lfence" ::: "memory")
17#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 21#define cpu_relax() asm volatile("rep; nop" ::: "memory");
18#define CPUINFO_PROC "model name" 22#define CPUINFO_PROC "model name"
@@ -23,45 +27,61 @@
23 27
24#ifdef __powerpc__ 28#ifdef __powerpc__
25#include "../../arch/powerpc/include/uapi/asm/unistd.h" 29#include "../../arch/powerpc/include/uapi/asm/unistd.h"
30#define mb() asm volatile ("sync" ::: "memory")
31#define wmb() asm volatile ("sync" ::: "memory")
26#define rmb() asm volatile ("sync" ::: "memory") 32#define rmb() asm volatile ("sync" ::: "memory")
27#define cpu_relax() asm volatile ("" ::: "memory");
28#define CPUINFO_PROC "cpu" 33#define CPUINFO_PROC "cpu"
29#endif 34#endif
30 35
31#ifdef __s390__ 36#ifdef __s390__
37#define mb() asm volatile("bcr 15,0" ::: "memory")
38#define wmb() asm volatile("bcr 15,0" ::: "memory")
32#define rmb() asm volatile("bcr 15,0" ::: "memory") 39#define rmb() asm volatile("bcr 15,0" ::: "memory")
33#define cpu_relax() asm volatile("" ::: "memory");
34#endif 40#endif
35 41
36#ifdef __sh__ 42#ifdef __sh__
37#if defined(__SH4A__) || defined(__SH5__) 43#if defined(__SH4A__) || defined(__SH5__)
44# define mb() asm volatile("synco" ::: "memory")
45# define wmb() asm volatile("synco" ::: "memory")
38# define rmb() asm volatile("synco" ::: "memory") 46# define rmb() asm volatile("synco" ::: "memory")
39#else 47#else
48# define mb() asm volatile("" ::: "memory")
49# define wmb() asm volatile("" ::: "memory")
40# define rmb() asm volatile("" ::: "memory") 50# define rmb() asm volatile("" ::: "memory")
41#endif 51#endif
42#define cpu_relax() asm volatile("" ::: "memory")
43#define CPUINFO_PROC "cpu type" 52#define CPUINFO_PROC "cpu type"
44#endif 53#endif
45 54
46#ifdef __hppa__ 55#ifdef __hppa__
56#define mb() asm volatile("" ::: "memory")
57#define wmb() asm volatile("" ::: "memory")
47#define rmb() asm volatile("" ::: "memory") 58#define rmb() asm volatile("" ::: "memory")
48#define cpu_relax() asm volatile("" ::: "memory");
49#define CPUINFO_PROC "cpu" 59#define CPUINFO_PROC "cpu"
50#endif 60#endif
51 61
52#ifdef __sparc__ 62#ifdef __sparc__
63#ifdef __LP64__
64#define mb() asm volatile("ba,pt %%xcc, 1f\n" \
65 "membar #StoreLoad\n" \
66 "1:\n":::"memory")
67#else
68#define mb() asm volatile("":::"memory")
69#endif
70#define wmb() asm volatile("":::"memory")
53#define rmb() asm volatile("":::"memory") 71#define rmb() asm volatile("":::"memory")
54#define cpu_relax() asm volatile("":::"memory")
55#define CPUINFO_PROC "cpu" 72#define CPUINFO_PROC "cpu"
56#endif 73#endif
57 74
58#ifdef __alpha__ 75#ifdef __alpha__
76#define mb() asm volatile("mb" ::: "memory")
77#define wmb() asm volatile("wmb" ::: "memory")
59#define rmb() asm volatile("mb" ::: "memory") 78#define rmb() asm volatile("mb" ::: "memory")
60#define cpu_relax() asm volatile("" ::: "memory")
61#define CPUINFO_PROC "cpu model" 79#define CPUINFO_PROC "cpu model"
62#endif 80#endif
63 81
64#ifdef __ia64__ 82#ifdef __ia64__
83#define mb() asm volatile ("mf" ::: "memory")
84#define wmb() asm volatile ("mf" ::: "memory")
65#define rmb() asm volatile ("mf" ::: "memory") 85#define rmb() asm volatile ("mf" ::: "memory")
66#define cpu_relax() asm volatile ("hint @pause" ::: "memory") 86#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
67#define CPUINFO_PROC "model name" 87#define CPUINFO_PROC "model name"
@@ -72,40 +92,55 @@
72 * Use the __kuser_memory_barrier helper in the CPU helper page. See 92 * Use the __kuser_memory_barrier helper in the CPU helper page. See
73 * arch/arm/kernel/entry-armv.S in the kernel source for details. 93 * arch/arm/kernel/entry-armv.S in the kernel source for details.
74 */ 94 */
95#define mb() ((void(*)(void))0xffff0fa0)()
96#define wmb() ((void(*)(void))0xffff0fa0)()
75#define rmb() ((void(*)(void))0xffff0fa0)() 97#define rmb() ((void(*)(void))0xffff0fa0)()
76#define cpu_relax() asm volatile("":::"memory")
77#define CPUINFO_PROC "Processor" 98#define CPUINFO_PROC "Processor"
78#endif 99#endif
79 100
80#ifdef __aarch64__ 101#ifdef __aarch64__
81#define rmb() asm volatile("dmb ld" ::: "memory") 102#define mb() asm volatile("dmb ish" ::: "memory")
103#define wmb() asm volatile("dmb ishld" ::: "memory")
104#define rmb() asm volatile("dmb ishst" ::: "memory")
82#define cpu_relax() asm volatile("yield" ::: "memory") 105#define cpu_relax() asm volatile("yield" ::: "memory")
83#endif 106#endif
84 107
85#ifdef __mips__ 108#ifdef __mips__
86#define rmb() asm volatile( \ 109#define mb() asm volatile( \
87 ".set mips2\n\t" \ 110 ".set mips2\n\t" \
88 "sync\n\t" \ 111 "sync\n\t" \
89 ".set mips0" \ 112 ".set mips0" \
90 : /* no output */ \ 113 : /* no output */ \
91 : /* no input */ \ 114 : /* no input */ \
92 : "memory") 115 : "memory")
93#define cpu_relax() asm volatile("" ::: "memory") 116#define wmb() mb()
117#define rmb() mb()
94#define CPUINFO_PROC "cpu model" 118#define CPUINFO_PROC "cpu model"
95#endif 119#endif
96 120
97#ifdef __arc__ 121#ifdef __arc__
122#define mb() asm volatile("" ::: "memory")
123#define wmb() asm volatile("" ::: "memory")
98#define rmb() asm volatile("" ::: "memory") 124#define rmb() asm volatile("" ::: "memory")
99#define cpu_relax() rmb()
100#define CPUINFO_PROC "Processor" 125#define CPUINFO_PROC "Processor"
101#endif 126#endif
102 127
103#ifdef __metag__ 128#ifdef __metag__
129#define mb() asm volatile("" ::: "memory")
130#define wmb() asm volatile("" ::: "memory")
104#define rmb() asm volatile("" ::: "memory") 131#define rmb() asm volatile("" ::: "memory")
105#define cpu_relax() asm volatile("" ::: "memory")
106#define CPUINFO_PROC "CPU" 132#define CPUINFO_PROC "CPU"
107#endif 133#endif
108 134
135#define barrier() asm volatile ("" ::: "memory")
136
137#ifndef cpu_relax
138#define cpu_relax() barrier()
139#endif
140
141#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
142
143
109#include <time.h> 144#include <time.h>
110#include <unistd.h> 145#include <unistd.h>
111#include <sys/types.h> 146#include <sys/types.h>
@@ -182,7 +217,9 @@ struct ip_callchain {
182struct branch_flags { 217struct branch_flags {
183 u64 mispred:1; 218 u64 mispred:1;
184 u64 predicted:1; 219 u64 predicted:1;
185 u64 reserved:62; 220 u64 in_tx:1;
221 u64 abort:1;
222 u64 reserved:60;
186}; 223};
187 224
188struct branch_entry { 225struct branch_entry {
@@ -218,7 +255,6 @@ struct perf_record_opts {
218 bool no_delay; 255 bool no_delay;
219 bool no_inherit; 256 bool no_inherit;
220 bool no_samples; 257 bool no_samples;
221 bool pipe_output;
222 bool raw_samples; 258 bool raw_samples;
223 bool sample_address; 259 bool sample_address;
224 bool sample_weight; 260 bool sample_weight;
@@ -231,6 +267,7 @@ struct perf_record_opts {
231 u64 default_interval; 267 u64 default_interval;
232 u64 user_interval; 268 u64 user_interval;
233 u16 stack_dump_size; 269 u16 stack_dump_size;
270 bool sample_transaction;
234}; 271};
235 272
236#endif 273#endif
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index 315067b8f552..fcd1dd667906 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -25,7 +25,7 @@
25 25
26PyMODINIT_FUNC initperf_trace_context(void); 26PyMODINIT_FUNC initperf_trace_context(void);
27 27
28static PyObject *perf_trace_context_common_pc(PyObject *self, PyObject *args) 28static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
29{ 29{
30 static struct scripting_context *scripting_context; 30 static struct scripting_context *scripting_context;
31 PyObject *context; 31 PyObject *context;
@@ -40,7 +40,7 @@ static PyObject *perf_trace_context_common_pc(PyObject *self, PyObject *args)
40 return Py_BuildValue("i", retval); 40 return Py_BuildValue("i", retval);
41} 41}
42 42
43static PyObject *perf_trace_context_common_flags(PyObject *self, 43static PyObject *perf_trace_context_common_flags(PyObject *obj,
44 PyObject *args) 44 PyObject *args)
45{ 45{
46 static struct scripting_context *scripting_context; 46 static struct scripting_context *scripting_context;
@@ -56,7 +56,7 @@ static PyObject *perf_trace_context_common_flags(PyObject *self,
56 return Py_BuildValue("i", retval); 56 return Py_BuildValue("i", retval);
57} 57}
58 58
59static PyObject *perf_trace_context_common_lock_depth(PyObject *self, 59static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
60 PyObject *args) 60 PyObject *args)
61{ 61{
62 static struct scripting_context *scripting_context; 62 static struct scripting_context *scripting_context;
diff --git a/tools/perf/tests/attr/README b/tools/perf/tests/attr/README
index d102957cd59a..430024f618f1 100644
--- a/tools/perf/tests/attr/README
+++ b/tools/perf/tests/attr/README
@@ -44,9 +44,9 @@ Following tests are defined (with perf commands):
44 perf record -c 123 kill (test-record-count) 44 perf record -c 123 kill (test-record-count)
45 perf record -d kill (test-record-data) 45 perf record -d kill (test-record-data)
46 perf record -F 100 kill (test-record-freq) 46 perf record -F 100 kill (test-record-freq)
47 perf record -g -- kill (test-record-graph-default) 47 perf record -g kill (test-record-graph-default)
48 perf record -g dwarf -- kill (test-record-graph-dwarf) 48 perf record --call-graph dwarf kill (test-record-graph-dwarf)
49 perf record -g fp kill (test-record-graph-fp) 49 perf record --call-graph fp kill (test-record-graph-fp)
50 perf record --group -e cycles,instructions kill (test-record-group) 50 perf record --group -e cycles,instructions kill (test-record-group)
51 perf record -e '{cycles,instructions}' kill (test-record-group1) 51 perf record -e '{cycles,instructions}' kill (test-record-group1)
52 perf record -D kill (test-record-no-delay) 52 perf record -D kill (test-record-no-delay)
diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default
index 833d1849d767..853597a9a8f6 100644
--- a/tools/perf/tests/attr/test-record-graph-default
+++ b/tools/perf/tests/attr/test-record-graph-default
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -g -- kill >/dev/null 2>&1 3args = -g kill >/dev/null 2>&1
4 4
5[event:base-record] 5[event:base-record]
6sample_type=295 6sample_type=295
diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf
index e93e082f5208..d6f324ea578c 100644
--- a/tools/perf/tests/attr/test-record-graph-dwarf
+++ b/tools/perf/tests/attr/test-record-graph-dwarf
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -g dwarf -- kill >/dev/null 2>&1 3args = --call-graph dwarf -- kill >/dev/null 2>&1
4 4
5[event:base-record] 5[event:base-record]
6sample_type=12583 6sample_type=12583
diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp
index 7cef3743f03f..055e3bee7993 100644
--- a/tools/perf/tests/attr/test-record-graph-fp
+++ b/tools/perf/tests/attr/test-record-graph-fp
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -g fp kill >/dev/null 2>&1 3args = --call-graph fp kill >/dev/null 2>&1
4 4
5[event:base-record] 5[event:base-record]
6sample_type=295 6sample_type=295
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 6fb781d5586c..49ccc3b2995e 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -276,7 +276,7 @@ static int process_event(struct machine *machine, struct perf_evlist *evlist,
276 return process_sample_event(machine, evlist, event, state); 276 return process_sample_event(machine, evlist, event, state);
277 277
278 if (event->header.type < PERF_RECORD_MAX) 278 if (event->header.type < PERF_RECORD_MAX)
279 return machine__process_event(machine, event); 279 return machine__process_event(machine, event, NULL);
280 280
281 return 0; 281 return 0;
282} 282}
@@ -290,6 +290,7 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist,
290 for (i = 0; i < evlist->nr_mmaps; i++) { 290 for (i = 0; i < evlist->nr_mmaps; i++) {
291 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 291 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
292 ret = process_event(machine, evlist, event, state); 292 ret = process_event(machine, evlist, event, state);
293 perf_evlist__mmap_consume(evlist, i);
293 if (ret < 0) 294 if (ret < 0)
294 return ret; 295 return ret;
295 } 296 }
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index dffe0551acaa..9cc81a3eb9b4 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -35,6 +35,7 @@ static char *test_file(int size)
35 if (size != write(fd, buf, size)) 35 if (size != write(fd, buf, size))
36 templ = NULL; 36 templ = NULL;
37 37
38 free(buf);
38 close(fd); 39 close(fd);
39 return templ; 40 return templ;
40} 41}
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 4228ffc0d968..173bf42cc03e 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -93,7 +93,7 @@ static struct machine *setup_fake_machine(struct machines *machines)
93 if (thread == NULL) 93 if (thread == NULL)
94 goto out; 94 goto out;
95 95
96 thread__set_comm(thread, fake_threads[i].comm); 96 thread__set_comm(thread, fake_threads[i].comm, 0);
97 } 97 }
98 98
99 for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { 99 for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) {
@@ -110,7 +110,7 @@ static struct machine *setup_fake_machine(struct machines *machines)
110 strcpy(fake_mmap_event.mmap.filename, 110 strcpy(fake_mmap_event.mmap.filename,
111 fake_mmap_info[i].filename); 111 fake_mmap_info[i].filename);
112 112
113 machine__process_mmap_event(machine, &fake_mmap_event); 113 machine__process_mmap_event(machine, &fake_mmap_event, NULL);
114 } 114 }
115 115
116 for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) { 116 for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) {
@@ -222,7 +222,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
222 &sample) < 0) 222 &sample) < 0)
223 goto out; 223 goto out;
224 224
225 he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); 225 he = __hists__add_entry(&evsel->hists, &al, NULL,
226 NULL, NULL, 1, 1, 0);
226 if (he == NULL) 227 if (he == NULL)
227 goto out; 228 goto out;
228 229
@@ -244,7 +245,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
244 &sample) < 0) 245 &sample) < 0)
245 goto out; 246 goto out;
246 247
247 he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); 248 he = __hists__add_entry(&evsel->hists, &al, NULL,
249 NULL, NULL, 1, 1, 0);
248 if (he == NULL) 250 if (he == NULL)
249 goto out; 251 goto out;
250 252
@@ -419,7 +421,7 @@ static void print_hists(struct hists *hists)
419 he = rb_entry(node, struct hist_entry, rb_node_in); 421 he = rb_entry(node, struct hist_entry, rb_node_in);
420 422
421 pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", 423 pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n",
422 i, he->thread->comm, he->ms.map->dso->short_name, 424 i, thread__comm_str(he->thread), he->ms.map->dso->short_name,
423 he->ms.sym->name, he->stat.period); 425 he->ms.sym->name, he->stat.period);
424 426
425 i++; 427 i++;
@@ -465,7 +467,7 @@ int test__hists_link(void)
465 goto out; 467 goto out;
466 468
467 list_for_each_entry(evsel, &evlist->entries, node) { 469 list_for_each_entry(evsel, &evlist->entries, node) {
468 hists__collapse_resort(&evsel->hists); 470 hists__collapse_resort(&evsel->hists, NULL);
469 471
470 if (verbose > 2) 472 if (verbose > 2)
471 print_hists(&evsel->hists); 473 print_hists(&evsel->hists);
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index d444ea2c47d9..376c35608534 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -36,6 +36,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm)
36 (pid_t)event->comm.tid == getpid() && 36 (pid_t)event->comm.tid == getpid() &&
37 strcmp(event->comm.comm, comm) == 0) 37 strcmp(event->comm.comm, comm) == 0)
38 found += 1; 38 found += 1;
39 perf_evlist__mmap_consume(evlist, i);
39 } 40 }
40 } 41 }
41 return found; 42 return found;
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index c4185b9aeb80..a7232c204eb9 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -122,6 +122,7 @@ int test__basic_mmap(void)
122 goto out_munmap; 122 goto out_munmap;
123 } 123 }
124 nr_events[evsel->idx]++; 124 nr_events[evsel->idx]++;
125 perf_evlist__mmap_consume(evlist, 0);
125 } 126 }
126 127
127 err = 0; 128 err = 0;
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index fc5b9fca8b47..524b221b829b 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -77,8 +77,10 @@ int test__syscall_open_tp_fields(void)
77 77
78 ++nr_events; 78 ++nr_events;
79 79
80 if (type != PERF_RECORD_SAMPLE) 80 if (type != PERF_RECORD_SAMPLE) {
81 perf_evlist__mmap_consume(evlist, i);
81 continue; 82 continue;
83 }
82 84
83 err = perf_evsel__parse_sample(evsel, event, &sample); 85 err = perf_evsel__parse_sample(evsel, event, &sample);
84 if (err) { 86 if (err) {
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 48114d164e9f..ef671cd41bb3 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -2,7 +2,7 @@
2#include "parse-events.h" 2#include "parse-events.h"
3#include "evsel.h" 3#include "evsel.h"
4#include "evlist.h" 4#include "evlist.h"
5#include "sysfs.h" 5#include "fs.h"
6#include <lk/debugfs.h> 6#include <lk/debugfs.h>
7#include "tests.h" 7#include "tests.h"
8#include <linux/hw_breakpoint.h> 8#include <linux/hw_breakpoint.h>
@@ -1456,7 +1456,7 @@ static int test_pmu(void)
1456 int ret; 1456 int ret;
1457 1457
1458 snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/format/", 1458 snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/format/",
1459 sysfs_find_mountpoint()); 1459 sysfs__mountpoint());
1460 1460
1461 ret = stat(path, &st); 1461 ret = stat(path, &st);
1462 if (ret) 1462 if (ret)
@@ -1473,7 +1473,7 @@ static int test_pmu_events(void)
1473 int ret; 1473 int ret;
1474 1474
1475 snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/", 1475 snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/",
1476 sysfs_find_mountpoint()); 1476 sysfs__mountpoint());
1477 1477
1478 ret = stat(path, &st); 1478 ret = stat(path, &st);
1479 if (ret) { 1479 if (ret) {
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index b8a7056519ac..93a62b06c3af 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -45,7 +45,7 @@ int test__PERF_RECORD(void)
45 }; 45 };
46 cpu_set_t cpu_mask; 46 cpu_set_t cpu_mask;
47 size_t cpu_mask_size = sizeof(cpu_mask); 47 size_t cpu_mask_size = sizeof(cpu_mask);
48 struct perf_evlist *evlist = perf_evlist__new(); 48 struct perf_evlist *evlist = perf_evlist__new_default();
49 struct perf_evsel *evsel; 49 struct perf_evsel *evsel;
50 struct perf_sample sample; 50 struct perf_sample sample;
51 const char *cmd = "sleep"; 51 const char *cmd = "sleep";
@@ -66,16 +66,6 @@ int test__PERF_RECORD(void)
66 } 66 }
67 67
68 /* 68 /*
69 * We need at least one evsel in the evlist, use the default
70 * one: "cycles".
71 */
72 err = perf_evlist__add_default(evlist);
73 if (err < 0) {
74 pr_debug("Not enough memory to create evsel\n");
75 goto out_delete_evlist;
76 }
77
78 /*
79 * Create maps of threads and cpus to monitor. In this case 69 * Create maps of threads and cpus to monitor. In this case
80 * we start with all threads and cpus (-1, -1) but then in 70 * we start with all threads and cpus (-1, -1) but then in
81 * perf_evlist__prepare_workload we'll fill in the only thread 71 * perf_evlist__prepare_workload we'll fill in the only thread
@@ -263,6 +253,8 @@ int test__PERF_RECORD(void)
263 type); 253 type);
264 ++errs; 254 ++errs;
265 } 255 }
256
257 perf_evlist__mmap_consume(evlist, i);
266 } 258 }
267 } 259 }
268 260
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index 0ab61b1f408e..4ca1b938f6a6 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -122,7 +122,7 @@ int test__perf_time_to_tsc(void)
122 if (event->header.type != PERF_RECORD_COMM || 122 if (event->header.type != PERF_RECORD_COMM ||
123 (pid_t)event->comm.pid != getpid() || 123 (pid_t)event->comm.pid != getpid() ||
124 (pid_t)event->comm.tid != getpid()) 124 (pid_t)event->comm.tid != getpid())
125 continue; 125 goto next_event;
126 126
127 if (strcmp(event->comm.comm, comm1) == 0) { 127 if (strcmp(event->comm.comm, comm1) == 0) {
128 CHECK__(perf_evsel__parse_sample(evsel, event, 128 CHECK__(perf_evsel__parse_sample(evsel, event,
@@ -134,6 +134,8 @@ int test__perf_time_to_tsc(void)
134 &sample)); 134 &sample));
135 comm2_time = sample.time; 135 comm2_time = sample.time;
136 } 136 }
137next_event:
138 perf_evlist__mmap_consume(evlist, i);
137 } 139 }
138 } 140 }
139 141
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c
index ff94886aad99..46649c25fa5e 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/tests/rdpmc.c
@@ -9,8 +9,6 @@
9 9
10#if defined(__x86_64__) || defined(__i386__) 10#if defined(__x86_64__) || defined(__i386__)
11 11
12#define barrier() asm volatile("" ::: "memory")
13
14static u64 rdpmc(unsigned int counter) 12static u64 rdpmc(unsigned int counter)
15{ 13{
16 unsigned int low, high; 14 unsigned int low, high;
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 77f598dbd97a..1b677202638d 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -121,6 +121,9 @@ static bool samples_same(const struct perf_sample *s1,
121 if (type & PERF_SAMPLE_DATA_SRC) 121 if (type & PERF_SAMPLE_DATA_SRC)
122 COMP(data_src); 122 COMP(data_src);
123 123
124 if (type & PERF_SAMPLE_TRANSACTION)
125 COMP(transaction);
126
124 return true; 127 return true;
125} 128}
126 129
@@ -165,6 +168,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
165 .cpu = 110, 168 .cpu = 110,
166 .raw_size = sizeof(raw_data), 169 .raw_size = sizeof(raw_data),
167 .data_src = 111, 170 .data_src = 111,
171 .transaction = 112,
168 .raw_data = (void *)raw_data, 172 .raw_data = (void *)raw_data,
169 .callchain = &callchain.callchain, 173 .callchain = &callchain.callchain,
170 .branch_stack = &branch_stack.branch_stack, 174 .branch_stack = &branch_stack.branch_stack,
@@ -273,10 +277,11 @@ int test__sample_parsing(void)
273 277
274 /* 278 /*
275 * Fail the test if it has not been updated when new sample format bits 279 * Fail the test if it has not been updated when new sample format bits
276 * were added. 280 * were added. Please actually update the test rather than just change
281 * the condition below.
277 */ 282 */
278 if (PERF_SAMPLE_MAX > PERF_SAMPLE_IDENTIFIER << 1) { 283 if (PERF_SAMPLE_MAX > PERF_SAMPLE_TRANSACTION << 1) {
279 pr_debug("sample format has changed - test needs updating\n"); 284 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
280 return -1; 285 return -1;
281 } 286 }
282 287
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 2e41e2d32ccc..6e2b44ec0749 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
78 struct perf_sample sample; 78 struct perf_sample sample;
79 79
80 if (event->header.type != PERF_RECORD_SAMPLE) 80 if (event->header.type != PERF_RECORD_SAMPLE)
81 continue; 81 goto next_event;
82 82
83 err = perf_evlist__parse_sample(evlist, event, &sample); 83 err = perf_evlist__parse_sample(evlist, event, &sample);
84 if (err < 0) { 84 if (err < 0) {
@@ -88,6 +88,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
88 88
89 total_periods += sample.period; 89 total_periods += sample.period;
90 nr_samples++; 90 nr_samples++;
91next_event:
92 perf_evlist__mmap_consume(evlist, 0);
91 } 93 }
92 94
93 if ((u64) nr_samples == total_periods) { 95 if ((u64) nr_samples == total_periods) {
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 28fe5894b061..c33d95f9559a 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -37,20 +37,11 @@ int test__task_exit(void)
37 signal(SIGCHLD, sig_handler); 37 signal(SIGCHLD, sig_handler);
38 signal(SIGUSR1, sig_handler); 38 signal(SIGUSR1, sig_handler);
39 39
40 evlist = perf_evlist__new(); 40 evlist = perf_evlist__new_default();
41 if (evlist == NULL) { 41 if (evlist == NULL) {
42 pr_debug("perf_evlist__new\n"); 42 pr_debug("perf_evlist__new_default\n");
43 return -1; 43 return -1;
44 } 44 }
45 /*
46 * We need at least one evsel in the evlist, use the default
47 * one: "cycles".
48 */
49 err = perf_evlist__add_default(evlist);
50 if (err < 0) {
51 pr_debug("Not enough memory to create evsel\n");
52 goto out_free_evlist;
53 }
54 45
55 /* 46 /*
56 * Create maps of threads and cpus to monitor. In this case 47 * Create maps of threads and cpus to monitor. In this case
@@ -96,10 +87,10 @@ int test__task_exit(void)
96 87
97retry: 88retry:
98 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 89 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
99 if (event->header.type != PERF_RECORD_EXIT) 90 if (event->header.type == PERF_RECORD_EXIT)
100 continue; 91 nr_exit++;
101 92
102 nr_exit++; 93 perf_evlist__mmap_consume(evlist, 0);
103 } 94 }
104 95
105 if (!exited || !nr_exit) { 96 if (!exited || !nr_exit) {
@@ -117,7 +108,6 @@ out_close_evlist:
117 perf_evlist__close(evlist); 108 perf_evlist__close(evlist);
118out_delete_maps: 109out_delete_maps:
119 perf_evlist__delete_maps(evlist); 110 perf_evlist__delete_maps(evlist);
120out_free_evlist:
121 perf_evlist__delete(evlist); 111 perf_evlist__delete(evlist);
122 return err; 112 return err;
123} 113}
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 404ff66a3e36..7d45d2f53601 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -21,32 +21,32 @@ struct ui_browser {
21 void *priv; 21 void *priv;
22 const char *title; 22 const char *title;
23 char *helpline; 23 char *helpline;
24 unsigned int (*refresh)(struct ui_browser *self); 24 unsigned int (*refresh)(struct ui_browser *browser);
25 void (*write)(struct ui_browser *self, void *entry, int row); 25 void (*write)(struct ui_browser *browser, void *entry, int row);
26 void (*seek)(struct ui_browser *self, off_t offset, int whence); 26 void (*seek)(struct ui_browser *browser, off_t offset, int whence);
27 bool (*filter)(struct ui_browser *self, void *entry); 27 bool (*filter)(struct ui_browser *browser, void *entry);
28 u32 nr_entries; 28 u32 nr_entries;
29 bool navkeypressed; 29 bool navkeypressed;
30 bool use_navkeypressed; 30 bool use_navkeypressed;
31}; 31};
32 32
33int ui_browser__set_color(struct ui_browser *browser, int color); 33int ui_browser__set_color(struct ui_browser *browser, int color);
34void ui_browser__set_percent_color(struct ui_browser *self, 34void ui_browser__set_percent_color(struct ui_browser *browser,
35 double percent, bool current); 35 double percent, bool current);
36bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row); 36bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row);
37void ui_browser__refresh_dimensions(struct ui_browser *self); 37void ui_browser__refresh_dimensions(struct ui_browser *browser);
38void ui_browser__reset_index(struct ui_browser *self); 38void ui_browser__reset_index(struct ui_browser *browser);
39 39
40void ui_browser__gotorc(struct ui_browser *self, int y, int x); 40void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
41void ui_browser__write_graph(struct ui_browser *browser, int graph); 41void ui_browser__write_graph(struct ui_browser *browser, int graph);
42void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, 42void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
43 u64 start, u64 end); 43 u64 start, u64 end);
44void __ui_browser__show_title(struct ui_browser *browser, const char *title); 44void __ui_browser__show_title(struct ui_browser *browser, const char *title);
45void ui_browser__show_title(struct ui_browser *browser, const char *title); 45void ui_browser__show_title(struct ui_browser *browser, const char *title);
46int ui_browser__show(struct ui_browser *self, const char *title, 46int ui_browser__show(struct ui_browser *browser, const char *title,
47 const char *helpline, ...); 47 const char *helpline, ...);
48void ui_browser__hide(struct ui_browser *self); 48void ui_browser__hide(struct ui_browser *browser);
49int ui_browser__refresh(struct ui_browser *self); 49int ui_browser__refresh(struct ui_browser *browser);
50int ui_browser__run(struct ui_browser *browser, int delay_secs); 50int ui_browser__run(struct ui_browser *browser, int delay_secs);
51void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries); 51void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
52void ui_browser__handle_resize(struct ui_browser *browser); 52void ui_browser__handle_resize(struct ui_browser *browser);
@@ -63,11 +63,11 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
63void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence); 63void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
64unsigned int ui_browser__argv_refresh(struct ui_browser *browser); 64unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
65 65
66void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence); 66void ui_browser__rb_tree_seek(struct ui_browser *browser, off_t offset, int whence);
67unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self); 67unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser);
68 68
69void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence); 69void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whence);
70unsigned int ui_browser__list_head_refresh(struct ui_browser *self); 70unsigned int ui_browser__list_head_refresh(struct ui_browser *browser);
71 71
72void ui_browser__init(void); 72void ui_browser__init(void);
73void annotate_browser__init(void); 73void annotate_browser__init(void);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 08545ae46992..f0697a3aede0 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -442,35 +442,37 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
442{ 442{
443 struct map_symbol *ms = browser->b.priv; 443 struct map_symbol *ms = browser->b.priv;
444 struct disasm_line *dl = browser->selection; 444 struct disasm_line *dl = browser->selection;
445 struct symbol *sym = ms->sym;
446 struct annotation *notes; 445 struct annotation *notes;
447 struct symbol *target; 446 struct addr_map_symbol target = {
448 u64 ip; 447 .map = ms->map,
448 .addr = map__objdump_2mem(ms->map, dl->ops.target.addr),
449 };
449 char title[SYM_TITLE_MAX_SIZE]; 450 char title[SYM_TITLE_MAX_SIZE];
450 451
451 if (!ins__is_call(dl->ins)) 452 if (!ins__is_call(dl->ins))
452 return false; 453 return false;
453 454
454 ip = ms->map->map_ip(ms->map, dl->ops.target.addr); 455 if (map_groups__find_ams(&target, NULL) ||
455 target = map__find_symbol(ms->map, ip, NULL); 456 map__rip_2objdump(target.map, target.map->map_ip(target.map,
456 if (target == NULL) { 457 target.addr)) !=
458 dl->ops.target.addr) {
457 ui_helpline__puts("The called function was not found."); 459 ui_helpline__puts("The called function was not found.");
458 return true; 460 return true;
459 } 461 }
460 462
461 notes = symbol__annotation(target); 463 notes = symbol__annotation(target.sym);
462 pthread_mutex_lock(&notes->lock); 464 pthread_mutex_lock(&notes->lock);
463 465
464 if (notes->src == NULL && symbol__alloc_hist(target) < 0) { 466 if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) {
465 pthread_mutex_unlock(&notes->lock); 467 pthread_mutex_unlock(&notes->lock);
466 ui__warning("Not enough memory for annotating '%s' symbol!\n", 468 ui__warning("Not enough memory for annotating '%s' symbol!\n",
467 target->name); 469 target.sym->name);
468 return true; 470 return true;
469 } 471 }
470 472
471 pthread_mutex_unlock(&notes->lock); 473 pthread_mutex_unlock(&notes->lock);
472 symbol__tui_annotate(target, ms->map, evsel, hbt); 474 symbol__tui_annotate(target.sym, target.map, evsel, hbt);
473 sym_title(sym, ms->map, title, sizeof(title)); 475 sym_title(ms->sym, ms->map, title, sizeof(title));
474 ui_browser__show_title(&browser->b, title); 476 ui_browser__show_title(&browser->b, title);
475 return true; 477 return true;
476} 478}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 7ef36c360471..16848bb4c418 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1255,7 +1255,7 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
1255 if (thread) 1255 if (thread)
1256 printed += scnprintf(bf + printed, size - printed, 1256 printed += scnprintf(bf + printed, size - printed,
1257 ", Thread: %s(%d)", 1257 ", Thread: %s(%d)",
1258 (thread->comm_set ? thread->comm : ""), 1258 (thread->comm_set ? thread__comm_str(thread) : ""),
1259 thread->tid); 1259 thread->tid);
1260 if (dso) 1260 if (dso)
1261 printed += scnprintf(bf + printed, size - printed, 1261 printed += scnprintf(bf + printed, size - printed,
@@ -1578,7 +1578,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1578 if (thread != NULL && 1578 if (thread != NULL &&
1579 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 1579 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
1580 (browser->hists->thread_filter ? "out of" : "into"), 1580 (browser->hists->thread_filter ? "out of" : "into"),
1581 (thread->comm_set ? thread->comm : ""), 1581 (thread->comm_set ? thread__comm_str(thread) : ""),
1582 thread->tid) > 0) 1582 thread->tid) > 0)
1583 zoom_thread = nr_options++; 1583 zoom_thread = nr_options++;
1584 1584
@@ -1598,7 +1598,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1598 struct symbol *sym; 1598 struct symbol *sym;
1599 1599
1600 if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]", 1600 if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]",
1601 browser->he_selection->thread->comm) > 0) 1601 thread__comm_str(browser->he_selection->thread)) > 0)
1602 scripts_comm = nr_options++; 1602 scripts_comm = nr_options++;
1603 1603
1604 sym = browser->he_selection->ms.sym; 1604 sym = browser->he_selection->ms.sym;
@@ -1701,7 +1701,7 @@ zoom_out_thread:
1701 sort_thread.elide = false; 1701 sort_thread.elide = false;
1702 } else { 1702 } else {
1703 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", 1703 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1704 thread->comm_set ? thread->comm : "", 1704 thread->comm_set ? thread__comm_str(thread) : "",
1705 thread->tid); 1705 thread->tid);
1706 browser->hists->thread_filter = thread; 1706 browser->hists->thread_filter = thread;
1707 sort_thread.elide = true; 1707 sort_thread.elide = true;
@@ -1717,7 +1717,7 @@ do_scripts:
1717 memset(script_opt, 0, 64); 1717 memset(script_opt, 0, 64);
1718 1718
1719 if (choice == scripts_comm) 1719 if (choice == scripts_comm)
1720 sprintf(script_opt, " -c %s ", browser->he_selection->thread->comm); 1720 sprintf(script_opt, " -c %s ", thread__comm_str(browser->he_selection->thread));
1721 1721
1722 if (choice == scripts_symbol) 1722 if (choice == scripts_symbol)
1723 sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name); 1723 sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name);
@@ -1889,7 +1889,7 @@ out:
1889 return key; 1889 return key;
1890} 1890}
1891 1891
1892static bool filter_group_entries(struct ui_browser *self __maybe_unused, 1892static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
1893 void *entry) 1893 void *entry)
1894{ 1894{
1895 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); 1895 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index 95c7cfb8f2c6..b11639f33682 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -18,30 +18,30 @@ struct map_browser {
18 u8 addrlen; 18 u8 addrlen;
19}; 19};
20 20
21static void map_browser__write(struct ui_browser *self, void *nd, int row) 21static void map_browser__write(struct ui_browser *browser, void *nd, int row)
22{ 22{
23 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 23 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
24 struct map_browser *mb = container_of(self, struct map_browser, b); 24 struct map_browser *mb = container_of(browser, struct map_browser, b);
25 bool current_entry = ui_browser__is_current_entry(self, row); 25 bool current_entry = ui_browser__is_current_entry(browser, row);
26 int width; 26 int width;
27 27
28 ui_browser__set_percent_color(self, 0, current_entry); 28 ui_browser__set_percent_color(browser, 0, current_entry);
29 slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ", 29 slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ",
30 mb->addrlen, sym->start, mb->addrlen, sym->end, 30 mb->addrlen, sym->start, mb->addrlen, sym->end,
31 sym->binding == STB_GLOBAL ? 'g' : 31 sym->binding == STB_GLOBAL ? 'g' :
32 sym->binding == STB_LOCAL ? 'l' : 'w'); 32 sym->binding == STB_LOCAL ? 'l' : 'w');
33 width = self->width - ((mb->addrlen * 2) + 4); 33 width = browser->width - ((mb->addrlen * 2) + 4);
34 if (width > 0) 34 if (width > 0)
35 slsmg_write_nstring(sym->name, width); 35 slsmg_write_nstring(sym->name, width);
36} 36}
37 37
38/* FIXME uber-kludgy, see comment on cmd_report... */ 38/* FIXME uber-kludgy, see comment on cmd_report... */
39static u32 *symbol__browser_index(struct symbol *self) 39static u32 *symbol__browser_index(struct symbol *browser)
40{ 40{
41 return ((void *)self) - sizeof(struct rb_node) - sizeof(u32); 41 return ((void *)browser) - sizeof(struct rb_node) - sizeof(u32);
42} 42}
43 43
44static int map_browser__search(struct map_browser *self) 44static int map_browser__search(struct map_browser *browser)
45{ 45{
46 char target[512]; 46 char target[512];
47 struct symbol *sym; 47 struct symbol *sym;
@@ -53,37 +53,37 @@ static int map_browser__search(struct map_browser *self)
53 53
54 if (target[0] == '0' && tolower(target[1]) == 'x') { 54 if (target[0] == '0' && tolower(target[1]) == 'x') {
55 u64 addr = strtoull(target, NULL, 16); 55 u64 addr = strtoull(target, NULL, 16);
56 sym = map__find_symbol(self->map, addr, NULL); 56 sym = map__find_symbol(browser->map, addr, NULL);
57 } else 57 } else
58 sym = map__find_symbol_by_name(self->map, target, NULL); 58 sym = map__find_symbol_by_name(browser->map, target, NULL);
59 59
60 if (sym != NULL) { 60 if (sym != NULL) {
61 u32 *idx = symbol__browser_index(sym); 61 u32 *idx = symbol__browser_index(sym);
62 62
63 self->b.top = &sym->rb_node; 63 browser->b.top = &sym->rb_node;
64 self->b.index = self->b.top_idx = *idx; 64 browser->b.index = browser->b.top_idx = *idx;
65 } else 65 } else
66 ui_helpline__fpush("%s not found!", target); 66 ui_helpline__fpush("%s not found!", target);
67 67
68 return 0; 68 return 0;
69} 69}
70 70
71static int map_browser__run(struct map_browser *self) 71static int map_browser__run(struct map_browser *browser)
72{ 72{
73 int key; 73 int key;
74 74
75 if (ui_browser__show(&self->b, self->map->dso->long_name, 75 if (ui_browser__show(&browser->b, browser->map->dso->long_name,
76 "Press <- or ESC to exit, %s / to search", 76 "Press <- or ESC to exit, %s / to search",
77 verbose ? "" : "restart with -v to use") < 0) 77 verbose ? "" : "restart with -v to use") < 0)
78 return -1; 78 return -1;
79 79
80 while (1) { 80 while (1) {
81 key = ui_browser__run(&self->b, 0); 81 key = ui_browser__run(&browser->b, 0);
82 82
83 switch (key) { 83 switch (key) {
84 case '/': 84 case '/':
85 if (verbose) 85 if (verbose)
86 map_browser__search(self); 86 map_browser__search(browser);
87 default: 87 default:
88 break; 88 break;
89 case K_LEFT: 89 case K_LEFT:
@@ -94,20 +94,20 @@ static int map_browser__run(struct map_browser *self)
94 } 94 }
95 } 95 }
96out: 96out:
97 ui_browser__hide(&self->b); 97 ui_browser__hide(&browser->b);
98 return key; 98 return key;
99} 99}
100 100
101int map__browse(struct map *self) 101int map__browse(struct map *map)
102{ 102{
103 struct map_browser mb = { 103 struct map_browser mb = {
104 .b = { 104 .b = {
105 .entries = &self->dso->symbols[self->type], 105 .entries = &map->dso->symbols[map->type],
106 .refresh = ui_browser__rb_tree_refresh, 106 .refresh = ui_browser__rb_tree_refresh,
107 .seek = ui_browser__rb_tree_seek, 107 .seek = ui_browser__rb_tree_seek,
108 .write = map_browser__write, 108 .write = map_browser__write,
109 }, 109 },
110 .map = self, 110 .map = map,
111 }; 111 };
112 struct rb_node *nd; 112 struct rb_node *nd;
113 char tmp[BITS_PER_LONG / 4]; 113 char tmp[BITS_PER_LONG / 4];
diff --git a/tools/perf/ui/browsers/map.h b/tools/perf/ui/browsers/map.h
index df8581a43e17..2d58e4b3eb6f 100644
--- a/tools/perf/ui/browsers/map.h
+++ b/tools/perf/ui/browsers/map.h
@@ -2,5 +2,5 @@
2#define _PERF_UI_MAP_BROWSER_H_ 1 2#define _PERF_UI_MAP_BROWSER_H_ 1
3struct map; 3struct map;
4 4
5int map__browse(struct map *self); 5int map__browse(struct map *map);
6#endif /* _PERF_UI_MAP_BROWSER_H_ */ 6#endif /* _PERF_UI_MAP_BROWSER_H_ */
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index 12f009e61e94..d63c68ea02a8 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -84,22 +84,22 @@ static void script_browser__write(struct ui_browser *browser,
84 slsmg_write_nstring(sline->line, browser->width); 84 slsmg_write_nstring(sline->line, browser->width);
85} 85}
86 86
87static int script_browser__run(struct perf_script_browser *self) 87static int script_browser__run(struct perf_script_browser *browser)
88{ 88{
89 int key; 89 int key;
90 90
91 if (ui_browser__show(&self->b, self->script_name, 91 if (ui_browser__show(&browser->b, browser->script_name,
92 "Press <- or ESC to exit") < 0) 92 "Press <- or ESC to exit") < 0)
93 return -1; 93 return -1;
94 94
95 while (1) { 95 while (1) {
96 key = ui_browser__run(&self->b, 0); 96 key = ui_browser__run(&browser->b, 0);
97 97
98 /* We can add some special key handling here if needed */ 98 /* We can add some special key handling here if needed */
99 break; 99 break;
100 } 100 }
101 101
102 ui_browser__hide(&self->b); 102 ui_browser__hide(&browser->b);
103 return key; 103 return key;
104} 104}
105 105
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index f538794615db..9c7ff8d31b27 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -154,9 +154,9 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
154 return 0; 154 return 0;
155} 155}
156 156
157int symbol__gtk_annotate(struct symbol *sym, struct map *map, 157static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
158 struct perf_evsel *evsel, 158 struct perf_evsel *evsel,
159 struct hist_browser_timer *hbt) 159 struct hist_browser_timer *hbt)
160{ 160{
161 GtkWidget *window; 161 GtkWidget *window;
162 GtkWidget *notebook; 162 GtkWidget *notebook;
@@ -226,6 +226,13 @@ int symbol__gtk_annotate(struct symbol *sym, struct map *map,
226 return 0; 226 return 0;
227} 227}
228 228
229int hist_entry__gtk_annotate(struct hist_entry *he,
230 struct perf_evsel *evsel,
231 struct hist_browser_timer *hbt)
232{
233 return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
234}
235
229void perf_gtk__show_annotations(void) 236void perf_gtk__show_annotations(void)
230{ 237{
231 GtkWidget *window; 238 GtkWidget *window;
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index c95012cdb438..c24d91221290 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -43,7 +43,7 @@ const char *perf_gtk__get_percent_color(double percent)
43 return NULL; 43 return NULL;
44} 44}
45 45
46#ifdef HAVE_GTK_INFO_BAR 46#ifdef HAVE_GTK_INFO_BAR_SUPPORT
47GtkWidget *perf_gtk__setup_info_bar(void) 47GtkWidget *perf_gtk__setup_info_bar(void)
48{ 48{
49 GtkWidget *info_bar; 49 GtkWidget *info_bar;
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 3d96785ef155..0a9173ff9a61 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -12,7 +12,7 @@ struct perf_gtk_context {
12 GtkWidget *main_window; 12 GtkWidget *main_window;
13 GtkWidget *notebook; 13 GtkWidget *notebook;
14 14
15#ifdef HAVE_GTK_INFO_BAR 15#ifdef HAVE_GTK_INFO_BAR_SUPPORT
16 GtkWidget *info_bar; 16 GtkWidget *info_bar;
17 GtkWidget *message_label; 17 GtkWidget *message_label;
18#endif 18#endif
@@ -20,6 +20,9 @@ struct perf_gtk_context {
20 guint statbar_ctx_id; 20 guint statbar_ctx_id;
21}; 21};
22 22
23int perf_gtk__init(void);
24void perf_gtk__exit(bool wait_for_ok);
25
23extern struct perf_gtk_context *pgctx; 26extern struct perf_gtk_context *pgctx;
24 27
25static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx) 28static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
@@ -31,7 +34,7 @@ struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window);
31int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); 34int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);
32 35
33void perf_gtk__init_helpline(void); 36void perf_gtk__init_helpline(void);
34void perf_gtk__init_progress(void); 37void gtk_ui_progress__init(void);
35void perf_gtk__init_hpp(void); 38void perf_gtk__init_hpp(void);
36 39
37void perf_gtk__signal(int sig); 40void perf_gtk__signal(int sig);
@@ -39,7 +42,7 @@ void perf_gtk__resize_window(GtkWidget *window);
39const char *perf_gtk__get_percent_color(double percent); 42const char *perf_gtk__get_percent_color(double percent);
40GtkWidget *perf_gtk__setup_statusbar(void); 43GtkWidget *perf_gtk__setup_statusbar(void);
41 44
42#ifdef HAVE_GTK_INFO_BAR 45#ifdef HAVE_GTK_INFO_BAR_SUPPORT
43GtkWidget *perf_gtk__setup_info_bar(void); 46GtkWidget *perf_gtk__setup_info_bar(void);
44#else 47#else
45static inline GtkWidget *perf_gtk__setup_info_bar(void) 48static inline GtkWidget *perf_gtk__setup_info_bar(void)
@@ -48,4 +51,17 @@ static inline GtkWidget *perf_gtk__setup_info_bar(void)
48} 51}
49#endif 52#endif
50 53
54struct perf_evsel;
55struct perf_evlist;
56struct hist_entry;
57struct hist_browser_timer;
58
59int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
60 struct hist_browser_timer *hbt,
61 float min_pcnt);
62int hist_entry__gtk_annotate(struct hist_entry *he,
63 struct perf_evsel *evsel,
64 struct hist_browser_timer *hbt);
65void perf_gtk__show_annotations(void);
66
51#endif /* _PERF_GTK_H_ */ 67#endif /* _PERF_GTK_H_ */
diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c
index 482bcf3df9b7..b656655fbc39 100644
--- a/tools/perf/ui/gtk/progress.c
+++ b/tools/perf/ui/gtk/progress.c
@@ -7,14 +7,14 @@
7static GtkWidget *dialog; 7static GtkWidget *dialog;
8static GtkWidget *progress; 8static GtkWidget *progress;
9 9
10static void gtk_progress_update(u64 curr, u64 total, const char *title) 10static void gtk_ui_progress__update(struct ui_progress *p)
11{ 11{
12 double fraction = total ? 1.0 * curr / total : 0.0; 12 double fraction = p->total ? 1.0 * p->curr / p->total : 0.0;
13 char buf[1024]; 13 char buf[1024];
14 14
15 if (dialog == NULL) { 15 if (dialog == NULL) {
16 GtkWidget *vbox = gtk_vbox_new(TRUE, 5); 16 GtkWidget *vbox = gtk_vbox_new(TRUE, 5);
17 GtkWidget *label = gtk_label_new(title); 17 GtkWidget *label = gtk_label_new(p->title);
18 18
19 dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); 19 dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
20 progress = gtk_progress_bar_new(); 20 progress = gtk_progress_bar_new();
@@ -32,7 +32,7 @@ static void gtk_progress_update(u64 curr, u64 total, const char *title)
32 } 32 }
33 33
34 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction); 34 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction);
35 snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, curr, total); 35 snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, p->curr, p->total);
36 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf); 36 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf);
37 37
38 /* we didn't call gtk_main yet, so do it manually */ 38 /* we didn't call gtk_main yet, so do it manually */
@@ -40,7 +40,7 @@ static void gtk_progress_update(u64 curr, u64 total, const char *title)
40 gtk_main_iteration(); 40 gtk_main_iteration();
41} 41}
42 42
43static void gtk_progress_finish(void) 43static void gtk_ui_progress__finish(void)
44{ 44{
45 /* this will also destroy all of its children */ 45 /* this will also destroy all of its children */
46 gtk_widget_destroy(dialog); 46 gtk_widget_destroy(dialog);
@@ -48,12 +48,12 @@ static void gtk_progress_finish(void)
48 dialog = NULL; 48 dialog = NULL;
49} 49}
50 50
51static struct ui_progress gtk_progress_fns = { 51static struct ui_progress_ops gtk_ui_progress__ops = {
52 .update = gtk_progress_update, 52 .update = gtk_ui_progress__update,
53 .finish = gtk_progress_finish, 53 .finish = gtk_ui_progress__finish,
54}; 54};
55 55
56void perf_gtk__init_progress(void) 56void gtk_ui_progress__init(void)
57{ 57{
58 progress_fns = &gtk_progress_fns; 58 ui_progress__ops = &gtk_ui_progress__ops;
59} 59}
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 6c2dd2e423f3..1d57676f8212 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -8,7 +8,7 @@ int perf_gtk__init(void)
8{ 8{
9 perf_error__register(&perf_gtk_eops); 9 perf_error__register(&perf_gtk_eops);
10 perf_gtk__init_helpline(); 10 perf_gtk__init_helpline();
11 perf_gtk__init_progress(); 11 gtk_ui_progress__init();
12 perf_gtk__init_hpp(); 12 perf_gtk__init_hpp();
13 13
14 return gtk_init_check(NULL, NULL) ? 0 : -1; 14 return gtk_init_check(NULL, NULL) ? 0 : -1;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index c06942a41c78..696c1fbe4248 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -53,7 +53,7 @@ static int perf_gtk__error(const char *format, va_list args)
53 return 0; 53 return 0;
54} 54}
55 55
56#ifdef HAVE_GTK_INFO_BAR 56#ifdef HAVE_GTK_INFO_BAR_SUPPORT
57static int perf_gtk__warning_info_bar(const char *format, va_list args) 57static int perf_gtk__warning_info_bar(const char *format, va_list args)
58{ 58{
59 char *msg; 59 char *msg;
@@ -105,7 +105,7 @@ static int perf_gtk__warning_statusbar(const char *format, va_list args)
105 105
106struct perf_error_ops perf_gtk_eops = { 106struct perf_error_ops perf_gtk_eops = {
107 .error = perf_gtk__error, 107 .error = perf_gtk__error,
108#ifdef HAVE_GTK_INFO_BAR 108#ifdef HAVE_GTK_INFO_BAR_SUPPORT
109 .warning = perf_gtk__warning_info_bar, 109 .warning = perf_gtk__warning_info_bar,
110#else 110#else
111 .warning = perf_gtk__warning_statusbar, 111 .warning = perf_gtk__warning_statusbar,
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 0a193281eba8..78f4c92e9b73 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -117,7 +117,7 @@ static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
117 struct perf_hpp *hpp, struct hist_entry *he) \ 117 struct perf_hpp *hpp, struct hist_entry *he) \
118{ \ 118{ \
119 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 119 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \
120 (hpp_snprint_fn)percent_color_snprintf, true); \ 120 percent_color_snprintf, true); \
121} 121}
122 122
123#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 123#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
index 3ec695607a4d..a0f24c7115c5 100644
--- a/tools/perf/ui/progress.c
+++ b/tools/perf/ui/progress.c
@@ -1,26 +1,38 @@
1#include "../cache.h" 1#include "../cache.h"
2#include "progress.h" 2#include "progress.h"
3 3
4static void nop_progress_update(u64 curr __maybe_unused, 4static void null_progress__update(struct ui_progress *p __maybe_unused)
5 u64 total __maybe_unused,
6 const char *title __maybe_unused)
7{ 5{
8} 6}
9 7
10static struct ui_progress default_progress_fns = 8static struct ui_progress_ops null_progress__ops =
11{ 9{
12 .update = nop_progress_update, 10 .update = null_progress__update,
13}; 11};
14 12
15struct ui_progress *progress_fns = &default_progress_fns; 13struct ui_progress_ops *ui_progress__ops = &null_progress__ops;
16 14
17void ui_progress__update(u64 curr, u64 total, const char *title) 15void ui_progress__update(struct ui_progress *p, u64 adv)
18{ 16{
19 return progress_fns->update(curr, total, title); 17 p->curr += adv;
18
19 if (p->curr >= p->next) {
20 p->next += p->step;
21 ui_progress__ops->update(p);
22 }
23}
24
25void ui_progress__init(struct ui_progress *p, u64 total, const char *title)
26{
27 p->curr = 0;
28 p->next = p->step = total / 16;
29 p->total = total;
30 p->title = title;
31
20} 32}
21 33
22void ui_progress__finish(void) 34void ui_progress__finish(void)
23{ 35{
24 if (progress_fns->finish) 36 if (ui_progress__ops->finish)
25 progress_fns->finish(); 37 ui_progress__ops->finish();
26} 38}
diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h
index 257cc224f9cf..29ec8efffefb 100644
--- a/tools/perf/ui/progress.h
+++ b/tools/perf/ui/progress.h
@@ -3,16 +3,21 @@
3 3
4#include <../types.h> 4#include <../types.h>
5 5
6void ui_progress__finish(void);
7
6struct ui_progress { 8struct ui_progress {
7 void (*update)(u64, u64, const char *); 9 const char *title;
8 void (*finish)(void); 10 u64 curr, next, step, total;
9}; 11};
12
13void ui_progress__init(struct ui_progress *p, u64 total, const char *title);
14void ui_progress__update(struct ui_progress *p, u64 adv);
10 15
11extern struct ui_progress *progress_fns; 16struct ui_progress_ops {
12 17 void (*update)(struct ui_progress *p);
13void ui_progress__init(void); 18 void (*finish)(void);
19};
14 20
15void ui_progress__update(u64 curr, u64 total, const char *title); 21extern struct ui_progress_ops *ui_progress__ops;
16void ui_progress__finish(void);
17 22
18#endif 23#endif
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 47d9a571f261..5df5140a9f29 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -1,10 +1,64 @@
1#include <pthread.h> 1#include <pthread.h>
2#include <dlfcn.h>
2 3
3#include "../util/cache.h" 4#include "../util/cache.h"
4#include "../util/debug.h" 5#include "../util/debug.h"
5#include "../util/hist.h" 6#include "../util/hist.h"
6 7
7pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; 8pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
9void *perf_gtk_handle;
10
11#ifdef HAVE_GTK2_SUPPORT
12static int setup_gtk_browser(void)
13{
14 int (*perf_ui_init)(void);
15
16 if (perf_gtk_handle)
17 return 0;
18
19 perf_gtk_handle = dlopen(PERF_GTK_DSO, RTLD_LAZY);
20 if (perf_gtk_handle == NULL) {
21 char buf[PATH_MAX];
22 scnprintf(buf, sizeof(buf), "%s/%s", LIBDIR, PERF_GTK_DSO);
23 perf_gtk_handle = dlopen(buf, RTLD_LAZY);
24 }
25 if (perf_gtk_handle == NULL)
26 return -1;
27
28 perf_ui_init = dlsym(perf_gtk_handle, "perf_gtk__init");
29 if (perf_ui_init == NULL)
30 goto out_close;
31
32 if (perf_ui_init() == 0)
33 return 0;
34
35out_close:
36 dlclose(perf_gtk_handle);
37 return -1;
38}
39
40static void exit_gtk_browser(bool wait_for_ok)
41{
42 void (*perf_ui_exit)(bool);
43
44 if (perf_gtk_handle == NULL)
45 return;
46
47 perf_ui_exit = dlsym(perf_gtk_handle, "perf_gtk__exit");
48 if (perf_ui_exit == NULL)
49 goto out_close;
50
51 perf_ui_exit(wait_for_ok);
52
53out_close:
54 dlclose(perf_gtk_handle);
55
56 perf_gtk_handle = NULL;
57}
58#else
59static inline int setup_gtk_browser(void) { return -1; }
60static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {}
61#endif
8 62
9void setup_browser(bool fallback_to_pager) 63void setup_browser(bool fallback_to_pager)
10{ 64{
@@ -17,8 +71,11 @@ void setup_browser(bool fallback_to_pager)
17 71
18 switch (use_browser) { 72 switch (use_browser) {
19 case 2: 73 case 2:
20 if (perf_gtk__init() == 0) 74 if (setup_gtk_browser() == 0)
21 break; 75 break;
76 printf("GTK browser requested but could not find %s\n",
77 PERF_GTK_DSO);
78 sleep(1);
22 /* fall through */ 79 /* fall through */
23 case 1: 80 case 1:
24 use_browser = 1; 81 use_browser = 1;
@@ -39,7 +96,7 @@ void exit_browser(bool wait_for_ok)
39{ 96{
40 switch (use_browser) { 97 switch (use_browser) {
41 case 2: 98 case 2:
42 perf_gtk__exit(wait_for_ok); 99 exit_gtk_browser(wait_for_ok);
43 break; 100 break;
44 101
45 case 1: 102 case 1:
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 194e2f42ff5d..c244cb524ef2 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -213,20 +213,19 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
213 return ret; 213 return ret;
214} 214}
215 215
216static size_t __callchain__fprintf_flat(FILE *fp, 216static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
217 struct callchain_node *self,
218 u64 total_samples) 217 u64 total_samples)
219{ 218{
220 struct callchain_list *chain; 219 struct callchain_list *chain;
221 size_t ret = 0; 220 size_t ret = 0;
222 221
223 if (!self) 222 if (!node)
224 return 0; 223 return 0;
225 224
226 ret += __callchain__fprintf_flat(fp, self->parent, total_samples); 225 ret += __callchain__fprintf_flat(fp, node->parent, total_samples);
227 226
228 227
229 list_for_each_entry(chain, &self->val, list) { 228 list_for_each_entry(chain, &node->val, list) {
230 if (chain->ip >= PERF_CONTEXT_MAX) 229 if (chain->ip >= PERF_CONTEXT_MAX)
231 continue; 230 continue;
232 if (chain->ms.sym) 231 if (chain->ms.sym)
@@ -239,15 +238,14 @@ static size_t __callchain__fprintf_flat(FILE *fp,
239 return ret; 238 return ret;
240} 239}
241 240
242static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self, 241static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
243 u64 total_samples) 242 u64 total_samples)
244{ 243{
245 size_t ret = 0; 244 size_t ret = 0;
246 u32 entries_printed = 0; 245 u32 entries_printed = 0;
247 struct rb_node *rb_node;
248 struct callchain_node *chain; 246 struct callchain_node *chain;
247 struct rb_node *rb_node = rb_first(tree);
249 248
250 rb_node = rb_first(self);
251 while (rb_node) { 249 while (rb_node) {
252 double percent; 250 double percent;
253 251
@@ -315,8 +313,7 @@ static inline void advance_hpp(struct perf_hpp *hpp, int inc)
315} 313}
316 314
317static int hist_entry__period_snprintf(struct perf_hpp *hpp, 315static int hist_entry__period_snprintf(struct perf_hpp *hpp,
318 struct hist_entry *he, 316 struct hist_entry *he)
319 bool color)
320{ 317{
321 const char *sep = symbol_conf.field_sep; 318 const char *sep = symbol_conf.field_sep;
322 struct perf_hpp_fmt *fmt; 319 struct perf_hpp_fmt *fmt;
@@ -338,7 +335,7 @@ static int hist_entry__period_snprintf(struct perf_hpp *hpp,
338 } else 335 } else
339 first = false; 336 first = false;
340 337
341 if (color && fmt->color) 338 if (perf_hpp__use_color() && fmt->color)
342 ret = fmt->color(fmt, hpp, he); 339 ret = fmt->color(fmt, hpp, he);
343 else 340 else
344 ret = fmt->entry(fmt, hpp, he); 341 ret = fmt->entry(fmt, hpp, he);
@@ -358,12 +355,11 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
358 .buf = bf, 355 .buf = bf,
359 .size = size, 356 .size = size,
360 }; 357 };
361 bool color = !symbol_conf.field_sep;
362 358
363 if (size == 0 || size > bfsz) 359 if (size == 0 || size > bfsz)
364 size = hpp.size = bfsz; 360 size = hpp.size = bfsz;
365 361
366 ret = hist_entry__period_snprintf(&hpp, he, color); 362 ret = hist_entry__period_snprintf(&hpp, he);
367 hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); 363 hist_entry__sort_snprintf(he, bf + ret, size - ret, hists);
368 364
369 ret = fprintf(fp, "%s\n", bf); 365 ret = fprintf(fp, "%s\n", bf);
@@ -482,6 +478,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
482 478
483print_entries: 479print_entries:
484 linesz = hists__sort_list_width(hists) + 3 + 1; 480 linesz = hists__sort_list_width(hists) + 3 + 1;
481 linesz += perf_hpp__color_overhead();
485 line = malloc(linesz); 482 line = malloc(linesz);
486 if (line == NULL) { 483 if (line == NULL) {
487 ret = -1; 484 ret = -1;
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c
index 6c2184d53cbf..3e2d936d7443 100644
--- a/tools/perf/ui/tui/progress.c
+++ b/tools/perf/ui/tui/progress.c
@@ -2,9 +2,10 @@
2#include "../progress.h" 2#include "../progress.h"
3#include "../libslang.h" 3#include "../libslang.h"
4#include "../ui.h" 4#include "../ui.h"
5#include "tui.h"
5#include "../browser.h" 6#include "../browser.h"
6 7
7static void tui_progress__update(u64 curr, u64 total, const char *title) 8static void tui_progress__update(struct ui_progress *p)
8{ 9{
9 int bar, y; 10 int bar, y;
10 /* 11 /*
@@ -14,7 +15,7 @@ static void tui_progress__update(u64 curr, u64 total, const char *title)
14 if (use_browser <= 0) 15 if (use_browser <= 0)
15 return; 16 return;
16 17
17 if (total == 0) 18 if (p->total == 0)
18 return; 19 return;
19 20
20 ui__refresh_dimensions(true); 21 ui__refresh_dimensions(true);
@@ -23,20 +24,20 @@ static void tui_progress__update(u64 curr, u64 total, const char *title)
23 SLsmg_set_color(0); 24 SLsmg_set_color(0);
24 SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols); 25 SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
25 SLsmg_gotorc(y++, 1); 26 SLsmg_gotorc(y++, 1);
26 SLsmg_write_string((char *)title); 27 SLsmg_write_string((char *)p->title);
27 SLsmg_set_color(HE_COLORSET_SELECTED); 28 SLsmg_set_color(HE_COLORSET_SELECTED);
28 bar = ((SLtt_Screen_Cols - 2) * curr) / total; 29 bar = ((SLtt_Screen_Cols - 2) * p->curr) / p->total;
29 SLsmg_fill_region(y, 1, 1, bar, ' '); 30 SLsmg_fill_region(y, 1, 1, bar, ' ');
30 SLsmg_refresh(); 31 SLsmg_refresh();
31 pthread_mutex_unlock(&ui__lock); 32 pthread_mutex_unlock(&ui__lock);
32} 33}
33 34
34static struct ui_progress tui_progress_fns = 35static struct ui_progress_ops tui_progress__ops =
35{ 36{
36 .update = tui_progress__update, 37 .update = tui_progress__update,
37}; 38};
38 39
39void ui_progress__init(void) 40void tui_progress__init(void)
40{ 41{
41 progress_fns = &tui_progress_fns; 42 ui_progress__ops = &tui_progress__ops;
42} 43}
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index b9401482d110..2f612562978c 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -9,6 +9,7 @@
9#include "../util.h" 9#include "../util.h"
10#include "../libslang.h" 10#include "../libslang.h"
11#include "../keysyms.h" 11#include "../keysyms.h"
12#include "tui.h"
12 13
13static volatile int ui__need_resize; 14static volatile int ui__need_resize;
14 15
@@ -119,7 +120,7 @@ int ui__init(void)
119 120
120 ui_helpline__init(); 121 ui_helpline__init();
121 ui_browser__init(); 122 ui_browser__init();
122 ui_progress__init(); 123 tui_progress__init();
123 124
124 signal(SIGSEGV, ui__signal); 125 signal(SIGSEGV, ui__signal);
125 signal(SIGFPE, ui__signal); 126 signal(SIGFPE, ui__signal);
diff --git a/tools/perf/ui/tui/tui.h b/tools/perf/ui/tui/tui.h
new file mode 100644
index 000000000000..18961c7b6ec5
--- /dev/null
+++ b/tools/perf/ui/tui/tui.h
@@ -0,0 +1,6 @@
1#ifndef _PERF_TUI_H_
2#define _PERF_TUI_H_ 1
3
4void tui_progress__init(void);
5
6#endif /* _PERF_TUI_H_ */
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h
index 70cb0d4eb8aa..ab88383f8be8 100644
--- a/tools/perf/ui/ui.h
+++ b/tools/perf/ui/ui.h
@@ -6,13 +6,14 @@
6#include <linux/compiler.h> 6#include <linux/compiler.h>
7 7
8extern pthread_mutex_t ui__lock; 8extern pthread_mutex_t ui__lock;
9extern void *perf_gtk_handle;
9 10
10extern int use_browser; 11extern int use_browser;
11 12
12void setup_browser(bool fallback_to_pager); 13void setup_browser(bool fallback_to_pager);
13void exit_browser(bool wait_for_ok); 14void exit_browser(bool wait_for_ok);
14 15
15#ifdef SLANG_SUPPORT 16#ifdef HAVE_SLANG_SUPPORT
16int ui__init(void); 17int ui__init(void);
17void ui__exit(bool wait_for_ok); 18void ui__exit(bool wait_for_ok);
18#else 19#else
@@ -23,17 +24,6 @@ static inline int ui__init(void)
23static inline void ui__exit(bool wait_for_ok __maybe_unused) {} 24static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
24#endif 25#endif
25 26
26#ifdef GTK2_SUPPORT
27int perf_gtk__init(void);
28void perf_gtk__exit(bool wait_for_ok);
29#else
30static inline int perf_gtk__init(void)
31{
32 return -1;
33}
34static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
35#endif
36
37void ui__refresh_dimensions(bool force); 27void ui__refresh_dimensions(bool force);
38 28
39#endif /* _PERF_UI_H_ */ 29#endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 15a77b7c0e36..39f17507578d 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -19,6 +19,9 @@ if test -d ../../.git -o -f ../../.git
19then 19then
20 TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null ) 20 TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null )
21 CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID" 21 CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID"
22elif test -f ../../PERF-VERSION-FILE
23then
24 TAG=$(cut -d' ' -f3 ../../PERF-VERSION-FILE | sed -e 's/\"//g')
22fi 25fi
23if test -z "$TAG" 26if test -z "$TAG"
24then 27then
@@ -40,7 +43,7 @@ else
40 VC=unset 43 VC=unset
41fi 44fi
42test "$VN" = "$VC" || { 45test "$VN" = "$VC" || {
43 echo >&2 "PERF_VERSION = $VN" 46 echo >&2 " PERF_VERSION = $VN"
44 echo "#define PERF_VERSION \"$VN\"" >$GVF 47 echo "#define PERF_VERSION \"$VN\"" >$GVF
45} 48}
46 49
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7eae5488ecea..cf6242c92ee2 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -825,20 +825,16 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
825 dl->ops.target.offset = dl->ops.target.addr - 825 dl->ops.target.offset = dl->ops.target.addr -
826 map__rip_2objdump(map, sym->start); 826 map__rip_2objdump(map, sym->start);
827 827
828 /* 828 /* kcore has no symbols, so add the call target name */
829 * kcore has no symbols, so add the call target name if it is on the
830 * same map.
831 */
832 if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) { 829 if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
833 struct symbol *s; 830 struct addr_map_symbol target = {
834 u64 ip = dl->ops.target.addr; 831 .map = map,
835 832 .addr = dl->ops.target.addr,
836 if (ip >= map->start && ip <= map->end) { 833 };
837 ip = map->map_ip(map, ip); 834
838 s = map__find_symbol(map, ip, NULL); 835 if (!map_groups__find_ams(&target, NULL) &&
839 if (s && s->start == ip) 836 target.sym->start == target.al_addr)
840 dl->ops.target.name = strdup(s->name); 837 dl->ops.target.name = strdup(target.sym->name);
841 }
842 } 838 }
843 839
844 disasm__add(&notes->src->source, dl); 840 disasm__add(&notes->src->source, dl);
@@ -879,6 +875,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
879 FILE *file; 875 FILE *file;
880 int err = 0; 876 int err = 0;
881 char symfs_filename[PATH_MAX]; 877 char symfs_filename[PATH_MAX];
878 struct kcore_extract kce;
879 bool delete_extract = false;
882 880
883 if (filename) { 881 if (filename) {
884 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 882 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
@@ -940,6 +938,23 @@ fallback:
940 pr_debug("annotating [%p] %30s : [%p] %30s\n", 938 pr_debug("annotating [%p] %30s : [%p] %30s\n",
941 dso, dso->long_name, sym, sym->name); 939 dso, dso->long_name, sym, sym->name);
942 940
941 if (dso__is_kcore(dso)) {
942 kce.kcore_filename = symfs_filename;
943 kce.addr = map__rip_2objdump(map, sym->start);
944 kce.offs = sym->start;
945 kce.len = sym->end + 1 - sym->start;
946 if (!kcore_extract__create(&kce)) {
947 delete_extract = true;
948 strlcpy(symfs_filename, kce.extract_filename,
949 sizeof(symfs_filename));
950 if (free_filename) {
951 free(filename);
952 free_filename = false;
953 }
954 filename = symfs_filename;
955 }
956 }
957
943 snprintf(command, sizeof(command), 958 snprintf(command, sizeof(command),
944 "%s %s%s --start-address=0x%016" PRIx64 959 "%s %s%s --start-address=0x%016" PRIx64
945 " --stop-address=0x%016" PRIx64 960 " --stop-address=0x%016" PRIx64
@@ -972,6 +987,8 @@ fallback:
972 987
973 pclose(file); 988 pclose(file);
974out_free_filename: 989out_free_filename:
990 if (delete_extract)
991 kcore_extract__delete(&kce);
975 if (free_filename) 992 if (free_filename)
976 free(filename); 993 free(filename);
977 return err; 994 return err;
@@ -1070,7 +1087,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1070 (sizeof(src_line->p) * (src_line->nr_pcnt - 1)); 1087 (sizeof(src_line->p) * (src_line->nr_pcnt - 1));
1071 1088
1072 for (i = 0; i < len; i++) { 1089 for (i = 0; i < len; i++) {
1073 free(src_line->path); 1090 free_srcline(src_line->path);
1074 src_line = (void *)src_line + sizeof_src_line; 1091 src_line = (void *)src_line + sizeof_src_line;
1075 } 1092 }
1076 1093
@@ -1081,13 +1098,11 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1081/* Get the filename:line for the colored entries */ 1098/* Get the filename:line for the colored entries */
1082static int symbol__get_source_line(struct symbol *sym, struct map *map, 1099static int symbol__get_source_line(struct symbol *sym, struct map *map,
1083 struct perf_evsel *evsel, 1100 struct perf_evsel *evsel,
1084 struct rb_root *root, int len, 1101 struct rb_root *root, int len)
1085 const char *filename)
1086{ 1102{
1087 u64 start; 1103 u64 start;
1088 int i, k; 1104 int i, k;
1089 int evidx = evsel->idx; 1105 int evidx = evsel->idx;
1090 char cmd[PATH_MAX * 2];
1091 struct source_line *src_line; 1106 struct source_line *src_line;
1092 struct annotation *notes = symbol__annotation(sym); 1107 struct annotation *notes = symbol__annotation(sym);
1093 struct sym_hist *h = annotation__histogram(notes, evidx); 1108 struct sym_hist *h = annotation__histogram(notes, evidx);
@@ -1115,10 +1130,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1115 start = map__rip_2objdump(map, sym->start); 1130 start = map__rip_2objdump(map, sym->start);
1116 1131
1117 for (i = 0; i < len; i++) { 1132 for (i = 0; i < len; i++) {
1118 char *path = NULL;
1119 size_t line_len;
1120 u64 offset; 1133 u64 offset;
1121 FILE *fp;
1122 double percent_max = 0.0; 1134 double percent_max = 0.0;
1123 1135
1124 src_line->nr_pcnt = nr_pcnt; 1136 src_line->nr_pcnt = nr_pcnt;
@@ -1135,23 +1147,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1135 goto next; 1147 goto next;
1136 1148
1137 offset = start + i; 1149 offset = start + i;
1138 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); 1150 src_line->path = get_srcline(map->dso, offset);
1139 fp = popen(cmd, "r");
1140 if (!fp)
1141 goto next;
1142
1143 if (getline(&path, &line_len, fp) < 0 || !line_len)
1144 goto next_close;
1145
1146 src_line->path = malloc(sizeof(char) * line_len + 1);
1147 if (!src_line->path)
1148 goto next_close;
1149
1150 strcpy(src_line->path, path);
1151 insert_source_line(&tmp_root, src_line); 1151 insert_source_line(&tmp_root, src_line);
1152 1152
1153 next_close:
1154 pclose(fp);
1155 next: 1153 next:
1156 src_line = (void *)src_line + sizeof_src_line; 1154 src_line = (void *)src_line + sizeof_src_line;
1157 } 1155 }
@@ -1192,7 +1190,7 @@ static void print_summary(struct rb_root *root, const char *filename)
1192 1190
1193 path = src_line->path; 1191 path = src_line->path;
1194 color = get_percent_color(percent_max); 1192 color = get_percent_color(percent_max);
1195 color_fprintf(stdout, color, " %s", path); 1193 color_fprintf(stdout, color, " %s\n", path);
1196 1194
1197 node = rb_next(node); 1195 node = rb_next(node);
1198 } 1196 }
@@ -1356,7 +1354,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1356 bool full_paths, int min_pcnt, int max_lines) 1354 bool full_paths, int min_pcnt, int max_lines)
1357{ 1355{
1358 struct dso *dso = map->dso; 1356 struct dso *dso = map->dso;
1359 const char *filename = dso->long_name;
1360 struct rb_root source_line = RB_ROOT; 1357 struct rb_root source_line = RB_ROOT;
1361 u64 len; 1358 u64 len;
1362 1359
@@ -1366,9 +1363,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1366 len = symbol__size(sym); 1363 len = symbol__size(sym);
1367 1364
1368 if (print_lines) { 1365 if (print_lines) {
1369 symbol__get_source_line(sym, map, evsel, &source_line, 1366 symbol__get_source_line(sym, map, evsel, &source_line, len);
1370 len, filename); 1367 print_summary(&source_line, dso->long_name);
1371 print_summary(&source_line, filename);
1372 } 1368 }
1373 1369
1374 symbol__annotate_printf(sym, map, evsel, full_paths, 1370 symbol__annotate_printf(sym, map, evsel, full_paths,
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index af755156d278..834b7b57b788 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -150,7 +150,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
150 struct perf_evsel *evsel, bool print_lines, 150 struct perf_evsel *evsel, bool print_lines,
151 bool full_paths, int min_pcnt, int max_lines); 151 bool full_paths, int min_pcnt, int max_lines);
152 152
153#ifdef SLANG_SUPPORT 153#ifdef HAVE_SLANG_SUPPORT
154int symbol__tui_annotate(struct symbol *sym, struct map *map, 154int symbol__tui_annotate(struct symbol *sym, struct map *map,
155 struct perf_evsel *evsel, 155 struct perf_evsel *evsel,
156 struct hist_browser_timer *hbt); 156 struct hist_browser_timer *hbt);
@@ -165,30 +165,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
165} 165}
166#endif 166#endif
167 167
168#ifdef GTK2_SUPPORT
169int symbol__gtk_annotate(struct symbol *sym, struct map *map,
170 struct perf_evsel *evsel,
171 struct hist_browser_timer *hbt);
172
173static inline int hist_entry__gtk_annotate(struct hist_entry *he,
174 struct perf_evsel *evsel,
175 struct hist_browser_timer *hbt)
176{
177 return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
178}
179
180void perf_gtk__show_annotations(void);
181#else
182static inline int hist_entry__gtk_annotate(struct hist_entry *he __maybe_unused,
183 struct perf_evsel *evsel __maybe_unused,
184 struct hist_browser_timer *hbt __maybe_unused)
185{
186 return 0;
187}
188
189static inline void perf_gtk__show_annotations(void) {}
190#endif
191
192extern const char *disassembler_style; 168extern const char *disassembler_style;
193 169
194#endif /* __PERF_ANNOTATE_H */ 170#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 7ded71d19d75..a92770c98cc7 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -89,14 +89,14 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
89 return raw - build_id; 89 return raw - build_id;
90} 90}
91 91
92char *dso__build_id_filename(struct dso *self, char *bf, size_t size) 92char *dso__build_id_filename(struct dso *dso, char *bf, size_t size)
93{ 93{
94 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 94 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
95 95
96 if (!self->has_build_id) 96 if (!dso->has_build_id)
97 return NULL; 97 return NULL;
98 98
99 build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex); 99 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
100 if (bf == NULL) { 100 if (bf == NULL) {
101 if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir, 101 if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir,
102 build_id_hex, build_id_hex + 2) < 0) 102 build_id_hex, build_id_hex + 2) < 0)
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index a811f5c62e18..929f28a7c14d 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -10,10 +10,9 @@ extern struct perf_tool build_id__mark_dso_hit_ops;
10struct dso; 10struct dso;
11 11
12int build_id__sprintf(const u8 *build_id, int len, char *bf); 12int build_id__sprintf(const u8 *build_id, int len, char *bf);
13char *dso__build_id_filename(struct dso *self, char *bf, size_t size); 13char *dso__build_id_filename(struct dso *dso, char *bf, size_t size);
14 14
15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
16 struct perf_sample *sample, struct perf_evsel *evsel, 16 struct perf_sample *sample, struct perf_evsel *evsel,
17 struct machine *machine); 17 struct machine *machine);
18
19#endif 18#endif
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 26e367239873..7b176dd02e1a 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -70,8 +70,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
70extern char *perf_pathdup(const char *fmt, ...) 70extern char *perf_pathdup(const char *fmt, ...)
71 __attribute__((format (printf, 1, 2))); 71 __attribute__((format (printf, 1, 2)));
72 72
73#ifndef HAVE_STRLCPY 73/* Matches the libc/libbsd function attribute so we declare this unconditionally: */
74extern size_t strlcpy(char *dest, const char *src, size_t size); 74extern size_t strlcpy(char *dest, const char *src, size_t size);
75#endif
76 75
77#endif /* __PERF_CACHE_H */ 76#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 482f68081cd8..e3970e3eaacf 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -21,12 +21,6 @@
21 21
22__thread struct callchain_cursor callchain_cursor; 22__thread struct callchain_cursor callchain_cursor;
23 23
24#define chain_for_each_child(child, parent) \
25 list_for_each_entry(child, &parent->children, siblings)
26
27#define chain_for_each_child_safe(child, next, parent) \
28 list_for_each_entry_safe(child, next, &parent->children, siblings)
29
30static void 24static void
31rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 25rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
32 enum chain_mode mode) 26 enum chain_mode mode)
@@ -71,10 +65,16 @@ static void
71__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, 65__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
72 u64 min_hit) 66 u64 min_hit)
73{ 67{
68 struct rb_node *n;
74 struct callchain_node *child; 69 struct callchain_node *child;
75 70
76 chain_for_each_child(child, node) 71 n = rb_first(&node->rb_root_in);
72 while (n) {
73 child = rb_entry(n, struct callchain_node, rb_node_in);
74 n = rb_next(n);
75
77 __sort_chain_flat(rb_root, child, min_hit); 76 __sort_chain_flat(rb_root, child, min_hit);
77 }
78 78
79 if (node->hit && node->hit >= min_hit) 79 if (node->hit && node->hit >= min_hit)
80 rb_insert_callchain(rb_root, node, CHAIN_FLAT); 80 rb_insert_callchain(rb_root, node, CHAIN_FLAT);
@@ -94,11 +94,16 @@ sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
94static void __sort_chain_graph_abs(struct callchain_node *node, 94static void __sort_chain_graph_abs(struct callchain_node *node,
95 u64 min_hit) 95 u64 min_hit)
96{ 96{
97 struct rb_node *n;
97 struct callchain_node *child; 98 struct callchain_node *child;
98 99
99 node->rb_root = RB_ROOT; 100 node->rb_root = RB_ROOT;
101 n = rb_first(&node->rb_root_in);
102
103 while (n) {
104 child = rb_entry(n, struct callchain_node, rb_node_in);
105 n = rb_next(n);
100 106
101 chain_for_each_child(child, node) {
102 __sort_chain_graph_abs(child, min_hit); 107 __sort_chain_graph_abs(child, min_hit);
103 if (callchain_cumul_hits(child) >= min_hit) 108 if (callchain_cumul_hits(child) >= min_hit)
104 rb_insert_callchain(&node->rb_root, child, 109 rb_insert_callchain(&node->rb_root, child,
@@ -117,13 +122,18 @@ sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
117static void __sort_chain_graph_rel(struct callchain_node *node, 122static void __sort_chain_graph_rel(struct callchain_node *node,
118 double min_percent) 123 double min_percent)
119{ 124{
125 struct rb_node *n;
120 struct callchain_node *child; 126 struct callchain_node *child;
121 u64 min_hit; 127 u64 min_hit;
122 128
123 node->rb_root = RB_ROOT; 129 node->rb_root = RB_ROOT;
124 min_hit = ceil(node->children_hit * min_percent); 130 min_hit = ceil(node->children_hit * min_percent);
125 131
126 chain_for_each_child(child, node) { 132 n = rb_first(&node->rb_root_in);
133 while (n) {
134 child = rb_entry(n, struct callchain_node, rb_node_in);
135 n = rb_next(n);
136
127 __sort_chain_graph_rel(child, min_percent); 137 __sort_chain_graph_rel(child, min_percent);
128 if (callchain_cumul_hits(child) >= min_hit) 138 if (callchain_cumul_hits(child) >= min_hit)
129 rb_insert_callchain(&node->rb_root, child, 139 rb_insert_callchain(&node->rb_root, child,
@@ -173,19 +183,26 @@ create_child(struct callchain_node *parent, bool inherit_children)
173 return NULL; 183 return NULL;
174 } 184 }
175 new->parent = parent; 185 new->parent = parent;
176 INIT_LIST_HEAD(&new->children);
177 INIT_LIST_HEAD(&new->val); 186 INIT_LIST_HEAD(&new->val);
178 187
179 if (inherit_children) { 188 if (inherit_children) {
180 struct callchain_node *next; 189 struct rb_node *n;
190 struct callchain_node *child;
191
192 new->rb_root_in = parent->rb_root_in;
193 parent->rb_root_in = RB_ROOT;
181 194
182 list_splice(&parent->children, &new->children); 195 n = rb_first(&new->rb_root_in);
183 INIT_LIST_HEAD(&parent->children); 196 while (n) {
197 child = rb_entry(n, struct callchain_node, rb_node_in);
198 child->parent = new;
199 n = rb_next(n);
200 }
184 201
185 chain_for_each_child(next, new) 202 /* make it the first child */
186 next->parent = new; 203 rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
204 rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
187 } 205 }
188 list_add_tail(&new->siblings, &parent->children);
189 206
190 return new; 207 return new;
191} 208}
@@ -223,7 +240,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
223 } 240 }
224} 241}
225 242
226static void 243static struct callchain_node *
227add_child(struct callchain_node *parent, 244add_child(struct callchain_node *parent,
228 struct callchain_cursor *cursor, 245 struct callchain_cursor *cursor,
229 u64 period) 246 u64 period)
@@ -235,6 +252,19 @@ add_child(struct callchain_node *parent,
235 252
236 new->children_hit = 0; 253 new->children_hit = 0;
237 new->hit = period; 254 new->hit = period;
255 return new;
256}
257
258static s64 match_chain(struct callchain_cursor_node *node,
259 struct callchain_list *cnode)
260{
261 struct symbol *sym = node->sym;
262
263 if (cnode->ms.sym && sym &&
264 callchain_param.key == CCKEY_FUNCTION)
265 return cnode->ms.sym->start - sym->start;
266 else
267 return cnode->ip - node->ip;
238} 268}
239 269
240/* 270/*
@@ -272,9 +302,33 @@ split_add_child(struct callchain_node *parent,
272 302
273 /* create a new child for the new branch if any */ 303 /* create a new child for the new branch if any */
274 if (idx_total < cursor->nr) { 304 if (idx_total < cursor->nr) {
305 struct callchain_node *first;
306 struct callchain_list *cnode;
307 struct callchain_cursor_node *node;
308 struct rb_node *p, **pp;
309
275 parent->hit = 0; 310 parent->hit = 0;
276 add_child(parent, cursor, period);
277 parent->children_hit += period; 311 parent->children_hit += period;
312
313 node = callchain_cursor_current(cursor);
314 new = add_child(parent, cursor, period);
315
316 /*
317 * This is second child since we moved parent's children
318 * to new (first) child above.
319 */
320 p = parent->rb_root_in.rb_node;
321 first = rb_entry(p, struct callchain_node, rb_node_in);
322 cnode = list_first_entry(&first->val, struct callchain_list,
323 list);
324
325 if (match_chain(node, cnode) < 0)
326 pp = &p->rb_left;
327 else
328 pp = &p->rb_right;
329
330 rb_link_node(&new->rb_node_in, p, pp);
331 rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
278 } else { 332 } else {
279 parent->hit = period; 333 parent->hit = period;
280 } 334 }
@@ -291,16 +345,40 @@ append_chain_children(struct callchain_node *root,
291 u64 period) 345 u64 period)
292{ 346{
293 struct callchain_node *rnode; 347 struct callchain_node *rnode;
348 struct callchain_cursor_node *node;
349 struct rb_node **p = &root->rb_root_in.rb_node;
350 struct rb_node *parent = NULL;
351
352 node = callchain_cursor_current(cursor);
353 if (!node)
354 return;
294 355
295 /* lookup in childrens */ 356 /* lookup in childrens */
296 chain_for_each_child(rnode, root) { 357 while (*p) {
297 unsigned int ret = append_chain(rnode, cursor, period); 358 s64 ret;
359 struct callchain_list *cnode;
298 360
299 if (!ret) 361 parent = *p;
362 rnode = rb_entry(parent, struct callchain_node, rb_node_in);
363 cnode = list_first_entry(&rnode->val, struct callchain_list,
364 list);
365
366 /* just check first entry */
367 ret = match_chain(node, cnode);
368 if (ret == 0) {
369 append_chain(rnode, cursor, period);
300 goto inc_children_hit; 370 goto inc_children_hit;
371 }
372
373 if (ret < 0)
374 p = &parent->rb_left;
375 else
376 p = &parent->rb_right;
301 } 377 }
302 /* nothing in children, add to the current node */ 378 /* nothing in children, add to the current node */
303 add_child(root, cursor, period); 379 rnode = add_child(root, cursor, period);
380 rb_link_node(&rnode->rb_node_in, parent, p);
381 rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
304 382
305inc_children_hit: 383inc_children_hit:
306 root->children_hit += period; 384 root->children_hit += period;
@@ -325,28 +403,20 @@ append_chain(struct callchain_node *root,
325 */ 403 */
326 list_for_each_entry(cnode, &root->val, list) { 404 list_for_each_entry(cnode, &root->val, list) {
327 struct callchain_cursor_node *node; 405 struct callchain_cursor_node *node;
328 struct symbol *sym;
329 406
330 node = callchain_cursor_current(cursor); 407 node = callchain_cursor_current(cursor);
331 if (!node) 408 if (!node)
332 break; 409 break;
333 410
334 sym = node->sym; 411 if (match_chain(node, cnode) != 0)
335
336 if (cnode->ms.sym && sym &&
337 callchain_param.key == CCKEY_FUNCTION) {
338 if (cnode->ms.sym->start != sym->start)
339 break;
340 } else if (cnode->ip != node->ip)
341 break; 412 break;
342 413
343 if (!found) 414 found = true;
344 found = true;
345 415
346 callchain_cursor_advance(cursor); 416 callchain_cursor_advance(cursor);
347 } 417 }
348 418
349 /* matches not, relay on the parent */ 419 /* matches not, relay no the parent */
350 if (!found) { 420 if (!found) {
351 cursor->curr = curr_snap; 421 cursor->curr = curr_snap;
352 cursor->pos = start; 422 cursor->pos = start;
@@ -395,8 +465,9 @@ merge_chain_branch(struct callchain_cursor *cursor,
395 struct callchain_node *dst, struct callchain_node *src) 465 struct callchain_node *dst, struct callchain_node *src)
396{ 466{
397 struct callchain_cursor_node **old_last = cursor->last; 467 struct callchain_cursor_node **old_last = cursor->last;
398 struct callchain_node *child, *next_child; 468 struct callchain_node *child;
399 struct callchain_list *list, *next_list; 469 struct callchain_list *list, *next_list;
470 struct rb_node *n;
400 int old_pos = cursor->nr; 471 int old_pos = cursor->nr;
401 int err = 0; 472 int err = 0;
402 473
@@ -412,12 +483,16 @@ merge_chain_branch(struct callchain_cursor *cursor,
412 append_chain_children(dst, cursor, src->hit); 483 append_chain_children(dst, cursor, src->hit);
413 } 484 }
414 485
415 chain_for_each_child_safe(child, next_child, src) { 486 n = rb_first(&src->rb_root_in);
487 while (n) {
488 child = container_of(n, struct callchain_node, rb_node_in);
489 n = rb_next(n);
490 rb_erase(&child->rb_node_in, &src->rb_root_in);
491
416 err = merge_chain_branch(cursor, dst, child); 492 err = merge_chain_branch(cursor, dst, child);
417 if (err) 493 if (err)
418 break; 494 break;
419 495
420 list_del(&child->siblings);
421 free(child); 496 free(child);
422 } 497 }
423 498
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 2b585bc308cf..4f7f989876ec 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -21,11 +21,11 @@ enum chain_order {
21 21
22struct callchain_node { 22struct callchain_node {
23 struct callchain_node *parent; 23 struct callchain_node *parent;
24 struct list_head siblings;
25 struct list_head children;
26 struct list_head val; 24 struct list_head val;
27 struct rb_node rb_node; /* to sort nodes in an rbtree */ 25 struct rb_node rb_node_in; /* to insert nodes in an rbtree */
28 struct rb_root rb_root; /* sorted tree of children */ 26 struct rb_node rb_node; /* to sort nodes in an output tree */
27 struct rb_root rb_root_in; /* input tree of children */
28 struct rb_root rb_root; /* sorted output tree of children */
29 unsigned int val_nr; 29 unsigned int val_nr;
30 u64 hit; 30 u64 hit;
31 u64 children_hit; 31 u64 children_hit;
@@ -86,13 +86,12 @@ extern __thread struct callchain_cursor callchain_cursor;
86 86
87static inline void callchain_init(struct callchain_root *root) 87static inline void callchain_init(struct callchain_root *root)
88{ 88{
89 INIT_LIST_HEAD(&root->node.siblings);
90 INIT_LIST_HEAD(&root->node.children);
91 INIT_LIST_HEAD(&root->node.val); 89 INIT_LIST_HEAD(&root->node.val);
92 90
93 root->node.parent = NULL; 91 root->node.parent = NULL;
94 root->node.hit = 0; 92 root->node.hit = 0;
95 root->node.children_hit = 0; 93 root->node.children_hit = 0;
94 root->node.rb_root_in = RB_ROOT;
96 root->max_depth = 0; 95 root->max_depth = 0;
97} 96}
98 97
@@ -147,6 +146,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
147 146
148struct option; 147struct option;
149 148
149int record_parse_callchain(const char *arg, struct perf_record_opts *opts);
150int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 150int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
151int record_callchain_opt(const struct option *opt, const char *arg, int unset);
152
151extern const char record_callchain_help[]; 153extern const char record_callchain_help[];
152#endif /* __PERF_CALLCHAIN_H */ 154#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 11e46da17bbb..66e44a5019d5 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -318,8 +318,15 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
318 return r; 318 return r;
319} 319}
320 320
321int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent) 321int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
322{ 322{
323 const char *color = get_percent_color(percent); 323 va_list args;
324 double percent;
325 const char *color;
326
327 va_start(args, fmt);
328 percent = va_arg(args, double);
329 va_end(args);
330 color = get_percent_color(percent);
324 return color_snprintf(bf, size, color, fmt, percent); 331 return color_snprintf(bf, size, color, fmt, percent);
325} 332}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index dea082b79602..fced3840e99c 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -39,7 +39,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
39int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); 39int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
40int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); 40int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent); 42int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
43int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 43int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
44const char *get_percent_color(double percent); 44const char *get_percent_color(double percent);
45 45
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
new file mode 100644
index 000000000000..ee0df0e24cdb
--- /dev/null
+++ b/tools/perf/util/comm.c
@@ -0,0 +1,121 @@
1#include "comm.h"
2#include "util.h"
3#include <stdlib.h>
4#include <stdio.h>
5
6struct comm_str {
7 char *str;
8 struct rb_node rb_node;
9 int ref;
10};
11
12/* Should perhaps be moved to struct machine */
13static struct rb_root comm_str_root;
14
15static void comm_str__get(struct comm_str *cs)
16{
17 cs->ref++;
18}
19
20static void comm_str__put(struct comm_str *cs)
21{
22 if (!--cs->ref) {
23 rb_erase(&cs->rb_node, &comm_str_root);
24 free(cs->str);
25 free(cs);
26 }
27}
28
29static struct comm_str *comm_str__alloc(const char *str)
30{
31 struct comm_str *cs;
32
33 cs = zalloc(sizeof(*cs));
34 if (!cs)
35 return NULL;
36
37 cs->str = strdup(str);
38 if (!cs->str) {
39 free(cs);
40 return NULL;
41 }
42
43 return cs;
44}
45
46static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
47{
48 struct rb_node **p = &root->rb_node;
49 struct rb_node *parent = NULL;
50 struct comm_str *iter, *new;
51 int cmp;
52
53 while (*p != NULL) {
54 parent = *p;
55 iter = rb_entry(parent, struct comm_str, rb_node);
56
57 cmp = strcmp(str, iter->str);
58 if (!cmp)
59 return iter;
60
61 if (cmp < 0)
62 p = &(*p)->rb_left;
63 else
64 p = &(*p)->rb_right;
65 }
66
67 new = comm_str__alloc(str);
68 if (!new)
69 return NULL;
70
71 rb_link_node(&new->rb_node, parent, p);
72 rb_insert_color(&new->rb_node, root);
73
74 return new;
75}
76
77struct comm *comm__new(const char *str, u64 timestamp)
78{
79 struct comm *comm = zalloc(sizeof(*comm));
80
81 if (!comm)
82 return NULL;
83
84 comm->start = timestamp;
85
86 comm->comm_str = comm_str__findnew(str, &comm_str_root);
87 if (!comm->comm_str) {
88 free(comm);
89 return NULL;
90 }
91
92 comm_str__get(comm->comm_str);
93
94 return comm;
95}
96
97void comm__override(struct comm *comm, const char *str, u64 timestamp)
98{
99 struct comm_str *old = comm->comm_str;
100
101 comm->comm_str = comm_str__findnew(str, &comm_str_root);
102 if (!comm->comm_str) {
103 comm->comm_str = old;
104 return;
105 }
106
107 comm->start = timestamp;
108 comm_str__get(comm->comm_str);
109 comm_str__put(old);
110}
111
112void comm__free(struct comm *comm)
113{
114 comm_str__put(comm->comm_str);
115 free(comm);
116}
117
118const char *comm__str(const struct comm *comm)
119{
120 return comm->comm_str->str;
121}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
new file mode 100644
index 000000000000..7a86e5656710
--- /dev/null
+++ b/tools/perf/util/comm.h
@@ -0,0 +1,21 @@
1#ifndef __PERF_COMM_H
2#define __PERF_COMM_H
3
4#include "../perf.h"
5#include <linux/rbtree.h>
6#include <linux/list.h>
7
8struct comm_str;
9
10struct comm {
11 struct comm_str *comm_str;
12 u64 start;
13 struct list_head list;
14};
15
16void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp);
18const char *comm__str(const struct comm *comm);
19void comm__override(struct comm *comm, const char *str, u64 timestamp);
20
21#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index beb8cf9f9976..a9b48c42e81e 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -1,5 +1,5 @@
1#include "util.h" 1#include "util.h"
2#include "sysfs.h" 2#include "fs.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "cpumap.h" 4#include "cpumap.h"
5#include <assert.h> 5#include <assert.h>
@@ -216,7 +216,7 @@ int cpu_map__get_socket(struct cpu_map *map, int idx)
216 216
217 cpu = map->map[idx]; 217 cpu = map->map[idx];
218 218
219 mnt = sysfs_find_mountpoint(); 219 mnt = sysfs__mountpoint();
220 if (!mnt) 220 if (!mnt)
221 return -1; 221 return -1;
222 222
@@ -279,7 +279,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
279 279
280 cpu = map->map[idx]; 280 cpu = map->map[idx];
281 281
282 mnt = sysfs_find_mountpoint(); 282 mnt = sysfs__mountpoint();
283 if (!mnt) 283 if (!mnt)
284 return -1; 284 return -1;
285 285
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
new file mode 100644
index 000000000000..7d09faf85cf1
--- /dev/null
+++ b/tools/perf/util/data.c
@@ -0,0 +1,120 @@
1#include <linux/compiler.h>
2#include <linux/kernel.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <unistd.h>
6#include <string.h>
7
8#include "data.h"
9#include "util.h"
10
11static bool check_pipe(struct perf_data_file *file)
12{
13 struct stat st;
14 bool is_pipe = false;
15 int fd = perf_data_file__is_read(file) ?
16 STDIN_FILENO : STDOUT_FILENO;
17
18 if (!file->path) {
19 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
20 is_pipe = true;
21 } else {
22 if (!strcmp(file->path, "-"))
23 is_pipe = true;
24 }
25
26 if (is_pipe)
27 file->fd = fd;
28
29 return file->is_pipe = is_pipe;
30}
31
32static int check_backup(struct perf_data_file *file)
33{
34 struct stat st;
35
36 if (!stat(file->path, &st) && st.st_size) {
37 /* TODO check errors properly */
38 char oldname[PATH_MAX];
39 snprintf(oldname, sizeof(oldname), "%s.old",
40 file->path);
41 unlink(oldname);
42 rename(file->path, oldname);
43 }
44
45 return 0;
46}
47
48static int open_file_read(struct perf_data_file *file)
49{
50 struct stat st;
51 int fd;
52
53 fd = open(file->path, O_RDONLY);
54 if (fd < 0) {
55 int err = errno;
56
57 pr_err("failed to open %s: %s", file->path, strerror(err));
58 if (err == ENOENT && !strcmp(file->path, "perf.data"))
59 pr_err(" (try 'perf record' first)");
60 pr_err("\n");
61 return -err;
62 }
63
64 if (fstat(fd, &st) < 0)
65 goto out_close;
66
67 if (!file->force && st.st_uid && (st.st_uid != geteuid())) {
68 pr_err("file %s not owned by current user or root\n",
69 file->path);
70 goto out_close;
71 }
72
73 if (!st.st_size) {
74 pr_info("zero-sized file (%s), nothing to do!\n",
75 file->path);
76 goto out_close;
77 }
78
79 file->size = st.st_size;
80 return fd;
81
82 out_close:
83 close(fd);
84 return -1;
85}
86
87static int open_file_write(struct perf_data_file *file)
88{
89 if (check_backup(file))
90 return -1;
91
92 return open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
93}
94
95static int open_file(struct perf_data_file *file)
96{
97 int fd;
98
99 fd = perf_data_file__is_read(file) ?
100 open_file_read(file) : open_file_write(file);
101
102 file->fd = fd;
103 return fd < 0 ? -1 : 0;
104}
105
106int perf_data_file__open(struct perf_data_file *file)
107{
108 if (check_pipe(file))
109 return 0;
110
111 if (!file->path)
112 file->path = "perf.data";
113
114 return open_file(file);
115}
116
117void perf_data_file__close(struct perf_data_file *file)
118{
119 close(file->fd);
120}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
new file mode 100644
index 000000000000..8c2df80152a5
--- /dev/null
+++ b/tools/perf/util/data.h
@@ -0,0 +1,48 @@
1#ifndef __PERF_DATA_H
2#define __PERF_DATA_H
3
4#include <stdbool.h>
5
6enum perf_data_mode {
7 PERF_DATA_MODE_WRITE,
8 PERF_DATA_MODE_READ,
9};
10
11struct perf_data_file {
12 const char *path;
13 int fd;
14 bool is_pipe;
15 bool force;
16 unsigned long size;
17 enum perf_data_mode mode;
18};
19
20static inline bool perf_data_file__is_read(struct perf_data_file *file)
21{
22 return file->mode == PERF_DATA_MODE_READ;
23}
24
25static inline bool perf_data_file__is_write(struct perf_data_file *file)
26{
27 return file->mode == PERF_DATA_MODE_WRITE;
28}
29
30static inline int perf_data_file__is_pipe(struct perf_data_file *file)
31{
32 return file->is_pipe;
33}
34
35static inline int perf_data_file__fd(struct perf_data_file *file)
36{
37 return file->fd;
38}
39
40static inline unsigned long perf_data_file__size(struct perf_data_file *file)
41{
42 return file->size;
43}
44
45int perf_data_file__open(struct perf_data_file *file);
46void perf_data_file__close(struct perf_data_file *file);
47
48#endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index e3c1ff8512c8..af4c687cc49b 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -7,19 +7,20 @@
7char dso__symtab_origin(const struct dso *dso) 7char dso__symtab_origin(const struct dso *dso)
8{ 8{
9 static const char origin[] = { 9 static const char origin[] = {
10 [DSO_BINARY_TYPE__KALLSYMS] = 'k', 10 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
11 [DSO_BINARY_TYPE__VMLINUX] = 'v', 11 [DSO_BINARY_TYPE__VMLINUX] = 'v',
12 [DSO_BINARY_TYPE__JAVA_JIT] = 'j', 12 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
13 [DSO_BINARY_TYPE__DEBUGLINK] = 'l', 13 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
14 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', 14 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
15 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f', 15 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
16 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u', 16 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
17 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', 17 [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
18 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', 18 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
19 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', 19 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
20 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', 20 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
21 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', 21 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
22 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', 22 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
23 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
23 }; 24 };
24 25
25 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND) 26 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
@@ -64,6 +65,28 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
64 symbol_conf.symfs, dso->long_name); 65 symbol_conf.symfs, dso->long_name);
65 break; 66 break;
66 67
68 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
69 {
70 char *last_slash;
71 size_t len;
72 size_t dir_size;
73
74 last_slash = dso->long_name + dso->long_name_len;
75 while (last_slash != dso->long_name && *last_slash != '/')
76 last_slash--;
77
78 len = scnprintf(file, size, "%s", symbol_conf.symfs);
79 dir_size = last_slash - dso->long_name + 2;
80 if (dir_size > (size - len)) {
81 ret = -1;
82 break;
83 }
84 len += scnprintf(file + len, dir_size, "%s", dso->long_name);
85 len += scnprintf(file + len , size - len, ".debug%s",
86 last_slash);
87 break;
88 }
89
67 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO: 90 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
68 if (!dso->has_build_id) { 91 if (!dso->has_build_id) {
69 ret = -1; 92 ret = -1;
@@ -427,6 +450,7 @@ struct dso *dso__new(const char *name)
427 dso->rel = 0; 450 dso->rel = 0;
428 dso->sorted_by_name = 0; 451 dso->sorted_by_name = 0;
429 dso->has_build_id = 0; 452 dso->has_build_id = 0;
453 dso->has_srcline = 1;
430 dso->kernel = DSO_TYPE_USER; 454 dso->kernel = DSO_TYPE_USER;
431 dso->needs_swap = DSO_SWAP__UNSET; 455 dso->needs_swap = DSO_SWAP__UNSET;
432 INIT_LIST_HEAD(&dso->node); 456 INIT_LIST_HEAD(&dso->node);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index b793053335d6..9ac666abbe7e 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -6,6 +6,7 @@
6#include <stdbool.h> 6#include <stdbool.h>
7#include "types.h" 7#include "types.h"
8#include "map.h" 8#include "map.h"
9#include "build-id.h"
9 10
10enum dso_binary_type { 11enum dso_binary_type {
11 DSO_BINARY_TYPE__KALLSYMS = 0, 12 DSO_BINARY_TYPE__KALLSYMS = 0,
@@ -23,6 +24,7 @@ enum dso_binary_type {
23 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 24 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
24 DSO_BINARY_TYPE__KCORE, 25 DSO_BINARY_TYPE__KCORE,
25 DSO_BINARY_TYPE__GUEST_KCORE, 26 DSO_BINARY_TYPE__GUEST_KCORE,
27 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
26 DSO_BINARY_TYPE__NOT_FOUND, 28 DSO_BINARY_TYPE__NOT_FOUND,
27}; 29};
28 30
@@ -81,6 +83,7 @@ struct dso {
81 enum dso_binary_type data_type; 83 enum dso_binary_type data_type;
82 u8 adjust_symbols:1; 84 u8 adjust_symbols:1;
83 u8 has_build_id:1; 85 u8 has_build_id:1;
86 u8 has_srcline:1;
84 u8 hit:1; 87 u8 hit:1;
85 u8 annotate_warned:1; 88 u8 annotate_warned:1;
86 u8 sname_alloc:1; 89 u8 sname_alloc:1;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 63df031fc9c7..ec9ae1114ed4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -213,7 +213,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
213 &event->mmap.pgoff, 213 &event->mmap.pgoff,
214 execname); 214 execname);
215 215
216 if (n != 8) 216 if (n != 5)
217 continue; 217 continue;
218 218
219 if (prot[2] != 'x') 219 if (prot[2] != 'x')
@@ -512,18 +512,18 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
512 512
513int perf_event__process_comm(struct perf_tool *tool __maybe_unused, 513int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
514 union perf_event *event, 514 union perf_event *event,
515 struct perf_sample *sample __maybe_unused, 515 struct perf_sample *sample,
516 struct machine *machine) 516 struct machine *machine)
517{ 517{
518 return machine__process_comm_event(machine, event); 518 return machine__process_comm_event(machine, event, sample);
519} 519}
520 520
521int perf_event__process_lost(struct perf_tool *tool __maybe_unused, 521int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
522 union perf_event *event, 522 union perf_event *event,
523 struct perf_sample *sample __maybe_unused, 523 struct perf_sample *sample,
524 struct machine *machine) 524 struct machine *machine)
525{ 525{
526 return machine__process_lost_event(machine, event); 526 return machine__process_lost_event(machine, event, sample);
527} 527}
528 528
529size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) 529size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
@@ -546,18 +546,18 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
546 546
547int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, 547int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
548 union perf_event *event, 548 union perf_event *event,
549 struct perf_sample *sample __maybe_unused, 549 struct perf_sample *sample,
550 struct machine *machine) 550 struct machine *machine)
551{ 551{
552 return machine__process_mmap_event(machine, event); 552 return machine__process_mmap_event(machine, event, sample);
553} 553}
554 554
555int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, 555int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
556 union perf_event *event, 556 union perf_event *event,
557 struct perf_sample *sample __maybe_unused, 557 struct perf_sample *sample,
558 struct machine *machine) 558 struct machine *machine)
559{ 559{
560 return machine__process_mmap2_event(machine, event); 560 return machine__process_mmap2_event(machine, event, sample);
561} 561}
562 562
563size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) 563size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
@@ -569,18 +569,18 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
569 569
570int perf_event__process_fork(struct perf_tool *tool __maybe_unused, 570int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
571 union perf_event *event, 571 union perf_event *event,
572 struct perf_sample *sample __maybe_unused, 572 struct perf_sample *sample,
573 struct machine *machine) 573 struct machine *machine)
574{ 574{
575 return machine__process_fork_event(machine, event); 575 return machine__process_fork_event(machine, event, sample);
576} 576}
577 577
578int perf_event__process_exit(struct perf_tool *tool __maybe_unused, 578int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
579 union perf_event *event, 579 union perf_event *event,
580 struct perf_sample *sample __maybe_unused, 580 struct perf_sample *sample,
581 struct machine *machine) 581 struct machine *machine)
582{ 582{
583 return machine__process_exit_event(machine, event); 583 return machine__process_exit_event(machine, event, sample);
584} 584}
585 585
586size_t perf_event__fprintf(union perf_event *event, FILE *fp) 586size_t perf_event__fprintf(union perf_event *event, FILE *fp)
@@ -611,21 +611,21 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
611 611
612int perf_event__process(struct perf_tool *tool __maybe_unused, 612int perf_event__process(struct perf_tool *tool __maybe_unused,
613 union perf_event *event, 613 union perf_event *event,
614 struct perf_sample *sample __maybe_unused, 614 struct perf_sample *sample,
615 struct machine *machine) 615 struct machine *machine)
616{ 616{
617 return machine__process_event(machine, event); 617 return machine__process_event(machine, event, sample);
618} 618}
619 619
620void thread__find_addr_map(struct thread *self, 620void thread__find_addr_map(struct thread *thread,
621 struct machine *machine, u8 cpumode, 621 struct machine *machine, u8 cpumode,
622 enum map_type type, u64 addr, 622 enum map_type type, u64 addr,
623 struct addr_location *al) 623 struct addr_location *al)
624{ 624{
625 struct map_groups *mg = &self->mg; 625 struct map_groups *mg = &thread->mg;
626 bool load_map = false; 626 bool load_map = false;
627 627
628 al->thread = self; 628 al->thread = thread;
629 al->addr = addr; 629 al->addr = addr;
630 al->cpumode = cpumode; 630 al->cpumode = cpumode;
631 al->filtered = false; 631 al->filtered = false;
@@ -721,10 +721,10 @@ int perf_event__preprocess_sample(const union perf_event *event,
721 return -1; 721 return -1;
722 722
723 if (symbol_conf.comm_list && 723 if (symbol_conf.comm_list &&
724 !strlist__has_entry(symbol_conf.comm_list, thread->comm)) 724 !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread)))
725 goto out_filtered; 725 goto out_filtered;
726 726
727 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid); 727 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
728 /* 728 /*
729 * Have we already created the kernel maps for this machine? 729 * Have we already created the kernel maps for this machine?
730 * 730 *
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c67ecc457d29..f8d70f3003ab 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -61,6 +61,12 @@ struct read_event {
61 u64 id; 61 u64 id;
62}; 62};
63 63
64struct throttle_event {
65 struct perf_event_header header;
66 u64 time;
67 u64 id;
68 u64 stream_id;
69};
64 70
65#define PERF_SAMPLE_MASK \ 71#define PERF_SAMPLE_MASK \
66 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ 72 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
@@ -69,6 +75,9 @@ struct read_event {
69 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \ 75 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
70 PERF_SAMPLE_IDENTIFIER) 76 PERF_SAMPLE_IDENTIFIER)
71 77
78/* perf sample has 16 bits size limit */
79#define PERF_SAMPLE_MAX_SIZE (1 << 16)
80
72struct sample_event { 81struct sample_event {
73 struct perf_event_header header; 82 struct perf_event_header header;
74 u64 array[]; 83 u64 array[];
@@ -111,6 +120,7 @@ struct perf_sample {
111 u64 stream_id; 120 u64 stream_id;
112 u64 period; 121 u64 period;
113 u64 weight; 122 u64 weight;
123 u64 transaction;
114 u32 cpu; 124 u32 cpu;
115 u32 raw_size; 125 u32 raw_size;
116 u64 data_src; 126 u64 data_src;
@@ -177,6 +187,7 @@ union perf_event {
177 struct fork_event fork; 187 struct fork_event fork;
178 struct lost_event lost; 188 struct lost_event lost;
179 struct read_event read; 189 struct read_event read;
190 struct throttle_event throttle;
180 struct sample_event sample; 191 struct sample_event sample;
181 struct attr_event attr; 192 struct attr_event attr;
182 struct event_type_event event_type; 193 struct event_type_event event_type;
@@ -240,7 +251,8 @@ int perf_event__process(struct perf_tool *tool,
240 struct machine *machine); 251 struct machine *machine);
241 252
242struct addr_location; 253struct addr_location;
243int perf_event__preprocess_sample(const union perf_event *self, 254
255int perf_event__preprocess_sample(const union perf_event *event,
244 struct machine *machine, 256 struct machine *machine,
245 struct addr_location *al, 257 struct addr_location *al,
246 struct perf_sample *sample); 258 struct perf_sample *sample);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f9f77bee0b1b..b939221efd8d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -18,6 +18,7 @@
18#include <unistd.h> 18#include <unistd.h>
19 19
20#include "parse-events.h" 20#include "parse-events.h"
21#include "parse-options.h"
21 22
22#include <sys/mman.h> 23#include <sys/mman.h>
23 24
@@ -49,6 +50,18 @@ struct perf_evlist *perf_evlist__new(void)
49 return evlist; 50 return evlist;
50} 51}
51 52
53struct perf_evlist *perf_evlist__new_default(void)
54{
55 struct perf_evlist *evlist = perf_evlist__new();
56
57 if (evlist && perf_evlist__add_default(evlist)) {
58 perf_evlist__delete(evlist);
59 evlist = NULL;
60 }
61
62 return evlist;
63}
64
52/** 65/**
53 * perf_evlist__set_id_pos - set the positions of event ids. 66 * perf_evlist__set_id_pos - set the positions of event ids.
54 * @evlist: selected event list 67 * @evlist: selected event list
@@ -242,7 +255,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
242 if (evsel == NULL) 255 if (evsel == NULL)
243 return -1; 256 return -1;
244 257
245 evsel->handler.func = handler; 258 evsel->handler = handler;
246 perf_evlist__add(evlist, evsel); 259 perf_evlist__add(evlist, evsel);
247 return 0; 260 return 0;
248} 261}
@@ -527,7 +540,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
527 if ((old & md->mask) + size != ((old + size) & md->mask)) { 540 if ((old & md->mask) + size != ((old + size) & md->mask)) {
528 unsigned int offset = old; 541 unsigned int offset = old;
529 unsigned int len = min(sizeof(*event), size), cpy; 542 unsigned int len = min(sizeof(*event), size), cpy;
530 void *dst = &md->event_copy; 543 void *dst = md->event_copy;
531 544
532 do { 545 do {
533 cpy = min(md->mask + 1 - (offset & md->mask), len); 546 cpy = min(md->mask + 1 - (offset & md->mask), len);
@@ -537,7 +550,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
537 len -= cpy; 550 len -= cpy;
538 } while (len); 551 } while (len);
539 552
540 event = &md->event_copy; 553 event = (union perf_event *) md->event_copy;
541 } 554 }
542 555
543 old += size; 556 old += size;
@@ -545,12 +558,19 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
545 558
546 md->prev = old; 559 md->prev = old;
547 560
548 if (!evlist->overwrite)
549 perf_mmap__write_tail(md, old);
550
551 return event; 561 return event;
552} 562}
553 563
564void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
565{
566 if (!evlist->overwrite) {
567 struct perf_mmap *md = &evlist->mmap[idx];
568 unsigned int old = md->prev;
569
570 perf_mmap__write_tail(md, old);
571 }
572}
573
554static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 574static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
555{ 575{
556 if (evlist->mmap[idx].base != NULL) { 576 if (evlist->mmap[idx].base != NULL) {
@@ -587,6 +607,8 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
587 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 607 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
588 MAP_SHARED, fd, 0); 608 MAP_SHARED, fd, 0);
589 if (evlist->mmap[idx].base == MAP_FAILED) { 609 if (evlist->mmap[idx].base == MAP_FAILED) {
610 pr_debug2("failed to mmap perf event ring buffer, error %d\n",
611 errno);
590 evlist->mmap[idx].base = NULL; 612 evlist->mmap[idx].base = NULL;
591 return -1; 613 return -1;
592 } 614 }
@@ -595,9 +617,36 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
595 return 0; 617 return 0;
596} 618}
597 619
598static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask) 620static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
621 int prot, int mask, int cpu, int thread,
622 int *output)
599{ 623{
600 struct perf_evsel *evsel; 624 struct perf_evsel *evsel;
625
626 list_for_each_entry(evsel, &evlist->entries, node) {
627 int fd = FD(evsel, cpu, thread);
628
629 if (*output == -1) {
630 *output = fd;
631 if (__perf_evlist__mmap(evlist, idx, prot, mask,
632 *output) < 0)
633 return -1;
634 } else {
635 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
636 return -1;
637 }
638
639 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
640 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
641 return -1;
642 }
643
644 return 0;
645}
646
647static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot,
648 int mask)
649{
601 int cpu, thread; 650 int cpu, thread;
602 int nr_cpus = cpu_map__nr(evlist->cpus); 651 int nr_cpus = cpu_map__nr(evlist->cpus);
603 int nr_threads = thread_map__nr(evlist->threads); 652 int nr_threads = thread_map__nr(evlist->threads);
@@ -607,23 +656,9 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m
607 int output = -1; 656 int output = -1;
608 657
609 for (thread = 0; thread < nr_threads; thread++) { 658 for (thread = 0; thread < nr_threads; thread++) {
610 list_for_each_entry(evsel, &evlist->entries, node) { 659 if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask,
611 int fd = FD(evsel, cpu, thread); 660 cpu, thread, &output))
612 661 goto out_unmap;
613 if (output == -1) {
614 output = fd;
615 if (__perf_evlist__mmap(evlist, cpu,
616 prot, mask, output) < 0)
617 goto out_unmap;
618 } else {
619 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
620 goto out_unmap;
621 }
622
623 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
624 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
625 goto out_unmap;
626 }
627 } 662 }
628 } 663 }
629 664
@@ -635,9 +670,9 @@ out_unmap:
635 return -1; 670 return -1;
636} 671}
637 672
638static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask) 673static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot,
674 int mask)
639{ 675{
640 struct perf_evsel *evsel;
641 int thread; 676 int thread;
642 int nr_threads = thread_map__nr(evlist->threads); 677 int nr_threads = thread_map__nr(evlist->threads);
643 678
@@ -645,23 +680,9 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in
645 for (thread = 0; thread < nr_threads; thread++) { 680 for (thread = 0; thread < nr_threads; thread++) {
646 int output = -1; 681 int output = -1;
647 682
648 list_for_each_entry(evsel, &evlist->entries, node) { 683 if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0,
649 int fd = FD(evsel, 0, thread); 684 thread, &output))
650 685 goto out_unmap;
651 if (output == -1) {
652 output = fd;
653 if (__perf_evlist__mmap(evlist, thread,
654 prot, mask, output) < 0)
655 goto out_unmap;
656 } else {
657 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
658 goto out_unmap;
659 }
660
661 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
662 perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0)
663 goto out_unmap;
664 }
665 } 686 }
666 687
667 return 0; 688 return 0;
@@ -672,20 +693,76 @@ out_unmap:
672 return -1; 693 return -1;
673} 694}
674 695
675/** perf_evlist__mmap - Create per cpu maps to receive events 696static size_t perf_evlist__mmap_size(unsigned long pages)
676 * 697{
677 * @evlist - list of events 698 /* 512 kiB: default amount of unprivileged mlocked memory */
678 * @pages - map length in pages 699 if (pages == UINT_MAX)
679 * @overwrite - overwrite older events? 700 pages = (512 * 1024) / page_size;
680 * 701 else if (!is_power_of_2(pages))
681 * If overwrite is false the user needs to signal event consuption using: 702 return 0;
682 * 703
683 * struct perf_mmap *m = &evlist->mmap[cpu]; 704 return (pages + 1) * page_size;
684 * unsigned int head = perf_mmap__read_head(m); 705}
706
707int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
708 int unset __maybe_unused)
709{
710 unsigned int *mmap_pages = opt->value;
711 unsigned long pages, val;
712 size_t size;
713 static struct parse_tag tags[] = {
714 { .tag = 'B', .mult = 1 },
715 { .tag = 'K', .mult = 1 << 10 },
716 { .tag = 'M', .mult = 1 << 20 },
717 { .tag = 'G', .mult = 1 << 30 },
718 { .tag = 0 },
719 };
720
721 val = parse_tag_value(str, tags);
722 if (val != (unsigned long) -1) {
723 /* we got file size value */
724 pages = PERF_ALIGN(val, page_size) / page_size;
725 if (pages < (1UL << 31) && !is_power_of_2(pages)) {
726 pages = next_pow2(pages);
727 pr_info("rounding mmap pages size to %lu (%lu pages)\n",
728 pages * page_size, pages);
729 }
730 } else {
731 /* we got pages count value */
732 char *eptr;
733 pages = strtoul(str, &eptr, 10);
734 if (*eptr != '\0') {
735 pr_err("failed to parse --mmap_pages/-m value\n");
736 return -1;
737 }
738 }
739
740 if (pages > UINT_MAX || pages > SIZE_MAX / page_size) {
741 pr_err("--mmap_pages/-m value too big\n");
742 return -1;
743 }
744
745 size = perf_evlist__mmap_size(pages);
746 if (!size) {
747 pr_err("--mmap_pages/-m value must be a power of two.");
748 return -1;
749 }
750
751 *mmap_pages = pages;
752 return 0;
753}
754
755/**
756 * perf_evlist__mmap - Create mmaps to receive events.
757 * @evlist: list of events
758 * @pages: map length in pages
759 * @overwrite: overwrite older events?
685 * 760 *
686 * perf_mmap__write_tail(m, head) 761 * If @overwrite is %false the user needs to signal event consumption using
762 * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this
763 * automatically.
687 * 764 *
688 * Using perf_evlist__read_on_cpu does this automatically. 765 * Return: %0 on success, negative error code otherwise.
689 */ 766 */
690int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 767int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
691 bool overwrite) 768 bool overwrite)
@@ -695,14 +772,6 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
695 const struct thread_map *threads = evlist->threads; 772 const struct thread_map *threads = evlist->threads;
696 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 773 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
697 774
698 /* 512 kiB: default amount of unprivileged mlocked memory */
699 if (pages == UINT_MAX)
700 pages = (512 * 1024) / page_size;
701 else if (!is_power_of_2(pages))
702 return -EINVAL;
703
704 mask = pages * page_size - 1;
705
706 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 775 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
707 return -ENOMEM; 776 return -ENOMEM;
708 777
@@ -710,7 +779,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
710 return -ENOMEM; 779 return -ENOMEM;
711 780
712 evlist->overwrite = overwrite; 781 evlist->overwrite = overwrite;
713 evlist->mmap_len = (pages + 1) * page_size; 782 evlist->mmap_len = perf_evlist__mmap_size(pages);
783 pr_debug("mmap size %zuB\n", evlist->mmap_len);
784 mask = evlist->mmap_len - page_size - 1;
714 785
715 list_for_each_entry(evsel, &evlist->entries, node) { 786 list_for_each_entry(evsel, &evlist->entries, node) {
716 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 787 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -1066,3 +1137,66 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
1066 1137
1067 return printed + fprintf(fp, "\n");; 1138 return printed + fprintf(fp, "\n");;
1068} 1139}
1140
1141int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused,
1142 int err, char *buf, size_t size)
1143{
1144 char sbuf[128];
1145
1146 switch (err) {
1147 case ENOENT:
1148 scnprintf(buf, size, "%s",
1149 "Error:\tUnable to find debugfs\n"
1150 "Hint:\tWas your kernel was compiled with debugfs support?\n"
1151 "Hint:\tIs the debugfs filesystem mounted?\n"
1152 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
1153 break;
1154 case EACCES:
1155 scnprintf(buf, size,
1156 "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n"
1157 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
1158 debugfs_mountpoint, debugfs_mountpoint);
1159 break;
1160 default:
1161 scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
1162 break;
1163 }
1164
1165 return 0;
1166}
1167
1168int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1169 int err, char *buf, size_t size)
1170{
1171 int printed, value;
1172 char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1173
1174 switch (err) {
1175 case EACCES:
1176 case EPERM:
1177 printed = scnprintf(buf, size,
1178 "Error:\t%s.\n"
1179 "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
1180
1181 if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value))
1182 break;
1183
1184 printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
1185
1186 if (value >= 2) {
1187 printed += scnprintf(buf + printed, size - printed,
1188 "For your workloads it needs to be <= 1\nHint:\t");
1189 }
1190 printed += scnprintf(buf + printed, size - printed,
1191 "For system wide tracing it needs to be set to -1");
1192
1193 printed += scnprintf(buf + printed, size - printed,
1194 ".\nHint:\tThe current value is %d.", value);
1195 break;
1196 default:
1197 scnprintf(buf, size, "%s", emsg);
1198 break;
1199 }
1200
1201 return 0;
1202}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 880d7139d2fb..ecaa582f40e2 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -21,7 +21,7 @@ struct perf_mmap {
21 void *base; 21 void *base;
22 int mask; 22 int mask;
23 unsigned int prev; 23 unsigned int prev;
24 union perf_event event_copy; 24 char event_copy[PERF_SAMPLE_MAX_SIZE];
25}; 25};
26 26
27struct perf_evlist { 27struct perf_evlist {
@@ -31,7 +31,7 @@ struct perf_evlist {
31 int nr_groups; 31 int nr_groups;
32 int nr_fds; 32 int nr_fds;
33 int nr_mmaps; 33 int nr_mmaps;
34 int mmap_len; 34 size_t mmap_len;
35 int id_pos; 35 int id_pos;
36 int is_pos; 36 int is_pos;
37 u64 combined_sample_type; 37 u64 combined_sample_type;
@@ -53,6 +53,7 @@ struct perf_evsel_str_handler {
53}; 53};
54 54
55struct perf_evlist *perf_evlist__new(void); 55struct perf_evlist *perf_evlist__new(void);
56struct perf_evlist *perf_evlist__new_default(void);
56void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 57void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
57 struct thread_map *threads); 58 struct thread_map *threads);
58void perf_evlist__exit(struct perf_evlist *evlist); 59void perf_evlist__exit(struct perf_evlist *evlist);
@@ -87,7 +88,9 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
87 88
88struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); 89struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
89 90
90union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); 91union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
92
93void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
91 94
92int perf_evlist__open(struct perf_evlist *evlist); 95int perf_evlist__open(struct perf_evlist *evlist);
93void perf_evlist__close(struct perf_evlist *evlist); 96void perf_evlist__close(struct perf_evlist *evlist);
@@ -96,6 +99,7 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist);
96bool perf_can_sample_identifier(void); 99bool perf_can_sample_identifier(void);
97void perf_evlist__config(struct perf_evlist *evlist, 100void perf_evlist__config(struct perf_evlist *evlist,
98 struct perf_record_opts *opts); 101 struct perf_record_opts *opts);
102int perf_record_opts__config(struct perf_record_opts *opts);
99 103
100int perf_evlist__prepare_workload(struct perf_evlist *evlist, 104int perf_evlist__prepare_workload(struct perf_evlist *evlist,
101 struct perf_target *target, 105 struct perf_target *target,
@@ -103,6 +107,10 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
103 bool want_signal); 107 bool want_signal);
104int perf_evlist__start_workload(struct perf_evlist *evlist); 108int perf_evlist__start_workload(struct perf_evlist *evlist);
105 109
110int perf_evlist__parse_mmap_pages(const struct option *opt,
111 const char *str,
112 int unset);
113
106int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 114int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
107 bool overwrite); 115 bool overwrite);
108void perf_evlist__munmap(struct perf_evlist *evlist); 116void perf_evlist__munmap(struct perf_evlist *evlist);
@@ -163,10 +171,13 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
163 171
164size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); 172size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
165 173
174int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size);
175int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
176
166static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) 177static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
167{ 178{
168 struct perf_event_mmap_page *pc = mm->base; 179 struct perf_event_mmap_page *pc = mm->base;
169 int head = pc->data_head; 180 int head = ACCESS_ONCE(pc->data_head);
170 rmb(); 181 rmb();
171 return head; 182 return head;
172} 183}
@@ -179,7 +190,7 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md,
179 /* 190 /*
180 * ensure all reads are done before we write the tail out. 191 * ensure all reads are done before we write the tail out.
181 */ 192 */
182 /* mb(); */ 193 mb();
183 pc->data_tail = tail; 194 pc->data_tail = tail;
184} 195}
185 196
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9f1ef9bee2d0..5280820ed389 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -663,7 +663,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
663 } 663 }
664 664
665 if (opts->sample_address) 665 if (opts->sample_address)
666 attr->sample_type |= PERF_SAMPLE_DATA_SRC; 666 perf_evsel__set_sample_bit(evsel, DATA_SRC);
667 667
668 if (opts->no_delay) { 668 if (opts->no_delay) {
669 attr->watermark = 0; 669 attr->watermark = 0;
@@ -675,11 +675,14 @@ void perf_evsel__config(struct perf_evsel *evsel,
675 } 675 }
676 676
677 if (opts->sample_weight) 677 if (opts->sample_weight)
678 attr->sample_type |= PERF_SAMPLE_WEIGHT; 678 perf_evsel__set_sample_bit(evsel, WEIGHT);
679 679
680 attr->mmap = track; 680 attr->mmap = track;
681 attr->comm = track; 681 attr->comm = track;
682 682
683 if (opts->sample_transaction)
684 perf_evsel__set_sample_bit(evsel, TRANSACTION);
685
683 /* 686 /*
684 * XXX see the function comment above 687 * XXX see the function comment above
685 * 688 *
@@ -982,6 +985,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
982 ret += PRINT_ATTR2(exclude_host, exclude_guest); 985 ret += PRINT_ATTR2(exclude_host, exclude_guest);
983 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, 986 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
984 "excl.callchain_user", exclude_callchain_user); 987 "excl.callchain_user", exclude_callchain_user);
988 ret += PRINT_ATTR_U32(mmap2);
985 989
986 ret += PRINT_ATTR_U32(wakeup_events); 990 ret += PRINT_ATTR_U32(wakeup_events);
987 ret += PRINT_ATTR_U32(wakeup_watermark); 991 ret += PRINT_ATTR_U32(wakeup_watermark);
@@ -1047,6 +1051,8 @@ retry_open:
1047 group_fd, flags); 1051 group_fd, flags);
1048 if (FD(evsel, cpu, thread) < 0) { 1052 if (FD(evsel, cpu, thread) < 0) {
1049 err = -errno; 1053 err = -errno;
1054 pr_debug2("perf_event_open failed, error %d\n",
1055 err);
1050 goto try_fallback; 1056 goto try_fallback;
1051 } 1057 }
1052 set_rlimit = NO_CHANGE; 1058 set_rlimit = NO_CHANGE;
@@ -1213,6 +1219,7 @@ static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
1213 1219
1214 sample->pid = u.val32[0]; 1220 sample->pid = u.val32[0];
1215 sample->tid = u.val32[1]; 1221 sample->tid = u.val32[1];
1222 array--;
1216 } 1223 }
1217 1224
1218 return 0; 1225 return 0;
@@ -1452,6 +1459,9 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1452 array = (void *)array + sz; 1459 array = (void *)array + sz;
1453 OVERFLOW_CHECK_u64(array); 1460 OVERFLOW_CHECK_u64(array);
1454 data->user_stack.size = *array++; 1461 data->user_stack.size = *array++;
1462 if (WARN_ONCE(data->user_stack.size > sz,
1463 "user stack dump failure\n"))
1464 return -EFAULT;
1455 } 1465 }
1456 } 1466 }
1457 1467
@@ -1469,6 +1479,13 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1469 array++; 1479 array++;
1470 } 1480 }
1471 1481
1482 data->transaction = 0;
1483 if (type & PERF_SAMPLE_TRANSACTION) {
1484 OVERFLOW_CHECK_u64(array);
1485 data->transaction = *array;
1486 array++;
1487 }
1488
1472 return 0; 1489 return 0;
1473} 1490}
1474 1491
@@ -1561,6 +1578,9 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1561 if (type & PERF_SAMPLE_DATA_SRC) 1578 if (type & PERF_SAMPLE_DATA_SRC)
1562 result += sizeof(u64); 1579 result += sizeof(u64);
1563 1580
1581 if (type & PERF_SAMPLE_TRANSACTION)
1582 result += sizeof(u64);
1583
1564 return result; 1584 return result;
1565} 1585}
1566 1586
@@ -1734,6 +1754,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
1734 array++; 1754 array++;
1735 } 1755 }
1736 1756
1757 if (type & PERF_SAMPLE_TRANSACTION) {
1758 *array = sample->transaction;
1759 array++;
1760 }
1761
1737 return 0; 1762 return 0;
1738} 1763}
1739 1764
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4a7bdc713bab..64ec8e1a7a28 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -74,10 +74,7 @@ struct perf_evsel {
74 off_t id_offset; 74 off_t id_offset;
75 }; 75 };
76 struct cgroup_sel *cgrp; 76 struct cgroup_sel *cgrp;
77 struct { 77 void *handler;
78 void *func;
79 void *data;
80 } handler;
81 struct cpu_map *cpus; 78 struct cpu_map *cpus;
82 unsigned int sample_size; 79 unsigned int sample_size;
83 int id_pos; 80 int id_pos;
@@ -197,6 +194,12 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
197 (e1->attr.config == e2->attr.config); 194 (e1->attr.config == e2->attr.config);
198} 195}
199 196
197#define perf_evsel__cmp(a, b) \
198 ((a) && \
199 (b) && \
200 (a)->attr.type == (b)->attr.type && \
201 (a)->attr.config == (b)->attr.config)
202
200int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 203int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
201 int cpu, int thread, bool scale); 204 int cpu, int thread, bool scale);
202 205
diff --git a/tools/perf/util/fs.c b/tools/perf/util/fs.c
new file mode 100644
index 000000000000..f5be1f26e724
--- /dev/null
+++ b/tools/perf/util/fs.c
@@ -0,0 +1,119 @@
1
2/* TODO merge/factor into tools/lib/lk/debugfs.c */
3
4#include "util.h"
5#include "util/fs.h"
6
7static const char * const sysfs__fs_known_mountpoints[] = {
8 "/sys",
9 0,
10};
11
12static const char * const procfs__known_mountpoints[] = {
13 "/proc",
14 0,
15};
16
17struct fs {
18 const char *name;
19 const char * const *mounts;
20 char path[PATH_MAX + 1];
21 bool found;
22 long magic;
23};
24
25enum {
26 FS__SYSFS = 0,
27 FS__PROCFS = 1,
28};
29
30static struct fs fs__entries[] = {
31 [FS__SYSFS] = {
32 .name = "sysfs",
33 .mounts = sysfs__fs_known_mountpoints,
34 .magic = SYSFS_MAGIC,
35 },
36 [FS__PROCFS] = {
37 .name = "proc",
38 .mounts = procfs__known_mountpoints,
39 .magic = PROC_SUPER_MAGIC,
40 },
41};
42
43static bool fs__read_mounts(struct fs *fs)
44{
45 bool found = false;
46 char type[100];
47 FILE *fp;
48
49 fp = fopen("/proc/mounts", "r");
50 if (fp == NULL)
51 return NULL;
52
53 while (!found &&
54 fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
55 fs->path, type) == 2) {
56
57 if (strcmp(type, fs->name) == 0)
58 found = true;
59 }
60
61 fclose(fp);
62 return fs->found = found;
63}
64
65static int fs__valid_mount(const char *fs, long magic)
66{
67 struct statfs st_fs;
68
69 if (statfs(fs, &st_fs) < 0)
70 return -ENOENT;
71 else if (st_fs.f_type != magic)
72 return -ENOENT;
73
74 return 0;
75}
76
77static bool fs__check_mounts(struct fs *fs)
78{
79 const char * const *ptr;
80
81 ptr = fs->mounts;
82 while (*ptr) {
83 if (fs__valid_mount(*ptr, fs->magic) == 0) {
84 fs->found = true;
85 strcpy(fs->path, *ptr);
86 return true;
87 }
88 ptr++;
89 }
90
91 return false;
92}
93
94static const char *fs__get_mountpoint(struct fs *fs)
95{
96 if (fs__check_mounts(fs))
97 return fs->path;
98
99 return fs__read_mounts(fs) ? fs->path : NULL;
100}
101
102static const char *fs__mountpoint(int idx)
103{
104 struct fs *fs = &fs__entries[idx];
105
106 if (fs->found)
107 return (const char *)fs->path;
108
109 return fs__get_mountpoint(fs);
110}
111
112#define FS__MOUNTPOINT(name, idx) \
113const char *name##__mountpoint(void) \
114{ \
115 return fs__mountpoint(idx); \
116}
117
118FS__MOUNTPOINT(sysfs, FS__SYSFS);
119FS__MOUNTPOINT(procfs, FS__PROCFS);
diff --git a/tools/perf/util/fs.h b/tools/perf/util/fs.h
new file mode 100644
index 000000000000..5e09ce1bab0e
--- /dev/null
+++ b/tools/perf/util/fs.h
@@ -0,0 +1,7 @@
1#ifndef __PERF_FS
2#define __PERF_FS
3
4const char *sysfs__mountpoint(void);
5const char *procfs__mountpoint(void);
6
7#endif /* __PERF_FS */
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 3ac38031d534..36a885d2cd22 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -22,7 +22,7 @@ do
22 }' "Documentation/perf-$cmd.txt" 22 }' "Documentation/perf-$cmd.txt"
23done 23done
24 24
25echo "#ifdef LIBELF_SUPPORT" 25echo "#ifdef HAVE_LIBELF_SUPPORT"
26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | 26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt |
27sort | 27sort |
28while read cmd 28while read cmd
@@ -35,5 +35,5 @@ do
35 p 35 p
36 }' "Documentation/perf-$cmd.txt" 36 }' "Documentation/perf-$cmd.txt"
37done 37done
38echo "#endif /* LIBELF_SUPPORT */" 38echo "#endif /* HAVE_LIBELF_SUPPORT */"
39echo "};" 39echo "};"
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c3e5a3b817ab..26d9520a0c1b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -22,6 +22,7 @@
22#include "vdso.h" 22#include "vdso.h"
23#include "strbuf.h" 23#include "strbuf.h"
24#include "build-id.h" 24#include "build-id.h"
25#include "data.h"
25 26
26static bool no_buildid_cache = false; 27static bool no_buildid_cache = false;
27 28
@@ -2189,7 +2190,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2189{ 2190{
2190 struct header_print_data hd; 2191 struct header_print_data hd;
2191 struct perf_header *header = &session->header; 2192 struct perf_header *header = &session->header;
2192 int fd = session->fd; 2193 int fd = perf_data_file__fd(session->file);
2193 hd.fp = fp; 2194 hd.fp = fp;
2194 hd.full = full; 2195 hd.full = full;
2195 2196
@@ -2650,7 +2651,8 @@ static int perf_header__read_pipe(struct perf_session *session)
2650 struct perf_header *header = &session->header; 2651 struct perf_header *header = &session->header;
2651 struct perf_pipe_file_header f_header; 2652 struct perf_pipe_file_header f_header;
2652 2653
2653 if (perf_file_header__read_pipe(&f_header, header, session->fd, 2654 if (perf_file_header__read_pipe(&f_header, header,
2655 perf_data_file__fd(session->file),
2654 session->repipe) < 0) { 2656 session->repipe) < 0) {
2655 pr_debug("incompatible file format\n"); 2657 pr_debug("incompatible file format\n");
2656 return -EINVAL; 2658 return -EINVAL;
@@ -2751,18 +2753,19 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2751 2753
2752int perf_session__read_header(struct perf_session *session) 2754int perf_session__read_header(struct perf_session *session)
2753{ 2755{
2756 struct perf_data_file *file = session->file;
2754 struct perf_header *header = &session->header; 2757 struct perf_header *header = &session->header;
2755 struct perf_file_header f_header; 2758 struct perf_file_header f_header;
2756 struct perf_file_attr f_attr; 2759 struct perf_file_attr f_attr;
2757 u64 f_id; 2760 u64 f_id;
2758 int nr_attrs, nr_ids, i, j; 2761 int nr_attrs, nr_ids, i, j;
2759 int fd = session->fd; 2762 int fd = perf_data_file__fd(file);
2760 2763
2761 session->evlist = perf_evlist__new(); 2764 session->evlist = perf_evlist__new();
2762 if (session->evlist == NULL) 2765 if (session->evlist == NULL)
2763 return -ENOMEM; 2766 return -ENOMEM;
2764 2767
2765 if (session->fd_pipe) 2768 if (perf_data_file__is_pipe(file))
2766 return perf_header__read_pipe(session); 2769 return perf_header__read_pipe(session);
2767 2770
2768 if (perf_file_header__read(&f_header, header, fd) < 0) 2771 if (perf_file_header__read(&f_header, header, fd) < 0)
@@ -2777,7 +2780,7 @@ int perf_session__read_header(struct perf_session *session)
2777 if (f_header.data.size == 0) { 2780 if (f_header.data.size == 0) {
2778 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" 2781 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n"
2779 "Was the 'perf record' command properly terminated?\n", 2782 "Was the 'perf record' command properly terminated?\n",
2780 session->filename); 2783 file->path);
2781 } 2784 }
2782 2785
2783 nr_attrs = f_header.attrs.size / f_header.attr_size; 2786 nr_attrs = f_header.attrs.size / f_header.attr_size;
@@ -2990,18 +2993,19 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
2990 struct perf_session *session) 2993 struct perf_session *session)
2991{ 2994{
2992 ssize_t size_read, padding, size = event->tracing_data.size; 2995 ssize_t size_read, padding, size = event->tracing_data.size;
2993 off_t offset = lseek(session->fd, 0, SEEK_CUR); 2996 int fd = perf_data_file__fd(session->file);
2997 off_t offset = lseek(fd, 0, SEEK_CUR);
2994 char buf[BUFSIZ]; 2998 char buf[BUFSIZ];
2995 2999
2996 /* setup for reading amidst mmap */ 3000 /* setup for reading amidst mmap */
2997 lseek(session->fd, offset + sizeof(struct tracing_data_event), 3001 lseek(fd, offset + sizeof(struct tracing_data_event),
2998 SEEK_SET); 3002 SEEK_SET);
2999 3003
3000 size_read = trace_report(session->fd, &session->pevent, 3004 size_read = trace_report(fd, &session->pevent,
3001 session->repipe); 3005 session->repipe);
3002 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; 3006 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
3003 3007
3004 if (readn(session->fd, buf, padding) < 0) { 3008 if (readn(fd, buf, padding) < 0) {
3005 pr_err("%s: reading input file", __func__); 3009 pr_err("%s: reading input file", __func__);
3006 return -1; 3010 return -1;
3007 } 3011 }
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9ff6cf3e9a99..822903eaa201 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -160,6 +160,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
160 hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3); 160 hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
161 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); 161 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
162 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); 162 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
163
164 if (h->transaction)
165 hists__new_col_len(hists, HISTC_TRANSACTION,
166 hist_entry__transaction_len());
163} 167}
164 168
165void hists__output_recalc_col_len(struct hists *hists, int max_rows) 169void hists__output_recalc_col_len(struct hists *hists, int max_rows)
@@ -346,7 +350,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
346 struct rb_node **p; 350 struct rb_node **p;
347 struct rb_node *parent = NULL; 351 struct rb_node *parent = NULL;
348 struct hist_entry *he; 352 struct hist_entry *he;
349 int cmp; 353 int64_t cmp;
350 354
351 p = &hists->entries_in->rb_node; 355 p = &hists->entries_in->rb_node;
352 356
@@ -395,6 +399,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
395 if (!he) 399 if (!he)
396 return NULL; 400 return NULL;
397 401
402 hists->nr_entries++;
398 rb_link_node(&he->rb_node_in, parent, p); 403 rb_link_node(&he->rb_node_in, parent, p);
399 rb_insert_color(&he->rb_node_in, hists->entries_in); 404 rb_insert_color(&he->rb_node_in, hists->entries_in);
400out: 405out:
@@ -402,74 +407,16 @@ out:
402 return he; 407 return he;
403} 408}
404 409
405struct hist_entry *__hists__add_mem_entry(struct hists *self, 410struct hist_entry *__hists__add_entry(struct hists *hists,
406 struct addr_location *al,
407 struct symbol *sym_parent,
408 struct mem_info *mi,
409 u64 period,
410 u64 weight)
411{
412 struct hist_entry entry = {
413 .thread = al->thread,
414 .ms = {
415 .map = al->map,
416 .sym = al->sym,
417 },
418 .stat = {
419 .period = period,
420 .weight = weight,
421 .nr_events = 1,
422 },
423 .cpu = al->cpu,
424 .ip = al->addr,
425 .level = al->level,
426 .parent = sym_parent,
427 .filtered = symbol__parent_filter(sym_parent),
428 .hists = self,
429 .mem_info = mi,
430 .branch_info = NULL,
431 };
432 return add_hist_entry(self, &entry, al, period, weight);
433}
434
435struct hist_entry *__hists__add_branch_entry(struct hists *self,
436 struct addr_location *al,
437 struct symbol *sym_parent,
438 struct branch_info *bi,
439 u64 period,
440 u64 weight)
441{
442 struct hist_entry entry = {
443 .thread = al->thread,
444 .ms = {
445 .map = bi->to.map,
446 .sym = bi->to.sym,
447 },
448 .cpu = al->cpu,
449 .ip = bi->to.addr,
450 .level = al->level,
451 .stat = {
452 .period = period,
453 .nr_events = 1,
454 .weight = weight,
455 },
456 .parent = sym_parent,
457 .filtered = symbol__parent_filter(sym_parent),
458 .branch_info = bi,
459 .hists = self,
460 .mem_info = NULL,
461 };
462
463 return add_hist_entry(self, &entry, al, period, weight);
464}
465
466struct hist_entry *__hists__add_entry(struct hists *self,
467 struct addr_location *al, 411 struct addr_location *al,
468 struct symbol *sym_parent, u64 period, 412 struct symbol *sym_parent,
469 u64 weight) 413 struct branch_info *bi,
414 struct mem_info *mi,
415 u64 period, u64 weight, u64 transaction)
470{ 416{
471 struct hist_entry entry = { 417 struct hist_entry entry = {
472 .thread = al->thread, 418 .thread = al->thread,
419 .comm = thread__comm(al->thread),
473 .ms = { 420 .ms = {
474 .map = al->map, 421 .map = al->map,
475 .sym = al->sym, 422 .sym = al->sym,
@@ -478,18 +425,19 @@ struct hist_entry *__hists__add_entry(struct hists *self,
478 .ip = al->addr, 425 .ip = al->addr,
479 .level = al->level, 426 .level = al->level,
480 .stat = { 427 .stat = {
481 .period = period,
482 .nr_events = 1, 428 .nr_events = 1,
429 .period = period,
483 .weight = weight, 430 .weight = weight,
484 }, 431 },
485 .parent = sym_parent, 432 .parent = sym_parent,
486 .filtered = symbol__parent_filter(sym_parent), 433 .filtered = symbol__parent_filter(sym_parent),
487 .hists = self, 434 .hists = hists,
488 .branch_info = NULL, 435 .branch_info = bi,
489 .mem_info = NULL, 436 .mem_info = mi,
437 .transaction = transaction,
490 }; 438 };
491 439
492 return add_hist_entry(self, &entry, al, period, weight); 440 return add_hist_entry(hists, &entry, al, period, weight);
493} 441}
494 442
495int64_t 443int64_t
@@ -530,6 +478,7 @@ void hist_entry__free(struct hist_entry *he)
530{ 478{
531 free(he->branch_info); 479 free(he->branch_info);
532 free(he->mem_info); 480 free(he->mem_info);
481 free_srcline(he->srcline);
533 free(he); 482 free(he);
534} 483}
535 484
@@ -598,7 +547,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
598 hists__filter_entry_by_symbol(hists, he); 547 hists__filter_entry_by_symbol(hists, he);
599} 548}
600 549
601void hists__collapse_resort(struct hists *hists) 550void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
602{ 551{
603 struct rb_root *root; 552 struct rb_root *root;
604 struct rb_node *next; 553 struct rb_node *next;
@@ -625,6 +574,8 @@ void hists__collapse_resort(struct hists *hists)
625 */ 574 */
626 hists__apply_filters(hists, n); 575 hists__apply_filters(hists, n);
627 } 576 }
577 if (prog)
578 ui_progress__update(prog, 1);
628 } 579 }
629} 580}
630 581
@@ -884,7 +835,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
884 struct rb_node **p; 835 struct rb_node **p;
885 struct rb_node *parent = NULL; 836 struct rb_node *parent = NULL;
886 struct hist_entry *he; 837 struct hist_entry *he;
887 int cmp; 838 int64_t cmp;
888 839
889 if (sort__need_collapse) 840 if (sort__need_collapse)
890 root = &hists->entries_collapsed; 841 root = &hists->entries_collapsed;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 1329b6b6ffe6..b621347a1585 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -5,6 +5,8 @@
5#include <pthread.h> 5#include <pthread.h>
6#include "callchain.h" 6#include "callchain.h"
7#include "header.h" 7#include "header.h"
8#include "color.h"
9#include "ui/progress.h"
8 10
9extern struct callchain_param callchain_param; 11extern struct callchain_param callchain_param;
10 12
@@ -45,6 +47,8 @@ enum hist_column {
45 HISTC_CPU, 47 HISTC_CPU,
46 HISTC_SRCLINE, 48 HISTC_SRCLINE,
47 HISTC_MISPREDICT, 49 HISTC_MISPREDICT,
50 HISTC_IN_TX,
51 HISTC_ABORT,
48 HISTC_SYMBOL_FROM, 52 HISTC_SYMBOL_FROM,
49 HISTC_SYMBOL_TO, 53 HISTC_SYMBOL_TO,
50 HISTC_DSO_FROM, 54 HISTC_DSO_FROM,
@@ -57,6 +61,7 @@ enum hist_column {
57 HISTC_MEM_TLB, 61 HISTC_MEM_TLB,
58 HISTC_MEM_LVL, 62 HISTC_MEM_LVL,
59 HISTC_MEM_SNOOP, 63 HISTC_MEM_SNOOP,
64 HISTC_TRANSACTION,
60 HISTC_NR_COLS, /* Last entry */ 65 HISTC_NR_COLS, /* Last entry */
61}; 66};
62 67
@@ -79,54 +84,43 @@ struct hists {
79 u16 col_len[HISTC_NR_COLS]; 84 u16 col_len[HISTC_NR_COLS];
80}; 85};
81 86
82struct hist_entry *__hists__add_entry(struct hists *self, 87struct hist_entry *__hists__add_entry(struct hists *hists,
83 struct addr_location *al, 88 struct addr_location *al,
84 struct symbol *parent, u64 period, 89 struct symbol *parent,
85 u64 weight); 90 struct branch_info *bi,
91 struct mem_info *mi, u64 period,
92 u64 weight, u64 transaction);
86int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); 93int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
87int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); 94int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
88int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, 95int hist_entry__transaction_len(void);
96int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
89 struct hists *hists); 97 struct hists *hists);
90void hist_entry__free(struct hist_entry *); 98void hist_entry__free(struct hist_entry *);
91 99
92struct hist_entry *__hists__add_branch_entry(struct hists *self, 100void hists__output_resort(struct hists *hists);
93 struct addr_location *al, 101void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
94 struct symbol *sym_parent,
95 struct branch_info *bi,
96 u64 period,
97 u64 weight);
98
99struct hist_entry *__hists__add_mem_entry(struct hists *self,
100 struct addr_location *al,
101 struct symbol *sym_parent,
102 struct mem_info *mi,
103 u64 period,
104 u64 weight);
105
106void hists__output_resort(struct hists *self);
107void hists__collapse_resort(struct hists *self);
108 102
109void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 103void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
110void hists__output_recalc_col_len(struct hists *hists, int max_rows); 104void hists__output_recalc_col_len(struct hists *hists, int max_rows);
111 105
112void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); 106void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h);
113void hists__inc_nr_events(struct hists *self, u32 type); 107void hists__inc_nr_events(struct hists *hists, u32 type);
114void events_stats__inc(struct events_stats *stats, u32 type); 108void events_stats__inc(struct events_stats *stats, u32 type);
115size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); 109size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
116 110
117size_t hists__fprintf(struct hists *self, bool show_header, int max_rows, 111size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
118 int max_cols, float min_pcnt, FILE *fp); 112 int max_cols, float min_pcnt, FILE *fp);
119 113
120int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); 114int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
121int hist_entry__annotate(struct hist_entry *self, size_t privsize); 115int hist_entry__annotate(struct hist_entry *he, size_t privsize);
122 116
123void hists__filter_by_dso(struct hists *hists); 117void hists__filter_by_dso(struct hists *hists);
124void hists__filter_by_thread(struct hists *hists); 118void hists__filter_by_thread(struct hists *hists);
125void hists__filter_by_symbol(struct hists *hists); 119void hists__filter_by_symbol(struct hists *hists);
126 120
127u16 hists__col_len(struct hists *self, enum hist_column col); 121u16 hists__col_len(struct hists *hists, enum hist_column col);
128void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); 122void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len);
129bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); 123bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len);
130void hists__reset_col_len(struct hists *hists); 124void hists__reset_col_len(struct hists *hists);
131void hists__calc_col_len(struct hists *hists, struct hist_entry *he); 125void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
132 126
@@ -175,6 +169,18 @@ void perf_hpp__init(void);
175void perf_hpp__column_register(struct perf_hpp_fmt *format); 169void perf_hpp__column_register(struct perf_hpp_fmt *format);
176void perf_hpp__column_enable(unsigned col); 170void perf_hpp__column_enable(unsigned col);
177 171
172static inline size_t perf_hpp__use_color(void)
173{
174 return !symbol_conf.field_sep;
175}
176
177static inline size_t perf_hpp__color_overhead(void)
178{
179 return perf_hpp__use_color() ?
180 (COLOR_MAXLEN + sizeof(PERF_COLOR_RESET)) * PERF_HPP__MAX_INDEX
181 : 0;
182}
183
178struct perf_evlist; 184struct perf_evlist;
179 185
180struct hist_browser_timer { 186struct hist_browser_timer {
@@ -183,7 +189,7 @@ struct hist_browser_timer {
183 int refresh; 189 int refresh;
184}; 190};
185 191
186#ifdef SLANG_SUPPORT 192#ifdef HAVE_SLANG_SUPPORT
187#include "../ui/keysyms.h" 193#include "../ui/keysyms.h"
188int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 194int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
189 struct hist_browser_timer *hbt); 195 struct hist_browser_timer *hbt);
@@ -204,12 +210,9 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
204 return 0; 210 return 0;
205} 211}
206 212
207static inline int hist_entry__tui_annotate(struct hist_entry *self 213static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
208 __maybe_unused, 214 struct perf_evsel *evsel __maybe_unused,
209 struct perf_evsel *evsel 215 struct hist_browser_timer *hbt __maybe_unused)
210 __maybe_unused,
211 struct hist_browser_timer *hbt
212 __maybe_unused)
213{ 216{
214 return 0; 217 return 0;
215} 218}
@@ -224,20 +227,5 @@ static inline int script_browse(const char *script_opt __maybe_unused)
224#define K_SWITCH_INPUT_DATA -3000 227#define K_SWITCH_INPUT_DATA -3000
225#endif 228#endif
226 229
227#ifdef GTK2_SUPPORT 230unsigned int hists__sort_list_width(struct hists *hists);
228int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
229 struct hist_browser_timer *hbt __maybe_unused,
230 float min_pcnt);
231#else
232static inline
233int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
234 const char *help __maybe_unused,
235 struct hist_browser_timer *hbt __maybe_unused,
236 float min_pcnt __maybe_unused)
237{
238 return 0;
239}
240#endif
241
242unsigned int hists__sort_list_width(struct hists *self);
243#endif /* __PERF_HIST_H */ 231#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index cf6727e99c44..8f149655f497 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -1,7 +1,7 @@
1#ifndef _PERF_DWARF_REGS_H_ 1#ifndef _PERF_DWARF_REGS_H_
2#define _PERF_DWARF_REGS_H_ 2#define _PERF_DWARF_REGS_H_
3 3
4#ifdef DWARF_SUPPORT 4#ifdef HAVE_DWARF_SUPPORT
5const char *get_arch_regstr(unsigned int n); 5const char *get_arch_regstr(unsigned int n);
6#endif 6#endif
7 7
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
index 96b919dae11c..b003ad7200b2 100644
--- a/tools/perf/util/include/linux/compiler.h
+++ b/tools/perf/util/include/linux/compiler.h
@@ -2,20 +2,29 @@
2#define _PERF_LINUX_COMPILER_H_ 2#define _PERF_LINUX_COMPILER_H_
3 3
4#ifndef __always_inline 4#ifndef __always_inline
5#define __always_inline inline 5# define __always_inline inline __attribute__((always_inline))
6#endif 6#endif
7
7#define __user 8#define __user
9
8#ifndef __attribute_const__ 10#ifndef __attribute_const__
9#define __attribute_const__ 11# define __attribute_const__
10#endif 12#endif
11 13
12#ifndef __maybe_unused 14#ifndef __maybe_unused
13#define __maybe_unused __attribute__((unused)) 15# define __maybe_unused __attribute__((unused))
16#endif
17
18#ifndef __packed
19# define __packed __attribute__((__packed__))
14#endif 20#endif
15#define __packed __attribute__((__packed__))
16 21
17#ifndef __force 22#ifndef __force
18#define __force 23# define __force
24#endif
25
26#ifndef __weak
27# define __weak __attribute__((weak))
19#endif 28#endif
20 29
21#endif 30#endif
diff --git a/tools/perf/util/include/linux/magic.h b/tools/perf/util/include/linux/magic.h
index 58b64ed4da12..07d63cf3e0f6 100644
--- a/tools/perf/util/include/linux/magic.h
+++ b/tools/perf/util/include/linux/magic.h
@@ -9,4 +9,8 @@
9#define SYSFS_MAGIC 0x62656572 9#define SYSFS_MAGIC 0x62656572
10#endif 10#endif
11 11
12#ifndef PROC_SUPER_MAGIC
13#define PROC_SUPER_MAGIC 0x9fa0
14#endif
15
12#endif 16#endif
diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c
index 11a8d86f7fea..89715b64a315 100644
--- a/tools/perf/util/intlist.c
+++ b/tools/perf/util/intlist.c
@@ -20,6 +20,7 @@ static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
20 20
21 if (node != NULL) { 21 if (node != NULL) {
22 node->i = i; 22 node->i = i;
23 node->priv = NULL;
23 rc = &node->rb_node; 24 rc = &node->rb_node;
24 } 25 }
25 26
@@ -57,22 +58,36 @@ void intlist__remove(struct intlist *ilist, struct int_node *node)
57 rblist__remove_node(&ilist->rblist, &node->rb_node); 58 rblist__remove_node(&ilist->rblist, &node->rb_node);
58} 59}
59 60
60struct int_node *intlist__find(struct intlist *ilist, int i) 61static struct int_node *__intlist__findnew(struct intlist *ilist,
62 int i, bool create)
61{ 63{
62 struct int_node *node; 64 struct int_node *node = NULL;
63 struct rb_node *rb_node; 65 struct rb_node *rb_node;
64 66
65 if (ilist == NULL) 67 if (ilist == NULL)
66 return NULL; 68 return NULL;
67 69
68 node = NULL; 70 if (create)
69 rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); 71 rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i));
72 else
73 rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
74
70 if (rb_node) 75 if (rb_node)
71 node = container_of(rb_node, struct int_node, rb_node); 76 node = container_of(rb_node, struct int_node, rb_node);
72 77
73 return node; 78 return node;
74} 79}
75 80
81struct int_node *intlist__find(struct intlist *ilist, int i)
82{
83 return __intlist__findnew(ilist, i, false);
84}
85
86struct int_node *intlist__findnew(struct intlist *ilist, int i)
87{
88 return __intlist__findnew(ilist, i, true);
89}
90
76static int intlist__parse_list(struct intlist *ilist, const char *s) 91static int intlist__parse_list(struct intlist *ilist, const char *s)
77{ 92{
78 char *sep; 93 char *sep;
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h
index 62351dad848f..aa6877d36858 100644
--- a/tools/perf/util/intlist.h
+++ b/tools/perf/util/intlist.h
@@ -9,6 +9,7 @@
9struct int_node { 9struct int_node {
10 struct rb_node rb_node; 10 struct rb_node rb_node;
11 int i; 11 int i;
12 void *priv;
12}; 13};
13 14
14struct intlist { 15struct intlist {
@@ -23,6 +24,7 @@ int intlist__add(struct intlist *ilist, int i);
23 24
24struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx); 25struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx);
25struct int_node *intlist__find(struct intlist *ilist, int i); 26struct int_node *intlist__find(struct intlist *ilist, int i);
27struct int_node *intlist__findnew(struct intlist *ilist, int i);
26 28
27static inline bool intlist__has_entry(struct intlist *ilist, int i) 29static inline bool intlist__has_entry(struct intlist *ilist, int i)
28{ 30{
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 6188d2876a71..ce034c183a7e 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -40,12 +40,29 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
40 return -ENOMEM; 40 return -ENOMEM;
41 41
42 snprintf(comm, sizeof(comm), "[guest/%d]", pid); 42 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
43 thread__set_comm(thread, comm); 43 thread__set_comm(thread, comm, 0);
44 } 44 }
45 45
46 return 0; 46 return 0;
47} 47}
48 48
49struct machine *machine__new_host(void)
50{
51 struct machine *machine = malloc(sizeof(*machine));
52
53 if (machine != NULL) {
54 machine__init(machine, "", HOST_KERNEL_ID);
55
56 if (machine__create_kernel_maps(machine) < 0)
57 goto out_delete;
58 }
59
60 return machine;
61out_delete:
62 free(machine);
63 return NULL;
64}
65
49static void dsos__delete(struct list_head *dsos) 66static void dsos__delete(struct list_head *dsos)
50{ 67{
51 struct dso *pos, *n; 68 struct dso *pos, *n;
@@ -314,7 +331,8 @@ struct thread *machine__find_thread(struct machine *machine, pid_t tid)
314 return __machine__findnew_thread(machine, 0, tid, false); 331 return __machine__findnew_thread(machine, 0, tid, false);
315} 332}
316 333
317int machine__process_comm_event(struct machine *machine, union perf_event *event) 334int machine__process_comm_event(struct machine *machine, union perf_event *event,
335 struct perf_sample *sample)
318{ 336{
319 struct thread *thread = machine__findnew_thread(machine, 337 struct thread *thread = machine__findnew_thread(machine,
320 event->comm.pid, 338 event->comm.pid,
@@ -323,7 +341,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
323 if (dump_trace) 341 if (dump_trace)
324 perf_event__fprintf_comm(event, stdout); 342 perf_event__fprintf_comm(event, stdout);
325 343
326 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 344 if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) {
327 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 345 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
328 return -1; 346 return -1;
329 } 347 }
@@ -332,7 +350,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
332} 350}
333 351
334int machine__process_lost_event(struct machine *machine __maybe_unused, 352int machine__process_lost_event(struct machine *machine __maybe_unused,
335 union perf_event *event) 353 union perf_event *event, struct perf_sample *sample __maybe_unused)
336{ 354{
337 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 355 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
338 event->lost.id, event->lost.lost); 356 event->lost.id, event->lost.lost);
@@ -776,75 +794,44 @@ static int machine__set_modules_path(struct machine *machine)
776 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 794 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
777} 795}
778 796
779static int machine__create_modules(struct machine *machine) 797static int machine__create_module(void *arg, const char *name, u64 start)
780{ 798{
781 char *line = NULL; 799 struct machine *machine = arg;
782 size_t n;
783 FILE *file;
784 struct map *map; 800 struct map *map;
801
802 map = machine__new_module(machine, start, name);
803 if (map == NULL)
804 return -1;
805
806 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
807
808 return 0;
809}
810
811static int machine__create_modules(struct machine *machine)
812{
785 const char *modules; 813 const char *modules;
786 char path[PATH_MAX]; 814 char path[PATH_MAX];
787 815
788 if (machine__is_default_guest(machine)) 816 if (machine__is_default_guest(machine)) {
789 modules = symbol_conf.default_guest_modules; 817 modules = symbol_conf.default_guest_modules;
790 else { 818 } else {
791 sprintf(path, "%s/proc/modules", machine->root_dir); 819 snprintf(path, PATH_MAX, "%s/proc/modules", machine->root_dir);
792 modules = path; 820 modules = path;
793 } 821 }
794 822
795 if (symbol__restricted_filename(modules, "/proc/modules")) 823 if (symbol__restricted_filename(modules, "/proc/modules"))
796 return -1; 824 return -1;
797 825
798 file = fopen(modules, "r"); 826 if (modules__parse(modules, machine, machine__create_module))
799 if (file == NULL)
800 return -1; 827 return -1;
801 828
802 while (!feof(file)) { 829 if (!machine__set_modules_path(machine))
803 char name[PATH_MAX]; 830 return 0;
804 u64 start;
805 char *sep;
806 int line_len;
807
808 line_len = getline(&line, &n, file);
809 if (line_len < 0)
810 break;
811
812 if (!line)
813 goto out_failure;
814
815 line[--line_len] = '\0'; /* \n */
816
817 sep = strrchr(line, 'x');
818 if (sep == NULL)
819 continue;
820
821 hex2u64(sep + 1, &start);
822
823 sep = strchr(line, ' ');
824 if (sep == NULL)
825 continue;
826
827 *sep = '\0';
828
829 snprintf(name, sizeof(name), "[%s]", line);
830 map = machine__new_module(machine, start, name);
831 if (map == NULL)
832 goto out_delete_line;
833 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
834 }
835 831
836 free(line); 832 pr_debug("Problems setting modules path maps, continuing anyway...\n");
837 fclose(file);
838 833
839 if (machine__set_modules_path(machine) < 0) {
840 pr_debug("Problems setting modules path maps, continuing anyway...\n");
841 }
842 return 0; 834 return 0;
843
844out_delete_line:
845 free(line);
846out_failure:
847 return -1;
848} 835}
849 836
850int machine__create_kernel_maps(struct machine *machine) 837int machine__create_kernel_maps(struct machine *machine)
@@ -998,7 +985,8 @@ out_problem:
998} 985}
999 986
1000int machine__process_mmap2_event(struct machine *machine, 987int machine__process_mmap2_event(struct machine *machine,
1001 union perf_event *event) 988 union perf_event *event,
989 struct perf_sample *sample __maybe_unused)
1002{ 990{
1003 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 991 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1004 struct thread *thread; 992 struct thread *thread;
@@ -1045,7 +1033,8 @@ out_problem:
1045 return 0; 1033 return 0;
1046} 1034}
1047 1035
1048int machine__process_mmap_event(struct machine *machine, union perf_event *event) 1036int machine__process_mmap_event(struct machine *machine, union perf_event *event,
1037 struct perf_sample *sample __maybe_unused)
1049{ 1038{
1050 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1039 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1051 struct thread *thread; 1040 struct thread *thread;
@@ -1102,7 +1091,8 @@ static void machine__remove_thread(struct machine *machine, struct thread *th)
1102 list_add_tail(&th->node, &machine->dead_threads); 1091 list_add_tail(&th->node, &machine->dead_threads);
1103} 1092}
1104 1093
1105int machine__process_fork_event(struct machine *machine, union perf_event *event) 1094int machine__process_fork_event(struct machine *machine, union perf_event *event,
1095 struct perf_sample *sample)
1106{ 1096{
1107 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1097 struct thread *thread = machine__find_thread(machine, event->fork.tid);
1108 struct thread *parent = machine__findnew_thread(machine, 1098 struct thread *parent = machine__findnew_thread(machine,
@@ -1119,7 +1109,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1119 perf_event__fprintf_task(event, stdout); 1109 perf_event__fprintf_task(event, stdout);
1120 1110
1121 if (thread == NULL || parent == NULL || 1111 if (thread == NULL || parent == NULL ||
1122 thread__fork(thread, parent) < 0) { 1112 thread__fork(thread, parent, sample->time) < 0) {
1123 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 1113 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
1124 return -1; 1114 return -1;
1125 } 1115 }
@@ -1127,8 +1117,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1127 return 0; 1117 return 0;
1128} 1118}
1129 1119
1130int machine__process_exit_event(struct machine *machine __maybe_unused, 1120int machine__process_exit_event(struct machine *machine, union perf_event *event,
1131 union perf_event *event) 1121 struct perf_sample *sample __maybe_unused)
1132{ 1122{
1133 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1123 struct thread *thread = machine__find_thread(machine, event->fork.tid);
1134 1124
@@ -1141,23 +1131,24 @@ int machine__process_exit_event(struct machine *machine __maybe_unused,
1141 return 0; 1131 return 0;
1142} 1132}
1143 1133
1144int machine__process_event(struct machine *machine, union perf_event *event) 1134int machine__process_event(struct machine *machine, union perf_event *event,
1135 struct perf_sample *sample)
1145{ 1136{
1146 int ret; 1137 int ret;
1147 1138
1148 switch (event->header.type) { 1139 switch (event->header.type) {
1149 case PERF_RECORD_COMM: 1140 case PERF_RECORD_COMM:
1150 ret = machine__process_comm_event(machine, event); break; 1141 ret = machine__process_comm_event(machine, event, sample); break;
1151 case PERF_RECORD_MMAP: 1142 case PERF_RECORD_MMAP:
1152 ret = machine__process_mmap_event(machine, event); break; 1143 ret = machine__process_mmap_event(machine, event, sample); break;
1153 case PERF_RECORD_MMAP2: 1144 case PERF_RECORD_MMAP2:
1154 ret = machine__process_mmap2_event(machine, event); break; 1145 ret = machine__process_mmap2_event(machine, event, sample); break;
1155 case PERF_RECORD_FORK: 1146 case PERF_RECORD_FORK:
1156 ret = machine__process_fork_event(machine, event); break; 1147 ret = machine__process_fork_event(machine, event, sample); break;
1157 case PERF_RECORD_EXIT: 1148 case PERF_RECORD_EXIT:
1158 ret = machine__process_exit_event(machine, event); break; 1149 ret = machine__process_exit_event(machine, event, sample); break;
1159 case PERF_RECORD_LOST: 1150 case PERF_RECORD_LOST:
1160 ret = machine__process_lost_event(machine, event); break; 1151 ret = machine__process_lost_event(machine, event, sample); break;
1161 default: 1152 default:
1162 ret = -1; 1153 ret = -1;
1163 break; 1154 break;
@@ -1267,10 +1258,12 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1267 struct thread *thread, 1258 struct thread *thread,
1268 struct ip_callchain *chain, 1259 struct ip_callchain *chain,
1269 struct symbol **parent, 1260 struct symbol **parent,
1270 struct addr_location *root_al) 1261 struct addr_location *root_al,
1262 int max_stack)
1271{ 1263{
1272 u8 cpumode = PERF_RECORD_MISC_USER; 1264 u8 cpumode = PERF_RECORD_MISC_USER;
1273 unsigned int i; 1265 int chain_nr = min(max_stack, (int)chain->nr);
1266 int i;
1274 int err; 1267 int err;
1275 1268
1276 callchain_cursor_reset(&callchain_cursor); 1269 callchain_cursor_reset(&callchain_cursor);
@@ -1280,7 +1273,7 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1280 return 0; 1273 return 0;
1281 } 1274 }
1282 1275
1283 for (i = 0; i < chain->nr; i++) { 1276 for (i = 0; i < chain_nr; i++) {
1284 u64 ip; 1277 u64 ip;
1285 struct addr_location al; 1278 struct addr_location al;
1286 1279
@@ -1352,12 +1345,14 @@ int machine__resolve_callchain(struct machine *machine,
1352 struct thread *thread, 1345 struct thread *thread,
1353 struct perf_sample *sample, 1346 struct perf_sample *sample,
1354 struct symbol **parent, 1347 struct symbol **parent,
1355 struct addr_location *root_al) 1348 struct addr_location *root_al,
1349 int max_stack)
1356{ 1350{
1357 int ret; 1351 int ret;
1358 1352
1359 ret = machine__resolve_callchain_sample(machine, thread, 1353 ret = machine__resolve_callchain_sample(machine, thread,
1360 sample->callchain, parent, root_al); 1354 sample->callchain, parent,
1355 root_al, max_stack);
1361 if (ret) 1356 if (ret)
1362 return ret; 1357 return ret;
1363 1358
@@ -1376,3 +1371,26 @@ int machine__resolve_callchain(struct machine *machine,
1376 sample); 1371 sample);
1377 1372
1378} 1373}
1374
1375int machine__for_each_thread(struct machine *machine,
1376 int (*fn)(struct thread *thread, void *p),
1377 void *priv)
1378{
1379 struct rb_node *nd;
1380 struct thread *thread;
1381 int rc = 0;
1382
1383 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
1384 thread = rb_entry(nd, struct thread, rb_node);
1385 rc = fn(thread, priv);
1386 if (rc != 0)
1387 return rc;
1388 }
1389
1390 list_for_each_entry(thread, &machine->dead_threads, node) {
1391 rc = fn(thread, priv);
1392 if (rc != 0)
1393 return rc;
1394 }
1395 return rc;
1396}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 58a6be1fc739..2389ba81fafe 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -40,13 +40,20 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
40 40
41struct thread *machine__find_thread(struct machine *machine, pid_t tid); 41struct thread *machine__find_thread(struct machine *machine, pid_t tid);
42 42
43int machine__process_comm_event(struct machine *machine, union perf_event *event); 43int machine__process_comm_event(struct machine *machine, union perf_event *event,
44int machine__process_exit_event(struct machine *machine, union perf_event *event); 44 struct perf_sample *sample);
45int machine__process_fork_event(struct machine *machine, union perf_event *event); 45int machine__process_exit_event(struct machine *machine, union perf_event *event,
46int machine__process_lost_event(struct machine *machine, union perf_event *event); 46 struct perf_sample *sample);
47int machine__process_mmap_event(struct machine *machine, union perf_event *event); 47int machine__process_fork_event(struct machine *machine, union perf_event *event,
48int machine__process_mmap2_event(struct machine *machine, union perf_event *event); 48 struct perf_sample *sample);
49int machine__process_event(struct machine *machine, union perf_event *event); 49int machine__process_lost_event(struct machine *machine, union perf_event *event,
50 struct perf_sample *sample);
51int machine__process_mmap_event(struct machine *machine, union perf_event *event,
52 struct perf_sample *sample);
53int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
54 struct perf_sample *sample);
55int machine__process_event(struct machine *machine, union perf_event *event,
56 struct perf_sample *sample);
50 57
51typedef void (*machine__process_t)(struct machine *machine, void *data); 58typedef void (*machine__process_t)(struct machine *machine, void *data);
52 59
@@ -74,6 +81,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
74void machines__set_symbol_filter(struct machines *machines, 81void machines__set_symbol_filter(struct machines *machines,
75 symbol_filter_t symbol_filter); 82 symbol_filter_t symbol_filter);
76 83
84struct machine *machine__new_host(void);
77int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 85int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
78void machine__exit(struct machine *machine); 86void machine__exit(struct machine *machine);
79void machine__delete_dead_threads(struct machine *machine); 87void machine__delete_dead_threads(struct machine *machine);
@@ -91,7 +99,8 @@ int machine__resolve_callchain(struct machine *machine,
91 struct thread *thread, 99 struct thread *thread,
92 struct perf_sample *sample, 100 struct perf_sample *sample,
93 struct symbol **parent, 101 struct symbol **parent,
94 struct addr_location *root_al); 102 struct addr_location *root_al,
103 int max_stack);
95 104
96/* 105/*
97 * Default guest kernel is defined by parameter --guestkallsyms 106 * Default guest kernel is defined by parameter --guestkallsyms
@@ -165,4 +174,8 @@ void machines__destroy_kernel_maps(struct machines *machines);
165 174
166size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 175size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
167 176
177int machine__for_each_thread(struct machine *machine,
178 int (*fn)(struct thread *thread, void *p),
179 void *priv);
180
168#endif /* __PERF_MACHINE_H */ 181#endif /* __PERF_MACHINE_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 4f6680d2043b..ef5bc913ca7a 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -172,7 +172,7 @@ int map__load(struct map *map, symbol_filter_t filter)
172 pr_warning(", continuing without symbols\n"); 172 pr_warning(", continuing without symbols\n");
173 return -1; 173 return -1;
174 } else if (nr == 0) { 174 } else if (nr == 0) {
175#ifdef LIBELF_SUPPORT 175#ifdef HAVE_LIBELF_SUPPORT
176 const size_t len = strlen(name); 176 const size_t len = strlen(name);
177 const size_t real_len = len - sizeof(DSO__DELETED); 177 const size_t real_len = len - sizeof(DSO__DELETED);
178 178
@@ -252,10 +252,16 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
252 return fprintf(fp, "%s", dsoname); 252 return fprintf(fp, "%s", dsoname);
253} 253}
254 254
255/* 255/**
256 * map__rip_2objdump - convert symbol start address to objdump address.
257 * @map: memory map
258 * @rip: symbol start address
259 *
256 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 260 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
257 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is 261 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
258 * relative to section start. 262 * relative to section start.
263 *
264 * Return: Address suitable for passing to "objdump --start-address="
259 */ 265 */
260u64 map__rip_2objdump(struct map *map, u64 rip) 266u64 map__rip_2objdump(struct map *map, u64 rip)
261{ 267{
@@ -268,6 +274,29 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
268 return map->unmap_ip(map, rip); 274 return map->unmap_ip(map, rip);
269} 275}
270 276
277/**
278 * map__objdump_2mem - convert objdump address to a memory address.
279 * @map: memory map
280 * @ip: objdump address
281 *
282 * Closely related to map__rip_2objdump(), this function takes an address from
283 * objdump and converts it to a memory address. Note this assumes that @map
284 * contains the address. To be sure the result is valid, check it forwards
285 * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip
286 *
287 * Return: Memory address.
288 */
289u64 map__objdump_2mem(struct map *map, u64 ip)
290{
291 if (!map->dso->adjust_symbols)
292 return map->unmap_ip(map, ip);
293
294 if (map->dso->rel)
295 return map->unmap_ip(map, ip + map->pgoff);
296
297 return ip;
298}
299
271void map_groups__init(struct map_groups *mg) 300void map_groups__init(struct map_groups *mg)
272{ 301{
273 int i; 302 int i;
@@ -371,6 +400,23 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
371 return NULL; 400 return NULL;
372} 401}
373 402
403int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
404{
405 if (ams->addr < ams->map->start || ams->addr > ams->map->end) {
406 if (ams->map->groups == NULL)
407 return -1;
408 ams->map = map_groups__find(ams->map->groups, ams->map->type,
409 ams->addr);
410 if (ams->map == NULL)
411 return -1;
412 }
413
414 ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
415 ams->sym = map__find_symbol(ams->map, ams->al_addr, filter);
416
417 return ams->sym ? 0 : -1;
418}
419
374size_t __map_groups__fprintf_maps(struct map_groups *mg, 420size_t __map_groups__fprintf_maps(struct map_groups *mg,
375 enum map_type type, int verbose, FILE *fp) 421 enum map_type type, int verbose, FILE *fp)
376{ 422{
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 4886ca280536..e4e259c3ba16 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -84,6 +84,9 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip)
84/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ 84/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
85u64 map__rip_2objdump(struct map *map, u64 rip); 85u64 map__rip_2objdump(struct map *map, u64 rip);
86 86
87/* objdump address -> memory address */
88u64 map__objdump_2mem(struct map *map, u64 ip);
89
87struct symbol; 90struct symbol;
88 91
89typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); 92typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
@@ -167,6 +170,10 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
167 struct map **mapp, 170 struct map **mapp,
168 symbol_filter_t filter); 171 symbol_filter_t filter);
169 172
173struct addr_map_symbol;
174
175int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter);
176
170static inline 177static inline
171struct symbol *map_groups__find_function_by_name(struct map_groups *mg, 178struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
172 const char *name, struct map **mapp, 179 const char *name, struct map **mapp,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 98125319b158..c90e55cf7e82 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -998,8 +998,10 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
998 char evt_path[MAXPATHLEN]; 998 char evt_path[MAXPATHLEN];
999 char dir_path[MAXPATHLEN]; 999 char dir_path[MAXPATHLEN];
1000 1000
1001 if (debugfs_valid_mountpoint(tracing_events_path)) 1001 if (debugfs_valid_mountpoint(tracing_events_path)) {
1002 printf(" [ Tracepoints not available: %s ]\n", strerror(errno));
1002 return; 1003 return;
1004 }
1003 1005
1004 sys_dir = opendir(tracing_events_path); 1006 sys_dir = opendir(tracing_events_path);
1005 if (!sys_dir) 1007 if (!sys_dir)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 91346b753960..343299575b30 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -126,6 +126,37 @@ modifier_bp [rwx]{1,3}
126 126
127} 127}
128 128
129<config>{
130config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
131config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
132config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
133name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
134period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
135branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
136, { return ','; }
137"/" { BEGIN(INITIAL); return '/'; }
138{name_minus} { return str(yyscanner, PE_NAME); }
139}
140
141<mem>{
142{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
143: { return ':'; }
144{num_dec} { return value(yyscanner, 10); }
145{num_hex} { return value(yyscanner, 16); }
146 /*
147 * We need to separate 'mem:' scanner part, in order to get specific
148 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
149 * and we'd need to parse it manually. During the escape from <mem>
150 * state we need to put the escaping char back, so we dont miss it.
151 */
152. { unput(*yytext); BEGIN(INITIAL); }
153 /*
154 * We destroy the scanner after reaching EOF,
155 * but anyway just to be sure get back to INIT state.
156 */
157<<EOF>> { BEGIN(INITIAL); }
158}
159
129cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 160cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
130stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 161stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
131stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 162stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
@@ -162,18 +193,6 @@ speculative-read|speculative-load |
162refs|Reference|ops|access | 193refs|Reference|ops|access |
163misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); } 194misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
164 195
165<config>{
166config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
167config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
168config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
169name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
170period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
171branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
172, { return ','; }
173"/" { BEGIN(INITIAL); return '/'; }
174{name_minus} { return str(yyscanner, PE_NAME); }
175}
176
177mem: { BEGIN(mem); return PE_PREFIX_MEM; } 196mem: { BEGIN(mem); return PE_PREFIX_MEM; }
178r{num_raw_hex} { return raw(yyscanner); } 197r{num_raw_hex} { return raw(yyscanner); }
179{num_dec} { return value(yyscanner, 10); } 198{num_dec} { return value(yyscanner, 10); }
@@ -189,25 +208,7 @@ r{num_raw_hex} { return raw(yyscanner); }
189"}" { return '}'; } 208"}" { return '}'; }
190= { return '='; } 209= { return '='; }
191\n { } 210\n { }
192 211. { }
193<mem>{
194{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
195: { return ':'; }
196{num_dec} { return value(yyscanner, 10); }
197{num_hex} { return value(yyscanner, 16); }
198 /*
199 * We need to separate 'mem:' scanner part, in order to get specific
200 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
201 * and we'd need to parse it manually. During the escape from <mem>
202 * state we need to put the escaping char back, so we dont miss it.
203 */
204. { unput(*yytext); BEGIN(INITIAL); }
205 /*
206 * We destroy the scanner after reaching EOF,
207 * but anyway just to be sure get back to INIT state.
208 */
209<<EOF>> { BEGIN(INITIAL); }
210}
211 212
212%% 213%%
213 214
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 2bc9e70df7e2..31f404a032a9 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -339,10 +339,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
339 if (arg[1] != '-') { 339 if (arg[1] != '-') {
340 ctx->opt = arg + 1; 340 ctx->opt = arg + 1;
341 if (internal_help && *ctx->opt == 'h') 341 if (internal_help && *ctx->opt == 'h')
342 return parse_options_usage(usagestr, options); 342 return usage_with_options_internal(usagestr, options, 0);
343 switch (parse_short_opt(ctx, options)) { 343 switch (parse_short_opt(ctx, options)) {
344 case -1: 344 case -1:
345 return parse_options_usage(usagestr, options); 345 return parse_options_usage(usagestr, options, arg + 1, 1);
346 case -2: 346 case -2:
347 goto unknown; 347 goto unknown;
348 default: 348 default:
@@ -352,10 +352,11 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
352 check_typos(arg + 1, options); 352 check_typos(arg + 1, options);
353 while (ctx->opt) { 353 while (ctx->opt) {
354 if (internal_help && *ctx->opt == 'h') 354 if (internal_help && *ctx->opt == 'h')
355 return parse_options_usage(usagestr, options); 355 return usage_with_options_internal(usagestr, options, 0);
356 arg = ctx->opt;
356 switch (parse_short_opt(ctx, options)) { 357 switch (parse_short_opt(ctx, options)) {
357 case -1: 358 case -1:
358 return parse_options_usage(usagestr, options); 359 return parse_options_usage(usagestr, options, arg, 1);
359 case -2: 360 case -2:
360 /* fake a short option thing to hide the fact that we may have 361 /* fake a short option thing to hide the fact that we may have
361 * started to parse aggregated stuff 362 * started to parse aggregated stuff
@@ -383,12 +384,12 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
383 if (internal_help && !strcmp(arg + 2, "help-all")) 384 if (internal_help && !strcmp(arg + 2, "help-all"))
384 return usage_with_options_internal(usagestr, options, 1); 385 return usage_with_options_internal(usagestr, options, 1);
385 if (internal_help && !strcmp(arg + 2, "help")) 386 if (internal_help && !strcmp(arg + 2, "help"))
386 return parse_options_usage(usagestr, options); 387 return usage_with_options_internal(usagestr, options, 0);
387 if (!strcmp(arg + 2, "list-opts")) 388 if (!strcmp(arg + 2, "list-opts"))
388 return PARSE_OPT_LIST; 389 return PARSE_OPT_LIST;
389 switch (parse_long_opt(ctx, arg + 2, options)) { 390 switch (parse_long_opt(ctx, arg + 2, options)) {
390 case -1: 391 case -1:
391 return parse_options_usage(usagestr, options); 392 return parse_options_usage(usagestr, options, arg + 2, 0);
392 case -2: 393 case -2:
393 goto unknown; 394 goto unknown;
394 default: 395 default:
@@ -445,6 +446,89 @@ int parse_options(int argc, const char **argv, const struct option *options,
445#define USAGE_OPTS_WIDTH 24 446#define USAGE_OPTS_WIDTH 24
446#define USAGE_GAP 2 447#define USAGE_GAP 2
447 448
449static void print_option_help(const struct option *opts, int full)
450{
451 size_t pos;
452 int pad;
453
454 if (opts->type == OPTION_GROUP) {
455 fputc('\n', stderr);
456 if (*opts->help)
457 fprintf(stderr, "%s\n", opts->help);
458 return;
459 }
460 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
461 return;
462
463 pos = fprintf(stderr, " ");
464 if (opts->short_name)
465 pos += fprintf(stderr, "-%c", opts->short_name);
466 else
467 pos += fprintf(stderr, " ");
468
469 if (opts->long_name && opts->short_name)
470 pos += fprintf(stderr, ", ");
471 if (opts->long_name)
472 pos += fprintf(stderr, "--%s", opts->long_name);
473
474 switch (opts->type) {
475 case OPTION_ARGUMENT:
476 break;
477 case OPTION_LONG:
478 case OPTION_U64:
479 case OPTION_INTEGER:
480 case OPTION_UINTEGER:
481 if (opts->flags & PARSE_OPT_OPTARG)
482 if (opts->long_name)
483 pos += fprintf(stderr, "[=<n>]");
484 else
485 pos += fprintf(stderr, "[<n>]");
486 else
487 pos += fprintf(stderr, " <n>");
488 break;
489 case OPTION_CALLBACK:
490 if (opts->flags & PARSE_OPT_NOARG)
491 break;
492 /* FALLTHROUGH */
493 case OPTION_STRING:
494 if (opts->argh) {
495 if (opts->flags & PARSE_OPT_OPTARG)
496 if (opts->long_name)
497 pos += fprintf(stderr, "[=<%s>]", opts->argh);
498 else
499 pos += fprintf(stderr, "[<%s>]", opts->argh);
500 else
501 pos += fprintf(stderr, " <%s>", opts->argh);
502 } else {
503 if (opts->flags & PARSE_OPT_OPTARG)
504 if (opts->long_name)
505 pos += fprintf(stderr, "[=...]");
506 else
507 pos += fprintf(stderr, "[...]");
508 else
509 pos += fprintf(stderr, " ...");
510 }
511 break;
512 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
513 case OPTION_END:
514 case OPTION_GROUP:
515 case OPTION_BIT:
516 case OPTION_BOOLEAN:
517 case OPTION_INCR:
518 case OPTION_SET_UINT:
519 case OPTION_SET_PTR:
520 break;
521 }
522
523 if (pos <= USAGE_OPTS_WIDTH)
524 pad = USAGE_OPTS_WIDTH - pos;
525 else {
526 fputc('\n', stderr);
527 pad = USAGE_OPTS_WIDTH;
528 }
529 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
530}
531
448int usage_with_options_internal(const char * const *usagestr, 532int usage_with_options_internal(const char * const *usagestr,
449 const struct option *opts, int full) 533 const struct option *opts, int full)
450{ 534{
@@ -464,87 +548,9 @@ int usage_with_options_internal(const char * const *usagestr,
464 if (opts->type != OPTION_GROUP) 548 if (opts->type != OPTION_GROUP)
465 fputc('\n', stderr); 549 fputc('\n', stderr);
466 550
467 for (; opts->type != OPTION_END; opts++) { 551 for ( ; opts->type != OPTION_END; opts++)
468 size_t pos; 552 print_option_help(opts, full);
469 int pad;
470
471 if (opts->type == OPTION_GROUP) {
472 fputc('\n', stderr);
473 if (*opts->help)
474 fprintf(stderr, "%s\n", opts->help);
475 continue;
476 }
477 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
478 continue;
479
480 pos = fprintf(stderr, " ");
481 if (opts->short_name)
482 pos += fprintf(stderr, "-%c", opts->short_name);
483 else
484 pos += fprintf(stderr, " ");
485
486 if (opts->long_name && opts->short_name)
487 pos += fprintf(stderr, ", ");
488 if (opts->long_name)
489 pos += fprintf(stderr, "--%s", opts->long_name);
490
491 switch (opts->type) {
492 case OPTION_ARGUMENT:
493 break;
494 case OPTION_LONG:
495 case OPTION_U64:
496 case OPTION_INTEGER:
497 case OPTION_UINTEGER:
498 if (opts->flags & PARSE_OPT_OPTARG)
499 if (opts->long_name)
500 pos += fprintf(stderr, "[=<n>]");
501 else
502 pos += fprintf(stderr, "[<n>]");
503 else
504 pos += fprintf(stderr, " <n>");
505 break;
506 case OPTION_CALLBACK:
507 if (opts->flags & PARSE_OPT_NOARG)
508 break;
509 /* FALLTHROUGH */
510 case OPTION_STRING:
511 if (opts->argh) {
512 if (opts->flags & PARSE_OPT_OPTARG)
513 if (opts->long_name)
514 pos += fprintf(stderr, "[=<%s>]", opts->argh);
515 else
516 pos += fprintf(stderr, "[<%s>]", opts->argh);
517 else
518 pos += fprintf(stderr, " <%s>", opts->argh);
519 } else {
520 if (opts->flags & PARSE_OPT_OPTARG)
521 if (opts->long_name)
522 pos += fprintf(stderr, "[=...]");
523 else
524 pos += fprintf(stderr, "[...]");
525 else
526 pos += fprintf(stderr, " ...");
527 }
528 break;
529 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
530 case OPTION_END:
531 case OPTION_GROUP:
532 case OPTION_BIT:
533 case OPTION_BOOLEAN:
534 case OPTION_INCR:
535 case OPTION_SET_UINT:
536 case OPTION_SET_PTR:
537 break;
538 }
539 553
540 if (pos <= USAGE_OPTS_WIDTH)
541 pad = USAGE_OPTS_WIDTH - pos;
542 else {
543 fputc('\n', stderr);
544 pad = USAGE_OPTS_WIDTH;
545 }
546 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
547 }
548 fputc('\n', stderr); 554 fputc('\n', stderr);
549 555
550 return PARSE_OPT_HELP; 556 return PARSE_OPT_HELP;
@@ -559,9 +565,45 @@ void usage_with_options(const char * const *usagestr,
559} 565}
560 566
561int parse_options_usage(const char * const *usagestr, 567int parse_options_usage(const char * const *usagestr,
562 const struct option *opts) 568 const struct option *opts,
569 const char *optstr, bool short_opt)
563{ 570{
564 return usage_with_options_internal(usagestr, opts, 0); 571 if (!usagestr)
572 goto opt;
573
574 fprintf(stderr, "\n usage: %s\n", *usagestr++);
575 while (*usagestr && **usagestr)
576 fprintf(stderr, " or: %s\n", *usagestr++);
577 while (*usagestr) {
578 fprintf(stderr, "%s%s\n",
579 **usagestr ? " " : "",
580 *usagestr);
581 usagestr++;
582 }
583 fputc('\n', stderr);
584
585opt:
586 for ( ; opts->type != OPTION_END; opts++) {
587 if (short_opt) {
588 if (opts->short_name == *optstr)
589 break;
590 continue;
591 }
592
593 if (opts->long_name == NULL)
594 continue;
595
596 if (!prefixcmp(optstr, opts->long_name))
597 break;
598 if (!prefixcmp(optstr, "no-") &&
599 !prefixcmp(optstr + 3, opts->long_name))
600 break;
601 }
602
603 if (opts->type != OPTION_END)
604 print_option_help(opts, 0);
605
606 return PARSE_OPT_HELP;
565} 607}
566 608
567 609
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 7bb5999940ca..b0241e28eaf7 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -158,7 +158,9 @@ struct parse_opt_ctx_t {
158}; 158};
159 159
160extern int parse_options_usage(const char * const *usagestr, 160extern int parse_options_usage(const char * const *usagestr,
161 const struct option *opts); 161 const struct option *opts,
162 const char *optstr,
163 bool short_opt);
162 164
163extern void parse_options_start(struct parse_opt_ctx_t *ctx, 165extern void parse_options_start(struct parse_opt_ctx_t *ctx,
164 int argc, const char **argv, int flags); 166 int argc, const char **argv, int flags);
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index a8c49548ca48..5d13cb45b317 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,19 +22,23 @@ static const char *get_perf_dir(void)
22 return "."; 22 return ".";
23} 23}
24 24
25#ifndef HAVE_STRLCPY 25/*
26size_t strlcpy(char *dest, const char *src, size_t size) 26 * If libc has strlcpy() then that version will override this
27 * implementation:
28 */
29size_t __weak strlcpy(char *dest, const char *src, size_t size)
27{ 30{
28 size_t ret = strlen(src); 31 size_t ret = strlen(src);
29 32
30 if (size) { 33 if (size) {
31 size_t len = (ret >= size) ? size - 1 : ret; 34 size_t len = (ret >= size) ? size - 1 : ret;
35
32 memcpy(dest, src, len); 36 memcpy(dest, src, len);
33 dest[len] = '\0'; 37 dest[len] = '\0';
34 } 38 }
39
35 return ret; 40 return ret;
36} 41}
37#endif
38 42
39static char *get_pathname(void) 43static char *get_pathname(void)
40{ 44{
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 5a4f2b6f3738..a3d42cd74919 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_REGS_H 1#ifndef __PERF_REGS_H
2#define __PERF_REGS_H 2#define __PERF_REGS_H
3 3
4#ifdef HAVE_PERF_REGS 4#ifdef HAVE_PERF_REGS_SUPPORT
5#include <perf_regs.h> 5#include <perf_regs.h>
6#else 6#else
7#define PERF_REGS_MASK 0 7#define PERF_REGS_MASK 0
@@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused)
10{ 10{
11 return NULL; 11 return NULL;
12} 12}
13#endif /* HAVE_PERF_REGS */ 13#endif /* HAVE_PERF_REGS_SUPPORT */
14#endif /* __PERF_REGS_H */ 14#endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index bc9d8069d376..c232d8dd410b 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -4,7 +4,7 @@
4#include <unistd.h> 4#include <unistd.h>
5#include <stdio.h> 5#include <stdio.h>
6#include <dirent.h> 6#include <dirent.h>
7#include "sysfs.h" 7#include "fs.h"
8#include "util.h" 8#include "util.h"
9#include "pmu.h" 9#include "pmu.h"
10#include "parse-events.h" 10#include "parse-events.h"
@@ -77,9 +77,8 @@ static int pmu_format(const char *name, struct list_head *format)
77{ 77{
78 struct stat st; 78 struct stat st;
79 char path[PATH_MAX]; 79 char path[PATH_MAX];
80 const char *sysfs; 80 const char *sysfs = sysfs__mountpoint();
81 81
82 sysfs = sysfs_find_mountpoint();
83 if (!sysfs) 82 if (!sysfs)
84 return -1; 83 return -1;
85 84
@@ -166,9 +165,8 @@ static int pmu_aliases(const char *name, struct list_head *head)
166{ 165{
167 struct stat st; 166 struct stat st;
168 char path[PATH_MAX]; 167 char path[PATH_MAX];
169 const char *sysfs; 168 const char *sysfs = sysfs__mountpoint();
170 169
171 sysfs = sysfs_find_mountpoint();
172 if (!sysfs) 170 if (!sysfs)
173 return -1; 171 return -1;
174 172
@@ -212,11 +210,10 @@ static int pmu_type(const char *name, __u32 *type)
212{ 210{
213 struct stat st; 211 struct stat st;
214 char path[PATH_MAX]; 212 char path[PATH_MAX];
215 const char *sysfs;
216 FILE *file; 213 FILE *file;
217 int ret = 0; 214 int ret = 0;
215 const char *sysfs = sysfs__mountpoint();
218 216
219 sysfs = sysfs_find_mountpoint();
220 if (!sysfs) 217 if (!sysfs)
221 return -1; 218 return -1;
222 219
@@ -241,11 +238,10 @@ static int pmu_type(const char *name, __u32 *type)
241static void pmu_read_sysfs(void) 238static void pmu_read_sysfs(void)
242{ 239{
243 char path[PATH_MAX]; 240 char path[PATH_MAX];
244 const char *sysfs;
245 DIR *dir; 241 DIR *dir;
246 struct dirent *dent; 242 struct dirent *dent;
243 const char *sysfs = sysfs__mountpoint();
247 244
248 sysfs = sysfs_find_mountpoint();
249 if (!sysfs) 245 if (!sysfs)
250 return; 246 return;
251 247
@@ -270,11 +266,10 @@ static struct cpu_map *pmu_cpumask(const char *name)
270{ 266{
271 struct stat st; 267 struct stat st;
272 char path[PATH_MAX]; 268 char path[PATH_MAX];
273 const char *sysfs;
274 FILE *file; 269 FILE *file;
275 struct cpu_map *cpus; 270 struct cpu_map *cpus;
271 const char *sysfs = sysfs__mountpoint();
276 272
277 sysfs = sysfs_find_mountpoint();
278 if (!sysfs) 273 if (!sysfs)
279 return NULL; 274 return NULL;
280 275
@@ -637,3 +632,19 @@ void print_pmu_events(const char *event_glob, bool name_only)
637 printf("\n"); 632 printf("\n");
638 free(aliases); 633 free(aliases);
639} 634}
635
636bool pmu_have_event(const char *pname, const char *name)
637{
638 struct perf_pmu *pmu;
639 struct perf_pmu_alias *alias;
640
641 pmu = NULL;
642 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
643 if (strcmp(pname, pmu->name))
644 continue;
645 list_for_each_entry(alias, &pmu->aliases, list)
646 if (!strcmp(alias->name, name))
647 return true;
648 }
649 return false;
650}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6b2cbe2d4cc3..1179b26f244a 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -42,6 +42,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
42struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); 42struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
43 43
44void print_pmu_events(const char *event_glob, bool name_only); 44void print_pmu_events(const char *event_glob, bool name_only);
45bool pmu_have_event(const char *pname, const char *name);
45 46
46int perf_pmu__test(void); 47int perf_pmu__test(void);
47#endif /* __PMU_H */ 48#endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index aa04bf9c9ad7..9c6989ca2bea 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -47,7 +47,6 @@
47#include "session.h" 47#include "session.h"
48 48
49#define MAX_CMDLEN 256 49#define MAX_CMDLEN 256
50#define MAX_PROBE_ARGS 128
51#define PERFPROBE_GROUP "probe" 50#define PERFPROBE_GROUP "probe"
52 51
53bool probe_event_dry_run; /* Dry run flag */ 52bool probe_event_dry_run; /* Dry run flag */
@@ -201,7 +200,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
201 return 0; 200 return 0;
202} 201}
203 202
204#ifdef DWARF_SUPPORT 203#ifdef HAVE_DWARF_SUPPORT
205/* Open new debuginfo of given module */ 204/* Open new debuginfo of given module */
206static struct debuginfo *open_debuginfo(const char *module) 205static struct debuginfo *open_debuginfo(const char *module)
207{ 206{
@@ -630,7 +629,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
630 return ret; 629 return ret;
631} 630}
632 631
633#else /* !DWARF_SUPPORT */ 632#else /* !HAVE_DWARF_SUPPORT */
634 633
635static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 634static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
636 struct perf_probe_point *pp) 635 struct perf_probe_point *pp)
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index f0692737ebf1..ffb657ffd327 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -115,7 +115,7 @@ static const Dwfl_Callbacks offline_callbacks = {
115}; 115};
116 116
117/* Get a Dwarf from offline image */ 117/* Get a Dwarf from offline image */
118static int debuginfo__init_offline_dwarf(struct debuginfo *self, 118static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
119 const char *path) 119 const char *path)
120{ 120{
121 int fd; 121 int fd;
@@ -124,25 +124,25 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self,
124 if (fd < 0) 124 if (fd < 0)
125 return fd; 125 return fd;
126 126
127 self->dwfl = dwfl_begin(&offline_callbacks); 127 dbg->dwfl = dwfl_begin(&offline_callbacks);
128 if (!self->dwfl) 128 if (!dbg->dwfl)
129 goto error; 129 goto error;
130 130
131 self->mod = dwfl_report_offline(self->dwfl, "", "", fd); 131 dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
132 if (!self->mod) 132 if (!dbg->mod)
133 goto error; 133 goto error;
134 134
135 self->dbg = dwfl_module_getdwarf(self->mod, &self->bias); 135 dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
136 if (!self->dbg) 136 if (!dbg->dbg)
137 goto error; 137 goto error;
138 138
139 return 0; 139 return 0;
140error: 140error:
141 if (self->dwfl) 141 if (dbg->dwfl)
142 dwfl_end(self->dwfl); 142 dwfl_end(dbg->dwfl);
143 else 143 else
144 close(fd); 144 close(fd);
145 memset(self, 0, sizeof(*self)); 145 memset(dbg, 0, sizeof(*dbg));
146 146
147 return -ENOENT; 147 return -ENOENT;
148} 148}
@@ -180,24 +180,24 @@ static const Dwfl_Callbacks kernel_callbacks = {
180}; 180};
181 181
182/* Get a Dwarf from live kernel image */ 182/* Get a Dwarf from live kernel image */
183static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, 183static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
184 Dwarf_Addr addr) 184 Dwarf_Addr addr)
185{ 185{
186 self->dwfl = dwfl_begin(&kernel_callbacks); 186 dbg->dwfl = dwfl_begin(&kernel_callbacks);
187 if (!self->dwfl) 187 if (!dbg->dwfl)
188 return -EINVAL; 188 return -EINVAL;
189 189
190 /* Load the kernel dwarves: Don't care the result here */ 190 /* Load the kernel dwarves: Don't care the result here */
191 dwfl_linux_kernel_report_kernel(self->dwfl); 191 dwfl_linux_kernel_report_kernel(dbg->dwfl);
192 dwfl_linux_kernel_report_modules(self->dwfl); 192 dwfl_linux_kernel_report_modules(dbg->dwfl);
193 193
194 self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias); 194 dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
195 /* Here, check whether we could get a real dwarf */ 195 /* Here, check whether we could get a real dwarf */
196 if (!self->dbg) { 196 if (!dbg->dbg) {
197 pr_debug("Failed to find kernel dwarf at %lx\n", 197 pr_debug("Failed to find kernel dwarf at %lx\n",
198 (unsigned long)addr); 198 (unsigned long)addr);
199 dwfl_end(self->dwfl); 199 dwfl_end(dbg->dwfl);
200 memset(self, 0, sizeof(*self)); 200 memset(dbg, 0, sizeof(*dbg));
201 return -ENOENT; 201 return -ENOENT;
202 } 202 }
203 203
@@ -205,7 +205,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
205} 205}
206#else 206#else
207/* With older elfutils, this just support kernel module... */ 207/* With older elfutils, this just support kernel module... */
208static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, 208static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
209 Dwarf_Addr addr __maybe_unused) 209 Dwarf_Addr addr __maybe_unused)
210{ 210{
211 const char *path = kernel_get_module_path("kernel"); 211 const char *path = kernel_get_module_path("kernel");
@@ -216,44 +216,45 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
216 } 216 }
217 217
218 pr_debug2("Use file %s for debuginfo\n", path); 218 pr_debug2("Use file %s for debuginfo\n", path);
219 return debuginfo__init_offline_dwarf(self, path); 219 return debuginfo__init_offline_dwarf(dbg, path);
220} 220}
221#endif 221#endif
222 222
223struct debuginfo *debuginfo__new(const char *path) 223struct debuginfo *debuginfo__new(const char *path)
224{ 224{
225 struct debuginfo *self = zalloc(sizeof(struct debuginfo)); 225 struct debuginfo *dbg = zalloc(sizeof(*dbg));
226 if (!self) 226 if (!dbg)
227 return NULL; 227 return NULL;
228 228
229 if (debuginfo__init_offline_dwarf(self, path) < 0) { 229 if (debuginfo__init_offline_dwarf(dbg, path) < 0) {
230 free(self); 230 free(dbg);
231 self = NULL; 231 dbg = NULL;
232 } 232 }
233 233
234 return self; 234 return dbg;
235} 235}
236 236
237struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) 237struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
238{ 238{
239 struct debuginfo *self = zalloc(sizeof(struct debuginfo)); 239 struct debuginfo *dbg = zalloc(sizeof(*dbg));
240 if (!self) 240
241 if (!dbg)
241 return NULL; 242 return NULL;
242 243
243 if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) { 244 if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) {
244 free(self); 245 free(dbg);
245 self = NULL; 246 dbg = NULL;
246 } 247 }
247 248
248 return self; 249 return dbg;
249} 250}
250 251
251void debuginfo__delete(struct debuginfo *self) 252void debuginfo__delete(struct debuginfo *dbg)
252{ 253{
253 if (self) { 254 if (dbg) {
254 if (self->dwfl) 255 if (dbg->dwfl)
255 dwfl_end(self->dwfl); 256 dwfl_end(dbg->dwfl);
256 free(self); 257 free(dbg);
257 } 258 }
258} 259}
259 260
@@ -273,12 +274,15 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
273/* 274/*
274 * Convert a location into trace_arg. 275 * Convert a location into trace_arg.
275 * If tvar == NULL, this just checks variable can be converted. 276 * If tvar == NULL, this just checks variable can be converted.
277 * If fentry == true and vr_die is a parameter, do huristic search
278 * for the location fuzzed by function entry mcount.
276 */ 279 */
277static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, 280static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
278 Dwarf_Op *fb_ops, 281 Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
279 struct probe_trace_arg *tvar) 282 struct probe_trace_arg *tvar)
280{ 283{
281 Dwarf_Attribute attr; 284 Dwarf_Attribute attr;
285 Dwarf_Addr tmp = 0;
282 Dwarf_Op *op; 286 Dwarf_Op *op;
283 size_t nops; 287 size_t nops;
284 unsigned int regn; 288 unsigned int regn;
@@ -291,12 +295,29 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
291 goto static_var; 295 goto static_var;
292 296
293 /* TODO: handle more than 1 exprs */ 297 /* TODO: handle more than 1 exprs */
294 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL || 298 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
295 dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 || 299 return -EINVAL; /* Broken DIE ? */
296 nops == 0) { 300 if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
297 /* TODO: Support const_value */ 301 ret = dwarf_entrypc(sp_die, &tmp);
302 if (ret || addr != tmp ||
303 dwarf_tag(vr_die) != DW_TAG_formal_parameter ||
304 dwarf_highpc(sp_die, &tmp))
305 return -ENOENT;
306 /*
307 * This is fuzzed by fentry mcount. We try to find the
308 * parameter location at the earliest address.
309 */
310 for (addr += 1; addr <= tmp; addr++) {
311 if (dwarf_getlocation_addr(&attr, addr, &op,
312 &nops, 1) > 0)
313 goto found;
314 }
298 return -ENOENT; 315 return -ENOENT;
299 } 316 }
317found:
318 if (nops == 0)
319 /* TODO: Support const_value */
320 return -ENOENT;
300 321
301 if (op->atom == DW_OP_addr) { 322 if (op->atom == DW_OP_addr) {
302static_var: 323static_var:
@@ -563,7 +584,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
563 } 584 }
564 585
565 if (die_find_member(&type, field->name, die_mem) == NULL) { 586 if (die_find_member(&type, field->name, die_mem) == NULL) {
566 pr_warning("%s(tyep:%s) has no member %s.\n", varname, 587 pr_warning("%s(type:%s) has no member %s.\n", varname,
567 dwarf_diename(&type), field->name); 588 dwarf_diename(&type), field->name);
568 return -EINVAL; 589 return -EINVAL;
569 } 590 }
@@ -600,7 +621,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
600 dwarf_diename(vr_die)); 621 dwarf_diename(vr_die));
601 622
602 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 623 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
603 pf->tvar); 624 &pf->sp_die, pf->tvar);
604 if (ret == -ENOENT) 625 if (ret == -ENOENT)
605 pr_err("Failed to find the location of %s at this address.\n" 626 pr_err("Failed to find the location of %s at this address.\n"
606 " Perhaps, it has been optimized out.\n", pf->pvar->var); 627 " Perhaps, it has been optimized out.\n", pf->pvar->var);
@@ -1063,7 +1084,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
1063} 1084}
1064 1085
1065/* Find probe points from debuginfo */ 1086/* Find probe points from debuginfo */
1066static int debuginfo__find_probes(struct debuginfo *self, 1087static int debuginfo__find_probes(struct debuginfo *dbg,
1067 struct probe_finder *pf) 1088 struct probe_finder *pf)
1068{ 1089{
1069 struct perf_probe_point *pp = &pf->pev->point; 1090 struct perf_probe_point *pp = &pf->pev->point;
@@ -1074,7 +1095,7 @@ static int debuginfo__find_probes(struct debuginfo *self,
1074 1095
1075#if _ELFUTILS_PREREQ(0, 142) 1096#if _ELFUTILS_PREREQ(0, 142)
1076 /* Get the call frame information from this dwarf */ 1097 /* Get the call frame information from this dwarf */
1077 pf->cfi = dwarf_getcfi(self->dbg); 1098 pf->cfi = dwarf_getcfi(dbg->dbg);
1078#endif 1099#endif
1079 1100
1080 off = 0; 1101 off = 0;
@@ -1093,7 +1114,7 @@ static int debuginfo__find_probes(struct debuginfo *self,
1093 .data = pf, 1114 .data = pf,
1094 }; 1115 };
1095 1116
1096 dwarf_getpubnames(self->dbg, pubname_search_cb, 1117 dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1097 &pubname_param, 0); 1118 &pubname_param, 0);
1098 if (pubname_param.found) { 1119 if (pubname_param.found) {
1099 ret = probe_point_search_cb(&pf->sp_die, &probe_param); 1120 ret = probe_point_search_cb(&pf->sp_die, &probe_param);
@@ -1103,9 +1124,9 @@ static int debuginfo__find_probes(struct debuginfo *self,
1103 } 1124 }
1104 1125
1105 /* Loop on CUs (Compilation Unit) */ 1126 /* Loop on CUs (Compilation Unit) */
1106 while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { 1127 while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1107 /* Get the DIE(Debugging Information Entry) of this CU */ 1128 /* Get the DIE(Debugging Information Entry) of this CU */
1108 diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die); 1129 diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
1109 if (!diep) 1130 if (!diep)
1110 continue; 1131 continue;
1111 1132
@@ -1136,12 +1157,80 @@ found:
1136 return ret; 1157 return ret;
1137} 1158}
1138 1159
1160struct local_vars_finder {
1161 struct probe_finder *pf;
1162 struct perf_probe_arg *args;
1163 int max_args;
1164 int nargs;
1165 int ret;
1166};
1167
1168/* Collect available variables in this scope */
1169static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
1170{
1171 struct local_vars_finder *vf = data;
1172 struct probe_finder *pf = vf->pf;
1173 int tag;
1174
1175 tag = dwarf_tag(die_mem);
1176 if (tag == DW_TAG_formal_parameter ||
1177 tag == DW_TAG_variable) {
1178 if (convert_variable_location(die_mem, vf->pf->addr,
1179 vf->pf->fb_ops, &pf->sp_die,
1180 NULL) == 0) {
1181 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1182 if (vf->args[vf->nargs].var == NULL) {
1183 vf->ret = -ENOMEM;
1184 return DIE_FIND_CB_END;
1185 }
1186 pr_debug(" %s", vf->args[vf->nargs].var);
1187 vf->nargs++;
1188 }
1189 }
1190
1191 if (dwarf_haspc(die_mem, vf->pf->addr))
1192 return DIE_FIND_CB_CONTINUE;
1193 else
1194 return DIE_FIND_CB_SIBLING;
1195}
1196
1197static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
1198 struct perf_probe_arg *args)
1199{
1200 Dwarf_Die die_mem;
1201 int i;
1202 int n = 0;
1203 struct local_vars_finder vf = {.pf = pf, .args = args,
1204 .max_args = MAX_PROBE_ARGS, .ret = 0};
1205
1206 for (i = 0; i < pf->pev->nargs; i++) {
1207 /* var never be NULL */
1208 if (strcmp(pf->pev->args[i].var, "$vars") == 0) {
1209 pr_debug("Expanding $vars into:");
1210 vf.nargs = n;
1211 /* Special local variables */
1212 die_find_child(sc_die, copy_variables_cb, (void *)&vf,
1213 &die_mem);
1214 pr_debug(" (%d)\n", vf.nargs - n);
1215 if (vf.ret < 0)
1216 return vf.ret;
1217 n = vf.nargs;
1218 } else {
1219 /* Copy normal argument */
1220 args[n] = pf->pev->args[i];
1221 n++;
1222 }
1223 }
1224 return n;
1225}
1226
1139/* Add a found probe point into trace event list */ 1227/* Add a found probe point into trace event list */
1140static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) 1228static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1141{ 1229{
1142 struct trace_event_finder *tf = 1230 struct trace_event_finder *tf =
1143 container_of(pf, struct trace_event_finder, pf); 1231 container_of(pf, struct trace_event_finder, pf);
1144 struct probe_trace_event *tev; 1232 struct probe_trace_event *tev;
1233 struct perf_probe_arg *args;
1145 int ret, i; 1234 int ret, i;
1146 1235
1147 /* Check number of tevs */ 1236 /* Check number of tevs */
@@ -1161,31 +1250,45 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1161 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 1250 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1162 tev->point.offset); 1251 tev->point.offset);
1163 1252
1164 /* Find each argument */ 1253 /* Expand special probe argument if exist */
1165 tev->nargs = pf->pev->nargs; 1254 args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1166 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1255 if (args == NULL)
1167 if (tev->args == NULL)
1168 return -ENOMEM; 1256 return -ENOMEM;
1169 for (i = 0; i < pf->pev->nargs; i++) { 1257
1170 pf->pvar = &pf->pev->args[i]; 1258 ret = expand_probe_args(sc_die, pf, args);
1259 if (ret < 0)
1260 goto end;
1261
1262 tev->nargs = ret;
1263 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1264 if (tev->args == NULL) {
1265 ret = -ENOMEM;
1266 goto end;
1267 }
1268
1269 /* Find each argument */
1270 for (i = 0; i < tev->nargs; i++) {
1271 pf->pvar = &args[i];
1171 pf->tvar = &tev->args[i]; 1272 pf->tvar = &tev->args[i];
1172 /* Variable should be found from scope DIE */ 1273 /* Variable should be found from scope DIE */
1173 ret = find_variable(sc_die, pf); 1274 ret = find_variable(sc_die, pf);
1174 if (ret != 0) 1275 if (ret != 0)
1175 return ret; 1276 break;
1176 } 1277 }
1177 1278
1178 return 0; 1279end:
1280 free(args);
1281 return ret;
1179} 1282}
1180 1283
1181/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1284/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1182int debuginfo__find_trace_events(struct debuginfo *self, 1285int debuginfo__find_trace_events(struct debuginfo *dbg,
1183 struct perf_probe_event *pev, 1286 struct perf_probe_event *pev,
1184 struct probe_trace_event **tevs, int max_tevs) 1287 struct probe_trace_event **tevs, int max_tevs)
1185{ 1288{
1186 struct trace_event_finder tf = { 1289 struct trace_event_finder tf = {
1187 .pf = {.pev = pev, .callback = add_probe_trace_event}, 1290 .pf = {.pev = pev, .callback = add_probe_trace_event},
1188 .mod = self->mod, .max_tevs = max_tevs}; 1291 .mod = dbg->mod, .max_tevs = max_tevs};
1189 int ret; 1292 int ret;
1190 1293
1191 /* Allocate result tevs array */ 1294 /* Allocate result tevs array */
@@ -1196,7 +1299,7 @@ int debuginfo__find_trace_events(struct debuginfo *self,
1196 tf.tevs = *tevs; 1299 tf.tevs = *tevs;
1197 tf.ntevs = 0; 1300 tf.ntevs = 0;
1198 1301
1199 ret = debuginfo__find_probes(self, &tf.pf); 1302 ret = debuginfo__find_probes(dbg, &tf.pf);
1200 if (ret < 0) { 1303 if (ret < 0) {
1201 free(*tevs); 1304 free(*tevs);
1202 *tevs = NULL; 1305 *tevs = NULL;
@@ -1222,7 +1325,8 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1222 if (tag == DW_TAG_formal_parameter || 1325 if (tag == DW_TAG_formal_parameter ||
1223 tag == DW_TAG_variable) { 1326 tag == DW_TAG_variable) {
1224 ret = convert_variable_location(die_mem, af->pf.addr, 1327 ret = convert_variable_location(die_mem, af->pf.addr,
1225 af->pf.fb_ops, NULL); 1328 af->pf.fb_ops, &af->pf.sp_die,
1329 NULL);
1226 if (ret == 0) { 1330 if (ret == 0) {
1227 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); 1331 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1228 pr_debug2("Add new var: %s\n", buf); 1332 pr_debug2("Add new var: %s\n", buf);
@@ -1286,14 +1390,14 @@ out:
1286} 1390}
1287 1391
1288/* Find available variables at given probe point */ 1392/* Find available variables at given probe point */
1289int debuginfo__find_available_vars_at(struct debuginfo *self, 1393int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1290 struct perf_probe_event *pev, 1394 struct perf_probe_event *pev,
1291 struct variable_list **vls, 1395 struct variable_list **vls,
1292 int max_vls, bool externs) 1396 int max_vls, bool externs)
1293{ 1397{
1294 struct available_var_finder af = { 1398 struct available_var_finder af = {
1295 .pf = {.pev = pev, .callback = add_available_vars}, 1399 .pf = {.pev = pev, .callback = add_available_vars},
1296 .mod = self->mod, 1400 .mod = dbg->mod,
1297 .max_vls = max_vls, .externs = externs}; 1401 .max_vls = max_vls, .externs = externs};
1298 int ret; 1402 int ret;
1299 1403
@@ -1305,7 +1409,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
1305 af.vls = *vls; 1409 af.vls = *vls;
1306 af.nvls = 0; 1410 af.nvls = 0;
1307 1411
1308 ret = debuginfo__find_probes(self, &af.pf); 1412 ret = debuginfo__find_probes(dbg, &af.pf);
1309 if (ret < 0) { 1413 if (ret < 0) {
1310 /* Free vlist for error */ 1414 /* Free vlist for error */
1311 while (af.nvls--) { 1415 while (af.nvls--) {
@@ -1323,7 +1427,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
1323} 1427}
1324 1428
1325/* Reverse search */ 1429/* Reverse search */
1326int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, 1430int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1327 struct perf_probe_point *ppt) 1431 struct perf_probe_point *ppt)
1328{ 1432{
1329 Dwarf_Die cudie, spdie, indie; 1433 Dwarf_Die cudie, spdie, indie;
@@ -1332,10 +1436,10 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
1332 int baseline = 0, lineno = 0, ret = 0; 1436 int baseline = 0, lineno = 0, ret = 0;
1333 1437
1334 /* Adjust address with bias */ 1438 /* Adjust address with bias */
1335 addr += self->bias; 1439 addr += dbg->bias;
1336 1440
1337 /* Find cu die */ 1441 /* Find cu die */
1338 if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) { 1442 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) {
1339 pr_warning("Failed to find debug information for address %lx\n", 1443 pr_warning("Failed to find debug information for address %lx\n",
1340 addr); 1444 addr);
1341 ret = -EINVAL; 1445 ret = -EINVAL;
@@ -1536,7 +1640,7 @@ static int find_line_range_by_func(struct line_finder *lf)
1536 return param.retval; 1640 return param.retval;
1537} 1641}
1538 1642
1539int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr) 1643int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
1540{ 1644{
1541 struct line_finder lf = {.lr = lr, .found = 0}; 1645 struct line_finder lf = {.lr = lr, .found = 0};
1542 int ret = 0; 1646 int ret = 0;
@@ -1553,7 +1657,7 @@ int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
1553 struct dwarf_callback_param line_range_param = { 1657 struct dwarf_callback_param line_range_param = {
1554 .data = (void *)&lf, .retval = 0}; 1658 .data = (void *)&lf, .retval = 0};
1555 1659
1556 dwarf_getpubnames(self->dbg, pubname_search_cb, 1660 dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1557 &pubname_param, 0); 1661 &pubname_param, 0);
1558 if (pubname_param.found) { 1662 if (pubname_param.found) {
1559 line_range_search_cb(&lf.sp_die, &line_range_param); 1663 line_range_search_cb(&lf.sp_die, &line_range_param);
@@ -1564,12 +1668,12 @@ int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
1564 1668
1565 /* Loop on CUs (Compilation Unit) */ 1669 /* Loop on CUs (Compilation Unit) */
1566 while (!lf.found && ret >= 0) { 1670 while (!lf.found && ret >= 0) {
1567 if (dwarf_nextcu(self->dbg, off, &noff, &cuhl, 1671 if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
1568 NULL, NULL, NULL) != 0) 1672 NULL, NULL, NULL) != 0)
1569 break; 1673 break;
1570 1674
1571 /* Get the DIE(Debugging Information Entry) of this CU */ 1675 /* Get the DIE(Debugging Information Entry) of this CU */
1572 diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die); 1676 diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
1573 if (!diep) 1677 if (!diep)
1574 continue; 1678 continue;
1575 1679
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 3b7d63018960..ffc33cdd25cc 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -7,6 +7,7 @@
7 7
8#define MAX_PROBE_BUFFER 1024 8#define MAX_PROBE_BUFFER 1024
9#define MAX_PROBES 128 9#define MAX_PROBES 128
10#define MAX_PROBE_ARGS 128
10 11
11static inline int is_c_varname(const char *name) 12static inline int is_c_varname(const char *name)
12{ 13{
@@ -14,7 +15,7 @@ static inline int is_c_varname(const char *name)
14 return isalpha(name[0]) || name[0] == '_'; 15 return isalpha(name[0]) || name[0] == '_';
15} 16}
16 17
17#ifdef DWARF_SUPPORT 18#ifdef HAVE_DWARF_SUPPORT
18 19
19#include "dwarf-aux.h" 20#include "dwarf-aux.h"
20 21
@@ -30,25 +31,25 @@ struct debuginfo {
30 31
31extern struct debuginfo *debuginfo__new(const char *path); 32extern struct debuginfo *debuginfo__new(const char *path);
32extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); 33extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
33extern void debuginfo__delete(struct debuginfo *self); 34extern void debuginfo__delete(struct debuginfo *dbg);
34 35
35/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 36/* Find probe_trace_events specified by perf_probe_event from debuginfo */
36extern int debuginfo__find_trace_events(struct debuginfo *self, 37extern int debuginfo__find_trace_events(struct debuginfo *dbg,
37 struct perf_probe_event *pev, 38 struct perf_probe_event *pev,
38 struct probe_trace_event **tevs, 39 struct probe_trace_event **tevs,
39 int max_tevs); 40 int max_tevs);
40 41
41/* Find a perf_probe_point from debuginfo */ 42/* Find a perf_probe_point from debuginfo */
42extern int debuginfo__find_probe_point(struct debuginfo *self, 43extern int debuginfo__find_probe_point(struct debuginfo *dbg,
43 unsigned long addr, 44 unsigned long addr,
44 struct perf_probe_point *ppt); 45 struct perf_probe_point *ppt);
45 46
46/* Find a line range */ 47/* Find a line range */
47extern int debuginfo__find_line_range(struct debuginfo *self, 48extern int debuginfo__find_line_range(struct debuginfo *dbg,
48 struct line_range *lr); 49 struct line_range *lr);
49 50
50/* Find available variables */ 51/* Find available variables */
51extern int debuginfo__find_available_vars_at(struct debuginfo *self, 52extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
52 struct perf_probe_event *pev, 53 struct perf_probe_event *pev,
53 struct variable_list **vls, 54 struct variable_list **vls,
54 int max_points, bool externs); 55 int max_points, bool externs);
@@ -105,6 +106,6 @@ struct line_finder {
105 int found; 106 int found;
106}; 107};
107 108
108#endif /* DWARF_SUPPORT */ 109#endif /* HAVE_DWARF_SUPPORT */
109 110
110#endif /*_PROBE_FINDER_H */ 111#endif /*_PROBE_FINDER_H */
diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h
index 4cedea59f518..c3cb6584d527 100644
--- a/tools/perf/util/pstack.h
+++ b/tools/perf/util/pstack.h
@@ -5,10 +5,10 @@
5 5
6struct pstack; 6struct pstack;
7struct pstack *pstack__new(unsigned short max_nr_entries); 7struct pstack *pstack__new(unsigned short max_nr_entries);
8void pstack__delete(struct pstack *self); 8void pstack__delete(struct pstack *pstack);
9bool pstack__empty(const struct pstack *self); 9bool pstack__empty(const struct pstack *pstack);
10void pstack__remove(struct pstack *self, void *key); 10void pstack__remove(struct pstack *pstack, void *key);
11void pstack__push(struct pstack *self, void *key); 11void pstack__push(struct pstack *pstack, void *key);
12void *pstack__pop(struct pstack *self); 12void *pstack__pop(struct pstack *pstack);
13 13
14#endif /* _PERF_PSTACK_ */ 14#endif /* _PERF_PSTACK_ */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index f75ae1b9900c..239036fb2b2c 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -17,5 +17,5 @@ util/xyarray.c
17util/cgroup.c 17util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/strlist.c 19util/strlist.c
20util/sysfs.c 20util/fs.c
21../../lib/rbtree.c 21../../lib/rbtree.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 71b5412bbbb9..4bf8ace7f511 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -33,13 +33,6 @@ int eprintf(int level, const char *fmt, ...)
33# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, 33# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
34#endif 34#endif
35 35
36struct throttle_event {
37 struct perf_event_header header;
38 u64 time;
39 u64 id;
40 u64 stream_id;
41};
42
43PyMODINIT_FUNC initperf(void); 36PyMODINIT_FUNC initperf(void);
44 37
45#define member_def(type, member, ptype, help) \ 38#define member_def(type, member, ptype, help) \
@@ -822,6 +815,8 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
822 PyObject *pyevent = pyrf_event__new(event); 815 PyObject *pyevent = pyrf_event__new(event);
823 struct pyrf_event *pevent = (struct pyrf_event *)pyevent; 816 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
824 817
818 perf_evlist__mmap_consume(evlist, cpu);
819
825 if (pyevent == NULL) 820 if (pyevent == NULL)
826 return PyErr_NoMemory(); 821 return PyErr_NoMemory();
827 822
@@ -1036,6 +1031,7 @@ PyMODINIT_FUNC initperf(void)
1036 pyrf_cpu_map__setup_types() < 0) 1031 pyrf_cpu_map__setup_types() < 0)
1037 return; 1032 return;
1038 1033
1034 /* The page_size is placed in util object. */
1039 page_size = sysconf(_SC_PAGE_SIZE); 1035 page_size = sysconf(_SC_PAGE_SIZE);
1040 1036
1041 Py_INCREF(&pyrf_evlist__type); 1037 Py_INCREF(&pyrf_evlist__type);
diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c
index a16cdd2625ad..0dfe27d99458 100644
--- a/tools/perf/util/rblist.c
+++ b/tools/perf/util/rblist.c
@@ -48,10 +48,12 @@ void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node)
48 rblist->node_delete(rblist, rb_node); 48 rblist->node_delete(rblist, rb_node);
49} 49}
50 50
51struct rb_node *rblist__find(struct rblist *rblist, const void *entry) 51static struct rb_node *__rblist__findnew(struct rblist *rblist,
52 const void *entry,
53 bool create)
52{ 54{
53 struct rb_node **p = &rblist->entries.rb_node; 55 struct rb_node **p = &rblist->entries.rb_node;
54 struct rb_node *parent = NULL; 56 struct rb_node *parent = NULL, *new_node = NULL;
55 57
56 while (*p != NULL) { 58 while (*p != NULL) {
57 int rc; 59 int rc;
@@ -67,7 +69,26 @@ struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
67 return parent; 69 return parent;
68 } 70 }
69 71
70 return NULL; 72 if (create) {
73 new_node = rblist->node_new(rblist, entry);
74 if (new_node) {
75 rb_link_node(new_node, parent, p);
76 rb_insert_color(new_node, &rblist->entries);
77 ++rblist->nr_entries;
78 }
79 }
80
81 return new_node;
82}
83
84struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
85{
86 return __rblist__findnew(rblist, entry, false);
87}
88
89struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry)
90{
91 return __rblist__findnew(rblist, entry, true);
71} 92}
72 93
73void rblist__init(struct rblist *rblist) 94void rblist__init(struct rblist *rblist)
diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h
index 6d0cae5ae83d..ff9913b994c2 100644
--- a/tools/perf/util/rblist.h
+++ b/tools/perf/util/rblist.h
@@ -32,6 +32,7 @@ void rblist__delete(struct rblist *rblist);
32int rblist__add_node(struct rblist *rblist, const void *new_entry); 32int rblist__add_node(struct rblist *rblist, const void *new_entry);
33void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node); 33void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node);
34struct rb_node *rblist__find(struct rblist *rblist, const void *entry); 34struct rb_node *rblist__find(struct rblist *rblist, const void *entry);
35struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry);
35struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx); 36struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx);
36 37
37static inline bool rblist__empty(const struct rblist *rblist) 38static inline bool rblist__empty(const struct rblist *rblist)
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 18d73aa2f0f8..c8845b107f60 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -2,6 +2,8 @@
2#include "evsel.h" 2#include "evsel.h"
3#include "cpumap.h" 3#include "cpumap.h"
4#include "parse-events.h" 4#include "parse-events.h"
5#include "fs.h"
6#include "util.h"
5 7
6typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); 8typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
7 9
@@ -106,3 +108,72 @@ void perf_evlist__config(struct perf_evlist *evlist,
106 108
107 perf_evlist__set_id_pos(evlist); 109 perf_evlist__set_id_pos(evlist);
108} 110}
111
112static int get_max_rate(unsigned int *rate)
113{
114 char path[PATH_MAX];
115 const char *procfs = procfs__mountpoint();
116
117 if (!procfs)
118 return -1;
119
120 snprintf(path, PATH_MAX,
121 "%s/sys/kernel/perf_event_max_sample_rate", procfs);
122
123 return filename__read_int(path, (int *) rate);
124}
125
126static int perf_record_opts__config_freq(struct perf_record_opts *opts)
127{
128 bool user_freq = opts->user_freq != UINT_MAX;
129 unsigned int max_rate;
130
131 if (opts->user_interval != ULLONG_MAX)
132 opts->default_interval = opts->user_interval;
133 if (user_freq)
134 opts->freq = opts->user_freq;
135
136 /*
137 * User specified count overrides default frequency.
138 */
139 if (opts->default_interval)
140 opts->freq = 0;
141 else if (opts->freq) {
142 opts->default_interval = opts->freq;
143 } else {
144 pr_err("frequency and count are zero, aborting\n");
145 return -1;
146 }
147
148 if (get_max_rate(&max_rate))
149 return 0;
150
151 /*
152 * User specified frequency is over current maximum.
153 */
154 if (user_freq && (max_rate < opts->freq)) {
155 pr_err("Maximum frequency rate (%u) reached.\n"
156 "Please use -F freq option with lower value or consider\n"
157 "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
158 max_rate);
159 return -1;
160 }
161
162 /*
163 * Default frequency is over current maximum.
164 */
165 if (max_rate < opts->freq) {
166 pr_warning("Lowering default frequency rate to %u.\n"
167 "Please consider tweaking "
168 "/proc/sys/kernel/perf_event_max_sample_rate.\n",
169 max_rate);
170 opts->freq = max_rate;
171 }
172
173 return 0;
174}
175
176int perf_record_opts__config(struct perf_record_opts *opts)
177{
178 return perf_record_opts__config_freq(opts);
179}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index c0c9795c4f02..d5e5969f6fea 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -273,7 +273,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
273 int cpu = sample->cpu; 273 int cpu = sample->cpu;
274 void *data = sample->raw_data; 274 void *data = sample->raw_data;
275 unsigned long long nsecs = sample->time; 275 unsigned long long nsecs = sample->time;
276 char *comm = thread->comm; 276 const char *comm = thread__comm_str(thread);
277 277
278 dSP; 278 dSP;
279 279
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cc75a3cef388..53c20e7fd900 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -56,6 +56,17 @@ static void handler_call_die(const char *handler_name)
56 Py_FatalError("problem in Python trace event handler"); 56 Py_FatalError("problem in Python trace event handler");
57} 57}
58 58
59/*
60 * Insert val into into the dictionary and decrement the reference counter.
61 * This is necessary for dictionaries since PyDict_SetItemString() does not
62 * steal a reference, as opposed to PyTuple_SetItem().
63 */
64static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val)
65{
66 PyDict_SetItemString(dict, key, val);
67 Py_DECREF(val);
68}
69
59static void define_value(enum print_arg_type field_type, 70static void define_value(enum print_arg_type field_type,
60 const char *ev_name, 71 const char *ev_name,
61 const char *field_name, 72 const char *field_name,
@@ -239,7 +250,7 @@ static void python_process_tracepoint(union perf_event *perf_event
239 int cpu = sample->cpu; 250 int cpu = sample->cpu;
240 void *data = sample->raw_data; 251 void *data = sample->raw_data;
241 unsigned long long nsecs = sample->time; 252 unsigned long long nsecs = sample->time;
242 char *comm = thread->comm; 253 const char *comm = thread__comm_str(thread);
243 254
244 t = PyTuple_New(MAX_FIELDS); 255 t = PyTuple_New(MAX_FIELDS);
245 if (!t) 256 if (!t)
@@ -279,11 +290,11 @@ static void python_process_tracepoint(union perf_event *perf_event
279 PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 290 PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
280 PyTuple_SetItem(t, n++, PyString_FromString(comm)); 291 PyTuple_SetItem(t, n++, PyString_FromString(comm));
281 } else { 292 } else {
282 PyDict_SetItemString(dict, "common_cpu", PyInt_FromLong(cpu)); 293 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
283 PyDict_SetItemString(dict, "common_s", PyInt_FromLong(s)); 294 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
284 PyDict_SetItemString(dict, "common_ns", PyInt_FromLong(ns)); 295 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
285 PyDict_SetItemString(dict, "common_pid", PyInt_FromLong(pid)); 296 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
286 PyDict_SetItemString(dict, "common_comm", PyString_FromString(comm)); 297 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
287 } 298 }
288 for (field = event->format.fields; field; field = field->next) { 299 for (field = event->format.fields; field; field = field->next) {
289 if (field->flags & FIELD_IS_STRING) { 300 if (field->flags & FIELD_IS_STRING) {
@@ -313,7 +324,7 @@ static void python_process_tracepoint(union perf_event *perf_event
313 if (handler) 324 if (handler)
314 PyTuple_SetItem(t, n++, obj); 325 PyTuple_SetItem(t, n++, obj);
315 else 326 else
316 PyDict_SetItemString(dict, field->name, obj); 327 pydict_set_item_string_decref(dict, field->name, obj);
317 328
318 } 329 }
319 if (!handler) 330 if (!handler)
@@ -370,21 +381,21 @@ static void python_process_general_event(union perf_event *perf_event
370 if (!handler || !PyCallable_Check(handler)) 381 if (!handler || !PyCallable_Check(handler))
371 goto exit; 382 goto exit;
372 383
373 PyDict_SetItemString(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 384 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
374 PyDict_SetItemString(dict, "attr", PyString_FromStringAndSize( 385 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
375 (const char *)&evsel->attr, sizeof(evsel->attr))); 386 (const char *)&evsel->attr, sizeof(evsel->attr)));
376 PyDict_SetItemString(dict, "sample", PyString_FromStringAndSize( 387 pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
377 (const char *)sample, sizeof(*sample))); 388 (const char *)sample, sizeof(*sample)));
378 PyDict_SetItemString(dict, "raw_buf", PyString_FromStringAndSize( 389 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
379 (const char *)sample->raw_data, sample->raw_size)); 390 (const char *)sample->raw_data, sample->raw_size));
380 PyDict_SetItemString(dict, "comm", 391 pydict_set_item_string_decref(dict, "comm",
381 PyString_FromString(thread->comm)); 392 PyString_FromString(thread__comm_str(thread)));
382 if (al->map) { 393 if (al->map) {
383 PyDict_SetItemString(dict, "dso", 394 pydict_set_item_string_decref(dict, "dso",
384 PyString_FromString(al->map->dso->name)); 395 PyString_FromString(al->map->dso->name));
385 } 396 }
386 if (al->sym) { 397 if (al->sym) {
387 PyDict_SetItemString(dict, "symbol", 398 pydict_set_item_string_decref(dict, "symbol",
388 PyString_FromString(al->sym->name)); 399 PyString_FromString(al->sym->name));
389 } 400 }
390 401
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 568b750c01f6..f36d24a02445 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,73 +16,34 @@
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "vdso.h" 17#include "vdso.h"
18 18
19static int perf_session__open(struct perf_session *self, bool force) 19static int perf_session__open(struct perf_session *session)
20{ 20{
21 struct stat input_stat; 21 struct perf_data_file *file = session->file;
22 22
23 if (!strcmp(self->filename, "-")) { 23 if (perf_session__read_header(session) < 0) {
24 self->fd_pipe = true;
25 self->fd = STDIN_FILENO;
26
27 if (perf_session__read_header(self) < 0)
28 pr_err("incompatible file format (rerun with -v to learn more)");
29
30 return 0;
31 }
32
33 self->fd = open(self->filename, O_RDONLY);
34 if (self->fd < 0) {
35 int err = errno;
36
37 pr_err("failed to open %s: %s", self->filename, strerror(err));
38 if (err == ENOENT && !strcmp(self->filename, "perf.data"))
39 pr_err(" (try 'perf record' first)");
40 pr_err("\n");
41 return -errno;
42 }
43
44 if (fstat(self->fd, &input_stat) < 0)
45 goto out_close;
46
47 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
48 pr_err("file %s not owned by current user or root\n",
49 self->filename);
50 goto out_close;
51 }
52
53 if (!input_stat.st_size) {
54 pr_info("zero-sized file (%s), nothing to do!\n",
55 self->filename);
56 goto out_close;
57 }
58
59 if (perf_session__read_header(self) < 0) {
60 pr_err("incompatible file format (rerun with -v to learn more)"); 24 pr_err("incompatible file format (rerun with -v to learn more)");
61 goto out_close; 25 return -1;
62 } 26 }
63 27
64 if (!perf_evlist__valid_sample_type(self->evlist)) { 28 if (perf_data_file__is_pipe(file))
29 return 0;
30
31 if (!perf_evlist__valid_sample_type(session->evlist)) {
65 pr_err("non matching sample_type"); 32 pr_err("non matching sample_type");
66 goto out_close; 33 return -1;
67 } 34 }
68 35
69 if (!perf_evlist__valid_sample_id_all(self->evlist)) { 36 if (!perf_evlist__valid_sample_id_all(session->evlist)) {
70 pr_err("non matching sample_id_all"); 37 pr_err("non matching sample_id_all");
71 goto out_close; 38 return -1;
72 } 39 }
73 40
74 if (!perf_evlist__valid_read_format(self->evlist)) { 41 if (!perf_evlist__valid_read_format(session->evlist)) {
75 pr_err("non matching read_format"); 42 pr_err("non matching read_format");
76 goto out_close; 43 return -1;
77 } 44 }
78 45
79 self->size = input_stat.st_size;
80 return 0; 46 return 0;
81
82out_close:
83 close(self->fd);
84 self->fd = -1;
85 return -1;
86} 47}
87 48
88void perf_session__set_id_hdr_size(struct perf_session *session) 49void perf_session__set_id_hdr_size(struct perf_session *session)
@@ -92,71 +53,70 @@ void perf_session__set_id_hdr_size(struct perf_session *session)
92 machines__set_id_hdr_size(&session->machines, id_hdr_size); 53 machines__set_id_hdr_size(&session->machines, id_hdr_size);
93} 54}
94 55
95int perf_session__create_kernel_maps(struct perf_session *self) 56int perf_session__create_kernel_maps(struct perf_session *session)
96{ 57{
97 int ret = machine__create_kernel_maps(&self->machines.host); 58 int ret = machine__create_kernel_maps(&session->machines.host);
98 59
99 if (ret >= 0) 60 if (ret >= 0)
100 ret = machines__create_guest_kernel_maps(&self->machines); 61 ret = machines__create_guest_kernel_maps(&session->machines);
101 return ret; 62 return ret;
102} 63}
103 64
104static void perf_session__destroy_kernel_maps(struct perf_session *self) 65static void perf_session__destroy_kernel_maps(struct perf_session *session)
105{ 66{
106 machines__destroy_kernel_maps(&self->machines); 67 machines__destroy_kernel_maps(&session->machines);
107} 68}
108 69
109struct perf_session *perf_session__new(const char *filename, int mode, 70struct perf_session *perf_session__new(struct perf_data_file *file,
110 bool force, bool repipe, 71 bool repipe, struct perf_tool *tool)
111 struct perf_tool *tool)
112{ 72{
113 struct perf_session *self; 73 struct perf_session *session = zalloc(sizeof(*session));
114 struct stat st;
115 size_t len;
116
117 if (!filename || !strlen(filename)) {
118 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
119 filename = "-";
120 else
121 filename = "perf.data";
122 }
123 74
124 len = strlen(filename); 75 if (!session)
125 self = zalloc(sizeof(*self) + len);
126
127 if (self == NULL)
128 goto out; 76 goto out;
129 77
130 memcpy(self->filename, filename, len); 78 session->repipe = repipe;
131 self->repipe = repipe; 79 INIT_LIST_HEAD(&session->ordered_samples.samples);
132 INIT_LIST_HEAD(&self->ordered_samples.samples); 80 INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
133 INIT_LIST_HEAD(&self->ordered_samples.sample_cache); 81 INIT_LIST_HEAD(&session->ordered_samples.to_free);
134 INIT_LIST_HEAD(&self->ordered_samples.to_free); 82 machines__init(&session->machines);
135 machines__init(&self->machines);
136 83
137 if (mode == O_RDONLY) { 84 if (file) {
138 if (perf_session__open(self, force) < 0) 85 if (perf_data_file__open(file))
139 goto out_delete; 86 goto out_delete;
140 perf_session__set_id_hdr_size(self); 87
141 } else if (mode == O_WRONLY) { 88 session->file = file;
89
90 if (perf_data_file__is_read(file)) {
91 if (perf_session__open(session) < 0)
92 goto out_close;
93
94 perf_session__set_id_hdr_size(session);
95 }
96 }
97
98 if (!file || perf_data_file__is_write(file)) {
142 /* 99 /*
143 * In O_RDONLY mode this will be performed when reading the 100 * In O_RDONLY mode this will be performed when reading the
144 * kernel MMAP event, in perf_event__process_mmap(). 101 * kernel MMAP event, in perf_event__process_mmap().
145 */ 102 */
146 if (perf_session__create_kernel_maps(self) < 0) 103 if (perf_session__create_kernel_maps(session) < 0)
147 goto out_delete; 104 goto out_delete;
148 } 105 }
149 106
150 if (tool && tool->ordering_requires_timestamps && 107 if (tool && tool->ordering_requires_timestamps &&
151 tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) { 108 tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) {
152 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 109 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
153 tool->ordered_samples = false; 110 tool->ordered_samples = false;
154 } 111 }
155 112
156out: 113 return session;
157 return self; 114
158out_delete: 115 out_close:
159 perf_session__delete(self); 116 perf_data_file__close(file);
117 out_delete:
118 perf_session__delete(session);
119 out:
160 return NULL; 120 return NULL;
161} 121}
162 122
@@ -186,15 +146,16 @@ static void perf_session_env__delete(struct perf_session_env *env)
186 free(env->pmu_mappings); 146 free(env->pmu_mappings);
187} 147}
188 148
189void perf_session__delete(struct perf_session *self) 149void perf_session__delete(struct perf_session *session)
190{ 150{
191 perf_session__destroy_kernel_maps(self); 151 perf_session__destroy_kernel_maps(session);
192 perf_session__delete_dead_threads(self); 152 perf_session__delete_dead_threads(session);
193 perf_session__delete_threads(self); 153 perf_session__delete_threads(session);
194 perf_session_env__delete(&self->header.env); 154 perf_session_env__delete(&session->header.env);
195 machines__exit(&self->machines); 155 machines__exit(&session->machines);
196 close(self->fd); 156 if (session->file)
197 free(self); 157 perf_data_file__close(session->file);
158 free(session);
198 vdso__exit(); 159 vdso__exit();
199} 160}
200 161
@@ -397,6 +358,17 @@ static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
397 swap_sample_id_all(event, &event->read + 1); 358 swap_sample_id_all(event, &event->read + 1);
398} 359}
399 360
361static void perf_event__throttle_swap(union perf_event *event,
362 bool sample_id_all)
363{
364 event->throttle.time = bswap_64(event->throttle.time);
365 event->throttle.id = bswap_64(event->throttle.id);
366 event->throttle.stream_id = bswap_64(event->throttle.stream_id);
367
368 if (sample_id_all)
369 swap_sample_id_all(event, &event->throttle + 1);
370}
371
400static u8 revbyte(u8 b) 372static u8 revbyte(u8 b)
401{ 373{
402 int rev = (b >> 4) | ((b & 0xf) << 4); 374 int rev = (b >> 4) | ((b & 0xf) << 4);
@@ -442,6 +414,9 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
442 attr->bp_type = bswap_32(attr->bp_type); 414 attr->bp_type = bswap_32(attr->bp_type);
443 attr->bp_addr = bswap_64(attr->bp_addr); 415 attr->bp_addr = bswap_64(attr->bp_addr);
444 attr->bp_len = bswap_64(attr->bp_len); 416 attr->bp_len = bswap_64(attr->bp_len);
417 attr->branch_sample_type = bswap_64(attr->branch_sample_type);
418 attr->sample_regs_user = bswap_64(attr->sample_regs_user);
419 attr->sample_stack_user = bswap_32(attr->sample_stack_user);
445 420
446 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); 421 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
447} 422}
@@ -482,6 +457,8 @@ static perf_event__swap_op perf_event__swap_ops[] = {
482 [PERF_RECORD_EXIT] = perf_event__task_swap, 457 [PERF_RECORD_EXIT] = perf_event__task_swap,
483 [PERF_RECORD_LOST] = perf_event__all64_swap, 458 [PERF_RECORD_LOST] = perf_event__all64_swap,
484 [PERF_RECORD_READ] = perf_event__read_swap, 459 [PERF_RECORD_READ] = perf_event__read_swap,
460 [PERF_RECORD_THROTTLE] = perf_event__throttle_swap,
461 [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap,
485 [PERF_RECORD_SAMPLE] = perf_event__all64_swap, 462 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
486 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, 463 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
487 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 464 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
@@ -525,13 +502,16 @@ static int flush_sample_queue(struct perf_session *s,
525 struct perf_sample sample; 502 struct perf_sample sample;
526 u64 limit = os->next_flush; 503 u64 limit = os->next_flush;
527 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; 504 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
528 unsigned idx = 0, progress_next = os->nr_samples / 16;
529 bool show_progress = limit == ULLONG_MAX; 505 bool show_progress = limit == ULLONG_MAX;
506 struct ui_progress prog;
530 int ret; 507 int ret;
531 508
532 if (!tool->ordered_samples || !limit) 509 if (!tool->ordered_samples || !limit)
533 return 0; 510 return 0;
534 511
512 if (show_progress)
513 ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
514
535 list_for_each_entry_safe(iter, tmp, head, list) { 515 list_for_each_entry_safe(iter, tmp, head, list) {
536 if (session_done()) 516 if (session_done())
537 return 0; 517 return 0;
@@ -552,11 +532,9 @@ static int flush_sample_queue(struct perf_session *s,
552 os->last_flush = iter->timestamp; 532 os->last_flush = iter->timestamp;
553 list_del(&iter->list); 533 list_del(&iter->list);
554 list_add(&iter->list, &os->sample_cache); 534 list_add(&iter->list, &os->sample_cache);
555 if (show_progress && (++idx >= progress_next)) { 535
556 progress_next += os->nr_samples / 16; 536 if (show_progress)
557 ui_progress__update(idx, os->nr_samples, 537 ui_progress__update(&prog, 1);
558 "Processing time ordered events...");
559 }
560 } 538 }
561 539
562 if (list_empty(head)) { 540 if (list_empty(head)) {
@@ -860,6 +838,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
860 if (sample_type & PERF_SAMPLE_DATA_SRC) 838 if (sample_type & PERF_SAMPLE_DATA_SRC)
861 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); 839 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
862 840
841 if (sample_type & PERF_SAMPLE_TRANSACTION)
842 printf("... transaction: %" PRIx64 "\n", sample->transaction);
843
863 if (sample_type & PERF_SAMPLE_READ) 844 if (sample_type & PERF_SAMPLE_READ)
864 sample_read__printf(sample, evsel->attr.read_format); 845 sample_read__printf(sample, evsel->attr.read_format);
865} 846}
@@ -1031,6 +1012,7 @@ static int perf_session_deliver_event(struct perf_session *session,
1031static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, 1012static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
1032 struct perf_tool *tool, u64 file_offset) 1013 struct perf_tool *tool, u64 file_offset)
1033{ 1014{
1015 int fd = perf_data_file__fd(session->file);
1034 int err; 1016 int err;
1035 1017
1036 dump_event(session, event, file_offset, NULL); 1018 dump_event(session, event, file_offset, NULL);
@@ -1044,7 +1026,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
1044 return err; 1026 return err;
1045 case PERF_RECORD_HEADER_TRACING_DATA: 1027 case PERF_RECORD_HEADER_TRACING_DATA:
1046 /* setup for reading amidst mmap */ 1028 /* setup for reading amidst mmap */
1047 lseek(session->fd, file_offset, SEEK_SET); 1029 lseek(fd, file_offset, SEEK_SET);
1048 return tool->tracing_data(tool, event, session); 1030 return tool->tracing_data(tool, event, session);
1049 case PERF_RECORD_HEADER_BUILD_ID: 1031 case PERF_RECORD_HEADER_BUILD_ID:
1050 return tool->build_id(tool, event, session); 1032 return tool->build_id(tool, event, session);
@@ -1101,11 +1083,11 @@ static int perf_session__process_event(struct perf_session *session,
1101 file_offset); 1083 file_offset);
1102} 1084}
1103 1085
1104void perf_event_header__bswap(struct perf_event_header *self) 1086void perf_event_header__bswap(struct perf_event_header *hdr)
1105{ 1087{
1106 self->type = bswap_32(self->type); 1088 hdr->type = bswap_32(hdr->type);
1107 self->misc = bswap_16(self->misc); 1089 hdr->misc = bswap_16(hdr->misc);
1108 self->size = bswap_16(self->size); 1090 hdr->size = bswap_16(hdr->size);
1109} 1091}
1110 1092
1111struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) 1093struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
@@ -1113,11 +1095,11 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1113 return machine__findnew_thread(&session->machines.host, 0, pid); 1095 return machine__findnew_thread(&session->machines.host, 0, pid);
1114} 1096}
1115 1097
1116static struct thread *perf_session__register_idle_thread(struct perf_session *self) 1098static struct thread *perf_session__register_idle_thread(struct perf_session *session)
1117{ 1099{
1118 struct thread *thread = perf_session__findnew(self, 0); 1100 struct thread *thread = perf_session__findnew(session, 0);
1119 1101
1120 if (thread == NULL || thread__set_comm(thread, "swapper")) { 1102 if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
1121 pr_err("problem inserting idle task.\n"); 1103 pr_err("problem inserting idle task.\n");
1122 thread = NULL; 1104 thread = NULL;
1123 } 1105 }
@@ -1167,9 +1149,10 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
1167 1149
1168volatile int session_done; 1150volatile int session_done;
1169 1151
1170static int __perf_session__process_pipe_events(struct perf_session *self, 1152static int __perf_session__process_pipe_events(struct perf_session *session,
1171 struct perf_tool *tool) 1153 struct perf_tool *tool)
1172{ 1154{
1155 int fd = perf_data_file__fd(session->file);
1173 union perf_event *event; 1156 union perf_event *event;
1174 uint32_t size, cur_size = 0; 1157 uint32_t size, cur_size = 0;
1175 void *buf = NULL; 1158 void *buf = NULL;
@@ -1188,7 +1171,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
1188 return -errno; 1171 return -errno;
1189more: 1172more:
1190 event = buf; 1173 event = buf;
1191 err = readn(self->fd, event, sizeof(struct perf_event_header)); 1174 err = readn(fd, event, sizeof(struct perf_event_header));
1192 if (err <= 0) { 1175 if (err <= 0) {
1193 if (err == 0) 1176 if (err == 0)
1194 goto done; 1177 goto done;
@@ -1197,7 +1180,7 @@ more:
1197 goto out_err; 1180 goto out_err;
1198 } 1181 }
1199 1182
1200 if (self->header.needs_swap) 1183 if (session->header.needs_swap)
1201 perf_event_header__bswap(&event->header); 1184 perf_event_header__bswap(&event->header);
1202 1185
1203 size = event->header.size; 1186 size = event->header.size;
@@ -1220,7 +1203,7 @@ more:
1220 p += sizeof(struct perf_event_header); 1203 p += sizeof(struct perf_event_header);
1221 1204
1222 if (size - sizeof(struct perf_event_header)) { 1205 if (size - sizeof(struct perf_event_header)) {
1223 err = readn(self->fd, p, size - sizeof(struct perf_event_header)); 1206 err = readn(fd, p, size - sizeof(struct perf_event_header));
1224 if (err <= 0) { 1207 if (err <= 0) {
1225 if (err == 0) { 1208 if (err == 0) {
1226 pr_err("unexpected end of event stream\n"); 1209 pr_err("unexpected end of event stream\n");
@@ -1232,7 +1215,7 @@ more:
1232 } 1215 }
1233 } 1216 }
1234 1217
1235 if ((skip = perf_session__process_event(self, event, tool, head)) < 0) { 1218 if ((skip = perf_session__process_event(session, event, tool, head)) < 0) {
1236 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1219 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1237 head, event->header.size, event->header.type); 1220 head, event->header.size, event->header.type);
1238 err = -EINVAL; 1221 err = -EINVAL;
@@ -1247,11 +1230,13 @@ more:
1247 if (!session_done()) 1230 if (!session_done())
1248 goto more; 1231 goto more;
1249done: 1232done:
1250 err = 0; 1233 /* do the final flush for ordered samples */
1234 session->ordered_samples.next_flush = ULLONG_MAX;
1235 err = flush_sample_queue(session, tool);
1251out_err: 1236out_err:
1252 free(buf); 1237 free(buf);
1253 perf_session__warn_about_errors(self, tool); 1238 perf_session__warn_about_errors(session, tool);
1254 perf_session_free_sample_buffers(self); 1239 perf_session_free_sample_buffers(session);
1255 return err; 1240 return err;
1256} 1241}
1257 1242
@@ -1299,12 +1284,14 @@ int __perf_session__process_events(struct perf_session *session,
1299 u64 data_offset, u64 data_size, 1284 u64 data_offset, u64 data_size,
1300 u64 file_size, struct perf_tool *tool) 1285 u64 file_size, struct perf_tool *tool)
1301{ 1286{
1302 u64 head, page_offset, file_offset, file_pos, progress_next; 1287 int fd = perf_data_file__fd(session->file);
1288 u64 head, page_offset, file_offset, file_pos;
1303 int err, mmap_prot, mmap_flags, map_idx = 0; 1289 int err, mmap_prot, mmap_flags, map_idx = 0;
1304 size_t mmap_size; 1290 size_t mmap_size;
1305 char *buf, *mmaps[NUM_MMAPS]; 1291 char *buf, *mmaps[NUM_MMAPS];
1306 union perf_event *event; 1292 union perf_event *event;
1307 uint32_t size; 1293 uint32_t size;
1294 struct ui_progress prog;
1308 1295
1309 perf_tool__fill_defaults(tool); 1296 perf_tool__fill_defaults(tool);
1310 1297
@@ -1315,7 +1302,7 @@ int __perf_session__process_events(struct perf_session *session,
1315 if (data_size && (data_offset + data_size < file_size)) 1302 if (data_size && (data_offset + data_size < file_size))
1316 file_size = data_offset + data_size; 1303 file_size = data_offset + data_size;
1317 1304
1318 progress_next = file_size / 16; 1305 ui_progress__init(&prog, file_size, "Processing events...");
1319 1306
1320 mmap_size = MMAP_SIZE; 1307 mmap_size = MMAP_SIZE;
1321 if (mmap_size > file_size) 1308 if (mmap_size > file_size)
@@ -1331,7 +1318,7 @@ int __perf_session__process_events(struct perf_session *session,
1331 mmap_flags = MAP_PRIVATE; 1318 mmap_flags = MAP_PRIVATE;
1332 } 1319 }
1333remap: 1320remap:
1334 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd, 1321 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, fd,
1335 file_offset); 1322 file_offset);
1336 if (buf == MAP_FAILED) { 1323 if (buf == MAP_FAILED) {
1337 pr_err("failed to mmap file\n"); 1324 pr_err("failed to mmap file\n");
@@ -1370,19 +1357,15 @@ more:
1370 head += size; 1357 head += size;
1371 file_pos += size; 1358 file_pos += size;
1372 1359
1373 if (file_pos >= progress_next) { 1360 ui_progress__update(&prog, size);
1374 progress_next += file_size / 16;
1375 ui_progress__update(file_pos, file_size,
1376 "Processing events...");
1377 }
1378 1361
1379 err = 0;
1380 if (session_done()) 1362 if (session_done())
1381 goto out_err; 1363 goto out;
1382 1364
1383 if (file_pos < file_size) 1365 if (file_pos < file_size)
1384 goto more; 1366 goto more;
1385 1367
1368out:
1386 /* do the final flush for ordered samples */ 1369 /* do the final flush for ordered samples */
1387 session->ordered_samples.next_flush = ULLONG_MAX; 1370 session->ordered_samples.next_flush = ULLONG_MAX;
1388 err = flush_sample_queue(session, tool); 1371 err = flush_sample_queue(session, tool);
@@ -1393,21 +1376,22 @@ out_err:
1393 return err; 1376 return err;
1394} 1377}
1395 1378
1396int perf_session__process_events(struct perf_session *self, 1379int perf_session__process_events(struct perf_session *session,
1397 struct perf_tool *tool) 1380 struct perf_tool *tool)
1398{ 1381{
1382 u64 size = perf_data_file__size(session->file);
1399 int err; 1383 int err;
1400 1384
1401 if (perf_session__register_idle_thread(self) == NULL) 1385 if (perf_session__register_idle_thread(session) == NULL)
1402 return -ENOMEM; 1386 return -ENOMEM;
1403 1387
1404 if (!self->fd_pipe) 1388 if (!perf_data_file__is_pipe(session->file))
1405 err = __perf_session__process_events(self, 1389 err = __perf_session__process_events(session,
1406 self->header.data_offset, 1390 session->header.data_offset,
1407 self->header.data_size, 1391 session->header.data_size,
1408 self->size, tool); 1392 size, tool);
1409 else 1393 else
1410 err = __perf_session__process_pipe_events(self, tool); 1394 err = __perf_session__process_pipe_events(session, tool);
1411 1395
1412 return err; 1396 return err;
1413} 1397}
@@ -1456,15 +1440,15 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1456 return 0; 1440 return 0;
1457} 1441}
1458 1442
1459size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) 1443size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp)
1460{ 1444{
1461 return machines__fprintf_dsos(&self->machines, fp); 1445 return machines__fprintf_dsos(&session->machines, fp);
1462} 1446}
1463 1447
1464size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, 1448size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
1465 bool (skip)(struct dso *dso, int parm), int parm) 1449 bool (skip)(struct dso *dso, int parm), int parm)
1466{ 1450{
1467 return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm); 1451 return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm);
1468} 1452}
1469 1453
1470size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) 1454size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
@@ -1525,7 +1509,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1525 if (symbol_conf.use_callchain && sample->callchain) { 1509 if (symbol_conf.use_callchain && sample->callchain) {
1526 1510
1527 if (machine__resolve_callchain(machine, evsel, al.thread, 1511 if (machine__resolve_callchain(machine, evsel, al.thread,
1528 sample, NULL, NULL) != 0) { 1512 sample, NULL, NULL,
1513 PERF_MAX_STACK_DEPTH) != 0) {
1529 if (verbose) 1514 if (verbose)
1530 error("Failed to resolve callchain. Skipping\n"); 1515 error("Failed to resolve callchain. Skipping\n");
1531 return; 1516 return;
@@ -1629,13 +1614,14 @@ int perf_session__cpu_bitmap(struct perf_session *session,
1629void perf_session__fprintf_info(struct perf_session *session, FILE *fp, 1614void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
1630 bool full) 1615 bool full)
1631{ 1616{
1617 int fd = perf_data_file__fd(session->file);
1632 struct stat st; 1618 struct stat st;
1633 int ret; 1619 int ret;
1634 1620
1635 if (session == NULL || fp == NULL) 1621 if (session == NULL || fp == NULL)
1636 return; 1622 return;
1637 1623
1638 ret = fstat(session->fd, &st); 1624 ret = fstat(fd, &st);
1639 if (ret == -1) 1625 if (ret == -1)
1640 return; 1626 return;
1641 1627
@@ -1664,9 +1650,9 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1664 continue; 1650 continue;
1665 1651
1666 err = -EEXIST; 1652 err = -EEXIST;
1667 if (evsel->handler.func != NULL) 1653 if (evsel->handler != NULL)
1668 goto out; 1654 goto out;
1669 evsel->handler.func = assocs[i].handler; 1655 evsel->handler = assocs[i].handler;
1670 } 1656 }
1671 1657
1672 err = 0; 1658 err = 0;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 04bf7373a7e5..50f640958f0f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -7,6 +7,7 @@
7#include "machine.h" 7#include "machine.h"
8#include "symbol.h" 8#include "symbol.h"
9#include "thread.h" 9#include "thread.h"
10#include "data.h"
10#include <linux/rbtree.h> 11#include <linux/rbtree.h>
11#include <linux/perf_event.h> 12#include <linux/perf_event.h>
12 13
@@ -29,16 +30,13 @@ struct ordered_samples {
29 30
30struct perf_session { 31struct perf_session {
31 struct perf_header header; 32 struct perf_header header;
32 unsigned long size;
33 struct machines machines; 33 struct machines machines;
34 struct perf_evlist *evlist; 34 struct perf_evlist *evlist;
35 struct pevent *pevent; 35 struct pevent *pevent;
36 struct events_stats stats; 36 struct events_stats stats;
37 int fd;
38 bool fd_pipe;
39 bool repipe; 37 bool repipe;
40 struct ordered_samples ordered_samples; 38 struct ordered_samples ordered_samples;
41 char filename[1]; 39 struct perf_data_file *file;
42}; 40};
43 41
44#define PRINT_IP_OPT_IP (1<<0) 42#define PRINT_IP_OPT_IP (1<<0)
@@ -49,17 +47,16 @@ struct perf_session {
49 47
50struct perf_tool; 48struct perf_tool;
51 49
52struct perf_session *perf_session__new(const char *filename, int mode, 50struct perf_session *perf_session__new(struct perf_data_file *file,
53 bool force, bool repipe, 51 bool repipe, struct perf_tool *tool);
54 struct perf_tool *tool);
55void perf_session__delete(struct perf_session *session); 52void perf_session__delete(struct perf_session *session);
56 53
57void perf_event_header__bswap(struct perf_event_header *self); 54void perf_event_header__bswap(struct perf_event_header *hdr);
58 55
59int __perf_session__process_events(struct perf_session *self, 56int __perf_session__process_events(struct perf_session *session,
60 u64 data_offset, u64 data_size, u64 size, 57 u64 data_offset, u64 data_size, u64 size,
61 struct perf_tool *tool); 58 struct perf_tool *tool);
62int perf_session__process_events(struct perf_session *self, 59int perf_session__process_events(struct perf_session *session,
63 struct perf_tool *tool); 60 struct perf_tool *tool);
64 61
65int perf_session_queue_event(struct perf_session *s, union perf_event *event, 62int perf_session_queue_event(struct perf_session *s, union perf_event *event,
@@ -67,37 +64,38 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
67 64
68void perf_tool__fill_defaults(struct perf_tool *tool); 65void perf_tool__fill_defaults(struct perf_tool *tool);
69 66
70int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel, 67int perf_session__resolve_callchain(struct perf_session *session,
68 struct perf_evsel *evsel,
71 struct thread *thread, 69 struct thread *thread,
72 struct ip_callchain *chain, 70 struct ip_callchain *chain,
73 struct symbol **parent); 71 struct symbol **parent);
74 72
75bool perf_session__has_traces(struct perf_session *self, const char *msg); 73bool perf_session__has_traces(struct perf_session *session, const char *msg);
76 74
77void mem_bswap_64(void *src, int byte_size); 75void mem_bswap_64(void *src, int byte_size);
78void mem_bswap_32(void *src, int byte_size); 76void mem_bswap_32(void *src, int byte_size);
79void perf_event__attr_swap(struct perf_event_attr *attr); 77void perf_event__attr_swap(struct perf_event_attr *attr);
80 78
81int perf_session__create_kernel_maps(struct perf_session *self); 79int perf_session__create_kernel_maps(struct perf_session *session);
82 80
83void perf_session__set_id_hdr_size(struct perf_session *session); 81void perf_session__set_id_hdr_size(struct perf_session *session);
84 82
85static inline 83static inline
86struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) 84struct machine *perf_session__find_machine(struct perf_session *session, pid_t pid)
87{ 85{
88 return machines__find(&self->machines, pid); 86 return machines__find(&session->machines, pid);
89} 87}
90 88
91static inline 89static inline
92struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) 90struct machine *perf_session__findnew_machine(struct perf_session *session, pid_t pid)
93{ 91{
94 return machines__findnew(&self->machines, pid); 92 return machines__findnew(&session->machines, pid);
95} 93}
96 94
97struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); 95struct thread *perf_session__findnew(struct perf_session *session, pid_t pid);
98size_t perf_session__fprintf(struct perf_session *self, FILE *fp); 96size_t perf_session__fprintf(struct perf_session *session, FILE *fp);
99 97
100size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); 98size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp);
101 99
102size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp, 100size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
103 bool (fn)(struct dso *dso, int parm), int parm); 101 bool (fn)(struct dso *dso, int parm), int parm);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5f118a089519..3c1b75c8b9a6 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,5 +1,6 @@
1#include "sort.h" 1#include "sort.h"
2#include "hist.h" 2#include "hist.h"
3#include "comm.h"
3#include "symbol.h" 4#include "symbol.h"
4 5
5regex_t parent_regex; 6regex_t parent_regex;
@@ -42,7 +43,7 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
42 return n; 43 return n;
43} 44}
44 45
45static int64_t cmp_null(void *l, void *r) 46static int64_t cmp_null(const void *l, const void *r)
46{ 47{
47 if (!l && !r) 48 if (!l && !r)
48 return 0; 49 return 0;
@@ -60,11 +61,12 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
60 return right->thread->tid - left->thread->tid; 61 return right->thread->tid - left->thread->tid;
61} 62}
62 63
63static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, 64static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
64 size_t size, unsigned int width) 65 size_t size, unsigned int width)
65{ 66{
67 const char *comm = thread__comm_str(he->thread);
66 return repsep_snprintf(bf, size, "%*s:%5d", width - 6, 68 return repsep_snprintf(bf, size, "%*s:%5d", width - 6,
67 self->thread->comm ?: "", self->thread->tid); 69 comm ?: "", he->thread->tid);
68} 70}
69 71
70struct sort_entry sort_thread = { 72struct sort_entry sort_thread = {
@@ -79,25 +81,21 @@ struct sort_entry sort_thread = {
79static int64_t 81static int64_t
80sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 82sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
81{ 83{
82 return right->thread->tid - left->thread->tid; 84 /* Compare the addr that should be unique among comm */
85 return comm__str(right->comm) - comm__str(left->comm);
83} 86}
84 87
85static int64_t 88static int64_t
86sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 89sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
87{ 90{
88 char *comm_l = left->thread->comm; 91 /* Compare the addr that should be unique among comm */
89 char *comm_r = right->thread->comm; 92 return comm__str(right->comm) - comm__str(left->comm);
90
91 if (!comm_l || !comm_r)
92 return cmp_null(comm_l, comm_r);
93
94 return strcmp(comm_l, comm_r);
95} 93}
96 94
97static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, 95static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
98 size_t size, unsigned int width) 96 size_t size, unsigned int width)
99{ 97{
100 return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); 98 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm));
101} 99}
102 100
103struct sort_entry sort_comm = { 101struct sort_entry sort_comm = {
@@ -148,10 +146,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf,
148 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 146 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
149} 147}
150 148
151static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, 149static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
152 size_t size, unsigned int width) 150 size_t size, unsigned int width)
153{ 151{
154 return _hist_entry__dso_snprintf(self->ms.map, bf, size, width); 152 return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
155} 153}
156 154
157struct sort_entry sort_dso = { 155struct sort_entry sort_dso = {
@@ -182,9 +180,19 @@ static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
182static int64_t 180static int64_t
183sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 181sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
184{ 182{
183 int64_t ret;
184
185 if (!left->ms.sym && !right->ms.sym) 185 if (!left->ms.sym && !right->ms.sym)
186 return right->level - left->level; 186 return right->level - left->level;
187 187
188 /*
189 * comparing symbol address alone is not enough since it's a
190 * relative address within a dso.
191 */
192 ret = sort__dso_cmp(left, right);
193 if (ret != 0)
194 return ret;
195
188 return _sort__sym_cmp(left->ms.sym, right->ms.sym); 196 return _sort__sym_cmp(left->ms.sym, right->ms.sym);
189} 197}
190 198
@@ -224,11 +232,11 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
224 return ret; 232 return ret;
225} 233}
226 234
227static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, 235static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
228 size_t size, unsigned int width) 236 size_t size, unsigned int width)
229{ 237{
230 return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip, 238 return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
231 self->level, bf, size, width); 239 he->level, bf, size, width);
232} 240}
233 241
234struct sort_entry sort_sym = { 242struct sort_entry sort_sym = {
@@ -243,50 +251,32 @@ struct sort_entry sort_sym = {
243static int64_t 251static int64_t
244sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) 252sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
245{ 253{
246 return (int64_t)(right->ip - left->ip); 254 if (!left->srcline) {
255 if (!left->ms.map)
256 left->srcline = SRCLINE_UNKNOWN;
257 else {
258 struct map *map = left->ms.map;
259 left->srcline = get_srcline(map->dso,
260 map__rip_2objdump(map, left->ip));
261 }
262 }
263 if (!right->srcline) {
264 if (!right->ms.map)
265 right->srcline = SRCLINE_UNKNOWN;
266 else {
267 struct map *map = right->ms.map;
268 right->srcline = get_srcline(map->dso,
269 map__rip_2objdump(map, right->ip));
270 }
271 }
272 return strcmp(left->srcline, right->srcline);
247} 273}
248 274
249static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, 275static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
250 size_t size, 276 size_t size,
251 unsigned int width __maybe_unused) 277 unsigned int width __maybe_unused)
252{ 278{
253 FILE *fp = NULL; 279 return repsep_snprintf(bf, size, "%s", he->srcline);
254 char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
255 size_t line_len;
256
257 if (path != NULL)
258 goto out_path;
259
260 if (!self->ms.map)
261 goto out_ip;
262
263 if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
264 goto out_ip;
265
266 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
267 self->ms.map->dso->long_name, self->ip);
268 fp = popen(cmd, "r");
269 if (!fp)
270 goto out_ip;
271
272 if (getline(&path, &line_len, fp) < 0 || !line_len)
273 goto out_ip;
274 self->srcline = strdup(path);
275 if (self->srcline == NULL)
276 goto out_ip;
277
278 nl = strchr(self->srcline, '\n');
279 if (nl != NULL)
280 *nl = '\0';
281 path = self->srcline;
282out_path:
283 if (fp)
284 pclose(fp);
285 return repsep_snprintf(bf, size, "%s", path);
286out_ip:
287 if (fp)
288 pclose(fp);
289 return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
290} 280}
291 281
292struct sort_entry sort_srcline = { 282struct sort_entry sort_srcline = {
@@ -310,11 +300,11 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
310 return strcmp(sym_l->name, sym_r->name); 300 return strcmp(sym_l->name, sym_r->name);
311} 301}
312 302
313static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, 303static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
314 size_t size, unsigned int width) 304 size_t size, unsigned int width)
315{ 305{
316 return repsep_snprintf(bf, size, "%-*s", width, 306 return repsep_snprintf(bf, size, "%-*s", width,
317 self->parent ? self->parent->name : "[other]"); 307 he->parent ? he->parent->name : "[other]");
318} 308}
319 309
320struct sort_entry sort_parent = { 310struct sort_entry sort_parent = {
@@ -332,10 +322,10 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
332 return right->cpu - left->cpu; 322 return right->cpu - left->cpu;
333} 323}
334 324
335static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, 325static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
336 size_t size, unsigned int width) 326 size_t size, unsigned int width)
337{ 327{
338 return repsep_snprintf(bf, size, "%*d", width, self->cpu); 328 return repsep_snprintf(bf, size, "%*d", width, he->cpu);
339} 329}
340 330
341struct sort_entry sort_cpu = { 331struct sort_entry sort_cpu = {
@@ -354,10 +344,10 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
354 right->branch_info->from.map); 344 right->branch_info->from.map);
355} 345}
356 346
357static int hist_entry__dso_from_snprintf(struct hist_entry *self, char *bf, 347static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
358 size_t size, unsigned int width) 348 size_t size, unsigned int width)
359{ 349{
360 return _hist_entry__dso_snprintf(self->branch_info->from.map, 350 return _hist_entry__dso_snprintf(he->branch_info->from.map,
361 bf, size, width); 351 bf, size, width);
362} 352}
363 353
@@ -368,10 +358,10 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
368 right->branch_info->to.map); 358 right->branch_info->to.map);
369} 359}
370 360
371static int hist_entry__dso_to_snprintf(struct hist_entry *self, char *bf, 361static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
372 size_t size, unsigned int width) 362 size_t size, unsigned int width)
373{ 363{
374 return _hist_entry__dso_snprintf(self->branch_info->to.map, 364 return _hist_entry__dso_snprintf(he->branch_info->to.map,
375 bf, size, width); 365 bf, size, width);
376} 366}
377 367
@@ -399,21 +389,21 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
399 return _sort__sym_cmp(to_l->sym, to_r->sym); 389 return _sort__sym_cmp(to_l->sym, to_r->sym);
400} 390}
401 391
402static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, 392static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
403 size_t size, unsigned int width) 393 size_t size, unsigned int width)
404{ 394{
405 struct addr_map_symbol *from = &self->branch_info->from; 395 struct addr_map_symbol *from = &he->branch_info->from;
406 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, 396 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
407 self->level, bf, size, width); 397 he->level, bf, size, width);
408 398
409} 399}
410 400
411static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, 401static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
412 size_t size, unsigned int width) 402 size_t size, unsigned int width)
413{ 403{
414 struct addr_map_symbol *to = &self->branch_info->to; 404 struct addr_map_symbol *to = &he->branch_info->to;
415 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, 405 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
416 self->level, bf, size, width); 406 he->level, bf, size, width);
417 407
418} 408}
419 409
@@ -456,13 +446,13 @@ sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
456 return mp || p; 446 return mp || p;
457} 447}
458 448
459static int hist_entry__mispredict_snprintf(struct hist_entry *self, char *bf, 449static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
460 size_t size, unsigned int width){ 450 size_t size, unsigned int width){
461 static const char *out = "N/A"; 451 static const char *out = "N/A";
462 452
463 if (self->branch_info->flags.predicted) 453 if (he->branch_info->flags.predicted)
464 out = "N"; 454 out = "N";
465 else if (self->branch_info->flags.mispred) 455 else if (he->branch_info->flags.mispred)
466 out = "Y"; 456 out = "Y";
467 457
468 return repsep_snprintf(bf, size, "%-*s", width, out); 458 return repsep_snprintf(bf, size, "%-*s", width, out);
@@ -482,19 +472,19 @@ sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
482 return (int64_t)(r - l); 472 return (int64_t)(r - l);
483} 473}
484 474
485static int hist_entry__daddr_snprintf(struct hist_entry *self, char *bf, 475static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
486 size_t size, unsigned int width) 476 size_t size, unsigned int width)
487{ 477{
488 uint64_t addr = 0; 478 uint64_t addr = 0;
489 struct map *map = NULL; 479 struct map *map = NULL;
490 struct symbol *sym = NULL; 480 struct symbol *sym = NULL;
491 481
492 if (self->mem_info) { 482 if (he->mem_info) {
493 addr = self->mem_info->daddr.addr; 483 addr = he->mem_info->daddr.addr;
494 map = self->mem_info->daddr.map; 484 map = he->mem_info->daddr.map;
495 sym = self->mem_info->daddr.sym; 485 sym = he->mem_info->daddr.sym;
496 } 486 }
497 return _hist_entry__sym_snprintf(map, sym, addr, self->level, bf, size, 487 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
498 width); 488 width);
499} 489}
500 490
@@ -512,13 +502,13 @@ sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
512 return _sort__dso_cmp(map_l, map_r); 502 return _sort__dso_cmp(map_l, map_r);
513} 503}
514 504
515static int hist_entry__dso_daddr_snprintf(struct hist_entry *self, char *bf, 505static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
516 size_t size, unsigned int width) 506 size_t size, unsigned int width)
517{ 507{
518 struct map *map = NULL; 508 struct map *map = NULL;
519 509
520 if (self->mem_info) 510 if (he->mem_info)
521 map = self->mem_info->daddr.map; 511 map = he->mem_info->daddr.map;
522 512
523 return _hist_entry__dso_snprintf(map, bf, size, width); 513 return _hist_entry__dso_snprintf(map, bf, size, width);
524} 514}
@@ -542,14 +532,14 @@ sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
542 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock); 532 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
543} 533}
544 534
545static int hist_entry__locked_snprintf(struct hist_entry *self, char *bf, 535static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
546 size_t size, unsigned int width) 536 size_t size, unsigned int width)
547{ 537{
548 const char *out; 538 const char *out;
549 u64 mask = PERF_MEM_LOCK_NA; 539 u64 mask = PERF_MEM_LOCK_NA;
550 540
551 if (self->mem_info) 541 if (he->mem_info)
552 mask = self->mem_info->data_src.mem_lock; 542 mask = he->mem_info->data_src.mem_lock;
553 543
554 if (mask & PERF_MEM_LOCK_NA) 544 if (mask & PERF_MEM_LOCK_NA)
555 out = "N/A"; 545 out = "N/A";
@@ -591,7 +581,7 @@ static const char * const tlb_access[] = {
591}; 581};
592#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *)) 582#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
593 583
594static int hist_entry__tlb_snprintf(struct hist_entry *self, char *bf, 584static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
595 size_t size, unsigned int width) 585 size_t size, unsigned int width)
596{ 586{
597 char out[64]; 587 char out[64];
@@ -602,8 +592,8 @@ static int hist_entry__tlb_snprintf(struct hist_entry *self, char *bf,
602 592
603 out[0] = '\0'; 593 out[0] = '\0';
604 594
605 if (self->mem_info) 595 if (he->mem_info)
606 m = self->mem_info->data_src.mem_dtlb; 596 m = he->mem_info->data_src.mem_dtlb;
607 597
608 hit = m & PERF_MEM_TLB_HIT; 598 hit = m & PERF_MEM_TLB_HIT;
609 miss = m & PERF_MEM_TLB_MISS; 599 miss = m & PERF_MEM_TLB_MISS;
@@ -668,7 +658,7 @@ static const char * const mem_lvl[] = {
668}; 658};
669#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *)) 659#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
670 660
671static int hist_entry__lvl_snprintf(struct hist_entry *self, char *bf, 661static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
672 size_t size, unsigned int width) 662 size_t size, unsigned int width)
673{ 663{
674 char out[64]; 664 char out[64];
@@ -677,8 +667,8 @@ static int hist_entry__lvl_snprintf(struct hist_entry *self, char *bf,
677 u64 m = PERF_MEM_LVL_NA; 667 u64 m = PERF_MEM_LVL_NA;
678 u64 hit, miss; 668 u64 hit, miss;
679 669
680 if (self->mem_info) 670 if (he->mem_info)
681 m = self->mem_info->data_src.mem_lvl; 671 m = he->mem_info->data_src.mem_lvl;
682 672
683 out[0] = '\0'; 673 out[0] = '\0';
684 674
@@ -736,7 +726,7 @@ static const char * const snoop_access[] = {
736}; 726};
737#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *)) 727#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
738 728
739static int hist_entry__snoop_snprintf(struct hist_entry *self, char *bf, 729static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
740 size_t size, unsigned int width) 730 size_t size, unsigned int width)
741{ 731{
742 char out[64]; 732 char out[64];
@@ -746,8 +736,8 @@ static int hist_entry__snoop_snprintf(struct hist_entry *self, char *bf,
746 736
747 out[0] = '\0'; 737 out[0] = '\0';
748 738
749 if (self->mem_info) 739 if (he->mem_info)
750 m = self->mem_info->data_src.mem_snoop; 740 m = he->mem_info->data_src.mem_snoop;
751 741
752 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) { 742 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
753 if (!(m & 0x1)) 743 if (!(m & 0x1))
@@ -784,10 +774,10 @@ sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
784 return he_weight(left) - he_weight(right); 774 return he_weight(left) - he_weight(right);
785} 775}
786 776
787static int hist_entry__local_weight_snprintf(struct hist_entry *self, char *bf, 777static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
788 size_t size, unsigned int width) 778 size_t size, unsigned int width)
789{ 779{
790 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(self)); 780 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
791} 781}
792 782
793struct sort_entry sort_local_weight = { 783struct sort_entry sort_local_weight = {
@@ -803,10 +793,10 @@ sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
803 return left->stat.weight - right->stat.weight; 793 return left->stat.weight - right->stat.weight;
804} 794}
805 795
806static int hist_entry__global_weight_snprintf(struct hist_entry *self, char *bf, 796static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
807 size_t size, unsigned int width) 797 size_t size, unsigned int width)
808{ 798{
809 return repsep_snprintf(bf, size, "%-*llu", width, self->stat.weight); 799 return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
810} 800}
811 801
812struct sort_entry sort_global_weight = { 802struct sort_entry sort_global_weight = {
@@ -858,6 +848,127 @@ struct sort_entry sort_mem_snoop = {
858 .se_width_idx = HISTC_MEM_SNOOP, 848 .se_width_idx = HISTC_MEM_SNOOP,
859}; 849};
860 850
851static int64_t
852sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
853{
854 return left->branch_info->flags.abort !=
855 right->branch_info->flags.abort;
856}
857
858static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
859 size_t size, unsigned int width)
860{
861 static const char *out = ".";
862
863 if (he->branch_info->flags.abort)
864 out = "A";
865 return repsep_snprintf(bf, size, "%-*s", width, out);
866}
867
868struct sort_entry sort_abort = {
869 .se_header = "Transaction abort",
870 .se_cmp = sort__abort_cmp,
871 .se_snprintf = hist_entry__abort_snprintf,
872 .se_width_idx = HISTC_ABORT,
873};
874
875static int64_t
876sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
877{
878 return left->branch_info->flags.in_tx !=
879 right->branch_info->flags.in_tx;
880}
881
882static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
883 size_t size, unsigned int width)
884{
885 static const char *out = ".";
886
887 if (he->branch_info->flags.in_tx)
888 out = "T";
889
890 return repsep_snprintf(bf, size, "%-*s", width, out);
891}
892
893struct sort_entry sort_in_tx = {
894 .se_header = "Branch in transaction",
895 .se_cmp = sort__in_tx_cmp,
896 .se_snprintf = hist_entry__in_tx_snprintf,
897 .se_width_idx = HISTC_IN_TX,
898};
899
900static int64_t
901sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
902{
903 return left->transaction - right->transaction;
904}
905
906static inline char *add_str(char *p, const char *str)
907{
908 strcpy(p, str);
909 return p + strlen(str);
910}
911
912static struct txbit {
913 unsigned flag;
914 const char *name;
915 int skip_for_len;
916} txbits[] = {
917 { PERF_TXN_ELISION, "EL ", 0 },
918 { PERF_TXN_TRANSACTION, "TX ", 1 },
919 { PERF_TXN_SYNC, "SYNC ", 1 },
920 { PERF_TXN_ASYNC, "ASYNC ", 0 },
921 { PERF_TXN_RETRY, "RETRY ", 0 },
922 { PERF_TXN_CONFLICT, "CON ", 0 },
923 { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
924 { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 },
925 { 0, NULL, 0 }
926};
927
928int hist_entry__transaction_len(void)
929{
930 int i;
931 int len = 0;
932
933 for (i = 0; txbits[i].name; i++) {
934 if (!txbits[i].skip_for_len)
935 len += strlen(txbits[i].name);
936 }
937 len += 4; /* :XX<space> */
938 return len;
939}
940
941static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
942 size_t size, unsigned int width)
943{
944 u64 t = he->transaction;
945 char buf[128];
946 char *p = buf;
947 int i;
948
949 buf[0] = 0;
950 for (i = 0; txbits[i].name; i++)
951 if (txbits[i].flag & t)
952 p = add_str(p, txbits[i].name);
953 if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
954 p = add_str(p, "NEITHER ");
955 if (t & PERF_TXN_ABORT_MASK) {
956 sprintf(p, ":%" PRIx64,
957 (t & PERF_TXN_ABORT_MASK) >>
958 PERF_TXN_ABORT_SHIFT);
959 p += strlen(p);
960 }
961
962 return repsep_snprintf(bf, size, "%-*s", width, buf);
963}
964
965struct sort_entry sort_transaction = {
966 .se_header = "Transaction ",
967 .se_cmp = sort__transaction_cmp,
968 .se_snprintf = hist_entry__transaction_snprintf,
969 .se_width_idx = HISTC_TRANSACTION,
970};
971
861struct sort_dimension { 972struct sort_dimension {
862 const char *name; 973 const char *name;
863 struct sort_entry *entry; 974 struct sort_entry *entry;
@@ -876,6 +987,7 @@ static struct sort_dimension common_sort_dimensions[] = {
876 DIM(SORT_SRCLINE, "srcline", sort_srcline), 987 DIM(SORT_SRCLINE, "srcline", sort_srcline),
877 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), 988 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
878 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), 989 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
990 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
879}; 991};
880 992
881#undef DIM 993#undef DIM
@@ -888,6 +1000,8 @@ static struct sort_dimension bstack_sort_dimensions[] = {
888 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from), 1000 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
889 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to), 1001 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
890 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), 1002 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
1003 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1004 DIM(SORT_ABORT, "abort", sort_abort),
891}; 1005};
892 1006
893#undef DIM 1007#undef DIM
@@ -1009,7 +1123,7 @@ int setup_sorting(void)
1009 return ret; 1123 return ret;
1010} 1124}
1011 1125
1012static void sort_entry__setup_elide(struct sort_entry *self, 1126static void sort_entry__setup_elide(struct sort_entry *se,
1013 struct strlist *list, 1127 struct strlist *list,
1014 const char *list_name, FILE *fp) 1128 const char *list_name, FILE *fp)
1015{ 1129{
@@ -1017,7 +1131,7 @@ static void sort_entry__setup_elide(struct sort_entry *self,
1017 if (fp != NULL) 1131 if (fp != NULL)
1018 fprintf(fp, "# %s: %s\n", list_name, 1132 fprintf(fp, "# %s: %s\n", list_name,
1019 strlist__entry(list, 0)->s); 1133 strlist__entry(list, 0)->s);
1020 self->elide = true; 1134 se->elide = true;
1021 } 1135 }
1022} 1136}
1023 1137
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 4e80dbd271e7..43e5ff42a609 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -22,7 +22,6 @@
22#include "parse-events.h" 22#include "parse-events.h"
23 23
24#include "thread.h" 24#include "thread.h"
25#include "sort.h"
26 25
27extern regex_t parent_regex; 26extern regex_t parent_regex;
28extern const char *sort_order; 27extern const char *sort_order;
@@ -84,7 +83,9 @@ struct hist_entry {
84 struct he_stat stat; 83 struct he_stat stat;
85 struct map_symbol ms; 84 struct map_symbol ms;
86 struct thread *thread; 85 struct thread *thread;
86 struct comm *comm;
87 u64 ip; 87 u64 ip;
88 u64 transaction;
88 s32 cpu; 89 s32 cpu;
89 90
90 struct hist_entry_diff diff; 91 struct hist_entry_diff diff;
@@ -145,6 +146,7 @@ enum sort_type {
145 SORT_SRCLINE, 146 SORT_SRCLINE,
146 SORT_LOCAL_WEIGHT, 147 SORT_LOCAL_WEIGHT,
147 SORT_GLOBAL_WEIGHT, 148 SORT_GLOBAL_WEIGHT,
149 SORT_TRANSACTION,
148 150
149 /* branch stack specific sort keys */ 151 /* branch stack specific sort keys */
150 __SORT_BRANCH_STACK, 152 __SORT_BRANCH_STACK,
@@ -153,6 +155,8 @@ enum sort_type {
153 SORT_SYM_FROM, 155 SORT_SYM_FROM,
154 SORT_SYM_TO, 156 SORT_SYM_TO,
155 SORT_MISPREDICT, 157 SORT_MISPREDICT,
158 SORT_ABORT,
159 SORT_IN_TX,
156 160
157 /* memory mode specific sort keys */ 161 /* memory mode specific sort keys */
158 __SORT_MEMORY_MODE, 162 __SORT_MEMORY_MODE,
@@ -175,7 +179,7 @@ struct sort_entry {
175 179
176 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *); 180 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *);
177 int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *); 181 int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *);
178 int (*se_snprintf)(struct hist_entry *self, char *bf, size_t size, 182 int (*se_snprintf)(struct hist_entry *he, char *bf, size_t size,
179 unsigned int width); 183 unsigned int width);
180 u8 se_width_idx; 184 u8 se_width_idx;
181 bool elide; 185 bool elide;
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
new file mode 100644
index 000000000000..d11aefbc4b8d
--- /dev/null
+++ b/tools/perf/util/srcline.c
@@ -0,0 +1,265 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include <linux/kernel.h>
6
7#include "util/dso.h"
8#include "util/util.h"
9#include "util/debug.h"
10
11#ifdef HAVE_LIBBFD_SUPPORT
12
13/*
14 * Implement addr2line using libbfd.
15 */
16#define PACKAGE "perf"
17#include <bfd.h>
18
19struct a2l_data {
20 const char *input;
21 unsigned long addr;
22
23 bool found;
24 const char *filename;
25 const char *funcname;
26 unsigned line;
27
28 bfd *abfd;
29 asymbol **syms;
30};
31
32static int bfd_error(const char *string)
33{
34 const char *errmsg;
35
36 errmsg = bfd_errmsg(bfd_get_error());
37 fflush(stdout);
38
39 if (string)
40 pr_debug("%s: %s\n", string, errmsg);
41 else
42 pr_debug("%s\n", errmsg);
43
44 return -1;
45}
46
47static int slurp_symtab(bfd *abfd, struct a2l_data *a2l)
48{
49 long storage;
50 long symcount;
51 asymbol **syms;
52 bfd_boolean dynamic = FALSE;
53
54 if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
55 return bfd_error(bfd_get_filename(abfd));
56
57 storage = bfd_get_symtab_upper_bound(abfd);
58 if (storage == 0L) {
59 storage = bfd_get_dynamic_symtab_upper_bound(abfd);
60 dynamic = TRUE;
61 }
62 if (storage < 0L)
63 return bfd_error(bfd_get_filename(abfd));
64
65 syms = malloc(storage);
66 if (dynamic)
67 symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
68 else
69 symcount = bfd_canonicalize_symtab(abfd, syms);
70
71 if (symcount < 0) {
72 free(syms);
73 return bfd_error(bfd_get_filename(abfd));
74 }
75
76 a2l->syms = syms;
77 return 0;
78}
79
80static void find_address_in_section(bfd *abfd, asection *section, void *data)
81{
82 bfd_vma pc, vma;
83 bfd_size_type size;
84 struct a2l_data *a2l = data;
85
86 if (a2l->found)
87 return;
88
89 if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
90 return;
91
92 pc = a2l->addr;
93 vma = bfd_get_section_vma(abfd, section);
94 size = bfd_get_section_size(section);
95
96 if (pc < vma || pc >= vma + size)
97 return;
98
99 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
100 &a2l->filename, &a2l->funcname,
101 &a2l->line);
102}
103
104static struct a2l_data *addr2line_init(const char *path)
105{
106 bfd *abfd;
107 struct a2l_data *a2l = NULL;
108
109 abfd = bfd_openr(path, NULL);
110 if (abfd == NULL)
111 return NULL;
112
113 if (!bfd_check_format(abfd, bfd_object))
114 goto out;
115
116 a2l = zalloc(sizeof(*a2l));
117 if (a2l == NULL)
118 goto out;
119
120 a2l->abfd = abfd;
121 a2l->input = strdup(path);
122 if (a2l->input == NULL)
123 goto out;
124
125 if (slurp_symtab(abfd, a2l))
126 goto out;
127
128 return a2l;
129
130out:
131 if (a2l) {
132 free((void *)a2l->input);
133 free(a2l);
134 }
135 bfd_close(abfd);
136 return NULL;
137}
138
139static void addr2line_cleanup(struct a2l_data *a2l)
140{
141 if (a2l->abfd)
142 bfd_close(a2l->abfd);
143 free((void *)a2l->input);
144 free(a2l->syms);
145 free(a2l);
146}
147
148static int addr2line(const char *dso_name, unsigned long addr,
149 char **file, unsigned int *line)
150{
151 int ret = 0;
152 struct a2l_data *a2l;
153
154 a2l = addr2line_init(dso_name);
155 if (a2l == NULL) {
156 pr_warning("addr2line_init failed for %s\n", dso_name);
157 return 0;
158 }
159
160 a2l->addr = addr;
161 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
162
163 if (a2l->found && a2l->filename) {
164 *file = strdup(a2l->filename);
165 *line = a2l->line;
166
167 if (*file)
168 ret = 1;
169 }
170
171 addr2line_cleanup(a2l);
172 return ret;
173}
174
175#else /* HAVE_LIBBFD_SUPPORT */
176
177static int addr2line(const char *dso_name, unsigned long addr,
178 char **file, unsigned int *line_nr)
179{
180 FILE *fp;
181 char cmd[PATH_MAX];
182 char *filename = NULL;
183 size_t len;
184 char *sep;
185 int ret = 0;
186
187 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
188 dso_name, addr);
189
190 fp = popen(cmd, "r");
191 if (fp == NULL) {
192 pr_warning("popen failed for %s\n", dso_name);
193 return 0;
194 }
195
196 if (getline(&filename, &len, fp) < 0 || !len) {
197 pr_warning("addr2line has no output for %s\n", dso_name);
198 goto out;
199 }
200
201 sep = strchr(filename, '\n');
202 if (sep)
203 *sep = '\0';
204
205 if (!strcmp(filename, "??:0")) {
206 pr_debug("no debugging info in %s\n", dso_name);
207 free(filename);
208 goto out;
209 }
210
211 sep = strchr(filename, ':');
212 if (sep) {
213 *sep++ = '\0';
214 *file = filename;
215 *line_nr = strtoul(sep, NULL, 0);
216 ret = 1;
217 }
218out:
219 pclose(fp);
220 return ret;
221}
222#endif /* HAVE_LIBBFD_SUPPORT */
223
224char *get_srcline(struct dso *dso, unsigned long addr)
225{
226 char *file = NULL;
227 unsigned line = 0;
228 char *srcline;
229 char *dso_name = dso->long_name;
230 size_t size;
231
232 if (!dso->has_srcline)
233 return SRCLINE_UNKNOWN;
234
235 if (dso_name[0] == '[')
236 goto out;
237
238 if (!strncmp(dso_name, "/tmp/perf-", 10))
239 goto out;
240
241 if (!addr2line(dso_name, addr, &file, &line))
242 goto out;
243
244 /* just calculate actual length */
245 size = snprintf(NULL, 0, "%s:%u", file, line) + 1;
246
247 srcline = malloc(size);
248 if (srcline)
249 snprintf(srcline, size, "%s:%u", file, line);
250 else
251 srcline = SRCLINE_UNKNOWN;
252
253 free(file);
254 return srcline;
255
256out:
257 dso->has_srcline = 0;
258 return SRCLINE_UNKNOWN;
259}
260
261void free_srcline(char *srcline)
262{
263 if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
264 free(srcline);
265}
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index 834c8ebfe38e..3edd0538161f 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -10,22 +10,22 @@ static const char *OP_not = "!"; /* Logical NOT */
10#define is_operator(c) ((c) == '|' || (c) == '&' || (c) == '!') 10#define is_operator(c) ((c) == '|' || (c) == '&' || (c) == '!')
11#define is_separator(c) (is_operator(c) || (c) == '(' || (c) == ')') 11#define is_separator(c) (is_operator(c) || (c) == '(' || (c) == ')')
12 12
13static void strfilter_node__delete(struct strfilter_node *self) 13static void strfilter_node__delete(struct strfilter_node *node)
14{ 14{
15 if (self) { 15 if (node) {
16 if (self->p && !is_operator(*self->p)) 16 if (node->p && !is_operator(*node->p))
17 free((char *)self->p); 17 free((char *)node->p);
18 strfilter_node__delete(self->l); 18 strfilter_node__delete(node->l);
19 strfilter_node__delete(self->r); 19 strfilter_node__delete(node->r);
20 free(self); 20 free(node);
21 } 21 }
22} 22}
23 23
24void strfilter__delete(struct strfilter *self) 24void strfilter__delete(struct strfilter *filter)
25{ 25{
26 if (self) { 26 if (filter) {
27 strfilter_node__delete(self->root); 27 strfilter_node__delete(filter->root);
28 free(self); 28 free(filter);
29 } 29 }
30} 30}
31 31
@@ -62,15 +62,15 @@ static struct strfilter_node *strfilter_node__alloc(const char *op,
62 struct strfilter_node *l, 62 struct strfilter_node *l,
63 struct strfilter_node *r) 63 struct strfilter_node *r)
64{ 64{
65 struct strfilter_node *ret = zalloc(sizeof(struct strfilter_node)); 65 struct strfilter_node *node = zalloc(sizeof(*node));
66 66
67 if (ret) { 67 if (node) {
68 ret->p = op; 68 node->p = op;
69 ret->l = l; 69 node->l = l;
70 ret->r = r; 70 node->r = r;
71 } 71 }
72 72
73 return ret; 73 return node;
74} 74}
75 75
76static struct strfilter_node *strfilter_node__new(const char *s, 76static struct strfilter_node *strfilter_node__new(const char *s,
@@ -154,46 +154,46 @@ error:
154 */ 154 */
155struct strfilter *strfilter__new(const char *rules, const char **err) 155struct strfilter *strfilter__new(const char *rules, const char **err)
156{ 156{
157 struct strfilter *ret = zalloc(sizeof(struct strfilter)); 157 struct strfilter *filter = zalloc(sizeof(*filter));
158 const char *ep = NULL; 158 const char *ep = NULL;
159 159
160 if (ret) 160 if (filter)
161 ret->root = strfilter_node__new(rules, &ep); 161 filter->root = strfilter_node__new(rules, &ep);
162 162
163 if (!ret || !ret->root || *ep != '\0') { 163 if (!filter || !filter->root || *ep != '\0') {
164 if (err) 164 if (err)
165 *err = ep; 165 *err = ep;
166 strfilter__delete(ret); 166 strfilter__delete(filter);
167 ret = NULL; 167 filter = NULL;
168 } 168 }
169 169
170 return ret; 170 return filter;
171} 171}
172 172
173static bool strfilter_node__compare(struct strfilter_node *self, 173static bool strfilter_node__compare(struct strfilter_node *node,
174 const char *str) 174 const char *str)
175{ 175{
176 if (!self || !self->p) 176 if (!node || !node->p)
177 return false; 177 return false;
178 178
179 switch (*self->p) { 179 switch (*node->p) {
180 case '|': /* OR */ 180 case '|': /* OR */
181 return strfilter_node__compare(self->l, str) || 181 return strfilter_node__compare(node->l, str) ||
182 strfilter_node__compare(self->r, str); 182 strfilter_node__compare(node->r, str);
183 case '&': /* AND */ 183 case '&': /* AND */
184 return strfilter_node__compare(self->l, str) && 184 return strfilter_node__compare(node->l, str) &&
185 strfilter_node__compare(self->r, str); 185 strfilter_node__compare(node->r, str);
186 case '!': /* NOT */ 186 case '!': /* NOT */
187 return !strfilter_node__compare(self->r, str); 187 return !strfilter_node__compare(node->r, str);
188 default: 188 default:
189 return strglobmatch(str, self->p); 189 return strglobmatch(str, node->p);
190 } 190 }
191} 191}
192 192
193/* Return true if STR matches the filter rules */ 193/* Return true if STR matches the filter rules */
194bool strfilter__compare(struct strfilter *self, const char *str) 194bool strfilter__compare(struct strfilter *filter, const char *str)
195{ 195{
196 if (!self) 196 if (!filter)
197 return false; 197 return false;
198 return strfilter_node__compare(self->root, str); 198 return strfilter_node__compare(filter->root, str);
199} 199}
diff --git a/tools/perf/util/strfilter.h b/tools/perf/util/strfilter.h
index 00f58a7506de..fe611f3c9e39 100644
--- a/tools/perf/util/strfilter.h
+++ b/tools/perf/util/strfilter.h
@@ -30,19 +30,19 @@ struct strfilter *strfilter__new(const char *rules, const char **err);
30 30
31/** 31/**
32 * strfilter__compare - compare given string and a string filter 32 * strfilter__compare - compare given string and a string filter
33 * @self: String filter 33 * @filter: String filter
34 * @str: target string 34 * @str: target string
35 * 35 *
36 * Compare @str and @self. Return true if the str match the rule 36 * Compare @str and @filter. Return true if the str match the rule
37 */ 37 */
38bool strfilter__compare(struct strfilter *self, const char *str); 38bool strfilter__compare(struct strfilter *filter, const char *str);
39 39
40/** 40/**
41 * strfilter__delete - delete a string filter 41 * strfilter__delete - delete a string filter
42 * @self: String filter to delete 42 * @filter: String filter to delete
43 * 43 *
44 * Delete @self. 44 * Delete @filter.
45 */ 45 */
46void strfilter__delete(struct strfilter *self); 46void strfilter__delete(struct strfilter *filter);
47 47
48#endif 48#endif
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index a9c829be5216..eed0b96302af 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -8,7 +8,7 @@
8#include "symbol.h" 8#include "symbol.h"
9#include "debug.h" 9#include "debug.h"
10 10
11#ifndef HAVE_ELF_GETPHDRNUM 11#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
12static int elf_getphdrnum(Elf *elf, size_t *dst) 12static int elf_getphdrnum(Elf *elf, size_t *dst)
13{ 13{
14 GElf_Ehdr gehdr; 14 GElf_Ehdr gehdr;
@@ -487,27 +487,27 @@ int filename__read_debuglink(const char *filename, char *debuglink,
487 487
488 ek = elf_kind(elf); 488 ek = elf_kind(elf);
489 if (ek != ELF_K_ELF) 489 if (ek != ELF_K_ELF)
490 goto out_close; 490 goto out_elf_end;
491 491
492 if (gelf_getehdr(elf, &ehdr) == NULL) { 492 if (gelf_getehdr(elf, &ehdr) == NULL) {
493 pr_err("%s: cannot get elf header.\n", __func__); 493 pr_err("%s: cannot get elf header.\n", __func__);
494 goto out_close; 494 goto out_elf_end;
495 } 495 }
496 496
497 sec = elf_section_by_name(elf, &ehdr, &shdr, 497 sec = elf_section_by_name(elf, &ehdr, &shdr,
498 ".gnu_debuglink", NULL); 498 ".gnu_debuglink", NULL);
499 if (sec == NULL) 499 if (sec == NULL)
500 goto out_close; 500 goto out_elf_end;
501 501
502 data = elf_getdata(sec, NULL); 502 data = elf_getdata(sec, NULL);
503 if (data == NULL) 503 if (data == NULL)
504 goto out_close; 504 goto out_elf_end;
505 505
506 /* the start of this section is a zero-terminated string */ 506 /* the start of this section is a zero-terminated string */
507 strncpy(debuglink, data->d_buf, size); 507 strncpy(debuglink, data->d_buf, size);
508 508
509out_elf_end:
509 elf_end(elf); 510 elf_end(elf);
510
511out_close: 511out_close:
512 close(fd); 512 close(fd);
513out: 513out:
@@ -1018,6 +1018,601 @@ int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
1018 return err; 1018 return err;
1019} 1019}
1020 1020
1021static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len)
1022{
1023 ssize_t r;
1024 size_t n;
1025 int err = -1;
1026 char *buf = malloc(page_size);
1027
1028 if (buf == NULL)
1029 return -1;
1030
1031 if (lseek(to, to_offs, SEEK_SET) != to_offs)
1032 goto out;
1033
1034 if (lseek(from, from_offs, SEEK_SET) != from_offs)
1035 goto out;
1036
1037 while (len) {
1038 n = page_size;
1039 if (len < n)
1040 n = len;
1041 /* Use read because mmap won't work on proc files */
1042 r = read(from, buf, n);
1043 if (r < 0)
1044 goto out;
1045 if (!r)
1046 break;
1047 n = r;
1048 r = write(to, buf, n);
1049 if (r < 0)
1050 goto out;
1051 if ((size_t)r != n)
1052 goto out;
1053 len -= n;
1054 }
1055
1056 err = 0;
1057out:
1058 free(buf);
1059 return err;
1060}
1061
1062struct kcore {
1063 int fd;
1064 int elfclass;
1065 Elf *elf;
1066 GElf_Ehdr ehdr;
1067};
1068
1069static int kcore__open(struct kcore *kcore, const char *filename)
1070{
1071 GElf_Ehdr *ehdr;
1072
1073 kcore->fd = open(filename, O_RDONLY);
1074 if (kcore->fd == -1)
1075 return -1;
1076
1077 kcore->elf = elf_begin(kcore->fd, ELF_C_READ, NULL);
1078 if (!kcore->elf)
1079 goto out_close;
1080
1081 kcore->elfclass = gelf_getclass(kcore->elf);
1082 if (kcore->elfclass == ELFCLASSNONE)
1083 goto out_end;
1084
1085 ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
1086 if (!ehdr)
1087 goto out_end;
1088
1089 return 0;
1090
1091out_end:
1092 elf_end(kcore->elf);
1093out_close:
1094 close(kcore->fd);
1095 return -1;
1096}
1097
1098static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
1099 bool temp)
1100{
1101 GElf_Ehdr *ehdr;
1102
1103 kcore->elfclass = elfclass;
1104
1105 if (temp)
1106 kcore->fd = mkstemp(filename);
1107 else
1108 kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400);
1109 if (kcore->fd == -1)
1110 return -1;
1111
1112 kcore->elf = elf_begin(kcore->fd, ELF_C_WRITE, NULL);
1113 if (!kcore->elf)
1114 goto out_close;
1115
1116 if (!gelf_newehdr(kcore->elf, elfclass))
1117 goto out_end;
1118
1119 ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
1120 if (!ehdr)
1121 goto out_end;
1122
1123 return 0;
1124
1125out_end:
1126 elf_end(kcore->elf);
1127out_close:
1128 close(kcore->fd);
1129 unlink(filename);
1130 return -1;
1131}
1132
1133static void kcore__close(struct kcore *kcore)
1134{
1135 elf_end(kcore->elf);
1136 close(kcore->fd);
1137}
1138
1139static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count)
1140{
1141 GElf_Ehdr *ehdr = &to->ehdr;
1142 GElf_Ehdr *kehdr = &from->ehdr;
1143
1144 memcpy(ehdr->e_ident, kehdr->e_ident, EI_NIDENT);
1145 ehdr->e_type = kehdr->e_type;
1146 ehdr->e_machine = kehdr->e_machine;
1147 ehdr->e_version = kehdr->e_version;
1148 ehdr->e_entry = 0;
1149 ehdr->e_shoff = 0;
1150 ehdr->e_flags = kehdr->e_flags;
1151 ehdr->e_phnum = count;
1152 ehdr->e_shentsize = 0;
1153 ehdr->e_shnum = 0;
1154 ehdr->e_shstrndx = 0;
1155
1156 if (from->elfclass == ELFCLASS32) {
1157 ehdr->e_phoff = sizeof(Elf32_Ehdr);
1158 ehdr->e_ehsize = sizeof(Elf32_Ehdr);
1159 ehdr->e_phentsize = sizeof(Elf32_Phdr);
1160 } else {
1161 ehdr->e_phoff = sizeof(Elf64_Ehdr);
1162 ehdr->e_ehsize = sizeof(Elf64_Ehdr);
1163 ehdr->e_phentsize = sizeof(Elf64_Phdr);
1164 }
1165
1166 if (!gelf_update_ehdr(to->elf, ehdr))
1167 return -1;
1168
1169 if (!gelf_newphdr(to->elf, count))
1170 return -1;
1171
1172 return 0;
1173}
1174
1175static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset,
1176 u64 addr, u64 len)
1177{
1178 GElf_Phdr gphdr;
1179 GElf_Phdr *phdr;
1180
1181 phdr = gelf_getphdr(kcore->elf, idx, &gphdr);
1182 if (!phdr)
1183 return -1;
1184
1185 phdr->p_type = PT_LOAD;
1186 phdr->p_flags = PF_R | PF_W | PF_X;
1187 phdr->p_offset = offset;
1188 phdr->p_vaddr = addr;
1189 phdr->p_paddr = 0;
1190 phdr->p_filesz = len;
1191 phdr->p_memsz = len;
1192 phdr->p_align = page_size;
1193
1194 if (!gelf_update_phdr(kcore->elf, idx, phdr))
1195 return -1;
1196
1197 return 0;
1198}
1199
1200static off_t kcore__write(struct kcore *kcore)
1201{
1202 return elf_update(kcore->elf, ELF_C_WRITE);
1203}
1204
1205struct phdr_data {
1206 off_t offset;
1207 u64 addr;
1208 u64 len;
1209};
1210
1211struct kcore_copy_info {
1212 u64 stext;
1213 u64 etext;
1214 u64 first_symbol;
1215 u64 last_symbol;
1216 u64 first_module;
1217 u64 last_module_symbol;
1218 struct phdr_data kernel_map;
1219 struct phdr_data modules_map;
1220};
1221
1222static int kcore_copy__process_kallsyms(void *arg, const char *name, char type,
1223 u64 start)
1224{
1225 struct kcore_copy_info *kci = arg;
1226
1227 if (!symbol_type__is_a(type, MAP__FUNCTION))
1228 return 0;
1229
1230 if (strchr(name, '[')) {
1231 if (start > kci->last_module_symbol)
1232 kci->last_module_symbol = start;
1233 return 0;
1234 }
1235
1236 if (!kci->first_symbol || start < kci->first_symbol)
1237 kci->first_symbol = start;
1238
1239 if (!kci->last_symbol || start > kci->last_symbol)
1240 kci->last_symbol = start;
1241
1242 if (!strcmp(name, "_stext")) {
1243 kci->stext = start;
1244 return 0;
1245 }
1246
1247 if (!strcmp(name, "_etext")) {
1248 kci->etext = start;
1249 return 0;
1250 }
1251
1252 return 0;
1253}
1254
1255static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci,
1256 const char *dir)
1257{
1258 char kallsyms_filename[PATH_MAX];
1259
1260 scnprintf(kallsyms_filename, PATH_MAX, "%s/kallsyms", dir);
1261
1262 if (symbol__restricted_filename(kallsyms_filename, "/proc/kallsyms"))
1263 return -1;
1264
1265 if (kallsyms__parse(kallsyms_filename, kci,
1266 kcore_copy__process_kallsyms) < 0)
1267 return -1;
1268
1269 return 0;
1270}
1271
1272static int kcore_copy__process_modules(void *arg,
1273 const char *name __maybe_unused,
1274 u64 start)
1275{
1276 struct kcore_copy_info *kci = arg;
1277
1278 if (!kci->first_module || start < kci->first_module)
1279 kci->first_module = start;
1280
1281 return 0;
1282}
1283
1284static int kcore_copy__parse_modules(struct kcore_copy_info *kci,
1285 const char *dir)
1286{
1287 char modules_filename[PATH_MAX];
1288
1289 scnprintf(modules_filename, PATH_MAX, "%s/modules", dir);
1290
1291 if (symbol__restricted_filename(modules_filename, "/proc/modules"))
1292 return -1;
1293
1294 if (modules__parse(modules_filename, kci,
1295 kcore_copy__process_modules) < 0)
1296 return -1;
1297
1298 return 0;
1299}
1300
1301static void kcore_copy__map(struct phdr_data *p, u64 start, u64 end, u64 pgoff,
1302 u64 s, u64 e)
1303{
1304 if (p->addr || s < start || s >= end)
1305 return;
1306
1307 p->addr = s;
1308 p->offset = (s - start) + pgoff;
1309 p->len = e < end ? e - s : end - s;
1310}
1311
1312static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data)
1313{
1314 struct kcore_copy_info *kci = data;
1315 u64 end = start + len;
1316
1317 kcore_copy__map(&kci->kernel_map, start, end, pgoff, kci->stext,
1318 kci->etext);
1319
1320 kcore_copy__map(&kci->modules_map, start, end, pgoff, kci->first_module,
1321 kci->last_module_symbol);
1322
1323 return 0;
1324}
1325
1326static int kcore_copy__read_maps(struct kcore_copy_info *kci, Elf *elf)
1327{
1328 if (elf_read_maps(elf, true, kcore_copy__read_map, kci) < 0)
1329 return -1;
1330
1331 return 0;
1332}
1333
1334static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir,
1335 Elf *elf)
1336{
1337 if (kcore_copy__parse_kallsyms(kci, dir))
1338 return -1;
1339
1340 if (kcore_copy__parse_modules(kci, dir))
1341 return -1;
1342
1343 if (kci->stext)
1344 kci->stext = round_down(kci->stext, page_size);
1345 else
1346 kci->stext = round_down(kci->first_symbol, page_size);
1347
1348 if (kci->etext) {
1349 kci->etext = round_up(kci->etext, page_size);
1350 } else if (kci->last_symbol) {
1351 kci->etext = round_up(kci->last_symbol, page_size);
1352 kci->etext += page_size;
1353 }
1354
1355 kci->first_module = round_down(kci->first_module, page_size);
1356
1357 if (kci->last_module_symbol) {
1358 kci->last_module_symbol = round_up(kci->last_module_symbol,
1359 page_size);
1360 kci->last_module_symbol += page_size;
1361 }
1362
1363 if (!kci->stext || !kci->etext)
1364 return -1;
1365
1366 if (kci->first_module && !kci->last_module_symbol)
1367 return -1;
1368
1369 return kcore_copy__read_maps(kci, elf);
1370}
1371
1372static int kcore_copy__copy_file(const char *from_dir, const char *to_dir,
1373 const char *name)
1374{
1375 char from_filename[PATH_MAX];
1376 char to_filename[PATH_MAX];
1377
1378 scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
1379 scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
1380
1381 return copyfile_mode(from_filename, to_filename, 0400);
1382}
1383
1384static int kcore_copy__unlink(const char *dir, const char *name)
1385{
1386 char filename[PATH_MAX];
1387
1388 scnprintf(filename, PATH_MAX, "%s/%s", dir, name);
1389
1390 return unlink(filename);
1391}
1392
1393static int kcore_copy__compare_fds(int from, int to)
1394{
1395 char *buf_from;
1396 char *buf_to;
1397 ssize_t ret;
1398 size_t len;
1399 int err = -1;
1400
1401 buf_from = malloc(page_size);
1402 buf_to = malloc(page_size);
1403 if (!buf_from || !buf_to)
1404 goto out;
1405
1406 while (1) {
1407 /* Use read because mmap won't work on proc files */
1408 ret = read(from, buf_from, page_size);
1409 if (ret < 0)
1410 goto out;
1411
1412 if (!ret)
1413 break;
1414
1415 len = ret;
1416
1417 if (readn(to, buf_to, len) != (int)len)
1418 goto out;
1419
1420 if (memcmp(buf_from, buf_to, len))
1421 goto out;
1422 }
1423
1424 err = 0;
1425out:
1426 free(buf_to);
1427 free(buf_from);
1428 return err;
1429}
1430
1431static int kcore_copy__compare_files(const char *from_filename,
1432 const char *to_filename)
1433{
1434 int from, to, err = -1;
1435
1436 from = open(from_filename, O_RDONLY);
1437 if (from < 0)
1438 return -1;
1439
1440 to = open(to_filename, O_RDONLY);
1441 if (to < 0)
1442 goto out_close_from;
1443
1444 err = kcore_copy__compare_fds(from, to);
1445
1446 close(to);
1447out_close_from:
1448 close(from);
1449 return err;
1450}
1451
1452static int kcore_copy__compare_file(const char *from_dir, const char *to_dir,
1453 const char *name)
1454{
1455 char from_filename[PATH_MAX];
1456 char to_filename[PATH_MAX];
1457
1458 scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
1459 scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
1460
1461 return kcore_copy__compare_files(from_filename, to_filename);
1462}
1463
1464/**
1465 * kcore_copy - copy kallsyms, modules and kcore from one directory to another.
1466 * @from_dir: from directory
1467 * @to_dir: to directory
1468 *
1469 * This function copies kallsyms, modules and kcore files from one directory to
1470 * another. kallsyms and modules are copied entirely. Only code segments are
1471 * copied from kcore. It is assumed that two segments suffice: one for the
1472 * kernel proper and one for all the modules. The code segments are determined
1473 * from kallsyms and modules files. The kernel map starts at _stext or the
1474 * lowest function symbol, and ends at _etext or the highest function symbol.
1475 * The module map starts at the lowest module address and ends at the highest
1476 * module symbol. Start addresses are rounded down to the nearest page. End
1477 * addresses are rounded up to the nearest page. An extra page is added to the
1478 * highest kernel symbol and highest module symbol to, hopefully, encompass that
1479 * symbol too. Because it contains only code sections, the resulting kcore is
1480 * unusual. One significant peculiarity is that the mapping (start -> pgoff)
1481 * is not the same for the kernel map and the modules map. That happens because
1482 * the data is copied adjacently whereas the original kcore has gaps. Finally,
1483 * kallsyms and modules files are compared with their copies to check that
1484 * modules have not been loaded or unloaded while the copies were taking place.
1485 *
1486 * Return: %0 on success, %-1 on failure.
1487 */
1488int kcore_copy(const char *from_dir, const char *to_dir)
1489{
1490 struct kcore kcore;
1491 struct kcore extract;
1492 size_t count = 2;
1493 int idx = 0, err = -1;
1494 off_t offset = page_size, sz, modules_offset = 0;
1495 struct kcore_copy_info kci = { .stext = 0, };
1496 char kcore_filename[PATH_MAX];
1497 char extract_filename[PATH_MAX];
1498
1499 if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms"))
1500 return -1;
1501
1502 if (kcore_copy__copy_file(from_dir, to_dir, "modules"))
1503 goto out_unlink_kallsyms;
1504
1505 scnprintf(kcore_filename, PATH_MAX, "%s/kcore", from_dir);
1506 scnprintf(extract_filename, PATH_MAX, "%s/kcore", to_dir);
1507
1508 if (kcore__open(&kcore, kcore_filename))
1509 goto out_unlink_modules;
1510
1511 if (kcore_copy__calc_maps(&kci, from_dir, kcore.elf))
1512 goto out_kcore_close;
1513
1514 if (kcore__init(&extract, extract_filename, kcore.elfclass, false))
1515 goto out_kcore_close;
1516
1517 if (!kci.modules_map.addr)
1518 count -= 1;
1519
1520 if (kcore__copy_hdr(&kcore, &extract, count))
1521 goto out_extract_close;
1522
1523 if (kcore__add_phdr(&extract, idx++, offset, kci.kernel_map.addr,
1524 kci.kernel_map.len))
1525 goto out_extract_close;
1526
1527 if (kci.modules_map.addr) {
1528 modules_offset = offset + kci.kernel_map.len;
1529 if (kcore__add_phdr(&extract, idx, modules_offset,
1530 kci.modules_map.addr, kci.modules_map.len))
1531 goto out_extract_close;
1532 }
1533
1534 sz = kcore__write(&extract);
1535 if (sz < 0 || sz > offset)
1536 goto out_extract_close;
1537
1538 if (copy_bytes(kcore.fd, kci.kernel_map.offset, extract.fd, offset,
1539 kci.kernel_map.len))
1540 goto out_extract_close;
1541
1542 if (modules_offset && copy_bytes(kcore.fd, kci.modules_map.offset,
1543 extract.fd, modules_offset,
1544 kci.modules_map.len))
1545 goto out_extract_close;
1546
1547 if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
1548 goto out_extract_close;
1549
1550 if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms"))
1551 goto out_extract_close;
1552
1553 err = 0;
1554
1555out_extract_close:
1556 kcore__close(&extract);
1557 if (err)
1558 unlink(extract_filename);
1559out_kcore_close:
1560 kcore__close(&kcore);
1561out_unlink_modules:
1562 if (err)
1563 kcore_copy__unlink(to_dir, "modules");
1564out_unlink_kallsyms:
1565 if (err)
1566 kcore_copy__unlink(to_dir, "kallsyms");
1567
1568 return err;
1569}
1570
1571int kcore_extract__create(struct kcore_extract *kce)
1572{
1573 struct kcore kcore;
1574 struct kcore extract;
1575 size_t count = 1;
1576 int idx = 0, err = -1;
1577 off_t offset = page_size, sz;
1578
1579 if (kcore__open(&kcore, kce->kcore_filename))
1580 return -1;
1581
1582 strcpy(kce->extract_filename, PERF_KCORE_EXTRACT);
1583 if (kcore__init(&extract, kce->extract_filename, kcore.elfclass, true))
1584 goto out_kcore_close;
1585
1586 if (kcore__copy_hdr(&kcore, &extract, count))
1587 goto out_extract_close;
1588
1589 if (kcore__add_phdr(&extract, idx, offset, kce->addr, kce->len))
1590 goto out_extract_close;
1591
1592 sz = kcore__write(&extract);
1593 if (sz < 0 || sz > offset)
1594 goto out_extract_close;
1595
1596 if (copy_bytes(kcore.fd, kce->offs, extract.fd, offset, kce->len))
1597 goto out_extract_close;
1598
1599 err = 0;
1600
1601out_extract_close:
1602 kcore__close(&extract);
1603 if (err)
1604 unlink(kce->extract_filename);
1605out_kcore_close:
1606 kcore__close(&kcore);
1607
1608 return err;
1609}
1610
1611void kcore_extract__delete(struct kcore_extract *kce)
1612{
1613 unlink(kce->extract_filename);
1614}
1615
1021void symbol__elf_init(void) 1616void symbol__elf_init(void)
1022{ 1617{
1023 elf_version(EV_CURRENT); 1618 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 3a802c300fc5..2d2dd0532b5a 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -308,6 +308,21 @@ int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
308 return -1; 308 return -1;
309} 309}
310 310
311int kcore_extract__create(struct kcore_extract *kce __maybe_unused)
312{
313 return -1;
314}
315
316void kcore_extract__delete(struct kcore_extract *kce __maybe_unused)
317{
318}
319
320int kcore_copy(const char *from_dir __maybe_unused,
321 const char *to_dir __maybe_unused)
322{
323 return -1;
324}
325
311void symbol__elf_init(void) 326void symbol__elf_init(void)
312{ 327{
313} 328}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 7eb0362f4ffd..c0c36965fff0 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -51,6 +51,7 @@ static enum dso_binary_type binary_type_symtab[] = {
51 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 51 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
52 DSO_BINARY_TYPE__GUEST_KMODULE, 52 DSO_BINARY_TYPE__GUEST_KMODULE,
53 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 53 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
54 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
54 DSO_BINARY_TYPE__NOT_FOUND, 55 DSO_BINARY_TYPE__NOT_FOUND,
55}; 56};
56 57
@@ -159,10 +160,12 @@ again:
159 160
160 if (choose_best_symbol(curr, next) == SYMBOL_A) { 161 if (choose_best_symbol(curr, next) == SYMBOL_A) {
161 rb_erase(&next->rb_node, symbols); 162 rb_erase(&next->rb_node, symbols);
163 symbol__delete(next);
162 goto again; 164 goto again;
163 } else { 165 } else {
164 nd = rb_next(&curr->rb_node); 166 nd = rb_next(&curr->rb_node);
165 rb_erase(&curr->rb_node, symbols); 167 rb_erase(&curr->rb_node, symbols);
168 symbol__delete(curr);
166 } 169 }
167 } 170 }
168} 171}
@@ -499,6 +502,64 @@ out_failure:
499 return -1; 502 return -1;
500} 503}
501 504
505int modules__parse(const char *filename, void *arg,
506 int (*process_module)(void *arg, const char *name,
507 u64 start))
508{
509 char *line = NULL;
510 size_t n;
511 FILE *file;
512 int err = 0;
513
514 file = fopen(filename, "r");
515 if (file == NULL)
516 return -1;
517
518 while (1) {
519 char name[PATH_MAX];
520 u64 start;
521 char *sep;
522 ssize_t line_len;
523
524 line_len = getline(&line, &n, file);
525 if (line_len < 0) {
526 if (feof(file))
527 break;
528 err = -1;
529 goto out;
530 }
531
532 if (!line) {
533 err = -1;
534 goto out;
535 }
536
537 line[--line_len] = '\0'; /* \n */
538
539 sep = strrchr(line, 'x');
540 if (sep == NULL)
541 continue;
542
543 hex2u64(sep + 1, &start);
544
545 sep = strchr(line, ' ');
546 if (sep == NULL)
547 continue;
548
549 *sep = '\0';
550
551 scnprintf(name, sizeof(name), "[%s]", line);
552
553 err = process_module(arg, name, start);
554 if (err)
555 break;
556 }
557out:
558 free(line);
559 fclose(file);
560 return err;
561}
562
502struct process_kallsyms_args { 563struct process_kallsyms_args {
503 struct map *map; 564 struct map *map;
504 struct dso *dso; 565 struct dso *dso;
@@ -739,51 +800,242 @@ bool symbol__restricted_filename(const char *filename,
739 return restricted; 800 return restricted;
740} 801}
741 802
742struct kcore_mapfn_data { 803struct module_info {
743 struct dso *dso; 804 struct rb_node rb_node;
744 enum map_type type; 805 char *name;
745 struct list_head maps; 806 u64 start;
746}; 807};
747 808
748static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) 809static void add_module(struct module_info *mi, struct rb_root *modules)
749{ 810{
750 struct kcore_mapfn_data *md = data; 811 struct rb_node **p = &modules->rb_node;
751 struct map *map; 812 struct rb_node *parent = NULL;
813 struct module_info *m;
752 814
753 map = map__new2(start, md->dso, md->type); 815 while (*p != NULL) {
754 if (map == NULL) 816 parent = *p;
817 m = rb_entry(parent, struct module_info, rb_node);
818 if (strcmp(mi->name, m->name) < 0)
819 p = &(*p)->rb_left;
820 else
821 p = &(*p)->rb_right;
822 }
823 rb_link_node(&mi->rb_node, parent, p);
824 rb_insert_color(&mi->rb_node, modules);
825}
826
827static void delete_modules(struct rb_root *modules)
828{
829 struct module_info *mi;
830 struct rb_node *next = rb_first(modules);
831
832 while (next) {
833 mi = rb_entry(next, struct module_info, rb_node);
834 next = rb_next(&mi->rb_node);
835 rb_erase(&mi->rb_node, modules);
836 free(mi->name);
837 free(mi);
838 }
839}
840
841static struct module_info *find_module(const char *name,
842 struct rb_root *modules)
843{
844 struct rb_node *n = modules->rb_node;
845
846 while (n) {
847 struct module_info *m;
848 int cmp;
849
850 m = rb_entry(n, struct module_info, rb_node);
851 cmp = strcmp(name, m->name);
852 if (cmp < 0)
853 n = n->rb_left;
854 else if (cmp > 0)
855 n = n->rb_right;
856 else
857 return m;
858 }
859
860 return NULL;
861}
862
863static int __read_proc_modules(void *arg, const char *name, u64 start)
864{
865 struct rb_root *modules = arg;
866 struct module_info *mi;
867
868 mi = zalloc(sizeof(struct module_info));
869 if (!mi)
755 return -ENOMEM; 870 return -ENOMEM;
756 871
757 map->end = map->start + len; 872 mi->name = strdup(name);
758 map->pgoff = pgoff; 873 mi->start = start;
759 874
760 list_add(&map->node, &md->maps); 875 if (!mi->name) {
876 free(mi);
877 return -ENOMEM;
878 }
879
880 add_module(mi, modules);
881
882 return 0;
883}
884
885static int read_proc_modules(const char *filename, struct rb_root *modules)
886{
887 if (symbol__restricted_filename(filename, "/proc/modules"))
888 return -1;
889
890 if (modules__parse(filename, modules, __read_proc_modules)) {
891 delete_modules(modules);
892 return -1;
893 }
761 894
762 return 0; 895 return 0;
763} 896}
764 897
898int compare_proc_modules(const char *from, const char *to)
899{
900 struct rb_root from_modules = RB_ROOT;
901 struct rb_root to_modules = RB_ROOT;
902 struct rb_node *from_node, *to_node;
903 struct module_info *from_m, *to_m;
904 int ret = -1;
905
906 if (read_proc_modules(from, &from_modules))
907 return -1;
908
909 if (read_proc_modules(to, &to_modules))
910 goto out_delete_from;
911
912 from_node = rb_first(&from_modules);
913 to_node = rb_first(&to_modules);
914 while (from_node) {
915 if (!to_node)
916 break;
917
918 from_m = rb_entry(from_node, struct module_info, rb_node);
919 to_m = rb_entry(to_node, struct module_info, rb_node);
920
921 if (from_m->start != to_m->start ||
922 strcmp(from_m->name, to_m->name))
923 break;
924
925 from_node = rb_next(from_node);
926 to_node = rb_next(to_node);
927 }
928
929 if (!from_node && !to_node)
930 ret = 0;
931
932 delete_modules(&to_modules);
933out_delete_from:
934 delete_modules(&from_modules);
935
936 return ret;
937}
938
939static int do_validate_kcore_modules(const char *filename, struct map *map,
940 struct map_groups *kmaps)
941{
942 struct rb_root modules = RB_ROOT;
943 struct map *old_map;
944 int err;
945
946 err = read_proc_modules(filename, &modules);
947 if (err)
948 return err;
949
950 old_map = map_groups__first(kmaps, map->type);
951 while (old_map) {
952 struct map *next = map_groups__next(old_map);
953 struct module_info *mi;
954
955 if (old_map == map || old_map->start == map->start) {
956 /* The kernel map */
957 old_map = next;
958 continue;
959 }
960
961 /* Module must be in memory at the same address */
962 mi = find_module(old_map->dso->short_name, &modules);
963 if (!mi || mi->start != old_map->start) {
964 err = -EINVAL;
965 goto out;
966 }
967
968 old_map = next;
969 }
970out:
971 delete_modules(&modules);
972 return err;
973}
974
765/* 975/*
766 * If kallsyms is referenced by name then we look for kcore in the same 976 * If kallsyms is referenced by name then we look for filename in the same
767 * directory. 977 * directory.
768 */ 978 */
769static bool kcore_filename_from_kallsyms_filename(char *kcore_filename, 979static bool filename_from_kallsyms_filename(char *filename,
770 const char *kallsyms_filename) 980 const char *base_name,
981 const char *kallsyms_filename)
771{ 982{
772 char *name; 983 char *name;
773 984
774 strcpy(kcore_filename, kallsyms_filename); 985 strcpy(filename, kallsyms_filename);
775 name = strrchr(kcore_filename, '/'); 986 name = strrchr(filename, '/');
776 if (!name) 987 if (!name)
777 return false; 988 return false;
778 989
779 if (!strcmp(name, "/kallsyms")) { 990 name += 1;
780 strcpy(name, "/kcore"); 991
992 if (!strcmp(name, "kallsyms")) {
993 strcpy(name, base_name);
781 return true; 994 return true;
782 } 995 }
783 996
784 return false; 997 return false;
785} 998}
786 999
1000static int validate_kcore_modules(const char *kallsyms_filename,
1001 struct map *map)
1002{
1003 struct map_groups *kmaps = map__kmap(map)->kmaps;
1004 char modules_filename[PATH_MAX];
1005
1006 if (!filename_from_kallsyms_filename(modules_filename, "modules",
1007 kallsyms_filename))
1008 return -EINVAL;
1009
1010 if (do_validate_kcore_modules(modules_filename, map, kmaps))
1011 return -EINVAL;
1012
1013 return 0;
1014}
1015
1016struct kcore_mapfn_data {
1017 struct dso *dso;
1018 enum map_type type;
1019 struct list_head maps;
1020};
1021
1022static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
1023{
1024 struct kcore_mapfn_data *md = data;
1025 struct map *map;
1026
1027 map = map__new2(start, md->dso, md->type);
1028 if (map == NULL)
1029 return -ENOMEM;
1030
1031 map->end = map->start + len;
1032 map->pgoff = pgoff;
1033
1034 list_add(&map->node, &md->maps);
1035
1036 return 0;
1037}
1038
787static int dso__load_kcore(struct dso *dso, struct map *map, 1039static int dso__load_kcore(struct dso *dso, struct map *map,
788 const char *kallsyms_filename) 1040 const char *kallsyms_filename)
789{ 1041{
@@ -800,8 +1052,12 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
800 if (map != machine->vmlinux_maps[map->type]) 1052 if (map != machine->vmlinux_maps[map->type])
801 return -EINVAL; 1053 return -EINVAL;
802 1054
803 if (!kcore_filename_from_kallsyms_filename(kcore_filename, 1055 if (!filename_from_kallsyms_filename(kcore_filename, "kcore",
804 kallsyms_filename)) 1056 kallsyms_filename))
1057 return -EINVAL;
1058
1059 /* All modules must be present at their original addresses */
1060 if (validate_kcore_modules(kallsyms_filename, map))
805 return -EINVAL; 1061 return -EINVAL;
806 1062
807 md.dso = dso; 1063 md.dso = dso;
@@ -1188,6 +1444,105 @@ out:
1188 return err; 1444 return err;
1189} 1445}
1190 1446
1447static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1448{
1449 char kallsyms_filename[PATH_MAX];
1450 struct dirent *dent;
1451 int ret = -1;
1452 DIR *d;
1453
1454 d = opendir(dir);
1455 if (!d)
1456 return -1;
1457
1458 while (1) {
1459 dent = readdir(d);
1460 if (!dent)
1461 break;
1462 if (dent->d_type != DT_DIR)
1463 continue;
1464 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1465 "%s/%s/kallsyms", dir, dent->d_name);
1466 if (!validate_kcore_modules(kallsyms_filename, map)) {
1467 strlcpy(dir, kallsyms_filename, dir_sz);
1468 ret = 0;
1469 break;
1470 }
1471 }
1472
1473 closedir(d);
1474
1475 return ret;
1476}
1477
1478static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1479{
1480 u8 host_build_id[BUILD_ID_SIZE];
1481 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1482 bool is_host = false;
1483 char path[PATH_MAX];
1484
1485 if (!dso->has_build_id) {
1486 /*
1487 * Last resort, if we don't have a build-id and couldn't find
1488 * any vmlinux file, try the running kernel kallsyms table.
1489 */
1490 goto proc_kallsyms;
1491 }
1492
1493 if (sysfs__read_build_id("/sys/kernel/notes", host_build_id,
1494 sizeof(host_build_id)) == 0)
1495 is_host = dso__build_id_equal(dso, host_build_id);
1496
1497 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1498
1499 /* Use /proc/kallsyms if possible */
1500 if (is_host) {
1501 DIR *d;
1502 int fd;
1503
1504 /* If no cached kcore go with /proc/kallsyms */
1505 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
1506 buildid_dir, sbuild_id);
1507 d = opendir(path);
1508 if (!d)
1509 goto proc_kallsyms;
1510 closedir(d);
1511
1512 /*
1513 * Do not check the build-id cache, until we know we cannot use
1514 * /proc/kcore.
1515 */
1516 fd = open("/proc/kcore", O_RDONLY);
1517 if (fd != -1) {
1518 close(fd);
1519 /* If module maps match go with /proc/kallsyms */
1520 if (!validate_kcore_modules("/proc/kallsyms", map))
1521 goto proc_kallsyms;
1522 }
1523
1524 /* Find kallsyms in build-id cache with kcore */
1525 if (!find_matching_kcore(map, path, sizeof(path)))
1526 return strdup(path);
1527
1528 goto proc_kallsyms;
1529 }
1530
1531 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
1532 buildid_dir, sbuild_id);
1533
1534 if (access(path, F_OK)) {
1535 pr_err("No kallsyms or vmlinux with build-id %s was found\n",
1536 sbuild_id);
1537 return NULL;
1538 }
1539
1540 return strdup(path);
1541
1542proc_kallsyms:
1543 return strdup("/proc/kallsyms");
1544}
1545
1191static int dso__load_kernel_sym(struct dso *dso, struct map *map, 1546static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1192 symbol_filter_t filter) 1547 symbol_filter_t filter)
1193{ 1548{
@@ -1214,7 +1569,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1214 goto do_kallsyms; 1569 goto do_kallsyms;
1215 } 1570 }
1216 1571
1217 if (symbol_conf.vmlinux_name != NULL) { 1572 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
1218 err = dso__load_vmlinux(dso, map, 1573 err = dso__load_vmlinux(dso, map,
1219 symbol_conf.vmlinux_name, filter); 1574 symbol_conf.vmlinux_name, filter);
1220 if (err > 0) { 1575 if (err > 0) {
@@ -1226,7 +1581,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1226 return err; 1581 return err;
1227 } 1582 }
1228 1583
1229 if (vmlinux_path != NULL) { 1584 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
1230 err = dso__load_vmlinux_path(dso, map, filter); 1585 err = dso__load_vmlinux_path(dso, map, filter);
1231 if (err > 0) 1586 if (err > 0)
1232 return err; 1587 return err;
@@ -1236,51 +1591,11 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1236 if (symbol_conf.symfs[0] != 0) 1591 if (symbol_conf.symfs[0] != 0)
1237 return -1; 1592 return -1;
1238 1593
1239 /* 1594 kallsyms_allocated_filename = dso__find_kallsyms(dso, map);
1240 * Say the kernel DSO was created when processing the build-id header table, 1595 if (!kallsyms_allocated_filename)
1241 * we have a build-id, so check if it is the same as the running kernel, 1596 return -1;
1242 * using it if it is.
1243 */
1244 if (dso->has_build_id) {
1245 u8 kallsyms_build_id[BUILD_ID_SIZE];
1246 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1247
1248 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
1249 sizeof(kallsyms_build_id)) == 0) {
1250 if (dso__build_id_equal(dso, kallsyms_build_id)) {
1251 kallsyms_filename = "/proc/kallsyms";
1252 goto do_kallsyms;
1253 }
1254 }
1255 /*
1256 * Now look if we have it on the build-id cache in
1257 * $HOME/.debug/[kernel.kallsyms].
1258 */
1259 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1260 sbuild_id);
1261
1262 if (asprintf(&kallsyms_allocated_filename,
1263 "%s/.debug/[kernel.kallsyms]/%s",
1264 getenv("HOME"), sbuild_id) == -1) {
1265 pr_err("Not enough memory for kallsyms file lookup\n");
1266 return -1;
1267 }
1268
1269 kallsyms_filename = kallsyms_allocated_filename;
1270 1597
1271 if (access(kallsyms_filename, F_OK)) { 1598 kallsyms_filename = kallsyms_allocated_filename;
1272 pr_err("No kallsyms or vmlinux with build-id %s "
1273 "was found\n", sbuild_id);
1274 free(kallsyms_allocated_filename);
1275 return -1;
1276 }
1277 } else {
1278 /*
1279 * Last resort, if we don't have a build-id and couldn't find
1280 * any vmlinux file, try the running kernel kallsyms table.
1281 */
1282 kallsyms_filename = "/proc/kallsyms";
1283 }
1284 1599
1285do_kallsyms: 1600do_kallsyms:
1286 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1601 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index fd5b70ea2981..07de8fea2f48 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,7 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15 15
16#ifdef LIBELF_SUPPORT 16#ifdef HAVE_LIBELF_SUPPORT
17#include <libelf.h> 17#include <libelf.h>
18#include <gelf.h> 18#include <gelf.h>
19#endif 19#endif
@@ -21,7 +21,7 @@
21 21
22#include "dso.h" 22#include "dso.h"
23 23
24#ifdef HAVE_CPLUS_DEMANGLE 24#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
25extern char *cplus_demangle(const char *, int); 25extern char *cplus_demangle(const char *, int);
26 26
27static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) 27static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
@@ -46,7 +46,7 @@ static inline char *bfd_demangle(void __maybe_unused *v,
46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
47 * for newer versions we can use mmap to reduce memory usage: 47 * for newer versions we can use mmap to reduce memory usage:
48 */ 48 */
49#ifdef LIBELF_MMAP 49#ifdef HAVE_LIBELF_MMAP_SUPPORT
50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP 50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
51#else 51#else
52# define PERF_ELF_C_READ_MMAP ELF_C_READ 52# define PERF_ELF_C_READ_MMAP ELF_C_READ
@@ -85,6 +85,7 @@ struct symbol_conf {
85 unsigned short priv_size; 85 unsigned short priv_size;
86 unsigned short nr_events; 86 unsigned short nr_events;
87 bool try_vmlinux_path, 87 bool try_vmlinux_path,
88 ignore_vmlinux,
88 show_kernel_path, 89 show_kernel_path,
89 use_modules, 90 use_modules,
90 sort_by_name, 91 sort_by_name,
@@ -178,7 +179,7 @@ struct symsrc {
178 int fd; 179 int fd;
179 enum dso_binary_type type; 180 enum dso_binary_type type;
180 181
181#ifdef LIBELF_SUPPORT 182#ifdef HAVE_LIBELF_SUPPORT
182 Elf *elf; 183 Elf *elf;
183 GElf_Ehdr ehdr; 184 GElf_Ehdr ehdr;
184 185
@@ -222,6 +223,9 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size);
222int kallsyms__parse(const char *filename, void *arg, 223int kallsyms__parse(const char *filename, void *arg,
223 int (*process_symbol)(void *arg, const char *name, 224 int (*process_symbol)(void *arg, const char *name,
224 char type, u64 start)); 225 char type, u64 start));
226int modules__parse(const char *filename, void *arg,
227 int (*process_module)(void *arg, const char *name,
228 u64 start));
225int filename__read_debuglink(const char *filename, char *debuglink, 229int filename__read_debuglink(const char *filename, char *debuglink,
226 size_t size); 230 size_t size);
227 231
@@ -252,4 +256,21 @@ typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data);
252int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, 256int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
253 bool *is_64_bit); 257 bool *is_64_bit);
254 258
259#define PERF_KCORE_EXTRACT "/tmp/perf-kcore-XXXXXX"
260
261struct kcore_extract {
262 char *kcore_filename;
263 u64 addr;
264 u64 offs;
265 u64 len;
266 char extract_filename[sizeof(PERF_KCORE_EXTRACT)];
267 int fd;
268};
269
270int kcore_extract__create(struct kcore_extract *kce);
271void kcore_extract__delete(struct kcore_extract *kce);
272
273int kcore_copy(const char *from_dir, const char *to_dir);
274int compare_proc_modules(const char *from, const char *to);
275
255#endif /* __PERF_SYMBOL */ 276#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/sysfs.c b/tools/perf/util/sysfs.c
deleted file mode 100644
index f71e9eafe15a..000000000000
--- a/tools/perf/util/sysfs.c
+++ /dev/null
@@ -1,60 +0,0 @@
1
2#include "util.h"
3#include "sysfs.h"
4
5static const char * const sysfs_known_mountpoints[] = {
6 "/sys",
7 0,
8};
9
10static int sysfs_found;
11char sysfs_mountpoint[PATH_MAX + 1];
12
13static int sysfs_valid_mountpoint(const char *sysfs)
14{
15 struct statfs st_fs;
16
17 if (statfs(sysfs, &st_fs) < 0)
18 return -ENOENT;
19 else if (st_fs.f_type != (long) SYSFS_MAGIC)
20 return -ENOENT;
21
22 return 0;
23}
24
25const char *sysfs_find_mountpoint(void)
26{
27 const char * const *ptr;
28 char type[100];
29 FILE *fp;
30
31 if (sysfs_found)
32 return (const char *) sysfs_mountpoint;
33
34 ptr = sysfs_known_mountpoints;
35 while (*ptr) {
36 if (sysfs_valid_mountpoint(*ptr) == 0) {
37 sysfs_found = 1;
38 strcpy(sysfs_mountpoint, *ptr);
39 return sysfs_mountpoint;
40 }
41 ptr++;
42 }
43
44 /* give up and parse /proc/mounts */
45 fp = fopen("/proc/mounts", "r");
46 if (fp == NULL)
47 return NULL;
48
49 while (!sysfs_found &&
50 fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
51 sysfs_mountpoint, type) == 2) {
52
53 if (strcmp(type, "sysfs") == 0)
54 sysfs_found = 1;
55 }
56
57 fclose(fp);
58
59 return sysfs_found ? sysfs_mountpoint : NULL;
60}
diff --git a/tools/perf/util/sysfs.h b/tools/perf/util/sysfs.h
deleted file mode 100644
index a813b7203938..000000000000
--- a/tools/perf/util/sysfs.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef __SYSFS_H__
2#define __SYSFS_H__
3
4const char *sysfs_find_mountpoint(void);
5
6#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index e3d4a550a703..cd8e2f592719 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -6,86 +6,137 @@
6#include "thread.h" 6#include "thread.h"
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9#include "comm.h"
9 10
10struct thread *thread__new(pid_t pid, pid_t tid) 11struct thread *thread__new(pid_t pid, pid_t tid)
11{ 12{
12 struct thread *self = zalloc(sizeof(*self)); 13 char *comm_str;
13 14 struct comm *comm;
14 if (self != NULL) { 15 struct thread *thread = zalloc(sizeof(*thread));
15 map_groups__init(&self->mg); 16
16 self->pid_ = pid; 17 if (thread != NULL) {
17 self->tid = tid; 18 map_groups__init(&thread->mg);
18 self->ppid = -1; 19 thread->pid_ = pid;
19 self->comm = malloc(32); 20 thread->tid = tid;
20 if (self->comm) 21 thread->ppid = -1;
21 snprintf(self->comm, 32, ":%d", self->tid); 22 INIT_LIST_HEAD(&thread->comm_list);
23
24 comm_str = malloc(32);
25 if (!comm_str)
26 goto err_thread;
27
28 snprintf(comm_str, 32, ":%d", tid);
29 comm = comm__new(comm_str, 0);
30 free(comm_str);
31 if (!comm)
32 goto err_thread;
33
34 list_add(&comm->list, &thread->comm_list);
35 }
36
37 return thread;
38
39err_thread:
40 free(thread);
41 return NULL;
42}
43
44void thread__delete(struct thread *thread)
45{
46 struct comm *comm, *tmp;
47
48 map_groups__exit(&thread->mg);
49 list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
50 list_del(&comm->list);
51 comm__free(comm);
22 } 52 }
23 53
24 return self; 54 free(thread);
25} 55}
26 56
27void thread__delete(struct thread *self) 57struct comm *thread__comm(const struct thread *thread)
28{ 58{
29 map_groups__exit(&self->mg); 59 if (list_empty(&thread->comm_list))
30 free(self->comm); 60 return NULL;
31 free(self); 61
62 return list_first_entry(&thread->comm_list, struct comm, list);
32} 63}
33 64
34int thread__set_comm(struct thread *self, const char *comm) 65/* CHECKME: time should always be 0 if event aren't ordered */
66int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
35{ 67{
36 int err; 68 struct comm *new, *curr = thread__comm(thread);
37 69
38 if (self->comm) 70 /* Override latest entry if it had no specific time coverage */
39 free(self->comm); 71 if (!curr->start) {
40 self->comm = strdup(comm); 72 comm__override(curr, str, timestamp);
41 err = self->comm == NULL ? -ENOMEM : 0; 73 return 0;
42 if (!err) {
43 self->comm_set = true;
44 } 74 }
45 return err; 75
76 new = comm__new(str, timestamp);
77 if (!new)
78 return -ENOMEM;
79
80 list_add(&new->list, &thread->comm_list);
81 thread->comm_set = true;
82
83 return 0;
84}
85
86const char *thread__comm_str(const struct thread *thread)
87{
88 const struct comm *comm = thread__comm(thread);
89
90 if (!comm)
91 return NULL;
92
93 return comm__str(comm);
46} 94}
47 95
48int thread__comm_len(struct thread *self) 96/* CHECKME: it should probably better return the max comm len from its comm list */
97int thread__comm_len(struct thread *thread)
49{ 98{
50 if (!self->comm_len) { 99 if (!thread->comm_len) {
51 if (!self->comm) 100 const char *comm = thread__comm_str(thread);
101 if (!comm)
52 return 0; 102 return 0;
53 self->comm_len = strlen(self->comm); 103 thread->comm_len = strlen(comm);
54 } 104 }
55 105
56 return self->comm_len; 106 return thread->comm_len;
57} 107}
58 108
59size_t thread__fprintf(struct thread *thread, FILE *fp) 109size_t thread__fprintf(struct thread *thread, FILE *fp)
60{ 110{
61 return fprintf(fp, "Thread %d %s\n", thread->tid, thread->comm) + 111 return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) +
62 map_groups__fprintf(&thread->mg, verbose, fp); 112 map_groups__fprintf(&thread->mg, verbose, fp);
63} 113}
64 114
65void thread__insert_map(struct thread *self, struct map *map) 115void thread__insert_map(struct thread *thread, struct map *map)
66{ 116{
67 map_groups__fixup_overlappings(&self->mg, map, verbose, stderr); 117 map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr);
68 map_groups__insert(&self->mg, map); 118 map_groups__insert(&thread->mg, map);
69} 119}
70 120
71int thread__fork(struct thread *self, struct thread *parent) 121int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
72{ 122{
73 int i; 123 int i, err;
74 124
75 if (parent->comm_set) { 125 if (parent->comm_set) {
76 if (self->comm) 126 const char *comm = thread__comm_str(parent);
77 free(self->comm); 127 if (!comm)
78 self->comm = strdup(parent->comm);
79 if (!self->comm)
80 return -ENOMEM; 128 return -ENOMEM;
81 self->comm_set = true; 129 err = thread__set_comm(thread, comm, timestamp);
130 if (!err)
131 return err;
132 thread->comm_set = true;
82 } 133 }
83 134
84 for (i = 0; i < MAP__NR_TYPES; ++i) 135 for (i = 0; i < MAP__NR_TYPES; ++i)
85 if (map_groups__clone(&self->mg, &parent->mg, i) < 0) 136 if (map_groups__clone(&thread->mg, &parent->mg, i) < 0)
86 return -ENOMEM; 137 return -ENOMEM;
87 138
88 self->ppid = parent->tid; 139 thread->ppid = parent->tid;
89 140
90 return 0; 141 return 0;
91} 142}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 4ebbb40d46d4..897c1b2a750a 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -2,6 +2,7 @@
2#define __PERF_THREAD_H 2#define __PERF_THREAD_H
3 3
4#include <linux/rbtree.h> 4#include <linux/rbtree.h>
5#include <linux/list.h>
5#include <unistd.h> 6#include <unistd.h>
6#include <sys/types.h> 7#include <sys/types.h>
7#include "symbol.h" 8#include "symbol.h"
@@ -18,31 +19,34 @@ struct thread {
18 char shortname[3]; 19 char shortname[3];
19 bool comm_set; 20 bool comm_set;
20 bool dead; /* if set thread has exited */ 21 bool dead; /* if set thread has exited */
21 char *comm; 22 struct list_head comm_list;
22 int comm_len; 23 int comm_len;
23 24
24 void *priv; 25 void *priv;
25}; 26};
26 27
27struct machine; 28struct machine;
29struct comm;
28 30
29struct thread *thread__new(pid_t pid, pid_t tid); 31struct thread *thread__new(pid_t pid, pid_t tid);
30void thread__delete(struct thread *self); 32void thread__delete(struct thread *thread);
31static inline void thread__exited(struct thread *thread) 33static inline void thread__exited(struct thread *thread)
32{ 34{
33 thread->dead = true; 35 thread->dead = true;
34} 36}
35 37
36int thread__set_comm(struct thread *self, const char *comm); 38int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp);
37int thread__comm_len(struct thread *self); 39int thread__comm_len(struct thread *thread);
38void thread__insert_map(struct thread *self, struct map *map); 40struct comm *thread__comm(const struct thread *thread);
39int thread__fork(struct thread *self, struct thread *parent); 41const char *thread__comm_str(const struct thread *thread);
42void thread__insert_map(struct thread *thread, struct map *map);
43int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
40size_t thread__fprintf(struct thread *thread, FILE *fp); 44size_t thread__fprintf(struct thread *thread, FILE *fp);
41 45
42static inline struct map *thread__find_map(struct thread *self, 46static inline struct map *thread__find_map(struct thread *thread,
43 enum map_type type, u64 addr) 47 enum map_type type, u64 addr)
44{ 48{
45 return self ? map_groups__find(&self->mg, type, addr) : NULL; 49 return thread ? map_groups__find(&thread->mg, type, addr) : NULL;
46} 50}
47 51
48void thread__find_addr_map(struct thread *thread, struct machine *machine, 52void thread__find_addr_map(struct thread *thread, struct machine *machine,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index b554ffc462b6..88cfeaff600b 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -24,6 +24,7 @@ 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 max_stack;
27 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool use_tui, use_stdio; 29 bool use_tui, use_stdio;
29 bool kptr_restrict_warned; 30 bool kptr_restrict_warned;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index e9e1c03f927d..6681f71f2f95 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -120,42 +120,6 @@ raw_field_value(struct event_format *event, const char *name, void *data)
120 return val; 120 return val;
121} 121}
122 122
123void *raw_field_ptr(struct event_format *event, const char *name, void *data)
124{
125 struct format_field *field;
126
127 field = pevent_find_any_field(event, name);
128 if (!field)
129 return NULL;
130
131 if (field->flags & FIELD_IS_DYNAMIC) {
132 int offset;
133
134 offset = *(int *)(data + field->offset);
135 offset &= 0xffff;
136
137 return data + offset;
138 }
139
140 return data + field->offset;
141}
142
143int trace_parse_common_type(struct pevent *pevent, void *data)
144{
145 struct pevent_record record;
146
147 record.data = data;
148 return pevent_data_type(pevent, &record);
149}
150
151int trace_parse_common_pid(struct pevent *pevent, void *data)
152{
153 struct pevent_record record;
154
155 record.data = data;
156 return pevent_data_pid(pevent, &record);
157}
158
159unsigned long long read_size(struct event_format *event, void *ptr, int size) 123unsigned long long read_size(struct event_format *event, void *ptr, int size)
160{ 124{
161 return pevent_read_number(event->pevent, ptr, size); 125 return pevent_read_number(event->pevent, ptr, size);
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index fafe1a40444a..04df63114109 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -11,8 +11,6 @@ union perf_event;
11struct perf_tool; 11struct perf_tool;
12struct thread; 12struct thread;
13 13
14extern struct pevent *perf_pevent;
15
16int bigendian(void); 14int bigendian(void);
17 15
18struct pevent *read_trace_init(int file_bigendian, int host_bigendian); 16struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
@@ -23,26 +21,19 @@ int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size);
23int parse_event_file(struct pevent *pevent, 21int parse_event_file(struct pevent *pevent,
24 char *buf, unsigned long size, char *sys); 22 char *buf, unsigned long size, char *sys);
25 23
26struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu);
27
28unsigned long long 24unsigned long long
29raw_field_value(struct event_format *event, const char *name, void *data); 25raw_field_value(struct event_format *event, const char *name, void *data);
30void *raw_field_ptr(struct event_format *event, const char *name, void *data);
31 26
32void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 27void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
33void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 28void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
34 29
35ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); 30ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
36 31
37int trace_parse_common_type(struct pevent *pevent, void *data);
38int trace_parse_common_pid(struct pevent *pevent, void *data);
39
40struct event_format *trace_find_next_event(struct pevent *pevent, 32struct event_format *trace_find_next_event(struct pevent *pevent,
41 struct event_format *event); 33 struct event_format *event);
42unsigned long long read_size(struct event_format *event, void *ptr, int size); 34unsigned long long read_size(struct event_format *event, void *ptr, int size);
43unsigned long long eval_flag(const char *flag); 35unsigned long long eval_flag(const char *flag);
44 36
45struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
46int read_tracing_data(int fd, struct list_head *pattrs); 37int read_tracing_data(int fd, struct list_head *pattrs);
47 38
48struct tracing_data { 39struct tracing_data {
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index cb6bc503a792..ec0c71a2ca2e 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -13,7 +13,7 @@ struct unwind_entry {
13 13
14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); 14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
15 15
16#ifdef LIBUNWIND_SUPPORT 16#ifdef HAVE_LIBUNWIND_SUPPORT
17int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 17int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
18 struct machine *machine, 18 struct machine *machine,
19 struct thread *thread, 19 struct thread *thread,
@@ -31,5 +31,5 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
31{ 31{
32 return 0; 32 return 0;
33} 33}
34#endif /* LIBUNWIND_SUPPORT */ 34#endif /* HAVE_LIBUNWIND_SUPPORT */
35#endif /* __UNWIND_H */ 35#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 6d17b18e915d..28a0a89c1f73 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,7 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include <sys/mman.h> 3#include <sys/mman.h>
4#ifdef BACKTRACE_SUPPORT 4#ifdef HAVE_BACKTRACE_SUPPORT
5#include <execinfo.h> 5#include <execinfo.h>
6#endif 6#endif
7#include <stdio.h> 7#include <stdio.h>
@@ -55,17 +55,20 @@ int mkdir_p(char *path, mode_t mode)
55 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 55 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
56} 56}
57 57
58static int slow_copyfile(const char *from, const char *to) 58static int slow_copyfile(const char *from, const char *to, mode_t mode)
59{ 59{
60 int err = 0; 60 int err = -1;
61 char *line = NULL; 61 char *line = NULL;
62 size_t n; 62 size_t n;
63 FILE *from_fp = fopen(from, "r"), *to_fp; 63 FILE *from_fp = fopen(from, "r"), *to_fp;
64 mode_t old_umask;
64 65
65 if (from_fp == NULL) 66 if (from_fp == NULL)
66 goto out; 67 goto out;
67 68
69 old_umask = umask(mode ^ 0777);
68 to_fp = fopen(to, "w"); 70 to_fp = fopen(to, "w");
71 umask(old_umask);
69 if (to_fp == NULL) 72 if (to_fp == NULL)
70 goto out_fclose_from; 73 goto out_fclose_from;
71 74
@@ -82,7 +85,7 @@ out:
82 return err; 85 return err;
83} 86}
84 87
85int copyfile(const char *from, const char *to) 88int copyfile_mode(const char *from, const char *to, mode_t mode)
86{ 89{
87 int fromfd, tofd; 90 int fromfd, tofd;
88 struct stat st; 91 struct stat st;
@@ -93,13 +96,13 @@ int copyfile(const char *from, const char *to)
93 goto out; 96 goto out;
94 97
95 if (st.st_size == 0) /* /proc? do it slowly... */ 98 if (st.st_size == 0) /* /proc? do it slowly... */
96 return slow_copyfile(from, to); 99 return slow_copyfile(from, to, mode);
97 100
98 fromfd = open(from, O_RDONLY); 101 fromfd = open(from, O_RDONLY);
99 if (fromfd < 0) 102 if (fromfd < 0)
100 goto out; 103 goto out;
101 104
102 tofd = creat(to, 0755); 105 tofd = creat(to, mode);
103 if (tofd < 0) 106 if (tofd < 0)
104 goto out_close_from; 107 goto out_close_from;
105 108
@@ -121,6 +124,11 @@ out:
121 return err; 124 return err;
122} 125}
123 126
127int copyfile(const char *from, const char *to)
128{
129 return copyfile_mode(from, to, 0755);
130}
131
124unsigned long convert_unit(unsigned long value, char *unit) 132unsigned long convert_unit(unsigned long value, char *unit)
125{ 133{
126 *unit = ' '; 134 *unit = ' ';
@@ -204,7 +212,7 @@ int hex2u64(const char *ptr, u64 *long_val)
204} 212}
205 213
206/* Obtain a backtrace and print it to stdout. */ 214/* Obtain a backtrace and print it to stdout. */
207#ifdef BACKTRACE_SUPPORT 215#ifdef HAVE_BACKTRACE_SUPPORT
208void dump_stack(void) 216void dump_stack(void)
209{ 217{
210 void *array[16]; 218 void *array[16];
@@ -361,3 +369,47 @@ int parse_nsec_time(const char *str, u64 *ptime)
361 *ptime = time_sec * NSEC_PER_SEC + time_nsec; 369 *ptime = time_sec * NSEC_PER_SEC + time_nsec;
362 return 0; 370 return 0;
363} 371}
372
373unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
374{
375 struct parse_tag *i = tags;
376
377 while (i->tag) {
378 char *s;
379
380 s = strchr(str, i->tag);
381 if (s) {
382 unsigned long int value;
383 char *endptr;
384
385 value = strtoul(str, &endptr, 10);
386 if (s != endptr)
387 break;
388
389 if (value > ULONG_MAX / i->mult)
390 break;
391 value *= i->mult;
392 return value;
393 }
394 i++;
395 }
396
397 return (unsigned long) -1;
398}
399
400int filename__read_int(const char *filename, int *value)
401{
402 char line[64];
403 int fd = open(filename, O_RDONLY), err = -1;
404
405 if (fd < 0)
406 return -1;
407
408 if (read(fd, line, sizeof(line)) > 0) {
409 *value = atoi(line);
410 err = 0;
411 }
412
413 close(fd);
414 return err;
415}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index a53535949043..c8f362daba87 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -128,6 +128,8 @@ void put_tracing_file(char *file);
128#endif 128#endif
129#endif 129#endif
130 130
131#define PERF_GTK_DSO "libperf-gtk.so"
132
131/* General helper functions */ 133/* General helper functions */
132extern void usage(const char *err) NORETURN; 134extern void usage(const char *err) NORETURN;
133extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); 135extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
@@ -241,6 +243,7 @@ static inline int sane_case(int x, int high)
241 243
242int mkdir_p(char *path, mode_t mode); 244int mkdir_p(char *path, mode_t mode);
243int copyfile(const char *from, const char *to); 245int copyfile(const char *from, const char *to);
246int copyfile_mode(const char *from, const char *to, mode_t mode);
244 247
245s64 perf_atoll(const char *str); 248s64 perf_atoll(const char *str);
246char **argv_split(const char *str, int *argcp); 249char **argv_split(const char *str, int *argcp);
@@ -270,6 +273,13 @@ bool is_power_of_2(unsigned long n)
270 return (n != 0 && ((n & (n - 1)) == 0)); 273 return (n != 0 && ((n & (n - 1)) == 0));
271} 274}
272 275
276static inline unsigned next_pow2(unsigned x)
277{
278 if (!x)
279 return 1;
280 return 1ULL << (32 - __builtin_clz(x - 1));
281}
282
273size_t hex_width(u64 v); 283size_t hex_width(u64 v);
274int hex2u64(const char *ptr, u64 *val); 284int hex2u64(const char *ptr, u64 *val);
275 285
@@ -281,4 +291,20 @@ void dump_stack(void);
281extern unsigned int page_size; 291extern unsigned int page_size;
282 292
283void get_term_dimensions(struct winsize *ws); 293void get_term_dimensions(struct winsize *ws);
294
295struct parse_tag {
296 char tag;
297 int mult;
298};
299
300unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
301
302#define SRCLINE_UNKNOWN ((char *) "??:0")
303
304struct dso;
305
306char *get_srcline(struct dso *dso, unsigned long addr);
307void free_srcline(char *srcline);
308
309int filename__read_int(const char *filename, int *value);
284#endif /* GIT_COMPAT_UTIL_H */ 310#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 0d0506d55c71..ee76544deecb 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -59,21 +59,22 @@ QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
59QUIET_SUBDIR1 = 59QUIET_SUBDIR1 =
60 60
61ifneq ($(findstring $(MAKEFLAGS),s),s) 61ifneq ($(findstring $(MAKEFLAGS),s),s)
62ifneq ($(V),1) 62 ifneq ($(V),1)
63 QUIET_CC = @echo ' ' CC $@; 63 QUIET_CC = @echo ' CC '$@;
64 QUIET_AR = @echo ' ' AR $@; 64 QUIET_AR = @echo ' AR '$@;
65 QUIET_LINK = @echo ' ' LINK $@; 65 QUIET_LINK = @echo ' LINK '$@;
66 QUIET_MKDIR = @echo ' ' MKDIR $@; 66 QUIET_MKDIR = @echo ' MKDIR '$@;
67 QUIET_GEN = @echo ' ' GEN $@; 67 QUIET_GEN = @echo ' GEN '$@;
68 QUIET_SUBDIR0 = +@subdir= 68 QUIET_SUBDIR0 = +@subdir=
69 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ 69 QUIET_SUBDIR1 = ;$(NO_SUBDIR) \
70 echo ' SUBDIR '$$subdir; \
70 $(MAKE) $(PRINT_DIR) -C $$subdir 71 $(MAKE) $(PRINT_DIR) -C $$subdir
71 QUIET_FLEX = @echo ' ' FLEX $@; 72 QUIET_FLEX = @echo ' FLEX '$@;
72 QUIET_BISON = @echo ' ' BISON $@; 73 QUIET_BISON = @echo ' BISON '$@;
73 74
74 descend = \ 75 descend = \
75 +@echo ' ' DESCEND $(1); \ 76 +@echo ' DESCEND '$(1); \
76 mkdir -p $(OUTPUT)$(1) && \ 77 mkdir -p $(OUTPUT)$(1) && \
77 $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) 78 $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
78endif 79 endif
79endif 80endif
diff --git a/tools/testing/ktest/examples/crosstests.conf b/tools/testing/ktest/examples/crosstests.conf
index 46736604c26c..a1203148dfa1 100644
--- a/tools/testing/ktest/examples/crosstests.conf
+++ b/tools/testing/ktest/examples/crosstests.conf
@@ -133,12 +133,6 @@ CROSS = frv-linux
133ARCH = frv 133ARCH = frv
134GCC_VER = 4.5.1 134GCC_VER = 4.5.1
135 135
136# h8300 - failed make defconfig??
137TEST_START IF ${RUN} == h8300 || ${DO_FAILED}
138CROSS = h8300-elf
139ARCH = h8300
140GCC_VER = 4.5.1
141
142# m68k fails with error? 136# m68k fails with error?
143TEST_START IF ${RUN} == m68k || ${DO_DEFAULT} 137TEST_START IF ${RUN} == m68k || ${DO_DEFAULT}
144CROSS = m68k-linux 138CROSS = m68k-linux
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index 71c9c2511ee7..d5e9d6d185c8 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -59,12 +59,14 @@
59#define PM_PSHIFT_BITS 6 59#define PM_PSHIFT_BITS 6
60#define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) 60#define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS)
61#define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) 61#define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET)
62#define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) 62#define __PM_PSHIFT(x) (((uint64_t) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK)
63#define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) 63#define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1)
64#define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) 64#define PM_PFRAME(x) ((x) & PM_PFRAME_MASK)
65 65
66#define __PM_SOFT_DIRTY (1LL)
66#define PM_PRESENT PM_STATUS(4LL) 67#define PM_PRESENT PM_STATUS(4LL)
67#define PM_SWAP PM_STATUS(2LL) 68#define PM_SWAP PM_STATUS(2LL)
69#define PM_SOFT_DIRTY __PM_PSHIFT(__PM_SOFT_DIRTY)
68 70
69 71
70/* 72/*
@@ -83,6 +85,7 @@
83#define KPF_OWNER_PRIVATE 37 85#define KPF_OWNER_PRIVATE 37
84#define KPF_ARCH 38 86#define KPF_ARCH 38
85#define KPF_UNCACHED 39 87#define KPF_UNCACHED 39
88#define KPF_SOFTDIRTY 40
86 89
87/* [48-] take some arbitrary free slots for expanding overloaded flags 90/* [48-] take some arbitrary free slots for expanding overloaded flags
88 * not part of kernel API 91 * not part of kernel API
@@ -132,6 +135,7 @@ static const char * const page_flag_names[] = {
132 [KPF_OWNER_PRIVATE] = "O:owner_private", 135 [KPF_OWNER_PRIVATE] = "O:owner_private",
133 [KPF_ARCH] = "h:arch", 136 [KPF_ARCH] = "h:arch",
134 [KPF_UNCACHED] = "c:uncached", 137 [KPF_UNCACHED] = "c:uncached",
138 [KPF_SOFTDIRTY] = "f:softdirty",
135 139
136 [KPF_READAHEAD] = "I:readahead", 140 [KPF_READAHEAD] = "I:readahead",
137 [KPF_SLOB_FREE] = "P:slob_free", 141 [KPF_SLOB_FREE] = "P:slob_free",
@@ -417,7 +421,7 @@ static int bit_mask_ok(uint64_t flags)
417 return 1; 421 return 1;
418} 422}
419 423
420static uint64_t expand_overloaded_flags(uint64_t flags) 424static uint64_t expand_overloaded_flags(uint64_t flags, uint64_t pme)
421{ 425{
422 /* SLOB/SLUB overload several page flags */ 426 /* SLOB/SLUB overload several page flags */
423 if (flags & BIT(SLAB)) { 427 if (flags & BIT(SLAB)) {
@@ -433,6 +437,9 @@ static uint64_t expand_overloaded_flags(uint64_t flags)
433 if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM)) 437 if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM))
434 flags ^= BIT(RECLAIM) | BIT(READAHEAD); 438 flags ^= BIT(RECLAIM) | BIT(READAHEAD);
435 439
440 if (pme & PM_SOFT_DIRTY)
441 flags |= BIT(SOFTDIRTY);
442
436 return flags; 443 return flags;
437} 444}
438 445
@@ -448,11 +455,11 @@ static uint64_t well_known_flags(uint64_t flags)
448 return flags; 455 return flags;
449} 456}
450 457
451static uint64_t kpageflags_flags(uint64_t flags) 458static uint64_t kpageflags_flags(uint64_t flags, uint64_t pme)
452{ 459{
453 flags = expand_overloaded_flags(flags); 460 if (opt_raw)
454 461 flags = expand_overloaded_flags(flags, pme);
455 if (!opt_raw) 462 else
456 flags = well_known_flags(flags); 463 flags = well_known_flags(flags);
457 464
458 return flags; 465 return flags;
@@ -545,9 +552,9 @@ static size_t hash_slot(uint64_t flags)
545} 552}
546 553
547static void add_page(unsigned long voffset, 554static void add_page(unsigned long voffset,
548 unsigned long offset, uint64_t flags) 555 unsigned long offset, uint64_t flags, uint64_t pme)
549{ 556{
550 flags = kpageflags_flags(flags); 557 flags = kpageflags_flags(flags, pme);
551 558
552 if (!bit_mask_ok(flags)) 559 if (!bit_mask_ok(flags))
553 return; 560 return;
@@ -569,7 +576,8 @@ static void add_page(unsigned long voffset,
569#define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */ 576#define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */
570static void walk_pfn(unsigned long voffset, 577static void walk_pfn(unsigned long voffset,
571 unsigned long index, 578 unsigned long index,
572 unsigned long count) 579 unsigned long count,
580 uint64_t pme)
573{ 581{
574 uint64_t buf[KPAGEFLAGS_BATCH]; 582 uint64_t buf[KPAGEFLAGS_BATCH];
575 unsigned long batch; 583 unsigned long batch;
@@ -583,7 +591,7 @@ static void walk_pfn(unsigned long voffset,
583 break; 591 break;
584 592
585 for (i = 0; i < pages; i++) 593 for (i = 0; i < pages; i++)
586 add_page(voffset + i, index + i, buf[i]); 594 add_page(voffset + i, index + i, buf[i], pme);
587 595
588 index += pages; 596 index += pages;
589 count -= pages; 597 count -= pages;
@@ -608,7 +616,7 @@ static void walk_vma(unsigned long index, unsigned long count)
608 for (i = 0; i < pages; i++) { 616 for (i = 0; i < pages; i++) {
609 pfn = pagemap_pfn(buf[i]); 617 pfn = pagemap_pfn(buf[i]);
610 if (pfn) 618 if (pfn)
611 walk_pfn(index + i, pfn, 1); 619 walk_pfn(index + i, pfn, 1, buf[i]);
612 } 620 }
613 621
614 index += pages; 622 index += pages;
@@ -659,7 +667,7 @@ static void walk_addr_ranges(void)
659 667
660 for (i = 0; i < nr_addr_ranges; i++) 668 for (i = 0; i < nr_addr_ranges; i++)
661 if (!opt_pid) 669 if (!opt_pid)
662 walk_pfn(0, opt_offset[i], opt_size[i]); 670 walk_pfn(0, opt_offset[i], opt_size[i], 0);
663 else 671 else
664 walk_task(opt_offset[i], opt_size[i]); 672 walk_task(opt_offset[i], opt_size[i]);
665 673