diff options
-rw-r--r-- | Documentation/perf_counter/builtin-report.c | 186 |
1 files changed, 98 insertions, 88 deletions
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c index 33b3b15fb014..333d31269e3f 100644 --- a/Documentation/perf_counter/builtin-report.c +++ b/Documentation/perf_counter/builtin-report.c | |||
@@ -147,7 +147,11 @@ static int load_kernel(void) | |||
147 | return err; | 147 | return err; |
148 | } | 148 | } |
149 | 149 | ||
150 | static int strcommon(const char *pathname, const char *cwd, int cwdlen) | 150 | static char __cwd[PATH_MAX]; |
151 | static char *cwd = __cwd; | ||
152 | static int cwdlen; | ||
153 | |||
154 | static int strcommon(const char *pathname) | ||
151 | { | 155 | { |
152 | int n = 0; | 156 | int n = 0; |
153 | 157 | ||
@@ -165,7 +169,7 @@ struct map { | |||
165 | struct dso *dso; | 169 | struct dso *dso; |
166 | }; | 170 | }; |
167 | 171 | ||
168 | static struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) | 172 | static struct map *map__new(struct mmap_event *event) |
169 | { | 173 | { |
170 | struct map *self = malloc(sizeof(*self)); | 174 | struct map *self = malloc(sizeof(*self)); |
171 | 175 | ||
@@ -174,7 +178,8 @@ static struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) | |||
174 | char newfilename[PATH_MAX]; | 178 | char newfilename[PATH_MAX]; |
175 | 179 | ||
176 | if (cwd) { | 180 | if (cwd) { |
177 | int n = strcommon(filename, cwd, cwdlen); | 181 | int n = strcommon(filename); |
182 | |||
178 | if (n == cwdlen) { | 183 | if (n == cwdlen) { |
179 | snprintf(newfilename, sizeof(newfilename), | 184 | snprintf(newfilename, sizeof(newfilename), |
180 | ".%s", filename + n); | 185 | ".%s", filename + n); |
@@ -752,85 +757,11 @@ static void register_idle_thread(void) | |||
752 | } | 757 | } |
753 | } | 758 | } |
754 | 759 | ||
760 | static unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0; | ||
755 | 761 | ||
756 | static int __cmd_report(void) | 762 | static int |
763 | process_event(event_t *event, unsigned long offset, unsigned long head) | ||
757 | { | 764 | { |
758 | unsigned long offset = 0; | ||
759 | unsigned long head = 0; | ||
760 | struct stat stat; | ||
761 | char *buf; | ||
762 | event_t *event; | ||
763 | int ret, rc = EXIT_FAILURE; | ||
764 | uint32_t size; | ||
765 | unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0; | ||
766 | char cwd[PATH_MAX], *cwdp = cwd; | ||
767 | int cwdlen; | ||
768 | |||
769 | register_idle_thread(); | ||
770 | |||
771 | input = open(input_name, O_RDONLY); | ||
772 | if (input < 0) { | ||
773 | perror("failed to open file"); | ||
774 | exit(-1); | ||
775 | } | ||
776 | |||
777 | ret = fstat(input, &stat); | ||
778 | if (ret < 0) { | ||
779 | perror("failed to stat file"); | ||
780 | exit(-1); | ||
781 | } | ||
782 | |||
783 | if (!stat.st_size) { | ||
784 | fprintf(stderr, "zero-sized file, nothing to do!\n"); | ||
785 | exit(0); | ||
786 | } | ||
787 | |||
788 | if (load_kernel() < 0) { | ||
789 | perror("failed to load kernel symbols"); | ||
790 | return EXIT_FAILURE; | ||
791 | } | ||
792 | |||
793 | if (!full_paths) { | ||
794 | if (getcwd(cwd, sizeof(cwd)) == NULL) { | ||
795 | perror("failed to get the current directory"); | ||
796 | return EXIT_FAILURE; | ||
797 | } | ||
798 | cwdlen = strlen(cwd); | ||
799 | } else { | ||
800 | cwdp = NULL; | ||
801 | cwdlen = 0; | ||
802 | } | ||
803 | remap: | ||
804 | buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, | ||
805 | MAP_SHARED, input, offset); | ||
806 | if (buf == MAP_FAILED) { | ||
807 | perror("failed to mmap file"); | ||
808 | exit(-1); | ||
809 | } | ||
810 | |||
811 | more: | ||
812 | event = (event_t *)(buf + head); | ||
813 | |||
814 | size = event->header.size; | ||
815 | if (!size) | ||
816 | size = 8; | ||
817 | |||
818 | if (head + event->header.size >= page_size * mmap_window) { | ||
819 | unsigned long shift = page_size * (head / page_size); | ||
820 | int ret; | ||
821 | |||
822 | ret = munmap(buf, page_size * mmap_window); | ||
823 | assert(ret == 0); | ||
824 | |||
825 | offset += shift; | ||
826 | head -= shift; | ||
827 | goto remap; | ||
828 | } | ||
829 | |||
830 | size = event->header.size; | ||
831 | if (!size) | ||
832 | goto broken_event; | ||
833 | |||
834 | if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { | 765 | if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { |
835 | char level; | 766 | char level; |
836 | int show = 0; | 767 | int show = 0; |
@@ -851,7 +782,7 @@ more: | |||
851 | if (thread == NULL) { | 782 | if (thread == NULL) { |
852 | fprintf(stderr, "problem processing %d event, skipping it.\n", | 783 | fprintf(stderr, "problem processing %d event, skipping it.\n", |
853 | event->header.type); | 784 | event->header.type); |
854 | goto broken_event; | 785 | return -1; |
855 | } | 786 | } |
856 | 787 | ||
857 | if (event->header.misc & PERF_EVENT_MISC_KERNEL) { | 788 | if (event->header.misc & PERF_EVENT_MISC_KERNEL) { |
@@ -895,14 +826,14 @@ more: | |||
895 | if (hist_entry__add(thread, map, dso, sym, ip, level)) { | 826 | if (hist_entry__add(thread, map, dso, sym, ip, level)) { |
896 | fprintf(stderr, | 827 | fprintf(stderr, |
897 | "problem incrementing symbol count, skipping event\n"); | 828 | "problem incrementing symbol count, skipping event\n"); |
898 | goto broken_event; | 829 | return -1; |
899 | } | 830 | } |
900 | } | 831 | } |
901 | total++; | 832 | total++; |
902 | } else switch (event->header.type) { | 833 | } else switch (event->header.type) { |
903 | case PERF_EVENT_MMAP: { | 834 | case PERF_EVENT_MMAP: { |
904 | struct thread *thread = threads__findnew(event->mmap.pid); | 835 | struct thread *thread = threads__findnew(event->mmap.pid); |
905 | struct map *map = map__new(&event->mmap, cwdp, cwdlen); | 836 | struct map *map = map__new(&event->mmap); |
906 | 837 | ||
907 | dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n", | 838 | dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n", |
908 | (void *)(offset + head), | 839 | (void *)(offset + head), |
@@ -915,7 +846,7 @@ more: | |||
915 | if (thread == NULL || map == NULL) { | 846 | if (thread == NULL || map == NULL) { |
916 | if (verbose) | 847 | if (verbose) |
917 | fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n"); | 848 | fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n"); |
918 | goto broken_event; | 849 | return -1; |
919 | } | 850 | } |
920 | thread__insert_map(thread, map); | 851 | thread__insert_map(thread, map); |
921 | total_mmap++; | 852 | total_mmap++; |
@@ -932,13 +863,93 @@ more: | |||
932 | if (thread == NULL || | 863 | if (thread == NULL || |
933 | thread__set_comm(thread, event->comm.comm)) { | 864 | thread__set_comm(thread, event->comm.comm)) { |
934 | fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n"); | 865 | fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n"); |
935 | goto broken_event; | 866 | return -1; |
936 | } | 867 | } |
937 | total_comm++; | 868 | total_comm++; |
938 | break; | 869 | break; |
939 | } | 870 | } |
940 | default: { | 871 | default: |
941 | broken_event: | 872 | return -1; |
873 | } | ||
874 | |||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | static int __cmd_report(void) | ||
879 | { | ||
880 | unsigned long offset = 0; | ||
881 | unsigned long head = 0; | ||
882 | struct stat stat; | ||
883 | char *buf; | ||
884 | event_t *event; | ||
885 | int ret, rc = EXIT_FAILURE; | ||
886 | uint32_t size; | ||
887 | |||
888 | register_idle_thread(); | ||
889 | |||
890 | input = open(input_name, O_RDONLY); | ||
891 | if (input < 0) { | ||
892 | perror("failed to open file"); | ||
893 | exit(-1); | ||
894 | } | ||
895 | |||
896 | ret = fstat(input, &stat); | ||
897 | if (ret < 0) { | ||
898 | perror("failed to stat file"); | ||
899 | exit(-1); | ||
900 | } | ||
901 | |||
902 | if (!stat.st_size) { | ||
903 | fprintf(stderr, "zero-sized file, nothing to do!\n"); | ||
904 | exit(0); | ||
905 | } | ||
906 | |||
907 | if (load_kernel() < 0) { | ||
908 | perror("failed to load kernel symbols"); | ||
909 | return EXIT_FAILURE; | ||
910 | } | ||
911 | |||
912 | if (!full_paths) { | ||
913 | if (getcwd(__cwd, sizeof(__cwd)) == NULL) { | ||
914 | perror("failed to get the current directory"); | ||
915 | return EXIT_FAILURE; | ||
916 | } | ||
917 | cwdlen = strlen(cwd); | ||
918 | } else { | ||
919 | cwd = NULL; | ||
920 | cwdlen = 0; | ||
921 | } | ||
922 | remap: | ||
923 | buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, | ||
924 | MAP_SHARED, input, offset); | ||
925 | if (buf == MAP_FAILED) { | ||
926 | perror("failed to mmap file"); | ||
927 | exit(-1); | ||
928 | } | ||
929 | |||
930 | more: | ||
931 | event = (event_t *)(buf + head); | ||
932 | |||
933 | size = event->header.size; | ||
934 | if (!size) | ||
935 | size = 8; | ||
936 | |||
937 | if (head + event->header.size >= page_size * mmap_window) { | ||
938 | unsigned long shift = page_size * (head / page_size); | ||
939 | int ret; | ||
940 | |||
941 | ret = munmap(buf, page_size * mmap_window); | ||
942 | assert(ret == 0); | ||
943 | |||
944 | offset += shift; | ||
945 | head -= shift; | ||
946 | goto remap; | ||
947 | } | ||
948 | |||
949 | size = event->header.size; | ||
950 | |||
951 | if (!size || process_event(event, offset, head) < 0) { | ||
952 | |||
942 | dprintf("%p [%p]: skipping unknown header type: %d\n", | 953 | dprintf("%p [%p]: skipping unknown header type: %d\n", |
943 | (void *)(offset + head), | 954 | (void *)(offset + head), |
944 | (void *)(long)(event->header.size), | 955 | (void *)(long)(event->header.size), |
@@ -956,7 +967,6 @@ broken_event: | |||
956 | 967 | ||
957 | size = 8; | 968 | size = 8; |
958 | } | 969 | } |
959 | } | ||
960 | 970 | ||
961 | head += size; | 971 | head += size; |
962 | 972 | ||