aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2013-10-14 06:43:43 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-10-14 09:29:25 -0400
commit0544d4225c52ca31ab2a55b22ddce1392d8f45a4 (patch)
tree6f09d3816bcdf31624d451c00e602a11afaba445
parent9a17d7268d71674f0bbff6821f7d8e6dc0ece19a (diff)
perf symbols: Add ability to find kcore in build-id cache
When no vmlinux is found, tools will use kallsyms and, if possible, kcore. Add the ability to find kcore in the build-id cache. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1381747424-3557-7-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/symbol.c147
1 files changed, 103 insertions, 44 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b2f60ddc864f..76a9e933a7a5 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1401,6 +1401,105 @@ out:
1401 return err; 1401 return err;
1402} 1402}
1403 1403
1404static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1405{
1406 char kallsyms_filename[PATH_MAX];
1407 struct dirent *dent;
1408 int ret = -1;
1409 DIR *d;
1410
1411 d = opendir(dir);
1412 if (!d)
1413 return -1;
1414
1415 while (1) {
1416 dent = readdir(d);
1417 if (!dent)
1418 break;
1419 if (dent->d_type != DT_DIR)
1420 continue;
1421 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1422 "%s/%s/kallsyms", dir, dent->d_name);
1423 if (!validate_kcore_modules(kallsyms_filename, map)) {
1424 strlcpy(dir, kallsyms_filename, dir_sz);
1425 ret = 0;
1426 break;
1427 }
1428 }
1429
1430 closedir(d);
1431
1432 return ret;
1433}
1434
1435static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1436{
1437 u8 host_build_id[BUILD_ID_SIZE];
1438 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1439 bool is_host = false;
1440 char path[PATH_MAX];
1441
1442 if (!dso->has_build_id) {
1443 /*
1444 * Last resort, if we don't have a build-id and couldn't find
1445 * any vmlinux file, try the running kernel kallsyms table.
1446 */
1447 goto proc_kallsyms;
1448 }
1449
1450 if (sysfs__read_build_id("/sys/kernel/notes", host_build_id,
1451 sizeof(host_build_id)) == 0)
1452 is_host = dso__build_id_equal(dso, host_build_id);
1453
1454 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1455
1456 /* Use /proc/kallsyms if possible */
1457 if (is_host) {
1458 DIR *d;
1459 int fd;
1460
1461 /* If no cached kcore go with /proc/kallsyms */
1462 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
1463 buildid_dir, sbuild_id);
1464 d = opendir(path);
1465 if (!d)
1466 goto proc_kallsyms;
1467 closedir(d);
1468
1469 /*
1470 * Do not check the build-id cache, until we know we cannot use
1471 * /proc/kcore.
1472 */
1473 fd = open("/proc/kcore", O_RDONLY);
1474 if (fd != -1) {
1475 close(fd);
1476 /* If module maps match go with /proc/kallsyms */
1477 if (!validate_kcore_modules("/proc/kallsyms", map))
1478 goto proc_kallsyms;
1479 }
1480
1481 /* Find kallsyms in build-id cache with kcore */
1482 if (!find_matching_kcore(map, path, sizeof(path)))
1483 return strdup(path);
1484
1485 goto proc_kallsyms;
1486 }
1487
1488 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
1489 buildid_dir, sbuild_id);
1490
1491 if (access(path, F_OK)) {
1492 pr_err("No kallsyms or vmlinux with build-id %s was found\n",
1493 sbuild_id);
1494 return NULL;
1495 }
1496
1497 return strdup(path);
1498
1499proc_kallsyms:
1500 return strdup("/proc/kallsyms");
1501}
1502
1404static int dso__load_kernel_sym(struct dso *dso, struct map *map, 1503static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1405 symbol_filter_t filter) 1504 symbol_filter_t filter)
1406{ 1505{
@@ -1449,51 +1548,11 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1449 if (symbol_conf.symfs[0] != 0) 1548 if (symbol_conf.symfs[0] != 0)
1450 return -1; 1549 return -1;
1451 1550
1452 /* 1551 kallsyms_allocated_filename = dso__find_kallsyms(dso, map);
1453 * Say the kernel DSO was created when processing the build-id header table, 1552 if (!kallsyms_allocated_filename)
1454 * we have a build-id, so check if it is the same as the running kernel, 1553 return -1;
1455 * using it if it is.
1456 */
1457 if (dso->has_build_id) {
1458 u8 kallsyms_build_id[BUILD_ID_SIZE];
1459 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1460
1461 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
1462 sizeof(kallsyms_build_id)) == 0) {
1463 if (dso__build_id_equal(dso, kallsyms_build_id)) {
1464 kallsyms_filename = "/proc/kallsyms";
1465 goto do_kallsyms;
1466 }
1467 }
1468 /*
1469 * Now look if we have it on the build-id cache in
1470 * $HOME/.debug/[kernel.kallsyms].
1471 */
1472 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1473 sbuild_id);
1474
1475 if (asprintf(&kallsyms_allocated_filename,
1476 "%s/.debug/[kernel.kallsyms]/%s",
1477 getenv("HOME"), sbuild_id) == -1) {
1478 pr_err("Not enough memory for kallsyms file lookup\n");
1479 return -1;
1480 }
1481
1482 kallsyms_filename = kallsyms_allocated_filename;
1483 1554
1484 if (access(kallsyms_filename, F_OK)) { 1555 kallsyms_filename = kallsyms_allocated_filename;
1485 pr_err("No kallsyms or vmlinux with build-id %s "
1486 "was found\n", sbuild_id);
1487 free(kallsyms_allocated_filename);
1488 return -1;
1489 }
1490 } else {
1491 /*
1492 * Last resort, if we don't have a build-id and couldn't find
1493 * any vmlinux file, try the running kernel kallsyms table.
1494 */
1495 kallsyms_filename = "/proc/kallsyms";
1496 }
1497 1556
1498do_kallsyms: 1557do_kallsyms:
1499 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1558 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);