aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c405
1 files changed, 331 insertions, 74 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 78c2efde01b7..16ddca202948 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -7,8 +7,23 @@
7#include <gelf.h> 7#include <gelf.h>
8#include <elf.h> 8#include <elf.h>
9 9
10#ifndef NO_DEMANGLE
11#include <bfd.h>
12#else
13static inline
14char *bfd_demangle(void __used *v, const char __used *c, int __used i)
15{
16 return NULL;
17}
18#endif
19
10const char *sym_hist_filter; 20const char *sym_hist_filter;
11 21
22#ifndef DMGL_PARAMS
23#define DMGL_PARAMS (1 << 0) /* Include function args */
24#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
25#endif
26
12static struct symbol *symbol__new(u64 start, u64 len, 27static struct symbol *symbol__new(u64 start, u64 len,
13 const char *name, unsigned int priv_size, 28 const char *name, unsigned int priv_size,
14 u64 obj_start, int verbose) 29 u64 obj_start, int verbose)
@@ -35,7 +50,7 @@ static struct symbol *symbol__new(u64 start, u64 len,
35 self = ((void *)self) + priv_size; 50 self = ((void *)self) + priv_size;
36 } 51 }
37 self->start = start; 52 self->start = start;
38 self->end = start + len - 1; 53 self->end = len ? start + len - 1 : start;
39 memcpy(self->name, name, namelen); 54 memcpy(self->name, name, namelen);
40 55
41 return self; 56 return self;
@@ -48,8 +63,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
48 63
49static size_t symbol__fprintf(struct symbol *self, FILE *fp) 64static size_t symbol__fprintf(struct symbol *self, FILE *fp)
50{ 65{
51 return fprintf(fp, " %llx-%llx %s\n", 66 if (!self->module)
67 return fprintf(fp, " %llx-%llx %s\n",
52 self->start, self->end, self->name); 68 self->start, self->end, self->name);
69 else
70 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
71 self->start, self->end, self->name, self->module->name);
53} 72}
54 73
55struct dso *dso__new(const char *name, unsigned int sym_priv_size) 74struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -61,6 +80,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
61 self->syms = RB_ROOT; 80 self->syms = RB_ROOT;
62 self->sym_priv_size = sym_priv_size; 81 self->sym_priv_size = sym_priv_size;
63 self->find_symbol = dso__find_symbol; 82 self->find_symbol = dso__find_symbol;
83 self->slen_calculated = 0;
64 } 84 }
65 85
66 return self; 86 return self;
@@ -146,6 +166,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
146 char *line = NULL; 166 char *line = NULL;
147 size_t n; 167 size_t n;
148 FILE *file = fopen("/proc/kallsyms", "r"); 168 FILE *file = fopen("/proc/kallsyms", "r");
169 int count = 0;
149 170
150 if (file == NULL) 171 if (file == NULL)
151 goto out_failure; 172 goto out_failure;
@@ -188,8 +209,10 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
188 209
189 if (filter && filter(self, sym)) 210 if (filter && filter(self, sym))
190 symbol__delete(sym, self->sym_priv_size); 211 symbol__delete(sym, self->sym_priv_size);
191 else 212 else {
192 dso__insert_symbol(self, sym); 213 dso__insert_symbol(self, sym);
214 count++;
215 }
193 } 216 }
194 217
195 /* 218 /*
@@ -212,7 +235,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
212 free(line); 235 free(line);
213 fclose(file); 236 fclose(file);
214 237
215 return 0; 238 return count;
216 239
217out_delete_line: 240out_delete_line:
218 free(line); 241 free(line);
@@ -307,6 +330,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
307 sym->st_size != 0; 330 sym->st_size != 0;
308} 331}
309 332
333static inline int elf_sym__is_label(const GElf_Sym *sym)
334{
335 return elf_sym__type(sym) == STT_NOTYPE &&
336 sym->st_name != 0 &&
337 sym->st_shndx != SHN_UNDEF &&
338 sym->st_shndx != SHN_ABS;
339}
340
341static inline const char *elf_sec__name(const GElf_Shdr *shdr,
342 const Elf_Data *secstrs)
343{
344 return secstrs->d_buf + shdr->sh_name;
345}
346
347static inline int elf_sec__is_text(const GElf_Shdr *shdr,
348 const Elf_Data *secstrs)
349{
350 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
351}
352
310static inline const char *elf_sym__name(const GElf_Sym *sym, 353static inline const char *elf_sym__name(const GElf_Sym *sym,
311 const Elf_Data *symstrs) 354 const Elf_Data *symstrs)
312{ 355{
@@ -346,36 +389,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
346 idx < nr_entries; \ 389 idx < nr_entries; \
347 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 390 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
348 391
349static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, 392/*
350 GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, 393 * We need to check if we have a .dynsym, so that we can handle the
351 GElf_Shdr *shdr_dynsym, 394 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
352 size_t dynsym_idx, int verbose) 395 * .dynsym or .symtab).
396 * And always look at the original dso, not at debuginfo packages, that
397 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
398 */
399static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
353{ 400{
354 uint32_t nr_rel_entries, idx; 401 uint32_t nr_rel_entries, idx;
355 GElf_Sym sym; 402 GElf_Sym sym;
356 u64 plt_offset; 403 u64 plt_offset;
357 GElf_Shdr shdr_plt; 404 GElf_Shdr shdr_plt;
358 struct symbol *f; 405 struct symbol *f;
359 GElf_Shdr shdr_rel_plt; 406 GElf_Shdr shdr_rel_plt, shdr_dynsym;
360 Elf_Data *reldata, *syms, *symstrs; 407 Elf_Data *reldata, *syms, *symstrs;
361 Elf_Scn *scn_plt_rel, *scn_symstrs; 408 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
409 size_t dynsym_idx;
410 GElf_Ehdr ehdr;
362 char sympltname[1024]; 411 char sympltname[1024];
363 int nr = 0, symidx; 412 Elf *elf;
413 int nr = 0, symidx, fd, err = 0;
414
415 fd = open(self->name, O_RDONLY);
416 if (fd < 0)
417 goto out;
418
419 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
420 if (elf == NULL)
421 goto out_close;
364 422
365 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 423 if (gelf_getehdr(elf, &ehdr) == NULL)
424 goto out_elf_end;
425
426 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
427 ".dynsym", &dynsym_idx);
428 if (scn_dynsym == NULL)
429 goto out_elf_end;
430
431 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
366 ".rela.plt", NULL); 432 ".rela.plt", NULL);
367 if (scn_plt_rel == NULL) { 433 if (scn_plt_rel == NULL) {
368 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 434 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
369 ".rel.plt", NULL); 435 ".rel.plt", NULL);
370 if (scn_plt_rel == NULL) 436 if (scn_plt_rel == NULL)
371 return 0; 437 goto out_elf_end;
372 } 438 }
373 439
440 err = -1;
441
374 if (shdr_rel_plt.sh_link != dynsym_idx) 442 if (shdr_rel_plt.sh_link != dynsym_idx)
375 return 0; 443 goto out_elf_end;
376 444
377 if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) 445 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
378 return 0; 446 goto out_elf_end;
379 447
380 /* 448 /*
381 * Fetch the relocation section to find the indexes to the GOT 449 * Fetch the relocation section to find the indexes to the GOT
@@ -383,19 +451,19 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
383 */ 451 */
384 reldata = elf_getdata(scn_plt_rel, NULL); 452 reldata = elf_getdata(scn_plt_rel, NULL);
385 if (reldata == NULL) 453 if (reldata == NULL)
386 return -1; 454 goto out_elf_end;
387 455
388 syms = elf_getdata(scn_dynsym, NULL); 456 syms = elf_getdata(scn_dynsym, NULL);
389 if (syms == NULL) 457 if (syms == NULL)
390 return -1; 458 goto out_elf_end;
391 459
392 scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); 460 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
393 if (scn_symstrs == NULL) 461 if (scn_symstrs == NULL)
394 return -1; 462 goto out_elf_end;
395 463
396 symstrs = elf_getdata(scn_symstrs, NULL); 464 symstrs = elf_getdata(scn_symstrs, NULL);
397 if (symstrs == NULL) 465 if (symstrs == NULL)
398 return -1; 466 goto out_elf_end;
399 467
400 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 468 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
401 plt_offset = shdr_plt.sh_offset; 469 plt_offset = shdr_plt.sh_offset;
@@ -414,7 +482,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
414 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 482 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
415 sympltname, self->sym_priv_size, 0, verbose); 483 sympltname, self->sym_priv_size, 0, verbose);
416 if (!f) 484 if (!f)
417 return -1; 485 goto out_elf_end;
418 486
419 dso__insert_symbol(self, f); 487 dso__insert_symbol(self, f);
420 ++nr; 488 ++nr;
@@ -432,25 +500,31 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
432 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 500 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
433 sympltname, self->sym_priv_size, 0, verbose); 501 sympltname, self->sym_priv_size, 0, verbose);
434 if (!f) 502 if (!f)
435 return -1; 503 goto out_elf_end;
436 504
437 dso__insert_symbol(self, f); 505 dso__insert_symbol(self, f);
438 ++nr; 506 ++nr;
439 } 507 }
440 } else {
441 /*
442 * TODO: There are still one more shdr_rel_plt.sh_type
443 * I have to investigate, but probably should be ignored.
444 */
445 } 508 }
446 509
447 return nr; 510 err = 0;
511out_elf_end:
512 elf_end(elf);
513out_close:
514 close(fd);
515
516 if (err == 0)
517 return nr;
518out:
519 fprintf(stderr, "%s: problems reading %s PLT info.\n",
520 __func__, self->name);
521 return 0;
448} 522}
449 523
450static int dso__load_sym(struct dso *self, int fd, const char *name, 524static int dso__load_sym(struct dso *self, int fd, const char *name,
451 symbol_filter_t filter, int verbose) 525 symbol_filter_t filter, int verbose, struct module *mod)
452{ 526{
453 Elf_Data *symstrs; 527 Elf_Data *symstrs, *secstrs;
454 uint32_t nr_syms; 528 uint32_t nr_syms;
455 int err = -1; 529 int err = -1;
456 uint32_t index; 530 uint32_t index;
@@ -458,10 +532,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
458 GElf_Shdr shdr; 532 GElf_Shdr shdr;
459 Elf_Data *syms; 533 Elf_Data *syms;
460 GElf_Sym sym; 534 GElf_Sym sym;
461 Elf_Scn *sec, *sec_dynsym; 535 Elf_Scn *sec, *sec_strndx;
462 Elf *elf; 536 Elf *elf;
463 size_t dynsym_idx; 537 int nr = 0, kernel = !strcmp("[kernel]", self->name);
464 int nr = 0;
465 538
466 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 539 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
467 if (elf == NULL) { 540 if (elf == NULL) {
@@ -477,32 +550,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
477 goto out_elf_end; 550 goto out_elf_end;
478 } 551 }
479 552
480 /*
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)
484 */
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,
489 sec_dynsym, &shdr,
490 dynsym_idx, verbose);
491 if (nr < 0)
492 goto out_elf_end;
493 }
494
495 /*
496 * But if we have a full .symtab (that is a superset of .dynsym) we
497 * should add the symbols not in the .dynsyn
498 */
499 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 553 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
500 if (sec == NULL) { 554 if (sec == NULL) {
501 if (sec_dynsym == NULL) 555 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
556 if (sec == NULL)
502 goto out_elf_end; 557 goto out_elf_end;
503
504 sec = sec_dynsym;
505 gelf_getshdr(sec, &shdr);
506 } 558 }
507 559
508 syms = elf_getdata(sec, NULL); 560 syms = elf_getdata(sec, NULL);
@@ -517,17 +569,34 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
517 if (symstrs == NULL) 569 if (symstrs == NULL)
518 goto out_elf_end; 570 goto out_elf_end;
519 571
572 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
573 if (sec_strndx == NULL)
574 goto out_elf_end;
575
576 secstrs = elf_getdata(sec_strndx, NULL);
577 if (secstrs == NULL)
578 goto out_elf_end;
579
520 nr_syms = shdr.sh_size / shdr.sh_entsize; 580 nr_syms = shdr.sh_size / shdr.sh_entsize;
521 581
522 memset(&sym, 0, sizeof(sym)); 582 memset(&sym, 0, sizeof(sym));
523 self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, 583 if (!kernel) {
524 ".gnu.prelink_undo", 584 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
525 NULL) != NULL; 585 elf_section_by_name(elf, &ehdr, &shdr,
586 ".gnu.prelink_undo",
587 NULL) != NULL);
588 } else self->adjust_symbols = 0;
589
526 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 590 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
527 struct symbol *f; 591 struct symbol *f;
592 const char *name;
593 char *demangled;
528 u64 obj_start; 594 u64 obj_start;
595 struct section *section = NULL;
596 int is_label = elf_sym__is_label(&sym);
597 const char *section_name;
529 598
530 if (!elf_sym__is_function(&sym)) 599 if (!is_label && !elf_sym__is_function(&sym))
531 continue; 600 continue;
532 601
533 sec = elf_getscn(elf, sym.st_shndx); 602 sec = elf_getscn(elf, sym.st_shndx);
@@ -535,9 +604,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
535 goto out_elf_end; 604 goto out_elf_end;
536 605
537 gelf_getshdr(sec, &shdr); 606 gelf_getshdr(sec, &shdr);
607
608 if (is_label && !elf_sec__is_text(&shdr, secstrs))
609 continue;
610
611 section_name = elf_sec__name(&shdr, secstrs);
538 obj_start = sym.st_value; 612 obj_start = sym.st_value;
539 613
540 if (self->prelinked) { 614 if (self->adjust_symbols) {
541 if (verbose >= 2) 615 if (verbose >= 2)
542 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 616 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
543 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 617 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
@@ -545,15 +619,36 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
545 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 619 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
546 } 620 }
547 621
548 f = symbol__new(sym.st_value, sym.st_size, 622 if (mod) {
549 elf_sym__name(&sym, symstrs), 623 section = mod->sections->find_section(mod->sections, section_name);
624 if (section)
625 sym.st_value += section->vma;
626 else {
627 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
628 mod->name, section_name);
629 goto out_elf_end;
630 }
631 }
632 /*
633 * We need to figure out if the object was created from C++ sources
634 * DWARF DW_compile_unit has this, but we don't always have access
635 * to it...
636 */
637 name = elf_sym__name(&sym, symstrs);
638 demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
639 if (demangled != NULL)
640 name = demangled;
641
642 f = symbol__new(sym.st_value, sym.st_size, name,
550 self->sym_priv_size, obj_start, verbose); 643 self->sym_priv_size, obj_start, verbose);
644 free(demangled);
551 if (!f) 645 if (!f)
552 goto out_elf_end; 646 goto out_elf_end;
553 647
554 if (filter && filter(self, f)) 648 if (filter && filter(self, f))
555 symbol__delete(f, self->sym_priv_size); 649 symbol__delete(f, self->sym_priv_size);
556 else { 650 else {
651 f->module = mod;
557 dso__insert_symbol(self, f); 652 dso__insert_symbol(self, f);
558 nr++; 653 nr++;
559 } 654 }
@@ -566,10 +661,69 @@ out_close:
566 return err; 661 return err;
567} 662}
568 663
664#define BUILD_ID_SIZE 128
665
666static char *dso__read_build_id(struct dso *self, int verbose)
667{
668 int i;
669 GElf_Ehdr ehdr;
670 GElf_Shdr shdr;
671 Elf_Data *build_id_data;
672 Elf_Scn *sec;
673 char *build_id = NULL, *bid;
674 unsigned char *raw;
675 Elf *elf;
676 int fd = open(self->name, O_RDONLY);
677
678 if (fd < 0)
679 goto out;
680
681 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
682 if (elf == NULL) {
683 if (verbose)
684 fprintf(stderr, "%s: cannot read %s ELF file.\n",
685 __func__, self->name);
686 goto out_close;
687 }
688
689 if (gelf_getehdr(elf, &ehdr) == NULL) {
690 if (verbose)
691 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
692 goto out_elf_end;
693 }
694
695 sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
696 if (sec == NULL)
697 goto out_elf_end;
698
699 build_id_data = elf_getdata(sec, NULL);
700 if (build_id_data == NULL)
701 goto out_elf_end;
702 build_id = malloc(BUILD_ID_SIZE);
703 if (build_id == NULL)
704 goto out_elf_end;
705 raw = build_id_data->d_buf + 16;
706 bid = build_id;
707
708 for (i = 0; i < 20; ++i) {
709 sprintf(bid, "%02x", *raw);
710 ++raw;
711 bid += 2;
712 }
713 if (verbose)
714 printf("%s(%s): %s\n", __func__, self->name, build_id);
715out_elf_end:
716 elf_end(elf);
717out_close:
718 close(fd);
719out:
720 return build_id;
721}
722
569int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 723int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
570{ 724{
571 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 725 int size = PATH_MAX;
572 char *name = malloc(size); 726 char *name = malloc(size), *build_id = NULL;
573 int variant = 0; 727 int variant = 0;
574 int ret = -1; 728 int ret = -1;
575 int fd; 729 int fd;
@@ -577,7 +731,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
577 if (!name) 731 if (!name)
578 return -1; 732 return -1;
579 733
580 self->prelinked = 0; 734 self->adjust_symbols = 0;
581 735
582 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 736 if (strncmp(self->name, "/tmp/perf-", 10) == 0)
583 return dso__load_perf_map(self, filter, verbose); 737 return dso__load_perf_map(self, filter, verbose);
@@ -591,7 +745,18 @@ more:
591 case 1: /* Ubuntu */ 745 case 1: /* Ubuntu */
592 snprintf(name, size, "/usr/lib/debug%s", self->name); 746 snprintf(name, size, "/usr/lib/debug%s", self->name);
593 break; 747 break;
594 case 2: /* Sane people */ 748 case 2:
749 build_id = dso__read_build_id(self, verbose);
750 if (build_id != NULL) {
751 snprintf(name, size,
752 "/usr/lib/debug/.build-id/%.2s/%s.debug",
753 build_id, build_id + 2);
754 free(build_id);
755 break;
756 }
757 variant++;
758 /* Fall thru */
759 case 3: /* Sane people */
595 snprintf(name, size, "%s", self->name); 760 snprintf(name, size, "%s", self->name);
596 break; 761 break;
597 762
@@ -603,7 +768,7 @@ more:
603 fd = open(name, O_RDONLY); 768 fd = open(name, O_RDONLY);
604 } while (fd < 0); 769 } while (fd < 0);
605 770
606 ret = dso__load_sym(self, fd, name, filter, verbose); 771 ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
607 close(fd); 772 close(fd);
608 773
609 /* 774 /*
@@ -612,11 +777,96 @@ more:
612 if (!ret) 777 if (!ret)
613 goto more; 778 goto more;
614 779
780 if (ret > 0) {
781 int nr_plt = dso__synthesize_plt_symbols(self, verbose);
782 if (nr_plt > 0)
783 ret += nr_plt;
784 }
615out: 785out:
616 free(name); 786 free(name);
617 return ret; 787 return ret;
618} 788}
619 789
790static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
791 symbol_filter_t filter, int verbose)
792{
793 struct module *mod = mod_dso__find_module(mods, name);
794 int err = 0, fd;
795
796 if (mod == NULL || !mod->active)
797 return err;
798
799 fd = open(mod->path, O_RDONLY);
800
801 if (fd < 0)
802 return err;
803
804 err = dso__load_sym(self, fd, name, filter, verbose, mod);
805 close(fd);
806
807 return err;
808}
809
810int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
811{
812 struct mod_dso *mods = mod_dso__new_dso("modules");
813 struct module *pos;
814 struct rb_node *next;
815 int err;
816
817 err = mod_dso__load_modules(mods);
818
819 if (err <= 0)
820 return err;
821
822 /*
823 * Iterate over modules, and load active symbols.
824 */
825 next = rb_first(&mods->mods);
826 while (next) {
827 pos = rb_entry(next, struct module, rb_node);
828 err = dso__load_module(self, mods, pos->name, filter, verbose);
829
830 if (err < 0)
831 break;
832
833 next = rb_next(&pos->rb_node);
834 }
835
836 if (err < 0) {
837 mod_dso__delete_modules(mods);
838 mod_dso__delete_self(mods);
839 }
840
841 return err;
842}
843
844static inline void dso__fill_symbol_holes(struct dso *self)
845{
846 struct symbol *prev = NULL;
847 struct rb_node *nd;
848
849 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
850 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
851
852 if (prev) {
853 u64 hole = 0;
854 int alias = pos->start == prev->start;
855
856 if (!alias)
857 hole = prev->start - pos->end - 1;
858
859 if (hole || alias) {
860 if (alias)
861 pos->end = prev->end;
862 else if (hole)
863 pos->end = prev->start - 1;
864 }
865 }
866 prev = pos;
867 }
868}
869
620static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 870static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
621 symbol_filter_t filter, int verbose) 871 symbol_filter_t filter, int verbose)
622{ 872{
@@ -625,21 +875,28 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
625 if (fd < 0) 875 if (fd < 0)
626 return -1; 876 return -1;
627 877
628 err = dso__load_sym(self, fd, vmlinux, filter, verbose); 878 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
879
880 if (err > 0)
881 dso__fill_symbol_holes(self);
882
629 close(fd); 883 close(fd);
630 884
631 return err; 885 return err;
632} 886}
633 887
634int dso__load_kernel(struct dso *self, const char *vmlinux, 888int dso__load_kernel(struct dso *self, const char *vmlinux,
635 symbol_filter_t filter, int verbose) 889 symbol_filter_t filter, int verbose, int modules)
636{ 890{
637 int err = -1; 891 int err = -1;
638 892
639 if (vmlinux) 893 if (vmlinux) {
640 err = dso__load_vmlinux(self, vmlinux, filter, verbose); 894 err = dso__load_vmlinux(self, vmlinux, filter, verbose);
895 if (err > 0 && modules)
896 err = dso__load_modules(self, filter, verbose);
897 }
641 898
642 if (err < 0) 899 if (err <= 0)
643 err = dso__load_kallsyms(self, filter, verbose); 900 err = dso__load_kallsyms(self, filter, verbose);
644 901
645 return err; 902 return err;