Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf maps: Move maps code to own C file

The maps code has its own header, move the corresponding C function
definitions to their own C file. In the process tidy and minimize
includes.

Committer notes:

Add back the 'static' for maps__init() and maps__exit().

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexey Bayduraev <alexey.v.bayduraev@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: André Almeida <andrealmeid@collabora.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Hao Luo <haoluo@google.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jin Yao <yao.jin@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.garry@huawei.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Miaoqian Lin <linmq006@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Riccardo Mancini <rickyman7@gmail.com>
Cc: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
Cc: Song Liu <song@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Stephen Brennan <stephen.s.brennan@oracle.com>
Cc: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Yury Norov <yury.norov@gmail.com>
Link: http://lore.kernel.org/lkml/20220211103415.2737789-9-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
9d31d18b 0f1b9149

+416 -411
+1
tools/perf/util/Build
··· 56 56 perf-y += fncache.o 57 57 perf-y += machine.o 58 58 perf-y += map.o 59 + perf-y += maps.o 59 60 perf-y += pstack.o 60 61 perf-y += session.o 61 62 perf-y += sample-raw.o
+10 -411
tools/perf/util/map.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include "symbol.h" 3 - #include <assert.h> 4 - #include <errno.h> 5 2 #include <inttypes.h> 6 3 #include <limits.h> 4 + #include <stdio.h> 7 5 #include <stdlib.h> 8 6 #include <string.h> 9 - #include <stdio.h> 10 - #include <unistd.h> 11 - #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 12 - #include "dso.h" 13 - #include "map.h" 14 - #include "map_symbol.h" 15 - #include "thread.h" 16 - #include "vdso.h" 17 - #include "build-id.h" 18 - #include "debug.h" 19 - #include "machine.h" 20 7 #include <linux/string.h> 21 8 #include <linux/zalloc.h> 22 - #include "srcline.h" 9 + #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 10 + #include "debug.h" 11 + #include "dso.h" 12 + #include "map.h" 23 13 #include "namespaces.h" 24 - #include "unwind.h" 25 - #include "srccode.h" 26 - #include "ui/ui.h" 27 - 28 - static void __maps__insert(struct maps *maps, struct map *map); 14 + #include "srcline.h" 15 + #include "symbol.h" 16 + #include "thread.h" 17 + #include "vdso.h" 29 18 30 19 static inline int is_android_lib(const char *filename) 31 20 { ··· 513 524 return ip + map->reloc; 514 525 } 515 526 516 - static void maps__init(struct maps *maps, struct machine *machine) 517 - { 518 - maps->entries = RB_ROOT; 519 - init_rwsem(&maps->lock); 520 - maps->machine = machine; 521 - maps->last_search_by_name = NULL; 522 - maps->nr_maps = 0; 523 - maps->maps_by_name = NULL; 524 - refcount_set(&maps->refcnt, 1); 525 - } 526 - 527 - static void __maps__free_maps_by_name(struct maps *maps) 528 - { 529 - /* 530 - * Free everything to try to do it from the rbtree in the next search 531 - */ 532 - zfree(&maps->maps_by_name); 533 - maps->nr_maps_allocated = 0; 534 - } 535 - 536 - void maps__insert(struct maps *maps, struct map *map) 537 - { 538 - down_write(&maps->lock); 539 - __maps__insert(maps, map); 540 - ++maps->nr_maps; 541 - 542 - if (map->dso && map->dso->kernel) { 543 - struct kmap *kmap = map__kmap(map); 544 - 545 - if (kmap) 546 - kmap->kmaps = maps; 547 - else 548 - pr_err("Internal error: kernel dso with non kernel map\n"); 549 - } 550 - 551 - 552 - /* 553 - * If we already performed some search by name, then we need to add the just 554 - * inserted map and resort. 555 - */ 556 - if (maps->maps_by_name) { 557 - if (maps->nr_maps > maps->nr_maps_allocated) { 558 - int nr_allocate = maps->nr_maps * 2; 559 - struct map **maps_by_name = realloc(maps->maps_by_name, nr_allocate * sizeof(map)); 560 - 561 - if (maps_by_name == NULL) { 562 - __maps__free_maps_by_name(maps); 563 - up_write(&maps->lock); 564 - return; 565 - } 566 - 567 - maps->maps_by_name = maps_by_name; 568 - maps->nr_maps_allocated = nr_allocate; 569 - } 570 - maps->maps_by_name[maps->nr_maps - 1] = map; 571 - __maps__sort_by_name(maps); 572 - } 573 - up_write(&maps->lock); 574 - } 575 - 576 - static void __maps__remove(struct maps *maps, struct map *map) 577 - { 578 - rb_erase_init(&map->rb_node, &maps->entries); 579 - map__put(map); 580 - } 581 - 582 - void maps__remove(struct maps *maps, struct map *map) 583 - { 584 - down_write(&maps->lock); 585 - if (maps->last_search_by_name == map) 586 - maps->last_search_by_name = NULL; 587 - 588 - __maps__remove(maps, map); 589 - --maps->nr_maps; 590 - if (maps->maps_by_name) 591 - __maps__free_maps_by_name(maps); 592 - up_write(&maps->lock); 593 - } 594 - 595 - static void __maps__purge(struct maps *maps) 596 - { 597 - struct map *pos, *next; 598 - 599 - maps__for_each_entry_safe(maps, pos, next) { 600 - rb_erase_init(&pos->rb_node, &maps->entries); 601 - map__put(pos); 602 - } 603 - } 604 - 605 - static void maps__exit(struct maps *maps) 606 - { 607 - down_write(&maps->lock); 608 - __maps__purge(maps); 609 - up_write(&maps->lock); 610 - } 611 - 612 - bool maps__empty(struct maps *maps) 613 - { 614 - return !maps__first(maps); 615 - } 616 - 617 - struct maps *maps__new(struct machine *machine) 618 - { 619 - struct maps *maps = zalloc(sizeof(*maps)); 620 - 621 - if (maps != NULL) 622 - maps__init(maps, machine); 623 - 624 - return maps; 625 - } 626 - 627 - void maps__delete(struct maps *maps) 628 - { 629 - maps__exit(maps); 630 - unwind__finish_access(maps); 631 - free(maps); 632 - } 633 - 634 - void maps__put(struct maps *maps) 635 - { 636 - if (maps && refcount_dec_and_test(&maps->refcnt)) 637 - maps__delete(maps); 638 - } 639 - 640 - struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp) 641 - { 642 - struct map *map = maps__find(maps, addr); 643 - 644 - /* Ensure map is loaded before using map->map_ip */ 645 - if (map != NULL && map__load(map) >= 0) { 646 - if (mapp != NULL) 647 - *mapp = map; 648 - return map__find_symbol(map, map->map_ip(map, addr)); 649 - } 650 - 651 - return NULL; 652 - } 653 - 654 - static bool map__contains_symbol(struct map *map, struct symbol *sym) 527 + bool map__contains_symbol(struct map *map, struct symbol *sym) 655 528 { 656 529 u64 ip = map->unmap_ip(map, sym->start); 657 530 658 531 return ip >= map->start && ip < map->end; 659 - } 660 - 661 - struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp) 662 - { 663 - struct symbol *sym; 664 - struct map *pos; 665 - 666 - down_read(&maps->lock); 667 - 668 - maps__for_each_entry(maps, pos) { 669 - sym = map__find_symbol_by_name(pos, name); 670 - 671 - if (sym == NULL) 672 - continue; 673 - if (!map__contains_symbol(pos, sym)) { 674 - sym = NULL; 675 - continue; 676 - } 677 - if (mapp != NULL) 678 - *mapp = pos; 679 - goto out; 680 - } 681 - 682 - sym = NULL; 683 - out: 684 - up_read(&maps->lock); 685 - return sym; 686 - } 687 - 688 - int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams) 689 - { 690 - if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) { 691 - if (maps == NULL) 692 - return -1; 693 - ams->ms.map = maps__find(maps, ams->addr); 694 - if (ams->ms.map == NULL) 695 - return -1; 696 - } 697 - 698 - ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr); 699 - ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr); 700 - 701 - return ams->ms.sym ? 0 : -1; 702 - } 703 - 704 - size_t maps__fprintf(struct maps *maps, FILE *fp) 705 - { 706 - size_t printed = 0; 707 - struct map *pos; 708 - 709 - down_read(&maps->lock); 710 - 711 - maps__for_each_entry(maps, pos) { 712 - printed += fprintf(fp, "Map:"); 713 - printed += map__fprintf(pos, fp); 714 - if (verbose > 2) { 715 - printed += dso__fprintf(pos->dso, fp); 716 - printed += fprintf(fp, "--\n"); 717 - } 718 - } 719 - 720 - up_read(&maps->lock); 721 - 722 - return printed; 723 - } 724 - 725 - int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 726 - { 727 - struct rb_root *root; 728 - struct rb_node *next, *first; 729 - int err = 0; 730 - 731 - down_write(&maps->lock); 732 - 733 - root = &maps->entries; 734 - 735 - /* 736 - * Find first map where end > map->start. 737 - * Same as find_vma() in kernel. 738 - */ 739 - next = root->rb_node; 740 - first = NULL; 741 - while (next) { 742 - struct map *pos = rb_entry(next, struct map, rb_node); 743 - 744 - if (pos->end > map->start) { 745 - first = next; 746 - if (pos->start <= map->start) 747 - break; 748 - next = next->rb_left; 749 - } else 750 - next = next->rb_right; 751 - } 752 - 753 - next = first; 754 - while (next) { 755 - struct map *pos = rb_entry(next, struct map, rb_node); 756 - next = rb_next(&pos->rb_node); 757 - 758 - /* 759 - * Stop if current map starts after map->end. 760 - * Maps are ordered by start: next will not overlap for sure. 761 - */ 762 - if (pos->start >= map->end) 763 - break; 764 - 765 - if (verbose >= 2) { 766 - 767 - if (use_browser) { 768 - pr_debug("overlapping maps in %s (disable tui for more info)\n", 769 - map->dso->name); 770 - } else { 771 - fputs("overlapping maps:\n", fp); 772 - map__fprintf(map, fp); 773 - map__fprintf(pos, fp); 774 - } 775 - } 776 - 777 - rb_erase_init(&pos->rb_node, root); 778 - /* 779 - * Now check if we need to create new maps for areas not 780 - * overlapped by the new map: 781 - */ 782 - if (map->start > pos->start) { 783 - struct map *before = map__clone(pos); 784 - 785 - if (before == NULL) { 786 - err = -ENOMEM; 787 - goto put_map; 788 - } 789 - 790 - before->end = map->start; 791 - __maps__insert(maps, before); 792 - if (verbose >= 2 && !use_browser) 793 - map__fprintf(before, fp); 794 - map__put(before); 795 - } 796 - 797 - if (map->end < pos->end) { 798 - struct map *after = map__clone(pos); 799 - 800 - if (after == NULL) { 801 - err = -ENOMEM; 802 - goto put_map; 803 - } 804 - 805 - after->start = map->end; 806 - after->pgoff += map->end - pos->start; 807 - assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end)); 808 - __maps__insert(maps, after); 809 - if (verbose >= 2 && !use_browser) 810 - map__fprintf(after, fp); 811 - map__put(after); 812 - } 813 - put_map: 814 - map__put(pos); 815 - 816 - if (err) 817 - goto out; 818 - } 819 - 820 - err = 0; 821 - out: 822 - up_write(&maps->lock); 823 - return err; 824 - } 825 - 826 - /* 827 - * XXX This should not really _copy_ te maps, but refcount them. 828 - */ 829 - int maps__clone(struct thread *thread, struct maps *parent) 830 - { 831 - struct maps *maps = thread->maps; 832 - int err; 833 - struct map *map; 834 - 835 - down_read(&parent->lock); 836 - 837 - maps__for_each_entry(parent, map) { 838 - struct map *new = map__clone(map); 839 - 840 - if (new == NULL) { 841 - err = -ENOMEM; 842 - goto out_unlock; 843 - } 844 - 845 - err = unwind__prepare_access(maps, new, NULL); 846 - if (err) 847 - goto out_unlock; 848 - 849 - maps__insert(maps, new); 850 - map__put(new); 851 - } 852 - 853 - err = 0; 854 - out_unlock: 855 - up_read(&parent->lock); 856 - return err; 857 - } 858 - 859 - static void __maps__insert(struct maps *maps, struct map *map) 860 - { 861 - struct rb_node **p = &maps->entries.rb_node; 862 - struct rb_node *parent = NULL; 863 - const u64 ip = map->start; 864 - struct map *m; 865 - 866 - while (*p != NULL) { 867 - parent = *p; 868 - m = rb_entry(parent, struct map, rb_node); 869 - if (ip < m->start) 870 - p = &(*p)->rb_left; 871 - else 872 - p = &(*p)->rb_right; 873 - } 874 - 875 - rb_link_node(&map->rb_node, parent, p); 876 - rb_insert_color(&map->rb_node, &maps->entries); 877 - map__get(map); 878 - } 879 - 880 - struct map *maps__find(struct maps *maps, u64 ip) 881 - { 882 - struct rb_node *p; 883 - struct map *m; 884 - 885 - down_read(&maps->lock); 886 - 887 - p = maps->entries.rb_node; 888 - while (p != NULL) { 889 - m = rb_entry(p, struct map, rb_node); 890 - if (ip < m->start) 891 - p = p->rb_left; 892 - else if (ip >= m->end) 893 - p = p->rb_right; 894 - else 895 - goto out; 896 - } 897 - 898 - m = NULL; 899 - out: 900 - up_read(&maps->lock); 901 - return m; 902 - } 903 - 904 - struct map *maps__first(struct maps *maps) 905 - { 906 - struct rb_node *first = rb_first(&maps->entries); 907 - 908 - if (first) 909 - return rb_entry(first, struct map, rb_node); 910 - return NULL; 911 532 } 912 533 913 534 static struct map *__map__next(struct map *map)
+2
tools/perf/util/map.h
··· 152 152 153 153 bool map__has_symbols(const struct map *map); 154 154 155 + bool map__contains_symbol(struct map *map, struct symbol *sym); 156 + 155 157 #define ENTRY_TRAMPOLINE_NAME "__entry_SYSCALL_64_trampoline" 156 158 157 159 static inline bool is_entry_trampoline(const char *name)
+403
tools/perf/util/maps.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <errno.h> 3 + #include <stdlib.h> 4 + #include <linux/zalloc.h> 5 + #include "debug.h" 6 + #include "dso.h" 7 + #include "map.h" 8 + #include "maps.h" 9 + #include "thread.h" 10 + #include "ui/ui.h" 11 + #include "unwind.h" 12 + 13 + static void __maps__insert(struct maps *maps, struct map *map); 14 + 15 + static void maps__init(struct maps *maps, struct machine *machine) 16 + { 17 + maps->entries = RB_ROOT; 18 + init_rwsem(&maps->lock); 19 + maps->machine = machine; 20 + maps->last_search_by_name = NULL; 21 + maps->nr_maps = 0; 22 + maps->maps_by_name = NULL; 23 + refcount_set(&maps->refcnt, 1); 24 + } 25 + 26 + static void __maps__free_maps_by_name(struct maps *maps) 27 + { 28 + /* 29 + * Free everything to try to do it from the rbtree in the next search 30 + */ 31 + zfree(&maps->maps_by_name); 32 + maps->nr_maps_allocated = 0; 33 + } 34 + 35 + void maps__insert(struct maps *maps, struct map *map) 36 + { 37 + down_write(&maps->lock); 38 + __maps__insert(maps, map); 39 + ++maps->nr_maps; 40 + 41 + if (map->dso && map->dso->kernel) { 42 + struct kmap *kmap = map__kmap(map); 43 + 44 + if (kmap) 45 + kmap->kmaps = maps; 46 + else 47 + pr_err("Internal error: kernel dso with non kernel map\n"); 48 + } 49 + 50 + 51 + /* 52 + * If we already performed some search by name, then we need to add the just 53 + * inserted map and resort. 54 + */ 55 + if (maps->maps_by_name) { 56 + if (maps->nr_maps > maps->nr_maps_allocated) { 57 + int nr_allocate = maps->nr_maps * 2; 58 + struct map **maps_by_name = realloc(maps->maps_by_name, nr_allocate * sizeof(map)); 59 + 60 + if (maps_by_name == NULL) { 61 + __maps__free_maps_by_name(maps); 62 + up_write(&maps->lock); 63 + return; 64 + } 65 + 66 + maps->maps_by_name = maps_by_name; 67 + maps->nr_maps_allocated = nr_allocate; 68 + } 69 + maps->maps_by_name[maps->nr_maps - 1] = map; 70 + __maps__sort_by_name(maps); 71 + } 72 + up_write(&maps->lock); 73 + } 74 + 75 + static void __maps__remove(struct maps *maps, struct map *map) 76 + { 77 + rb_erase_init(&map->rb_node, &maps->entries); 78 + map__put(map); 79 + } 80 + 81 + void maps__remove(struct maps *maps, struct map *map) 82 + { 83 + down_write(&maps->lock); 84 + if (maps->last_search_by_name == map) 85 + maps->last_search_by_name = NULL; 86 + 87 + __maps__remove(maps, map); 88 + --maps->nr_maps; 89 + if (maps->maps_by_name) 90 + __maps__free_maps_by_name(maps); 91 + up_write(&maps->lock); 92 + } 93 + 94 + static void __maps__purge(struct maps *maps) 95 + { 96 + struct map *pos, *next; 97 + 98 + maps__for_each_entry_safe(maps, pos, next) { 99 + rb_erase_init(&pos->rb_node, &maps->entries); 100 + map__put(pos); 101 + } 102 + } 103 + 104 + static void maps__exit(struct maps *maps) 105 + { 106 + down_write(&maps->lock); 107 + __maps__purge(maps); 108 + up_write(&maps->lock); 109 + } 110 + 111 + bool maps__empty(struct maps *maps) 112 + { 113 + return !maps__first(maps); 114 + } 115 + 116 + struct maps *maps__new(struct machine *machine) 117 + { 118 + struct maps *maps = zalloc(sizeof(*maps)); 119 + 120 + if (maps != NULL) 121 + maps__init(maps, machine); 122 + 123 + return maps; 124 + } 125 + 126 + void maps__delete(struct maps *maps) 127 + { 128 + maps__exit(maps); 129 + unwind__finish_access(maps); 130 + free(maps); 131 + } 132 + 133 + void maps__put(struct maps *maps) 134 + { 135 + if (maps && refcount_dec_and_test(&maps->refcnt)) 136 + maps__delete(maps); 137 + } 138 + 139 + struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp) 140 + { 141 + struct map *map = maps__find(maps, addr); 142 + 143 + /* Ensure map is loaded before using map->map_ip */ 144 + if (map != NULL && map__load(map) >= 0) { 145 + if (mapp != NULL) 146 + *mapp = map; 147 + return map__find_symbol(map, map->map_ip(map, addr)); 148 + } 149 + 150 + return NULL; 151 + } 152 + 153 + struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp) 154 + { 155 + struct symbol *sym; 156 + struct map *pos; 157 + 158 + down_read(&maps->lock); 159 + 160 + maps__for_each_entry(maps, pos) { 161 + sym = map__find_symbol_by_name(pos, name); 162 + 163 + if (sym == NULL) 164 + continue; 165 + if (!map__contains_symbol(pos, sym)) { 166 + sym = NULL; 167 + continue; 168 + } 169 + if (mapp != NULL) 170 + *mapp = pos; 171 + goto out; 172 + } 173 + 174 + sym = NULL; 175 + out: 176 + up_read(&maps->lock); 177 + return sym; 178 + } 179 + 180 + int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams) 181 + { 182 + if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) { 183 + if (maps == NULL) 184 + return -1; 185 + ams->ms.map = maps__find(maps, ams->addr); 186 + if (ams->ms.map == NULL) 187 + return -1; 188 + } 189 + 190 + ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr); 191 + ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr); 192 + 193 + return ams->ms.sym ? 0 : -1; 194 + } 195 + 196 + size_t maps__fprintf(struct maps *maps, FILE *fp) 197 + { 198 + size_t printed = 0; 199 + struct map *pos; 200 + 201 + down_read(&maps->lock); 202 + 203 + maps__for_each_entry(maps, pos) { 204 + printed += fprintf(fp, "Map:"); 205 + printed += map__fprintf(pos, fp); 206 + if (verbose > 2) { 207 + printed += dso__fprintf(pos->dso, fp); 208 + printed += fprintf(fp, "--\n"); 209 + } 210 + } 211 + 212 + up_read(&maps->lock); 213 + 214 + return printed; 215 + } 216 + 217 + int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 218 + { 219 + struct rb_root *root; 220 + struct rb_node *next, *first; 221 + int err = 0; 222 + 223 + down_write(&maps->lock); 224 + 225 + root = &maps->entries; 226 + 227 + /* 228 + * Find first map where end > map->start. 229 + * Same as find_vma() in kernel. 230 + */ 231 + next = root->rb_node; 232 + first = NULL; 233 + while (next) { 234 + struct map *pos = rb_entry(next, struct map, rb_node); 235 + 236 + if (pos->end > map->start) { 237 + first = next; 238 + if (pos->start <= map->start) 239 + break; 240 + next = next->rb_left; 241 + } else 242 + next = next->rb_right; 243 + } 244 + 245 + next = first; 246 + while (next) { 247 + struct map *pos = rb_entry(next, struct map, rb_node); 248 + next = rb_next(&pos->rb_node); 249 + 250 + /* 251 + * Stop if current map starts after map->end. 252 + * Maps are ordered by start: next will not overlap for sure. 253 + */ 254 + if (pos->start >= map->end) 255 + break; 256 + 257 + if (verbose >= 2) { 258 + 259 + if (use_browser) { 260 + pr_debug("overlapping maps in %s (disable tui for more info)\n", 261 + map->dso->name); 262 + } else { 263 + fputs("overlapping maps:\n", fp); 264 + map__fprintf(map, fp); 265 + map__fprintf(pos, fp); 266 + } 267 + } 268 + 269 + rb_erase_init(&pos->rb_node, root); 270 + /* 271 + * Now check if we need to create new maps for areas not 272 + * overlapped by the new map: 273 + */ 274 + if (map->start > pos->start) { 275 + struct map *before = map__clone(pos); 276 + 277 + if (before == NULL) { 278 + err = -ENOMEM; 279 + goto put_map; 280 + } 281 + 282 + before->end = map->start; 283 + __maps__insert(maps, before); 284 + if (verbose >= 2 && !use_browser) 285 + map__fprintf(before, fp); 286 + map__put(before); 287 + } 288 + 289 + if (map->end < pos->end) { 290 + struct map *after = map__clone(pos); 291 + 292 + if (after == NULL) { 293 + err = -ENOMEM; 294 + goto put_map; 295 + } 296 + 297 + after->start = map->end; 298 + after->pgoff += map->end - pos->start; 299 + assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end)); 300 + __maps__insert(maps, after); 301 + if (verbose >= 2 && !use_browser) 302 + map__fprintf(after, fp); 303 + map__put(after); 304 + } 305 + put_map: 306 + map__put(pos); 307 + 308 + if (err) 309 + goto out; 310 + } 311 + 312 + err = 0; 313 + out: 314 + up_write(&maps->lock); 315 + return err; 316 + } 317 + 318 + /* 319 + * XXX This should not really _copy_ te maps, but refcount them. 320 + */ 321 + int maps__clone(struct thread *thread, struct maps *parent) 322 + { 323 + struct maps *maps = thread->maps; 324 + int err; 325 + struct map *map; 326 + 327 + down_read(&parent->lock); 328 + 329 + maps__for_each_entry(parent, map) { 330 + struct map *new = map__clone(map); 331 + 332 + if (new == NULL) { 333 + err = -ENOMEM; 334 + goto out_unlock; 335 + } 336 + 337 + err = unwind__prepare_access(maps, new, NULL); 338 + if (err) 339 + goto out_unlock; 340 + 341 + maps__insert(maps, new); 342 + map__put(new); 343 + } 344 + 345 + err = 0; 346 + out_unlock: 347 + up_read(&parent->lock); 348 + return err; 349 + } 350 + 351 + static void __maps__insert(struct maps *maps, struct map *map) 352 + { 353 + struct rb_node **p = &maps->entries.rb_node; 354 + struct rb_node *parent = NULL; 355 + const u64 ip = map->start; 356 + struct map *m; 357 + 358 + while (*p != NULL) { 359 + parent = *p; 360 + m = rb_entry(parent, struct map, rb_node); 361 + if (ip < m->start) 362 + p = &(*p)->rb_left; 363 + else 364 + p = &(*p)->rb_right; 365 + } 366 + 367 + rb_link_node(&map->rb_node, parent, p); 368 + rb_insert_color(&map->rb_node, &maps->entries); 369 + map__get(map); 370 + } 371 + 372 + struct map *maps__find(struct maps *maps, u64 ip) 373 + { 374 + struct rb_node *p; 375 + struct map *m; 376 + 377 + down_read(&maps->lock); 378 + 379 + p = maps->entries.rb_node; 380 + while (p != NULL) { 381 + m = rb_entry(p, struct map, rb_node); 382 + if (ip < m->start) 383 + p = p->rb_left; 384 + else if (ip >= m->end) 385 + p = p->rb_right; 386 + else 387 + goto out; 388 + } 389 + 390 + m = NULL; 391 + out: 392 + up_read(&maps->lock); 393 + return m; 394 + } 395 + 396 + struct map *maps__first(struct maps *maps) 397 + { 398 + struct rb_node *first = rb_first(&maps->entries); 399 + 400 + if (first) 401 + return rb_entry(first, struct map, rb_node); 402 + return NULL; 403 + }