xref: /linux/tools/perf/util/annotate-data.h (revision d261f9ebcf424535fe04e720a1cfa023be409f52)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _PERF_ANNOTATE_DATA_H
3 #define _PERF_ANNOTATE_DATA_H
4 
5 #include <errno.h>
6 #include <linux/compiler.h>
7 #include <linux/rbtree.h>
8 #include <linux/types.h>
9 #include "dwarf-regs.h"
10 #include "annotate.h"
11 
12 #ifdef HAVE_DWARF_SUPPORT
13 #include "debuginfo.h"
14 #endif
15 
16 struct annotated_op_loc;
17 struct debuginfo;
18 struct evsel;
19 struct hist_browser_timer;
20 struct hist_entry;
21 struct map_symbol;
22 struct thread;
23 
24 #define pr_debug_dtp(fmt, ...)					\
25 do {								\
26 	if (debug_type_profile)					\
27 		pr_info(fmt, ##__VA_ARGS__);			\
28 	else							\
29 		pr_debug3(fmt, ##__VA_ARGS__);			\
30 } while (0)
31 
32 enum type_state_kind {
33 	TSR_KIND_INVALID = 0,
34 	TSR_KIND_TYPE,
35 	TSR_KIND_PERCPU_BASE,
36 	TSR_KIND_CONST,
37 	TSR_KIND_POINTER,
38 	TSR_KIND_CANARY,
39 };
40 
41 /**
42  * struct annotated_member - Type of member field
43  * @node: List entry in the parent list
44  * @children: List head for child nodes
45  * @type_name: Name of the member type
46  * @var_name: Name of the member variable
47  * @offset: Offset from the outer data type
48  * @size: Size of the member field
49  *
50  * This represents a member type in a data type.
51  */
52 struct annotated_member {
53 	struct list_head node;
54 	struct list_head children;
55 	char *type_name;
56 	char *var_name;
57 	int offset;
58 	int size;
59 };
60 
61 /**
62  * struct type_hist_entry - Histogram entry per offset
63  * @nr_samples: Number of samples
64  * @period: Count of event
65  */
66 struct type_hist_entry {
67 	int nr_samples;
68 	u64 period;
69 };
70 
71 /**
72  * struct type_hist - Type histogram for each event
73  * @nr_samples: Total number of samples in this data type
74  * @period: Total count of the event in this data type
75  * @offset: Array of histogram entry
76  */
77 struct type_hist {
78 	u64			nr_samples;
79 	u64			period;
80 	struct type_hist_entry	addr[];
81 };
82 
83 /**
84  * struct annotated_data_type - Data type to profile
85  * @node: RB-tree node for dso->type_tree
86  * @self: Actual type information
87  * @nr_histogram: Number of histogram entries
88  * @histograms: An array of pointers to histograms
89  *
90  * This represents a data type accessed by samples in the profile data.
91  */
92 struct annotated_data_type {
93 	struct rb_node node;
94 	struct annotated_member self;
95 	int nr_histograms;
96 	struct type_hist **histograms;
97 };
98 
99 extern struct annotated_data_type unknown_type;
100 extern struct annotated_data_type stackop_type;
101 extern struct annotated_data_type canary_type;
102 
103 /**
104  * struct data_loc_info - Data location information
105  * @arch: CPU architecture info
106  * @thread: Thread info
107  * @ms: Map and Symbol info
108  * @ip: Instruction address
109  * @var_addr: Data address (for global variables)
110  * @cpumode: CPU execution mode
111  * @op: Instruction operand location (regs and offset)
112  * @di: Debug info
113  * @fbreg: Frame base register
114  * @fb_cfa: Whether the frame needs to check CFA
115  * @type_offset: Final offset in the type
116  */
117 struct data_loc_info {
118 	/* These are input field, should be filled by caller */
119 	struct arch *arch;
120 	struct thread *thread;
121 	struct map_symbol *ms;
122 	u64 ip;
123 	u64 var_addr;
124 	u8 cpumode;
125 	struct annotated_op_loc *op;
126 
127 	/* These are used internally */
128 	struct debuginfo *di;
129 	int fbreg;
130 	bool fb_cfa;
131 
132 	/* This is for the result */
133 	int type_offset;
134 };
135 
136 /**
137  * struct annotated_data_stat - Debug statistics
138  * @total: Total number of entry
139  * @no_sym: No symbol or map found
140  * @no_insn: Failed to get disasm line
141  * @no_insn_ops: The instruction has no operands
142  * @no_mem_ops: The instruction has no memory operands
143  * @no_reg: Failed to extract a register from the operand
144  * @no_dbginfo: The binary has no debug information
145  * @no_cuinfo: Failed to find a compile_unit
146  * @no_var: Failed to find a matching variable
147  * @no_typeinfo: Failed to get a type info for the variable
148  * @invalid_size: Failed to get a size info of the type
149  * @bad_offset: The access offset is out of the type
150  */
151 struct annotated_data_stat {
152 	int total;
153 	int no_sym;
154 	int no_insn;
155 	int no_insn_ops;
156 	int no_mem_ops;
157 	int no_reg;
158 	int no_dbginfo;
159 	int no_cuinfo;
160 	int no_var;
161 	int no_typeinfo;
162 	int invalid_size;
163 	int bad_offset;
164 	int insn_track;
165 };
166 extern struct annotated_data_stat ann_data_stat;
167 
168 #ifdef HAVE_DWARF_SUPPORT
169 /*
170  * Type information in a register, valid when @ok is true.
171  * The @caller_saved registers are invalidated after a function call.
172  */
173 struct type_state_reg {
174 	Dwarf_Die type;
175 	u32 imm_value;
176 	bool ok;
177 	bool caller_saved;
178 	u8 kind;
179 };
180 
181 /* Type information in a stack location, dynamically allocated */
182 struct type_state_stack {
183 	struct list_head list;
184 	Dwarf_Die type;
185 	int offset;
186 	int size;
187 	bool compound;
188 	u8 kind;
189 };
190 
191 /* FIXME: This should be arch-dependent */
192 #ifdef __powerpc__
193 #define TYPE_STATE_MAX_REGS  32
194 #else
195 #define TYPE_STATE_MAX_REGS  16
196 #endif
197 
198 /*
199  * State table to maintain type info in each register and stack location.
200  * It'll be updated when new variable is allocated or type info is moved
201  * to a new location (register or stack).  As it'd be used with the
202  * shortest path of basic blocks, it only maintains a single table.
203  */
204 struct type_state {
205 	/* state of general purpose registers */
206 	struct type_state_reg regs[TYPE_STATE_MAX_REGS];
207 	/* state of stack location */
208 	struct list_head stack_vars;
209 	/* return value register */
210 	int ret_reg;
211 	/* stack pointer register */
212 	int stack_reg;
213 };
214 
215 /* Returns data type at the location (ip, reg, offset) */
216 struct annotated_data_type *find_data_type(struct data_loc_info *dloc);
217 
218 /* Update type access histogram at the given offset */
219 int annotated_data_type__update_samples(struct annotated_data_type *adt,
220 					struct evsel *evsel, int offset,
221 					int nr_samples, u64 period);
222 
223 /* Release all data type information in the tree */
224 void annotated_data_type__tree_delete(struct rb_root *root);
225 
226 /* Release all global variable information in the tree */
227 void global_var_type__tree_delete(struct rb_root *root);
228 
229 int hist_entry__annotate_data_tty(struct hist_entry *he, struct evsel *evsel);
230 
231 bool has_reg_type(struct type_state *state, int reg);
232 struct type_state_stack *findnew_stack_state(struct type_state *state,
233 						int offset, u8 kind,
234 						Dwarf_Die *type_die);
235 void set_stack_state(struct type_state_stack *stack, int offset, u8 kind,
236 				Dwarf_Die *type_die);
237 struct type_state_stack *find_stack_state(struct type_state *state,
238 						int offset);
239 bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc,
240 				u64 ip, u64 var_addr, int *var_offset,
241 				Dwarf_Die *type_die);
242 bool get_global_var_info(struct data_loc_info *dloc, u64 addr,
243 				const char **var_name, int *var_offset);
244 void pr_debug_type_name(Dwarf_Die *die, enum type_state_kind kind);
245 
246 #else /* HAVE_DWARF_SUPPORT */
247 
248 static inline struct annotated_data_type *
249 find_data_type(struct data_loc_info *dloc __maybe_unused)
250 {
251 	return NULL;
252 }
253 
254 static inline int
255 annotated_data_type__update_samples(struct annotated_data_type *adt __maybe_unused,
256 				    struct evsel *evsel __maybe_unused,
257 				    int offset __maybe_unused,
258 				    int nr_samples __maybe_unused,
259 				    u64 period __maybe_unused)
260 {
261 	return -1;
262 }
263 
264 static inline void annotated_data_type__tree_delete(struct rb_root *root __maybe_unused)
265 {
266 }
267 
268 static inline void global_var_type__tree_delete(struct rb_root *root __maybe_unused)
269 {
270 }
271 
272 static inline int hist_entry__annotate_data_tty(struct hist_entry *he __maybe_unused,
273 						struct evsel *evsel __maybe_unused)
274 {
275 	return -1;
276 }
277 
278 #endif /* HAVE_DWARF_SUPPORT */
279 
280 #ifdef HAVE_SLANG_SUPPORT
281 int hist_entry__annotate_data_tui(struct hist_entry *he, struct evsel *evsel,
282 				  struct hist_browser_timer *hbt);
283 #else
284 static inline int hist_entry__annotate_data_tui(struct hist_entry *he __maybe_unused,
285 						struct evsel *evsel __maybe_unused,
286 						struct hist_browser_timer *hbt __maybe_unused)
287 {
288 	return -1;
289 }
290 #endif /* HAVE_SLANG_SUPPORT */
291 
292 #endif /* _PERF_ANNOTATE_DATA_H */
293