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