diff options
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 524 |
1 files changed, 484 insertions, 40 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 6c9aa16ee51f..75d016768021 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -99,13 +99,6 @@ int perf_header__add_attr(struct perf_header *self, | |||
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | 101 | ||
102 | #define MAX_EVENT_NAME 64 | ||
103 | |||
104 | struct perf_trace_event_type { | ||
105 | u64 event_id; | ||
106 | char name[MAX_EVENT_NAME]; | ||
107 | }; | ||
108 | |||
109 | static int event_count; | 102 | static int event_count; |
110 | static struct perf_trace_event_type *events; | 103 | static struct perf_trace_event_type *events; |
111 | 104 | ||
@@ -197,7 +190,8 @@ static int write_padded(int fd, const void *bf, size_t count, | |||
197 | continue; \ | 190 | continue; \ |
198 | else | 191 | else |
199 | 192 | ||
200 | static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) | 193 | static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, |
194 | u16 misc, int fd) | ||
201 | { | 195 | { |
202 | struct dso *pos; | 196 | struct dso *pos; |
203 | 197 | ||
@@ -212,6 +206,7 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) | |||
212 | len = ALIGN(len, NAME_ALIGN); | 206 | len = ALIGN(len, NAME_ALIGN); |
213 | memset(&b, 0, sizeof(b)); | 207 | memset(&b, 0, sizeof(b)); |
214 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); | 208 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); |
209 | b.pid = pid; | ||
215 | b.header.misc = misc; | 210 | b.header.misc = misc; |
216 | b.header.size = sizeof(b) + len; | 211 | b.header.size = sizeof(b) + len; |
217 | err = do_write(fd, &b, sizeof(b)); | 212 | err = do_write(fd, &b, sizeof(b)); |
@@ -226,13 +221,33 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) | |||
226 | return 0; | 221 | return 0; |
227 | } | 222 | } |
228 | 223 | ||
229 | static int dsos__write_buildid_table(int fd) | 224 | static int dsos__write_buildid_table(struct perf_header *header, int fd) |
230 | { | 225 | { |
231 | int err = __dsos__write_buildid_table(&dsos__kernel, | 226 | struct perf_session *session = container_of(header, |
232 | PERF_RECORD_MISC_KERNEL, fd); | 227 | struct perf_session, header); |
233 | if (err == 0) | 228 | struct rb_node *nd; |
234 | err = __dsos__write_buildid_table(&dsos__user, | 229 | int err = 0; |
235 | PERF_RECORD_MISC_USER, fd); | 230 | u16 kmisc, umisc; |
231 | |||
232 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | ||
233 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | ||
234 | rb_node); | ||
235 | if (is_host_kernel(pos)) { | ||
236 | kmisc = PERF_RECORD_MISC_KERNEL; | ||
237 | umisc = PERF_RECORD_MISC_USER; | ||
238 | } else { | ||
239 | kmisc = PERF_RECORD_MISC_GUEST_KERNEL; | ||
240 | umisc = PERF_RECORD_MISC_GUEST_USER; | ||
241 | } | ||
242 | |||
243 | err = __dsos__write_buildid_table(&pos->dsos__kernel, pos->pid, | ||
244 | kmisc, fd); | ||
245 | if (err == 0) | ||
246 | err = __dsos__write_buildid_table(&pos->dsos__user, | ||
247 | pos->pid, umisc, fd); | ||
248 | if (err) | ||
249 | break; | ||
250 | } | ||
236 | return err; | 251 | return err; |
237 | } | 252 | } |
238 | 253 | ||
@@ -349,9 +364,12 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) | |||
349 | return err; | 364 | return err; |
350 | } | 365 | } |
351 | 366 | ||
352 | static int dsos__cache_build_ids(void) | 367 | static int dsos__cache_build_ids(struct perf_header *self) |
353 | { | 368 | { |
354 | int err_kernel, err_user; | 369 | struct perf_session *session = container_of(self, |
370 | struct perf_session, header); | ||
371 | struct rb_node *nd; | ||
372 | int ret = 0; | ||
355 | char debugdir[PATH_MAX]; | 373 | char debugdir[PATH_MAX]; |
356 | 374 | ||
357 | snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), | 375 | snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), |
@@ -360,9 +378,30 @@ static int dsos__cache_build_ids(void) | |||
360 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | 378 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) |
361 | return -1; | 379 | return -1; |
362 | 380 | ||
363 | err_kernel = __dsos__cache_build_ids(&dsos__kernel, debugdir); | 381 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { |
364 | err_user = __dsos__cache_build_ids(&dsos__user, debugdir); | 382 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, |
365 | return err_kernel || err_user ? -1 : 0; | 383 | rb_node); |
384 | ret |= __dsos__cache_build_ids(&pos->dsos__kernel, debugdir); | ||
385 | ret |= __dsos__cache_build_ids(&pos->dsos__user, debugdir); | ||
386 | } | ||
387 | return ret ? -1 : 0; | ||
388 | } | ||
389 | |||
390 | static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) | ||
391 | { | ||
392 | bool ret = false; | ||
393 | struct perf_session *session = container_of(self, | ||
394 | struct perf_session, header); | ||
395 | struct rb_node *nd; | ||
396 | |||
397 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | ||
398 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | ||
399 | rb_node); | ||
400 | ret |= __dsos__read_build_ids(&pos->dsos__kernel, with_hits); | ||
401 | ret |= __dsos__read_build_ids(&pos->dsos__user, with_hits); | ||
402 | } | ||
403 | |||
404 | return ret; | ||
366 | } | 405 | } |
367 | 406 | ||
368 | static int perf_header__adds_write(struct perf_header *self, int fd) | 407 | static int perf_header__adds_write(struct perf_header *self, int fd) |
@@ -373,7 +412,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
373 | u64 sec_start; | 412 | u64 sec_start; |
374 | int idx = 0, err; | 413 | int idx = 0, err; |
375 | 414 | ||
376 | if (dsos__read_build_ids(true)) | 415 | if (dsos__read_build_ids(self, true)) |
377 | perf_header__set_feat(self, HEADER_BUILD_ID); | 416 | perf_header__set_feat(self, HEADER_BUILD_ID); |
378 | 417 | ||
379 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | 418 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); |
@@ -408,14 +447,14 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
408 | 447 | ||
409 | /* Write build-ids */ | 448 | /* Write build-ids */ |
410 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | 449 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); |
411 | err = dsos__write_buildid_table(fd); | 450 | err = dsos__write_buildid_table(self, fd); |
412 | if (err < 0) { | 451 | if (err < 0) { |
413 | pr_debug("failed to write buildid table\n"); | 452 | pr_debug("failed to write buildid table\n"); |
414 | goto out_free; | 453 | goto out_free; |
415 | } | 454 | } |
416 | buildid_sec->size = lseek(fd, 0, SEEK_CUR) - | 455 | buildid_sec->size = lseek(fd, 0, SEEK_CUR) - |
417 | buildid_sec->offset; | 456 | buildid_sec->offset; |
418 | dsos__cache_build_ids(); | 457 | dsos__cache_build_ids(self); |
419 | } | 458 | } |
420 | 459 | ||
421 | lseek(fd, sec_start, SEEK_SET); | 460 | lseek(fd, sec_start, SEEK_SET); |
@@ -427,6 +466,25 @@ out_free: | |||
427 | return err; | 466 | return err; |
428 | } | 467 | } |
429 | 468 | ||
469 | int perf_header__write_pipe(int fd) | ||
470 | { | ||
471 | struct perf_pipe_file_header f_header; | ||
472 | int err; | ||
473 | |||
474 | f_header = (struct perf_pipe_file_header){ | ||
475 | .magic = PERF_MAGIC, | ||
476 | .size = sizeof(f_header), | ||
477 | }; | ||
478 | |||
479 | err = do_write(fd, &f_header, sizeof(f_header)); | ||
480 | if (err < 0) { | ||
481 | pr_debug("failed to write perf pipe header\n"); | ||
482 | return err; | ||
483 | } | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
430 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) | 488 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) |
431 | { | 489 | { |
432 | struct perf_file_header f_header; | 490 | struct perf_file_header f_header; |
@@ -518,25 +576,10 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
518 | return 0; | 576 | return 0; |
519 | } | 577 | } |
520 | 578 | ||
521 | static int do_read(int fd, void *buf, size_t size) | ||
522 | { | ||
523 | while (size) { | ||
524 | int ret = read(fd, buf, size); | ||
525 | |||
526 | if (ret <= 0) | ||
527 | return -1; | ||
528 | |||
529 | size -= ret; | ||
530 | buf += ret; | ||
531 | } | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static int perf_header__getbuffer64(struct perf_header *self, | 579 | static int perf_header__getbuffer64(struct perf_header *self, |
537 | int fd, void *buf, size_t size) | 580 | int fd, void *buf, size_t size) |
538 | { | 581 | { |
539 | if (do_read(fd, buf, size)) | 582 | if (do_read(fd, buf, size) <= 0) |
540 | return -1; | 583 | return -1; |
541 | 584 | ||
542 | if (self->needs_swap) | 585 | if (self->needs_swap) |
@@ -592,7 +635,7 @@ int perf_file_header__read(struct perf_file_header *self, | |||
592 | { | 635 | { |
593 | lseek(fd, 0, SEEK_SET); | 636 | lseek(fd, 0, SEEK_SET); |
594 | 637 | ||
595 | if (do_read(fd, self, sizeof(*self)) || | 638 | if (do_read(fd, self, sizeof(*self)) <= 0 || |
596 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 639 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
597 | return -1; | 640 | return -1; |
598 | 641 | ||
@@ -636,6 +679,85 @@ int perf_file_header__read(struct perf_file_header *self, | |||
636 | return 0; | 679 | return 0; |
637 | } | 680 | } |
638 | 681 | ||
682 | static int __event_process_build_id(struct build_id_event *bev, | ||
683 | char *filename, | ||
684 | struct perf_session *session) | ||
685 | { | ||
686 | int err = -1; | ||
687 | struct list_head *head; | ||
688 | struct kernel_info *kerninfo; | ||
689 | u16 misc; | ||
690 | struct dso *dso; | ||
691 | enum dso_kernel_type dso_type; | ||
692 | |||
693 | kerninfo = kerninfo__findnew(&session->kerninfo_root, bev->pid); | ||
694 | if (!kerninfo) | ||
695 | goto out; | ||
696 | |||
697 | misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
698 | |||
699 | switch (misc) { | ||
700 | case PERF_RECORD_MISC_KERNEL: | ||
701 | dso_type = DSO_TYPE_KERNEL; | ||
702 | head = &kerninfo->dsos__kernel; | ||
703 | break; | ||
704 | case PERF_RECORD_MISC_GUEST_KERNEL: | ||
705 | dso_type = DSO_TYPE_GUEST_KERNEL; | ||
706 | head = &kerninfo->dsos__kernel; | ||
707 | break; | ||
708 | case PERF_RECORD_MISC_USER: | ||
709 | case PERF_RECORD_MISC_GUEST_USER: | ||
710 | dso_type = DSO_TYPE_USER; | ||
711 | head = &kerninfo->dsos__user; | ||
712 | break; | ||
713 | default: | ||
714 | goto out; | ||
715 | } | ||
716 | |||
717 | dso = __dsos__findnew(head, filename); | ||
718 | if (dso != NULL) { | ||
719 | dso__set_build_id(dso, &bev->build_id); | ||
720 | if (filename[0] == '[') | ||
721 | dso->kernel = dso_type; | ||
722 | } | ||
723 | |||
724 | err = 0; | ||
725 | out: | ||
726 | return err; | ||
727 | } | ||
728 | |||
729 | static int perf_header__read_build_ids(struct perf_header *self, | ||
730 | int input, u64 offset, u64 size) | ||
731 | { | ||
732 | struct perf_session *session = container_of(self, | ||
733 | struct perf_session, header); | ||
734 | struct build_id_event bev; | ||
735 | char filename[PATH_MAX]; | ||
736 | u64 limit = offset + size; | ||
737 | int err = -1; | ||
738 | |||
739 | while (offset < limit) { | ||
740 | ssize_t len; | ||
741 | |||
742 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) | ||
743 | goto out; | ||
744 | |||
745 | if (self->needs_swap) | ||
746 | perf_event_header__bswap(&bev.header); | ||
747 | |||
748 | len = bev.header.size - sizeof(bev); | ||
749 | if (read(input, filename, len) != len) | ||
750 | goto out; | ||
751 | |||
752 | __event_process_build_id(&bev, filename, session); | ||
753 | |||
754 | offset += bev.header.size; | ||
755 | } | ||
756 | err = 0; | ||
757 | out: | ||
758 | return err; | ||
759 | } | ||
760 | |||
639 | static int perf_file_section__process(struct perf_file_section *self, | 761 | static int perf_file_section__process(struct perf_file_section *self, |
640 | struct perf_header *ph, | 762 | struct perf_header *ph, |
641 | int feat, int fd) | 763 | int feat, int fd) |
@@ -662,13 +784,51 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
662 | return 0; | 784 | return 0; |
663 | } | 785 | } |
664 | 786 | ||
665 | int perf_header__read(struct perf_header *self, int fd) | 787 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, |
788 | struct perf_header *ph, int fd) | ||
789 | { | ||
790 | if (do_read(fd, self, sizeof(*self)) <= 0 || | ||
791 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | ||
792 | return -1; | ||
793 | |||
794 | if (self->size != sizeof(*self)) { | ||
795 | u64 size = bswap_64(self->size); | ||
796 | |||
797 | if (size != sizeof(*self)) | ||
798 | return -1; | ||
799 | |||
800 | ph->needs_swap = true; | ||
801 | } | ||
802 | |||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | static int perf_header__read_pipe(struct perf_session *session, int fd) | ||
807 | { | ||
808 | struct perf_header *self = &session->header; | ||
809 | struct perf_pipe_file_header f_header; | ||
810 | |||
811 | if (perf_file_header__read_pipe(&f_header, self, fd) < 0) { | ||
812 | pr_debug("incompatible file format\n"); | ||
813 | return -EINVAL; | ||
814 | } | ||
815 | |||
816 | session->fd = fd; | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | int perf_header__read(struct perf_session *session, int fd) | ||
666 | { | 822 | { |
823 | struct perf_header *self = &session->header; | ||
667 | struct perf_file_header f_header; | 824 | struct perf_file_header f_header; |
668 | struct perf_file_attr f_attr; | 825 | struct perf_file_attr f_attr; |
669 | u64 f_id; | 826 | u64 f_id; |
670 | int nr_attrs, nr_ids, i, j; | 827 | int nr_attrs, nr_ids, i, j; |
671 | 828 | ||
829 | if (session->fd_pipe) | ||
830 | return perf_header__read_pipe(session, fd); | ||
831 | |||
672 | if (perf_file_header__read(&f_header, self, fd) < 0) { | 832 | if (perf_file_header__read(&f_header, self, fd) < 0) { |
673 | pr_debug("incompatible file format\n"); | 833 | pr_debug("incompatible file format\n"); |
674 | return -EINVAL; | 834 | return -EINVAL; |
@@ -765,3 +925,287 @@ perf_header__find_attr(u64 id, struct perf_header *header) | |||
765 | 925 | ||
766 | return NULL; | 926 | return NULL; |
767 | } | 927 | } |
928 | |||
929 | int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, | ||
930 | event__handler_t process, | ||
931 | struct perf_session *session) | ||
932 | { | ||
933 | event_t *ev; | ||
934 | size_t size; | ||
935 | int err; | ||
936 | |||
937 | size = sizeof(struct perf_event_attr); | ||
938 | size = ALIGN(size, sizeof(u64)); | ||
939 | size += sizeof(struct perf_event_header); | ||
940 | size += ids * sizeof(u64); | ||
941 | |||
942 | ev = malloc(size); | ||
943 | |||
944 | ev->attr.attr = *attr; | ||
945 | memcpy(ev->attr.id, id, ids * sizeof(u64)); | ||
946 | |||
947 | ev->attr.header.type = PERF_RECORD_HEADER_ATTR; | ||
948 | ev->attr.header.size = size; | ||
949 | |||
950 | err = process(ev, session); | ||
951 | |||
952 | free(ev); | ||
953 | |||
954 | return err; | ||
955 | } | ||
956 | |||
957 | int event__synthesize_attrs(struct perf_header *self, | ||
958 | event__handler_t process, | ||
959 | struct perf_session *session) | ||
960 | { | ||
961 | struct perf_header_attr *attr; | ||
962 | int i, err = 0; | ||
963 | |||
964 | for (i = 0; i < self->attrs; i++) { | ||
965 | attr = self->attr[i]; | ||
966 | |||
967 | err = event__synthesize_attr(&attr->attr, attr->ids, attr->id, | ||
968 | process, session); | ||
969 | if (err) { | ||
970 | pr_debug("failed to create perf header attribute\n"); | ||
971 | return err; | ||
972 | } | ||
973 | } | ||
974 | |||
975 | return err; | ||
976 | } | ||
977 | |||
978 | int event__process_attr(event_t *self, struct perf_session *session) | ||
979 | { | ||
980 | struct perf_header_attr *attr; | ||
981 | unsigned int i, ids, n_ids; | ||
982 | |||
983 | attr = perf_header_attr__new(&self->attr.attr); | ||
984 | if (attr == NULL) | ||
985 | return -ENOMEM; | ||
986 | |||
987 | ids = self->header.size; | ||
988 | ids -= (void *)&self->attr.id - (void *)self; | ||
989 | n_ids = ids / sizeof(u64); | ||
990 | |||
991 | for (i = 0; i < n_ids; i++) { | ||
992 | if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) { | ||
993 | perf_header_attr__delete(attr); | ||
994 | return -ENOMEM; | ||
995 | } | ||
996 | } | ||
997 | |||
998 | if (perf_header__add_attr(&session->header, attr) < 0) { | ||
999 | perf_header_attr__delete(attr); | ||
1000 | return -ENOMEM; | ||
1001 | } | ||
1002 | |||
1003 | perf_session__update_sample_type(session); | ||
1004 | |||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | int event__synthesize_event_type(u64 event_id, char *name, | ||
1009 | event__handler_t process, | ||
1010 | struct perf_session *session) | ||
1011 | { | ||
1012 | event_t ev; | ||
1013 | size_t size = 0; | ||
1014 | int err = 0; | ||
1015 | |||
1016 | memset(&ev, 0, sizeof(ev)); | ||
1017 | |||
1018 | ev.event_type.event_type.event_id = event_id; | ||
1019 | memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME); | ||
1020 | strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); | ||
1021 | |||
1022 | ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; | ||
1023 | size = strlen(name); | ||
1024 | size = ALIGN(size, sizeof(u64)); | ||
1025 | ev.event_type.header.size = sizeof(ev.event_type) - | ||
1026 | (sizeof(ev.event_type.event_type.name) - size); | ||
1027 | |||
1028 | err = process(&ev, session); | ||
1029 | |||
1030 | return err; | ||
1031 | } | ||
1032 | |||
1033 | int event__synthesize_event_types(event__handler_t process, | ||
1034 | struct perf_session *session) | ||
1035 | { | ||
1036 | struct perf_trace_event_type *type; | ||
1037 | int i, err = 0; | ||
1038 | |||
1039 | for (i = 0; i < event_count; i++) { | ||
1040 | type = &events[i]; | ||
1041 | |||
1042 | err = event__synthesize_event_type(type->event_id, type->name, | ||
1043 | process, session); | ||
1044 | if (err) { | ||
1045 | pr_debug("failed to create perf header event type\n"); | ||
1046 | return err; | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | return err; | ||
1051 | } | ||
1052 | |||
1053 | int event__process_event_type(event_t *self, | ||
1054 | struct perf_session *session __unused) | ||
1055 | { | ||
1056 | if (perf_header__push_event(self->event_type.event_type.event_id, | ||
1057 | self->event_type.event_type.name) < 0) | ||
1058 | return -ENOMEM; | ||
1059 | |||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1063 | int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | ||
1064 | int nb_events, | ||
1065 | event__handler_t process, | ||
1066 | struct perf_session *session __unused) | ||
1067 | { | ||
1068 | event_t ev; | ||
1069 | ssize_t size = 0, aligned_size = 0, padding; | ||
1070 | int err = 0; | ||
1071 | |||
1072 | memset(&ev, 0, sizeof(ev)); | ||
1073 | |||
1074 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; | ||
1075 | size = read_tracing_data_size(fd, pattrs, nb_events); | ||
1076 | if (size <= 0) | ||
1077 | return size; | ||
1078 | aligned_size = ALIGN(size, sizeof(u64)); | ||
1079 | padding = aligned_size - size; | ||
1080 | ev.tracing_data.header.size = sizeof(ev.tracing_data); | ||
1081 | ev.tracing_data.size = aligned_size; | ||
1082 | |||
1083 | process(&ev, session); | ||
1084 | |||
1085 | err = read_tracing_data(fd, pattrs, nb_events); | ||
1086 | write_padded(fd, NULL, 0, padding); | ||
1087 | |||
1088 | return aligned_size; | ||
1089 | } | ||
1090 | |||
1091 | int event__process_tracing_data(event_t *self, | ||
1092 | struct perf_session *session) | ||
1093 | { | ||
1094 | ssize_t size_read, padding, size = self->tracing_data.size; | ||
1095 | off_t offset = lseek(session->fd, 0, SEEK_CUR); | ||
1096 | char buf[BUFSIZ]; | ||
1097 | |||
1098 | /* setup for reading amidst mmap */ | ||
1099 | lseek(session->fd, offset + sizeof(struct tracing_data_event), | ||
1100 | SEEK_SET); | ||
1101 | |||
1102 | size_read = trace_report(session->fd); | ||
1103 | |||
1104 | padding = ALIGN(size_read, sizeof(u64)) - size_read; | ||
1105 | |||
1106 | if (read(session->fd, buf, padding) < 0) | ||
1107 | die("reading input file"); | ||
1108 | |||
1109 | if (size_read + padding != size) | ||
1110 | die("tracing data size mismatch"); | ||
1111 | |||
1112 | return size_read + padding; | ||
1113 | } | ||
1114 | |||
1115 | int event__synthesize_build_id(struct dso *pos, u16 misc, | ||
1116 | event__handler_t process, | ||
1117 | struct kernel_info *kerninfo, | ||
1118 | struct perf_session *session) | ||
1119 | { | ||
1120 | event_t ev; | ||
1121 | size_t len; | ||
1122 | int err = 0; | ||
1123 | |||
1124 | if (!pos->hit) | ||
1125 | return err; | ||
1126 | |||
1127 | memset(&ev, 0, sizeof(ev)); | ||
1128 | |||
1129 | len = pos->long_name_len + 1; | ||
1130 | len = ALIGN(len, NAME_ALIGN); | ||
1131 | memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); | ||
1132 | ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; | ||
1133 | ev.build_id.header.misc = misc; | ||
1134 | ev.build_id.pid = kerninfo->pid; | ||
1135 | ev.build_id.header.size = sizeof(ev.build_id) + len; | ||
1136 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); | ||
1137 | |||
1138 | err = process(&ev, session); | ||
1139 | |||
1140 | return err; | ||
1141 | } | ||
1142 | |||
1143 | static int __event_synthesize_build_ids(struct list_head *head, u16 misc, | ||
1144 | event__handler_t process, | ||
1145 | struct kernel_info *kerninfo, | ||
1146 | struct perf_session *session) | ||
1147 | { | ||
1148 | struct dso *pos; | ||
1149 | |||
1150 | dsos__for_each_with_build_id(pos, head) { | ||
1151 | int err; | ||
1152 | if (!pos->hit) | ||
1153 | continue; | ||
1154 | |||
1155 | err = event__synthesize_build_id(pos, misc, process, | ||
1156 | kerninfo, session); | ||
1157 | if (err < 0) | ||
1158 | return err; | ||
1159 | } | ||
1160 | |||
1161 | return 0; | ||
1162 | } | ||
1163 | |||
1164 | int event__synthesize_build_ids(event__handler_t process, | ||
1165 | struct perf_session *session) | ||
1166 | { | ||
1167 | int err = 0; | ||
1168 | u16 kmisc, umisc; | ||
1169 | struct kernel_info *pos; | ||
1170 | struct rb_node *nd; | ||
1171 | |||
1172 | if (!dsos__read_build_ids(&session->header, true)) | ||
1173 | return 0; | ||
1174 | |||
1175 | for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { | ||
1176 | pos = rb_entry(nd, struct kernel_info, rb_node); | ||
1177 | if (is_host_kernel(pos)) { | ||
1178 | kmisc = PERF_RECORD_MISC_KERNEL; | ||
1179 | umisc = PERF_RECORD_MISC_USER; | ||
1180 | } else { | ||
1181 | kmisc = PERF_RECORD_MISC_GUEST_KERNEL; | ||
1182 | umisc = PERF_RECORD_MISC_GUEST_USER; | ||
1183 | } | ||
1184 | |||
1185 | err = __event_synthesize_build_ids(&pos->dsos__kernel, | ||
1186 | kmisc, process, pos, session); | ||
1187 | if (err == 0) | ||
1188 | err = __event_synthesize_build_ids(&pos->dsos__user, | ||
1189 | umisc, process, pos, session); | ||
1190 | if (err) | ||
1191 | break; | ||
1192 | } | ||
1193 | |||
1194 | if (err < 0) { | ||
1195 | pr_debug("failed to synthesize build ids\n"); | ||
1196 | return err; | ||
1197 | } | ||
1198 | |||
1199 | dsos__cache_build_ids(&session->header); | ||
1200 | |||
1201 | return 0; | ||
1202 | } | ||
1203 | |||
1204 | int event__process_build_id(event_t *self, | ||
1205 | struct perf_session *session) | ||
1206 | { | ||
1207 | __event_process_build_id(&self->build_id, | ||
1208 | self->build_id.filename, | ||
1209 | session); | ||
1210 | return 0; | ||
1211 | } | ||