aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2017-11-03 10:06:53 -0400
committerIngo Molnar <mingo@kernel.org>2017-11-03 10:06:53 -0400
commit340b5319c98eb14f7a70947a38e17d06f5beea88 (patch)
treeece6aeb203be9207ae16eb2ffb985fddc42db46d /tools/perf
parent0d3d73aac2ff05c78387aa9dcc2c8aa3804405e7 (diff)
parent7285cf3325b4a1dfb336d31eebc27dfbc30fb9aa (diff)
Merge tag 'perf-core-for-mingo-4.15-20171103' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: - Beautify the 'kcmp' and 'prctl' syscall arguments in 'perf trace' (Arnaldo Carvalho de Melo) - Implement a way to print formatted output to per-event files in 'perf script' to facilitate generate flamegraphs, elliminating the need to write scripts to do that separation (yuzhoujian, Arnaldo Carvalho de Melo) Make 'perf stat --per-thread' update shadow stats to show metrics (Jiri Olsa) - Fix double mapping al->addr in callchain processing for children without self period (Namhyung Kim) - Fix memory leak in addr2inlines() when libbfd is not used (Namhyung Kim) - Show correct function name for srcline of callchains when libbfd is not used (Namhyung Kim) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-script.txt4
-rw-r--r--tools/perf/Makefile.perf22
-rw-r--r--tools/perf/builtin-annotate.c10
-rw-r--r--tools/perf/builtin-buildid-cache.c8
-rw-r--r--tools/perf/builtin-buildid-list.c16
-rw-r--r--tools/perf/builtin-c2c.c10
-rw-r--r--tools/perf/builtin-diff.c18
-rw-r--r--tools/perf/builtin-evlist.c12
-rw-r--r--tools/perf/builtin-inject.c36
-rw-r--r--tools/perf/builtin-kmem.c8
-rw-r--r--tools/perf/builtin-kvm.c14
-rw-r--r--tools/perf/builtin-lock.c12
-rw-r--r--tools/perf/builtin-mem.c12
-rw-r--r--tools/perf/builtin-record.c50
-rw-r--r--tools/perf/builtin-report.c14
-rw-r--r--tools/perf/builtin-sched.c24
-rw-r--r--tools/perf/builtin-script.c169
-rw-r--r--tools/perf/builtin-stat.c39
-rw-r--r--tools/perf/builtin-timechart.c14
-rw-r--r--tools/perf/builtin-trace.c40
-rwxr-xr-xtools/perf/check-headers.sh2
-rw-r--r--tools/perf/tests/topology.c22
-rw-r--r--tools/perf/trace/beauty/Build2
-rw-r--r--tools/perf/trace/beauty/beauty.h18
-rw-r--r--tools/perf/trace/beauty/kcmp.c44
-rwxr-xr-xtools/perf/trace/beauty/kcmp_type.sh10
-rw-r--r--tools/perf/trace/beauty/prctl.c82
-rwxr-xr-xtools/perf/trace/beauty/prctl_option.sh17
-rw-r--r--tools/perf/util/auxtrace.c4
-rw-r--r--tools/perf/util/callchain.c5
-rw-r--r--tools/perf/util/data-convert-bt.c12
-rw-r--r--tools/perf/util/data.c94
-rw-r--r--tools/perf/util/data.h38
-rw-r--r--tools/perf/util/evsel.h3
-rw-r--r--tools/perf/util/header.c20
-rw-r--r--tools/perf/util/intel-bts.c6
-rw-r--r--tools/perf/util/intel-pt.c6
-rw-r--r--tools/perf/util/jit.h2
-rw-r--r--tools/perf/util/jitdump.c10
-rw-r--r--tools/perf/util/session.c44
-rw-r--r--tools/perf/util/session.h4
-rw-r--r--tools/perf/util/srcline.c102
-rw-r--r--tools/perf/util/stat-shadow.c48
-rw-r--r--tools/perf/util/stat.c24
-rw-r--r--tools/perf/util/stat.h2
45 files changed, 772 insertions, 381 deletions
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 25e677344728..2811fcf684cb 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -325,6 +325,10 @@ include::itrace.txt[]
325 Set the maximum number of program blocks to print with brstackasm for 325 Set the maximum number of program blocks to print with brstackasm for
326 each sample. 326 each sample.
327 327
328--per-event-dump::
329 Create per event files with a "perf.data.EVENT.dump" name instead of
330 printing to stdout, useful, for instance, for generating flamegraphs.
331
328--inline:: 332--inline::
329 If a callgraph address belongs to an inlined function, the inline stack 333 If a callgraph address belongs to an inlined function, the inline stack
330 will be printed. Each entry has function name and file/line. Enabled by 334 will be printed. Each entry has function name and file/line. Enabled by
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 5f7408118a2d..68cf1360a3f3 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -420,6 +420,13 @@ sndrv_pcm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
420$(sndrv_pcm_ioctl_array): $(sndrv_pcm_hdr_dir)/asound.h $(sndrv_pcm_ioctl_tbl) 420$(sndrv_pcm_ioctl_array): $(sndrv_pcm_hdr_dir)/asound.h $(sndrv_pcm_ioctl_tbl)
421 $(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(sndrv_pcm_hdr_dir) > $@ 421 $(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(sndrv_pcm_hdr_dir) > $@
422 422
423kcmp_type_array := $(beauty_outdir)/kcmp_type_array.c
424kcmp_hdr_dir := $(srctree)/tools/include/uapi/linux/
425kcmp_type_tbl := $(srctree)/tools/perf/trace/beauty/kcmp_type.sh
426
427$(kcmp_type_array): $(kcmp_hdr_dir)/kcmp.h $(kcmp_type_tbl)
428 $(Q)$(SHELL) '$(kcmp_type_tbl)' $(kcmp_hdr_dir) > $@
429
423kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c 430kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c
424kvm_hdr_dir := $(srctree)/tools/include/uapi/linux 431kvm_hdr_dir := $(srctree)/tools/include/uapi/linux
425kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh 432kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh
@@ -448,6 +455,13 @@ madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh
448$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) 455$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl)
449 $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ 456 $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@
450 457
458prctl_option_array := $(beauty_outdir)/prctl_option_array.c
459prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/
460prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh
461
462$(prctl_option_array): $(prctl_hdr_dir)/prctl.h $(prctl_option_tbl)
463 $(Q)$(SHELL) '$(prctl_option_tbl)' $(prctl_hdr_dir) > $@
464
451all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) 465all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
452 466
453$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) 467$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
@@ -546,10 +560,12 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc
546 $(pkey_alloc_access_rights_array) \ 560 $(pkey_alloc_access_rights_array) \
547 $(sndrv_pcm_ioctl_array) \ 561 $(sndrv_pcm_ioctl_array) \
548 $(sndrv_ctl_ioctl_array) \ 562 $(sndrv_ctl_ioctl_array) \
563 $(kcmp_type_array) \
549 $(kvm_ioctl_array) \ 564 $(kvm_ioctl_array) \
550 $(vhost_virtio_ioctl_array) \ 565 $(vhost_virtio_ioctl_array) \
551 $(madvise_behavior_array) \ 566 $(madvise_behavior_array) \
552 $(perf_ioctl_array) 567 $(perf_ioctl_array) \
568 $(prctl_option_array)
553 569
554$(OUTPUT)%.o: %.c prepare FORCE 570$(OUTPUT)%.o: %.c prepare FORCE
555 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 571 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -828,8 +844,10 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
828 $(OUTPUT)$(sndrv_ctl_ioctl_array) \ 844 $(OUTPUT)$(sndrv_ctl_ioctl_array) \
829 $(OUTPUT)$(sndrv_pcm_ioctl_array) \ 845 $(OUTPUT)$(sndrv_pcm_ioctl_array) \
830 $(OUTPUT)$(kvm_ioctl_array) \ 846 $(OUTPUT)$(kvm_ioctl_array) \
847 $(OUTPUT)$(kcmp_type_array) \
831 $(OUTPUT)$(vhost_virtio_ioctl_array) \ 848 $(OUTPUT)$(vhost_virtio_ioctl_array) \
832 $(OUTPUT)$(perf_ioctl_array) 849 $(OUTPUT)$(perf_ioctl_array) \
850 $(OUTPUT)$(prctl_option_array)
833 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 851 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
834 852
835# 853#
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index c38373195c4a..2d5c87578f83 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -356,7 +356,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
356 } 356 }
357 357
358 if (total_nr_samples == 0) { 358 if (total_nr_samples == 0) {
359 ui__error("The %s file has no samples!\n", session->file->path); 359 ui__error("The %s file has no samples!\n", session->data->file.path);
360 goto out; 360 goto out;
361 } 361 }
362 362
@@ -400,7 +400,7 @@ int cmd_annotate(int argc, const char **argv)
400 .ordering_requires_timestamps = true, 400 .ordering_requires_timestamps = true,
401 }, 401 },
402 }; 402 };
403 struct perf_data_file file = { 403 struct perf_data data = {
404 .mode = PERF_DATA_MODE_READ, 404 .mode = PERF_DATA_MODE_READ,
405 }; 405 };
406 struct option options[] = { 406 struct option options[] = {
@@ -410,7 +410,7 @@ int cmd_annotate(int argc, const char **argv)
410 "only consider symbols in these dsos"), 410 "only consider symbols in these dsos"),
411 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", 411 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
412 "symbol to annotate"), 412 "symbol to annotate"),
413 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 413 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
414 OPT_INCR('v', "verbose", &verbose, 414 OPT_INCR('v', "verbose", &verbose,
415 "be more verbose (show symbol address, etc)"), 415 "be more verbose (show symbol address, etc)"),
416 OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"), 416 OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"),
@@ -482,9 +482,9 @@ int cmd_annotate(int argc, const char **argv)
482 if (quiet) 482 if (quiet)
483 perf_quiet_option(); 483 perf_quiet_option();
484 484
485 file.path = input_name; 485 data.file.path = input_name;
486 486
487 annotate.session = perf_session__new(&file, false, &annotate.tool); 487 annotate.session = perf_session__new(&data, false, &annotate.tool);
488 if (annotate.session == NULL) 488 if (annotate.session == NULL)
489 return -1; 489 return -1;
490 490
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index e3eb6240ced0..cb2453b29365 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -311,7 +311,7 @@ int cmd_buildid_cache(int argc, const char **argv)
311 *kcore_filename = NULL; 311 *kcore_filename = NULL;
312 char sbuf[STRERR_BUFSIZE]; 312 char sbuf[STRERR_BUFSIZE];
313 313
314 struct perf_data_file file = { 314 struct perf_data data = {
315 .mode = PERF_DATA_MODE_READ, 315 .mode = PERF_DATA_MODE_READ,
316 }; 316 };
317 struct perf_session *session = NULL; 317 struct perf_session *session = NULL;
@@ -352,10 +352,10 @@ int cmd_buildid_cache(int argc, const char **argv)
352 nsi = nsinfo__new(ns_id); 352 nsi = nsinfo__new(ns_id);
353 353
354 if (missing_filename) { 354 if (missing_filename) {
355 file.path = missing_filename; 355 data.file.path = missing_filename;
356 file.force = force; 356 data.force = force;
357 357
358 session = perf_session__new(&file, false, NULL); 358 session = perf_session__new(&data, false, NULL);
359 if (session == NULL) 359 if (session == NULL)
360 return -1; 360 return -1;
361 } 361 }
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index fdaca16e0c74..00099a830b0d 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -50,10 +50,12 @@ static bool dso__skip_buildid(struct dso *dso, int with_hits)
50static int perf_session__list_build_ids(bool force, bool with_hits) 50static int perf_session__list_build_ids(bool force, bool with_hits)
51{ 51{
52 struct perf_session *session; 52 struct perf_session *session;
53 struct perf_data_file file = { 53 struct perf_data data = {
54 .path = input_name, 54 .file = {
55 .mode = PERF_DATA_MODE_READ, 55 .path = input_name,
56 .force = force, 56 },
57 .mode = PERF_DATA_MODE_READ,
58 .force = force,
57 }; 59 };
58 60
59 symbol__elf_init(); 61 symbol__elf_init();
@@ -63,7 +65,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
63 if (filename__fprintf_build_id(input_name, stdout) > 0) 65 if (filename__fprintf_build_id(input_name, stdout) > 0)
64 goto out; 66 goto out;
65 67
66 session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops); 68 session = perf_session__new(&data, false, &build_id__mark_dso_hit_ops);
67 if (session == NULL) 69 if (session == NULL)
68 return -1; 70 return -1;
69 71
@@ -71,7 +73,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
71 * We take all buildids when the file contains AUX area tracing data 73 * We take all buildids when the file contains AUX area tracing data
72 * because we do not decode the trace because it would take too long. 74 * because we do not decode the trace because it would take too long.
73 */ 75 */
74 if (!perf_data_file__is_pipe(&file) && 76 if (!perf_data__is_pipe(&data) &&
75 perf_header__has_feat(&session->header, HEADER_AUXTRACE)) 77 perf_header__has_feat(&session->header, HEADER_AUXTRACE))
76 with_hits = false; 78 with_hits = false;
77 79
@@ -79,7 +81,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
79 * in pipe-mode, the only way to get the buildids is to parse 81 * in pipe-mode, the only way to get the buildids is to parse
80 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID 82 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
81 */ 83 */
82 if (with_hits || perf_data_file__is_pipe(&file)) 84 if (with_hits || perf_data__is_pipe(&data))
83 perf_session__process_events(session); 85 perf_session__process_events(session);
84 86
85 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); 87 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index bb1ee22bd221..9590fdcc6484 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -2523,7 +2523,7 @@ static int perf_c2c__report(int argc, const char **argv)
2523{ 2523{
2524 struct perf_session *session; 2524 struct perf_session *session;
2525 struct ui_progress prog; 2525 struct ui_progress prog;
2526 struct perf_data_file file = { 2526 struct perf_data data = {
2527 .mode = PERF_DATA_MODE_READ, 2527 .mode = PERF_DATA_MODE_READ,
2528 }; 2528 };
2529 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; 2529 char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
@@ -2572,8 +2572,8 @@ static int perf_c2c__report(int argc, const char **argv)
2572 if (!input_name || !strlen(input_name)) 2572 if (!input_name || !strlen(input_name))
2573 input_name = "perf.data"; 2573 input_name = "perf.data";
2574 2574
2575 file.path = input_name; 2575 data.file.path = input_name;
2576 file.force = symbol_conf.force; 2576 data.force = symbol_conf.force;
2577 2577
2578 err = setup_display(display); 2578 err = setup_display(display);
2579 if (err) 2579 if (err)
@@ -2591,7 +2591,7 @@ static int perf_c2c__report(int argc, const char **argv)
2591 goto out; 2591 goto out;
2592 } 2592 }
2593 2593
2594 session = perf_session__new(&file, 0, &c2c.tool); 2594 session = perf_session__new(&data, 0, &c2c.tool);
2595 if (session == NULL) { 2595 if (session == NULL) {
2596 pr_debug("No memory for session\n"); 2596 pr_debug("No memory for session\n");
2597 goto out; 2597 goto out;
@@ -2611,7 +2611,7 @@ static int perf_c2c__report(int argc, const char **argv)
2611 goto out_session; 2611 goto out_session;
2612 2612
2613 /* No pipe support at the moment. */ 2613 /* No pipe support at the moment. */
2614 if (perf_data_file__is_pipe(session->file)) { 2614 if (perf_data__is_pipe(session->data)) {
2615 pr_debug("No pipe support at the moment.\n"); 2615 pr_debug("No pipe support at the moment.\n");
2616 goto out_session; 2616 goto out_session;
2617 } 2617 }
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 0cd4cf6a344b..67570e6417e5 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -47,7 +47,7 @@ struct diff_hpp_fmt {
47 47
48struct data__file { 48struct data__file {
49 struct perf_session *session; 49 struct perf_session *session;
50 struct perf_data_file file; 50 struct perf_data data;
51 int idx; 51 int idx;
52 struct hists *hists; 52 struct hists *hists;
53 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; 53 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX];
@@ -707,7 +707,7 @@ static void data__fprintf(void)
707 707
708 data__for_each_file(i, d) 708 data__for_each_file(i, d)
709 fprintf(stdout, "# [%d] %s %s\n", 709 fprintf(stdout, "# [%d] %s %s\n",
710 d->idx, d->file.path, 710 d->idx, d->data.file.path,
711 !d->idx ? "(Baseline)" : ""); 711 !d->idx ? "(Baseline)" : "");
712 712
713 fprintf(stdout, "#\n"); 713 fprintf(stdout, "#\n");
@@ -776,16 +776,16 @@ static int __cmd_diff(void)
776 int ret = -EINVAL, i; 776 int ret = -EINVAL, i;
777 777
778 data__for_each_file(i, d) { 778 data__for_each_file(i, d) {
779 d->session = perf_session__new(&d->file, false, &tool); 779 d->session = perf_session__new(&d->data, false, &tool);
780 if (!d->session) { 780 if (!d->session) {
781 pr_err("Failed to open %s\n", d->file.path); 781 pr_err("Failed to open %s\n", d->data.file.path);
782 ret = -1; 782 ret = -1;
783 goto out_delete; 783 goto out_delete;
784 } 784 }
785 785
786 ret = perf_session__process_events(d->session); 786 ret = perf_session__process_events(d->session);
787 if (ret) { 787 if (ret) {
788 pr_err("Failed to process %s\n", d->file.path); 788 pr_err("Failed to process %s\n", d->data.file.path);
789 goto out_delete; 789 goto out_delete;
790 } 790 }
791 791
@@ -1286,11 +1286,11 @@ static int data_init(int argc, const char **argv)
1286 return -ENOMEM; 1286 return -ENOMEM;
1287 1287
1288 data__for_each_file(i, d) { 1288 data__for_each_file(i, d) {
1289 struct perf_data_file *file = &d->file; 1289 struct perf_data *data = &d->data;
1290 1290
1291 file->path = use_default ? defaults[i] : argv[i]; 1291 data->file.path = use_default ? defaults[i] : argv[i];
1292 file->mode = PERF_DATA_MODE_READ, 1292 data->mode = PERF_DATA_MODE_READ,
1293 file->force = force, 1293 data->force = force,
1294 1294
1295 d->idx = i; 1295 d->idx = i;
1296 } 1296 }
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 6d210e40d611..93b85dc857b6 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -21,14 +21,16 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
21{ 21{
22 struct perf_session *session; 22 struct perf_session *session;
23 struct perf_evsel *pos; 23 struct perf_evsel *pos;
24 struct perf_data_file file = { 24 struct perf_data data = {
25 .path = file_name, 25 .file = {
26 .mode = PERF_DATA_MODE_READ, 26 .path = file_name,
27 .force = details->force, 27 },
28 .mode = PERF_DATA_MODE_READ,
29 .force = details->force,
28 }; 30 };
29 bool has_tracepoint = false; 31 bool has_tracepoint = false;
30 32
31 session = perf_session__new(&file, 0, NULL); 33 session = perf_session__new(&data, 0, NULL);
32 if (session == NULL) 34 if (session == NULL)
33 return -1; 35 return -1;
34 36
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 2b8032908fb2..91e65093d3c2 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -35,7 +35,7 @@ struct perf_inject {
35 bool strip; 35 bool strip;
36 bool jit_mode; 36 bool jit_mode;
37 const char *input_name; 37 const char *input_name;
38 struct perf_data_file output; 38 struct perf_data output;
39 u64 bytes_written; 39 u64 bytes_written;
40 u64 aux_id; 40 u64 aux_id;
41 struct list_head samples; 41 struct list_head samples;
@@ -52,7 +52,7 @@ static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
52{ 52{
53 ssize_t size; 53 ssize_t size;
54 54
55 size = perf_data_file__write(&inject->output, buf, sz); 55 size = perf_data__write(&inject->output, buf, sz);
56 if (size < 0) 56 if (size < 0)
57 return -errno; 57 return -errno;
58 58
@@ -145,7 +145,7 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
145 if (!inject->output.is_pipe) { 145 if (!inject->output.is_pipe) {
146 off_t offset; 146 off_t offset;
147 147
148 offset = lseek(inject->output.fd, 0, SEEK_CUR); 148 offset = lseek(inject->output.file.fd, 0, SEEK_CUR);
149 if (offset == -1) 149 if (offset == -1)
150 return -errno; 150 return -errno;
151 ret = auxtrace_index__auxtrace_event(&session->auxtrace_index, 151 ret = auxtrace_index__auxtrace_event(&session->auxtrace_index,
@@ -154,11 +154,11 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
154 return ret; 154 return ret;
155 } 155 }
156 156
157 if (perf_data_file__is_pipe(session->file) || !session->one_mmap) { 157 if (perf_data__is_pipe(session->data) || !session->one_mmap) {
158 ret = output_bytes(inject, event, event->header.size); 158 ret = output_bytes(inject, event, event->header.size);
159 if (ret < 0) 159 if (ret < 0)
160 return ret; 160 return ret;
161 ret = copy_bytes(inject, perf_data_file__fd(session->file), 161 ret = copy_bytes(inject, perf_data__fd(session->data),
162 event->auxtrace.size); 162 event->auxtrace.size);
163 } else { 163 } else {
164 ret = output_bytes(inject, event, 164 ret = output_bytes(inject, event,
@@ -637,8 +637,8 @@ static int __cmd_inject(struct perf_inject *inject)
637{ 637{
638 int ret = -EINVAL; 638 int ret = -EINVAL;
639 struct perf_session *session = inject->session; 639 struct perf_session *session = inject->session;
640 struct perf_data_file *file_out = &inject->output; 640 struct perf_data *data_out = &inject->output;
641 int fd = perf_data_file__fd(file_out); 641 int fd = perf_data__fd(data_out);
642 u64 output_data_offset; 642 u64 output_data_offset;
643 643
644 signal(SIGINT, sig_handler); 644 signal(SIGINT, sig_handler);
@@ -693,14 +693,14 @@ static int __cmd_inject(struct perf_inject *inject)
693 if (!inject->itrace_synth_opts.set) 693 if (!inject->itrace_synth_opts.set)
694 auxtrace_index__free(&session->auxtrace_index); 694 auxtrace_index__free(&session->auxtrace_index);
695 695
696 if (!file_out->is_pipe) 696 if (!data_out->is_pipe)
697 lseek(fd, output_data_offset, SEEK_SET); 697 lseek(fd, output_data_offset, SEEK_SET);
698 698
699 ret = perf_session__process_events(session); 699 ret = perf_session__process_events(session);
700 if (ret) 700 if (ret)
701 return ret; 701 return ret;
702 702
703 if (!file_out->is_pipe) { 703 if (!data_out->is_pipe) {
704 if (inject->build_ids) 704 if (inject->build_ids)
705 perf_header__set_feat(&session->header, 705 perf_header__set_feat(&session->header,
706 HEADER_BUILD_ID); 706 HEADER_BUILD_ID);
@@ -775,11 +775,13 @@ int cmd_inject(int argc, const char **argv)
775 .input_name = "-", 775 .input_name = "-",
776 .samples = LIST_HEAD_INIT(inject.samples), 776 .samples = LIST_HEAD_INIT(inject.samples),
777 .output = { 777 .output = {
778 .path = "-", 778 .file = {
779 .mode = PERF_DATA_MODE_WRITE, 779 .path = "-",
780 },
781 .mode = PERF_DATA_MODE_WRITE,
780 }, 782 },
781 }; 783 };
782 struct perf_data_file file = { 784 struct perf_data data = {
783 .mode = PERF_DATA_MODE_READ, 785 .mode = PERF_DATA_MODE_READ,
784 }; 786 };
785 int ret; 787 int ret;
@@ -789,7 +791,7 @@ int cmd_inject(int argc, const char **argv)
789 "Inject build-ids into the output stream"), 791 "Inject build-ids into the output stream"),
790 OPT_STRING('i', "input", &inject.input_name, "file", 792 OPT_STRING('i', "input", &inject.input_name, "file",
791 "input file name"), 793 "input file name"),
792 OPT_STRING('o', "output", &inject.output.path, "file", 794 OPT_STRING('o', "output", &inject.output.file.path, "file",
793 "output file name"), 795 "output file name"),
794 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, 796 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
795 "Merge sched-stat and sched-switch for getting events " 797 "Merge sched-stat and sched-switch for getting events "
@@ -801,7 +803,7 @@ int cmd_inject(int argc, const char **argv)
801 "be more verbose (show build ids, etc)"), 803 "be more verbose (show build ids, etc)"),
802 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", 804 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
803 "kallsyms pathname"), 805 "kallsyms pathname"),
804 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 806 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
805 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, 807 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
806 NULL, "opts", "Instruction Tracing options", 808 NULL, "opts", "Instruction Tracing options",
807 itrace_parse_synth_opts), 809 itrace_parse_synth_opts),
@@ -829,15 +831,15 @@ int cmd_inject(int argc, const char **argv)
829 return -1; 831 return -1;
830 } 832 }
831 833
832 if (perf_data_file__open(&inject.output)) { 834 if (perf_data__open(&inject.output)) {
833 perror("failed to create output file"); 835 perror("failed to create output file");
834 return -1; 836 return -1;
835 } 837 }
836 838
837 inject.tool.ordered_events = inject.sched_stat; 839 inject.tool.ordered_events = inject.sched_stat;
838 840
839 file.path = inject.input_name; 841 data.file.path = inject.input_name;
840 inject.session = perf_session__new(&file, true, &inject.tool); 842 inject.session = perf_session__new(&data, true, &inject.tool);
841 if (inject.session == NULL) 843 if (inject.session == NULL)
842 return -1; 844 return -1;
843 845
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index d8f25ef8157b..abcab75cc5b9 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1893,7 +1893,7 @@ int cmd_kmem(int argc, const char **argv)
1893{ 1893{
1894 const char * const default_slab_sort = "frag,hit,bytes"; 1894 const char * const default_slab_sort = "frag,hit,bytes";
1895 const char * const default_page_sort = "bytes,hit"; 1895 const char * const default_page_sort = "bytes,hit";
1896 struct perf_data_file file = { 1896 struct perf_data data = {
1897 .mode = PERF_DATA_MODE_READ, 1897 .mode = PERF_DATA_MODE_READ,
1898 }; 1898 };
1899 const struct option kmem_options[] = { 1899 const struct option kmem_options[] = {
@@ -1909,7 +1909,7 @@ int cmd_kmem(int argc, const char **argv)
1909 "page, order, migtype, gfp", parse_sort_opt), 1909 "page, order, migtype, gfp", parse_sort_opt),
1910 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt), 1910 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
1911 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), 1911 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
1912 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 1912 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
1913 OPT_CALLBACK_NOOPT(0, "slab", NULL, NULL, "Analyze slab allocator", 1913 OPT_CALLBACK_NOOPT(0, "slab", NULL, NULL, "Analyze slab allocator",
1914 parse_slab_opt), 1914 parse_slab_opt),
1915 OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator", 1915 OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator",
@@ -1949,9 +1949,9 @@ int cmd_kmem(int argc, const char **argv)
1949 return __cmd_record(argc, argv); 1949 return __cmd_record(argc, argv);
1950 } 1950 }
1951 1951
1952 file.path = input_name; 1952 data.file.path = input_name;
1953 1953
1954 kmem_session = session = perf_session__new(&file, false, &perf_kmem); 1954 kmem_session = session = perf_session__new(&data, false, &perf_kmem);
1955 if (session == NULL) 1955 if (session == NULL)
1956 return -1; 1956 return -1;
1957 1957
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 721f4f91291a..0af4c092b471 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1067,10 +1067,12 @@ static int read_events(struct perf_kvm_stat *kvm)
1067 .namespaces = perf_event__process_namespaces, 1067 .namespaces = perf_event__process_namespaces,
1068 .ordered_events = true, 1068 .ordered_events = true,
1069 }; 1069 };
1070 struct perf_data_file file = { 1070 struct perf_data file = {
1071 .path = kvm->file_name, 1071 .file = {
1072 .mode = PERF_DATA_MODE_READ, 1072 .path = kvm->file_name,
1073 .force = kvm->force, 1073 },
1074 .mode = PERF_DATA_MODE_READ,
1075 .force = kvm->force,
1074 }; 1076 };
1075 1077
1076 kvm->tool = eops; 1078 kvm->tool = eops;
@@ -1358,7 +1360,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1358 "perf kvm stat live [<options>]", 1360 "perf kvm stat live [<options>]",
1359 NULL 1361 NULL
1360 }; 1362 };
1361 struct perf_data_file file = { 1363 struct perf_data data = {
1362 .mode = PERF_DATA_MODE_WRITE, 1364 .mode = PERF_DATA_MODE_WRITE,
1363 }; 1365 };
1364 1366
@@ -1432,7 +1434,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1432 /* 1434 /*
1433 * perf session 1435 * perf session
1434 */ 1436 */
1435 kvm->session = perf_session__new(&file, false, &kvm->tool); 1437 kvm->session = perf_session__new(&data, false, &kvm->tool);
1436 if (kvm->session == NULL) { 1438 if (kvm->session == NULL) {
1437 err = -1; 1439 err = -1;
1438 goto out; 1440 goto out;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ff98652484a7..81af29400b64 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -864,13 +864,15 @@ static int __cmd_report(bool display_info)
864 .namespaces = perf_event__process_namespaces, 864 .namespaces = perf_event__process_namespaces,
865 .ordered_events = true, 865 .ordered_events = true,
866 }; 866 };
867 struct perf_data_file file = { 867 struct perf_data data = {
868 .path = input_name, 868 .file = {
869 .mode = PERF_DATA_MODE_READ, 869 .path = input_name,
870 .force = force, 870 },
871 .mode = PERF_DATA_MODE_READ,
872 .force = force,
871 }; 873 };
872 874
873 session = perf_session__new(&file, false, &eops); 875 session = perf_session__new(&data, false, &eops);
874 if (!session) { 876 if (!session) {
875 pr_err("Initializing perf session failed\n"); 877 pr_err("Initializing perf session failed\n");
876 return -1; 878 return -1;
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 6940490bc3f9..f09fd1a1b813 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -236,13 +236,15 @@ static int process_sample_event(struct perf_tool *tool,
236 236
237static int report_raw_events(struct perf_mem *mem) 237static int report_raw_events(struct perf_mem *mem)
238{ 238{
239 struct perf_data_file file = { 239 struct perf_data data = {
240 .path = input_name, 240 .file = {
241 .mode = PERF_DATA_MODE_READ, 241 .path = input_name,
242 .force = mem->force, 242 },
243 .mode = PERF_DATA_MODE_READ,
244 .force = mem->force,
243 }; 245 };
244 int ret; 246 int ret;
245 struct perf_session *session = perf_session__new(&file, false, 247 struct perf_session *session = perf_session__new(&data, false,
246 &mem->tool); 248 &mem->tool);
247 249
248 if (session == NULL) 250 if (session == NULL)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a6cbf1640269..f4d9fc54b382 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -66,7 +66,7 @@ struct record {
66 struct perf_tool tool; 66 struct perf_tool tool;
67 struct record_opts opts; 67 struct record_opts opts;
68 u64 bytes_written; 68 u64 bytes_written;
69 struct perf_data_file file; 69 struct perf_data data;
70 struct auxtrace_record *itr; 70 struct auxtrace_record *itr;
71 struct perf_evlist *evlist; 71 struct perf_evlist *evlist;
72 struct perf_session *session; 72 struct perf_session *session;
@@ -107,7 +107,7 @@ static bool switch_output_time(struct record *rec)
107 107
108static int record__write(struct record *rec, void *bf, size_t size) 108static int record__write(struct record *rec, void *bf, size_t size)
109{ 109{
110 if (perf_data_file__write(rec->session->file, bf, size) < 0) { 110 if (perf_data__write(rec->session->data, bf, size) < 0) {
111 pr_err("failed to write perf data, error: %m\n"); 111 pr_err("failed to write perf data, error: %m\n");
112 return -1; 112 return -1;
113 } 113 }
@@ -173,13 +173,13 @@ static int record__process_auxtrace(struct perf_tool *tool,
173 size_t len1, void *data2, size_t len2) 173 size_t len1, void *data2, size_t len2)
174{ 174{
175 struct record *rec = container_of(tool, struct record, tool); 175 struct record *rec = container_of(tool, struct record, tool);
176 struct perf_data_file *file = &rec->file; 176 struct perf_data *data = &rec->data;
177 size_t padding; 177 size_t padding;
178 u8 pad[8] = {0}; 178 u8 pad[8] = {0};
179 179
180 if (!perf_data_file__is_pipe(file)) { 180 if (!perf_data__is_pipe(data)) {
181 off_t file_offset; 181 off_t file_offset;
182 int fd = perf_data_file__fd(file); 182 int fd = perf_data__fd(data);
183 int err; 183 int err;
184 184
185 file_offset = lseek(fd, 0, SEEK_CUR); 185 file_offset = lseek(fd, 0, SEEK_CUR);
@@ -398,10 +398,10 @@ static int process_sample_event(struct perf_tool *tool,
398 398
399static int process_buildids(struct record *rec) 399static int process_buildids(struct record *rec)
400{ 400{
401 struct perf_data_file *file = &rec->file; 401 struct perf_data *data = &rec->data;
402 struct perf_session *session = rec->session; 402 struct perf_session *session = rec->session;
403 403
404 if (file->size == 0) 404 if (data->size == 0)
405 return 0; 405 return 0;
406 406
407 /* 407 /*
@@ -544,14 +544,14 @@ static void record__init_features(struct record *rec)
544static void 544static void
545record__finish_output(struct record *rec) 545record__finish_output(struct record *rec)
546{ 546{
547 struct perf_data_file *file = &rec->file; 547 struct perf_data *data = &rec->data;
548 int fd = perf_data_file__fd(file); 548 int fd = perf_data__fd(data);
549 549
550 if (file->is_pipe) 550 if (data->is_pipe)
551 return; 551 return;
552 552
553 rec->session->header.data_size += rec->bytes_written; 553 rec->session->header.data_size += rec->bytes_written;
554 file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 554 data->size = lseek(perf_data__fd(data), 0, SEEK_CUR);
555 555
556 if (!rec->no_buildid) { 556 if (!rec->no_buildid) {
557 process_buildids(rec); 557 process_buildids(rec);
@@ -590,7 +590,7 @@ static int record__synthesize(struct record *rec, bool tail);
590static int 590static int
591record__switch_output(struct record *rec, bool at_exit) 591record__switch_output(struct record *rec, bool at_exit)
592{ 592{
593 struct perf_data_file *file = &rec->file; 593 struct perf_data *data = &rec->data;
594 int fd, err; 594 int fd, err;
595 595
596 /* Same Size: "2015122520103046"*/ 596 /* Same Size: "2015122520103046"*/
@@ -608,7 +608,7 @@ record__switch_output(struct record *rec, bool at_exit)
608 return -EINVAL; 608 return -EINVAL;
609 } 609 }
610 610
611 fd = perf_data_file__switch(file, timestamp, 611 fd = perf_data__switch(data, timestamp,
612 rec->session->header.data_offset, 612 rec->session->header.data_offset,
613 at_exit); 613 at_exit);
614 if (fd >= 0 && !at_exit) { 614 if (fd >= 0 && !at_exit) {
@@ -618,7 +618,7 @@ record__switch_output(struct record *rec, bool at_exit)
618 618
619 if (!quiet) 619 if (!quiet)
620 fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 620 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
621 file->path, timestamp); 621 data->file.path, timestamp);
622 622
623 /* Output tracking events */ 623 /* Output tracking events */
624 if (!at_exit) { 624 if (!at_exit) {
@@ -693,16 +693,16 @@ static int record__synthesize(struct record *rec, bool tail)
693{ 693{
694 struct perf_session *session = rec->session; 694 struct perf_session *session = rec->session;
695 struct machine *machine = &session->machines.host; 695 struct machine *machine = &session->machines.host;
696 struct perf_data_file *file = &rec->file; 696 struct perf_data *data = &rec->data;
697 struct record_opts *opts = &rec->opts; 697 struct record_opts *opts = &rec->opts;
698 struct perf_tool *tool = &rec->tool; 698 struct perf_tool *tool = &rec->tool;
699 int fd = perf_data_file__fd(file); 699 int fd = perf_data__fd(data);
700 int err = 0; 700 int err = 0;
701 701
702 if (rec->opts.tail_synthesize != tail) 702 if (rec->opts.tail_synthesize != tail)
703 return 0; 703 return 0;
704 704
705 if (file->is_pipe) { 705 if (data->is_pipe) {
706 err = perf_event__synthesize_features( 706 err = perf_event__synthesize_features(
707 tool, session, rec->evlist, process_synthesized_event); 707 tool, session, rec->evlist, process_synthesized_event);
708 if (err < 0) { 708 if (err < 0) {
@@ -781,7 +781,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
781 struct machine *machine; 781 struct machine *machine;
782 struct perf_tool *tool = &rec->tool; 782 struct perf_tool *tool = &rec->tool;
783 struct record_opts *opts = &rec->opts; 783 struct record_opts *opts = &rec->opts;
784 struct perf_data_file *file = &rec->file; 784 struct perf_data *data = &rec->data;
785 struct perf_session *session; 785 struct perf_session *session;
786 bool disabled = false, draining = false; 786 bool disabled = false, draining = false;
787 int fd; 787 int fd;
@@ -807,20 +807,20 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
807 signal(SIGUSR2, SIG_IGN); 807 signal(SIGUSR2, SIG_IGN);
808 } 808 }
809 809
810 session = perf_session__new(file, false, tool); 810 session = perf_session__new(data, false, tool);
811 if (session == NULL) { 811 if (session == NULL) {
812 pr_err("Perf session creation failed.\n"); 812 pr_err("Perf session creation failed.\n");
813 return -1; 813 return -1;
814 } 814 }
815 815
816 fd = perf_data_file__fd(file); 816 fd = perf_data__fd(data);
817 rec->session = session; 817 rec->session = session;
818 818
819 record__init_features(rec); 819 record__init_features(rec);
820 820
821 if (forks) { 821 if (forks) {
822 err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 822 err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
823 argv, file->is_pipe, 823 argv, data->is_pipe,
824 workload_exec_failed_signal); 824 workload_exec_failed_signal);
825 if (err < 0) { 825 if (err < 0) {
826 pr_err("Couldn't run the workload!\n"); 826 pr_err("Couldn't run the workload!\n");
@@ -856,7 +856,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
856 if (!rec->evlist->nr_groups) 856 if (!rec->evlist->nr_groups)
857 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 857 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
858 858
859 if (file->is_pipe) { 859 if (data->is_pipe) {
860 err = perf_header__write_pipe(fd); 860 err = perf_header__write_pipe(fd);
861 if (err < 0) 861 if (err < 0)
862 goto out_child; 862 goto out_child;
@@ -1117,8 +1117,8 @@ out_child:
1117 samples[0] = '\0'; 1117 samples[0] = '\0';
1118 1118
1119 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 1119 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
1120 perf_data_file__size(file) / 1024.0 / 1024.0, 1120 perf_data__size(data) / 1024.0 / 1024.0,
1121 file->path, postfix, samples); 1121 data->file.path, postfix, samples);
1122 } 1122 }
1123 1123
1124out_delete_session: 1124out_delete_session:
@@ -1482,7 +1482,7 @@ static struct option __record_options[] = {
1482 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1482 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1483 "list of cpus to monitor"), 1483 "list of cpus to monitor"),
1484 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1484 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1485 OPT_STRING('o', "output", &record.file.path, "file", 1485 OPT_STRING('o', "output", &record.data.file.path, "file",
1486 "output file name"), 1486 "output file name"),
1487 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 1487 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
1488 &record.opts.no_inherit_set, 1488 &record.opts.no_inherit_set,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f9dff652dcbd..3c2d9d4932f3 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -257,7 +257,7 @@ static int report__setup_sample_type(struct report *rep)
257{ 257{
258 struct perf_session *session = rep->session; 258 struct perf_session *session = rep->session;
259 u64 sample_type = perf_evlist__combined_sample_type(session->evlist); 259 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
260 bool is_pipe = perf_data_file__is_pipe(session->file); 260 bool is_pipe = perf_data__is_pipe(session->data);
261 261
262 if (session->itrace_synth_opts->callchain || 262 if (session->itrace_synth_opts->callchain ||
263 (!is_pipe && 263 (!is_pipe &&
@@ -568,7 +568,7 @@ static int __cmd_report(struct report *rep)
568 int ret; 568 int ret;
569 struct perf_session *session = rep->session; 569 struct perf_session *session = rep->session;
570 struct perf_evsel *pos; 570 struct perf_evsel *pos;
571 struct perf_data_file *file = session->file; 571 struct perf_data *data = session->data;
572 572
573 signal(SIGINT, sig_handler); 573 signal(SIGINT, sig_handler);
574 574
@@ -637,7 +637,7 @@ static int __cmd_report(struct report *rep)
637 rep->nr_entries += evsel__hists(pos)->nr_entries; 637 rep->nr_entries += evsel__hists(pos)->nr_entries;
638 638
639 if (rep->nr_entries == 0) { 639 if (rep->nr_entries == 0) {
640 ui__error("The %s file has no samples!\n", file->path); 640 ui__error("The %s file has no samples!\n", data->file.path);
641 return 0; 641 return 0;
642 } 642 }
643 643
@@ -879,7 +879,7 @@ int cmd_report(int argc, const char **argv)
879 "Show inline function"), 879 "Show inline function"),
880 OPT_END() 880 OPT_END()
881 }; 881 };
882 struct perf_data_file file = { 882 struct perf_data data = {
883 .mode = PERF_DATA_MODE_READ, 883 .mode = PERF_DATA_MODE_READ,
884 }; 884 };
885 int ret = hists__init(); 885 int ret = hists__init();
@@ -940,11 +940,11 @@ int cmd_report(int argc, const char **argv)
940 input_name = "perf.data"; 940 input_name = "perf.data";
941 } 941 }
942 942
943 file.path = input_name; 943 data.file.path = input_name;
944 file.force = symbol_conf.force; 944 data.force = symbol_conf.force;
945 945
946repeat: 946repeat:
947 session = perf_session__new(&file, false, &report.tool); 947 session = perf_session__new(&data, false, &report.tool);
948 if (session == NULL) 948 if (session == NULL)
949 return -1; 949 return -1;
950 950
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index b7e8812ee80c..47e54348b5ed 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1700,14 +1700,16 @@ static int perf_sched__read_events(struct perf_sched *sched)
1700 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1700 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1701 }; 1701 };
1702 struct perf_session *session; 1702 struct perf_session *session;
1703 struct perf_data_file file = { 1703 struct perf_data data = {
1704 .path = input_name, 1704 .file = {
1705 .mode = PERF_DATA_MODE_READ, 1705 .path = input_name,
1706 .force = sched->force, 1706 },
1707 .mode = PERF_DATA_MODE_READ,
1708 .force = sched->force,
1707 }; 1709 };
1708 int rc = -1; 1710 int rc = -1;
1709 1711
1710 session = perf_session__new(&file, false, &sched->tool); 1712 session = perf_session__new(&data, false, &sched->tool);
1711 if (session == NULL) { 1713 if (session == NULL) {
1712 pr_debug("No Memory for session\n"); 1714 pr_debug("No Memory for session\n");
1713 return -1; 1715 return -1;
@@ -2902,10 +2904,12 @@ static int perf_sched__timehist(struct perf_sched *sched)
2902 const struct perf_evsel_str_handler migrate_handlers[] = { 2904 const struct perf_evsel_str_handler migrate_handlers[] = {
2903 { "sched:sched_migrate_task", timehist_migrate_task_event, }, 2905 { "sched:sched_migrate_task", timehist_migrate_task_event, },
2904 }; 2906 };
2905 struct perf_data_file file = { 2907 struct perf_data data = {
2906 .path = input_name, 2908 .file = {
2907 .mode = PERF_DATA_MODE_READ, 2909 .path = input_name,
2908 .force = sched->force, 2910 },
2911 .mode = PERF_DATA_MODE_READ,
2912 .force = sched->force,
2909 }; 2913 };
2910 2914
2911 struct perf_session *session; 2915 struct perf_session *session;
@@ -2930,7 +2934,7 @@ static int perf_sched__timehist(struct perf_sched *sched)
2930 2934
2931 symbol_conf.use_callchain = sched->show_callchain; 2935 symbol_conf.use_callchain = sched->show_callchain;
2932 2936
2933 session = perf_session__new(&file, false, &sched->tool); 2937 session = perf_session__new(&data, false, &sched->tool);
2934 if (session == NULL) 2938 if (session == NULL)
2935 return -ENOMEM; 2939 return -ENOMEM;
2936 2940
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index a3add2cd7856..89975e30c0ba 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -210,6 +210,51 @@ static struct {
210 }, 210 },
211}; 211};
212 212
213struct perf_evsel_script {
214 char *filename;
215 FILE *fp;
216 u64 samples;
217};
218
219static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel,
220 struct perf_data *data)
221{
222 struct perf_evsel_script *es = malloc(sizeof(*es));
223
224 if (es != NULL) {
225 if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0)
226 goto out_free;
227 es->fp = fopen(es->filename, "w");
228 if (es->fp == NULL)
229 goto out_free_filename;
230 es->samples = 0;
231 }
232
233 return es;
234out_free_filename:
235 zfree(&es->filename);
236out_free:
237 free(es);
238 return NULL;
239}
240
241static void perf_evsel_script__delete(struct perf_evsel_script *es)
242{
243 zfree(&es->filename);
244 fclose(es->fp);
245 es->fp = NULL;
246 free(es);
247}
248
249static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp)
250{
251 struct stat st;
252
253 fstat(fileno(es->fp), &st);
254 return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n",
255 st.st_size / 1024.0 / 1024.0, es->filename, es->samples);
256}
257
213static inline int output_type(unsigned int type) 258static inline int output_type(unsigned int type)
214{ 259{
215 switch (type) { 260 switch (type) {
@@ -769,27 +814,26 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
769 * but the exit is not. Let the caller patch it up. 814 * but the exit is not. Let the caller patch it up.
770 */ 815 */
771 if (kernel != machine__kernel_ip(machine, end)) { 816 if (kernel != machine__kernel_ip(machine, end)) {
772 printf("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", 817 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", start, end);
773 start, end);
774 return -ENXIO; 818 return -ENXIO;
775 } 819 }
776 820
777 memset(&al, 0, sizeof(al)); 821 memset(&al, 0, sizeof(al));
778 if (end - start > MAXBB - MAXINSN) { 822 if (end - start > MAXBB - MAXINSN) {
779 if (last) 823 if (last)
780 printf("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end); 824 pr_debug("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);
781 else 825 else
782 printf("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start); 826 pr_debug("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start);
783 return 0; 827 return 0;
784 } 828 }
785 829
786 thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al); 830 thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al);
787 if (!al.map || !al.map->dso) { 831 if (!al.map || !al.map->dso) {
788 printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); 832 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
789 return 0; 833 return 0;
790 } 834 }
791 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) { 835 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) {
792 printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); 836 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
793 return 0; 837 return 0;
794 } 838 }
795 839
@@ -802,7 +846,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
802 846
803 *is64bit = al.map->dso->is_64_bit; 847 *is64bit = al.map->dso->is_64_bit;
804 if (len <= 0) 848 if (len <= 0)
805 printf("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n", 849 pr_debug("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",
806 start, end); 850 start, end);
807 return len; 851 return len;
808} 852}
@@ -1393,6 +1437,7 @@ struct perf_script {
1393 bool show_switch_events; 1437 bool show_switch_events;
1394 bool show_namespace_events; 1438 bool show_namespace_events;
1395 bool allocated; 1439 bool allocated;
1440 bool per_event_dump;
1396 struct cpu_map *cpus; 1441 struct cpu_map *cpus;
1397 struct thread_map *threads; 1442 struct thread_map *threads;
1398 int name_width; 1443 int name_width;
@@ -1439,15 +1484,18 @@ static void process_event(struct perf_script *script,
1439 struct thread *thread = al->thread; 1484 struct thread *thread = al->thread;
1440 struct perf_event_attr *attr = &evsel->attr; 1485 struct perf_event_attr *attr = &evsel->attr;
1441 unsigned int type = output_type(attr->type); 1486 unsigned int type = output_type(attr->type);
1442 FILE *fp = stdout; 1487 struct perf_evsel_script *es = evsel->priv;
1488 FILE *fp = es->fp;
1443 1489
1444 if (output[type].fields == 0) 1490 if (output[type].fields == 0)
1445 return; 1491 return;
1446 1492
1493 ++es->samples;
1494
1447 perf_sample__fprintf_start(sample, thread, evsel, fp); 1495 perf_sample__fprintf_start(sample, thread, evsel, fp);
1448 1496
1449 if (PRINT_FIELD(PERIOD)) 1497 if (PRINT_FIELD(PERIOD))
1450 printf("%10" PRIu64 " ", sample->period); 1498 fprintf(fp, "%10" PRIu64 " ", sample->period);
1451 1499
1452 if (PRINT_FIELD(EVNAME)) { 1500 if (PRINT_FIELD(EVNAME)) {
1453 const char *evname = perf_evsel__name(evsel); 1501 const char *evname = perf_evsel__name(evsel);
@@ -1455,8 +1503,7 @@ static void process_event(struct perf_script *script,
1455 if (!script->name_width) 1503 if (!script->name_width)
1456 script->name_width = perf_evlist__max_name_len(script->session->evlist); 1504 script->name_width = perf_evlist__max_name_len(script->session->evlist);
1457 1505
1458 printf("%*s: ", script->name_width, 1506 fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]");
1459 evname ? evname : "[unknown]");
1460 } 1507 }
1461 1508
1462 if (print_flags) 1509 if (print_flags)
@@ -1467,9 +1514,10 @@ static void process_event(struct perf_script *script,
1467 return; 1514 return;
1468 } 1515 }
1469 1516
1470 if (PRINT_FIELD(TRACE)) 1517 if (PRINT_FIELD(TRACE)) {
1471 event_format__print(evsel->tp_format, sample->cpu, 1518 event_format__fprintf(evsel->tp_format, sample->cpu,
1472 sample->raw_data, sample->raw_size); 1519 sample->raw_data, sample->raw_size, fp);
1520 }
1473 1521
1474 if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH)) 1522 if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH))
1475 perf_sample__fprintf_synth(sample, evsel, fp); 1523 perf_sample__fprintf_synth(sample, evsel, fp);
@@ -1513,8 +1561,8 @@ static void process_event(struct perf_script *script,
1513 perf_sample__fprintf_insn(sample, attr, thread, machine, fp); 1561 perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
1514 1562
1515 if (PRINT_FIELD(PHYS_ADDR)) 1563 if (PRINT_FIELD(PHYS_ADDR))
1516 printf("%16" PRIx64, sample->phys_addr); 1564 fprintf(fp, "%16" PRIx64, sample->phys_addr);
1517 printf("\n"); 1565 fprintf(fp, "\n");
1518} 1566}
1519 1567
1520static struct scripting_ops *scripting_ops; 1568static struct scripting_ops *scripting_ops;
@@ -1888,6 +1936,65 @@ static void sig_handler(int sig __maybe_unused)
1888 session_done = 1; 1936 session_done = 1;
1889} 1937}
1890 1938
1939static void perf_script__fclose_per_event_dump(struct perf_script *script)
1940{
1941 struct perf_evlist *evlist = script->session->evlist;
1942 struct perf_evsel *evsel;
1943
1944 evlist__for_each_entry(evlist, evsel) {
1945 if (!evsel->priv)
1946 break;
1947 perf_evsel_script__delete(evsel->priv);
1948 evsel->priv = NULL;
1949 }
1950}
1951
1952static int perf_script__fopen_per_event_dump(struct perf_script *script)
1953{
1954 struct perf_evsel *evsel;
1955
1956 evlist__for_each_entry(script->session->evlist, evsel) {
1957 evsel->priv = perf_evsel_script__new(evsel, script->session->data);
1958 if (evsel->priv == NULL)
1959 goto out_err_fclose;
1960 }
1961
1962 return 0;
1963
1964out_err_fclose:
1965 perf_script__fclose_per_event_dump(script);
1966 return -1;
1967}
1968
1969static int perf_script__setup_per_event_dump(struct perf_script *script)
1970{
1971 struct perf_evsel *evsel;
1972 static struct perf_evsel_script es_stdout;
1973
1974 if (script->per_event_dump)
1975 return perf_script__fopen_per_event_dump(script);
1976
1977 es_stdout.fp = stdout;
1978
1979 evlist__for_each_entry(script->session->evlist, evsel)
1980 evsel->priv = &es_stdout;
1981
1982 return 0;
1983}
1984
1985static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
1986{
1987 struct perf_evsel *evsel;
1988
1989 evlist__for_each_entry(script->session->evlist, evsel) {
1990 struct perf_evsel_script *es = evsel->priv;
1991
1992 perf_evsel_script__fprintf(es, stdout);
1993 perf_evsel_script__delete(es);
1994 evsel->priv = NULL;
1995 }
1996}
1997
1891static int __cmd_script(struct perf_script *script) 1998static int __cmd_script(struct perf_script *script)
1892{ 1999{
1893 int ret; 2000 int ret;
@@ -1909,8 +2016,16 @@ static int __cmd_script(struct perf_script *script)
1909 if (script->show_namespace_events) 2016 if (script->show_namespace_events)
1910 script->tool.namespaces = process_namespaces_event; 2017 script->tool.namespaces = process_namespaces_event;
1911 2018
2019 if (perf_script__setup_per_event_dump(script)) {
2020 pr_err("Couldn't create the per event dump files\n");
2021 return -1;
2022 }
2023
1912 ret = perf_session__process_events(script->session); 2024 ret = perf_session__process_events(script->session);
1913 2025
2026 if (script->per_event_dump)
2027 perf_script__exit_per_event_dump_stats(script);
2028
1914 if (debug_mode) 2029 if (debug_mode)
1915 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 2030 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
1916 2031
@@ -2475,14 +2590,16 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
2475 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; 2590 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
2476 DIR *scripts_dir, *lang_dir; 2591 DIR *scripts_dir, *lang_dir;
2477 struct perf_session *session; 2592 struct perf_session *session;
2478 struct perf_data_file file = { 2593 struct perf_data data = {
2479 .path = input_name, 2594 .file = {
2480 .mode = PERF_DATA_MODE_READ, 2595 .path = input_name,
2596 },
2597 .mode = PERF_DATA_MODE_READ,
2481 }; 2598 };
2482 char *temp; 2599 char *temp;
2483 int i = 0; 2600 int i = 0;
2484 2601
2485 session = perf_session__new(&file, false, NULL); 2602 session = perf_session__new(&data, false, NULL);
2486 if (!session) 2603 if (!session)
2487 return -1; 2604 return -1;
2488 2605
@@ -2760,7 +2877,7 @@ int cmd_script(int argc, const char **argv)
2760 .ordering_requires_timestamps = true, 2877 .ordering_requires_timestamps = true,
2761 }, 2878 },
2762 }; 2879 };
2763 struct perf_data_file file = { 2880 struct perf_data data = {
2764 .mode = PERF_DATA_MODE_READ, 2881 .mode = PERF_DATA_MODE_READ,
2765 }; 2882 };
2766 const struct option options[] = { 2883 const struct option options[] = {
@@ -2828,6 +2945,8 @@ int cmd_script(int argc, const char **argv)
2828 "Show context switch events (if recorded)"), 2945 "Show context switch events (if recorded)"),
2829 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events, 2946 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,
2830 "Show namespace events (if recorded)"), 2947 "Show namespace events (if recorded)"),
2948 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
2949 "Dump trace output to files named by the monitored events"),
2831 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 2950 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
2832 OPT_INTEGER(0, "max-blocks", &max_blocks, 2951 OPT_INTEGER(0, "max-blocks", &max_blocks,
2833 "Maximum number of code blocks to dump with brstackinsn"), 2952 "Maximum number of code blocks to dump with brstackinsn"),
@@ -2865,8 +2984,8 @@ int cmd_script(int argc, const char **argv)
2865 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, 2984 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
2866 PARSE_OPT_STOP_AT_NON_OPTION); 2985 PARSE_OPT_STOP_AT_NON_OPTION);
2867 2986
2868 file.path = input_name; 2987 data.file.path = input_name;
2869 file.force = symbol_conf.force; 2988 data.force = symbol_conf.force;
2870 2989
2871 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 2990 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
2872 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 2991 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
@@ -3033,7 +3152,7 @@ int cmd_script(int argc, const char **argv)
3033 if (!script_name) 3152 if (!script_name)
3034 setup_pager(); 3153 setup_pager();
3035 3154
3036 session = perf_session__new(&file, false, &script.tool); 3155 session = perf_session__new(&data, false, &script.tool);
3037 if (session == NULL) 3156 if (session == NULL)
3038 return -1; 3157 return -1;
3039 3158
@@ -3089,7 +3208,7 @@ int cmd_script(int argc, const char **argv)
3089 goto out_delete; 3208 goto out_delete;
3090 } 3209 }
3091 3210
3092 input = open(file.path, O_RDONLY); /* input_name */ 3211 input = open(data.file.path, O_RDONLY); /* input_name */
3093 if (input < 0) { 3212 if (input < 0) {
3094 err = -errno; 3213 err = -errno;
3095 perror("failed to open file"); 3214 perror("failed to open file");
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index dd525417880a..59af5a8419e2 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -175,7 +175,7 @@ static int print_free_counters_hint;
175 175
176struct perf_stat { 176struct perf_stat {
177 bool record; 177 bool record;
178 struct perf_data_file file; 178 struct perf_data data;
179 struct perf_session *session; 179 struct perf_session *session;
180 u64 bytes_written; 180 u64 bytes_written;
181 struct perf_tool tool; 181 struct perf_tool tool;
@@ -253,7 +253,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
253 * by attr->sample_type != 0, and we can't run it on 253 * by attr->sample_type != 0, and we can't run it on
254 * stat sessions. 254 * stat sessions.
255 */ 255 */
256 if (!(STAT_RECORD && perf_stat.file.is_pipe)) 256 if (!(STAT_RECORD && perf_stat.data.is_pipe))
257 attr->sample_type = PERF_SAMPLE_IDENTIFIER; 257 attr->sample_type = PERF_SAMPLE_IDENTIFIER;
258 258
259 /* 259 /*
@@ -295,7 +295,7 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
295 struct perf_sample *sample __maybe_unused, 295 struct perf_sample *sample __maybe_unused,
296 struct machine *machine __maybe_unused) 296 struct machine *machine __maybe_unused)
297{ 297{
298 if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) { 298 if (perf_data__write(&perf_stat.data, event, event->header.size) < 0) {
299 pr_err("failed to write perf data, error: %m\n"); 299 pr_err("failed to write perf data, error: %m\n");
300 return -1; 300 return -1;
301 } 301 }
@@ -628,7 +628,7 @@ static int __run_perf_stat(int argc, const char **argv)
628 size_t l; 628 size_t l;
629 int status = 0; 629 int status = 0;
630 const bool forks = (argc > 0); 630 const bool forks = (argc > 0);
631 bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false; 631 bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false;
632 struct perf_evsel_config_term *err_term; 632 struct perf_evsel_config_term *err_term;
633 633
634 if (interval) { 634 if (interval) {
@@ -719,10 +719,10 @@ try_again:
719 } 719 }
720 720
721 if (STAT_RECORD) { 721 if (STAT_RECORD) {
722 int err, fd = perf_data_file__fd(&perf_stat.file); 722 int err, fd = perf_data__fd(&perf_stat.data);
723 723
724 if (is_pipe) { 724 if (is_pipe) {
725 err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file)); 725 err = perf_header__write_pipe(perf_data__fd(&perf_stat.data));
726 } else { 726 } else {
727 err = perf_session__write_header(perf_stat.session, evsel_list, 727 err = perf_session__write_header(perf_stat.session, evsel_list,
728 fd, false); 728 fd, false);
@@ -845,7 +845,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)
845 if (run_count == 1) 845 if (run_count == 1)
846 return; 846 return;
847 847
848 ps = evsel->priv; 848 ps = evsel->stats;
849 print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 849 print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
850} 850}
851 851
@@ -1267,8 +1267,7 @@ static void aggr_update_shadow(void)
1267 continue; 1267 continue;
1268 val += perf_counts(counter->counts, cpu, 0)->val; 1268 val += perf_counts(counter->counts, cpu, 0)->val;
1269 } 1269 }
1270 val = val * counter->scale; 1270 perf_stat__update_shadow_stats(counter, val,
1271 perf_stat__update_shadow_stats(counter, &val,
1272 first_shadow_cpu(counter, id)); 1271 first_shadow_cpu(counter, id));
1273 } 1272 }
1274 } 1273 }
@@ -1432,7 +1431,7 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data,
1432 bool first __maybe_unused) 1431 bool first __maybe_unused)
1433{ 1432{
1434 struct caggr_data *cd = data; 1433 struct caggr_data *cd = data;
1435 struct perf_stat_evsel *ps = counter->priv; 1434 struct perf_stat_evsel *ps = counter->stats;
1436 1435
1437 cd->avg += avg_stats(&ps->res_stats[0]); 1436 cd->avg += avg_stats(&ps->res_stats[0]);
1438 cd->avg_enabled += avg_stats(&ps->res_stats[1]); 1437 cd->avg_enabled += avg_stats(&ps->res_stats[1]);
@@ -1696,7 +1695,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1696 char buf[64], *prefix = NULL; 1695 char buf[64], *prefix = NULL;
1697 1696
1698 /* Do not print anything if we record to the pipe. */ 1697 /* Do not print anything if we record to the pipe. */
1699 if (STAT_RECORD && perf_stat.file.is_pipe) 1698 if (STAT_RECORD && perf_stat.data.is_pipe)
1700 return; 1699 return;
1701 1700
1702 if (interval) 1701 if (interval)
@@ -2406,20 +2405,20 @@ static void init_features(struct perf_session *session)
2406static int __cmd_record(int argc, const char **argv) 2405static int __cmd_record(int argc, const char **argv)
2407{ 2406{
2408 struct perf_session *session; 2407 struct perf_session *session;
2409 struct perf_data_file *file = &perf_stat.file; 2408 struct perf_data *data = &perf_stat.data;
2410 2409
2411 argc = parse_options(argc, argv, stat_options, stat_record_usage, 2410 argc = parse_options(argc, argv, stat_options, stat_record_usage,
2412 PARSE_OPT_STOP_AT_NON_OPTION); 2411 PARSE_OPT_STOP_AT_NON_OPTION);
2413 2412
2414 if (output_name) 2413 if (output_name)
2415 file->path = output_name; 2414 data->file.path = output_name;
2416 2415
2417 if (run_count != 1 || forever) { 2416 if (run_count != 1 || forever) {
2418 pr_err("Cannot use -r option with perf stat record.\n"); 2417 pr_err("Cannot use -r option with perf stat record.\n");
2419 return -1; 2418 return -1;
2420 } 2419 }
2421 2420
2422 session = perf_session__new(file, false, NULL); 2421 session = perf_session__new(data, false, NULL);
2423 if (session == NULL) { 2422 if (session == NULL) {
2424 pr_err("Perf session creation failed.\n"); 2423 pr_err("Perf session creation failed.\n");
2425 return -1; 2424 return -1;
@@ -2477,7 +2476,7 @@ int process_stat_config_event(struct perf_tool *tool,
2477 if (st->aggr_mode != AGGR_UNSET) 2476 if (st->aggr_mode != AGGR_UNSET)
2478 stat_config.aggr_mode = st->aggr_mode; 2477 stat_config.aggr_mode = st->aggr_mode;
2479 2478
2480 if (perf_stat.file.is_pipe) 2479 if (perf_stat.data.is_pipe)
2481 perf_stat_init_aggr_mode(); 2480 perf_stat_init_aggr_mode();
2482 else 2481 else
2483 perf_stat_init_aggr_mode_file(st); 2482 perf_stat_init_aggr_mode_file(st);
@@ -2585,10 +2584,10 @@ static int __cmd_report(int argc, const char **argv)
2585 input_name = "perf.data"; 2584 input_name = "perf.data";
2586 } 2585 }
2587 2586
2588 perf_stat.file.path = input_name; 2587 perf_stat.data.file.path = input_name;
2589 perf_stat.file.mode = PERF_DATA_MODE_READ; 2588 perf_stat.data.mode = PERF_DATA_MODE_READ;
2590 2589
2591 session = perf_session__new(&perf_stat.file, false, &perf_stat.tool); 2590 session = perf_session__new(&perf_stat.data, false, &perf_stat.tool);
2592 if (session == NULL) 2591 if (session == NULL)
2593 return -1; 2592 return -1;
2594 2593
@@ -2859,7 +2858,7 @@ int cmd_stat(int argc, const char **argv)
2859 * records, but the need to suppress the kptr_restrict messages in older 2858 * records, but the need to suppress the kptr_restrict messages in older
2860 * tools remain -acme 2859 * tools remain -acme
2861 */ 2860 */
2862 int fd = perf_data_file__fd(&perf_stat.file); 2861 int fd = perf_data__fd(&perf_stat.data);
2863 int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat, 2862 int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
2864 process_synthesized_event, 2863 process_synthesized_event,
2865 &perf_stat.session->machines.host); 2864 &perf_stat.session->machines.host);
@@ -2873,7 +2872,7 @@ int cmd_stat(int argc, const char **argv)
2873 pr_err("failed to write stat round event\n"); 2872 pr_err("failed to write stat round event\n");
2874 } 2873 }
2875 2874
2876 if (!perf_stat.file.is_pipe) { 2875 if (!perf_stat.data.is_pipe) {
2877 perf_stat.session->header.data_size += perf_stat.bytes_written; 2876 perf_stat.session->header.data_size += perf_stat.bytes_written;
2878 perf_session__write_header(perf_stat.session, evsel_list, fd, true); 2877 perf_session__write_header(perf_stat.session, evsel_list, fd, true);
2879 } 2878 }
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 01de01ca14f2..813698a9b8c7 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1601,13 +1601,15 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1601 { "syscalls:sys_exit_pselect6", process_exit_poll }, 1601 { "syscalls:sys_exit_pselect6", process_exit_poll },
1602 { "syscalls:sys_exit_select", process_exit_poll }, 1602 { "syscalls:sys_exit_select", process_exit_poll },
1603 }; 1603 };
1604 struct perf_data_file file = { 1604 struct perf_data data = {
1605 .path = input_name, 1605 .file = {
1606 .mode = PERF_DATA_MODE_READ, 1606 .path = input_name,
1607 .force = tchart->force, 1607 },
1608 .mode = PERF_DATA_MODE_READ,
1609 .force = tchart->force,
1608 }; 1610 };
1609 1611
1610 struct perf_session *session = perf_session__new(&file, false, 1612 struct perf_session *session = perf_session__new(&data, false,
1611 &tchart->tool); 1613 &tchart->tool);
1612 int ret = -EINVAL; 1614 int ret = -EINVAL;
1613 1615
@@ -1617,7 +1619,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1617 symbol__init(&session->header.env); 1619 symbol__init(&session->header.env);
1618 1620
1619 (void)perf_header__process_sections(&session->header, 1621 (void)perf_header__process_sections(&session->header,
1620 perf_data_file__fd(session->file), 1622 perf_data__fd(session->data),
1621 tchart, 1623 tchart,
1622 process_header); 1624 process_header);
1623 1625
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8b23982dd9f2..505b871fdc82 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -578,7 +578,6 @@ static struct syscall_fmt {
578} syscall_fmts[] = { 578} syscall_fmts[] = {
579 { .name = "access", 579 { .name = "access",
580 .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, 580 .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
581 { .name = "arch_prctl", .alias = "prctl", },
582 { .name = "bpf", 581 { .name = "bpf",
583 .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, 582 .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
584 { .name = "brk", .hexret = true, 583 { .name = "brk", .hexret = true,
@@ -634,6 +633,12 @@ static struct syscall_fmt {
634#else 633#else
635 [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, }, 634 [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
636#endif 635#endif
636 { .name = "kcmp", .nr_args = 5,
637 .arg = { [0] = { .name = "pid1", .scnprintf = SCA_PID, },
638 [1] = { .name = "pid2", .scnprintf = SCA_PID, },
639 [2] = { .name = "type", .scnprintf = SCA_KCMP_TYPE, },
640 [3] = { .name = "idx1", .scnprintf = SCA_KCMP_IDX, },
641 [4] = { .name = "idx2", .scnprintf = SCA_KCMP_IDX, }, }, },
637 { .name = "keyctl", 642 { .name = "keyctl",
638 .arg = { [0] = STRARRAY(option, keyctl_options), }, }, 643 .arg = { [0] = STRARRAY(option, keyctl_options), }, },
639 { .name = "kill", 644 { .name = "kill",
@@ -703,6 +708,10 @@ static struct syscall_fmt {
703 [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, }, 708 [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, },
704 { .name = "poll", .timeout = true, }, 709 { .name = "poll", .timeout = true, },
705 { .name = "ppoll", .timeout = true, }, 710 { .name = "ppoll", .timeout = true, },
711 { .name = "prctl", .alias = "arch_prctl",
712 .arg = { [0] = { .scnprintf = SCA_PRCTL_OPTION, /* option */ },
713 [1] = { .scnprintf = SCA_PRCTL_ARG2, /* arg2 */ },
714 [2] = { .scnprintf = SCA_PRCTL_ARG3, /* arg3 */ }, }, },
706 { .name = "pread", .alias = "pread64", }, 715 { .name = "pread", .alias = "pread64", },
707 { .name = "preadv", .alias = "pread", }, 716 { .name = "preadv", .alias = "pread", },
708 { .name = "prlimit64", 717 { .name = "prlimit64",
@@ -985,6 +994,23 @@ size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)
985 return printed; 994 return printed;
986} 995}
987 996
997size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size)
998{
999 size_t printed = scnprintf(bf, size, "%d", fd);
1000 struct thread *thread = machine__find_thread(trace->host, pid, pid);
1001
1002 if (thread) {
1003 const char *path = thread__fd_path(thread, fd, trace);
1004
1005 if (path)
1006 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1007
1008 thread__put(thread);
1009 }
1010
1011 return printed;
1012}
1013
988static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size, 1014static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
989 struct syscall_arg *arg) 1015 struct syscall_arg *arg)
990{ 1016{
@@ -2529,10 +2555,12 @@ static int trace__replay(struct trace *trace)
2529 const struct perf_evsel_str_handler handlers[] = { 2555 const struct perf_evsel_str_handler handlers[] = {
2530 { "probe:vfs_getname", trace__vfs_getname, }, 2556 { "probe:vfs_getname", trace__vfs_getname, },
2531 }; 2557 };
2532 struct perf_data_file file = { 2558 struct perf_data data = {
2533 .path = input_name, 2559 .file = {
2534 .mode = PERF_DATA_MODE_READ, 2560 .path = input_name,
2535 .force = trace->force, 2561 },
2562 .mode = PERF_DATA_MODE_READ,
2563 .force = trace->force,
2536 }; 2564 };
2537 struct perf_session *session; 2565 struct perf_session *session;
2538 struct perf_evsel *evsel; 2566 struct perf_evsel *evsel;
@@ -2555,7 +2583,7 @@ static int trace__replay(struct trace *trace)
2555 /* add tid to output */ 2583 /* add tid to output */
2556 trace->multiple_threads = true; 2584 trace->multiple_threads = true;
2557 2585
2558 session = perf_session__new(&file, false, &trace->tool); 2586 session = perf_session__new(&data, false, &trace->tool);
2559 if (session == NULL) 2587 if (session == NULL)
2560 return -1; 2588 return -1;
2561 2589
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 322629423b49..a3a041b0d35e 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -4,8 +4,10 @@ HEADERS='
4include/uapi/drm/drm.h 4include/uapi/drm/drm.h
5include/uapi/drm/i915_drm.h 5include/uapi/drm/i915_drm.h
6include/uapi/linux/fcntl.h 6include/uapi/linux/fcntl.h
7include/uapi/linux/kcmp.h
7include/uapi/linux/kvm.h 8include/uapi/linux/kvm.h
8include/uapi/linux/perf_event.h 9include/uapi/linux/perf_event.h
10include/uapi/linux/prctl.h
9include/uapi/linux/sched.h 11include/uapi/linux/sched.h
10include/uapi/linux/stat.h 12include/uapi/linux/stat.h
11include/uapi/linux/vhost.h 13include/uapi/linux/vhost.h
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 19b0561fd6f6..9bbfed51f1d6 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -29,12 +29,14 @@ static int get_temp(char *path)
29static int session_write_header(char *path) 29static int session_write_header(char *path)
30{ 30{
31 struct perf_session *session; 31 struct perf_session *session;
32 struct perf_data_file file = { 32 struct perf_data data = {
33 .path = path, 33 .file = {
34 .mode = PERF_DATA_MODE_WRITE, 34 .path = path,
35 },
36 .mode = PERF_DATA_MODE_WRITE,
35 }; 37 };
36 38
37 session = perf_session__new(&file, false, NULL); 39 session = perf_session__new(&data, false, NULL);
38 TEST_ASSERT_VAL("can't get session", session); 40 TEST_ASSERT_VAL("can't get session", session);
39 41
40 session->evlist = perf_evlist__new_default(); 42 session->evlist = perf_evlist__new_default();
@@ -46,7 +48,7 @@ static int session_write_header(char *path)
46 session->header.data_size += DATA_SIZE; 48 session->header.data_size += DATA_SIZE;
47 49
48 TEST_ASSERT_VAL("failed to write header", 50 TEST_ASSERT_VAL("failed to write header",
49 !perf_session__write_header(session, session->evlist, file.fd, true)); 51 !perf_session__write_header(session, session->evlist, data.file.fd, true));
50 52
51 perf_session__delete(session); 53 perf_session__delete(session);
52 54
@@ -56,13 +58,15 @@ static int session_write_header(char *path)
56static int check_cpu_topology(char *path, struct cpu_map *map) 58static int check_cpu_topology(char *path, struct cpu_map *map)
57{ 59{
58 struct perf_session *session; 60 struct perf_session *session;
59 struct perf_data_file file = { 61 struct perf_data data = {
60 .path = path, 62 .file = {
61 .mode = PERF_DATA_MODE_READ, 63 .path = path,
64 },
65 .mode = PERF_DATA_MODE_READ,
62 }; 66 };
63 int i; 67 int i;
64 68
65 session = perf_session__new(&file, false, NULL); 69 session = perf_session__new(&data, false, NULL);
66 TEST_ASSERT_VAL("can't get session", session); 70 TEST_ASSERT_VAL("can't get session", session);
67 71
68 for (i = 0; i < session->header.env.nr_cpus_avail; i++) { 72 for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index 175d633c6b49..066bbf0f4a74 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -3,5 +3,7 @@ libperf-y += fcntl.o
3ifeq ($(SRCARCH),$(filter $(SRCARCH),x86)) 3ifeq ($(SRCARCH),$(filter $(SRCARCH),x86))
4libperf-y += ioctl.o 4libperf-y += ioctl.o
5endif 5endif
6libperf-y += kcmp.o
6libperf-y += pkey_alloc.o 7libperf-y += pkey_alloc.o
8libperf-y += prctl.o
7libperf-y += statx.o 9libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 4b58581a6053..3f067bdab84f 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -3,6 +3,7 @@
3 3
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <linux/types.h> 5#include <linux/types.h>
6#include <sys/types.h>
6 7
7struct strarray { 8struct strarray {
8 int offset; 9 int offset;
@@ -26,6 +27,8 @@ size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const cha
26struct trace; 27struct trace;
27struct thread; 28struct thread;
28 29
30size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size);
31
29/** 32/**
30 * @val: value of syscall argument being formatted 33 * @val: value of syscall argument being formatted
31 * @args: All the args, use syscall_args__val(arg, nth) to access one 34 * @args: All the args, use syscall_args__val(arg, nth) to access one
@@ -78,12 +81,27 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar
78size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg); 81size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg);
79#define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd 82#define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd
80 83
84size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_arg *arg);
85#define SCA_KCMP_TYPE syscall_arg__scnprintf_kcmp_type
86
87size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg);
88#define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx
89
81size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg); 90size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg);
82#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights 91#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights
83 92
84size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg); 93size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg);
85#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags 94#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
86 95
96size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg);
97#define SCA_PRCTL_OPTION syscall_arg__scnprintf_prctl_option
98
99size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg);
100#define SCA_PRCTL_ARG2 syscall_arg__scnprintf_prctl_arg2
101
102size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg);
103#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3
104
87size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg); 105size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
88#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags 106#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags
89 107
diff --git a/tools/perf/trace/beauty/kcmp.c b/tools/perf/trace/beauty/kcmp.c
new file mode 100644
index 000000000000..f62040eb9d5c
--- /dev/null
+++ b/tools/perf/trace/beauty/kcmp.c
@@ -0,0 +1,44 @@
1/*
2 * trace/beauty/kcmp.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <sys/types.h>
12#include <machine.h>
13#include <uapi/linux/kcmp.h>
14
15#include "trace/beauty/generated/kcmp_type_array.c"
16
17size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg)
18{
19 unsigned long fd = arg->val;
20 int type = syscall_arg__val(arg, 2);
21 pid_t pid;
22
23 if (type != KCMP_FILE)
24 return syscall_arg__scnprintf_long(bf, size, arg);
25
26 pid = syscall_arg__val(arg, arg->idx == 3 ? 0 : 1); /* idx1 -> pid1, idx2 -> pid2 */
27 return pid__scnprintf_fd(arg->trace, pid, fd, bf, size);
28}
29
30static size_t kcmp__scnprintf_type(int type, char *bf, size_t size)
31{
32 static DEFINE_STRARRAY(kcmp_types);
33 return strarray__scnprintf(&strarray__kcmp_types, bf, size, "%d", type);
34}
35
36size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_arg *arg)
37{
38 unsigned long type = arg->val;
39
40 if (type != KCMP_FILE)
41 arg->mask |= (1 << 3) | (1 << 4); /* Ignore idx1 and idx2 */
42
43 return kcmp__scnprintf_type(type, bf, size);
44}
diff --git a/tools/perf/trace/beauty/kcmp_type.sh b/tools/perf/trace/beauty/kcmp_type.sh
new file mode 100755
index 000000000000..40d063b8c082
--- /dev/null
+++ b/tools/perf/trace/beauty/kcmp_type.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2
3header_dir=$1
4
5printf "static const char *kcmp_types[] = {\n"
6regex='^[[:space:]]+(KCMP_(\w+)),'
7egrep $regex ${header_dir}/kcmp.h | grep -v KCMP_TYPES, | \
8 sed -r "s/$regex/\1 \2/g" | \
9 xargs printf "\t[%s]\t= \"%s\",\n"
10printf "};\n"
diff --git a/tools/perf/trace/beauty/prctl.c b/tools/perf/trace/beauty/prctl.c
new file mode 100644
index 000000000000..246130dad6c4
--- /dev/null
+++ b/tools/perf/trace/beauty/prctl.c
@@ -0,0 +1,82 @@
1/*
2 * trace/beauty/prctl.c
3 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */
8
9#include "trace/beauty/beauty.h"
10#include <linux/kernel.h>
11#include <uapi/linux/prctl.h>
12
13#include "trace/beauty/generated/prctl_option_array.c"
14
15static size_t prctl__scnprintf_option(int option, char *bf, size_t size)
16{
17 static DEFINE_STRARRAY(prctl_options);
18 return strarray__scnprintf(&strarray__prctl_options, bf, size, "%d", option);
19}
20
21static size_t prctl__scnprintf_set_mm(int option, char *bf, size_t size)
22{
23 static DEFINE_STRARRAY(prctl_set_mm_options);
24 return strarray__scnprintf(&strarray__prctl_set_mm_options, bf, size, "%d", option);
25}
26
27size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg)
28{
29 int option = syscall_arg__val(arg, 0);
30
31 if (option == PR_SET_MM)
32 return prctl__scnprintf_set_mm(arg->val, bf, size);
33 /*
34 * We still don't grab the contents of pointers on entry or exit,
35 * so just print them as hex numbers
36 */
37 if (option == PR_SET_NAME)
38 return syscall_arg__scnprintf_hex(bf, size, arg);
39
40 return syscall_arg__scnprintf_long(bf, size, arg);
41}
42
43size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg)
44{
45 int option = syscall_arg__val(arg, 0);
46
47 if (option == PR_SET_MM)
48 return syscall_arg__scnprintf_hex(bf, size, arg);
49
50 return syscall_arg__scnprintf_long(bf, size, arg);
51}
52
53size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg)
54{
55 unsigned long option = arg->val;
56 enum {
57 SPO_ARG2 = (1 << 1),
58 SPO_ARG3 = (1 << 2),
59 SPO_ARG4 = (1 << 3),
60 SPO_ARG5 = (1 << 4),
61 SPO_ARG6 = (1 << 5),
62 };
63 const u8 all_but2 = SPO_ARG3 | SPO_ARG4 | SPO_ARG5 | SPO_ARG6;
64 const u8 all = SPO_ARG2 | all_but2;
65 const u8 masks[] = {
66 [PR_GET_DUMPABLE] = all,
67 [PR_SET_DUMPABLE] = all_but2,
68 [PR_SET_NAME] = all_but2,
69 [PR_GET_CHILD_SUBREAPER] = all_but2,
70 [PR_SET_CHILD_SUBREAPER] = all_but2,
71 [PR_GET_SECUREBITS] = all,
72 [PR_SET_SECUREBITS] = all_but2,
73 [PR_SET_MM] = SPO_ARG4 | SPO_ARG5 | SPO_ARG6,
74 [PR_GET_PDEATHSIG] = all,
75 [PR_SET_PDEATHSIG] = all_but2,
76 };
77
78 if (option < ARRAY_SIZE(masks))
79 arg->mask |= masks[option];
80
81 return prctl__scnprintf_option(option, bf, size);
82}
diff --git a/tools/perf/trace/beauty/prctl_option.sh b/tools/perf/trace/beauty/prctl_option.sh
new file mode 100755
index 000000000000..0be4138fbe71
--- /dev/null
+++ b/tools/perf/trace/beauty/prctl_option.sh
@@ -0,0 +1,17 @@
1#!/bin/sh
2
3header_dir=$1
4
5printf "static const char *prctl_options[] = {\n"
6regex='^#define[[:space:]]+PR_([GS]ET\w+)[[:space:]]*([[:xdigit:]]+).*'
7egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \
8 sed -r "s/$regex/\2 \1/g" | \
9 sort -n | xargs printf "\t[%s] = \"%s\",\n"
10printf "};\n"
11
12printf "static const char *prctl_set_mm_options[] = {\n"
13regex='^#[[:space:]]+define[[:space:]]+PR_SET_MM_(\w+)[[:space:]]*([[:digit:]]+).*'
14egrep $regex ${header_dir}/prctl.h | \
15 sed -r "s/$regex/\2 \1/g" | \
16 sort -n | xargs printf "\t[%s] = \"%s\",\n"
17printf "};\n"
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 5547457566a7..a33491416400 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -208,7 +208,7 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues,
208 208
209static void *auxtrace_copy_data(u64 size, struct perf_session *session) 209static void *auxtrace_copy_data(u64 size, struct perf_session *session)
210{ 210{
211 int fd = perf_data_file__fd(session->file); 211 int fd = perf_data__fd(session->data);
212 void *p; 212 void *p;
213 ssize_t ret; 213 ssize_t ret;
214 214
@@ -305,7 +305,7 @@ static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues,
305 if (session->one_mmap) { 305 if (session->one_mmap) {
306 buffer->data = buffer->data_offset - session->one_mmap_offset + 306 buffer->data = buffer->data_offset - session->one_mmap_offset +
307 session->one_mmap_addr; 307 session->one_mmap_addr;
308 } else if (perf_data_file__is_pipe(session->file)) { 308 } else if (perf_data__is_pipe(session->data)) {
309 buffer->data = auxtrace_copy_data(buffer->size, session); 309 buffer->data = auxtrace_copy_data(buffer->size, session);
310 if (!buffer->data) 310 if (!buffer->data)
311 return -ENOMEM; 311 return -ENOMEM;
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 3a3916934a92..837012147c7b 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -1091,10 +1091,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
1091 al->map = node->map; 1091 al->map = node->map;
1092 al->sym = node->sym; 1092 al->sym = node->sym;
1093 al->srcline = node->srcline; 1093 al->srcline = node->srcline;
1094 if (node->map) 1094 al->addr = node->ip;
1095 al->addr = node->map->map_ip(node->map, node->ip);
1096 else
1097 al->addr = node->ip;
1098 1095
1099 if (al->sym == NULL) { 1096 if (al->sym == NULL) {
1100 if (hide_unresolved) 1097 if (hide_unresolved)
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 2346cecb8ea2..5744c12641a5 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1577,10 +1577,10 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1577 struct perf_data_convert_opts *opts) 1577 struct perf_data_convert_opts *opts)
1578{ 1578{
1579 struct perf_session *session; 1579 struct perf_session *session;
1580 struct perf_data_file file = { 1580 struct perf_data data = {
1581 .path = input, 1581 .file.path = input,
1582 .mode = PERF_DATA_MODE_READ, 1582 .mode = PERF_DATA_MODE_READ,
1583 .force = opts->force, 1583 .force = opts->force,
1584 }; 1584 };
1585 struct convert c = { 1585 struct convert c = {
1586 .tool = { 1586 .tool = {
@@ -1619,7 +1619,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1619 1619
1620 err = -1; 1620 err = -1;
1621 /* perf.data session */ 1621 /* perf.data session */
1622 session = perf_session__new(&file, 0, &c.tool); 1622 session = perf_session__new(&data, 0, &c.tool);
1623 if (!session) 1623 if (!session)
1624 goto free_writer; 1624 goto free_writer;
1625 1625
@@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1650 1650
1651 fprintf(stderr, 1651 fprintf(stderr,
1652 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", 1652 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
1653 file.path, path); 1653 data.file.path, path);
1654 1654
1655 fprintf(stderr, 1655 fprintf(stderr,
1656 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples", 1656 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 1123b30e3033..f80a23d031d6 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -21,56 +21,56 @@
21#endif 21#endif
22#endif 22#endif
23 23
24static bool check_pipe(struct perf_data_file *file) 24static bool check_pipe(struct perf_data *data)
25{ 25{
26 struct stat st; 26 struct stat st;
27 bool is_pipe = false; 27 bool is_pipe = false;
28 int fd = perf_data_file__is_read(file) ? 28 int fd = perf_data__is_read(data) ?
29 STDIN_FILENO : STDOUT_FILENO; 29 STDIN_FILENO : STDOUT_FILENO;
30 30
31 if (!file->path) { 31 if (!data->file.path) {
32 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) 32 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
33 is_pipe = true; 33 is_pipe = true;
34 } else { 34 } else {
35 if (!strcmp(file->path, "-")) 35 if (!strcmp(data->file.path, "-"))
36 is_pipe = true; 36 is_pipe = true;
37 } 37 }
38 38
39 if (is_pipe) 39 if (is_pipe)
40 file->fd = fd; 40 data->file.fd = fd;
41 41
42 return file->is_pipe = is_pipe; 42 return data->is_pipe = is_pipe;
43} 43}
44 44
45static int check_backup(struct perf_data_file *file) 45static int check_backup(struct perf_data *data)
46{ 46{
47 struct stat st; 47 struct stat st;
48 48
49 if (!stat(file->path, &st) && st.st_size) { 49 if (!stat(data->file.path, &st) && st.st_size) {
50 /* TODO check errors properly */ 50 /* TODO check errors properly */
51 char oldname[PATH_MAX]; 51 char oldname[PATH_MAX];
52 snprintf(oldname, sizeof(oldname), "%s.old", 52 snprintf(oldname, sizeof(oldname), "%s.old",
53 file->path); 53 data->file.path);
54 unlink(oldname); 54 unlink(oldname);
55 rename(file->path, oldname); 55 rename(data->file.path, oldname);
56 } 56 }
57 57
58 return 0; 58 return 0;
59} 59}
60 60
61static int open_file_read(struct perf_data_file *file) 61static int open_file_read(struct perf_data *data)
62{ 62{
63 struct stat st; 63 struct stat st;
64 int fd; 64 int fd;
65 char sbuf[STRERR_BUFSIZE]; 65 char sbuf[STRERR_BUFSIZE];
66 66
67 fd = open(file->path, O_RDONLY); 67 fd = open(data->file.path, O_RDONLY);
68 if (fd < 0) { 68 if (fd < 0) {
69 int err = errno; 69 int err = errno;
70 70
71 pr_err("failed to open %s: %s", file->path, 71 pr_err("failed to open %s: %s", data->file.path,
72 str_error_r(err, sbuf, sizeof(sbuf))); 72 str_error_r(err, sbuf, sizeof(sbuf)));
73 if (err == ENOENT && !strcmp(file->path, "perf.data")) 73 if (err == ENOENT && !strcmp(data->file.path, "perf.data"))
74 pr_err(" (try 'perf record' first)"); 74 pr_err(" (try 'perf record' first)");
75 pr_err("\n"); 75 pr_err("\n");
76 return -err; 76 return -err;
@@ -79,19 +79,19 @@ static int open_file_read(struct perf_data_file *file)
79 if (fstat(fd, &st) < 0) 79 if (fstat(fd, &st) < 0)
80 goto out_close; 80 goto out_close;
81 81
82 if (!file->force && st.st_uid && (st.st_uid != geteuid())) { 82 if (!data->force && st.st_uid && (st.st_uid != geteuid())) {
83 pr_err("File %s not owned by current user or root (use -f to override)\n", 83 pr_err("File %s not owned by current user or root (use -f to override)\n",
84 file->path); 84 data->file.path);
85 goto out_close; 85 goto out_close;
86 } 86 }
87 87
88 if (!st.st_size) { 88 if (!st.st_size) {
89 pr_info("zero-sized file (%s), nothing to do!\n", 89 pr_info("zero-sized data (%s), nothing to do!\n",
90 file->path); 90 data->file.path);
91 goto out_close; 91 goto out_close;
92 } 92 }
93 93
94 file->size = st.st_size; 94 data->size = st.st_size;
95 return fd; 95 return fd;
96 96
97 out_close: 97 out_close:
@@ -99,49 +99,49 @@ static int open_file_read(struct perf_data_file *file)
99 return -1; 99 return -1;
100} 100}
101 101
102static int open_file_write(struct perf_data_file *file) 102static int open_file_write(struct perf_data *data)
103{ 103{
104 int fd; 104 int fd;
105 char sbuf[STRERR_BUFSIZE]; 105 char sbuf[STRERR_BUFSIZE];
106 106
107 if (check_backup(file)) 107 if (check_backup(data))
108 return -1; 108 return -1;
109 109
110 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 110 fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC,
111 S_IRUSR|S_IWUSR); 111 S_IRUSR|S_IWUSR);
112 112
113 if (fd < 0) 113 if (fd < 0)
114 pr_err("failed to open %s : %s\n", file->path, 114 pr_err("failed to open %s : %s\n", data->file.path,
115 str_error_r(errno, sbuf, sizeof(sbuf))); 115 str_error_r(errno, sbuf, sizeof(sbuf)));
116 116
117 return fd; 117 return fd;
118} 118}
119 119
120static int open_file(struct perf_data_file *file) 120static int open_file(struct perf_data *data)
121{ 121{
122 int fd; 122 int fd;
123 123
124 fd = perf_data_file__is_read(file) ? 124 fd = perf_data__is_read(data) ?
125 open_file_read(file) : open_file_write(file); 125 open_file_read(data) : open_file_write(data);
126 126
127 file->fd = fd; 127 data->file.fd = fd;
128 return fd < 0 ? -1 : 0; 128 return fd < 0 ? -1 : 0;
129} 129}
130 130
131int perf_data_file__open(struct perf_data_file *file) 131int perf_data__open(struct perf_data *data)
132{ 132{
133 if (check_pipe(file)) 133 if (check_pipe(data))
134 return 0; 134 return 0;
135 135
136 if (!file->path) 136 if (!data->file.path)
137 file->path = "perf.data"; 137 data->file.path = "perf.data";
138 138
139 return open_file(file); 139 return open_file(data);
140} 140}
141 141
142void perf_data_file__close(struct perf_data_file *file) 142void perf_data__close(struct perf_data *data)
143{ 143{
144 close(file->fd); 144 close(data->file.fd);
145} 145}
146 146
147ssize_t perf_data_file__write(struct perf_data_file *file, 147ssize_t perf_data_file__write(struct perf_data_file *file,
@@ -150,42 +150,48 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
150 return writen(file->fd, buf, size); 150 return writen(file->fd, buf, size);
151} 151}
152 152
153int perf_data_file__switch(struct perf_data_file *file, 153ssize_t perf_data__write(struct perf_data *data,
154 void *buf, size_t size)
155{
156 return perf_data_file__write(&data->file, buf, size);
157}
158
159int perf_data__switch(struct perf_data *data,
154 const char *postfix, 160 const char *postfix,
155 size_t pos, bool at_exit) 161 size_t pos, bool at_exit)
156{ 162{
157 char *new_filepath; 163 char *new_filepath;
158 int ret; 164 int ret;
159 165
160 if (check_pipe(file)) 166 if (check_pipe(data))
161 return -EINVAL; 167 return -EINVAL;
162 if (perf_data_file__is_read(file)) 168 if (perf_data__is_read(data))
163 return -EINVAL; 169 return -EINVAL;
164 170
165 if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0) 171 if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0)
166 return -ENOMEM; 172 return -ENOMEM;
167 173
168 /* 174 /*
169 * Only fire a warning, don't return error, continue fill 175 * Only fire a warning, don't return error, continue fill
170 * original file. 176 * original file.
171 */ 177 */
172 if (rename(file->path, new_filepath)) 178 if (rename(data->file.path, new_filepath))
173 pr_warning("Failed to rename %s to %s\n", file->path, new_filepath); 179 pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath);
174 180
175 if (!at_exit) { 181 if (!at_exit) {
176 close(file->fd); 182 close(data->file.fd);
177 ret = perf_data_file__open(file); 183 ret = perf_data__open(data);
178 if (ret < 0) 184 if (ret < 0)
179 goto out; 185 goto out;
180 186
181 if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) { 187 if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) {
182 ret = -errno; 188 ret = -errno;
183 pr_debug("Failed to lseek to %zu: %s", 189 pr_debug("Failed to lseek to %zu: %s",
184 pos, strerror(errno)); 190 pos, strerror(errno));
185 goto out; 191 goto out;
186 } 192 }
187 } 193 }
188 ret = file->fd; 194 ret = data->file.fd;
189out: 195out:
190 free(new_filepath); 196 free(new_filepath);
191 return ret; 197 return ret;
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index ae510ce16cb1..000c43bbb7ac 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -9,51 +9,57 @@ enum perf_data_mode {
9}; 9};
10 10
11struct perf_data_file { 11struct perf_data_file {
12 const char *path; 12 const char *path;
13 int fd; 13 int fd;
14};
15
16struct perf_data {
17 struct perf_data_file file;
14 bool is_pipe; 18 bool is_pipe;
15 bool force; 19 bool force;
16 unsigned long size; 20 unsigned long size;
17 enum perf_data_mode mode; 21 enum perf_data_mode mode;
18}; 22};
19 23
20static inline bool perf_data_file__is_read(struct perf_data_file *file) 24static inline bool perf_data__is_read(struct perf_data *data)
21{ 25{
22 return file->mode == PERF_DATA_MODE_READ; 26 return data->mode == PERF_DATA_MODE_READ;
23} 27}
24 28
25static inline bool perf_data_file__is_write(struct perf_data_file *file) 29static inline bool perf_data__is_write(struct perf_data *data)
26{ 30{
27 return file->mode == PERF_DATA_MODE_WRITE; 31 return data->mode == PERF_DATA_MODE_WRITE;
28} 32}
29 33
30static inline int perf_data_file__is_pipe(struct perf_data_file *file) 34static inline int perf_data__is_pipe(struct perf_data *data)
31{ 35{
32 return file->is_pipe; 36 return data->is_pipe;
33} 37}
34 38
35static inline int perf_data_file__fd(struct perf_data_file *file) 39static inline int perf_data__fd(struct perf_data *data)
36{ 40{
37 return file->fd; 41 return data->file.fd;
38} 42}
39 43
40static inline unsigned long perf_data_file__size(struct perf_data_file *file) 44static inline unsigned long perf_data__size(struct perf_data *data)
41{ 45{
42 return file->size; 46 return data->size;
43} 47}
44 48
45int perf_data_file__open(struct perf_data_file *file); 49int perf_data__open(struct perf_data *data);
46void perf_data_file__close(struct perf_data_file *file); 50void perf_data__close(struct perf_data *data);
51ssize_t perf_data__write(struct perf_data *data,
52 void *buf, size_t size);
47ssize_t perf_data_file__write(struct perf_data_file *file, 53ssize_t perf_data_file__write(struct perf_data_file *file,
48 void *buf, size_t size); 54 void *buf, size_t size);
49/* 55/*
50 * If at_exit is set, only rename current perf.data to 56 * If at_exit is set, only rename current perf.data to
51 * perf.data.<postfix>, continue write on original file. 57 * perf.data.<postfix>, continue write on original data.
52 * Set at_exit when flushing the last output. 58 * Set at_exit when flushing the last output.
53 * 59 *
54 * Return value is fd of new output. 60 * Return value is fd of new output.
55 */ 61 */
56int perf_data_file__switch(struct perf_data_file *file, 62int perf_data__switch(struct perf_data *data,
57 const char *postfix, 63 const char *postfix,
58 size_t pos, bool at_exit); 64 size_t pos, bool at_exit);
59#endif /* __PERF_DATA_H */ 65#endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index db658785d828..64782b19089d 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -68,6 +68,8 @@ struct perf_evsel_config_term {
68 } val; 68 } val;
69}; 69};
70 70
71struct perf_stat_evsel;
72
71/** struct perf_evsel - event selector 73/** struct perf_evsel - event selector
72 * 74 *
73 * @evlist - evlist this evsel is in, if it is in one. 75 * @evlist - evlist this evsel is in, if it is in one.
@@ -101,6 +103,7 @@ struct perf_evsel {
101 const char *unit; 103 const char *unit;
102 struct event_format *tp_format; 104 struct event_format *tp_format;
103 off_t id_offset; 105 off_t id_offset;
106 struct perf_stat_evsel *stats;
104 void *priv; 107 void *priv;
105 u64 db_id; 108 u64 db_id;
106 struct cgroup_sel *cgrp; 109 struct cgroup_sel *cgrp;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 605bbd5404fb..6e59dcca9df2 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1762,7 +1762,7 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
1762 1762
1763 session = container_of(ff->ph, struct perf_session, header); 1763 session = container_of(ff->ph, struct perf_session, header);
1764 1764
1765 if (session->file->is_pipe) { 1765 if (session->data->is_pipe) {
1766 /* Save events for reading later by print_event_desc, 1766 /* Save events for reading later by print_event_desc,
1767 * since they can't be read again in pipe mode. */ 1767 * since they can't be read again in pipe mode. */
1768 ff->events = events; 1768 ff->events = events;
@@ -1771,7 +1771,7 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused)
1771 for (evsel = events; evsel->attr.size; evsel++) 1771 for (evsel = events; evsel->attr.size; evsel++)
1772 perf_evlist__set_event_name(session->evlist, evsel); 1772 perf_evlist__set_event_name(session->evlist, evsel);
1773 1773
1774 if (!session->file->is_pipe) 1774 if (!session->data->is_pipe)
1775 free_event_desc(events); 1775 free_event_desc(events);
1776 1776
1777 return 0; 1777 return 0;
@@ -2248,7 +2248,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2248{ 2248{
2249 struct header_print_data hd; 2249 struct header_print_data hd;
2250 struct perf_header *header = &session->header; 2250 struct perf_header *header = &session->header;
2251 int fd = perf_data_file__fd(session->file); 2251 int fd = perf_data__fd(session->data);
2252 struct stat st; 2252 struct stat st;
2253 int ret, bit; 2253 int ret, bit;
2254 2254
@@ -2264,7 +2264,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2264 perf_header__process_sections(header, fd, &hd, 2264 perf_header__process_sections(header, fd, &hd,
2265 perf_file_section__fprintf_info); 2265 perf_file_section__fprintf_info);
2266 2266
2267 if (session->file->is_pipe) 2267 if (session->data->is_pipe)
2268 return 0; 2268 return 0;
2269 2269
2270 fprintf(fp, "# missing features: "); 2270 fprintf(fp, "# missing features: ");
@@ -2757,7 +2757,7 @@ static int perf_header__read_pipe(struct perf_session *session)
2757 struct perf_pipe_file_header f_header; 2757 struct perf_pipe_file_header f_header;
2758 2758
2759 if (perf_file_header__read_pipe(&f_header, header, 2759 if (perf_file_header__read_pipe(&f_header, header,
2760 perf_data_file__fd(session->file), 2760 perf_data__fd(session->data),
2761 session->repipe) < 0) { 2761 session->repipe) < 0) {
2762 pr_debug("incompatible file format\n"); 2762 pr_debug("incompatible file format\n");
2763 return -EINVAL; 2763 return -EINVAL;
@@ -2860,13 +2860,13 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2860 2860
2861int perf_session__read_header(struct perf_session *session) 2861int perf_session__read_header(struct perf_session *session)
2862{ 2862{
2863 struct perf_data_file *file = session->file; 2863 struct perf_data *data = session->data;
2864 struct perf_header *header = &session->header; 2864 struct perf_header *header = &session->header;
2865 struct perf_file_header f_header; 2865 struct perf_file_header f_header;
2866 struct perf_file_attr f_attr; 2866 struct perf_file_attr f_attr;
2867 u64 f_id; 2867 u64 f_id;
2868 int nr_attrs, nr_ids, i, j; 2868 int nr_attrs, nr_ids, i, j;
2869 int fd = perf_data_file__fd(file); 2869 int fd = perf_data__fd(data);
2870 2870
2871 session->evlist = perf_evlist__new(); 2871 session->evlist = perf_evlist__new();
2872 if (session->evlist == NULL) 2872 if (session->evlist == NULL)
@@ -2874,7 +2874,7 @@ int perf_session__read_header(struct perf_session *session)
2874 2874
2875 session->evlist->env = &header->env; 2875 session->evlist->env = &header->env;
2876 session->machines.host.env = &header->env; 2876 session->machines.host.env = &header->env;
2877 if (perf_data_file__is_pipe(file)) 2877 if (perf_data__is_pipe(data))
2878 return perf_header__read_pipe(session); 2878 return perf_header__read_pipe(session);
2879 2879
2880 if (perf_file_header__read(&f_header, header, fd) < 0) 2880 if (perf_file_header__read(&f_header, header, fd) < 0)
@@ -2889,7 +2889,7 @@ int perf_session__read_header(struct perf_session *session)
2889 if (f_header.data.size == 0) { 2889 if (f_header.data.size == 0) {
2890 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" 2890 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n"
2891 "Was the 'perf record' command properly terminated?\n", 2891 "Was the 'perf record' command properly terminated?\n",
2892 file->path); 2892 data->file.path);
2893 } 2893 }
2894 2894
2895 nr_attrs = f_header.attrs.size / f_header.attr_size; 2895 nr_attrs = f_header.attrs.size / f_header.attr_size;
@@ -3397,7 +3397,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3397 struct perf_session *session) 3397 struct perf_session *session)
3398{ 3398{
3399 ssize_t size_read, padding, size = event->tracing_data.size; 3399 ssize_t size_read, padding, size = event->tracing_data.size;
3400 int fd = perf_data_file__fd(session->file); 3400 int fd = perf_data__fd(session->data);
3401 off_t offset = lseek(fd, 0, SEEK_CUR); 3401 off_t offset = lseek(fd, 0, SEEK_CUR);
3402 char buf[BUFSIZ]; 3402 char buf[BUFSIZ];
3403 3403
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 218ee2bac9a5..5325e65f9711 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -500,7 +500,7 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp)
500 } 500 }
501 501
502 if (!buffer->data) { 502 if (!buffer->data) {
503 int fd = perf_data_file__fd(btsq->bts->session->file); 503 int fd = perf_data__fd(btsq->bts->session->data);
504 504
505 buffer->data = auxtrace_buffer__get_data(buffer, fd); 505 buffer->data = auxtrace_buffer__get_data(buffer, fd);
506 if (!buffer->data) { 506 if (!buffer->data) {
@@ -664,10 +664,10 @@ static int intel_bts_process_auxtrace_event(struct perf_session *session,
664 if (!bts->data_queued) { 664 if (!bts->data_queued) {
665 struct auxtrace_buffer *buffer; 665 struct auxtrace_buffer *buffer;
666 off_t data_offset; 666 off_t data_offset;
667 int fd = perf_data_file__fd(session->file); 667 int fd = perf_data__fd(session->data);
668 int err; 668 int err;
669 669
670 if (perf_data_file__is_pipe(session->file)) { 670 if (perf_data__is_pipe(session->data)) {
671 data_offset = 0; 671 data_offset = 0;
672 } else { 672 } else {
673 data_offset = lseek(fd, 0, SEEK_CUR); 673 data_offset = lseek(fd, 0, SEEK_CUR);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index b58f9fd1e2ee..23f9ba676df0 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -271,7 +271,7 @@ next:
271 ptq->buffer = buffer; 271 ptq->buffer = buffer;
272 272
273 if (!buffer->data) { 273 if (!buffer->data) {
274 int fd = perf_data_file__fd(ptq->pt->session->file); 274 int fd = perf_data__fd(ptq->pt->session->data);
275 275
276 buffer->data = auxtrace_buffer__get_data(buffer, fd); 276 buffer->data = auxtrace_buffer__get_data(buffer, fd);
277 if (!buffer->data) 277 if (!buffer->data)
@@ -2084,10 +2084,10 @@ static int intel_pt_process_auxtrace_event(struct perf_session *session,
2084 if (!pt->data_queued) { 2084 if (!pt->data_queued) {
2085 struct auxtrace_buffer *buffer; 2085 struct auxtrace_buffer *buffer;
2086 off_t data_offset; 2086 off_t data_offset;
2087 int fd = perf_data_file__fd(session->file); 2087 int fd = perf_data__fd(session->data);
2088 int err; 2088 int err;
2089 2089
2090 if (perf_data_file__is_pipe(session->file)) { 2090 if (perf_data__is_pipe(session->data)) {
2091 data_offset = 0; 2091 data_offset = 0;
2092 } else { 2092 } else {
2093 data_offset = lseek(fd, 0, SEEK_CUR); 2093 data_offset = lseek(fd, 0, SEEK_CUR);
diff --git a/tools/perf/util/jit.h b/tools/perf/util/jit.h
index 3f42ee4d2a0b..961e7a8a0e17 100644
--- a/tools/perf/util/jit.h
+++ b/tools/perf/util/jit.h
@@ -3,7 +3,7 @@
3 3
4#include <data.h> 4#include <data.h>
5 5
6int jit_process(struct perf_session *session, struct perf_data_file *output, 6int jit_process(struct perf_session *session, struct perf_data *output,
7 struct machine *machine, char *filename, pid_t pid, u64 *nbytes); 7 struct machine *machine, char *filename, pid_t pid, u64 *nbytes);
8 8
9int jit_inject_record(const char *filename); 9int jit_inject_record(const char *filename);
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index 9084930e1757..e7645098a323 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -29,7 +29,7 @@
29#include "sane_ctype.h" 29#include "sane_ctype.h"
30 30
31struct jit_buf_desc { 31struct jit_buf_desc {
32 struct perf_data_file *output; 32 struct perf_data *output;
33 struct perf_session *session; 33 struct perf_session *session;
34 struct machine *machine; 34 struct machine *machine;
35 union jr_entry *entry; 35 union jr_entry *entry;
@@ -60,8 +60,8 @@ struct debug_line_info {
60 60
61struct jit_tool { 61struct jit_tool {
62 struct perf_tool tool; 62 struct perf_tool tool;
63 struct perf_data_file output; 63 struct perf_data output;
64 struct perf_data_file input; 64 struct perf_data input;
65 u64 bytes_written; 65 u64 bytes_written;
66}; 66};
67 67
@@ -356,7 +356,7 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
356{ 356{
357 ssize_t size; 357 ssize_t size;
358 358
359 size = perf_data_file__write(jd->output, event, event->header.size); 359 size = perf_data__write(jd->output, event, event->header.size);
360 if (size < 0) 360 if (size < 0)
361 return -1; 361 return -1;
362 362
@@ -751,7 +751,7 @@ jit_detect(char *mmap_name, pid_t pid)
751 751
752int 752int
753jit_process(struct perf_session *session, 753jit_process(struct perf_session *session,
754 struct perf_data_file *output, 754 struct perf_data *output,
755 struct machine *machine, 755 struct machine *machine,
756 char *filename, 756 char *filename,
757 pid_t pid, 757 pid_t pid,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b3fd62f7e4c9..c09b748ab599 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -32,14 +32,14 @@ static int perf_session__deliver_event(struct perf_session *session,
32 32
33static int perf_session__open(struct perf_session *session) 33static int perf_session__open(struct perf_session *session)
34{ 34{
35 struct perf_data_file *file = session->file; 35 struct perf_data *data = session->data;
36 36
37 if (perf_session__read_header(session) < 0) { 37 if (perf_session__read_header(session) < 0) {
38 pr_err("incompatible file format (rerun with -v to learn more)\n"); 38 pr_err("incompatible file format (rerun with -v to learn more)\n");
39 return -1; 39 return -1;
40 } 40 }
41 41
42 if (perf_data_file__is_pipe(file)) 42 if (perf_data__is_pipe(data))
43 return 0; 43 return 0;
44 44
45 if (perf_header__has_feat(&session->header, HEADER_STAT)) 45 if (perf_header__has_feat(&session->header, HEADER_STAT))
@@ -120,7 +120,7 @@ static int ordered_events__deliver_event(struct ordered_events *oe,
120 session->tool, event->file_offset); 120 session->tool, event->file_offset);
121} 121}
122 122
123struct perf_session *perf_session__new(struct perf_data_file *file, 123struct perf_session *perf_session__new(struct perf_data *data,
124 bool repipe, struct perf_tool *tool) 124 bool repipe, struct perf_tool *tool)
125{ 125{
126 struct perf_session *session = zalloc(sizeof(*session)); 126 struct perf_session *session = zalloc(sizeof(*session));
@@ -134,13 +134,13 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
134 machines__init(&session->machines); 134 machines__init(&session->machines);
135 ordered_events__init(&session->ordered_events, ordered_events__deliver_event); 135 ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
136 136
137 if (file) { 137 if (data) {
138 if (perf_data_file__open(file)) 138 if (perf_data__open(data))
139 goto out_delete; 139 goto out_delete;
140 140
141 session->file = file; 141 session->data = data;
142 142
143 if (perf_data_file__is_read(file)) { 143 if (perf_data__is_read(data)) {
144 if (perf_session__open(session) < 0) 144 if (perf_session__open(session) < 0)
145 goto out_close; 145 goto out_close;
146 146
@@ -148,7 +148,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
148 * set session attributes that are present in perf.data 148 * set session attributes that are present in perf.data
149 * but not in pipe-mode. 149 * but not in pipe-mode.
150 */ 150 */
151 if (!file->is_pipe) { 151 if (!data->is_pipe) {
152 perf_session__set_id_hdr_size(session); 152 perf_session__set_id_hdr_size(session);
153 perf_session__set_comm_exec(session); 153 perf_session__set_comm_exec(session);
154 } 154 }
@@ -157,7 +157,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
157 session->machines.host.env = &perf_env; 157 session->machines.host.env = &perf_env;
158 } 158 }
159 159
160 if (!file || perf_data_file__is_write(file)) { 160 if (!data || perf_data__is_write(data)) {
161 /* 161 /*
162 * In O_RDONLY mode this will be performed when reading the 162 * In O_RDONLY mode this will be performed when reading the
163 * kernel MMAP event, in perf_event__process_mmap(). 163 * kernel MMAP event, in perf_event__process_mmap().
@@ -170,7 +170,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
170 * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is 170 * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is
171 * processed, so perf_evlist__sample_id_all is not meaningful here. 171 * processed, so perf_evlist__sample_id_all is not meaningful here.
172 */ 172 */
173 if ((!file || !file->is_pipe) && tool && tool->ordering_requires_timestamps && 173 if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps &&
174 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { 174 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
175 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 175 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
176 tool->ordered_events = false; 176 tool->ordered_events = false;
@@ -179,7 +179,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
179 return session; 179 return session;
180 180
181 out_close: 181 out_close:
182 perf_data_file__close(file); 182 perf_data__close(data);
183 out_delete: 183 out_delete:
184 perf_session__delete(session); 184 perf_session__delete(session);
185 out: 185 out:
@@ -201,8 +201,8 @@ void perf_session__delete(struct perf_session *session)
201 perf_session__delete_threads(session); 201 perf_session__delete_threads(session);
202 perf_env__exit(&session->header.env); 202 perf_env__exit(&session->header.env);
203 machines__exit(&session->machines); 203 machines__exit(&session->machines);
204 if (session->file) 204 if (session->data)
205 perf_data_file__close(session->file); 205 perf_data__close(session->data);
206 free(session); 206 free(session);
207} 207}
208 208
@@ -290,8 +290,8 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
290 __maybe_unused) 290 __maybe_unused)
291{ 291{
292 dump_printf(": unhandled!\n"); 292 dump_printf(": unhandled!\n");
293 if (perf_data_file__is_pipe(session->file)) 293 if (perf_data__is_pipe(session->data))
294 skipn(perf_data_file__fd(session->file), event->auxtrace.size); 294 skipn(perf_data__fd(session->data), event->auxtrace.size);
295 return event->auxtrace.size; 295 return event->auxtrace.size;
296} 296}
297 297
@@ -1349,7 +1349,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1349{ 1349{
1350 struct ordered_events *oe = &session->ordered_events; 1350 struct ordered_events *oe = &session->ordered_events;
1351 struct perf_tool *tool = session->tool; 1351 struct perf_tool *tool = session->tool;
1352 int fd = perf_data_file__fd(session->file); 1352 int fd = perf_data__fd(session->data);
1353 int err; 1353 int err;
1354 1354
1355 dump_event(session->evlist, event, file_offset, NULL); 1355 dump_event(session->evlist, event, file_offset, NULL);
@@ -1449,10 +1449,10 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
1449 goto out_parse_sample; 1449 goto out_parse_sample;
1450 } 1450 }
1451 1451
1452 if (perf_data_file__is_pipe(session->file)) 1452 if (perf_data__is_pipe(session->data))
1453 return -1; 1453 return -1;
1454 1454
1455 fd = perf_data_file__fd(session->file); 1455 fd = perf_data__fd(session->data);
1456 hdr_sz = sizeof(struct perf_event_header); 1456 hdr_sz = sizeof(struct perf_event_header);
1457 1457
1458 if (buf_sz < hdr_sz) 1458 if (buf_sz < hdr_sz)
@@ -1687,7 +1687,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session)
1687{ 1687{
1688 struct ordered_events *oe = &session->ordered_events; 1688 struct ordered_events *oe = &session->ordered_events;
1689 struct perf_tool *tool = session->tool; 1689 struct perf_tool *tool = session->tool;
1690 int fd = perf_data_file__fd(session->file); 1690 int fd = perf_data__fd(session->data);
1691 union perf_event *event; 1691 union perf_event *event;
1692 uint32_t size, cur_size = 0; 1692 uint32_t size, cur_size = 0;
1693 void *buf = NULL; 1693 void *buf = NULL;
@@ -1828,7 +1828,7 @@ static int __perf_session__process_events(struct perf_session *session,
1828{ 1828{
1829 struct ordered_events *oe = &session->ordered_events; 1829 struct ordered_events *oe = &session->ordered_events;
1830 struct perf_tool *tool = session->tool; 1830 struct perf_tool *tool = session->tool;
1831 int fd = perf_data_file__fd(session->file); 1831 int fd = perf_data__fd(session->data);
1832 u64 head, page_offset, file_offset, file_pos, size; 1832 u64 head, page_offset, file_offset, file_pos, size;
1833 int err, mmap_prot, mmap_flags, map_idx = 0; 1833 int err, mmap_prot, mmap_flags, map_idx = 0;
1834 size_t mmap_size; 1834 size_t mmap_size;
@@ -1945,13 +1945,13 @@ out_err:
1945 1945
1946int perf_session__process_events(struct perf_session *session) 1946int perf_session__process_events(struct perf_session *session)
1947{ 1947{
1948 u64 size = perf_data_file__size(session->file); 1948 u64 size = perf_data__size(session->data);
1949 int err; 1949 int err;
1950 1950
1951 if (perf_session__register_idle_thread(session) < 0) 1951 if (perf_session__register_idle_thread(session) < 0)
1952 return -ENOMEM; 1952 return -ENOMEM;
1953 1953
1954 if (!perf_data_file__is_pipe(session->file)) 1954 if (!perf_data__is_pipe(session->data))
1955 err = __perf_session__process_events(session, 1955 err = __perf_session__process_events(session,
1956 session->header.data_offset, 1956 session->header.data_offset,
1957 session->header.data_size, size); 1957 session->header.data_size, size);
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 47b5e7dbcb18..cc1c5ea53c39 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -32,13 +32,13 @@ struct perf_session {
32 void *one_mmap_addr; 32 void *one_mmap_addr;
33 u64 one_mmap_offset; 33 u64 one_mmap_offset;
34 struct ordered_events ordered_events; 34 struct ordered_events ordered_events;
35 struct perf_data_file *file; 35 struct perf_data *data;
36 struct perf_tool *tool; 36 struct perf_tool *tool;
37}; 37};
38 38
39struct perf_tool; 39struct perf_tool;
40 40
41struct perf_session *perf_session__new(struct perf_data_file *file, 41struct perf_session *perf_session__new(struct perf_data *data,
42 bool repipe, struct perf_tool *tool); 42 bool repipe, struct perf_tool *tool);
43void perf_session__delete(struct perf_session *session); 43void perf_session__delete(struct perf_session *session);
44 44
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index c143c3bc1ef8..ad1b46f1f2cf 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -10,7 +10,7 @@
10#include "util/debug.h" 10#include "util/debug.h"
11#include "util/callchain.h" 11#include "util/callchain.h"
12#include "srcline.h" 12#include "srcline.h"
13 13#include "string2.h"
14#include "symbol.h" 14#include "symbol.h"
15 15
16bool srcline_full_filename; 16bool srcline_full_filename;
@@ -77,6 +77,41 @@ static char *srcline_from_fileline(const char *file, unsigned int line)
77 return srcline; 77 return srcline;
78} 78}
79 79
80static struct symbol *new_inline_sym(struct dso *dso,
81 struct symbol *base_sym,
82 const char *funcname)
83{
84 struct symbol *inline_sym;
85 char *demangled = NULL;
86
87 if (dso) {
88 demangled = dso__demangle_sym(dso, 0, funcname);
89 if (demangled)
90 funcname = demangled;
91 }
92
93 if (base_sym && strcmp(funcname, base_sym->name) == 0) {
94 /* reuse the real, existing symbol */
95 inline_sym = base_sym;
96 /* ensure that we don't alias an inlined symbol, which could
97 * lead to double frees in inline_node__delete
98 */
99 assert(!base_sym->inlined);
100 } else {
101 /* create a fake symbol for the inline frame */
102 inline_sym = symbol__new(base_sym ? base_sym->start : 0,
103 base_sym ? base_sym->end : 0,
104 base_sym ? base_sym->binding : 0,
105 funcname);
106 if (inline_sym)
107 inline_sym->inlined = 1;
108 }
109
110 free(demangled);
111
112 return inline_sym;
113}
114
80#ifdef HAVE_LIBBFD_SUPPORT 115#ifdef HAVE_LIBBFD_SUPPORT
81 116
82/* 117/*
@@ -219,41 +254,6 @@ static void addr2line_cleanup(struct a2l_data *a2l)
219 254
220#define MAX_INLINE_NEST 1024 255#define MAX_INLINE_NEST 1024
221 256
222static struct symbol *new_inline_sym(struct dso *dso,
223 struct symbol *base_sym,
224 const char *funcname)
225{
226 struct symbol *inline_sym;
227 char *demangled = NULL;
228
229 if (dso) {
230 demangled = dso__demangle_sym(dso, 0, funcname);
231 if (demangled)
232 funcname = demangled;
233 }
234
235 if (base_sym && strcmp(funcname, base_sym->name) == 0) {
236 /* reuse the real, existing symbol */
237 inline_sym = base_sym;
238 /* ensure that we don't alias an inlined symbol, which could
239 * lead to double frees in inline_node__delete
240 */
241 assert(!base_sym->inlined);
242 } else {
243 /* create a fake symbol for the inline frame */
244 inline_sym = symbol__new(base_sym ? base_sym->start : 0,
245 base_sym ? base_sym->end : 0,
246 base_sym ? base_sym->binding : 0,
247 funcname);
248 if (inline_sym)
249 inline_sym->inlined = 1;
250 }
251
252 free(demangled);
253
254 return inline_sym;
255}
256
257static int inline_list__append_dso_a2l(struct dso *dso, 257static int inline_list__append_dso_a2l(struct dso *dso,
258 struct inline_node *node, 258 struct inline_node *node,
259 struct symbol *sym) 259 struct symbol *sym)
@@ -432,10 +432,11 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
432 char cmd[PATH_MAX]; 432 char cmd[PATH_MAX];
433 struct inline_node *node; 433 struct inline_node *node;
434 char *filename = NULL; 434 char *filename = NULL;
435 size_t len; 435 char *funcname = NULL;
436 size_t filelen, funclen;
436 unsigned int line_nr = 0; 437 unsigned int line_nr = 0;
437 438
438 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64, 439 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i -f %016"PRIx64,
439 dso_name, addr); 440 dso_name, addr);
440 441
441 fp = popen(cmd, "r"); 442 fp = popen(cmd, "r");
@@ -453,23 +454,34 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
453 INIT_LIST_HEAD(&node->val); 454 INIT_LIST_HEAD(&node->val);
454 node->addr = addr; 455 node->addr = addr;
455 456
456 while (getline(&filename, &len, fp) != -1) { 457 /* addr2line -f generates two lines for each inlined functions */
458 while (getline(&funcname, &funclen, fp) != -1) {
457 char *srcline; 459 char *srcline;
460 struct symbol *inline_sym;
461
462 rtrim(funcname);
458 463
459 if (filename_split(filename, &line_nr) != 1) { 464 if (getline(&filename, &filelen, fp) == -1)
460 free(filename);
461 goto out; 465 goto out;
462 }
463 466
464 srcline = srcline_from_fileline(filename, line_nr); 467 if (filename_split(filename, &line_nr) != 1)
465 if (inline_list__append(sym, srcline, node) != 0)
466 goto out; 468 goto out;
467 469
468 filename = NULL; 470 srcline = srcline_from_fileline(filename, line_nr);
471 inline_sym = new_inline_sym(dso, sym, funcname);
472
473 if (inline_list__append(inline_sym, srcline, node) != 0) {
474 free(srcline);
475 if (inline_sym && inline_sym->inlined)
476 symbol__delete(inline_sym);
477 goto out;
478 }
469 } 479 }
470 480
471out: 481out:
472 pclose(fp); 482 pclose(fp);
483 free(filename);
484 free(funcname);
473 485
474 return node; 486 return node;
475} 487}
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index a2c12d1ef32a..51ad03a799ec 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -178,58 +178,60 @@ void perf_stat__reset_shadow_stats(void)
178 * more semantic information such as miss/hit ratios, 178 * more semantic information such as miss/hit ratios,
179 * instruction rates, etc: 179 * instruction rates, etc:
180 */ 180 */
181void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, 181void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
182 int cpu) 182 int cpu)
183{ 183{
184 int ctx = evsel_context(counter); 184 int ctx = evsel_context(counter);
185 185
186 count *= counter->scale;
187
186 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) || 188 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) ||
187 perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK)) 189 perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK))
188 update_stats(&runtime_nsecs_stats[cpu], count[0]); 190 update_stats(&runtime_nsecs_stats[cpu], count);
189 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 191 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
190 update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); 192 update_stats(&runtime_cycles_stats[ctx][cpu], count);
191 else if (perf_stat_evsel__is(counter, CYCLES_IN_TX)) 193 else if (perf_stat_evsel__is(counter, CYCLES_IN_TX))
192 update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count[0]); 194 update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count);
193 else if (perf_stat_evsel__is(counter, TRANSACTION_START)) 195 else if (perf_stat_evsel__is(counter, TRANSACTION_START))
194 update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); 196 update_stats(&runtime_transaction_stats[ctx][cpu], count);
195 else if (perf_stat_evsel__is(counter, ELISION_START)) 197 else if (perf_stat_evsel__is(counter, ELISION_START))
196 update_stats(&runtime_elision_stats[ctx][cpu], count[0]); 198 update_stats(&runtime_elision_stats[ctx][cpu], count);
197 else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS)) 199 else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS))
198 update_stats(&runtime_topdown_total_slots[ctx][cpu], count[0]); 200 update_stats(&runtime_topdown_total_slots[ctx][cpu], count);
199 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED)) 201 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED))
200 update_stats(&runtime_topdown_slots_issued[ctx][cpu], count[0]); 202 update_stats(&runtime_topdown_slots_issued[ctx][cpu], count);
201 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED)) 203 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED))
202 update_stats(&runtime_topdown_slots_retired[ctx][cpu], count[0]); 204 update_stats(&runtime_topdown_slots_retired[ctx][cpu], count);
203 else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES)) 205 else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES))
204 update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu],count[0]); 206 update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu], count);
205 else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES)) 207 else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES))
206 update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count[0]); 208 update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count);
207 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 209 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
208 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]); 210 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count);
209 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 211 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
210 update_stats(&runtime_stalled_cycles_back_stats[ctx][cpu], count[0]); 212 update_stats(&runtime_stalled_cycles_back_stats[ctx][cpu], count);
211 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 213 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
212 update_stats(&runtime_branches_stats[ctx][cpu], count[0]); 214 update_stats(&runtime_branches_stats[ctx][cpu], count);
213 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 215 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
214 update_stats(&runtime_cacherefs_stats[ctx][cpu], count[0]); 216 update_stats(&runtime_cacherefs_stats[ctx][cpu], count);
215 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) 217 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
216 update_stats(&runtime_l1_dcache_stats[ctx][cpu], count[0]); 218 update_stats(&runtime_l1_dcache_stats[ctx][cpu], count);
217 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) 219 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
218 update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]); 220 update_stats(&runtime_ll_cache_stats[ctx][cpu], count);
219 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) 221 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
220 update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]); 222 update_stats(&runtime_ll_cache_stats[ctx][cpu], count);
221 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) 223 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
222 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]); 224 update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count);
223 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 225 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
224 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]); 226 update_stats(&runtime_itlb_cache_stats[ctx][cpu], count);
225 else if (perf_stat_evsel__is(counter, SMI_NUM)) 227 else if (perf_stat_evsel__is(counter, SMI_NUM))
226 update_stats(&runtime_smi_num_stats[ctx][cpu], count[0]); 228 update_stats(&runtime_smi_num_stats[ctx][cpu], count);
227 else if (perf_stat_evsel__is(counter, APERF)) 229 else if (perf_stat_evsel__is(counter, APERF))
228 update_stats(&runtime_aperf_stats[ctx][cpu], count[0]); 230 update_stats(&runtime_aperf_stats[ctx][cpu], count);
229 231
230 if (counter->collect_stat) { 232 if (counter->collect_stat) {
231 struct saved_value *v = saved_value_lookup(counter, cpu, true); 233 struct saved_value *v = saved_value_lookup(counter, cpu, true);
232 update_stats(&v->stats, count[0]); 234 update_stats(&v->stats, count);
233 } 235 }
234} 236}
235 237
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 35e9848734d6..203f5d8d11d1 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -69,7 +69,7 @@ double rel_stddev_stats(double stddev, double avg)
69bool __perf_evsel_stat__is(struct perf_evsel *evsel, 69bool __perf_evsel_stat__is(struct perf_evsel *evsel,
70 enum perf_stat_evsel_id id) 70 enum perf_stat_evsel_id id)
71{ 71{
72 struct perf_stat_evsel *ps = evsel->priv; 72 struct perf_stat_evsel *ps = evsel->stats;
73 73
74 return ps->id == id; 74 return ps->id == id;
75} 75}
@@ -93,7 +93,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
93 93
94void perf_stat_evsel_id_init(struct perf_evsel *evsel) 94void perf_stat_evsel_id_init(struct perf_evsel *evsel)
95{ 95{
96 struct perf_stat_evsel *ps = evsel->priv; 96 struct perf_stat_evsel *ps = evsel->stats;
97 int i; 97 int i;
98 98
99 /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */ 99 /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
@@ -109,7 +109,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
109static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) 109static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
110{ 110{
111 int i; 111 int i;
112 struct perf_stat_evsel *ps = evsel->priv; 112 struct perf_stat_evsel *ps = evsel->stats;
113 113
114 for (i = 0; i < 3; i++) 114 for (i = 0; i < 3; i++)
115 init_stats(&ps->res_stats[i]); 115 init_stats(&ps->res_stats[i]);
@@ -119,8 +119,8 @@ static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
119 119
120static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 120static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
121{ 121{
122 evsel->priv = zalloc(sizeof(struct perf_stat_evsel)); 122 evsel->stats = zalloc(sizeof(struct perf_stat_evsel));
123 if (evsel->priv == NULL) 123 if (evsel->stats == NULL)
124 return -ENOMEM; 124 return -ENOMEM;
125 perf_evsel__reset_stat_priv(evsel); 125 perf_evsel__reset_stat_priv(evsel);
126 return 0; 126 return 0;
@@ -128,11 +128,11 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
128 128
129static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 129static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
130{ 130{
131 struct perf_stat_evsel *ps = evsel->priv; 131 struct perf_stat_evsel *ps = evsel->stats;
132 132
133 if (ps) 133 if (ps)
134 free(ps->group_data); 134 free(ps->group_data);
135 zfree(&evsel->priv); 135 zfree(&evsel->stats);
136} 136}
137 137
138static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, 138static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
@@ -277,7 +277,9 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
277 perf_evsel__compute_deltas(evsel, cpu, thread, count); 277 perf_evsel__compute_deltas(evsel, cpu, thread, count);
278 perf_counts_values__scale(count, config->scale, NULL); 278 perf_counts_values__scale(count, config->scale, NULL);
279 if (config->aggr_mode == AGGR_NONE) 279 if (config->aggr_mode == AGGR_NONE)
280 perf_stat__update_shadow_stats(evsel, count->values, cpu); 280 perf_stat__update_shadow_stats(evsel, count->val, cpu);
281 if (config->aggr_mode == AGGR_THREAD)
282 perf_stat__update_shadow_stats(evsel, count->val, 0);
281 break; 283 break;
282 case AGGR_GLOBAL: 284 case AGGR_GLOBAL:
283 aggr->val += count->val; 285 aggr->val += count->val;
@@ -318,9 +320,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
318 struct perf_evsel *counter) 320 struct perf_evsel *counter)
319{ 321{
320 struct perf_counts_values *aggr = &counter->counts->aggr; 322 struct perf_counts_values *aggr = &counter->counts->aggr;
321 struct perf_stat_evsel *ps = counter->priv; 323 struct perf_stat_evsel *ps = counter->stats;
322 u64 *count = counter->counts->aggr.values; 324 u64 *count = counter->counts->aggr.values;
323 u64 val;
324 int i, ret; 325 int i, ret;
325 326
326 aggr->val = aggr->ena = aggr->run = 0; 327 aggr->val = aggr->ena = aggr->run = 0;
@@ -360,8 +361,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
360 /* 361 /*
361 * Save the full runtime - to allow normalization during printout: 362 * Save the full runtime - to allow normalization during printout:
362 */ 363 */
363 val = counter->scale * *count; 364 perf_stat__update_shadow_stats(counter, *count, 0);
364 perf_stat__update_shadow_stats(counter, &val, 0);
365 365
366 return 0; 366 return 0;
367} 367}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 47915df346fb..490b78aa7230 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -82,7 +82,7 @@ typedef void (*new_line_t )(void *ctx);
82 82
83void perf_stat__init_shadow_stats(void); 83void perf_stat__init_shadow_stats(void);
84void perf_stat__reset_shadow_stats(void); 84void perf_stat__reset_shadow_stats(void);
85void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, 85void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count,
86 int cpu); 86 int cpu);
87struct perf_stat_output_ctx { 87struct perf_stat_output_ctx {
88 void *ctx; 88 void *ctx;