aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung.kim@lge.com>2012-08-06 00:41:20 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-08-09 15:26:33 -0400
commite5a1845fc0aeca85c98115980c3531129f87e18d (patch)
treef67ec3bfc5dc9ae6e2d89ad9b6493a873d4c8652 /tools/perf/util
parent166ccc9c244828da9214a0e7ba4d5dde6a26dcc1 (diff)
perf symbols: Split out util/symbol-elf.c
Factor out the dependency of ELF handling into separate symbol-elf.c file. It is a preparation of building a minimalistic version perf tools which doesn't depend on the elfutils. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1344228082-15569-3-git-send-email-namhyung@kernel.org [ committer note: removed blank line at symbol-elf.c EOF ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/map.c19
-rw-r--r--tools/perf/util/map.h1
-rw-r--r--tools/perf/util/symbol-elf.c774
-rw-r--r--tools/perf/util/symbol.c804
-rw-r--r--tools/perf/util/symbol.h15
5 files changed, 816 insertions, 797 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index cc33486ad9e2..115654c469c6 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -86,6 +86,25 @@ out_delete:
86 return NULL; 86 return NULL;
87} 87}
88 88
89/*
90 * Constructor variant for modules (where we know from /proc/modules where
91 * they are loaded) and for vmlinux, where only after we load all the
92 * symbols we'll know where it starts and ends.
93 */
94struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
95{
96 struct map *map = calloc(1, (sizeof(*map) +
97 (dso->kernel ? sizeof(struct kmap) : 0)));
98 if (map != NULL) {
99 /*
100 * ->end will be filled after we load all the symbols
101 */
102 map__init(map, type, start, 0, 0, dso);
103 }
104
105 return map;
106}
107
89void map__delete(struct map *self) 108void map__delete(struct map *self)
90{ 109{
91 free(self); 110 free(self);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 03a1e9b08b21..1e183d1ae581 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -115,6 +115,7 @@ void map__init(struct map *self, enum map_type type,
115struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, 115struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
116 u64 pgoff, u32 pid, char *filename, 116 u64 pgoff, u32 pid, char *filename,
117 enum map_type type); 117 enum map_type type);
118struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
118void map__delete(struct map *self); 119void map__delete(struct map *self);
119struct map *map__clone(struct map *self); 120struct map *map__clone(struct map *self);
120int map__overlap(struct map *l, struct map *r); 121int map__overlap(struct map *l, struct map *r);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
new file mode 100644
index 000000000000..9ca89f8f6c97
--- /dev/null
+++ b/tools/perf/util/symbol-elf.c
@@ -0,0 +1,774 @@
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
235 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
236 plt_offset = shdr_plt.sh_offset;
237
238 if (shdr_rel_plt.sh_type == SHT_RELA) {
239 GElf_Rela pos_mem, *pos;
240
241 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
242 nr_rel_entries) {
243 symidx = GELF_R_SYM(pos->r_info);
244 plt_offset += shdr_plt.sh_entsize;
245 gelf_getsym(syms, symidx, &sym);
246 snprintf(sympltname, sizeof(sympltname),
247 "%s@plt", elf_sym__name(&sym, symstrs));
248
249 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
250 STB_GLOBAL, sympltname);
251 if (!f)
252 goto out_elf_end;
253
254 if (filter && filter(map, f))
255 symbol__delete(f);
256 else {
257 symbols__insert(&dso->symbols[map->type], f);
258 ++nr;
259 }
260 }
261 } else if (shdr_rel_plt.sh_type == SHT_REL) {
262 GElf_Rel pos_mem, *pos;
263 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
264 nr_rel_entries) {
265 symidx = GELF_R_SYM(pos->r_info);
266 plt_offset += shdr_plt.sh_entsize;
267 gelf_getsym(syms, symidx, &sym);
268 snprintf(sympltname, sizeof(sympltname),
269 "%s@plt", elf_sym__name(&sym, symstrs));
270
271 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
272 STB_GLOBAL, sympltname);
273 if (!f)
274 goto out_elf_end;
275
276 if (filter && filter(map, f))
277 symbol__delete(f);
278 else {
279 symbols__insert(&dso->symbols[map->type], f);
280 ++nr;
281 }
282 }
283 }
284
285 err = 0;
286out_elf_end:
287 elf_end(elf);
288out_close:
289 close(fd);
290
291 if (err == 0)
292 return nr;
293out:
294 pr_debug("%s: problems reading %s PLT info.\n",
295 __func__, dso->long_name);
296 return 0;
297}
298
299/*
300 * Align offset to 4 bytes as needed for note name and descriptor data.
301 */
302#define NOTE_ALIGN(n) (((n) + 3) & -4U)
303
304static int elf_read_build_id(Elf *elf, void *bf, size_t size)
305{
306 int err = -1;
307 GElf_Ehdr ehdr;
308 GElf_Shdr shdr;
309 Elf_Data *data;
310 Elf_Scn *sec;
311 Elf_Kind ek;
312 void *ptr;
313
314 if (size < BUILD_ID_SIZE)
315 goto out;
316
317 ek = elf_kind(elf);
318 if (ek != ELF_K_ELF)
319 goto out;
320
321 if (gelf_getehdr(elf, &ehdr) == NULL) {
322 pr_err("%s: cannot get elf header.\n", __func__);
323 goto out;
324 }
325
326 /*
327 * Check following sections for notes:
328 * '.note.gnu.build-id'
329 * '.notes'
330 * '.note' (VDSO specific)
331 */
332 do {
333 sec = elf_section_by_name(elf, &ehdr, &shdr,
334 ".note.gnu.build-id", NULL);
335 if (sec)
336 break;
337
338 sec = elf_section_by_name(elf, &ehdr, &shdr,
339 ".notes", NULL);
340 if (sec)
341 break;
342
343 sec = elf_section_by_name(elf, &ehdr, &shdr,
344 ".note", NULL);
345 if (sec)
346 break;
347
348 return err;
349
350 } while (0);
351
352 data = elf_getdata(sec, NULL);
353 if (data == NULL)
354 goto out;
355
356 ptr = data->d_buf;
357 while (ptr < (data->d_buf + data->d_size)) {
358 GElf_Nhdr *nhdr = ptr;
359 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
360 descsz = NOTE_ALIGN(nhdr->n_descsz);
361 const char *name;
362
363 ptr += sizeof(*nhdr);
364 name = ptr;
365 ptr += namesz;
366 if (nhdr->n_type == NT_GNU_BUILD_ID &&
367 nhdr->n_namesz == sizeof("GNU")) {
368 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
369 size_t sz = min(size, descsz);
370 memcpy(bf, ptr, sz);
371 memset(bf + sz, 0, size - sz);
372 err = descsz;
373 break;
374 }
375 }
376 ptr += descsz;
377 }
378
379out:
380 return err;
381}
382
383int filename__read_build_id(const char *filename, void *bf, size_t size)
384{
385 int fd, err = -1;
386 Elf *elf;
387
388 if (size < BUILD_ID_SIZE)
389 goto out;
390
391 fd = open(filename, O_RDONLY);
392 if (fd < 0)
393 goto out;
394
395 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
396 if (elf == NULL) {
397 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
398 goto out_close;
399 }
400
401 err = elf_read_build_id(elf, bf, size);
402
403 elf_end(elf);
404out_close:
405 close(fd);
406out:
407 return err;
408}
409
410int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
411{
412 int fd, err = -1;
413
414 if (size < BUILD_ID_SIZE)
415 goto out;
416
417 fd = open(filename, O_RDONLY);
418 if (fd < 0)
419 goto out;
420
421 while (1) {
422 char bf[BUFSIZ];
423 GElf_Nhdr nhdr;
424 size_t namesz, descsz;
425
426 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
427 break;
428
429 namesz = NOTE_ALIGN(nhdr.n_namesz);
430 descsz = NOTE_ALIGN(nhdr.n_descsz);
431 if (nhdr.n_type == NT_GNU_BUILD_ID &&
432 nhdr.n_namesz == sizeof("GNU")) {
433 if (read(fd, bf, namesz) != (ssize_t)namesz)
434 break;
435 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
436 size_t sz = min(descsz, size);
437 if (read(fd, build_id, sz) == (ssize_t)sz) {
438 memset(build_id + sz, 0, size - sz);
439 err = 0;
440 break;
441 }
442 } else if (read(fd, bf, descsz) != (ssize_t)descsz)
443 break;
444 } else {
445 int n = namesz + descsz;
446 if (read(fd, bf, n) != n)
447 break;
448 }
449 }
450 close(fd);
451out:
452 return err;
453}
454
455int filename__read_debuglink(const char *filename, char *debuglink,
456 size_t size)
457{
458 int fd, err = -1;
459 Elf *elf;
460 GElf_Ehdr ehdr;
461 GElf_Shdr shdr;
462 Elf_Data *data;
463 Elf_Scn *sec;
464 Elf_Kind ek;
465
466 fd = open(filename, O_RDONLY);
467 if (fd < 0)
468 goto out;
469
470 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
471 if (elf == NULL) {
472 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
473 goto out_close;
474 }
475
476 ek = elf_kind(elf);
477 if (ek != ELF_K_ELF)
478 goto out_close;
479
480 if (gelf_getehdr(elf, &ehdr) == NULL) {
481 pr_err("%s: cannot get elf header.\n", __func__);
482 goto out_close;
483 }
484
485 sec = elf_section_by_name(elf, &ehdr, &shdr,
486 ".gnu_debuglink", NULL);
487 if (sec == NULL)
488 goto out_close;
489
490 data = elf_getdata(sec, NULL);
491 if (data == NULL)
492 goto out_close;
493
494 /* the start of this section is a zero-terminated string */
495 strncpy(debuglink, data->d_buf, size);
496
497 elf_end(elf);
498
499out_close:
500 close(fd);
501out:
502 return err;
503}
504
505static int dso__swap_init(struct dso *dso, unsigned char eidata)
506{
507 static unsigned int const endian = 1;
508
509 dso->needs_swap = DSO_SWAP__NO;
510
511 switch (eidata) {
512 case ELFDATA2LSB:
513 /* We are big endian, DSO is little endian. */
514 if (*(unsigned char const *)&endian != 1)
515 dso->needs_swap = DSO_SWAP__YES;
516 break;
517
518 case ELFDATA2MSB:
519 /* We are little endian, DSO is big endian. */
520 if (*(unsigned char const *)&endian != 0)
521 dso->needs_swap = DSO_SWAP__YES;
522 break;
523
524 default:
525 pr_err("unrecognized DSO data encoding %d\n", eidata);
526 return -EINVAL;
527 }
528
529 return 0;
530}
531
532int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd,
533 symbol_filter_t filter, int kmodule, int want_symtab)
534{
535 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
536 struct map *curr_map = map;
537 struct dso *curr_dso = dso;
538 Elf_Data *symstrs, *secstrs;
539 uint32_t nr_syms;
540 int err = -1;
541 uint32_t idx;
542 GElf_Ehdr ehdr;
543 GElf_Shdr shdr, opdshdr;
544 Elf_Data *syms, *opddata = NULL;
545 GElf_Sym sym;
546 Elf_Scn *sec, *sec_strndx, *opdsec;
547 Elf *elf;
548 int nr = 0;
549 size_t opdidx = 0;
550
551 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
552 if (elf == NULL) {
553 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
554 goto out_close;
555 }
556
557 if (gelf_getehdr(elf, &ehdr) == NULL) {
558 pr_debug("%s: cannot get elf header.\n", __func__);
559 goto out_elf_end;
560 }
561
562 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
563 goto out_elf_end;
564
565 /* Always reject images with a mismatched build-id: */
566 if (dso->has_build_id) {
567 u8 build_id[BUILD_ID_SIZE];
568
569 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
570 goto out_elf_end;
571
572 if (!dso__build_id_equal(dso, build_id))
573 goto out_elf_end;
574 }
575
576 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
577 if (sec == NULL) {
578 if (want_symtab)
579 goto out_elf_end;
580
581 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
582 if (sec == NULL)
583 goto out_elf_end;
584 }
585
586 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
587 if (opdshdr.sh_type != SHT_PROGBITS)
588 opdsec = NULL;
589 if (opdsec)
590 opddata = elf_rawdata(opdsec, NULL);
591
592 syms = elf_getdata(sec, NULL);
593 if (syms == NULL)
594 goto out_elf_end;
595
596 sec = elf_getscn(elf, shdr.sh_link);
597 if (sec == NULL)
598 goto out_elf_end;
599
600 symstrs = elf_getdata(sec, NULL);
601 if (symstrs == NULL)
602 goto out_elf_end;
603
604 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
605 if (sec_strndx == NULL)
606 goto out_elf_end;
607
608 secstrs = elf_getdata(sec_strndx, NULL);
609 if (secstrs == NULL)
610 goto out_elf_end;
611
612 nr_syms = shdr.sh_size / shdr.sh_entsize;
613
614 memset(&sym, 0, sizeof(sym));
615 if (dso->kernel == DSO_TYPE_USER) {
616 dso->adjust_symbols = (ehdr.e_type == ET_EXEC ||
617 elf_section_by_name(elf, &ehdr, &shdr,
618 ".gnu.prelink_undo",
619 NULL) != NULL);
620 } else {
621 dso->adjust_symbols = 0;
622 }
623 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
624 struct symbol *f;
625 const char *elf_name = elf_sym__name(&sym, symstrs);
626 char *demangled = NULL;
627 int is_label = elf_sym__is_label(&sym);
628 const char *section_name;
629
630 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
631 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
632 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
633
634 if (!is_label && !elf_sym__is_a(&sym, map->type))
635 continue;
636
637 /* Reject ARM ELF "mapping symbols": these aren't unique and
638 * don't identify functions, so will confuse the profile
639 * output: */
640 if (ehdr.e_machine == EM_ARM) {
641 if (!strcmp(elf_name, "$a") ||
642 !strcmp(elf_name, "$d") ||
643 !strcmp(elf_name, "$t"))
644 continue;
645 }
646
647 if (opdsec && sym.st_shndx == opdidx) {
648 u32 offset = sym.st_value - opdshdr.sh_addr;
649 u64 *opd = opddata->d_buf + offset;
650 sym.st_value = DSO__SWAP(dso, u64, *opd);
651 sym.st_shndx = elf_addr_to_index(elf, sym.st_value);
652 }
653
654 sec = elf_getscn(elf, sym.st_shndx);
655 if (!sec)
656 goto out_elf_end;
657
658 gelf_getshdr(sec, &shdr);
659
660 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
661 continue;
662
663 section_name = elf_sec__name(&shdr, secstrs);
664
665 /* On ARM, symbols for thumb functions have 1 added to
666 * the symbol address as a flag - remove it */
667 if ((ehdr.e_machine == EM_ARM) &&
668 (map->type == MAP__FUNCTION) &&
669 (sym.st_value & 1))
670 --sym.st_value;
671
672 if (dso->kernel != DSO_TYPE_USER || kmodule) {
673 char dso_name[PATH_MAX];
674
675 if (strcmp(section_name,
676 (curr_dso->short_name +
677 dso->short_name_len)) == 0)
678 goto new_symbol;
679
680 if (strcmp(section_name, ".text") == 0) {
681 curr_map = map;
682 curr_dso = dso;
683 goto new_symbol;
684 }
685
686 snprintf(dso_name, sizeof(dso_name),
687 "%s%s", dso->short_name, section_name);
688
689 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
690 if (curr_map == NULL) {
691 u64 start = sym.st_value;
692
693 if (kmodule)
694 start += map->start + shdr.sh_offset;
695
696 curr_dso = dso__new(dso_name);
697 if (curr_dso == NULL)
698 goto out_elf_end;
699 curr_dso->kernel = dso->kernel;
700 curr_dso->long_name = dso->long_name;
701 curr_dso->long_name_len = dso->long_name_len;
702 curr_map = map__new2(start, curr_dso,
703 map->type);
704 if (curr_map == NULL) {
705 dso__delete(curr_dso);
706 goto out_elf_end;
707 }
708 curr_map->map_ip = identity__map_ip;
709 curr_map->unmap_ip = identity__map_ip;
710 curr_dso->symtab_type = dso->symtab_type;
711 map_groups__insert(kmap->kmaps, curr_map);
712 dsos__add(&dso->node, curr_dso);
713 dso__set_loaded(curr_dso, map->type);
714 } else
715 curr_dso = curr_map->dso;
716
717 goto new_symbol;
718 }
719
720 if (curr_dso->adjust_symbols) {
721 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
722 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
723 (u64)sym.st_value, (u64)shdr.sh_addr,
724 (u64)shdr.sh_offset);
725 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
726 }
727 /*
728 * We need to figure out if the object was created from C++ sources
729 * DWARF DW_compile_unit has this, but we don't always have access
730 * to it...
731 */
732 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
733 if (demangled != NULL)
734 elf_name = demangled;
735new_symbol:
736 f = symbol__new(sym.st_value, sym.st_size,
737 GELF_ST_BIND(sym.st_info), elf_name);
738 free(demangled);
739 if (!f)
740 goto out_elf_end;
741
742 if (filter && filter(curr_map, f))
743 symbol__delete(f);
744 else {
745 symbols__insert(&curr_dso->symbols[curr_map->type], f);
746 nr++;
747 }
748 }
749
750 /*
751 * For misannotated, zeroed, ASM function sizes.
752 */
753 if (nr > 0) {
754 symbols__fixup_duplicate(&dso->symbols[map->type]);
755 symbols__fixup_end(&dso->symbols[map->type]);
756 if (kmap) {
757 /*
758 * We need to fixup this here too because we create new
759 * maps here, for things like vsyscall sections.
760 */
761 __map_groups__fixup_end(kmap->kmaps, map->type);
762 }
763 }
764 err = nr;
765out_elf_end:
766 elf_end(elf);
767out_close:
768 return err;
769}
770
771void symbol__elf_init(void)
772{
773 elf_version(EV_CURRENT);
774}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index a61fec4518da..f02de8ac842d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,8 +15,6 @@
15#include "symbol.h" 15#include "symbol.h"
16#include "strlist.h" 16#include "strlist.h"
17 17
18#include <libelf.h>
19#include <gelf.h>
20#include <elf.h> 18#include <elf.h>
21#include <limits.h> 19#include <limits.h>
22#include <sys/utsname.h> 20#include <sys/utsname.h>
@@ -25,15 +23,7 @@
25#define KSYM_NAME_LEN 256 23#define KSYM_NAME_LEN 256
26#endif 24#endif
27 25
28#ifndef NT_GNU_BUILD_ID
29#define NT_GNU_BUILD_ID 3
30#endif
31
32static void dso_cache__free(struct rb_root *root); 26static void dso_cache__free(struct rb_root *root);
33static bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
34static int elf_read_build_id(Elf *elf, void *bf, size_t size);
35static void dsos__add(struct list_head *head, struct dso *dso);
36static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
37static int dso__load_kernel_sym(struct dso *dso, struct map *map, 27static int dso__load_kernel_sym(struct dso *dso, struct map *map,
38 symbol_filter_t filter); 28 symbol_filter_t filter);
39static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
@@ -170,7 +160,7 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
170 return SYMBOL_B; 160 return SYMBOL_B;
171} 161}
172 162
173static void symbols__fixup_duplicate(struct rb_root *symbols) 163void symbols__fixup_duplicate(struct rb_root *symbols)
174{ 164{
175 struct rb_node *nd; 165 struct rb_node *nd;
176 struct symbol *curr, *next; 166 struct symbol *curr, *next;
@@ -199,7 +189,7 @@ again:
199 } 189 }
200} 190}
201 191
202static void symbols__fixup_end(struct rb_root *symbols) 192void symbols__fixup_end(struct rb_root *symbols)
203{ 193{
204 struct rb_node *nd, *prevnd = rb_first(symbols); 194 struct rb_node *nd, *prevnd = rb_first(symbols);
205 struct symbol *curr, *prev; 195 struct symbol *curr, *prev;
@@ -222,7 +212,7 @@ static void symbols__fixup_end(struct rb_root *symbols)
222 curr->end = roundup(curr->start, 4096); 212 curr->end = roundup(curr->start, 4096);
223} 213}
224 214
225static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) 215void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
226{ 216{
227 struct map *prev, *curr; 217 struct map *prev, *curr;
228 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); 218 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]);
@@ -252,8 +242,7 @@ static void map_groups__fixup_end(struct map_groups *mg)
252 __map_groups__fixup_end(mg, i); 242 __map_groups__fixup_end(mg, i);
253} 243}
254 244
255static struct symbol *symbol__new(u64 start, u64 len, u8 binding, 245struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
256 const char *name)
257{ 246{
258 size_t namelen = strlen(name) + 1; 247 size_t namelen = strlen(name) + 1;
259 struct symbol *sym = calloc(1, (symbol_conf.priv_size + 248 struct symbol *sym = calloc(1, (symbol_conf.priv_size +
@@ -390,7 +379,7 @@ void dso__set_build_id(struct dso *dso, void *build_id)
390 dso->has_build_id = 1; 379 dso->has_build_id = 1;
391} 380}
392 381
393static void symbols__insert(struct rb_root *symbols, struct symbol *sym) 382void symbols__insert(struct rb_root *symbols, struct symbol *sym)
394{ 383{
395 struct rb_node **p = &symbols->rb_node; 384 struct rb_node **p = &symbols->rb_node;
396 struct rb_node *parent = NULL; 385 struct rb_node *parent = NULL;
@@ -904,561 +893,7 @@ out_failure:
904 return -1; 893 return -1;
905} 894}
906 895
907/** 896bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
908 * elf_symtab__for_each_symbol - iterate thru all the symbols
909 *
910 * @syms: struct elf_symtab instance to iterate
911 * @idx: uint32_t idx
912 * @sym: GElf_Sym iterator
913 */
914#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
915 for (idx = 0, gelf_getsym(syms, idx, &sym);\
916 idx < nr_syms; \
917 idx++, gelf_getsym(syms, idx, &sym))
918
919static inline uint8_t elf_sym__type(const GElf_Sym *sym)
920{
921 return GELF_ST_TYPE(sym->st_info);
922}
923
924static inline int elf_sym__is_function(const GElf_Sym *sym)
925{
926 return elf_sym__type(sym) == STT_FUNC &&
927 sym->st_name != 0 &&
928 sym->st_shndx != SHN_UNDEF;
929}
930
931static inline bool elf_sym__is_object(const GElf_Sym *sym)
932{
933 return elf_sym__type(sym) == STT_OBJECT &&
934 sym->st_name != 0 &&
935 sym->st_shndx != SHN_UNDEF;
936}
937
938static inline int elf_sym__is_label(const GElf_Sym *sym)
939{
940 return elf_sym__type(sym) == STT_NOTYPE &&
941 sym->st_name != 0 &&
942 sym->st_shndx != SHN_UNDEF &&
943 sym->st_shndx != SHN_ABS;
944}
945
946static inline const char *elf_sec__name(const GElf_Shdr *shdr,
947 const Elf_Data *secstrs)
948{
949 return secstrs->d_buf + shdr->sh_name;
950}
951
952static inline int elf_sec__is_text(const GElf_Shdr *shdr,
953 const Elf_Data *secstrs)
954{
955 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
956}
957
958static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
959 const Elf_Data *secstrs)
960{
961 return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
962}
963
964static inline const char *elf_sym__name(const GElf_Sym *sym,
965 const Elf_Data *symstrs)
966{
967 return symstrs->d_buf + sym->st_name;
968}
969
970static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
971 GElf_Shdr *shp, const char *name,
972 size_t *idx)
973{
974 Elf_Scn *sec = NULL;
975 size_t cnt = 1;
976
977 while ((sec = elf_nextscn(elf, sec)) != NULL) {
978 char *str;
979
980 gelf_getshdr(sec, shp);
981 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
982 if (!strcmp(name, str)) {
983 if (idx)
984 *idx = cnt;
985 break;
986 }
987 ++cnt;
988 }
989
990 return sec;
991}
992
993#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
994 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
995 idx < nr_entries; \
996 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
997
998#define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
999 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
1000 idx < nr_entries; \
1001 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
1002
1003/*
1004 * We need to check if we have a .dynsym, so that we can handle the
1005 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
1006 * .dynsym or .symtab).
1007 * And always look at the original dso, not at debuginfo packages, that
1008 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
1009 */
1010static int
1011dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map,
1012 symbol_filter_t filter)
1013{
1014 uint32_t nr_rel_entries, idx;
1015 GElf_Sym sym;
1016 u64 plt_offset;
1017 GElf_Shdr shdr_plt;
1018 struct symbol *f;
1019 GElf_Shdr shdr_rel_plt, shdr_dynsym;
1020 Elf_Data *reldata, *syms, *symstrs;
1021 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
1022 size_t dynsym_idx;
1023 GElf_Ehdr ehdr;
1024 char sympltname[1024];
1025 Elf *elf;
1026 int nr = 0, symidx, fd, err = 0;
1027
1028 fd = open(name, O_RDONLY);
1029 if (fd < 0)
1030 goto out;
1031
1032 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1033 if (elf == NULL)
1034 goto out_close;
1035
1036 if (gelf_getehdr(elf, &ehdr) == NULL)
1037 goto out_elf_end;
1038
1039 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
1040 ".dynsym", &dynsym_idx);
1041 if (scn_dynsym == NULL)
1042 goto out_elf_end;
1043
1044 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
1045 ".rela.plt", NULL);
1046 if (scn_plt_rel == NULL) {
1047 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
1048 ".rel.plt", NULL);
1049 if (scn_plt_rel == NULL)
1050 goto out_elf_end;
1051 }
1052
1053 err = -1;
1054
1055 if (shdr_rel_plt.sh_link != dynsym_idx)
1056 goto out_elf_end;
1057
1058 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
1059 goto out_elf_end;
1060
1061 /*
1062 * Fetch the relocation section to find the idxes to the GOT
1063 * and the symbols in the .dynsym they refer to.
1064 */
1065 reldata = elf_getdata(scn_plt_rel, NULL);
1066 if (reldata == NULL)
1067 goto out_elf_end;
1068
1069 syms = elf_getdata(scn_dynsym, NULL);
1070 if (syms == NULL)
1071 goto out_elf_end;
1072
1073 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
1074 if (scn_symstrs == NULL)
1075 goto out_elf_end;
1076
1077 symstrs = elf_getdata(scn_symstrs, NULL);
1078 if (symstrs == NULL)
1079 goto out_elf_end;
1080
1081 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
1082 plt_offset = shdr_plt.sh_offset;
1083
1084 if (shdr_rel_plt.sh_type == SHT_RELA) {
1085 GElf_Rela pos_mem, *pos;
1086
1087 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
1088 nr_rel_entries) {
1089 symidx = GELF_R_SYM(pos->r_info);
1090 plt_offset += shdr_plt.sh_entsize;
1091 gelf_getsym(syms, symidx, &sym);
1092 snprintf(sympltname, sizeof(sympltname),
1093 "%s@plt", elf_sym__name(&sym, symstrs));
1094
1095 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
1096 STB_GLOBAL, sympltname);
1097 if (!f)
1098 goto out_elf_end;
1099
1100 if (filter && filter(map, f))
1101 symbol__delete(f);
1102 else {
1103 symbols__insert(&dso->symbols[map->type], f);
1104 ++nr;
1105 }
1106 }
1107 } else if (shdr_rel_plt.sh_type == SHT_REL) {
1108 GElf_Rel pos_mem, *pos;
1109 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
1110 nr_rel_entries) {
1111 symidx = GELF_R_SYM(pos->r_info);
1112 plt_offset += shdr_plt.sh_entsize;
1113 gelf_getsym(syms, symidx, &sym);
1114 snprintf(sympltname, sizeof(sympltname),
1115 "%s@plt", elf_sym__name(&sym, symstrs));
1116
1117 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
1118 STB_GLOBAL, sympltname);
1119 if (!f)
1120 goto out_elf_end;
1121
1122 if (filter && filter(map, f))
1123 symbol__delete(f);
1124 else {
1125 symbols__insert(&dso->symbols[map->type], f);
1126 ++nr;
1127 }
1128 }
1129 }
1130
1131 err = 0;
1132out_elf_end:
1133 elf_end(elf);
1134out_close:
1135 close(fd);
1136
1137 if (err == 0)
1138 return nr;
1139out:
1140 pr_debug("%s: problems reading %s PLT info.\n",
1141 __func__, dso->long_name);
1142 return 0;
1143}
1144
1145static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type)
1146{
1147 switch (type) {
1148 case MAP__FUNCTION:
1149 return elf_sym__is_function(sym);
1150 case MAP__VARIABLE:
1151 return elf_sym__is_object(sym);
1152 default:
1153 return false;
1154 }
1155}
1156
1157static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs,
1158 enum map_type type)
1159{
1160 switch (type) {
1161 case MAP__FUNCTION:
1162 return elf_sec__is_text(shdr, secstrs);
1163 case MAP__VARIABLE:
1164 return elf_sec__is_data(shdr, secstrs);
1165 default:
1166 return false;
1167 }
1168}
1169
1170static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
1171{
1172 Elf_Scn *sec = NULL;
1173 GElf_Shdr shdr;
1174 size_t cnt = 1;
1175
1176 while ((sec = elf_nextscn(elf, sec)) != NULL) {
1177 gelf_getshdr(sec, &shdr);
1178
1179 if ((addr >= shdr.sh_addr) &&
1180 (addr < (shdr.sh_addr + shdr.sh_size)))
1181 return cnt;
1182
1183 ++cnt;
1184 }
1185
1186 return -1;
1187}
1188
1189static int dso__swap_init(struct dso *dso, unsigned char eidata)
1190{
1191 static unsigned int const endian = 1;
1192
1193 dso->needs_swap = DSO_SWAP__NO;
1194
1195 switch (eidata) {
1196 case ELFDATA2LSB:
1197 /* We are big endian, DSO is little endian. */
1198 if (*(unsigned char const *)&endian != 1)
1199 dso->needs_swap = DSO_SWAP__YES;
1200 break;
1201
1202 case ELFDATA2MSB:
1203 /* We are little endian, DSO is big endian. */
1204 if (*(unsigned char const *)&endian != 0)
1205 dso->needs_swap = DSO_SWAP__YES;
1206 break;
1207
1208 default:
1209 pr_err("unrecognized DSO data encoding %d\n", eidata);
1210 return -EINVAL;
1211 }
1212
1213 return 0;
1214}
1215
1216static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1217 int fd, symbol_filter_t filter, int kmodule,
1218 int want_symtab)
1219{
1220 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
1221 struct map *curr_map = map;
1222 struct dso *curr_dso = dso;
1223 Elf_Data *symstrs, *secstrs;
1224 uint32_t nr_syms;
1225 int err = -1;
1226 uint32_t idx;
1227 GElf_Ehdr ehdr;
1228 GElf_Shdr shdr, opdshdr;
1229 Elf_Data *syms, *opddata = NULL;
1230 GElf_Sym sym;
1231 Elf_Scn *sec, *sec_strndx, *opdsec;
1232 Elf *elf;
1233 int nr = 0;
1234 size_t opdidx = 0;
1235
1236 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1237 if (elf == NULL) {
1238 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
1239 goto out_close;
1240 }
1241
1242 if (gelf_getehdr(elf, &ehdr) == NULL) {
1243 pr_debug("%s: cannot get elf header.\n", __func__);
1244 goto out_elf_end;
1245 }
1246
1247 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
1248 goto out_elf_end;
1249
1250 /* Always reject images with a mismatched build-id: */
1251 if (dso->has_build_id) {
1252 u8 build_id[BUILD_ID_SIZE];
1253
1254 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
1255 goto out_elf_end;
1256
1257 if (!dso__build_id_equal(dso, build_id))
1258 goto out_elf_end;
1259 }
1260
1261 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
1262 if (sec == NULL) {
1263 if (want_symtab)
1264 goto out_elf_end;
1265
1266 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
1267 if (sec == NULL)
1268 goto out_elf_end;
1269 }
1270
1271 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
1272 if (opdshdr.sh_type != SHT_PROGBITS)
1273 opdsec = NULL;
1274 if (opdsec)
1275 opddata = elf_rawdata(opdsec, NULL);
1276
1277 syms = elf_getdata(sec, NULL);
1278 if (syms == NULL)
1279 goto out_elf_end;
1280
1281 sec = elf_getscn(elf, shdr.sh_link);
1282 if (sec == NULL)
1283 goto out_elf_end;
1284
1285 symstrs = elf_getdata(sec, NULL);
1286 if (symstrs == NULL)
1287 goto out_elf_end;
1288
1289 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
1290 if (sec_strndx == NULL)
1291 goto out_elf_end;
1292
1293 secstrs = elf_getdata(sec_strndx, NULL);
1294 if (secstrs == NULL)
1295 goto out_elf_end;
1296
1297 nr_syms = shdr.sh_size / shdr.sh_entsize;
1298
1299 memset(&sym, 0, sizeof(sym));
1300 if (dso->kernel == DSO_TYPE_USER) {
1301 dso->adjust_symbols = (ehdr.e_type == ET_EXEC ||
1302 elf_section_by_name(elf, &ehdr, &shdr,
1303 ".gnu.prelink_undo",
1304 NULL) != NULL);
1305 } else {
1306 dso->adjust_symbols = 0;
1307 }
1308 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
1309 struct symbol *f;
1310 const char *elf_name = elf_sym__name(&sym, symstrs);
1311 char *demangled = NULL;
1312 int is_label = elf_sym__is_label(&sym);
1313 const char *section_name;
1314
1315 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
1316 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
1317 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
1318
1319 if (!is_label && !elf_sym__is_a(&sym, map->type))
1320 continue;
1321
1322 /* Reject ARM ELF "mapping symbols": these aren't unique and
1323 * don't identify functions, so will confuse the profile
1324 * output: */
1325 if (ehdr.e_machine == EM_ARM) {
1326 if (!strcmp(elf_name, "$a") ||
1327 !strcmp(elf_name, "$d") ||
1328 !strcmp(elf_name, "$t"))
1329 continue;
1330 }
1331
1332 if (opdsec && sym.st_shndx == opdidx) {
1333 u32 offset = sym.st_value - opdshdr.sh_addr;
1334 u64 *opd = opddata->d_buf + offset;
1335 sym.st_value = DSO__SWAP(dso, u64, *opd);
1336 sym.st_shndx = elf_addr_to_index(elf, sym.st_value);
1337 }
1338
1339 sec = elf_getscn(elf, sym.st_shndx);
1340 if (!sec)
1341 goto out_elf_end;
1342
1343 gelf_getshdr(sec, &shdr);
1344
1345 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
1346 continue;
1347
1348 section_name = elf_sec__name(&shdr, secstrs);
1349
1350 /* On ARM, symbols for thumb functions have 1 added to
1351 * the symbol address as a flag - remove it */
1352 if ((ehdr.e_machine == EM_ARM) &&
1353 (map->type == MAP__FUNCTION) &&
1354 (sym.st_value & 1))
1355 --sym.st_value;
1356
1357 if (dso->kernel != DSO_TYPE_USER || kmodule) {
1358 char dso_name[PATH_MAX];
1359
1360 if (strcmp(section_name,
1361 (curr_dso->short_name +
1362 dso->short_name_len)) == 0)
1363 goto new_symbol;
1364
1365 if (strcmp(section_name, ".text") == 0) {
1366 curr_map = map;
1367 curr_dso = dso;
1368 goto new_symbol;
1369 }
1370
1371 snprintf(dso_name, sizeof(dso_name),
1372 "%s%s", dso->short_name, section_name);
1373
1374 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
1375 if (curr_map == NULL) {
1376 u64 start = sym.st_value;
1377
1378 if (kmodule)
1379 start += map->start + shdr.sh_offset;
1380
1381 curr_dso = dso__new(dso_name);
1382 if (curr_dso == NULL)
1383 goto out_elf_end;
1384 curr_dso->kernel = dso->kernel;
1385 curr_dso->long_name = dso->long_name;
1386 curr_dso->long_name_len = dso->long_name_len;
1387 curr_map = map__new2(start, curr_dso,
1388 map->type);
1389 if (curr_map == NULL) {
1390 dso__delete(curr_dso);
1391 goto out_elf_end;
1392 }
1393 curr_map->map_ip = identity__map_ip;
1394 curr_map->unmap_ip = identity__map_ip;
1395 curr_dso->symtab_type = dso->symtab_type;
1396 map_groups__insert(kmap->kmaps, curr_map);
1397 dsos__add(&dso->node, curr_dso);
1398 dso__set_loaded(curr_dso, map->type);
1399 } else
1400 curr_dso = curr_map->dso;
1401
1402 goto new_symbol;
1403 }
1404
1405 if (curr_dso->adjust_symbols) {
1406 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
1407 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
1408 (u64)sym.st_value, (u64)shdr.sh_addr,
1409 (u64)shdr.sh_offset);
1410 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
1411 }
1412 /*
1413 * We need to figure out if the object was created from C++ sources
1414 * DWARF DW_compile_unit has this, but we don't always have access
1415 * to it...
1416 */
1417 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
1418 if (demangled != NULL)
1419 elf_name = demangled;
1420new_symbol:
1421 f = symbol__new(sym.st_value, sym.st_size,
1422 GELF_ST_BIND(sym.st_info), elf_name);
1423 free(demangled);
1424 if (!f)
1425 goto out_elf_end;
1426
1427 if (filter && filter(curr_map, f))
1428 symbol__delete(f);
1429 else {
1430 symbols__insert(&curr_dso->symbols[curr_map->type], f);
1431 nr++;
1432 }
1433 }
1434
1435 /*
1436 * For misannotated, zeroed, ASM function sizes.
1437 */
1438 if (nr > 0) {
1439 symbols__fixup_duplicate(&dso->symbols[map->type]);
1440 symbols__fixup_end(&dso->symbols[map->type]);
1441 if (kmap) {
1442 /*
1443 * We need to fixup this here too because we create new
1444 * maps here, for things like vsyscall sections.
1445 */
1446 __map_groups__fixup_end(kmap->kmaps, map->type);
1447 }
1448 }
1449 err = nr;
1450out_elf_end:
1451 elf_end(elf);
1452out_close:
1453 return err;
1454}
1455
1456void symbol__elf_init(void)
1457{
1458 elf_version(EV_CURRENT);
1459}
1460
1461static bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
1462{ 897{
1463 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0; 898 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
1464} 899}
@@ -1485,212 +920,6 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1485 return have_build_id; 920 return have_build_id;
1486} 921}
1487 922
1488/*
1489 * Align offset to 4 bytes as needed for note name and descriptor data.
1490 */
1491#define NOTE_ALIGN(n) (((n) + 3) & -4U)
1492
1493static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1494{
1495 int err = -1;
1496 GElf_Ehdr ehdr;
1497 GElf_Shdr shdr;
1498 Elf_Data *data;
1499 Elf_Scn *sec;
1500 Elf_Kind ek;
1501 void *ptr;
1502
1503 if (size < BUILD_ID_SIZE)
1504 goto out;
1505
1506 ek = elf_kind(elf);
1507 if (ek != ELF_K_ELF)
1508 goto out;
1509
1510 if (gelf_getehdr(elf, &ehdr) == NULL) {
1511 pr_err("%s: cannot get elf header.\n", __func__);
1512 goto out;
1513 }
1514
1515 /*
1516 * Check following sections for notes:
1517 * '.note.gnu.build-id'
1518 * '.notes'
1519 * '.note' (VDSO specific)
1520 */
1521 do {
1522 sec = elf_section_by_name(elf, &ehdr, &shdr,
1523 ".note.gnu.build-id", NULL);
1524 if (sec)
1525 break;
1526
1527 sec = elf_section_by_name(elf, &ehdr, &shdr,
1528 ".notes", NULL);
1529 if (sec)
1530 break;
1531
1532 sec = elf_section_by_name(elf, &ehdr, &shdr,
1533 ".note", NULL);
1534 if (sec)
1535 break;
1536
1537 return err;
1538
1539 } while (0);
1540
1541 data = elf_getdata(sec, NULL);
1542 if (data == NULL)
1543 goto out;
1544
1545 ptr = data->d_buf;
1546 while (ptr < (data->d_buf + data->d_size)) {
1547 GElf_Nhdr *nhdr = ptr;
1548 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
1549 descsz = NOTE_ALIGN(nhdr->n_descsz);
1550 const char *name;
1551
1552 ptr += sizeof(*nhdr);
1553 name = ptr;
1554 ptr += namesz;
1555 if (nhdr->n_type == NT_GNU_BUILD_ID &&
1556 nhdr->n_namesz == sizeof("GNU")) {
1557 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
1558 size_t sz = min(size, descsz);
1559 memcpy(bf, ptr, sz);
1560 memset(bf + sz, 0, size - sz);
1561 err = descsz;
1562 break;
1563 }
1564 }
1565 ptr += descsz;
1566 }
1567
1568out:
1569 return err;
1570}
1571
1572int filename__read_build_id(const char *filename, void *bf, size_t size)
1573{
1574 int fd, err = -1;
1575 Elf *elf;
1576
1577 if (size < BUILD_ID_SIZE)
1578 goto out;
1579
1580 fd = open(filename, O_RDONLY);
1581 if (fd < 0)
1582 goto out;
1583
1584 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1585 if (elf == NULL) {
1586 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1587 goto out_close;
1588 }
1589
1590 err = elf_read_build_id(elf, bf, size);
1591
1592 elf_end(elf);
1593out_close:
1594 close(fd);
1595out:
1596 return err;
1597}
1598
1599int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1600{
1601 int fd, err = -1;
1602
1603 if (size < BUILD_ID_SIZE)
1604 goto out;
1605
1606 fd = open(filename, O_RDONLY);
1607 if (fd < 0)
1608 goto out;
1609
1610 while (1) {
1611 char bf[BUFSIZ];
1612 GElf_Nhdr nhdr;
1613 size_t namesz, descsz;
1614
1615 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1616 break;
1617
1618 namesz = NOTE_ALIGN(nhdr.n_namesz);
1619 descsz = NOTE_ALIGN(nhdr.n_descsz);
1620 if (nhdr.n_type == NT_GNU_BUILD_ID &&
1621 nhdr.n_namesz == sizeof("GNU")) {
1622 if (read(fd, bf, namesz) != (ssize_t)namesz)
1623 break;
1624 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1625 size_t sz = min(descsz, size);
1626 if (read(fd, build_id, sz) == (ssize_t)sz) {
1627 memset(build_id + sz, 0, size - sz);
1628 err = 0;
1629 break;
1630 }
1631 } else if (read(fd, bf, descsz) != (ssize_t)descsz)
1632 break;
1633 } else {
1634 int n = namesz + descsz;
1635 if (read(fd, bf, n) != n)
1636 break;
1637 }
1638 }
1639 close(fd);
1640out:
1641 return err;
1642}
1643
1644static int filename__read_debuglink(const char *filename,
1645 char *debuglink, size_t size)
1646{
1647 int fd, err = -1;
1648 Elf *elf;
1649 GElf_Ehdr ehdr;
1650 GElf_Shdr shdr;
1651 Elf_Data *data;
1652 Elf_Scn *sec;
1653 Elf_Kind ek;
1654
1655 fd = open(filename, O_RDONLY);
1656 if (fd < 0)
1657 goto out;
1658
1659 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1660 if (elf == NULL) {
1661 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1662 goto out_close;
1663 }
1664
1665 ek = elf_kind(elf);
1666 if (ek != ELF_K_ELF)
1667 goto out_close;
1668
1669 if (gelf_getehdr(elf, &ehdr) == NULL) {
1670 pr_err("%s: cannot get elf header.\n", __func__);
1671 goto out_close;
1672 }
1673
1674 sec = elf_section_by_name(elf, &ehdr, &shdr,
1675 ".gnu_debuglink", NULL);
1676 if (sec == NULL)
1677 goto out_close;
1678
1679 data = elf_getdata(sec, NULL);
1680 if (data == NULL)
1681 goto out_close;
1682
1683 /* the start of this section is a zero-terminated string */
1684 strncpy(debuglink, data->d_buf, size);
1685
1686 elf_end(elf);
1687
1688out_close:
1689 close(fd);
1690out:
1691 return err;
1692}
1693
1694char dso__symtab_origin(const struct dso *dso) 923char dso__symtab_origin(const struct dso *dso)
1695{ 924{
1696 static const char origin[] = { 925 static const char origin[] = {
@@ -2035,25 +1264,6 @@ static int machine__set_modules_path(struct machine *machine)
2035 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 1264 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
2036} 1265}
2037 1266
2038/*
2039 * Constructor variant for modules (where we know from /proc/modules where
2040 * they are loaded) and for vmlinux, where only after we load all the
2041 * symbols we'll know where it starts and ends.
2042 */
2043static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
2044{
2045 struct map *map = calloc(1, (sizeof(*map) +
2046 (dso->kernel ? sizeof(struct kmap) : 0)));
2047 if (map != NULL) {
2048 /*
2049 * ->end will be filled after we load all the symbols
2050 */
2051 map__init(map, type, start, 0, 0, dso);
2052 }
2053
2054 return map;
2055}
2056
2057struct map *machine__new_module(struct machine *machine, u64 start, 1267struct map *machine__new_module(struct machine *machine, u64 start,
2058 const char *filename) 1268 const char *filename)
2059{ 1269{
@@ -2357,7 +1567,7 @@ out_try_fixup:
2357 return err; 1567 return err;
2358} 1568}
2359 1569
2360static void dsos__add(struct list_head *head, struct dso *dso) 1570void dsos__add(struct list_head *head, struct dso *dso)
2361{ 1571{
2362 list_add_tail(&dso->node, head); 1572 list_add_tail(&dso->node, head);
2363} 1573}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 355993d3abbf..38ccbbb39faa 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -254,6 +254,7 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type)
254 254
255void dso__sort_by_name(struct dso *dso, enum map_type type); 255void dso__sort_by_name(struct dso *dso, enum map_type type);
256 256
257void dsos__add(struct list_head *head, struct dso *dso);
257struct dso *__dsos__findnew(struct list_head *head, const char *name); 258struct dso *__dsos__findnew(struct list_head *head, const char *name);
258 259
259int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 260int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
@@ -283,6 +284,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
283char dso__symtab_origin(const struct dso *dso); 284char dso__symtab_origin(const struct dso *dso);
284void dso__set_long_name(struct dso *dso, char *name); 285void dso__set_long_name(struct dso *dso, char *name);
285void dso__set_build_id(struct dso *dso, void *build_id); 286void dso__set_build_id(struct dso *dso, void *build_id);
287bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
286void dso__read_running_kernel_build_id(struct dso *dso, 288void dso__read_running_kernel_build_id(struct dso *dso,
287 struct machine *machine); 289 struct machine *machine);
288struct map *dso__new_map(const char *name); 290struct map *dso__new_map(const char *name);
@@ -298,6 +300,8 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf);
298int kallsyms__parse(const char *filename, void *arg, 300int kallsyms__parse(const char *filename, void *arg,
299 int (*process_symbol)(void *arg, const char *name, 301 int (*process_symbol)(void *arg, const char *name,
300 char type, u64 start, u64 end)); 302 char type, u64 start, u64 end));
303int filename__read_debuglink(const char *filename, char *debuglink,
304 size_t size);
301 305
302void machine__destroy_kernel_maps(struct machine *machine); 306void machine__destroy_kernel_maps(struct machine *machine);
303int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); 307int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
@@ -310,6 +314,7 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
310int symbol__init(void); 314int symbol__init(void);
311void symbol__exit(void); 315void symbol__exit(void);
312void symbol__elf_init(void); 316void symbol__elf_init(void);
317struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
313size_t symbol__fprintf_symname_offs(const struct symbol *sym, 318size_t symbol__fprintf_symname_offs(const struct symbol *sym,
314 const struct addr_location *al, FILE *fp); 319 const struct addr_location *al, FILE *fp);
315size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 320size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
@@ -327,4 +332,14 @@ ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
327 struct machine *machine, u64 addr, 332 struct machine *machine, u64 addr,
328 u8 *data, ssize_t size); 333 u8 *data, ssize_t size);
329int dso__test_data(void); 334int dso__test_data(void);
335int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd,
336 symbol_filter_t filter, int kmodule, int want_symtab);
337int dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map,
338 symbol_filter_t filter);
339
340void symbols__insert(struct rb_root *symbols, struct symbol *sym);
341void symbols__fixup_duplicate(struct rb_root *symbols);
342void symbols__fixup_end(struct rb_root *symbols);
343void __map_groups__fixup_end(struct map_groups *mg, enum map_type type);
344
330#endif /* __PERF_SYMBOL */ 345#endif /* __PERF_SYMBOL */