.. | .. |
---|
5 | 5 | #include <string.h> |
---|
6 | 6 | |
---|
7 | 7 | #include <linux/kernel.h> |
---|
| 8 | +#include <linux/string.h> |
---|
| 9 | +#include <linux/zalloc.h> |
---|
8 | 10 | |
---|
9 | 11 | #include "util/dso.h" |
---|
10 | | -#include "util/util.h" |
---|
11 | 12 | #include "util/debug.h" |
---|
12 | 13 | #include "util/callchain.h" |
---|
| 14 | +#include "util/symbol_conf.h" |
---|
13 | 15 | #include "srcline.h" |
---|
14 | 16 | #include "string2.h" |
---|
15 | 17 | #include "symbol.h" |
---|
.. | .. |
---|
301 | 303 | } |
---|
302 | 304 | |
---|
303 | 305 | if (a2l == NULL) { |
---|
304 | | - pr_warning("addr2line_init failed for %s\n", dso_name); |
---|
| 306 | + if (!symbol_conf.disable_add2line_warn) |
---|
| 307 | + pr_warning("addr2line_init failed for %s\n", dso_name); |
---|
305 | 308 | return 0; |
---|
306 | 309 | } |
---|
307 | 310 | |
---|
.. | .. |
---|
478 | 481 | char *srcline; |
---|
479 | 482 | struct symbol *inline_sym; |
---|
480 | 483 | |
---|
481 | | - rtrim(funcname); |
---|
| 484 | + strim(funcname); |
---|
482 | 485 | |
---|
483 | 486 | if (getline(&filename, &filelen, fp) == -1) |
---|
484 | 487 | goto out; |
---|
.. | .. |
---|
562 | 565 | return srcline; |
---|
563 | 566 | } |
---|
564 | 567 | |
---|
| 568 | +/* Returns filename and fills in line number in line */ |
---|
| 569 | +char *get_srcline_split(struct dso *dso, u64 addr, unsigned *line) |
---|
| 570 | +{ |
---|
| 571 | + char *file = NULL; |
---|
| 572 | + const char *dso_name; |
---|
| 573 | + |
---|
| 574 | + if (!dso->has_srcline) |
---|
| 575 | + goto out; |
---|
| 576 | + |
---|
| 577 | + dso_name = dso__name(dso); |
---|
| 578 | + if (dso_name == NULL) |
---|
| 579 | + goto out; |
---|
| 580 | + |
---|
| 581 | + if (!addr2line(dso_name, addr, &file, line, dso, true, NULL, NULL)) |
---|
| 582 | + goto out; |
---|
| 583 | + |
---|
| 584 | + dso->a2l_fails = 0; |
---|
| 585 | + return file; |
---|
| 586 | + |
---|
| 587 | +out: |
---|
| 588 | + if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) { |
---|
| 589 | + dso->has_srcline = 0; |
---|
| 590 | + dso__free_a2l(dso); |
---|
| 591 | + } |
---|
| 592 | + |
---|
| 593 | + return NULL; |
---|
| 594 | +} |
---|
| 595 | + |
---|
565 | 596 | void free_srcline(char *srcline) |
---|
566 | 597 | { |
---|
567 | 598 | if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) |
---|
.. | .. |
---|
580 | 611 | struct rb_node rb_node; |
---|
581 | 612 | }; |
---|
582 | 613 | |
---|
583 | | -void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline) |
---|
| 614 | +void srcline__tree_insert(struct rb_root_cached *tree, u64 addr, char *srcline) |
---|
584 | 615 | { |
---|
585 | | - struct rb_node **p = &tree->rb_node; |
---|
| 616 | + struct rb_node **p = &tree->rb_root.rb_node; |
---|
586 | 617 | struct rb_node *parent = NULL; |
---|
587 | 618 | struct srcline_node *i, *node; |
---|
| 619 | + bool leftmost = true; |
---|
588 | 620 | |
---|
589 | 621 | node = zalloc(sizeof(struct srcline_node)); |
---|
590 | 622 | if (!node) { |
---|
.. | .. |
---|
600 | 632 | i = rb_entry(parent, struct srcline_node, rb_node); |
---|
601 | 633 | if (addr < i->addr) |
---|
602 | 634 | p = &(*p)->rb_left; |
---|
603 | | - else |
---|
| 635 | + else { |
---|
604 | 636 | p = &(*p)->rb_right; |
---|
| 637 | + leftmost = false; |
---|
| 638 | + } |
---|
605 | 639 | } |
---|
606 | 640 | rb_link_node(&node->rb_node, parent, p); |
---|
607 | | - rb_insert_color(&node->rb_node, tree); |
---|
| 641 | + rb_insert_color_cached(&node->rb_node, tree, leftmost); |
---|
608 | 642 | } |
---|
609 | 643 | |
---|
610 | | -char *srcline__tree_find(struct rb_root *tree, u64 addr) |
---|
| 644 | +char *srcline__tree_find(struct rb_root_cached *tree, u64 addr) |
---|
611 | 645 | { |
---|
612 | | - struct rb_node *n = tree->rb_node; |
---|
| 646 | + struct rb_node *n = tree->rb_root.rb_node; |
---|
613 | 647 | |
---|
614 | 648 | while (n) { |
---|
615 | 649 | struct srcline_node *i = rb_entry(n, struct srcline_node, |
---|
.. | .. |
---|
626 | 660 | return NULL; |
---|
627 | 661 | } |
---|
628 | 662 | |
---|
629 | | -void srcline__tree_delete(struct rb_root *tree) |
---|
| 663 | +void srcline__tree_delete(struct rb_root_cached *tree) |
---|
630 | 664 | { |
---|
631 | 665 | struct srcline_node *pos; |
---|
632 | | - struct rb_node *next = rb_first(tree); |
---|
| 666 | + struct rb_node *next = rb_first_cached(tree); |
---|
633 | 667 | |
---|
634 | 668 | while (next) { |
---|
635 | 669 | pos = rb_entry(next, struct srcline_node, rb_node); |
---|
636 | 670 | next = rb_next(&pos->rb_node); |
---|
637 | | - rb_erase(&pos->rb_node, tree); |
---|
| 671 | + rb_erase_cached(&pos->rb_node, tree); |
---|
638 | 672 | free_srcline(pos->srcline); |
---|
639 | 673 | zfree(&pos); |
---|
640 | 674 | } |
---|
.. | .. |
---|
668 | 702 | free(node); |
---|
669 | 703 | } |
---|
670 | 704 | |
---|
671 | | -void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines) |
---|
| 705 | +void inlines__tree_insert(struct rb_root_cached *tree, |
---|
| 706 | + struct inline_node *inlines) |
---|
672 | 707 | { |
---|
673 | | - struct rb_node **p = &tree->rb_node; |
---|
| 708 | + struct rb_node **p = &tree->rb_root.rb_node; |
---|
674 | 709 | struct rb_node *parent = NULL; |
---|
675 | 710 | const u64 addr = inlines->addr; |
---|
676 | 711 | struct inline_node *i; |
---|
| 712 | + bool leftmost = true; |
---|
677 | 713 | |
---|
678 | 714 | while (*p != NULL) { |
---|
679 | 715 | parent = *p; |
---|
680 | 716 | i = rb_entry(parent, struct inline_node, rb_node); |
---|
681 | 717 | if (addr < i->addr) |
---|
682 | 718 | p = &(*p)->rb_left; |
---|
683 | | - else |
---|
| 719 | + else { |
---|
684 | 720 | p = &(*p)->rb_right; |
---|
| 721 | + leftmost = false; |
---|
| 722 | + } |
---|
685 | 723 | } |
---|
686 | 724 | rb_link_node(&inlines->rb_node, parent, p); |
---|
687 | | - rb_insert_color(&inlines->rb_node, tree); |
---|
| 725 | + rb_insert_color_cached(&inlines->rb_node, tree, leftmost); |
---|
688 | 726 | } |
---|
689 | 727 | |
---|
690 | | -struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr) |
---|
| 728 | +struct inline_node *inlines__tree_find(struct rb_root_cached *tree, u64 addr) |
---|
691 | 729 | { |
---|
692 | | - struct rb_node *n = tree->rb_node; |
---|
| 730 | + struct rb_node *n = tree->rb_root.rb_node; |
---|
693 | 731 | |
---|
694 | 732 | while (n) { |
---|
695 | 733 | struct inline_node *i = rb_entry(n, struct inline_node, |
---|
.. | .. |
---|
706 | 744 | return NULL; |
---|
707 | 745 | } |
---|
708 | 746 | |
---|
709 | | -void inlines__tree_delete(struct rb_root *tree) |
---|
| 747 | +void inlines__tree_delete(struct rb_root_cached *tree) |
---|
710 | 748 | { |
---|
711 | 749 | struct inline_node *pos; |
---|
712 | | - struct rb_node *next = rb_first(tree); |
---|
| 750 | + struct rb_node *next = rb_first_cached(tree); |
---|
713 | 751 | |
---|
714 | 752 | while (next) { |
---|
715 | 753 | pos = rb_entry(next, struct inline_node, rb_node); |
---|
716 | 754 | next = rb_next(&pos->rb_node); |
---|
717 | | - rb_erase(&pos->rb_node, tree); |
---|
| 755 | + rb_erase_cached(&pos->rb_node, tree); |
---|
718 | 756 | inline_node__delete(pos); |
---|
719 | 757 | } |
---|
720 | 758 | } |
---|