10 static struct symbol *symbol__new(uint64_t start, uint64_t len,
11 const char *name, unsigned int priv_size)
13 size_t namelen = strlen(name) + 1;
14 struct symbol *self = malloc(priv_size + sizeof(*self) + namelen);
18 memset(self, 0, priv_size);
19 self = ((void *)self) + priv_size;
22 self->end = start + len;
23 memcpy(self->name, name, namelen);
29 static void symbol__delete(struct symbol *self, unsigned int priv_size)
31 free(((void *)self) - priv_size);
34 static size_t symbol__fprintf(struct symbol *self, FILE *fp)
36 return fprintf(fp, " %llx-%llx %s\n",
37 self->start, self->end, self->name);
40 struct dso *dso__new(const char *name, unsigned int sym_priv_size)
42 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1);
45 strcpy(self->name, name);
47 self->sym_priv_size = sym_priv_size;
53 static void dso__delete_symbols(struct dso *self)
56 struct rb_node *next = rb_first(&self->syms);
59 pos = rb_entry(next, struct symbol, rb_node);
60 next = rb_next(&pos->rb_node);
61 rb_erase(&pos->rb_node, &self->syms);
62 symbol__delete(pos, self->sym_priv_size);
66 void dso__delete(struct dso *self)
68 dso__delete_symbols(self);
72 static void dso__insert_symbol(struct dso *self, struct symbol *sym)
74 struct rb_node **p = &self->syms.rb_node;
75 struct rb_node *parent = NULL;
76 const uint64_t ip = sym->start;
81 s = rb_entry(parent, struct symbol, rb_node);
87 rb_link_node(&sym->rb_node, parent, p);
88 rb_insert_color(&sym->rb_node, &self->syms);
91 struct symbol *dso__find_symbol(struct dso *self, uint64_t ip)
98 n = self->syms.rb_node;
101 struct symbol *s = rb_entry(n, struct symbol, rb_node);
105 else if (ip > s->end)
114 size_t dso__fprintf(struct dso *self, FILE *fp)
116 size_t ret = fprintf(fp, "dso: %s\n", self->name);
119 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
120 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
121 ret += symbol__fprintf(pos, fp);
127 static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter)
129 struct rb_node *nd, *prevnd;
132 FILE *file = fopen("/proc/kallsyms", "r");
137 while (!feof(file)) {
143 line_len = getline(&line, &n, file);
150 line[--line_len] = '\0'; /* \n */
152 len = hex2u64(line, &start);
155 if (len + 2 >= line_len)
158 symbol_type = toupper(line[len]);
160 * We're interested only in code ('T'ext)
162 if (symbol_type != 'T' && symbol_type != 'W')
165 * Well fix up the end later, when we have all sorted.
167 sym = symbol__new(start, 0xdead, line + len + 2,
168 self->sym_priv_size);
171 goto out_delete_line;
173 if (filter && filter(self, sym))
174 symbol__delete(sym, self->sym_priv_size);
176 dso__insert_symbol(self, sym);
180 * Now that we have all sorted out, just set the ->end of all
183 prevnd = rb_first(&self->syms);
186 goto out_delete_line;
188 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
189 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
190 *curr = rb_entry(nd, struct symbol, rb_node);
192 prev->end = curr->start - 1;
208 * elf_symtab__for_each_symbol - iterate thru all the symbols
210 * @self: struct elf_symtab instance to iterate
211 * @index: uint32_t index
212 * @sym: GElf_Sym iterator
214 #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \
215 for (index = 0, gelf_getsym(syms, index, &sym);\
217 index++, gelf_getsym(syms, index, &sym))
219 static inline uint8_t elf_sym__type(const GElf_Sym *sym)
221 return GELF_ST_TYPE(sym->st_info);
224 static inline int elf_sym__is_function(const GElf_Sym *sym)
226 return elf_sym__type(sym) == STT_FUNC &&
228 sym->st_shndx != SHN_UNDEF &&
232 static inline const char *elf_sym__name(const GElf_Sym *sym,
233 const Elf_Data *symstrs)
235 return symstrs->d_buf + sym->st_name;
238 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
239 GElf_Shdr *shp, const char *name,
245 while ((sec = elf_nextscn(elf, sec)) != NULL) {
248 gelf_getshdr(sec, shp);
249 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
250 if (!strcmp(name, str)) {
261 static int dso__load_sym(struct dso *self, int fd, const char *name,
262 symbol_filter_t filter)
276 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
278 fprintf(stderr, "%s: cannot read %s ELF file.\n",
283 if (gelf_getehdr(elf, &ehdr) == NULL) {
284 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
288 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
290 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
295 syms = elf_getdata(sec, NULL);
299 sec = elf_getscn(elf, shdr.sh_link);
303 symstrs = elf_getdata(sec, NULL);
307 nr_syms = shdr.sh_size / shdr.sh_entsize;
309 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
312 if (!elf_sym__is_function(&sym))
315 sec = elf_getscn(elf, sym.st_shndx);
319 gelf_getshdr(sec, &shdr);
320 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
322 f = symbol__new(sym.st_value, sym.st_size,
323 elf_sym__name(&sym, symstrs),
324 self->sym_priv_size);
328 if (filter && filter(self, f))
329 symbol__delete(f, self->sym_priv_size);
331 dso__insert_symbol(self, f);
343 int dso__load(struct dso *self, symbol_filter_t filter)
345 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
346 char *name = malloc(size);
358 snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
361 snprintf(name, size, "/usr/lib/debug%s", self->name);
363 case 2: /* Sane people */
364 snprintf(name, size, "%s", self->name);
372 fd = open(name, O_RDONLY);
375 ret = dso__load_sym(self, fd, name, filter);
379 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
389 static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
390 symbol_filter_t filter)
392 int err, fd = open(vmlinux, O_RDONLY);
397 err = dso__load_sym(self, fd, vmlinux, filter);
403 int dso__load_kernel(struct dso *self, const char *vmlinux, symbol_filter_t filter)
408 err = dso__load_vmlinux(self, vmlinux, filter);
411 err = dso__load_kallsyms(self, filter);
416 void symbol__init(void)
418 elf_version(EV_CURRENT);