11 const char *sym_hist_filter
;
14 #define DMGL_PARAMS (1 << 0) /* Include function args */
15 #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
18 static struct symbol
*symbol__new(u64 start
, u64 len
,
19 const char *name
, unsigned int priv_size
,
20 u64 obj_start
, int verbose
)
22 size_t namelen
= strlen(name
) + 1;
23 struct symbol
*self
= calloc(1, priv_size
+ sizeof(*self
) + namelen
);
29 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n",
30 (u64
)start
, (unsigned long)len
, name
, self
->hist
, (void *)(unsigned long)obj_start
);
32 self
->obj_start
= obj_start
;
36 if (sym_hist_filter
&& !strcmp(name
, sym_hist_filter
))
37 self
->hist
= calloc(sizeof(u64
), len
);
40 memset(self
, 0, priv_size
);
41 self
= ((void *)self
) + priv_size
;
44 self
->end
= len
? start
+ len
- 1 : start
;
45 memcpy(self
->name
, name
, namelen
);
50 static void symbol__delete(struct symbol
*self
, unsigned int priv_size
)
52 free(((void *)self
) - priv_size
);
55 static size_t symbol__fprintf(struct symbol
*self
, FILE *fp
)
58 return fprintf(fp
, " %llx-%llx %s\n",
59 self
->start
, self
->end
, self
->name
);
61 return fprintf(fp
, " %llx-%llx %s \t[%s]\n",
62 self
->start
, self
->end
, self
->name
, self
->module
->name
);
65 struct dso
*dso__new(const char *name
, unsigned int sym_priv_size
)
67 struct dso
*self
= malloc(sizeof(*self
) + strlen(name
) + 1);
70 strcpy(self
->name
, name
);
72 self
->sym_priv_size
= sym_priv_size
;
73 self
->find_symbol
= dso__find_symbol
;
74 self
->slen_calculated
= 0;
80 static void dso__delete_symbols(struct dso
*self
)
83 struct rb_node
*next
= rb_first(&self
->syms
);
86 pos
= rb_entry(next
, struct symbol
, rb_node
);
87 next
= rb_next(&pos
->rb_node
);
88 rb_erase(&pos
->rb_node
, &self
->syms
);
89 symbol__delete(pos
, self
->sym_priv_size
);
93 void dso__delete(struct dso
*self
)
95 dso__delete_symbols(self
);
99 static void dso__insert_symbol(struct dso
*self
, struct symbol
*sym
)
101 struct rb_node
**p
= &self
->syms
.rb_node
;
102 struct rb_node
*parent
= NULL
;
103 const u64 ip
= sym
->start
;
108 s
= rb_entry(parent
, struct symbol
, rb_node
);
114 rb_link_node(&sym
->rb_node
, parent
, p
);
115 rb_insert_color(&sym
->rb_node
, &self
->syms
);
118 struct symbol
*dso__find_symbol(struct dso
*self
, u64 ip
)
125 n
= self
->syms
.rb_node
;
128 struct symbol
*s
= rb_entry(n
, struct symbol
, rb_node
);
132 else if (ip
> s
->end
)
141 size_t dso__fprintf(struct dso
*self
, FILE *fp
)
143 size_t ret
= fprintf(fp
, "dso: %s\n", self
->name
);
146 for (nd
= rb_first(&self
->syms
); nd
; nd
= rb_next(nd
)) {
147 struct symbol
*pos
= rb_entry(nd
, struct symbol
, rb_node
);
148 ret
+= symbol__fprintf(pos
, fp
);
154 static int dso__load_kallsyms(struct dso
*self
, symbol_filter_t filter
, int verbose
)
156 struct rb_node
*nd
, *prevnd
;
159 FILE *file
= fopen("/proc/kallsyms", "r");
165 while (!feof(file
)) {
171 line_len
= getline(&line
, &n
, file
);
178 line
[--line_len
] = '\0'; /* \n */
180 len
= hex2u64(line
, &start
);
183 if (len
+ 2 >= line_len
)
186 symbol_type
= toupper(line
[len
]);
188 * We're interested only in code ('T'ext)
190 if (symbol_type
!= 'T' && symbol_type
!= 'W')
193 * Well fix up the end later, when we have all sorted.
195 sym
= symbol__new(start
, 0xdead, line
+ len
+ 2,
196 self
->sym_priv_size
, 0, verbose
);
199 goto out_delete_line
;
201 if (filter
&& filter(self
, sym
))
202 symbol__delete(sym
, self
->sym_priv_size
);
204 dso__insert_symbol(self
, sym
);
210 * Now that we have all sorted out, just set the ->end of all
213 prevnd
= rb_first(&self
->syms
);
216 goto out_delete_line
;
218 for (nd
= rb_next(prevnd
); nd
; nd
= rb_next(nd
)) {
219 struct symbol
*prev
= rb_entry(prevnd
, struct symbol
, rb_node
),
220 *curr
= rb_entry(nd
, struct symbol
, rb_node
);
222 prev
->end
= curr
->start
- 1;
237 static int dso__load_perf_map(struct dso
*self
, symbol_filter_t filter
, int verbose
)
244 file
= fopen(self
->name
, "r");
248 while (!feof(file
)) {
253 line_len
= getline(&line
, &n
, file
);
260 line
[--line_len
] = '\0'; /* \n */
262 len
= hex2u64(line
, &start
);
265 if (len
+ 2 >= line_len
)
268 len
+= hex2u64(line
+ len
, &size
);
271 if (len
+ 2 >= line_len
)
274 sym
= symbol__new(start
, size
, line
+ len
,
275 self
->sym_priv_size
, start
, verbose
);
278 goto out_delete_line
;
280 if (filter
&& filter(self
, sym
))
281 symbol__delete(sym
, self
->sym_priv_size
);
283 dso__insert_symbol(self
, sym
);
300 * elf_symtab__for_each_symbol - iterate thru all the symbols
302 * @self: struct elf_symtab instance to iterate
303 * @index: uint32_t index
304 * @sym: GElf_Sym iterator
306 #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \
307 for (index = 0, gelf_getsym(syms, index, &sym);\
309 index++, gelf_getsym(syms, index, &sym))
311 static inline uint8_t elf_sym__type(const GElf_Sym
*sym
)
313 return GELF_ST_TYPE(sym
->st_info
);
316 static inline int elf_sym__is_function(const GElf_Sym
*sym
)
318 return elf_sym__type(sym
) == STT_FUNC
&&
320 sym
->st_shndx
!= SHN_UNDEF
&&
324 static inline int elf_sym__is_label(const GElf_Sym
*sym
)
326 return elf_sym__type(sym
) == STT_NOTYPE
&&
328 sym
->st_shndx
!= SHN_UNDEF
&&
329 sym
->st_shndx
!= SHN_ABS
;
332 static inline const char *elf_sec__name(const GElf_Shdr
*shdr
,
333 const Elf_Data
*secstrs
)
335 return secstrs
->d_buf
+ shdr
->sh_name
;
338 static inline int elf_sec__is_text(const GElf_Shdr
*shdr
,
339 const Elf_Data
*secstrs
)
341 return strstr(elf_sec__name(shdr
, secstrs
), "text") != NULL
;
344 static inline const char *elf_sym__name(const GElf_Sym
*sym
,
345 const Elf_Data
*symstrs
)
347 return symstrs
->d_buf
+ sym
->st_name
;
350 static Elf_Scn
*elf_section_by_name(Elf
*elf
, GElf_Ehdr
*ep
,
351 GElf_Shdr
*shp
, const char *name
,
357 while ((sec
= elf_nextscn(elf
, sec
)) != NULL
) {
360 gelf_getshdr(sec
, shp
);
361 str
= elf_strptr(elf
, ep
->e_shstrndx
, shp
->sh_name
);
362 if (!strcmp(name
, str
)) {
373 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
374 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
376 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
378 #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
379 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
381 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
384 * We need to check if we have a .dynsym, so that we can handle the
385 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
386 * .dynsym or .symtab).
387 * And always look at the original dso, not at debuginfo packages, that
388 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
390 static int dso__synthesize_plt_symbols(struct dso
*self
, int verbose
)
392 uint32_t nr_rel_entries
, idx
;
397 GElf_Shdr shdr_rel_plt
, shdr_dynsym
;
398 Elf_Data
*reldata
, *syms
, *symstrs
;
399 Elf_Scn
*scn_plt_rel
, *scn_symstrs
, *scn_dynsym
;
402 char sympltname
[1024];
404 int nr
= 0, symidx
, fd
, err
= 0;
406 fd
= open(self
->name
, O_RDONLY
);
410 elf
= elf_begin(fd
, ELF_C_READ_MMAP
, NULL
);
414 if (gelf_getehdr(elf
, &ehdr
) == NULL
)
417 scn_dynsym
= elf_section_by_name(elf
, &ehdr
, &shdr_dynsym
,
418 ".dynsym", &dynsym_idx
);
419 if (scn_dynsym
== NULL
)
422 scn_plt_rel
= elf_section_by_name(elf
, &ehdr
, &shdr_rel_plt
,
424 if (scn_plt_rel
== NULL
) {
425 scn_plt_rel
= elf_section_by_name(elf
, &ehdr
, &shdr_rel_plt
,
427 if (scn_plt_rel
== NULL
)
433 if (shdr_rel_plt
.sh_link
!= dynsym_idx
)
436 if (elf_section_by_name(elf
, &ehdr
, &shdr_plt
, ".plt", NULL
) == NULL
)
440 * Fetch the relocation section to find the indexes to the GOT
441 * and the symbols in the .dynsym they refer to.
443 reldata
= elf_getdata(scn_plt_rel
, NULL
);
447 syms
= elf_getdata(scn_dynsym
, NULL
);
451 scn_symstrs
= elf_getscn(elf
, shdr_dynsym
.sh_link
);
452 if (scn_symstrs
== NULL
)
455 symstrs
= elf_getdata(scn_symstrs
, NULL
);
459 nr_rel_entries
= shdr_rel_plt
.sh_size
/ shdr_rel_plt
.sh_entsize
;
460 plt_offset
= shdr_plt
.sh_offset
;
462 if (shdr_rel_plt
.sh_type
== SHT_RELA
) {
463 GElf_Rela pos_mem
, *pos
;
465 elf_section__for_each_rela(reldata
, pos
, pos_mem
, idx
,
467 symidx
= GELF_R_SYM(pos
->r_info
);
468 plt_offset
+= shdr_plt
.sh_entsize
;
469 gelf_getsym(syms
, symidx
, &sym
);
470 snprintf(sympltname
, sizeof(sympltname
),
471 "%s@plt", elf_sym__name(&sym
, symstrs
));
473 f
= symbol__new(plt_offset
, shdr_plt
.sh_entsize
,
474 sympltname
, self
->sym_priv_size
, 0, verbose
);
478 dso__insert_symbol(self
, f
);
481 } else if (shdr_rel_plt
.sh_type
== SHT_REL
) {
482 GElf_Rel pos_mem
, *pos
;
483 elf_section__for_each_rel(reldata
, pos
, pos_mem
, idx
,
485 symidx
= GELF_R_SYM(pos
->r_info
);
486 plt_offset
+= shdr_plt
.sh_entsize
;
487 gelf_getsym(syms
, symidx
, &sym
);
488 snprintf(sympltname
, sizeof(sympltname
),
489 "%s@plt", elf_sym__name(&sym
, symstrs
));
491 f
= symbol__new(plt_offset
, shdr_plt
.sh_entsize
,
492 sympltname
, self
->sym_priv_size
, 0, verbose
);
496 dso__insert_symbol(self
, f
);
510 fprintf(stderr
, "%s: problems reading %s PLT info.\n",
511 __func__
, self
->name
);
515 static int dso__load_sym(struct dso
*self
, int fd
, const char *name
,
516 symbol_filter_t filter
, int verbose
, struct module
*mod
)
518 Elf_Data
*symstrs
, *secstrs
;
526 Elf_Scn
*sec
, *sec_strndx
;
528 int nr
= 0, kernel
= !strcmp("[kernel]", self
->name
);
530 elf
= elf_begin(fd
, ELF_C_READ_MMAP
, NULL
);
533 fprintf(stderr
, "%s: cannot read %s ELF file.\n",
538 if (gelf_getehdr(elf
, &ehdr
) == NULL
) {
540 fprintf(stderr
, "%s: cannot get elf header.\n", __func__
);
544 sec
= elf_section_by_name(elf
, &ehdr
, &shdr
, ".symtab", NULL
);
546 sec
= elf_section_by_name(elf
, &ehdr
, &shdr
, ".dynsym", NULL
);
551 syms
= elf_getdata(sec
, NULL
);
555 sec
= elf_getscn(elf
, shdr
.sh_link
);
559 symstrs
= elf_getdata(sec
, NULL
);
563 sec_strndx
= elf_getscn(elf
, ehdr
.e_shstrndx
);
564 if (sec_strndx
== NULL
)
567 secstrs
= elf_getdata(sec_strndx
, NULL
);
571 nr_syms
= shdr
.sh_size
/ shdr
.sh_entsize
;
573 memset(&sym
, 0, sizeof(sym
));
575 self
->adjust_symbols
= (ehdr
.e_type
== ET_EXEC
||
576 elf_section_by_name(elf
, &ehdr
, &shdr
,
579 } else self
->adjust_symbols
= 0;
581 elf_symtab__for_each_symbol(syms
, nr_syms
, index
, sym
) {
586 struct section
*section
= NULL
;
587 int is_label
= elf_sym__is_label(&sym
);
588 const char *section_name
;
590 if (!is_label
&& !elf_sym__is_function(&sym
))
593 sec
= elf_getscn(elf
, sym
.st_shndx
);
597 gelf_getshdr(sec
, &shdr
);
599 if (is_label
&& !elf_sec__is_text(&shdr
, secstrs
))
602 section_name
= elf_sec__name(&shdr
, secstrs
);
603 obj_start
= sym
.st_value
;
605 if (self
->adjust_symbols
) {
607 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
608 (u64
)sym
.st_value
, (u64
)shdr
.sh_addr
, (u64
)shdr
.sh_offset
);
610 sym
.st_value
-= shdr
.sh_addr
- shdr
.sh_offset
;
614 section
= mod
->sections
->find_section(mod
->sections
, section_name
);
616 sym
.st_value
+= section
->vma
;
618 fprintf(stderr
, "dso__load_sym() module %s lookup of %s failed\n",
619 mod
->name
, section_name
);
624 * We need to figure out if the object was created from C++ sources
625 * DWARF DW_compile_unit has this, but we don't always have access
628 name
= elf_sym__name(&sym
, symstrs
);
629 demangled
= bfd_demangle(NULL
, name
, DMGL_PARAMS
| DMGL_ANSI
);
630 if (demangled
!= NULL
)
633 f
= symbol__new(sym
.st_value
, sym
.st_size
, name
,
634 self
->sym_priv_size
, obj_start
, verbose
);
639 if (filter
&& filter(self
, f
))
640 symbol__delete(f
, self
->sym_priv_size
);
643 dso__insert_symbol(self
, f
);
655 int dso__load(struct dso
*self
, symbol_filter_t filter
, int verbose
)
657 int size
= strlen(self
->name
) + sizeof("/usr/lib/debug%s.debug");
658 char *name
= malloc(size
);
666 self
->adjust_symbols
= 0;
668 if (strncmp(self
->name
, "/tmp/perf-", 10) == 0)
669 return dso__load_perf_map(self
, filter
, verbose
);
675 snprintf(name
, size
, "/usr/lib/debug%s.debug", self
->name
);
678 snprintf(name
, size
, "/usr/lib/debug%s", self
->name
);
680 case 2: /* Sane people */
681 snprintf(name
, size
, "%s", self
->name
);
689 fd
= open(name
, O_RDONLY
);
692 ret
= dso__load_sym(self
, fd
, name
, filter
, verbose
, NULL
);
696 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
702 int nr_plt
= dso__synthesize_plt_symbols(self
, verbose
);
711 static int dso__load_module(struct dso
*self
, struct mod_dso
*mods
, const char *name
,
712 symbol_filter_t filter
, int verbose
)
714 struct module
*mod
= mod_dso__find_module(mods
, name
);
717 if (mod
== NULL
|| !mod
->active
)
720 fd
= open(mod
->path
, O_RDONLY
);
725 err
= dso__load_sym(self
, fd
, name
, filter
, verbose
, mod
);
731 int dso__load_modules(struct dso
*self
, symbol_filter_t filter
, int verbose
)
733 struct mod_dso
*mods
= mod_dso__new_dso("modules");
735 struct rb_node
*next
;
738 err
= mod_dso__load_modules(mods
);
744 * Iterate over modules, and load active symbols.
746 next
= rb_first(&mods
->mods
);
748 pos
= rb_entry(next
, struct module
, rb_node
);
749 err
= dso__load_module(self
, mods
, pos
->name
, filter
, verbose
);
754 next
= rb_next(&pos
->rb_node
);
758 mod_dso__delete_modules(mods
);
759 mod_dso__delete_self(mods
);
765 static inline void dso__fill_symbol_holes(struct dso
*self
)
767 struct symbol
*prev
= NULL
;
770 for (nd
= rb_last(&self
->syms
); nd
; nd
= rb_prev(nd
)) {
771 struct symbol
*pos
= rb_entry(nd
, struct symbol
, rb_node
);
775 int alias
= pos
->start
== prev
->start
;
778 hole
= prev
->start
- pos
->end
- 1;
782 pos
->end
= prev
->end
;
784 pos
->end
= prev
->start
- 1;
791 static int dso__load_vmlinux(struct dso
*self
, const char *vmlinux
,
792 symbol_filter_t filter
, int verbose
)
794 int err
, fd
= open(vmlinux
, O_RDONLY
);
799 err
= dso__load_sym(self
, fd
, vmlinux
, filter
, verbose
, NULL
);
802 dso__fill_symbol_holes(self
);
809 int dso__load_kernel(struct dso
*self
, const char *vmlinux
,
810 symbol_filter_t filter
, int verbose
, int modules
)
815 err
= dso__load_vmlinux(self
, vmlinux
, filter
, verbose
);
816 if (err
> 0 && modules
)
817 err
= dso__load_modules(self
, filter
, verbose
);
821 err
= dso__load_kallsyms(self
, filter
, verbose
);
826 void symbol__init(void)
828 elf_version(EV_CURRENT
);