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