294 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#ifndef _PERF_ANNOTATE_DATA_H3#define _PERF_ANNOTATE_DATA_H4 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_SUPPORT13#include "debuginfo.h"14#endif15 16struct annotated_op_loc;17struct debuginfo;18struct evsel;19struct hist_browser_timer;20struct hist_entry;21struct map_symbol;22struct thread;23 24#define pr_debug_dtp(fmt, ...) \25do { \26 if (debug_type_profile) \27 pr_info(fmt, ##__VA_ARGS__); \28 else \29 pr_debug3(fmt, ##__VA_ARGS__); \30} while (0)31 32enum 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 field43 * @node: List entry in the parent list44 * @children: List head for child nodes45 * @type_name: Name of the member type46 * @var_name: Name of the member variable47 * @offset: Offset from the outer data type48 * @size: Size of the member field49 *50 * This represents a member type in a data type.51 */52struct 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 offset63 * @nr_samples: Number of samples64 * @period: Count of event65 */66struct type_hist_entry {67 int nr_samples;68 u64 period;69};70 71/**72 * struct type_hist - Type histogram for each event73 * @nr_samples: Total number of samples in this data type74 * @period: Total count of the event in this data type75 * @offset: Array of histogram entry76 */77struct 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 profile85 * @node: RB-tree node for dso->type_tree86 * @self: Actual type information87 * @nr_histogram: Number of histogram entries88 * @histograms: An array of pointers to histograms89 *90 * This represents a data type accessed by samples in the profile data.91 */92struct annotated_data_type {93 struct rb_node node;94 struct annotated_member self;95 int nr_histograms;96 struct type_hist **histograms;97};98 99extern struct annotated_data_type unknown_type;100extern struct annotated_data_type stackop_type;101extern struct annotated_data_type canary_type;102 103/**104 * struct data_loc_info - Data location information105 * @arch: CPU architecture info106 * @thread: Thread info107 * @ms: Map and Symbol info108 * @ip: Instruction address109 * @var_addr: Data address (for global variables)110 * @cpumode: CPU execution mode111 * @op: Instruction operand location (regs and offset)112 * @di: Debug info113 * @fbreg: Frame base register114 * @fb_cfa: Whether the frame needs to check CFA115 * @type_offset: Final offset in the type116 */117struct 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 statistics138 * @total: Total number of entry139 * @no_sym: No symbol or map found140 * @no_insn: Failed to get disasm line141 * @no_insn_ops: The instruction has no operands142 * @no_mem_ops: The instruction has no memory operands143 * @no_reg: Failed to extract a register from the operand144 * @no_dbginfo: The binary has no debug information145 * @no_cuinfo: Failed to find a compile_unit146 * @no_var: Failed to find a matching variable147 * @no_typeinfo: Failed to get a type info for the variable148 * @invalid_size: Failed to get a size info of the type149 * @bad_offset: The access offset is out of the type150 */151struct 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};166extern struct annotated_data_stat ann_data_stat;167 168#ifdef HAVE_DWARF_SUPPORT169/*170 * Type information in a register, valid when @ok is true.171 * The @caller_saved registers are invalidated after a function call.172 */173struct 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 */183struct 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 32195#else196#define TYPE_STATE_MAX_REGS 16197#endif198 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 moved202 * to a new location (register or stack). As it'd be used with the203 * shortest path of basic blocks, it only maintains a single table.204 */205struct 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) */217struct annotated_data_type *find_data_type(struct data_loc_info *dloc);218 219/* Update type access histogram at the given offset */220int 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 */225void annotated_data_type__tree_delete(struct rb_root *root);226 227/* Release all global variable information in the tree */228void global_var_type__tree_delete(struct rb_root *root);229 230int hist_entry__annotate_data_tty(struct hist_entry *he, struct evsel *evsel);231 232bool has_reg_type(struct type_state *state, int reg);233struct type_state_stack *findnew_stack_state(struct type_state *state,234 int offset, u8 kind,235 Dwarf_Die *type_die);236void set_stack_state(struct type_state_stack *stack, int offset, u8 kind,237 Dwarf_Die *type_die);238struct type_state_stack *find_stack_state(struct type_state *state,239 int offset);240bool 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);243bool get_global_var_info(struct data_loc_info *dloc, u64 addr,244 const char **var_name, int *var_offset);245void pr_debug_type_name(Dwarf_Die *die, enum type_state_kind kind);246 247#else /* HAVE_DWARF_SUPPORT */248 249static inline struct annotated_data_type *250find_data_type(struct data_loc_info *dloc __maybe_unused)251{252 return NULL;253}254 255static inline int256annotated_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 265static inline void annotated_data_type__tree_delete(struct rb_root *root __maybe_unused)266{267}268 269static inline void global_var_type__tree_delete(struct rb_root *root __maybe_unused)270{271}272 273static 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_SUPPORT282int hist_entry__annotate_data_tui(struct hist_entry *he, struct evsel *evsel,283 struct hist_browser_timer *hbt);284#else285static 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