• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
3  *
4  * Handle the callchains from the stream in an ad-hoc radix tree and then
5  * sort them in an rbtree.
6  *
7  * Using a radix for code path provides a fast retrieval and factorizes
8  * memory use. Also that lets us use the paths in a hierarchical graph view.
9  *
10  */
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <stdbool.h>
15 #include <errno.h>
16 #include <math.h>
17 
18 #include "asm/bug.h"
19 
20 #include "hist.h"
21 #include "util.h"
22 #include "sort.h"
23 #include "machine.h"
24 #include "callchain.h"
25 
26 __thread struct callchain_cursor callchain_cursor;
27 
parse_callchain_record_opt(const char * arg,struct callchain_param * param)28 int parse_callchain_record_opt(const char *arg, struct callchain_param *param)
29 {
30 	return parse_callchain_record(arg, param);
31 }
32 
parse_callchain_mode(const char * value)33 static int parse_callchain_mode(const char *value)
34 {
35 	if (!strncmp(value, "graph", strlen(value))) {
36 		callchain_param.mode = CHAIN_GRAPH_ABS;
37 		return 0;
38 	}
39 	if (!strncmp(value, "flat", strlen(value))) {
40 		callchain_param.mode = CHAIN_FLAT;
41 		return 0;
42 	}
43 	if (!strncmp(value, "fractal", strlen(value))) {
44 		callchain_param.mode = CHAIN_GRAPH_REL;
45 		return 0;
46 	}
47 	return -1;
48 }
49 
parse_callchain_order(const char * value)50 static int parse_callchain_order(const char *value)
51 {
52 	if (!strncmp(value, "caller", strlen(value))) {
53 		callchain_param.order = ORDER_CALLER;
54 		callchain_param.order_set = true;
55 		return 0;
56 	}
57 	if (!strncmp(value, "callee", strlen(value))) {
58 		callchain_param.order = ORDER_CALLEE;
59 		callchain_param.order_set = true;
60 		return 0;
61 	}
62 	return -1;
63 }
64 
parse_callchain_sort_key(const char * value)65 static int parse_callchain_sort_key(const char *value)
66 {
67 	if (!strncmp(value, "function", strlen(value))) {
68 		callchain_param.key = CCKEY_FUNCTION;
69 		return 0;
70 	}
71 	if (!strncmp(value, "address", strlen(value))) {
72 		callchain_param.key = CCKEY_ADDRESS;
73 		return 0;
74 	}
75 	if (!strncmp(value, "branch", strlen(value))) {
76 		callchain_param.branch_callstack = 1;
77 		return 0;
78 	}
79 	return -1;
80 }
81 
82 static int
__parse_callchain_report_opt(const char * arg,bool allow_record_opt)83 __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
84 {
85 	char *tok;
86 	char *endptr;
87 	bool minpcnt_set = false;
88 	bool record_opt_set = false;
89 	bool try_stack_size = false;
90 
91 	symbol_conf.use_callchain = true;
92 
93 	if (!arg)
94 		return 0;
95 
96 	while ((tok = strtok((char *)arg, ",")) != NULL) {
97 		if (!strncmp(tok, "none", strlen(tok))) {
98 			callchain_param.mode = CHAIN_NONE;
99 			symbol_conf.use_callchain = false;
100 			return 0;
101 		}
102 
103 		if (!parse_callchain_mode(tok) ||
104 		    !parse_callchain_order(tok) ||
105 		    !parse_callchain_sort_key(tok)) {
106 			/* parsing ok - move on to the next */
107 			try_stack_size = false;
108 			goto next;
109 		} else if (allow_record_opt && !record_opt_set) {
110 			if (parse_callchain_record(tok, &callchain_param))
111 				goto try_numbers;
112 
113 			/* assume that number followed by 'dwarf' is stack size */
114 			if (callchain_param.record_mode == CALLCHAIN_DWARF)
115 				try_stack_size = true;
116 
117 			record_opt_set = true;
118 			goto next;
119 		}
120 
121 try_numbers:
122 		if (try_stack_size) {
123 			unsigned long size = 0;
124 
125 			if (get_stack_size(tok, &size) < 0)
126 				return -1;
127 			callchain_param.dump_size = size;
128 			try_stack_size = false;
129 		} else if (!minpcnt_set) {
130 			/* try to get the min percent */
131 			callchain_param.min_percent = strtod(tok, &endptr);
132 			if (tok == endptr)
133 				return -1;
134 			minpcnt_set = true;
135 		} else {
136 			/* try print limit at last */
137 			callchain_param.print_limit = strtoul(tok, &endptr, 0);
138 			if (tok == endptr)
139 				return -1;
140 		}
141 next:
142 		arg = NULL;
143 	}
144 
145 	if (callchain_register_param(&callchain_param) < 0) {
146 		pr_err("Can't register callchain params\n");
147 		return -1;
148 	}
149 	return 0;
150 }
151 
parse_callchain_report_opt(const char * arg)152 int parse_callchain_report_opt(const char *arg)
153 {
154 	return __parse_callchain_report_opt(arg, false);
155 }
156 
parse_callchain_top_opt(const char * arg)157 int parse_callchain_top_opt(const char *arg)
158 {
159 	return __parse_callchain_report_opt(arg, true);
160 }
161 
perf_callchain_config(const char * var,const char * value)162 int perf_callchain_config(const char *var, const char *value)
163 {
164 	char *endptr;
165 
166 	if (prefixcmp(var, "call-graph."))
167 		return 0;
168 	var += sizeof("call-graph.") - 1;
169 
170 	if (!strcmp(var, "record-mode"))
171 		return parse_callchain_record_opt(value, &callchain_param);
172 #ifdef HAVE_DWARF_UNWIND_SUPPORT
173 	if (!strcmp(var, "dump-size")) {
174 		unsigned long size = 0;
175 		int ret;
176 
177 		ret = get_stack_size(value, &size);
178 		callchain_param.dump_size = size;
179 
180 		return ret;
181 	}
182 #endif
183 	if (!strcmp(var, "print-type"))
184 		return parse_callchain_mode(value);
185 	if (!strcmp(var, "order"))
186 		return parse_callchain_order(value);
187 	if (!strcmp(var, "sort-key"))
188 		return parse_callchain_sort_key(value);
189 	if (!strcmp(var, "threshold")) {
190 		callchain_param.min_percent = strtod(value, &endptr);
191 		if (value == endptr)
192 			return -1;
193 	}
194 	if (!strcmp(var, "print-limit")) {
195 		callchain_param.print_limit = strtod(value, &endptr);
196 		if (value == endptr)
197 			return -1;
198 	}
199 
200 	return 0;
201 }
202 
203 static void
rb_insert_callchain(struct rb_root * root,struct callchain_node * chain,enum chain_mode mode)204 rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
205 		    enum chain_mode mode)
206 {
207 	struct rb_node **p = &root->rb_node;
208 	struct rb_node *parent = NULL;
209 	struct callchain_node *rnode;
210 	u64 chain_cumul = callchain_cumul_hits(chain);
211 
212 	while (*p) {
213 		u64 rnode_cumul;
214 
215 		parent = *p;
216 		rnode = rb_entry(parent, struct callchain_node, rb_node);
217 		rnode_cumul = callchain_cumul_hits(rnode);
218 
219 		switch (mode) {
220 		case CHAIN_FLAT:
221 			if (rnode->hit < chain->hit)
222 				p = &(*p)->rb_left;
223 			else
224 				p = &(*p)->rb_right;
225 			break;
226 		case CHAIN_GRAPH_ABS: /* Falldown */
227 		case CHAIN_GRAPH_REL:
228 			if (rnode_cumul < chain_cumul)
229 				p = &(*p)->rb_left;
230 			else
231 				p = &(*p)->rb_right;
232 			break;
233 		case CHAIN_NONE:
234 		default:
235 			break;
236 		}
237 	}
238 
239 	rb_link_node(&chain->rb_node, parent, p);
240 	rb_insert_color(&chain->rb_node, root);
241 }
242 
243 static void
__sort_chain_flat(struct rb_root * rb_root,struct callchain_node * node,u64 min_hit)244 __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
245 		  u64 min_hit)
246 {
247 	struct rb_node *n;
248 	struct callchain_node *child;
249 
250 	n = rb_first(&node->rb_root_in);
251 	while (n) {
252 		child = rb_entry(n, struct callchain_node, rb_node_in);
253 		n = rb_next(n);
254 
255 		__sort_chain_flat(rb_root, child, min_hit);
256 	}
257 
258 	if (node->hit && node->hit >= min_hit)
259 		rb_insert_callchain(rb_root, node, CHAIN_FLAT);
260 }
261 
262 /*
263  * Once we get every callchains from the stream, we can now
264  * sort them by hit
265  */
266 static void
sort_chain_flat(struct rb_root * rb_root,struct callchain_root * root,u64 min_hit,struct callchain_param * param __maybe_unused)267 sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
268 		u64 min_hit, struct callchain_param *param __maybe_unused)
269 {
270 	__sort_chain_flat(rb_root, &root->node, min_hit);
271 }
272 
__sort_chain_graph_abs(struct callchain_node * node,u64 min_hit)273 static void __sort_chain_graph_abs(struct callchain_node *node,
274 				   u64 min_hit)
275 {
276 	struct rb_node *n;
277 	struct callchain_node *child;
278 
279 	node->rb_root = RB_ROOT;
280 	n = rb_first(&node->rb_root_in);
281 
282 	while (n) {
283 		child = rb_entry(n, struct callchain_node, rb_node_in);
284 		n = rb_next(n);
285 
286 		__sort_chain_graph_abs(child, min_hit);
287 		if (callchain_cumul_hits(child) >= min_hit)
288 			rb_insert_callchain(&node->rb_root, child,
289 					    CHAIN_GRAPH_ABS);
290 	}
291 }
292 
293 static void
sort_chain_graph_abs(struct rb_root * rb_root,struct callchain_root * chain_root,u64 min_hit,struct callchain_param * param __maybe_unused)294 sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
295 		     u64 min_hit, struct callchain_param *param __maybe_unused)
296 {
297 	__sort_chain_graph_abs(&chain_root->node, min_hit);
298 	rb_root->rb_node = chain_root->node.rb_root.rb_node;
299 }
300 
__sort_chain_graph_rel(struct callchain_node * node,double min_percent)301 static void __sort_chain_graph_rel(struct callchain_node *node,
302 				   double min_percent)
303 {
304 	struct rb_node *n;
305 	struct callchain_node *child;
306 	u64 min_hit;
307 
308 	node->rb_root = RB_ROOT;
309 	min_hit = ceil(node->children_hit * min_percent);
310 
311 	n = rb_first(&node->rb_root_in);
312 	while (n) {
313 		child = rb_entry(n, struct callchain_node, rb_node_in);
314 		n = rb_next(n);
315 
316 		__sort_chain_graph_rel(child, min_percent);
317 		if (callchain_cumul_hits(child) >= min_hit)
318 			rb_insert_callchain(&node->rb_root, child,
319 					    CHAIN_GRAPH_REL);
320 	}
321 }
322 
323 static void
sort_chain_graph_rel(struct rb_root * rb_root,struct callchain_root * chain_root,u64 min_hit __maybe_unused,struct callchain_param * param)324 sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
325 		     u64 min_hit __maybe_unused, struct callchain_param *param)
326 {
327 	__sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
328 	rb_root->rb_node = chain_root->node.rb_root.rb_node;
329 }
330 
callchain_register_param(struct callchain_param * param)331 int callchain_register_param(struct callchain_param *param)
332 {
333 	switch (param->mode) {
334 	case CHAIN_GRAPH_ABS:
335 		param->sort = sort_chain_graph_abs;
336 		break;
337 	case CHAIN_GRAPH_REL:
338 		param->sort = sort_chain_graph_rel;
339 		break;
340 	case CHAIN_FLAT:
341 		param->sort = sort_chain_flat;
342 		break;
343 	case CHAIN_NONE:
344 	default:
345 		return -1;
346 	}
347 	return 0;
348 }
349 
350 /*
351  * Create a child for a parent. If inherit_children, then the new child
352  * will become the new parent of it's parent children
353  */
354 static struct callchain_node *
create_child(struct callchain_node * parent,bool inherit_children)355 create_child(struct callchain_node *parent, bool inherit_children)
356 {
357 	struct callchain_node *new;
358 
359 	new = zalloc(sizeof(*new));
360 	if (!new) {
361 		perror("not enough memory to create child for code path tree");
362 		return NULL;
363 	}
364 	new->parent = parent;
365 	INIT_LIST_HEAD(&new->val);
366 
367 	if (inherit_children) {
368 		struct rb_node *n;
369 		struct callchain_node *child;
370 
371 		new->rb_root_in = parent->rb_root_in;
372 		parent->rb_root_in = RB_ROOT;
373 
374 		n = rb_first(&new->rb_root_in);
375 		while (n) {
376 			child = rb_entry(n, struct callchain_node, rb_node_in);
377 			child->parent = new;
378 			n = rb_next(n);
379 		}
380 
381 		/* make it the first child */
382 		rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
383 		rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
384 	}
385 
386 	return new;
387 }
388 
389 
390 /*
391  * Fill the node with callchain values
392  */
393 static void
fill_node(struct callchain_node * node,struct callchain_cursor * cursor)394 fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
395 {
396 	struct callchain_cursor_node *cursor_node;
397 
398 	node->val_nr = cursor->nr - cursor->pos;
399 	if (!node->val_nr)
400 		pr_warning("Warning: empty node in callchain tree\n");
401 
402 	cursor_node = callchain_cursor_current(cursor);
403 
404 	while (cursor_node) {
405 		struct callchain_list *call;
406 
407 		call = zalloc(sizeof(*call));
408 		if (!call) {
409 			perror("not enough memory for the code path tree");
410 			return;
411 		}
412 		call->ip = cursor_node->ip;
413 		call->ms.sym = cursor_node->sym;
414 		call->ms.map = cursor_node->map;
415 		list_add_tail(&call->list, &node->val);
416 
417 		callchain_cursor_advance(cursor);
418 		cursor_node = callchain_cursor_current(cursor);
419 	}
420 }
421 
422 static struct callchain_node *
add_child(struct callchain_node * parent,struct callchain_cursor * cursor,u64 period)423 add_child(struct callchain_node *parent,
424 	  struct callchain_cursor *cursor,
425 	  u64 period)
426 {
427 	struct callchain_node *new;
428 
429 	new = create_child(parent, false);
430 	fill_node(new, cursor);
431 
432 	new->children_hit = 0;
433 	new->hit = period;
434 	return new;
435 }
436 
match_chain(struct callchain_cursor_node * node,struct callchain_list * cnode)437 static s64 match_chain(struct callchain_cursor_node *node,
438 		      struct callchain_list *cnode)
439 {
440 	struct symbol *sym = node->sym;
441 
442 	if (cnode->ms.sym && sym &&
443 	    callchain_param.key == CCKEY_FUNCTION)
444 		return cnode->ms.sym->start - sym->start;
445 	else
446 		return cnode->ip - node->ip;
447 }
448 
449 /*
450  * Split the parent in two parts (a new child is created) and
451  * give a part of its callchain to the created child.
452  * Then create another child to host the given callchain of new branch
453  */
454 static void
split_add_child(struct callchain_node * parent,struct callchain_cursor * cursor,struct callchain_list * to_split,u64 idx_parents,u64 idx_local,u64 period)455 split_add_child(struct callchain_node *parent,
456 		struct callchain_cursor *cursor,
457 		struct callchain_list *to_split,
458 		u64 idx_parents, u64 idx_local, u64 period)
459 {
460 	struct callchain_node *new;
461 	struct list_head *old_tail;
462 	unsigned int idx_total = idx_parents + idx_local;
463 
464 	/* split */
465 	new = create_child(parent, true);
466 
467 	/* split the callchain and move a part to the new child */
468 	old_tail = parent->val.prev;
469 	list_del_range(&to_split->list, old_tail);
470 	new->val.next = &to_split->list;
471 	new->val.prev = old_tail;
472 	to_split->list.prev = &new->val;
473 	old_tail->next = &new->val;
474 
475 	/* split the hits */
476 	new->hit = parent->hit;
477 	new->children_hit = parent->children_hit;
478 	parent->children_hit = callchain_cumul_hits(new);
479 	new->val_nr = parent->val_nr - idx_local;
480 	parent->val_nr = idx_local;
481 
482 	/* create a new child for the new branch if any */
483 	if (idx_total < cursor->nr) {
484 		struct callchain_node *first;
485 		struct callchain_list *cnode;
486 		struct callchain_cursor_node *node;
487 		struct rb_node *p, **pp;
488 
489 		parent->hit = 0;
490 		parent->children_hit += period;
491 
492 		node = callchain_cursor_current(cursor);
493 		new = add_child(parent, cursor, period);
494 
495 		/*
496 		 * This is second child since we moved parent's children
497 		 * to new (first) child above.
498 		 */
499 		p = parent->rb_root_in.rb_node;
500 		first = rb_entry(p, struct callchain_node, rb_node_in);
501 		cnode = list_first_entry(&first->val, struct callchain_list,
502 					 list);
503 
504 		if (match_chain(node, cnode) < 0)
505 			pp = &p->rb_left;
506 		else
507 			pp = &p->rb_right;
508 
509 		rb_link_node(&new->rb_node_in, p, pp);
510 		rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
511 	} else {
512 		parent->hit = period;
513 	}
514 }
515 
516 static int
517 append_chain(struct callchain_node *root,
518 	     struct callchain_cursor *cursor,
519 	     u64 period);
520 
521 static void
append_chain_children(struct callchain_node * root,struct callchain_cursor * cursor,u64 period)522 append_chain_children(struct callchain_node *root,
523 		      struct callchain_cursor *cursor,
524 		      u64 period)
525 {
526 	struct callchain_node *rnode;
527 	struct callchain_cursor_node *node;
528 	struct rb_node **p = &root->rb_root_in.rb_node;
529 	struct rb_node *parent = NULL;
530 
531 	node = callchain_cursor_current(cursor);
532 	if (!node)
533 		return;
534 
535 	/* lookup in childrens */
536 	while (*p) {
537 		s64 ret;
538 
539 		parent = *p;
540 		rnode = rb_entry(parent, struct callchain_node, rb_node_in);
541 
542 		/* If at least first entry matches, rely to children */
543 		ret = append_chain(rnode, cursor, period);
544 		if (ret == 0)
545 			goto inc_children_hit;
546 
547 		if (ret < 0)
548 			p = &parent->rb_left;
549 		else
550 			p = &parent->rb_right;
551 	}
552 	/* nothing in children, add to the current node */
553 	rnode = add_child(root, cursor, period);
554 	rb_link_node(&rnode->rb_node_in, parent, p);
555 	rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
556 
557 inc_children_hit:
558 	root->children_hit += period;
559 }
560 
561 static int
append_chain(struct callchain_node * root,struct callchain_cursor * cursor,u64 period)562 append_chain(struct callchain_node *root,
563 	     struct callchain_cursor *cursor,
564 	     u64 period)
565 {
566 	struct callchain_list *cnode;
567 	u64 start = cursor->pos;
568 	bool found = false;
569 	u64 matches;
570 	int cmp = 0;
571 
572 	/*
573 	 * Lookup in the current node
574 	 * If we have a symbol, then compare the start to match
575 	 * anywhere inside a function, unless function
576 	 * mode is disabled.
577 	 */
578 	list_for_each_entry(cnode, &root->val, list) {
579 		struct callchain_cursor_node *node;
580 
581 		node = callchain_cursor_current(cursor);
582 		if (!node)
583 			break;
584 
585 		cmp = match_chain(node, cnode);
586 		if (cmp)
587 			break;
588 
589 		found = true;
590 
591 		callchain_cursor_advance(cursor);
592 	}
593 
594 	/* matches not, relay no the parent */
595 	if (!found) {
596 		WARN_ONCE(!cmp, "Chain comparison error\n");
597 		return cmp;
598 	}
599 
600 	matches = cursor->pos - start;
601 
602 	/* we match only a part of the node. Split it and add the new chain */
603 	if (matches < root->val_nr) {
604 		split_add_child(root, cursor, cnode, start, matches, period);
605 		return 0;
606 	}
607 
608 	/* we match 100% of the path, increment the hit */
609 	if (matches == root->val_nr && cursor->pos == cursor->nr) {
610 		root->hit += period;
611 		return 0;
612 	}
613 
614 	/* We match the node and still have a part remaining */
615 	append_chain_children(root, cursor, period);
616 
617 	return 0;
618 }
619 
callchain_append(struct callchain_root * root,struct callchain_cursor * cursor,u64 period)620 int callchain_append(struct callchain_root *root,
621 		     struct callchain_cursor *cursor,
622 		     u64 period)
623 {
624 	if (!cursor->nr)
625 		return 0;
626 
627 	callchain_cursor_commit(cursor);
628 
629 	append_chain_children(&root->node, cursor, period);
630 
631 	if (cursor->nr > root->max_depth)
632 		root->max_depth = cursor->nr;
633 
634 	return 0;
635 }
636 
637 static int
merge_chain_branch(struct callchain_cursor * cursor,struct callchain_node * dst,struct callchain_node * src)638 merge_chain_branch(struct callchain_cursor *cursor,
639 		   struct callchain_node *dst, struct callchain_node *src)
640 {
641 	struct callchain_cursor_node **old_last = cursor->last;
642 	struct callchain_node *child;
643 	struct callchain_list *list, *next_list;
644 	struct rb_node *n;
645 	int old_pos = cursor->nr;
646 	int err = 0;
647 
648 	list_for_each_entry_safe(list, next_list, &src->val, list) {
649 		callchain_cursor_append(cursor, list->ip,
650 					list->ms.map, list->ms.sym);
651 		list_del(&list->list);
652 		free(list);
653 	}
654 
655 	if (src->hit) {
656 		callchain_cursor_commit(cursor);
657 		append_chain_children(dst, cursor, src->hit);
658 	}
659 
660 	n = rb_first(&src->rb_root_in);
661 	while (n) {
662 		child = container_of(n, struct callchain_node, rb_node_in);
663 		n = rb_next(n);
664 		rb_erase(&child->rb_node_in, &src->rb_root_in);
665 
666 		err = merge_chain_branch(cursor, dst, child);
667 		if (err)
668 			break;
669 
670 		free(child);
671 	}
672 
673 	cursor->nr = old_pos;
674 	cursor->last = old_last;
675 
676 	return err;
677 }
678 
callchain_merge(struct callchain_cursor * cursor,struct callchain_root * dst,struct callchain_root * src)679 int callchain_merge(struct callchain_cursor *cursor,
680 		    struct callchain_root *dst, struct callchain_root *src)
681 {
682 	return merge_chain_branch(cursor, &dst->node, &src->node);
683 }
684 
callchain_cursor_append(struct callchain_cursor * cursor,u64 ip,struct map * map,struct symbol * sym)685 int callchain_cursor_append(struct callchain_cursor *cursor,
686 			    u64 ip, struct map *map, struct symbol *sym)
687 {
688 	struct callchain_cursor_node *node = *cursor->last;
689 
690 	if (!node) {
691 		node = calloc(1, sizeof(*node));
692 		if (!node)
693 			return -ENOMEM;
694 
695 		*cursor->last = node;
696 	}
697 
698 	node->ip = ip;
699 	node->map = map;
700 	node->sym = sym;
701 
702 	cursor->nr++;
703 
704 	cursor->last = &node->next;
705 
706 	return 0;
707 }
708 
sample__resolve_callchain(struct perf_sample * sample,struct symbol ** parent,struct perf_evsel * evsel,struct addr_location * al,int max_stack)709 int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
710 			      struct perf_evsel *evsel, struct addr_location *al,
711 			      int max_stack)
712 {
713 	if (sample->callchain == NULL)
714 		return 0;
715 
716 	if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
717 	    sort__has_parent) {
718 		return thread__resolve_callchain(al->thread, evsel, sample,
719 						 parent, al, max_stack);
720 	}
721 	return 0;
722 }
723 
hist_entry__append_callchain(struct hist_entry * he,struct perf_sample * sample)724 int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
725 {
726 	if (!symbol_conf.use_callchain || sample->callchain == NULL)
727 		return 0;
728 	return callchain_append(he->callchain, &callchain_cursor, sample->period);
729 }
730 
fill_callchain_info(struct addr_location * al,struct callchain_cursor_node * node,bool hide_unresolved)731 int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
732 			bool hide_unresolved)
733 {
734 	al->map = node->map;
735 	al->sym = node->sym;
736 	if (node->map)
737 		al->addr = node->map->map_ip(node->map, node->ip);
738 	else
739 		al->addr = node->ip;
740 
741 	if (al->sym == NULL) {
742 		if (hide_unresolved)
743 			return 0;
744 		if (al->map == NULL)
745 			goto out;
746 	}
747 
748 	if (al->map->groups == &al->machine->kmaps) {
749 		if (machine__is_host(al->machine)) {
750 			al->cpumode = PERF_RECORD_MISC_KERNEL;
751 			al->level = 'k';
752 		} else {
753 			al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
754 			al->level = 'g';
755 		}
756 	} else {
757 		if (machine__is_host(al->machine)) {
758 			al->cpumode = PERF_RECORD_MISC_USER;
759 			al->level = '.';
760 		} else if (perf_guest) {
761 			al->cpumode = PERF_RECORD_MISC_GUEST_USER;
762 			al->level = 'u';
763 		} else {
764 			al->cpumode = PERF_RECORD_MISC_HYPERVISOR;
765 			al->level = 'H';
766 		}
767 	}
768 
769 out:
770 	return 1;
771 }
772 
callchain_list__sym_name(struct callchain_list * cl,char * bf,size_t bfsize,bool show_dso)773 char *callchain_list__sym_name(struct callchain_list *cl,
774 			       char *bf, size_t bfsize, bool show_dso)
775 {
776 	int printed;
777 
778 	if (cl->ms.sym) {
779 		if (callchain_param.key == CCKEY_ADDRESS &&
780 		    cl->ms.map && !cl->srcline)
781 			cl->srcline = get_srcline(cl->ms.map->dso,
782 						  map__rip_2objdump(cl->ms.map,
783 								    cl->ip),
784 						  cl->ms.sym, false);
785 		if (cl->srcline)
786 			printed = scnprintf(bf, bfsize, "%s %s",
787 					cl->ms.sym->name, cl->srcline);
788 		else
789 			printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
790 	} else
791 		printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
792 
793 	if (show_dso)
794 		scnprintf(bf + printed, bfsize - printed, " %s",
795 			  cl->ms.map ?
796 			  cl->ms.map->dso->short_name :
797 			  "unknown");
798 
799 	return bf;
800 }
801 
free_callchain_node(struct callchain_node * node)802 static void free_callchain_node(struct callchain_node *node)
803 {
804 	struct callchain_list *list, *tmp;
805 	struct callchain_node *child;
806 	struct rb_node *n;
807 
808 	list_for_each_entry_safe(list, tmp, &node->val, list) {
809 		list_del(&list->list);
810 		free(list);
811 	}
812 
813 	n = rb_first(&node->rb_root_in);
814 	while (n) {
815 		child = container_of(n, struct callchain_node, rb_node_in);
816 		n = rb_next(n);
817 		rb_erase(&child->rb_node_in, &node->rb_root_in);
818 
819 		free_callchain_node(child);
820 		free(child);
821 	}
822 }
823 
free_callchain(struct callchain_root * root)824 void free_callchain(struct callchain_root *root)
825 {
826 	if (!symbol_conf.use_callchain)
827 		return;
828 
829 	free_callchain_node(&root->node);
830 }
831