Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
4 *
5 * Handle the callchains from the stream in an ad-hoc radix tree and then
6 * sort them in an rbtree.
7 *
8 * Using a radix for code path provides a fast retrieval and factorizes
9 * memory use. Also that lets us use the paths in a hierarchical graph view.
10 *
11 */
12
13#include <inttypes.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <stdbool.h>
17#include <errno.h>
18#include <math.h>
19
20#include "asm/bug.h"
21
22#include "hist.h"
23#include "util.h"
24#include "sort.h"
25#include "machine.h"
26#include "callchain.h"
27#include "branch.h"
28
29#define CALLCHAIN_PARAM_DEFAULT \
30 .mode = CHAIN_GRAPH_ABS, \
31 .min_percent = 0.5, \
32 .order = ORDER_CALLEE, \
33 .key = CCKEY_FUNCTION, \
34 .value = CCVAL_PERCENT, \
35
36struct callchain_param callchain_param = {
37 CALLCHAIN_PARAM_DEFAULT
38};
39
40struct callchain_param callchain_param_default = {
41 CALLCHAIN_PARAM_DEFAULT
42};
43
44__thread struct callchain_cursor callchain_cursor;
45
46int parse_callchain_record_opt(const char *arg, struct callchain_param *param)
47{
48 return parse_callchain_record(arg, param);
49}
50
51static int parse_callchain_mode(const char *value)
52{
53 if (!strncmp(value, "graph", strlen(value))) {
54 callchain_param.mode = CHAIN_GRAPH_ABS;
55 return 0;
56 }
57 if (!strncmp(value, "flat", strlen(value))) {
58 callchain_param.mode = CHAIN_FLAT;
59 return 0;
60 }
61 if (!strncmp(value, "fractal", strlen(value))) {
62 callchain_param.mode = CHAIN_GRAPH_REL;
63 return 0;
64 }
65 if (!strncmp(value, "folded", strlen(value))) {
66 callchain_param.mode = CHAIN_FOLDED;
67 return 0;
68 }
69 return -1;
70}
71
72static int parse_callchain_order(const char *value)
73{
74 if (!strncmp(value, "caller", strlen(value))) {
75 callchain_param.order = ORDER_CALLER;
76 callchain_param.order_set = true;
77 return 0;
78 }
79 if (!strncmp(value, "callee", strlen(value))) {
80 callchain_param.order = ORDER_CALLEE;
81 callchain_param.order_set = true;
82 return 0;
83 }
84 return -1;
85}
86
87static int parse_callchain_sort_key(const char *value)
88{
89 if (!strncmp(value, "function", strlen(value))) {
90 callchain_param.key = CCKEY_FUNCTION;
91 return 0;
92 }
93 if (!strncmp(value, "address", strlen(value))) {
94 callchain_param.key = CCKEY_ADDRESS;
95 return 0;
96 }
97 if (!strncmp(value, "srcline", strlen(value))) {
98 callchain_param.key = CCKEY_SRCLINE;
99 return 0;
100 }
101 if (!strncmp(value, "branch", strlen(value))) {
102 callchain_param.branch_callstack = 1;
103 return 0;
104 }
105 return -1;
106}
107
108static int parse_callchain_value(const char *value)
109{
110 if (!strncmp(value, "percent", strlen(value))) {
111 callchain_param.value = CCVAL_PERCENT;
112 return 0;
113 }
114 if (!strncmp(value, "period", strlen(value))) {
115 callchain_param.value = CCVAL_PERIOD;
116 return 0;
117 }
118 if (!strncmp(value, "count", strlen(value))) {
119 callchain_param.value = CCVAL_COUNT;
120 return 0;
121 }
122 return -1;
123}
124
125static int get_stack_size(const char *str, unsigned long *_size)
126{
127 char *endptr;
128 unsigned long size;
129 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
130
131 size = strtoul(str, &endptr, 0);
132
133 do {
134 if (*endptr)
135 break;
136
137 size = round_up(size, sizeof(u64));
138 if (!size || size > max_size)
139 break;
140
141 *_size = size;
142 return 0;
143
144 } while (0);
145
146 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
147 max_size, str);
148 return -1;
149}
150
151static int
152__parse_callchain_report_opt(const char *arg, bool allow_record_opt)
153{
154 char *tok;
155 char *endptr, *saveptr = NULL;
156 bool minpcnt_set = false;
157 bool record_opt_set = false;
158 bool try_stack_size = false;
159
160 callchain_param.enabled = true;
161 symbol_conf.use_callchain = true;
162
163 if (!arg)
164 return 0;
165
166 while ((tok = strtok_r((char *)arg, ",", &saveptr)) != NULL) {
167 if (!strncmp(tok, "none", strlen(tok))) {
168 callchain_param.mode = CHAIN_NONE;
169 callchain_param.enabled = false;
170 symbol_conf.use_callchain = false;
171 return 0;
172 }
173
174 if (!parse_callchain_mode(tok) ||
175 !parse_callchain_order(tok) ||
176 !parse_callchain_sort_key(tok) ||
177 !parse_callchain_value(tok)) {
178 /* parsing ok - move on to the next */
179 try_stack_size = false;
180 goto next;
181 } else if (allow_record_opt && !record_opt_set) {
182 if (parse_callchain_record(tok, &callchain_param))
183 goto try_numbers;
184
185 /* assume that number followed by 'dwarf' is stack size */
186 if (callchain_param.record_mode == CALLCHAIN_DWARF)
187 try_stack_size = true;
188
189 record_opt_set = true;
190 goto next;
191 }
192
193try_numbers:
194 if (try_stack_size) {
195 unsigned long size = 0;
196
197 if (get_stack_size(tok, &size) < 0)
198 return -1;
199 callchain_param.dump_size = size;
200 try_stack_size = false;
201 } else if (!minpcnt_set) {
202 /* try to get the min percent */
203 callchain_param.min_percent = strtod(tok, &endptr);
204 if (tok == endptr)
205 return -1;
206 minpcnt_set = true;
207 } else {
208 /* try print limit at last */
209 callchain_param.print_limit = strtoul(tok, &endptr, 0);
210 if (tok == endptr)
211 return -1;
212 }
213next:
214 arg = NULL;
215 }
216
217 if (callchain_register_param(&callchain_param) < 0) {
218 pr_err("Can't register callchain params\n");
219 return -1;
220 }
221 return 0;
222}
223
224int parse_callchain_report_opt(const char *arg)
225{
226 return __parse_callchain_report_opt(arg, false);
227}
228
229int parse_callchain_top_opt(const char *arg)
230{
231 return __parse_callchain_report_opt(arg, true);
232}
233
234int parse_callchain_record(const char *arg, struct callchain_param *param)
235{
236 char *tok, *name, *saveptr = NULL;
237 char *buf;
238 int ret = -1;
239
240 /* We need buffer that we know we can write to. */
241 buf = malloc(strlen(arg) + 1);
242 if (!buf)
243 return -ENOMEM;
244
245 strcpy(buf, arg);
246
247 tok = strtok_r((char *)buf, ",", &saveptr);
248 name = tok ? : (char *)buf;
249
250 do {
251 /* Framepointer style */
252 if (!strncmp(name, "fp", sizeof("fp"))) {
253 if (!strtok_r(NULL, ",", &saveptr)) {
254 param->record_mode = CALLCHAIN_FP;
255 ret = 0;
256 } else
257 pr_err("callchain: No more arguments "
258 "needed for --call-graph fp\n");
259 break;
260
261 /* Dwarf style */
262 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
263 const unsigned long default_stack_dump_size = 8192;
264
265 ret = 0;
266 param->record_mode = CALLCHAIN_DWARF;
267 param->dump_size = default_stack_dump_size;
268
269 tok = strtok_r(NULL, ",", &saveptr);
270 if (tok) {
271 unsigned long size = 0;
272
273 ret = get_stack_size(tok, &size);
274 param->dump_size = size;
275 }
276 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
277 if (!strtok_r(NULL, ",", &saveptr)) {
278 param->record_mode = CALLCHAIN_LBR;
279 ret = 0;
280 } else
281 pr_err("callchain: No more arguments "
282 "needed for --call-graph lbr\n");
283 break;
284 } else {
285 pr_err("callchain: Unknown --call-graph option "
286 "value: %s\n", arg);
287 break;
288 }
289
290 } while (0);
291
292 free(buf);
293 return ret;
294}
295
296int perf_callchain_config(const char *var, const char *value)
297{
298 char *endptr;
299
300 if (!strstarts(var, "call-graph."))
301 return 0;
302 var += sizeof("call-graph.") - 1;
303
304 if (!strcmp(var, "record-mode"))
305 return parse_callchain_record_opt(value, &callchain_param);
306 if (!strcmp(var, "dump-size")) {
307 unsigned long size = 0;
308 int ret;
309
310 ret = get_stack_size(value, &size);
311 callchain_param.dump_size = size;
312
313 return ret;
314 }
315 if (!strcmp(var, "print-type")){
316 int ret;
317 ret = parse_callchain_mode(value);
318 if (ret == -1)
319 pr_err("Invalid callchain mode: %s\n", value);
320 return ret;
321 }
322 if (!strcmp(var, "order")){
323 int ret;
324 ret = parse_callchain_order(value);
325 if (ret == -1)
326 pr_err("Invalid callchain order: %s\n", value);
327 return ret;
328 }
329 if (!strcmp(var, "sort-key")){
330 int ret;
331 ret = parse_callchain_sort_key(value);
332 if (ret == -1)
333 pr_err("Invalid callchain sort key: %s\n", value);
334 return ret;
335 }
336 if (!strcmp(var, "threshold")) {
337 callchain_param.min_percent = strtod(value, &endptr);
338 if (value == endptr) {
339 pr_err("Invalid callchain threshold: %s\n", value);
340 return -1;
341 }
342 }
343 if (!strcmp(var, "print-limit")) {
344 callchain_param.print_limit = strtod(value, &endptr);
345 if (value == endptr) {
346 pr_err("Invalid callchain print limit: %s\n", value);
347 return -1;
348 }
349 }
350
351 return 0;
352}
353
354static void
355rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
356 enum chain_mode mode)
357{
358 struct rb_node **p = &root->rb_node;
359 struct rb_node *parent = NULL;
360 struct callchain_node *rnode;
361 u64 chain_cumul = callchain_cumul_hits(chain);
362
363 while (*p) {
364 u64 rnode_cumul;
365
366 parent = *p;
367 rnode = rb_entry(parent, struct callchain_node, rb_node);
368 rnode_cumul = callchain_cumul_hits(rnode);
369
370 switch (mode) {
371 case CHAIN_FLAT:
372 case CHAIN_FOLDED:
373 if (rnode->hit < chain->hit)
374 p = &(*p)->rb_left;
375 else
376 p = &(*p)->rb_right;
377 break;
378 case CHAIN_GRAPH_ABS: /* Falldown */
379 case CHAIN_GRAPH_REL:
380 if (rnode_cumul < chain_cumul)
381 p = &(*p)->rb_left;
382 else
383 p = &(*p)->rb_right;
384 break;
385 case CHAIN_NONE:
386 default:
387 break;
388 }
389 }
390
391 rb_link_node(&chain->rb_node, parent, p);
392 rb_insert_color(&chain->rb_node, root);
393}
394
395static void
396__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
397 u64 min_hit)
398{
399 struct rb_node *n;
400 struct callchain_node *child;
401
402 n = rb_first(&node->rb_root_in);
403 while (n) {
404 child = rb_entry(n, struct callchain_node, rb_node_in);
405 n = rb_next(n);
406
407 __sort_chain_flat(rb_root, child, min_hit);
408 }
409
410 if (node->hit && node->hit >= min_hit)
411 rb_insert_callchain(rb_root, node, CHAIN_FLAT);
412}
413
414/*
415 * Once we get every callchains from the stream, we can now
416 * sort them by hit
417 */
418static void
419sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
420 u64 min_hit, struct callchain_param *param __maybe_unused)
421{
422 *rb_root = RB_ROOT;
423 __sort_chain_flat(rb_root, &root->node, min_hit);
424}
425
426static void __sort_chain_graph_abs(struct callchain_node *node,
427 u64 min_hit)
428{
429 struct rb_node *n;
430 struct callchain_node *child;
431
432 node->rb_root = RB_ROOT;
433 n = rb_first(&node->rb_root_in);
434
435 while (n) {
436 child = rb_entry(n, struct callchain_node, rb_node_in);
437 n = rb_next(n);
438
439 __sort_chain_graph_abs(child, min_hit);
440 if (callchain_cumul_hits(child) >= min_hit)
441 rb_insert_callchain(&node->rb_root, child,
442 CHAIN_GRAPH_ABS);
443 }
444}
445
446static void
447sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
448 u64 min_hit, struct callchain_param *param __maybe_unused)
449{
450 __sort_chain_graph_abs(&chain_root->node, min_hit);
451 rb_root->rb_node = chain_root->node.rb_root.rb_node;
452}
453
454static void __sort_chain_graph_rel(struct callchain_node *node,
455 double min_percent)
456{
457 struct rb_node *n;
458 struct callchain_node *child;
459 u64 min_hit;
460
461 node->rb_root = RB_ROOT;
462 min_hit = ceil(node->children_hit * min_percent);
463
464 n = rb_first(&node->rb_root_in);
465 while (n) {
466 child = rb_entry(n, struct callchain_node, rb_node_in);
467 n = rb_next(n);
468
469 __sort_chain_graph_rel(child, min_percent);
470 if (callchain_cumul_hits(child) >= min_hit)
471 rb_insert_callchain(&node->rb_root, child,
472 CHAIN_GRAPH_REL);
473 }
474}
475
476static void
477sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
478 u64 min_hit __maybe_unused, struct callchain_param *param)
479{
480 __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
481 rb_root->rb_node = chain_root->node.rb_root.rb_node;
482}
483
484int callchain_register_param(struct callchain_param *param)
485{
486 switch (param->mode) {
487 case CHAIN_GRAPH_ABS:
488 param->sort = sort_chain_graph_abs;
489 break;
490 case CHAIN_GRAPH_REL:
491 param->sort = sort_chain_graph_rel;
492 break;
493 case CHAIN_FLAT:
494 case CHAIN_FOLDED:
495 param->sort = sort_chain_flat;
496 break;
497 case CHAIN_NONE:
498 default:
499 return -1;
500 }
501 return 0;
502}
503
504/*
505 * Create a child for a parent. If inherit_children, then the new child
506 * will become the new parent of it's parent children
507 */
508static struct callchain_node *
509create_child(struct callchain_node *parent, bool inherit_children)
510{
511 struct callchain_node *new;
512
513 new = zalloc(sizeof(*new));
514 if (!new) {
515 perror("not enough memory to create child for code path tree");
516 return NULL;
517 }
518 new->parent = parent;
519 INIT_LIST_HEAD(&new->val);
520 INIT_LIST_HEAD(&new->parent_val);
521
522 if (inherit_children) {
523 struct rb_node *n;
524 struct callchain_node *child;
525
526 new->rb_root_in = parent->rb_root_in;
527 parent->rb_root_in = RB_ROOT;
528
529 n = rb_first(&new->rb_root_in);
530 while (n) {
531 child = rb_entry(n, struct callchain_node, rb_node_in);
532 child->parent = new;
533 n = rb_next(n);
534 }
535
536 /* make it the first child */
537 rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
538 rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
539 }
540
541 return new;
542}
543
544
545/*
546 * Fill the node with callchain values
547 */
548static int
549fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
550{
551 struct callchain_cursor_node *cursor_node;
552
553 node->val_nr = cursor->nr - cursor->pos;
554 if (!node->val_nr)
555 pr_warning("Warning: empty node in callchain tree\n");
556
557 cursor_node = callchain_cursor_current(cursor);
558
559 while (cursor_node) {
560 struct callchain_list *call;
561
562 call = zalloc(sizeof(*call));
563 if (!call) {
564 perror("not enough memory for the code path tree");
565 return -1;
566 }
567 call->ip = cursor_node->ip;
568 call->ms.sym = cursor_node->sym;
569 call->ms.map = map__get(cursor_node->map);
570 call->srcline = cursor_node->srcline;
571
572 if (cursor_node->branch) {
573 call->branch_count = 1;
574
575 if (cursor_node->branch_from) {
576 /*
577 * branch_from is set with value somewhere else
578 * to imply it's "to" of a branch.
579 */
580 call->brtype_stat.branch_to = true;
581
582 if (cursor_node->branch_flags.predicted)
583 call->predicted_count = 1;
584
585 if (cursor_node->branch_flags.abort)
586 call->abort_count = 1;
587
588 branch_type_count(&call->brtype_stat,
589 &cursor_node->branch_flags,
590 cursor_node->branch_from,
591 cursor_node->ip);
592 } else {
593 /*
594 * It's "from" of a branch
595 */
596 call->brtype_stat.branch_to = false;
597 call->cycles_count =
598 cursor_node->branch_flags.cycles;
599 call->iter_count = cursor_node->nr_loop_iter;
600 call->iter_cycles = cursor_node->iter_cycles;
601 }
602 }
603
604 list_add_tail(&call->list, &node->val);
605
606 callchain_cursor_advance(cursor);
607 cursor_node = callchain_cursor_current(cursor);
608 }
609 return 0;
610}
611
612static struct callchain_node *
613add_child(struct callchain_node *parent,
614 struct callchain_cursor *cursor,
615 u64 period)
616{
617 struct callchain_node *new;
618
619 new = create_child(parent, false);
620 if (new == NULL)
621 return NULL;
622
623 if (fill_node(new, cursor) < 0) {
624 struct callchain_list *call, *tmp;
625
626 list_for_each_entry_safe(call, tmp, &new->val, list) {
627 list_del(&call->list);
628 map__zput(call->ms.map);
629 free(call);
630 }
631 free(new);
632 return NULL;
633 }
634
635 new->children_hit = 0;
636 new->hit = period;
637 new->children_count = 0;
638 new->count = 1;
639 return new;
640}
641
642enum match_result {
643 MATCH_ERROR = -1,
644 MATCH_EQ,
645 MATCH_LT,
646 MATCH_GT,
647};
648
649static enum match_result match_chain_strings(const char *left,
650 const char *right)
651{
652 enum match_result ret = MATCH_EQ;
653 int cmp;
654
655 if (left && right)
656 cmp = strcmp(left, right);
657 else if (!left && right)
658 cmp = 1;
659 else if (left && !right)
660 cmp = -1;
661 else
662 return MATCH_ERROR;
663
664 if (cmp != 0)
665 ret = cmp < 0 ? MATCH_LT : MATCH_GT;
666
667 return ret;
668}
669
670/*
671 * We need to always use relative addresses because we're aggregating
672 * callchains from multiple threads, i.e. different address spaces, so
673 * comparing absolute addresses make no sense as a symbol in a DSO may end up
674 * in a different address when used in a different binary or even the same
675 * binary but with some sort of address randomization technique, thus we need
676 * to compare just relative addresses. -acme
677 */
678static enum match_result match_chain_dso_addresses(struct map *left_map, u64 left_ip,
679 struct map *right_map, u64 right_ip)
680{
681 struct dso *left_dso = left_map ? left_map->dso : NULL;
682 struct dso *right_dso = right_map ? right_map->dso : NULL;
683
684 if (left_dso != right_dso)
685 return left_dso < right_dso ? MATCH_LT : MATCH_GT;
686
687 if (left_ip != right_ip)
688 return left_ip < right_ip ? MATCH_LT : MATCH_GT;
689
690 return MATCH_EQ;
691}
692
693static enum match_result match_chain(struct callchain_cursor_node *node,
694 struct callchain_list *cnode)
695{
696 enum match_result match = MATCH_ERROR;
697
698 switch (callchain_param.key) {
699 case CCKEY_SRCLINE:
700 match = match_chain_strings(cnode->srcline, node->srcline);
701 if (match != MATCH_ERROR)
702 break;
703 /* otherwise fall-back to symbol-based comparison below */
704 __fallthrough;
705 case CCKEY_FUNCTION:
706 if (node->sym && cnode->ms.sym) {
707 /*
708 * Compare inlined frames based on their symbol name
709 * because different inlined frames will have the same
710 * symbol start. Otherwise do a faster comparison based
711 * on the symbol start address.
712 */
713 if (cnode->ms.sym->inlined || node->sym->inlined) {
714 match = match_chain_strings(cnode->ms.sym->name,
715 node->sym->name);
716 if (match != MATCH_ERROR)
717 break;
718 } else {
719 match = match_chain_dso_addresses(cnode->ms.map, cnode->ms.sym->start,
720 node->map, node->sym->start);
721 break;
722 }
723 }
724 /* otherwise fall-back to IP-based comparison below */
725 __fallthrough;
726 case CCKEY_ADDRESS:
727 default:
728 match = match_chain_dso_addresses(cnode->ms.map, cnode->ip, node->map, node->ip);
729 break;
730 }
731
732 if (match == MATCH_EQ && node->branch) {
733 cnode->branch_count++;
734
735 if (node->branch_from) {
736 /*
737 * It's "to" of a branch
738 */
739 cnode->brtype_stat.branch_to = true;
740
741 if (node->branch_flags.predicted)
742 cnode->predicted_count++;
743
744 if (node->branch_flags.abort)
745 cnode->abort_count++;
746
747 branch_type_count(&cnode->brtype_stat,
748 &node->branch_flags,
749 node->branch_from,
750 node->ip);
751 } else {
752 /*
753 * It's "from" of a branch
754 */
755 cnode->brtype_stat.branch_to = false;
756 cnode->cycles_count += node->branch_flags.cycles;
757 cnode->iter_count += node->nr_loop_iter;
758 cnode->iter_cycles += node->iter_cycles;
759 }
760 }
761
762 return match;
763}
764
765/*
766 * Split the parent in two parts (a new child is created) and
767 * give a part of its callchain to the created child.
768 * Then create another child to host the given callchain of new branch
769 */
770static int
771split_add_child(struct callchain_node *parent,
772 struct callchain_cursor *cursor,
773 struct callchain_list *to_split,
774 u64 idx_parents, u64 idx_local, u64 period)
775{
776 struct callchain_node *new;
777 struct list_head *old_tail;
778 unsigned int idx_total = idx_parents + idx_local;
779
780 /* split */
781 new = create_child(parent, true);
782 if (new == NULL)
783 return -1;
784
785 /* split the callchain and move a part to the new child */
786 old_tail = parent->val.prev;
787 list_del_range(&to_split->list, old_tail);
788 new->val.next = &to_split->list;
789 new->val.prev = old_tail;
790 to_split->list.prev = &new->val;
791 old_tail->next = &new->val;
792
793 /* split the hits */
794 new->hit = parent->hit;
795 new->children_hit = parent->children_hit;
796 parent->children_hit = callchain_cumul_hits(new);
797 new->val_nr = parent->val_nr - idx_local;
798 parent->val_nr = idx_local;
799 new->count = parent->count;
800 new->children_count = parent->children_count;
801 parent->children_count = callchain_cumul_counts(new);
802
803 /* create a new child for the new branch if any */
804 if (idx_total < cursor->nr) {
805 struct callchain_node *first;
806 struct callchain_list *cnode;
807 struct callchain_cursor_node *node;
808 struct rb_node *p, **pp;
809
810 parent->hit = 0;
811 parent->children_hit += period;
812 parent->count = 0;
813 parent->children_count += 1;
814
815 node = callchain_cursor_current(cursor);
816 new = add_child(parent, cursor, period);
817 if (new == NULL)
818 return -1;
819
820 /*
821 * This is second child since we moved parent's children
822 * to new (first) child above.
823 */
824 p = parent->rb_root_in.rb_node;
825 first = rb_entry(p, struct callchain_node, rb_node_in);
826 cnode = list_first_entry(&first->val, struct callchain_list,
827 list);
828
829 if (match_chain(node, cnode) == MATCH_LT)
830 pp = &p->rb_left;
831 else
832 pp = &p->rb_right;
833
834 rb_link_node(&new->rb_node_in, p, pp);
835 rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
836 } else {
837 parent->hit = period;
838 parent->count = 1;
839 }
840 return 0;
841}
842
843static enum match_result
844append_chain(struct callchain_node *root,
845 struct callchain_cursor *cursor,
846 u64 period);
847
848static int
849append_chain_children(struct callchain_node *root,
850 struct callchain_cursor *cursor,
851 u64 period)
852{
853 struct callchain_node *rnode;
854 struct callchain_cursor_node *node;
855 struct rb_node **p = &root->rb_root_in.rb_node;
856 struct rb_node *parent = NULL;
857
858 node = callchain_cursor_current(cursor);
859 if (!node)
860 return -1;
861
862 /* lookup in childrens */
863 while (*p) {
864 enum match_result ret;
865
866 parent = *p;
867 rnode = rb_entry(parent, struct callchain_node, rb_node_in);
868
869 /* If at least first entry matches, rely to children */
870 ret = append_chain(rnode, cursor, period);
871 if (ret == MATCH_EQ)
872 goto inc_children_hit;
873 if (ret == MATCH_ERROR)
874 return -1;
875
876 if (ret == MATCH_LT)
877 p = &parent->rb_left;
878 else
879 p = &parent->rb_right;
880 }
881 /* nothing in children, add to the current node */
882 rnode = add_child(root, cursor, period);
883 if (rnode == NULL)
884 return -1;
885
886 rb_link_node(&rnode->rb_node_in, parent, p);
887 rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
888
889inc_children_hit:
890 root->children_hit += period;
891 root->children_count++;
892 return 0;
893}
894
895static enum match_result
896append_chain(struct callchain_node *root,
897 struct callchain_cursor *cursor,
898 u64 period)
899{
900 struct callchain_list *cnode;
901 u64 start = cursor->pos;
902 bool found = false;
903 u64 matches;
904 enum match_result cmp = MATCH_ERROR;
905
906 /*
907 * Lookup in the current node
908 * If we have a symbol, then compare the start to match
909 * anywhere inside a function, unless function
910 * mode is disabled.
911 */
912 list_for_each_entry(cnode, &root->val, list) {
913 struct callchain_cursor_node *node;
914
915 node = callchain_cursor_current(cursor);
916 if (!node)
917 break;
918
919 cmp = match_chain(node, cnode);
920 if (cmp != MATCH_EQ)
921 break;
922
923 found = true;
924
925 callchain_cursor_advance(cursor);
926 }
927
928 /* matches not, relay no the parent */
929 if (!found) {
930 WARN_ONCE(cmp == MATCH_ERROR, "Chain comparison error\n");
931 return cmp;
932 }
933
934 matches = cursor->pos - start;
935
936 /* we match only a part of the node. Split it and add the new chain */
937 if (matches < root->val_nr) {
938 if (split_add_child(root, cursor, cnode, start, matches,
939 period) < 0)
940 return MATCH_ERROR;
941
942 return MATCH_EQ;
943 }
944
945 /* we match 100% of the path, increment the hit */
946 if (matches == root->val_nr && cursor->pos == cursor->nr) {
947 root->hit += period;
948 root->count++;
949 return MATCH_EQ;
950 }
951
952 /* We match the node and still have a part remaining */
953 if (append_chain_children(root, cursor, period) < 0)
954 return MATCH_ERROR;
955
956 return MATCH_EQ;
957}
958
959int callchain_append(struct callchain_root *root,
960 struct callchain_cursor *cursor,
961 u64 period)
962{
963 if (!cursor->nr)
964 return 0;
965
966 callchain_cursor_commit(cursor);
967
968 if (append_chain_children(&root->node, cursor, period) < 0)
969 return -1;
970
971 if (cursor->nr > root->max_depth)
972 root->max_depth = cursor->nr;
973
974 return 0;
975}
976
977static int
978merge_chain_branch(struct callchain_cursor *cursor,
979 struct callchain_node *dst, struct callchain_node *src)
980{
981 struct callchain_cursor_node **old_last = cursor->last;
982 struct callchain_node *child;
983 struct callchain_list *list, *next_list;
984 struct rb_node *n;
985 int old_pos = cursor->nr;
986 int err = 0;
987
988 list_for_each_entry_safe(list, next_list, &src->val, list) {
989 callchain_cursor_append(cursor, list->ip,
990 list->ms.map, list->ms.sym,
991 false, NULL, 0, 0, 0, list->srcline);
992 list_del(&list->list);
993 map__zput(list->ms.map);
994 free(list);
995 }
996
997 if (src->hit) {
998 callchain_cursor_commit(cursor);
999 if (append_chain_children(dst, cursor, src->hit) < 0)
1000 return -1;
1001 }
1002
1003 n = rb_first(&src->rb_root_in);
1004 while (n) {
1005 child = container_of(n, struct callchain_node, rb_node_in);
1006 n = rb_next(n);
1007 rb_erase(&child->rb_node_in, &src->rb_root_in);
1008
1009 err = merge_chain_branch(cursor, dst, child);
1010 if (err)
1011 break;
1012
1013 free(child);
1014 }
1015
1016 cursor->nr = old_pos;
1017 cursor->last = old_last;
1018
1019 return err;
1020}
1021
1022int callchain_merge(struct callchain_cursor *cursor,
1023 struct callchain_root *dst, struct callchain_root *src)
1024{
1025 return merge_chain_branch(cursor, &dst->node, &src->node);
1026}
1027
1028int callchain_cursor_append(struct callchain_cursor *cursor,
1029 u64 ip, struct map *map, struct symbol *sym,
1030 bool branch, struct branch_flags *flags,
1031 int nr_loop_iter, u64 iter_cycles, u64 branch_from,
1032 const char *srcline)
1033{
1034 struct callchain_cursor_node *node = *cursor->last;
1035
1036 if (!node) {
1037 node = calloc(1, sizeof(*node));
1038 if (!node)
1039 return -ENOMEM;
1040
1041 *cursor->last = node;
1042 }
1043
1044 node->ip = ip;
1045 map__zput(node->map);
1046 node->map = map__get(map);
1047 node->sym = sym;
1048 node->branch = branch;
1049 node->nr_loop_iter = nr_loop_iter;
1050 node->iter_cycles = iter_cycles;
1051 node->srcline = srcline;
1052
1053 if (flags)
1054 memcpy(&node->branch_flags, flags,
1055 sizeof(struct branch_flags));
1056
1057 node->branch_from = branch_from;
1058 cursor->nr++;
1059
1060 cursor->last = &node->next;
1061
1062 return 0;
1063}
1064
1065int sample__resolve_callchain(struct perf_sample *sample,
1066 struct callchain_cursor *cursor, struct symbol **parent,
1067 struct perf_evsel *evsel, struct addr_location *al,
1068 int max_stack)
1069{
1070 if (sample->callchain == NULL && !symbol_conf.show_branchflag_count)
1071 return 0;
1072
1073 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
1074 perf_hpp_list.parent || symbol_conf.show_branchflag_count) {
1075 return thread__resolve_callchain(al->thread, cursor, evsel, sample,
1076 parent, al, max_stack);
1077 }
1078 return 0;
1079}
1080
1081int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
1082{
1083 if ((!symbol_conf.use_callchain || sample->callchain == NULL) &&
1084 !symbol_conf.show_branchflag_count)
1085 return 0;
1086 return callchain_append(he->callchain, &callchain_cursor, sample->period);
1087}
1088
1089int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
1090 bool hide_unresolved)
1091{
1092 al->map = node->map;
1093 al->sym = node->sym;
1094 al->srcline = node->srcline;
1095 al->addr = node->ip;
1096
1097 if (al->sym == NULL) {
1098 if (hide_unresolved)
1099 return 0;
1100 if (al->map == NULL)
1101 goto out;
1102 }
1103
1104 if (al->map->groups == &al->machine->kmaps) {
1105 if (machine__is_host(al->machine)) {
1106 al->cpumode = PERF_RECORD_MISC_KERNEL;
1107 al->level = 'k';
1108 } else {
1109 al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
1110 al->level = 'g';
1111 }
1112 } else {
1113 if (machine__is_host(al->machine)) {
1114 al->cpumode = PERF_RECORD_MISC_USER;
1115 al->level = '.';
1116 } else if (perf_guest) {
1117 al->cpumode = PERF_RECORD_MISC_GUEST_USER;
1118 al->level = 'u';
1119 } else {
1120 al->cpumode = PERF_RECORD_MISC_HYPERVISOR;
1121 al->level = 'H';
1122 }
1123 }
1124
1125out:
1126 return 1;
1127}
1128
1129char *callchain_list__sym_name(struct callchain_list *cl,
1130 char *bf, size_t bfsize, bool show_dso)
1131{
1132 bool show_addr = callchain_param.key == CCKEY_ADDRESS;
1133 bool show_srcline = show_addr || callchain_param.key == CCKEY_SRCLINE;
1134 int printed;
1135
1136 if (cl->ms.sym) {
1137 const char *inlined = cl->ms.sym->inlined ? " (inlined)" : "";
1138
1139 if (show_srcline && cl->srcline)
1140 printed = scnprintf(bf, bfsize, "%s %s%s",
1141 cl->ms.sym->name, cl->srcline,
1142 inlined);
1143 else
1144 printed = scnprintf(bf, bfsize, "%s%s",
1145 cl->ms.sym->name, inlined);
1146 } else
1147 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
1148
1149 if (show_dso)
1150 scnprintf(bf + printed, bfsize - printed, " %s",
1151 cl->ms.map ?
1152 cl->ms.map->dso->short_name :
1153 "unknown");
1154
1155 return bf;
1156}
1157
1158char *callchain_node__scnprintf_value(struct callchain_node *node,
1159 char *bf, size_t bfsize, u64 total)
1160{
1161 double percent = 0.0;
1162 u64 period = callchain_cumul_hits(node);
1163 unsigned count = callchain_cumul_counts(node);
1164
1165 if (callchain_param.mode == CHAIN_FOLDED) {
1166 period = node->hit;
1167 count = node->count;
1168 }
1169
1170 switch (callchain_param.value) {
1171 case CCVAL_PERIOD:
1172 scnprintf(bf, bfsize, "%"PRIu64, period);
1173 break;
1174 case CCVAL_COUNT:
1175 scnprintf(bf, bfsize, "%u", count);
1176 break;
1177 case CCVAL_PERCENT:
1178 default:
1179 if (total)
1180 percent = period * 100.0 / total;
1181 scnprintf(bf, bfsize, "%.2f%%", percent);
1182 break;
1183 }
1184 return bf;
1185}
1186
1187int callchain_node__fprintf_value(struct callchain_node *node,
1188 FILE *fp, u64 total)
1189{
1190 double percent = 0.0;
1191 u64 period = callchain_cumul_hits(node);
1192 unsigned count = callchain_cumul_counts(node);
1193
1194 if (callchain_param.mode == CHAIN_FOLDED) {
1195 period = node->hit;
1196 count = node->count;
1197 }
1198
1199 switch (callchain_param.value) {
1200 case CCVAL_PERIOD:
1201 return fprintf(fp, "%"PRIu64, period);
1202 case CCVAL_COUNT:
1203 return fprintf(fp, "%u", count);
1204 case CCVAL_PERCENT:
1205 default:
1206 if (total)
1207 percent = period * 100.0 / total;
1208 return percent_color_fprintf(fp, "%.2f%%", percent);
1209 }
1210 return 0;
1211}
1212
1213static void callchain_counts_value(struct callchain_node *node,
1214 u64 *branch_count, u64 *predicted_count,
1215 u64 *abort_count, u64 *cycles_count)
1216{
1217 struct callchain_list *clist;
1218
1219 list_for_each_entry(clist, &node->val, list) {
1220 if (branch_count)
1221 *branch_count += clist->branch_count;
1222
1223 if (predicted_count)
1224 *predicted_count += clist->predicted_count;
1225
1226 if (abort_count)
1227 *abort_count += clist->abort_count;
1228
1229 if (cycles_count)
1230 *cycles_count += clist->cycles_count;
1231 }
1232}
1233
1234static int callchain_node_branch_counts_cumul(struct callchain_node *node,
1235 u64 *branch_count,
1236 u64 *predicted_count,
1237 u64 *abort_count,
1238 u64 *cycles_count)
1239{
1240 struct callchain_node *child;
1241 struct rb_node *n;
1242
1243 n = rb_first(&node->rb_root_in);
1244 while (n) {
1245 child = rb_entry(n, struct callchain_node, rb_node_in);
1246 n = rb_next(n);
1247
1248 callchain_node_branch_counts_cumul(child, branch_count,
1249 predicted_count,
1250 abort_count,
1251 cycles_count);
1252
1253 callchain_counts_value(child, branch_count,
1254 predicted_count, abort_count,
1255 cycles_count);
1256 }
1257
1258 return 0;
1259}
1260
1261int callchain_branch_counts(struct callchain_root *root,
1262 u64 *branch_count, u64 *predicted_count,
1263 u64 *abort_count, u64 *cycles_count)
1264{
1265 if (branch_count)
1266 *branch_count = 0;
1267
1268 if (predicted_count)
1269 *predicted_count = 0;
1270
1271 if (abort_count)
1272 *abort_count = 0;
1273
1274 if (cycles_count)
1275 *cycles_count = 0;
1276
1277 return callchain_node_branch_counts_cumul(&root->node,
1278 branch_count,
1279 predicted_count,
1280 abort_count,
1281 cycles_count);
1282}
1283
1284static int count_pri64_printf(int idx, const char *str, u64 value, char *bf, int bfsize)
1285{
1286 int printed;
1287
1288 printed = scnprintf(bf, bfsize, "%s%s:%" PRId64 "", (idx) ? " " : " (", str, value);
1289
1290 return printed;
1291}
1292
1293static int count_float_printf(int idx, const char *str, float value,
1294 char *bf, int bfsize, float threshold)
1295{
1296 int printed;
1297
1298 if (threshold != 0.0 && value < threshold)
1299 return 0;
1300
1301 printed = scnprintf(bf, bfsize, "%s%s:%.1f%%", (idx) ? " " : " (", str, value);
1302
1303 return printed;
1304}
1305
1306static int branch_to_str(char *bf, int bfsize,
1307 u64 branch_count, u64 predicted_count,
1308 u64 abort_count,
1309 struct branch_type_stat *brtype_stat)
1310{
1311 int printed, i = 0;
1312
1313 printed = branch_type_str(brtype_stat, bf, bfsize);
1314 if (printed)
1315 i++;
1316
1317 if (predicted_count < branch_count) {
1318 printed += count_float_printf(i++, "predicted",
1319 predicted_count * 100.0 / branch_count,
1320 bf + printed, bfsize - printed, 0.0);
1321 }
1322
1323 if (abort_count) {
1324 printed += count_float_printf(i++, "abort",
1325 abort_count * 100.0 / branch_count,
1326 bf + printed, bfsize - printed, 0.1);
1327 }
1328
1329 if (i)
1330 printed += scnprintf(bf + printed, bfsize - printed, ")");
1331
1332 return printed;
1333}
1334
1335static int branch_from_str(char *bf, int bfsize,
1336 u64 branch_count,
1337 u64 cycles_count, u64 iter_count,
1338 u64 iter_cycles)
1339{
1340 int printed = 0, i = 0;
1341 u64 cycles;
1342
1343 cycles = cycles_count / branch_count;
1344 if (cycles) {
1345 printed += count_pri64_printf(i++, "cycles",
1346 cycles,
1347 bf + printed, bfsize - printed);
1348 }
1349
1350 if (iter_count) {
1351 printed += count_pri64_printf(i++, "iter",
1352 iter_count,
1353 bf + printed, bfsize - printed);
1354
1355 printed += count_pri64_printf(i++, "avg_cycles",
1356 iter_cycles / iter_count,
1357 bf + printed, bfsize - printed);
1358 }
1359
1360 if (i)
1361 printed += scnprintf(bf + printed, bfsize - printed, ")");
1362
1363 return printed;
1364}
1365
1366static int counts_str_build(char *bf, int bfsize,
1367 u64 branch_count, u64 predicted_count,
1368 u64 abort_count, u64 cycles_count,
1369 u64 iter_count, u64 iter_cycles,
1370 struct branch_type_stat *brtype_stat)
1371{
1372 int printed;
1373
1374 if (branch_count == 0)
1375 return scnprintf(bf, bfsize, " (calltrace)");
1376
1377 if (brtype_stat->branch_to) {
1378 printed = branch_to_str(bf, bfsize, branch_count,
1379 predicted_count, abort_count, brtype_stat);
1380 } else {
1381 printed = branch_from_str(bf, bfsize, branch_count,
1382 cycles_count, iter_count, iter_cycles);
1383 }
1384
1385 if (!printed)
1386 bf[0] = 0;
1387
1388 return printed;
1389}
1390
1391static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1392 u64 branch_count, u64 predicted_count,
1393 u64 abort_count, u64 cycles_count,
1394 u64 iter_count, u64 iter_cycles,
1395 struct branch_type_stat *brtype_stat)
1396{
1397 char str[256];
1398
1399 counts_str_build(str, sizeof(str), branch_count,
1400 predicted_count, abort_count, cycles_count,
1401 iter_count, iter_cycles, brtype_stat);
1402
1403 if (fp)
1404 return fprintf(fp, "%s", str);
1405
1406 return scnprintf(bf, bfsize, "%s", str);
1407}
1408
1409int callchain_list_counts__printf_value(struct callchain_list *clist,
1410 FILE *fp, char *bf, int bfsize)
1411{
1412 u64 branch_count, predicted_count;
1413 u64 abort_count, cycles_count;
1414 u64 iter_count, iter_cycles;
1415
1416 branch_count = clist->branch_count;
1417 predicted_count = clist->predicted_count;
1418 abort_count = clist->abort_count;
1419 cycles_count = clist->cycles_count;
1420 iter_count = clist->iter_count;
1421 iter_cycles = clist->iter_cycles;
1422
1423 return callchain_counts_printf(fp, bf, bfsize, branch_count,
1424 predicted_count, abort_count,
1425 cycles_count, iter_count, iter_cycles,
1426 &clist->brtype_stat);
1427}
1428
1429static void free_callchain_node(struct callchain_node *node)
1430{
1431 struct callchain_list *list, *tmp;
1432 struct callchain_node *child;
1433 struct rb_node *n;
1434
1435 list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
1436 list_del(&list->list);
1437 map__zput(list->ms.map);
1438 free(list);
1439 }
1440
1441 list_for_each_entry_safe(list, tmp, &node->val, list) {
1442 list_del(&list->list);
1443 map__zput(list->ms.map);
1444 free(list);
1445 }
1446
1447 n = rb_first(&node->rb_root_in);
1448 while (n) {
1449 child = container_of(n, struct callchain_node, rb_node_in);
1450 n = rb_next(n);
1451 rb_erase(&child->rb_node_in, &node->rb_root_in);
1452
1453 free_callchain_node(child);
1454 free(child);
1455 }
1456}
1457
1458void free_callchain(struct callchain_root *root)
1459{
1460 if (!symbol_conf.use_callchain)
1461 return;
1462
1463 free_callchain_node(&root->node);
1464}
1465
1466static u64 decay_callchain_node(struct callchain_node *node)
1467{
1468 struct callchain_node *child;
1469 struct rb_node *n;
1470 u64 child_hits = 0;
1471
1472 n = rb_first(&node->rb_root_in);
1473 while (n) {
1474 child = container_of(n, struct callchain_node, rb_node_in);
1475
1476 child_hits += decay_callchain_node(child);
1477 n = rb_next(n);
1478 }
1479
1480 node->hit = (node->hit * 7) / 8;
1481 node->children_hit = child_hits;
1482
1483 return node->hit;
1484}
1485
1486void decay_callchain(struct callchain_root *root)
1487{
1488 if (!symbol_conf.use_callchain)
1489 return;
1490
1491 decay_callchain_node(&root->node);
1492}
1493
1494int callchain_node__make_parent_list(struct callchain_node *node)
1495{
1496 struct callchain_node *parent = node->parent;
1497 struct callchain_list *chain, *new;
1498 LIST_HEAD(head);
1499
1500 while (parent) {
1501 list_for_each_entry_reverse(chain, &parent->val, list) {
1502 new = malloc(sizeof(*new));
1503 if (new == NULL)
1504 goto out;
1505 *new = *chain;
1506 new->has_children = false;
1507 map__get(new->ms.map);
1508 list_add_tail(&new->list, &head);
1509 }
1510 parent = parent->parent;
1511 }
1512
1513 list_for_each_entry_safe_reverse(chain, new, &head, list)
1514 list_move_tail(&chain->list, &node->parent_val);
1515
1516 if (!list_empty(&node->parent_val)) {
1517 chain = list_first_entry(&node->parent_val, struct callchain_list, list);
1518 chain->has_children = rb_prev(&node->rb_node) || rb_next(&node->rb_node);
1519
1520 chain = list_first_entry(&node->val, struct callchain_list, list);
1521 chain->has_children = false;
1522 }
1523 return 0;
1524
1525out:
1526 list_for_each_entry_safe(chain, new, &head, list) {
1527 list_del(&chain->list);
1528 map__zput(chain->ms.map);
1529 free(chain);
1530 }
1531 return -ENOMEM;
1532}
1533
1534int callchain_cursor__copy(struct callchain_cursor *dst,
1535 struct callchain_cursor *src)
1536{
1537 int rc = 0;
1538
1539 callchain_cursor_reset(dst);
1540 callchain_cursor_commit(src);
1541
1542 while (true) {
1543 struct callchain_cursor_node *node;
1544
1545 node = callchain_cursor_current(src);
1546 if (node == NULL)
1547 break;
1548
1549 rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
1550 node->branch, &node->branch_flags,
1551 node->nr_loop_iter,
1552 node->iter_cycles,
1553 node->branch_from, node->srcline);
1554 if (rc)
1555 break;
1556
1557 callchain_cursor_advance(src);
1558 }
1559
1560 return rc;
1561}