blob: 58be0cecb081932eec91f5196a4f746d1231330a [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Namhyung Kimaca7a942012-04-04 00:14:26 -07002#include "../../util/util.h"
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -03003#include "../browser.h"
4#include "../helpline.h"
Arnaldo Carvalho de Meloae557952011-10-26 08:00:55 -02005#include "../ui.h"
6#include "../util.h"
Namhyung Kimaca7a942012-04-04 00:14:26 -07007#include "../../util/annotate.h"
8#include "../../util/hist.h"
9#include "../../util/sort.h"
10#include "../../util/symbol.h"
Namhyung Kimdb8fd072013-03-05 14:53:21 +090011#include "../../util/evsel.h"
Taeung Song41840d22016-06-23 17:55:17 +090012#include "../../util/config.h"
Jin Yao69fb09f2017-07-07 13:06:34 +080013#include "../../util/evlist.h"
Arnaldo Carvalho de Melofd20e812017-04-17 15:23:08 -030014#include <inttypes.h>
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -030015#include <pthread.h>
Arnaldo Carvalho de Melo877a7a12017-04-17 11:39:06 -030016#include <linux/kernel.h>
Arnaldo Carvalho de Melo8e99b6d2017-07-20 15:27:39 -030017#include <linux/string.h>
Arnaldo Carvalho de Melob0742e92017-04-18 11:08:10 -030018#include <sys/ttydefaults.h>
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -030019
Martin Liška0c4a5bc2015-06-19 16:10:43 -030020struct disasm_line_samples {
Arnaldo Carvalho de Melobb79a232017-07-27 11:24:59 -030021 double percent;
22 struct sym_hist_entry he;
Martin Liška0c4a5bc2015-06-19 16:10:43 -030023};
24
Jiri Olsa0d957972017-11-06 11:55:36 +010025struct browser_line {
26 u32 idx;
27 int idx_asm;
Arnaldo Carvalho de Melob793a402012-04-19 12:19:22 -030028};
29
Arnaldo Carvalho de Melo98bc80b2018-03-15 10:03:34 -030030static struct annotation_options annotate_browser__opts = {
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -030031 .use_offset = true,
32 .jump_arrows = true,
33};
34
Jin Yaodcaa3942017-06-19 10:55:56 +080035struct arch;
36
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -030037struct annotate_browser {
Jiri Olsa7bcbcd52017-11-06 11:56:17 +010038 struct ui_browser b;
39 struct rb_root entries;
40 struct rb_node *curr_hot;
41 struct annotation_line *selection;
Jiri Olsa7bcbcd52017-11-06 11:56:17 +010042 struct arch *arch;
Jiri Olsa7bcbcd52017-11-06 11:56:17 +010043 u64 start;
44 int nr_asm_entries;
45 int nr_entries;
Jiri Olsa7bcbcd52017-11-06 11:56:17 +010046 bool searching_backwards;
Jiri Olsa7bcbcd52017-11-06 11:56:17 +010047 u8 addr_width;
48 u8 jumps_width;
49 u8 target_width;
50 u8 min_addr_width;
51 u8 max_addr_width;
52 char search_bf[128];
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -030053};
54
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -030055static inline struct annotation *browser__annotation(struct ui_browser *browser)
56{
57 struct map_symbol *ms = browser->priv;
58 return symbol__annotation(ms->sym);
59}
60
Jiri Olsaa5ef2702017-10-11 17:01:54 +020061static inline struct browser_line *browser_line(struct annotation_line *al)
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -030062{
Jiri Olsaa5ef2702017-10-11 17:01:54 +020063 void *ptr = al;
64
65 ptr = container_of(al, struct disasm_line, al);
66 return ptr - sizeof(struct browser_line);
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -030067}
68
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -030069static bool disasm_line__filter(struct ui_browser *browser, void *entry)
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -030070{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -030071 struct annotation *notes = browser__annotation(browser);
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -030072
73 if (notes->options->hide_src_code) {
Jiri Olsad5490b92017-10-11 17:01:26 +020074 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
75
76 return al->offset == -1;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -030077 }
78
79 return false;
80}
81
Arnaldo Carvalho de Melo27feb762018-03-15 15:14:45 -030082static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -030083{
Arnaldo Carvalho de Melo27feb762018-03-15 15:14:45 -030084 struct annotation *notes = browser__annotation(browser);
Arnaldo Carvalho de Melobc1c0f32018-03-15 15:10:28 -030085
Arnaldo Carvalho de Melo27feb762018-03-15 15:14:45 -030086 if (current && (!browser->use_navkeypressed || browser->navkeypressed))
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -030087 return HE_COLORSET_SELECTED;
Arnaldo Carvalho de Melobc1c0f32018-03-15 15:10:28 -030088 if (nr == notes->max_jump_sources)
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -030089 return HE_COLORSET_TOP;
90 if (nr > 1)
91 return HE_COLORSET_MEDIUM;
92 return HE_COLORSET_NORMAL;
93}
94
Arnaldo Carvalho de Melo27feb762018-03-15 15:14:45 -030095static int ui_browser__set_jumps_percent_color(struct ui_browser *browser, int nr, bool current)
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -030096{
Arnaldo Carvalho de Melo27feb762018-03-15 15:14:45 -030097 int color = ui_browser__jumps_percent_color(browser, nr, current);
98 return ui_browser__set_color(browser, color);
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -030099}
100
Jiri Olsaa5433b32017-10-11 17:01:57 +0200101static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser,
102 char *bf, size_t size)
103{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300104 struct annotation *notes = browser__annotation(browser);
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300105
Jiri Olsaa5433b32017-10-11 17:01:57 +0200106 if (dl->ins.ops && dl->ins.ops->scnprintf) {
107 if (ins__is_jump(&dl->ins)) {
108 bool fwd = dl->ops.target.offset > dl->al.offset;
109
110 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
111 SLSMG_UARROW_CHAR);
112 SLsmg_write_char(' ');
113 } else if (ins__is_call(&dl->ins)) {
114 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
115 SLsmg_write_char(' ');
116 } else if (ins__is_ret(&dl->ins)) {
117 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
118 SLsmg_write_char(' ');
119 } else {
120 ui_browser__write_nstring(browser, " ", 2);
121 }
122 } else {
123 ui_browser__write_nstring(browser, " ", 2);
124 }
125
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300126 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
Jiri Olsaa5433b32017-10-11 17:01:57 +0200127}
128
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300129static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300130{
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300131 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300132 struct annotation *notes = browser__annotation(browser);
Jiri Olsaa5433b32017-10-11 17:01:57 +0200133 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300134 bool current_entry = ui_browser__is_current_entry(browser, row);
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300135 bool change_color = (!notes->options->hide_src_code &&
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300136 (!current_entry || (browser->use_navkeypressed &&
137 !browser->navkeypressed)));
138 int width = browser->width, printed;
Arnaldo Carvalho de Melo6af612d2018-03-15 12:41:39 -0300139 int i, pcnt_width = annotation__pcnt_width(notes),
Arnaldo Carvalho de Melo0e83a7e2018-03-15 10:35:04 -0300140 cycles_width = annotation__cycles_width(notes);
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900141 double percent_max = 0.0;
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300142 char bf[256];
Jin Yaoec27ae12017-05-04 22:58:15 +0800143 bool show_title = false;
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300144
Arnaldo Carvalho de Melo0553e832018-03-15 11:52:32 -0300145 for (i = 0; i < notes->nr_events; i++) {
Jiri Olsaa5433b32017-10-11 17:01:57 +0200146 if (al->samples[i].percent > percent_max)
147 percent_max = al->samples[i].percent;
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900148 }
149
Jiri Olsaa5433b32017-10-11 17:01:57 +0200150 if ((row == 0) && (al->offset == -1 || percent_max == 0.0)) {
Arnaldo Carvalho de Melo0e83a7e2018-03-15 10:35:04 -0300151 if (notes->have_cycles) {
Jiri Olsaa5433b32017-10-11 17:01:57 +0200152 if (al->ipc == 0.0 && al->cycles == 0)
Jin Yaoec27ae12017-05-04 22:58:15 +0800153 show_title = true;
154 } else
155 show_title = true;
156 }
157
Jiri Olsaa5433b32017-10-11 17:01:57 +0200158 if (al->offset != -1 && percent_max != 0.0) {
Arnaldo Carvalho de Melo0553e832018-03-15 11:52:32 -0300159 for (i = 0; i < notes->nr_events; i++) {
Jin Yaoc564f0d2017-05-04 22:58:14 +0800160 ui_browser__set_percent_color(browser,
Jiri Olsaa5433b32017-10-11 17:01:57 +0200161 al->samples[i].percent,
Jin Yaoc564f0d2017-05-04 22:58:14 +0800162 current_entry);
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300163 if (notes->options->show_total_period) {
Arnaldo Carvalho de Melo3861c4a2017-07-28 13:19:32 -0300164 ui_browser__printf(browser, "%11" PRIu64 " ",
Jiri Olsaa5433b32017-10-11 17:01:57 +0200165 al->samples[i].he.period);
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300166 } else if (notes->options->show_nr_samples) {
Taeung Song9cef4b02017-08-18 17:47:03 +0900167 ui_browser__printf(browser, "%6" PRIu64 " ",
Jiri Olsaa5433b32017-10-11 17:01:57 +0200168 al->samples[i].he.nr_samples);
Jin Yaoc564f0d2017-05-04 22:58:14 +0800169 } else {
170 ui_browser__printf(browser, "%6.2f ",
Jiri Olsaa5433b32017-10-11 17:01:57 +0200171 al->samples[i].percent);
Andi Kleenf8f4aae2015-07-18 08:24:51 -0700172 }
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900173 }
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300174 } else {
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300175 ui_browser__set_percent_color(browser, 0, current_entry);
Jin Yaoec27ae12017-05-04 22:58:15 +0800176
177 if (!show_title)
Arnaldo Carvalho de Melobc1e5d62017-07-27 12:05:58 -0300178 ui_browser__write_nstring(browser, " ", pcnt_width);
Arnaldo Carvalho de Melo3861c4a2017-07-28 13:19:32 -0300179 else {
180 ui_browser__printf(browser, "%*s", pcnt_width,
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300181 notes->options->show_total_period ? "Period" :
182 notes->options->show_nr_samples ? "Samples" : "Percent");
Arnaldo Carvalho de Melo3861c4a2017-07-28 13:19:32 -0300183 }
Andi Kleenf8f4aae2015-07-18 08:24:51 -0700184 }
Arnaldo Carvalho de Melo0e83a7e2018-03-15 10:35:04 -0300185 if (notes->have_cycles) {
Jiri Olsaa5433b32017-10-11 17:01:57 +0200186 if (al->ipc)
Arnaldo Carvalho de Meloc426e582018-03-15 10:26:17 -0300187 ui_browser__printf(browser, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
Jin Yaoec27ae12017-05-04 22:58:15 +0800188 else if (!show_title)
Arnaldo Carvalho de Meloc426e582018-03-15 10:26:17 -0300189 ui_browser__write_nstring(browser, " ", ANNOTATION__IPC_WIDTH);
Jin Yaoec27ae12017-05-04 22:58:15 +0800190 else
Arnaldo Carvalho de Meloc426e582018-03-15 10:26:17 -0300191 ui_browser__printf(browser, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
Jin Yaoec27ae12017-05-04 22:58:15 +0800192
Jiri Olsaa5433b32017-10-11 17:01:57 +0200193 if (al->cycles)
Arnaldo Carvalho de Melo517dfdb2015-08-11 12:50:55 -0300194 ui_browser__printf(browser, "%*" PRIu64 " ",
Arnaldo Carvalho de Meloc426e582018-03-15 10:26:17 -0300195 ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
Jin Yaoec27ae12017-05-04 22:58:15 +0800196 else if (!show_title)
Arnaldo Carvalho de Meloc426e582018-03-15 10:26:17 -0300197 ui_browser__write_nstring(browser, " ", ANNOTATION__CYCLES_WIDTH);
Jin Yaoec27ae12017-05-04 22:58:15 +0800198 else
Arnaldo Carvalho de Meloc426e582018-03-15 10:26:17 -0300199 ui_browser__printf(browser, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle");
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300200 }
201
Arnaldo Carvalho de Melocf2dacc2012-04-19 15:19:17 -0300202 SLsmg_write_char(' ');
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -0200203
204 /* The scroll bar isn't being used */
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300205 if (!browser->navkeypressed)
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -0200206 width += 1;
207
Jiri Olsaa5433b32017-10-11 17:01:57 +0200208 if (!*al->line)
Arnaldo Carvalho de Melobc1e5d62017-07-27 12:05:58 -0300209 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
Jiri Olsaa5433b32017-10-11 17:01:57 +0200210 else if (al->offset == -1) {
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300211 if (al->line_nr && notes->options->show_linenr)
Andi Kleene5924882014-11-12 18:05:26 -0800212 printed = scnprintf(bf, sizeof(bf), "%-*d ",
Jiri Olsaa5433b32017-10-11 17:01:57 +0200213 ab->addr_width + 1, al->line_nr);
Andi Kleene5924882014-11-12 18:05:26 -0800214 else
215 printed = scnprintf(bf, sizeof(bf), "%*s ",
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300216 ab->addr_width, " ");
Arnaldo Carvalho de Melo26270a02015-08-11 12:24:27 -0300217 ui_browser__write_nstring(browser, bf, printed);
Jiri Olsaa5433b32017-10-11 17:01:57 +0200218 ui_browser__write_nstring(browser, al->line, width - printed - pcnt_width - cycles_width + 1);
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300219 } else {
Jiri Olsaa5433b32017-10-11 17:01:57 +0200220 u64 addr = al->offset;
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300221 int color = -1;
Arnaldo Carvalho de Melo058b4cc2012-04-02 12:59:01 -0300222
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300223 if (!notes->options->use_offset)
Arnaldo Carvalho de Meloe235f3f2012-04-02 13:21:55 -0300224 addr += ab->start;
225
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300226 if (!notes->options->use_offset) {
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300227 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
Arnaldo Carvalho de Melo61e04b32012-04-19 13:15:24 -0300228 } else {
Arnaldo Carvalho de Melo0db45bc2018-03-15 15:31:56 -0300229 if (al->jump_sources) {
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300230 if (notes->options->show_nr_jumps) {
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -0300231 int prev;
232 printed = scnprintf(bf, sizeof(bf), "%*d ",
233 ab->jumps_width,
Arnaldo Carvalho de Melo0db45bc2018-03-15 15:31:56 -0300234 al->jump_sources);
235 prev = ui_browser__set_jumps_percent_color(browser, al->jump_sources,
Arnaldo Carvalho de Melo27feb762018-03-15 15:14:45 -0300236 current_entry);
Arnaldo Carvalho de Melo26270a02015-08-11 12:24:27 -0300237 ui_browser__write_nstring(browser, bf, printed);
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300238 ui_browser__set_color(browser, prev);
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -0300239 }
240
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300241 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -0300242 ab->target_width, addr);
Arnaldo Carvalho de Melo61e04b32012-04-19 13:15:24 -0300243 } else {
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300244 printed = scnprintf(bf, sizeof(bf), "%*s ",
245 ab->addr_width, " ");
Arnaldo Carvalho de Melo61e04b32012-04-19 13:15:24 -0300246 }
247 }
Arnaldo Carvalho de Melob793a402012-04-19 12:19:22 -0300248
Arnaldo Carvalho de Melo058b4cc2012-04-02 12:59:01 -0300249 if (change_color)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300250 color = ui_browser__set_color(browser, HE_COLORSET_ADDR);
Arnaldo Carvalho de Melo26270a02015-08-11 12:24:27 -0300251 ui_browser__write_nstring(browser, bf, printed);
Arnaldo Carvalho de Melo058b4cc2012-04-02 12:59:01 -0300252 if (change_color)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300253 ui_browser__set_color(browser, color);
Arnaldo Carvalho de Melo51a0d452012-04-20 15:40:20 -0300254
Jiri Olsaa5433b32017-10-11 17:01:57 +0200255 disasm_line__write(disasm_line(al), browser, bf, sizeof(bf));
Arnaldo Carvalho de Melo4ea08b52012-04-20 15:51:40 -0300256
Arnaldo Carvalho de Melobc1e5d62017-07-27 12:05:58 -0300257 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed);
Arnaldo Carvalho de Melo058b4cc2012-04-02 12:59:01 -0300258 }
Arnaldo Carvalho de Melob99976e2011-02-09 13:59:14 -0200259
Namhyung Kim58e817d2012-02-23 17:46:20 +0900260 if (current_entry)
Jiri Olsaa5433b32017-10-11 17:01:57 +0200261 ab->selection = al;
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300262}
263
Jin Yao7e63a132017-07-07 13:06:35 +0800264static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
265{
Jiri Olsaa17c4ca2017-10-11 17:01:25 +0200266 struct disasm_line *pos = list_prev_entry(cursor, al.node);
Jin Yao7e63a132017-07-07 13:06:35 +0800267 const char *name;
268
269 if (!pos)
270 return false;
271
272 if (ins__is_lock(&pos->ins))
273 name = pos->ops.locked.ins.name;
274 else
275 name = pos->ins.name;
276
277 if (!name || !cursor->ins.name)
278 return false;
279
280 return ins__is_fused(ab->arch, name, cursor->ins.name);
281}
282
Arnaldo Carvalho de Melo9d1ef562012-04-27 16:35:29 -0300283static void annotate_browser__draw_current_jump(struct ui_browser *browser)
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300284{
285 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
Jiri Olsa7bcbcd52017-11-06 11:56:17 +0100286 struct disasm_line *cursor = disasm_line(ab->selection);
Jiri Olsaa5ef2702017-10-11 17:01:54 +0200287 struct annotation_line *target;
Jiri Olsa0d957972017-11-06 11:55:36 +0100288 struct browser_line *btarget, *bcursor;
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300289 unsigned int from, to;
Namhyung Kim32ae1ef2012-11-10 02:27:15 +0900290 struct map_symbol *ms = ab->b.priv;
291 struct symbol *sym = ms->sym;
Arnaldo Carvalho de Melo0e83a7e2018-03-15 10:35:04 -0300292 struct annotation *notes = symbol__annotation(sym);
Arnaldo Carvalho de Melo6af612d2018-03-15 12:41:39 -0300293 u8 pcnt_width = annotation__pcnt_width(notes);
Arnaldo Carvalho de Melo00ea0eb2018-03-15 10:28:06 -0300294 int width;
Namhyung Kim32ae1ef2012-11-10 02:27:15 +0900295
296 /* PLT symbols contain external offsets */
297 if (strstr(sym->name, "@plt"))
298 return;
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300299
Frederik Deweerdt865c66c2013-01-14 14:47:17 -0500300 if (!disasm_line__is_valid_jump(cursor, sym))
Arnaldo Carvalho de Melo9d1ef562012-04-27 16:35:29 -0300301 return;
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300302
Arnaldo Carvalho de Melo9c044092018-03-01 11:33:59 -0300303 /*
304 * This first was seen with a gcc function, _cpp_lex_token, that
305 * has the usual jumps:
306 *
307 * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92>
308 *
309 * I.e. jumps to a label inside that function (_cpp_lex_token), and
310 * those works, but also this kind:
311 *
312 * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72>
313 *
314 * I.e. jumps to another function, outside _cpp_lex_token, which
315 * are not being correctly handled generating as a side effect references
316 * to ab->offset[] entries that are set to NULL, so to make this code
317 * more robust, check that here.
318 *
319 * A proper fix for will be put in place, looking at the function
320 * name right after the '<' token and probably treating this like a
321 * 'call' instruction.
322 */
Arnaldo Carvalho de Melo9d6bb412018-03-15 10:47:54 -0300323 target = notes->offsets[cursor->ops.target.offset];
Arnaldo Carvalho de Melo9c044092018-03-01 11:33:59 -0300324 if (target == NULL) {
Arnaldo Carvalho de Melo9d6bb412018-03-15 10:47:54 -0300325 ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
Arnaldo Carvalho de Melo9c044092018-03-01 11:33:59 -0300326 cursor->ops.target.offset);
327 return;
328 }
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300329
Jiri Olsaa5ef2702017-10-11 17:01:54 +0200330 bcursor = browser_line(&cursor->al);
Jiri Olsadaf25d42017-11-06 11:55:52 +0100331 btarget = browser_line(target);
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300332
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300333 if (notes->options->hide_src_code) {
Arnaldo Carvalho de Melo9d1ef562012-04-27 16:35:29 -0300334 from = bcursor->idx_asm;
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300335 to = btarget->idx_asm;
336 } else {
Arnaldo Carvalho de Melo9d1ef562012-04-27 16:35:29 -0300337 from = (u64)bcursor->idx;
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300338 to = (u64)btarget->idx;
339 }
340
Arnaldo Carvalho de Melo0e83a7e2018-03-15 10:35:04 -0300341 width = annotation__cycles_width(notes);
Jin Yaob40982e2018-01-29 18:57:53 +0800342
Taeung Song78ce08d2016-01-08 17:16:11 +0900343 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
Jin Yaob40982e2018-01-29 18:57:53 +0800344 __ui_browser__line_arrow(browser,
345 pcnt_width + 2 + ab->addr_width + width,
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900346 from, to);
Jin Yao7e63a132017-07-07 13:06:35 +0800347
348 if (is_fused(ab, cursor)) {
349 ui_browser__mark_fused(browser,
Jin Yaob40982e2018-01-29 18:57:53 +0800350 pcnt_width + 3 + ab->addr_width + width,
Jin Yao7e63a132017-07-07 13:06:35 +0800351 from - 1,
352 to > from ? true : false);
353 }
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300354}
355
356static unsigned int annotate_browser__refresh(struct ui_browser *browser)
357{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300358 struct annotation *notes = browser__annotation(browser);
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300359 int ret = ui_browser__list_head_refresh(browser);
Arnaldo Carvalho de Melo6af612d2018-03-15 12:41:39 -0300360 int pcnt_width = annotation__pcnt_width(notes);
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300361
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300362 if (notes->options->jump_arrows)
Arnaldo Carvalho de Melo9d1ef562012-04-27 16:35:29 -0300363 annotate_browser__draw_current_jump(browser);
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300364
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -0300365 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900366 __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300367 return ret;
368}
369
Jiri Olsab15636c2017-10-11 17:01:49 +0200370static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900371{
372 int i;
373
Jiri Olsab15636c2017-10-11 17:01:49 +0200374 for (i = 0; i < a->samples_nr; i++) {
Martin Liška0c4a5bc2015-06-19 16:10:43 -0300375 if (a->samples[i].percent == b->samples[i].percent)
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900376 continue;
Martin Liška0c4a5bc2015-06-19 16:10:43 -0300377 return a->samples[i].percent < b->samples[i].percent;
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900378 }
379 return 0;
380}
381
Jiri Olsab15636c2017-10-11 17:01:49 +0200382static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al)
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -0300383{
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300384 struct rb_node **p = &root->rb_node;
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -0300385 struct rb_node *parent = NULL;
Jiri Olsa3ab6db82017-10-11 17:01:48 +0200386 struct annotation_line *l;
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -0300387
388 while (*p != NULL) {
389 parent = *p;
Jiri Olsa3ab6db82017-10-11 17:01:48 +0200390 l = rb_entry(parent, struct annotation_line, rb_node);
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900391
Jiri Olsab15636c2017-10-11 17:01:49 +0200392 if (disasm__cmp(al, l))
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -0300393 p = &(*p)->rb_left;
394 else
395 p = &(*p)->rb_right;
396 }
Jiri Olsa3ab6db82017-10-11 17:01:48 +0200397 rb_link_node(&al->rb_node, parent, p);
398 rb_insert_color(&al->rb_node, root);
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -0300399}
400
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300401static void annotate_browser__set_top(struct annotate_browser *browser,
Jiri Olsaec03a772017-10-11 17:01:56 +0200402 struct annotation_line *pos, u32 idx)
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300403{
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300404 unsigned back;
405
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300406 ui_browser__refresh_dimensions(&browser->b);
407 back = browser->b.height / 2;
408 browser->b.top_idx = browser->b.index = idx;
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300409
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300410 while (browser->b.top_idx != 0 && back != 0) {
Jiri Olsaec03a772017-10-11 17:01:56 +0200411 pos = list_entry(pos->node.prev, struct annotation_line, node);
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300412
Jiri Olsaec03a772017-10-11 17:01:56 +0200413 if (disasm_line__filter(&browser->b, &pos->node))
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300414 continue;
415
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300416 --browser->b.top_idx;
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300417 --back;
418 }
419
Jiri Olsaec03a772017-10-11 17:01:56 +0200420 browser->b.top = pos;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300421 browser->b.navkeypressed = true;
Arnaldo Carvalho de Melob0ffb2c2012-04-03 15:32:45 -0300422}
423
424static void annotate_browser__set_rb_top(struct annotate_browser *browser,
425 struct rb_node *nd)
426{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300427 struct annotation *notes = browser__annotation(&browser->b);
Jiri Olsa0d957972017-11-06 11:55:36 +0100428 struct browser_line *bpos;
Jiri Olsaec03a772017-10-11 17:01:56 +0200429 struct annotation_line *pos;
Arnaldo Carvalho de Meloa44b45f2012-05-29 20:49:14 -0300430 u32 idx;
Arnaldo Carvalho de Melob0ffb2c2012-04-03 15:32:45 -0300431
Jiri Olsaec03a772017-10-11 17:01:56 +0200432 pos = rb_entry(nd, struct annotation_line, rb_node);
433 bpos = browser_line(pos);
Jiri Olsa5b12adc2017-10-11 17:01:36 +0200434
Arnaldo Carvalho de Meloa44b45f2012-05-29 20:49:14 -0300435 idx = bpos->idx;
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300436 if (notes->options->hide_src_code)
Arnaldo Carvalho de Meloa44b45f2012-05-29 20:49:14 -0300437 idx = bpos->idx_asm;
438 annotate_browser__set_top(browser, pos, idx);
Arnaldo Carvalho de Melob0ffb2c2012-04-03 15:32:45 -0300439 browser->curr_hot = nd;
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300440}
441
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300442static void annotate_browser__calc_percent(struct annotate_browser *browser,
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900443 struct perf_evsel *evsel)
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300444{
Arnaldo Carvalho de Melo34958542011-10-05 19:35:54 -0300445 struct map_symbol *ms = browser->b.priv;
446 struct symbol *sym = ms->sym;
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300447 struct annotation *notes = symbol__annotation(sym);
Jiri Olsac4c72432017-10-11 17:01:34 +0200448 struct disasm_line *pos;
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300449
450 browser->entries = RB_ROOT;
451
452 pthread_mutex_lock(&notes->lock);
453
Jiri Olsae425da62017-10-11 17:01:43 +0200454 symbol__calc_percent(sym, evsel);
455
Jiri Olsaa17c4ca2017-10-11 17:01:25 +0200456 list_for_each_entry(pos, &notes->src->source, al.node) {
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900457 double max_percent = 0.0;
458 int i;
Namhyung Kime64aa752013-03-05 14:53:30 +0900459
Jiri Olsad5490b92017-10-11 17:01:26 +0200460 if (pos->al.offset == -1) {
Jiri Olsa5b12adc2017-10-11 17:01:36 +0200461 RB_CLEAR_NODE(&pos->al.rb_node);
Namhyung Kime64aa752013-03-05 14:53:30 +0900462 continue;
463 }
464
Jiri Olsab15636c2017-10-11 17:01:49 +0200465 for (i = 0; i < pos->al.samples_nr; i++) {
Jiri Olsae425da62017-10-11 17:01:43 +0200466 struct annotation_data *sample = &pos->al.samples[i];
Martin Liška0c4a5bc2015-06-19 16:10:43 -0300467
Jiri Olsa3ab6db82017-10-11 17:01:48 +0200468 if (max_percent < sample->percent)
469 max_percent = sample->percent;
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900470 }
471
Jiri Olsa37236d52017-10-11 17:01:27 +0200472 if (max_percent < 0.01 && pos->al.ipc == 0) {
Jiri Olsa5b12adc2017-10-11 17:01:36 +0200473 RB_CLEAR_NODE(&pos->al.rb_node);
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300474 continue;
475 }
Jiri Olsab15636c2017-10-11 17:01:49 +0200476 disasm_rb_tree__insert(&browser->entries, &pos->al);
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300477 }
478 pthread_mutex_unlock(&notes->lock);
479
480 browser->curr_hot = rb_last(&browser->entries);
481}
482
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300483static bool annotate_browser__toggle_source(struct annotate_browser *browser)
484{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300485 struct annotation *notes = browser__annotation(&browser->b);
Jiri Olsaec03a772017-10-11 17:01:56 +0200486 struct annotation_line *al;
Jiri Olsaa5ef2702017-10-11 17:01:54 +0200487 struct browser_line *bl;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300488 off_t offset = browser->b.index - browser->b.top_idx;
489
490 browser->b.seek(&browser->b, offset, SEEK_CUR);
Jiri Olsaec03a772017-10-11 17:01:56 +0200491 al = list_entry(browser->b.top, struct annotation_line, node);
492 bl = browser_line(al);
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300493
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300494 if (notes->options->hide_src_code) {
Jiri Olsaa5ef2702017-10-11 17:01:54 +0200495 if (bl->idx_asm < offset)
496 offset = bl->idx;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300497
498 browser->b.nr_entries = browser->nr_entries;
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300499 notes->options->hide_src_code = false;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300500 browser->b.seek(&browser->b, -offset, SEEK_CUR);
Jiri Olsaa5ef2702017-10-11 17:01:54 +0200501 browser->b.top_idx = bl->idx - offset;
502 browser->b.index = bl->idx;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300503 } else {
Jiri Olsaa5ef2702017-10-11 17:01:54 +0200504 if (bl->idx_asm < 0) {
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300505 ui_helpline__puts("Only available for assembly lines.");
506 browser->b.seek(&browser->b, -offset, SEEK_CUR);
507 return false;
508 }
509
Jiri Olsaa5ef2702017-10-11 17:01:54 +0200510 if (bl->idx_asm < offset)
511 offset = bl->idx_asm;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300512
513 browser->b.nr_entries = browser->nr_asm_entries;
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300514 notes->options->hide_src_code = true;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300515 browser->b.seek(&browser->b, -offset, SEEK_CUR);
Jiri Olsaa5ef2702017-10-11 17:01:54 +0200516 browser->b.top_idx = bl->idx_asm - offset;
517 browser->b.index = bl->idx_asm;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300518 }
519
520 return true;
521}
522
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -0300523static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
524{
525 ui_browser__reset_index(&browser->b);
526 browser->b.nr_entries = browser->nr_asm_entries;
527}
528
Adrian Hunter34f77ab2013-08-07 14:38:55 +0300529#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
530
531static int sym_title(struct symbol *sym, struct map *map, char *title,
532 size_t sz)
533{
534 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name);
535}
536
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900537static bool annotate_browser__callq(struct annotate_browser *browser,
538 struct perf_evsel *evsel,
Namhyung Kim9783adf2012-11-02 14:50:05 +0900539 struct hist_browser_timer *hbt)
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300540{
541 struct map_symbol *ms = browser->b.priv;
Jiri Olsa7bcbcd52017-11-06 11:56:17 +0100542 struct disasm_line *dl = disasm_line(browser->selection);
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300543 struct annotation *notes;
Adrian Hunter34f77ab2013-08-07 14:38:55 +0300544 char title[SYM_TITLE_MAX_SIZE];
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300545
Arnaldo Carvalho de Melo75b49202016-11-24 11:16:06 -0300546 if (!ins__is_call(&dl->ins))
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300547 return false;
548
Arnaldo Carvalho de Melo696703a2018-03-02 11:59:36 -0300549 if (!dl->ops.target.sym) {
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300550 ui_helpline__puts("The called function was not found.");
551 return true;
552 }
553
Arnaldo Carvalho de Melo696703a2018-03-02 11:59:36 -0300554 notes = symbol__annotation(dl->ops.target.sym);
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300555 pthread_mutex_lock(&notes->lock);
556
Arnaldo Carvalho de Melo696703a2018-03-02 11:59:36 -0300557 if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) {
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300558 pthread_mutex_unlock(&notes->lock);
559 ui__warning("Not enough memory for annotating '%s' symbol!\n",
Arnaldo Carvalho de Melo696703a2018-03-02 11:59:36 -0300560 dl->ops.target.sym->name);
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300561 return true;
562 }
563
564 pthread_mutex_unlock(&notes->lock);
Arnaldo Carvalho de Melo696703a2018-03-02 11:59:36 -0300565 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt);
Adrian Hunter1179e112013-10-14 13:43:39 +0300566 sym_title(ms->sym, ms->map, title, sizeof(title));
Adrian Hunter34f77ab2013-08-07 14:38:55 +0300567 ui_browser__show_title(&browser->b, title);
Arnaldo Carvalho de Melo60521702012-04-02 13:58:33 -0300568 return true;
569}
570
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300571static
572struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
573 s64 offset, s64 *idx)
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300574{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300575 struct annotation *notes = browser__annotation(&browser->b);
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300576 struct disasm_line *pos;
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300577
578 *idx = 0;
Jiri Olsaa17c4ca2017-10-11 17:01:25 +0200579 list_for_each_entry(pos, &notes->src->source, al.node) {
Jiri Olsad5490b92017-10-11 17:01:26 +0200580 if (pos->al.offset == offset)
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300581 return pos;
Jiri Olsaa17c4ca2017-10-11 17:01:25 +0200582 if (!disasm_line__filter(&browser->b, &pos->al.node))
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300583 ++*idx;
584 }
585
586 return NULL;
587}
588
589static bool annotate_browser__jump(struct annotate_browser *browser)
590{
Jiri Olsa7bcbcd52017-11-06 11:56:17 +0100591 struct disasm_line *dl = disasm_line(browser->selection);
Arnaldo Carvalho de Melo5252b1a2016-11-25 15:56:34 -0300592 u64 offset;
Arnaldo Carvalho de Melo4f9d0322012-04-18 13:58:34 -0300593 s64 idx;
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300594
Arnaldo Carvalho de Melo75b49202016-11-24 11:16:06 -0300595 if (!ins__is_jump(&dl->ins))
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300596 return false;
597
Arnaldo Carvalho de Melo5252b1a2016-11-25 15:56:34 -0300598 offset = dl->ops.target.offset;
599 dl = annotate_browser__find_offset(browser, offset, &idx);
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300600 if (dl == NULL) {
Arnaldo Carvalho de Melo5252b1a2016-11-25 15:56:34 -0300601 ui_helpline__printf("Invalid jump offset: %" PRIx64, offset);
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300602 return true;
603 }
604
Jiri Olsaec03a772017-10-11 17:01:56 +0200605 annotate_browser__set_top(browser, &dl->al, idx);
Arnaldo Carvalho de Melo48000a12014-12-17 17:24:45 -0300606
Arnaldo Carvalho de Melo08be4ee2012-04-03 21:35:35 -0300607 return true;
608}
609
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300610static
Jiri Olsa9213afb2017-10-11 17:01:55 +0200611struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300612 char *s, s64 *idx)
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300613{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300614 struct annotation *notes = browser__annotation(&browser->b);
Jiri Olsa9213afb2017-10-11 17:01:55 +0200615 struct annotation_line *al = browser->selection;
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300616
617 *idx = browser->b.index;
Jiri Olsa9213afb2017-10-11 17:01:55 +0200618 list_for_each_entry_continue(al, &notes->src->source, node) {
619 if (disasm_line__filter(&browser->b, &al->node))
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300620 continue;
621
622 ++*idx;
623
Jiri Olsa9213afb2017-10-11 17:01:55 +0200624 if (al->line && strstr(al->line, s) != NULL)
625 return al;
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300626 }
627
628 return NULL;
629}
630
631static bool __annotate_browser__search(struct annotate_browser *browser)
632{
Jiri Olsa9213afb2017-10-11 17:01:55 +0200633 struct annotation_line *al;
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300634 s64 idx;
635
Jiri Olsa9213afb2017-10-11 17:01:55 +0200636 al = annotate_browser__find_string(browser, browser->search_bf, &idx);
637 if (al == NULL) {
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300638 ui_helpline__puts("String not found!");
639 return false;
640 }
641
Jiri Olsaec03a772017-10-11 17:01:56 +0200642 annotate_browser__set_top(browser, al, idx);
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300643 browser->searching_backwards = false;
644 return true;
645}
646
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300647static
Jiri Olsa9213afb2017-10-11 17:01:55 +0200648struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300649 char *s, s64 *idx)
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300650{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300651 struct annotation *notes = browser__annotation(&browser->b);
Jiri Olsa9213afb2017-10-11 17:01:55 +0200652 struct annotation_line *al = browser->selection;
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300653
654 *idx = browser->b.index;
Jiri Olsa9213afb2017-10-11 17:01:55 +0200655 list_for_each_entry_continue_reverse(al, &notes->src->source, node) {
656 if (disasm_line__filter(&browser->b, &al->node))
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300657 continue;
658
659 --*idx;
660
Jiri Olsa9213afb2017-10-11 17:01:55 +0200661 if (al->line && strstr(al->line, s) != NULL)
662 return al;
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300663 }
664
665 return NULL;
666}
667
668static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
669{
Jiri Olsa9213afb2017-10-11 17:01:55 +0200670 struct annotation_line *al;
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300671 s64 idx;
672
Jiri Olsa9213afb2017-10-11 17:01:55 +0200673 al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
674 if (al == NULL) {
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300675 ui_helpline__puts("String not found!");
676 return false;
677 }
678
Jiri Olsaec03a772017-10-11 17:01:56 +0200679 annotate_browser__set_top(browser, al, idx);
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300680 browser->searching_backwards = true;
681 return true;
682}
683
684static bool annotate_browser__search_window(struct annotate_browser *browser,
685 int delay_secs)
686{
687 if (ui_browser__input_window("Search", "String: ", browser->search_bf,
688 "ENTER: OK, ESC: Cancel",
689 delay_secs * 2) != K_ENTER ||
690 !*browser->search_bf)
691 return false;
692
693 return true;
694}
695
696static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs)
697{
698 if (annotate_browser__search_window(browser, delay_secs))
699 return __annotate_browser__search(browser);
700
701 return false;
702}
703
704static bool annotate_browser__continue_search(struct annotate_browser *browser,
705 int delay_secs)
706{
707 if (!*browser->search_bf)
708 return annotate_browser__search(browser, delay_secs);
709
710 return __annotate_browser__search(browser);
711}
712
713static bool annotate_browser__search_reverse(struct annotate_browser *browser,
714 int delay_secs)
715{
716 if (annotate_browser__search_window(browser, delay_secs))
717 return __annotate_browser__search_reverse(browser);
718
719 return false;
720}
721
722static
723bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
724 int delay_secs)
725{
726 if (!*browser->search_bf)
727 return annotate_browser__search_reverse(browser, delay_secs);
728
729 return __annotate_browser__search_reverse(browser);
730}
731
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -0300732static void annotate_browser__update_addr_width(struct annotate_browser *browser)
733{
Arnaldo Carvalho de Melo95aa89d2018-03-15 15:04:33 -0300734 struct annotation *notes = browser__annotation(&browser->b);
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300735
736 if (notes->options->use_offset)
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -0300737 browser->target_width = browser->min_addr_width;
738 else
739 browser->target_width = browser->max_addr_width;
740
741 browser->addr_width = browser->target_width;
742
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300743 if (notes->options->show_nr_jumps)
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -0300744 browser->addr_width += browser->jumps_width + 1;
745}
746
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900747static int annotate_browser__run(struct annotate_browser *browser,
748 struct perf_evsel *evsel,
Namhyung Kim9783adf2012-11-02 14:50:05 +0900749 struct hist_browser_timer *hbt)
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300750{
751 struct rb_node *nd = NULL;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300752 struct map_symbol *ms = browser->b.priv;
Arnaldo Carvalho de Melo34958542011-10-05 19:35:54 -0300753 struct symbol *sym = ms->sym;
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300754 struct annotation *notes = symbol__annotation(ms->sym);
Arnaldo Carvalho de Melo54e7a4e2012-05-12 16:36:55 -0300755 const char *help = "Press 'h' for help on key bindings";
Namhyung Kim9783adf2012-11-02 14:50:05 +0900756 int delay_secs = hbt ? hbt->refresh : 0;
Arnaldo Carvalho de Melob50e0032010-08-11 10:07:43 -0300757 int key;
Adrian Hunter34f77ab2013-08-07 14:38:55 +0300758 char title[SYM_TITLE_MAX_SIZE];
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300759
Adrian Hunter34f77ab2013-08-07 14:38:55 +0300760 sym_title(sym, ms->map, title, sizeof(title));
761 if (ui_browser__show(&browser->b, title, help) < 0)
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300762 return -1;
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300763
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900764 annotate_browser__calc_percent(browser, evsel);
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300765
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300766 if (browser->curr_hot) {
767 annotate_browser__set_rb_top(browser, browser->curr_hot);
768 browser->b.navkeypressed = false;
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300769 }
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300770
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300771 nd = browser->curr_hot;
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300772
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300773 while (1) {
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300774 key = ui_browser__run(&browser->b, delay_secs);
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300775
Arnaldo Carvalho de Melo81cce8d2011-10-05 19:11:32 -0300776 if (delay_secs != 0) {
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900777 annotate_browser__calc_percent(browser, evsel);
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300778 /*
779 * Current line focus got out of the list of most active
780 * lines, NULL it so that if TAB|UNTAB is pressed, we
781 * move to curr_hot (current hottest line).
782 */
783 if (nd != NULL && RB_EMPTY_NODE(nd))
784 nd = NULL;
785 }
786
Arnaldo Carvalho de Melob50e0032010-08-11 10:07:43 -0300787 switch (key) {
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200788 case K_TIMER:
Namhyung Kim9783adf2012-11-02 14:50:05 +0900789 if (hbt)
790 hbt->timer(hbt->arg);
Arnaldo Carvalho de Melo81cce8d2011-10-05 19:11:32 -0300791
792 if (delay_secs != 0)
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900793 symbol__annotate_decay_histogram(sym, evsel->idx);
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300794 continue;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200795 case K_TAB:
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300796 if (nd != NULL) {
797 nd = rb_prev(nd);
798 if (nd == NULL)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300799 nd = rb_last(&browser->entries);
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300800 } else
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300801 nd = browser->curr_hot;
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300802 break;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200803 case K_UNTAB:
Markus Trippelsdorfd4913cb2015-12-14 16:44:03 +0100804 if (nd != NULL) {
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300805 nd = rb_next(nd);
806 if (nd == NULL)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300807 nd = rb_first(&browser->entries);
Markus Trippelsdorfd4913cb2015-12-14 16:44:03 +0100808 } else
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300809 nd = browser->curr_hot;
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300810 break;
Arnaldo Carvalho de Melo54e7a4e2012-05-12 16:36:55 -0300811 case K_F1:
Namhyung Kimef7c5372012-02-23 17:46:21 +0900812 case 'h':
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300813 ui_browser__help_window(&browser->b,
Arnaldo Carvalho de Melo54e7a4e2012-05-12 16:36:55 -0300814 "UP/DOWN/PGUP\n"
815 "PGDN/SPACE Navigate\n"
816 "q/ESC/CTRL+C Exit\n\n"
Arnaldo Carvalho de Melo7727a922015-10-12 13:56:50 -0300817 "ENTER Go to target\n"
818 "ESC Exit\n"
Arnaldo Carvalho de Meloeba9fac2017-09-01 14:55:40 -0300819 "H Go to hottest instruction\n"
820 "TAB/shift+TAB Cycle thru hottest instructions\n"
Arnaldo Carvalho de Melo54e7a4e2012-05-12 16:36:55 -0300821 "j Toggle showing jump to target arrows\n"
822 "J Toggle showing number of jump sources on targets\n"
823 "n Search next string\n"
824 "o Toggle disassembler output/simplified view\n"
825 "s Toggle source code view\n"
Taeung Song3a555c72017-08-18 17:47:08 +0900826 "t Circulate percent, total period, samples view\n"
Arnaldo Carvalho de Melo54e7a4e2012-05-12 16:36:55 -0300827 "/ Search string\n"
Andi Kleene5924882014-11-12 18:05:26 -0800828 "k Toggle line numbers\n"
Feng Tang79ee47f2012-10-30 11:56:05 +0800829 "r Run available scripts\n"
Arnaldo Carvalho de Melofcd9fef2013-08-07 15:55:48 -0300830 "? Search string backwards\n");
Arnaldo Carvalho de Melo54e7a4e2012-05-12 16:36:55 -0300831 continue;
Feng Tang79ee47f2012-10-30 11:56:05 +0800832 case 'r':
833 {
834 script_browse(NULL);
835 continue;
836 }
Andi Kleene5924882014-11-12 18:05:26 -0800837 case 'k':
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300838 notes->options->show_linenr = !notes->options->show_linenr;
Andi Kleene5924882014-11-12 18:05:26 -0800839 break;
Arnaldo Carvalho de Melo54e7a4e2012-05-12 16:36:55 -0300840 case 'H':
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300841 nd = browser->curr_hot;
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300842 break;
Namhyung Kimef7c5372012-02-23 17:46:21 +0900843 case 's':
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300844 if (annotate_browser__toggle_source(browser))
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -0300845 ui_helpline__puts(help);
846 continue;
Arnaldo Carvalho de Meloe235f3f2012-04-02 13:21:55 -0300847 case 'o':
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300848 notes->options->use_offset = !notes->options->use_offset;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300849 annotate_browser__update_addr_width(browser);
Arnaldo Carvalho de Meloe235f3f2012-04-02 13:21:55 -0300850 continue;
Arnaldo Carvalho de Melo9d1ef562012-04-27 16:35:29 -0300851 case 'j':
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300852 notes->options->jump_arrows = !notes->options->jump_arrows;
Arnaldo Carvalho de Melo9d1ef562012-04-27 16:35:29 -0300853 continue;
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -0300854 case 'J':
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300855 notes->options->show_nr_jumps = !notes->options->show_nr_jumps;
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300856 annotate_browser__update_addr_width(browser);
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -0300857 continue;
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300858 case '/':
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300859 if (annotate_browser__search(browser, delay_secs)) {
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300860show_help:
861 ui_helpline__puts(help);
862 }
863 continue;
864 case 'n':
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300865 if (browser->searching_backwards ?
866 annotate_browser__continue_search_reverse(browser, delay_secs) :
867 annotate_browser__continue_search(browser, delay_secs))
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300868 goto show_help;
869 continue;
870 case '?':
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300871 if (annotate_browser__search_reverse(browser, delay_secs))
Arnaldo Carvalho de Melod3d1f612012-04-07 17:10:30 -0300872 goto show_help;
873 continue;
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -0300874 case 'D': {
875 static int seq;
876 ui_helpline__pop();
877 ui_helpline__fpush("%d: nr_ent=%d, height=%d, idx=%d, top_idx=%d, nr_asm_entries=%d",
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300878 seq++, browser->b.nr_entries,
879 browser->b.height,
880 browser->b.index,
881 browser->b.top_idx,
882 browser->nr_asm_entries);
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -0300883 }
884 continue;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200885 case K_ENTER:
886 case K_RIGHT:
Jiri Olsa7bcbcd52017-11-06 11:56:17 +0100887 {
888 struct disasm_line *dl = disasm_line(browser->selection);
889
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300890 if (browser->selection == NULL)
Arnaldo Carvalho de Melo234a5372011-10-06 09:45:29 -0300891 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
Jiri Olsa7bcbcd52017-11-06 11:56:17 +0100892 else if (browser->selection->offset == -1)
Arnaldo Carvalho de Melo234a5372011-10-06 09:45:29 -0300893 ui_helpline__puts("Actions are only available for assembly lines.");
Jiri Olsa7bcbcd52017-11-06 11:56:17 +0100894 else if (!dl->ins.ops)
Naveen N. Rao6ef94922016-06-24 17:23:58 +0530895 goto show_sup_ins;
Jiri Olsa7bcbcd52017-11-06 11:56:17 +0100896 else if (ins__is_ret(&dl->ins))
Arnaldo Carvalho de Meloc4cceae2012-04-20 15:57:15 -0300897 goto out;
Naveen N. Rao6ef94922016-06-24 17:23:58 +0530898 else if (!(annotate_browser__jump(browser) ||
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900899 annotate_browser__callq(browser, evsel, hbt))) {
Arnaldo Carvalho de Meloc4cceae2012-04-20 15:57:15 -0300900show_sup_ins:
Naveen N. Rao6ef94922016-06-24 17:23:58 +0530901 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
Arnaldo Carvalho de Meloc4cceae2012-04-20 15:57:15 -0300902 }
Arnaldo Carvalho de Melofe46e642011-10-19 13:18:13 -0200903 continue;
Jiri Olsa7bcbcd52017-11-06 11:56:17 +0100904 }
Martin Liška0c4a5bc2015-06-19 16:10:43 -0300905 case 't':
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300906 if (notes->options->show_total_period) {
907 notes->options->show_total_period = false;
908 notes->options->show_nr_samples = true;
909 } else if (notes->options->show_nr_samples)
910 notes->options->show_nr_samples = false;
Taeung Song3a555c72017-08-18 17:47:08 +0900911 else
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300912 notes->options->show_total_period = true;
Martin Liška0c4a5bc2015-06-19 16:10:43 -0300913 annotate_browser__update_addr_width(browser);
914 continue;
Arnaldo Carvalho de Melocf958002011-10-20 16:59:15 -0200915 case K_LEFT:
916 case K_ESC:
Arnaldo Carvalho de Meloed7e5662011-10-13 08:31:22 -0300917 case 'q':
918 case CTRL('c'):
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300919 goto out;
Arnaldo Carvalho de Meloed7e5662011-10-13 08:31:22 -0300920 default:
921 continue;
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300922 }
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -0300923
924 if (nd != NULL)
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300925 annotate_browser__set_rb_top(browser, nd);
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300926 }
927out:
Arnaldo Carvalho de Melo05e8b082012-05-29 22:42:18 -0300928 ui_browser__hide(&browser->b);
Arnaldo Carvalho de Melob50e0032010-08-11 10:07:43 -0300929 return key;
Arnaldo Carvalho de Melof1e92142010-08-10 15:14:53 -0300930}
931
Arnaldo Carvalho de Melod5dbc512015-03-17 18:27:28 -0300932int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
933 struct hist_browser_timer *hbt)
934{
Taeung Song9cef4b02017-08-18 17:47:03 +0900935 /* Set default value for show_total_period and show_nr_samples */
Martin Liška0c4a5bc2015-06-19 16:10:43 -0300936 annotate_browser__opts.show_total_period =
Taeung Song9cef4b02017-08-18 17:47:03 +0900937 symbol_conf.show_total_period;
938 annotate_browser__opts.show_nr_samples =
939 symbol_conf.show_nr_samples;
Martin Liška0c4a5bc2015-06-19 16:10:43 -0300940
Arnaldo Carvalho de Melod5dbc512015-03-17 18:27:28 -0300941 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
942}
943
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900944int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
Namhyung Kim9783adf2012-11-02 14:50:05 +0900945 struct hist_browser_timer *hbt)
Arnaldo Carvalho de Melo78f7def2011-02-04 09:45:46 -0200946{
Namhyung Kimed426912015-05-29 21:53:44 +0900947 /* reset abort key so that it can get Ctrl-C as a key */
948 SLang_reset_tty();
949 SLang_init_tty(0, 0, 0);
950
Arnaldo Carvalho de Melod5dbc512015-03-17 18:27:28 -0300951 return map_symbol__tui_annotate(&he->ms, evsel, hbt);
Arnaldo Carvalho de Melo78f7def2011-02-04 09:45:46 -0200952}
953
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -0300954static inline int width_jumps(int n)
955{
956 if (n >= 100)
957 return 5;
958 if (n / 10)
959 return 2;
960 return 1;
961}
962
Namhyung Kimdb8fd072013-03-05 14:53:21 +0900963int symbol__tui_annotate(struct symbol *sym, struct map *map,
964 struct perf_evsel *evsel,
Namhyung Kim9783adf2012-11-02 14:50:05 +0900965 struct hist_browser_timer *hbt)
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300966{
Jiri Olsae1b60b52017-10-11 17:01:53 +0200967 struct annotation_line *al;
Arnaldo Carvalho de Melo9d6bb412018-03-15 10:47:54 -0300968 struct annotation *notes = symbol__annotation(sym);
Samuel Liaoc0a58fb2012-06-05 13:14:59 +0800969 size_t size;
Arnaldo Carvalho de Melo34958542011-10-05 19:35:54 -0300970 struct map_symbol ms = {
971 .map = map,
972 .sym = sym,
973 };
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -0300974 struct annotate_browser browser = {
975 .b = {
Arnaldo Carvalho de Meloa3f895b2012-04-24 14:24:28 -0300976 .refresh = annotate_browser__refresh,
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -0300977 .seek = ui_browser__list_head_seek,
978 .write = annotate_browser__write,
Arnaldo Carvalho de Melo29ed6e72012-04-15 15:24:39 -0300979 .filter = disasm_line__filter,
Arnaldo Carvalho de Melo34958542011-10-05 19:35:54 -0300980 .priv = &ms,
Arnaldo Carvalho de Meloc172f742011-10-18 14:31:35 -0200981 .use_navkeypressed = true,
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -0300982 },
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300983 };
Arnaldo Carvalho de Meloee51d852016-07-29 16:27:18 -0300984 int ret = -1, err;
Namhyung Kimc7e7b612012-11-10 01:21:02 +0900985 int nr_pcnt = 1;
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300986
Arnaldo Carvalho de Melo78f7def2011-02-04 09:45:46 -0200987 if (sym == NULL)
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300988 return -1;
989
Samuel Liaoc0a58fb2012-06-05 13:14:59 +0800990 size = symbol__size(sym);
991
Arnaldo Carvalho de Melo78f7def2011-02-04 09:45:46 -0200992 if (map->dso->annotate_warned)
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -0300993 return -1;
994
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -0300995 notes->options = &annotate_browser__opts;
996
Arnaldo Carvalho de Melo9d6bb412018-03-15 10:47:54 -0300997 notes->offsets = zalloc(size * sizeof(struct annotation_line *));
998 if (notes->offsets == NULL) {
Arnaldo Carvalho de Melob793a402012-04-19 12:19:22 -0300999 ui__error("Not enough memory!");
1000 return -1;
1001 }
1002
Jiri Olsa3ab6db82017-10-11 17:01:48 +02001003 if (perf_evsel__is_group_event(evsel))
Namhyung Kimc7e7b612012-11-10 01:21:02 +09001004 nr_pcnt = evsel->nr_members;
Namhyung Kimc7e7b612012-11-10 01:21:02 +09001005
Arnaldo Carvalho de Melo5449f132017-12-11 12:46:11 -03001006 err = symbol__annotate(sym, map, evsel, sizeof(struct browser_line), &browser.arch);
Arnaldo Carvalho de Meloee51d852016-07-29 16:27:18 -03001007 if (err) {
1008 char msg[BUFSIZ];
1009 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
1010 ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
Arnaldo Carvalho de Melob793a402012-04-19 12:19:22 -03001011 goto out_free_offsets;
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -03001012 }
1013
Jiri Olsa05d3f1a2017-11-15 12:20:08 +01001014 symbol__calc_percent(sym, evsel);
1015
Arnaldo Carvalho de Melo7727a922015-10-12 13:56:50 -03001016 ui_helpline__push("Press ESC to exit");
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -03001017
Arnaldo Carvalho de Melo058b4cc2012-04-02 12:59:01 -03001018 browser.start = map__rip_2objdump(map, sym->start);
Lin Mingdb9a9cbc2011-04-08 14:31:26 +08001019
Jiri Olsae1b60b52017-10-11 17:01:53 +02001020 list_for_each_entry(al, &notes->src->source, node) {
Jiri Olsa0d957972017-11-06 11:55:36 +01001021 struct browser_line *bpos;
Jiri Olsae1b60b52017-10-11 17:01:53 +02001022 size_t line_len = strlen(al->line);
Arnaldo Carvalho de Meloc97cf422011-02-22 12:02:07 -03001023
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -03001024 if (browser.b.width < line_len)
1025 browser.b.width = line_len;
Jiri Olsaa5ef2702017-10-11 17:01:54 +02001026 bpos = browser_line(al);
Arnaldo Carvalho de Melo887c0062012-04-19 10:29:53 -03001027 bpos->idx = browser.nr_entries++;
Jiri Olsae1b60b52017-10-11 17:01:53 +02001028 if (al->offset != -1) {
Arnaldo Carvalho de Melo887c0062012-04-19 10:29:53 -03001029 bpos->idx_asm = browser.nr_asm_entries++;
Arnaldo Carvalho de Melo97148a92012-04-20 15:17:50 -03001030 /*
1031 * FIXME: short term bandaid to cope with assembly
1032 * routines that comes with labels in the same column
1033 * as the address in objdump, sigh.
1034 *
1035 * E.g. copy_user_generic_unrolled
1036 */
Jiri Olsae1b60b52017-10-11 17:01:53 +02001037 if (al->offset < (s64)size)
Arnaldo Carvalho de Melo9d6bb412018-03-15 10:47:54 -03001038 notes->offsets[al->offset] = al;
Arnaldo Carvalho de Melob793a402012-04-19 12:19:22 -03001039 } else
Arnaldo Carvalho de Melo887c0062012-04-19 10:29:53 -03001040 bpos->idx_asm = -1;
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -03001041 }
1042
Arnaldo Carvalho de Melo6dcd57e2018-03-15 15:20:12 -03001043 annotation__mark_jump_targets(notes, sym);
Arnaldo Carvalho de Melof56c0832018-03-15 11:46:23 -03001044 annotation__compute_ipc(notes, size);
Arnaldo Carvalho de Melob793a402012-04-19 12:19:22 -03001045
Arnaldo Carvalho de Melo2402e4a2012-05-12 16:21:53 -03001046 browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);
Arnaldo Carvalho de Melo83b1f2a2012-05-03 13:12:49 -03001047 browser.max_addr_width = hex_width(sym->end);
Arnaldo Carvalho de Melobc1c0f32018-03-15 15:10:28 -03001048 browser.jumps_width = width_jumps(notes->max_jump_sources);
Arnaldo Carvalho de Melo0553e832018-03-15 11:52:32 -03001049 notes->nr_events = nr_pcnt;
Arnaldo Carvalho de Melo0361fc22011-10-14 12:31:21 -03001050 browser.b.nr_entries = browser.nr_entries;
Lin Mingdb9a9cbc2011-04-08 14:31:26 +08001051 browser.b.entries = &notes->src->source,
Arnaldo Carvalho de Melo92221162010-08-09 15:30:40 -03001052 browser.b.width += 18; /* Percentage */
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -03001053
Arnaldo Carvalho de Melo16932d72018-03-15 12:33:56 -03001054 if (notes->options->hide_src_code)
Arnaldo Carvalho de Meloe9823b22012-05-29 21:24:05 -03001055 annotate_browser__init_asm_mode(&browser);
1056
1057 annotate_browser__update_addr_width(&browser);
1058
Namhyung Kimdb8fd072013-03-05 14:53:21 +09001059 ret = annotate_browser__run(&browser, evsel, hbt);
Jiri Olsaf8eb37b2017-10-11 17:01:38 +02001060
1061 annotated_source__purge(notes->src);
Arnaldo Carvalho de Melob793a402012-04-19 12:19:22 -03001062
1063out_free_offsets:
Arnaldo Carvalho de Melo9d6bb412018-03-15 10:47:54 -03001064 zfree(&notes->offsets);
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -03001065 return ret;
1066}
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001067
1068#define ANNOTATE_CFG(n) \
1069 { .name = #n, .value = &annotate_browser__opts.n, }
Frederik Deweerdt865c66c2013-01-14 14:47:17 -05001070
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001071/*
1072 * Keep the entries sorted, they are bsearch'ed
1073 */
Arnaldo Carvalho de Melo7c3102b2013-01-18 16:55:52 -03001074static struct annotate_config {
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001075 const char *name;
1076 bool *value;
1077} annotate__configs[] = {
1078 ANNOTATE_CFG(hide_src_code),
1079 ANNOTATE_CFG(jump_arrows),
Andi Kleene5924882014-11-12 18:05:26 -08001080 ANNOTATE_CFG(show_linenr),
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001081 ANNOTATE_CFG(show_nr_jumps),
Taeung Song9cef4b02017-08-18 17:47:03 +09001082 ANNOTATE_CFG(show_nr_samples),
Martin Liška0c4a5bc2015-06-19 16:10:43 -03001083 ANNOTATE_CFG(show_total_period),
Namhyung Kim39ff7cd2015-10-21 11:57:20 +09001084 ANNOTATE_CFG(use_offset),
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001085};
1086
1087#undef ANNOTATE_CFG
1088
1089static int annotate_config__cmp(const void *name, const void *cfgp)
1090{
Arnaldo Carvalho de Melo7c3102b2013-01-18 16:55:52 -03001091 const struct annotate_config *cfg = cfgp;
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001092
1093 return strcmp(name, cfg->name);
1094}
1095
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001096static int annotate__config(const char *var, const char *value,
1097 void *data __maybe_unused)
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001098{
Arnaldo Carvalho de Melo7c3102b2013-01-18 16:55:52 -03001099 struct annotate_config *cfg;
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001100 const char *name;
1101
Arnaldo Carvalho de Melo8e99b6d2017-07-20 15:27:39 -03001102 if (!strstarts(var, "annotate."))
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001103 return 0;
1104
1105 name = var + 9;
1106 cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs),
Arnaldo Carvalho de Melo7c3102b2013-01-18 16:55:52 -03001107 sizeof(struct annotate_config), annotate_config__cmp);
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001108
1109 if (cfg == NULL)
Arnaldo Carvalho de Melof06cff7c2015-10-22 18:10:52 -03001110 ui__warning("%s variable unknown, ignoring...", var);
1111 else
1112 *cfg->value = perf_config_bool(name, value);
Arnaldo Carvalho de Meloc323cf02012-05-29 22:06:30 -03001113 return 0;
1114}
1115
1116void annotate_browser__init(void)
1117{
1118 perf_config(annotate__config, NULL);
1119}