at v4.15-rc4 226 lines 6.0 kB view raw
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 15struct ins_ops; 16 17struct ins { 18 const char *name; 19 struct ins_ops *ops; 20}; 21 22struct 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 44struct arch; 45 46struct 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 53bool ins__is_jump(const struct ins *ins); 54bool ins__is_call(const struct ins *ins); 55bool ins__is_ret(const struct ins *ins); 56bool ins__is_lock(const struct ins *ins); 57int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 58bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2); 59 60struct annotation; 61 62struct 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 73static inline bool disasm_line__has_offset(const struct disasm_line *dl) 74{ 75 return dl->ops.target.offset_avail; 76} 77 78struct sym_hist_entry { 79 u64 nr_samples; 80 u64 period; 81}; 82 83void disasm_line__free(struct disasm_line *dl); 84struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos); 85int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 86size_t disasm__fprintf(struct list_head *head, FILE *fp); 87double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset, 88 s64 end, const char **path, struct sym_hist_entry *sample); 89 90struct sym_hist { 91 u64 nr_samples; 92 u64 period; 93 struct sym_hist_entry addr[0]; 94}; 95 96struct 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 107struct source_line_samples { 108 double percent; 109 double percent_sum; 110 u64 nr; 111}; 112 113struct 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 */ 133struct 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 142struct annotation { 143 pthread_mutex_t lock; 144 u64 max_coverage; 145 struct annotated_source *src; 146}; 147 148static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) 149{ 150 return (((void *)&notes->src->histograms) + 151 (notes->src->sizeof_sym_hist * idx)); 152} 153 154static inline struct annotation *symbol__annotation(struct symbol *sym) 155{ 156 return (void *)sym - symbol_conf.priv_size; 157} 158 159int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, 160 int evidx); 161 162int addr_map_symbol__account_cycles(struct addr_map_symbol *ams, 163 struct addr_map_symbol *start, 164 unsigned cycles); 165 166int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample, 167 int evidx, u64 addr); 168 169int symbol__alloc_hist(struct symbol *sym); 170void symbol__annotate_zero_histograms(struct symbol *sym); 171 172int symbol__disassemble(struct symbol *sym, struct map *map, 173 const char *arch_name, size_t privsize, 174 struct arch **parch, char *cpuid); 175 176enum 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 193int symbol__strerror_disassemble(struct symbol *sym, struct map *map, 194 int errnum, char *buf, size_t buflen); 195 196int 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); 199void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 200void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 201void disasm__purge(struct list_head *head); 202 203bool ui__has_annotation(void); 204 205int 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 210int symbol__tui_annotate(struct symbol *sym, struct map *map, 211 struct perf_evsel *evsel, 212 struct hist_browser_timer *hbt); 213#else 214static 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 224extern const char *disassembler_style; 225 226#endif /* __PERF_ANNOTATE_H */