15aab621bSArnaldo Carvalho de Melo #include <dirent.h> 25aab621bSArnaldo Carvalho de Melo #include <errno.h> 35aab621bSArnaldo Carvalho de Melo #include <stdlib.h> 45aab621bSArnaldo Carvalho de Melo #include <stdio.h> 55aab621bSArnaldo Carvalho de Melo #include <string.h> 65aab621bSArnaldo Carvalho de Melo #include <sys/types.h> 75aab621bSArnaldo Carvalho de Melo #include <sys/stat.h> 85aab621bSArnaldo Carvalho de Melo #include <sys/param.h> 95aab621bSArnaldo Carvalho de Melo #include <fcntl.h> 105aab621bSArnaldo Carvalho de Melo #include <unistd.h> 119486aa38SArnaldo Carvalho de Melo #include <inttypes.h> 12b36f19d5SArnaldo Carvalho de Melo #include "build-id.h" 13e334c726SNamhyung Kim #include "util.h" 148a6c5b26SArnaldo Carvalho de Melo #include "debug.h" 1586470930SIngo Molnar #include "symbol.h" 165aab621bSArnaldo Carvalho de Melo #include "strlist.h" 1786470930SIngo Molnar 1886470930SIngo Molnar #include <elf.h> 19f1617b40SArnaldo Carvalho de Melo #include <limits.h> 20439d473bSArnaldo Carvalho de Melo #include <sys/utsname.h> 212cdbc46dSPeter Zijlstra 223b01a413SArnaldo Carvalho de Melo #ifndef KSYM_NAME_LEN 23c752d040SRicardo Ribalda Delgado #define KSYM_NAME_LEN 256 243b01a413SArnaldo Carvalho de Melo #endif 253b01a413SArnaldo Carvalho de Melo 26aeafcbafSArnaldo Carvalho de Melo static int dso__load_kernel_sym(struct dso *dso, struct map *map, 279de89fe7SArnaldo Carvalho de Melo symbol_filter_t filter); 28aeafcbafSArnaldo Carvalho de Melo static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 29a1645ce1SZhang, Yanmin symbol_filter_t filter); 30cc612d81SArnaldo Carvalho de Melo static int vmlinux_path__nr_entries; 31cc612d81SArnaldo Carvalho de Melo static char **vmlinux_path; 32439d473bSArnaldo Carvalho de Melo 3375be6cf4SArnaldo Carvalho de Melo struct symbol_conf symbol_conf = { 34d599db3fSArnaldo Carvalho de Melo .exclude_other = true, 35b32d133aSArnaldo Carvalho de Melo .use_modules = true, 36b32d133aSArnaldo Carvalho de Melo .try_vmlinux_path = true, 373e6a2a7fSStephane Eranian .annotate_src = true, 38ec5761eaSDavid Ahern .symfs = "", 39b32d133aSArnaldo Carvalho de Melo }; 40b32d133aSArnaldo Carvalho de Melo 4144f24cb3SJiri Olsa static enum dso_binary_type binary_type_symtab[] = { 4244f24cb3SJiri Olsa DSO_BINARY_TYPE__KALLSYMS, 4344f24cb3SJiri Olsa DSO_BINARY_TYPE__GUEST_KALLSYMS, 4444f24cb3SJiri Olsa DSO_BINARY_TYPE__JAVA_JIT, 4544f24cb3SJiri Olsa DSO_BINARY_TYPE__DEBUGLINK, 4644f24cb3SJiri Olsa DSO_BINARY_TYPE__BUILD_ID_CACHE, 4744f24cb3SJiri Olsa DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 4844f24cb3SJiri Olsa DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 4944f24cb3SJiri Olsa DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 5044f24cb3SJiri Olsa DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 5144f24cb3SJiri Olsa DSO_BINARY_TYPE__GUEST_KMODULE, 5244f24cb3SJiri Olsa DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 5344f24cb3SJiri Olsa DSO_BINARY_TYPE__NOT_FOUND, 5444f24cb3SJiri Olsa }; 5544f24cb3SJiri Olsa 56028df767SJiri Olsa #define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab) 5744f24cb3SJiri Olsa 5836a3e646SArnaldo Carvalho de Melo bool symbol_type__is_a(char symbol_type, enum map_type map_type) 596893d4eeSArnaldo Carvalho de Melo { 6031877908SAnton Blanchard symbol_type = toupper(symbol_type); 6131877908SAnton Blanchard 626893d4eeSArnaldo Carvalho de Melo switch (map_type) { 636893d4eeSArnaldo Carvalho de Melo case MAP__FUNCTION: 646893d4eeSArnaldo Carvalho de Melo return symbol_type == 'T' || symbol_type == 'W'; 65f1dfa0b1SArnaldo Carvalho de Melo case MAP__VARIABLE: 6631877908SAnton Blanchard return symbol_type == 'D'; 676893d4eeSArnaldo Carvalho de Melo default: 686893d4eeSArnaldo Carvalho de Melo return false; 696893d4eeSArnaldo Carvalho de Melo } 706893d4eeSArnaldo Carvalho de Melo } 716893d4eeSArnaldo Carvalho de Melo 72694bf407SAnton Blanchard static int prefix_underscores_count(const char *str) 73694bf407SAnton Blanchard { 74694bf407SAnton Blanchard const char *tail = str; 75694bf407SAnton Blanchard 76694bf407SAnton Blanchard while (*tail == '_') 77694bf407SAnton Blanchard tail++; 78694bf407SAnton Blanchard 79694bf407SAnton Blanchard return tail - str; 80694bf407SAnton Blanchard } 81694bf407SAnton Blanchard 82694bf407SAnton Blanchard #define SYMBOL_A 0 83694bf407SAnton Blanchard #define SYMBOL_B 1 84694bf407SAnton Blanchard 85694bf407SAnton Blanchard static int choose_best_symbol(struct symbol *syma, struct symbol *symb) 86694bf407SAnton Blanchard { 87694bf407SAnton Blanchard s64 a; 88694bf407SAnton Blanchard s64 b; 89694bf407SAnton Blanchard 90694bf407SAnton Blanchard /* Prefer a symbol with non zero length */ 91694bf407SAnton Blanchard a = syma->end - syma->start; 92694bf407SAnton Blanchard b = symb->end - symb->start; 93694bf407SAnton Blanchard if ((b == 0) && (a > 0)) 94694bf407SAnton Blanchard return SYMBOL_A; 95694bf407SAnton Blanchard else if ((a == 0) && (b > 0)) 96694bf407SAnton Blanchard return SYMBOL_B; 97694bf407SAnton Blanchard 98694bf407SAnton Blanchard /* Prefer a non weak symbol over a weak one */ 99694bf407SAnton Blanchard a = syma->binding == STB_WEAK; 100694bf407SAnton Blanchard b = symb->binding == STB_WEAK; 101694bf407SAnton Blanchard if (b && !a) 102694bf407SAnton Blanchard return SYMBOL_A; 103694bf407SAnton Blanchard if (a && !b) 104694bf407SAnton Blanchard return SYMBOL_B; 105694bf407SAnton Blanchard 106694bf407SAnton Blanchard /* Prefer a global symbol over a non global one */ 107694bf407SAnton Blanchard a = syma->binding == STB_GLOBAL; 108694bf407SAnton Blanchard b = symb->binding == STB_GLOBAL; 109694bf407SAnton Blanchard if (a && !b) 110694bf407SAnton Blanchard return SYMBOL_A; 111694bf407SAnton Blanchard if (b && !a) 112694bf407SAnton Blanchard return SYMBOL_B; 113694bf407SAnton Blanchard 114694bf407SAnton Blanchard /* Prefer a symbol with less underscores */ 115694bf407SAnton Blanchard a = prefix_underscores_count(syma->name); 116694bf407SAnton Blanchard b = prefix_underscores_count(symb->name); 117694bf407SAnton Blanchard if (b > a) 118694bf407SAnton Blanchard return SYMBOL_A; 119694bf407SAnton Blanchard else if (a > b) 120694bf407SAnton Blanchard return SYMBOL_B; 121694bf407SAnton Blanchard 122694bf407SAnton Blanchard /* If all else fails, choose the symbol with the longest name */ 123694bf407SAnton Blanchard if (strlen(syma->name) >= strlen(symb->name)) 124694bf407SAnton Blanchard return SYMBOL_A; 125694bf407SAnton Blanchard else 126694bf407SAnton Blanchard return SYMBOL_B; 127694bf407SAnton Blanchard } 128694bf407SAnton Blanchard 129e5a1845fSNamhyung Kim void symbols__fixup_duplicate(struct rb_root *symbols) 130694bf407SAnton Blanchard { 131694bf407SAnton Blanchard struct rb_node *nd; 132694bf407SAnton Blanchard struct symbol *curr, *next; 133694bf407SAnton Blanchard 134694bf407SAnton Blanchard nd = rb_first(symbols); 135694bf407SAnton Blanchard 136694bf407SAnton Blanchard while (nd) { 137694bf407SAnton Blanchard curr = rb_entry(nd, struct symbol, rb_node); 138694bf407SAnton Blanchard again: 139694bf407SAnton Blanchard nd = rb_next(&curr->rb_node); 140694bf407SAnton Blanchard next = rb_entry(nd, struct symbol, rb_node); 141694bf407SAnton Blanchard 142694bf407SAnton Blanchard if (!nd) 143694bf407SAnton Blanchard break; 144694bf407SAnton Blanchard 145694bf407SAnton Blanchard if (curr->start != next->start) 146694bf407SAnton Blanchard continue; 147694bf407SAnton Blanchard 148694bf407SAnton Blanchard if (choose_best_symbol(curr, next) == SYMBOL_A) { 149694bf407SAnton Blanchard rb_erase(&next->rb_node, symbols); 150694bf407SAnton Blanchard goto again; 151694bf407SAnton Blanchard } else { 152694bf407SAnton Blanchard nd = rb_next(&curr->rb_node); 153694bf407SAnton Blanchard rb_erase(&curr->rb_node, symbols); 154694bf407SAnton Blanchard } 155694bf407SAnton Blanchard } 156694bf407SAnton Blanchard } 157694bf407SAnton Blanchard 158e5a1845fSNamhyung Kim void symbols__fixup_end(struct rb_root *symbols) 159af427bf5SArnaldo Carvalho de Melo { 160aeafcbafSArnaldo Carvalho de Melo struct rb_node *nd, *prevnd = rb_first(symbols); 1612e538c4aSArnaldo Carvalho de Melo struct symbol *curr, *prev; 162af427bf5SArnaldo Carvalho de Melo 163af427bf5SArnaldo Carvalho de Melo if (prevnd == NULL) 164af427bf5SArnaldo Carvalho de Melo return; 165af427bf5SArnaldo Carvalho de Melo 1662e538c4aSArnaldo Carvalho de Melo curr = rb_entry(prevnd, struct symbol, rb_node); 1672e538c4aSArnaldo Carvalho de Melo 168af427bf5SArnaldo Carvalho de Melo for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 1692e538c4aSArnaldo Carvalho de Melo prev = curr; 1702e538c4aSArnaldo Carvalho de Melo curr = rb_entry(nd, struct symbol, rb_node); 171af427bf5SArnaldo Carvalho de Melo 1723b01a413SArnaldo Carvalho de Melo if (prev->end == prev->start && prev->end != curr->start) 173af427bf5SArnaldo Carvalho de Melo prev->end = curr->start - 1; 174af427bf5SArnaldo Carvalho de Melo } 175af427bf5SArnaldo Carvalho de Melo 1762e538c4aSArnaldo Carvalho de Melo /* Last entry */ 1772e538c4aSArnaldo Carvalho de Melo if (curr->end == curr->start) 1782e538c4aSArnaldo Carvalho de Melo curr->end = roundup(curr->start, 4096); 1792e538c4aSArnaldo Carvalho de Melo } 1802e538c4aSArnaldo Carvalho de Melo 181e5a1845fSNamhyung Kim void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) 182af427bf5SArnaldo Carvalho de Melo { 183af427bf5SArnaldo Carvalho de Melo struct map *prev, *curr; 184aeafcbafSArnaldo Carvalho de Melo struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); 185af427bf5SArnaldo Carvalho de Melo 186af427bf5SArnaldo Carvalho de Melo if (prevnd == NULL) 187af427bf5SArnaldo Carvalho de Melo return; 188af427bf5SArnaldo Carvalho de Melo 189af427bf5SArnaldo Carvalho de Melo curr = rb_entry(prevnd, struct map, rb_node); 190af427bf5SArnaldo Carvalho de Melo 191af427bf5SArnaldo Carvalho de Melo for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 192af427bf5SArnaldo Carvalho de Melo prev = curr; 193af427bf5SArnaldo Carvalho de Melo curr = rb_entry(nd, struct map, rb_node); 194af427bf5SArnaldo Carvalho de Melo prev->end = curr->start - 1; 1952e538c4aSArnaldo Carvalho de Melo } 19690c83218SArnaldo Carvalho de Melo 19790c83218SArnaldo Carvalho de Melo /* 19890c83218SArnaldo Carvalho de Melo * We still haven't the actual symbols, so guess the 19990c83218SArnaldo Carvalho de Melo * last map final address. 20090c83218SArnaldo Carvalho de Melo */ 2019d1faba5SIan Munsie curr->end = ~0ULL; 202af427bf5SArnaldo Carvalho de Melo } 203af427bf5SArnaldo Carvalho de Melo 204aeafcbafSArnaldo Carvalho de Melo static void map_groups__fixup_end(struct map_groups *mg) 20523ea4a3fSArnaldo Carvalho de Melo { 20623ea4a3fSArnaldo Carvalho de Melo int i; 20723ea4a3fSArnaldo Carvalho de Melo for (i = 0; i < MAP__NR_TYPES; ++i) 208aeafcbafSArnaldo Carvalho de Melo __map_groups__fixup_end(mg, i); 20923ea4a3fSArnaldo Carvalho de Melo } 21023ea4a3fSArnaldo Carvalho de Melo 211e5a1845fSNamhyung Kim struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) 21286470930SIngo Molnar { 21386470930SIngo Molnar size_t namelen = strlen(name) + 1; 214aeafcbafSArnaldo Carvalho de Melo struct symbol *sym = calloc(1, (symbol_conf.priv_size + 215aeafcbafSArnaldo Carvalho de Melo sizeof(*sym) + namelen)); 216aeafcbafSArnaldo Carvalho de Melo if (sym == NULL) 21786470930SIngo Molnar return NULL; 21886470930SIngo Molnar 21975be6cf4SArnaldo Carvalho de Melo if (symbol_conf.priv_size) 220aeafcbafSArnaldo Carvalho de Melo sym = ((void *)sym) + symbol_conf.priv_size; 22136479484SArnaldo Carvalho de Melo 222aeafcbafSArnaldo Carvalho de Melo sym->start = start; 223aeafcbafSArnaldo Carvalho de Melo sym->end = len ? start + len - 1 : start; 224aeafcbafSArnaldo Carvalho de Melo sym->binding = binding; 225aeafcbafSArnaldo Carvalho de Melo sym->namelen = namelen - 1; 226e4204992SArnaldo Carvalho de Melo 227aeafcbafSArnaldo Carvalho de Melo pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", 228aeafcbafSArnaldo Carvalho de Melo __func__, name, start, sym->end); 229aeafcbafSArnaldo Carvalho de Melo memcpy(sym->name, name, namelen); 230e4204992SArnaldo Carvalho de Melo 231aeafcbafSArnaldo Carvalho de Melo return sym; 23286470930SIngo Molnar } 23386470930SIngo Molnar 234aeafcbafSArnaldo Carvalho de Melo void symbol__delete(struct symbol *sym) 23586470930SIngo Molnar { 236aeafcbafSArnaldo Carvalho de Melo free(((void *)sym) - symbol_conf.priv_size); 23786470930SIngo Molnar } 23886470930SIngo Molnar 239*cdd059d7SJiri Olsa size_t symbol__fprintf(struct symbol *sym, FILE *fp) 24086470930SIngo Molnar { 2419486aa38SArnaldo Carvalho de Melo return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", 242aeafcbafSArnaldo Carvalho de Melo sym->start, sym->end, 243aeafcbafSArnaldo Carvalho de Melo sym->binding == STB_GLOBAL ? 'g' : 244aeafcbafSArnaldo Carvalho de Melo sym->binding == STB_LOCAL ? 'l' : 'w', 245aeafcbafSArnaldo Carvalho de Melo sym->name); 24686470930SIngo Molnar } 24786470930SIngo Molnar 248a978f2abSAkihiro Nagai size_t symbol__fprintf_symname_offs(const struct symbol *sym, 249a978f2abSAkihiro Nagai const struct addr_location *al, FILE *fp) 250a978f2abSAkihiro Nagai { 251a978f2abSAkihiro Nagai unsigned long offset; 252a978f2abSAkihiro Nagai size_t length; 253a978f2abSAkihiro Nagai 254a978f2abSAkihiro Nagai if (sym && sym->name) { 255a978f2abSAkihiro Nagai length = fprintf(fp, "%s", sym->name); 256a978f2abSAkihiro Nagai if (al) { 257a978f2abSAkihiro Nagai offset = al->addr - sym->start; 258a978f2abSAkihiro Nagai length += fprintf(fp, "+0x%lx", offset); 259a978f2abSAkihiro Nagai } 260a978f2abSAkihiro Nagai return length; 261a978f2abSAkihiro Nagai } else 262a978f2abSAkihiro Nagai return fprintf(fp, "[unknown]"); 263a978f2abSAkihiro Nagai } 264a978f2abSAkihiro Nagai 265547a92e0SAkihiro Nagai size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp) 266547a92e0SAkihiro Nagai { 267a978f2abSAkihiro Nagai return symbol__fprintf_symname_offs(sym, NULL, fp); 268547a92e0SAkihiro Nagai } 269547a92e0SAkihiro Nagai 270*cdd059d7SJiri Olsa void symbols__delete(struct rb_root *symbols) 27186470930SIngo Molnar { 27286470930SIngo Molnar struct symbol *pos; 273aeafcbafSArnaldo Carvalho de Melo struct rb_node *next = rb_first(symbols); 27486470930SIngo Molnar 27586470930SIngo Molnar while (next) { 27686470930SIngo Molnar pos = rb_entry(next, struct symbol, rb_node); 27786470930SIngo Molnar next = rb_next(&pos->rb_node); 278aeafcbafSArnaldo Carvalho de Melo rb_erase(&pos->rb_node, symbols); 27900a192b3SArnaldo Carvalho de Melo symbol__delete(pos); 28086470930SIngo Molnar } 28186470930SIngo Molnar } 28286470930SIngo Molnar 283e5a1845fSNamhyung Kim void symbols__insert(struct rb_root *symbols, struct symbol *sym) 28486470930SIngo Molnar { 285aeafcbafSArnaldo Carvalho de Melo struct rb_node **p = &symbols->rb_node; 28686470930SIngo Molnar struct rb_node *parent = NULL; 2879cffa8d5SPaul Mackerras const u64 ip = sym->start; 28886470930SIngo Molnar struct symbol *s; 28986470930SIngo Molnar 29086470930SIngo Molnar while (*p != NULL) { 29186470930SIngo Molnar parent = *p; 29286470930SIngo Molnar s = rb_entry(parent, struct symbol, rb_node); 29386470930SIngo Molnar if (ip < s->start) 29486470930SIngo Molnar p = &(*p)->rb_left; 29586470930SIngo Molnar else 29686470930SIngo Molnar p = &(*p)->rb_right; 29786470930SIngo Molnar } 29886470930SIngo Molnar rb_link_node(&sym->rb_node, parent, p); 299aeafcbafSArnaldo Carvalho de Melo rb_insert_color(&sym->rb_node, symbols); 30086470930SIngo Molnar } 30186470930SIngo Molnar 302aeafcbafSArnaldo Carvalho de Melo static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) 30386470930SIngo Molnar { 30486470930SIngo Molnar struct rb_node *n; 30586470930SIngo Molnar 306aeafcbafSArnaldo Carvalho de Melo if (symbols == NULL) 30786470930SIngo Molnar return NULL; 30886470930SIngo Molnar 309aeafcbafSArnaldo Carvalho de Melo n = symbols->rb_node; 31086470930SIngo Molnar 31186470930SIngo Molnar while (n) { 31286470930SIngo Molnar struct symbol *s = rb_entry(n, struct symbol, rb_node); 31386470930SIngo Molnar 31486470930SIngo Molnar if (ip < s->start) 31586470930SIngo Molnar n = n->rb_left; 31686470930SIngo Molnar else if (ip > s->end) 31786470930SIngo Molnar n = n->rb_right; 31886470930SIngo Molnar else 31986470930SIngo Molnar return s; 32086470930SIngo Molnar } 32186470930SIngo Molnar 32286470930SIngo Molnar return NULL; 32386470930SIngo Molnar } 32486470930SIngo Molnar 32579406cd7SArnaldo Carvalho de Melo struct symbol_name_rb_node { 32679406cd7SArnaldo Carvalho de Melo struct rb_node rb_node; 32779406cd7SArnaldo Carvalho de Melo struct symbol sym; 32879406cd7SArnaldo Carvalho de Melo }; 32979406cd7SArnaldo Carvalho de Melo 330aeafcbafSArnaldo Carvalho de Melo static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) 33179406cd7SArnaldo Carvalho de Melo { 332aeafcbafSArnaldo Carvalho de Melo struct rb_node **p = &symbols->rb_node; 33379406cd7SArnaldo Carvalho de Melo struct rb_node *parent = NULL; 33402a9d037SRabin Vincent struct symbol_name_rb_node *symn, *s; 33502a9d037SRabin Vincent 33602a9d037SRabin Vincent symn = container_of(sym, struct symbol_name_rb_node, sym); 33779406cd7SArnaldo Carvalho de Melo 33879406cd7SArnaldo Carvalho de Melo while (*p != NULL) { 33979406cd7SArnaldo Carvalho de Melo parent = *p; 34079406cd7SArnaldo Carvalho de Melo s = rb_entry(parent, struct symbol_name_rb_node, rb_node); 34179406cd7SArnaldo Carvalho de Melo if (strcmp(sym->name, s->sym.name) < 0) 34279406cd7SArnaldo Carvalho de Melo p = &(*p)->rb_left; 34379406cd7SArnaldo Carvalho de Melo else 34479406cd7SArnaldo Carvalho de Melo p = &(*p)->rb_right; 34579406cd7SArnaldo Carvalho de Melo } 34679406cd7SArnaldo Carvalho de Melo rb_link_node(&symn->rb_node, parent, p); 347aeafcbafSArnaldo Carvalho de Melo rb_insert_color(&symn->rb_node, symbols); 34879406cd7SArnaldo Carvalho de Melo } 34979406cd7SArnaldo Carvalho de Melo 350aeafcbafSArnaldo Carvalho de Melo static void symbols__sort_by_name(struct rb_root *symbols, 351aeafcbafSArnaldo Carvalho de Melo struct rb_root *source) 35279406cd7SArnaldo Carvalho de Melo { 35379406cd7SArnaldo Carvalho de Melo struct rb_node *nd; 35479406cd7SArnaldo Carvalho de Melo 35579406cd7SArnaldo Carvalho de Melo for (nd = rb_first(source); nd; nd = rb_next(nd)) { 35679406cd7SArnaldo Carvalho de Melo struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 357aeafcbafSArnaldo Carvalho de Melo symbols__insert_by_name(symbols, pos); 35879406cd7SArnaldo Carvalho de Melo } 35979406cd7SArnaldo Carvalho de Melo } 36079406cd7SArnaldo Carvalho de Melo 361aeafcbafSArnaldo Carvalho de Melo static struct symbol *symbols__find_by_name(struct rb_root *symbols, 362aeafcbafSArnaldo Carvalho de Melo const char *name) 36379406cd7SArnaldo Carvalho de Melo { 36479406cd7SArnaldo Carvalho de Melo struct rb_node *n; 36579406cd7SArnaldo Carvalho de Melo 366aeafcbafSArnaldo Carvalho de Melo if (symbols == NULL) 36779406cd7SArnaldo Carvalho de Melo return NULL; 36879406cd7SArnaldo Carvalho de Melo 369aeafcbafSArnaldo Carvalho de Melo n = symbols->rb_node; 37079406cd7SArnaldo Carvalho de Melo 37179406cd7SArnaldo Carvalho de Melo while (n) { 37279406cd7SArnaldo Carvalho de Melo struct symbol_name_rb_node *s; 37379406cd7SArnaldo Carvalho de Melo int cmp; 37479406cd7SArnaldo Carvalho de Melo 37579406cd7SArnaldo Carvalho de Melo s = rb_entry(n, struct symbol_name_rb_node, rb_node); 37679406cd7SArnaldo Carvalho de Melo cmp = strcmp(name, s->sym.name); 37779406cd7SArnaldo Carvalho de Melo 37879406cd7SArnaldo Carvalho de Melo if (cmp < 0) 37979406cd7SArnaldo Carvalho de Melo n = n->rb_left; 38079406cd7SArnaldo Carvalho de Melo else if (cmp > 0) 38179406cd7SArnaldo Carvalho de Melo n = n->rb_right; 38279406cd7SArnaldo Carvalho de Melo else 38379406cd7SArnaldo Carvalho de Melo return &s->sym; 38479406cd7SArnaldo Carvalho de Melo } 38579406cd7SArnaldo Carvalho de Melo 38679406cd7SArnaldo Carvalho de Melo return NULL; 38779406cd7SArnaldo Carvalho de Melo } 38879406cd7SArnaldo Carvalho de Melo 389aeafcbafSArnaldo Carvalho de Melo struct symbol *dso__find_symbol(struct dso *dso, 39079406cd7SArnaldo Carvalho de Melo enum map_type type, u64 addr) 391fcf1203aSArnaldo Carvalho de Melo { 392aeafcbafSArnaldo Carvalho de Melo return symbols__find(&dso->symbols[type], addr); 393fcf1203aSArnaldo Carvalho de Melo } 394fcf1203aSArnaldo Carvalho de Melo 395aeafcbafSArnaldo Carvalho de Melo struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 39679406cd7SArnaldo Carvalho de Melo const char *name) 39779406cd7SArnaldo Carvalho de Melo { 398aeafcbafSArnaldo Carvalho de Melo return symbols__find_by_name(&dso->symbol_names[type], name); 39979406cd7SArnaldo Carvalho de Melo } 40079406cd7SArnaldo Carvalho de Melo 401aeafcbafSArnaldo Carvalho de Melo void dso__sort_by_name(struct dso *dso, enum map_type type) 40279406cd7SArnaldo Carvalho de Melo { 403aeafcbafSArnaldo Carvalho de Melo dso__set_sorted_by_name(dso, type); 404aeafcbafSArnaldo Carvalho de Melo return symbols__sort_by_name(&dso->symbol_names[type], 405aeafcbafSArnaldo Carvalho de Melo &dso->symbols[type]); 40679406cd7SArnaldo Carvalho de Melo } 40779406cd7SArnaldo Carvalho de Melo 408aeafcbafSArnaldo Carvalho de Melo size_t dso__fprintf_symbols_by_name(struct dso *dso, 409aeafcbafSArnaldo Carvalho de Melo enum map_type type, FILE *fp) 41090f18e63SSrikar Dronamraju { 41190f18e63SSrikar Dronamraju size_t ret = 0; 41290f18e63SSrikar Dronamraju struct rb_node *nd; 41390f18e63SSrikar Dronamraju struct symbol_name_rb_node *pos; 41490f18e63SSrikar Dronamraju 415aeafcbafSArnaldo Carvalho de Melo for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) { 41690f18e63SSrikar Dronamraju pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); 41790f18e63SSrikar Dronamraju fprintf(fp, "%s\n", pos->sym.name); 41890f18e63SSrikar Dronamraju } 41990f18e63SSrikar Dronamraju 42090f18e63SSrikar Dronamraju return ret; 42190f18e63SSrikar Dronamraju } 42290f18e63SSrikar Dronamraju 4239e201442SArnaldo Carvalho de Melo int kallsyms__parse(const char *filename, void *arg, 4249e201442SArnaldo Carvalho de Melo int (*process_symbol)(void *arg, const char *name, 42582151520SCody P Schafer char type, u64 start)) 42686470930SIngo Molnar { 42786470930SIngo Molnar char *line = NULL; 42886470930SIngo Molnar size_t n; 4293b01a413SArnaldo Carvalho de Melo int err = -1; 4309e201442SArnaldo Carvalho de Melo FILE *file = fopen(filename, "r"); 43186470930SIngo Molnar 43286470930SIngo Molnar if (file == NULL) 43386470930SIngo Molnar goto out_failure; 43486470930SIngo Molnar 4353b01a413SArnaldo Carvalho de Melo err = 0; 4363b01a413SArnaldo Carvalho de Melo 43786470930SIngo Molnar while (!feof(file)) { 4389cffa8d5SPaul Mackerras u64 start; 43986470930SIngo Molnar int line_len, len; 44086470930SIngo Molnar char symbol_type; 4412e538c4aSArnaldo Carvalho de Melo char *symbol_name; 44286470930SIngo Molnar 44386470930SIngo Molnar line_len = getline(&line, &n, file); 444a1645ce1SZhang, Yanmin if (line_len < 0 || !line) 44586470930SIngo Molnar break; 44686470930SIngo Molnar 44786470930SIngo Molnar line[--line_len] = '\0'; /* \n */ 44886470930SIngo Molnar 44986470930SIngo Molnar len = hex2u64(line, &start); 45086470930SIngo Molnar 45186470930SIngo Molnar len++; 45286470930SIngo Molnar if (len + 2 >= line_len) 45386470930SIngo Molnar continue; 45486470930SIngo Molnar 45531877908SAnton Blanchard symbol_type = line[len]; 4563b01a413SArnaldo Carvalho de Melo len += 2; 4573b01a413SArnaldo Carvalho de Melo symbol_name = line + len; 4583b01a413SArnaldo Carvalho de Melo len = line_len - len; 459682b335aSArnaldo Carvalho de Melo 4603b01a413SArnaldo Carvalho de Melo if (len >= KSYM_NAME_LEN) { 4613b01a413SArnaldo Carvalho de Melo err = -1; 4623b01a413SArnaldo Carvalho de Melo break; 4633b01a413SArnaldo Carvalho de Melo } 4643b01a413SArnaldo Carvalho de Melo 4653f5a4272SAnton Blanchard err = process_symbol(arg, symbol_name, 46682151520SCody P Schafer symbol_type, start); 467682b335aSArnaldo Carvalho de Melo if (err) 468682b335aSArnaldo Carvalho de Melo break; 469682b335aSArnaldo Carvalho de Melo } 470682b335aSArnaldo Carvalho de Melo 471682b335aSArnaldo Carvalho de Melo free(line); 472682b335aSArnaldo Carvalho de Melo fclose(file); 473682b335aSArnaldo Carvalho de Melo return err; 474682b335aSArnaldo Carvalho de Melo 475682b335aSArnaldo Carvalho de Melo out_failure: 476682b335aSArnaldo Carvalho de Melo return -1; 477682b335aSArnaldo Carvalho de Melo } 478682b335aSArnaldo Carvalho de Melo 479682b335aSArnaldo Carvalho de Melo struct process_kallsyms_args { 480682b335aSArnaldo Carvalho de Melo struct map *map; 481682b335aSArnaldo Carvalho de Melo struct dso *dso; 482682b335aSArnaldo Carvalho de Melo }; 483682b335aSArnaldo Carvalho de Melo 484c408fedfSArnaldo Carvalho de Melo static u8 kallsyms2elf_type(char type) 485c408fedfSArnaldo Carvalho de Melo { 486c408fedfSArnaldo Carvalho de Melo if (type == 'W') 487c408fedfSArnaldo Carvalho de Melo return STB_WEAK; 488c408fedfSArnaldo Carvalho de Melo 489c408fedfSArnaldo Carvalho de Melo return isupper(type) ? STB_GLOBAL : STB_LOCAL; 490c408fedfSArnaldo Carvalho de Melo } 491c408fedfSArnaldo Carvalho de Melo 492682b335aSArnaldo Carvalho de Melo static int map__process_kallsym_symbol(void *arg, const char *name, 49382151520SCody P Schafer char type, u64 start) 494682b335aSArnaldo Carvalho de Melo { 495682b335aSArnaldo Carvalho de Melo struct symbol *sym; 496682b335aSArnaldo Carvalho de Melo struct process_kallsyms_args *a = arg; 497682b335aSArnaldo Carvalho de Melo struct rb_root *root = &a->dso->symbols[a->map->type]; 498682b335aSArnaldo Carvalho de Melo 499682b335aSArnaldo Carvalho de Melo if (!symbol_type__is_a(type, a->map->type)) 500682b335aSArnaldo Carvalho de Melo return 0; 501682b335aSArnaldo Carvalho de Melo 50282151520SCody P Schafer /* 50382151520SCody P Schafer * module symbols are not sorted so we add all 50482151520SCody P Schafer * symbols, setting length to 0, and rely on 50582151520SCody P Schafer * symbols__fixup_end() to fix it up. 50682151520SCody P Schafer */ 50782151520SCody P Schafer sym = symbol__new(start, 0, kallsyms2elf_type(type), name); 5082e538c4aSArnaldo Carvalho de Melo if (sym == NULL) 509682b335aSArnaldo Carvalho de Melo return -ENOMEM; 51082164161SArnaldo Carvalho de Melo /* 51182164161SArnaldo Carvalho de Melo * We will pass the symbols to the filter later, in 5124e06255fSArnaldo Carvalho de Melo * map__split_kallsyms, when we have split the maps per module 51382164161SArnaldo Carvalho de Melo */ 5144e06255fSArnaldo Carvalho de Melo symbols__insert(root, sym); 515a1645ce1SZhang, Yanmin 516682b335aSArnaldo Carvalho de Melo return 0; 5172e538c4aSArnaldo Carvalho de Melo } 5182e538c4aSArnaldo Carvalho de Melo 519682b335aSArnaldo Carvalho de Melo /* 520682b335aSArnaldo Carvalho de Melo * Loads the function entries in /proc/kallsyms into kernel_map->dso, 521682b335aSArnaldo Carvalho de Melo * so that we can in the next step set the symbol ->end address and then 522682b335aSArnaldo Carvalho de Melo * call kernel_maps__split_kallsyms. 523682b335aSArnaldo Carvalho de Melo */ 524aeafcbafSArnaldo Carvalho de Melo static int dso__load_all_kallsyms(struct dso *dso, const char *filename, 5259e201442SArnaldo Carvalho de Melo struct map *map) 526682b335aSArnaldo Carvalho de Melo { 527aeafcbafSArnaldo Carvalho de Melo struct process_kallsyms_args args = { .map = map, .dso = dso, }; 5289e201442SArnaldo Carvalho de Melo return kallsyms__parse(filename, &args, map__process_kallsym_symbol); 5292e538c4aSArnaldo Carvalho de Melo } 5302e538c4aSArnaldo Carvalho de Melo 5312e538c4aSArnaldo Carvalho de Melo /* 5322e538c4aSArnaldo Carvalho de Melo * Split the symbols into maps, making sure there are no overlaps, i.e. the 5332e538c4aSArnaldo Carvalho de Melo * kernel range is broken in several maps, named [kernel].N, as we don't have 5342e538c4aSArnaldo Carvalho de Melo * the original ELF section names vmlinux have. 5352e538c4aSArnaldo Carvalho de Melo */ 536aeafcbafSArnaldo Carvalho de Melo static int dso__split_kallsyms(struct dso *dso, struct map *map, 5379de89fe7SArnaldo Carvalho de Melo symbol_filter_t filter) 5382e538c4aSArnaldo Carvalho de Melo { 5399de89fe7SArnaldo Carvalho de Melo struct map_groups *kmaps = map__kmap(map)->kmaps; 54023346f21SArnaldo Carvalho de Melo struct machine *machine = kmaps->machine; 5414e06255fSArnaldo Carvalho de Melo struct map *curr_map = map; 5422e538c4aSArnaldo Carvalho de Melo struct symbol *pos; 5438a953312SArnaldo Carvalho de Melo int count = 0, moved = 0; 544aeafcbafSArnaldo Carvalho de Melo struct rb_root *root = &dso->symbols[map->type]; 5454e06255fSArnaldo Carvalho de Melo struct rb_node *next = rb_first(root); 5462e538c4aSArnaldo Carvalho de Melo int kernel_range = 0; 5472e538c4aSArnaldo Carvalho de Melo 5482e538c4aSArnaldo Carvalho de Melo while (next) { 5492e538c4aSArnaldo Carvalho de Melo char *module; 5502e538c4aSArnaldo Carvalho de Melo 5512e538c4aSArnaldo Carvalho de Melo pos = rb_entry(next, struct symbol, rb_node); 5522e538c4aSArnaldo Carvalho de Melo next = rb_next(&pos->rb_node); 5532e538c4aSArnaldo Carvalho de Melo 5542e538c4aSArnaldo Carvalho de Melo module = strchr(pos->name, '\t'); 5552e538c4aSArnaldo Carvalho de Melo if (module) { 55675be6cf4SArnaldo Carvalho de Melo if (!symbol_conf.use_modules) 5571de8e245SArnaldo Carvalho de Melo goto discard_symbol; 5581de8e245SArnaldo Carvalho de Melo 5592e538c4aSArnaldo Carvalho de Melo *module++ = '\0'; 5602e538c4aSArnaldo Carvalho de Melo 561b7cece76SArnaldo Carvalho de Melo if (strcmp(curr_map->dso->short_name, module)) { 562a1645ce1SZhang, Yanmin if (curr_map != map && 563aeafcbafSArnaldo Carvalho de Melo dso->kernel == DSO_TYPE_GUEST_KERNEL && 56423346f21SArnaldo Carvalho de Melo machine__is_default_guest(machine)) { 565a1645ce1SZhang, Yanmin /* 566a1645ce1SZhang, Yanmin * We assume all symbols of a module are 567a1645ce1SZhang, Yanmin * continuous in * kallsyms, so curr_map 568a1645ce1SZhang, Yanmin * points to a module and all its 569a1645ce1SZhang, Yanmin * symbols are in its kmap. Mark it as 570a1645ce1SZhang, Yanmin * loaded. 571a1645ce1SZhang, Yanmin */ 572a1645ce1SZhang, Yanmin dso__set_loaded(curr_map->dso, 573a1645ce1SZhang, Yanmin curr_map->type); 574af427bf5SArnaldo Carvalho de Melo } 575b7cece76SArnaldo Carvalho de Melo 576a1645ce1SZhang, Yanmin curr_map = map_groups__find_by_name(kmaps, 577a1645ce1SZhang, Yanmin map->type, module); 578a1645ce1SZhang, Yanmin if (curr_map == NULL) { 5792f51903bSArnaldo Carvalho de Melo pr_debug("%s/proc/{kallsyms,modules} " 580a1645ce1SZhang, Yanmin "inconsistency while looking " 581a1645ce1SZhang, Yanmin "for \"%s\" module!\n", 58223346f21SArnaldo Carvalho de Melo machine->root_dir, module); 583a1645ce1SZhang, Yanmin curr_map = map; 584a1645ce1SZhang, Yanmin goto discard_symbol; 585a1645ce1SZhang, Yanmin } 586a1645ce1SZhang, Yanmin 587a1645ce1SZhang, Yanmin if (curr_map->dso->loaded && 58823346f21SArnaldo Carvalho de Melo !machine__is_default_guest(machine)) 589b7cece76SArnaldo Carvalho de Melo goto discard_symbol; 590af427bf5SArnaldo Carvalho de Melo } 59186470930SIngo Molnar /* 5922e538c4aSArnaldo Carvalho de Melo * So that we look just like we get from .ko files, 5932e538c4aSArnaldo Carvalho de Melo * i.e. not prelinked, relative to map->start. 59486470930SIngo Molnar */ 5954e06255fSArnaldo Carvalho de Melo pos->start = curr_map->map_ip(curr_map, pos->start); 5964e06255fSArnaldo Carvalho de Melo pos->end = curr_map->map_ip(curr_map, pos->end); 5974e06255fSArnaldo Carvalho de Melo } else if (curr_map != map) { 5982e538c4aSArnaldo Carvalho de Melo char dso_name[PATH_MAX]; 599aeafcbafSArnaldo Carvalho de Melo struct dso *ndso; 60086470930SIngo Molnar 6018a953312SArnaldo Carvalho de Melo if (count == 0) { 6028a953312SArnaldo Carvalho de Melo curr_map = map; 6038a953312SArnaldo Carvalho de Melo goto filter_symbol; 6048a953312SArnaldo Carvalho de Melo } 6058a953312SArnaldo Carvalho de Melo 606aeafcbafSArnaldo Carvalho de Melo if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 607a1645ce1SZhang, Yanmin snprintf(dso_name, sizeof(dso_name), 608a1645ce1SZhang, Yanmin "[guest.kernel].%d", 609a1645ce1SZhang, Yanmin kernel_range++); 610a1645ce1SZhang, Yanmin else 611a1645ce1SZhang, Yanmin snprintf(dso_name, sizeof(dso_name), 612a1645ce1SZhang, Yanmin "[kernel].%d", 6132e538c4aSArnaldo Carvalho de Melo kernel_range++); 61486470930SIngo Molnar 615aeafcbafSArnaldo Carvalho de Melo ndso = dso__new(dso_name); 616aeafcbafSArnaldo Carvalho de Melo if (ndso == NULL) 6172e538c4aSArnaldo Carvalho de Melo return -1; 6182e538c4aSArnaldo Carvalho de Melo 619aeafcbafSArnaldo Carvalho de Melo ndso->kernel = dso->kernel; 620a1645ce1SZhang, Yanmin 621aeafcbafSArnaldo Carvalho de Melo curr_map = map__new2(pos->start, ndso, map->type); 62237fe5fcbSZhang, Yanmin if (curr_map == NULL) { 623aeafcbafSArnaldo Carvalho de Melo dso__delete(ndso); 6242e538c4aSArnaldo Carvalho de Melo return -1; 6252e538c4aSArnaldo Carvalho de Melo } 6262e538c4aSArnaldo Carvalho de Melo 6274e06255fSArnaldo Carvalho de Melo curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; 6289de89fe7SArnaldo Carvalho de Melo map_groups__insert(kmaps, curr_map); 6292e538c4aSArnaldo Carvalho de Melo ++kernel_range; 6302e538c4aSArnaldo Carvalho de Melo } 6318a953312SArnaldo Carvalho de Melo filter_symbol: 6324e06255fSArnaldo Carvalho de Melo if (filter && filter(curr_map, pos)) { 6331de8e245SArnaldo Carvalho de Melo discard_symbol: rb_erase(&pos->rb_node, root); 63400a192b3SArnaldo Carvalho de Melo symbol__delete(pos); 6352e538c4aSArnaldo Carvalho de Melo } else { 6364e06255fSArnaldo Carvalho de Melo if (curr_map != map) { 6374e06255fSArnaldo Carvalho de Melo rb_erase(&pos->rb_node, root); 6384e06255fSArnaldo Carvalho de Melo symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); 6398a953312SArnaldo Carvalho de Melo ++moved; 6408a953312SArnaldo Carvalho de Melo } else 6418a953312SArnaldo Carvalho de Melo ++count; 6429974f496SMike Galbraith } 64386470930SIngo Molnar } 64486470930SIngo Molnar 645a1645ce1SZhang, Yanmin if (curr_map != map && 646aeafcbafSArnaldo Carvalho de Melo dso->kernel == DSO_TYPE_GUEST_KERNEL && 64723346f21SArnaldo Carvalho de Melo machine__is_default_guest(kmaps->machine)) { 648a1645ce1SZhang, Yanmin dso__set_loaded(curr_map->dso, curr_map->type); 649a1645ce1SZhang, Yanmin } 650a1645ce1SZhang, Yanmin 6518a953312SArnaldo Carvalho de Melo return count + moved; 65286470930SIngo Molnar } 65386470930SIngo Molnar 654ec80fde7SArnaldo Carvalho de Melo static bool symbol__restricted_filename(const char *filename, 655ec80fde7SArnaldo Carvalho de Melo const char *restricted_filename) 656ec80fde7SArnaldo Carvalho de Melo { 657ec80fde7SArnaldo Carvalho de Melo bool restricted = false; 658ec80fde7SArnaldo Carvalho de Melo 659ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) { 660ec80fde7SArnaldo Carvalho de Melo char *r = realpath(filename, NULL); 661ec80fde7SArnaldo Carvalho de Melo 662ec80fde7SArnaldo Carvalho de Melo if (r != NULL) { 663ec80fde7SArnaldo Carvalho de Melo restricted = strcmp(r, restricted_filename) == 0; 664ec80fde7SArnaldo Carvalho de Melo free(r); 665ec80fde7SArnaldo Carvalho de Melo return restricted; 666ec80fde7SArnaldo Carvalho de Melo } 667ec80fde7SArnaldo Carvalho de Melo } 668ec80fde7SArnaldo Carvalho de Melo 669ec80fde7SArnaldo Carvalho de Melo return restricted; 670ec80fde7SArnaldo Carvalho de Melo } 671ec80fde7SArnaldo Carvalho de Melo 672aeafcbafSArnaldo Carvalho de Melo int dso__load_kallsyms(struct dso *dso, const char *filename, 6739de89fe7SArnaldo Carvalho de Melo struct map *map, symbol_filter_t filter) 6742e538c4aSArnaldo Carvalho de Melo { 675ec80fde7SArnaldo Carvalho de Melo if (symbol__restricted_filename(filename, "/proc/kallsyms")) 676ec80fde7SArnaldo Carvalho de Melo return -1; 677ec80fde7SArnaldo Carvalho de Melo 678aeafcbafSArnaldo Carvalho de Melo if (dso__load_all_kallsyms(dso, filename, map) < 0) 6792e538c4aSArnaldo Carvalho de Melo return -1; 6802e538c4aSArnaldo Carvalho de Melo 681694bf407SAnton Blanchard symbols__fixup_duplicate(&dso->symbols[map->type]); 6823f5a4272SAnton Blanchard symbols__fixup_end(&dso->symbols[map->type]); 6833f5a4272SAnton Blanchard 684aeafcbafSArnaldo Carvalho de Melo if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 68544f24cb3SJiri Olsa dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; 686a1645ce1SZhang, Yanmin else 68744f24cb3SJiri Olsa dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; 6882e538c4aSArnaldo Carvalho de Melo 689aeafcbafSArnaldo Carvalho de Melo return dso__split_kallsyms(dso, map, filter); 690af427bf5SArnaldo Carvalho de Melo } 691af427bf5SArnaldo Carvalho de Melo 692aeafcbafSArnaldo Carvalho de Melo static int dso__load_perf_map(struct dso *dso, struct map *map, 6936beba7adSArnaldo Carvalho de Melo symbol_filter_t filter) 69480d496beSPekka Enberg { 69580d496beSPekka Enberg char *line = NULL; 69680d496beSPekka Enberg size_t n; 69780d496beSPekka Enberg FILE *file; 69880d496beSPekka Enberg int nr_syms = 0; 69980d496beSPekka Enberg 700aeafcbafSArnaldo Carvalho de Melo file = fopen(dso->long_name, "r"); 70180d496beSPekka Enberg if (file == NULL) 70280d496beSPekka Enberg goto out_failure; 70380d496beSPekka Enberg 70480d496beSPekka Enberg while (!feof(file)) { 7059cffa8d5SPaul Mackerras u64 start, size; 70680d496beSPekka Enberg struct symbol *sym; 70780d496beSPekka Enberg int line_len, len; 70880d496beSPekka Enberg 70980d496beSPekka Enberg line_len = getline(&line, &n, file); 71080d496beSPekka Enberg if (line_len < 0) 71180d496beSPekka Enberg break; 71280d496beSPekka Enberg 71380d496beSPekka Enberg if (!line) 71480d496beSPekka Enberg goto out_failure; 71580d496beSPekka Enberg 71680d496beSPekka Enberg line[--line_len] = '\0'; /* \n */ 71780d496beSPekka Enberg 71880d496beSPekka Enberg len = hex2u64(line, &start); 71980d496beSPekka Enberg 72080d496beSPekka Enberg len++; 72180d496beSPekka Enberg if (len + 2 >= line_len) 72280d496beSPekka Enberg continue; 72380d496beSPekka Enberg 72480d496beSPekka Enberg len += hex2u64(line + len, &size); 72580d496beSPekka Enberg 72680d496beSPekka Enberg len++; 72780d496beSPekka Enberg if (len + 2 >= line_len) 72880d496beSPekka Enberg continue; 72980d496beSPekka Enberg 730c408fedfSArnaldo Carvalho de Melo sym = symbol__new(start, size, STB_GLOBAL, line + len); 73180d496beSPekka Enberg 73280d496beSPekka Enberg if (sym == NULL) 73380d496beSPekka Enberg goto out_delete_line; 73480d496beSPekka Enberg 735439d473bSArnaldo Carvalho de Melo if (filter && filter(map, sym)) 73600a192b3SArnaldo Carvalho de Melo symbol__delete(sym); 73780d496beSPekka Enberg else { 738aeafcbafSArnaldo Carvalho de Melo symbols__insert(&dso->symbols[map->type], sym); 73980d496beSPekka Enberg nr_syms++; 74080d496beSPekka Enberg } 74180d496beSPekka Enberg } 74280d496beSPekka Enberg 74380d496beSPekka Enberg free(line); 74480d496beSPekka Enberg fclose(file); 74580d496beSPekka Enberg 74680d496beSPekka Enberg return nr_syms; 74780d496beSPekka Enberg 74880d496beSPekka Enberg out_delete_line: 74980d496beSPekka Enberg free(line); 75080d496beSPekka Enberg out_failure: 75180d496beSPekka Enberg return -1; 75280d496beSPekka Enberg } 75380d496beSPekka Enberg 754aeafcbafSArnaldo Carvalho de Melo int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 75586470930SIngo Molnar { 756c338aee8SArnaldo Carvalho de Melo char *name; 75786470930SIngo Molnar int ret = -1; 75844f24cb3SJiri Olsa u_int i; 75923346f21SArnaldo Carvalho de Melo struct machine *machine; 76044f24cb3SJiri Olsa char *root_dir = (char *) ""; 7613aafe5aeSCody P Schafer int ss_pos = 0; 7623aafe5aeSCody P Schafer struct symsrc ss_[2]; 7633aafe5aeSCody P Schafer struct symsrc *syms_ss = NULL, *runtime_ss = NULL; 76486470930SIngo Molnar 765aeafcbafSArnaldo Carvalho de Melo dso__set_loaded(dso, map->type); 76666bd8424SArnaldo Carvalho de Melo 767aeafcbafSArnaldo Carvalho de Melo if (dso->kernel == DSO_TYPE_KERNEL) 768aeafcbafSArnaldo Carvalho de Melo return dso__load_kernel_sym(dso, map, filter); 769aeafcbafSArnaldo Carvalho de Melo else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 770aeafcbafSArnaldo Carvalho de Melo return dso__load_guest_kernel_sym(dso, map, filter); 771a1645ce1SZhang, Yanmin 77223346f21SArnaldo Carvalho de Melo if (map->groups && map->groups->machine) 77323346f21SArnaldo Carvalho de Melo machine = map->groups->machine; 774a1645ce1SZhang, Yanmin else 77523346f21SArnaldo Carvalho de Melo machine = NULL; 776c338aee8SArnaldo Carvalho de Melo 77744f24cb3SJiri Olsa name = malloc(PATH_MAX); 77886470930SIngo Molnar if (!name) 77986470930SIngo Molnar return -1; 78086470930SIngo Molnar 781aeafcbafSArnaldo Carvalho de Melo dso->adjust_symbols = 0; 782f5812a7aSArnaldo Carvalho de Melo 783aeafcbafSArnaldo Carvalho de Melo if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { 784981c1252SPekka Enberg struct stat st; 785981c1252SPekka Enberg 786e9b52ef2SVasiliy Kulikov if (lstat(dso->name, &st) < 0) 787981c1252SPekka Enberg return -1; 788981c1252SPekka Enberg 789981c1252SPekka Enberg if (st.st_uid && (st.st_uid != geteuid())) { 790981c1252SPekka Enberg pr_warning("File %s not owned by current user or root, " 791981c1252SPekka Enberg "ignoring it.\n", dso->name); 792981c1252SPekka Enberg return -1; 793981c1252SPekka Enberg } 794981c1252SPekka Enberg 795aeafcbafSArnaldo Carvalho de Melo ret = dso__load_perf_map(dso, map, filter); 79644f24cb3SJiri Olsa dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : 79744f24cb3SJiri Olsa DSO_BINARY_TYPE__NOT_FOUND; 79894cb9e38SArnaldo Carvalho de Melo return ret; 79994cb9e38SArnaldo Carvalho de Melo } 80094cb9e38SArnaldo Carvalho de Melo 80144f24cb3SJiri Olsa if (machine) 80244f24cb3SJiri Olsa root_dir = machine->root_dir; 80344f24cb3SJiri Olsa 8046da80ce8SDave Martin /* Iterate over candidate debug images. 8053aafe5aeSCody P Schafer * Keep track of "interesting" ones (those which have a symtab, dynsym, 8063aafe5aeSCody P Schafer * and/or opd section) for processing. 8076da80ce8SDave Martin */ 80844f24cb3SJiri Olsa for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) { 8093aafe5aeSCody P Schafer struct symsrc *ss = &ss_[ss_pos]; 8103aafe5aeSCody P Schafer bool next_slot = false; 81144f24cb3SJiri Olsa 812005f9294SCody P Schafer enum dso_binary_type symtab_type = binary_type_symtab[i]; 81344f24cb3SJiri Olsa 814005f9294SCody P Schafer if (dso__binary_type_file(dso, symtab_type, 81544f24cb3SJiri Olsa root_dir, name, PATH_MAX)) 8166da80ce8SDave Martin continue; 81786470930SIngo Molnar 8186da80ce8SDave Martin /* Name is now the name of the next image to try */ 8193aafe5aeSCody P Schafer if (symsrc__init(ss, dso, name, symtab_type) < 0) 8206da80ce8SDave Martin continue; 8216da80ce8SDave Martin 8223aafe5aeSCody P Schafer if (!syms_ss && symsrc__has_symtab(ss)) { 8233aafe5aeSCody P Schafer syms_ss = ss; 8243aafe5aeSCody P Schafer next_slot = true; 825d26cd12bSCody P Schafer } 826d26cd12bSCody P Schafer 8273aafe5aeSCody P Schafer if (!runtime_ss && symsrc__possibly_runtime(ss)) { 8283aafe5aeSCody P Schafer runtime_ss = ss; 8293aafe5aeSCody P Schafer next_slot = true; 830a44f605bSCody P Schafer } 83186470930SIngo Molnar 8323aafe5aeSCody P Schafer if (next_slot) { 8333aafe5aeSCody P Schafer ss_pos++; 83433ff581eSJiri Olsa 8353aafe5aeSCody P Schafer if (syms_ss && runtime_ss) 8366da80ce8SDave Martin break; 837a25e46c4SArnaldo Carvalho de Melo } 8383aafe5aeSCody P Schafer 8396da80ce8SDave Martin } 8406da80ce8SDave Martin 8413aafe5aeSCody P Schafer if (!runtime_ss && !syms_ss) 8423aafe5aeSCody P Schafer goto out_free; 8433aafe5aeSCody P Schafer 8443aafe5aeSCody P Schafer if (runtime_ss && !syms_ss) { 8453aafe5aeSCody P Schafer syms_ss = runtime_ss; 84660e4b10cSArnaldo Carvalho de Melo } 84760e4b10cSArnaldo Carvalho de Melo 8483aafe5aeSCody P Schafer /* We'll have to hope for the best */ 8493aafe5aeSCody P Schafer if (!runtime_ss && syms_ss) 8503aafe5aeSCody P Schafer runtime_ss = syms_ss; 8513aafe5aeSCody P Schafer 8523aafe5aeSCody P Schafer if (syms_ss) 8533aafe5aeSCody P Schafer ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, 0); 8543aafe5aeSCody P Schafer else 8553aafe5aeSCody P Schafer ret = -1; 8563aafe5aeSCody P Schafer 857f47b58b7SDavid Ahern if (ret > 0) { 8583aafe5aeSCody P Schafer int nr_plt; 8593aafe5aeSCody P Schafer 8603aafe5aeSCody P Schafer nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map, filter); 8613aafe5aeSCody P Schafer if (nr_plt > 0) 8623aafe5aeSCody P Schafer ret += nr_plt; 8633aafe5aeSCody P Schafer } 8643aafe5aeSCody P Schafer 8653aafe5aeSCody P Schafer for (; ss_pos > 0; ss_pos--) 8663aafe5aeSCody P Schafer symsrc__destroy(&ss_[ss_pos - 1]); 8673aafe5aeSCody P Schafer out_free: 86886470930SIngo Molnar free(name); 869aeafcbafSArnaldo Carvalho de Melo if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) 8701340e6bbSArnaldo Carvalho de Melo return 0; 87186470930SIngo Molnar return ret; 87286470930SIngo Molnar } 87386470930SIngo Molnar 874aeafcbafSArnaldo Carvalho de Melo struct map *map_groups__find_by_name(struct map_groups *mg, 87579406cd7SArnaldo Carvalho de Melo enum map_type type, const char *name) 876439d473bSArnaldo Carvalho de Melo { 877439d473bSArnaldo Carvalho de Melo struct rb_node *nd; 878439d473bSArnaldo Carvalho de Melo 879aeafcbafSArnaldo Carvalho de Melo for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { 880439d473bSArnaldo Carvalho de Melo struct map *map = rb_entry(nd, struct map, rb_node); 881439d473bSArnaldo Carvalho de Melo 882b7cece76SArnaldo Carvalho de Melo if (map->dso && strcmp(map->dso->short_name, name) == 0) 883439d473bSArnaldo Carvalho de Melo return map; 884439d473bSArnaldo Carvalho de Melo } 885439d473bSArnaldo Carvalho de Melo 886439d473bSArnaldo Carvalho de Melo return NULL; 887439d473bSArnaldo Carvalho de Melo } 888439d473bSArnaldo Carvalho de Melo 889aeafcbafSArnaldo Carvalho de Melo static int map_groups__set_modules_path_dir(struct map_groups *mg, 890a1645ce1SZhang, Yanmin const char *dir_name) 8916cfcc53eSMike Galbraith { 892439d473bSArnaldo Carvalho de Melo struct dirent *dent; 8935aab621bSArnaldo Carvalho de Melo DIR *dir = opendir(dir_name); 89474534341SGui Jianfeng int ret = 0; 8956cfcc53eSMike Galbraith 896439d473bSArnaldo Carvalho de Melo if (!dir) { 8975aab621bSArnaldo Carvalho de Melo pr_debug("%s: cannot open %s dir\n", __func__, dir_name); 898439d473bSArnaldo Carvalho de Melo return -1; 899439d473bSArnaldo Carvalho de Melo } 9006cfcc53eSMike Galbraith 901439d473bSArnaldo Carvalho de Melo while ((dent = readdir(dir)) != NULL) { 902439d473bSArnaldo Carvalho de Melo char path[PATH_MAX]; 903a1645ce1SZhang, Yanmin struct stat st; 904439d473bSArnaldo Carvalho de Melo 905a1645ce1SZhang, Yanmin /*sshfs might return bad dent->d_type, so we have to stat*/ 9062b600f95SNamhyung Kim snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name); 907a1645ce1SZhang, Yanmin if (stat(path, &st)) 908a1645ce1SZhang, Yanmin continue; 909a1645ce1SZhang, Yanmin 910a1645ce1SZhang, Yanmin if (S_ISDIR(st.st_mode)) { 911439d473bSArnaldo Carvalho de Melo if (!strcmp(dent->d_name, ".") || 912439d473bSArnaldo Carvalho de Melo !strcmp(dent->d_name, "..")) 913439d473bSArnaldo Carvalho de Melo continue; 914439d473bSArnaldo Carvalho de Melo 915aeafcbafSArnaldo Carvalho de Melo ret = map_groups__set_modules_path_dir(mg, path); 91674534341SGui Jianfeng if (ret < 0) 91774534341SGui Jianfeng goto out; 918439d473bSArnaldo Carvalho de Melo } else { 919439d473bSArnaldo Carvalho de Melo char *dot = strrchr(dent->d_name, '.'), 920439d473bSArnaldo Carvalho de Melo dso_name[PATH_MAX]; 921439d473bSArnaldo Carvalho de Melo struct map *map; 922cfc10d3bSArnaldo Carvalho de Melo char *long_name; 923439d473bSArnaldo Carvalho de Melo 924439d473bSArnaldo Carvalho de Melo if (dot == NULL || strcmp(dot, ".ko")) 925439d473bSArnaldo Carvalho de Melo continue; 926439d473bSArnaldo Carvalho de Melo snprintf(dso_name, sizeof(dso_name), "[%.*s]", 927439d473bSArnaldo Carvalho de Melo (int)(dot - dent->d_name), dent->d_name); 928439d473bSArnaldo Carvalho de Melo 929a2a99e8eSArnaldo Carvalho de Melo strxfrchar(dso_name, '-', '_'); 930aeafcbafSArnaldo Carvalho de Melo map = map_groups__find_by_name(mg, MAP__FUNCTION, 931aeafcbafSArnaldo Carvalho de Melo dso_name); 932439d473bSArnaldo Carvalho de Melo if (map == NULL) 933439d473bSArnaldo Carvalho de Melo continue; 934439d473bSArnaldo Carvalho de Melo 935cfc10d3bSArnaldo Carvalho de Melo long_name = strdup(path); 93674534341SGui Jianfeng if (long_name == NULL) { 93774534341SGui Jianfeng ret = -1; 93874534341SGui Jianfeng goto out; 93974534341SGui Jianfeng } 940cfc10d3bSArnaldo Carvalho de Melo dso__set_long_name(map->dso, long_name); 9416e406257SArnaldo Carvalho de Melo map->dso->lname_alloc = 1; 942a1645ce1SZhang, Yanmin dso__kernel_module_get_build_id(map->dso, ""); 943439d473bSArnaldo Carvalho de Melo } 944439d473bSArnaldo Carvalho de Melo } 945439d473bSArnaldo Carvalho de Melo 94674534341SGui Jianfeng out: 947439d473bSArnaldo Carvalho de Melo closedir(dir); 94874534341SGui Jianfeng return ret; 949439d473bSArnaldo Carvalho de Melo } 950439d473bSArnaldo Carvalho de Melo 951a1645ce1SZhang, Yanmin static char *get_kernel_version(const char *root_dir) 952439d473bSArnaldo Carvalho de Melo { 953a1645ce1SZhang, Yanmin char version[PATH_MAX]; 954a1645ce1SZhang, Yanmin FILE *file; 955a1645ce1SZhang, Yanmin char *name, *tmp; 956a1645ce1SZhang, Yanmin const char *prefix = "Linux version "; 957a1645ce1SZhang, Yanmin 958a1645ce1SZhang, Yanmin sprintf(version, "%s/proc/version", root_dir); 959a1645ce1SZhang, Yanmin file = fopen(version, "r"); 960a1645ce1SZhang, Yanmin if (!file) 961a1645ce1SZhang, Yanmin return NULL; 962a1645ce1SZhang, Yanmin 963a1645ce1SZhang, Yanmin version[0] = '\0'; 964a1645ce1SZhang, Yanmin tmp = fgets(version, sizeof(version), file); 965a1645ce1SZhang, Yanmin fclose(file); 966a1645ce1SZhang, Yanmin 967a1645ce1SZhang, Yanmin name = strstr(version, prefix); 968a1645ce1SZhang, Yanmin if (!name) 969a1645ce1SZhang, Yanmin return NULL; 970a1645ce1SZhang, Yanmin name += strlen(prefix); 971a1645ce1SZhang, Yanmin tmp = strchr(name, ' '); 972a1645ce1SZhang, Yanmin if (tmp) 973a1645ce1SZhang, Yanmin *tmp = '\0'; 974a1645ce1SZhang, Yanmin 975a1645ce1SZhang, Yanmin return strdup(name); 976a1645ce1SZhang, Yanmin } 977a1645ce1SZhang, Yanmin 978aeafcbafSArnaldo Carvalho de Melo static int machine__set_modules_path(struct machine *machine) 979a1645ce1SZhang, Yanmin { 980a1645ce1SZhang, Yanmin char *version; 981439d473bSArnaldo Carvalho de Melo char modules_path[PATH_MAX]; 982439d473bSArnaldo Carvalho de Melo 983aeafcbafSArnaldo Carvalho de Melo version = get_kernel_version(machine->root_dir); 984a1645ce1SZhang, Yanmin if (!version) 985439d473bSArnaldo Carvalho de Melo return -1; 986439d473bSArnaldo Carvalho de Melo 987a1645ce1SZhang, Yanmin snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", 988aeafcbafSArnaldo Carvalho de Melo machine->root_dir, version); 989a1645ce1SZhang, Yanmin free(version); 990439d473bSArnaldo Carvalho de Melo 991aeafcbafSArnaldo Carvalho de Melo return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 992439d473bSArnaldo Carvalho de Melo } 9936cfcc53eSMike Galbraith 994aeafcbafSArnaldo Carvalho de Melo struct map *machine__new_module(struct machine *machine, u64 start, 995d28c6223SArnaldo Carvalho de Melo const char *filename) 996b7cece76SArnaldo Carvalho de Melo { 997b7cece76SArnaldo Carvalho de Melo struct map *map; 998aeafcbafSArnaldo Carvalho de Melo struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 999b7cece76SArnaldo Carvalho de Melo 1000b7cece76SArnaldo Carvalho de Melo if (dso == NULL) 1001b7cece76SArnaldo Carvalho de Melo return NULL; 1002b7cece76SArnaldo Carvalho de Melo 1003b7cece76SArnaldo Carvalho de Melo map = map__new2(start, dso, MAP__FUNCTION); 1004b7cece76SArnaldo Carvalho de Melo if (map == NULL) 1005b7cece76SArnaldo Carvalho de Melo return NULL; 1006b7cece76SArnaldo Carvalho de Melo 1007aeafcbafSArnaldo Carvalho de Melo if (machine__is_host(machine)) 100844f24cb3SJiri Olsa dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 1009a1645ce1SZhang, Yanmin else 101044f24cb3SJiri Olsa dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; 1011aeafcbafSArnaldo Carvalho de Melo map_groups__insert(&machine->kmaps, map); 1012b7cece76SArnaldo Carvalho de Melo return map; 1013b7cece76SArnaldo Carvalho de Melo } 1014b7cece76SArnaldo Carvalho de Melo 1015aeafcbafSArnaldo Carvalho de Melo static int machine__create_modules(struct machine *machine) 1016439d473bSArnaldo Carvalho de Melo { 1017439d473bSArnaldo Carvalho de Melo char *line = NULL; 1018439d473bSArnaldo Carvalho de Melo size_t n; 1019a1645ce1SZhang, Yanmin FILE *file; 1020439d473bSArnaldo Carvalho de Melo struct map *map; 1021a1645ce1SZhang, Yanmin const char *modules; 1022a1645ce1SZhang, Yanmin char path[PATH_MAX]; 1023439d473bSArnaldo Carvalho de Melo 1024aeafcbafSArnaldo Carvalho de Melo if (machine__is_default_guest(machine)) 1025a1645ce1SZhang, Yanmin modules = symbol_conf.default_guest_modules; 1026a1645ce1SZhang, Yanmin else { 1027aeafcbafSArnaldo Carvalho de Melo sprintf(path, "%s/proc/modules", machine->root_dir); 1028a1645ce1SZhang, Yanmin modules = path; 1029a1645ce1SZhang, Yanmin } 1030a1645ce1SZhang, Yanmin 1031ec80fde7SArnaldo Carvalho de Melo if (symbol__restricted_filename(path, "/proc/modules")) 1032ec80fde7SArnaldo Carvalho de Melo return -1; 1033ec80fde7SArnaldo Carvalho de Melo 1034a1645ce1SZhang, Yanmin file = fopen(modules, "r"); 1035439d473bSArnaldo Carvalho de Melo if (file == NULL) 1036439d473bSArnaldo Carvalho de Melo return -1; 1037439d473bSArnaldo Carvalho de Melo 1038439d473bSArnaldo Carvalho de Melo while (!feof(file)) { 1039439d473bSArnaldo Carvalho de Melo char name[PATH_MAX]; 1040439d473bSArnaldo Carvalho de Melo u64 start; 1041439d473bSArnaldo Carvalho de Melo char *sep; 1042439d473bSArnaldo Carvalho de Melo int line_len; 1043439d473bSArnaldo Carvalho de Melo 1044439d473bSArnaldo Carvalho de Melo line_len = getline(&line, &n, file); 1045439d473bSArnaldo Carvalho de Melo if (line_len < 0) 10466cfcc53eSMike Galbraith break; 10476cfcc53eSMike Galbraith 1048439d473bSArnaldo Carvalho de Melo if (!line) 1049439d473bSArnaldo Carvalho de Melo goto out_failure; 1050439d473bSArnaldo Carvalho de Melo 1051439d473bSArnaldo Carvalho de Melo line[--line_len] = '\0'; /* \n */ 1052439d473bSArnaldo Carvalho de Melo 1053439d473bSArnaldo Carvalho de Melo sep = strrchr(line, 'x'); 1054439d473bSArnaldo Carvalho de Melo if (sep == NULL) 1055439d473bSArnaldo Carvalho de Melo continue; 1056439d473bSArnaldo Carvalho de Melo 1057439d473bSArnaldo Carvalho de Melo hex2u64(sep + 1, &start); 1058439d473bSArnaldo Carvalho de Melo 1059439d473bSArnaldo Carvalho de Melo sep = strchr(line, ' '); 1060439d473bSArnaldo Carvalho de Melo if (sep == NULL) 1061439d473bSArnaldo Carvalho de Melo continue; 1062439d473bSArnaldo Carvalho de Melo 1063439d473bSArnaldo Carvalho de Melo *sep = '\0'; 1064439d473bSArnaldo Carvalho de Melo 1065439d473bSArnaldo Carvalho de Melo snprintf(name, sizeof(name), "[%s]", line); 1066aeafcbafSArnaldo Carvalho de Melo map = machine__new_module(machine, start, name); 1067b7cece76SArnaldo Carvalho de Melo if (map == NULL) 1068439d473bSArnaldo Carvalho de Melo goto out_delete_line; 1069aeafcbafSArnaldo Carvalho de Melo dso__kernel_module_get_build_id(map->dso, machine->root_dir); 10706cfcc53eSMike Galbraith } 10716cfcc53eSMike Galbraith 1072439d473bSArnaldo Carvalho de Melo free(line); 1073439d473bSArnaldo Carvalho de Melo fclose(file); 1074439d473bSArnaldo Carvalho de Melo 1075aeafcbafSArnaldo Carvalho de Melo return machine__set_modules_path(machine); 1076439d473bSArnaldo Carvalho de Melo 1077439d473bSArnaldo Carvalho de Melo out_delete_line: 1078439d473bSArnaldo Carvalho de Melo free(line); 1079439d473bSArnaldo Carvalho de Melo out_failure: 1080439d473bSArnaldo Carvalho de Melo return -1; 10816cfcc53eSMike Galbraith } 10826cfcc53eSMike Galbraith 1083aeafcbafSArnaldo Carvalho de Melo int dso__load_vmlinux(struct dso *dso, struct map *map, 10846beba7adSArnaldo Carvalho de Melo const char *vmlinux, symbol_filter_t filter) 108586470930SIngo Molnar { 1086b68e2f91SCody P Schafer int err = -1; 1087b68e2f91SCody P Schafer struct symsrc ss; 1088ec5761eaSDavid Ahern char symfs_vmlinux[PATH_MAX]; 1089005f9294SCody P Schafer enum dso_binary_type symtab_type; 109086470930SIngo Molnar 1091a639dc64SArnaldo Carvalho de Melo snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1092ec5761eaSDavid Ahern symbol_conf.symfs, vmlinux); 109386470930SIngo Molnar 109421ea4539SCody P Schafer if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1095005f9294SCody P Schafer symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 109621ea4539SCody P Schafer else 1097005f9294SCody P Schafer symtab_type = DSO_BINARY_TYPE__VMLINUX; 109821ea4539SCody P Schafer 1099005f9294SCody P Schafer if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) 1100b68e2f91SCody P Schafer return -1; 1101b68e2f91SCody P Schafer 1102261360b6SCody P Schafer err = dso__load_sym(dso, map, &ss, &ss, filter, 0); 1103b68e2f91SCody P Schafer symsrc__destroy(&ss); 110486470930SIngo Molnar 1105515850e4SCody P Schafer if (err > 0) { 1106515850e4SCody P Schafer dso__set_long_name(dso, (char *)vmlinux); 1107515850e4SCody P Schafer dso__set_loaded(dso, map->type); 1108ec5761eaSDavid Ahern pr_debug("Using %s for symbols\n", symfs_vmlinux); 1109515850e4SCody P Schafer } 11103846df2eSArnaldo Carvalho de Melo 111186470930SIngo Molnar return err; 111286470930SIngo Molnar } 111386470930SIngo Molnar 1114aeafcbafSArnaldo Carvalho de Melo int dso__load_vmlinux_path(struct dso *dso, struct map *map, 11159de89fe7SArnaldo Carvalho de Melo symbol_filter_t filter) 1116a19afe46SArnaldo Carvalho de Melo { 1117a19afe46SArnaldo Carvalho de Melo int i, err = 0; 11185ad90e4eSArnaldo Carvalho de Melo char *filename; 1119a19afe46SArnaldo Carvalho de Melo 1120a19afe46SArnaldo Carvalho de Melo pr_debug("Looking at the vmlinux_path (%d entries long)\n", 11215ad90e4eSArnaldo Carvalho de Melo vmlinux_path__nr_entries + 1); 11225ad90e4eSArnaldo Carvalho de Melo 1123aeafcbafSArnaldo Carvalho de Melo filename = dso__build_id_filename(dso, NULL, 0); 11245ad90e4eSArnaldo Carvalho de Melo if (filename != NULL) { 1125aeafcbafSArnaldo Carvalho de Melo err = dso__load_vmlinux(dso, map, filename, filter); 1126261ee821SCody P Schafer if (err > 0) 11275ad90e4eSArnaldo Carvalho de Melo goto out; 11285ad90e4eSArnaldo Carvalho de Melo free(filename); 11295ad90e4eSArnaldo Carvalho de Melo } 1130a19afe46SArnaldo Carvalho de Melo 1131a19afe46SArnaldo Carvalho de Melo for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1132aeafcbafSArnaldo Carvalho de Melo err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); 1133a19afe46SArnaldo Carvalho de Melo if (err > 0) { 1134aeafcbafSArnaldo Carvalho de Melo dso__set_long_name(dso, strdup(vmlinux_path[i])); 1135a19afe46SArnaldo Carvalho de Melo break; 1136a19afe46SArnaldo Carvalho de Melo } 1137a19afe46SArnaldo Carvalho de Melo } 11385ad90e4eSArnaldo Carvalho de Melo out: 1139a19afe46SArnaldo Carvalho de Melo return err; 1140a19afe46SArnaldo Carvalho de Melo } 1141a19afe46SArnaldo Carvalho de Melo 1142aeafcbafSArnaldo Carvalho de Melo static int dso__load_kernel_sym(struct dso *dso, struct map *map, 11439de89fe7SArnaldo Carvalho de Melo symbol_filter_t filter) 114486470930SIngo Molnar { 1145cc612d81SArnaldo Carvalho de Melo int err; 11469e201442SArnaldo Carvalho de Melo const char *kallsyms_filename = NULL; 11479e201442SArnaldo Carvalho de Melo char *kallsyms_allocated_filename = NULL; 1148dc8d6ab2SArnaldo Carvalho de Melo /* 1149b226a5a7SDavid Ahern * Step 1: if the user specified a kallsyms or vmlinux filename, use 1150b226a5a7SDavid Ahern * it and only it, reporting errors to the user if it cannot be used. 1151dc8d6ab2SArnaldo Carvalho de Melo * 1152dc8d6ab2SArnaldo Carvalho de Melo * For instance, try to analyse an ARM perf.data file _without_ a 1153dc8d6ab2SArnaldo Carvalho de Melo * build-id, or if the user specifies the wrong path to the right 1154dc8d6ab2SArnaldo Carvalho de Melo * vmlinux file, obviously we can't fallback to another vmlinux (a 1155dc8d6ab2SArnaldo Carvalho de Melo * x86_86 one, on the machine where analysis is being performed, say), 1156dc8d6ab2SArnaldo Carvalho de Melo * or worse, /proc/kallsyms. 1157dc8d6ab2SArnaldo Carvalho de Melo * 1158dc8d6ab2SArnaldo Carvalho de Melo * If the specified file _has_ a build-id and there is a build-id 1159dc8d6ab2SArnaldo Carvalho de Melo * section in the perf.data file, we will still do the expected 1160dc8d6ab2SArnaldo Carvalho de Melo * validation in dso__load_vmlinux and will bail out if they don't 1161dc8d6ab2SArnaldo Carvalho de Melo * match. 1162dc8d6ab2SArnaldo Carvalho de Melo */ 1163b226a5a7SDavid Ahern if (symbol_conf.kallsyms_name != NULL) { 1164b226a5a7SDavid Ahern kallsyms_filename = symbol_conf.kallsyms_name; 1165b226a5a7SDavid Ahern goto do_kallsyms; 1166b226a5a7SDavid Ahern } 1167b226a5a7SDavid Ahern 1168dc8d6ab2SArnaldo Carvalho de Melo if (symbol_conf.vmlinux_name != NULL) { 1169aeafcbafSArnaldo Carvalho de Melo err = dso__load_vmlinux(dso, map, 1170dc8d6ab2SArnaldo Carvalho de Melo symbol_conf.vmlinux_name, filter); 1171e7dadc00SArnaldo Carvalho de Melo if (err > 0) { 1172aeafcbafSArnaldo Carvalho de Melo dso__set_long_name(dso, 1173e7dadc00SArnaldo Carvalho de Melo strdup(symbol_conf.vmlinux_name)); 1174e7dadc00SArnaldo Carvalho de Melo goto out_fixup; 1175e7dadc00SArnaldo Carvalho de Melo } 1176e7dadc00SArnaldo Carvalho de Melo return err; 1177dc8d6ab2SArnaldo Carvalho de Melo } 1178439d473bSArnaldo Carvalho de Melo 1179cc612d81SArnaldo Carvalho de Melo if (vmlinux_path != NULL) { 1180aeafcbafSArnaldo Carvalho de Melo err = dso__load_vmlinux_path(dso, map, filter); 1181a19afe46SArnaldo Carvalho de Melo if (err > 0) 1182cc612d81SArnaldo Carvalho de Melo goto out_fixup; 1183cc612d81SArnaldo Carvalho de Melo } 1184cc612d81SArnaldo Carvalho de Melo 1185ec5761eaSDavid Ahern /* do not try local files if a symfs was given */ 1186ec5761eaSDavid Ahern if (symbol_conf.symfs[0] != 0) 1187ec5761eaSDavid Ahern return -1; 1188ec5761eaSDavid Ahern 1189b7cece76SArnaldo Carvalho de Melo /* 1190b7cece76SArnaldo Carvalho de Melo * Say the kernel DSO was created when processing the build-id header table, 1191b7cece76SArnaldo Carvalho de Melo * we have a build-id, so check if it is the same as the running kernel, 1192b7cece76SArnaldo Carvalho de Melo * using it if it is. 1193b7cece76SArnaldo Carvalho de Melo */ 1194aeafcbafSArnaldo Carvalho de Melo if (dso->has_build_id) { 1195b7cece76SArnaldo Carvalho de Melo u8 kallsyms_build_id[BUILD_ID_SIZE]; 11969e201442SArnaldo Carvalho de Melo char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1197b7cece76SArnaldo Carvalho de Melo 1198b7cece76SArnaldo Carvalho de Melo if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id, 11998d0591f6SArnaldo Carvalho de Melo sizeof(kallsyms_build_id)) == 0) { 1200aeafcbafSArnaldo Carvalho de Melo if (dso__build_id_equal(dso, kallsyms_build_id)) { 12019e201442SArnaldo Carvalho de Melo kallsyms_filename = "/proc/kallsyms"; 1202b7cece76SArnaldo Carvalho de Melo goto do_kallsyms; 12038d0591f6SArnaldo Carvalho de Melo } 12049e201442SArnaldo Carvalho de Melo } 1205dc8d6ab2SArnaldo Carvalho de Melo /* 1206dc8d6ab2SArnaldo Carvalho de Melo * Now look if we have it on the build-id cache in 1207dc8d6ab2SArnaldo Carvalho de Melo * $HOME/.debug/[kernel.kallsyms]. 1208dc8d6ab2SArnaldo Carvalho de Melo */ 1209aeafcbafSArnaldo Carvalho de Melo build_id__sprintf(dso->build_id, sizeof(dso->build_id), 12109e201442SArnaldo Carvalho de Melo sbuild_id); 12119e201442SArnaldo Carvalho de Melo 12129e201442SArnaldo Carvalho de Melo if (asprintf(&kallsyms_allocated_filename, 12139e201442SArnaldo Carvalho de Melo "%s/.debug/[kernel.kallsyms]/%s", 12143846df2eSArnaldo Carvalho de Melo getenv("HOME"), sbuild_id) == -1) { 12153846df2eSArnaldo Carvalho de Melo pr_err("Not enough memory for kallsyms file lookup\n"); 12168d0591f6SArnaldo Carvalho de Melo return -1; 12173846df2eSArnaldo Carvalho de Melo } 12188d0591f6SArnaldo Carvalho de Melo 121919fc2dedSArnaldo Carvalho de Melo kallsyms_filename = kallsyms_allocated_filename; 122019fc2dedSArnaldo Carvalho de Melo 1221dc8d6ab2SArnaldo Carvalho de Melo if (access(kallsyms_filename, F_OK)) { 12223846df2eSArnaldo Carvalho de Melo pr_err("No kallsyms or vmlinux with build-id %s " 12233846df2eSArnaldo Carvalho de Melo "was found\n", sbuild_id); 12249e201442SArnaldo Carvalho de Melo free(kallsyms_allocated_filename); 1225dc8d6ab2SArnaldo Carvalho de Melo return -1; 1226ef6ae724SArnaldo Carvalho de Melo } 1227dc8d6ab2SArnaldo Carvalho de Melo } else { 1228dc8d6ab2SArnaldo Carvalho de Melo /* 1229dc8d6ab2SArnaldo Carvalho de Melo * Last resort, if we don't have a build-id and couldn't find 1230dc8d6ab2SArnaldo Carvalho de Melo * any vmlinux file, try the running kernel kallsyms table. 1231dc8d6ab2SArnaldo Carvalho de Melo */ 1232dc8d6ab2SArnaldo Carvalho de Melo kallsyms_filename = "/proc/kallsyms"; 1233dc8d6ab2SArnaldo Carvalho de Melo } 1234dc8d6ab2SArnaldo Carvalho de Melo 1235dc8d6ab2SArnaldo Carvalho de Melo do_kallsyms: 1236aeafcbafSArnaldo Carvalho de Melo err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 12373846df2eSArnaldo Carvalho de Melo if (err > 0) 12383846df2eSArnaldo Carvalho de Melo pr_debug("Using %s for symbols\n", kallsyms_filename); 1239dc8d6ab2SArnaldo Carvalho de Melo free(kallsyms_allocated_filename); 1240dc8d6ab2SArnaldo Carvalho de Melo 1241439d473bSArnaldo Carvalho de Melo if (err > 0) { 1242aeafcbafSArnaldo Carvalho de Melo dso__set_long_name(dso, strdup("[kernel.kallsyms]")); 12430a0317b4SCody P Schafer out_fixup: 12446a4694a4SArnaldo Carvalho de Melo map__fixup_start(map); 12456a4694a4SArnaldo Carvalho de Melo map__fixup_end(map); 1246439d473bSArnaldo Carvalho de Melo } 124794cb9e38SArnaldo Carvalho de Melo 124886470930SIngo Molnar return err; 124986470930SIngo Molnar } 125086470930SIngo Molnar 1251aeafcbafSArnaldo Carvalho de Melo static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 1252a1645ce1SZhang, Yanmin symbol_filter_t filter) 1253a1645ce1SZhang, Yanmin { 1254a1645ce1SZhang, Yanmin int err; 1255a1645ce1SZhang, Yanmin const char *kallsyms_filename = NULL; 125623346f21SArnaldo Carvalho de Melo struct machine *machine; 1257a1645ce1SZhang, Yanmin char path[PATH_MAX]; 1258a1645ce1SZhang, Yanmin 1259a1645ce1SZhang, Yanmin if (!map->groups) { 1260a1645ce1SZhang, Yanmin pr_debug("Guest kernel map hasn't the point to groups\n"); 1261a1645ce1SZhang, Yanmin return -1; 1262a1645ce1SZhang, Yanmin } 126323346f21SArnaldo Carvalho de Melo machine = map->groups->machine; 1264a1645ce1SZhang, Yanmin 126523346f21SArnaldo Carvalho de Melo if (machine__is_default_guest(machine)) { 1266a1645ce1SZhang, Yanmin /* 1267a1645ce1SZhang, Yanmin * if the user specified a vmlinux filename, use it and only 1268a1645ce1SZhang, Yanmin * it, reporting errors to the user if it cannot be used. 1269a1645ce1SZhang, Yanmin * Or use file guest_kallsyms inputted by user on commandline 1270a1645ce1SZhang, Yanmin */ 1271a1645ce1SZhang, Yanmin if (symbol_conf.default_guest_vmlinux_name != NULL) { 1272aeafcbafSArnaldo Carvalho de Melo err = dso__load_vmlinux(dso, map, 1273a1645ce1SZhang, Yanmin symbol_conf.default_guest_vmlinux_name, filter); 1274a1645ce1SZhang, Yanmin goto out_try_fixup; 1275a1645ce1SZhang, Yanmin } 1276a1645ce1SZhang, Yanmin 1277a1645ce1SZhang, Yanmin kallsyms_filename = symbol_conf.default_guest_kallsyms; 1278a1645ce1SZhang, Yanmin if (!kallsyms_filename) 1279a1645ce1SZhang, Yanmin return -1; 1280a1645ce1SZhang, Yanmin } else { 128123346f21SArnaldo Carvalho de Melo sprintf(path, "%s/proc/kallsyms", machine->root_dir); 1282a1645ce1SZhang, Yanmin kallsyms_filename = path; 1283a1645ce1SZhang, Yanmin } 1284a1645ce1SZhang, Yanmin 1285aeafcbafSArnaldo Carvalho de Melo err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1286a1645ce1SZhang, Yanmin if (err > 0) 1287a1645ce1SZhang, Yanmin pr_debug("Using %s for symbols\n", kallsyms_filename); 1288a1645ce1SZhang, Yanmin 1289a1645ce1SZhang, Yanmin out_try_fixup: 1290a1645ce1SZhang, Yanmin if (err > 0) { 1291a1645ce1SZhang, Yanmin if (kallsyms_filename != NULL) { 129248ea8f54SArnaldo Carvalho de Melo machine__mmap_name(machine, path, sizeof(path)); 1293aeafcbafSArnaldo Carvalho de Melo dso__set_long_name(dso, strdup(path)); 1294a1645ce1SZhang, Yanmin } 1295a1645ce1SZhang, Yanmin map__fixup_start(map); 1296a1645ce1SZhang, Yanmin map__fixup_end(map); 1297a1645ce1SZhang, Yanmin } 1298a1645ce1SZhang, Yanmin 1299a1645ce1SZhang, Yanmin return err; 1300a1645ce1SZhang, Yanmin } 1301cd84c2acSFrederic Weisbecker 1302aeafcbafSArnaldo Carvalho de Melo size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) 1303b0da954aSArnaldo Carvalho de Melo { 1304a1645ce1SZhang, Yanmin struct rb_node *nd; 1305cbf69680SArnaldo Carvalho de Melo size_t ret = 0; 1306a1645ce1SZhang, Yanmin 1307aeafcbafSArnaldo Carvalho de Melo for (nd = rb_first(machines); nd; nd = rb_next(nd)) { 130823346f21SArnaldo Carvalho de Melo struct machine *pos = rb_entry(nd, struct machine, rb_node); 1309cbf69680SArnaldo Carvalho de Melo ret += __dsos__fprintf(&pos->kernel_dsos, fp); 1310cbf69680SArnaldo Carvalho de Melo ret += __dsos__fprintf(&pos->user_dsos, fp); 1311a1645ce1SZhang, Yanmin } 1312cbf69680SArnaldo Carvalho de Melo 1313cbf69680SArnaldo Carvalho de Melo return ret; 1314b0da954aSArnaldo Carvalho de Melo } 1315b0da954aSArnaldo Carvalho de Melo 1316aeafcbafSArnaldo Carvalho de Melo size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 1317aeafcbafSArnaldo Carvalho de Melo bool with_hits) 1318f869097eSArnaldo Carvalho de Melo { 1319aeafcbafSArnaldo Carvalho de Melo return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) + 1320aeafcbafSArnaldo Carvalho de Melo __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits); 1321f869097eSArnaldo Carvalho de Melo } 1322f869097eSArnaldo Carvalho de Melo 1323aeafcbafSArnaldo Carvalho de Melo size_t machines__fprintf_dsos_buildid(struct rb_root *machines, 1324aeafcbafSArnaldo Carvalho de Melo FILE *fp, bool with_hits) 1325b0da954aSArnaldo Carvalho de Melo { 1326a1645ce1SZhang, Yanmin struct rb_node *nd; 1327a1645ce1SZhang, Yanmin size_t ret = 0; 1328a1645ce1SZhang, Yanmin 1329aeafcbafSArnaldo Carvalho de Melo for (nd = rb_first(machines); nd; nd = rb_next(nd)) { 133023346f21SArnaldo Carvalho de Melo struct machine *pos = rb_entry(nd, struct machine, rb_node); 1331f869097eSArnaldo Carvalho de Melo ret += machine__fprintf_dsos_buildid(pos, fp, with_hits); 1332a1645ce1SZhang, Yanmin } 1333a1645ce1SZhang, Yanmin return ret; 1334b0da954aSArnaldo Carvalho de Melo } 1335b0da954aSArnaldo Carvalho de Melo 1336f57b05edSJiri Olsa static struct dso *machine__get_kernel(struct machine *machine) 1337cd84c2acSFrederic Weisbecker { 1338a1645ce1SZhang, Yanmin const char *vmlinux_name = NULL; 1339a1645ce1SZhang, Yanmin struct dso *kernel; 1340cd84c2acSFrederic Weisbecker 1341aeafcbafSArnaldo Carvalho de Melo if (machine__is_host(machine)) { 1342a1645ce1SZhang, Yanmin vmlinux_name = symbol_conf.vmlinux_name; 1343f57b05edSJiri Olsa if (!vmlinux_name) 1344f57b05edSJiri Olsa vmlinux_name = "[kernel.kallsyms]"; 1345f57b05edSJiri Olsa 1346f57b05edSJiri Olsa kernel = dso__kernel_findnew(machine, vmlinux_name, 1347f57b05edSJiri Olsa "[kernel]", 1348f57b05edSJiri Olsa DSO_TYPE_KERNEL); 1349a1645ce1SZhang, Yanmin } else { 1350f57b05edSJiri Olsa char bf[PATH_MAX]; 1351f57b05edSJiri Olsa 1352aeafcbafSArnaldo Carvalho de Melo if (machine__is_default_guest(machine)) 1353a1645ce1SZhang, Yanmin vmlinux_name = symbol_conf.default_guest_vmlinux_name; 1354f57b05edSJiri Olsa if (!vmlinux_name) 1355f57b05edSJiri Olsa vmlinux_name = machine__mmap_name(machine, bf, 1356f57b05edSJiri Olsa sizeof(bf)); 1357f57b05edSJiri Olsa 1358f57b05edSJiri Olsa kernel = dso__kernel_findnew(machine, vmlinux_name, 1359f57b05edSJiri Olsa "[guest.kernel]", 1360f57b05edSJiri Olsa DSO_TYPE_GUEST_KERNEL); 13618d92c02aSArnaldo Carvalho de Melo } 1362cd84c2acSFrederic Weisbecker 1363f57b05edSJiri Olsa if (kernel != NULL && (!kernel->has_build_id)) 1364aeafcbafSArnaldo Carvalho de Melo dso__read_running_kernel_build_id(kernel, machine); 1365f57b05edSJiri Olsa 1366f1dfa0b1SArnaldo Carvalho de Melo return kernel; 1367f1dfa0b1SArnaldo Carvalho de Melo } 1368f1dfa0b1SArnaldo Carvalho de Melo 1369d214afbdSMing Lei struct process_args { 1370d214afbdSMing Lei u64 start; 1371d214afbdSMing Lei }; 1372d214afbdSMing Lei 1373d214afbdSMing Lei static int symbol__in_kernel(void *arg, const char *name, 13741d037ca1SIrina Tirdea char type __maybe_unused, u64 start) 1375d214afbdSMing Lei { 1376d214afbdSMing Lei struct process_args *args = arg; 1377d214afbdSMing Lei 1378d214afbdSMing Lei if (strchr(name, '[')) 1379d214afbdSMing Lei return 0; 1380d214afbdSMing Lei 1381d214afbdSMing Lei args->start = start; 1382d214afbdSMing Lei return 1; 1383d214afbdSMing Lei } 1384d214afbdSMing Lei 1385d214afbdSMing Lei /* Figure out the start address of kernel map from /proc/kallsyms */ 1386d214afbdSMing Lei static u64 machine__get_kernel_start_addr(struct machine *machine) 1387d214afbdSMing Lei { 1388d214afbdSMing Lei const char *filename; 1389d214afbdSMing Lei char path[PATH_MAX]; 1390d214afbdSMing Lei struct process_args args; 1391d214afbdSMing Lei 1392d214afbdSMing Lei if (machine__is_host(machine)) { 1393d214afbdSMing Lei filename = "/proc/kallsyms"; 1394d214afbdSMing Lei } else { 1395d214afbdSMing Lei if (machine__is_default_guest(machine)) 1396d214afbdSMing Lei filename = (char *)symbol_conf.default_guest_kallsyms; 1397d214afbdSMing Lei else { 1398d214afbdSMing Lei sprintf(path, "%s/proc/kallsyms", machine->root_dir); 1399d214afbdSMing Lei filename = path; 1400d214afbdSMing Lei } 1401d214afbdSMing Lei } 1402d214afbdSMing Lei 1403ec80fde7SArnaldo Carvalho de Melo if (symbol__restricted_filename(filename, "/proc/kallsyms")) 1404ec80fde7SArnaldo Carvalho de Melo return 0; 1405ec80fde7SArnaldo Carvalho de Melo 1406d214afbdSMing Lei if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) 1407d214afbdSMing Lei return 0; 1408d214afbdSMing Lei 1409d214afbdSMing Lei return args.start; 1410d214afbdSMing Lei } 1411d214afbdSMing Lei 1412aeafcbafSArnaldo Carvalho de Melo int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 1413f1dfa0b1SArnaldo Carvalho de Melo { 1414de176489SArnaldo Carvalho de Melo enum map_type type; 1415aeafcbafSArnaldo Carvalho de Melo u64 start = machine__get_kernel_start_addr(machine); 1416f1dfa0b1SArnaldo Carvalho de Melo 1417de176489SArnaldo Carvalho de Melo for (type = 0; type < MAP__NR_TYPES; ++type) { 14189de89fe7SArnaldo Carvalho de Melo struct kmap *kmap; 14199de89fe7SArnaldo Carvalho de Melo 1420aeafcbafSArnaldo Carvalho de Melo machine->vmlinux_maps[type] = map__new2(start, kernel, type); 1421aeafcbafSArnaldo Carvalho de Melo if (machine->vmlinux_maps[type] == NULL) 1422f1dfa0b1SArnaldo Carvalho de Melo return -1; 1423f1dfa0b1SArnaldo Carvalho de Melo 1424aeafcbafSArnaldo Carvalho de Melo machine->vmlinux_maps[type]->map_ip = 1425aeafcbafSArnaldo Carvalho de Melo machine->vmlinux_maps[type]->unmap_ip = 1426aeafcbafSArnaldo Carvalho de Melo identity__map_ip; 1427aeafcbafSArnaldo Carvalho de Melo kmap = map__kmap(machine->vmlinux_maps[type]); 1428aeafcbafSArnaldo Carvalho de Melo kmap->kmaps = &machine->kmaps; 1429aeafcbafSArnaldo Carvalho de Melo map_groups__insert(&machine->kmaps, 1430aeafcbafSArnaldo Carvalho de Melo machine->vmlinux_maps[type]); 1431f1dfa0b1SArnaldo Carvalho de Melo } 1432f1dfa0b1SArnaldo Carvalho de Melo 1433f1dfa0b1SArnaldo Carvalho de Melo return 0; 14342446042cSArnaldo Carvalho de Melo } 14352446042cSArnaldo Carvalho de Melo 1436aeafcbafSArnaldo Carvalho de Melo void machine__destroy_kernel_maps(struct machine *machine) 1437076c6e45SArnaldo Carvalho de Melo { 1438076c6e45SArnaldo Carvalho de Melo enum map_type type; 1439076c6e45SArnaldo Carvalho de Melo 1440076c6e45SArnaldo Carvalho de Melo for (type = 0; type < MAP__NR_TYPES; ++type) { 1441076c6e45SArnaldo Carvalho de Melo struct kmap *kmap; 1442076c6e45SArnaldo Carvalho de Melo 1443aeafcbafSArnaldo Carvalho de Melo if (machine->vmlinux_maps[type] == NULL) 1444076c6e45SArnaldo Carvalho de Melo continue; 1445076c6e45SArnaldo Carvalho de Melo 1446aeafcbafSArnaldo Carvalho de Melo kmap = map__kmap(machine->vmlinux_maps[type]); 1447aeafcbafSArnaldo Carvalho de Melo map_groups__remove(&machine->kmaps, 1448aeafcbafSArnaldo Carvalho de Melo machine->vmlinux_maps[type]); 1449076c6e45SArnaldo Carvalho de Melo if (kmap->ref_reloc_sym) { 1450076c6e45SArnaldo Carvalho de Melo /* 1451076c6e45SArnaldo Carvalho de Melo * ref_reloc_sym is shared among all maps, so free just 1452076c6e45SArnaldo Carvalho de Melo * on one of them. 1453076c6e45SArnaldo Carvalho de Melo */ 1454076c6e45SArnaldo Carvalho de Melo if (type == MAP__FUNCTION) { 1455076c6e45SArnaldo Carvalho de Melo free((char *)kmap->ref_reloc_sym->name); 1456076c6e45SArnaldo Carvalho de Melo kmap->ref_reloc_sym->name = NULL; 1457076c6e45SArnaldo Carvalho de Melo free(kmap->ref_reloc_sym); 1458076c6e45SArnaldo Carvalho de Melo } 1459076c6e45SArnaldo Carvalho de Melo kmap->ref_reloc_sym = NULL; 1460076c6e45SArnaldo Carvalho de Melo } 1461076c6e45SArnaldo Carvalho de Melo 1462aeafcbafSArnaldo Carvalho de Melo map__delete(machine->vmlinux_maps[type]); 1463aeafcbafSArnaldo Carvalho de Melo machine->vmlinux_maps[type] = NULL; 1464076c6e45SArnaldo Carvalho de Melo } 1465076c6e45SArnaldo Carvalho de Melo } 1466076c6e45SArnaldo Carvalho de Melo 1467aeafcbafSArnaldo Carvalho de Melo int machine__create_kernel_maps(struct machine *machine) 14685c0541d5SArnaldo Carvalho de Melo { 1469f57b05edSJiri Olsa struct dso *kernel = machine__get_kernel(machine); 14705c0541d5SArnaldo Carvalho de Melo 14715c0541d5SArnaldo Carvalho de Melo if (kernel == NULL || 1472aeafcbafSArnaldo Carvalho de Melo __machine__create_kernel_maps(machine, kernel) < 0) 14735c0541d5SArnaldo Carvalho de Melo return -1; 14745c0541d5SArnaldo Carvalho de Melo 1475f51304d3SDavid Ahern if (symbol_conf.use_modules && machine__create_modules(machine) < 0) { 1476f51304d3SDavid Ahern if (machine__is_host(machine)) 1477f51304d3SDavid Ahern pr_debug("Problems creating module maps, " 1478f51304d3SDavid Ahern "continuing anyway...\n"); 1479f51304d3SDavid Ahern else 1480f51304d3SDavid Ahern pr_debug("Problems creating module maps for guest %d, " 1481f51304d3SDavid Ahern "continuing anyway...\n", machine->pid); 1482f51304d3SDavid Ahern } 1483f51304d3SDavid Ahern 14845c0541d5SArnaldo Carvalho de Melo /* 14855c0541d5SArnaldo Carvalho de Melo * Now that we have all the maps created, just set the ->end of them: 14865c0541d5SArnaldo Carvalho de Melo */ 1487aeafcbafSArnaldo Carvalho de Melo map_groups__fixup_end(&machine->kmaps); 14885c0541d5SArnaldo Carvalho de Melo return 0; 14895c0541d5SArnaldo Carvalho de Melo } 14905c0541d5SArnaldo Carvalho de Melo 1491cc612d81SArnaldo Carvalho de Melo static void vmlinux_path__exit(void) 14922446042cSArnaldo Carvalho de Melo { 1493cc612d81SArnaldo Carvalho de Melo while (--vmlinux_path__nr_entries >= 0) { 1494cc612d81SArnaldo Carvalho de Melo free(vmlinux_path[vmlinux_path__nr_entries]); 1495cc612d81SArnaldo Carvalho de Melo vmlinux_path[vmlinux_path__nr_entries] = NULL; 1496cc612d81SArnaldo Carvalho de Melo } 1497cc612d81SArnaldo Carvalho de Melo 1498cc612d81SArnaldo Carvalho de Melo free(vmlinux_path); 1499cc612d81SArnaldo Carvalho de Melo vmlinux_path = NULL; 1500cc612d81SArnaldo Carvalho de Melo } 1501cc612d81SArnaldo Carvalho de Melo 1502cc612d81SArnaldo Carvalho de Melo static int vmlinux_path__init(void) 1503cc612d81SArnaldo Carvalho de Melo { 1504cc612d81SArnaldo Carvalho de Melo struct utsname uts; 1505cc612d81SArnaldo Carvalho de Melo char bf[PATH_MAX]; 1506cc612d81SArnaldo Carvalho de Melo 1507cc612d81SArnaldo Carvalho de Melo vmlinux_path = malloc(sizeof(char *) * 5); 1508cc612d81SArnaldo Carvalho de Melo if (vmlinux_path == NULL) 1509cc612d81SArnaldo Carvalho de Melo return -1; 1510cc612d81SArnaldo Carvalho de Melo 1511cc612d81SArnaldo Carvalho de Melo vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux"); 1512cc612d81SArnaldo Carvalho de Melo if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1513cc612d81SArnaldo Carvalho de Melo goto out_fail; 1514cc612d81SArnaldo Carvalho de Melo ++vmlinux_path__nr_entries; 1515cc612d81SArnaldo Carvalho de Melo vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux"); 1516cc612d81SArnaldo Carvalho de Melo if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1517cc612d81SArnaldo Carvalho de Melo goto out_fail; 1518cc612d81SArnaldo Carvalho de Melo ++vmlinux_path__nr_entries; 1519ec5761eaSDavid Ahern 1520ec5761eaSDavid Ahern /* only try running kernel version if no symfs was given */ 1521ec5761eaSDavid Ahern if (symbol_conf.symfs[0] != 0) 1522ec5761eaSDavid Ahern return 0; 1523ec5761eaSDavid Ahern 1524ec5761eaSDavid Ahern if (uname(&uts) < 0) 1525ec5761eaSDavid Ahern return -1; 1526ec5761eaSDavid Ahern 1527cc612d81SArnaldo Carvalho de Melo snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 1528cc612d81SArnaldo Carvalho de Melo vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1529cc612d81SArnaldo Carvalho de Melo if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1530cc612d81SArnaldo Carvalho de Melo goto out_fail; 1531cc612d81SArnaldo Carvalho de Melo ++vmlinux_path__nr_entries; 1532cc612d81SArnaldo Carvalho de Melo snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); 1533cc612d81SArnaldo Carvalho de Melo vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1534cc612d81SArnaldo Carvalho de Melo if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1535cc612d81SArnaldo Carvalho de Melo goto out_fail; 1536cc612d81SArnaldo Carvalho de Melo ++vmlinux_path__nr_entries; 1537cc612d81SArnaldo Carvalho de Melo snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", 1538cc612d81SArnaldo Carvalho de Melo uts.release); 1539cc612d81SArnaldo Carvalho de Melo vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1540cc612d81SArnaldo Carvalho de Melo if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1541cc612d81SArnaldo Carvalho de Melo goto out_fail; 1542cc612d81SArnaldo Carvalho de Melo ++vmlinux_path__nr_entries; 1543cc612d81SArnaldo Carvalho de Melo 1544cc612d81SArnaldo Carvalho de Melo return 0; 1545cc612d81SArnaldo Carvalho de Melo 1546cc612d81SArnaldo Carvalho de Melo out_fail: 1547cc612d81SArnaldo Carvalho de Melo vmlinux_path__exit(); 1548cc612d81SArnaldo Carvalho de Melo return -1; 1549cc612d81SArnaldo Carvalho de Melo } 1550cc612d81SArnaldo Carvalho de Melo 1551aeafcbafSArnaldo Carvalho de Melo size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp) 1552b0a9ab62SArnaldo Carvalho de Melo { 1553b0a9ab62SArnaldo Carvalho de Melo int i; 1554b0a9ab62SArnaldo Carvalho de Melo size_t printed = 0; 1555aeafcbafSArnaldo Carvalho de Melo struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso; 15565ad90e4eSArnaldo Carvalho de Melo 15575ad90e4eSArnaldo Carvalho de Melo if (kdso->has_build_id) { 15585ad90e4eSArnaldo Carvalho de Melo char filename[PATH_MAX]; 15595ad90e4eSArnaldo Carvalho de Melo if (dso__build_id_filename(kdso, filename, sizeof(filename))) 15605ad90e4eSArnaldo Carvalho de Melo printed += fprintf(fp, "[0] %s\n", filename); 15615ad90e4eSArnaldo Carvalho de Melo } 1562b0a9ab62SArnaldo Carvalho de Melo 1563b0a9ab62SArnaldo Carvalho de Melo for (i = 0; i < vmlinux_path__nr_entries; ++i) 15645ad90e4eSArnaldo Carvalho de Melo printed += fprintf(fp, "[%d] %s\n", 15655ad90e4eSArnaldo Carvalho de Melo i + kdso->has_build_id, vmlinux_path[i]); 1566b0a9ab62SArnaldo Carvalho de Melo 1567b0a9ab62SArnaldo Carvalho de Melo return printed; 1568b0a9ab62SArnaldo Carvalho de Melo } 1569b0a9ab62SArnaldo Carvalho de Melo 1570655000e7SArnaldo Carvalho de Melo static int setup_list(struct strlist **list, const char *list_str, 1571655000e7SArnaldo Carvalho de Melo const char *list_name) 1572655000e7SArnaldo Carvalho de Melo { 1573655000e7SArnaldo Carvalho de Melo if (list_str == NULL) 1574655000e7SArnaldo Carvalho de Melo return 0; 1575655000e7SArnaldo Carvalho de Melo 1576655000e7SArnaldo Carvalho de Melo *list = strlist__new(true, list_str); 1577655000e7SArnaldo Carvalho de Melo if (!*list) { 1578655000e7SArnaldo Carvalho de Melo pr_err("problems parsing %s list\n", list_name); 1579655000e7SArnaldo Carvalho de Melo return -1; 1580655000e7SArnaldo Carvalho de Melo } 1581655000e7SArnaldo Carvalho de Melo return 0; 1582655000e7SArnaldo Carvalho de Melo } 1583655000e7SArnaldo Carvalho de Melo 1584ec80fde7SArnaldo Carvalho de Melo static bool symbol__read_kptr_restrict(void) 1585ec80fde7SArnaldo Carvalho de Melo { 1586ec80fde7SArnaldo Carvalho de Melo bool value = false; 1587ec80fde7SArnaldo Carvalho de Melo 1588ec80fde7SArnaldo Carvalho de Melo if (geteuid() != 0) { 1589ec80fde7SArnaldo Carvalho de Melo FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r"); 1590ec80fde7SArnaldo Carvalho de Melo if (fp != NULL) { 1591ec80fde7SArnaldo Carvalho de Melo char line[8]; 1592ec80fde7SArnaldo Carvalho de Melo 1593ec80fde7SArnaldo Carvalho de Melo if (fgets(line, sizeof(line), fp) != NULL) 1594ec80fde7SArnaldo Carvalho de Melo value = atoi(line) != 0; 1595ec80fde7SArnaldo Carvalho de Melo 1596ec80fde7SArnaldo Carvalho de Melo fclose(fp); 1597ec80fde7SArnaldo Carvalho de Melo } 1598ec80fde7SArnaldo Carvalho de Melo } 1599ec80fde7SArnaldo Carvalho de Melo 1600ec80fde7SArnaldo Carvalho de Melo return value; 1601ec80fde7SArnaldo Carvalho de Melo } 1602ec80fde7SArnaldo Carvalho de Melo 160375be6cf4SArnaldo Carvalho de Melo int symbol__init(void) 1604cc612d81SArnaldo Carvalho de Melo { 1605ec5761eaSDavid Ahern const char *symfs; 1606ec5761eaSDavid Ahern 160785e00b55SJovi Zhang if (symbol_conf.initialized) 160885e00b55SJovi Zhang return 0; 160985e00b55SJovi Zhang 16109ac3e487SIrina Tirdea symbol_conf.priv_size = PERF_ALIGN(symbol_conf.priv_size, sizeof(u64)); 16114d439517SDavid S. Miller 1612166ccc9cSNamhyung Kim symbol__elf_init(); 1613166ccc9cSNamhyung Kim 161475be6cf4SArnaldo Carvalho de Melo if (symbol_conf.sort_by_name) 161575be6cf4SArnaldo Carvalho de Melo symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 161679406cd7SArnaldo Carvalho de Melo sizeof(struct symbol)); 1617b32d133aSArnaldo Carvalho de Melo 161875be6cf4SArnaldo Carvalho de Melo if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) 1619cc612d81SArnaldo Carvalho de Melo return -1; 1620cc612d81SArnaldo Carvalho de Melo 1621c410a338SArnaldo Carvalho de Melo if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 1622c410a338SArnaldo Carvalho de Melo pr_err("'.' is the only non valid --field-separator argument\n"); 1623c410a338SArnaldo Carvalho de Melo return -1; 1624c410a338SArnaldo Carvalho de Melo } 1625c410a338SArnaldo Carvalho de Melo 1626655000e7SArnaldo Carvalho de Melo if (setup_list(&symbol_conf.dso_list, 1627655000e7SArnaldo Carvalho de Melo symbol_conf.dso_list_str, "dso") < 0) 1628655000e7SArnaldo Carvalho de Melo return -1; 1629655000e7SArnaldo Carvalho de Melo 1630655000e7SArnaldo Carvalho de Melo if (setup_list(&symbol_conf.comm_list, 1631655000e7SArnaldo Carvalho de Melo symbol_conf.comm_list_str, "comm") < 0) 1632655000e7SArnaldo Carvalho de Melo goto out_free_dso_list; 1633655000e7SArnaldo Carvalho de Melo 1634655000e7SArnaldo Carvalho de Melo if (setup_list(&symbol_conf.sym_list, 1635655000e7SArnaldo Carvalho de Melo symbol_conf.sym_list_str, "symbol") < 0) 1636655000e7SArnaldo Carvalho de Melo goto out_free_comm_list; 1637655000e7SArnaldo Carvalho de Melo 1638ec5761eaSDavid Ahern /* 1639ec5761eaSDavid Ahern * A path to symbols of "/" is identical to "" 1640ec5761eaSDavid Ahern * reset here for simplicity. 1641ec5761eaSDavid Ahern */ 1642ec5761eaSDavid Ahern symfs = realpath(symbol_conf.symfs, NULL); 1643ec5761eaSDavid Ahern if (symfs == NULL) 1644ec5761eaSDavid Ahern symfs = symbol_conf.symfs; 1645ec5761eaSDavid Ahern if (strcmp(symfs, "/") == 0) 1646ec5761eaSDavid Ahern symbol_conf.symfs = ""; 1647ec5761eaSDavid Ahern if (symfs != symbol_conf.symfs) 1648ec5761eaSDavid Ahern free((void *)symfs); 1649ec5761eaSDavid Ahern 1650ec80fde7SArnaldo Carvalho de Melo symbol_conf.kptr_restrict = symbol__read_kptr_restrict(); 1651ec80fde7SArnaldo Carvalho de Melo 165285e00b55SJovi Zhang symbol_conf.initialized = true; 16534aa65636SArnaldo Carvalho de Melo return 0; 1654655000e7SArnaldo Carvalho de Melo 1655655000e7SArnaldo Carvalho de Melo out_free_comm_list: 1656655000e7SArnaldo Carvalho de Melo strlist__delete(symbol_conf.comm_list); 1657d74c896bSNamhyung Kim out_free_dso_list: 1658d74c896bSNamhyung Kim strlist__delete(symbol_conf.dso_list); 1659655000e7SArnaldo Carvalho de Melo return -1; 1660cc612d81SArnaldo Carvalho de Melo } 1661cc612d81SArnaldo Carvalho de Melo 1662d65a458bSArnaldo Carvalho de Melo void symbol__exit(void) 1663d65a458bSArnaldo Carvalho de Melo { 166485e00b55SJovi Zhang if (!symbol_conf.initialized) 166585e00b55SJovi Zhang return; 1666d65a458bSArnaldo Carvalho de Melo strlist__delete(symbol_conf.sym_list); 1667d65a458bSArnaldo Carvalho de Melo strlist__delete(symbol_conf.dso_list); 1668d65a458bSArnaldo Carvalho de Melo strlist__delete(symbol_conf.comm_list); 1669d65a458bSArnaldo Carvalho de Melo vmlinux_path__exit(); 1670d65a458bSArnaldo Carvalho de Melo symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 167185e00b55SJovi Zhang symbol_conf.initialized = false; 1672d65a458bSArnaldo Carvalho de Melo } 1673d65a458bSArnaldo Carvalho de Melo 1674aeafcbafSArnaldo Carvalho de Melo int machines__create_kernel_maps(struct rb_root *machines, pid_t pid) 16754aa65636SArnaldo Carvalho de Melo { 1676aeafcbafSArnaldo Carvalho de Melo struct machine *machine = machines__findnew(machines, pid); 16779de89fe7SArnaldo Carvalho de Melo 167823346f21SArnaldo Carvalho de Melo if (machine == NULL) 1679a1645ce1SZhang, Yanmin return -1; 16804aa65636SArnaldo Carvalho de Melo 16815c0541d5SArnaldo Carvalho de Melo return machine__create_kernel_maps(machine); 1682cd84c2acSFrederic Weisbecker } 16835aab621bSArnaldo Carvalho de Melo 1684aeafcbafSArnaldo Carvalho de Melo int machines__create_guest_kernel_maps(struct rb_root *machines) 1685a1645ce1SZhang, Yanmin { 1686a1645ce1SZhang, Yanmin int ret = 0; 1687a1645ce1SZhang, Yanmin struct dirent **namelist = NULL; 1688a1645ce1SZhang, Yanmin int i, items = 0; 1689a1645ce1SZhang, Yanmin char path[PATH_MAX]; 1690a1645ce1SZhang, Yanmin pid_t pid; 1691347ed990SDavid Ahern char *endp; 1692a1645ce1SZhang, Yanmin 1693a1645ce1SZhang, Yanmin if (symbol_conf.default_guest_vmlinux_name || 1694a1645ce1SZhang, Yanmin symbol_conf.default_guest_modules || 1695a1645ce1SZhang, Yanmin symbol_conf.default_guest_kallsyms) { 1696aeafcbafSArnaldo Carvalho de Melo machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); 1697a1645ce1SZhang, Yanmin } 1698a1645ce1SZhang, Yanmin 1699a1645ce1SZhang, Yanmin if (symbol_conf.guestmount) { 1700a1645ce1SZhang, Yanmin items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL); 1701a1645ce1SZhang, Yanmin if (items <= 0) 1702a1645ce1SZhang, Yanmin return -ENOENT; 1703a1645ce1SZhang, Yanmin for (i = 0; i < items; i++) { 1704a1645ce1SZhang, Yanmin if (!isdigit(namelist[i]->d_name[0])) { 1705a1645ce1SZhang, Yanmin /* Filter out . and .. */ 1706a1645ce1SZhang, Yanmin continue; 1707a1645ce1SZhang, Yanmin } 1708347ed990SDavid Ahern pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10); 1709347ed990SDavid Ahern if ((*endp != '\0') || 1710347ed990SDavid Ahern (endp == namelist[i]->d_name) || 1711347ed990SDavid Ahern (errno == ERANGE)) { 1712347ed990SDavid Ahern pr_debug("invalid directory (%s). Skipping.\n", 1713347ed990SDavid Ahern namelist[i]->d_name); 1714347ed990SDavid Ahern continue; 1715347ed990SDavid Ahern } 1716a1645ce1SZhang, Yanmin sprintf(path, "%s/%s/proc/kallsyms", 1717a1645ce1SZhang, Yanmin symbol_conf.guestmount, 1718a1645ce1SZhang, Yanmin namelist[i]->d_name); 1719a1645ce1SZhang, Yanmin ret = access(path, R_OK); 1720a1645ce1SZhang, Yanmin if (ret) { 1721a1645ce1SZhang, Yanmin pr_debug("Can't access file %s\n", path); 1722a1645ce1SZhang, Yanmin goto failure; 1723a1645ce1SZhang, Yanmin } 1724aeafcbafSArnaldo Carvalho de Melo machines__create_kernel_maps(machines, pid); 1725a1645ce1SZhang, Yanmin } 1726a1645ce1SZhang, Yanmin failure: 1727a1645ce1SZhang, Yanmin free(namelist); 1728a1645ce1SZhang, Yanmin } 1729a1645ce1SZhang, Yanmin 1730a1645ce1SZhang, Yanmin return ret; 1731a1645ce1SZhang, Yanmin } 17325c0541d5SArnaldo Carvalho de Melo 1733aeafcbafSArnaldo Carvalho de Melo void machines__destroy_guest_kernel_maps(struct rb_root *machines) 1734076c6e45SArnaldo Carvalho de Melo { 1735aeafcbafSArnaldo Carvalho de Melo struct rb_node *next = rb_first(machines); 1736076c6e45SArnaldo Carvalho de Melo 1737076c6e45SArnaldo Carvalho de Melo while (next) { 1738076c6e45SArnaldo Carvalho de Melo struct machine *pos = rb_entry(next, struct machine, rb_node); 1739076c6e45SArnaldo Carvalho de Melo 1740076c6e45SArnaldo Carvalho de Melo next = rb_next(&pos->rb_node); 1741aeafcbafSArnaldo Carvalho de Melo rb_erase(&pos->rb_node, machines); 1742076c6e45SArnaldo Carvalho de Melo machine__delete(pos); 1743076c6e45SArnaldo Carvalho de Melo } 1744076c6e45SArnaldo Carvalho de Melo } 1745076c6e45SArnaldo Carvalho de Melo 1746aeafcbafSArnaldo Carvalho de Melo int machine__load_kallsyms(struct machine *machine, const char *filename, 17475c0541d5SArnaldo Carvalho de Melo enum map_type type, symbol_filter_t filter) 17485c0541d5SArnaldo Carvalho de Melo { 1749aeafcbafSArnaldo Carvalho de Melo struct map *map = machine->vmlinux_maps[type]; 17505c0541d5SArnaldo Carvalho de Melo int ret = dso__load_kallsyms(map->dso, filename, map, filter); 17515c0541d5SArnaldo Carvalho de Melo 17525c0541d5SArnaldo Carvalho de Melo if (ret > 0) { 17535c0541d5SArnaldo Carvalho de Melo dso__set_loaded(map->dso, type); 17545c0541d5SArnaldo Carvalho de Melo /* 17555c0541d5SArnaldo Carvalho de Melo * Since /proc/kallsyms will have multiple sessions for the 17565c0541d5SArnaldo Carvalho de Melo * kernel, with modules between them, fixup the end of all 17575c0541d5SArnaldo Carvalho de Melo * sections. 17585c0541d5SArnaldo Carvalho de Melo */ 1759aeafcbafSArnaldo Carvalho de Melo __map_groups__fixup_end(&machine->kmaps, type); 17605c0541d5SArnaldo Carvalho de Melo } 17615c0541d5SArnaldo Carvalho de Melo 17625c0541d5SArnaldo Carvalho de Melo return ret; 17635c0541d5SArnaldo Carvalho de Melo } 17645c0541d5SArnaldo Carvalho de Melo 1765aeafcbafSArnaldo Carvalho de Melo int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 17665c0541d5SArnaldo Carvalho de Melo symbol_filter_t filter) 17675c0541d5SArnaldo Carvalho de Melo { 1768aeafcbafSArnaldo Carvalho de Melo struct map *map = machine->vmlinux_maps[type]; 17695c0541d5SArnaldo Carvalho de Melo int ret = dso__load_vmlinux_path(map->dso, map, filter); 17705c0541d5SArnaldo Carvalho de Melo 17715c0541d5SArnaldo Carvalho de Melo if (ret > 0) { 17725c0541d5SArnaldo Carvalho de Melo dso__set_loaded(map->dso, type); 17735c0541d5SArnaldo Carvalho de Melo map__reloc_vmlinux(map); 17745c0541d5SArnaldo Carvalho de Melo } 17755c0541d5SArnaldo Carvalho de Melo 17765c0541d5SArnaldo Carvalho de Melo return ret; 17775c0541d5SArnaldo Carvalho de Melo } 1778