aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/ui/browsers/annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/ui/browsers/annotate.c')
-rw-r--r--tools/perf/ui/browsers/annotate.c399
1 files changed, 197 insertions, 202 deletions
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 8f7f59d1a2b5..286427975112 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -25,16 +25,10 @@ struct disasm_line_samples {
25#define IPC_WIDTH 6 25#define IPC_WIDTH 6
26#define CYCLES_WIDTH 6 26#define CYCLES_WIDTH 6
27 27
28struct browser_disasm_line { 28struct browser_line {
29 struct rb_node rb_node; 29 u32 idx;
30 u32 idx; 30 int idx_asm;
31 int idx_asm; 31 int jump_sources;
32 int jump_sources;
33 /*
34 * actual length of this array is saved on the nr_events field
35 * of the struct annotate_browser
36 */
37 struct disasm_line_samples samples[1];
38}; 32};
39 33
40static struct annotate_browser_opt { 34static struct annotate_browser_opt {
@@ -53,39 +47,43 @@ static struct annotate_browser_opt {
53struct arch; 47struct arch;
54 48
55struct annotate_browser { 49struct annotate_browser {
56 struct ui_browser b; 50 struct ui_browser b;
57 struct rb_root entries; 51 struct rb_root entries;
58 struct rb_node *curr_hot; 52 struct rb_node *curr_hot;
59 struct disasm_line *selection; 53 struct annotation_line *selection;
60 struct disasm_line **offsets; 54 struct annotation_line **offsets;
61 struct arch *arch; 55 struct arch *arch;
62 int nr_events; 56 int nr_events;
63 u64 start; 57 u64 start;
64 int nr_asm_entries; 58 int nr_asm_entries;
65 int nr_entries; 59 int nr_entries;
66 int max_jump_sources; 60 int max_jump_sources;
67 int nr_jumps; 61 int nr_jumps;
68 bool searching_backwards; 62 bool searching_backwards;
69 bool have_cycles; 63 bool have_cycles;
70 u8 addr_width; 64 u8 addr_width;
71 u8 jumps_width; 65 u8 jumps_width;
72 u8 target_width; 66 u8 target_width;
73 u8 min_addr_width; 67 u8 min_addr_width;
74 u8 max_addr_width; 68 u8 max_addr_width;
75 char search_bf[128]; 69 char search_bf[128];
76}; 70};
77 71
78static inline struct browser_disasm_line *disasm_line__browser(struct disasm_line *dl) 72static inline struct browser_line *browser_line(struct annotation_line *al)
79{ 73{
80 return (struct browser_disasm_line *)(dl + 1); 74 void *ptr = al;
75
76 ptr = container_of(al, struct disasm_line, al);
77 return ptr - sizeof(struct browser_line);
81} 78}
82 79
83static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 80static bool disasm_line__filter(struct ui_browser *browser __maybe_unused,
84 void *entry) 81 void *entry)
85{ 82{
86 if (annotate_browser__opts.hide_src_code) { 83 if (annotate_browser__opts.hide_src_code) {
87 struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 84 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
88 return dl->offset == -1; 85
86 return al->offset == -1;
89 } 87 }
90 88
91 return false; 89 return false;
@@ -120,11 +118,37 @@ static int annotate_browser__cycles_width(struct annotate_browser *ab)
120 return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0; 118 return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0;
121} 119}
122 120
121static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser,
122 char *bf, size_t size)
123{
124 if (dl->ins.ops && dl->ins.ops->scnprintf) {
125 if (ins__is_jump(&dl->ins)) {
126 bool fwd = dl->ops.target.offset > dl->al.offset;
127
128 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
129 SLSMG_UARROW_CHAR);
130 SLsmg_write_char(' ');
131 } else if (ins__is_call(&dl->ins)) {
132 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
133 SLsmg_write_char(' ');
134 } else if (ins__is_ret(&dl->ins)) {
135 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
136 SLsmg_write_char(' ');
137 } else {
138 ui_browser__write_nstring(browser, " ", 2);
139 }
140 } else {
141 ui_browser__write_nstring(browser, " ", 2);
142 }
143
144 disasm_line__scnprintf(dl, bf, size, !annotate_browser__opts.use_offset);
145}
146
123static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 147static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
124{ 148{
125 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 149 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
126 struct disasm_line *dl = list_entry(entry, struct disasm_line, node); 150 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
127 struct browser_disasm_line *bdl = disasm_line__browser(dl); 151 struct browser_line *bl = browser_line(al);
128 bool current_entry = ui_browser__is_current_entry(browser, row); 152 bool current_entry = ui_browser__is_current_entry(browser, row);
129 bool change_color = (!annotate_browser__opts.hide_src_code && 153 bool change_color = (!annotate_browser__opts.hide_src_code &&
130 (!current_entry || (browser->use_navkeypressed && 154 (!current_entry || (browser->use_navkeypressed &&
@@ -137,32 +161,32 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
137 bool show_title = false; 161 bool show_title = false;
138 162
139 for (i = 0; i < ab->nr_events; i++) { 163 for (i = 0; i < ab->nr_events; i++) {
140 if (bdl->samples[i].percent > percent_max) 164 if (al->samples[i].percent > percent_max)
141 percent_max = bdl->samples[i].percent; 165 percent_max = al->samples[i].percent;
142 } 166 }
143 167
144 if ((row == 0) && (dl->offset == -1 || percent_max == 0.0)) { 168 if ((row == 0) && (al->offset == -1 || percent_max == 0.0)) {
145 if (ab->have_cycles) { 169 if (ab->have_cycles) {
146 if (dl->ipc == 0.0 && dl->cycles == 0) 170 if (al->ipc == 0.0 && al->cycles == 0)
147 show_title = true; 171 show_title = true;
148 } else 172 } else
149 show_title = true; 173 show_title = true;
150 } 174 }
151 175
152 if (dl->offset != -1 && percent_max != 0.0) { 176 if (al->offset != -1 && percent_max != 0.0) {
153 for (i = 0; i < ab->nr_events; i++) { 177 for (i = 0; i < ab->nr_events; i++) {
154 ui_browser__set_percent_color(browser, 178 ui_browser__set_percent_color(browser,
155 bdl->samples[i].percent, 179 al->samples[i].percent,
156 current_entry); 180 current_entry);
157 if (annotate_browser__opts.show_total_period) { 181 if (annotate_browser__opts.show_total_period) {
158 ui_browser__printf(browser, "%11" PRIu64 " ", 182 ui_browser__printf(browser, "%11" PRIu64 " ",
159 bdl->samples[i].he.period); 183 al->samples[i].he.period);
160 } else if (annotate_browser__opts.show_nr_samples) { 184 } else if (annotate_browser__opts.show_nr_samples) {
161 ui_browser__printf(browser, "%6" PRIu64 " ", 185 ui_browser__printf(browser, "%6" PRIu64 " ",
162 bdl->samples[i].he.nr_samples); 186 al->samples[i].he.nr_samples);
163 } else { 187 } else {
164 ui_browser__printf(browser, "%6.2f ", 188 ui_browser__printf(browser, "%6.2f ",
165 bdl->samples[i].percent); 189 al->samples[i].percent);
166 } 190 }
167 } 191 }
168 } else { 192 } else {
@@ -177,16 +201,16 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
177 } 201 }
178 } 202 }
179 if (ab->have_cycles) { 203 if (ab->have_cycles) {
180 if (dl->ipc) 204 if (al->ipc)
181 ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc); 205 ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, al->ipc);
182 else if (!show_title) 206 else if (!show_title)
183 ui_browser__write_nstring(browser, " ", IPC_WIDTH); 207 ui_browser__write_nstring(browser, " ", IPC_WIDTH);
184 else 208 else
185 ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC"); 209 ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC");
186 210
187 if (dl->cycles) 211 if (al->cycles)
188 ui_browser__printf(browser, "%*" PRIu64 " ", 212 ui_browser__printf(browser, "%*" PRIu64 " ",
189 CYCLES_WIDTH - 1, dl->cycles); 213 CYCLES_WIDTH - 1, al->cycles);
190 else if (!show_title) 214 else if (!show_title)
191 ui_browser__write_nstring(browser, " ", CYCLES_WIDTH); 215 ui_browser__write_nstring(browser, " ", CYCLES_WIDTH);
192 else 216 else
@@ -199,19 +223,19 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
199 if (!browser->navkeypressed) 223 if (!browser->navkeypressed)
200 width += 1; 224 width += 1;
201 225
202 if (!*dl->line) 226 if (!*al->line)
203 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width); 227 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
204 else if (dl->offset == -1) { 228 else if (al->offset == -1) {
205 if (dl->line_nr && annotate_browser__opts.show_linenr) 229 if (al->line_nr && annotate_browser__opts.show_linenr)
206 printed = scnprintf(bf, sizeof(bf), "%-*d ", 230 printed = scnprintf(bf, sizeof(bf), "%-*d ",
207 ab->addr_width + 1, dl->line_nr); 231 ab->addr_width + 1, al->line_nr);
208 else 232 else
209 printed = scnprintf(bf, sizeof(bf), "%*s ", 233 printed = scnprintf(bf, sizeof(bf), "%*s ",
210 ab->addr_width, " "); 234 ab->addr_width, " ");
211 ui_browser__write_nstring(browser, bf, printed); 235 ui_browser__write_nstring(browser, bf, printed);
212 ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width - cycles_width + 1); 236 ui_browser__write_nstring(browser, al->line, width - printed - pcnt_width - cycles_width + 1);
213 } else { 237 } else {
214 u64 addr = dl->offset; 238 u64 addr = al->offset;
215 int color = -1; 239 int color = -1;
216 240
217 if (!annotate_browser__opts.use_offset) 241 if (!annotate_browser__opts.use_offset)
@@ -220,13 +244,13 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
220 if (!annotate_browser__opts.use_offset) { 244 if (!annotate_browser__opts.use_offset) {
221 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); 245 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
222 } else { 246 } else {
223 if (bdl->jump_sources) { 247 if (bl->jump_sources) {
224 if (annotate_browser__opts.show_nr_jumps) { 248 if (annotate_browser__opts.show_nr_jumps) {
225 int prev; 249 int prev;
226 printed = scnprintf(bf, sizeof(bf), "%*d ", 250 printed = scnprintf(bf, sizeof(bf), "%*d ",
227 ab->jumps_width, 251 ab->jumps_width,
228 bdl->jump_sources); 252 bl->jump_sources);
229 prev = annotate_browser__set_jumps_percent_color(ab, bdl->jump_sources, 253 prev = annotate_browser__set_jumps_percent_color(ab, bl->jump_sources,
230 current_entry); 254 current_entry);
231 ui_browser__write_nstring(browser, bf, printed); 255 ui_browser__write_nstring(browser, bf, printed);
232 ui_browser__set_color(browser, prev); 256 ui_browser__set_color(browser, prev);
@@ -245,32 +269,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
245 ui_browser__write_nstring(browser, bf, printed); 269 ui_browser__write_nstring(browser, bf, printed);
246 if (change_color) 270 if (change_color)
247 ui_browser__set_color(browser, color); 271 ui_browser__set_color(browser, color);
248 if (dl->ins.ops && dl->ins.ops->scnprintf) {
249 if (ins__is_jump(&dl->ins)) {
250 bool fwd = dl->ops.target.offset > dl->offset;
251
252 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
253 SLSMG_UARROW_CHAR);
254 SLsmg_write_char(' ');
255 } else if (ins__is_call(&dl->ins)) {
256 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
257 SLsmg_write_char(' ');
258 } else if (ins__is_ret(&dl->ins)) {
259 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
260 SLsmg_write_char(' ');
261 } else {
262 ui_browser__write_nstring(browser, " ", 2);
263 }
264 } else {
265 ui_browser__write_nstring(browser, " ", 2);
266 }
267 272
268 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 273 disasm_line__write(disasm_line(al), browser, bf, sizeof(bf));
274
269 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed); 275 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed);
270 } 276 }
271 277
272 if (current_entry) 278 if (current_entry)
273 ab->selection = dl; 279 ab->selection = al;
274} 280}
275 281
276static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym) 282static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym)
@@ -286,7 +292,7 @@ static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sy
286 292
287static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 293static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
288{ 294{
289 struct disasm_line *pos = list_prev_entry(cursor, node); 295 struct disasm_line *pos = list_prev_entry(cursor, al.node);
290 const char *name; 296 const char *name;
291 297
292 if (!pos) 298 if (!pos)
@@ -306,8 +312,9 @@ static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
306static void annotate_browser__draw_current_jump(struct ui_browser *browser) 312static void annotate_browser__draw_current_jump(struct ui_browser *browser)
307{ 313{
308 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 314 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
309 struct disasm_line *cursor = ab->selection, *target; 315 struct disasm_line *cursor = disasm_line(ab->selection);
310 struct browser_disasm_line *btarget, *bcursor; 316 struct annotation_line *target;
317 struct browser_line *btarget, *bcursor;
311 unsigned int from, to; 318 unsigned int from, to;
312 struct map_symbol *ms = ab->b.priv; 319 struct map_symbol *ms = ab->b.priv;
313 struct symbol *sym = ms->sym; 320 struct symbol *sym = ms->sym;
@@ -321,11 +328,9 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
321 return; 328 return;
322 329
323 target = ab->offsets[cursor->ops.target.offset]; 330 target = ab->offsets[cursor->ops.target.offset];
324 if (!target)
325 return;
326 331
327 bcursor = disasm_line__browser(cursor); 332 bcursor = browser_line(&cursor->al);
328 btarget = disasm_line__browser(target); 333 btarget = browser_line(target);
329 334
330 if (annotate_browser__opts.hide_src_code) { 335 if (annotate_browser__opts.hide_src_code) {
331 from = bcursor->idx_asm; 336 from = bcursor->idx_asm;
@@ -361,12 +366,11 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)
361 return ret; 366 return ret;
362} 367}
363 368
364static int disasm__cmp(struct browser_disasm_line *a, 369static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
365 struct browser_disasm_line *b, int nr_pcnt)
366{ 370{
367 int i; 371 int i;
368 372
369 for (i = 0; i < nr_pcnt; i++) { 373 for (i = 0; i < a->samples_nr; i++) {
370 if (a->samples[i].percent == b->samples[i].percent) 374 if (a->samples[i].percent == b->samples[i].percent)
371 continue; 375 continue;
372 return a->samples[i].percent < b->samples[i].percent; 376 return a->samples[i].percent < b->samples[i].percent;
@@ -374,28 +378,27 @@ static int disasm__cmp(struct browser_disasm_line *a,
374 return 0; 378 return 0;
375} 379}
376 380
377static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl, 381static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al)
378 int nr_events)
379{ 382{
380 struct rb_node **p = &root->rb_node; 383 struct rb_node **p = &root->rb_node;
381 struct rb_node *parent = NULL; 384 struct rb_node *parent = NULL;
382 struct browser_disasm_line *l; 385 struct annotation_line *l;
383 386
384 while (*p != NULL) { 387 while (*p != NULL) {
385 parent = *p; 388 parent = *p;
386 l = rb_entry(parent, struct browser_disasm_line, rb_node); 389 l = rb_entry(parent, struct annotation_line, rb_node);
387 390
388 if (disasm__cmp(bdl, l, nr_events)) 391 if (disasm__cmp(al, l))
389 p = &(*p)->rb_left; 392 p = &(*p)->rb_left;
390 else 393 else
391 p = &(*p)->rb_right; 394 p = &(*p)->rb_right;
392 } 395 }
393 rb_link_node(&bdl->rb_node, parent, p); 396 rb_link_node(&al->rb_node, parent, p);
394 rb_insert_color(&bdl->rb_node, root); 397 rb_insert_color(&al->rb_node, root);
395} 398}
396 399
397static void annotate_browser__set_top(struct annotate_browser *browser, 400static void annotate_browser__set_top(struct annotate_browser *browser,
398 struct disasm_line *pos, u32 idx) 401 struct annotation_line *pos, u32 idx)
399{ 402{
400 unsigned back; 403 unsigned back;
401 404
@@ -404,7 +407,7 @@ static void annotate_browser__set_top(struct annotate_browser *browser,
404 browser->b.top_idx = browser->b.index = idx; 407 browser->b.top_idx = browser->b.index = idx;
405 408
406 while (browser->b.top_idx != 0 && back != 0) { 409 while (browser->b.top_idx != 0 && back != 0) {
407 pos = list_entry(pos->node.prev, struct disasm_line, node); 410 pos = list_entry(pos->node.prev, struct annotation_line, node);
408 411
409 if (disasm_line__filter(&browser->b, &pos->node)) 412 if (disasm_line__filter(&browser->b, &pos->node))
410 continue; 413 continue;
@@ -420,12 +423,13 @@ static void annotate_browser__set_top(struct annotate_browser *browser,
420static void annotate_browser__set_rb_top(struct annotate_browser *browser, 423static void annotate_browser__set_rb_top(struct annotate_browser *browser,
421 struct rb_node *nd) 424 struct rb_node *nd)
422{ 425{
423 struct browser_disasm_line *bpos; 426 struct browser_line *bpos;
424 struct disasm_line *pos; 427 struct annotation_line *pos;
425 u32 idx; 428 u32 idx;
426 429
427 bpos = rb_entry(nd, struct browser_disasm_line, rb_node); 430 pos = rb_entry(nd, struct annotation_line, rb_node);
428 pos = ((struct disasm_line *)bpos) - 1; 431 bpos = browser_line(pos);
432
429 idx = bpos->idx; 433 idx = bpos->idx;
430 if (annotate_browser__opts.hide_src_code) 434 if (annotate_browser__opts.hide_src_code)
431 idx = bpos->idx_asm; 435 idx = bpos->idx_asm;
@@ -439,46 +443,35 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
439 struct map_symbol *ms = browser->b.priv; 443 struct map_symbol *ms = browser->b.priv;
440 struct symbol *sym = ms->sym; 444 struct symbol *sym = ms->sym;
441 struct annotation *notes = symbol__annotation(sym); 445 struct annotation *notes = symbol__annotation(sym);
442 struct disasm_line *pos, *next; 446 struct disasm_line *pos;
443 s64 len = symbol__size(sym);
444 447
445 browser->entries = RB_ROOT; 448 browser->entries = RB_ROOT;
446 449
447 pthread_mutex_lock(&notes->lock); 450 pthread_mutex_lock(&notes->lock);
448 451
449 list_for_each_entry(pos, &notes->src->source, node) { 452 symbol__calc_percent(sym, evsel);
450 struct browser_disasm_line *bpos = disasm_line__browser(pos); 453
451 const char *path = NULL; 454 list_for_each_entry(pos, &notes->src->source, al.node) {
452 double max_percent = 0.0; 455 double max_percent = 0.0;
453 int i; 456 int i;
454 457
455 if (pos->offset == -1) { 458 if (pos->al.offset == -1) {
456 RB_CLEAR_NODE(&bpos->rb_node); 459 RB_CLEAR_NODE(&pos->al.rb_node);
457 continue; 460 continue;
458 } 461 }
459 462
460 next = disasm__get_next_ip_line(&notes->src->source, pos); 463 for (i = 0; i < pos->al.samples_nr; i++) {
461 464 struct annotation_data *sample = &pos->al.samples[i];
462 for (i = 0; i < browser->nr_events; i++) {
463 struct sym_hist_entry sample;
464
465 bpos->samples[i].percent = disasm__calc_percent(notes,
466 evsel->idx + i,
467 pos->offset,
468 next ? next->offset : len,
469 &path, &sample);
470 bpos->samples[i].he = sample;
471 465
472 if (max_percent < bpos->samples[i].percent) 466 if (max_percent < sample->percent)
473 max_percent = bpos->samples[i].percent; 467 max_percent = sample->percent;
474 } 468 }
475 469
476 if (max_percent < 0.01 && pos->ipc == 0) { 470 if (max_percent < 0.01 && pos->al.ipc == 0) {
477 RB_CLEAR_NODE(&bpos->rb_node); 471 RB_CLEAR_NODE(&pos->al.rb_node);
478 continue; 472 continue;
479 } 473 }
480 disasm_rb_tree__insert(&browser->entries, bpos, 474 disasm_rb_tree__insert(&browser->entries, &pos->al);
481 browser->nr_events);
482 } 475 }
483 pthread_mutex_unlock(&notes->lock); 476 pthread_mutex_unlock(&notes->lock);
484 477
@@ -487,38 +480,38 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
487 480
488static bool annotate_browser__toggle_source(struct annotate_browser *browser) 481static bool annotate_browser__toggle_source(struct annotate_browser *browser)
489{ 482{
490 struct disasm_line *dl; 483 struct annotation_line *al;
491 struct browser_disasm_line *bdl; 484 struct browser_line *bl;
492 off_t offset = browser->b.index - browser->b.top_idx; 485 off_t offset = browser->b.index - browser->b.top_idx;
493 486
494 browser->b.seek(&browser->b, offset, SEEK_CUR); 487 browser->b.seek(&browser->b, offset, SEEK_CUR);
495 dl = list_entry(browser->b.top, struct disasm_line, node); 488 al = list_entry(browser->b.top, struct annotation_line, node);
496 bdl = disasm_line__browser(dl); 489 bl = browser_line(al);
497 490
498 if (annotate_browser__opts.hide_src_code) { 491 if (annotate_browser__opts.hide_src_code) {
499 if (bdl->idx_asm < offset) 492 if (bl->idx_asm < offset)
500 offset = bdl->idx; 493 offset = bl->idx;
501 494
502 browser->b.nr_entries = browser->nr_entries; 495 browser->b.nr_entries = browser->nr_entries;
503 annotate_browser__opts.hide_src_code = false; 496 annotate_browser__opts.hide_src_code = false;
504 browser->b.seek(&browser->b, -offset, SEEK_CUR); 497 browser->b.seek(&browser->b, -offset, SEEK_CUR);
505 browser->b.top_idx = bdl->idx - offset; 498 browser->b.top_idx = bl->idx - offset;
506 browser->b.index = bdl->idx; 499 browser->b.index = bl->idx;
507 } else { 500 } else {
508 if (bdl->idx_asm < 0) { 501 if (bl->idx_asm < 0) {
509 ui_helpline__puts("Only available for assembly lines."); 502 ui_helpline__puts("Only available for assembly lines.");
510 browser->b.seek(&browser->b, -offset, SEEK_CUR); 503 browser->b.seek(&browser->b, -offset, SEEK_CUR);
511 return false; 504 return false;
512 } 505 }
513 506
514 if (bdl->idx_asm < offset) 507 if (bl->idx_asm < offset)
515 offset = bdl->idx_asm; 508 offset = bl->idx_asm;
516 509
517 browser->b.nr_entries = browser->nr_asm_entries; 510 browser->b.nr_entries = browser->nr_asm_entries;
518 annotate_browser__opts.hide_src_code = true; 511 annotate_browser__opts.hide_src_code = true;
519 browser->b.seek(&browser->b, -offset, SEEK_CUR); 512 browser->b.seek(&browser->b, -offset, SEEK_CUR);
520 browser->b.top_idx = bdl->idx_asm - offset; 513 browser->b.top_idx = bl->idx_asm - offset;
521 browser->b.index = bdl->idx_asm; 514 browser->b.index = bl->idx_asm;
522 } 515 }
523 516
524 return true; 517 return true;
@@ -543,7 +536,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
543 struct hist_browser_timer *hbt) 536 struct hist_browser_timer *hbt)
544{ 537{
545 struct map_symbol *ms = browser->b.priv; 538 struct map_symbol *ms = browser->b.priv;
546 struct disasm_line *dl = browser->selection; 539 struct disasm_line *dl = disasm_line(browser->selection);
547 struct annotation *notes; 540 struct annotation *notes;
548 struct addr_map_symbol target = { 541 struct addr_map_symbol target = {
549 .map = ms->map, 542 .map = ms->map,
@@ -589,10 +582,10 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows
589 struct disasm_line *pos; 582 struct disasm_line *pos;
590 583
591 *idx = 0; 584 *idx = 0;
592 list_for_each_entry(pos, &notes->src->source, node) { 585 list_for_each_entry(pos, &notes->src->source, al.node) {
593 if (pos->offset == offset) 586 if (pos->al.offset == offset)
594 return pos; 587 return pos;
595 if (!disasm_line__filter(&browser->b, &pos->node)) 588 if (!disasm_line__filter(&browser->b, &pos->al.node))
596 ++*idx; 589 ++*idx;
597 } 590 }
598 591
@@ -601,7 +594,7 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows
601 594
602static bool annotate_browser__jump(struct annotate_browser *browser) 595static bool annotate_browser__jump(struct annotate_browser *browser)
603{ 596{
604 struct disasm_line *dl = browser->selection; 597 struct disasm_line *dl = disasm_line(browser->selection);
605 u64 offset; 598 u64 offset;
606 s64 idx; 599 s64 idx;
607 600
@@ -615,29 +608,29 @@ static bool annotate_browser__jump(struct annotate_browser *browser)
615 return true; 608 return true;
616 } 609 }
617 610
618 annotate_browser__set_top(browser, dl, idx); 611 annotate_browser__set_top(browser, &dl->al, idx);
619 612
620 return true; 613 return true;
621} 614}
622 615
623static 616static
624struct disasm_line *annotate_browser__find_string(struct annotate_browser *browser, 617struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
625 char *s, s64 *idx) 618 char *s, s64 *idx)
626{ 619{
627 struct map_symbol *ms = browser->b.priv; 620 struct map_symbol *ms = browser->b.priv;
628 struct symbol *sym = ms->sym; 621 struct symbol *sym = ms->sym;
629 struct annotation *notes = symbol__annotation(sym); 622 struct annotation *notes = symbol__annotation(sym);
630 struct disasm_line *pos = browser->selection; 623 struct annotation_line *al = browser->selection;
631 624
632 *idx = browser->b.index; 625 *idx = browser->b.index;
633 list_for_each_entry_continue(pos, &notes->src->source, node) { 626 list_for_each_entry_continue(al, &notes->src->source, node) {
634 if (disasm_line__filter(&browser->b, &pos->node)) 627 if (disasm_line__filter(&browser->b, &al->node))
635 continue; 628 continue;
636 629
637 ++*idx; 630 ++*idx;
638 631
639 if (pos->line && strstr(pos->line, s) != NULL) 632 if (al->line && strstr(al->line, s) != NULL)
640 return pos; 633 return al;
641 } 634 }
642 635
643 return NULL; 636 return NULL;
@@ -645,38 +638,38 @@ struct disasm_line *annotate_browser__find_string(struct annotate_browser *brows
645 638
646static bool __annotate_browser__search(struct annotate_browser *browser) 639static bool __annotate_browser__search(struct annotate_browser *browser)
647{ 640{
648 struct disasm_line *dl; 641 struct annotation_line *al;
649 s64 idx; 642 s64 idx;
650 643
651 dl = annotate_browser__find_string(browser, browser->search_bf, &idx); 644 al = annotate_browser__find_string(browser, browser->search_bf, &idx);
652 if (dl == NULL) { 645 if (al == NULL) {
653 ui_helpline__puts("String not found!"); 646 ui_helpline__puts("String not found!");
654 return false; 647 return false;
655 } 648 }
656 649
657 annotate_browser__set_top(browser, dl, idx); 650 annotate_browser__set_top(browser, al, idx);
658 browser->searching_backwards = false; 651 browser->searching_backwards = false;
659 return true; 652 return true;
660} 653}
661 654
662static 655static
663struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 656struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
664 char *s, s64 *idx) 657 char *s, s64 *idx)
665{ 658{
666 struct map_symbol *ms = browser->b.priv; 659 struct map_symbol *ms = browser->b.priv;
667 struct symbol *sym = ms->sym; 660 struct symbol *sym = ms->sym;
668 struct annotation *notes = symbol__annotation(sym); 661 struct annotation *notes = symbol__annotation(sym);
669 struct disasm_line *pos = browser->selection; 662 struct annotation_line *al = browser->selection;
670 663
671 *idx = browser->b.index; 664 *idx = browser->b.index;
672 list_for_each_entry_continue_reverse(pos, &notes->src->source, node) { 665 list_for_each_entry_continue_reverse(al, &notes->src->source, node) {
673 if (disasm_line__filter(&browser->b, &pos->node)) 666 if (disasm_line__filter(&browser->b, &al->node))
674 continue; 667 continue;
675 668
676 --*idx; 669 --*idx;
677 670
678 if (pos->line && strstr(pos->line, s) != NULL) 671 if (al->line && strstr(al->line, s) != NULL)
679 return pos; 672 return al;
680 } 673 }
681 674
682 return NULL; 675 return NULL;
@@ -684,16 +677,16 @@ struct disasm_line *annotate_browser__find_string_reverse(struct annotate_browse
684 677
685static bool __annotate_browser__search_reverse(struct annotate_browser *browser) 678static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
686{ 679{
687 struct disasm_line *dl; 680 struct annotation_line *al;
688 s64 idx; 681 s64 idx;
689 682
690 dl = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx); 683 al = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
691 if (dl == NULL) { 684 if (al == NULL) {
692 ui_helpline__puts("String not found!"); 685 ui_helpline__puts("String not found!");
693 return false; 686 return false;
694 } 687 }
695 688
696 annotate_browser__set_top(browser, dl, idx); 689 annotate_browser__set_top(browser, al, idx);
697 browser->searching_backwards = true; 690 browser->searching_backwards = true;
698 return true; 691 return true;
699} 692}
@@ -899,13 +892,16 @@ show_help:
899 continue; 892 continue;
900 case K_ENTER: 893 case K_ENTER:
901 case K_RIGHT: 894 case K_RIGHT:
895 {
896 struct disasm_line *dl = disasm_line(browser->selection);
897
902 if (browser->selection == NULL) 898 if (browser->selection == NULL)
903 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 899 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
904 else if (browser->selection->offset == -1) 900 else if (browser->selection->offset == -1)
905 ui_helpline__puts("Actions are only available for assembly lines."); 901 ui_helpline__puts("Actions are only available for assembly lines.");
906 else if (!browser->selection->ins.ops) 902 else if (!dl->ins.ops)
907 goto show_sup_ins; 903 goto show_sup_ins;
908 else if (ins__is_ret(&browser->selection->ins)) 904 else if (ins__is_ret(&dl->ins))
909 goto out; 905 goto out;
910 else if (!(annotate_browser__jump(browser) || 906 else if (!(annotate_browser__jump(browser) ||
911 annotate_browser__callq(browser, evsel, hbt))) { 907 annotate_browser__callq(browser, evsel, hbt))) {
@@ -913,6 +909,7 @@ show_sup_ins:
913 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 909 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
914 } 910 }
915 continue; 911 continue;
912 }
916 case 't': 913 case 't':
917 if (annotate_browser__opts.show_total_period) { 914 if (annotate_browser__opts.show_total_period) {
918 annotate_browser__opts.show_total_period = false; 915 annotate_browser__opts.show_total_period = false;
@@ -990,10 +987,10 @@ static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,
990 return; 987 return;
991 988
992 for (offset = start; offset <= end; offset++) { 989 for (offset = start; offset <= end; offset++) {
993 struct disasm_line *dl = browser->offsets[offset]; 990 struct annotation_line *al = browser->offsets[offset];
994 991
995 if (dl) 992 if (al)
996 dl->ipc = ipc; 993 al->ipc = ipc;
997 } 994 }
998 } 995 }
999} 996}
@@ -1018,13 +1015,13 @@ static void annotate__compute_ipc(struct annotate_browser *browser, size_t size,
1018 1015
1019 ch = &notes->src->cycles_hist[offset]; 1016 ch = &notes->src->cycles_hist[offset];
1020 if (ch && ch->cycles) { 1017 if (ch && ch->cycles) {
1021 struct disasm_line *dl; 1018 struct annotation_line *al;
1022 1019
1023 if (ch->have_start) 1020 if (ch->have_start)
1024 count_and_fill(browser, ch->start, offset, ch); 1021 count_and_fill(browser, ch->start, offset, ch);
1025 dl = browser->offsets[offset]; 1022 al = browser->offsets[offset];
1026 if (dl && ch->num_aggr) 1023 if (al && ch->num_aggr)
1027 dl->cycles = ch->cycles_aggr / ch->num_aggr; 1024 al->cycles = ch->cycles_aggr / ch->num_aggr;
1028 browser->have_cycles = true; 1025 browser->have_cycles = true;
1029 } 1026 }
1030 } 1027 }
@@ -1043,23 +1040,27 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser
1043 return; 1040 return;
1044 1041
1045 for (offset = 0; offset < size; ++offset) { 1042 for (offset = 0; offset < size; ++offset) {
1046 struct disasm_line *dl = browser->offsets[offset], *dlt; 1043 struct annotation_line *al = browser->offsets[offset];
1047 struct browser_disasm_line *bdlt; 1044 struct disasm_line *dl;
1045 struct browser_line *blt;
1046
1047 dl = disasm_line(al);
1048 1048
1049 if (!disasm_line__is_valid_jump(dl, sym)) 1049 if (!disasm_line__is_valid_jump(dl, sym))
1050 continue; 1050 continue;
1051 1051
1052 dlt = browser->offsets[dl->ops.target.offset]; 1052 al = browser->offsets[dl->ops.target.offset];
1053
1053 /* 1054 /*
1054 * FIXME: Oops, no jump target? Buggy disassembler? Or do we 1055 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
1055 * have to adjust to the previous offset? 1056 * have to adjust to the previous offset?
1056 */ 1057 */
1057 if (dlt == NULL) 1058 if (al == NULL)
1058 continue; 1059 continue;
1059 1060
1060 bdlt = disasm_line__browser(dlt); 1061 blt = browser_line(al);
1061 if (++bdlt->jump_sources > browser->max_jump_sources) 1062 if (++blt->jump_sources > browser->max_jump_sources)
1062 browser->max_jump_sources = bdlt->jump_sources; 1063 browser->max_jump_sources = blt->jump_sources;
1063 1064
1064 ++browser->nr_jumps; 1065 ++browser->nr_jumps;
1065 } 1066 }
@@ -1078,7 +1079,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1078 struct perf_evsel *evsel, 1079 struct perf_evsel *evsel,
1079 struct hist_browser_timer *hbt) 1080 struct hist_browser_timer *hbt)
1080{ 1081{
1081 struct disasm_line *pos, *n; 1082 struct annotation_line *al;
1082 struct annotation *notes; 1083 struct annotation *notes;
1083 size_t size; 1084 size_t size;
1084 struct map_symbol ms = { 1085 struct map_symbol ms = {
@@ -1097,7 +1098,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1097 }; 1098 };
1098 int ret = -1, err; 1099 int ret = -1, err;
1099 int nr_pcnt = 1; 1100 int nr_pcnt = 1;
1100 size_t sizeof_bdl = sizeof(struct browser_disasm_line);
1101 1101
1102 if (sym == NULL) 1102 if (sym == NULL)
1103 return -1; 1103 return -1;
@@ -1107,21 +1107,16 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1107 if (map->dso->annotate_warned) 1107 if (map->dso->annotate_warned)
1108 return -1; 1108 return -1;
1109 1109
1110 browser.offsets = zalloc(size * sizeof(struct disasm_line *)); 1110 browser.offsets = zalloc(size * sizeof(struct annotation_line *));
1111 if (browser.offsets == NULL) { 1111 if (browser.offsets == NULL) {
1112 ui__error("Not enough memory!"); 1112 ui__error("Not enough memory!");
1113 return -1; 1113 return -1;
1114 } 1114 }
1115 1115
1116 if (perf_evsel__is_group_event(evsel)) { 1116 if (perf_evsel__is_group_event(evsel))
1117 nr_pcnt = evsel->nr_members; 1117 nr_pcnt = evsel->nr_members;
1118 sizeof_bdl += sizeof(struct disasm_line_samples) *
1119 (nr_pcnt - 1);
1120 }
1121 1118
1122 err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 1119 err = symbol__annotate(sym, map, evsel, sizeof(struct browser_line), &browser.arch);
1123 sizeof_bdl, &browser.arch,
1124 perf_evsel__env_cpuid(evsel));
1125 if (err) { 1120 if (err) {
1126 char msg[BUFSIZ]; 1121 char msg[BUFSIZ];
1127 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 1122 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
@@ -1129,20 +1124,22 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1129 goto out_free_offsets; 1124 goto out_free_offsets;
1130 } 1125 }
1131 1126
1127 symbol__calc_percent(sym, evsel);
1128
1132 ui_helpline__push("Press ESC to exit"); 1129 ui_helpline__push("Press ESC to exit");
1133 1130
1134 notes = symbol__annotation(sym); 1131 notes = symbol__annotation(sym);
1135 browser.start = map__rip_2objdump(map, sym->start); 1132 browser.start = map__rip_2objdump(map, sym->start);
1136 1133
1137 list_for_each_entry(pos, &notes->src->source, node) { 1134 list_for_each_entry(al, &notes->src->source, node) {
1138 struct browser_disasm_line *bpos; 1135 struct browser_line *bpos;
1139 size_t line_len = strlen(pos->line); 1136 size_t line_len = strlen(al->line);
1140 1137
1141 if (browser.b.width < line_len) 1138 if (browser.b.width < line_len)
1142 browser.b.width = line_len; 1139 browser.b.width = line_len;
1143 bpos = disasm_line__browser(pos); 1140 bpos = browser_line(al);
1144 bpos->idx = browser.nr_entries++; 1141 bpos->idx = browser.nr_entries++;
1145 if (pos->offset != -1) { 1142 if (al->offset != -1) {
1146 bpos->idx_asm = browser.nr_asm_entries++; 1143 bpos->idx_asm = browser.nr_asm_entries++;
1147 /* 1144 /*
1148 * FIXME: short term bandaid to cope with assembly 1145 * FIXME: short term bandaid to cope with assembly
@@ -1151,8 +1148,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1151 * 1148 *
1152 * E.g. copy_user_generic_unrolled 1149 * E.g. copy_user_generic_unrolled
1153 */ 1150 */
1154 if (pos->offset < (s64)size) 1151 if (al->offset < (s64)size)
1155 browser.offsets[pos->offset] = pos; 1152 browser.offsets[al->offset] = al;
1156 } else 1153 } else
1157 bpos->idx_asm = -1; 1154 bpos->idx_asm = -1;
1158 } 1155 }
@@ -1174,10 +1171,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1174 annotate_browser__update_addr_width(&browser); 1171 annotate_browser__update_addr_width(&browser);
1175 1172
1176 ret = annotate_browser__run(&browser, evsel, hbt); 1173 ret = annotate_browser__run(&browser, evsel, hbt);
1177 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 1174
1178 list_del(&pos->node); 1175 annotated_source__purge(notes->src);
1179 disasm_line__free(pos);
1180 }
1181 1176
1182out_free_offsets: 1177out_free_offsets:
1183 free(browser.offsets); 1178 free(browser.offsets);