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.c116
1 files changed, 84 insertions, 32 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8e6627e6b778..381999dd5c1f 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -161,7 +161,7 @@ static size_t symbol__fprintf(struct symbol *self, FILE *fp)
161 self->start, self->end, self->name); 161 self->start, self->end, self->name);
162} 162}
163 163
164static void dso__set_long_name(struct dso *self, char *name) 164void dso__set_long_name(struct dso *self, char *name)
165{ 165{
166 if (name == NULL) 166 if (name == NULL)
167 return; 167 return;
@@ -176,7 +176,7 @@ static void dso__set_basename(struct dso *self)
176 176
177struct dso *dso__new(const char *name) 177struct dso *dso__new(const char *name)
178{ 178{
179 struct dso *self = malloc(sizeof(*self) + strlen(name) + 1); 179 struct dso *self = zalloc(sizeof(*self) + strlen(name) + 1);
180 180
181 if (self != NULL) { 181 if (self != NULL) {
182 int i; 182 int i;
@@ -500,13 +500,17 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
500 500
501 *module++ = '\0'; 501 *module++ = '\0';
502 502
503 if (strcmp(self->name, module)) { 503 if (strcmp(curr_map->dso->short_name, module)) {
504 curr_map = map_groups__find_by_name(&session->kmaps, map->type, module); 504 curr_map = map_groups__find_by_name(&session->kmaps, map->type, module);
505 if (curr_map == NULL) { 505 if (curr_map == NULL) {
506 pr_debug("/proc/{kallsyms,modules} " 506 pr_debug("/proc/{kallsyms,modules} "
507 "inconsistency!\n"); 507 "inconsistency while looking "
508 "for \"%s\" module!\n", module);
508 return -1; 509 return -1;
509 } 510 }
511
512 if (curr_map->dso->loaded)
513 goto discard_symbol;
510 } 514 }
511 /* 515 /*
512 * So that we look just like we get from .ko files, 516 * So that we look just like we get from .ko files,
@@ -1343,13 +1347,33 @@ struct map *map_groups__find_by_name(struct map_groups *self,
1343 for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { 1347 for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
1344 struct map *map = rb_entry(nd, struct map, rb_node); 1348 struct map *map = rb_entry(nd, struct map, rb_node);
1345 1349
1346 if (map->dso && strcmp(map->dso->name, name) == 0) 1350 if (map->dso && strcmp(map->dso->short_name, name) == 0)
1347 return map; 1351 return map;
1348 } 1352 }
1349 1353
1350 return NULL; 1354 return NULL;
1351} 1355}
1352 1356
1357static int dso__kernel_module_get_build_id(struct dso *self)
1358{
1359 char filename[PATH_MAX];
1360 /*
1361 * kernel module short names are of the form "[module]" and
1362 * we need just "module" here.
1363 */
1364 const char *name = self->short_name + 1;
1365
1366 snprintf(filename, sizeof(filename),
1367 "/sys/module/%.*s/notes/.note.gnu.build-id",
1368 (int)strlen(name - 1), name);
1369
1370 if (sysfs__read_build_id(filename, self->build_id,
1371 sizeof(self->build_id)) == 0)
1372 self->has_build_id = true;
1373
1374 return 0;
1375}
1376
1353static int perf_session__set_modules_path_dir(struct perf_session *self, char *dirname) 1377static int perf_session__set_modules_path_dir(struct perf_session *self, char *dirname)
1354{ 1378{
1355 struct dirent *dent; 1379 struct dirent *dent;
@@ -1395,6 +1419,7 @@ static int perf_session__set_modules_path_dir(struct perf_session *self, char *d
1395 if (long_name == NULL) 1419 if (long_name == NULL)
1396 goto failure; 1420 goto failure;
1397 dso__set_long_name(map->dso, long_name); 1421 dso__set_long_name(map->dso, long_name);
1422 dso__kernel_module_get_build_id(map->dso);
1398 } 1423 }
1399 } 1424 }
1400 1425
@@ -1437,6 +1462,24 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1437 return self; 1462 return self;
1438} 1463}
1439 1464
1465struct map *perf_session__new_module_map(struct perf_session *self, u64 start,
1466 const char *filename)
1467{
1468 struct map *map;
1469 struct dso *dso = __dsos__findnew(&dsos__kernel, filename);
1470
1471 if (dso == NULL)
1472 return NULL;
1473
1474 map = map__new2(start, dso, MAP__FUNCTION);
1475 if (map == NULL)
1476 return NULL;
1477
1478 dso->origin = DSO__ORIG_KMODULE;
1479 map_groups__insert(&self->kmaps, map);
1480 return map;
1481}
1482
1440static int perf_session__create_module_maps(struct perf_session *self) 1483static int perf_session__create_module_maps(struct perf_session *self)
1441{ 1484{
1442 char *line = NULL; 1485 char *line = NULL;
@@ -1450,7 +1493,6 @@ static int perf_session__create_module_maps(struct perf_session *self)
1450 while (!feof(file)) { 1493 while (!feof(file)) {
1451 char name[PATH_MAX]; 1494 char name[PATH_MAX];
1452 u64 start; 1495 u64 start;
1453 struct dso *dso;
1454 char *sep; 1496 char *sep;
1455 int line_len; 1497 int line_len;
1456 1498
@@ -1476,26 +1518,10 @@ static int perf_session__create_module_maps(struct perf_session *self)
1476 *sep = '\0'; 1518 *sep = '\0';
1477 1519
1478 snprintf(name, sizeof(name), "[%s]", line); 1520 snprintf(name, sizeof(name), "[%s]", line);
1479 dso = dso__new(name); 1521 map = perf_session__new_module_map(self, start, name);
1480 1522 if (map == NULL)
1481 if (dso == NULL)
1482 goto out_delete_line;
1483
1484 map = map__new2(start, dso, MAP__FUNCTION);
1485 if (map == NULL) {
1486 dso__delete(dso);
1487 goto out_delete_line; 1523 goto out_delete_line;
1488 } 1524 dso__kernel_module_get_build_id(map->dso);
1489
1490 snprintf(name, sizeof(name),
1491 "/sys/module/%s/notes/.note.gnu.build-id", line);
1492 if (sysfs__read_build_id(name, dso->build_id,
1493 sizeof(dso->build_id)) == 0)
1494 dso->has_build_id = true;
1495
1496 dso->origin = DSO__ORIG_KMODULE;
1497 map_groups__insert(&self->kmaps, map);
1498 dsos__add(&dsos__kernel, dso);
1499 } 1525 }
1500 1526
1501 free(line); 1527 free(line);
@@ -1573,10 +1599,28 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1573 } 1599 }
1574 } 1600 }
1575 1601
1602 /*
1603 * Say the kernel DSO was created when processing the build-id header table,
1604 * we have a build-id, so check if it is the same as the running kernel,
1605 * using it if it is.
1606 */
1607 if (self->has_build_id) {
1608 u8 kallsyms_build_id[BUILD_ID_SIZE];
1609
1610 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
1611 sizeof(kallsyms_build_id)) == 0)
1612
1613 is_kallsyms = dso__build_id_equal(self, kallsyms_build_id);
1614 if (is_kallsyms)
1615 goto do_kallsyms;
1616 goto do_vmlinux;
1617 }
1618
1576 is_kallsyms = self->long_name[0] == '['; 1619 is_kallsyms = self->long_name[0] == '[';
1577 if (is_kallsyms) 1620 if (is_kallsyms)
1578 goto do_kallsyms; 1621 goto do_kallsyms;
1579 1622
1623do_vmlinux:
1580 err = dso__load_vmlinux(self, map, session, self->long_name, filter); 1624 err = dso__load_vmlinux(self, map, session, self->long_name, filter);
1581 if (err <= 0) { 1625 if (err <= 0) {
1582 pr_info("The file %s cannot be used, " 1626 pr_info("The file %s cannot be used, "
@@ -1694,16 +1738,12 @@ out_delete_kernel_dso:
1694 return NULL; 1738 return NULL;
1695} 1739}
1696 1740
1697static int map_groups__create_kernel_maps(struct map_groups *self, 1741int __map_groups__create_kernel_maps(struct map_groups *self,
1698 struct map *vmlinux_maps[MAP__NR_TYPES], 1742 struct map *vmlinux_maps[MAP__NR_TYPES],
1699 const char *vmlinux) 1743 struct dso *kernel)
1700{ 1744{
1701 struct dso *kernel = dsos__create_kernel(vmlinux);
1702 enum map_type type; 1745 enum map_type type;
1703 1746
1704 if (kernel == NULL)
1705 return -1;
1706
1707 for (type = 0; type < MAP__NR_TYPES; ++type) { 1747 for (type = 0; type < MAP__NR_TYPES; ++type) {
1708 vmlinux_maps[type] = map__new2(0, kernel, type); 1748 vmlinux_maps[type] = map__new2(0, kernel, type);
1709 if (vmlinux_maps[type] == NULL) 1749 if (vmlinux_maps[type] == NULL)
@@ -1717,6 +1757,18 @@ static int map_groups__create_kernel_maps(struct map_groups *self,
1717 return 0; 1757 return 0;
1718} 1758}
1719 1759
1760static int map_groups__create_kernel_maps(struct map_groups *self,
1761 struct map *vmlinux_maps[MAP__NR_TYPES],
1762 const char *vmlinux)
1763{
1764 struct dso *kernel = dsos__create_kernel(vmlinux);
1765
1766 if (kernel == NULL)
1767 return -1;
1768
1769 return __map_groups__create_kernel_maps(self, vmlinux_maps, kernel);
1770}
1771
1720static void vmlinux_path__exit(void) 1772static void vmlinux_path__exit(void)
1721{ 1773{
1722 while (--vmlinux_path__nr_entries >= 0) { 1774 while (--vmlinux_path__nr_entries >= 0) {