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