0001
0002 #ifndef __PERF_ANNOTATE_H
0003 #define __PERF_ANNOTATE_H
0004
0005 #include <stdbool.h>
0006 #include <stdint.h>
0007 #include <stdio.h>
0008 #include <linux/types.h>
0009 #include <linux/list.h>
0010 #include <linux/rbtree.h>
0011 #include <pthread.h>
0012 #include <asm/bug.h>
0013 #include "symbol_conf.h"
0014 #include "spark.h"
0015
0016 struct hist_browser_timer;
0017 struct hist_entry;
0018 struct ins_ops;
0019 struct map;
0020 struct map_symbol;
0021 struct addr_map_symbol;
0022 struct option;
0023 struct perf_sample;
0024 struct evsel;
0025 struct symbol;
0026
0027 struct ins {
0028 const char *name;
0029 struct ins_ops *ops;
0030 };
0031
0032 struct ins_operands {
0033 char *raw;
0034 char *raw_comment;
0035 char *raw_func_start;
0036 struct {
0037 char *raw;
0038 char *name;
0039 struct symbol *sym;
0040 u64 addr;
0041 s64 offset;
0042 bool offset_avail;
0043 bool outside;
0044 } target;
0045 union {
0046 struct {
0047 char *raw;
0048 char *name;
0049 u64 addr;
0050 } source;
0051 struct {
0052 struct ins ins;
0053 struct ins_operands *ops;
0054 } locked;
0055 };
0056 };
0057
0058 struct arch;
0059
0060 struct ins_ops {
0061 void (*free)(struct ins_operands *ops);
0062 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms);
0063 int (*scnprintf)(struct ins *ins, char *bf, size_t size,
0064 struct ins_operands *ops, int max_ins_name);
0065 };
0066
0067 bool ins__is_jump(const struct ins *ins);
0068 bool ins__is_call(const struct ins *ins);
0069 bool ins__is_ret(const struct ins *ins);
0070 bool ins__is_lock(const struct ins *ins);
0071 int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops, int max_ins_name);
0072 bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
0073
0074 #define ANNOTATION__IPC_WIDTH 6
0075 #define ANNOTATION__CYCLES_WIDTH 6
0076 #define ANNOTATION__MINMAX_CYCLES_WIDTH 19
0077 #define ANNOTATION__AVG_IPC_WIDTH 36
0078 #define ANNOTATION_DUMMY_LEN 256
0079
0080 struct annotation_options {
0081 bool hide_src_code,
0082 use_offset,
0083 jump_arrows,
0084 print_lines,
0085 full_path,
0086 show_linenr,
0087 show_fileloc,
0088 show_nr_jumps,
0089 show_minmax_cycle,
0090 show_asm_raw,
0091 annotate_src;
0092 u8 offset_level;
0093 int min_pcnt;
0094 int max_lines;
0095 int context;
0096 const char *objdump_path;
0097 const char *disassembler_style;
0098 const char *prefix;
0099 const char *prefix_strip;
0100 unsigned int percent_type;
0101 };
0102
0103 enum {
0104 ANNOTATION__OFFSET_JUMP_TARGETS = 1,
0105 ANNOTATION__OFFSET_CALL,
0106 ANNOTATION__MAX_OFFSET_LEVEL,
0107 };
0108
0109 #define ANNOTATION__MIN_OFFSET_LEVEL ANNOTATION__OFFSET_JUMP_TARGETS
0110
0111 extern struct annotation_options annotation__default_options;
0112
0113 struct annotation;
0114
0115 struct sym_hist_entry {
0116 u64 nr_samples;
0117 u64 period;
0118 };
0119
0120 enum {
0121 PERCENT_HITS_LOCAL,
0122 PERCENT_HITS_GLOBAL,
0123 PERCENT_PERIOD_LOCAL,
0124 PERCENT_PERIOD_GLOBAL,
0125 PERCENT_MAX,
0126 };
0127
0128 struct annotation_data {
0129 double percent[PERCENT_MAX];
0130 double percent_sum;
0131 struct sym_hist_entry he;
0132 };
0133
0134 struct annotation_line {
0135 struct list_head node;
0136 struct rb_node rb_node;
0137 s64 offset;
0138 char *line;
0139 int line_nr;
0140 char *fileloc;
0141 int jump_sources;
0142 float ipc;
0143 u64 cycles;
0144 u64 cycles_max;
0145 u64 cycles_min;
0146 char *path;
0147 u32 idx;
0148 int idx_asm;
0149 int data_nr;
0150 struct annotation_data data[];
0151 };
0152
0153 struct disasm_line {
0154 struct ins ins;
0155 struct ins_operands ops;
0156
0157
0158 struct annotation_line al;
0159 };
0160
0161 static inline double annotation_data__percent(struct annotation_data *data,
0162 unsigned int which)
0163 {
0164 return which < PERCENT_MAX ? data->percent[which] : -1;
0165 }
0166
0167 static inline const char *percent_type_str(unsigned int type)
0168 {
0169 static const char *str[PERCENT_MAX] = {
0170 "local hits",
0171 "global hits",
0172 "local period",
0173 "global period",
0174 };
0175
0176 if (WARN_ON(type >= PERCENT_MAX))
0177 return "N/A";
0178
0179 return str[type];
0180 }
0181
0182 static inline struct disasm_line *disasm_line(struct annotation_line *al)
0183 {
0184 return al ? container_of(al, struct disasm_line, al) : NULL;
0185 }
0186
0187
0188
0189
0190
0191 static inline bool disasm_line__has_local_offset(const struct disasm_line *dl)
0192 {
0193 return dl->ops.target.offset_avail && !dl->ops.target.outside;
0194 }
0195
0196
0197
0198
0199
0200 bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym);
0201
0202 void disasm_line__free(struct disasm_line *dl);
0203 struct annotation_line *
0204 annotation_line__next(struct annotation_line *pos, struct list_head *head);
0205
0206 struct annotation_write_ops {
0207 bool first_line, current_entry, change_color;
0208 int width;
0209 void *obj;
0210 int (*set_color)(void *obj, int color);
0211 void (*set_percent_color)(void *obj, double percent, bool current);
0212 int (*set_jumps_percent_color)(void *obj, int nr, bool current);
0213 void (*printf)(void *obj, const char *fmt, ...);
0214 void (*write_graph)(void *obj, int graph);
0215 };
0216
0217 void annotation_line__write(struct annotation_line *al, struct annotation *notes,
0218 struct annotation_write_ops *ops,
0219 struct annotation_options *opts);
0220
0221 int __annotation__scnprintf_samples_period(struct annotation *notes,
0222 char *bf, size_t size,
0223 struct evsel *evsel,
0224 bool show_freq);
0225
0226 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name);
0227 size_t disasm__fprintf(struct list_head *head, FILE *fp);
0228 void symbol__calc_percent(struct symbol *sym, struct evsel *evsel);
0229
0230 struct sym_hist {
0231 u64 nr_samples;
0232 u64 period;
0233 struct sym_hist_entry addr[];
0234 };
0235
0236 struct cyc_hist {
0237 u64 start;
0238 u64 cycles;
0239 u64 cycles_aggr;
0240 u64 cycles_max;
0241 u64 cycles_min;
0242 s64 cycles_spark[NUM_SPARKS];
0243 u32 num;
0244 u32 num_aggr;
0245 u8 have_start;
0246
0247 u16 reset;
0248 };
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 struct annotated_source {
0268 struct list_head source;
0269 int nr_histograms;
0270 size_t sizeof_sym_hist;
0271 struct cyc_hist *cycles_hist;
0272 struct sym_hist *histograms;
0273 };
0274
0275 struct annotation {
0276 pthread_mutex_t lock;
0277 u64 max_coverage;
0278 u64 start;
0279 u64 hit_cycles;
0280 u64 hit_insn;
0281 unsigned int total_insn;
0282 unsigned int cover_insn;
0283 struct annotation_options *options;
0284 struct annotation_line **offsets;
0285 int nr_events;
0286 int max_jump_sources;
0287 int nr_entries;
0288 int nr_asm_entries;
0289 u16 max_line_len;
0290 struct {
0291 u8 addr;
0292 u8 jumps;
0293 u8 target;
0294 u8 min_addr;
0295 u8 max_addr;
0296 u8 max_ins_name;
0297 } widths;
0298 bool have_cycles;
0299 struct annotated_source *src;
0300 };
0301
0302 void annotation__init(struct annotation *notes);
0303 void annotation__exit(struct annotation *notes);
0304
0305 static inline int annotation__cycles_width(struct annotation *notes)
0306 {
0307 if (notes->have_cycles && notes->options->show_minmax_cycle)
0308 return ANNOTATION__IPC_WIDTH + ANNOTATION__MINMAX_CYCLES_WIDTH;
0309
0310 return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
0311 }
0312
0313 static inline int annotation__pcnt_width(struct annotation *notes)
0314 {
0315 return (symbol_conf.show_total_period ? 12 : 7) * notes->nr_events;
0316 }
0317
0318 static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes)
0319 {
0320 return notes->options->hide_src_code && al->offset == -1;
0321 }
0322
0323 void annotation__set_offsets(struct annotation *notes, s64 size);
0324 void annotation__compute_ipc(struct annotation *notes, size_t size);
0325 void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym);
0326 void annotation__update_column_widths(struct annotation *notes);
0327 void annotation__init_column_widths(struct annotation *notes, struct symbol *sym);
0328
0329 static inline struct sym_hist *annotated_source__histogram(struct annotated_source *src, int idx)
0330 {
0331 return ((void *)src->histograms) + (src->sizeof_sym_hist * idx);
0332 }
0333
0334 static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
0335 {
0336 return annotated_source__histogram(notes->src, idx);
0337 }
0338
0339 static inline struct annotation *symbol__annotation(struct symbol *sym)
0340 {
0341 return (void *)sym - symbol_conf.priv_size;
0342 }
0343
0344 int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
0345 struct evsel *evsel);
0346
0347 int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
0348 struct addr_map_symbol *start,
0349 unsigned cycles);
0350
0351 int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
0352 struct evsel *evsel, u64 addr);
0353
0354 struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
0355 void symbol__annotate_zero_histograms(struct symbol *sym);
0356
0357 int symbol__annotate(struct map_symbol *ms,
0358 struct evsel *evsel,
0359 struct annotation_options *options,
0360 struct arch **parch);
0361 int symbol__annotate2(struct map_symbol *ms,
0362 struct evsel *evsel,
0363 struct annotation_options *options,
0364 struct arch **parch);
0365
0366 enum symbol_disassemble_errno {
0367 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
0368
0369
0370
0371
0372
0373
0374
0375
0376 __SYMBOL_ANNOTATE_ERRNO__START = -10000,
0377
0378 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START,
0379 SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF,
0380 SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING,
0381 SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP,
0382 SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE,
0383 SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF,
0384
0385 __SYMBOL_ANNOTATE_ERRNO__END,
0386 };
0387
0388 int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen);
0389
0390 int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
0391 struct annotation_options *options);
0392 void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
0393 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
0394 void annotated_source__purge(struct annotated_source *as);
0395
0396 int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
0397 struct annotation_options *opts);
0398
0399 bool ui__has_annotation(void);
0400
0401 int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts);
0402
0403 int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel, struct annotation_options *opts);
0404
0405 #ifdef HAVE_SLANG_SUPPORT
0406 int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
0407 struct hist_browser_timer *hbt,
0408 struct annotation_options *opts);
0409 #else
0410 static inline int symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
0411 struct evsel *evsel __maybe_unused,
0412 struct hist_browser_timer *hbt __maybe_unused,
0413 struct annotation_options *opts __maybe_unused)
0414 {
0415 return 0;
0416 }
0417 #endif
0418
0419 void annotation_config__init(struct annotation_options *opt);
0420
0421 int annotate_parse_percent_type(const struct option *opt, const char *_str,
0422 int unset);
0423
0424 int annotate_check_args(struct annotation_options *args);
0425
0426 #endif