blob: 5b01df633f9adb1082809ba4d91d50c411e74f72 [file] [log] [blame]
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -03001#include "../browser.h"
2#include "../helpline.h"
3#include "../libslang.h"
4#include "../../hist.h"
5#include "../../sort.h"
6#include "../../symbol.h"
7
8static void ui__error_window(const char *fmt, ...)
9{
10 va_list ap;
11
12 va_start(ap, fmt);
13 newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
14 va_end(ap);
15}
16
17static void annotate_browser__write(struct ui_browser *self, void *entry, int row)
18{
19 struct objdump_line *ol = rb_entry(entry, struct objdump_line, node);
20 bool current_entry = ui_browser__is_current_entry(self, row);
21 int width = self->width;
22
23 if (ol->offset != -1) {
24 struct hist_entry *he = self->priv;
25 struct symbol *sym = he->ms.sym;
26 int len = he->ms.sym->end - he->ms.sym->start;
27 unsigned int hits = 0;
28 double percent = 0.0;
29 int color;
30 struct sym_priv *priv = symbol__priv(sym);
31 struct sym_ext *sym_ext = priv->ext;
32 struct sym_hist *h = priv->hist;
33 s64 offset = ol->offset;
34 struct objdump_line *next = objdump__get_next_ip_line(self->entries, ol);
35
36 while (offset < (s64)len &&
37 (next == NULL || offset < next->offset)) {
38 if (sym_ext) {
39 percent += sym_ext[offset].percent;
40 } else
41 hits += h->ip[offset];
42
43 ++offset;
44 }
45
46 if (sym_ext == NULL && h->sum)
47 percent = 100.0 * hits / h->sum;
48
49 color = ui_browser__percent_color(percent, current_entry);
50 SLsmg_set_color(color);
51 slsmg_printf(" %7.2f ", percent);
52 if (!current_entry)
53 SLsmg_set_color(HE_COLORSET_CODE);
54 } else {
55 int color = ui_browser__percent_color(0, current_entry);
56 SLsmg_set_color(color);
57 slsmg_write_nstring(" ", 9);
58 }
59
60 SLsmg_write_char(':');
61 slsmg_write_nstring(" ", 8);
62 if (!*ol->line)
63 slsmg_write_nstring(" ", width - 18);
64 else
65 slsmg_write_nstring(ol->line, width - 18);
66}
67
68int hist_entry__tui_annotate(struct hist_entry *self)
69{
70 struct newtExitStruct es;
71 struct objdump_line *pos, *n;
72 LIST_HEAD(head);
73 struct ui_browser browser = {
74 .entries = &head,
75 .refresh = ui_browser__list_head_refresh,
76 .seek = ui_browser__list_head_seek,
77 .write = annotate_browser__write,
78 .priv = self,
79 };
80 int ret;
81
82 if (self->ms.sym == NULL)
83 return -1;
84
85 if (self->ms.map->dso->annotate_warned)
86 return -1;
87
88 if (hist_entry__annotate(self, &head) < 0) {
Arnaldo Carvalho de Melo1e6dd072010-08-10 15:58:50 -030089 ui__error_window(ui_helpline__last_msg);
Arnaldo Carvalho de Melo211ef122010-08-10 14:54:09 -030090 return -1;
91 }
92
93 ui_helpline__push("Press <- or ESC to exit");
94
95 list_for_each_entry(pos, &head, node) {
96 size_t line_len = strlen(pos->line);
97 if (browser.width < line_len)
98 browser.width = line_len;
99 ++browser.nr_entries;
100 }
101
102 browser.width += 18; /* Percentage */
103 ui_browser__show(&browser, self->ms.sym->name);
104 newtFormAddHotKey(browser.form, ' ');
105 ret = ui_browser__run(&browser, &es);
106 newtFormDestroy(browser.form);
107 newtPopWindow();
108 list_for_each_entry_safe(pos, n, &head, node) {
109 list_del(&pos->node);
110 objdump_line__free(pos);
111 }
112 ui_helpline__pop();
113 return ret;
114}