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