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