0001
0002 #ifndef __PERF_CALLCHAIN_H
0003 #define __PERF_CALLCHAIN_H
0004
0005 #include <linux/list.h>
0006 #include <linux/rbtree.h>
0007 #include "map_symbol.h"
0008 #include "branch.h"
0009
0010 struct addr_location;
0011 struct evsel;
0012 struct ip_callchain;
0013 struct map;
0014 struct perf_sample;
0015 struct thread;
0016 struct hists;
0017
0018 #define HELP_PAD "\t\t\t\t"
0019
0020 #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n"
0021
0022 # define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n"
0023
0024 #define RECORD_SIZE_HELP \
0025 HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \
0026 HELP_PAD "\t\tdefault: 8192 (bytes)\n"
0027
0028 #define CALLCHAIN_RECORD_HELP CALLCHAIN_HELP RECORD_MODE_HELP RECORD_SIZE_HELP
0029
0030 #define CALLCHAIN_REPORT_HELP \
0031 HELP_PAD "print_type:\tcall graph printing style (graph|flat|fractal|folded|none)\n" \
0032 HELP_PAD "threshold:\tminimum call graph inclusion threshold (<percent>)\n" \
0033 HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \
0034 HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \
0035 HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \
0036 HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" \
0037 HELP_PAD "value:\t\tcall graph value (percent|period|count)\n"
0038
0039 enum perf_call_graph_mode {
0040 CALLCHAIN_NONE,
0041 CALLCHAIN_FP,
0042 CALLCHAIN_DWARF,
0043 CALLCHAIN_LBR,
0044 CALLCHAIN_MAX
0045 };
0046
0047 enum chain_mode {
0048 CHAIN_NONE,
0049 CHAIN_FLAT,
0050 CHAIN_GRAPH_ABS,
0051 CHAIN_GRAPH_REL,
0052 CHAIN_FOLDED,
0053 };
0054
0055 enum chain_order {
0056 ORDER_CALLER,
0057 ORDER_CALLEE
0058 };
0059
0060 struct callchain_node {
0061 struct callchain_node *parent;
0062 struct list_head val;
0063 struct list_head parent_val;
0064 struct rb_node rb_node_in;
0065 struct rb_node rb_node;
0066 struct rb_root rb_root_in;
0067 struct rb_root rb_root;
0068 unsigned int val_nr;
0069 unsigned int count;
0070 unsigned int children_count;
0071 u64 hit;
0072 u64 children_hit;
0073 };
0074
0075 struct callchain_root {
0076 u64 max_depth;
0077 struct callchain_node node;
0078 };
0079
0080 struct callchain_param;
0081
0082 typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
0083 u64, struct callchain_param *);
0084
0085 enum chain_key {
0086 CCKEY_FUNCTION,
0087 CCKEY_ADDRESS,
0088 CCKEY_SRCLINE
0089 };
0090
0091 enum chain_value {
0092 CCVAL_PERCENT,
0093 CCVAL_PERIOD,
0094 CCVAL_COUNT,
0095 };
0096
0097 extern bool dwarf_callchain_users;
0098
0099 struct callchain_param {
0100 bool enabled;
0101 enum perf_call_graph_mode record_mode;
0102 u32 dump_size;
0103 enum chain_mode mode;
0104 u16 max_stack;
0105 u32 print_limit;
0106 double min_percent;
0107 sort_chain_func_t sort;
0108 enum chain_order order;
0109 bool order_set;
0110 enum chain_key key;
0111 bool branch_callstack;
0112 enum chain_value value;
0113 };
0114
0115 extern struct callchain_param callchain_param;
0116 extern struct callchain_param callchain_param_default;
0117
0118 struct callchain_list {
0119 u64 ip;
0120 struct map_symbol ms;
0121 struct {
0122 bool unfolded;
0123 bool has_children;
0124 };
0125 u64 branch_count;
0126 u64 from_count;
0127 u64 predicted_count;
0128 u64 abort_count;
0129 u64 cycles_count;
0130 u64 iter_count;
0131 u64 iter_cycles;
0132 struct branch_type_stat brtype_stat;
0133 const char *srcline;
0134 struct list_head list;
0135 };
0136
0137
0138
0139
0140
0141
0142
0143 struct callchain_cursor_node {
0144 u64 ip;
0145 struct map_symbol ms;
0146 const char *srcline;
0147
0148 bool valid;
0149
0150 bool branch;
0151 struct branch_flags branch_flags;
0152 u64 branch_from;
0153 int nr_loop_iter;
0154 u64 iter_cycles;
0155 struct callchain_cursor_node *next;
0156 };
0157
0158 struct stitch_list {
0159 struct list_head node;
0160 struct callchain_cursor_node cursor;
0161 };
0162
0163 struct callchain_cursor {
0164 u64 nr;
0165 struct callchain_cursor_node *first;
0166 struct callchain_cursor_node **last;
0167 u64 pos;
0168 struct callchain_cursor_node *curr;
0169 };
0170
0171 extern __thread struct callchain_cursor callchain_cursor;
0172
0173 static inline void callchain_init(struct callchain_root *root)
0174 {
0175 INIT_LIST_HEAD(&root->node.val);
0176 INIT_LIST_HEAD(&root->node.parent_val);
0177
0178 root->node.parent = NULL;
0179 root->node.hit = 0;
0180 root->node.children_hit = 0;
0181 root->node.rb_root_in = RB_ROOT;
0182 root->max_depth = 0;
0183 }
0184
0185 static inline u64 callchain_cumul_hits(struct callchain_node *node)
0186 {
0187 return node->hit + node->children_hit;
0188 }
0189
0190 static inline unsigned callchain_cumul_counts(struct callchain_node *node)
0191 {
0192 return node->count + node->children_count;
0193 }
0194
0195 int callchain_register_param(struct callchain_param *param);
0196 int callchain_append(struct callchain_root *root,
0197 struct callchain_cursor *cursor,
0198 u64 period);
0199
0200 int callchain_merge(struct callchain_cursor *cursor,
0201 struct callchain_root *dst, struct callchain_root *src);
0202
0203 void callchain_cursor_reset(struct callchain_cursor *cursor);
0204
0205 int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
0206 struct map_symbol *ms,
0207 bool branch, struct branch_flags *flags,
0208 int nr_loop_iter, u64 iter_cycles, u64 branch_from,
0209 const char *srcline);
0210
0211
0212 static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
0213 {
0214 cursor->curr = cursor->first;
0215 cursor->pos = 0;
0216 }
0217
0218
0219 static inline struct callchain_cursor_node *
0220 callchain_cursor_current(struct callchain_cursor *cursor)
0221 {
0222 if (cursor->pos == cursor->nr)
0223 return NULL;
0224
0225 return cursor->curr;
0226 }
0227
0228 static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
0229 {
0230 cursor->curr = cursor->curr->next;
0231 cursor->pos++;
0232 }
0233
0234 int callchain_cursor__copy(struct callchain_cursor *dst,
0235 struct callchain_cursor *src);
0236
0237 struct option;
0238 struct hist_entry;
0239
0240 int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
0241 int record_callchain_opt(const struct option *opt, const char *arg, int unset);
0242
0243 struct record_opts;
0244
0245 int record_opts__parse_callchain(struct record_opts *record,
0246 struct callchain_param *callchain,
0247 const char *arg, bool unset);
0248
0249 int sample__resolve_callchain(struct perf_sample *sample,
0250 struct callchain_cursor *cursor, struct symbol **parent,
0251 struct evsel *evsel, struct addr_location *al,
0252 int max_stack);
0253 int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
0254 int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
0255 bool hide_unresolved);
0256
0257 extern const char record_callchain_help[];
0258 int parse_callchain_record(const char *arg, struct callchain_param *param);
0259 int parse_callchain_record_opt(const char *arg, struct callchain_param *param);
0260 int parse_callchain_report_opt(const char *arg);
0261 int parse_callchain_top_opt(const char *arg);
0262 int perf_callchain_config(const char *var, const char *value);
0263
0264 static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
0265 struct callchain_cursor *src)
0266 {
0267 *dest = *src;
0268
0269 dest->first = src->curr;
0270 dest->nr -= src->pos;
0271 }
0272
0273 #ifdef HAVE_SKIP_CALLCHAIN_IDX
0274 int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain);
0275 #else
0276 static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
0277 struct ip_callchain *chain __maybe_unused)
0278 {
0279 return -1;
0280 }
0281 #endif
0282
0283 void arch__add_leaf_frame_record_opts(struct record_opts *opts);
0284
0285 char *callchain_list__sym_name(struct callchain_list *cl,
0286 char *bf, size_t bfsize, bool show_dso);
0287 char *callchain_node__scnprintf_value(struct callchain_node *node,
0288 char *bf, size_t bfsize, u64 total);
0289 int callchain_node__fprintf_value(struct callchain_node *node,
0290 FILE *fp, u64 total);
0291
0292 int callchain_list_counts__printf_value(struct callchain_list *clist,
0293 FILE *fp, char *bf, int bfsize);
0294
0295 void free_callchain(struct callchain_root *root);
0296 void decay_callchain(struct callchain_root *root);
0297 int callchain_node__make_parent_list(struct callchain_node *node);
0298
0299 int callchain_branch_counts(struct callchain_root *root,
0300 u64 *branch_count, u64 *predicted_count,
0301 u64 *abort_count, u64 *cycles_count);
0302
0303 void callchain_param_setup(u64 sample_type, const char *arch);
0304
0305 bool callchain_cnode_matched(struct callchain_node *base_cnode,
0306 struct callchain_node *pair_cnode);
0307
0308 u64 callchain_total_hits(struct hists *hists);
0309
0310 s64 callchain_avg_cycles(struct callchain_node *cnode);
0311
0312 #endif