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 struct debuginfo *di; 127 128 /* These are used internally */ 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 u8 copied_from; 180 }; 181 182 /* Type information in a stack location, dynamically allocated */ 183 struct type_state_stack { 184 struct list_head list; 185 Dwarf_Die type; 186 int offset; 187 int size; 188 bool compound; 189 u8 kind; 190 }; 191 192 /* FIXME: This should be arch-dependent */ 193 #ifdef __powerpc__ 194 #define TYPE_STATE_MAX_REGS 32 195 #else 196 #define TYPE_STATE_MAX_REGS 16 197 #endif 198 199 /* 200 * State table to maintain type info in each register and stack location. 201 * It'll be updated when new variable is allocated or type info is moved 202 * to a new location (register or stack). As it'd be used with the 203 * shortest path of basic blocks, it only maintains a single table. 204 */ 205 struct type_state { 206 /* state of general purpose registers */ 207 struct type_state_reg regs[TYPE_STATE_MAX_REGS]; 208 /* state of stack location */ 209 struct list_head stack_vars; 210 /* return value register */ 211 int ret_reg; 212 /* stack pointer register */ 213 int stack_reg; 214 }; 215 216 /* Returns data type at the location (ip, reg, offset) */ 217 struct annotated_data_type *find_data_type(struct data_loc_info *dloc); 218 219 /* Update type access histogram at the given offset */ 220 int annotated_data_type__update_samples(struct annotated_data_type *adt, 221 struct evsel *evsel, int offset, 222 int nr_samples, u64 period); 223 224 /* Release all data type information in the tree */ 225 void annotated_data_type__tree_delete(struct rb_root *root); 226 227 /* Release all global variable information in the tree */ 228 void global_var_type__tree_delete(struct rb_root *root); 229 230 int hist_entry__annotate_data_tty(struct hist_entry *he, struct evsel *evsel); 231 232 bool has_reg_type(struct type_state *state, int reg); 233 struct type_state_stack *findnew_stack_state(struct type_state *state, 234 int offset, u8 kind, 235 Dwarf_Die *type_die); 236 void set_stack_state(struct type_state_stack *stack, int offset, u8 kind, 237 Dwarf_Die *type_die); 238 struct type_state_stack *find_stack_state(struct type_state *state, 239 int offset); 240 bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc, 241 u64 ip, u64 var_addr, int *var_offset, 242 Dwarf_Die *type_die); 243 bool get_global_var_info(struct data_loc_info *dloc, u64 addr, 244 const char **var_name, int *var_offset); 245 void pr_debug_type_name(Dwarf_Die *die, enum type_state_kind kind); 246 247 #else /* HAVE_DWARF_SUPPORT */ 248 249 static inline struct annotated_data_type * 250 find_data_type(struct data_loc_info *dloc __maybe_unused) 251 { 252 return NULL; 253 } 254 255 static inline int 256 annotated_data_type__update_samples(struct annotated_data_type *adt __maybe_unused, 257 struct evsel *evsel __maybe_unused, 258 int offset __maybe_unused, 259 int nr_samples __maybe_unused, 260 u64 period __maybe_unused) 261 { 262 return -1; 263 } 264 265 static inline void annotated_data_type__tree_delete(struct rb_root *root __maybe_unused) 266 { 267 } 268 269 static inline void global_var_type__tree_delete(struct rb_root *root __maybe_unused) 270 { 271 } 272 273 static inline int hist_entry__annotate_data_tty(struct hist_entry *he __maybe_unused, 274 struct evsel *evsel __maybe_unused) 275 { 276 return -1; 277 } 278 279 #endif /* HAVE_DWARF_SUPPORT */ 280 281 #ifdef HAVE_SLANG_SUPPORT 282 int hist_entry__annotate_data_tui(struct hist_entry *he, struct evsel *evsel, 283 struct hist_browser_timer *hbt); 284 #else 285 static inline int hist_entry__annotate_data_tui(struct hist_entry *he __maybe_unused, 286 struct evsel *evsel __maybe_unused, 287 struct hist_browser_timer *hbt __maybe_unused) 288 { 289 return -1; 290 } 291 #endif /* HAVE_SLANG_SUPPORT */ 292 293 #endif /* _PERF_ANNOTATE_DATA_H */ 294