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