1
2#ifndef __PERF_ANNOTATE_H
3#define __PERF_ANNOTATE_H
4
5#include <stdbool.h>
6#include <stdint.h>
7#include <linux/types.h>
8#include "symbol.h"
9#include "hist.h"
10#include "sort.h"
11#include <linux/list.h>
12#include <linux/rbtree.h>
13#include <pthread.h>
14#include <asm/bug.h>
15
16struct ins_ops;
17
18struct ins {
19 const char *name;
20 struct ins_ops *ops;
21};
22
23struct ins_operands {
24 char *raw;
25 char *raw_comment;
26 struct {
27 char *raw;
28 char *name;
29 struct symbol *sym;
30 u64 addr;
31 s64 offset;
32 bool offset_avail;
33 bool outside;
34 } target;
35 union {
36 struct {
37 char *raw;
38 char *name;
39 u64 addr;
40 } source;
41 struct {
42 struct ins ins;
43 struct ins_operands *ops;
44 } locked;
45 };
46};
47
48struct arch;
49
50struct ins_ops {
51 void (*free)(struct ins_operands *ops);
52 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms);
53 int (*scnprintf)(struct ins *ins, char *bf, size_t size,
54 struct ins_operands *ops);
55};
56
57bool ins__is_jump(const struct ins *ins);
58bool ins__is_call(const struct ins *ins);
59bool ins__is_ret(const struct ins *ins);
60bool ins__is_lock(const struct ins *ins);
61int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
62bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
63
64#define ANNOTATION__IPC_WIDTH 6
65#define ANNOTATION__CYCLES_WIDTH 6
66#define ANNOTATION__MINMAX_CYCLES_WIDTH 19
67#define ANNOTATION__AVG_IPC_WIDTH 36
68
69struct annotation_options {
70 bool hide_src_code,
71 use_offset,
72 jump_arrows,
73 print_lines,
74 full_path,
75 show_linenr,
76 show_nr_jumps,
77 show_nr_samples,
78 show_total_period,
79 show_minmax_cycle,
80 show_asm_raw,
81 annotate_src;
82 u8 offset_level;
83 int min_pcnt;
84 int max_lines;
85 int context;
86 const char *objdump_path;
87 const char *disassembler_style;
88 unsigned int percent_type;
89};
90
91enum {
92 ANNOTATION__OFFSET_JUMP_TARGETS = 1,
93 ANNOTATION__OFFSET_CALL,
94 ANNOTATION__MAX_OFFSET_LEVEL,
95};
96
97#define ANNOTATION__MIN_OFFSET_LEVEL ANNOTATION__OFFSET_JUMP_TARGETS
98
99extern struct annotation_options annotation__default_options;
100
101struct annotation;
102
103struct sym_hist_entry {
104 u64 nr_samples;
105 u64 period;
106};
107
108enum {
109 PERCENT_HITS_LOCAL,
110 PERCENT_HITS_GLOBAL,
111 PERCENT_PERIOD_LOCAL,
112 PERCENT_PERIOD_GLOBAL,
113 PERCENT_MAX,
114};
115
116struct annotation_data {
117 double percent[PERCENT_MAX];
118 double percent_sum;
119 struct sym_hist_entry he;
120};
121
122struct annotation_line {
123 struct list_head node;
124 struct rb_node rb_node;
125 s64 offset;
126 char *line;
127 int line_nr;
128 int jump_sources;
129 float ipc;
130 u64 cycles;
131 u64 cycles_max;
132 u64 cycles_min;
133 size_t privsize;
134 char *path;
135 u32 idx;
136 int idx_asm;
137 int data_nr;
138 struct annotation_data data[0];
139};
140
141struct disasm_line {
142 struct ins ins;
143 struct ins_operands ops;
144
145
146 struct annotation_line al;
147};
148
149static inline double annotation_data__percent(struct annotation_data *data,
150 unsigned int which)
151{
152 return which < PERCENT_MAX ? data->percent[which] : -1;
153}
154
155static inline const char *percent_type_str(unsigned int type)
156{
157 static const char *str[PERCENT_MAX] = {
158 "local hits",
159 "global hits",
160 "local period",
161 "global period",
162 };
163
164 if (WARN_ON(type >= PERCENT_MAX))
165 return "N/A";
166
167 return str[type];
168}
169
170static inline struct disasm_line *disasm_line(struct annotation_line *al)
171{
172 return al ? container_of(al, struct disasm_line, al) : NULL;
173}
174
175
176
177
178
179static inline bool disasm_line__has_local_offset(const struct disasm_line *dl)
180{
181 return dl->ops.target.offset_avail && !dl->ops.target.outside;
182}
183
184
185
186
187
188bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym);
189
190void disasm_line__free(struct disasm_line *dl);
191struct annotation_line *
192annotation_line__next(struct annotation_line *pos, struct list_head *head);
193
194struct annotation_write_ops {
195 bool first_line, current_entry, change_color;
196 int width;
197 void *obj;
198 int (*set_color)(void *obj, int color);
199 void (*set_percent_color)(void *obj, double percent, bool current);
200 int (*set_jumps_percent_color)(void *obj, int nr, bool current);
201 void (*printf)(void *obj, const char *fmt, ...);
202 void (*write_graph)(void *obj, int graph);
203};
204
205void annotation_line__write(struct annotation_line *al, struct annotation *notes,
206 struct annotation_write_ops *ops,
207 struct annotation_options *opts);
208
209int __annotation__scnprintf_samples_period(struct annotation *notes,
210 char *bf, size_t size,
211 struct perf_evsel *evsel,
212 bool show_freq);
213
214int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
215size_t disasm__fprintf(struct list_head *head, FILE *fp);
216void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
217
218struct sym_hist {
219 u64 nr_samples;
220 u64 period;
221 struct sym_hist_entry addr[0];
222};
223
224struct cyc_hist {
225 u64 start;
226 u64 cycles;
227 u64 cycles_aggr;
228 u64 cycles_max;
229 u64 cycles_min;
230 u32 num;
231 u32 num_aggr;
232 u8 have_start;
233
234 u16 reset;
235};
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254struct annotated_source {
255 struct list_head source;
256 int nr_histograms;
257 size_t sizeof_sym_hist;
258 struct cyc_hist *cycles_hist;
259 struct sym_hist *histograms;
260};
261
262struct annotation {
263 pthread_mutex_t lock;
264 u64 max_coverage;
265 u64 start;
266 u64 hit_cycles;
267 u64 hit_insn;
268 unsigned int total_insn;
269 unsigned int cover_insn;
270 struct annotation_options *options;
271 struct annotation_line **offsets;
272 int nr_events;
273 int nr_jumps;
274 int max_jump_sources;
275 int nr_entries;
276 int nr_asm_entries;
277 u16 max_line_len;
278 struct {
279 u8 addr;
280 u8 jumps;
281 u8 target;
282 u8 min_addr;
283 u8 max_addr;
284 } widths;
285 bool have_cycles;
286 struct annotated_source *src;
287};
288
289static inline int annotation__cycles_width(struct annotation *notes)
290{
291 if (notes->have_cycles && notes->options->show_minmax_cycle)
292 return ANNOTATION__IPC_WIDTH + ANNOTATION__MINMAX_CYCLES_WIDTH;
293
294 return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
295}
296
297static inline int annotation__pcnt_width(struct annotation *notes)
298{
299 return (notes->options->show_total_period ? 12 : 7) * notes->nr_events;
300}
301
302static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes)
303{
304 return notes->options->hide_src_code && al->offset == -1;
305}
306
307void annotation__set_offsets(struct annotation *notes, s64 size);
308void annotation__compute_ipc(struct annotation *notes, size_t size);
309void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym);
310void annotation__update_column_widths(struct annotation *notes);
311void annotation__init_column_widths(struct annotation *notes, struct symbol *sym);
312
313static inline struct sym_hist *annotated_source__histogram(struct annotated_source *src, int idx)
314{
315 return ((void *)src->histograms) + (src->sizeof_sym_hist * idx);
316}
317
318static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
319{
320 return annotated_source__histogram(notes->src, idx);
321}
322
323static inline struct annotation *symbol__annotation(struct symbol *sym)
324{
325 return (void *)sym - symbol_conf.priv_size;
326}
327
328int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
329 struct perf_evsel *evsel);
330
331int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
332 struct addr_map_symbol *start,
333 unsigned cycles);
334
335int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
336 struct perf_evsel *evsel, u64 addr);
337
338struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
339void symbol__annotate_zero_histograms(struct symbol *sym);
340
341int symbol__annotate(struct symbol *sym, struct map *map,
342 struct perf_evsel *evsel, size_t privsize,
343 struct annotation_options *options,
344 struct arch **parch);
345int symbol__annotate2(struct symbol *sym, struct map *map,
346 struct perf_evsel *evsel,
347 struct annotation_options *options,
348 struct arch **parch);
349
350enum symbol_disassemble_errno {
351 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
352
353
354
355
356
357
358
359
360 __SYMBOL_ANNOTATE_ERRNO__START = -10000,
361
362 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START,
363
364 __SYMBOL_ANNOTATE_ERRNO__END,
365};
366
367int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
368 int errnum, char *buf, size_t buflen);
369
370int symbol__annotate_printf(struct symbol *sym, struct map *map,
371 struct perf_evsel *evsel,
372 struct annotation_options *options);
373void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
374void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
375void annotated_source__purge(struct annotated_source *as);
376
377int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
378 struct annotation_options *opts);
379
380bool ui__has_annotation(void);
381
382int symbol__tty_annotate(struct symbol *sym, struct map *map,
383 struct perf_evsel *evsel, struct annotation_options *opts);
384
385int symbol__tty_annotate2(struct symbol *sym, struct map *map,
386 struct perf_evsel *evsel, struct annotation_options *opts);
387
388#ifdef HAVE_SLANG_SUPPORT
389int symbol__tui_annotate(struct symbol *sym, struct map *map,
390 struct perf_evsel *evsel,
391 struct hist_browser_timer *hbt,
392 struct annotation_options *opts);
393#else
394static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
395 struct map *map __maybe_unused,
396 struct perf_evsel *evsel __maybe_unused,
397 struct hist_browser_timer *hbt __maybe_unused,
398 struct annotation_options *opts __maybe_unused)
399{
400 return 0;
401}
402#endif
403
404void annotation_config__init(void);
405
406int annotate_parse_percent_type(const struct option *opt, const char *_str,
407 int unset);
408#endif
409