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.c149
1 files changed, 98 insertions, 51 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index be1caabb9290..da1c4c4a0dd8 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -47,7 +47,11 @@ struct arch {
47 bool sorted_instructions; 47 bool sorted_instructions;
48 bool initialized; 48 bool initialized;
49 void *priv; 49 void *priv;
50 int (*init)(struct arch *arch); 50 unsigned int model;
51 unsigned int family;
52 int (*init)(struct arch *arch, char *cpuid);
53 bool (*ins_is_fused)(struct arch *arch, const char *ins1,
54 const char *ins2);
51 struct { 55 struct {
52 char comment_char; 56 char comment_char;
53 char skip_functions_char; 57 char skip_functions_char;
@@ -127,8 +131,10 @@ static struct arch architectures[] = {
127 }, 131 },
128 { 132 {
129 .name = "x86", 133 .name = "x86",
134 .init = x86__annotate_init,
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,
132 .objdump = { 138 .objdump = {
133 .comment_char = '#', 139 .comment_char = '#',
134 }, 140 },
@@ -171,6 +177,14 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size,
171 return ins__raw_scnprintf(ins, bf, size, ops); 177 return ins__raw_scnprintf(ins, bf, size, ops);
172} 178}
173 179
180bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
181{
182 if (!arch || !arch->ins_is_fused)
183 return false;
184
185 return arch->ins_is_fused(arch, ins1, ins2);
186}
187
174static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 188static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map)
175{ 189{
176 char *endptr, *tok, *name; 190 char *endptr, *tok, *name;
@@ -502,6 +516,11 @@ bool ins__is_ret(const struct ins *ins)
502 return ins->ops == &ret_ops; 516 return ins->ops == &ret_ops;
503} 517}
504 518
519bool ins__is_lock(const struct ins *ins)
520{
521 return ins->ops == &lock_ops;
522}
523
505static int ins__key_cmp(const void *name, const void *insp) 524static int ins__key_cmp(const void *name, const void *insp)
506{ 525{
507 const struct ins *ins = insp; 526 const struct ins *ins = insp;
@@ -586,14 +605,24 @@ static struct arch *arch__find(const char *name)
586int symbol__alloc_hist(struct symbol *sym) 605int symbol__alloc_hist(struct symbol *sym)
587{ 606{
588 struct annotation *notes = symbol__annotation(sym); 607 struct annotation *notes = symbol__annotation(sym);
589 const size_t size = symbol__size(sym); 608 size_t size = symbol__size(sym);
590 size_t sizeof_sym_hist; 609 size_t sizeof_sym_hist;
591 610
611 /*
612 * Add buffer of one element for zero length symbol.
613 * When sample is taken from first instruction of
614 * zero length symbol, perf still resolves it and
615 * shows symbol name in perf report and allows to
616 * annotate it.
617 */
618 if (size == 0)
619 size = 1;
620
592 /* Check for overflow when calculating sizeof_sym_hist */ 621 /* Check for overflow when calculating sizeof_sym_hist */
593 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64)) 622 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
594 return -1; 623 return -1;
595 624
596 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); 625 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
597 626
598 /* Check for overflow in zalloc argument */ 627 /* Check for overflow in zalloc argument */
599 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src)) 628 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
@@ -677,7 +706,8 @@ static int __symbol__account_cycles(struct annotation *notes,
677} 706}
678 707
679static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, 708static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
680 struct annotation *notes, int evidx, u64 addr) 709 struct annotation *notes, int evidx, u64 addr,
710 struct perf_sample *sample)
681{ 711{
682 unsigned offset; 712 unsigned offset;
683 struct sym_hist *h; 713 struct sym_hist *h;
@@ -693,12 +723,15 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
693 723
694 offset = addr - sym->start; 724 offset = addr - sym->start;
695 h = annotation__histogram(notes, evidx); 725 h = annotation__histogram(notes, evidx);
696 h->sum++; 726 h->nr_samples++;
697 h->addr[offset]++; 727 h->addr[offset].nr_samples++;
728 h->period += sample->period;
729 h->addr[offset].period += sample->period;
698 730
699 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64 731 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
700 ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name, 732 ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
701 addr, addr - sym->start, evidx, h->addr[offset]); 733 sym->start, sym->name, addr, addr - sym->start, evidx,
734 h->addr[offset].nr_samples, h->addr[offset].period);
702 return 0; 735 return 0;
703} 736}
704 737
@@ -718,7 +751,8 @@ static struct annotation *symbol__get_annotation(struct symbol *sym, bool cycles
718} 751}
719 752
720static int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 753static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
721 int evidx, u64 addr) 754 int evidx, u64 addr,
755 struct perf_sample *sample)
722{ 756{
723 struct annotation *notes; 757 struct annotation *notes;
724 758
@@ -727,7 +761,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
727 notes = symbol__get_annotation(sym, false); 761 notes = symbol__get_annotation(sym, false);
728 if (notes == NULL) 762 if (notes == NULL)
729 return -ENOMEM; 763 return -ENOMEM;
730 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr); 764 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr, sample);
731} 765}
732 766
733static int symbol__account_cycles(u64 addr, u64 start, 767static int symbol__account_cycles(u64 addr, u64 start,
@@ -791,14 +825,16 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
791 return err; 825 return err;
792} 826}
793 827
794int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx) 828int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
829 int evidx)
795{ 830{
796 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr); 831 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr, sample);
797} 832}
798 833
799int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip) 834int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
835 int evidx, u64 ip)
800{ 836{
801 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 837 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample);
802} 838}
803 839
804static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 840static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
@@ -908,11 +944,12 @@ struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disa
908} 944}
909 945
910double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 946double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
911 s64 end, const char **path, u64 *nr_samples) 947 s64 end, const char **path, struct sym_hist_entry *sample)
912{ 948{
913 struct source_line *src_line = notes->src->lines; 949 struct source_line *src_line = notes->src->lines;
914 double percent = 0.0; 950 double percent = 0.0;
915 *nr_samples = 0; 951
952 sample->nr_samples = sample->period = 0;
916 953
917 if (src_line) { 954 if (src_line) {
918 size_t sizeof_src_line = sizeof(*src_line) + 955 size_t sizeof_src_line = sizeof(*src_line) +
@@ -926,19 +963,24 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
926 *path = src_line->path; 963 *path = src_line->path;
927 964
928 percent += src_line->samples[evidx].percent; 965 percent += src_line->samples[evidx].percent;
929 *nr_samples += src_line->samples[evidx].nr; 966 sample->nr_samples += src_line->samples[evidx].nr;
930 offset++; 967 offset++;
931 } 968 }
932 } else { 969 } else {
933 struct sym_hist *h = annotation__histogram(notes, evidx); 970 struct sym_hist *h = annotation__histogram(notes, evidx);
934 unsigned int hits = 0; 971 unsigned int hits = 0;
972 u64 period = 0;
935 973
936 while (offset < end) 974 while (offset < end) {
937 hits += h->addr[offset++]; 975 hits += h->addr[offset].nr_samples;
976 period += h->addr[offset].period;
977 ++offset;
978 }
938 979
939 if (h->sum) { 980 if (h->nr_samples) {
940 *nr_samples = hits; 981 sample->period = period;
941 percent = 100.0 * hits / h->sum; 982 sample->nr_samples = hits;
983 percent = 100.0 * hits / h->nr_samples;
942 } 984 }
943 } 985 }
944 986
@@ -1037,10 +1079,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1037 1079
1038 if (dl->offset != -1) { 1080 if (dl->offset != -1) {
1039 const char *path = NULL; 1081 const char *path = NULL;
1040 u64 nr_samples;
1041 double percent, max_percent = 0.0; 1082 double percent, max_percent = 0.0;
1042 double *ppercents = &percent; 1083 double *ppercents = &percent;
1043 u64 *psamples = &nr_samples; 1084 struct sym_hist_entry sample;
1085 struct sym_hist_entry *psamples = &sample;
1044 int i, nr_percent = 1; 1086 int i, nr_percent = 1;
1045 const char *color; 1087 const char *color;
1046 struct annotation *notes = symbol__annotation(sym); 1088 struct annotation *notes = symbol__annotation(sym);
@@ -1054,7 +1096,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1054 if (perf_evsel__is_group_event(evsel)) { 1096 if (perf_evsel__is_group_event(evsel)) {
1055 nr_percent = evsel->nr_members; 1097 nr_percent = evsel->nr_members;
1056 ppercents = calloc(nr_percent, sizeof(double)); 1098 ppercents = calloc(nr_percent, sizeof(double));
1057 psamples = calloc(nr_percent, sizeof(u64)); 1099 psamples = calloc(nr_percent, sizeof(struct sym_hist_entry));
1058 if (ppercents == NULL || psamples == NULL) { 1100 if (ppercents == NULL || psamples == NULL) {
1059 return -1; 1101 return -1;
1060 } 1102 }
@@ -1065,10 +1107,10 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1065 notes->src->lines ? i : evsel->idx + i, 1107 notes->src->lines ? i : evsel->idx + i,
1066 offset, 1108 offset,
1067 next ? next->offset : (s64) len, 1109 next ? next->offset : (s64) len,
1068 &path, &nr_samples); 1110 &path, &sample);
1069 1111
1070 ppercents[i] = percent; 1112 ppercents[i] = percent;
1071 psamples[i] = nr_samples; 1113 psamples[i] = sample;
1072 if (percent > max_percent) 1114 if (percent > max_percent)
1073 max_percent = percent; 1115 max_percent = percent;
1074 } 1116 }
@@ -1106,12 +1148,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1106 1148
1107 for (i = 0; i < nr_percent; i++) { 1149 for (i = 0; i < nr_percent; i++) {
1108 percent = ppercents[i]; 1150 percent = ppercents[i];
1109 nr_samples = psamples[i]; 1151 sample = psamples[i];
1110 color = get_percent_color(percent); 1152 color = get_percent_color(percent);
1111 1153
1112 if (symbol_conf.show_total_period) 1154 if (symbol_conf.show_total_period)
1155 color_fprintf(stdout, color, " %11" PRIu64,
1156 sample.period);
1157 else if (symbol_conf.show_nr_samples)
1113 color_fprintf(stdout, color, " %7" PRIu64, 1158 color_fprintf(stdout, color, " %7" PRIu64,
1114 nr_samples); 1159 sample.nr_samples);
1115 else 1160 else
1116 color_fprintf(stdout, color, " %7.2f", percent); 1161 color_fprintf(stdout, color, " %7.2f", percent);
1117 } 1162 }
@@ -1127,13 +1172,13 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1127 if (ppercents != &percent) 1172 if (ppercents != &percent)
1128 free(ppercents); 1173 free(ppercents);
1129 1174
1130 if (psamples != &nr_samples) 1175 if (psamples != &sample)
1131 free(psamples); 1176 free(psamples);
1132 1177
1133 } else if (max_lines && printed >= max_lines) 1178 } else if (max_lines && printed >= max_lines)
1134 return 1; 1179 return 1;
1135 else { 1180 else {
1136 int width = 8; 1181 int width = symbol_conf.show_total_period ? 12 : 8;
1137 1182
1138 if (queue) 1183 if (queue)
1139 return -1; 1184 return -1;
@@ -1327,7 +1372,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
1327 !dso__is_kcore(dso)) 1372 !dso__is_kcore(dso))
1328 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; 1373 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1329 1374
1330 build_id_filename = dso__build_id_filename(dso, NULL, 0); 1375 build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
1331 if (build_id_filename) { 1376 if (build_id_filename) {
1332 __symbol__join_symfs(filename, filename_size, build_id_filename); 1377 __symbol__join_symfs(filename, filename_size, build_id_filename);
1333 free(build_id_filename); 1378 free(build_id_filename);
@@ -1381,7 +1426,7 @@ static const char *annotate__norm_arch(const char *arch_name)
1381 1426
1382int symbol__disassemble(struct symbol *sym, struct map *map, 1427int symbol__disassemble(struct symbol *sym, struct map *map,
1383 const char *arch_name, size_t privsize, 1428 const char *arch_name, size_t privsize,
1384 struct arch **parch) 1429 struct arch **parch, char *cpuid)
1385{ 1430{
1386 struct dso *dso = map->dso; 1431 struct dso *dso = map->dso;
1387 char command[PATH_MAX * 2]; 1432 char command[PATH_MAX * 2];
@@ -1411,7 +1456,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map,
1411 *parch = arch; 1456 *parch = arch;
1412 1457
1413 if (arch->init) { 1458 if (arch->init) {
1414 err = arch->init(arch); 1459 err = arch->init(arch, cpuid);
1415 if (err) { 1460 if (err) {
1416 pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name); 1461 pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name);
1417 return err; 1462 return err;
@@ -1648,19 +1693,19 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1648 struct sym_hist *h = annotation__histogram(notes, evidx); 1693 struct sym_hist *h = annotation__histogram(notes, evidx);
1649 struct rb_root tmp_root = RB_ROOT; 1694 struct rb_root tmp_root = RB_ROOT;
1650 int nr_pcnt = 1; 1695 int nr_pcnt = 1;
1651 u64 h_sum = h->sum; 1696 u64 nr_samples = h->nr_samples;
1652 size_t sizeof_src_line = sizeof(struct source_line); 1697 size_t sizeof_src_line = sizeof(struct source_line);
1653 1698
1654 if (perf_evsel__is_group_event(evsel)) { 1699 if (perf_evsel__is_group_event(evsel)) {
1655 for (i = 1; i < evsel->nr_members; i++) { 1700 for (i = 1; i < evsel->nr_members; i++) {
1656 h = annotation__histogram(notes, evidx + i); 1701 h = annotation__histogram(notes, evidx + i);
1657 h_sum += h->sum; 1702 nr_samples += h->nr_samples;
1658 } 1703 }
1659 nr_pcnt = evsel->nr_members; 1704 nr_pcnt = evsel->nr_members;
1660 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples); 1705 sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
1661 } 1706 }
1662 1707
1663 if (!h_sum) 1708 if (!nr_samples)
1664 return 0; 1709 return 0;
1665 1710
1666 src_line = notes->src->lines = calloc(len, sizeof_src_line); 1711 src_line = notes->src->lines = calloc(len, sizeof_src_line);
@@ -1670,7 +1715,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1670 start = map__rip_2objdump(map, sym->start); 1715 start = map__rip_2objdump(map, sym->start);
1671 1716
1672 for (i = 0; i < len; i++) { 1717 for (i = 0; i < len; i++) {
1673 u64 offset, nr_samples; 1718 u64 offset;
1674 double percent_max = 0.0; 1719 double percent_max = 0.0;
1675 1720
1676 src_line->nr_pcnt = nr_pcnt; 1721 src_line->nr_pcnt = nr_pcnt;
@@ -1679,9 +1724,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1679 double percent = 0.0; 1724 double percent = 0.0;
1680 1725
1681 h = annotation__histogram(notes, evidx + k); 1726 h = annotation__histogram(notes, evidx + k);
1682 nr_samples = h->addr[i]; 1727 nr_samples = h->addr[i].nr_samples;
1683 if (h->sum) 1728 if (h->nr_samples)
1684 percent = 100.0 * nr_samples / h->sum; 1729 percent = 100.0 * nr_samples / h->nr_samples;
1685 1730
1686 if (percent > percent_max) 1731 if (percent > percent_max)
1687 percent_max = percent; 1732 percent_max = percent;
@@ -1750,10 +1795,10 @@ static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
1750 u64 len = symbol__size(sym), offset; 1795 u64 len = symbol__size(sym), offset;
1751 1796
1752 for (offset = 0; offset < len; ++offset) 1797 for (offset = 0; offset < len; ++offset)
1753 if (h->addr[offset] != 0) 1798 if (h->addr[offset].nr_samples != 0)
1754 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, 1799 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
1755 sym->start + offset, h->addr[offset]); 1800 sym->start + offset, h->addr[offset].nr_samples);
1756 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); 1801 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
1757} 1802}
1758 1803
1759int symbol__annotate_printf(struct symbol *sym, struct map *map, 1804int symbol__annotate_printf(struct symbol *sym, struct map *map,
@@ -1771,7 +1816,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1771 int printed = 2, queue_len = 0; 1816 int printed = 2, queue_len = 0;
1772 int more = 0; 1817 int more = 0;
1773 u64 len; 1818 u64 len;
1774 int width = 8; 1819 int width = symbol_conf.show_total_period ? 12 : 8;
1775 int graph_dotted_len; 1820 int graph_dotted_len;
1776 1821
1777 filename = strdup(dso->long_name); 1822 filename = strdup(dso->long_name);
@@ -1789,7 +1834,9 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1789 width *= evsel->nr_members; 1834 width *= evsel->nr_members;
1790 1835
1791 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 1836 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); 1837 width, width, symbol_conf.show_total_period ? "Period" :
1838 symbol_conf.show_nr_samples ? "Samples" : "Percent",
1839 d_filename, evsel_name, h->nr_samples);
1793 1840
1794 printf("%-*.*s----\n", 1841 printf("%-*.*s----\n",
1795 graph_dotted_len, graph_dotted_len, graph_dotted_line); 1842 graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -1853,10 +1900,10 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
1853 struct sym_hist *h = annotation__histogram(notes, evidx); 1900 struct sym_hist *h = annotation__histogram(notes, evidx);
1854 int len = symbol__size(sym), offset; 1901 int len = symbol__size(sym), offset;
1855 1902
1856 h->sum = 0; 1903 h->nr_samples = 0;
1857 for (offset = 0; offset < len; ++offset) { 1904 for (offset = 0; offset < len; ++offset) {
1858 h->addr[offset] = h->addr[offset] * 7 / 8; 1905 h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
1859 h->sum += h->addr[offset]; 1906 h->nr_samples += h->addr[offset].nr_samples;
1860 } 1907 }
1861} 1908}
1862 1909
@@ -1907,7 +1954,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1907 u64 len; 1954 u64 len;
1908 1955
1909 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 1956 if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
1910 0, NULL) < 0) 1957 0, NULL, NULL) < 0)
1911 return -1; 1958 return -1;
1912 1959
1913 len = symbol__size(sym); 1960 len = symbol__size(sym);