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.c285
1 files changed, 263 insertions, 22 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index d5528e1cc03a..7eb0362f4ffd 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -87,6 +87,7 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
87{ 87{
88 s64 a; 88 s64 a;
89 s64 b; 89 s64 b;
90 size_t na, nb;
90 91
91 /* Prefer a symbol with non zero length */ 92 /* Prefer a symbol with non zero length */
92 a = syma->end - syma->start; 93 a = syma->end - syma->start;
@@ -120,11 +121,21 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
120 else if (a > b) 121 else if (a > b)
121 return SYMBOL_B; 122 return SYMBOL_B;
122 123
123 /* If all else fails, choose the symbol with the longest name */ 124 /* Choose the symbol with the longest name */
124 if (strlen(syma->name) >= strlen(symb->name)) 125 na = strlen(syma->name);
126 nb = strlen(symb->name);
127 if (na > nb)
125 return SYMBOL_A; 128 return SYMBOL_A;
126 else 129 else if (na < nb)
130 return SYMBOL_B;
131
132 /* Avoid "SyS" kernel syscall aliases */
133 if (na >= 3 && !strncmp(syma->name, "SyS", 3))
134 return SYMBOL_B;
135 if (na >= 10 && !strncmp(syma->name, "compat_SyS", 10))
127 return SYMBOL_B; 136 return SYMBOL_B;
137
138 return SYMBOL_A;
128} 139}
129 140
130void symbols__fixup_duplicate(struct rb_root *symbols) 141void symbols__fixup_duplicate(struct rb_root *symbols)
@@ -248,7 +259,10 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym,
248 if (sym && sym->name) { 259 if (sym && sym->name) {
249 length = fprintf(fp, "%s", sym->name); 260 length = fprintf(fp, "%s", sym->name);
250 if (al) { 261 if (al) {
251 offset = al->addr - sym->start; 262 if (al->addr < sym->end)
263 offset = al->addr - sym->start;
264 else
265 offset = al->addr - al->map->start - sym->start;
252 length += fprintf(fp, "+0x%lx", offset); 266 length += fprintf(fp, "+0x%lx", offset);
253 } 267 }
254 return length; 268 return length;
@@ -316,6 +330,16 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
316 return NULL; 330 return NULL;
317} 331}
318 332
333static struct symbol *symbols__first(struct rb_root *symbols)
334{
335 struct rb_node *n = rb_first(symbols);
336
337 if (n)
338 return rb_entry(n, struct symbol, rb_node);
339
340 return NULL;
341}
342
319struct symbol_name_rb_node { 343struct symbol_name_rb_node {
320 struct rb_node rb_node; 344 struct rb_node rb_node;
321 struct symbol sym; 345 struct symbol sym;
@@ -386,6 +410,11 @@ struct symbol *dso__find_symbol(struct dso *dso,
386 return symbols__find(&dso->symbols[type], addr); 410 return symbols__find(&dso->symbols[type], addr);
387} 411}
388 412
413struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
414{
415 return symbols__first(&dso->symbols[type]);
416}
417
389struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 418struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
390 const char *name) 419 const char *name)
391{ 420{
@@ -522,6 +551,53 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
522 return kallsyms__parse(filename, &args, map__process_kallsym_symbol); 551 return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
523} 552}
524 553
554static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
555 symbol_filter_t filter)
556{
557 struct map_groups *kmaps = map__kmap(map)->kmaps;
558 struct map *curr_map;
559 struct symbol *pos;
560 int count = 0, moved = 0;
561 struct rb_root *root = &dso->symbols[map->type];
562 struct rb_node *next = rb_first(root);
563
564 while (next) {
565 char *module;
566
567 pos = rb_entry(next, struct symbol, rb_node);
568 next = rb_next(&pos->rb_node);
569
570 module = strchr(pos->name, '\t');
571 if (module)
572 *module = '\0';
573
574 curr_map = map_groups__find(kmaps, map->type, pos->start);
575
576 if (!curr_map || (filter && filter(curr_map, pos))) {
577 rb_erase(&pos->rb_node, root);
578 symbol__delete(pos);
579 } else {
580 pos->start -= curr_map->start - curr_map->pgoff;
581 if (pos->end)
582 pos->end -= curr_map->start - curr_map->pgoff;
583 if (curr_map != map) {
584 rb_erase(&pos->rb_node, root);
585 symbols__insert(
586 &curr_map->dso->symbols[curr_map->type],
587 pos);
588 ++moved;
589 } else {
590 ++count;
591 }
592 }
593 }
594
595 /* Symbols have been adjusted */
596 dso->adjust_symbols = 1;
597
598 return count + moved;
599}
600
525/* 601/*
526 * Split the symbols into maps, making sure there are no overlaps, i.e. the 602 * Split the symbols into maps, making sure there are no overlaps, i.e. the
527 * kernel range is broken in several maps, named [kernel].N, as we don't have 603 * kernel range is broken in several maps, named [kernel].N, as we don't have
@@ -663,6 +739,161 @@ bool symbol__restricted_filename(const char *filename,
663 return restricted; 739 return restricted;
664} 740}
665 741
742struct kcore_mapfn_data {
743 struct dso *dso;
744 enum map_type type;
745 struct list_head maps;
746};
747
748static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
749{
750 struct kcore_mapfn_data *md = data;
751 struct map *map;
752
753 map = map__new2(start, md->dso, md->type);
754 if (map == NULL)
755 return -ENOMEM;
756
757 map->end = map->start + len;
758 map->pgoff = pgoff;
759
760 list_add(&map->node, &md->maps);
761
762 return 0;
763}
764
765/*
766 * If kallsyms is referenced by name then we look for kcore in the same
767 * directory.
768 */
769static bool kcore_filename_from_kallsyms_filename(char *kcore_filename,
770 const char *kallsyms_filename)
771{
772 char *name;
773
774 strcpy(kcore_filename, kallsyms_filename);
775 name = strrchr(kcore_filename, '/');
776 if (!name)
777 return false;
778
779 if (!strcmp(name, "/kallsyms")) {
780 strcpy(name, "/kcore");
781 return true;
782 }
783
784 return false;
785}
786
787static int dso__load_kcore(struct dso *dso, struct map *map,
788 const char *kallsyms_filename)
789{
790 struct map_groups *kmaps = map__kmap(map)->kmaps;
791 struct machine *machine = kmaps->machine;
792 struct kcore_mapfn_data md;
793 struct map *old_map, *new_map, *replacement_map = NULL;
794 bool is_64_bit;
795 int err, fd;
796 char kcore_filename[PATH_MAX];
797 struct symbol *sym;
798
799 /* This function requires that the map is the kernel map */
800 if (map != machine->vmlinux_maps[map->type])
801 return -EINVAL;
802
803 if (!kcore_filename_from_kallsyms_filename(kcore_filename,
804 kallsyms_filename))
805 return -EINVAL;
806
807 md.dso = dso;
808 md.type = map->type;
809 INIT_LIST_HEAD(&md.maps);
810
811 fd = open(kcore_filename, O_RDONLY);
812 if (fd < 0)
813 return -EINVAL;
814
815 /* Read new maps into temporary lists */
816 err = file__read_maps(fd, md.type == MAP__FUNCTION, kcore_mapfn, &md,
817 &is_64_bit);
818 if (err)
819 goto out_err;
820
821 if (list_empty(&md.maps)) {
822 err = -EINVAL;
823 goto out_err;
824 }
825
826 /* Remove old maps */
827 old_map = map_groups__first(kmaps, map->type);
828 while (old_map) {
829 struct map *next = map_groups__next(old_map);
830
831 if (old_map != map)
832 map_groups__remove(kmaps, old_map);
833 old_map = next;
834 }
835
836 /* Find the kernel map using the first symbol */
837 sym = dso__first_symbol(dso, map->type);
838 list_for_each_entry(new_map, &md.maps, node) {
839 if (sym && sym->start >= new_map->start &&
840 sym->start < new_map->end) {
841 replacement_map = new_map;
842 break;
843 }
844 }
845
846 if (!replacement_map)
847 replacement_map = list_entry(md.maps.next, struct map, node);
848
849 /* Add new maps */
850 while (!list_empty(&md.maps)) {
851 new_map = list_entry(md.maps.next, struct map, node);
852 list_del(&new_map->node);
853 if (new_map == replacement_map) {
854 map->start = new_map->start;
855 map->end = new_map->end;
856 map->pgoff = new_map->pgoff;
857 map->map_ip = new_map->map_ip;
858 map->unmap_ip = new_map->unmap_ip;
859 map__delete(new_map);
860 /* Ensure maps are correctly ordered */
861 map_groups__remove(kmaps, map);
862 map_groups__insert(kmaps, map);
863 } else {
864 map_groups__insert(kmaps, new_map);
865 }
866 }
867
868 /*
869 * Set the data type and long name so that kcore can be read via
870 * dso__data_read_addr().
871 */
872 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
873 dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE;
874 else
875 dso->data_type = DSO_BINARY_TYPE__KCORE;
876 dso__set_long_name(dso, strdup(kcore_filename));
877
878 close(fd);
879
880 if (map->type == MAP__FUNCTION)
881 pr_debug("Using %s for kernel object code\n", kcore_filename);
882 else
883 pr_debug("Using %s for kernel data\n", kcore_filename);
884
885 return 0;
886
887out_err:
888 while (!list_empty(&md.maps)) {
889 map = list_entry(md.maps.next, struct map, node);
890 list_del(&map->node);
891 map__delete(map);
892 }
893 close(fd);
894 return -EINVAL;
895}
896
666int dso__load_kallsyms(struct dso *dso, const char *filename, 897int dso__load_kallsyms(struct dso *dso, const char *filename,
667 struct map *map, symbol_filter_t filter) 898 struct map *map, symbol_filter_t filter)
668{ 899{
@@ -680,7 +911,10 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
680 else 911 else
681 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; 912 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
682 913
683 return dso__split_kallsyms(dso, map, filter); 914 if (!dso__load_kcore(dso, map, filename))
915 return dso__split_kallsyms_for_kcore(dso, map, filter);
916 else
917 return dso__split_kallsyms(dso, map, filter);
684} 918}
685 919
686static int dso__load_perf_map(struct dso *dso, struct map *map, 920static int dso__load_perf_map(struct dso *dso, struct map *map,
@@ -843,10 +1077,15 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
843 if (!runtime_ss && syms_ss) 1077 if (!runtime_ss && syms_ss)
844 runtime_ss = syms_ss; 1078 runtime_ss = syms_ss;
845 1079
846 if (syms_ss) 1080 if (syms_ss) {
847 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, 0); 1081 int km;
848 else 1082
1083 km = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1084 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
1085 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, km);
1086 } else {
849 ret = -1; 1087 ret = -1;
1088 }
850 1089
851 if (ret > 0) { 1090 if (ret > 0) {
852 int nr_plt; 1091 int nr_plt;
@@ -888,8 +1127,11 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
888 char symfs_vmlinux[PATH_MAX]; 1127 char symfs_vmlinux[PATH_MAX];
889 enum dso_binary_type symtab_type; 1128 enum dso_binary_type symtab_type;
890 1129
891 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1130 if (vmlinux[0] == '/')
892 symbol_conf.symfs, vmlinux); 1131 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux);
1132 else
1133 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s",
1134 symbol_conf.symfs, vmlinux);
893 1135
894 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1136 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
895 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1137 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
@@ -903,6 +1145,10 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
903 symsrc__destroy(&ss); 1145 symsrc__destroy(&ss);
904 1146
905 if (err > 0) { 1147 if (err > 0) {
1148 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1149 dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
1150 else
1151 dso->data_type = DSO_BINARY_TYPE__VMLINUX;
906 dso__set_long_name(dso, (char *)vmlinux); 1152 dso__set_long_name(dso, (char *)vmlinux);
907 dso__set_loaded(dso, map->type); 1153 dso__set_loaded(dso, map->type);
908 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1154 pr_debug("Using %s for symbols\n", symfs_vmlinux);
@@ -975,7 +1221,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
975 dso__set_long_name(dso, 1221 dso__set_long_name(dso,
976 strdup(symbol_conf.vmlinux_name)); 1222 strdup(symbol_conf.vmlinux_name));
977 dso->lname_alloc = 1; 1223 dso->lname_alloc = 1;
978 goto out_fixup; 1224 return err;
979 } 1225 }
980 return err; 1226 return err;
981 } 1227 }
@@ -983,7 +1229,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
983 if (vmlinux_path != NULL) { 1229 if (vmlinux_path != NULL) {
984 err = dso__load_vmlinux_path(dso, map, filter); 1230 err = dso__load_vmlinux_path(dso, map, filter);
985 if (err > 0) 1231 if (err > 0)
986 goto out_fixup; 1232 return err;
987 } 1233 }
988 1234
989 /* do not try local files if a symfs was given */ 1235 /* do not try local files if a symfs was given */
@@ -1042,9 +1288,8 @@ do_kallsyms:
1042 pr_debug("Using %s for symbols\n", kallsyms_filename); 1288 pr_debug("Using %s for symbols\n", kallsyms_filename);
1043 free(kallsyms_allocated_filename); 1289 free(kallsyms_allocated_filename);
1044 1290
1045 if (err > 0) { 1291 if (err > 0 && !dso__is_kcore(dso)) {
1046 dso__set_long_name(dso, strdup("[kernel.kallsyms]")); 1292 dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
1047out_fixup:
1048 map__fixup_start(map); 1293 map__fixup_start(map);
1049 map__fixup_end(map); 1294 map__fixup_end(map);
1050 } 1295 }
@@ -1075,7 +1320,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1075 if (symbol_conf.default_guest_vmlinux_name != NULL) { 1320 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1076 err = dso__load_vmlinux(dso, map, 1321 err = dso__load_vmlinux(dso, map,
1077 symbol_conf.default_guest_vmlinux_name, filter); 1322 symbol_conf.default_guest_vmlinux_name, filter);
1078 goto out_try_fixup; 1323 return err;
1079 } 1324 }
1080 1325
1081 kallsyms_filename = symbol_conf.default_guest_kallsyms; 1326 kallsyms_filename = symbol_conf.default_guest_kallsyms;
@@ -1089,13 +1334,9 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1089 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1334 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
1090 if (err > 0) 1335 if (err > 0)
1091 pr_debug("Using %s for symbols\n", kallsyms_filename); 1336 pr_debug("Using %s for symbols\n", kallsyms_filename);
1092 1337 if (err > 0 && !dso__is_kcore(dso)) {
1093out_try_fixup: 1338 machine__mmap_name(machine, path, sizeof(path));
1094 if (err > 0) { 1339 dso__set_long_name(dso, strdup(path));
1095 if (kallsyms_filename != NULL) {
1096 machine__mmap_name(machine, path, sizeof(path));
1097 dso__set_long_name(dso, strdup(path));
1098 }
1099 map__fixup_start(map); 1340 map__fixup_start(map);
1100 map__fixup_end(map); 1341 map__fixup_end(map);
1101 } 1342 }