]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - tools/perf/util/symbol-elf.c
perf symbols: Set symtab_type in dso__load_sym
[mirror_ubuntu-artful-kernel.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
49274654
CS
132 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
133 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL))
134 return NULL;
135
e5a1845f
NK
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 */
169int 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
52f9ddba
CS
239 if (symstrs->d_size == 0)
240 goto out_elf_end;
241
e5a1845f
NK
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;
293out_elf_end:
294 elf_end(elf);
295out_close:
296 close(fd);
297
298 if (err == 0)
299 return nr;
300out:
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
311static 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
386out:
387 return err;
388}
389
390int 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);
411out_close:
412 close(fd);
413out:
414 return err;
415}
416
417int 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);
458out:
459 return err;
460}
461
462int 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
506out_close:
507 close(fd);
508out:
509 return err;
510}
511
512static 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
b68e2f91
CS
539
540void symsrc__destroy(struct symsrc *ss)
541{
542 free(ss->name);
543 elf_end(ss->elf);
544 close(ss->fd);
545}
546
547int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
548 enum dso_binary_type type)
e5a1845f 549{
e5a1845f 550 int err = -1;
e5a1845f 551 GElf_Ehdr ehdr;
e5a1845f 552 Elf *elf;
b68e2f91
CS
553 int fd;
554
555 fd = open(name, O_RDONLY);
556 if (fd < 0)
557 return -1;
e5a1845f
NK
558
559 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
560 if (elf == NULL) {
561 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
562 goto out_close;
563 }
564
565 if (gelf_getehdr(elf, &ehdr) == NULL) {
566 pr_debug("%s: cannot get elf header.\n", __func__);
567 goto out_elf_end;
568 }
569
570 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
571 goto out_elf_end;
572
573 /* Always reject images with a mismatched build-id: */
574 if (dso->has_build_id) {
575 u8 build_id[BUILD_ID_SIZE];
576
577 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
578 goto out_elf_end;
579
580 if (!dso__build_id_equal(dso, build_id))
581 goto out_elf_end;
582 }
583
b68e2f91
CS
584 ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab",
585 NULL);
586 if (ss->symshdr.sh_type != SHT_SYMTAB)
587 ss->symtab = NULL;
588
589 ss->dynsym_idx = 0;
590 ss->dynsym = elf_section_by_name(elf, &ehdr, &ss->dynshdr, ".dynsym",
591 &ss->dynsym_idx);
592 if (ss->dynshdr.sh_type != SHT_DYNSYM)
593 ss->dynsym = NULL;
594
595 ss->opdidx = 0;
596 ss->opdsec = elf_section_by_name(elf, &ehdr, &ss->opdshdr, ".opd",
597 &ss->opdidx);
598 if (ss->opdshdr.sh_type != SHT_PROGBITS)
599 ss->opdsec = NULL;
600
601 if (dso->kernel == DSO_TYPE_USER) {
602 GElf_Shdr shdr;
603 ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
604 elf_section_by_name(elf, &ehdr, &shdr,
605 ".gnu.prelink_undo",
606 NULL) != NULL);
607 } else {
608 ss->adjust_symbols = 0;
609 }
610
611 ss->name = strdup(name);
612 if (!ss->name)
613 goto out_elf_end;
614
615 ss->elf = elf;
616 ss->fd = fd;
617 ss->ehdr = ehdr;
618 ss->type = type;
619
620 return 0;
621
622out_elf_end:
623 elf_end(elf);
624out_close:
625 close(fd);
626 return err;
627}
628
629int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss,
630 symbol_filter_t filter, int kmodule, int want_symtab)
631{
632 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
633 struct map *curr_map = map;
634 struct dso *curr_dso = dso;
635 Elf_Data *symstrs, *secstrs;
636 uint32_t nr_syms;
637 int err = -1;
638 uint32_t idx;
639 GElf_Ehdr ehdr;
640 GElf_Shdr shdr, opdshdr;
641 Elf_Data *syms, *opddata = NULL;
642 GElf_Sym sym;
643 Elf_Scn *sec, *sec_strndx, *opdsec;
644 Elf *elf;
645 int nr = 0;
646 size_t opdidx = 0;
647
005f9294
CS
648 dso->symtab_type = ss->type;
649
b68e2f91
CS
650 elf = ss->elf;
651 ehdr = ss->ehdr;
652 sec = ss->symtab;
653 shdr = ss->symshdr;
654
e5a1845f
NK
655 if (sec == NULL) {
656 if (want_symtab)
657 goto out_elf_end;
658
b68e2f91
CS
659 sec = ss->dynsym;
660 shdr = ss->dynshdr;
e5a1845f
NK
661 if (sec == NULL)
662 goto out_elf_end;
663 }
664
b68e2f91
CS
665 opdsec = ss->opdsec;
666 opdshdr = ss->opdshdr;
667 opdidx = ss->opdidx;
e5a1845f
NK
668 if (opdsec)
669 opddata = elf_rawdata(opdsec, NULL);
670
671 syms = elf_getdata(sec, NULL);
672 if (syms == NULL)
673 goto out_elf_end;
674
675 sec = elf_getscn(elf, shdr.sh_link);
676 if (sec == NULL)
677 goto out_elf_end;
678
679 symstrs = elf_getdata(sec, NULL);
680 if (symstrs == NULL)
681 goto out_elf_end;
682
683 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
684 if (sec_strndx == NULL)
685 goto out_elf_end;
686
687 secstrs = elf_getdata(sec_strndx, NULL);
688 if (secstrs == NULL)
689 goto out_elf_end;
690
691 nr_syms = shdr.sh_size / shdr.sh_entsize;
692
693 memset(&sym, 0, sizeof(sym));
b68e2f91 694 dso->adjust_symbols = ss->adjust_symbols;
e5a1845f
NK
695 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
696 struct symbol *f;
697 const char *elf_name = elf_sym__name(&sym, symstrs);
698 char *demangled = NULL;
699 int is_label = elf_sym__is_label(&sym);
700 const char *section_name;
701
702 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
703 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
704 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
705
706 if (!is_label && !elf_sym__is_a(&sym, map->type))
707 continue;
708
709 /* Reject ARM ELF "mapping symbols": these aren't unique and
710 * don't identify functions, so will confuse the profile
711 * output: */
712 if (ehdr.e_machine == EM_ARM) {
713 if (!strcmp(elf_name, "$a") ||
714 !strcmp(elf_name, "$d") ||
715 !strcmp(elf_name, "$t"))
716 continue;
717 }
718
719 if (opdsec && sym.st_shndx == opdidx) {
720 u32 offset = sym.st_value - opdshdr.sh_addr;
721 u64 *opd = opddata->d_buf + offset;
722 sym.st_value = DSO__SWAP(dso, u64, *opd);
723 sym.st_shndx = elf_addr_to_index(elf, sym.st_value);
724 }
725
726 sec = elf_getscn(elf, sym.st_shndx);
727 if (!sec)
728 goto out_elf_end;
729
730 gelf_getshdr(sec, &shdr);
731
732 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
733 continue;
734
735 section_name = elf_sec__name(&shdr, secstrs);
736
737 /* On ARM, symbols for thumb functions have 1 added to
738 * the symbol address as a flag - remove it */
739 if ((ehdr.e_machine == EM_ARM) &&
740 (map->type == MAP__FUNCTION) &&
741 (sym.st_value & 1))
742 --sym.st_value;
743
744 if (dso->kernel != DSO_TYPE_USER || kmodule) {
745 char dso_name[PATH_MAX];
746
747 if (strcmp(section_name,
748 (curr_dso->short_name +
749 dso->short_name_len)) == 0)
750 goto new_symbol;
751
752 if (strcmp(section_name, ".text") == 0) {
753 curr_map = map;
754 curr_dso = dso;
755 goto new_symbol;
756 }
757
758 snprintf(dso_name, sizeof(dso_name),
759 "%s%s", dso->short_name, section_name);
760
761 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
762 if (curr_map == NULL) {
763 u64 start = sym.st_value;
764
765 if (kmodule)
766 start += map->start + shdr.sh_offset;
767
768 curr_dso = dso__new(dso_name);
769 if (curr_dso == NULL)
770 goto out_elf_end;
771 curr_dso->kernel = dso->kernel;
772 curr_dso->long_name = dso->long_name;
773 curr_dso->long_name_len = dso->long_name_len;
774 curr_map = map__new2(start, curr_dso,
775 map->type);
776 if (curr_map == NULL) {
777 dso__delete(curr_dso);
778 goto out_elf_end;
779 }
780 curr_map->map_ip = identity__map_ip;
781 curr_map->unmap_ip = identity__map_ip;
782 curr_dso->symtab_type = dso->symtab_type;
783 map_groups__insert(kmap->kmaps, curr_map);
784 dsos__add(&dso->node, curr_dso);
785 dso__set_loaded(curr_dso, map->type);
786 } else
787 curr_dso = curr_map->dso;
788
789 goto new_symbol;
790 }
791
8db24c70 792 if (curr_dso->adjust_symbols && sym.st_value) {
e5a1845f
NK
793 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
794 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
795 (u64)sym.st_value, (u64)shdr.sh_addr,
796 (u64)shdr.sh_offset);
797 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
798 }
799 /*
800 * We need to figure out if the object was created from C++ sources
801 * DWARF DW_compile_unit has this, but we don't always have access
802 * to it...
803 */
804 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
805 if (demangled != NULL)
806 elf_name = demangled;
807new_symbol:
808 f = symbol__new(sym.st_value, sym.st_size,
809 GELF_ST_BIND(sym.st_info), elf_name);
810 free(demangled);
811 if (!f)
812 goto out_elf_end;
813
814 if (filter && filter(curr_map, f))
815 symbol__delete(f);
816 else {
817 symbols__insert(&curr_dso->symbols[curr_map->type], f);
818 nr++;
819 }
820 }
821
822 /*
823 * For misannotated, zeroed, ASM function sizes.
824 */
825 if (nr > 0) {
826 symbols__fixup_duplicate(&dso->symbols[map->type]);
827 symbols__fixup_end(&dso->symbols[map->type]);
828 if (kmap) {
829 /*
830 * We need to fixup this here too because we create new
831 * maps here, for things like vsyscall sections.
832 */
833 __map_groups__fixup_end(kmap->kmaps, map->type);
834 }
835 }
836 err = nr;
837out_elf_end:
e5a1845f
NK
838 return err;
839}
840
841void symbol__elf_init(void)
842{
843 elf_version(EV_CURRENT);
844}