1 /* SPDX-License-Identifier: GPL-2.0 */ 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 15 struct ins_ops; 16 17 struct ins { 18 const char *name; 19 struct ins_ops *ops; 20 }; 21 22 struct ins_operands { 23 char *raw; 24 struct { 25 char *raw; 26 char *name; 27 u64 addr; 28 s64 offset; 29 bool offset_avail; 30 } target; 31 union { 32 struct { 33 char *raw; 34 char *name; 35 u64 addr; 36 } source; 37 struct { 38 struct ins ins; 39 struct ins_operands *ops; 40 } locked; 41 }; 42 }; 43 44 struct arch; 45 46 struct ins_ops { 47 void (*free)(struct ins_operands *ops); 48 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map *map); 49 int (*scnprintf)(struct ins *ins, char *bf, size_t size, 50 struct ins_operands *ops); 51 }; 52 53 bool ins__is_jump(const struct ins *ins); 54 bool ins__is_call(const struct ins *ins); 55 bool ins__is_ret(const struct ins *ins); 56 bool ins__is_lock(const struct ins *ins); 57 int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 58 bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2); 59 60 struct annotation; 61 62 struct disasm_line { 63 struct list_head node; 64 s64 offset; 65 char *line; 66 struct ins ins; 67 int line_nr; 68 float ipc; 69 u64 cycles; 70 struct ins_operands ops; 71 }; 72 73 static inline bool disasm_line__has_offset(const struct disasm_line *dl) 74 { 75 return dl->ops.target.offset_avail; 76 } 77 78 struct sym_hist_entry { 79 u64 nr_samples; 80 u64 period; 81 }; 82 83 void disasm_line__free(struct disasm_line *dl); 84 struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos); 85 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 86 size_t disasm__fprintf(struct list_head *head, FILE *fp); 87 double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 88 s64 end, const char **path, struct sym_hist_entry *sample); 89 90 struct sym_hist { 91 u64 nr_samples; 92 u64 period; 93 struct sym_hist_entry addr[0]; 94 }; 95 96 struct cyc_hist { 97 u64 start; 98 u64 cycles; 99 u64 cycles_aggr; 100 u32 num; 101 u32 num_aggr; 102 u8 have_start; 103 /* 1 byte padding */ 104 u16 reset; 105 }; 106 107 struct source_line_samples { 108 double percent; 109 double percent_sum; 110 u64 nr; 111 }; 112 113 struct source_line { 114 struct rb_node node; 115 char *path; 116 int nr_pcnt; 117 struct source_line_samples samples[1]; 118 }; 119 120 /** struct annotated_source - symbols with hits have this attached as in sannotation 121 * 122 * @histogram: Array of addr hit histograms per event being monitored 123 * @lines: If 'print_lines' is specified, per source code line percentages 124 * @source: source parsed from a disassembler like objdump -dS 125 * @cyc_hist: Average cycles per basic block 126 * 127 * lines is allocated, percentages calculated and all sorted by percentage 128 * when the annotation is about to be presented, so the percentages are for 129 * one of the entries in the histogram array, i.e. for the event/counter being 130 * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate 131 * returns. 132 */ 133 struct annotated_source { 134 struct list_head source; 135 struct source_line *lines; 136 int nr_histograms; 137 size_t sizeof_sym_hist; 138 struct cyc_hist *cycles_hist; 139 struct sym_hist histograms[0]; 140 }; 141 142 struct annotation { 143 pthread_mutex_t lock; 144 u64 max_coverage; 145 struct annotated_source *src; 146 }; 147 148 static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) 149 { 150 return (((void *)¬es->src->histograms) + 151 (notes->src->sizeof_sym_hist * idx)); 152 } 153 154 static inline struct annotation *symbol__annotation(struct symbol *sym) 155 { 156 return (void *)sym - symbol_conf.priv_size; 157 } 158 159 int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, 160 int evidx); 161 162 int addr_map_symbol__account_cycles(struct addr_map_symbol *ams, 163 struct addr_map_symbol *start, 164 unsigned cycles); 165 166 int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, 167 int evidx, u64 addr); 168 169 int symbol__alloc_hist(struct symbol *sym); 170 void symbol__annotate_zero_histograms(struct symbol *sym); 171 172 int symbol__disassemble(struct symbol *sym, struct map *map, 173 const char *arch_name, size_t privsize, 174 struct arch **parch, char *cpuid); 175 176 enum symbol_disassemble_errno { 177 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, 178 179 /* 180 * Choose an arbitrary negative big number not to clash with standard 181 * errno since SUS requires the errno has distinct positive values. 182 * See 'Issue 6' in the link below. 183 * 184 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html 185 */ 186 __SYMBOL_ANNOTATE_ERRNO__START = -10000, 187 188 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START, 189 190 __SYMBOL_ANNOTATE_ERRNO__END, 191 }; 192 193 int symbol__strerror_disassemble(struct symbol *sym, struct map *map, 194 int errnum, char *buf, size_t buflen); 195 196 int symbol__annotate_printf(struct symbol *sym, struct map *map, 197 struct perf_evsel *evsel, bool full_paths, 198 int min_pcnt, int max_lines, int context); 199 void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 200 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 201 void disasm__purge(struct list_head *head); 202 203 bool ui__has_annotation(void); 204 205 int symbol__tty_annotate(struct symbol *sym, struct map *map, 206 struct perf_evsel *evsel, bool print_lines, 207 bool full_paths, int min_pcnt, int max_lines); 208 209 #ifdef HAVE_SLANG_SUPPORT 210 int symbol__tui_annotate(struct symbol *sym, struct map *map, 211 struct perf_evsel *evsel, 212 struct hist_browser_timer *hbt); 213 #else 214 static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, 215 struct map *map __maybe_unused, 216 struct perf_evsel *evsel __maybe_unused, 217 struct hist_browser_timer *hbt 218 __maybe_unused) 219 { 220 return 0; 221 } 222 #endif 223 224 extern const char *disassembler_style; 225 226 #endif /* __PERF_ANNOTATE_H */ 227