a9a194d49c1b5f7b9b89752bda997c9c36ae72f2
[cascardo/linux.git] / tools / perf / util / symbol-elf.c
1 #include <libelf.h>
2 #include <gelf.h>
3 #include <elf.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <inttypes.h>
10
11 #include "symbol.h"
12 #include "debug.h"
13
14 #ifndef NT_GNU_BUILD_ID
15 #define NT_GNU_BUILD_ID 3
16 #endif
17
18 /**
19  * elf_symtab__for_each_symbol - iterate thru all the symbols
20  *
21  * @syms: struct elf_symtab instance to iterate
22  * @idx: uint32_t idx
23  * @sym: GElf_Sym iterator
24  */
25 #define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
26         for (idx = 0, gelf_getsym(syms, idx, &sym);\
27              idx < nr_syms; \
28              idx++, gelf_getsym(syms, idx, &sym))
29
30 static inline uint8_t elf_sym__type(const GElf_Sym *sym)
31 {
32         return GELF_ST_TYPE(sym->st_info);
33 }
34
35 static inline int elf_sym__is_function(const GElf_Sym *sym)
36 {
37         return elf_sym__type(sym) == STT_FUNC &&
38                sym->st_name != 0 &&
39                sym->st_shndx != SHN_UNDEF;
40 }
41
42 static inline bool elf_sym__is_object(const GElf_Sym *sym)
43 {
44         return elf_sym__type(sym) == STT_OBJECT &&
45                 sym->st_name != 0 &&
46                 sym->st_shndx != SHN_UNDEF;
47 }
48
49 static inline int elf_sym__is_label(const GElf_Sym *sym)
50 {
51         return elf_sym__type(sym) == STT_NOTYPE &&
52                 sym->st_name != 0 &&
53                 sym->st_shndx != SHN_UNDEF &&
54                 sym->st_shndx != SHN_ABS;
55 }
56
57 static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type)
58 {
59         switch (type) {
60         case MAP__FUNCTION:
61                 return elf_sym__is_function(sym);
62         case MAP__VARIABLE:
63                 return elf_sym__is_object(sym);
64         default:
65                 return false;
66         }
67 }
68
69 static inline const char *elf_sym__name(const GElf_Sym *sym,
70                                         const Elf_Data *symstrs)
71 {
72         return symstrs->d_buf + sym->st_name;
73 }
74
75 static inline const char *elf_sec__name(const GElf_Shdr *shdr,
76                                         const Elf_Data *secstrs)
77 {
78         return secstrs->d_buf + shdr->sh_name;
79 }
80
81 static inline int elf_sec__is_text(const GElf_Shdr *shdr,
82                                         const Elf_Data *secstrs)
83 {
84         return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
85 }
86
87 static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
88                                     const Elf_Data *secstrs)
89 {
90         return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
91 }
92
93 static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs,
94                           enum map_type type)
95 {
96         switch (type) {
97         case MAP__FUNCTION:
98                 return elf_sec__is_text(shdr, secstrs);
99         case MAP__VARIABLE:
100                 return elf_sec__is_data(shdr, secstrs);
101         default:
102                 return false;
103         }
104 }
105
106 static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
107 {
108         Elf_Scn *sec = NULL;
109         GElf_Shdr shdr;
110         size_t cnt = 1;
111
112         while ((sec = elf_nextscn(elf, sec)) != NULL) {
113                 gelf_getshdr(sec, &shdr);
114
115                 if ((addr >= shdr.sh_addr) &&
116                     (addr < (shdr.sh_addr + shdr.sh_size)))
117                         return cnt;
118
119                 ++cnt;
120         }
121
122         return -1;
123 }
124
125 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
126                                     GElf_Shdr *shp, const char *name,
127                                     size_t *idx)
128 {
129         Elf_Scn *sec = NULL;
130         size_t cnt = 1;
131
132         /* Elf is corrupted/truncated, avoid calling elf_strptr. */
133         if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL))
134                 return NULL;
135
136         while ((sec = elf_nextscn(elf, sec)) != NULL) {
137                 char *str;
138
139                 gelf_getshdr(sec, shp);
140                 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
141                 if (!strcmp(name, str)) {
142                         if (idx)
143                                 *idx = cnt;
144                         break;
145                 }
146                 ++cnt;
147         }
148
149         return sec;
150 }
151
152 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
153         for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
154              idx < nr_entries; \
155              ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
156
157 #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
158         for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
159              idx < nr_entries; \
160              ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
161
162 /*
163  * We need to check if we have a .dynsym, so that we can handle the
164  * .plt, synthesizing its symbols, that aren't on the symtabs (be it
165  * .dynsym or .symtab).
166  * And always look at the original dso, not at debuginfo packages, that
167  * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
168  */
169 int dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map,
170                                 symbol_filter_t filter)
171 {
172         uint32_t nr_rel_entries, idx;
173         GElf_Sym sym;
174         u64 plt_offset;
175         GElf_Shdr shdr_plt;
176         struct symbol *f;
177         GElf_Shdr shdr_rel_plt, shdr_dynsym;
178         Elf_Data *reldata, *syms, *symstrs;
179         Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
180         size_t dynsym_idx;
181         GElf_Ehdr ehdr;
182         char sympltname[1024];
183         Elf *elf;
184         int nr = 0, symidx, fd, err = 0;
185
186         fd = open(name, O_RDONLY);
187         if (fd < 0)
188                 goto out;
189
190         elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
191         if (elf == NULL)
192                 goto out_close;
193
194         if (gelf_getehdr(elf, &ehdr) == NULL)
195                 goto out_elf_end;
196
197         scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
198                                          ".dynsym", &dynsym_idx);
199         if (scn_dynsym == NULL)
200                 goto out_elf_end;
201
202         scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
203                                           ".rela.plt", NULL);
204         if (scn_plt_rel == NULL) {
205                 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
206                                                   ".rel.plt", NULL);
207                 if (scn_plt_rel == NULL)
208                         goto out_elf_end;
209         }
210
211         err = -1;
212
213         if (shdr_rel_plt.sh_link != dynsym_idx)
214                 goto out_elf_end;
215
216         if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
217                 goto out_elf_end;
218
219         /*
220          * Fetch the relocation section to find the idxes to the GOT
221          * and the symbols in the .dynsym they refer to.
222          */
223         reldata = elf_getdata(scn_plt_rel, NULL);
224         if (reldata == NULL)
225                 goto out_elf_end;
226
227         syms = elf_getdata(scn_dynsym, NULL);
228         if (syms == NULL)
229                 goto out_elf_end;
230
231         scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
232         if (scn_symstrs == NULL)
233                 goto out_elf_end;
234
235         symstrs = elf_getdata(scn_symstrs, NULL);
236         if (symstrs == NULL)
237                 goto out_elf_end;
238
239         if (symstrs->d_size == 0)
240                 goto out_elf_end;
241
242         nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
243         plt_offset = shdr_plt.sh_offset;
244
245         if (shdr_rel_plt.sh_type == SHT_RELA) {
246                 GElf_Rela pos_mem, *pos;
247
248                 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
249                                            nr_rel_entries) {
250                         symidx = GELF_R_SYM(pos->r_info);
251                         plt_offset += shdr_plt.sh_entsize;
252                         gelf_getsym(syms, symidx, &sym);
253                         snprintf(sympltname, sizeof(sympltname),
254                                  "%s@plt", elf_sym__name(&sym, symstrs));
255
256                         f = symbol__new(plt_offset, shdr_plt.sh_entsize,
257                                         STB_GLOBAL, sympltname);
258                         if (!f)
259                                 goto out_elf_end;
260
261                         if (filter && filter(map, f))
262                                 symbol__delete(f);
263                         else {
264                                 symbols__insert(&dso->symbols[map->type], f);
265                                 ++nr;
266                         }
267                 }
268         } else if (shdr_rel_plt.sh_type == SHT_REL) {
269                 GElf_Rel pos_mem, *pos;
270                 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
271                                           nr_rel_entries) {
272                         symidx = GELF_R_SYM(pos->r_info);
273                         plt_offset += shdr_plt.sh_entsize;
274                         gelf_getsym(syms, symidx, &sym);
275                         snprintf(sympltname, sizeof(sympltname),
276                                  "%s@plt", elf_sym__name(&sym, symstrs));
277
278                         f = symbol__new(plt_offset, shdr_plt.sh_entsize,
279                                         STB_GLOBAL, sympltname);
280                         if (!f)
281                                 goto out_elf_end;
282
283                         if (filter && filter(map, f))
284                                 symbol__delete(f);
285                         else {
286                                 symbols__insert(&dso->symbols[map->type], f);
287                                 ++nr;
288                         }
289                 }
290         }
291
292         err = 0;
293 out_elf_end:
294         elf_end(elf);
295 out_close:
296         close(fd);
297
298         if (err == 0)
299                 return nr;
300 out:
301         pr_debug("%s: problems reading %s PLT info.\n",
302                  __func__, dso->long_name);
303         return 0;
304 }
305
306 /*
307  * Align offset to 4 bytes as needed for note name and descriptor data.
308  */
309 #define NOTE_ALIGN(n) (((n) + 3) & -4U)
310
311 static int elf_read_build_id(Elf *elf, void *bf, size_t size)
312 {
313         int err = -1;
314         GElf_Ehdr ehdr;
315         GElf_Shdr shdr;
316         Elf_Data *data;
317         Elf_Scn *sec;
318         Elf_Kind ek;
319         void *ptr;
320
321         if (size < BUILD_ID_SIZE)
322                 goto out;
323
324         ek = elf_kind(elf);
325         if (ek != ELF_K_ELF)
326                 goto out;
327
328         if (gelf_getehdr(elf, &ehdr) == NULL) {
329                 pr_err("%s: cannot get elf header.\n", __func__);
330                 goto out;
331         }
332
333         /*
334          * Check following sections for notes:
335          *   '.note.gnu.build-id'
336          *   '.notes'
337          *   '.note' (VDSO specific)
338          */
339         do {
340                 sec = elf_section_by_name(elf, &ehdr, &shdr,
341                                           ".note.gnu.build-id", NULL);
342                 if (sec)
343                         break;
344
345                 sec = elf_section_by_name(elf, &ehdr, &shdr,
346                                           ".notes", NULL);
347                 if (sec)
348                         break;
349
350                 sec = elf_section_by_name(elf, &ehdr, &shdr,
351                                           ".note", NULL);
352                 if (sec)
353                         break;
354
355                 return err;
356
357         } while (0);
358
359         data = elf_getdata(sec, NULL);
360         if (data == NULL)
361                 goto out;
362
363         ptr = data->d_buf;
364         while (ptr < (data->d_buf + data->d_size)) {
365                 GElf_Nhdr *nhdr = ptr;
366                 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
367                        descsz = NOTE_ALIGN(nhdr->n_descsz);
368                 const char *name;
369
370                 ptr += sizeof(*nhdr);
371                 name = ptr;
372                 ptr += namesz;
373                 if (nhdr->n_type == NT_GNU_BUILD_ID &&
374                     nhdr->n_namesz == sizeof("GNU")) {
375                         if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
376                                 size_t sz = min(size, descsz);
377                                 memcpy(bf, ptr, sz);
378                                 memset(bf + sz, 0, size - sz);
379                                 err = descsz;
380                                 break;
381                         }
382                 }
383                 ptr += descsz;
384         }
385
386 out:
387         return err;
388 }
389
390 int filename__read_build_id(const char *filename, void *bf, size_t size)
391 {
392         int fd, err = -1;
393         Elf *elf;
394
395         if (size < BUILD_ID_SIZE)
396                 goto out;
397
398         fd = open(filename, O_RDONLY);
399         if (fd < 0)
400                 goto out;
401
402         elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
403         if (elf == NULL) {
404                 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
405                 goto out_close;
406         }
407
408         err = elf_read_build_id(elf, bf, size);
409
410         elf_end(elf);
411 out_close:
412         close(fd);
413 out:
414         return err;
415 }
416
417 int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
418 {
419         int fd, err = -1;
420
421         if (size < BUILD_ID_SIZE)
422                 goto out;
423
424         fd = open(filename, O_RDONLY);
425         if (fd < 0)
426                 goto out;
427
428         while (1) {
429                 char bf[BUFSIZ];
430                 GElf_Nhdr nhdr;
431                 size_t namesz, descsz;
432
433                 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
434                         break;
435
436                 namesz = NOTE_ALIGN(nhdr.n_namesz);
437                 descsz = NOTE_ALIGN(nhdr.n_descsz);
438                 if (nhdr.n_type == NT_GNU_BUILD_ID &&
439                     nhdr.n_namesz == sizeof("GNU")) {
440                         if (read(fd, bf, namesz) != (ssize_t)namesz)
441                                 break;
442                         if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
443                                 size_t sz = min(descsz, size);
444                                 if (read(fd, build_id, sz) == (ssize_t)sz) {
445                                         memset(build_id + sz, 0, size - sz);
446                                         err = 0;
447                                         break;
448                                 }
449                         } else if (read(fd, bf, descsz) != (ssize_t)descsz)
450                                 break;
451                 } else {
452                         int n = namesz + descsz;
453                         if (read(fd, bf, n) != n)
454                                 break;
455                 }
456         }
457         close(fd);
458 out:
459         return err;
460 }
461
462 int filename__read_debuglink(const char *filename, char *debuglink,
463                              size_t size)
464 {
465         int fd, err = -1;
466         Elf *elf;
467         GElf_Ehdr ehdr;
468         GElf_Shdr shdr;
469         Elf_Data *data;
470         Elf_Scn *sec;
471         Elf_Kind ek;
472
473         fd = open(filename, O_RDONLY);
474         if (fd < 0)
475                 goto out;
476
477         elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
478         if (elf == NULL) {
479                 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
480                 goto out_close;
481         }
482
483         ek = elf_kind(elf);
484         if (ek != ELF_K_ELF)
485                 goto out_close;
486
487         if (gelf_getehdr(elf, &ehdr) == NULL) {
488                 pr_err("%s: cannot get elf header.\n", __func__);
489                 goto out_close;
490         }
491
492         sec = elf_section_by_name(elf, &ehdr, &shdr,
493                                   ".gnu_debuglink", NULL);
494         if (sec == NULL)
495                 goto out_close;
496
497         data = elf_getdata(sec, NULL);
498         if (data == NULL)
499                 goto out_close;
500
501         /* the start of this section is a zero-terminated string */
502         strncpy(debuglink, data->d_buf, size);
503
504         elf_end(elf);
505
506 out_close:
507         close(fd);
508 out:
509         return err;
510 }
511
512 static int dso__swap_init(struct dso *dso, unsigned char eidata)
513 {
514         static unsigned int const endian = 1;
515
516         dso->needs_swap = DSO_SWAP__NO;
517
518         switch (eidata) {
519         case ELFDATA2LSB:
520                 /* We are big endian, DSO is little endian. */
521                 if (*(unsigned char const *)&endian != 1)
522                         dso->needs_swap = DSO_SWAP__YES;
523                 break;
524
525         case ELFDATA2MSB:
526                 /* We are little endian, DSO is big endian. */
527                 if (*(unsigned char const *)&endian != 0)
528                         dso->needs_swap = DSO_SWAP__YES;
529                 break;
530
531         default:
532                 pr_err("unrecognized DSO data encoding %d\n", eidata);
533                 return -EINVAL;
534         }
535
536         return 0;
537 }
538
539 int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd,
540                   symbol_filter_t filter, int kmodule, int want_symtab)
541 {
542         struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
543         struct map *curr_map = map;
544         struct dso *curr_dso = dso;
545         Elf_Data *symstrs, *secstrs;
546         uint32_t nr_syms;
547         int err = -1;
548         uint32_t idx;
549         GElf_Ehdr ehdr;
550         GElf_Shdr shdr, opdshdr;
551         Elf_Data *syms, *opddata = NULL;
552         GElf_Sym sym;
553         Elf_Scn *sec, *sec_strndx, *opdsec;
554         Elf *elf;
555         int nr = 0;
556         size_t opdidx = 0;
557
558         elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
559         if (elf == NULL) {
560                 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
561                 goto out_close;
562         }
563
564         if (gelf_getehdr(elf, &ehdr) == NULL) {
565                 pr_debug("%s: cannot get elf header.\n", __func__);
566                 goto out_elf_end;
567         }
568
569         if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
570                 goto out_elf_end;
571
572         /* Always reject images with a mismatched build-id: */
573         if (dso->has_build_id) {
574                 u8 build_id[BUILD_ID_SIZE];
575
576                 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
577                         goto out_elf_end;
578
579                 if (!dso__build_id_equal(dso, build_id))
580                         goto out_elf_end;
581         }
582
583         sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
584         if (sec == NULL) {
585                 if (want_symtab)
586                         goto out_elf_end;
587
588                 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
589                 if (sec == NULL)
590                         goto out_elf_end;
591         }
592
593         opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
594         if (opdshdr.sh_type != SHT_PROGBITS)
595                 opdsec = NULL;
596         if (opdsec)
597                 opddata = elf_rawdata(opdsec, NULL);
598
599         syms = elf_getdata(sec, NULL);
600         if (syms == NULL)
601                 goto out_elf_end;
602
603         sec = elf_getscn(elf, shdr.sh_link);
604         if (sec == NULL)
605                 goto out_elf_end;
606
607         symstrs = elf_getdata(sec, NULL);
608         if (symstrs == NULL)
609                 goto out_elf_end;
610
611         sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
612         if (sec_strndx == NULL)
613                 goto out_elf_end;
614
615         secstrs = elf_getdata(sec_strndx, NULL);
616         if (secstrs == NULL)
617                 goto out_elf_end;
618
619         nr_syms = shdr.sh_size / shdr.sh_entsize;
620
621         memset(&sym, 0, sizeof(sym));
622         if (dso->kernel == DSO_TYPE_USER) {
623                 dso->adjust_symbols = (ehdr.e_type == ET_EXEC ||
624                                 elf_section_by_name(elf, &ehdr, &shdr,
625                                                      ".gnu.prelink_undo",
626                                                      NULL) != NULL);
627         } else {
628                 dso->adjust_symbols = 0;
629         }
630         elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
631                 struct symbol *f;
632                 const char *elf_name = elf_sym__name(&sym, symstrs);
633                 char *demangled = NULL;
634                 int is_label = elf_sym__is_label(&sym);
635                 const char *section_name;
636
637                 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
638                     strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
639                         kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
640
641                 if (!is_label && !elf_sym__is_a(&sym, map->type))
642                         continue;
643
644                 /* Reject ARM ELF "mapping symbols": these aren't unique and
645                  * don't identify functions, so will confuse the profile
646                  * output: */
647                 if (ehdr.e_machine == EM_ARM) {
648                         if (!strcmp(elf_name, "$a") ||
649                             !strcmp(elf_name, "$d") ||
650                             !strcmp(elf_name, "$t"))
651                                 continue;
652                 }
653
654                 if (opdsec && sym.st_shndx == opdidx) {
655                         u32 offset = sym.st_value - opdshdr.sh_addr;
656                         u64 *opd = opddata->d_buf + offset;
657                         sym.st_value = DSO__SWAP(dso, u64, *opd);
658                         sym.st_shndx = elf_addr_to_index(elf, sym.st_value);
659                 }
660
661                 sec = elf_getscn(elf, sym.st_shndx);
662                 if (!sec)
663                         goto out_elf_end;
664
665                 gelf_getshdr(sec, &shdr);
666
667                 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
668                         continue;
669
670                 section_name = elf_sec__name(&shdr, secstrs);
671
672                 /* On ARM, symbols for thumb functions have 1 added to
673                  * the symbol address as a flag - remove it */
674                 if ((ehdr.e_machine == EM_ARM) &&
675                     (map->type == MAP__FUNCTION) &&
676                     (sym.st_value & 1))
677                         --sym.st_value;
678
679                 if (dso->kernel != DSO_TYPE_USER || kmodule) {
680                         char dso_name[PATH_MAX];
681
682                         if (strcmp(section_name,
683                                    (curr_dso->short_name +
684                                     dso->short_name_len)) == 0)
685                                 goto new_symbol;
686
687                         if (strcmp(section_name, ".text") == 0) {
688                                 curr_map = map;
689                                 curr_dso = dso;
690                                 goto new_symbol;
691                         }
692
693                         snprintf(dso_name, sizeof(dso_name),
694                                  "%s%s", dso->short_name, section_name);
695
696                         curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
697                         if (curr_map == NULL) {
698                                 u64 start = sym.st_value;
699
700                                 if (kmodule)
701                                         start += map->start + shdr.sh_offset;
702
703                                 curr_dso = dso__new(dso_name);
704                                 if (curr_dso == NULL)
705                                         goto out_elf_end;
706                                 curr_dso->kernel = dso->kernel;
707                                 curr_dso->long_name = dso->long_name;
708                                 curr_dso->long_name_len = dso->long_name_len;
709                                 curr_map = map__new2(start, curr_dso,
710                                                      map->type);
711                                 if (curr_map == NULL) {
712                                         dso__delete(curr_dso);
713                                         goto out_elf_end;
714                                 }
715                                 curr_map->map_ip = identity__map_ip;
716                                 curr_map->unmap_ip = identity__map_ip;
717                                 curr_dso->symtab_type = dso->symtab_type;
718                                 map_groups__insert(kmap->kmaps, curr_map);
719                                 dsos__add(&dso->node, curr_dso);
720                                 dso__set_loaded(curr_dso, map->type);
721                         } else
722                                 curr_dso = curr_map->dso;
723
724                         goto new_symbol;
725                 }
726
727                 if (curr_dso->adjust_symbols && sym.st_value) {
728                         pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
729                                   "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
730                                   (u64)sym.st_value, (u64)shdr.sh_addr,
731                                   (u64)shdr.sh_offset);
732                         sym.st_value -= shdr.sh_addr - shdr.sh_offset;
733                 }
734                 /*
735                  * We need to figure out if the object was created from C++ sources
736                  * DWARF DW_compile_unit has this, but we don't always have access
737                  * to it...
738                  */
739                 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
740                 if (demangled != NULL)
741                         elf_name = demangled;
742 new_symbol:
743                 f = symbol__new(sym.st_value, sym.st_size,
744                                 GELF_ST_BIND(sym.st_info), elf_name);
745                 free(demangled);
746                 if (!f)
747                         goto out_elf_end;
748
749                 if (filter && filter(curr_map, f))
750                         symbol__delete(f);
751                 else {
752                         symbols__insert(&curr_dso->symbols[curr_map->type], f);
753                         nr++;
754                 }
755         }
756
757         /*
758          * For misannotated, zeroed, ASM function sizes.
759          */
760         if (nr > 0) {
761                 symbols__fixup_duplicate(&dso->symbols[map->type]);
762                 symbols__fixup_end(&dso->symbols[map->type]);
763                 if (kmap) {
764                         /*
765                          * We need to fixup this here too because we create new
766                          * maps here, for things like vsyscall sections.
767                          */
768                         __map_groups__fixup_end(kmap->kmaps, map->type);
769                 }
770         }
771         err = nr;
772 out_elf_end:
773         elf_end(elf);
774 out_close:
775         return err;
776 }
777
778 void symbol__elf_init(void)
779 {
780         elf_version(EV_CURRENT);
781 }