162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <errno.h> 362306a36Sopenharmony_ci#include <stdlib.h> 462306a36Sopenharmony_ci#include <linux/zalloc.h> 562306a36Sopenharmony_ci#include "debug.h" 662306a36Sopenharmony_ci#include "dso.h" 762306a36Sopenharmony_ci#include "map.h" 862306a36Sopenharmony_ci#include "maps.h" 962306a36Sopenharmony_ci#include "thread.h" 1062306a36Sopenharmony_ci#include "ui/ui.h" 1162306a36Sopenharmony_ci#include "unwind.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic void maps__init(struct maps *maps, struct machine *machine) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci refcount_set(maps__refcnt(maps), 1); 1662306a36Sopenharmony_ci init_rwsem(maps__lock(maps)); 1762306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->entries = RB_ROOT; 1862306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->machine = machine; 1962306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->last_search_by_name = NULL; 2062306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->nr_maps = 0; 2162306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->maps_by_name = NULL; 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic void __maps__free_maps_by_name(struct maps *maps) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci /* 2762306a36Sopenharmony_ci * Free everything to try to do it from the rbtree in the next search 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_ci for (unsigned int i = 0; i < maps__nr_maps(maps); i++) 3062306a36Sopenharmony_ci map__put(maps__maps_by_name(maps)[i]); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci zfree(&RC_CHK_ACCESS(maps)->maps_by_name); 3362306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->nr_maps_allocated = 0; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int __maps__insert(struct maps *maps, struct map *map) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct rb_node **p = &maps__entries(maps)->rb_node; 3962306a36Sopenharmony_ci struct rb_node *parent = NULL; 4062306a36Sopenharmony_ci const u64 ip = map__start(map); 4162306a36Sopenharmony_ci struct map_rb_node *m, *new_rb_node; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci new_rb_node = malloc(sizeof(*new_rb_node)); 4462306a36Sopenharmony_ci if (!new_rb_node) 4562306a36Sopenharmony_ci return -ENOMEM; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci RB_CLEAR_NODE(&new_rb_node->rb_node); 4862306a36Sopenharmony_ci new_rb_node->map = map__get(map); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci while (*p != NULL) { 5162306a36Sopenharmony_ci parent = *p; 5262306a36Sopenharmony_ci m = rb_entry(parent, struct map_rb_node, rb_node); 5362306a36Sopenharmony_ci if (ip < map__start(m->map)) 5462306a36Sopenharmony_ci p = &(*p)->rb_left; 5562306a36Sopenharmony_ci else 5662306a36Sopenharmony_ci p = &(*p)->rb_right; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci rb_link_node(&new_rb_node->rb_node, parent, p); 6062306a36Sopenharmony_ci rb_insert_color(&new_rb_node->rb_node, maps__entries(maps)); 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciint maps__insert(struct maps *maps, struct map *map) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci int err; 6762306a36Sopenharmony_ci const struct dso *dso = map__dso(map); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci down_write(maps__lock(maps)); 7062306a36Sopenharmony_ci err = __maps__insert(maps, map); 7162306a36Sopenharmony_ci if (err) 7262306a36Sopenharmony_ci goto out; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci ++RC_CHK_ACCESS(maps)->nr_maps; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (dso && dso->kernel) { 7762306a36Sopenharmony_ci struct kmap *kmap = map__kmap(map); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (kmap) 8062306a36Sopenharmony_ci kmap->kmaps = maps; 8162306a36Sopenharmony_ci else 8262306a36Sopenharmony_ci pr_err("Internal error: kernel dso with non kernel map\n"); 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* 8762306a36Sopenharmony_ci * If we already performed some search by name, then we need to add the just 8862306a36Sopenharmony_ci * inserted map and resort. 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_ci if (maps__maps_by_name(maps)) { 9162306a36Sopenharmony_ci if (maps__nr_maps(maps) > RC_CHK_ACCESS(maps)->nr_maps_allocated) { 9262306a36Sopenharmony_ci int nr_allocate = maps__nr_maps(maps) * 2; 9362306a36Sopenharmony_ci struct map **maps_by_name = realloc(maps__maps_by_name(maps), 9462306a36Sopenharmony_ci nr_allocate * sizeof(map)); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci if (maps_by_name == NULL) { 9762306a36Sopenharmony_ci __maps__free_maps_by_name(maps); 9862306a36Sopenharmony_ci err = -ENOMEM; 9962306a36Sopenharmony_ci goto out; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->maps_by_name = maps_by_name; 10362306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->nr_maps_allocated = nr_allocate; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci maps__maps_by_name(maps)[maps__nr_maps(maps) - 1] = map__get(map); 10662306a36Sopenharmony_ci __maps__sort_by_name(maps); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci out: 10962306a36Sopenharmony_ci up_write(maps__lock(maps)); 11062306a36Sopenharmony_ci return err; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic void __maps__remove(struct maps *maps, struct map_rb_node *rb_node) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci rb_erase_init(&rb_node->rb_node, maps__entries(maps)); 11662306a36Sopenharmony_ci map__put(rb_node->map); 11762306a36Sopenharmony_ci free(rb_node); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_civoid maps__remove(struct maps *maps, struct map *map) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct map_rb_node *rb_node; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci down_write(maps__lock(maps)); 12562306a36Sopenharmony_ci if (RC_CHK_ACCESS(maps)->last_search_by_name == map) 12662306a36Sopenharmony_ci RC_CHK_ACCESS(maps)->last_search_by_name = NULL; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci rb_node = maps__find_node(maps, map); 12962306a36Sopenharmony_ci assert(rb_node->RC_CHK_ACCESS(map) == RC_CHK_ACCESS(map)); 13062306a36Sopenharmony_ci __maps__remove(maps, rb_node); 13162306a36Sopenharmony_ci if (maps__maps_by_name(maps)) 13262306a36Sopenharmony_ci __maps__free_maps_by_name(maps); 13362306a36Sopenharmony_ci --RC_CHK_ACCESS(maps)->nr_maps; 13462306a36Sopenharmony_ci up_write(maps__lock(maps)); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic void __maps__purge(struct maps *maps) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci struct map_rb_node *pos, *next; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if (maps__maps_by_name(maps)) 14262306a36Sopenharmony_ci __maps__free_maps_by_name(maps); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci maps__for_each_entry_safe(maps, pos, next) { 14562306a36Sopenharmony_ci rb_erase_init(&pos->rb_node, maps__entries(maps)); 14662306a36Sopenharmony_ci map__put(pos->map); 14762306a36Sopenharmony_ci free(pos); 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic void maps__exit(struct maps *maps) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci down_write(maps__lock(maps)); 15462306a36Sopenharmony_ci __maps__purge(maps); 15562306a36Sopenharmony_ci up_write(maps__lock(maps)); 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cibool maps__empty(struct maps *maps) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci return !maps__first(maps); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistruct maps *maps__new(struct machine *machine) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct maps *result; 16662306a36Sopenharmony_ci RC_STRUCT(maps) *maps = zalloc(sizeof(*maps)); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (ADD_RC_CHK(result, maps)) 16962306a36Sopenharmony_ci maps__init(result, machine); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return result; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic void maps__delete(struct maps *maps) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci maps__exit(maps); 17762306a36Sopenharmony_ci unwind__finish_access(maps); 17862306a36Sopenharmony_ci RC_CHK_FREE(maps); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistruct maps *maps__get(struct maps *maps) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci struct maps *result; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (RC_CHK_GET(result, maps)) 18662306a36Sopenharmony_ci refcount_inc(maps__refcnt(maps)); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci return result; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_civoid maps__put(struct maps *maps) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci if (maps && refcount_dec_and_test(maps__refcnt(maps))) 19462306a36Sopenharmony_ci maps__delete(maps); 19562306a36Sopenharmony_ci else 19662306a36Sopenharmony_ci RC_CHK_PUT(maps); 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistruct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct map *map = maps__find(maps, addr); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Ensure map is loaded before using map->map_ip */ 20462306a36Sopenharmony_ci if (map != NULL && map__load(map) >= 0) { 20562306a36Sopenharmony_ci if (mapp != NULL) 20662306a36Sopenharmony_ci *mapp = map; 20762306a36Sopenharmony_ci return map__find_symbol(map, map__map_ip(map, addr)); 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci return NULL; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistruct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci struct symbol *sym; 21662306a36Sopenharmony_ci struct map_rb_node *pos; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci down_read(maps__lock(maps)); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci maps__for_each_entry(maps, pos) { 22162306a36Sopenharmony_ci sym = map__find_symbol_by_name(pos->map, name); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (sym == NULL) 22462306a36Sopenharmony_ci continue; 22562306a36Sopenharmony_ci if (!map__contains_symbol(pos->map, sym)) { 22662306a36Sopenharmony_ci sym = NULL; 22762306a36Sopenharmony_ci continue; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci if (mapp != NULL) 23062306a36Sopenharmony_ci *mapp = pos->map; 23162306a36Sopenharmony_ci goto out; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci sym = NULL; 23562306a36Sopenharmony_ciout: 23662306a36Sopenharmony_ci up_read(maps__lock(maps)); 23762306a36Sopenharmony_ci return sym; 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ciint maps__find_ams(struct maps *maps, struct addr_map_symbol *ams) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci if (ams->addr < map__start(ams->ms.map) || ams->addr >= map__end(ams->ms.map)) { 24362306a36Sopenharmony_ci if (maps == NULL) 24462306a36Sopenharmony_ci return -1; 24562306a36Sopenharmony_ci ams->ms.map = maps__find(maps, ams->addr); 24662306a36Sopenharmony_ci if (ams->ms.map == NULL) 24762306a36Sopenharmony_ci return -1; 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci ams->al_addr = map__map_ip(ams->ms.map, ams->addr); 25162306a36Sopenharmony_ci ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return ams->ms.sym ? 0 : -1; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cisize_t maps__fprintf(struct maps *maps, FILE *fp) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci size_t printed = 0; 25962306a36Sopenharmony_ci struct map_rb_node *pos; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci down_read(maps__lock(maps)); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci maps__for_each_entry(maps, pos) { 26462306a36Sopenharmony_ci printed += fprintf(fp, "Map:"); 26562306a36Sopenharmony_ci printed += map__fprintf(pos->map, fp); 26662306a36Sopenharmony_ci if (verbose > 2) { 26762306a36Sopenharmony_ci printed += dso__fprintf(map__dso(pos->map), fp); 26862306a36Sopenharmony_ci printed += fprintf(fp, "--\n"); 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci up_read(maps__lock(maps)); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci return printed; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ciint maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci struct rb_root *root; 28062306a36Sopenharmony_ci struct rb_node *next, *first; 28162306a36Sopenharmony_ci int err = 0; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci down_write(maps__lock(maps)); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci root = maps__entries(maps); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci /* 28862306a36Sopenharmony_ci * Find first map where end > map->start. 28962306a36Sopenharmony_ci * Same as find_vma() in kernel. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_ci next = root->rb_node; 29262306a36Sopenharmony_ci first = NULL; 29362306a36Sopenharmony_ci while (next) { 29462306a36Sopenharmony_ci struct map_rb_node *pos = rb_entry(next, struct map_rb_node, rb_node); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci if (map__end(pos->map) > map__start(map)) { 29762306a36Sopenharmony_ci first = next; 29862306a36Sopenharmony_ci if (map__start(pos->map) <= map__start(map)) 29962306a36Sopenharmony_ci break; 30062306a36Sopenharmony_ci next = next->rb_left; 30162306a36Sopenharmony_ci } else 30262306a36Sopenharmony_ci next = next->rb_right; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci next = first; 30662306a36Sopenharmony_ci while (next && !err) { 30762306a36Sopenharmony_ci struct map_rb_node *pos = rb_entry(next, struct map_rb_node, rb_node); 30862306a36Sopenharmony_ci next = rb_next(&pos->rb_node); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* 31162306a36Sopenharmony_ci * Stop if current map starts after map->end. 31262306a36Sopenharmony_ci * Maps are ordered by start: next will not overlap for sure. 31362306a36Sopenharmony_ci */ 31462306a36Sopenharmony_ci if (map__start(pos->map) >= map__end(map)) 31562306a36Sopenharmony_ci break; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci if (verbose >= 2) { 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (use_browser) { 32062306a36Sopenharmony_ci pr_debug("overlapping maps in %s (disable tui for more info)\n", 32162306a36Sopenharmony_ci map__dso(map)->name); 32262306a36Sopenharmony_ci } else { 32362306a36Sopenharmony_ci fputs("overlapping maps:\n", fp); 32462306a36Sopenharmony_ci map__fprintf(map, fp); 32562306a36Sopenharmony_ci map__fprintf(pos->map, fp); 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci rb_erase_init(&pos->rb_node, root); 33062306a36Sopenharmony_ci /* 33162306a36Sopenharmony_ci * Now check if we need to create new maps for areas not 33262306a36Sopenharmony_ci * overlapped by the new map: 33362306a36Sopenharmony_ci */ 33462306a36Sopenharmony_ci if (map__start(map) > map__start(pos->map)) { 33562306a36Sopenharmony_ci struct map *before = map__clone(pos->map); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (before == NULL) { 33862306a36Sopenharmony_ci err = -ENOMEM; 33962306a36Sopenharmony_ci goto put_map; 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci map__set_end(before, map__start(map)); 34362306a36Sopenharmony_ci err = __maps__insert(maps, before); 34462306a36Sopenharmony_ci if (err) { 34562306a36Sopenharmony_ci map__put(before); 34662306a36Sopenharmony_ci goto put_map; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (verbose >= 2 && !use_browser) 35062306a36Sopenharmony_ci map__fprintf(before, fp); 35162306a36Sopenharmony_ci map__put(before); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci if (map__end(map) < map__end(pos->map)) { 35562306a36Sopenharmony_ci struct map *after = map__clone(pos->map); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (after == NULL) { 35862306a36Sopenharmony_ci err = -ENOMEM; 35962306a36Sopenharmony_ci goto put_map; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci map__set_start(after, map__end(map)); 36362306a36Sopenharmony_ci map__add_pgoff(after, map__end(map) - map__start(pos->map)); 36462306a36Sopenharmony_ci assert(map__map_ip(pos->map, map__end(map)) == 36562306a36Sopenharmony_ci map__map_ip(after, map__end(map))); 36662306a36Sopenharmony_ci err = __maps__insert(maps, after); 36762306a36Sopenharmony_ci if (err) { 36862306a36Sopenharmony_ci map__put(after); 36962306a36Sopenharmony_ci goto put_map; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci if (verbose >= 2 && !use_browser) 37262306a36Sopenharmony_ci map__fprintf(after, fp); 37362306a36Sopenharmony_ci map__put(after); 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ciput_map: 37662306a36Sopenharmony_ci map__put(pos->map); 37762306a36Sopenharmony_ci free(pos); 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci up_write(maps__lock(maps)); 38062306a36Sopenharmony_ci return err; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci/* 38462306a36Sopenharmony_ci * XXX This should not really _copy_ te maps, but refcount them. 38562306a36Sopenharmony_ci */ 38662306a36Sopenharmony_ciint maps__clone(struct thread *thread, struct maps *parent) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci struct maps *maps = thread__maps(thread); 38962306a36Sopenharmony_ci int err; 39062306a36Sopenharmony_ci struct map_rb_node *rb_node; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci down_read(maps__lock(parent)); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci maps__for_each_entry(parent, rb_node) { 39562306a36Sopenharmony_ci struct map *new = map__clone(rb_node->map); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci if (new == NULL) { 39862306a36Sopenharmony_ci err = -ENOMEM; 39962306a36Sopenharmony_ci goto out_unlock; 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci err = unwind__prepare_access(maps, new, NULL); 40362306a36Sopenharmony_ci if (err) 40462306a36Sopenharmony_ci goto out_unlock; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci err = maps__insert(maps, new); 40762306a36Sopenharmony_ci if (err) 40862306a36Sopenharmony_ci goto out_unlock; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci map__put(new); 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci err = 0; 41462306a36Sopenharmony_ciout_unlock: 41562306a36Sopenharmony_ci up_read(maps__lock(parent)); 41662306a36Sopenharmony_ci return err; 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistruct map_rb_node *maps__find_node(struct maps *maps, struct map *map) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct map_rb_node *rb_node; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci maps__for_each_entry(maps, rb_node) { 42462306a36Sopenharmony_ci if (rb_node->RC_CHK_ACCESS(map) == RC_CHK_ACCESS(map)) 42562306a36Sopenharmony_ci return rb_node; 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci return NULL; 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistruct map *maps__find(struct maps *maps, u64 ip) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci struct rb_node *p; 43362306a36Sopenharmony_ci struct map_rb_node *m; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci down_read(maps__lock(maps)); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci p = maps__entries(maps)->rb_node; 43962306a36Sopenharmony_ci while (p != NULL) { 44062306a36Sopenharmony_ci m = rb_entry(p, struct map_rb_node, rb_node); 44162306a36Sopenharmony_ci if (ip < map__start(m->map)) 44262306a36Sopenharmony_ci p = p->rb_left; 44362306a36Sopenharmony_ci else if (ip >= map__end(m->map)) 44462306a36Sopenharmony_ci p = p->rb_right; 44562306a36Sopenharmony_ci else 44662306a36Sopenharmony_ci goto out; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci m = NULL; 45062306a36Sopenharmony_ciout: 45162306a36Sopenharmony_ci up_read(maps__lock(maps)); 45262306a36Sopenharmony_ci return m ? m->map : NULL; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistruct map_rb_node *maps__first(struct maps *maps) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci struct rb_node *first = rb_first(maps__entries(maps)); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (first) 46062306a36Sopenharmony_ci return rb_entry(first, struct map_rb_node, rb_node); 46162306a36Sopenharmony_ci return NULL; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistruct map_rb_node *map_rb_node__next(struct map_rb_node *node) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct rb_node *next; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci if (!node) 46962306a36Sopenharmony_ci return NULL; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci next = rb_next(&node->rb_node); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci if (!next) 47462306a36Sopenharmony_ci return NULL; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci return rb_entry(next, struct map_rb_node, rb_node); 47762306a36Sopenharmony_ci} 478