1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include "gtk.h"
3*4882a593Smuzhiyun #include "util/sort.h"
4*4882a593Smuzhiyun #include "util/debug.h"
5*4882a593Smuzhiyun #include "util/annotate.h"
6*4882a593Smuzhiyun #include "util/evsel.h"
7*4882a593Smuzhiyun #include "util/map.h"
8*4882a593Smuzhiyun #include "util/dso.h"
9*4882a593Smuzhiyun #include "util/symbol.h"
10*4882a593Smuzhiyun #include "ui/helpline.h"
11*4882a593Smuzhiyun #include <inttypes.h>
12*4882a593Smuzhiyun #include <signal.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun enum {
15*4882a593Smuzhiyun ANN_COL__PERCENT,
16*4882a593Smuzhiyun ANN_COL__OFFSET,
17*4882a593Smuzhiyun ANN_COL__LINE,
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun MAX_ANN_COLS
20*4882a593Smuzhiyun };
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun static const char *const col_names[] = {
23*4882a593Smuzhiyun "Overhead",
24*4882a593Smuzhiyun "Offset",
25*4882a593Smuzhiyun "Line"
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun
perf_gtk__get_percent(char * buf,size_t size,struct symbol * sym,struct disasm_line * dl,int evidx)28*4882a593Smuzhiyun static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
29*4882a593Smuzhiyun struct disasm_line *dl, int evidx)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun struct sym_hist *symhist;
32*4882a593Smuzhiyun double percent = 0.0;
33*4882a593Smuzhiyun const char *markup;
34*4882a593Smuzhiyun int ret = 0;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun strcpy(buf, "");
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun if (dl->al.offset == (s64) -1)
39*4882a593Smuzhiyun return 0;
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun symhist = annotation__histogram(symbol__annotation(sym), evidx);
42*4882a593Smuzhiyun if (!symbol_conf.event_group && !symhist->addr[dl->al.offset].nr_samples)
43*4882a593Smuzhiyun return 0;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun percent = 100.0 * symhist->addr[dl->al.offset].nr_samples / symhist->nr_samples;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun markup = perf_gtk__get_percent_color(percent);
48*4882a593Smuzhiyun if (markup)
49*4882a593Smuzhiyun ret += scnprintf(buf, size, "%s", markup);
50*4882a593Smuzhiyun ret += scnprintf(buf + ret, size - ret, "%6.2f%%", percent);
51*4882a593Smuzhiyun if (markup)
52*4882a593Smuzhiyun ret += scnprintf(buf + ret, size - ret, "</span>");
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun return ret;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
perf_gtk__get_offset(char * buf,size_t size,struct map_symbol * ms,struct disasm_line * dl)57*4882a593Smuzhiyun static int perf_gtk__get_offset(char *buf, size_t size, struct map_symbol *ms,
58*4882a593Smuzhiyun struct disasm_line *dl)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun u64 start = map__rip_2objdump(ms->map, ms->sym->start);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun strcpy(buf, "");
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun if (dl->al.offset == (s64) -1)
65*4882a593Smuzhiyun return 0;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun return scnprintf(buf, size, "%"PRIx64, start + dl->al.offset);
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
perf_gtk__get_line(char * buf,size_t size,struct disasm_line * dl)70*4882a593Smuzhiyun static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun int ret = 0;
73*4882a593Smuzhiyun char *line = g_markup_escape_text(dl->al.line, -1);
74*4882a593Smuzhiyun const char *markup = "<span fgcolor='gray'>";
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun strcpy(buf, "");
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun if (!line)
79*4882a593Smuzhiyun return 0;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun if (dl->al.offset != (s64) -1)
82*4882a593Smuzhiyun markup = NULL;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (markup)
85*4882a593Smuzhiyun ret += scnprintf(buf, size, "%s", markup);
86*4882a593Smuzhiyun ret += scnprintf(buf + ret, size - ret, "%s", line);
87*4882a593Smuzhiyun if (markup)
88*4882a593Smuzhiyun ret += scnprintf(buf + ret, size - ret, "</span>");
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun g_free(line);
91*4882a593Smuzhiyun return ret;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
perf_gtk__annotate_symbol(GtkWidget * window,struct map_symbol * ms,struct evsel * evsel,struct hist_browser_timer * hbt __maybe_unused)94*4882a593Smuzhiyun static int perf_gtk__annotate_symbol(GtkWidget *window, struct map_symbol *ms,
95*4882a593Smuzhiyun struct evsel *evsel,
96*4882a593Smuzhiyun struct hist_browser_timer *hbt __maybe_unused)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun struct symbol *sym = ms->sym;
99*4882a593Smuzhiyun struct disasm_line *pos, *n;
100*4882a593Smuzhiyun struct annotation *notes;
101*4882a593Smuzhiyun GType col_types[MAX_ANN_COLS];
102*4882a593Smuzhiyun GtkCellRenderer *renderer;
103*4882a593Smuzhiyun GtkListStore *store;
104*4882a593Smuzhiyun GtkWidget *view;
105*4882a593Smuzhiyun int i;
106*4882a593Smuzhiyun char s[512];
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun notes = symbol__annotation(sym);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun for (i = 0; i < MAX_ANN_COLS; i++) {
111*4882a593Smuzhiyun col_types[i] = G_TYPE_STRING;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun store = gtk_list_store_newv(MAX_ANN_COLS, col_types);
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun view = gtk_tree_view_new();
116*4882a593Smuzhiyun renderer = gtk_cell_renderer_text_new();
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun for (i = 0; i < MAX_ANN_COLS; i++) {
119*4882a593Smuzhiyun gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
120*4882a593Smuzhiyun -1, col_names[i], renderer, "markup",
121*4882a593Smuzhiyun i, NULL);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
125*4882a593Smuzhiyun g_object_unref(GTK_TREE_MODEL(store));
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun list_for_each_entry(pos, ¬es->src->source, al.node) {
128*4882a593Smuzhiyun GtkTreeIter iter;
129*4882a593Smuzhiyun int ret = 0;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun gtk_list_store_append(store, &iter);
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun if (evsel__is_group_event(evsel)) {
134*4882a593Smuzhiyun for (i = 0; i < evsel->core.nr_members; i++) {
135*4882a593Smuzhiyun ret += perf_gtk__get_percent(s + ret,
136*4882a593Smuzhiyun sizeof(s) - ret,
137*4882a593Smuzhiyun sym, pos,
138*4882a593Smuzhiyun evsel->idx + i);
139*4882a593Smuzhiyun ret += scnprintf(s + ret, sizeof(s) - ret, " ");
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun } else {
142*4882a593Smuzhiyun ret = perf_gtk__get_percent(s, sizeof(s), sym, pos,
143*4882a593Smuzhiyun evsel->idx);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun if (ret)
147*4882a593Smuzhiyun gtk_list_store_set(store, &iter, ANN_COL__PERCENT, s, -1);
148*4882a593Smuzhiyun if (perf_gtk__get_offset(s, sizeof(s), ms, pos))
149*4882a593Smuzhiyun gtk_list_store_set(store, &iter, ANN_COL__OFFSET, s, -1);
150*4882a593Smuzhiyun if (perf_gtk__get_line(s, sizeof(s), pos))
151*4882a593Smuzhiyun gtk_list_store_set(store, &iter, ANN_COL__LINE, s, -1);
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun gtk_container_add(GTK_CONTAINER(window), view);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun list_for_each_entry_safe(pos, n, ¬es->src->source, al.node) {
157*4882a593Smuzhiyun list_del_init(&pos->al.node);
158*4882a593Smuzhiyun disasm_line__free(pos);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
symbol__gtk_annotate(struct map_symbol * ms,struct evsel * evsel,struct hist_browser_timer * hbt)164*4882a593Smuzhiyun static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel,
165*4882a593Smuzhiyun struct hist_browser_timer *hbt)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun struct symbol *sym = ms->sym;
168*4882a593Smuzhiyun GtkWidget *window;
169*4882a593Smuzhiyun GtkWidget *notebook;
170*4882a593Smuzhiyun GtkWidget *scrolled_window;
171*4882a593Smuzhiyun GtkWidget *tab_label;
172*4882a593Smuzhiyun int err;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (ms->map->dso->annotate_warned)
175*4882a593Smuzhiyun return -1;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun err = symbol__annotate(ms, evsel, &annotation__default_options, NULL);
178*4882a593Smuzhiyun if (err) {
179*4882a593Smuzhiyun char msg[BUFSIZ];
180*4882a593Smuzhiyun symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
181*4882a593Smuzhiyun ui__error("Couldn't annotate %s: %s\n", sym->name, msg);
182*4882a593Smuzhiyun return -1;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun symbol__calc_percent(sym, evsel);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (perf_gtk__is_active_context(pgctx)) {
188*4882a593Smuzhiyun window = pgctx->main_window;
189*4882a593Smuzhiyun notebook = pgctx->notebook;
190*4882a593Smuzhiyun } else {
191*4882a593Smuzhiyun GtkWidget *vbox;
192*4882a593Smuzhiyun GtkWidget *infobar;
193*4882a593Smuzhiyun GtkWidget *statbar;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun signal(SIGSEGV, perf_gtk__signal);
196*4882a593Smuzhiyun signal(SIGFPE, perf_gtk__signal);
197*4882a593Smuzhiyun signal(SIGINT, perf_gtk__signal);
198*4882a593Smuzhiyun signal(SIGQUIT, perf_gtk__signal);
199*4882a593Smuzhiyun signal(SIGTERM, perf_gtk__signal);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
202*4882a593Smuzhiyun gtk_window_set_title(GTK_WINDOW(window), "perf annotate");
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun pgctx = perf_gtk__activate_context(window);
207*4882a593Smuzhiyun if (!pgctx)
208*4882a593Smuzhiyun return -1;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun vbox = gtk_vbox_new(FALSE, 0);
211*4882a593Smuzhiyun notebook = gtk_notebook_new();
212*4882a593Smuzhiyun pgctx->notebook = notebook;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun infobar = perf_gtk__setup_info_bar();
217*4882a593Smuzhiyun if (infobar) {
218*4882a593Smuzhiyun gtk_box_pack_start(GTK_BOX(vbox), infobar,
219*4882a593Smuzhiyun FALSE, FALSE, 0);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun statbar = perf_gtk__setup_statusbar();
223*4882a593Smuzhiyun gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun gtk_container_add(GTK_CONTAINER(window), vbox);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun scrolled_window = gtk_scrolled_window_new(NULL, NULL);
229*4882a593Smuzhiyun tab_label = gtk_label_new(sym->name);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
232*4882a593Smuzhiyun GTK_POLICY_AUTOMATIC,
233*4882a593Smuzhiyun GTK_POLICY_AUTOMATIC);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window,
236*4882a593Smuzhiyun tab_label);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun perf_gtk__annotate_symbol(scrolled_window, ms, evsel, hbt);
239*4882a593Smuzhiyun return 0;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
hist_entry__gtk_annotate(struct hist_entry * he,struct evsel * evsel,struct hist_browser_timer * hbt)242*4882a593Smuzhiyun int hist_entry__gtk_annotate(struct hist_entry *he,
243*4882a593Smuzhiyun struct evsel *evsel,
244*4882a593Smuzhiyun struct hist_browser_timer *hbt)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun return symbol__gtk_annotate(&he->ms, evsel, hbt);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
perf_gtk__show_annotations(void)249*4882a593Smuzhiyun void perf_gtk__show_annotations(void)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun GtkWidget *window;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun if (!perf_gtk__is_active_context(pgctx))
254*4882a593Smuzhiyun return;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun window = pgctx->main_window;
257*4882a593Smuzhiyun gtk_widget_show_all(window);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun perf_gtk__resize_window(window);
260*4882a593Smuzhiyun gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun gtk_main();
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun perf_gtk__deactivate_context(&pgctx);
265*4882a593Smuzhiyun }
266