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.c157
1 files changed, 58 insertions, 99 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 581db4c43251..b6a2941e7786 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -29,12 +29,11 @@ enum dso_origin {
29}; 29};
30 30
31static void dsos__add(struct list_head *head, struct dso *dso); 31static void dsos__add(struct list_head *head, struct dso *dso);
32static struct map *kernel_maps__find_by_dso_name(const char *name); 32static struct map *thread__find_map_by_name(struct thread *self, char *name);
33static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 33static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
34static void kernel_maps__insert(struct map *map);
35struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); 34struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr);
36static int dso__load_kernel_sym(struct dso *self, struct map *map, 35static int dso__load_kernel_sym(struct dso *self, struct map *map,
37 symbol_filter_t filter); 36 struct thread *thread, symbol_filter_t filter);
38unsigned int symbol__priv_size; 37unsigned int symbol__priv_size;
39static int vmlinux_path__nr_entries; 38static int vmlinux_path__nr_entries;
40static char **vmlinux_path; 39static char **vmlinux_path;
@@ -44,7 +43,7 @@ static struct symbol_conf symbol_conf__defaults = {
44 .try_vmlinux_path = true, 43 .try_vmlinux_path = true,
45}; 44};
46 45
47static struct rb_root kernel_maps[MAP__NR_TYPES]; 46static struct thread kthread_mem, *kthread = &kthread_mem;
48 47
49bool dso__loaded(const struct dso *self, enum map_type type) 48bool dso__loaded(const struct dso *self, enum map_type type)
50{ 49{
@@ -79,10 +78,10 @@ static void symbols__fixup_end(struct rb_root *self)
79 curr->end = roundup(curr->start, 4096); 78 curr->end = roundup(curr->start, 4096);
80} 79}
81 80
82static void __kernel_maps__fixup_end(struct rb_root *root) 81static void __thread__fixup_maps_end(struct thread *self, enum map_type type)
83{ 82{
84 struct map *prev, *curr; 83 struct map *prev, *curr;
85 struct rb_node *nd, *prevnd = rb_first(root); 84 struct rb_node *nd, *prevnd = rb_first(&self->maps[type]);
86 85
87 if (prevnd == NULL) 86 if (prevnd == NULL)
88 return; 87 return;
@@ -102,11 +101,11 @@ static void __kernel_maps__fixup_end(struct rb_root *root)
102 curr->end = ~0UL; 101 curr->end = ~0UL;
103} 102}
104 103
105static void kernel_maps__fixup_end(void) 104static void thread__fixup_maps_end(struct thread *self)
106{ 105{
107 int i; 106 int i;
108 for (i = 0; i < MAP__NR_TYPES; ++i) 107 for (i = 0; i < MAP__NR_TYPES; ++i)
109 __kernel_maps__fixup_end(&kernel_maps[i]); 108 __thread__fixup_maps_end(self, i);
110} 109}
111 110
112static struct symbol *symbol__new(u64 start, u64 len, const char *name) 111static struct symbol *symbol__new(u64 start, u64 len, const char *name)
@@ -274,25 +273,16 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
274 return fprintf(fp, "%s", sbuild_id); 273 return fprintf(fp, "%s", sbuild_id);
275} 274}
276 275
277static const char * map_type__name[MAP__NR_TYPES] = { 276size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
278 [MAP__FUNCTION] = "Functions",
279};
280
281size_t dso__fprintf(struct dso *self, FILE *fp)
282{ 277{
283 int i;
284 struct rb_node *nd; 278 struct rb_node *nd;
285 size_t ret = fprintf(fp, "dso: %s (", self->short_name); 279 size_t ret = fprintf(fp, "dso: %s (", self->short_name);
286 280
287 ret += dso__fprintf_buildid(self, fp); 281 ret += dso__fprintf_buildid(self, fp);
288 ret += fprintf(fp, ")\n"); 282 ret += fprintf(fp, ")\n");
289 for (i = 0; i < MAP__NR_TYPES; ++i) { 283 for (nd = rb_first(&self->symbols[type]); nd; nd = rb_next(nd)) {
290 ret += fprintf(fp, "%s:\n", map_type__name[i]); 284 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
291 285 ret += symbol__fprintf(pos, fp);
292 for (nd = rb_first(&self->symbols[i]); nd; nd = rb_next(nd)) {
293 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
294 ret += symbol__fprintf(pos, fp);
295 }
296 } 286 }
297 287
298 return ret; 288 return ret;
@@ -373,7 +363,7 @@ out_failure:
373 * kernel range is broken in several maps, named [kernel].N, as we don't have 363 * kernel range is broken in several maps, named [kernel].N, as we don't have
374 * the original ELF section names vmlinux have. 364 * the original ELF section names vmlinux have.
375 */ 365 */
376static int dso__split_kallsyms(struct dso *self, struct map *map, 366static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread *thread,
377 symbol_filter_t filter) 367 symbol_filter_t filter)
378{ 368{
379 struct map *curr_map = map; 369 struct map *curr_map = map;
@@ -394,10 +384,10 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
394 *module++ = '\0'; 384 *module++ = '\0';
395 385
396 if (strcmp(self->name, module)) { 386 if (strcmp(self->name, module)) {
397 curr_map = kernel_maps__find_by_dso_name(module); 387 curr_map = thread__find_map_by_name(thread, module);
398 if (curr_map == NULL) { 388 if (curr_map == NULL) {
399 pr_err("/proc/{kallsyms,modules} " 389 pr_debug("/proc/{kallsyms,modules} "
400 "inconsistency!\n"); 390 "inconsistency!\n");
401 return -1; 391 return -1;
402 } 392 }
403 } 393 }
@@ -425,7 +415,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
425 } 415 }
426 416
427 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; 417 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
428 kernel_maps__insert(curr_map); 418 __thread__insert_map(thread, curr_map);
429 ++kernel_range; 419 ++kernel_range;
430 } 420 }
431 421
@@ -446,7 +436,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
446 436
447 437
448static int dso__load_kallsyms(struct dso *self, struct map *map, 438static int dso__load_kallsyms(struct dso *self, struct map *map,
449 symbol_filter_t filter) 439 struct thread *thread, symbol_filter_t filter)
450{ 440{
451 if (dso__load_all_kallsyms(self, map) < 0) 441 if (dso__load_all_kallsyms(self, map) < 0)
452 return -1; 442 return -1;
@@ -454,35 +444,13 @@ static int dso__load_kallsyms(struct dso *self, struct map *map,
454 symbols__fixup_end(&self->symbols[map->type]); 444 symbols__fixup_end(&self->symbols[map->type]);
455 self->origin = DSO__ORIG_KERNEL; 445 self->origin = DSO__ORIG_KERNEL;
456 446
457 return dso__split_kallsyms(self, map, filter); 447 return dso__split_kallsyms(self, map, thread, filter);
458}
459
460static size_t __kernel_maps__fprintf(enum map_type type, FILE *fp)
461{
462 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
463 struct rb_node *nd;
464
465 for (nd = rb_first(&kernel_maps[type]); nd; nd = rb_next(nd)) {
466 struct map *pos = rb_entry(nd, struct map, rb_node);
467
468 printed += fprintf(fp, "Map:");
469 printed += map__fprintf(pos, fp);
470 if (verbose > 1) {
471 printed += dso__fprintf(pos->dso, fp);
472 printed += fprintf(fp, "--\n");
473 }
474 }
475
476 return printed;
477} 448}
478 449
479size_t kernel_maps__fprintf(FILE *fp) 450size_t kernel_maps__fprintf(FILE *fp)
480{ 451{
481 size_t printed = fprintf(fp, "Kernel maps:\n"); 452 size_t printed = fprintf(fp, "Kernel maps:\n");
482 int i; 453 printed += thread__fprintf_maps(kthread, fp);
483 for (i = 0; i < MAP__NR_TYPES; ++i)
484 printed += __kernel_maps__fprintf(i, fp);
485
486 return printed + fprintf(fp, "END kernel maps\n"); 454 return printed + fprintf(fp, "END kernel maps\n");
487} 455}
488 456
@@ -772,9 +740,9 @@ out:
772 return 0; 740 return 0;
773} 741}
774 742
775static int dso__load_sym(struct dso *self, struct map *map, const char *name, 743static int dso__load_sym(struct dso *self, struct map *map,
776 int fd, symbol_filter_t filter, int kernel, 744 struct thread *thread, const char *name, int fd,
777 int kmodule) 745 symbol_filter_t filter, int kernel, int kmodule)
778{ 746{
779 struct map *curr_map = map; 747 struct map *curr_map = map;
780 struct dso *curr_dso = self; 748 struct dso *curr_dso = self;
@@ -877,7 +845,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
877 snprintf(dso_name, sizeof(dso_name), 845 snprintf(dso_name, sizeof(dso_name),
878 "%s%s", self->short_name, section_name); 846 "%s%s", self->short_name, section_name);
879 847
880 curr_map = kernel_maps__find_by_dso_name(dso_name); 848 curr_map = thread__find_map_by_name(thread, dso_name);
881 if (curr_map == NULL) { 849 if (curr_map == NULL) {
882 u64 start = sym.st_value; 850 u64 start = sym.st_value;
883 851
@@ -896,7 +864,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
896 curr_map->map_ip = identity__map_ip; 864 curr_map->map_ip = identity__map_ip;
897 curr_map->unmap_ip = identity__map_ip; 865 curr_map->unmap_ip = identity__map_ip;
898 curr_dso->origin = DSO__ORIG_KERNEL; 866 curr_dso->origin = DSO__ORIG_KERNEL;
899 kernel_maps__insert(curr_map); 867 __thread__insert_map(kthread, curr_map);
900 dsos__add(&dsos__kernel, curr_dso); 868 dsos__add(&dsos__kernel, curr_dso);
901 } else 869 } else
902 curr_dso = curr_map->dso; 870 curr_dso = curr_map->dso;
@@ -1121,7 +1089,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1121 dso__set_loaded(self, map->type); 1089 dso__set_loaded(self, map->type);
1122 1090
1123 if (self->kernel) 1091 if (self->kernel)
1124 return dso__load_kernel_sym(self, map, filter); 1092 return dso__load_kernel_sym(self, map, kthread, filter);
1125 1093
1126 name = malloc(size); 1094 name = malloc(size);
1127 if (!name) 1095 if (!name)
@@ -1186,7 +1154,7 @@ compare_build_id:
1186 fd = open(name, O_RDONLY); 1154 fd = open(name, O_RDONLY);
1187 } while (fd < 0); 1155 } while (fd < 0);
1188 1156
1189 ret = dso__load_sym(self, map, name, fd, filter, 0, 0); 1157 ret = dso__load_sym(self, map, NULL, name, fd, filter, 0, 0);
1190 close(fd); 1158 close(fd);
1191 1159
1192 /* 1160 /*
@@ -1207,16 +1175,11 @@ out:
1207 return ret; 1175 return ret;
1208} 1176}
1209 1177
1210static void kernel_maps__insert(struct map *map) 1178static struct symbol *thread__find_symbol(struct thread *self, u64 ip,
1211{ 1179 enum map_type type, struct map **mapp,
1212 maps__insert(&kernel_maps[map->type], map); 1180 symbol_filter_t filter)
1213}
1214
1215static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type,
1216 struct map **mapp,
1217 symbol_filter_t filter)
1218{ 1181{
1219 struct map *map = maps__find(&kernel_maps[type], ip); 1182 struct map *map = thread__find_map(self, type, ip);
1220 1183
1221 if (mapp) 1184 if (mapp)
1222 *mapp = map; 1185 *mapp = map;
@@ -1224,9 +1187,7 @@ static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type,
1224 if (map) { 1187 if (map) {
1225 ip = map->map_ip(map, ip); 1188 ip = map->map_ip(map, ip);
1226 return map__find_symbol(map, ip, filter); 1189 return map__find_symbol(map, ip, filter);
1227 } else 1190 }
1228 WARN_ONCE(RB_EMPTY_ROOT(&kernel_maps[type]),
1229 "Empty kernel_maps, was symbol__init() called?\n");
1230 1191
1231 return NULL; 1192 return NULL;
1232} 1193}
@@ -1234,14 +1195,14 @@ static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type,
1234struct symbol *kernel_maps__find_function(u64 ip, struct map **mapp, 1195struct symbol *kernel_maps__find_function(u64 ip, struct map **mapp,
1235 symbol_filter_t filter) 1196 symbol_filter_t filter)
1236{ 1197{
1237 return kernel_maps__find_symbol(ip, MAP__FUNCTION, mapp, filter); 1198 return thread__find_symbol(kthread, ip, MAP__FUNCTION, mapp, filter);
1238} 1199}
1239 1200
1240static struct map *kernel_maps__find_by_dso_name(const char *name) 1201static struct map *thread__find_map_by_name(struct thread *self, char *name)
1241{ 1202{
1242 struct rb_node *nd; 1203 struct rb_node *nd;
1243 1204
1244 for (nd = rb_first(&kernel_maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { 1205 for (nd = rb_first(&self->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
1245 struct map *map = rb_entry(nd, struct map, rb_node); 1206 struct map *map = rb_entry(nd, struct map, rb_node);
1246 1207
1247 if (map->dso && strcmp(map->dso->name, name) == 0) 1208 if (map->dso && strcmp(map->dso->name, name) == 0)
@@ -1285,7 +1246,7 @@ static int dsos__set_modules_path_dir(char *dirname)
1285 (int)(dot - dent->d_name), dent->d_name); 1246 (int)(dot - dent->d_name), dent->d_name);
1286 1247
1287 strxfrchar(dso_name, '-', '_'); 1248 strxfrchar(dso_name, '-', '_');
1288 map = kernel_maps__find_by_dso_name(dso_name); 1249 map = thread__find_map_by_name(kthread, dso_name);
1289 if (map == NULL) 1250 if (map == NULL)
1290 continue; 1251 continue;
1291 1252
@@ -1338,7 +1299,7 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1338 return self; 1299 return self;
1339} 1300}
1340 1301
1341static int kernel_maps__create_module_maps(void) 1302static int thread__create_module_maps(struct thread *self)
1342{ 1303{
1343 char *line = NULL; 1304 char *line = NULL;
1344 size_t n; 1305 size_t n;
@@ -1395,7 +1356,7 @@ static int kernel_maps__create_module_maps(void)
1395 dso->has_build_id = true; 1356 dso->has_build_id = true;
1396 1357
1397 dso->origin = DSO__ORIG_KMODULE; 1358 dso->origin = DSO__ORIG_KMODULE;
1398 kernel_maps__insert(map); 1359 __thread__insert_map(self, map);
1399 dsos__add(&dsos__kernel, dso); 1360 dsos__add(&dsos__kernel, dso);
1400 } 1361 }
1401 1362
@@ -1410,7 +1371,7 @@ out_failure:
1410 return -1; 1371 return -1;
1411} 1372}
1412 1373
1413static int dso__load_vmlinux(struct dso *self, struct map *map, 1374static int dso__load_vmlinux(struct dso *self, struct map *map, struct thread *thread,
1414 const char *vmlinux, symbol_filter_t filter) 1375 const char *vmlinux, symbol_filter_t filter)
1415{ 1376{
1416 int err = -1, fd; 1377 int err = -1, fd;
@@ -1444,15 +1405,14 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1444 return -1; 1405 return -1;
1445 1406
1446 dso__set_loaded(self, map->type); 1407 dso__set_loaded(self, map->type);
1447 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0); 1408 err = dso__load_sym(self, map, thread, self->long_name, fd, filter, 1, 0);
1448
1449 close(fd); 1409 close(fd);
1450 1410
1451 return err; 1411 return err;
1452} 1412}
1453 1413
1454static int dso__load_kernel_sym(struct dso *self, struct map *map, 1414static int dso__load_kernel_sym(struct dso *self, struct map *map,
1455 symbol_filter_t filter) 1415 struct thread *thread, symbol_filter_t filter)
1456{ 1416{
1457 int err; 1417 int err;
1458 bool is_kallsyms; 1418 bool is_kallsyms;
@@ -1462,8 +1422,8 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1462 pr_debug("Looking at the vmlinux_path (%d entries long)\n", 1422 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1463 vmlinux_path__nr_entries); 1423 vmlinux_path__nr_entries);
1464 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1424 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1465 err = dso__load_vmlinux(self, map, vmlinux_path[i], 1425 err = dso__load_vmlinux(self, map, thread,
1466 filter); 1426 vmlinux_path[i], filter);
1467 if (err > 0) { 1427 if (err > 0) {
1468 pr_debug("Using %s for symbols\n", 1428 pr_debug("Using %s for symbols\n",
1469 vmlinux_path[i]); 1429 vmlinux_path[i]);
@@ -1478,12 +1438,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1478 if (is_kallsyms) 1438 if (is_kallsyms)
1479 goto do_kallsyms; 1439 goto do_kallsyms;
1480 1440
1481 err = dso__load_vmlinux(self, map, self->long_name, filter); 1441 err = dso__load_vmlinux(self, map, thread, self->long_name, filter);
1482 if (err <= 0) { 1442 if (err <= 0) {
1483 pr_info("The file %s cannot be used, " 1443 pr_info("The file %s cannot be used, "
1484 "trying to use /proc/kallsyms...", self->long_name); 1444 "trying to use /proc/kallsyms...", self->long_name);
1485do_kallsyms: 1445do_kallsyms:
1486 err = dso__load_kallsyms(self, map, filter); 1446 err = dso__load_kallsyms(self, map, thread, filter);
1487 if (err > 0 && !is_kallsyms) 1447 if (err > 0 && !is_kallsyms)
1488 dso__set_long_name(self, strdup("[kernel.kallsyms]")); 1448 dso__set_long_name(self, strdup("[kernel.kallsyms]"));
1489 } 1449 }
@@ -1535,8 +1495,11 @@ static void __dsos__fprintf(struct list_head *head, FILE *fp)
1535{ 1495{
1536 struct dso *pos; 1496 struct dso *pos;
1537 1497
1538 list_for_each_entry(pos, head, node) 1498 list_for_each_entry(pos, head, node) {
1539 dso__fprintf(pos, fp); 1499 int i;
1500 for (i = 0; i < MAP__NR_TYPES; ++i)
1501 dso__fprintf(pos, i, fp);
1502 }
1540} 1503}
1541 1504
1542void dsos__fprintf(FILE *fp) 1505void dsos__fprintf(FILE *fp)
@@ -1563,10 +1526,10 @@ size_t dsos__fprintf_buildid(FILE *fp)
1563 __dsos__fprintf_buildid(&dsos__user, fp)); 1526 __dsos__fprintf_buildid(&dsos__user, fp));
1564} 1527}
1565 1528
1566static int kernel_maps__create_kernel_map(const struct symbol_conf *conf) 1529static int thread__create_kernel_map(struct thread *self, const char *vmlinux)
1567{ 1530{
1568 struct map *kmap; 1531 struct map *kmap;
1569 struct dso *kernel = dso__new(conf->vmlinux_name ?: "[kernel.kallsyms]"); 1532 struct dso *kernel = dso__new(vmlinux ?: "[kernel.kallsyms]");
1570 1533
1571 if (kernel == NULL) 1534 if (kernel == NULL)
1572 return -1; 1535 return -1;
@@ -1588,7 +1551,7 @@ static int kernel_maps__create_kernel_map(const struct symbol_conf *conf)
1588 sizeof(kernel->build_id)) == 0) 1551 sizeof(kernel->build_id)) == 0)
1589 kernel->has_build_id = true; 1552 kernel->has_build_id = true;
1590 1553
1591 kernel_maps__insert(kmap); 1554 __thread__insert_map(self, kmap);
1592 dsos__add(&dsos__kernel, kernel); 1555 dsos__add(&dsos__kernel, kernel);
1593 dsos__add(&dsos__user, vdso); 1556 dsos__add(&dsos__user, vdso);
1594 1557
@@ -1656,32 +1619,28 @@ out_fail:
1656 return -1; 1619 return -1;
1657} 1620}
1658 1621
1659static int kernel_maps__init(const struct symbol_conf *conf) 1622int symbol__init(struct symbol_conf *conf)
1660{ 1623{
1661 const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults; 1624 const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults;
1662 1625
1626 elf_version(EV_CURRENT);
1663 symbol__priv_size = pconf->priv_size; 1627 symbol__priv_size = pconf->priv_size;
1628 thread__init(kthread, 0);
1664 1629
1665 if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) 1630 if (pconf->try_vmlinux_path && vmlinux_path__init() < 0)
1666 return -1; 1631 return -1;
1667 1632
1668 if (kernel_maps__create_kernel_map(pconf) < 0) { 1633 if (thread__create_kernel_map(kthread, pconf->vmlinux_name) < 0) {
1669 vmlinux_path__exit(); 1634 vmlinux_path__exit();
1670 return -1; 1635 return -1;
1671 } 1636 }
1672 1637
1673 if (pconf->use_modules && kernel_maps__create_module_maps() < 0) 1638 if (pconf->use_modules && thread__create_module_maps(kthread) < 0)
1674 pr_debug("Failed to load list of modules in use, " 1639 pr_debug("Failed to load list of modules in use, "
1675 "continuing...\n"); 1640 "continuing...\n");
1676 /* 1641 /*
1677 * Now that we have all the maps created, just set the ->end of them: 1642 * Now that we have all the maps created, just set the ->end of them:
1678 */ 1643 */
1679 kernel_maps__fixup_end(); 1644 thread__fixup_maps_end(kthread);
1680 return 0; 1645 return 0;
1681} 1646}
1682
1683int symbol__init(struct symbol_conf *conf)
1684{
1685 elf_version(EV_CURRENT);
1686 return kernel_maps__init(conf);
1687}