blob: 99d38ac019b8980c38f8ab4d2f67e3f9df5ebe1a [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +02002#ifndef __PERF_CALLCHAIN_H
3#define __PERF_CALLCHAIN_H
4
5#include "../perf.h"
Arnaldo Carvalho de Melo5da50252009-07-01 14:46:08 -03006#include <linux/list.h>
Arnaldo Carvalho de Melo43cbcd82009-07-01 12:28:37 -03007#include <linux/rbtree.h>
Arnaldo Carvalho de Melo139633c2010-05-09 11:47:13 -03008#include "event.h"
Krister Johansenaa33b9b2017-01-05 22:23:31 -08009#include "map.h"
Frederic Weisbecker44249612009-07-01 05:35:14 +020010#include "symbol.h"
Jin Yaob851dd42017-07-18 20:13:15 +080011#include "branch.h"
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020012
Namhyung Kim76a26542015-10-22 23:28:32 +090013#define HELP_PAD "\t\t\t\t"
14
15#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n"
Namhyung Kim21cf6282015-10-22 15:28:48 +090016
Namhyung Kim76a26542015-10-22 23:28:32 +090017# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n"
Namhyung Kim21cf6282015-10-22 15:28:48 +090018
Namhyung Kim76a26542015-10-22 23:28:32 +090019#define RECORD_SIZE_HELP \
20 HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \
21 HELP_PAD "\t\tdefault: 8192 (bytes)\n"
22
23#define CALLCHAIN_RECORD_HELP CALLCHAIN_HELP RECORD_MODE_HELP RECORD_SIZE_HELP
24
25#define CALLCHAIN_REPORT_HELP \
Namhyung Kim26e77922015-11-09 14:45:37 +090026 HELP_PAD "print_type:\tcall graph printing style (graph|flat|fractal|folded|none)\n" \
Namhyung Kim76a26542015-10-22 23:28:32 +090027 HELP_PAD "threshold:\tminimum call graph inclusion threshold (<percent>)\n" \
28 HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \
29 HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \
30 HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \
Namhyung Kimf2af0082015-11-09 14:45:41 +090031 HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" \
32 HELP_PAD "value:\t\tcall graph value (percent|period|count)\n"
Namhyung Kim21cf6282015-10-22 15:28:48 +090033
Jiri Olsa2c83bc02014-05-05 12:46:17 +020034enum perf_call_graph_mode {
35 CALLCHAIN_NONE,
36 CALLCHAIN_FP,
37 CALLCHAIN_DWARF,
Kan Liangaad2b212015-01-05 13:23:04 -050038 CALLCHAIN_LBR,
Jiri Olsa2c83bc02014-05-05 12:46:17 +020039 CALLCHAIN_MAX
40};
41
Frederic Weisbecker4eb3e472009-07-02 17:58:21 +020042enum chain_mode {
Frederic Weisbeckerb1a88342009-08-08 02:16:24 +020043 CHAIN_NONE,
Frederic Weisbecker805d1272009-07-05 07:39:21 +020044 CHAIN_FLAT,
45 CHAIN_GRAPH_ABS,
Namhyung Kim26e77922015-11-09 14:45:37 +090046 CHAIN_GRAPH_REL,
47 CHAIN_FOLDED,
Frederic Weisbecker4eb3e472009-07-02 17:58:21 +020048};
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020049
Sam Liaod797fdc2011-06-07 23:49:46 +080050enum chain_order {
51 ORDER_CALLER,
52 ORDER_CALLEE
53};
54
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020055struct callchain_node {
56 struct callchain_node *parent;
Ingo Molnarf37a2912009-07-01 12:37:06 +020057 struct list_head val;
Namhyung Kim4b3a3212015-11-09 14:45:43 +090058 struct list_head parent_val;
Namhyung Kime3695172013-10-11 14:15:36 +090059 struct rb_node rb_node_in; /* to insert nodes in an rbtree */
60 struct rb_node rb_node; /* to sort nodes in an output tree */
61 struct rb_root rb_root_in; /* input tree of children */
62 struct rb_root rb_root; /* sorted output tree of children */
Ingo Molnarf37a2912009-07-01 12:37:06 +020063 unsigned int val_nr;
Namhyung Kim5e47f8f2015-11-09 14:45:40 +090064 unsigned int count;
65 unsigned int children_count;
Ingo Molnarf37a2912009-07-01 12:37:06 +020066 u64 hit;
Frederic Weisbecker19532872009-08-07 07:11:05 +020067 u64 children_hit;
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020068};
69
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +020070struct callchain_root {
71 u64 max_depth;
72 struct callchain_node node;
73};
74
Frederic Weisbecker805d1272009-07-05 07:39:21 +020075struct callchain_param;
76
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +020077typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
Frederic Weisbecker805d1272009-07-05 07:39:21 +020078 u64, struct callchain_param *);
79
Andi Kleen99571ab2013-07-18 15:33:57 -070080enum chain_key {
81 CCKEY_FUNCTION,
Milian Wolff5dfa2102017-03-18 22:49:28 +010082 CCKEY_ADDRESS,
83 CCKEY_SRCLINE
Andi Kleen99571ab2013-07-18 15:33:57 -070084};
85
Namhyung Kimf2af0082015-11-09 14:45:41 +090086enum chain_value {
87 CCVAL_PERCENT,
88 CCVAL_PERIOD,
89 CCVAL_COUNT,
90};
91
Arnaldo Carvalho de Meloeabad8c2018-01-15 16:48:46 -030092extern bool dwarf_callchain_users;
93
Frederic Weisbecker805d1272009-07-05 07:39:21 +020094struct callchain_param {
Namhyung Kim72a128a2014-09-23 10:01:41 +090095 bool enabled;
96 enum perf_call_graph_mode record_mode;
97 u32 dump_size;
Frederic Weisbecker805d1272009-07-05 07:39:21 +020098 enum chain_mode mode;
Arnaldo Carvalho de Melo792d48b2016-04-28 19:03:42 -030099 u16 max_stack;
Arnaldo Carvalho de Melo232a5c92010-05-09 20:28:10 -0300100 u32 print_limit;
Frederic Weisbecker805d1272009-07-05 07:39:21 +0200101 double min_percent;
102 sort_chain_func_t sort;
Sam Liaod797fdc2011-06-07 23:49:46 +0800103 enum chain_order order;
Namhyung Kim792aeaf2015-10-22 16:45:46 +0900104 bool order_set;
Andi Kleen99571ab2013-07-18 15:33:57 -0700105 enum chain_key key;
Andi Kleen8b7bad52014-11-12 18:05:20 -0800106 bool branch_callstack;
Namhyung Kimf2af0082015-11-09 14:45:41 +0900107 enum chain_value value;
Frederic Weisbecker805d1272009-07-05 07:39:21 +0200108};
109
Arnaldo Carvalho de Melo8f651ea2014-10-09 16:12:24 -0300110extern struct callchain_param callchain_param;
Jiri Olsa347ca872016-07-04 14:16:21 +0200111extern struct callchain_param callchain_param_default;
Arnaldo Carvalho de Melo8f651ea2014-10-09 16:12:24 -0300112
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +0200113struct callchain_list {
Ingo Molnarf37a2912009-07-01 12:37:06 +0200114 u64 ip;
Arnaldo Carvalho de Melob3c9ac02010-03-24 16:40:18 -0300115 struct map_symbol ms;
Namhyung Kim3698dab2015-05-05 23:55:46 +0900116 struct /* for TUI */ {
117 bool unfolded;
118 bool has_children;
119 };
Jin Yao3dd029e2016-10-31 09:19:51 +0800120 u64 branch_count;
Jin Yaoa3366db02019-01-04 14:10:30 +0800121 u64 from_count;
Jin Yao3dd029e2016-10-31 09:19:51 +0800122 u64 predicted_count;
123 u64 abort_count;
124 u64 cycles_count;
125 u64 iter_count;
Jin Yaoc4ee0622017-08-07 21:05:15 +0800126 u64 iter_cycles;
Jin Yaob851dd42017-07-18 20:13:15 +0800127 struct branch_type_stat brtype_stat;
Milian Wolff40a342c2017-10-09 22:32:56 +0200128 const char *srcline;
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +0200129 struct list_head list;
130};
131
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100132/*
133 * A callchain cursor is a single linked list that
134 * let one feed a callchain progressively.
Masanari Iida3fd44cd2012-07-18 01:20:59 +0900135 * It keeps persistent allocated entries to minimize
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100136 * allocations.
137 */
138struct callchain_cursor_node {
139 u64 ip;
140 struct map *map;
141 struct symbol *sym;
Milian Wolff40a342c2017-10-09 22:32:56 +0200142 const char *srcline;
Jin Yao410024d2016-10-31 09:19:49 +0800143 bool branch;
144 struct branch_flags branch_flags;
Jin Yaob851dd42017-07-18 20:13:15 +0800145 u64 branch_from;
Jin Yao410024d2016-10-31 09:19:49 +0800146 int nr_loop_iter;
Jin Yaoc4ee0622017-08-07 21:05:15 +0800147 u64 iter_cycles;
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100148 struct callchain_cursor_node *next;
149};
150
151struct callchain_cursor {
152 u64 nr;
153 struct callchain_cursor_node *first;
154 struct callchain_cursor_node **last;
155 u64 pos;
156 struct callchain_cursor_node *curr;
157};
158
Namhyung Kim47260642012-05-31 14:43:26 +0900159extern __thread struct callchain_cursor callchain_cursor;
160
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +0200161static inline void callchain_init(struct callchain_root *root)
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +0200162{
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +0200163 INIT_LIST_HEAD(&root->node.val);
Jiri Olsa646a6e82015-11-21 11:23:55 +0100164 INIT_LIST_HEAD(&root->node.parent_val);
Frederic Weisbecker97aa1052010-07-08 06:06:17 +0200165
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +0200166 root->node.parent = NULL;
167 root->node.hit = 0;
Frederic Weisbecker98ee74a2010-08-27 02:28:40 +0200168 root->node.children_hit = 0;
Namhyung Kime3695172013-10-11 14:15:36 +0900169 root->node.rb_root_in = RB_ROOT;
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +0200170 root->max_depth = 0;
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +0200171}
172
Frederic Weisbeckerf08c3152011-01-14 04:51:59 +0100173static inline u64 callchain_cumul_hits(struct callchain_node *node)
Frederic Weisbecker19532872009-08-07 07:11:05 +0200174{
175 return node->hit + node->children_hit;
176}
177
Namhyung Kim5e47f8f2015-11-09 14:45:40 +0900178static inline unsigned callchain_cumul_counts(struct callchain_node *node)
179{
180 return node->count + node->children_count;
181}
182
Frederic Weisbecker16537f12011-01-14 04:52:00 +0100183int callchain_register_param(struct callchain_param *param);
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100184int callchain_append(struct callchain_root *root,
185 struct callchain_cursor *cursor,
186 u64 period);
187
188int callchain_merge(struct callchain_cursor *cursor,
189 struct callchain_root *dst, struct callchain_root *src);
Arnaldo Carvalho de Melo139633c2010-05-09 11:47:13 -0300190
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100191/*
192 * Initialize a cursor before adding entries inside, but keep
193 * the previously allocated entries as a cache.
194 */
195static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
196{
Krister Johansenaa33b9b2017-01-05 22:23:31 -0800197 struct callchain_cursor_node *node;
198
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100199 cursor->nr = 0;
200 cursor->last = &cursor->first;
Krister Johansenaa33b9b2017-01-05 22:23:31 -0800201
202 for (node = cursor->first; node != NULL; node = node->next)
203 map__zput(node->map);
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100204}
205
206int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
Jin Yao410024d2016-10-31 09:19:49 +0800207 struct map *map, struct symbol *sym,
208 bool branch, struct branch_flags *flags,
Milian Wolff40a342c2017-10-09 22:32:56 +0200209 int nr_loop_iter, u64 iter_cycles, u64 branch_from,
210 const char *srcline);
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100211
212/* Close a cursor writing session. Initialize for the reader */
213static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
214{
215 cursor->curr = cursor->first;
216 cursor->pos = 0;
217}
218
219/* Cursor reading iteration helpers */
220static inline struct callchain_cursor_node *
221callchain_cursor_current(struct callchain_cursor *cursor)
222{
223 if (cursor->pos == cursor->nr)
224 return NULL;
225
226 return cursor->curr;
227}
228
229static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
230{
231 cursor->curr = cursor->curr->next;
232 cursor->pos++;
233}
Arnaldo Carvalho de Melo75d9a1082012-12-11 16:46:05 -0300234
Namhyung Kim571f1eb2016-12-06 12:40:02 +0900235int callchain_cursor__copy(struct callchain_cursor *dst,
236 struct callchain_cursor *src);
237
Arnaldo Carvalho de Melo75d9a1082012-12-11 16:46:05 -0300238struct option;
Namhyung Kim2dc9fb12014-01-14 14:25:35 +0900239struct hist_entry;
Arnaldo Carvalho de Melo75d9a1082012-12-11 16:46:05 -0300240
241int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
Jiri Olsa09b0fd42013-10-26 16:25:33 +0200242int record_callchain_opt(const struct option *opt, const char *arg, int unset);
243
Arnaldo Carvalho de Melo0883e822016-04-15 16:37:17 -0300244struct record_opts;
245
246int record_opts__parse_callchain(struct record_opts *record,
247 struct callchain_param *callchain,
248 const char *arg, bool unset);
249
Arnaldo Carvalho de Melo91d7b2d2016-04-14 14:48:07 -0300250int sample__resolve_callchain(struct perf_sample *sample,
251 struct callchain_cursor *cursor, struct symbol **parent,
Namhyung Kim2dc9fb12014-01-14 14:25:35 +0900252 struct perf_evsel *evsel, struct addr_location *al,
253 int max_stack);
254int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
Namhyung Kimc7405d82013-10-31 13:58:30 +0900255int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
256 bool hide_unresolved);
Namhyung Kim2dc9fb12014-01-14 14:25:35 +0900257
Arnaldo Carvalho de Melo75d9a1082012-12-11 16:46:05 -0300258extern const char record_callchain_help[];
Arnaldo Carvalho de Melo3938bad2016-03-23 15:06:35 -0300259int parse_callchain_record(const char *arg, struct callchain_param *param);
Kan Liangc3a6a8c2015-08-04 04:30:20 -0400260int parse_callchain_record_opt(const char *arg, struct callchain_param *param);
Don Zickuscff6bb42014-04-07 14:55:24 -0400261int parse_callchain_report_opt(const char *arg);
Namhyung Kima2c10d32015-10-22 15:28:49 +0900262int parse_callchain_top_opt(const char *arg);
Namhyung Kim2b9240c2014-09-23 10:01:43 +0900263int perf_callchain_config(const char *var, const char *value);
Namhyung Kimbe1f13e2012-09-10 13:38:00 +0900264
265static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
266 struct callchain_cursor *src)
267{
268 *dest = *src;
269
270 dest->first = src->curr;
271 dest->nr -= src->pos;
272}
Sukadev Bhattiprolua60335b2014-06-25 08:49:03 -0700273
274#ifdef HAVE_SKIP_CALLCHAIN_IDX
Arnaldo Carvalho de Melo3938bad2016-03-23 15:06:35 -0300275int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain);
Sukadev Bhattiprolua60335b2014-06-25 08:49:03 -0700276#else
Arnaldo Carvalho de Melobb871a92014-10-23 12:50:25 -0300277static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
Sukadev Bhattiprolua60335b2014-06-25 08:49:03 -0700278 struct ip_callchain *chain __maybe_unused)
279{
280 return -1;
281}
282#endif
283
Andi Kleen2989cca2014-11-12 18:05:23 -0800284char *callchain_list__sym_name(struct callchain_list *cl,
285 char *bf, size_t bfsize, bool show_dso);
Namhyung Kim5ab250c2015-11-09 14:45:39 +0900286char *callchain_node__scnprintf_value(struct callchain_node *node,
287 char *bf, size_t bfsize, u64 total);
288int callchain_node__fprintf_value(struct callchain_node *node,
289 FILE *fp, u64 total);
Andi Kleen2989cca2014-11-12 18:05:23 -0800290
Jin Yaoc4ee0622017-08-07 21:05:15 +0800291int callchain_list_counts__printf_value(struct callchain_list *clist,
Jin Yao3dd029e2016-10-31 09:19:51 +0800292 FILE *fp, char *bf, int bfsize);
293
Namhyung Kimd1149602014-12-30 14:38:13 +0900294void free_callchain(struct callchain_root *root);
Namhyung Kim42b276a2016-01-05 12:06:00 +0900295void decay_callchain(struct callchain_root *root);
Namhyung Kim4b3a3212015-11-09 14:45:43 +0900296int callchain_node__make_parent_list(struct callchain_node *node);
Namhyung Kimd1149602014-12-30 14:38:13 +0900297
Jin Yao3dd029e2016-10-31 09:19:51 +0800298int callchain_branch_counts(struct callchain_root *root,
299 u64 *branch_count, u64 *predicted_count,
300 u64 *abort_count, u64 *cycles_count);
301
John Kacur8b40f522009-09-24 18:02:18 +0200302#endif /* __PERF_CALLCHAIN_H */