diff options
-rw-r--r-- | Documentation/perf_counter/builtin-report.c | 211 |
1 files changed, 118 insertions, 93 deletions
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c index 333d31269e3f..82b62529e659 100644 --- a/Documentation/perf_counter/builtin-report.c +++ b/Documentation/perf_counter/builtin-report.c | |||
@@ -50,6 +50,7 @@ struct ip_event { | |||
50 | __u64 ip; | 50 | __u64 ip; |
51 | __u32 pid, tid; | 51 | __u32 pid, tid; |
52 | }; | 52 | }; |
53 | |||
53 | struct mmap_event { | 54 | struct mmap_event { |
54 | struct perf_event_header header; | 55 | struct perf_event_header header; |
55 | __u32 pid, tid; | 56 | __u32 pid, tid; |
@@ -58,9 +59,10 @@ struct mmap_event { | |||
58 | __u64 pgoff; | 59 | __u64 pgoff; |
59 | char filename[PATH_MAX]; | 60 | char filename[PATH_MAX]; |
60 | }; | 61 | }; |
62 | |||
61 | struct comm_event { | 63 | struct comm_event { |
62 | struct perf_event_header header; | 64 | struct perf_event_header header; |
63 | __u32 pid,tid; | 65 | __u32 pid, tid; |
64 | char comm[16]; | 66 | char comm[16]; |
65 | }; | 67 | }; |
66 | 68 | ||
@@ -760,114 +762,137 @@ static void register_idle_thread(void) | |||
760 | static unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0; | 762 | static unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0; |
761 | 763 | ||
762 | static int | 764 | static int |
763 | process_event(event_t *event, unsigned long offset, unsigned long head) | 765 | process_overflow_event(event_t *event, unsigned long offset, unsigned long head) |
764 | { | 766 | { |
765 | if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { | 767 | char level; |
766 | char level; | 768 | int show = 0; |
767 | int show = 0; | 769 | struct dso *dso = NULL; |
768 | struct dso *dso = NULL; | 770 | struct thread *thread = threads__findnew(event->ip.pid); |
769 | struct thread *thread = threads__findnew(event->ip.pid); | 771 | uint64_t ip = event->ip.ip; |
770 | uint64_t ip = event->ip.ip; | 772 | struct map *map = NULL; |
771 | struct map *map = NULL; | 773 | |
772 | 774 | dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", | |
773 | dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", | 775 | (void *)(offset + head), |
774 | (void *)(offset + head), | 776 | (void *)(long)(event->header.size), |
775 | (void *)(long)(event->header.size), | 777 | event->header.misc, |
776 | event->header.misc, | 778 | event->ip.pid, |
777 | event->ip.pid, | 779 | (void *)(long)ip); |
778 | (void *)(long)ip); | 780 | |
779 | 781 | dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); | |
780 | dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); | 782 | |
781 | 783 | if (thread == NULL) { | |
782 | if (thread == NULL) { | 784 | fprintf(stderr, "problem processing %d event, skipping it.\n", |
783 | fprintf(stderr, "problem processing %d event, skipping it.\n", | 785 | event->header.type); |
784 | event->header.type); | 786 | return -1; |
785 | return -1; | 787 | } |
786 | } | ||
787 | |||
788 | if (event->header.misc & PERF_EVENT_MISC_KERNEL) { | ||
789 | show = SHOW_KERNEL; | ||
790 | level = 'k'; | ||
791 | 788 | ||
792 | dso = kernel_dso; | 789 | if (event->header.misc & PERF_EVENT_MISC_KERNEL) { |
790 | show = SHOW_KERNEL; | ||
791 | level = 'k'; | ||
793 | 792 | ||
794 | dprintf(" ...... dso: %s\n", dso->name); | 793 | dso = kernel_dso; |
795 | 794 | ||
796 | } else if (event->header.misc & PERF_EVENT_MISC_USER) { | 795 | dprintf(" ...... dso: %s\n", dso->name); |
797 | 796 | ||
798 | show = SHOW_USER; | 797 | } else if (event->header.misc & PERF_EVENT_MISC_USER) { |
799 | level = '.'; | ||
800 | 798 | ||
801 | map = thread__find_map(thread, ip); | 799 | show = SHOW_USER; |
802 | if (map != NULL) { | 800 | level = '.'; |
803 | dso = map->dso; | ||
804 | ip -= map->start + map->pgoff; | ||
805 | } else { | ||
806 | /* | ||
807 | * If this is outside of all known maps, | ||
808 | * and is a negative address, try to look it | ||
809 | * up in the kernel dso, as it might be a | ||
810 | * vsyscall (which executes in user-mode): | ||
811 | */ | ||
812 | if ((long long)ip < 0) | ||
813 | dso = kernel_dso; | ||
814 | } | ||
815 | dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); | ||
816 | 801 | ||
802 | map = thread__find_map(thread, ip); | ||
803 | if (map != NULL) { | ||
804 | dso = map->dso; | ||
805 | ip -= map->start + map->pgoff; | ||
817 | } else { | 806 | } else { |
818 | show = SHOW_HV; | 807 | /* |
819 | level = 'H'; | 808 | * If this is outside of all known maps, |
820 | dprintf(" ...... dso: [hypervisor]\n"); | 809 | * and is a negative address, try to look it |
810 | * up in the kernel dso, as it might be a | ||
811 | * vsyscall (which executes in user-mode): | ||
812 | */ | ||
813 | if ((long long)ip < 0) | ||
814 | dso = kernel_dso; | ||
821 | } | 815 | } |
816 | dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); | ||
822 | 817 | ||
823 | if (show & show_mask) { | 818 | } else { |
824 | struct symbol *sym = dso__find_symbol(dso, ip); | 819 | show = SHOW_HV; |
820 | level = 'H'; | ||
821 | dprintf(" ...... dso: [hypervisor]\n"); | ||
822 | } | ||
825 | 823 | ||
826 | if (hist_entry__add(thread, map, dso, sym, ip, level)) { | 824 | if (show & show_mask) { |
827 | fprintf(stderr, | 825 | struct symbol *sym = dso__find_symbol(dso, ip); |
828 | "problem incrementing symbol count, skipping event\n"); | ||
829 | return -1; | ||
830 | } | ||
831 | } | ||
832 | total++; | ||
833 | } else switch (event->header.type) { | ||
834 | case PERF_EVENT_MMAP: { | ||
835 | struct thread *thread = threads__findnew(event->mmap.pid); | ||
836 | struct map *map = map__new(&event->mmap); | ||
837 | 826 | ||
838 | dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n", | 827 | if (hist_entry__add(thread, map, dso, sym, ip, level)) { |
839 | (void *)(offset + head), | 828 | fprintf(stderr, |
840 | (void *)(long)(event->header.size), | 829 | "problem incrementing symbol count, skipping event\n"); |
841 | (void *)(long)event->mmap.start, | ||
842 | (void *)(long)event->mmap.len, | ||
843 | (void *)(long)event->mmap.pgoff, | ||
844 | event->mmap.filename); | ||
845 | |||
846 | if (thread == NULL || map == NULL) { | ||
847 | if (verbose) | ||
848 | fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n"); | ||
849 | return -1; | 830 | return -1; |
850 | } | 831 | } |
851 | thread__insert_map(thread, map); | ||
852 | total_mmap++; | ||
853 | break; | ||
854 | } | 832 | } |
855 | case PERF_EVENT_COMM: { | 833 | total++; |
856 | struct thread *thread = threads__findnew(event->comm.pid); | ||
857 | 834 | ||
858 | dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", | 835 | return 0; |
859 | (void *)(offset + head), | 836 | } |
860 | (void *)(long)(event->header.size), | ||
861 | event->comm.comm, event->comm.pid); | ||
862 | 837 | ||
863 | if (thread == NULL || | 838 | static int |
864 | thread__set_comm(thread, event->comm.comm)) { | 839 | process_mmap_event(event_t *event, unsigned long offset, unsigned long head) |
865 | fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n"); | 840 | { |
866 | return -1; | 841 | struct thread *thread = threads__findnew(event->mmap.pid); |
867 | } | 842 | struct map *map = map__new(&event->mmap); |
868 | total_comm++; | 843 | |
869 | break; | 844 | dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n", |
845 | (void *)(offset + head), | ||
846 | (void *)(long)(event->header.size), | ||
847 | (void *)(long)event->mmap.start, | ||
848 | (void *)(long)event->mmap.len, | ||
849 | (void *)(long)event->mmap.pgoff, | ||
850 | event->mmap.filename); | ||
851 | |||
852 | if (thread == NULL || map == NULL) { | ||
853 | dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n"); | ||
854 | return -1; | ||
855 | } | ||
856 | |||
857 | thread__insert_map(thread, map); | ||
858 | total_mmap++; | ||
859 | |||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | static int | ||
864 | process_comm_event(event_t *event, unsigned long offset, unsigned long head) | ||
865 | { | ||
866 | struct thread *thread = threads__findnew(event->comm.pid); | ||
867 | |||
868 | dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", | ||
869 | (void *)(offset + head), | ||
870 | (void *)(long)(event->header.size), | ||
871 | event->comm.comm, event->comm.pid); | ||
872 | |||
873 | if (thread == NULL || | ||
874 | thread__set_comm(thread, event->comm.comm)) { | ||
875 | dprintf("problem processing PERF_EVENT_COMM, skipping event.\n"); | ||
876 | return -1; | ||
870 | } | 877 | } |
878 | total_comm++; | ||
879 | |||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | static int | ||
884 | process_event(event_t *event, unsigned long offset, unsigned long head) | ||
885 | { | ||
886 | if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) | ||
887 | return process_overflow_event(event, offset, head); | ||
888 | |||
889 | switch (event->header.type) { | ||
890 | case PERF_EVENT_MMAP: | ||
891 | return process_mmap_event(event, offset, head); | ||
892 | |||
893 | case PERF_EVENT_COMM: | ||
894 | return process_comm_event(event, offset, head); | ||
895 | |||
871 | default: | 896 | default: |
872 | return -1; | 897 | return -1; |
873 | } | 898 | } |
@@ -877,13 +902,13 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
877 | 902 | ||
878 | static int __cmd_report(void) | 903 | static int __cmd_report(void) |
879 | { | 904 | { |
905 | int ret, rc = EXIT_FAILURE; | ||
880 | unsigned long offset = 0; | 906 | unsigned long offset = 0; |
881 | unsigned long head = 0; | 907 | unsigned long head = 0; |
882 | struct stat stat; | 908 | struct stat stat; |
883 | char *buf; | ||
884 | event_t *event; | 909 | event_t *event; |
885 | int ret, rc = EXIT_FAILURE; | ||
886 | uint32_t size; | 910 | uint32_t size; |
911 | char *buf; | ||
887 | 912 | ||
888 | register_idle_thread(); | 913 | register_idle_thread(); |
889 | 914 | ||