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