1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "symbol.h" 2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <errno.h> 3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <inttypes.h> 4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <limits.h> 5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdlib.h> 6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <string.h> 7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdio.h> 8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <unistd.h> 9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "map.h" 10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengconst char *map_type__name[MAP__NR_TYPES] = { 12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [MAP__FUNCTION] = "Functions", 13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [MAP__VARIABLE] = "Variables", 14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline int is_anon_memory(const char *filename) 17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return strcmp(filename, "//anon") == 0; 19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__init(struct map *self, enum map_type type, 22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 start, u64 end, u64 pgoff, struct dso *dso) 23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->type = type; 25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->start = start; 26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->end = end; 27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->pgoff = pgoff; 28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->dso = dso; 29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->map_ip = map__map_ip; 30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->unmap_ip = map__unmap_ip; 31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng RB_CLEAR_NODE(&self->rb_node); 32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->groups = NULL; 33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->referenced = false; 34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct map *map__new(struct list_head *dsos__list, u64 start, u64 len, 37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 pgoff, u32 pid, char *filename, 38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng enum map_type type) 39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *self = malloc(sizeof(*self)); 41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (self != NULL) { 43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char newfilename[PATH_MAX]; 44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dso *dso; 45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int anon; 46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng anon = is_anon_memory(filename); 48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (anon) { 50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng filename = newfilename; 52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso = __dsos__findnew(dsos__list, filename); 55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dso == NULL) 56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_delete; 57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__init(self, type, start, start + len, pgoff, dso); 59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (anon) { 61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengset_identity: 62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->map_ip = self->unmap_ip = identity__map_ip; 63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (strcmp(filename, "[vdso]") == 0) { 64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso__set_loaded(dso, self->type); 65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto set_identity; 66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return self; 69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_delete: 70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(self); 71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__delete(struct map *self) 75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(self); 77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__fixup_start(struct map *self) 80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_root *symbols = &self->dso->symbols[self->type]; 82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *nd = rb_first(symbols); 83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (nd != NULL) { 84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->start = sym->start; 86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__fixup_end(struct map *self) 90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_root *symbols = &self->dso->symbols[self->type]; 92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *nd = rb_last(symbols); 93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (nd != NULL) { 94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->end = sym->end; 96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define DSO__DELETED "(deleted)" 100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint map__load(struct map *self, symbol_filter_t filter) 102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *name = self->dso->long_name; 104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int nr; 105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dso__loaded(self->dso, self->type)) 107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng nr = dso__load(self->dso, self, filter); 110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (nr < 0) { 111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (self->dso->has_build_id) { 112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng build_id__sprintf(self->dso->build_id, 115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sizeof(self->dso->build_id), 116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sbuild_id); 117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("%s with build id %s not found", 118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng name, sbuild_id); 119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else 120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("Failed to open %s", name); 121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning(", continuing without symbols\n"); 123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (nr == 0) { 125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const size_t len = strlen(name); 126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const size_t real_len = len - sizeof(DSO__DELETED); 127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (len > sizeof(DSO__DELETED) && 129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strcmp(name + real_len + 1, DSO__DELETED) == 0) { 130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("%.*s was updated, restart the long " 131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "running apps that use it!\n", 132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (int)real_len, name); 133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("no symbols found in %s, maybe install " 135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "a debug package?\n", name); 136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Only applies to the kernel, as its symtabs aren't relative like the 142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * module ones. 143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (self->dso->kernel) 145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__reloc_vmlinux(self); 146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct symbol *map__find_symbol(struct map *self, u64 addr, 151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_filter_t filter) 152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (map__load(self, filter) < 0) 154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return dso__find_symbol(self->dso, self->type, addr); 157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct symbol *map__find_symbol_by_name(struct map *self, const char *name, 160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_filter_t filter) 161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (map__load(self, filter) < 0) 163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!dso__sorted_by_name(self->dso, self->type)) 166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso__sort_by_name(self->dso, self->type); 167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return dso__find_symbol_by_name(self->dso, self->type, name); 169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct map *map__clone(struct map *self) 172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map = malloc(sizeof(*self)); 174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!map) 176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memcpy(map, self, sizeof(*self)); 179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return map; 181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint map__overlap(struct map *l, struct map *r) 184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (l->start > r->start) { 186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *t = l; 187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng l = r; 188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng r = t; 189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (l->end > r->start) 192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengsize_t map__fprintf(struct map *self, FILE *fp) 198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n", 200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->start, self->end, self->pgoff, self->dso->name); 201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * map->dso->adjust_symbols==1 for ET_EXEC-like cases. 206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengu64 map__rip_2objdump(struct map *map, u64 rip) 208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 addr = map->dso->adjust_symbols ? 210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map->unmap_ip(map, rip) : /* RIP -> IP */ 211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rip; 212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return addr; 213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengu64 map__objdump_2ip(struct map *map, u64 addr) 216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 ip = map->dso->adjust_symbols ? 218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng addr : 219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map->unmap_ip(map, addr); /* RIP -> IP */ 220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ip; 221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map_groups__init(struct map_groups *self) 224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < MAP__NR_TYPES; ++i) { 227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->maps[i] = RB_ROOT; 228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng INIT_LIST_HEAD(&self->removed_maps[i]); 229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->machine = NULL; 231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void maps__delete(struct rb_root *self) 234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *next = rb_first(self); 236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (next) { 238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos = rb_entry(next, struct map, rb_node); 239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next = rb_next(&pos->rb_node); 241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_erase(&pos->rb_node, self); 242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__delete(pos); 243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void maps__delete_removed(struct list_head *self) 247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos, *n; 249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry_safe(pos, n, self, node) { 251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_del(&pos->node); 252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__delete(pos); 253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map_groups__exit(struct map_groups *self) 257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < MAP__NR_TYPES; ++i) { 261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng maps__delete(&self->maps[i]); 262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng maps__delete_removed(&self->removed_maps[i]); 263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map_groups__flush(struct map_groups *self) 267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int type; 269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (type = 0; type < MAP__NR_TYPES; type++) { 271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_root *root = &self->maps[type]; 272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *next = rb_first(root); 273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (next) { 275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos = rb_entry(next, struct map, rb_node); 276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next = rb_next(&pos->rb_node); 277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_erase(&pos->rb_node, root); 278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * We may have references to this map, for 280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * instance in some hist_entry instances, so 281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * just move them to a separate list. 282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_add_tail(&pos->node, &self->removed_maps[pos->type]); 284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct symbol *map_groups__find_symbol(struct map_groups *self, 289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng enum map_type type, u64 addr, 290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map **mapp, 291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_filter_t filter) 292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map = map_groups__find(self, type, addr); 294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (map != NULL) { 296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (mapp != NULL) 297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *mapp = map; 298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return map__find_symbol(map, map->map_ip(map, addr), filter); 299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct symbol *map_groups__find_symbol_by_name(struct map_groups *self, 305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng enum map_type type, 306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *name, 307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map **mapp, 308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_filter_t filter) 309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *nd; 311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { 313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos = rb_entry(nd, struct map, rb_node); 314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct symbol *sym = map__find_symbol_by_name(pos, name, filter); 315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (sym == NULL) 317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (mapp != NULL) 319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *mapp = pos; 320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return sym; 321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengsize_t __map_groups__fprintf_maps(struct map_groups *self, 327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng enum map_type type, int verbose, FILE *fp) 328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *nd; 331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { 333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos = rb_entry(nd, struct map, rb_node); 334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += fprintf(fp, "Map:"); 335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += map__fprintf(pos, fp); 336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (verbose > 2) { 337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += dso__fprintf(pos->dso, type, fp); 338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += fprintf(fp, "--\n"); 339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return printed; 343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengsize_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp) 346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t printed = 0, i; 348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < MAP__NR_TYPES; ++i) 349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += __map_groups__fprintf_maps(self, i, verbose, fp); 350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return printed; 351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic size_t __map_groups__fprintf_removed_maps(struct map_groups *self, 354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng enum map_type type, 355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int verbose, FILE *fp) 356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos; 358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t printed = 0; 359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry(pos, &self->removed_maps[type], node) { 361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += fprintf(fp, "Map:"); 362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += map__fprintf(pos, fp); 363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (verbose > 1) { 364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += dso__fprintf(pos->dso, type, fp); 365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += fprintf(fp, "--\n"); 366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return printed; 369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic size_t map_groups__fprintf_removed_maps(struct map_groups *self, 372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int verbose, FILE *fp) 373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t printed = 0, i; 375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < MAP__NR_TYPES; ++i) 376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += __map_groups__fprintf_removed_maps(self, i, verbose, fp); 377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return printed; 378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengsize_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp) 381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t printed = map_groups__fprintf_maps(self, verbose, fp); 383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += fprintf(fp, "Removed maps:\n"); 384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return printed + map_groups__fprintf_removed_maps(self, verbose, fp); 385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint map_groups__fixup_overlappings(struct map_groups *self, struct map *map, 388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int verbose, FILE *fp) 389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_root *root = &self->maps[map->type]; 391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *next = rb_first(root); 392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int err = 0; 393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (next) { 395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos = rb_entry(next, struct map, rb_node); 396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next = rb_next(&pos->rb_node); 397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!map__overlap(pos, map)) 399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (verbose >= 2) { 402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fputs("overlapping maps:\n", fp); 403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__fprintf(map, fp); 404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__fprintf(pos, fp); 405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_erase(&pos->rb_node, root); 408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Now check if we need to create new maps for areas not 410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * overlapped by the new map: 411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (map->start > pos->start) { 413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *before = map__clone(pos); 414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (before == NULL) { 416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = -ENOMEM; 417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto move_map; 418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 420e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng before->end = map->start - 1; 421e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map_groups__insert(self, before); 422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (verbose >= 2) 423e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__fprintf(before, fp); 424e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 425e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 426e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (map->end < pos->end) { 427e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *after = map__clone(pos); 428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (after == NULL) { 430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = -ENOMEM; 431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto move_map; 432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng after->start = map->end + 1; 435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map_groups__insert(self, after); 436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (verbose >= 2) 437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__fprintf(after, fp); 438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 439e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengmove_map: 440e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 441e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * If we have references, just move them to a separate list. 442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pos->referenced) 444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_add_tail(&pos->node, &self->removed_maps[map->type]); 445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__delete(pos); 447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (err) 449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return err; 450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * XXX This should not really _copy_ te maps, but refcount them. 457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint map_groups__clone(struct map_groups *self, 459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map_groups *parent, enum map_type type) 460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *nd; 462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { 463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map = rb_entry(nd, struct map, rb_node); 464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *new = map__clone(map); 465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (new == NULL) 466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map_groups__insert(self, new); 468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic u64 map__reloc_map_ip(struct map *map, u64 ip) 473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ip + (s64)map->pgoff; 475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic u64 map__reloc_unmap_ip(struct map *map, u64 ip) 478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return ip - (s64)map->pgoff; 480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid map__reloc_vmlinux(struct map *self) 483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct kmap *kmap = map__kmap(self); 485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng s64 reloc; 486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr) 488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng reloc = (kmap->ref_reloc_sym->unrelocated_addr - 491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng kmap->ref_reloc_sym->addr); 492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!reloc) 494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->map_ip = map__reloc_map_ip; 497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->unmap_ip = map__reloc_unmap_ip; 498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->pgoff = reloc; 499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid maps__insert(struct rb_root *maps, struct map *map) 502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node **p = &maps->rb_node; 504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *parent = NULL; 505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const u64 ip = map->start; 506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *m; 507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*p != NULL) { 509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parent = *p; 510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng m = rb_entry(parent, struct map, rb_node); 511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ip < m->start) 512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_left; 513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_right; 515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_link_node(&map->rb_node, parent, p); 518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_insert_color(&map->rb_node, maps); 519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid maps__remove(struct rb_root *self, struct map *map) 522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_erase(&map->rb_node, self); 524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct map *maps__find(struct rb_root *maps, u64 ip) 527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node **p = &maps->rb_node; 529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *parent = NULL; 530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *m; 531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*p != NULL) { 533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parent = *p; 534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng m = rb_entry(parent, struct map, rb_node); 535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ip < m->start) 536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_left; 537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (ip > m->end) 538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_right; 539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return m; 541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint machine__init(struct machine *self, const char *root_dir, pid_t pid) 547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map_groups__init(&self->kmaps); 549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng RB_CLEAR_NODE(&self->rb_node); 550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng INIT_LIST_HEAD(&self->user_dsos); 551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng INIT_LIST_HEAD(&self->kernel_dsos); 552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->kmaps.machine = self; 554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->pid = pid; 555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->root_dir = strdup(root_dir); 556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return self->root_dir == NULL ? -ENOMEM : 0; 557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void dsos__delete(struct list_head *self) 560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dso *pos, *n; 562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry_safe(pos, n, self, node) { 564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_del(&pos->node); 565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso__delete(pos); 566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid machine__exit(struct machine *self) 570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map_groups__exit(&self->kmaps); 572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dsos__delete(&self->user_dsos); 573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dsos__delete(&self->kernel_dsos); 574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(self->root_dir); 575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->root_dir = NULL; 576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid machine__delete(struct machine *self) 579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine__exit(self); 581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(self); 582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct machine *machines__add(struct rb_root *self, pid_t pid, 585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *root_dir) 586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node **p = &self->rb_node; 588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *parent = NULL; 589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *pos, *machine = malloc(sizeof(*machine)); 590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!machine) 592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine__init(machine, root_dir, pid) != 0) { 595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(machine); 596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*p != NULL) { 600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parent = *p; 601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pos = rb_entry(parent, struct machine, rb_node); 602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pid < pos->pid) 603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_left; 604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_right; 606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_link_node(&machine->rb_node, parent, p); 609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_insert_color(&machine->rb_node, self); 610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return machine; 612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 613e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 614e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct machine *machines__find(struct rb_root *self, pid_t pid) 615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node **p = &self->rb_node; 617e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *parent = NULL; 618e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *machine; 619e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *default_machine = NULL; 620e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 621e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*p != NULL) { 622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parent = *p; 623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine = rb_entry(parent, struct machine, rb_node); 624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pid < machine->pid) 625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_left; 626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (pid > machine->pid) 627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_right; 628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return machine; 630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!machine->pid) 631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng default_machine = machine; 632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return default_machine; 635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct machine *machines__findnew(struct rb_root *self, pid_t pid) 638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char path[PATH_MAX]; 640e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *root_dir; 641e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *machine = machines__find(self, pid); 642e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 643e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!machine || machine->pid != pid) { 644e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) 645e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng root_dir = ""; 646e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else { 647e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!symbol_conf.guestmount) 648e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 649e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sprintf(path, "%s/%d", symbol_conf.guestmount, pid); 650e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (access(path, R_OK)) { 651e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Can't access file %s\n", path); 652e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 653e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 654e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng root_dir = path; 655e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 656e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine = machines__add(self, pid, root_dir); 657e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 658e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 659e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout: 660e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return machine; 661e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 662e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 663e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid machines__process(struct rb_root *self, machine__process_t process, void *data) 664e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 665e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *nd; 666e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 667e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (nd = rb_first(self); nd; nd = rb_next(nd)) { 668e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *pos = rb_entry(nd, struct machine, rb_node); 669e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process(pos, data); 670e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 671e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 672e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 673e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengchar *machine__mmap_name(struct machine *self, char *bf, size_t size) 674e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 675e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine__is_host(self)) 676e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(bf, size, "[%s]", "kernel.kallsyms"); 677e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else if (machine__is_default_guest(self)) 678e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(bf, size, "[%s]", "guest.kernel.kallsyms"); 679e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 680e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid); 681e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 682e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return bf; 683e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 684