1 // SPDX-License-Identifier: GPL-2.0
4 #include "util/debug.h"
5 #include "util/annotate.h"
6 #include "util/evsel.h"
9 #include "util/symbol.h"
10 #include "ui/helpline.h"
22 static const char *const col_names
[] = {
28 static int perf_gtk__get_percent(char *buf
, size_t size
, struct symbol
*sym
,
29 struct disasm_line
*dl
, int evidx
)
31 struct annotation
*notes
;
32 struct sym_hist
*symhist
;
33 struct sym_hist_entry
*entry
;
41 if (dl
->al
.offset
== (s64
) -1)
44 notes
= symbol__annotation(sym
);
45 symhist
= annotation__histogram(notes
, evidx
);
46 entry
= annotated_source__hist_entry(notes
->src
, evidx
, dl
->al
.offset
);
48 nr_samples
= entry
->nr_samples
;
50 if (!symbol_conf
.event_group
&& nr_samples
== 0)
53 percent
= 100.0 * nr_samples
/ symhist
->nr_samples
;
55 markup
= perf_gtk__get_percent_color(percent
);
57 ret
+= scnprintf(buf
, size
, "%s", markup
);
58 ret
+= scnprintf(buf
+ ret
, size
- ret
, "%6.2f%%", percent
);
60 ret
+= scnprintf(buf
+ ret
, size
- ret
, "</span>");
65 static int perf_gtk__get_offset(char *buf
, size_t size
, struct map_symbol
*ms
,
66 struct disasm_line
*dl
)
68 u64 start
= map__rip_2objdump(ms
->map
, ms
->sym
->start
);
72 if (dl
->al
.offset
== (s64
) -1)
75 return scnprintf(buf
, size
, "%"PRIx64
, start
+ dl
->al
.offset
);
78 static int perf_gtk__get_line(char *buf
, size_t size
, struct disasm_line
*dl
)
81 char *line
= g_markup_escape_text(dl
->al
.line
, -1);
82 const char *markup
= "<span fgcolor='gray'>";
89 if (dl
->al
.offset
!= (s64
) -1)
93 ret
+= scnprintf(buf
, size
, "%s", markup
);
94 ret
+= scnprintf(buf
+ ret
, size
- ret
, "%s", line
);
96 ret
+= scnprintf(buf
+ ret
, size
- ret
, "</span>");
102 static int perf_gtk__annotate_symbol(GtkWidget
*window
, struct map_symbol
*ms
,
104 struct hist_browser_timer
*hbt __maybe_unused
)
106 struct symbol
*sym
= ms
->sym
;
107 struct disasm_line
*pos
, *n
;
108 struct annotation
*notes
;
109 GType col_types
[MAX_ANN_COLS
];
110 GtkCellRenderer
*renderer
;
116 notes
= symbol__annotation(sym
);
118 for (i
= 0; i
< MAX_ANN_COLS
; i
++) {
119 col_types
[i
] = G_TYPE_STRING
;
121 store
= gtk_list_store_newv(MAX_ANN_COLS
, col_types
);
123 view
= gtk_tree_view_new();
124 renderer
= gtk_cell_renderer_text_new();
126 for (i
= 0; i
< MAX_ANN_COLS
; i
++) {
127 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view
),
128 -1, col_names
[i
], renderer
, "markup",
132 gtk_tree_view_set_model(GTK_TREE_VIEW(view
), GTK_TREE_MODEL(store
));
133 g_object_unref(GTK_TREE_MODEL(store
));
135 list_for_each_entry(pos
, ¬es
->src
->source
, al
.node
) {
139 gtk_list_store_append(store
, &iter
);
141 if (evsel__is_group_event(evsel
)) {
142 for (i
= 0; i
< evsel
->core
.nr_members
; i
++) {
143 ret
+= perf_gtk__get_percent(s
+ ret
,
146 evsel
->core
.idx
+ i
);
147 ret
+= scnprintf(s
+ ret
, sizeof(s
) - ret
, " ");
150 ret
= perf_gtk__get_percent(s
, sizeof(s
), sym
, pos
,
155 gtk_list_store_set(store
, &iter
, ANN_COL__PERCENT
, s
, -1);
156 if (perf_gtk__get_offset(s
, sizeof(s
), ms
, pos
))
157 gtk_list_store_set(store
, &iter
, ANN_COL__OFFSET
, s
, -1);
158 if (perf_gtk__get_line(s
, sizeof(s
), pos
))
159 gtk_list_store_set(store
, &iter
, ANN_COL__LINE
, s
, -1);
162 gtk_container_add(GTK_CONTAINER(window
), view
);
164 list_for_each_entry_safe(pos
, n
, ¬es
->src
->source
, al
.node
) {
165 list_del_init(&pos
->al
.node
);
166 disasm_line__free(pos
);
172 static int symbol__gtk_annotate(struct map_symbol
*ms
, struct evsel
*evsel
,
173 struct hist_browser_timer
*hbt
)
175 struct dso
*dso
= map__dso(ms
->map
);
176 struct symbol
*sym
= ms
->sym
;
179 GtkWidget
*scrolled_window
;
180 GtkWidget
*tab_label
;
183 if (dso__annotate_warned(dso
))
186 err
= symbol__annotate(ms
, evsel
, NULL
);
190 dso__set_annotate_warned(dso
);
191 symbol__strerror_disassemble(ms
, err
, msg
, sizeof(msg
));
192 ui__error("Couldn't annotate %s: %s\n", sym
->name
, msg
);
196 symbol__calc_percent(sym
, evsel
);
198 if (perf_gtk__is_active_context(pgctx
)) {
199 window
= pgctx
->main_window
;
200 notebook
= pgctx
->notebook
;
206 signal(SIGSEGV
, perf_gtk__signal
);
207 signal(SIGFPE
, perf_gtk__signal
);
208 signal(SIGINT
, perf_gtk__signal
);
209 signal(SIGQUIT
, perf_gtk__signal
);
210 signal(SIGTERM
, perf_gtk__signal
);
212 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
213 gtk_window_set_title(GTK_WINDOW(window
), "perf annotate");
215 g_signal_connect(window
, "delete_event", gtk_main_quit
, NULL
);
217 pgctx
= perf_gtk__activate_context(window
);
221 vbox
= gtk_vbox_new(FALSE
, 0);
222 notebook
= gtk_notebook_new();
223 pgctx
->notebook
= notebook
;
225 gtk_box_pack_start(GTK_BOX(vbox
), notebook
, TRUE
, TRUE
, 0);
227 infobar
= perf_gtk__setup_info_bar();
229 gtk_box_pack_start(GTK_BOX(vbox
), infobar
,
233 statbar
= perf_gtk__setup_statusbar();
234 gtk_box_pack_start(GTK_BOX(vbox
), statbar
, FALSE
, FALSE
, 0);
236 gtk_container_add(GTK_CONTAINER(window
), vbox
);
239 scrolled_window
= gtk_scrolled_window_new(NULL
, NULL
);
240 tab_label
= gtk_label_new(sym
->name
);
242 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window
),
243 GTK_POLICY_AUTOMATIC
,
244 GTK_POLICY_AUTOMATIC
);
246 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
), scrolled_window
,
249 perf_gtk__annotate_symbol(scrolled_window
, ms
, evsel
, hbt
);
253 int hist_entry__gtk_annotate(struct hist_entry
*he
,
255 struct hist_browser_timer
*hbt
)
257 return symbol__gtk_annotate(&he
->ms
, evsel
, hbt
);
260 void perf_gtk__show_annotations(void)
264 if (!perf_gtk__is_active_context(pgctx
))
267 window
= pgctx
->main_window
;
268 gtk_widget_show_all(window
);
270 perf_gtk__resize_window(window
);
271 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
275 perf_gtk__deactivate_context(&pgctx
);