1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "symbol.h" 2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <errno.h> 3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <inttypes.h> 4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <limits.h> 5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h> 6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <string.h> 7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h> 8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <unistd.h> 9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "map.h" 10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "thread.h" 11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "strlist.h" 12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "vdso.h" 13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "build-id.h" 14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <linux/string.h> 15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengconst char *map_type__name[MAP__NR_TYPES] = { 17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng [MAP__FUNCTION] = "Functions", 18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng [MAP__VARIABLE] = "Variables", 19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline int is_anon_memory(const char *filename) 22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return !strcmp(filename, "//anon") || 24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng !strcmp(filename, "/dev/zero (deleted)") || 25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng !strcmp(filename, "/anon_hugepage (deleted)"); 26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline int is_no_dso_memory(const char *filename) 29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return !strncmp(filename, "[stack", 6) || 31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng !strcmp(filename, "[heap]"); 32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map__init(struct map *map, enum map_type type, 35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 start, u64 end, u64 pgoff, struct dso *dso) 36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->type = type; 38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->start = start; 39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->end = end; 40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->pgoff = pgoff; 41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->dso = dso; 42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->map_ip = map__map_ip; 43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->unmap_ip = map__unmap_ip; 44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng RB_CLEAR_NODE(&map->rb_node); 45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->groups = NULL; 46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->referenced = false; 47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->erange_warned = false; 48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *map__new(struct list_head *dsos__list, u64 start, u64 len, 51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 ino_gen, char *filename, 53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng enum map_type type) 54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *map = malloc(sizeof(*map)); 56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map != NULL) { 58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char newfilename[PATH_MAX]; 59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct dso *dso; 60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int anon, no_dso, vdso; 61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng anon = is_anon_memory(filename); 63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng vdso = is_vdso_map(filename); 64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng no_dso = is_no_dso_memory(filename); 65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->maj = d_maj; 67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->min = d_min; 68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->ino = ino; 69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->ino_generation = ino_gen; 70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (anon) { 72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng filename = newfilename; 74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (vdso) { 77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pgoff = 0; 78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dso = vdso__dso_findnew(dsos__list); 79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else 80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dso = __dsos__findnew(dsos__list, filename); 81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dso == NULL) 83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_delete; 84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__init(map, type, start, start + len, pgoff, dso); 86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (anon || no_dso) { 88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->map_ip = map->unmap_ip = identity__map_ip; 89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Set memory without DSO as loaded. All map__find_* 92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * functions still return NULL, and we avoid the 93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * unnecessary map__load warning. 94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (no_dso) 96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dso__set_loaded(dso, map->type); 97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return map; 100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_delete: 101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(map); 102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* 106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Constructor variant for modules (where we know from /proc/modules where 107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * they are loaded) and for vmlinux, where only after we load all the 108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * symbols we'll know where it starts and ends. 109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *map__new2(u64 start, struct dso *dso, enum map_type type) 111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *map = calloc(1, (sizeof(*map) + 113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (dso->kernel ? sizeof(struct kmap) : 0))); 114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map != NULL) { 115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * ->end will be filled after we load all the symbols 117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__init(map, type, start, 0, 0, dso); 119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return map; 122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map__delete(struct map *map) 125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(map); 127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map__fixup_start(struct map *map) 130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_root *symbols = &map->dso->symbols[map->type]; 132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *nd = rb_first(symbols); 133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nd != NULL) { 134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->start = sym->start; 136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map__fixup_end(struct map *map) 140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_root *symbols = &map->dso->symbols[map->type]; 142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *nd = rb_last(symbols); 143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nd != NULL) { 144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->end = sym->end; 146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define DSO__DELETED "(deleted)" 150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint map__load(struct map *map, symbol_filter_t filter) 152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *name = map->dso->long_name; 154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr; 155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dso__loaded(map->dso, map->type)) 157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nr = dso__load(map->dso, map, filter); 160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nr < 0) { 161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map->dso->has_build_id) { 162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng build_id__sprintf(map->dso->build_id, 165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sizeof(map->dso->build_id), 166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sbuild_id); 167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_warning("%s with build id %s not found", 168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng name, sbuild_id); 169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else 170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_warning("Failed to open %s", name); 171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_warning(", continuing without symbols\n"); 173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else if (nr == 0) { 175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#ifdef LIBELF_SUPPORT 176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const size_t len = strlen(name); 177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const size_t real_len = len - sizeof(DSO__DELETED); 178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (len > sizeof(DSO__DELETED) && 180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng strcmp(name + real_len + 1, DSO__DELETED) == 0) { 181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_warning("%.*s was updated (is prelink enabled?). " 182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "Restart the long running apps that use it!\n", 183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (int)real_len, name); 184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_warning("no symbols found in %s, maybe install " 186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "a debug package?\n", name); 187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#endif 189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct symbol *map__find_symbol(struct map *map, u64 addr, 196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng symbol_filter_t filter) 197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map__load(map, filter) < 0) 199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return dso__find_symbol(map->dso, map->type, addr); 202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct symbol *map__find_symbol_by_name(struct map *map, const char *name, 205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng symbol_filter_t filter) 206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map__load(map, filter) < 0) 208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!dso__sorted_by_name(map->dso, map->type)) 211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dso__sort_by_name(map->dso, map->type); 212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return dso__find_symbol_by_name(map->dso, map->type, name); 214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *map__clone(struct map *map) 217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return memdup(map, sizeof(*map)); 219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint map__overlap(struct map *l, struct map *r) 222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->start > r->start) { 224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *t = l; 225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng l = r; 226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r = t; 227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->end > r->start) 230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t map__fprintf(struct map *map, FILE *fp) 236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n", 238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map->start, map->end, map->pgoff, map->dso->name); 239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t map__fprintf_dsoname(struct map *map, FILE *fp) 242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *dsoname = "[unknown]"; 244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map && map->dso && (map->dso->name || map->dso->long_name)) { 246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (symbol_conf.show_kernel_path && map->dso->long_name) 247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dsoname = map->dso->long_name; 248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else if (map->dso->name) 249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dsoname = map->dso->name; 250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return fprintf(fp, "%s", dsoname); 253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* 256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is 258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * relative to section start. 259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengu64 map__rip_2objdump(struct map *map, u64 rip) 261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!map->dso->adjust_symbols) 263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return rip; 264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map->dso->rel) 266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return rip - map->pgoff; 267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return map->unmap_ip(map, rip); 269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map_groups__init(struct map_groups *mg) 272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < MAP__NR_TYPES; ++i) { 275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng mg->maps[i] = RB_ROOT; 276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng INIT_LIST_HEAD(&mg->removed_maps[i]); 277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng mg->machine = NULL; 279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void maps__delete(struct rb_root *maps) 282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *next = rb_first(maps); 284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (next) { 286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *pos = rb_entry(next, struct map, rb_node); 287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next = rb_next(&pos->rb_node); 289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_erase(&pos->rb_node, maps); 290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__delete(pos); 291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void maps__delete_removed(struct list_head *maps) 295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *pos, *n; 297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry_safe(pos, n, maps, node) { 299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_del(&pos->node); 300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__delete(pos); 301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map_groups__exit(struct map_groups *mg) 305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < MAP__NR_TYPES; ++i) { 309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng maps__delete(&mg->maps[i]); 310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng maps__delete_removed(&mg->removed_maps[i]); 311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid map_groups__flush(struct map_groups *mg) 315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int type; 317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (type = 0; type < MAP__NR_TYPES; type++) { 319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_root *root = &mg->maps[type]; 320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *next = rb_first(root); 321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (next) { 323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *pos = rb_entry(next, struct map, rb_node); 324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next = rb_next(&pos->rb_node); 325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_erase(&pos->rb_node, root); 326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * We may have references to this map, for 328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * instance in some hist_entry instances, so 329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * just move them to a separate list. 330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_add_tail(&pos->node, &mg->removed_maps[pos->type]); 332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct symbol *map_groups__find_symbol(struct map_groups *mg, 337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng enum map_type type, u64 addr, 338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map **mapp, 339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng symbol_filter_t filter) 340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *map = map_groups__find(mg, type, addr); 342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map != NULL) { 344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (mapp != NULL) 345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *mapp = map; 346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return map__find_symbol(map, map->map_ip(map, addr), filter); 347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng enum map_type type, 354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *name, 355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map **mapp, 356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng symbol_filter_t filter) 357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *nd; 359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { 361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *pos = rb_entry(nd, struct map, rb_node); 362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct symbol *sym = map__find_symbol_by_name(pos, name, filter); 363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sym == NULL) 365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (mapp != NULL) 367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *mapp = pos; 368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return sym; 369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t __map_groups__fprintf_maps(struct map_groups *mg, 375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng enum map_type type, int verbose, FILE *fp) 376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *nd; 379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { 381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *pos = rb_entry(nd, struct map, rb_node); 382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += fprintf(fp, "Map:"); 383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += map__fprintf(pos, fp); 384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose > 2) { 385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += dso__fprintf(pos->dso, type, fp); 386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += fprintf(fp, "--\n"); 387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return printed; 391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp) 394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t printed = 0, i; 396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < MAP__NR_TYPES; ++i) 397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += __map_groups__fprintf_maps(mg, i, verbose, fp); 398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return printed; 399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t __map_groups__fprintf_removed_maps(struct map_groups *mg, 402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng enum map_type type, 403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int verbose, FILE *fp) 404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *pos; 406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t printed = 0; 407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(pos, &mg->removed_maps[type], node) { 409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += fprintf(fp, "Map:"); 410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += map__fprintf(pos, fp); 411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose > 1) { 412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += dso__fprintf(pos->dso, type, fp); 413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += fprintf(fp, "--\n"); 414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return printed; 417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t map_groups__fprintf_removed_maps(struct map_groups *mg, 420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int verbose, FILE *fp) 421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t printed = 0, i; 423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < MAP__NR_TYPES; ++i) 424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += __map_groups__fprintf_removed_maps(mg, i, verbose, fp); 425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return printed; 426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp) 429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t printed = map_groups__fprintf_maps(mg, verbose, fp); 431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += fprintf(fp, "Removed maps:\n"); 432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return printed + map_groups__fprintf_removed_maps(mg, verbose, fp); 433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int verbose, FILE *fp) 437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_root *root = &mg->maps[map->type]; 439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *next = rb_first(root); 440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int err = 0; 441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (next) { 443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *pos = rb_entry(next, struct map, rb_node); 444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next = rb_next(&pos->rb_node); 445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!map__overlap(pos, map)) 447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose >= 2) { 450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fputs("overlapping maps:\n", fp); 451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__fprintf(map, fp); 452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__fprintf(pos, fp); 453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_erase(&pos->rb_node, root); 456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Now check if we need to create new maps for areas not 458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * overlapped by the new map: 459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map->start > pos->start) { 461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *before = map__clone(pos); 462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (before == NULL) { 464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = -ENOMEM; 465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto move_map; 466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng before->end = map->start - 1; 469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map_groups__insert(mg, before); 470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose >= 2) 471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__fprintf(before, fp); 472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (map->end < pos->end) { 475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *after = map__clone(pos); 476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (after == NULL) { 478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = -ENOMEM; 479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto move_map; 480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng after->start = map->end + 1; 483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map_groups__insert(mg, after); 484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose >= 2) 485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__fprintf(after, fp); 486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengmove_map: 488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * If we have references, just move them to a separate list. 490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pos->referenced) 492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_add_tail(&pos->node, &mg->removed_maps[map->type]); 493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map__delete(pos); 495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (err) 497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return err; 498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* 504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * XXX This should not really _copy_ te maps, but refcount them. 505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint map_groups__clone(struct map_groups *mg, 507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map_groups *parent, enum map_type type) 508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *nd; 510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { 511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *map = rb_entry(nd, struct map, rb_node); 512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *new = map__clone(map); 513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (new == NULL) 514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -ENOMEM; 515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng map_groups__insert(mg, new); 516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid maps__insert(struct rb_root *maps, struct map *map) 521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node **p = &maps->rb_node; 523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *parent = NULL; 524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u64 ip = map->start; 525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *m; 526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (*p != NULL) { 528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng parent = *p; 529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng m = rb_entry(parent, struct map, rb_node); 530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ip < m->start) 531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng p = &(*p)->rb_left; 532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng p = &(*p)->rb_right; 534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_link_node(&map->rb_node, parent, p); 537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_insert_color(&map->rb_node, maps); 538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid maps__remove(struct rb_root *maps, struct map *map) 541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_erase(&map->rb_node, maps); 543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *maps__find(struct rb_root *maps, u64 ip) 546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node **p = &maps->rb_node; 548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *parent = NULL; 549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct map *m; 550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (*p != NULL) { 552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng parent = *p; 553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng m = rb_entry(parent, struct map, rb_node); 554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ip < m->start) 555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng p = &(*p)->rb_left; 556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else if (ip > m->end) 557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng p = &(*p)->rb_right; 558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return m; 560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *maps__first(struct rb_root *maps) 566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *first = rb_first(maps); 568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (first) 570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return rb_entry(first, struct map, rb_node); 571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 574e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct map *maps__next(struct map *map) 575e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 576e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *next = rb_next(&map->rb_node); 577e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 578e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (next) 579e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return rb_entry(next, struct map, rb_node); 580e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 581e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 582