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.c505
1 files changed, 313 insertions, 192 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 5cc96c86861b..44d81d5ae8cf 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -9,8 +9,13 @@
9#include <libelf.h> 9#include <libelf.h>
10#include <gelf.h> 10#include <gelf.h>
11#include <elf.h> 11#include <elf.h>
12#include <limits.h>
12#include <sys/utsname.h> 13#include <sys/utsname.h>
13 14
15#ifndef NT_GNU_BUILD_ID
16#define NT_GNU_BUILD_ID 3
17#endif
18
14enum dso_origin { 19enum dso_origin {
15 DSO__ORIG_KERNEL = 0, 20 DSO__ORIG_KERNEL = 0,
16 DSO__ORIG_JAVA_JIT, 21 DSO__ORIG_JAVA_JIT,
@@ -26,7 +31,11 @@ static void dsos__add(struct dso *dso);
26static struct dso *dsos__find(const char *name); 31static struct dso *dsos__find(const char *name);
27static struct map *map__new2(u64 start, struct dso *dso); 32static struct map *map__new2(u64 start, struct dso *dso);
28static void kernel_maps__insert(struct map *map); 33static void kernel_maps__insert(struct map *map);
34static int dso__load_kernel_sym(struct dso *self, struct map *map,
35 symbol_filter_t filter);
29unsigned int symbol__priv_size; 36unsigned int symbol__priv_size;
37static int vmlinux_path__nr_entries;
38static char **vmlinux_path;
30 39
31static struct rb_root kernel_maps; 40static struct rb_root kernel_maps;
32 41
@@ -69,11 +78,11 @@ static void kernel_maps__fixup_end(void)
69 prev->end = curr->start - 1; 78 prev->end = curr->start - 1;
70 } 79 }
71 80
72 nd = rb_last(&curr->dso->syms); 81 /*
73 if (nd) { 82 * We still haven't the actual symbols, so guess the
74 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 83 * last map final address.
75 curr->end = sym->end; 84 */
76 } 85 curr->end = ~0UL;
77} 86}
78 87
79static struct symbol *symbol__new(u64 start, u64 len, const char *name) 88static struct symbol *symbol__new(u64 start, u64 len, const char *name)
@@ -111,6 +120,8 @@ static size_t symbol__fprintf(struct symbol *self, FILE *fp)
111 120
112static void dso__set_long_name(struct dso *self, char *name) 121static void dso__set_long_name(struct dso *self, char *name)
113{ 122{
123 if (name == NULL)
124 return;
114 self->long_name = name; 125 self->long_name = name;
115 self->long_name_len = strlen(name); 126 self->long_name_len = strlen(name);
116} 127}
@@ -323,7 +334,7 @@ out_failure:
323 * kernel range is broken in several maps, named [kernel].N, as we don't have 334 * kernel range is broken in several maps, named [kernel].N, as we don't have
324 * the original ELF section names vmlinux have. 335 * the original ELF section names vmlinux have.
325 */ 336 */
326static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules) 337static int kernel_maps__split_kallsyms(symbol_filter_t filter)
327{ 338{
328 struct map *map = kernel_map; 339 struct map *map = kernel_map;
329 struct symbol *pos; 340 struct symbol *pos;
@@ -339,9 +350,6 @@ static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules)
339 350
340 module = strchr(pos->name, '\t'); 351 module = strchr(pos->name, '\t');
341 if (module) { 352 if (module) {
342 if (!use_modules)
343 goto delete_symbol;
344
345 *module++ = '\0'; 353 *module++ = '\0';
346 354
347 if (strcmp(map->dso->name, module)) { 355 if (strcmp(map->dso->name, module)) {
@@ -381,7 +389,6 @@ static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules)
381 } 389 }
382 390
383 if (filter && filter(map, pos)) { 391 if (filter && filter(map, pos)) {
384delete_symbol:
385 rb_erase(&pos->rb_node, &kernel_map->dso->syms); 392 rb_erase(&pos->rb_node, &kernel_map->dso->syms);
386 symbol__delete(pos); 393 symbol__delete(pos);
387 } else { 394 } else {
@@ -397,17 +404,18 @@ delete_symbol:
397} 404}
398 405
399 406
400static int kernel_maps__load_kallsyms(symbol_filter_t filter, int use_modules) 407static int kernel_maps__load_kallsyms(symbol_filter_t filter)
401{ 408{
402 if (kernel_maps__load_all_kallsyms()) 409 if (kernel_maps__load_all_kallsyms())
403 return -1; 410 return -1;
404 411
405 dso__fixup_sym_end(kernel_map->dso); 412 dso__fixup_sym_end(kernel_map->dso);
413 kernel_map->dso->origin = DSO__ORIG_KERNEL;
406 414
407 return kernel_maps__split_kallsyms(filter, use_modules); 415 return kernel_maps__split_kallsyms(filter);
408} 416}
409 417
410static size_t kernel_maps__fprintf(FILE *fp) 418size_t kernel_maps__fprintf(FILE *fp)
411{ 419{
412 size_t printed = fprintf(fp, "Kernel maps:\n"); 420 size_t printed = fprintf(fp, "Kernel maps:\n");
413 struct rb_node *nd; 421 struct rb_node *nd;
@@ -883,47 +891,40 @@ out_close:
883 return err; 891 return err;
884} 892}
885 893
886bool fetch_build_id_table(struct list_head *head) 894static bool dso__build_id_equal(const struct dso *self, u8 *build_id)
887{ 895{
888 bool have_buildid = false; 896 return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0;
889 struct dso *pos; 897}
890
891 list_for_each_entry(pos, &dsos, node) {
892 struct build_id_list *new;
893 struct build_id_event b;
894 size_t len;
895
896 if (filename__read_build_id(pos->long_name,
897 &b.build_id,
898 sizeof(b.build_id)) < 0)
899 continue;
900 have_buildid = true;
901 memset(&b.header, 0, sizeof(b.header));
902 len = pos->long_name_len + 1;
903 len = ALIGN(len, 64);
904 b.header.size = sizeof(b) + len;
905
906 new = malloc(sizeof(*new));
907 if (!new)
908 die("No memory\n");
909 898
910 memcpy(&new->event, &b, sizeof(b)); 899bool dsos__read_build_ids(void)
911 new->dso_name = pos->long_name; 900{
912 new->len = len; 901 bool have_build_id = false;
902 struct dso *pos;
913 903
914 list_add_tail(&new->list, head); 904 list_for_each_entry(pos, &dsos, node)
915 } 905 if (filename__read_build_id(pos->long_name, pos->build_id,
906 sizeof(pos->build_id)) > 0) {
907 have_build_id = true;
908 pos->has_build_id = true;
909 }
916 910
917 return have_buildid; 911 return have_build_id;
918} 912}
919 913
914/*
915 * Align offset to 4 bytes as needed for note name and descriptor data.
916 */
917#define NOTE_ALIGN(n) (((n) + 3) & -4U)
918
920int filename__read_build_id(const char *filename, void *bf, size_t size) 919int filename__read_build_id(const char *filename, void *bf, size_t size)
921{ 920{
922 int fd, err = -1; 921 int fd, err = -1;
923 GElf_Ehdr ehdr; 922 GElf_Ehdr ehdr;
924 GElf_Shdr shdr; 923 GElf_Shdr shdr;
925 Elf_Data *build_id_data; 924 Elf_Data *data;
926 Elf_Scn *sec; 925 Elf_Scn *sec;
926 Elf_Kind ek;
927 void *ptr;
927 Elf *elf; 928 Elf *elf;
928 929
929 if (size < BUILD_ID_SIZE) 930 if (size < BUILD_ID_SIZE)
@@ -939,6 +940,10 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
939 goto out_close; 940 goto out_close;
940 } 941 }
941 942
943 ek = elf_kind(elf);
944 if (ek != ELF_K_ELF)
945 goto out_elf_end;
946
942 if (gelf_getehdr(elf, &ehdr) == NULL) { 947 if (gelf_getehdr(elf, &ehdr) == NULL) {
943 pr_err("%s: cannot get elf header.\n", __func__); 948 pr_err("%s: cannot get elf header.\n", __func__);
944 goto out_elf_end; 949 goto out_elf_end;
@@ -946,14 +951,37 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
946 951
947 sec = elf_section_by_name(elf, &ehdr, &shdr, 952 sec = elf_section_by_name(elf, &ehdr, &shdr,
948 ".note.gnu.build-id", NULL); 953 ".note.gnu.build-id", NULL);
949 if (sec == NULL) 954 if (sec == NULL) {
950 goto out_elf_end; 955 sec = elf_section_by_name(elf, &ehdr, &shdr,
956 ".notes", NULL);
957 if (sec == NULL)
958 goto out_elf_end;
959 }
951 960
952 build_id_data = elf_getdata(sec, NULL); 961 data = elf_getdata(sec, NULL);
953 if (build_id_data == NULL) 962 if (data == NULL)
954 goto out_elf_end; 963 goto out_elf_end;
955 memcpy(bf, build_id_data->d_buf + 16, BUILD_ID_SIZE); 964
956 err = BUILD_ID_SIZE; 965 ptr = data->d_buf;
966 while (ptr < (data->d_buf + data->d_size)) {
967 GElf_Nhdr *nhdr = ptr;
968 int namesz = NOTE_ALIGN(nhdr->n_namesz),
969 descsz = NOTE_ALIGN(nhdr->n_descsz);
970 const char *name;
971
972 ptr += sizeof(*nhdr);
973 name = ptr;
974 ptr += namesz;
975 if (nhdr->n_type == NT_GNU_BUILD_ID &&
976 nhdr->n_namesz == sizeof("GNU")) {
977 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
978 memcpy(bf, ptr, BUILD_ID_SIZE);
979 err = BUILD_ID_SIZE;
980 break;
981 }
982 }
983 ptr += descsz;
984 }
957out_elf_end: 985out_elf_end:
958 elf_end(elf); 986 elf_end(elf);
959out_close: 987out_close:
@@ -962,23 +990,48 @@ out:
962 return err; 990 return err;
963} 991}
964 992
965static char *dso__read_build_id(struct dso *self) 993int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
966{ 994{
967 int len; 995 int fd, err = -1;
968 char *build_id = NULL;
969 unsigned char rawbf[BUILD_ID_SIZE];
970 996
971 len = filename__read_build_id(self->long_name, rawbf, sizeof(rawbf)); 997 if (size < BUILD_ID_SIZE)
972 if (len < 0)
973 goto out; 998 goto out;
974 999
975 build_id = malloc(len * 2 + 1); 1000 fd = open(filename, O_RDONLY);
976 if (build_id == NULL) 1001 if (fd < 0)
977 goto out; 1002 goto out;
978 1003
979 build_id__sprintf(rawbf, len, build_id); 1004 while (1) {
1005 char bf[BUFSIZ];
1006 GElf_Nhdr nhdr;
1007 int namesz, descsz;
1008
1009 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1010 break;
1011
1012 namesz = NOTE_ALIGN(nhdr.n_namesz);
1013 descsz = NOTE_ALIGN(nhdr.n_descsz);
1014 if (nhdr.n_type == NT_GNU_BUILD_ID &&
1015 nhdr.n_namesz == sizeof("GNU")) {
1016 if (read(fd, bf, namesz) != namesz)
1017 break;
1018 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1019 if (read(fd, build_id,
1020 BUILD_ID_SIZE) == BUILD_ID_SIZE) {
1021 err = 0;
1022 break;
1023 }
1024 } else if (read(fd, bf, descsz) != descsz)
1025 break;
1026 } else {
1027 int n = namesz + descsz;
1028 if (read(fd, bf, n) != n)
1029 break;
1030 }
1031 }
1032 close(fd);
980out: 1033out:
981 return build_id; 1034 return err;
982} 1035}
983 1036
984char dso__symtab_origin(const struct dso *self) 1037char dso__symtab_origin(const struct dso *self)
@@ -1001,12 +1054,17 @@ char dso__symtab_origin(const struct dso *self)
1001int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) 1054int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1002{ 1055{
1003 int size = PATH_MAX; 1056 int size = PATH_MAX;
1004 char *name = malloc(size), *build_id = NULL; 1057 char *name;
1058 u8 build_id[BUILD_ID_SIZE];
1005 int ret = -1; 1059 int ret = -1;
1006 int fd; 1060 int fd;
1007 1061
1008 self->loaded = 1; 1062 self->loaded = 1;
1009 1063
1064 if (self->kernel)
1065 return dso__load_kernel_sym(self, map, filter);
1066
1067 name = malloc(size);
1010 if (!name) 1068 if (!name)
1011 return -1; 1069 return -1;
1012 1070
@@ -1023,8 +1081,6 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1023 1081
1024more: 1082more:
1025 do { 1083 do {
1026 int berr = 0;
1027
1028 self->origin++; 1084 self->origin++;
1029 switch (self->origin) { 1085 switch (self->origin) {
1030 case DSO__ORIG_FEDORA: 1086 case DSO__ORIG_FEDORA:
@@ -1036,12 +1092,18 @@ more:
1036 self->long_name); 1092 self->long_name);
1037 break; 1093 break;
1038 case DSO__ORIG_BUILDID: 1094 case DSO__ORIG_BUILDID:
1039 build_id = dso__read_build_id(self); 1095 if (filename__read_build_id(self->long_name, build_id,
1040 if (build_id != NULL) { 1096 sizeof(build_id))) {
1097 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1098
1099 build_id__sprintf(build_id, sizeof(build_id),
1100 build_id_hex);
1041 snprintf(name, size, 1101 snprintf(name, size,
1042 "/usr/lib/debug/.build-id/%.2s/%s.debug", 1102 "/usr/lib/debug/.build-id/%.2s/%s.debug",
1043 build_id, build_id + 2); 1103 build_id_hex, build_id_hex + 2);
1044 goto compare_build_id; 1104 if (self->has_build_id)
1105 goto compare_build_id;
1106 break;
1045 } 1107 }
1046 self->origin++; 1108 self->origin++;
1047 /* Fall thru */ 1109 /* Fall thru */
@@ -1054,18 +1116,11 @@ more:
1054 } 1116 }
1055 1117
1056 if (self->has_build_id) { 1118 if (self->has_build_id) {
1057 bool match; 1119 if (filename__read_build_id(name, build_id,
1058 build_id = malloc(BUILD_ID_SIZE); 1120 sizeof(build_id)) < 0)
1059 if (build_id == NULL)
1060 goto more; 1121 goto more;
1061 berr = filename__read_build_id(name, build_id,
1062 BUILD_ID_SIZE);
1063compare_build_id: 1122compare_build_id:
1064 match = berr > 0 && memcmp(build_id, self->build_id, 1123 if (!dso__build_id_equal(self, build_id))
1065 sizeof(self->build_id)) == 0;
1066 free(build_id);
1067 build_id = NULL;
1068 if (!match)
1069 goto more; 1124 goto more;
1070 } 1125 }
1071 1126
@@ -1100,7 +1155,8 @@ static void kernel_maps__insert(struct map *map)
1100 maps__insert(&kernel_maps, map); 1155 maps__insert(&kernel_maps, map);
1101} 1156}
1102 1157
1103struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp) 1158struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp,
1159 symbol_filter_t filter)
1104{ 1160{
1105 struct map *map = maps__find(&kernel_maps, ip); 1161 struct map *map = maps__find(&kernel_maps, ip);
1106 1162
@@ -1109,7 +1165,7 @@ struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp)
1109 1165
1110 if (map) { 1166 if (map) {
1111 ip = map->map_ip(map, ip); 1167 ip = map->map_ip(map, ip);
1112 return map->dso->find_symbol(map->dso, ip); 1168 return map__find_symbol(map, ip, filter);
1113 } 1169 }
1114 1170
1115 return NULL; 1171 return NULL;
@@ -1129,32 +1185,13 @@ struct map *kernel_maps__find_by_dso_name(const char *name)
1129 return NULL; 1185 return NULL;
1130} 1186}
1131 1187
1132static int dso__load_module_sym(struct dso *self, struct map *map, 1188static int dsos__set_modules_path_dir(char *dirname)
1133 symbol_filter_t filter)
1134{
1135 int err = 0, fd = open(self->long_name, O_RDONLY);
1136
1137 self->loaded = 1;
1138
1139 if (fd < 0) {
1140 pr_err("%s: cannot open %s\n", __func__, self->long_name);
1141 return err;
1142 }
1143
1144 err = dso__load_sym(self, map, self->long_name, fd, filter, 0, 1);
1145 close(fd);
1146
1147 return err;
1148}
1149
1150static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter)
1151{ 1189{
1152 struct dirent *dent; 1190 struct dirent *dent;
1153 int nr_symbols = 0, err;
1154 DIR *dir = opendir(dirname); 1191 DIR *dir = opendir(dirname);
1155 1192
1156 if (!dir) { 1193 if (!dir) {
1157 pr_err("%s: cannot open %s dir\n", __func__, dirname); 1194 pr_debug("%s: cannot open %s dir\n", __func__, dirname);
1158 return -1; 1195 return -1;
1159 } 1196 }
1160 1197
@@ -1168,14 +1205,12 @@ static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter)
1168 1205
1169 snprintf(path, sizeof(path), "%s/%s", 1206 snprintf(path, sizeof(path), "%s/%s",
1170 dirname, dent->d_name); 1207 dirname, dent->d_name);
1171 err = dsos__load_modules_sym_dir(path, filter); 1208 if (dsos__set_modules_path_dir(path) < 0)
1172 if (err < 0)
1173 goto failure; 1209 goto failure;
1174 } else { 1210 } else {
1175 char *dot = strrchr(dent->d_name, '.'), 1211 char *dot = strrchr(dent->d_name, '.'),
1176 dso_name[PATH_MAX]; 1212 dso_name[PATH_MAX];
1177 struct map *map; 1213 struct map *map;
1178 struct rb_node *last;
1179 char *long_name; 1214 char *long_name;
1180 1215
1181 if (dot == NULL || strcmp(dot, ".ko")) 1216 if (dot == NULL || strcmp(dot, ".ko"))
@@ -1195,36 +1230,16 @@ static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter)
1195 if (long_name == NULL) 1230 if (long_name == NULL)
1196 goto failure; 1231 goto failure;
1197 dso__set_long_name(map->dso, long_name); 1232 dso__set_long_name(map->dso, long_name);
1198 dso__set_basename(map->dso);
1199
1200 err = dso__load_module_sym(map->dso, map, filter);
1201 if (err < 0)
1202 goto failure;
1203 last = rb_last(&map->dso->syms);
1204 if (last) {
1205 struct symbol *sym;
1206 /*
1207 * We do this here as well, even having the
1208 * symbol size found in the symtab because
1209 * misannotated ASM symbols may have the size
1210 * set to zero.
1211 */
1212 dso__fixup_sym_end(map->dso);
1213
1214 sym = rb_entry(last, struct symbol, rb_node);
1215 map->end = map->start + sym->end;
1216 }
1217 } 1233 }
1218 nr_symbols += err;
1219 } 1234 }
1220 1235
1221 return nr_symbols; 1236 return 0;
1222failure: 1237failure:
1223 closedir(dir); 1238 closedir(dir);
1224 return -1; 1239 return -1;
1225} 1240}
1226 1241
1227static int dsos__load_modules_sym(symbol_filter_t filter) 1242static int dsos__set_modules_path(void)
1228{ 1243{
1229 struct utsname uts; 1244 struct utsname uts;
1230 char modules_path[PATH_MAX]; 1245 char modules_path[PATH_MAX];
@@ -1235,7 +1250,7 @@ static int dsos__load_modules_sym(symbol_filter_t filter)
1235 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", 1250 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
1236 uts.release); 1251 uts.release);
1237 1252
1238 return dsos__load_modules_sym_dir(modules_path, filter); 1253 return dsos__set_modules_path_dir(modules_path);
1239} 1254}
1240 1255
1241/* 1256/*
@@ -1257,7 +1272,7 @@ static struct map *map__new2(u64 start, struct dso *dso)
1257 return self; 1272 return self;
1258} 1273}
1259 1274
1260static int dsos__load_modules(void) 1275static int kernel_maps__create_module_maps(void)
1261{ 1276{
1262 char *line = NULL; 1277 char *line = NULL;
1263 size_t n; 1278 size_t n;
@@ -1307,6 +1322,12 @@ static int dsos__load_modules(void)
1307 goto out_delete_line; 1322 goto out_delete_line;
1308 } 1323 }
1309 1324
1325 snprintf(name, sizeof(name),
1326 "/sys/module/%s/notes/.note.gnu.build-id", line);
1327 if (sysfs__read_build_id(name, dso->build_id,
1328 sizeof(dso->build_id)) == 0)
1329 dso->has_build_id = true;
1330
1310 dso->origin = DSO__ORIG_KMODULE; 1331 dso->origin = DSO__ORIG_KMODULE;
1311 kernel_maps__insert(map); 1332 kernel_maps__insert(map);
1312 dsos__add(dso); 1333 dsos__add(dso);
@@ -1315,7 +1336,7 @@ static int dsos__load_modules(void)
1315 free(line); 1336 free(line);
1316 fclose(file); 1337 fclose(file);
1317 1338
1318 return 0; 1339 return dsos__set_modules_path();
1319 1340
1320out_delete_line: 1341out_delete_line:
1321 free(line); 1342 free(line);
@@ -1326,13 +1347,37 @@ out_failure:
1326static int dso__load_vmlinux(struct dso *self, struct map *map, 1347static int dso__load_vmlinux(struct dso *self, struct map *map,
1327 const char *vmlinux, symbol_filter_t filter) 1348 const char *vmlinux, symbol_filter_t filter)
1328{ 1349{
1329 int err, fd = open(vmlinux, O_RDONLY); 1350 int err = -1, fd;
1330 1351
1331 self->loaded = 1; 1352 if (self->has_build_id) {
1353 u8 build_id[BUILD_ID_SIZE];
1354
1355 if (filename__read_build_id(vmlinux, build_id,
1356 sizeof(build_id)) < 0) {
1357 pr_debug("No build_id in %s, ignoring it\n", vmlinux);
1358 return -1;
1359 }
1360 if (!dso__build_id_equal(self, build_id)) {
1361 char expected_build_id[BUILD_ID_SIZE * 2 + 1],
1362 vmlinux_build_id[BUILD_ID_SIZE * 2 + 1];
1363
1364 build_id__sprintf(self->build_id,
1365 sizeof(self->build_id),
1366 expected_build_id);
1367 build_id__sprintf(build_id, sizeof(build_id),
1368 vmlinux_build_id);
1369 pr_debug("build_id in %s is %s while expected is %s, "
1370 "ignoring it\n", vmlinux, vmlinux_build_id,
1371 expected_build_id);
1372 return -1;
1373 }
1374 }
1332 1375
1376 fd = open(vmlinux, O_RDONLY);
1333 if (fd < 0) 1377 if (fd < 0)
1334 return -1; 1378 return -1;
1335 1379
1380 self->loaded = 1;
1336 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0); 1381 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0);
1337 1382
1338 close(fd); 1383 close(fd);
@@ -1340,78 +1385,55 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1340 return err; 1385 return err;
1341} 1386}
1342 1387
1343int dsos__load_kernel(const char *vmlinux, symbol_filter_t filter, 1388static int dso__load_kernel_sym(struct dso *self, struct map *map,
1344 int use_modules) 1389 symbol_filter_t filter)
1345{ 1390{
1346 int err = -1; 1391 int err;
1347 struct dso *dso = dso__new(vmlinux); 1392 bool is_kallsyms;
1348 1393
1349 if (dso == NULL) 1394 if (vmlinux_path != NULL) {
1350 return -1; 1395 int i;
1351 1396 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1352 dso->short_name = "[kernel]"; 1397 vmlinux_path__nr_entries);
1353 kernel_map = map__new2(0, dso); 1398 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1354 if (kernel_map == NULL) 1399 err = dso__load_vmlinux(self, map, vmlinux_path[i],
1355 goto out_delete_dso; 1400 filter);
1356 1401 if (err > 0) {
1357 kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip; 1402 pr_debug("Using %s for symbols\n",
1358 1403 vmlinux_path[i]);
1359 if (use_modules && dsos__load_modules() < 0) { 1404 dso__set_long_name(self,
1360 pr_warning("Failed to load list of modules in use! " 1405 strdup(vmlinux_path[i]));
1361 "Continuing...\n"); 1406 goto out_fixup;
1362 use_modules = 0; 1407 }
1363 }
1364
1365 if (vmlinux) {
1366 err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter);
1367 if (err > 0 && use_modules) {
1368 int syms = dsos__load_modules_sym(filter);
1369
1370 if (syms < 0)
1371 pr_warning("Failed to read module symbols!"
1372 " Continuing...\n");
1373 else
1374 err += syms;
1375 } 1408 }
1376 } 1409 }
1377 1410
1378 if (err <= 0) 1411 is_kallsyms = self->long_name[0] == '[';
1379 err = kernel_maps__load_kallsyms(filter, use_modules); 1412 if (is_kallsyms)
1413 goto do_kallsyms;
1414
1415 err = dso__load_vmlinux(self, map, self->long_name, filter);
1416 if (err <= 0) {
1417 pr_info("The file %s cannot be used, "
1418 "trying to use /proc/kallsyms...", self->long_name);
1419 sleep(2);
1420do_kallsyms:
1421 err = kernel_maps__load_kallsyms(filter);
1422 if (err > 0 && !is_kallsyms)
1423 dso__set_long_name(self, strdup("[kernel.kallsyms]"));
1424 }
1380 1425
1381 if (err > 0) { 1426 if (err > 0) {
1382 struct rb_node *node = rb_first(&dso->syms); 1427out_fixup:
1383 struct symbol *sym = rb_entry(node, struct symbol, rb_node); 1428 map__fixup_start(map);
1384 1429 map__fixup_end(map);
1385 kernel_map->start = sym->start;
1386 node = rb_last(&dso->syms);
1387 sym = rb_entry(node, struct symbol, rb_node);
1388 kernel_map->end = sym->end;
1389
1390 dso->origin = DSO__ORIG_KERNEL;
1391 kernel_maps__insert(kernel_map);
1392 /*
1393 * Now that we have all sorted out, just set the ->end of all
1394 * maps:
1395 */
1396 kernel_maps__fixup_end();
1397 dsos__add(dso);
1398
1399 if (verbose)
1400 kernel_maps__fprintf(stderr);
1401 } 1430 }
1402 1431
1403 return err; 1432 return err;
1404
1405out_delete_dso:
1406 dso__delete(dso);
1407 return -1;
1408} 1433}
1409 1434
1410LIST_HEAD(dsos); 1435LIST_HEAD(dsos);
1411struct dso *vdso; 1436struct dso *vdso;
1412
1413const char *vmlinux_name = "vmlinux";
1414int modules;
1415 1437
1416static void dsos__add(struct dso *dso) 1438static void dsos__add(struct dso *dso)
1417{ 1439{
@@ -1463,18 +1485,117 @@ size_t dsos__fprintf_buildid(FILE *fp)
1463 return ret; 1485 return ret;
1464} 1486}
1465 1487
1466int load_kernel(symbol_filter_t filter) 1488static int kernel_maps__create_kernel_map(const char *vmlinux_name)
1467{ 1489{
1468 if (dsos__load_kernel(vmlinux_name, filter, modules) <= 0) 1490 struct dso *kernel = dso__new(vmlinux_name ?: "[kernel.kallsyms]");
1491
1492 if (kernel == NULL)
1469 return -1; 1493 return -1;
1470 1494
1495 kernel_map = map__new2(0, kernel);
1496 if (kernel_map == NULL)
1497 goto out_delete_kernel_dso;
1498
1499 kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip;
1500 kernel->short_name = "[kernel]";
1501 kernel->kernel = 1;
1502
1471 vdso = dso__new("[vdso]"); 1503 vdso = dso__new("[vdso]");
1472 if (!vdso) 1504 if (vdso == NULL)
1473 return -1; 1505 goto out_delete_kernel_map;
1506
1507 if (sysfs__read_build_id("/sys/kernel/notes", kernel->build_id,
1508 sizeof(kernel->build_id)) == 0)
1509 kernel->has_build_id = true;
1474 1510
1511 kernel_maps__insert(kernel_map);
1512 dsos__add(kernel);
1475 dsos__add(vdso); 1513 dsos__add(vdso);
1476 1514
1477 return 0; 1515 return 0;
1516
1517out_delete_kernel_map:
1518 map__delete(kernel_map);
1519 kernel_map = NULL;
1520out_delete_kernel_dso:
1521 dso__delete(kernel);
1522 return -1;
1523}
1524
1525static void vmlinux_path__exit(void)
1526{
1527 while (--vmlinux_path__nr_entries >= 0) {
1528 free(vmlinux_path[vmlinux_path__nr_entries]);
1529 vmlinux_path[vmlinux_path__nr_entries] = NULL;
1530 }
1531
1532 free(vmlinux_path);
1533 vmlinux_path = NULL;
1534}
1535
1536static int vmlinux_path__init(void)
1537{
1538 struct utsname uts;
1539 char bf[PATH_MAX];
1540
1541 if (uname(&uts) < 0)
1542 return -1;
1543
1544 vmlinux_path = malloc(sizeof(char *) * 5);
1545 if (vmlinux_path == NULL)
1546 return -1;
1547
1548 vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux");
1549 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1550 goto out_fail;
1551 ++vmlinux_path__nr_entries;
1552 vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux");
1553 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1554 goto out_fail;
1555 ++vmlinux_path__nr_entries;
1556 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
1557 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1558 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1559 goto out_fail;
1560 ++vmlinux_path__nr_entries;
1561 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release);
1562 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1563 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1564 goto out_fail;
1565 ++vmlinux_path__nr_entries;
1566 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1567 uts.release);
1568 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1569 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1570 goto out_fail;
1571 ++vmlinux_path__nr_entries;
1572
1573 return 0;
1574
1575out_fail:
1576 vmlinux_path__exit();
1577 return -1;
1578}
1579
1580int kernel_maps__init(const char *vmlinux_name, bool try_vmlinux_path,
1581 bool use_modules)
1582{
1583 if (try_vmlinux_path && vmlinux_path__init() < 0)
1584 return -1;
1585
1586 if (kernel_maps__create_kernel_map(vmlinux_name) < 0) {
1587 vmlinux_path__exit();
1588 return -1;
1589 }
1590
1591 if (use_modules && kernel_maps__create_module_maps() < 0)
1592 pr_debug("Failed to load list of modules in use, "
1593 "continuing...\n");
1594 /*
1595 * Now that we have all the maps created, just set the ->end of them:
1596 */
1597 kernel_maps__fixup_end();
1598 return 0;
1478} 1599}
1479 1600
1480void symbol__init(unsigned int priv_size) 1601void symbol__init(unsigned int priv_size)