]> bbs.cooldavid.org Git - net-next-2.6.git/blame - tools/perf/util/symbol.c
Merge commit 'v2.6.32-rc6' into perf/core
[net-next-2.6.git] / tools / perf / util / symbol.c
CommitLineData
a2928c42
ACM
1#include "util.h"
2#include "../perf.h"
a0055ae2 3#include "string.h"
a2928c42 4#include "symbol.h"
439d473b 5#include "thread.h"
a2928c42 6
8f28827a
FW
7#include "debug.h"
8
a2928c42
ACM
9#include <libelf.h>
10#include <gelf.h>
11#include <elf.h>
439d473b 12#include <sys/utsname.h>
2cdbc46d 13
94cb9e38
ACM
14enum dso_origin {
15 DSO__ORIG_KERNEL = 0,
16 DSO__ORIG_JAVA_JIT,
17 DSO__ORIG_FEDORA,
18 DSO__ORIG_UBUNTU,
19 DSO__ORIG_BUILDID,
20 DSO__ORIG_DSO,
439d473b 21 DSO__ORIG_KMODULE,
94cb9e38
ACM
22 DSO__ORIG_NOT_FOUND,
23};
24
439d473b
ACM
25static void dsos__add(struct dso *dso);
26static struct dso *dsos__find(const char *name);
2e538c4a
ACM
27static struct map *map__new2(u64 start, struct dso *dso);
28static void kernel_maps__insert(struct map *map);
00a192b3 29unsigned int symbol__priv_size;
439d473b 30
af427bf5
ACM
31static struct rb_root kernel_maps;
32
2e538c4a 33static void dso__fixup_sym_end(struct dso *self)
af427bf5
ACM
34{
35 struct rb_node *nd, *prevnd = rb_first(&self->syms);
2e538c4a 36 struct symbol *curr, *prev;
af427bf5
ACM
37
38 if (prevnd == NULL)
39 return;
40
2e538c4a
ACM
41 curr = rb_entry(prevnd, struct symbol, rb_node);
42
af427bf5 43 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
2e538c4a
ACM
44 prev = curr;
45 curr = rb_entry(nd, struct symbol, rb_node);
af427bf5
ACM
46
47 if (prev->end == prev->start)
48 prev->end = curr->start - 1;
af427bf5 49 }
2e538c4a
ACM
50
51 /* Last entry */
52 if (curr->end == curr->start)
53 curr->end = roundup(curr->start, 4096);
af427bf5
ACM
54}
55
2e538c4a 56static void kernel_maps__fixup_end(void)
af427bf5
ACM
57{
58 struct map *prev, *curr;
59 struct rb_node *nd, *prevnd = rb_first(&kernel_maps);
60
61 if (prevnd == NULL)
62 return;
63
64 curr = rb_entry(prevnd, struct map, rb_node);
af427bf5
ACM
65
66 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
67 prev = curr;
68 curr = rb_entry(nd, struct map, rb_node);
69 prev->end = curr->start - 1;
2e538c4a
ACM
70 }
71
72 nd = rb_last(&curr->dso->syms);
73 if (nd) {
74 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
75 curr->end = sym->end;
af427bf5
ACM
76 }
77}
78
00a192b3 79static struct symbol *symbol__new(u64 start, u64 len, const char *name)
a2928c42 80{
0085c954 81 size_t namelen = strlen(name) + 1;
00a192b3
ACM
82 struct symbol *self = calloc(1, (symbol__priv_size +
83 sizeof(*self) + namelen));
0b73da3f
IM
84 if (!self)
85 return NULL;
86
00a192b3
ACM
87 if (symbol__priv_size) {
88 memset(self, 0, symbol__priv_size);
89 self = ((void *)self) + symbol__priv_size;
a2928c42 90 }
0b73da3f 91 self->start = start;
6cfcc53e 92 self->end = len ? start + len - 1 : start;
e4204992 93
6beba7ad 94 pr_debug3("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end);
e4204992 95
0b73da3f 96 memcpy(self->name, name, namelen);
a2928c42
ACM
97
98 return self;
99}
100
00a192b3 101static void symbol__delete(struct symbol *self)
a2928c42 102{
00a192b3 103 free(((void *)self) - symbol__priv_size);
a2928c42
ACM
104}
105
106static size_t symbol__fprintf(struct symbol *self, FILE *fp)
107{
439d473b 108 return fprintf(fp, " %llx-%llx %s\n",
a2928c42
ACM
109 self->start, self->end, self->name);
110}
111
00a192b3 112struct dso *dso__new(const char *name)
a2928c42
ACM
113{
114 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1);
115
116 if (self != NULL) {
117 strcpy(self->name, name);
439d473b
ACM
118 self->long_name = self->name;
119 self->short_name = self->name;
a2928c42 120 self->syms = RB_ROOT;
fc54db51 121 self->find_symbol = dso__find_symbol;
52d422de 122 self->slen_calculated = 0;
94cb9e38 123 self->origin = DSO__ORIG_NOT_FOUND;
6d7aa9d7 124 self->loaded = false;
a2928c42
ACM
125 }
126
127 return self;
128}
129
130static void dso__delete_symbols(struct dso *self)
131{
132 struct symbol *pos;
133 struct rb_node *next = rb_first(&self->syms);
134
135 while (next) {
136 pos = rb_entry(next, struct symbol, rb_node);
137 next = rb_next(&pos->rb_node);
c8c96525 138 rb_erase(&pos->rb_node, &self->syms);
00a192b3 139 symbol__delete(pos);
a2928c42
ACM
140 }
141}
142
143void dso__delete(struct dso *self)
144{
145 dso__delete_symbols(self);
439d473b
ACM
146 if (self->long_name != self->name)
147 free(self->long_name);
a2928c42
ACM
148 free(self);
149}
150
151static void dso__insert_symbol(struct dso *self, struct symbol *sym)
152{
153 struct rb_node **p = &self->syms.rb_node;
154 struct rb_node *parent = NULL;
9cffa8d5 155 const u64 ip = sym->start;
a2928c42
ACM
156 struct symbol *s;
157
158 while (*p != NULL) {
159 parent = *p;
160 s = rb_entry(parent, struct symbol, rb_node);
161 if (ip < s->start)
162 p = &(*p)->rb_left;
163 else
164 p = &(*p)->rb_right;
165 }
166 rb_link_node(&sym->rb_node, parent, p);
167 rb_insert_color(&sym->rb_node, &self->syms);
168}
169
9cffa8d5 170struct symbol *dso__find_symbol(struct dso *self, u64 ip)
a2928c42
ACM
171{
172 struct rb_node *n;
173
174 if (self == NULL)
175 return NULL;
176
177 n = self->syms.rb_node;
178
179 while (n) {
180 struct symbol *s = rb_entry(n, struct symbol, rb_node);
181
182 if (ip < s->start)
183 n = n->rb_left;
184 else if (ip > s->end)
185 n = n->rb_right;
186 else
187 return s;
188 }
189
190 return NULL;
191}
192
193size_t dso__fprintf(struct dso *self, FILE *fp)
194{
a2a99e8e 195 size_t ret = fprintf(fp, "dso: %s\n", self->short_name);
a2928c42
ACM
196
197 struct rb_node *nd;
198 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
199 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
200 ret += symbol__fprintf(pos, fp);
201 }
202
203 return ret;
204}
205
2e538c4a
ACM
206/*
207 * Loads the function entries in /proc/kallsyms into kernel_map->dso,
208 * so that we can in the next step set the symbol ->end address and then
209 * call kernel_maps__split_kallsyms.
210 */
6beba7ad 211static int kernel_maps__load_all_kallsyms(void)
a2928c42 212{
a2928c42
ACM
213 char *line = NULL;
214 size_t n;
215 FILE *file = fopen("/proc/kallsyms", "r");
216
217 if (file == NULL)
218 goto out_failure;
219
220 while (!feof(file)) {
9cffa8d5 221 u64 start;
a2928c42
ACM
222 struct symbol *sym;
223 int line_len, len;
224 char symbol_type;
2e538c4a 225 char *symbol_name;
a2928c42
ACM
226
227 line_len = getline(&line, &n, file);
228 if (line_len < 0)
229 break;
230
231 if (!line)
232 goto out_failure;
233
234 line[--line_len] = '\0'; /* \n */
235
a0055ae2 236 len = hex2u64(line, &start);
a2928c42
ACM
237
238 len++;
239 if (len + 2 >= line_len)
240 continue;
241
242 symbol_type = toupper(line[len]);
243 /*
244 * We're interested only in code ('T'ext)
245 */
246 if (symbol_type != 'T' && symbol_type != 'W')
247 continue;
af427bf5
ACM
248
249 symbol_name = line + len + 2;
2e538c4a
ACM
250 /*
251 * Will fix up the end later, when we have all symbols sorted.
252 */
00a192b3 253 sym = symbol__new(start, 0, symbol_name);
af427bf5 254
2e538c4a
ACM
255 if (sym == NULL)
256 goto out_delete_line;
257
258 dso__insert_symbol(kernel_map->dso, sym);
259 }
260
261 free(line);
262 fclose(file);
263
264 return 0;
265
266out_delete_line:
267 free(line);
268out_failure:
269 return -1;
270}
271
272/*
273 * Split the symbols into maps, making sure there are no overlaps, i.e. the
274 * kernel range is broken in several maps, named [kernel].N, as we don't have
275 * the original ELF section names vmlinux have.
276 */
277static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules)
278{
279 struct map *map = kernel_map;
280 struct symbol *pos;
281 int count = 0;
282 struct rb_node *next = rb_first(&kernel_map->dso->syms);
283 int kernel_range = 0;
284
285 while (next) {
286 char *module;
287
288 pos = rb_entry(next, struct symbol, rb_node);
289 next = rb_next(&pos->rb_node);
290
291 module = strchr(pos->name, '\t');
292 if (module) {
af427bf5 293 if (!use_modules)
2e538c4a
ACM
294 goto delete_symbol;
295
296 *module++ = '\0';
297
af427bf5
ACM
298 if (strcmp(map->dso->name, module)) {
299 map = kernel_maps__find_by_dso_name(module);
300 if (!map) {
6beba7ad
ACM
301 pr_err("/proc/{kallsyms,modules} "
302 "inconsistency!\n");
af427bf5
ACM
303 return -1;
304 }
305 }
2e538c4a
ACM
306 /*
307 * So that we look just like we get from .ko files,
308 * i.e. not prelinked, relative to map->start.
309 */
310 pos->start = map->map_ip(map, pos->start);
311 pos->end = map->map_ip(map, pos->end);
312 } else if (map != kernel_map) {
313 char dso_name[PATH_MAX];
314 struct dso *dso;
315
316 snprintf(dso_name, sizeof(dso_name), "[kernel].%d",
317 kernel_range++);
318
00a192b3 319 dso = dso__new(dso_name);
2e538c4a
ACM
320 if (dso == NULL)
321 return -1;
322
323 map = map__new2(pos->start, dso);
324 if (map == NULL) {
325 dso__delete(dso);
326 return -1;
327 }
a2928c42 328
ed52ce2e 329 map->map_ip = map->unmap_ip = identity__map_ip;
2e538c4a
ACM
330 kernel_maps__insert(map);
331 ++kernel_range;
332 }
a2928c42 333
2e538c4a
ACM
334 if (filter && filter(map, pos)) {
335delete_symbol:
336 rb_erase(&pos->rb_node, &kernel_map->dso->syms);
00a192b3 337 symbol__delete(pos);
2e538c4a
ACM
338 } else {
339 if (map != kernel_map) {
340 rb_erase(&pos->rb_node, &kernel_map->dso->syms);
341 dso__insert_symbol(map->dso, pos);
342 }
9974f496
MG
343 count++;
344 }
a2928c42
ACM
345 }
346
9974f496 347 return count;
2e538c4a 348}
a2928c42 349
2e538c4a 350
6beba7ad 351static int kernel_maps__load_kallsyms(symbol_filter_t filter, int use_modules)
2e538c4a 352{
6beba7ad 353 if (kernel_maps__load_all_kallsyms())
2e538c4a
ACM
354 return -1;
355
356 dso__fixup_sym_end(kernel_map->dso);
357
358 return kernel_maps__split_kallsyms(filter, use_modules);
a2928c42
ACM
359}
360
6beba7ad 361static size_t kernel_maps__fprintf(FILE *fp)
af427bf5 362{
6beba7ad 363 size_t printed = fprintf(fp, "Kernel maps:\n");
af427bf5
ACM
364 struct rb_node *nd;
365
af427bf5
ACM
366 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
367 struct map *pos = rb_entry(nd, struct map, rb_node);
368
2e538c4a 369 printed += fprintf(fp, "Map:");
af427bf5 370 printed += map__fprintf(pos, fp);
6beba7ad 371 if (verbose > 1) {
2e538c4a
ACM
372 printed += dso__fprintf(pos->dso, fp);
373 printed += fprintf(fp, "--\n");
374 }
af427bf5
ACM
375 }
376
6beba7ad 377 return printed + fprintf(fp, "END kernel maps\n");
af427bf5
ACM
378}
379
439d473b 380static int dso__load_perf_map(struct dso *self, struct map *map,
6beba7ad 381 symbol_filter_t filter)
80d496be
PE
382{
383 char *line = NULL;
384 size_t n;
385 FILE *file;
386 int nr_syms = 0;
387
439d473b 388 file = fopen(self->long_name, "r");
80d496be
PE
389 if (file == NULL)
390 goto out_failure;
391
392 while (!feof(file)) {
9cffa8d5 393 u64 start, size;
80d496be
PE
394 struct symbol *sym;
395 int line_len, len;
396
397 line_len = getline(&line, &n, file);
398 if (line_len < 0)
399 break;
400
401 if (!line)
402 goto out_failure;
403
404 line[--line_len] = '\0'; /* \n */
405
406 len = hex2u64(line, &start);
407
408 len++;
409 if (len + 2 >= line_len)
410 continue;
411
412 len += hex2u64(line + len, &size);
413
414 len++;
415 if (len + 2 >= line_len)
416 continue;
417
00a192b3 418 sym = symbol__new(start, size, line + len);
80d496be
PE
419
420 if (sym == NULL)
421 goto out_delete_line;
422
439d473b 423 if (filter && filter(map, sym))
00a192b3 424 symbol__delete(sym);
80d496be
PE
425 else {
426 dso__insert_symbol(self, sym);
427 nr_syms++;
428 }
429 }
430
431 free(line);
432 fclose(file);
433
434 return nr_syms;
435
436out_delete_line:
437 free(line);
438out_failure:
439 return -1;
440}
441
a2928c42
ACM
442/**
443 * elf_symtab__for_each_symbol - iterate thru all the symbols
444 *
445 * @self: struct elf_symtab instance to iterate
83a0944f 446 * @idx: uint32_t idx
a2928c42
ACM
447 * @sym: GElf_Sym iterator
448 */
83a0944f
IM
449#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
450 for (idx = 0, gelf_getsym(syms, idx, &sym);\
451 idx < nr_syms; \
452 idx++, gelf_getsym(syms, idx, &sym))
a2928c42
ACM
453
454static inline uint8_t elf_sym__type(const GElf_Sym *sym)
455{
456 return GELF_ST_TYPE(sym->st_info);
457}
458
459static inline int elf_sym__is_function(const GElf_Sym *sym)
460{
461 return elf_sym__type(sym) == STT_FUNC &&
462 sym->st_name != 0 &&
81833130 463 sym->st_shndx != SHN_UNDEF;
a2928c42
ACM
464}
465
6cfcc53e
MG
466static inline int elf_sym__is_label(const GElf_Sym *sym)
467{
468 return elf_sym__type(sym) == STT_NOTYPE &&
469 sym->st_name != 0 &&
470 sym->st_shndx != SHN_UNDEF &&
471 sym->st_shndx != SHN_ABS;
472}
473
474static inline const char *elf_sec__name(const GElf_Shdr *shdr,
475 const Elf_Data *secstrs)
476{
477 return secstrs->d_buf + shdr->sh_name;
478}
479
480static inline int elf_sec__is_text(const GElf_Shdr *shdr,
481 const Elf_Data *secstrs)
482{
483 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
484}
485
a2928c42
ACM
486static inline const char *elf_sym__name(const GElf_Sym *sym,
487 const Elf_Data *symstrs)
488{
489 return symstrs->d_buf + sym->st_name;
490}
491
492static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
493 GElf_Shdr *shp, const char *name,
83a0944f 494 size_t *idx)
a2928c42
ACM
495{
496 Elf_Scn *sec = NULL;
497 size_t cnt = 1;
498
499 while ((sec = elf_nextscn(elf, sec)) != NULL) {
500 char *str;
501
502 gelf_getshdr(sec, shp);
503 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
504 if (!strcmp(name, str)) {
83a0944f
IM
505 if (idx)
506 *idx = cnt;
a2928c42
ACM
507 break;
508 }
509 ++cnt;
510 }
511
512 return sec;
513}
514
8ce998d6
ACM
515#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
516 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
517 idx < nr_entries; \
518 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
519
520#define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
521 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
522 idx < nr_entries; \
523 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
524
a25e46c4
ACM
525/*
526 * We need to check if we have a .dynsym, so that we can handle the
527 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
528 * .dynsym or .symtab).
529 * And always look at the original dso, not at debuginfo packages, that
530 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
531 */
6beba7ad 532static int dso__synthesize_plt_symbols(struct dso *self)
8ce998d6
ACM
533{
534 uint32_t nr_rel_entries, idx;
535 GElf_Sym sym;
9cffa8d5 536 u64 plt_offset;
8ce998d6
ACM
537 GElf_Shdr shdr_plt;
538 struct symbol *f;
a25e46c4 539 GElf_Shdr shdr_rel_plt, shdr_dynsym;
8ce998d6 540 Elf_Data *reldata, *syms, *symstrs;
a25e46c4
ACM
541 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
542 size_t dynsym_idx;
543 GElf_Ehdr ehdr;
8ce998d6 544 char sympltname[1024];
a25e46c4
ACM
545 Elf *elf;
546 int nr = 0, symidx, fd, err = 0;
547
439d473b 548 fd = open(self->long_name, O_RDONLY);
a25e46c4
ACM
549 if (fd < 0)
550 goto out;
551
84087126 552 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
a25e46c4
ACM
553 if (elf == NULL)
554 goto out_close;
555
556 if (gelf_getehdr(elf, &ehdr) == NULL)
557 goto out_elf_end;
558
559 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
560 ".dynsym", &dynsym_idx);
561 if (scn_dynsym == NULL)
562 goto out_elf_end;
8ce998d6 563
a25e46c4 564 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
8ce998d6
ACM
565 ".rela.plt", NULL);
566 if (scn_plt_rel == NULL) {
a25e46c4 567 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
8ce998d6
ACM
568 ".rel.plt", NULL);
569 if (scn_plt_rel == NULL)
a25e46c4 570 goto out_elf_end;
8ce998d6
ACM
571 }
572
a25e46c4
ACM
573 err = -1;
574
8ce998d6 575 if (shdr_rel_plt.sh_link != dynsym_idx)
a25e46c4 576 goto out_elf_end;
8ce998d6 577
a25e46c4
ACM
578 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
579 goto out_elf_end;
8ce998d6
ACM
580
581 /*
83a0944f 582 * Fetch the relocation section to find the idxes to the GOT
8ce998d6
ACM
583 * and the symbols in the .dynsym they refer to.
584 */
585 reldata = elf_getdata(scn_plt_rel, NULL);
586 if (reldata == NULL)
a25e46c4 587 goto out_elf_end;
8ce998d6
ACM
588
589 syms = elf_getdata(scn_dynsym, NULL);
590 if (syms == NULL)
a25e46c4 591 goto out_elf_end;
8ce998d6 592
a25e46c4 593 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
8ce998d6 594 if (scn_symstrs == NULL)
a25e46c4 595 goto out_elf_end;
8ce998d6
ACM
596
597 symstrs = elf_getdata(scn_symstrs, NULL);
598 if (symstrs == NULL)
a25e46c4 599 goto out_elf_end;
8ce998d6
ACM
600
601 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
602 plt_offset = shdr_plt.sh_offset;
603
604 if (shdr_rel_plt.sh_type == SHT_RELA) {
605 GElf_Rela pos_mem, *pos;
606
607 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
608 nr_rel_entries) {
609 symidx = GELF_R_SYM(pos->r_info);
610 plt_offset += shdr_plt.sh_entsize;
611 gelf_getsym(syms, symidx, &sym);
612 snprintf(sympltname, sizeof(sympltname),
613 "%s@plt", elf_sym__name(&sym, symstrs));
614
615 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
00a192b3 616 sympltname);
8ce998d6 617 if (!f)
a25e46c4 618 goto out_elf_end;
8ce998d6
ACM
619
620 dso__insert_symbol(self, f);
621 ++nr;
622 }
623 } else if (shdr_rel_plt.sh_type == SHT_REL) {
624 GElf_Rel pos_mem, *pos;
625 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
626 nr_rel_entries) {
627 symidx = GELF_R_SYM(pos->r_info);
628 plt_offset += shdr_plt.sh_entsize;
629 gelf_getsym(syms, symidx, &sym);
630 snprintf(sympltname, sizeof(sympltname),
631 "%s@plt", elf_sym__name(&sym, symstrs));
632
633 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
00a192b3 634 sympltname);
8ce998d6 635 if (!f)
a25e46c4 636 goto out_elf_end;
8ce998d6
ACM
637
638 dso__insert_symbol(self, f);
639 ++nr;
640 }
8ce998d6
ACM
641 }
642
a25e46c4
ACM
643 err = 0;
644out_elf_end:
645 elf_end(elf);
646out_close:
647 close(fd);
648
649 if (err == 0)
650 return nr;
651out:
6beba7ad
ACM
652 pr_warning("%s: problems reading %s PLT info.\n",
653 __func__, self->long_name);
a25e46c4 654 return 0;
8ce998d6
ACM
655}
656
439d473b
ACM
657static int dso__load_sym(struct dso *self, struct map *map, const char *name,
658 int fd, symbol_filter_t filter, int kernel,
6beba7ad 659 int kmodule)
a2928c42 660{
2e538c4a
ACM
661 struct map *curr_map = map;
662 struct dso *curr_dso = self;
663 size_t dso_name_len = strlen(self->short_name);
6cfcc53e 664 Elf_Data *symstrs, *secstrs;
a2928c42
ACM
665 uint32_t nr_syms;
666 int err = -1;
83a0944f 667 uint32_t idx;
a2928c42
ACM
668 GElf_Ehdr ehdr;
669 GElf_Shdr shdr;
670 Elf_Data *syms;
671 GElf_Sym sym;
a25e46c4 672 Elf_Scn *sec, *sec_strndx;
a2928c42 673 Elf *elf;
439d473b 674 int nr = 0;
a2928c42 675
84087126 676 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
a2928c42 677 if (elf == NULL) {
6beba7ad 678 pr_err("%s: cannot read %s ELF file.\n", __func__, name);
a2928c42
ACM
679 goto out_close;
680 }
681
682 if (gelf_getehdr(elf, &ehdr) == NULL) {
6beba7ad 683 pr_err("%s: cannot get elf header.\n", __func__);
a2928c42
ACM
684 goto out_elf_end;
685 }
686
687 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
8ce998d6 688 if (sec == NULL) {
a25e46c4
ACM
689 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
690 if (sec == NULL)
8ce998d6 691 goto out_elf_end;
8ce998d6 692 }
a2928c42
ACM
693
694 syms = elf_getdata(sec, NULL);
695 if (syms == NULL)
696 goto out_elf_end;
697
698 sec = elf_getscn(elf, shdr.sh_link);
699 if (sec == NULL)
700 goto out_elf_end;
701
702 symstrs = elf_getdata(sec, NULL);
703 if (symstrs == NULL)
704 goto out_elf_end;
705
6cfcc53e
MG
706 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
707 if (sec_strndx == NULL)
708 goto out_elf_end;
709
710 secstrs = elf_getdata(sec_strndx, NULL);
9b30a26b 711 if (secstrs == NULL)
6cfcc53e
MG
712 goto out_elf_end;
713
a2928c42
ACM
714 nr_syms = shdr.sh_size / shdr.sh_entsize;
715
e9fbc9dc 716 memset(&sym, 0, sizeof(sym));
d20ff6bd
MG
717 if (!kernel) {
718 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
30d7a77d
ACM
719 elf_section_by_name(elf, &ehdr, &shdr,
720 ".gnu.prelink_undo",
721 NULL) != NULL);
d20ff6bd
MG
722 } else self->adjust_symbols = 0;
723
83a0944f 724 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
a2928c42 725 struct symbol *f;
83a0944f 726 const char *elf_name;
2e538c4a 727 char *demangled = NULL;
6cfcc53e
MG
728 int is_label = elf_sym__is_label(&sym);
729 const char *section_name;
a2928c42 730
6cfcc53e 731 if (!is_label && !elf_sym__is_function(&sym))
a2928c42
ACM
732 continue;
733
734 sec = elf_getscn(elf, sym.st_shndx);
735 if (!sec)
736 goto out_elf_end;
737
738 gelf_getshdr(sec, &shdr);
6cfcc53e
MG
739
740 if (is_label && !elf_sec__is_text(&shdr, secstrs))
741 continue;
742
2e538c4a 743 elf_name = elf_sym__name(&sym, symstrs);
6cfcc53e 744 section_name = elf_sec__name(&shdr, secstrs);
0b73da3f 745
2e538c4a
ACM
746 if (kernel || kmodule) {
747 char dso_name[PATH_MAX];
748
749 if (strcmp(section_name,
750 curr_dso->short_name + dso_name_len) == 0)
751 goto new_symbol;
752
753 if (strcmp(section_name, ".text") == 0) {
754 curr_map = map;
755 curr_dso = self;
756 goto new_symbol;
757 }
758
759 snprintf(dso_name, sizeof(dso_name),
760 "%s%s", self->short_name, section_name);
761
762 curr_map = kernel_maps__find_by_dso_name(dso_name);
763 if (curr_map == NULL) {
764 u64 start = sym.st_value;
765
766 if (kmodule)
767 start += map->start + shdr.sh_offset;
768
00a192b3 769 curr_dso = dso__new(dso_name);
2e538c4a
ACM
770 if (curr_dso == NULL)
771 goto out_elf_end;
772 curr_map = map__new2(start, curr_dso);
773 if (curr_map == NULL) {
774 dso__delete(curr_dso);
775 goto out_elf_end;
776 }
ed52ce2e
ACM
777 curr_map->map_ip = identity__map_ip;
778 curr_map->unmap_ip = identity__map_ip;
2e538c4a
ACM
779 curr_dso->origin = DSO__ORIG_KERNEL;
780 kernel_maps__insert(curr_map);
781 dsos__add(curr_dso);
782 } else
783 curr_dso = curr_map->dso;
784
785 goto new_symbol;
af427bf5
ACM
786 }
787
2e538c4a 788 if (curr_dso->adjust_symbols) {
6beba7ad
ACM
789 pr_debug2("adjusting symbol: st_value: %Lx sh_addr: "
790 "%Lx sh_offset: %Lx\n", (u64)sym.st_value,
791 (u64)shdr.sh_addr, (u64)shdr.sh_offset);
f5812a7a 792 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
af427bf5 793 }
28ac909b
ACM
794 /*
795 * We need to figure out if the object was created from C++ sources
796 * DWARF DW_compile_unit has this, but we don't always have access
797 * to it...
798 */
83a0944f 799 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
28ac909b 800 if (demangled != NULL)
83a0944f 801 elf_name = demangled;
2e538c4a 802new_symbol:
00a192b3 803 f = symbol__new(sym.st_value, sym.st_size, elf_name);
28ac909b 804 free(demangled);
a2928c42
ACM
805 if (!f)
806 goto out_elf_end;
807
2e538c4a 808 if (filter && filter(curr_map, f))
00a192b3 809 symbol__delete(f);
69ee69f6 810 else {
2e538c4a 811 dso__insert_symbol(curr_dso, f);
69ee69f6
ACM
812 nr++;
813 }
a2928c42
ACM
814 }
815
2e538c4a
ACM
816 /*
817 * For misannotated, zeroed, ASM function sizes.
818 */
819 if (nr > 0)
820 dso__fixup_sym_end(self);
a2928c42
ACM
821 err = nr;
822out_elf_end:
823 elf_end(elf);
824out_close:
825 return err;
826}
827
4d1e00a8
ACM
828#define BUILD_ID_SIZE 128
829
6beba7ad 830static char *dso__read_build_id(struct dso *self)
4d1e00a8
ACM
831{
832 int i;
833 GElf_Ehdr ehdr;
834 GElf_Shdr shdr;
835 Elf_Data *build_id_data;
836 Elf_Scn *sec;
837 char *build_id = NULL, *bid;
838 unsigned char *raw;
839 Elf *elf;
439d473b 840 int fd = open(self->long_name, O_RDONLY);
4d1e00a8
ACM
841
842 if (fd < 0)
843 goto out;
844
84087126 845 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
4d1e00a8 846 if (elf == NULL) {
6beba7ad
ACM
847 pr_err("%s: cannot read %s ELF file.\n", __func__,
848 self->long_name);
4d1e00a8
ACM
849 goto out_close;
850 }
851
852 if (gelf_getehdr(elf, &ehdr) == NULL) {
6beba7ad 853 pr_err("%s: cannot get elf header.\n", __func__);
4d1e00a8
ACM
854 goto out_elf_end;
855 }
856
857 sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
858 if (sec == NULL)
859 goto out_elf_end;
860
861 build_id_data = elf_getdata(sec, NULL);
862 if (build_id_data == NULL)
863 goto out_elf_end;
864 build_id = malloc(BUILD_ID_SIZE);
865 if (build_id == NULL)
866 goto out_elf_end;
867 raw = build_id_data->d_buf + 16;
868 bid = build_id;
869
870 for (i = 0; i < 20; ++i) {
871 sprintf(bid, "%02x", *raw);
872 ++raw;
873 bid += 2;
874 }
6beba7ad 875 pr_debug2("%s(%s): %s\n", __func__, self->long_name, build_id);
4d1e00a8
ACM
876out_elf_end:
877 elf_end(elf);
878out_close:
879 close(fd);
880out:
881 return build_id;
882}
883
94cb9e38
ACM
884char dso__symtab_origin(const struct dso *self)
885{
886 static const char origin[] = {
887 [DSO__ORIG_KERNEL] = 'k',
888 [DSO__ORIG_JAVA_JIT] = 'j',
889 [DSO__ORIG_FEDORA] = 'f',
890 [DSO__ORIG_UBUNTU] = 'u',
891 [DSO__ORIG_BUILDID] = 'b',
892 [DSO__ORIG_DSO] = 'd',
439d473b 893 [DSO__ORIG_KMODULE] = 'K',
94cb9e38
ACM
894 };
895
896 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
897 return '!';
898 return origin[self->origin];
899}
900
6beba7ad 901int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
a2928c42 902{
4d1e00a8
ACM
903 int size = PATH_MAX;
904 char *name = malloc(size), *build_id = NULL;
a2928c42
ACM
905 int ret = -1;
906 int fd;
907
66bd8424
ACM
908 self->loaded = true;
909
a2928c42
ACM
910 if (!name)
911 return -1;
912
30d7a77d 913 self->adjust_symbols = 0;
f5812a7a 914
94cb9e38 915 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
6beba7ad 916 ret = dso__load_perf_map(self, map, filter);
94cb9e38
ACM
917 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
918 DSO__ORIG_NOT_FOUND;
919 return ret;
920 }
921
922 self->origin = DSO__ORIG_FEDORA - 1;
80d496be 923
a2928c42
ACM
924more:
925 do {
94cb9e38
ACM
926 self->origin++;
927 switch (self->origin) {
928 case DSO__ORIG_FEDORA:
439d473b
ACM
929 snprintf(name, size, "/usr/lib/debug%s.debug",
930 self->long_name);
a2928c42 931 break;
94cb9e38 932 case DSO__ORIG_UBUNTU:
439d473b
ACM
933 snprintf(name, size, "/usr/lib/debug%s",
934 self->long_name);
a2928c42 935 break;
94cb9e38 936 case DSO__ORIG_BUILDID:
6beba7ad 937 build_id = dso__read_build_id(self);
4d1e00a8
ACM
938 if (build_id != NULL) {
939 snprintf(name, size,
940 "/usr/lib/debug/.build-id/%.2s/%s.debug",
941 build_id, build_id + 2);
942 free(build_id);
943 break;
944 }
94cb9e38 945 self->origin++;
4d1e00a8 946 /* Fall thru */
94cb9e38 947 case DSO__ORIG_DSO:
439d473b 948 snprintf(name, size, "%s", self->long_name);
a2928c42
ACM
949 break;
950
951 default:
952 goto out;
953 }
a2928c42
ACM
954
955 fd = open(name, O_RDONLY);
956 } while (fd < 0);
957
6beba7ad 958 ret = dso__load_sym(self, map, name, fd, filter, 0, 0);
a2928c42
ACM
959 close(fd);
960
961 /*
962 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
963 */
964 if (!ret)
965 goto more;
966
a25e46c4 967 if (ret > 0) {
6beba7ad 968 int nr_plt = dso__synthesize_plt_symbols(self);
a25e46c4
ACM
969 if (nr_plt > 0)
970 ret += nr_plt;
971 }
a2928c42
ACM
972out:
973 free(name);
1340e6bb
ACM
974 if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
975 return 0;
a2928c42
ACM
976 return ret;
977}
978
439d473b
ACM
979struct map *kernel_map;
980
981static void kernel_maps__insert(struct map *map)
6cfcc53e 982{
439d473b
ACM
983 maps__insert(&kernel_maps, map);
984}
6cfcc53e 985
439d473b
ACM
986struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp)
987{
439d473b 988 struct map *map = maps__find(&kernel_maps, ip);
2e538c4a
ACM
989
990 if (mapp)
991 *mapp = map;
439d473b
ACM
992
993 if (map) {
994 ip = map->map_ip(map, ip);
2e538c4a 995 return map->dso->find_symbol(map->dso, ip);
439d473b 996 }
6cfcc53e 997
2e538c4a 998 return NULL;
439d473b
ACM
999}
1000
1001struct map *kernel_maps__find_by_dso_name(const char *name)
1002{
1003 struct rb_node *nd;
1004
1005 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
1006 struct map *map = rb_entry(nd, struct map, rb_node);
1007
1008 if (map->dso && strcmp(map->dso->name, name) == 0)
1009 return map;
1010 }
1011
1012 return NULL;
1013}
1014
1015static int dso__load_module_sym(struct dso *self, struct map *map,
6beba7ad 1016 symbol_filter_t filter)
439d473b
ACM
1017{
1018 int err = 0, fd = open(self->long_name, O_RDONLY);
1019
66bd8424
ACM
1020 self->loaded = true;
1021
439d473b 1022 if (fd < 0) {
6beba7ad 1023 pr_err("%s: cannot open %s\n", __func__, self->long_name);
6cfcc53e 1024 return err;
439d473b 1025 }
6cfcc53e 1026
6beba7ad 1027 err = dso__load_sym(self, map, self->long_name, fd, filter, 0, 1);
6cfcc53e
MG
1028 close(fd);
1029
1030 return err;
1031}
1032
6beba7ad 1033static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter)
6cfcc53e 1034{
439d473b
ACM
1035 struct dirent *dent;
1036 int nr_symbols = 0, err;
1037 DIR *dir = opendir(dirname);
6cfcc53e 1038
439d473b 1039 if (!dir) {
6beba7ad 1040 pr_err("%s: cannot open %s dir\n", __func__, dirname);
439d473b
ACM
1041 return -1;
1042 }
6cfcc53e 1043
439d473b
ACM
1044 while ((dent = readdir(dir)) != NULL) {
1045 char path[PATH_MAX];
1046
1047 if (dent->d_type == DT_DIR) {
1048 if (!strcmp(dent->d_name, ".") ||
1049 !strcmp(dent->d_name, ".."))
1050 continue;
1051
1052 snprintf(path, sizeof(path), "%s/%s",
1053 dirname, dent->d_name);
6beba7ad 1054 err = dsos__load_modules_sym_dir(path, filter);
439d473b
ACM
1055 if (err < 0)
1056 goto failure;
1057 } else {
1058 char *dot = strrchr(dent->d_name, '.'),
1059 dso_name[PATH_MAX];
1060 struct map *map;
1061 struct rb_node *last;
1062
1063 if (dot == NULL || strcmp(dot, ".ko"))
1064 continue;
1065 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
1066 (int)(dot - dent->d_name), dent->d_name);
1067
a2a99e8e 1068 strxfrchar(dso_name, '-', '_');
439d473b
ACM
1069 map = kernel_maps__find_by_dso_name(dso_name);
1070 if (map == NULL)
1071 continue;
1072
1073 snprintf(path, sizeof(path), "%s/%s",
1074 dirname, dent->d_name);
1075
1076 map->dso->long_name = strdup(path);
1077 if (map->dso->long_name == NULL)
1078 goto failure;
1079
6beba7ad 1080 err = dso__load_module_sym(map->dso, map, filter);
439d473b
ACM
1081 if (err < 0)
1082 goto failure;
1083 last = rb_last(&map->dso->syms);
1084 if (last) {
1085 struct symbol *sym;
2e538c4a
ACM
1086 /*
1087 * We do this here as well, even having the
1088 * symbol size found in the symtab because
1089 * misannotated ASM symbols may have the size
1090 * set to zero.
1091 */
1092 dso__fixup_sym_end(map->dso);
1093
439d473b
ACM
1094 sym = rb_entry(last, struct symbol, rb_node);
1095 map->end = map->start + sym->end;
1096 }
1097 }
1098 nr_symbols += err;
1099 }
6cfcc53e 1100
439d473b
ACM
1101 return nr_symbols;
1102failure:
1103 closedir(dir);
1104 return -1;
1105}
6cfcc53e 1106
6beba7ad 1107static int dsos__load_modules_sym(symbol_filter_t filter)
439d473b
ACM
1108{
1109 struct utsname uts;
1110 char modules_path[PATH_MAX];
6cfcc53e 1111
439d473b
ACM
1112 if (uname(&uts) < 0)
1113 return -1;
6cfcc53e 1114
439d473b
ACM
1115 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
1116 uts.release);
6cfcc53e 1117
6beba7ad 1118 return dsos__load_modules_sym_dir(modules_path, filter);
6cfcc53e
MG
1119}
1120
439d473b
ACM
1121/*
1122 * Constructor variant for modules (where we know from /proc/modules where
1123 * they are loaded) and for vmlinux, where only after we load all the
1124 * symbols we'll know where it starts and ends.
1125 */
1126static struct map *map__new2(u64 start, struct dso *dso)
6cfcc53e 1127{
439d473b 1128 struct map *self = malloc(sizeof(*self));
6cfcc53e 1129
439d473b 1130 if (self != NULL) {
439d473b 1131 /*
afb7b4f0 1132 * ->end will be filled after we load all the symbols
439d473b 1133 */
afb7b4f0 1134 map__init(self, start, 0, 0, dso);
439d473b 1135 }
afb7b4f0 1136
439d473b
ACM
1137 return self;
1138}
1139
00a192b3 1140static int dsos__load_modules(void)
439d473b
ACM
1141{
1142 char *line = NULL;
1143 size_t n;
1144 FILE *file = fopen("/proc/modules", "r");
1145 struct map *map;
6cfcc53e 1146
439d473b
ACM
1147 if (file == NULL)
1148 return -1;
6cfcc53e 1149
439d473b
ACM
1150 while (!feof(file)) {
1151 char name[PATH_MAX];
1152 u64 start;
1153 struct dso *dso;
1154 char *sep;
1155 int line_len;
6cfcc53e 1156
439d473b
ACM
1157 line_len = getline(&line, &n, file);
1158 if (line_len < 0)
1159 break;
1160
1161 if (!line)
1162 goto out_failure;
1163
1164 line[--line_len] = '\0'; /* \n */
1165
1166 sep = strrchr(line, 'x');
1167 if (sep == NULL)
1168 continue;
1169
1170 hex2u64(sep + 1, &start);
1171
1172 sep = strchr(line, ' ');
1173 if (sep == NULL)
1174 continue;
1175
1176 *sep = '\0';
1177
1178 snprintf(name, sizeof(name), "[%s]", line);
00a192b3 1179 dso = dso__new(name);
439d473b
ACM
1180
1181 if (dso == NULL)
1182 goto out_delete_line;
1183
1184 map = map__new2(start, dso);
1185 if (map == NULL) {
1186 dso__delete(dso);
1187 goto out_delete_line;
6cfcc53e 1188 }
439d473b
ACM
1189
1190 dso->origin = DSO__ORIG_KMODULE;
1191 kernel_maps__insert(map);
1192 dsos__add(dso);
6cfcc53e 1193 }
439d473b
ACM
1194
1195 free(line);
1196 fclose(file);
1197
af427bf5 1198 return 0;
439d473b
ACM
1199
1200out_delete_line:
1201 free(line);
1202out_failure:
1203 return -1;
6cfcc53e
MG
1204}
1205
439d473b 1206static int dso__load_vmlinux(struct dso *self, struct map *map,
6beba7ad 1207 const char *vmlinux, symbol_filter_t filter)
a2928c42
ACM
1208{
1209 int err, fd = open(vmlinux, O_RDONLY);
1210
66bd8424
ACM
1211 self->loaded = true;
1212
a2928c42
ACM
1213 if (fd < 0)
1214 return -1;
1215
6beba7ad 1216 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0);
6cfcc53e 1217
a2928c42
ACM
1218 close(fd);
1219
1220 return err;
1221}
1222
00a192b3
ACM
1223int dsos__load_kernel(const char *vmlinux, symbol_filter_t filter,
1224 int use_modules)
a827c875
ACM
1225{
1226 int err = -1;
00a192b3 1227 struct dso *dso = dso__new(vmlinux);
439d473b
ACM
1228
1229 if (dso == NULL)
1230 return -1;
1231
1232 dso->short_name = "[kernel]";
1233 kernel_map = map__new2(0, dso);
1234 if (kernel_map == NULL)
1235 goto out_delete_dso;
1236
ed52ce2e 1237 kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip;
a827c875 1238
00a192b3 1239 if (use_modules && dsos__load_modules() < 0) {
6beba7ad
ACM
1240 pr_warning("Failed to load list of modules in use! "
1241 "Continuing...\n");
af427bf5
ACM
1242 use_modules = 0;
1243 }
1244
6cfcc53e 1245 if (vmlinux) {
6beba7ad 1246 err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter);
508c4d08 1247 if (err > 0 && use_modules) {
6beba7ad 1248 int syms = dsos__load_modules_sym(filter);
508c4d08 1249
af427bf5 1250 if (syms < 0)
6beba7ad
ACM
1251 pr_warning("Failed to read module symbols!"
1252 " Continuing...\n");
af427bf5
ACM
1253 else
1254 err += syms;
508c4d08 1255 }
6cfcc53e 1256 }
a827c875 1257
9974f496 1258 if (err <= 0)
6beba7ad 1259 err = kernel_maps__load_kallsyms(filter, use_modules);
439d473b
ACM
1260
1261 if (err > 0) {
1262 struct rb_node *node = rb_first(&dso->syms);
1263 struct symbol *sym = rb_entry(node, struct symbol, rb_node);
a827c875 1264
439d473b
ACM
1265 kernel_map->start = sym->start;
1266 node = rb_last(&dso->syms);
1267 sym = rb_entry(node, struct symbol, rb_node);
1268 kernel_map->end = sym->end;
1269
1270 dso->origin = DSO__ORIG_KERNEL;
2e538c4a 1271 kernel_maps__insert(kernel_map);
439d473b 1272 /*
2e538c4a
ACM
1273 * Now that we have all sorted out, just set the ->end of all
1274 * maps:
439d473b 1275 */
2e538c4a 1276 kernel_maps__fixup_end();
439d473b 1277 dsos__add(dso);
af427bf5 1278
6beba7ad
ACM
1279 if (verbose)
1280 kernel_maps__fprintf(stderr);
439d473b 1281 }
94cb9e38 1282
a827c875 1283 return err;
439d473b
ACM
1284
1285out_delete_dso:
1286 dso__delete(dso);
1287 return -1;
a827c875
ACM
1288}
1289
cd84c2ac 1290LIST_HEAD(dsos);
cd84c2ac 1291struct dso *vdso;
cd84c2ac 1292
83a0944f 1293const char *vmlinux_name = "vmlinux";
cd84c2ac
FW
1294int modules;
1295
1296static void dsos__add(struct dso *dso)
1297{
1298 list_add_tail(&dso->node, &dsos);
1299}
1300
1301static struct dso *dsos__find(const char *name)
1302{
1303 struct dso *pos;
1304
1305 list_for_each_entry(pos, &dsos, node)
1306 if (strcmp(pos->name, name) == 0)
1307 return pos;
1308 return NULL;
1309}
1310
00a192b3 1311struct dso *dsos__findnew(const char *name)
cd84c2ac
FW
1312{
1313 struct dso *dso = dsos__find(name);
cd84c2ac 1314
e4204992 1315 if (!dso) {
00a192b3 1316 dso = dso__new(name);
66bd8424 1317 if (dso != NULL)
e4204992 1318 dsos__add(dso);
66bd8424 1319 }
cd84c2ac
FW
1320
1321 return dso;
cd84c2ac
FW
1322}
1323
1324void dsos__fprintf(FILE *fp)
1325{
1326 struct dso *pos;
1327
1328 list_for_each_entry(pos, &dsos, node)
1329 dso__fprintf(pos, fp);
1330}
1331
00a192b3 1332int load_kernel(symbol_filter_t filter)
cd84c2ac 1333{
00a192b3 1334 if (dsos__load_kernel(vmlinux_name, filter, modules) <= 0)
cd84c2ac
FW
1335 return -1;
1336
00a192b3 1337 vdso = dso__new("[vdso]");
cd84c2ac
FW
1338 if (!vdso)
1339 return -1;
1340
cd84c2ac
FW
1341 dsos__add(vdso);
1342
439d473b 1343 return 0;
cd84c2ac
FW
1344}
1345
00a192b3 1346void symbol__init(unsigned int priv_size)
a2928c42
ACM
1347{
1348 elf_version(EV_CURRENT);
00a192b3 1349 symbol__priv_size = priv_size;
a2928c42 1350}