1 #include "../browser.h"
2 #include "../helpline.h"
3 #include "../libslang.h"
4 #include "../../annotate.h"
5 #include "../../hist.h"
6 #include "../../sort.h"
7 #include "../../symbol.h"
8 #include "../../annotate.h"
10 static void ui__error_window(const char *fmt
, ...)
15 newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt
, ap
);
19 struct annotate_browser
{
21 struct rb_root entries
;
22 struct rb_node
*curr_hot
;
25 struct objdump_line_rb_node
{
26 struct rb_node rb_node
;
32 struct objdump_line_rb_node
*objdump_line__rb(struct objdump_line
*self
)
34 return (struct objdump_line_rb_node
*)(self
+ 1);
37 static void annotate_browser__write(struct ui_browser
*self
, void *entry
, int row
)
39 struct objdump_line
*ol
= rb_entry(entry
, struct objdump_line
, node
);
40 bool current_entry
= ui_browser__is_current_entry(self
, row
);
41 int width
= self
->width
;
43 if (ol
->offset
!= -1) {
44 struct objdump_line_rb_node
*olrb
= objdump_line__rb(ol
);
45 ui_browser__set_percent_color(self
, olrb
->percent
, current_entry
);
46 slsmg_printf(" %7.2f ", olrb
->percent
);
48 ui_browser__set_color(self
, HE_COLORSET_CODE
);
50 ui_browser__set_percent_color(self
, 0, current_entry
);
51 slsmg_write_nstring(" ", 9);
54 SLsmg_write_char(':');
55 slsmg_write_nstring(" ", 8);
57 slsmg_write_nstring(" ", width
- 18);
59 slsmg_write_nstring(ol
->line
, width
- 18);
62 static double objdump_line__calc_percent(struct objdump_line
*self
,
63 struct symbol
*sym
, int evidx
)
67 if (self
->offset
!= -1) {
68 int len
= sym
->end
- sym
->start
;
69 unsigned int hits
= 0;
70 struct annotation
*notes
= symbol__annotation(sym
);
71 struct source_line
*src_line
= notes
->src
->lines
;
72 struct sym_hist
*h
= annotation__histogram(notes
, evidx
);
73 s64 offset
= self
->offset
;
74 struct objdump_line
*next
;
76 next
= objdump__get_next_ip_line(¬es
->src
->source
, self
);
77 while (offset
< (s64
)len
&&
78 (next
== NULL
|| offset
< next
->offset
)) {
80 percent
+= src_line
[offset
].percent
;
82 hits
+= h
->addr
[offset
];
87 * If the percentage wasn't already calculated in
88 * symbol__get_source_line, do it now:
90 if (src_line
== NULL
&& h
->sum
)
91 percent
= 100.0 * hits
/ h
->sum
;
97 static void objdump__insert_line(struct rb_root
*self
,
98 struct objdump_line_rb_node
*line
)
100 struct rb_node
**p
= &self
->rb_node
;
101 struct rb_node
*parent
= NULL
;
102 struct objdump_line_rb_node
*l
;
106 l
= rb_entry(parent
, struct objdump_line_rb_node
, rb_node
);
107 if (line
->percent
< l
->percent
)
112 rb_link_node(&line
->rb_node
, parent
, p
);
113 rb_insert_color(&line
->rb_node
, self
);
116 static void annotate_browser__set_top(struct annotate_browser
*self
,
119 struct objdump_line_rb_node
*rbpos
;
120 struct objdump_line
*pos
;
123 ui_browser__refresh_dimensions(&self
->b
);
124 back
= self
->b
.height
/ 2;
125 rbpos
= rb_entry(nd
, struct objdump_line_rb_node
, rb_node
);
126 pos
= ((struct objdump_line
*)rbpos
) - 1;
127 self
->b
.top_idx
= self
->b
.index
= rbpos
->idx
;
129 while (self
->b
.top_idx
!= 0 && back
!= 0) {
130 pos
= list_entry(pos
->node
.prev
, struct objdump_line
, node
);
140 static int annotate_browser__run(struct annotate_browser
*self
)
143 struct symbol
*sym
= self
->b
.priv
;
146 if (ui_browser__show(&self
->b
, sym
->name
,
147 "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
150 * To allow builtin-annotate to cycle thru multiple symbols by
151 * examining the exit key for this function.
153 ui_browser__add_exit_key(&self
->b
, NEWT_KEY_RIGHT
);
157 int tabs
[] = { NEWT_KEY_TAB
, NEWT_KEY_UNTAB
, 0 };
158 ui_browser__add_exit_keys(&self
->b
, tabs
);
162 key
= ui_browser__run(&self
->b
);
168 nd
= rb_last(&self
->entries
);
169 annotate_browser__set_top(self
, nd
);
174 nd
= rb_first(&self
->entries
);
175 annotate_browser__set_top(self
, nd
);
182 ui_browser__hide(&self
->b
);
186 int hist_entry__tui_annotate(struct hist_entry
*he
, int evidx
)
188 return symbol__tui_annotate(he
->ms
.sym
, he
->ms
.map
, evidx
);
191 int symbol__tui_annotate(struct symbol
*sym
, struct map
*map
, int evidx
)
193 struct objdump_line
*pos
, *n
;
194 struct objdump_line_rb_node
*rbpos
;
195 struct annotation
*notes
= symbol__annotation(sym
);
196 struct annotate_browser browser
= {
198 .entries
= ¬es
->src
->source
,
199 .refresh
= ui_browser__list_head_refresh
,
200 .seek
= ui_browser__list_head_seek
,
201 .write
= annotate_browser__write
,
210 if (map
->dso
->annotate_warned
)
213 if (symbol__annotate(sym
, map
, sizeof(*rbpos
)) < 0) {
214 ui__error_window(ui_helpline__last_msg
);
218 ui_helpline__push("Press <- or ESC to exit");
220 list_for_each_entry(pos
, ¬es
->src
->source
, node
) {
221 size_t line_len
= strlen(pos
->line
);
222 if (browser
.b
.width
< line_len
)
223 browser
.b
.width
= line_len
;
224 rbpos
= objdump_line__rb(pos
);
225 rbpos
->idx
= browser
.b
.nr_entries
++;
226 rbpos
->percent
= objdump_line__calc_percent(pos
, sym
, evidx
);
227 if (rbpos
->percent
< 0.01)
229 objdump__insert_line(&browser
.entries
, rbpos
);
233 * Position the browser at the hottest line.
235 browser
.curr_hot
= rb_last(&browser
.entries
);
236 if (browser
.curr_hot
)
237 annotate_browser__set_top(&browser
, browser
.curr_hot
);
239 browser
.b
.width
+= 18; /* Percentage */
240 ret
= annotate_browser__run(&browser
);
241 list_for_each_entry_safe(pos
, n
, ¬es
->src
->source
, node
) {
242 list_del(&pos
->node
);
243 objdump_line__free(pos
);