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 sym_hist
*symhist
;
38 if (dl
->al
.offset
== (s64
) -1)
41 symhist
= annotation__histogram(symbol__annotation(sym
), evidx
);
42 if (!symbol_conf
.event_group
&& !symhist
->addr
[dl
->al
.offset
].nr_samples
)
45 percent
= 100.0 * symhist
->addr
[dl
->al
.offset
].nr_samples
/ symhist
->nr_samples
;
47 markup
= perf_gtk__get_percent_color(percent
);
49 ret
+= scnprintf(buf
, size
, "%s", markup
);
50 ret
+= scnprintf(buf
+ ret
, size
- ret
, "%6.2f%%", percent
);
52 ret
+= scnprintf(buf
+ ret
, size
- ret
, "</span>");
57 static int perf_gtk__get_offset(char *buf
, size_t size
, struct map_symbol
*ms
,
58 struct disasm_line
*dl
)
60 u64 start
= map__rip_2objdump(ms
->map
, ms
->sym
->start
);
64 if (dl
->al
.offset
== (s64
) -1)
67 return scnprintf(buf
, size
, "%"PRIx64
, start
+ dl
->al
.offset
);
70 static int perf_gtk__get_line(char *buf
, size_t size
, struct disasm_line
*dl
)
73 char *line
= g_markup_escape_text(dl
->al
.line
, -1);
74 const char *markup
= "<span fgcolor='gray'>";
81 if (dl
->al
.offset
!= (s64
) -1)
85 ret
+= scnprintf(buf
, size
, "%s", markup
);
86 ret
+= scnprintf(buf
+ ret
, size
- ret
, "%s", line
);
88 ret
+= scnprintf(buf
+ ret
, size
- ret
, "</span>");
94 static int perf_gtk__annotate_symbol(GtkWidget
*window
, struct map_symbol
*ms
,
96 struct hist_browser_timer
*hbt __maybe_unused
)
98 struct symbol
*sym
= ms
->sym
;
99 struct disasm_line
*pos
, *n
;
100 struct annotation
*notes
;
101 GType col_types
[MAX_ANN_COLS
];
102 GtkCellRenderer
*renderer
;
108 notes
= symbol__annotation(sym
);
110 for (i
= 0; i
< MAX_ANN_COLS
; i
++) {
111 col_types
[i
] = G_TYPE_STRING
;
113 store
= gtk_list_store_newv(MAX_ANN_COLS
, col_types
);
115 view
= gtk_tree_view_new();
116 renderer
= gtk_cell_renderer_text_new();
118 for (i
= 0; i
< MAX_ANN_COLS
; i
++) {
119 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view
),
120 -1, col_names
[i
], renderer
, "markup",
124 gtk_tree_view_set_model(GTK_TREE_VIEW(view
), GTK_TREE_MODEL(store
));
125 g_object_unref(GTK_TREE_MODEL(store
));
127 list_for_each_entry(pos
, ¬es
->src
->source
, al
.node
) {
131 gtk_list_store_append(store
, &iter
);
133 if (evsel__is_group_event(evsel
)) {
134 for (i
= 0; i
< evsel
->core
.nr_members
; i
++) {
135 ret
+= perf_gtk__get_percent(s
+ ret
,
139 ret
+= scnprintf(s
+ ret
, sizeof(s
) - ret
, " ");
142 ret
= perf_gtk__get_percent(s
, sizeof(s
), sym
, pos
,
147 gtk_list_store_set(store
, &iter
, ANN_COL__PERCENT
, s
, -1);
148 if (perf_gtk__get_offset(s
, sizeof(s
), ms
, pos
))
149 gtk_list_store_set(store
, &iter
, ANN_COL__OFFSET
, s
, -1);
150 if (perf_gtk__get_line(s
, sizeof(s
), pos
))
151 gtk_list_store_set(store
, &iter
, ANN_COL__LINE
, s
, -1);
154 gtk_container_add(GTK_CONTAINER(window
), view
);
156 list_for_each_entry_safe(pos
, n
, ¬es
->src
->source
, al
.node
) {
157 list_del_init(&pos
->al
.node
);
158 disasm_line__free(pos
);
164 static int symbol__gtk_annotate(struct map_symbol
*ms
, struct evsel
*evsel
,
165 struct hist_browser_timer
*hbt
)
167 struct symbol
*sym
= ms
->sym
;
170 GtkWidget
*scrolled_window
;
171 GtkWidget
*tab_label
;
174 if (ms
->map
->dso
->annotate_warned
)
177 err
= symbol__annotate(ms
, evsel
, &annotation__default_options
, NULL
);
180 symbol__strerror_disassemble(ms
, err
, msg
, sizeof(msg
));
181 ui__error("Couldn't annotate %s: %s\n", sym
->name
, msg
);
185 symbol__calc_percent(sym
, evsel
);
187 if (perf_gtk__is_active_context(pgctx
)) {
188 window
= pgctx
->main_window
;
189 notebook
= pgctx
->notebook
;
195 signal(SIGSEGV
, perf_gtk__signal
);
196 signal(SIGFPE
, perf_gtk__signal
);
197 signal(SIGINT
, perf_gtk__signal
);
198 signal(SIGQUIT
, perf_gtk__signal
);
199 signal(SIGTERM
, perf_gtk__signal
);
201 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
202 gtk_window_set_title(GTK_WINDOW(window
), "perf annotate");
204 g_signal_connect(window
, "delete_event", gtk_main_quit
, NULL
);
206 pgctx
= perf_gtk__activate_context(window
);
210 vbox
= gtk_vbox_new(FALSE
, 0);
211 notebook
= gtk_notebook_new();
212 pgctx
->notebook
= notebook
;
214 gtk_box_pack_start(GTK_BOX(vbox
), notebook
, TRUE
, TRUE
, 0);
216 infobar
= perf_gtk__setup_info_bar();
218 gtk_box_pack_start(GTK_BOX(vbox
), infobar
,
222 statbar
= perf_gtk__setup_statusbar();
223 gtk_box_pack_start(GTK_BOX(vbox
), statbar
, FALSE
, FALSE
, 0);
225 gtk_container_add(GTK_CONTAINER(window
), vbox
);
228 scrolled_window
= gtk_scrolled_window_new(NULL
, NULL
);
229 tab_label
= gtk_label_new(sym
->name
);
231 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window
),
232 GTK_POLICY_AUTOMATIC
,
233 GTK_POLICY_AUTOMATIC
);
235 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
), scrolled_window
,
238 perf_gtk__annotate_symbol(scrolled_window
, ms
, evsel
, hbt
);
242 int hist_entry__gtk_annotate(struct hist_entry
*he
,
244 struct hist_browser_timer
*hbt
)
246 return symbol__gtk_annotate(&he
->ms
, evsel
, hbt
);
249 void perf_gtk__show_annotations(void)
253 if (!perf_gtk__is_active_context(pgctx
))
256 window
= pgctx
->main_window
;
257 gtk_widget_show_all(window
);
259 perf_gtk__resize_window(window
);
260 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
264 perf_gtk__deactivate_context(&pgctx
);