1 // SPDX-License-Identifier: GPL-2.0
3 #include "util/debug.h"
4 #include "util/annotate.h"
5 #include "util/evsel.h"
6 #include "ui/helpline.h"
18 static const char *const col_names
[] = {
24 static int perf_gtk__get_percent(char *buf
, size_t size
, struct symbol
*sym
,
25 struct disasm_line
*dl
, int evidx
)
27 struct sym_hist
*symhist
;
34 if (dl
->al
.offset
== (s64
) -1)
37 symhist
= annotation__histogram(symbol__annotation(sym
), evidx
);
38 if (!symbol_conf
.event_group
&& !symhist
->addr
[dl
->al
.offset
].nr_samples
)
41 percent
= 100.0 * symhist
->addr
[dl
->al
.offset
].nr_samples
/ symhist
->nr_samples
;
43 markup
= perf_gtk__get_percent_color(percent
);
45 ret
+= scnprintf(buf
, size
, "%s", markup
);
46 ret
+= scnprintf(buf
+ ret
, size
- ret
, "%6.2f%%", percent
);
48 ret
+= scnprintf(buf
+ ret
, size
- ret
, "</span>");
53 static int perf_gtk__get_offset(char *buf
, size_t size
, struct symbol
*sym
,
54 struct map
*map
, struct disasm_line
*dl
)
56 u64 start
= map__rip_2objdump(map
, sym
->start
);
60 if (dl
->al
.offset
== (s64
) -1)
63 return scnprintf(buf
, size
, "%"PRIx64
, start
+ dl
->al
.offset
);
66 static int perf_gtk__get_line(char *buf
, size_t size
, struct disasm_line
*dl
)
69 char *line
= g_markup_escape_text(dl
->al
.line
, -1);
70 const char *markup
= "<span fgcolor='gray'>";
77 if (dl
->al
.offset
!= (s64
) -1)
81 ret
+= scnprintf(buf
, size
, "%s", markup
);
82 ret
+= scnprintf(buf
+ ret
, size
- ret
, "%s", line
);
84 ret
+= scnprintf(buf
+ ret
, size
- ret
, "</span>");
90 static int perf_gtk__annotate_symbol(GtkWidget
*window
, struct symbol
*sym
,
91 struct map
*map
, struct perf_evsel
*evsel
,
92 struct hist_browser_timer
*hbt __maybe_unused
)
94 struct disasm_line
*pos
, *n
;
95 struct annotation
*notes
;
96 GType col_types
[MAX_ANN_COLS
];
97 GtkCellRenderer
*renderer
;
103 notes
= symbol__annotation(sym
);
105 for (i
= 0; i
< MAX_ANN_COLS
; i
++) {
106 col_types
[i
] = G_TYPE_STRING
;
108 store
= gtk_list_store_newv(MAX_ANN_COLS
, col_types
);
110 view
= gtk_tree_view_new();
111 renderer
= gtk_cell_renderer_text_new();
113 for (i
= 0; i
< MAX_ANN_COLS
; i
++) {
114 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view
),
115 -1, col_names
[i
], renderer
, "markup",
119 gtk_tree_view_set_model(GTK_TREE_VIEW(view
), GTK_TREE_MODEL(store
));
120 g_object_unref(GTK_TREE_MODEL(store
));
122 list_for_each_entry(pos
, ¬es
->src
->source
, al
.node
) {
126 gtk_list_store_append(store
, &iter
);
128 if (perf_evsel__is_group_event(evsel
)) {
129 for (i
= 0; i
< evsel
->nr_members
; i
++) {
130 ret
+= perf_gtk__get_percent(s
+ ret
,
134 ret
+= scnprintf(s
+ ret
, sizeof(s
) - ret
, " ");
137 ret
= perf_gtk__get_percent(s
, sizeof(s
), sym
, pos
,
142 gtk_list_store_set(store
, &iter
, ANN_COL__PERCENT
, s
, -1);
143 if (perf_gtk__get_offset(s
, sizeof(s
), sym
, map
, pos
))
144 gtk_list_store_set(store
, &iter
, ANN_COL__OFFSET
, s
, -1);
145 if (perf_gtk__get_line(s
, sizeof(s
), pos
))
146 gtk_list_store_set(store
, &iter
, ANN_COL__LINE
, s
, -1);
149 gtk_container_add(GTK_CONTAINER(window
), view
);
151 list_for_each_entry_safe(pos
, n
, ¬es
->src
->source
, al
.node
) {
152 list_del(&pos
->al
.node
);
153 disasm_line__free(pos
);
159 static int symbol__gtk_annotate(struct symbol
*sym
, struct map
*map
,
160 struct perf_evsel
*evsel
,
161 struct hist_browser_timer
*hbt
)
165 GtkWidget
*scrolled_window
;
166 GtkWidget
*tab_label
;
169 if (map
->dso
->annotate_warned
)
172 err
= symbol__annotate(sym
, map
, evsel
, 0, NULL
);
175 symbol__strerror_disassemble(sym
, map
, err
, msg
, sizeof(msg
));
176 ui__error("Couldn't annotate %s: %s\n", sym
->name
, msg
);
180 symbol__calc_percent(sym
, evsel
);
182 if (perf_gtk__is_active_context(pgctx
)) {
183 window
= pgctx
->main_window
;
184 notebook
= pgctx
->notebook
;
190 signal(SIGSEGV
, perf_gtk__signal
);
191 signal(SIGFPE
, perf_gtk__signal
);
192 signal(SIGINT
, perf_gtk__signal
);
193 signal(SIGQUIT
, perf_gtk__signal
);
194 signal(SIGTERM
, perf_gtk__signal
);
196 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
197 gtk_window_set_title(GTK_WINDOW(window
), "perf annotate");
199 g_signal_connect(window
, "delete_event", gtk_main_quit
, NULL
);
201 pgctx
= perf_gtk__activate_context(window
);
205 vbox
= gtk_vbox_new(FALSE
, 0);
206 notebook
= gtk_notebook_new();
207 pgctx
->notebook
= notebook
;
209 gtk_box_pack_start(GTK_BOX(vbox
), notebook
, TRUE
, TRUE
, 0);
211 infobar
= perf_gtk__setup_info_bar();
213 gtk_box_pack_start(GTK_BOX(vbox
), infobar
,
217 statbar
= perf_gtk__setup_statusbar();
218 gtk_box_pack_start(GTK_BOX(vbox
), statbar
, FALSE
, FALSE
, 0);
220 gtk_container_add(GTK_CONTAINER(window
), vbox
);
223 scrolled_window
= gtk_scrolled_window_new(NULL
, NULL
);
224 tab_label
= gtk_label_new(sym
->name
);
226 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window
),
227 GTK_POLICY_AUTOMATIC
,
228 GTK_POLICY_AUTOMATIC
);
230 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
), scrolled_window
,
233 perf_gtk__annotate_symbol(scrolled_window
, sym
, map
, evsel
, hbt
);
237 int hist_entry__gtk_annotate(struct hist_entry
*he
,
238 struct perf_evsel
*evsel
,
239 struct hist_browser_timer
*hbt
)
241 return symbol__gtk_annotate(he
->ms
.sym
, he
->ms
.map
, evsel
, hbt
);
244 void perf_gtk__show_annotations(void)
248 if (!perf_gtk__is_active_context(pgctx
))
251 window
= pgctx
->main_window
;
252 gtk_widget_show_all(window
);
254 perf_gtk__resize_window(window
);
255 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
259 perf_gtk__deactivate_context(&pgctx
);