ipv6: fix race condition regarding dst->expires and dst->from.
[pandora-kernel.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, struct symsrc *ss, 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, err = 0;
185
186         if (!ss->dynsym)
187                 return 0;
188
189         elf = ss->elf;
190         ehdr = ss->ehdr;
191
192         scn_dynsym = ss->dynsym;
193         shdr_dynsym = ss->dynshdr;
194         dynsym_idx = ss->dynsym_idx;
195
196         if (scn_dynsym == NULL)
197                 goto out_elf_end;
198
199         scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
200                                           ".rela.plt", NULL);
201         if (scn_plt_rel == NULL) {
202                 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
203                                                   ".rel.plt", NULL);
204                 if (scn_plt_rel == NULL)
205                         goto out_elf_end;
206         }
207
208         err = -1;
209
210         if (shdr_rel_plt.sh_link != dynsym_idx)
211                 goto out_elf_end;
212
213         if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
214                 goto out_elf_end;
215
216         /*
217          * Fetch the relocation section to find the idxes to the GOT
218          * and the symbols in the .dynsym they refer to.
219          */
220         reldata = elf_getdata(scn_plt_rel, NULL);
221         if (reldata == NULL)
222                 goto out_elf_end;
223
224         syms = elf_getdata(scn_dynsym, NULL);
225         if (syms == NULL)
226                 goto out_elf_end;
227
228         scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
229         if (scn_symstrs == NULL)
230                 goto out_elf_end;
231
232         symstrs = elf_getdata(scn_symstrs, NULL);
233         if (symstrs == NULL)
234                 goto out_elf_end;
235
236         if (symstrs->d_size == 0)
237                 goto out_elf_end;
238
239         nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
240         plt_offset = shdr_plt.sh_offset;
241
242         if (shdr_rel_plt.sh_type == SHT_RELA) {
243                 GElf_Rela pos_mem, *pos;
244
245                 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
246                                            nr_rel_entries) {
247                         symidx = GELF_R_SYM(pos->r_info);
248                         plt_offset += shdr_plt.sh_entsize;
249                         gelf_getsym(syms, symidx, &sym);
250                         snprintf(sympltname, sizeof(sympltname),
251                                  "%s@plt", elf_sym__name(&sym, symstrs));
252
253                         f = symbol__new(plt_offset, shdr_plt.sh_entsize,
254                                         STB_GLOBAL, sympltname);
255                         if (!f)
256                                 goto out_elf_end;
257
258                         if (filter && filter(map, f))
259                                 symbol__delete(f);
260                         else {
261                                 symbols__insert(&dso->symbols[map->type], f);
262                                 ++nr;
263                         }
264                 }
265         } else if (shdr_rel_plt.sh_type == SHT_REL) {
266                 GElf_Rel pos_mem, *pos;
267                 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
268                                           nr_rel_entries) {
269                         symidx = GELF_R_SYM(pos->r_info);
270                         plt_offset += shdr_plt.sh_entsize;
271                         gelf_getsym(syms, symidx, &sym);
272                         snprintf(sympltname, sizeof(sympltname),
273                                  "%s@plt", elf_sym__name(&sym, symstrs));
274
275                         f = symbol__new(plt_offset, shdr_plt.sh_entsize,
276                                         STB_GLOBAL, sympltname);
277                         if (!f)
278                                 goto out_elf_end;
279
280                         if (filter && filter(map, f))
281                                 symbol__delete(f);
282                         else {
283                                 symbols__insert(&dso->symbols[map->type], f);
284                                 ++nr;
285                         }
286                 }
287         }
288
289         err = 0;
290 out_elf_end:
291         if (err == 0)
292                 return nr;
293         pr_debug("%s: problems reading %s PLT info.\n",
294                  __func__, dso->long_name);
295         return 0;
296 }
297
298 /*
299  * Align offset to 4 bytes as needed for note name and descriptor data.
300  */
301 #define NOTE_ALIGN(n) (((n) + 3) & -4U)
302
303 static int elf_read_build_id(Elf *elf, void *bf, size_t size)
304 {
305         int err = -1;
306         GElf_Ehdr ehdr;
307         GElf_Shdr shdr;
308         Elf_Data *data;
309         Elf_Scn *sec;
310         Elf_Kind ek;
311         void *ptr;
312
313         if (size < BUILD_ID_SIZE)
314                 goto out;
315
316         ek = elf_kind(elf);
317         if (ek != ELF_K_ELF)
318                 goto out;
319
320         if (gelf_getehdr(elf, &ehdr) == NULL) {
321                 pr_err("%s: cannot get elf header.\n", __func__);
322                 goto out;
323         }
324
325         /*
326          * Check following sections for notes:
327          *   '.note.gnu.build-id'
328          *   '.notes'
329          *   '.note' (VDSO specific)
330          */
331         do {
332                 sec = elf_section_by_name(elf, &ehdr, &shdr,
333                                           ".note.gnu.build-id", NULL);
334                 if (sec)
335                         break;
336
337                 sec = elf_section_by_name(elf, &ehdr, &shdr,
338                                           ".notes", NULL);
339                 if (sec)
340                         break;
341
342                 sec = elf_section_by_name(elf, &ehdr, &shdr,
343                                           ".note", NULL);
344                 if (sec)
345                         break;
346
347                 return err;
348
349         } while (0);
350
351         data = elf_getdata(sec, NULL);
352         if (data == NULL)
353                 goto out;
354
355         ptr = data->d_buf;
356         while (ptr < (data->d_buf + data->d_size)) {
357                 GElf_Nhdr *nhdr = ptr;
358                 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
359                        descsz = NOTE_ALIGN(nhdr->n_descsz);
360                 const char *name;
361
362                 ptr += sizeof(*nhdr);
363                 name = ptr;
364                 ptr += namesz;
365                 if (nhdr->n_type == NT_GNU_BUILD_ID &&
366                     nhdr->n_namesz == sizeof("GNU")) {
367                         if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
368                                 size_t sz = min(size, descsz);
369                                 memcpy(bf, ptr, sz);
370                                 memset(bf + sz, 0, size - sz);
371                                 err = descsz;
372                                 break;
373                         }
374                 }
375                 ptr += descsz;
376         }
377
378 out:
379         return err;
380 }
381
382 int filename__read_build_id(const char *filename, void *bf, size_t size)
383 {
384         int fd, err = -1;
385         Elf *elf;
386
387         if (size < BUILD_ID_SIZE)
388                 goto out;
389
390         fd = open(filename, O_RDONLY);
391         if (fd < 0)
392                 goto out;
393
394         elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
395         if (elf == NULL) {
396                 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
397                 goto out_close;
398         }
399
400         err = elf_read_build_id(elf, bf, size);
401
402         elf_end(elf);
403 out_close:
404         close(fd);
405 out:
406         return err;
407 }
408
409 int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
410 {
411         int fd, err = -1;
412
413         if (size < BUILD_ID_SIZE)
414                 goto out;
415
416         fd = open(filename, O_RDONLY);
417         if (fd < 0)
418                 goto out;
419
420         while (1) {
421                 char bf[BUFSIZ];
422                 GElf_Nhdr nhdr;
423                 size_t namesz, descsz;
424
425                 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
426                         break;
427
428                 namesz = NOTE_ALIGN(nhdr.n_namesz);
429                 descsz = NOTE_ALIGN(nhdr.n_descsz);
430                 if (nhdr.n_type == NT_GNU_BUILD_ID &&
431                     nhdr.n_namesz == sizeof("GNU")) {
432                         if (read(fd, bf, namesz) != (ssize_t)namesz)
433                                 break;
434                         if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
435                                 size_t sz = min(descsz, size);
436                                 if (read(fd, build_id, sz) == (ssize_t)sz) {
437                                         memset(build_id + sz, 0, size - sz);
438                                         err = 0;
439                                         break;
440                                 }
441                         } else if (read(fd, bf, descsz) != (ssize_t)descsz)
442                                 break;
443                 } else {
444                         int n = namesz + descsz;
445                         if (read(fd, bf, n) != n)
446                                 break;
447                 }
448         }
449         close(fd);
450 out:
451         return err;
452 }
453
454 int filename__read_debuglink(const char *filename, char *debuglink,
455                              size_t size)
456 {
457         int fd, err = -1;
458         Elf *elf;
459         GElf_Ehdr ehdr;
460         GElf_Shdr shdr;
461         Elf_Data *data;
462         Elf_Scn *sec;
463         Elf_Kind ek;
464
465         fd = open(filename, O_RDONLY);
466         if (fd < 0)
467                 goto out;
468
469         elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
470         if (elf == NULL) {
471                 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
472                 goto out_close;
473         }
474
475         ek = elf_kind(elf);
476         if (ek != ELF_K_ELF)
477                 goto out_close;
478
479         if (gelf_getehdr(elf, &ehdr) == NULL) {
480                 pr_err("%s: cannot get elf header.\n", __func__);
481                 goto out_close;
482         }
483
484         sec = elf_section_by_name(elf, &ehdr, &shdr,
485                                   ".gnu_debuglink", NULL);
486         if (sec == NULL)
487                 goto out_close;
488
489         data = elf_getdata(sec, NULL);
490         if (data == NULL)
491                 goto out_close;
492
493         /* the start of this section is a zero-terminated string */
494         strncpy(debuglink, data->d_buf, size);
495
496         elf_end(elf);
497
498 out_close:
499         close(fd);
500 out:
501         return err;
502 }
503
504 static int dso__swap_init(struct dso *dso, unsigned char eidata)
505 {
506         static unsigned int const endian = 1;
507
508         dso->needs_swap = DSO_SWAP__NO;
509
510         switch (eidata) {
511         case ELFDATA2LSB:
512                 /* We are big endian, DSO is little endian. */
513                 if (*(unsigned char const *)&endian != 1)
514                         dso->needs_swap = DSO_SWAP__YES;
515                 break;
516
517         case ELFDATA2MSB:
518                 /* We are little endian, DSO is big endian. */
519                 if (*(unsigned char const *)&endian != 0)
520                         dso->needs_swap = DSO_SWAP__YES;
521                 break;
522
523         default:
524                 pr_err("unrecognized DSO data encoding %d\n", eidata);
525                 return -EINVAL;
526         }
527
528         return 0;
529 }
530
531 bool symsrc__possibly_runtime(struct symsrc *ss)
532 {
533         return ss->dynsym || ss->opdsec;
534 }
535
536 bool symsrc__has_symtab(struct symsrc *ss)
537 {
538         return ss->symtab != NULL;
539 }
540
541 void symsrc__destroy(struct symsrc *ss)
542 {
543         free(ss->name);
544         elf_end(ss->elf);
545         close(ss->fd);
546 }
547
548 int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
549                  enum dso_binary_type type)
550 {
551         int err = -1;
552         GElf_Ehdr ehdr;
553         Elf *elf;
554         int fd;
555
556         fd = open(name, O_RDONLY);
557         if (fd < 0)
558                 return -1;
559
560         elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
561         if (elf == NULL) {
562                 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
563                 goto out_close;
564         }
565
566         if (gelf_getehdr(elf, &ehdr) == NULL) {
567                 pr_debug("%s: cannot get elf header.\n", __func__);
568                 goto out_elf_end;
569         }
570
571         if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
572                 goto out_elf_end;
573
574         /* Always reject images with a mismatched build-id: */
575         if (dso->has_build_id) {
576                 u8 build_id[BUILD_ID_SIZE];
577
578                 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
579                         goto out_elf_end;
580
581                 if (!dso__build_id_equal(dso, build_id))
582                         goto out_elf_end;
583         }
584
585         ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab",
586                         NULL);
587         if (ss->symshdr.sh_type != SHT_SYMTAB)
588                 ss->symtab = NULL;
589
590         ss->dynsym_idx = 0;
591         ss->dynsym = elf_section_by_name(elf, &ehdr, &ss->dynshdr, ".dynsym",
592                         &ss->dynsym_idx);
593         if (ss->dynshdr.sh_type != SHT_DYNSYM)
594                 ss->dynsym = NULL;
595
596         ss->opdidx = 0;
597         ss->opdsec = elf_section_by_name(elf, &ehdr, &ss->opdshdr, ".opd",
598                         &ss->opdidx);
599         if (ss->opdshdr.sh_type != SHT_PROGBITS)
600                 ss->opdsec = NULL;
601
602         if (dso->kernel == DSO_TYPE_USER) {
603                 GElf_Shdr shdr;
604                 ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
605                                 elf_section_by_name(elf, &ehdr, &shdr,
606                                                      ".gnu.prelink_undo",
607                                                      NULL) != NULL);
608         } else {
609                 ss->adjust_symbols = 0;
610         }
611
612         ss->name   = strdup(name);
613         if (!ss->name)
614                 goto out_elf_end;
615
616         ss->elf    = elf;
617         ss->fd     = fd;
618         ss->ehdr   = ehdr;
619         ss->type   = type;
620
621         return 0;
622
623 out_elf_end:
624         elf_end(elf);
625 out_close:
626         close(fd);
627         return err;
628 }
629
630 int dso__load_sym(struct dso *dso, struct map *map,
631                   struct symsrc *syms_ss, struct symsrc *runtime_ss,
632                   symbol_filter_t filter, int kmodule)
633 {
634         struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
635         struct map *curr_map = map;
636         struct dso *curr_dso = dso;
637         Elf_Data *symstrs, *secstrs;
638         uint32_t nr_syms;
639         int err = -1;
640         uint32_t idx;
641         GElf_Ehdr ehdr;
642         GElf_Shdr shdr;
643         Elf_Data *syms, *opddata = NULL;
644         GElf_Sym sym;
645         Elf_Scn *sec, *sec_strndx;
646         Elf *elf;
647         int nr = 0;
648
649         dso->symtab_type = syms_ss->type;
650
651         if (!syms_ss->symtab) {
652                 syms_ss->symtab  = syms_ss->dynsym;
653                 syms_ss->symshdr = syms_ss->dynshdr;
654         }
655
656         elf = syms_ss->elf;
657         ehdr = syms_ss->ehdr;
658         sec = syms_ss->symtab;
659         shdr = syms_ss->symshdr;
660
661         if (runtime_ss->opdsec)
662                 opddata = elf_rawdata(runtime_ss->opdsec, NULL);
663
664         syms = elf_getdata(sec, NULL);
665         if (syms == NULL)
666                 goto out_elf_end;
667
668         sec = elf_getscn(elf, shdr.sh_link);
669         if (sec == NULL)
670                 goto out_elf_end;
671
672         symstrs = elf_getdata(sec, NULL);
673         if (symstrs == NULL)
674                 goto out_elf_end;
675
676         sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
677         if (sec_strndx == NULL)
678                 goto out_elf_end;
679
680         secstrs = elf_getdata(sec_strndx, NULL);
681         if (secstrs == NULL)
682                 goto out_elf_end;
683
684         nr_syms = shdr.sh_size / shdr.sh_entsize;
685
686         memset(&sym, 0, sizeof(sym));
687         dso->adjust_symbols = runtime_ss->adjust_symbols;
688         elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
689                 struct symbol *f;
690                 const char *elf_name = elf_sym__name(&sym, symstrs);
691                 char *demangled = NULL;
692                 int is_label = elf_sym__is_label(&sym);
693                 const char *section_name;
694                 bool used_opd = false;
695
696                 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
697                     strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
698                         kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
699
700                 if (!is_label && !elf_sym__is_a(&sym, map->type))
701                         continue;
702
703                 /* Reject ARM ELF "mapping symbols": these aren't unique and
704                  * don't identify functions, so will confuse the profile
705                  * output: */
706                 if (ehdr.e_machine == EM_ARM) {
707                         if (!strcmp(elf_name, "$a") ||
708                             !strcmp(elf_name, "$d") ||
709                             !strcmp(elf_name, "$t"))
710                                 continue;
711                 }
712
713                 if (runtime_ss->opdsec && sym.st_shndx == runtime_ss->opdidx) {
714                         u32 offset = sym.st_value - syms_ss->opdshdr.sh_addr;
715                         u64 *opd = opddata->d_buf + offset;
716                         sym.st_value = DSO__SWAP(dso, u64, *opd);
717                         sym.st_shndx = elf_addr_to_index(runtime_ss->elf,
718                                         sym.st_value);
719                         used_opd = true;
720                 }
721
722                 sec = elf_getscn(runtime_ss->elf, sym.st_shndx);
723                 if (!sec)
724                         goto out_elf_end;
725
726                 gelf_getshdr(sec, &shdr);
727
728                 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
729                         continue;
730
731                 section_name = elf_sec__name(&shdr, secstrs);
732
733                 /* On ARM, symbols for thumb functions have 1 added to
734                  * the symbol address as a flag - remove it */
735                 if ((ehdr.e_machine == EM_ARM) &&
736                     (map->type == MAP__FUNCTION) &&
737                     (sym.st_value & 1))
738                         --sym.st_value;
739
740                 if (dso->kernel != DSO_TYPE_USER || kmodule) {
741                         char dso_name[PATH_MAX];
742
743                         if (strcmp(section_name,
744                                    (curr_dso->short_name +
745                                     dso->short_name_len)) == 0)
746                                 goto new_symbol;
747
748                         if (strcmp(section_name, ".text") == 0) {
749                                 curr_map = map;
750                                 curr_dso = dso;
751                                 goto new_symbol;
752                         }
753
754                         snprintf(dso_name, sizeof(dso_name),
755                                  "%s%s", dso->short_name, section_name);
756
757                         curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
758                         if (curr_map == NULL) {
759                                 u64 start = sym.st_value;
760
761                                 if (kmodule)
762                                         start += map->start + shdr.sh_offset;
763
764                                 curr_dso = dso__new(dso_name);
765                                 if (curr_dso == NULL)
766                                         goto out_elf_end;
767                                 curr_dso->kernel = dso->kernel;
768                                 curr_dso->long_name = dso->long_name;
769                                 curr_dso->long_name_len = dso->long_name_len;
770                                 curr_map = map__new2(start, curr_dso,
771                                                      map->type);
772                                 if (curr_map == NULL) {
773                                         dso__delete(curr_dso);
774                                         goto out_elf_end;
775                                 }
776                                 curr_map->map_ip = identity__map_ip;
777                                 curr_map->unmap_ip = identity__map_ip;
778                                 curr_dso->symtab_type = dso->symtab_type;
779                                 map_groups__insert(kmap->kmaps, curr_map);
780                                 dsos__add(&dso->node, curr_dso);
781                                 dso__set_loaded(curr_dso, map->type);
782                         } else
783                                 curr_dso = curr_map->dso;
784
785                         goto new_symbol;
786                 }
787
788                 if ((used_opd && runtime_ss->adjust_symbols)
789                                 || (!used_opd && syms_ss->adjust_symbols)) {
790                         pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
791                                   "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
792                                   (u64)sym.st_value, (u64)shdr.sh_addr,
793                                   (u64)shdr.sh_offset);
794                         sym.st_value -= shdr.sh_addr - shdr.sh_offset;
795                 }
796                 /*
797                  * We need to figure out if the object was created from C++ sources
798                  * DWARF DW_compile_unit has this, but we don't always have access
799                  * to it...
800                  */
801                 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
802                 if (demangled != NULL)
803                         elf_name = demangled;
804 new_symbol:
805                 f = symbol__new(sym.st_value, sym.st_size,
806                                 GELF_ST_BIND(sym.st_info), elf_name);
807                 free(demangled);
808                 if (!f)
809                         goto out_elf_end;
810
811                 if (filter && filter(curr_map, f))
812                         symbol__delete(f);
813                 else {
814                         symbols__insert(&curr_dso->symbols[curr_map->type], f);
815                         nr++;
816                 }
817         }
818
819         /*
820          * For misannotated, zeroed, ASM function sizes.
821          */
822         if (nr > 0) {
823                 symbols__fixup_duplicate(&dso->symbols[map->type]);
824                 symbols__fixup_end(&dso->symbols[map->type]);
825                 if (kmap) {
826                         /*
827                          * We need to fixup this here too because we create new
828                          * maps here, for things like vsyscall sections.
829                          */
830                         __map_groups__fixup_end(kmap->kmaps, map->type);
831                 }
832         }
833         err = nr;
834 out_elf_end:
835         return err;
836 }
837
838 void symbol__elf_init(void)
839 {
840         elf_version(EV_CURRENT);
841 }