1 #include "symbol.h" 2 #include <errno.h> 3 #include <inttypes.h> 4 #include <limits.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <stdio.h> 8 #include <unistd.h> 9 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ 10 #include "map.h" 11 #include "thread.h" 12 #include "vdso.h" 13 #include "build-id.h" 14 #include "util.h" 15 #include "debug.h" 16 #include "machine.h" 17 #include <linux/string.h> 18 #include "srcline.h" 19 #include "namespaces.h" 20 #include "unwind.h" 21 22 static void __maps__insert(struct maps *maps, struct map *map); 23 24 const char *map_type__name[MAP__NR_TYPES] = { 25 [MAP__FUNCTION] = "Functions", 26 [MAP__VARIABLE] = "Variables", 27 }; 28 29 static inline int is_anon_memory(const char *filename, u32 flags) 30 { 31 return flags & MAP_HUGETLB || 32 !strcmp(filename, "//anon") || 33 !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) || 34 !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1); 35 } 36 37 static inline int is_no_dso_memory(const char *filename) 38 { 39 return !strncmp(filename, "[stack", 6) || 40 !strncmp(filename, "/SYSV",5) || 41 !strcmp(filename, "[heap]"); 42 } 43 44 static inline int is_android_lib(const char *filename) 45 { 46 return !strncmp(filename, "/data/app-lib", 13) || 47 !strncmp(filename, "/system/lib", 11); 48 } 49 50 static inline bool replace_android_lib(const char *filename, char *newfilename) 51 { 52 const char *libname; 53 char *app_abi; 54 size_t app_abi_length, new_length; 55 size_t lib_length = 0; 56 57 libname = strrchr(filename, '/'); 58 if (libname) 59 lib_length = strlen(libname); 60 61 app_abi = getenv("APP_ABI"); 62 if (!app_abi) 63 return false; 64 65 app_abi_length = strlen(app_abi); 66 67 if (!strncmp(filename, "/data/app-lib", 13)) { 68 char *apk_path; 69 70 if (!app_abi_length) 71 return false; 72 73 new_length = 7 + app_abi_length + lib_length; 74 75 apk_path = getenv("APK_PATH"); 76 if (apk_path) { 77 new_length += strlen(apk_path) + 1; 78 if (new_length > PATH_MAX) 79 return false; 80 snprintf(newfilename, new_length, 81 "%s/libs/%s/%s", apk_path, app_abi, libname); 82 } else { 83 if (new_length > PATH_MAX) 84 return false; 85 snprintf(newfilename, new_length, 86 "libs/%s/%s", app_abi, libname); 87 } 88 return true; 89 } 90 91 if (!strncmp(filename, "/system/lib/", 11)) { 92 char *ndk, *app; 93 const char *arch; 94 size_t ndk_length; 95 size_t app_length; 96 97 ndk = getenv("NDK_ROOT"); 98 app = getenv("APP_PLATFORM"); 99 100 if (!(ndk && app)) 101 return false; 102 103 ndk_length = strlen(ndk); 104 app_length = strlen(app); 105 106 if (!(ndk_length && app_length && app_abi_length)) 107 return false; 108 109 arch = !strncmp(app_abi, "arm", 3) ? "arm" : 110 !strncmp(app_abi, "mips", 4) ? "mips" : 111 !strncmp(app_abi, "x86", 3) ? "x86" : NULL; 112 113 if (!arch) 114 return false; 115 116 new_length = 27 + ndk_length + 117 app_length + lib_length 118 + strlen(arch); 119 120 if (new_length > PATH_MAX) 121 return false; 122 snprintf(newfilename, new_length, 123 "%s/platforms/%s/arch-%s/usr/lib/%s", 124 ndk, app, arch, libname); 125 126 return true; 127 } 128 return false; 129 } 130 131 void map__init(struct map *map, enum map_type type, 132 u64 start, u64 end, u64 pgoff, struct dso *dso) 133 { 134 map->type = type; 135 map->start = start; 136 map->end = end; 137 map->pgoff = pgoff; 138 map->reloc = 0; 139 map->dso = dso__get(dso); 140 map->map_ip = map__map_ip; 141 map->unmap_ip = map__unmap_ip; 142 RB_CLEAR_NODE(&map->rb_node); 143 map->groups = NULL; 144 map->erange_warned = false; 145 refcount_set(&map->refcnt, 1); 146 } 147 148 struct map *map__new(struct machine *machine, u64 start, u64 len, 149 u64 pgoff, u32 d_maj, u32 d_min, u64 ino, 150 u64 ino_gen, u32 prot, u32 flags, char *filename, 151 enum map_type type, struct thread *thread) 152 { 153 struct map *map = malloc(sizeof(*map)); 154 struct nsinfo *nsi = NULL; 155 struct nsinfo *nnsi; 156 157 if (map != NULL) { 158 char newfilename[PATH_MAX]; 159 struct dso *dso; 160 int anon, no_dso, vdso, android; 161 162 android = is_android_lib(filename); 163 anon = is_anon_memory(filename, flags); 164 vdso = is_vdso_map(filename); 165 no_dso = is_no_dso_memory(filename); 166 167 map->maj = d_maj; 168 map->min = d_min; 169 map->ino = ino; 170 map->ino_generation = ino_gen; 171 map->prot = prot; 172 map->flags = flags; 173 nsi = nsinfo__get(thread->nsinfo); 174 175 if ((anon || no_dso) && nsi && type == MAP__FUNCTION) { 176 snprintf(newfilename, sizeof(newfilename), 177 "/tmp/perf-%d.map", nsi->pid); 178 filename = newfilename; 179 } 180 181 if (android) { 182 if (replace_android_lib(filename, newfilename)) 183 filename = newfilename; 184 } 185 186 if (vdso) { 187 /* The vdso maps are always on the host and not the 188 * container. Ensure that we don't use setns to look 189 * them up. 190 */ 191 nnsi = nsinfo__copy(nsi); 192 if (nnsi) { 193 nsinfo__put(nsi); 194 nnsi->need_setns = false; 195 nsi = nnsi; 196 } 197 pgoff = 0; 198 dso = machine__findnew_vdso(machine, thread); 199 } else 200 dso = machine__findnew_dso(machine, filename); 201 202 if (dso == NULL) 203 goto out_delete; 204 205 map__init(map, type, start, start + len, pgoff, dso); 206 207 if (anon || no_dso) { 208 map->map_ip = map->unmap_ip = identity__map_ip; 209 210 /* 211 * Set memory without DSO as loaded. All map__find_* 212 * functions still return NULL, and we avoid the 213 * unnecessary map__load warning. 214 */ 215 if (type != MAP__FUNCTION) 216 dso__set_loaded(dso, map->type); 217 } 218 dso->nsinfo = nsi; 219 dso__put(dso); 220 } 221 return map; 222 out_delete: 223 nsinfo__put(nsi); 224 free(map); 225 return NULL; 226 } 227 228 /* 229 * Constructor variant for modules (where we know from /proc/modules where 230 * they are loaded) and for vmlinux, where only after we load all the 231 * symbols we'll know where it starts and ends. 232 */ 233 struct map *map__new2(u64 start, struct dso *dso, enum map_type type) 234 { 235 struct map *map = calloc(1, (sizeof(*map) + 236 (dso->kernel ? sizeof(struct kmap) : 0))); 237 if (map != NULL) { 238 /* 239 * ->end will be filled after we load all the symbols 240 */ 241 map__init(map, type, start, 0, 0, dso); 242 } 243 244 return map; 245 } 246 247 /* 248 * Use this and __map__is_kmodule() for map instances that are in 249 * machine->kmaps, and thus have map->groups->machine all properly set, to 250 * disambiguate between the kernel and modules. 251 * 252 * When the need arises, introduce map__is_{kernel,kmodule)() that 253 * checks (map->groups != NULL && map->groups->machine != NULL && 254 * map->dso->kernel) before calling __map__is_{kernel,kmodule}()) 255 */ 256 bool __map__is_kernel(const struct map *map) 257 { 258 return __machine__kernel_map(map->groups->machine, map->type) == map; 259 } 260 261 static void map__exit(struct map *map) 262 { 263 BUG_ON(!RB_EMPTY_NODE(&map->rb_node)); 264 dso__zput(map->dso); 265 } 266 267 void map__delete(struct map *map) 268 { 269 map__exit(map); 270 free(map); 271 } 272 273 void map__put(struct map *map) 274 { 275 if (map && refcount_dec_and_test(&map->refcnt)) 276 map__delete(map); 277 } 278 279 void map__fixup_start(struct map *map) 280 { 281 struct rb_root *symbols = &map->dso->symbols[map->type]; 282 struct rb_node *nd = rb_first(symbols); 283 if (nd != NULL) { 284 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 285 map->start = sym->start; 286 } 287 } 288 289 void map__fixup_end(struct map *map) 290 { 291 struct rb_root *symbols = &map->dso->symbols[map->type]; 292 struct rb_node *nd = rb_last(symbols); 293 if (nd != NULL) { 294 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 295 map->end = sym->end; 296 } 297 } 298 299 #define DSO__DELETED "(deleted)" 300 301 int map__load(struct map *map) 302 { 303 const char *name = map->dso->long_name; 304 int nr; 305 306 if (dso__loaded(map->dso, map->type)) 307 return 0; 308 309 nr = dso__load(map->dso, map); 310 if (nr < 0) { 311 if (map->dso->has_build_id) { 312 char sbuild_id[SBUILD_ID_SIZE]; 313 314 build_id__sprintf(map->dso->build_id, 315 sizeof(map->dso->build_id), 316 sbuild_id); 317 pr_warning("%s with build id %s not found", 318 name, sbuild_id); 319 } else 320 pr_warning("Failed to open %s", name); 321 322 pr_warning(", continuing without symbols\n"); 323 return -1; 324 } else if (nr == 0) { 325 #ifdef HAVE_LIBELF_SUPPORT 326 const size_t len = strlen(name); 327 const size_t real_len = len - sizeof(DSO__DELETED); 328 329 if (len > sizeof(DSO__DELETED) && 330 strcmp(name + real_len + 1, DSO__DELETED) == 0) { 331 pr_warning("%.*s was updated (is prelink enabled?). " 332 "Restart the long running apps that use it!\n", 333 (int)real_len, name); 334 } else { 335 pr_warning("no symbols found in %s, maybe install " 336 "a debug package?\n", name); 337 } 338 #endif 339 return -1; 340 } 341 342 return 0; 343 } 344 345 struct symbol *map__find_symbol(struct map *map, u64 addr) 346 { 347 if (map__load(map) < 0) 348 return NULL; 349 350 return dso__find_symbol(map->dso, map->type, addr); 351 } 352 353 struct symbol *map__find_symbol_by_name(struct map *map, const char *name) 354 { 355 if (map__load(map) < 0) 356 return NULL; 357 358 if (!dso__sorted_by_name(map->dso, map->type)) 359 dso__sort_by_name(map->dso, map->type); 360 361 return dso__find_symbol_by_name(map->dso, map->type, name); 362 } 363 364 struct map *map__clone(struct map *from) 365 { 366 struct map *map = memdup(from, sizeof(*map)); 367 368 if (map != NULL) { 369 refcount_set(&map->refcnt, 1); 370 RB_CLEAR_NODE(&map->rb_node); 371 dso__get(map->dso); 372 map->groups = NULL; 373 } 374 375 return map; 376 } 377 378 int map__overlap(struct map *l, struct map *r) 379 { 380 if (l->start > r->start) { 381 struct map *t = l; 382 l = r; 383 r = t; 384 } 385 386 if (l->end > r->start) 387 return 1; 388 389 return 0; 390 } 391 392 size_t map__fprintf(struct map *map, FILE *fp) 393 { 394 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n", 395 map->start, map->end, map->pgoff, map->dso->name); 396 } 397 398 size_t map__fprintf_dsoname(struct map *map, FILE *fp) 399 { 400 const char *dsoname = "[unknown]"; 401 402 if (map && map->dso) { 403 if (symbol_conf.show_kernel_path && map->dso->long_name) 404 dsoname = map->dso->long_name; 405 else 406 dsoname = map->dso->name; 407 } 408 409 return fprintf(fp, "%s", dsoname); 410 } 411 412 int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, 413 FILE *fp) 414 { 415 char *srcline; 416 int ret = 0; 417 418 if (map && map->dso) { 419 srcline = get_srcline(map->dso, 420 map__rip_2objdump(map, addr), NULL, 421 true, true); 422 if (srcline != SRCLINE_UNKNOWN) 423 ret = fprintf(fp, "%s%s", prefix, srcline); 424 free_srcline(srcline); 425 } 426 return ret; 427 } 428 429 /** 430 * map__rip_2objdump - convert symbol start address to objdump address. 431 * @map: memory map 432 * @rip: symbol start address 433 * 434 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 435 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is 436 * relative to section start. 437 * 438 * Return: Address suitable for passing to "objdump --start-address=" 439 */ 440 u64 map__rip_2objdump(struct map *map, u64 rip) 441 { 442 if (!map->dso->adjust_symbols) 443 return rip; 444 445 if (map->dso->rel) 446 return rip - map->pgoff; 447 448 /* 449 * kernel modules also have DSO_TYPE_USER in dso->kernel, 450 * but all kernel modules are ET_REL, so won't get here. 451 */ 452 if (map->dso->kernel == DSO_TYPE_USER) 453 return rip + map->dso->text_offset; 454 455 return map->unmap_ip(map, rip) - map->reloc; 456 } 457 458 /** 459 * map__objdump_2mem - convert objdump address to a memory address. 460 * @map: memory map 461 * @ip: objdump address 462 * 463 * Closely related to map__rip_2objdump(), this function takes an address from 464 * objdump and converts it to a memory address. Note this assumes that @map 465 * contains the address. To be sure the result is valid, check it forwards 466 * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip 467 * 468 * Return: Memory address. 469 */ 470 u64 map__objdump_2mem(struct map *map, u64 ip) 471 { 472 if (!map->dso->adjust_symbols) 473 return map->unmap_ip(map, ip); 474 475 if (map->dso->rel) 476 return map->unmap_ip(map, ip + map->pgoff); 477 478 /* 479 * kernel modules also have DSO_TYPE_USER in dso->kernel, 480 * but all kernel modules are ET_REL, so won't get here. 481 */ 482 if (map->dso->kernel == DSO_TYPE_USER) 483 return map->unmap_ip(map, ip - map->dso->text_offset); 484 485 return ip + map->reloc; 486 } 487 488 static void maps__init(struct maps *maps) 489 { 490 maps->entries = RB_ROOT; 491 pthread_rwlock_init(&maps->lock, NULL); 492 } 493 494 void map_groups__init(struct map_groups *mg, struct machine *machine) 495 { 496 int i; 497 for (i = 0; i < MAP__NR_TYPES; ++i) { 498 maps__init(&mg->maps[i]); 499 } 500 mg->machine = machine; 501 refcount_set(&mg->refcnt, 1); 502 } 503 504 static void __maps__purge(struct maps *maps) 505 { 506 struct rb_root *root = &maps->entries; 507 struct rb_node *next = rb_first(root); 508 509 while (next) { 510 struct map *pos = rb_entry(next, struct map, rb_node); 511 512 next = rb_next(&pos->rb_node); 513 rb_erase_init(&pos->rb_node, root); 514 map__put(pos); 515 } 516 } 517 518 static void maps__exit(struct maps *maps) 519 { 520 pthread_rwlock_wrlock(&maps->lock); 521 __maps__purge(maps); 522 pthread_rwlock_unlock(&maps->lock); 523 } 524 525 void map_groups__exit(struct map_groups *mg) 526 { 527 int i; 528 529 for (i = 0; i < MAP__NR_TYPES; ++i) 530 maps__exit(&mg->maps[i]); 531 } 532 533 bool map_groups__empty(struct map_groups *mg) 534 { 535 int i; 536 537 for (i = 0; i < MAP__NR_TYPES; ++i) { 538 if (maps__first(&mg->maps[i])) 539 return false; 540 } 541 542 return true; 543 } 544 545 struct map_groups *map_groups__new(struct machine *machine) 546 { 547 struct map_groups *mg = malloc(sizeof(*mg)); 548 549 if (mg != NULL) 550 map_groups__init(mg, machine); 551 552 return mg; 553 } 554 555 void map_groups__delete(struct map_groups *mg) 556 { 557 map_groups__exit(mg); 558 free(mg); 559 } 560 561 void map_groups__put(struct map_groups *mg) 562 { 563 if (mg && refcount_dec_and_test(&mg->refcnt)) 564 map_groups__delete(mg); 565 } 566 567 struct symbol *map_groups__find_symbol(struct map_groups *mg, 568 enum map_type type, u64 addr, 569 struct map **mapp) 570 { 571 struct map *map = map_groups__find(mg, type, addr); 572 573 /* Ensure map is loaded before using map->map_ip */ 574 if (map != NULL && map__load(map) >= 0) { 575 if (mapp != NULL) 576 *mapp = map; 577 return map__find_symbol(map, map->map_ip(map, addr)); 578 } 579 580 return NULL; 581 } 582 583 struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, 584 struct map **mapp) 585 { 586 struct symbol *sym; 587 struct rb_node *nd; 588 589 pthread_rwlock_rdlock(&maps->lock); 590 591 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) { 592 struct map *pos = rb_entry(nd, struct map, rb_node); 593 594 sym = map__find_symbol_by_name(pos, name); 595 596 if (sym == NULL) 597 continue; 598 if (mapp != NULL) 599 *mapp = pos; 600 goto out; 601 } 602 603 sym = NULL; 604 out: 605 pthread_rwlock_unlock(&maps->lock); 606 return sym; 607 } 608 609 struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 610 enum map_type type, 611 const char *name, 612 struct map **mapp) 613 { 614 struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp); 615 616 return sym; 617 } 618 619 int map_groups__find_ams(struct addr_map_symbol *ams) 620 { 621 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { 622 if (ams->map->groups == NULL) 623 return -1; 624 ams->map = map_groups__find(ams->map->groups, ams->map->type, 625 ams->addr); 626 if (ams->map == NULL) 627 return -1; 628 } 629 630 ams->al_addr = ams->map->map_ip(ams->map, ams->addr); 631 ams->sym = map__find_symbol(ams->map, ams->al_addr); 632 633 return ams->sym ? 0 : -1; 634 } 635 636 static size_t maps__fprintf(struct maps *maps, FILE *fp) 637 { 638 size_t printed = 0; 639 struct rb_node *nd; 640 641 pthread_rwlock_rdlock(&maps->lock); 642 643 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) { 644 struct map *pos = rb_entry(nd, struct map, rb_node); 645 printed += fprintf(fp, "Map:"); 646 printed += map__fprintf(pos, fp); 647 if (verbose > 2) { 648 printed += dso__fprintf(pos->dso, pos->type, fp); 649 printed += fprintf(fp, "--\n"); 650 } 651 } 652 653 pthread_rwlock_unlock(&maps->lock); 654 655 return printed; 656 } 657 658 size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, 659 FILE *fp) 660 { 661 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 662 return printed += maps__fprintf(&mg->maps[type], fp); 663 } 664 665 size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) 666 { 667 size_t printed = 0, i; 668 for (i = 0; i < MAP__NR_TYPES; ++i) 669 printed += __map_groups__fprintf_maps(mg, i, fp); 670 return printed; 671 } 672 673 static void __map_groups__insert(struct map_groups *mg, struct map *map) 674 { 675 __maps__insert(&mg->maps[map->type], map); 676 map->groups = mg; 677 } 678 679 static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 680 { 681 struct rb_root *root; 682 struct rb_node *next; 683 int err = 0; 684 685 pthread_rwlock_wrlock(&maps->lock); 686 687 root = &maps->entries; 688 next = rb_first(root); 689 690 while (next) { 691 struct map *pos = rb_entry(next, struct map, rb_node); 692 next = rb_next(&pos->rb_node); 693 694 if (!map__overlap(pos, map)) 695 continue; 696 697 if (verbose >= 2) { 698 699 if (use_browser) { 700 pr_warning("overlapping maps in %s " 701 "(disable tui for more info)\n", 702 map->dso->name); 703 } else { 704 fputs("overlapping maps:\n", fp); 705 map__fprintf(map, fp); 706 map__fprintf(pos, fp); 707 } 708 } 709 710 rb_erase_init(&pos->rb_node, root); 711 /* 712 * Now check if we need to create new maps for areas not 713 * overlapped by the new map: 714 */ 715 if (map->start > pos->start) { 716 struct map *before = map__clone(pos); 717 718 if (before == NULL) { 719 err = -ENOMEM; 720 goto put_map; 721 } 722 723 before->end = map->start; 724 __map_groups__insert(pos->groups, before); 725 if (verbose >= 2 && !use_browser) 726 map__fprintf(before, fp); 727 map__put(before); 728 } 729 730 if (map->end < pos->end) { 731 struct map *after = map__clone(pos); 732 733 if (after == NULL) { 734 err = -ENOMEM; 735 goto put_map; 736 } 737 738 after->start = map->end; 739 __map_groups__insert(pos->groups, after); 740 if (verbose >= 2 && !use_browser) 741 map__fprintf(after, fp); 742 map__put(after); 743 } 744 put_map: 745 map__put(pos); 746 747 if (err) 748 goto out; 749 } 750 751 err = 0; 752 out: 753 pthread_rwlock_unlock(&maps->lock); 754 return err; 755 } 756 757 int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 758 FILE *fp) 759 { 760 return maps__fixup_overlappings(&mg->maps[map->type], map, fp); 761 } 762 763 /* 764 * XXX This should not really _copy_ te maps, but refcount them. 765 */ 766 int map_groups__clone(struct thread *thread, 767 struct map_groups *parent, enum map_type type) 768 { 769 struct map_groups *mg = thread->mg; 770 int err = -ENOMEM; 771 struct map *map; 772 struct maps *maps = &parent->maps[type]; 773 774 pthread_rwlock_rdlock(&maps->lock); 775 776 for (map = maps__first(maps); map; map = map__next(map)) { 777 struct map *new = map__clone(map); 778 if (new == NULL) 779 goto out_unlock; 780 781 err = unwind__prepare_access(thread, new, NULL); 782 if (err) 783 goto out_unlock; 784 785 map_groups__insert(mg, new); 786 map__put(new); 787 } 788 789 err = 0; 790 out_unlock: 791 pthread_rwlock_unlock(&maps->lock); 792 return err; 793 } 794 795 static void __maps__insert(struct maps *maps, struct map *map) 796 { 797 struct rb_node **p = &maps->entries.rb_node; 798 struct rb_node *parent = NULL; 799 const u64 ip = map->start; 800 struct map *m; 801 802 while (*p != NULL) { 803 parent = *p; 804 m = rb_entry(parent, struct map, rb_node); 805 if (ip < m->start) 806 p = &(*p)->rb_left; 807 else 808 p = &(*p)->rb_right; 809 } 810 811 rb_link_node(&map->rb_node, parent, p); 812 rb_insert_color(&map->rb_node, &maps->entries); 813 map__get(map); 814 } 815 816 void maps__insert(struct maps *maps, struct map *map) 817 { 818 pthread_rwlock_wrlock(&maps->lock); 819 __maps__insert(maps, map); 820 pthread_rwlock_unlock(&maps->lock); 821 } 822 823 static void __maps__remove(struct maps *maps, struct map *map) 824 { 825 rb_erase_init(&map->rb_node, &maps->entries); 826 map__put(map); 827 } 828 829 void maps__remove(struct maps *maps, struct map *map) 830 { 831 pthread_rwlock_wrlock(&maps->lock); 832 __maps__remove(maps, map); 833 pthread_rwlock_unlock(&maps->lock); 834 } 835 836 struct map *maps__find(struct maps *maps, u64 ip) 837 { 838 struct rb_node **p, *parent = NULL; 839 struct map *m; 840 841 pthread_rwlock_rdlock(&maps->lock); 842 843 p = &maps->entries.rb_node; 844 while (*p != NULL) { 845 parent = *p; 846 m = rb_entry(parent, struct map, rb_node); 847 if (ip < m->start) 848 p = &(*p)->rb_left; 849 else if (ip >= m->end) 850 p = &(*p)->rb_right; 851 else 852 goto out; 853 } 854 855 m = NULL; 856 out: 857 pthread_rwlock_unlock(&maps->lock); 858 return m; 859 } 860 861 struct map *maps__first(struct maps *maps) 862 { 863 struct rb_node *first = rb_first(&maps->entries); 864 865 if (first) 866 return rb_entry(first, struct map, rb_node); 867 return NULL; 868 } 869 870 struct map *map__next(struct map *map) 871 { 872 struct rb_node *next = rb_next(&map->rb_node); 873 874 if (next) 875 return rb_entry(next, struct map, rb_node); 876 return NULL; 877 } 878 879 struct kmap *map__kmap(struct map *map) 880 { 881 if (!map->dso || !map->dso->kernel) { 882 pr_err("Internal error: map__kmap with a non-kernel map\n"); 883 return NULL; 884 } 885 return (struct kmap *)(map + 1); 886 } 887 888 struct map_groups *map__kmaps(struct map *map) 889 { 890 struct kmap *kmap = map__kmap(map); 891 892 if (!kmap || !kmap->kmaps) { 893 pr_err("Internal error: map__kmaps with a non-kernel map\n"); 894 return NULL; 895 } 896 return kmap->kmaps; 897 } 898