diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 79 |
1 files changed, 56 insertions, 23 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d7e67b167ea3..989fa2dee2fd 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -152,6 +152,11 @@ void perf_header__set_feat(struct perf_header *self, int feat) | |||
152 | set_bit(feat, self->adds_features); | 152 | set_bit(feat, self->adds_features); |
153 | } | 153 | } |
154 | 154 | ||
155 | void perf_header__clear_feat(struct perf_header *self, int feat) | ||
156 | { | ||
157 | clear_bit(feat, self->adds_features); | ||
158 | } | ||
159 | |||
155 | bool perf_header__has_feat(const struct perf_header *self, int feat) | 160 | bool perf_header__has_feat(const struct perf_header *self, int feat) |
156 | { | 161 | { |
157 | return test_bit(feat, self->adds_features); | 162 | return test_bit(feat, self->adds_features); |
@@ -265,15 +270,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | |||
265 | const char *name, bool is_kallsyms) | 270 | const char *name, bool is_kallsyms) |
266 | { | 271 | { |
267 | const size_t size = PATH_MAX; | 272 | const size_t size = PATH_MAX; |
268 | char *filename = malloc(size), | 273 | char *realname = realpath(name, NULL), |
274 | *filename = malloc(size), | ||
269 | *linkname = malloc(size), *targetname; | 275 | *linkname = malloc(size), *targetname; |
270 | int len, err = -1; | 276 | int len, err = -1; |
271 | 277 | ||
272 | if (filename == NULL || linkname == NULL) | 278 | if (realname == NULL || filename == NULL || linkname == NULL) |
273 | goto out_free; | 279 | goto out_free; |
274 | 280 | ||
275 | len = snprintf(filename, size, "%s%s%s", | 281 | len = snprintf(filename, size, "%s%s%s", |
276 | debugdir, is_kallsyms ? "/" : "", name); | 282 | debugdir, is_kallsyms ? "/" : "", realname); |
277 | if (mkdir_p(filename, 0755)) | 283 | if (mkdir_p(filename, 0755)) |
278 | goto out_free; | 284 | goto out_free; |
279 | 285 | ||
@@ -283,7 +289,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | |||
283 | if (is_kallsyms) { | 289 | if (is_kallsyms) { |
284 | if (copyfile("/proc/kallsyms", filename)) | 290 | if (copyfile("/proc/kallsyms", filename)) |
285 | goto out_free; | 291 | goto out_free; |
286 | } else if (link(name, filename) && copyfile(name, filename)) | 292 | } else if (link(realname, filename) && copyfile(name, filename)) |
287 | goto out_free; | 293 | goto out_free; |
288 | } | 294 | } |
289 | 295 | ||
@@ -300,6 +306,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | |||
300 | if (symlink(targetname, linkname) == 0) | 306 | if (symlink(targetname, linkname) == 0) |
301 | err = 0; | 307 | err = 0; |
302 | out_free: | 308 | out_free: |
309 | free(realname); | ||
303 | free(filename); | 310 | free(filename); |
304 | free(linkname); | 311 | free(linkname); |
305 | return err; | 312 | return err; |
@@ -431,8 +438,10 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
431 | int idx = 0, err; | 438 | int idx = 0, err; |
432 | 439 | ||
433 | session = container_of(self, struct perf_session, header); | 440 | session = container_of(self, struct perf_session, header); |
434 | if (perf_session__read_build_ids(session, true)) | 441 | |
435 | perf_header__set_feat(self, HEADER_BUILD_ID); | 442 | if (perf_header__has_feat(self, HEADER_BUILD_ID && |
443 | !perf_session__read_build_ids(session, true))) | ||
444 | perf_header__clear_feat(self, HEADER_BUILD_ID); | ||
436 | 445 | ||
437 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 446 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); |
438 | if (!nr_sections) | 447 | if (!nr_sections) |
@@ -454,7 +463,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
454 | 463 | ||
455 | /* Write trace info */ | 464 | /* Write trace info */ |
456 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); | 465 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); |
457 | read_tracing_data(fd, attrs, nr_counters); | 466 | read_tracing_data(fd, &evsel_list); |
458 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; | 467 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; |
459 | } | 468 | } |
460 | 469 | ||
@@ -597,7 +606,7 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
597 | static int perf_header__getbuffer64(struct perf_header *self, | 606 | static int perf_header__getbuffer64(struct perf_header *self, |
598 | int fd, void *buf, size_t size) | 607 | int fd, void *buf, size_t size) |
599 | { | 608 | { |
600 | if (do_read(fd, buf, size) <= 0) | 609 | if (readn(fd, buf, size) <= 0) |
601 | return -1; | 610 | return -1; |
602 | 611 | ||
603 | if (self->needs_swap) | 612 | if (self->needs_swap) |
@@ -653,7 +662,7 @@ int perf_file_header__read(struct perf_file_header *self, | |||
653 | { | 662 | { |
654 | lseek(fd, 0, SEEK_SET); | 663 | lseek(fd, 0, SEEK_SET); |
655 | 664 | ||
656 | if (do_read(fd, self, sizeof(*self)) <= 0 || | 665 | if (readn(fd, self, sizeof(*self)) <= 0 || |
657 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 666 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
658 | return -1; | 667 | return -1; |
659 | 668 | ||
@@ -814,7 +823,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, | |||
814 | struct perf_header *ph, int fd, | 823 | struct perf_header *ph, int fd, |
815 | bool repipe) | 824 | bool repipe) |
816 | { | 825 | { |
817 | if (do_read(fd, self, sizeof(*self)) <= 0 || | 826 | if (readn(fd, self, sizeof(*self)) <= 0 || |
818 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 827 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
819 | return -1; | 828 | return -1; |
820 | 829 | ||
@@ -939,6 +948,24 @@ u64 perf_header__sample_type(struct perf_header *header) | |||
939 | return type; | 948 | return type; |
940 | } | 949 | } |
941 | 950 | ||
951 | bool perf_header__sample_id_all(const struct perf_header *header) | ||
952 | { | ||
953 | bool value = false, first = true; | ||
954 | int i; | ||
955 | |||
956 | for (i = 0; i < header->attrs; i++) { | ||
957 | struct perf_header_attr *attr = header->attr[i]; | ||
958 | |||
959 | if (first) { | ||
960 | value = attr->attr.sample_id_all; | ||
961 | first = false; | ||
962 | } else if (value != attr->attr.sample_id_all) | ||
963 | die("non matching sample_id_all"); | ||
964 | } | ||
965 | |||
966 | return value; | ||
967 | } | ||
968 | |||
942 | struct perf_event_attr * | 969 | struct perf_event_attr * |
943 | perf_header__find_attr(u64 id, struct perf_header *header) | 970 | perf_header__find_attr(u64 id, struct perf_header *header) |
944 | { | 971 | { |
@@ -946,11 +973,16 @@ perf_header__find_attr(u64 id, struct perf_header *header) | |||
946 | 973 | ||
947 | /* | 974 | /* |
948 | * We set id to -1 if the data file doesn't contain sample | 975 | * We set id to -1 if the data file doesn't contain sample |
949 | * ids. Check for this and avoid walking through the entire | 976 | * ids. This can happen when the data file contains one type |
950 | * list of ids which may be large. | 977 | * of event and in that case, the header can still store the |
978 | * event attribute information. Check for this and avoid | ||
979 | * walking through the entire list of ids which may be large. | ||
951 | */ | 980 | */ |
952 | if (id == -1ULL) | 981 | if (id == -1ULL) { |
982 | if (header->attrs > 0) | ||
983 | return &header->attr[0]->attr; | ||
953 | return NULL; | 984 | return NULL; |
985 | } | ||
954 | 986 | ||
955 | for (i = 0; i < header->attrs; i++) { | 987 | for (i = 0; i < header->attrs; i++) { |
956 | struct perf_header_attr *attr = header->attr[i]; | 988 | struct perf_header_attr *attr = header->attr[i]; |
@@ -980,21 +1012,23 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, | |||
980 | 1012 | ||
981 | ev = malloc(size); | 1013 | ev = malloc(size); |
982 | 1014 | ||
1015 | if (ev == NULL) | ||
1016 | return -ENOMEM; | ||
1017 | |||
983 | ev->attr.attr = *attr; | 1018 | ev->attr.attr = *attr; |
984 | memcpy(ev->attr.id, id, ids * sizeof(u64)); | 1019 | memcpy(ev->attr.id, id, ids * sizeof(u64)); |
985 | 1020 | ||
986 | ev->attr.header.type = PERF_RECORD_HEADER_ATTR; | 1021 | ev->attr.header.type = PERF_RECORD_HEADER_ATTR; |
987 | ev->attr.header.size = size; | 1022 | ev->attr.header.size = size; |
988 | 1023 | ||
989 | err = process(ev, session); | 1024 | err = process(ev, NULL, session); |
990 | 1025 | ||
991 | free(ev); | 1026 | free(ev); |
992 | 1027 | ||
993 | return err; | 1028 | return err; |
994 | } | 1029 | } |
995 | 1030 | ||
996 | int event__synthesize_attrs(struct perf_header *self, | 1031 | int event__synthesize_attrs(struct perf_header *self, event__handler_t process, |
997 | event__handler_t process, | ||
998 | struct perf_session *session) | 1032 | struct perf_session *session) |
999 | { | 1033 | { |
1000 | struct perf_header_attr *attr; | 1034 | struct perf_header_attr *attr; |
@@ -1064,7 +1098,7 @@ int event__synthesize_event_type(u64 event_id, char *name, | |||
1064 | ev.event_type.header.size = sizeof(ev.event_type) - | 1098 | ev.event_type.header.size = sizeof(ev.event_type) - |
1065 | (sizeof(ev.event_type.event_type.name) - size); | 1099 | (sizeof(ev.event_type.event_type.name) - size); |
1066 | 1100 | ||
1067 | err = process(&ev, session); | 1101 | err = process(&ev, NULL, session); |
1068 | 1102 | ||
1069 | return err; | 1103 | return err; |
1070 | } | 1104 | } |
@@ -1099,8 +1133,7 @@ int event__process_event_type(event_t *self, | |||
1099 | return 0; | 1133 | return 0; |
1100 | } | 1134 | } |
1101 | 1135 | ||
1102 | int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | 1136 | int event__synthesize_tracing_data(int fd, struct list_head *pattrs, |
1103 | int nb_events, | ||
1104 | event__handler_t process, | 1137 | event__handler_t process, |
1105 | struct perf_session *session __unused) | 1138 | struct perf_session *session __unused) |
1106 | { | 1139 | { |
@@ -1111,7 +1144,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | |||
1111 | memset(&ev, 0, sizeof(ev)); | 1144 | memset(&ev, 0, sizeof(ev)); |
1112 | 1145 | ||
1113 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; | 1146 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; |
1114 | size = read_tracing_data_size(fd, pattrs, nb_events); | 1147 | size = read_tracing_data_size(fd, pattrs); |
1115 | if (size <= 0) | 1148 | if (size <= 0) |
1116 | return size; | 1149 | return size; |
1117 | aligned_size = ALIGN(size, sizeof(u64)); | 1150 | aligned_size = ALIGN(size, sizeof(u64)); |
@@ -1119,9 +1152,9 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | |||
1119 | ev.tracing_data.header.size = sizeof(ev.tracing_data); | 1152 | ev.tracing_data.header.size = sizeof(ev.tracing_data); |
1120 | ev.tracing_data.size = aligned_size; | 1153 | ev.tracing_data.size = aligned_size; |
1121 | 1154 | ||
1122 | process(&ev, session); | 1155 | process(&ev, NULL, session); |
1123 | 1156 | ||
1124 | err = read_tracing_data(fd, pattrs, nb_events); | 1157 | err = read_tracing_data(fd, pattrs); |
1125 | write_padded(fd, NULL, 0, padding); | 1158 | write_padded(fd, NULL, 0, padding); |
1126 | 1159 | ||
1127 | return aligned_size; | 1160 | return aligned_size; |
@@ -1179,7 +1212,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, | |||
1179 | ev.build_id.header.size = sizeof(ev.build_id) + len; | 1212 | ev.build_id.header.size = sizeof(ev.build_id) + len; |
1180 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); | 1213 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); |
1181 | 1214 | ||
1182 | err = process(&ev, session); | 1215 | err = process(&ev, NULL, session); |
1183 | 1216 | ||
1184 | return err; | 1217 | return err; |
1185 | } | 1218 | } |