aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/header.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2019-09-20 12:14:00 -0400
committerIngo Molnar <mingo@kernel.org>2019-09-20 12:16:42 -0400
commit351a1f5c8afa13ea5cfcdae543f6596ef8ebdbd9 (patch)
tree6d039ac0d47666bd6de701911a283c51bea7105e /tools/perf/util/header.c
parent7f2444d38f6bbfa12bc15e2533d8f9daa85ca02b (diff)
parent2bff2b828502b5e5d5ea5a52643d3542053df03f (diff)
Merge tag 'perf-core-for-mingo-5.4-20190920-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: perf stat: Srikar Dronamraju: - Fix a segmentation fault when using repeat forever. - Reset previous counts on repeat with interval. aarch64: James Clark: - Add PMU event JSON files for Cortex-A76 and Neoverse N1. PowerPC: Anju T Sudhakar: - Make 'trace_cycles' the default event for 'perf kvm record' in PowerPC. S/390: - Link libjvmti to tools/lib/string.o to have a weak strlcpy() implementation, providing previously unresolved symbol on s/390. perf test: Jiri Olsa: - Add libperf automated tests to 'make -C tools/perf build-test'. Colin Ian King: - Fix spelling mistake. Tree wide: Arnaldo Carvalho de Melo: - Some more header file sanitization. libperf: Jiri Olsa: - Add dependency on libperf for python.so binding. libtraceevent: Sakari Ailus: - Convert remaining %p[fF] users to %p[sS]. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r--tools/perf/util/header.c395
1 files changed, 5 insertions, 390 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index b0c34dda30a0..5722ff717777 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -42,11 +42,12 @@
42#include "tool.h" 42#include "tool.h"
43#include "time-utils.h" 43#include "time-utils.h"
44#include "units.h" 44#include "units.h"
45#include "util.h" 45#include "util.h" // page_size, perf_exe()
46#include "cputopo.h" 46#include "cputopo.h"
47#include "bpf-event.h" 47#include "bpf-event.h"
48 48
49#include <linux/ctype.h> 49#include <linux/ctype.h>
50#include <internal/lib.h>
50 51
51/* 52/*
52 * magic2 = "PERFILE2" 53 * magic2 = "PERFILE2"
@@ -70,15 +71,6 @@ struct perf_file_attr {
70 struct perf_file_section ids; 71 struct perf_file_section ids;
71}; 72};
72 73
73struct feat_fd {
74 struct perf_header *ph;
75 int fd;
76 void *buf; /* Either buf != NULL or fd >= 0 */
77 ssize_t offset;
78 size_t size;
79 struct evsel *events;
80};
81
82void perf_header__set_feat(struct perf_header *header, int feat) 74void perf_header__set_feat(struct perf_header *header, int feat)
83{ 75{
84 set_bit(feat, header->adds_features); 76 set_bit(feat, header->adds_features);
@@ -2823,15 +2815,6 @@ static int process_compressed(struct feat_fd *ff,
2823 return 0; 2815 return 0;
2824} 2816}
2825 2817
2826struct feature_ops {
2827 int (*write)(struct feat_fd *ff, struct evlist *evlist);
2828 void (*print)(struct feat_fd *ff, FILE *fp);
2829 int (*process)(struct feat_fd *ff, void *data);
2830 const char *name;
2831 bool full_only;
2832 bool synthesize;
2833};
2834
2835#define FEAT_OPR(n, func, __full_only) \ 2818#define FEAT_OPR(n, func, __full_only) \
2836 [HEADER_##n] = { \ 2819 [HEADER_##n] = { \
2837 .name = __stringify(n), \ 2820 .name = __stringify(n), \
@@ -2858,8 +2841,10 @@ struct feature_ops {
2858#define process_branch_stack NULL 2841#define process_branch_stack NULL
2859#define process_stat NULL 2842#define process_stat NULL
2860 2843
2844// Only used in util/synthetic-events.c
2845const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE];
2861 2846
2862static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 2847const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2863 FEAT_OPN(TRACING_DATA, tracing_data, false), 2848 FEAT_OPN(TRACING_DATA, tracing_data, false),
2864 FEAT_OPN(BUILD_ID, build_id, false), 2849 FEAT_OPN(BUILD_ID, build_id, false),
2865 FEAT_OPR(HOSTNAME, hostname, false), 2850 FEAT_OPR(HOSTNAME, hostname, false),
@@ -3656,105 +3641,6 @@ out_delete_evlist:
3656 return -ENOMEM; 3641 return -ENOMEM;
3657} 3642}
3658 3643
3659int perf_event__synthesize_attr(struct perf_tool *tool,
3660 struct perf_event_attr *attr, u32 ids, u64 *id,
3661 perf_event__handler_t process)
3662{
3663 union perf_event *ev;
3664 size_t size;
3665 int err;
3666
3667 size = sizeof(struct perf_event_attr);
3668 size = PERF_ALIGN(size, sizeof(u64));
3669 size += sizeof(struct perf_event_header);
3670 size += ids * sizeof(u64);
3671
3672 ev = zalloc(size);
3673
3674 if (ev == NULL)
3675 return -ENOMEM;
3676
3677 ev->attr.attr = *attr;
3678 memcpy(ev->attr.id, id, ids * sizeof(u64));
3679
3680 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
3681 ev->attr.header.size = (u16)size;
3682
3683 if (ev->attr.header.size == size)
3684 err = process(tool, ev, NULL, NULL);
3685 else
3686 err = -E2BIG;
3687
3688 free(ev);
3689
3690 return err;
3691}
3692
3693int perf_event__synthesize_features(struct perf_tool *tool,
3694 struct perf_session *session,
3695 struct evlist *evlist,
3696 perf_event__handler_t process)
3697{
3698 struct perf_header *header = &session->header;
3699 struct feat_fd ff;
3700 struct perf_record_header_feature *fe;
3701 size_t sz, sz_hdr;
3702 int feat, ret;
3703
3704 sz_hdr = sizeof(fe->header);
3705 sz = sizeof(union perf_event);
3706 /* get a nice alignment */
3707 sz = PERF_ALIGN(sz, page_size);
3708
3709 memset(&ff, 0, sizeof(ff));
3710
3711 ff.buf = malloc(sz);
3712 if (!ff.buf)
3713 return -ENOMEM;
3714
3715 ff.size = sz - sz_hdr;
3716 ff.ph = &session->header;
3717
3718 for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
3719 if (!feat_ops[feat].synthesize) {
3720 pr_debug("No record header feature for header :%d\n", feat);
3721 continue;
3722 }
3723
3724 ff.offset = sizeof(*fe);
3725
3726 ret = feat_ops[feat].write(&ff, evlist);
3727 if (ret || ff.offset <= (ssize_t)sizeof(*fe)) {
3728 pr_debug("Error writing feature\n");
3729 continue;
3730 }
3731 /* ff.buf may have changed due to realloc in do_write() */
3732 fe = ff.buf;
3733 memset(fe, 0, sizeof(*fe));
3734
3735 fe->feat_id = feat;
3736 fe->header.type = PERF_RECORD_HEADER_FEATURE;
3737 fe->header.size = ff.offset;
3738
3739 ret = process(tool, ff.buf, NULL, NULL);
3740 if (ret) {
3741 free(ff.buf);
3742 return ret;
3743 }
3744 }
3745
3746 /* Send HEADER_LAST_FEATURE mark. */
3747 fe = ff.buf;
3748 fe->feat_id = HEADER_LAST_FEATURE;
3749 fe->header.type = PERF_RECORD_HEADER_FEATURE;
3750 fe->header.size = sizeof(*fe);
3751
3752 ret = process(tool, ff.buf, NULL, NULL);
3753
3754 free(ff.buf);
3755 return ret;
3756}
3757
3758int perf_event__process_feature(struct perf_session *session, 3644int perf_event__process_feature(struct perf_session *session,
3759 union perf_event *event) 3645 union perf_event *event)
3760{ 3646{
@@ -3797,113 +3683,6 @@ int perf_event__process_feature(struct perf_session *session,
3797 return 0; 3683 return 0;
3798} 3684}
3799 3685
3800static struct perf_record_event_update *
3801event_update_event__new(size_t size, u64 type, u64 id)
3802{
3803 struct perf_record_event_update *ev;
3804
3805 size += sizeof(*ev);
3806 size = PERF_ALIGN(size, sizeof(u64));
3807
3808 ev = zalloc(size);
3809 if (ev) {
3810 ev->header.type = PERF_RECORD_EVENT_UPDATE;
3811 ev->header.size = (u16)size;
3812 ev->type = type;
3813 ev->id = id;
3814 }
3815 return ev;
3816}
3817
3818int
3819perf_event__synthesize_event_update_unit(struct perf_tool *tool,
3820 struct evsel *evsel,
3821 perf_event__handler_t process)
3822{
3823 struct perf_record_event_update *ev;
3824 size_t size = strlen(evsel->unit);
3825 int err;
3826
3827 ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->id[0]);
3828 if (ev == NULL)
3829 return -ENOMEM;
3830
3831 strlcpy(ev->data, evsel->unit, size + 1);
3832 err = process(tool, (union perf_event *)ev, NULL, NULL);
3833 free(ev);
3834 return err;
3835}
3836
3837int
3838perf_event__synthesize_event_update_scale(struct perf_tool *tool,
3839 struct evsel *evsel,
3840 perf_event__handler_t process)
3841{
3842 struct perf_record_event_update *ev;
3843 struct perf_record_event_update_scale *ev_data;
3844 int err;
3845
3846 ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->id[0]);
3847 if (ev == NULL)
3848 return -ENOMEM;
3849
3850 ev_data = (struct perf_record_event_update_scale *)ev->data;
3851 ev_data->scale = evsel->scale;
3852 err = process(tool, (union perf_event*) ev, NULL, NULL);
3853 free(ev);
3854 return err;
3855}
3856
3857int
3858perf_event__synthesize_event_update_name(struct perf_tool *tool,
3859 struct evsel *evsel,
3860 perf_event__handler_t process)
3861{
3862 struct perf_record_event_update *ev;
3863 size_t len = strlen(evsel->name);
3864 int err;
3865
3866 ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->id[0]);
3867 if (ev == NULL)
3868 return -ENOMEM;
3869
3870 strlcpy(ev->data, evsel->name, len + 1);
3871 err = process(tool, (union perf_event*) ev, NULL, NULL);
3872 free(ev);
3873 return err;
3874}
3875
3876int
3877perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
3878 struct evsel *evsel,
3879 perf_event__handler_t process)
3880{
3881 size_t size = sizeof(struct perf_record_event_update);
3882 struct perf_record_event_update *ev;
3883 int max, err;
3884 u16 type;
3885
3886 if (!evsel->core.own_cpus)
3887 return 0;
3888
3889 ev = cpu_map_data__alloc(evsel->core.own_cpus, &size, &type, &max);
3890 if (!ev)
3891 return -ENOMEM;
3892
3893 ev->header.type = PERF_RECORD_EVENT_UPDATE;
3894 ev->header.size = (u16)size;
3895 ev->type = PERF_EVENT_UPDATE__CPUS;
3896 ev->id = evsel->id[0];
3897
3898 cpu_map_data__synthesize((struct perf_record_cpu_map_data *)ev->data,
3899 evsel->core.own_cpus,
3900 type, max);
3901
3902 err = process(tool, (union perf_event*) ev, NULL, NULL);
3903 free(ev);
3904 return err;
3905}
3906
3907size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) 3686size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
3908{ 3687{
3909 struct perf_record_event_update *ev = &event->event_update; 3688 struct perf_record_event_update *ev = &event->event_update;
@@ -3943,93 +3722,6 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
3943 return ret; 3722 return ret;
3944} 3723}
3945 3724
3946int perf_event__synthesize_attrs(struct perf_tool *tool,
3947 struct evlist *evlist,
3948 perf_event__handler_t process)
3949{
3950 struct evsel *evsel;
3951 int err = 0;
3952
3953 evlist__for_each_entry(evlist, evsel) {
3954 err = perf_event__synthesize_attr(tool, &evsel->core.attr, evsel->ids,
3955 evsel->id, process);
3956 if (err) {
3957 pr_debug("failed to create perf header attribute\n");
3958 return err;
3959 }
3960 }
3961
3962 return err;
3963}
3964
3965static bool has_unit(struct evsel *counter)
3966{
3967 return counter->unit && *counter->unit;
3968}
3969
3970static bool has_scale(struct evsel *counter)
3971{
3972 return counter->scale != 1;
3973}
3974
3975int perf_event__synthesize_extra_attr(struct perf_tool *tool,
3976 struct evlist *evsel_list,
3977 perf_event__handler_t process,
3978 bool is_pipe)
3979{
3980 struct evsel *counter;
3981 int err;
3982
3983 /*
3984 * Synthesize other events stuff not carried within
3985 * attr event - unit, scale, name
3986 */
3987 evlist__for_each_entry(evsel_list, counter) {
3988 if (!counter->supported)
3989 continue;
3990
3991 /*
3992 * Synthesize unit and scale only if it's defined.
3993 */
3994 if (has_unit(counter)) {
3995 err = perf_event__synthesize_event_update_unit(tool, counter, process);
3996 if (err < 0) {
3997 pr_err("Couldn't synthesize evsel unit.\n");
3998 return err;
3999 }
4000 }
4001
4002 if (has_scale(counter)) {
4003 err = perf_event__synthesize_event_update_scale(tool, counter, process);
4004 if (err < 0) {
4005 pr_err("Couldn't synthesize evsel counter.\n");
4006 return err;
4007 }
4008 }
4009
4010 if (counter->core.own_cpus) {
4011 err = perf_event__synthesize_event_update_cpus(tool, counter, process);
4012 if (err < 0) {
4013 pr_err("Couldn't synthesize evsel cpus.\n");
4014 return err;
4015 }
4016 }
4017
4018 /*
4019 * Name is needed only for pipe output,
4020 * perf.data carries event names.
4021 */
4022 if (is_pipe) {
4023 err = perf_event__synthesize_event_update_name(tool, counter, process);
4024 if (err < 0) {
4025 pr_err("Couldn't synthesize evsel name.\n");
4026 return err;
4027 }
4028 }
4029 }
4030 return 0;
4031}
4032
4033int perf_event__process_attr(struct perf_tool *tool __maybe_unused, 3725int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
4034 union perf_event *event, 3726 union perf_event *event,
4035 struct evlist **pevlist) 3727 struct evlist **pevlist)
@@ -4114,55 +3806,6 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
4114 return 0; 3806 return 0;
4115} 3807}
4116 3808
4117int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
4118 struct evlist *evlist,
4119 perf_event__handler_t process)
4120{
4121 union perf_event ev;
4122 struct tracing_data *tdata;
4123 ssize_t size = 0, aligned_size = 0, padding;
4124 struct feat_fd ff;
4125 int err __maybe_unused = 0;
4126
4127 /*
4128 * We are going to store the size of the data followed
4129 * by the data contents. Since the fd descriptor is a pipe,
4130 * we cannot seek back to store the size of the data once
4131 * we know it. Instead we:
4132 *
4133 * - write the tracing data to the temp file
4134 * - get/write the data size to pipe
4135 * - write the tracing data from the temp file
4136 * to the pipe
4137 */
4138 tdata = tracing_data_get(&evlist->core.entries, fd, true);
4139 if (!tdata)
4140 return -1;
4141
4142 memset(&ev, 0, sizeof(ev));
4143
4144 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
4145 size = tdata->size;
4146 aligned_size = PERF_ALIGN(size, sizeof(u64));
4147 padding = aligned_size - size;
4148 ev.tracing_data.header.size = sizeof(ev.tracing_data);
4149 ev.tracing_data.size = aligned_size;
4150
4151 process(tool, &ev, NULL, NULL);
4152
4153 /*
4154 * The put function will copy all the tracing data
4155 * stored in temp file to the pipe.
4156 */
4157 tracing_data_put(tdata);
4158
4159 ff = (struct feat_fd){ .fd = fd };
4160 if (write_padded(&ff, NULL, 0, padding))
4161 return -1;
4162
4163 return aligned_size;
4164}
4165
4166int perf_event__process_tracing_data(struct perf_session *session, 3809int perf_event__process_tracing_data(struct perf_session *session,
4167 union perf_event *event) 3810 union perf_event *event)
4168{ 3811{
@@ -4202,34 +3845,6 @@ int perf_event__process_tracing_data(struct perf_session *session,
4202 return size_read + padding; 3845 return size_read + padding;
4203} 3846}
4204 3847
4205int perf_event__synthesize_build_id(struct perf_tool *tool,
4206 struct dso *pos, u16 misc,
4207 perf_event__handler_t process,
4208 struct machine *machine)
4209{
4210 union perf_event ev;
4211 size_t len;
4212 int err = 0;
4213
4214 if (!pos->hit)
4215 return err;
4216
4217 memset(&ev, 0, sizeof(ev));
4218
4219 len = pos->long_name_len + 1;
4220 len = PERF_ALIGN(len, NAME_ALIGN);
4221 memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id));
4222 ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID;
4223 ev.build_id.header.misc = misc;
4224 ev.build_id.pid = machine->pid;
4225 ev.build_id.header.size = sizeof(ev.build_id) + len;
4226 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
4227
4228 err = process(tool, &ev, NULL, machine);
4229
4230 return err;
4231}
4232
4233int perf_event__process_build_id(struct perf_session *session, 3848int perf_event__process_build_id(struct perf_session *session,
4234 union perf_event *event) 3849 union perf_event *event)
4235{ 3850{