aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r--tools/perf/util/annotate.c137
1 files changed, 89 insertions, 48 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index be1caabb9290..4397a8b6e6cd 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -47,7 +47,12 @@ struct arch {
47 bool sorted_instructions; 47 bool sorted_instructions;
48 bool initialized; 48 bool initialized;
49 void *priv; 49 void *priv;
50 unsigned int model;
51 unsigned int family;
50 int (*init)(struct arch *arch); 52 int (*init)(struct arch *arch);
53 bool (*ins_is_fused)(struct arch *arch, const char *ins1,
54 const char *ins2);
55 int (*cpuid_parse)(struct arch *arch, char *cpuid);
51 struct { 56 struct {
52 char comment_char; 57 char comment_char;
53 char skip_functions_char; 58 char skip_functions_char;
@@ -129,6 +134,8 @@ static struct arch architectures[] = {
129 .name = "x86", 134 .name = "x86",
130 .instructions = x86__instructions, 135 .instructions = x86__instructions,
131 .nr_instructions = ARRAY_SIZE(x86__instructions), 136 .nr_instructions = ARRAY_SIZE(x86__instructions),
137 .ins_is_fused = x86__ins_is_fused,
138 .cpuid_parse = x86__cpuid_parse,
132 .objdump = { 139 .objdump = {
133 .comment_char = '#', 140 .comment_char = '#',
134 }, 141 },
@@ -171,6 +178,14 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size,
171 return ins__raw_scnprintf(ins, bf, size, ops); 178 return ins__raw_scnprintf(ins, bf, size, ops);
172} 179}
173 180
181bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
182{
183 if (!arch || !arch->ins_is_fused)
184 return false;
185
186 return arch->ins_is_fused(arch, ins1, ins2);
187}
188
174static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 189static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map)
175{ 190{
176 char *endptr, *tok, *name; 191 char *endptr, *tok, *name;
@@ -502,6 +517,11 @@ bool ins__is_ret(const struct ins *ins)
502 return ins->ops == &ret_ops; 517 return ins->ops == &ret_ops;
503} 518}
504 519
520bool ins__is_lock(const struct ins *ins)
521{
522 return ins->ops == &lock_ops;
523}
524
505static int ins__key_cmp(const void *name, const void *insp) 525static int ins__key_cmp(const void *name, const void *insp)
506{ 526{
507 const struct ins *ins = insp; 527 const struct ins *ins = insp;
@@ -590,10 +610,10 @@ int symbol__alloc_hist(struct symbol *sym)
590 size_t sizeof_sym_hist; 610 size_t sizeof_sym_hist;
591 611
592 /* Check for overflow when calculating sizeof_sym_hist */ 612 /* Check for overflow when calculating sizeof_sym_hist */
593 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64)) 613 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
594 return -1; 614 return -1;
595 615
596 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); 616 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
597 617
598 /* Check for overflow in zalloc argument */ 618 /* Check for overflow in zalloc argument */
599 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src)) 619 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
@@ -677,7 +697,8 @@ static int __symbol__account_cycles(struct annotation *notes,
677} 697}
678 698
679static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, 699static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
680 struct annotation *notes, int evidx, u64 addr) 700 struct annotation *notes, int evidx, u64 addr,
701 struct perf_sample *sample)
681{ 702{
682 unsigned offset; 703 unsigned offset;
683 struct sym_hist *h; 704 struct sym_hist *h;
@@ -693,12 +714,15 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
693 714
694 offset = addr - sym->start; 715 offset = addr - sym->start;
695 h = annotation__histogram(notes, evidx); 716 h = annotation__histogram(notes, evidx);
696 h->sum++; 717 h->nr_samples++;
697 h->addr[offset]++; 718 h->addr[offset].nr_samples++;
719 h->period += sample->period;
720 h->addr[offset].period += sample->period;
698 721
699 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64 722 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
700 ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name, 723 ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
701 addr, addr - sym->start, evidx, h->addr[offset]); 724 sym->start, sym->name, addr, addr - sym->start, evidx,
725 h->addr[offset].nr_samples, h->addr[offset].period);
702 return 0; 726 return 0;
703} 727}
704 728
@@ -718,7 +742,8 @@ static struct annotation *symbol__get_annotation(struct symbol *sym, bool cycles
718} 742}
719 743
720static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 744static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
721 int evidx, u64 addr) 745 int evidx, u64 addr,
746 struct perf_sample *sample)
722{ 747{
723 struct annotation *notes; 748 struct annotation *notes;
724 749
@@ -727,7 +752,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
727 notes = symbol__get_annotation(sym, false); 752 notes = symbol__get_annotation(sym, false);
728 if (notes == NULL) 753 if (notes == NULL)
729 return -ENOMEM; 754 return -ENOMEM;
730 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); 755 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr, sample);
731} 756}
732 757
733static int symbol__account_cycles(u64 addr, u64 start, 758static int symbol__account_cycles(u64 addr, u64 start,
@@ -791,14 +816,16 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
791 return err; 816 return err;
792} 817}
793 818
794int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx) 819int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
820 int evidx)
795{ 821{
796 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr); 822 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr, sample);
797} 823}
798 824
799int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) 825int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
826 int evidx, u64 ip)
800{ 827{
801 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 828 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample);
802} 829}
803 830
804static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 831static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
@@ -908,11 +935,12 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
908} 935}
909 936
910double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 937double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
911 s64 end, const char **path, u64 *nr_samples) 938 s64 end, const char **path, struct sym_hist_entry *sample)
912{ 939{
913 struct source_line *src_line = notes->src->lines; 940 struct source_line *src_line = notes->src->lines;
914 double percent = 0.0; 941 double percent = 0.0;
915 *nr_samples = 0; 942
943 sample->nr_samples = sample->period = 0;
916 944
917 if (src_line) { 945 if (src_line) {
918 size_t sizeof_src_line = sizeof(*src_line) + 946 size_t sizeof_src_line = sizeof(*src_line) +
@@ -926,19 +954,24 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
926 *path = src_line->path; 954 *path = src_line->path;
927 955
928 percent += src_line->samples[evidx].percent; 956 percent += src_line->samples[evidx].percent;
929 *nr_samples += src_line->samples[evidx].nr; 957 sample->nr_samples += src_line->samples[evidx].nr;
930 offset++; 958 offset++;
931 } 959 }
932 } else { 960 } else {
933 struct sym_hist *h = annotation__histogram(notes, evidx); 961 struct sym_hist *h = annotation__histogram(notes, evidx);
934 unsigned int hits = 0; 962 unsigned int hits = 0;
963 u64 period = 0;
935 964
936 while (offset < end) 965 while (offset < end) {
937 hits += h->addr[offset++]; 966 hits += h->addr[offset].nr_samples;
967 period += h->addr[offset].period;
968 ++offset;
969 }
938 970
939 if (h->sum) { 971 if (h->nr_samples) {
940 *nr_samples = hits; 972 sample->period = period;
941 percent = 100.0 * hits / h->sum; 973 sample->nr_samples = hits;
974 percent = 100.0 * hits / h->nr_samples;
942 } 975 }
943 } 976 }
944 977
@@ -1037,10 +1070,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1037 1070
1038 if (dl->offset != -1) { 1071 if (dl->offset != -1) {
1039 const char *path = NULL; 1072 const char *path = NULL;
1040 u64 nr_samples;
1041 double percent, max_percent = 0.0; 1073 double percent, max_percent = 0.0;
1042 double *ppercents = &percent; 1074 double *ppercents = &percent;
1043 u64 *psamples = &nr_samples; 1075 struct sym_hist_entry sample;
1076 struct sym_hist_entry *psamples = &sample;
1044 int i, nr_percent = 1; 1077 int i, nr_percent = 1;
1045 const char *color; 1078 const char *color;
1046 struct annotation *notes = symbol__annotation(sym); 1079 struct annotation *notes = symbol__annotation(sym);
@@ -1054,7 +1087,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1054 if (perf_evsel__is_group_event(evsel)) { 1087 if (perf_evsel__is_group_event(evsel)) {
1055 nr_percent = evsel->nr_members; 1088 nr_percent = evsel->nr_members;
1056 ppercents = calloc(nr_percent, sizeof(double)); 1089 ppercents = calloc(nr_percent, sizeof(double));
1057 psamples = calloc(nr_percent, sizeof(u64)); 1090 psamples = calloc(nr_percent, sizeof(struct sym_hist_entry));
1058 if (ppercents == NULL || psamples == NULL) { 1091 if (ppercents == NULL || psamples == NULL) {
1059 return -1; 1092 return -1;
1060 } 1093 }
@@ -1065,10 +1098,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1065 notes->src->lines ? i : evsel->idx + i, 1098 notes->src->lines ? i : evsel->idx + i,
1066 offset, 1099 offset,
1067 next ? next->offset : (s64) len, 1100 next ? next->offset : (s64) len,
1068 &path, &nr_samples); 1101 &path, &sample);
1069 1102
1070 ppercents[i] = percent; 1103 ppercents[i] = percent;
1071 psamples[i] = nr_samples; 1104 psamples[i] = sample;
1072 if (percent > max_percent) 1105 if (percent > max_percent)
1073 max_percent = percent; 1106 max_percent = percent;
1074 } 1107 }
@@ -1106,12 +1139,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1106 1139
1107 for (i = 0; i < nr_percent; i++) { 1140 for (i = 0; i < nr_percent; i++) {
1108 percent = ppercents[i]; 1141 percent = ppercents[i];
1109 nr_samples = psamples[i]; 1142 sample = psamples[i];
1110 color = get_percent_color(percent); 1143 color = get_percent_color(percent);
1111 1144
1112 if (symbol_conf.show_total_period) 1145 if (symbol_conf.show_total_period)
1146 color_fprintf(stdout, color, " %11" PRIu64,
1147 sample.period);
1148 else if (symbol_conf.show_nr_samples)
1113 color_fprintf(stdout, color, " %7" PRIu64, 1149 color_fprintf(stdout, color, " %7" PRIu64,
1114 nr_samples); 1150 sample.nr_samples);
1115 else 1151 else
1116 color_fprintf(stdout, color, " %7.2f", percent); 1152 color_fprintf(stdout, color, " %7.2f", percent);
1117 } 1153 }
@@ -1127,13 +1163,13 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1127 if (ppercents != &percent) 1163 if (ppercents != &percent)
1128 free(ppercents); 1164 free(ppercents);
1129 1165
1130 if (psamples != &nr_samples) 1166 if (psamples != &sample)
1131 free(psamples); 1167 free(psamples);
1132 1168
1133 } else if (max_lines && printed >= max_lines) 1169 } else if (max_lines && printed >= max_lines)
1134 return 1; 1170 return 1;
1135 else { 1171 else {
1136 int width = 8; 1172 int width = symbol_conf.show_total_period ? 12 : 8;
1137 1173
1138 if (queue) 1174 if (queue)
1139 return -1; 1175 return -1;
@@ -1327,7 +1363,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1327 !dso__is_kcore(dso)) 1363 !dso__is_kcore(dso))
1328 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; 1364 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1329 1365
1330 build_id_filename = dso__build_id_filename(dso, NULL, 0); 1366 build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
1331 if (build_id_filename) { 1367 if (build_id_filename) {
1332 __symbol__join_symfs(filename, filename_size, build_id_filename); 1368 __symbol__join_symfs(filename, filename_size, build_id_filename);
1333 free(build_id_filename); 1369 free(build_id_filename);
@@ -1381,7 +1417,7 @@ static const char *annotate__norm_arch(const char *arch_name)
1381 1417
1382int symbol__disassemble(struct symbol *sym, struct map *map, 1418int symbol__disassemble(struct symbol *sym, struct map *map,
1383 const char *arch_name, size_t privsize, 1419 const char *arch_name, size_t privsize,
1384 struct arch **parch) 1420 struct arch **parch, char *cpuid)
1385{ 1421{
1386 struct dso *dso = map->dso; 1422 struct dso *dso = map->dso;
1387 char command[PATH_MAX * 2]; 1423 char command[PATH_MAX * 2];
@@ -1418,6 +1454,9 @@ int symbol__disassemble(struct symbol *sym, struct map *map,
1418 } 1454 }
1419 } 1455 }
1420 1456
1457 if (arch->cpuid_parse && cpuid)
1458 arch->cpuid_parse(arch, cpuid);
1459
1421 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, 1460 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1422 symfs_filename, sym->name, map->unmap_ip(map, sym->start), 1461 symfs_filename, sym->name, map->unmap_ip(map, sym->start),
1423 map->unmap_ip(map, sym->end)); 1462 map->unmap_ip(map, sym->end));
@@ -1648,19 +1687,19 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1648 struct sym_hist *h = annotation__histogram(notes, evidx); 1687 struct sym_hist *h = annotation__histogram(notes, evidx);
1649 struct rb_root tmp_root = RB_ROOT; 1688 struct rb_root tmp_root = RB_ROOT;
1650 int nr_pcnt = 1; 1689 int nr_pcnt = 1;
1651 u64 h_sum = h->sum; 1690 u64 nr_samples = h->nr_samples;
1652 size_t sizeof_src_line = sizeof(struct source_line); 1691 size_t sizeof_src_line = sizeof(struct source_line);
1653 1692
1654 if (perf_evsel__is_group_event(evsel)) { 1693 if (perf_evsel__is_group_event(evsel)) {
1655 for (i = 1; i < evsel->nr_members; i++) { 1694 for (i = 1; i < evsel->nr_members; i++) {
1656 h = annotation__histogram(notes, evidx + i); 1695 h = annotation__histogram(notes, evidx + i);
1657 h_sum += h->sum; 1696 nr_samples += h->nr_samples;
1658 } 1697 }
1659 nr_pcnt = evsel->nr_members; 1698 nr_pcnt = evsel->nr_members;
1660 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples); 1699 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
1661 } 1700 }
1662 1701
1663 if (!h_sum) 1702 if (!nr_samples)
1664 return 0; 1703 return 0;
1665 1704
1666 src_line = notes->src->lines = calloc(len, sizeof_src_line); 1705 src_line = notes->src->lines = calloc(len, sizeof_src_line);
@@ -1670,7 +1709,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1670 start = map__rip_2objdump(map, sym->start); 1709 start = map__rip_2objdump(map, sym->start);
1671 1710
1672 for (i = 0; i < len; i++) { 1711 for (i = 0; i < len; i++) {
1673 u64 offset, nr_samples; 1712 u64 offset;
1674 double percent_max = 0.0; 1713 double percent_max = 0.0;
1675 1714
1676 src_line->nr_pcnt = nr_pcnt; 1715 src_line->nr_pcnt = nr_pcnt;
@@ -1679,9 +1718,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1679 double percent = 0.0; 1718 double percent = 0.0;
1680 1719
1681 h = annotation__histogram(notes, evidx + k); 1720 h = annotation__histogram(notes, evidx + k);
1682 nr_samples = h->addr[i]; 1721 nr_samples = h->addr[i].nr_samples;
1683 if (h->sum) 1722 if (h->nr_samples)
1684 percent = 100.0 * nr_samples / h->sum; 1723 percent = 100.0 * nr_samples / h->nr_samples;
1685 1724
1686 if (percent > percent_max) 1725 if (percent > percent_max)
1687 percent_max = percent; 1726 percent_max = percent;
@@ -1750,10 +1789,10 @@ static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
1750 u64 len = symbol__size(sym), offset; 1789 u64 len = symbol__size(sym), offset;
1751 1790
1752 for (offset = 0; offset < len; ++offset) 1791 for (offset = 0; offset < len; ++offset)
1753 if (h->addr[offset] != 0) 1792 if (h->addr[offset].nr_samples != 0)
1754 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, 1793 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
1755 sym->start + offset, h->addr[offset]); 1794 sym->start + offset, h->addr[offset].nr_samples);
1756 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); 1795 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
1757} 1796}
1758 1797
1759int symbol__annotate_printf(struct symbol *sym, struct map *map, 1798int symbol__annotate_printf(struct symbol *sym, struct map *map,
@@ -1771,7 +1810,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1771 int printed = 2, queue_len = 0; 1810 int printed = 2, queue_len = 0;
1772 int more = 0; 1811 int more = 0;
1773 u64 len; 1812 u64 len;
1774 int width = 8; 1813 int width = symbol_conf.show_total_period ? 12 : 8;
1775 int graph_dotted_len; 1814 int graph_dotted_len;
1776 1815
1777 filename = strdup(dso->long_name); 1816 filename = strdup(dso->long_name);
@@ -1789,7 +1828,9 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1789 width *= evsel->nr_members; 1828 width *= evsel->nr_members;
1790 1829
1791 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 1830 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1792 width, width, "Percent", d_filename, evsel_name, h->sum); 1831 width, width, symbol_conf.show_total_period ? "Period" :
1832 symbol_conf.show_nr_samples ? "Samples" : "Percent",
1833 d_filename, evsel_name, h->nr_samples);
1793 1834
1794 printf("%-*.*s----\n", 1835 printf("%-*.*s----\n",
1795 graph_dotted_len, graph_dotted_len, graph_dotted_line); 1836 graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -1853,10 +1894,10 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
1853 struct sym_hist *h = annotation__histogram(notes, evidx); 1894 struct sym_hist *h = annotation__histogram(notes, evidx);
1854 int len = symbol__size(sym), offset; 1895 int len = symbol__size(sym), offset;
1855 1896
1856 h->sum = 0; 1897 h->nr_samples = 0;
1857 for (offset = 0; offset < len; ++offset) { 1898 for (offset = 0; offset < len; ++offset) {
1858 h->addr[offset] = h->addr[offset] * 7 / 8; 1899 h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
1859 h->sum += h->addr[offset]; 1900 h->nr_samples += h->addr[offset].nr_samples;
1860 } 1901 }
1861} 1902}
1862 1903
@@ -1907,7 +1948,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1907 u64 len; 1948 u64 len;
1908 1949
1909 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 1950 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
1910 0, NULL) < 0) 1951 0, NULL, NULL) < 0)
1911 return -1; 1952 return -1;
1912 1953
1913 len = symbol__size(sym); 1954 len = symbol__size(sym);