perf_counter tools: PLT info is stripped in -debuginfo packages
[linux-2.6] / tools / perf / util / symbol.c
1 #include "util.h"
2 #include "../perf.h"
3 #include "string.h"
4 #include "symbol.h"
5
6 #include <libelf.h>
7 #include <gelf.h>
8 #include <elf.h>
9
10 const char *sym_hist_filter;
11
12 static struct symbol *symbol__new(u64 start, u64 len,
13                                   const char *name, unsigned int priv_size,
14                                   u64 obj_start, int verbose)
15 {
16         size_t namelen = strlen(name) + 1;
17         struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
18
19         if (!self)
20                 return NULL;
21
22         if (verbose >= 2)
23                 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n",
24                         (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start);
25
26         self->obj_start= obj_start;
27         self->hist = NULL;
28         self->hist_sum = 0;
29
30         if (sym_hist_filter && !strcmp(name, sym_hist_filter))
31                 self->hist = calloc(sizeof(u64), len);
32
33         if (priv_size) {
34                 memset(self, 0, priv_size);
35                 self = ((void *)self) + priv_size;
36         }
37         self->start = start;
38         self->end   = len ? start + len - 1 : start;
39         memcpy(self->name, name, namelen);
40
41         return self;
42 }
43
44 static void symbol__delete(struct symbol *self, unsigned int priv_size)
45 {
46         free(((void *)self) - priv_size);
47 }
48
49 static size_t symbol__fprintf(struct symbol *self, FILE *fp)
50 {
51         if (!self->module)
52                 return fprintf(fp, " %llx-%llx %s\n",
53                        self->start, self->end, self->name);
54         else
55                 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
56                        self->start, self->end, self->name, self->module->name);
57 }
58
59 struct dso *dso__new(const char *name, unsigned int sym_priv_size)
60 {
61         struct dso *self = malloc(sizeof(*self) + strlen(name) + 1);
62
63         if (self != NULL) {
64                 strcpy(self->name, name);
65                 self->syms = RB_ROOT;
66                 self->sym_priv_size = sym_priv_size;
67                 self->find_symbol = dso__find_symbol;
68                 self->slen_calculated = 0;
69         }
70
71         return self;
72 }
73
74 static void dso__delete_symbols(struct dso *self)
75 {
76         struct symbol *pos;
77         struct rb_node *next = rb_first(&self->syms);
78
79         while (next) {
80                 pos = rb_entry(next, struct symbol, rb_node);
81                 next = rb_next(&pos->rb_node);
82                 rb_erase(&pos->rb_node, &self->syms);
83                 symbol__delete(pos, self->sym_priv_size);
84         }
85 }
86
87 void dso__delete(struct dso *self)
88 {
89         dso__delete_symbols(self);
90         free(self);
91 }
92
93 static void dso__insert_symbol(struct dso *self, struct symbol *sym)
94 {
95         struct rb_node **p = &self->syms.rb_node;
96         struct rb_node *parent = NULL;
97         const u64 ip = sym->start;
98         struct symbol *s;
99
100         while (*p != NULL) {
101                 parent = *p;
102                 s = rb_entry(parent, struct symbol, rb_node);
103                 if (ip < s->start)
104                         p = &(*p)->rb_left;
105                 else
106                         p = &(*p)->rb_right;
107         }
108         rb_link_node(&sym->rb_node, parent, p);
109         rb_insert_color(&sym->rb_node, &self->syms);
110 }
111
112 struct symbol *dso__find_symbol(struct dso *self, u64 ip)
113 {
114         struct rb_node *n;
115
116         if (self == NULL)
117                 return NULL;
118
119         n = self->syms.rb_node;
120
121         while (n) {
122                 struct symbol *s = rb_entry(n, struct symbol, rb_node);
123
124                 if (ip < s->start)
125                         n = n->rb_left;
126                 else if (ip > s->end)
127                         n = n->rb_right;
128                 else
129                         return s;
130         }
131
132         return NULL;
133 }
134
135 size_t dso__fprintf(struct dso *self, FILE *fp)
136 {
137         size_t ret = fprintf(fp, "dso: %s\n", self->name);
138
139         struct rb_node *nd;
140         for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
141                 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
142                 ret += symbol__fprintf(pos, fp);
143         }
144
145         return ret;
146 }
147
148 static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose)
149 {
150         struct rb_node *nd, *prevnd;
151         char *line = NULL;
152         size_t n;
153         FILE *file = fopen("/proc/kallsyms", "r");
154         int count = 0;
155
156         if (file == NULL)
157                 goto out_failure;
158
159         while (!feof(file)) {
160                 u64 start;
161                 struct symbol *sym;
162                 int line_len, len;
163                 char symbol_type;
164
165                 line_len = getline(&line, &n, file);
166                 if (line_len < 0)
167                         break;
168
169                 if (!line)
170                         goto out_failure;
171
172                 line[--line_len] = '\0'; /* \n */
173
174                 len = hex2u64(line, &start);
175
176                 len++;
177                 if (len + 2 >= line_len)
178                         continue;
179
180                 symbol_type = toupper(line[len]);
181                 /*
182                  * We're interested only in code ('T'ext)
183                  */
184                 if (symbol_type != 'T' && symbol_type != 'W')
185                         continue;
186                 /*
187                  * Well fix up the end later, when we have all sorted.
188                  */
189                 sym = symbol__new(start, 0xdead, line + len + 2,
190                                   self->sym_priv_size, 0, verbose);
191
192                 if (sym == NULL)
193                         goto out_delete_line;
194
195                 if (filter && filter(self, sym))
196                         symbol__delete(sym, self->sym_priv_size);
197                 else {
198                         dso__insert_symbol(self, sym);
199                         count++;
200                 }
201         }
202
203         /*
204          * Now that we have all sorted out, just set the ->end of all
205          * symbols
206          */
207         prevnd = rb_first(&self->syms);
208
209         if (prevnd == NULL)
210                 goto out_delete_line;
211
212         for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
213                 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
214                               *curr = rb_entry(nd, struct symbol, rb_node);
215
216                 prev->end = curr->start - 1;
217                 prevnd = nd;
218         }
219
220         free(line);
221         fclose(file);
222
223         return count;
224
225 out_delete_line:
226         free(line);
227 out_failure:
228         return -1;
229 }
230
231 static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose)
232 {
233         char *line = NULL;
234         size_t n;
235         FILE *file;
236         int nr_syms = 0;
237
238         file = fopen(self->name, "r");
239         if (file == NULL)
240                 goto out_failure;
241
242         while (!feof(file)) {
243                 u64 start, size;
244                 struct symbol *sym;
245                 int line_len, len;
246
247                 line_len = getline(&line, &n, file);
248                 if (line_len < 0)
249                         break;
250
251                 if (!line)
252                         goto out_failure;
253
254                 line[--line_len] = '\0'; /* \n */
255
256                 len = hex2u64(line, &start);
257
258                 len++;
259                 if (len + 2 >= line_len)
260                         continue;
261
262                 len += hex2u64(line + len, &size);
263
264                 len++;
265                 if (len + 2 >= line_len)
266                         continue;
267
268                 sym = symbol__new(start, size, line + len,
269                                   self->sym_priv_size, start, verbose);
270
271                 if (sym == NULL)
272                         goto out_delete_line;
273
274                 if (filter && filter(self, sym))
275                         symbol__delete(sym, self->sym_priv_size);
276                 else {
277                         dso__insert_symbol(self, sym);
278                         nr_syms++;
279                 }
280         }
281
282         free(line);
283         fclose(file);
284
285         return nr_syms;
286
287 out_delete_line:
288         free(line);
289 out_failure:
290         return -1;
291 }
292
293 /**
294  * elf_symtab__for_each_symbol - iterate thru all the symbols
295  *
296  * @self: struct elf_symtab instance to iterate
297  * @index: uint32_t index
298  * @sym: GElf_Sym iterator
299  */
300 #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \
301         for (index = 0, gelf_getsym(syms, index, &sym);\
302              index < nr_syms; \
303              index++, gelf_getsym(syms, index, &sym))
304
305 static inline uint8_t elf_sym__type(const GElf_Sym *sym)
306 {
307         return GELF_ST_TYPE(sym->st_info);
308 }
309
310 static inline int elf_sym__is_function(const GElf_Sym *sym)
311 {
312         return elf_sym__type(sym) == STT_FUNC &&
313                sym->st_name != 0 &&
314                sym->st_shndx != SHN_UNDEF &&
315                sym->st_size != 0;
316 }
317
318 static inline int elf_sym__is_label(const GElf_Sym *sym)
319 {
320         return elf_sym__type(sym) == STT_NOTYPE &&
321                 sym->st_name != 0 &&
322                 sym->st_shndx != SHN_UNDEF &&
323                 sym->st_shndx != SHN_ABS;
324 }
325
326 static inline const char *elf_sec__name(const GElf_Shdr *shdr,
327                                         const Elf_Data *secstrs)
328 {
329         return secstrs->d_buf + shdr->sh_name;
330 }
331
332 static inline int elf_sec__is_text(const GElf_Shdr *shdr,
333                                         const Elf_Data *secstrs)
334 {
335         return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
336 }
337
338 static inline const char *elf_sym__name(const GElf_Sym *sym,
339                                         const Elf_Data *symstrs)
340 {
341         return symstrs->d_buf + sym->st_name;
342 }
343
344 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
345                                     GElf_Shdr *shp, const char *name,
346                                     size_t *index)
347 {
348         Elf_Scn *sec = NULL;
349         size_t cnt = 1;
350
351         while ((sec = elf_nextscn(elf, sec)) != NULL) {
352                 char *str;
353
354                 gelf_getshdr(sec, shp);
355                 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
356                 if (!strcmp(name, str)) {
357                         if (index)
358                                 *index = cnt;
359                         break;
360                 }
361                 ++cnt;
362         }
363
364         return sec;
365 }
366
367 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
368         for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
369              idx < nr_entries; \
370              ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
371
372 #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
373         for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
374              idx < nr_entries; \
375              ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
376
377 /*
378  * We need to check if we have a .dynsym, so that we can handle the
379  * .plt, synthesizing its symbols, that aren't on the symtabs (be it
380  * .dynsym or .symtab).
381  * And always look at the original dso, not at debuginfo packages, that
382  * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
383  */
384 static int dso__synthesize_plt_symbols(struct  dso *self, int verbose)
385 {
386         uint32_t nr_rel_entries, idx;
387         GElf_Sym sym;
388         u64 plt_offset;
389         GElf_Shdr shdr_plt;
390         struct symbol *f;
391         GElf_Shdr shdr_rel_plt, shdr_dynsym;
392         Elf_Data *reldata, *syms, *symstrs;
393         Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
394         size_t dynsym_idx;
395         GElf_Ehdr ehdr;
396         char sympltname[1024];
397         Elf *elf;
398         int nr = 0, symidx, fd, err = 0;
399
400         fd = open(self->name, O_RDONLY);
401         if (fd < 0)
402                 goto out;
403
404         elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
405         if (elf == NULL)
406                 goto out_close;
407
408         if (gelf_getehdr(elf, &ehdr) == NULL)
409                 goto out_elf_end;
410
411         scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
412                                          ".dynsym", &dynsym_idx);
413         if (scn_dynsym == NULL)
414                 goto out_elf_end;
415
416         scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
417                                           ".rela.plt", NULL);
418         if (scn_plt_rel == NULL) {
419                 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
420                                                   ".rel.plt", NULL);
421                 if (scn_plt_rel == NULL)
422                         goto out_elf_end;
423         }
424
425         err = -1;
426
427         if (shdr_rel_plt.sh_link != dynsym_idx)
428                 goto out_elf_end;
429
430         if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
431                 goto out_elf_end;
432
433         /*
434          * Fetch the relocation section to find the indexes to the GOT
435          * and the symbols in the .dynsym they refer to.
436          */
437         reldata = elf_getdata(scn_plt_rel, NULL);
438         if (reldata == NULL)
439                 goto out_elf_end;
440
441         syms = elf_getdata(scn_dynsym, NULL);
442         if (syms == NULL)
443                 goto out_elf_end;
444
445         scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
446         if (scn_symstrs == NULL)
447                 goto out_elf_end;
448
449         symstrs = elf_getdata(scn_symstrs, NULL);
450         if (symstrs == NULL)
451                 goto out_elf_end;
452
453         nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
454         plt_offset = shdr_plt.sh_offset;
455
456         if (shdr_rel_plt.sh_type == SHT_RELA) {
457                 GElf_Rela pos_mem, *pos;
458
459                 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
460                                            nr_rel_entries) {
461                         symidx = GELF_R_SYM(pos->r_info);
462                         plt_offset += shdr_plt.sh_entsize;
463                         gelf_getsym(syms, symidx, &sym);
464                         snprintf(sympltname, sizeof(sympltname),
465                                  "%s@plt", elf_sym__name(&sym, symstrs));
466
467                         f = symbol__new(plt_offset, shdr_plt.sh_entsize,
468                                         sympltname, self->sym_priv_size, 0, verbose);
469                         if (!f)
470                                 goto out_elf_end;
471
472                         dso__insert_symbol(self, f);
473                         ++nr;
474                 }
475         } else if (shdr_rel_plt.sh_type == SHT_REL) {
476                 GElf_Rel pos_mem, *pos;
477                 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
478                                           nr_rel_entries) {
479                         symidx = GELF_R_SYM(pos->r_info);
480                         plt_offset += shdr_plt.sh_entsize;
481                         gelf_getsym(syms, symidx, &sym);
482                         snprintf(sympltname, sizeof(sympltname),
483                                  "%s@plt", elf_sym__name(&sym, symstrs));
484
485                         f = symbol__new(plt_offset, shdr_plt.sh_entsize,
486                                         sympltname, self->sym_priv_size, 0, verbose);
487                         if (!f)
488                                 goto out_elf_end;
489
490                         dso__insert_symbol(self, f);
491                         ++nr;
492                 }
493         }
494
495         err = 0;
496 out_elf_end:
497         elf_end(elf);
498 out_close:
499         close(fd);
500
501         if (err == 0)
502                 return nr;
503 out:
504         fprintf(stderr, "%s: problems reading %s PLT info.\n",
505                 __func__, self->name);
506         return 0;
507 }
508
509 static int dso__load_sym(struct dso *self, int fd, const char *name,
510                          symbol_filter_t filter, int verbose, struct module *mod)
511 {
512         Elf_Data *symstrs, *secstrs;
513         uint32_t nr_syms;
514         int err = -1;
515         uint32_t index;
516         GElf_Ehdr ehdr;
517         GElf_Shdr shdr;
518         Elf_Data *syms;
519         GElf_Sym sym;
520         Elf_Scn *sec, *sec_strndx;
521         Elf *elf;
522         int nr = 0;
523
524         elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
525         if (elf == NULL) {
526                 if (verbose)
527                         fprintf(stderr, "%s: cannot read %s ELF file.\n",
528                                 __func__, name);
529                 goto out_close;
530         }
531
532         if (gelf_getehdr(elf, &ehdr) == NULL) {
533                 if (verbose)
534                         fprintf(stderr, "%s: cannot get elf header.\n", __func__);
535                 goto out_elf_end;
536         }
537
538         sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
539         if (sec == NULL) {
540                 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
541                 if (sec == NULL)
542                         goto out_elf_end;
543         }
544
545         syms = elf_getdata(sec, NULL);
546         if (syms == NULL)
547                 goto out_elf_end;
548
549         sec = elf_getscn(elf, shdr.sh_link);
550         if (sec == NULL)
551                 goto out_elf_end;
552
553         symstrs = elf_getdata(sec, NULL);
554         if (symstrs == NULL)
555                 goto out_elf_end;
556
557         sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
558         if (sec_strndx == NULL)
559                 goto out_elf_end;
560
561         secstrs = elf_getdata(sec_strndx, NULL);
562         if (symstrs == NULL)
563                 goto out_elf_end;
564
565         nr_syms = shdr.sh_size / shdr.sh_entsize;
566
567         memset(&sym, 0, sizeof(sym));
568         self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
569                                 elf_section_by_name(elf, &ehdr, &shdr,
570                                                      ".gnu.prelink_undo",
571                                                      NULL) != NULL);
572         elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
573                 struct symbol *f;
574                 u64 obj_start;
575                 struct section *section = NULL;
576                 int is_label = elf_sym__is_label(&sym);
577                 const char *section_name;
578
579                 if (!is_label && !elf_sym__is_function(&sym))
580                         continue;
581
582                 sec = elf_getscn(elf, sym.st_shndx);
583                 if (!sec)
584                         goto out_elf_end;
585
586                 gelf_getshdr(sec, &shdr);
587
588                 if (is_label && !elf_sec__is_text(&shdr, secstrs))
589                         continue;
590
591                 section_name = elf_sec__name(&shdr, secstrs);
592                 obj_start = sym.st_value;
593
594                 if (self->adjust_symbols) {
595                         if (verbose >= 2)
596                                 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
597                                         (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
598
599                         sym.st_value -= shdr.sh_addr - shdr.sh_offset;
600                 }
601
602                 if (mod) {
603                         section = mod->sections->find_section(mod->sections, section_name);
604                         if (section)
605                                 sym.st_value += section->vma;
606                         else {
607                                 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
608                                         mod->name, section_name);
609                                 goto out_elf_end;
610                         }
611                 }
612
613                 f = symbol__new(sym.st_value, sym.st_size,
614                                 elf_sym__name(&sym, symstrs),
615                                 self->sym_priv_size, obj_start, verbose);
616                 if (!f)
617                         goto out_elf_end;
618
619                 if (filter && filter(self, f))
620                         symbol__delete(f, self->sym_priv_size);
621                 else {
622                         f->module = mod;
623                         dso__insert_symbol(self, f);
624                         nr++;
625                 }
626         }
627
628         err = nr;
629 out_elf_end:
630         elf_end(elf);
631 out_close:
632         return err;
633 }
634
635 int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
636 {
637         int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
638         char *name = malloc(size);
639         int variant = 0;
640         int ret = -1;
641         int fd;
642
643         if (!name)
644                 return -1;
645
646         self->adjust_symbols = 0;
647
648         if (strncmp(self->name, "/tmp/perf-", 10) == 0)
649                 return dso__load_perf_map(self, filter, verbose);
650
651 more:
652         do {
653                 switch (variant) {
654                 case 0: /* Fedora */
655                         snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
656                         break;
657                 case 1: /* Ubuntu */
658                         snprintf(name, size, "/usr/lib/debug%s", self->name);
659                         break;
660                 case 2: /* Sane people */
661                         snprintf(name, size, "%s", self->name);
662                         break;
663
664                 default:
665                         goto out;
666                 }
667                 variant++;
668
669                 fd = open(name, O_RDONLY);
670         } while (fd < 0);
671
672         ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
673         close(fd);
674
675         /*
676          * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
677          */
678         if (!ret)
679                 goto more;
680
681         if (ret > 0) {
682                 int nr_plt = dso__synthesize_plt_symbols(self, verbose);
683                 if (nr_plt > 0)
684                         ret += nr_plt;
685         }
686 out:
687         free(name);
688         return ret;
689 }
690
691 static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
692                              symbol_filter_t filter, int verbose)
693 {
694         struct module *mod = mod_dso__find_module(mods, name);
695         int err = 0, fd;
696
697         if (mod == NULL || !mod->active)
698                 return err;
699
700         fd = open(mod->path, O_RDONLY);
701
702         if (fd < 0)
703                 return err;
704
705         err = dso__load_sym(self, fd, name, filter, verbose, mod);
706         close(fd);
707
708         return err;
709 }
710
711 int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
712 {
713         struct mod_dso *mods = mod_dso__new_dso("modules");
714         struct module *pos;
715         struct rb_node *next;
716         int err;
717
718         err = mod_dso__load_modules(mods);
719
720         if (err <= 0)
721                 return err;
722
723         /*
724          * Iterate over modules, and load active symbols.
725          */
726         next = rb_first(&mods->mods);
727         while (next) {
728                 pos = rb_entry(next, struct module, rb_node);
729                 err = dso__load_module(self, mods, pos->name, filter, verbose);
730
731                 if (err < 0)
732                         break;
733
734                 next = rb_next(&pos->rb_node);
735         }
736
737         if (err < 0) {
738                 mod_dso__delete_modules(mods);
739                 mod_dso__delete_self(mods);
740         }
741
742         return err;
743 }
744
745 static inline void dso__fill_symbol_holes(struct dso *self)
746 {
747         struct symbol *prev = NULL;
748         struct rb_node *nd;
749
750         for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
751                 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
752
753                 if (prev) {
754                         u64 hole = 0;
755                         int alias = pos->start == prev->start;
756
757                         if (!alias)
758                                 hole = prev->start - pos->end - 1;
759
760                         if (hole || alias) {
761                                 if (alias)
762                                         pos->end = prev->end;
763                                 else if (hole)
764                                         pos->end = prev->start - 1;
765                         }
766                 }
767                 prev = pos;
768         }
769 }
770
771 static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
772                              symbol_filter_t filter, int verbose)
773 {
774         int err, fd = open(vmlinux, O_RDONLY);
775
776         if (fd < 0)
777                 return -1;
778
779         err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
780
781         if (err > 0)
782                 dso__fill_symbol_holes(self);
783
784         close(fd);
785
786         return err;
787 }
788
789 int dso__load_kernel(struct dso *self, const char *vmlinux,
790                      symbol_filter_t filter, int verbose, int modules)
791 {
792         int err = -1;
793
794         if (vmlinux) {
795                 err = dso__load_vmlinux(self, vmlinux, filter, verbose);
796                 if (err > 0 && modules)
797                         err = dso__load_modules(self, filter, verbose);
798         }
799
800         if (err <= 0)
801                 err = dso__load_kallsyms(self, filter, verbose);
802
803         return err;
804 }
805
806 void symbol__init(void)
807 {
808         elf_version(EV_CURRENT);
809 }