10 const char *sym_hist_filter
;
12 static struct symbol
*symbol__new(u64 start
, u64 len
,
13 const char *name
, unsigned int priv_size
,
14 u64 obj_start
, int verbose
)
16 size_t namelen
= strlen(name
) + 1;
17 struct symbol
*self
= calloc(1, priv_size
+ sizeof(*self
) + namelen
);
23 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n",
24 (u64
)start
, (unsigned long)len
, name
, self
->hist
, (void *)(unsigned long)obj_start
);
26 self
->obj_start
= obj_start
;
30 if (sym_hist_filter
&& !strcmp(name
, sym_hist_filter
))
31 self
->hist
= calloc(sizeof(u64
), len
);
34 memset(self
, 0, priv_size
);
35 self
= ((void *)self
) + priv_size
;
38 self
->end
= start
+ len
- 1;
39 memcpy(self
->name
, name
, namelen
);
44 static void symbol__delete(struct symbol
*self
, unsigned int priv_size
)
46 free(((void *)self
) - priv_size
);
49 static size_t symbol__fprintf(struct symbol
*self
, FILE *fp
)
51 return fprintf(fp
, " %llx-%llx %s\n",
52 self
->start
, self
->end
, self
->name
);
55 struct dso
*dso__new(const char *name
, unsigned int sym_priv_size
)
57 struct dso
*self
= malloc(sizeof(*self
) + strlen(name
) + 1);
60 strcpy(self
->name
, name
);
62 self
->sym_priv_size
= sym_priv_size
;
63 self
->find_symbol
= dso__find_symbol
;
69 static void dso__delete_symbols(struct dso
*self
)
72 struct rb_node
*next
= rb_first(&self
->syms
);
75 pos
= rb_entry(next
, struct symbol
, rb_node
);
76 next
= rb_next(&pos
->rb_node
);
77 rb_erase(&pos
->rb_node
, &self
->syms
);
78 symbol__delete(pos
, self
->sym_priv_size
);
82 void dso__delete(struct dso
*self
)
84 dso__delete_symbols(self
);
88 static void dso__insert_symbol(struct dso
*self
, struct symbol
*sym
)
90 struct rb_node
**p
= &self
->syms
.rb_node
;
91 struct rb_node
*parent
= NULL
;
92 const u64 ip
= sym
->start
;
97 s
= rb_entry(parent
, struct symbol
, rb_node
);
103 rb_link_node(&sym
->rb_node
, parent
, p
);
104 rb_insert_color(&sym
->rb_node
, &self
->syms
);
107 struct symbol
*dso__find_symbol(struct dso
*self
, u64 ip
)
114 n
= self
->syms
.rb_node
;
117 struct symbol
*s
= rb_entry(n
, struct symbol
, rb_node
);
121 else if (ip
> s
->end
)
130 size_t dso__fprintf(struct dso
*self
, FILE *fp
)
132 size_t ret
= fprintf(fp
, "dso: %s\n", self
->name
);
135 for (nd
= rb_first(&self
->syms
); nd
; nd
= rb_next(nd
)) {
136 struct symbol
*pos
= rb_entry(nd
, struct symbol
, rb_node
);
137 ret
+= symbol__fprintf(pos
, fp
);
143 static int dso__load_kallsyms(struct dso
*self
, symbol_filter_t filter
, int verbose
)
145 struct rb_node
*nd
, *prevnd
;
148 FILE *file
= fopen("/proc/kallsyms", "r");
153 while (!feof(file
)) {
159 line_len
= getline(&line
, &n
, file
);
166 line
[--line_len
] = '\0'; /* \n */
168 len
= hex2u64(line
, &start
);
171 if (len
+ 2 >= line_len
)
174 symbol_type
= toupper(line
[len
]);
176 * We're interested only in code ('T'ext)
178 if (symbol_type
!= 'T' && symbol_type
!= 'W')
181 * Well fix up the end later, when we have all sorted.
183 sym
= symbol__new(start
, 0xdead, line
+ len
+ 2,
184 self
->sym_priv_size
, 0, verbose
);
187 goto out_delete_line
;
189 if (filter
&& filter(self
, sym
))
190 symbol__delete(sym
, self
->sym_priv_size
);
192 dso__insert_symbol(self
, sym
);
196 * Now that we have all sorted out, just set the ->end of all
199 prevnd
= rb_first(&self
->syms
);
202 goto out_delete_line
;
204 for (nd
= rb_next(prevnd
); nd
; nd
= rb_next(nd
)) {
205 struct symbol
*prev
= rb_entry(prevnd
, struct symbol
, rb_node
),
206 *curr
= rb_entry(nd
, struct symbol
, rb_node
);
208 prev
->end
= curr
->start
- 1;
223 static int dso__load_perf_map(struct dso
*self
, symbol_filter_t filter
, int verbose
)
230 file
= fopen(self
->name
, "r");
234 while (!feof(file
)) {
239 line_len
= getline(&line
, &n
, file
);
246 line
[--line_len
] = '\0'; /* \n */
248 len
= hex2u64(line
, &start
);
251 if (len
+ 2 >= line_len
)
254 len
+= hex2u64(line
+ len
, &size
);
257 if (len
+ 2 >= line_len
)
260 sym
= symbol__new(start
, size
, line
+ len
,
261 self
->sym_priv_size
, start
, verbose
);
264 goto out_delete_line
;
266 if (filter
&& filter(self
, sym
))
267 symbol__delete(sym
, self
->sym_priv_size
);
269 dso__insert_symbol(self
, sym
);
286 * elf_symtab__for_each_symbol - iterate thru all the symbols
288 * @self: struct elf_symtab instance to iterate
289 * @index: uint32_t index
290 * @sym: GElf_Sym iterator
292 #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \
293 for (index = 0, gelf_getsym(syms, index, &sym);\
295 index++, gelf_getsym(syms, index, &sym))
297 static inline uint8_t elf_sym__type(const GElf_Sym
*sym
)
299 return GELF_ST_TYPE(sym
->st_info
);
302 static inline int elf_sym__is_function(const GElf_Sym
*sym
)
304 return elf_sym__type(sym
) == STT_FUNC
&&
306 sym
->st_shndx
!= SHN_UNDEF
&&
310 static inline const char *elf_sym__name(const GElf_Sym
*sym
,
311 const Elf_Data
*symstrs
)
313 return symstrs
->d_buf
+ sym
->st_name
;
316 static Elf_Scn
*elf_section_by_name(Elf
*elf
, GElf_Ehdr
*ep
,
317 GElf_Shdr
*shp
, const char *name
,
323 while ((sec
= elf_nextscn(elf
, sec
)) != NULL
) {
326 gelf_getshdr(sec
, shp
);
327 str
= elf_strptr(elf
, ep
->e_shstrndx
, shp
->sh_name
);
328 if (!strcmp(name
, str
)) {
339 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
340 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
342 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
344 #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
345 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
347 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
349 static int dso__synthesize_plt_symbols(struct dso
*self
, Elf
*elf
,
350 GElf_Ehdr
*ehdr
, Elf_Scn
*scn_dynsym
,
351 GElf_Shdr
*shdr_dynsym
,
352 size_t dynsym_idx
, int verbose
)
354 uint32_t nr_rel_entries
, idx
;
359 GElf_Shdr shdr_rel_plt
;
360 Elf_Data
*reldata
, *syms
, *symstrs
;
361 Elf_Scn
*scn_plt_rel
, *scn_symstrs
;
362 char sympltname
[1024];
365 scn_plt_rel
= elf_section_by_name(elf
, ehdr
, &shdr_rel_plt
,
367 if (scn_plt_rel
== NULL
) {
368 scn_plt_rel
= elf_section_by_name(elf
, ehdr
, &shdr_rel_plt
,
370 if (scn_plt_rel
== NULL
)
374 if (shdr_rel_plt
.sh_link
!= dynsym_idx
)
377 if (elf_section_by_name(elf
, ehdr
, &shdr_plt
, ".plt", NULL
) == NULL
)
381 * Fetch the relocation section to find the indexes to the GOT
382 * and the symbols in the .dynsym they refer to.
384 reldata
= elf_getdata(scn_plt_rel
, NULL
);
388 syms
= elf_getdata(scn_dynsym
, NULL
);
392 scn_symstrs
= elf_getscn(elf
, shdr_dynsym
->sh_link
);
393 if (scn_symstrs
== NULL
)
396 symstrs
= elf_getdata(scn_symstrs
, NULL
);
400 nr_rel_entries
= shdr_rel_plt
.sh_size
/ shdr_rel_plt
.sh_entsize
;
401 plt_offset
= shdr_plt
.sh_offset
;
403 if (shdr_rel_plt
.sh_type
== SHT_RELA
) {
404 GElf_Rela pos_mem
, *pos
;
406 elf_section__for_each_rela(reldata
, pos
, pos_mem
, idx
,
408 symidx
= GELF_R_SYM(pos
->r_info
);
409 plt_offset
+= shdr_plt
.sh_entsize
;
410 gelf_getsym(syms
, symidx
, &sym
);
411 snprintf(sympltname
, sizeof(sympltname
),
412 "%s@plt", elf_sym__name(&sym
, symstrs
));
414 f
= symbol__new(plt_offset
, shdr_plt
.sh_entsize
,
415 sympltname
, self
->sym_priv_size
, 0, verbose
);
419 dso__insert_symbol(self
, f
);
422 } else if (shdr_rel_plt
.sh_type
== SHT_REL
) {
423 GElf_Rel pos_mem
, *pos
;
424 elf_section__for_each_rel(reldata
, pos
, pos_mem
, idx
,
426 symidx
= GELF_R_SYM(pos
->r_info
);
427 plt_offset
+= shdr_plt
.sh_entsize
;
428 gelf_getsym(syms
, symidx
, &sym
);
429 snprintf(sympltname
, sizeof(sympltname
),
430 "%s@plt", elf_sym__name(&sym
, symstrs
));
432 f
= symbol__new(plt_offset
, shdr_plt
.sh_entsize
,
433 sympltname
, self
->sym_priv_size
, 0, verbose
);
437 dso__insert_symbol(self
, f
);
442 * TODO: There are still one more shdr_rel_plt.sh_type
443 * I have to investigate, but probably should be ignored.
450 static int dso__load_sym(struct dso
*self
, int fd
, const char *name
,
451 symbol_filter_t filter
, int verbose
)
461 Elf_Scn
*sec
, *sec_dynsym
;
466 elf
= elf_begin(fd
, ELF_C_READ_MMAP
, NULL
);
469 fprintf(stderr
, "%s: cannot read %s ELF file.\n",
474 if (gelf_getehdr(elf
, &ehdr
) == NULL
) {
476 fprintf(stderr
, "%s: cannot get elf header.\n", __func__
);
481 * We need to check if we have a .dynsym, so that we can handle the
482 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
483 * .dynsym or .symtab)
485 sec_dynsym
= elf_section_by_name(elf
, &ehdr
, &shdr
,
486 ".dynsym", &dynsym_idx
);
487 if (sec_dynsym
!= NULL
) {
488 nr
= dso__synthesize_plt_symbols(self
, elf
, &ehdr
,
490 dynsym_idx
, verbose
);
496 * But if we have a full .symtab (that is a superset of .dynsym) we
497 * should add the symbols not in the .dynsyn
499 sec
= elf_section_by_name(elf
, &ehdr
, &shdr
, ".symtab", NULL
);
501 if (sec_dynsym
== NULL
)
505 gelf_getshdr(sec
, &shdr
);
508 syms
= elf_getdata(sec
, NULL
);
512 sec
= elf_getscn(elf
, shdr
.sh_link
);
516 symstrs
= elf_getdata(sec
, NULL
);
520 nr_syms
= shdr
.sh_size
/ shdr
.sh_entsize
;
522 memset(&sym
, 0, sizeof(sym
));
524 elf_symtab__for_each_symbol(syms
, nr_syms
, index
, sym
) {
528 if (!elf_sym__is_function(&sym
))
531 sec
= elf_getscn(elf
, sym
.st_shndx
);
535 gelf_getshdr(sec
, &shdr
);
536 obj_start
= sym
.st_value
;
538 sym
.st_value
-= shdr
.sh_addr
- shdr
.sh_offset
;
540 f
= symbol__new(sym
.st_value
, sym
.st_size
,
541 elf_sym__name(&sym
, symstrs
),
542 self
->sym_priv_size
, obj_start
, verbose
);
546 if (filter
&& filter(self
, f
))
547 symbol__delete(f
, self
->sym_priv_size
);
549 dso__insert_symbol(self
, f
);
561 int dso__load(struct dso
*self
, symbol_filter_t filter
, int verbose
)
563 int size
= strlen(self
->name
) + sizeof("/usr/lib/debug%s.debug");
564 char *name
= malloc(size
);
572 if (strncmp(self
->name
, "/tmp/perf-", 10) == 0)
573 return dso__load_perf_map(self
, filter
, verbose
);
579 snprintf(name
, size
, "/usr/lib/debug%s.debug", self
->name
);
582 snprintf(name
, size
, "/usr/lib/debug%s", self
->name
);
584 case 2: /* Sane people */
585 snprintf(name
, size
, "%s", self
->name
);
593 fd
= open(name
, O_RDONLY
);
596 ret
= dso__load_sym(self
, fd
, name
, filter
, verbose
);
600 * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
610 static int dso__load_vmlinux(struct dso
*self
, const char *vmlinux
,
611 symbol_filter_t filter
, int verbose
)
613 int err
, fd
= open(vmlinux
, O_RDONLY
);
618 err
= dso__load_sym(self
, fd
, vmlinux
, filter
, verbose
);
624 int dso__load_kernel(struct dso
*self
, const char *vmlinux
,
625 symbol_filter_t filter
, int verbose
)
630 err
= dso__load_vmlinux(self
, vmlinux
, filter
, verbose
);
633 err
= dso__load_kallsyms(self
, filter
, verbose
);
638 void symbol__init(void)
640 elf_version(EV_CURRENT
);