| .. | .. |
|---|
| 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 | } |
|---|