xref: /linux/tools/perf/util/annotate.h (revision c06310fd6b1c98f27f51a81637311ad560c614e9)
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 <stdio.h>
8  #include <linux/types.h>
9  #include <linux/list.h>
10  #include <linux/rbtree.h>
11  #include <asm/bug.h>
12  #include "symbol_conf.h"
13  #include "mutex.h"
14  #include "spark.h"
15  #include "hashmap.h"
16  #include "disasm.h"
17  #include "branch.h"
18  #include "evsel.h"
19  
20  struct hist_browser_timer;
21  struct hist_entry;
22  struct map;
23  struct map_symbol;
24  struct addr_map_symbol;
25  struct option;
26  struct perf_sample;
27  struct symbol;
28  struct annotated_data_type;
29  
30  #define ANNOTATION__IPC_WIDTH 6
31  #define ANNOTATION__CYCLES_WIDTH 6
32  #define ANNOTATION__MINMAX_CYCLES_WIDTH 19
33  #define ANNOTATION__AVG_IPC_WIDTH 36
34  #define ANNOTATION__BR_CNTR_WIDTH 30
35  #define ANNOTATION_DUMMY_LEN	256
36  
37  enum perf_disassembler {
38  	PERF_DISASM_UNKNOWN = 0,
39  	PERF_DISASM_LLVM,
40  	PERF_DISASM_CAPSTONE,
41  	PERF_DISASM_OBJDUMP,
42  };
43  #define MAX_DISASSEMBLERS (PERF_DISASM_OBJDUMP + 1)
44  
45  struct annotation_options {
46  	bool hide_src_code,
47  	     use_offset,
48  	     jump_arrows,
49  	     print_lines,
50  	     full_path,
51  	     show_linenr,
52  	     show_fileloc,
53  	     show_nr_jumps,
54  	     show_minmax_cycle,
55  	     show_asm_raw,
56  	     show_br_cntr,
57  	     annotate_src,
58  	     full_addr;
59  	u8   offset_level;
60  	u8   disassemblers[MAX_DISASSEMBLERS];
61  	int  min_pcnt;
62  	int  max_lines;
63  	int  context;
64  	char *objdump_path;
65  	char *disassembler_style;
66  	const char *prefix;
67  	const char *prefix_strip;
68  	unsigned int percent_type;
69  };
70  
71  extern struct annotation_options annotate_opts;
72  
73  enum {
74  	ANNOTATION__OFFSET_JUMP_TARGETS = 1,
75  	ANNOTATION__OFFSET_CALL,
76  	ANNOTATION__MAX_OFFSET_LEVEL,
77  };
78  
79  #define ANNOTATION__MIN_OFFSET_LEVEL ANNOTATION__OFFSET_JUMP_TARGETS
80  
81  struct annotation;
82  
83  struct sym_hist_entry {
84  	u64		nr_samples;
85  	u64		period;
86  };
87  
88  enum {
89  	PERCENT_HITS_LOCAL,
90  	PERCENT_HITS_GLOBAL,
91  	PERCENT_PERIOD_LOCAL,
92  	PERCENT_PERIOD_GLOBAL,
93  	PERCENT_MAX,
94  };
95  
96  struct annotation_data {
97  	double			 percent[PERCENT_MAX];
98  	double			 percent_sum;
99  	struct sym_hist_entry	 he;
100  };
101  
102  struct cycles_info {
103  	float			 ipc;
104  	u64			 avg;
105  	u64			 max;
106  	u64			 min;
107  };
108  
109  struct annotation_line {
110  	struct list_head	 node;
111  	struct rb_node		 rb_node;
112  	s64			 offset;
113  	char			*line;
114  	int			 line_nr;
115  	char			*fileloc;
116  	char			*path;
117  	struct cycles_info	*cycles;
118  	int			 num_aggr;
119  	int			 br_cntr_nr;
120  	u64			*br_cntr;
121  	struct evsel		*evsel;
122  	int			 jump_sources;
123  	u32			 idx;
124  	int			 idx_asm;
125  	int			 data_nr;
126  	struct annotation_data	 data[];
127  };
128  
129  struct disasm_line {
130  	struct ins		 ins;
131  	struct ins_operands	 ops;
132  	union {
133  		u8 bytes[4];
134  		u32 raw_insn;
135  	} raw;
136  	/* This needs to be at the end. */
137  	struct annotation_line	 al;
138  };
139  
140  extern const char * const perf_disassembler__strs[];
141  
142  void annotation_line__add(struct annotation_line *al, struct list_head *head);
143  
annotation_data__percent(struct annotation_data * data,unsigned int which)144  static inline double annotation_data__percent(struct annotation_data *data,
145  					      unsigned int which)
146  {
147  	return which < PERCENT_MAX ? data->percent[which] : -1;
148  }
149  
percent_type_str(unsigned int type)150  static inline const char *percent_type_str(unsigned int type)
151  {
152  	static const char *str[PERCENT_MAX] = {
153  		"local hits",
154  		"global hits",
155  		"local period",
156  		"global period",
157  	};
158  
159  	if (WARN_ON(type >= PERCENT_MAX))
160  		return "N/A";
161  
162  	return str[type];
163  }
164  
disasm_line(struct annotation_line * al)165  static inline struct disasm_line *disasm_line(struct annotation_line *al)
166  {
167  	return al ? container_of(al, struct disasm_line, al) : NULL;
168  }
169  
170  /*
171   * Is this offset in the same function as the line it is used?
172   * asm functions jump to other functions, for instance.
173   */
disasm_line__has_local_offset(const struct disasm_line * dl)174  static inline bool disasm_line__has_local_offset(const struct disasm_line *dl)
175  {
176  	return dl->ops.target.offset_avail && !dl->ops.target.outside;
177  }
178  
179  /*
180   * Can we draw an arrow from the jump to its target, for instance? I.e.
181   * is the jump and its target in the same function?
182   */
183  bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym);
184  
185  struct annotation_line *
186  annotation_line__next(struct annotation_line *pos, struct list_head *head);
187  
188  struct annotation_write_ops {
189  	bool first_line, current_entry, change_color;
190  	int  width;
191  	void *obj;
192  	int  (*set_color)(void *obj, int color);
193  	void (*set_percent_color)(void *obj, double percent, bool current);
194  	int  (*set_jumps_percent_color)(void *obj, int nr, bool current);
195  	void (*printf)(void *obj, const char *fmt, ...);
196  	void (*write_graph)(void *obj, int graph);
197  };
198  
199  void annotation_line__write(struct annotation_line *al, struct annotation *notes,
200  			    struct annotation_write_ops *ops);
201  
202  int __annotation__scnprintf_samples_period(struct annotation *notes,
203  					   char *bf, size_t size,
204  					   struct evsel *evsel,
205  					   bool show_freq);
206  
207  size_t disasm__fprintf(struct list_head *head, FILE *fp);
208  void symbol__calc_percent(struct symbol *sym, struct evsel *evsel);
209  
210  /**
211   * struct sym_hist - symbol histogram information for an event
212   *
213   * @nr_samples: Total number of samples.
214   * @period: Sum of sample periods.
215   */
216  struct sym_hist {
217  	u64		      nr_samples;
218  	u64		      period;
219  };
220  
221  /**
222   * struct cyc_hist - (CPU) cycle histogram for a basic block
223   *
224   * @start: Start address of current block (if known).
225   * @cycles: Sum of cycles for the longest basic block.
226   * @cycles_aggr: Total cycles for this address.
227   * @cycles_max: Max cycles for this address.
228   * @cycles_min: Min cycles for this address.
229   * @cycles_spark: History of cycles for the longest basic block.
230   * @num: Number of samples for the longest basic block.
231   * @num_aggr: Total number of samples for this address.
232   * @have_start: Whether the current branch info has a start address.
233   * @reset: Number of resets due to a different start address.
234   *
235   * If sample has branch_stack and cycles info, it can construct basic blocks
236   * between two adjacent branches.  It'd have start and end addresses but
237   * sometimes the start address may not be available.  So the cycles are
238   * accounted at the end address.  If multiple basic blocks end at the same
239   * address, it will take the longest one.
240   *
241   * The @start, @cycles, @cycles_spark and @num fields are used for the longest
242   * block only.  Other fields are used for all cases.
243   *
244   * See __symbol__account_cycles().
245   */
246  struct cyc_hist {
247  	u64	start;
248  	u64	cycles;
249  	u64	cycles_aggr;
250  	u64	cycles_max;
251  	u64	cycles_min;
252  	s64	cycles_spark[NUM_SPARKS];
253  	u32	num;
254  	u32	num_aggr;
255  	u8	have_start;
256  	/* 1 byte padding */
257  	u16	reset;
258  };
259  
260  /**
261   * struct annotated_source - symbols with hits have this attached as in annotation
262   *
263   * @source: List head for annotated_line (embeded in disasm_line).
264   * @histograms: Array of symbol histograms per event to maintain the total number
265   * 		of samples and period.
266   * @nr_histograms: This may not be the same as evsel->evlist->core.nr_entries if
267   * 		  we have more than a group in a evlist, where we will want
268   * 		  to see each group separately, that is why symbol__annotate2()
269   * 		  sets src->nr_histograms to evsel->nr_members.
270   * @samples: Hash map of sym_hist_entry.  Keyed by event index and offset in symbol.
271   * @nr_events: Number of events in the current output.
272   * @nr_entries: Number of annotated_line in the source list.
273   * @nr_asm_entries: Number of annotated_line with actual asm instruction in the
274   * 		    source list.
275   * @max_jump_sources: Maximum number of jump instructions targeting to the same
276   * 		      instruction.
277   * @widths: Precalculated width of each column in the TUI output.
278   *
279   * disasm_lines are allocated, percentages calculated and all sorted by percentage
280   * when the annotation is about to be presented, so the percentages are for
281   * one of the entries in the histogram array, i.e. for the event/counter being
282   * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate
283   * returns.
284   */
285  struct annotated_source {
286  	struct list_head	source;
287  	struct sym_hist		*histograms;
288  	struct hashmap	   	*samples;
289  	int    			nr_histograms;
290  	int    			nr_events;
291  	int			nr_entries;
292  	int			nr_asm_entries;
293  	int			max_jump_sources;
294  	u64			start;
295  	struct {
296  		u8		addr;
297  		u8		jumps;
298  		u8		target;
299  		u8		min_addr;
300  		u8		max_addr;
301  		u8		max_ins_name;
302  		u16		max_line_len;
303  	} widths;
304  };
305  
306  struct annotation_line *annotated_source__get_line(struct annotated_source *src,
307  						   s64 offset);
308  
309  /* A branch counter once saturated */
310  #define ANNOTATION__BR_CNTR_SATURATED_FLAG	(1ULL << 63)
311  
312  /**
313   * struct annotated_branch - basic block and IPC information for a symbol.
314   *
315   * @hit_cycles: Total executed cycles.
316   * @hit_insn: Total number of instructions executed.
317   * @total_insn: Number of instructions in the function.
318   * @cover_insn: Number of distinct, actually executed instructions.
319   * @cycles_hist: Array of cyc_hist for each instruction.
320   * @max_coverage: Maximum number of covered basic block (used for block-range).
321   * @br_cntr: Array of the occurrences of events (branch counters) during a block.
322   *
323   * This struct is used by two different codes when the sample has branch stack
324   * and cycles information.  annotation__compute_ipc() calculates average IPC
325   * using @hit_insn / @hit_cycles.  The actual coverage can be calculated using
326   * @cover_insn / @total_insn.  The @cycles_hist can give IPC for each (longest)
327   * basic block ends at the given address.
328   * process_basic_block() calculates coverage of instructions (or basic blocks)
329   * in the function.
330   */
331  struct annotated_branch {
332  	u64			hit_cycles;
333  	u64			hit_insn;
334  	unsigned int		total_insn;
335  	unsigned int		cover_insn;
336  	struct cyc_hist		*cycles_hist;
337  	u64			max_coverage;
338  	u64			*br_cntr;
339  };
340  
341  struct LOCKABLE annotation {
342  	struct annotated_source *src;
343  	struct annotated_branch *branch;
344  };
345  
annotation__init(struct annotation * notes __maybe_unused)346  static inline void annotation__init(struct annotation *notes __maybe_unused)
347  {
348  }
349  void annotation__exit(struct annotation *notes);
350  
351  void annotation__lock(struct annotation *notes) EXCLUSIVE_LOCK_FUNCTION(*notes);
352  void annotation__unlock(struct annotation *notes) UNLOCK_FUNCTION(*notes);
353  bool annotation__trylock(struct annotation *notes) EXCLUSIVE_TRYLOCK_FUNCTION(true, *notes);
354  
annotation__cycles_width(struct annotation * notes)355  static inline int annotation__cycles_width(struct annotation *notes)
356  {
357  	if (notes->branch && annotate_opts.show_minmax_cycle)
358  		return ANNOTATION__IPC_WIDTH + ANNOTATION__MINMAX_CYCLES_WIDTH;
359  
360  	return notes->branch ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
361  }
362  
annotation__pcnt_width(struct annotation * notes)363  static inline int annotation__pcnt_width(struct annotation *notes)
364  {
365  	return (symbol_conf.show_total_period ? 12 : 8) * notes->src->nr_events;
366  }
367  
annotation_line__filter(struct annotation_line * al)368  static inline bool annotation_line__filter(struct annotation_line *al)
369  {
370  	return annotate_opts.hide_src_code && al->offset == -1;
371  }
372  
annotation__br_cntr_width(void)373  static inline u8 annotation__br_cntr_width(void)
374  {
375  	return annotate_opts.show_br_cntr ? ANNOTATION__BR_CNTR_WIDTH : 0;
376  }
377  
378  void annotation__update_column_widths(struct annotation *notes);
379  void annotation__toggle_full_addr(struct annotation *notes, struct map_symbol *ms);
380  
annotated_source__histogram(struct annotated_source * src,const struct evsel * evsel)381  static inline struct sym_hist *annotated_source__histogram(struct annotated_source *src,
382  							   const struct evsel *evsel)
383  {
384  	return &src->histograms[evsel->core.idx];
385  }
386  
annotation__histogram(struct annotation * notes,const struct evsel * evsel)387  static inline struct sym_hist *annotation__histogram(struct annotation *notes,
388  						     const struct evsel *evsel)
389  {
390  	return annotated_source__histogram(notes->src, evsel);
391  }
392  
393  static inline struct sym_hist_entry *
annotated_source__hist_entry(struct annotated_source * src,const struct evsel * evsel,u64 offset)394  annotated_source__hist_entry(struct annotated_source *src, const struct evsel *evsel, u64 offset)
395  {
396  	struct sym_hist_entry *entry;
397  	long key = offset << 16 | evsel->core.idx;
398  
399  	if (!hashmap__find(src->samples, key, &entry))
400  		return NULL;
401  	return entry;
402  }
403  
symbol__annotation(struct symbol * sym)404  static inline struct annotation *symbol__annotation(struct symbol *sym)
405  {
406  	return (void *)sym - symbol_conf.priv_size;
407  }
408  
409  int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
410  				 struct evsel *evsel);
411  
412  struct annotated_branch *annotation__get_branch(struct annotation *notes);
413  
414  int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
415  				    struct addr_map_symbol *start,
416  				    unsigned cycles,
417  				    struct evsel *evsel,
418  				    u64 br_cntr);
419  
420  int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
421  				 struct evsel *evsel, u64 addr);
422  
423  struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
424  void symbol__annotate_zero_histograms(struct symbol *sym);
425  
426  int symbol__annotate(struct map_symbol *ms,
427  		     struct evsel *evsel,
428  		     struct arch **parch);
429  int symbol__annotate2(struct map_symbol *ms,
430  		      struct evsel *evsel,
431  		      struct arch **parch);
432  
433  enum symbol_disassemble_errno {
434  	SYMBOL_ANNOTATE_ERRNO__SUCCESS		= 0,
435  
436  	/*
437  	 * Choose an arbitrary negative big number not to clash with standard
438  	 * errno since SUS requires the errno has distinct positive values.
439  	 * See 'Issue 6' in the link below.
440  	 *
441  	 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
442  	 */
443  	__SYMBOL_ANNOTATE_ERRNO__START		= -10000,
444  
445  	SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX	= __SYMBOL_ANNOTATE_ERRNO__START,
446  	SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF,
447  	SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING,
448  	SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP,
449  	SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE,
450  	SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF,
451  	SYMBOL_ANNOTATE_ERRNO__COULDNT_DETERMINE_FILE_TYPE,
452  
453  	__SYMBOL_ANNOTATE_ERRNO__END,
454  };
455  
456  int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen);
457  
458  int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel);
459  void symbol__annotate_zero_histogram(struct symbol *sym, struct evsel *evsel);
460  void symbol__annotate_decay_histogram(struct symbol *sym, struct evsel *evsel);
461  void annotated_source__purge(struct annotated_source *as);
462  
463  int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel);
464  
465  bool ui__has_annotation(void);
466  
467  int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel);
468  
469  int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel);
470  
471  #ifdef HAVE_SLANG_SUPPORT
472  int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
473  			 struct hist_browser_timer *hbt);
474  #else
symbol__tui_annotate(struct map_symbol * ms __maybe_unused,struct evsel * evsel __maybe_unused,struct hist_browser_timer * hbt __maybe_unused)475  static inline int symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
476  				struct evsel *evsel  __maybe_unused,
477  				struct hist_browser_timer *hbt __maybe_unused)
478  {
479  	return 0;
480  }
481  #endif
482  
483  void annotation_options__init(void);
484  void annotation_options__exit(void);
485  
486  void annotation_config__init(void);
487  
488  int annotate_parse_percent_type(const struct option *opt, const char *_str,
489  				int unset);
490  
491  int annotate_check_args(void);
492  
493  /**
494   * struct annotated_op_loc - Location info of instruction operand
495   * @reg1: First register in the operand
496   * @reg2: Second register in the operand
497   * @offset: Memory access offset in the operand
498   * @segment: Segment selector register
499   * @mem_ref: Whether the operand accesses memory
500   * @multi_regs: Whether the second register is used
501   * @imm: Whether the operand is an immediate value (in offset)
502   */
503  struct annotated_op_loc {
504  	int reg1;
505  	int reg2;
506  	int offset;
507  	u8 segment;
508  	bool mem_ref;
509  	bool multi_regs;
510  	bool imm;
511  };
512  
513  enum annotated_insn_ops {
514  	INSN_OP_SOURCE = 0,
515  	INSN_OP_TARGET = 1,
516  
517  	INSN_OP_MAX,
518  };
519  
520  enum annotated_x86_segment {
521  	INSN_SEG_NONE = 0,
522  
523  	INSN_SEG_X86_CS,
524  	INSN_SEG_X86_DS,
525  	INSN_SEG_X86_ES,
526  	INSN_SEG_X86_FS,
527  	INSN_SEG_X86_GS,
528  	INSN_SEG_X86_SS,
529  };
530  
531  /**
532   * struct annotated_insn_loc - Location info of instruction
533   * @ops: Array of location info for source and target operands
534   */
535  struct annotated_insn_loc {
536  	struct annotated_op_loc ops[INSN_OP_MAX];
537  };
538  
539  #define for_each_insn_op_loc(insn_loc, i, op_loc)			\
540  	for (i = INSN_OP_SOURCE, op_loc = &(insn_loc)->ops[i];		\
541  	     i < INSN_OP_MAX;						\
542  	     i++, op_loc++)
543  
544  /* Get detailed location info in the instruction */
545  int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl,
546  			       struct annotated_insn_loc *loc);
547  
548  /* Returns a data type from the sample instruction (if any) */
549  struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he);
550  
551  struct annotated_item_stat {
552  	struct list_head list;
553  	char *name;
554  	int good;
555  	int bad;
556  };
557  extern struct list_head ann_insn_stat;
558  
559  /* Calculate PC-relative address */
560  u64 annotate_calc_pcrel(struct map_symbol *ms, u64 ip, int offset,
561  			struct disasm_line *dl);
562  
563  /**
564   * struct annotated_basic_block - Basic block of instructions
565   * @list: List node
566   * @begin: start instruction in the block
567   * @end: end instruction in the block
568   */
569  struct annotated_basic_block {
570  	struct list_head list;
571  	struct disasm_line *begin;
572  	struct disasm_line *end;
573  };
574  
575  /* Get a list of basic blocks from src to dst addresses */
576  int annotate_get_basic_blocks(struct symbol *sym, s64 src, s64 dst,
577  			      struct list_head *head);
578  
579  void debuginfo_cache__delete(void);
580  
581  int annotation_br_cntr_entry(char **str, int br_cntr_nr, u64 *br_cntr,
582  			     int num_aggr, struct evsel *evsel);
583  int annotation_br_cntr_abbr_list(char **str, struct evsel *evsel, bool header);
584  #endif	/* __PERF_ANNOTATE_H */
585