diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
| -rw-r--r-- | tools/perf/util/symbol.c | 204 |
1 files changed, 163 insertions, 41 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index b39f499e575a..15ccfba8cdf8 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -22,6 +22,10 @@ | |||
| 22 | #include <limits.h> | 22 | #include <limits.h> |
| 23 | #include <sys/utsname.h> | 23 | #include <sys/utsname.h> |
| 24 | 24 | ||
| 25 | #ifndef KSYM_NAME_LEN | ||
| 26 | #define KSYM_NAME_LEN 128 | ||
| 27 | #endif | ||
| 28 | |||
| 25 | #ifndef NT_GNU_BUILD_ID | 29 | #ifndef NT_GNU_BUILD_ID |
| 26 | #define NT_GNU_BUILD_ID 3 | 30 | #define NT_GNU_BUILD_ID 3 |
| 27 | #endif | 31 | #endif |
| @@ -41,6 +45,7 @@ struct symbol_conf symbol_conf = { | |||
| 41 | .exclude_other = true, | 45 | .exclude_other = true, |
| 42 | .use_modules = true, | 46 | .use_modules = true, |
| 43 | .try_vmlinux_path = true, | 47 | .try_vmlinux_path = true, |
| 48 | .symfs = "", | ||
| 44 | }; | 49 | }; |
| 45 | 50 | ||
| 46 | int dso__name_len(const struct dso *self) | 51 | int dso__name_len(const struct dso *self) |
| @@ -92,7 +97,7 @@ static void symbols__fixup_end(struct rb_root *self) | |||
| 92 | prev = curr; | 97 | prev = curr; |
| 93 | curr = rb_entry(nd, struct symbol, rb_node); | 98 | curr = rb_entry(nd, struct symbol, rb_node); |
| 94 | 99 | ||
| 95 | if (prev->end == prev->start) | 100 | if (prev->end == prev->start && prev->end != curr->start) |
| 96 | prev->end = curr->start - 1; | 101 | prev->end = curr->start - 1; |
| 97 | } | 102 | } |
| 98 | 103 | ||
| @@ -121,7 +126,7 @@ static void __map_groups__fixup_end(struct map_groups *self, enum map_type type) | |||
| 121 | * We still haven't the actual symbols, so guess the | 126 | * We still haven't the actual symbols, so guess the |
| 122 | * last map final address. | 127 | * last map final address. |
| 123 | */ | 128 | */ |
| 124 | curr->end = ~0UL; | 129 | curr->end = ~0ULL; |
| 125 | } | 130 | } |
| 126 | 131 | ||
| 127 | static void map_groups__fixup_end(struct map_groups *self) | 132 | static void map_groups__fixup_end(struct map_groups *self) |
| @@ -295,7 +300,9 @@ static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym) | |||
| 295 | { | 300 | { |
| 296 | struct rb_node **p = &self->rb_node; | 301 | struct rb_node **p = &self->rb_node; |
| 297 | struct rb_node *parent = NULL; | 302 | struct rb_node *parent = NULL; |
| 298 | struct symbol_name_rb_node *symn = ((void *)sym) - sizeof(*parent), *s; | 303 | struct symbol_name_rb_node *symn, *s; |
| 304 | |||
| 305 | symn = container_of(sym, struct symbol_name_rb_node, sym); | ||
| 299 | 306 | ||
| 300 | while (*p != NULL) { | 307 | while (*p != NULL) { |
| 301 | parent = *p; | 308 | parent = *p; |
| @@ -423,16 +430,25 @@ size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp) | |||
| 423 | 430 | ||
| 424 | int kallsyms__parse(const char *filename, void *arg, | 431 | int kallsyms__parse(const char *filename, void *arg, |
| 425 | int (*process_symbol)(void *arg, const char *name, | 432 | int (*process_symbol)(void *arg, const char *name, |
| 426 | char type, u64 start)) | 433 | char type, u64 start, u64 end)) |
| 427 | { | 434 | { |
| 428 | char *line = NULL; | 435 | char *line = NULL; |
| 429 | size_t n; | 436 | size_t n; |
| 430 | int err = 0; | 437 | int err = -1; |
| 438 | u64 prev_start = 0; | ||
| 439 | char prev_symbol_type = 0; | ||
| 440 | char *prev_symbol_name; | ||
| 431 | FILE *file = fopen(filename, "r"); | 441 | FILE *file = fopen(filename, "r"); |
| 432 | 442 | ||
| 433 | if (file == NULL) | 443 | if (file == NULL) |
| 434 | goto out_failure; | 444 | goto out_failure; |
| 435 | 445 | ||
| 446 | prev_symbol_name = malloc(KSYM_NAME_LEN); | ||
| 447 | if (prev_symbol_name == NULL) | ||
| 448 | goto out_close; | ||
| 449 | |||
| 450 | err = 0; | ||
| 451 | |||
| 436 | while (!feof(file)) { | 452 | while (!feof(file)) { |
| 437 | u64 start; | 453 | u64 start; |
| 438 | int line_len, len; | 454 | int line_len, len; |
| @@ -452,14 +468,33 @@ int kallsyms__parse(const char *filename, void *arg, | |||
| 452 | continue; | 468 | continue; |
| 453 | 469 | ||
| 454 | symbol_type = toupper(line[len]); | 470 | symbol_type = toupper(line[len]); |
| 455 | symbol_name = line + len + 2; | 471 | len += 2; |
| 472 | symbol_name = line + len; | ||
| 473 | len = line_len - len; | ||
| 456 | 474 | ||
| 457 | err = process_symbol(arg, symbol_name, symbol_type, start); | 475 | if (len >= KSYM_NAME_LEN) { |
| 458 | if (err) | 476 | err = -1; |
| 459 | break; | 477 | break; |
| 478 | } | ||
| 479 | |||
| 480 | if (prev_symbol_type) { | ||
| 481 | u64 end = start; | ||
| 482 | if (end != prev_start) | ||
| 483 | --end; | ||
| 484 | err = process_symbol(arg, prev_symbol_name, | ||
| 485 | prev_symbol_type, prev_start, end); | ||
| 486 | if (err) | ||
| 487 | break; | ||
| 488 | } | ||
| 489 | |||
| 490 | memcpy(prev_symbol_name, symbol_name, len + 1); | ||
| 491 | prev_symbol_type = symbol_type; | ||
| 492 | prev_start = start; | ||
| 460 | } | 493 | } |
| 461 | 494 | ||
| 495 | free(prev_symbol_name); | ||
| 462 | free(line); | 496 | free(line); |
| 497 | out_close: | ||
| 463 | fclose(file); | 498 | fclose(file); |
| 464 | return err; | 499 | return err; |
| 465 | 500 | ||
| @@ -481,7 +516,7 @@ static u8 kallsyms2elf_type(char type) | |||
| 481 | } | 516 | } |
| 482 | 517 | ||
| 483 | static int map__process_kallsym_symbol(void *arg, const char *name, | 518 | static int map__process_kallsym_symbol(void *arg, const char *name, |
| 484 | char type, u64 start) | 519 | char type, u64 start, u64 end) |
| 485 | { | 520 | { |
| 486 | struct symbol *sym; | 521 | struct symbol *sym; |
| 487 | struct process_kallsyms_args *a = arg; | 522 | struct process_kallsyms_args *a = arg; |
| @@ -490,11 +525,8 @@ static int map__process_kallsym_symbol(void *arg, const char *name, | |||
| 490 | if (!symbol_type__is_a(type, a->map->type)) | 525 | if (!symbol_type__is_a(type, a->map->type)) |
| 491 | return 0; | 526 | return 0; |
| 492 | 527 | ||
| 493 | /* | 528 | sym = symbol__new(start, end - start + 1, |
| 494 | * Will fix up the end later, when we have all symbols sorted. | 529 | kallsyms2elf_type(type), name); |
| 495 | */ | ||
| 496 | sym = symbol__new(start, 0, kallsyms2elf_type(type), name); | ||
| 497 | |||
| 498 | if (sym == NULL) | 530 | if (sym == NULL) |
| 499 | return -ENOMEM; | 531 | return -ENOMEM; |
| 500 | /* | 532 | /* |
| @@ -530,7 +562,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
| 530 | struct machine *machine = kmaps->machine; | 562 | struct machine *machine = kmaps->machine; |
| 531 | struct map *curr_map = map; | 563 | struct map *curr_map = map; |
| 532 | struct symbol *pos; | 564 | struct symbol *pos; |
| 533 | int count = 0; | 565 | int count = 0, moved = 0; |
| 534 | struct rb_root *root = &self->symbols[map->type]; | 566 | struct rb_root *root = &self->symbols[map->type]; |
| 535 | struct rb_node *next = rb_first(root); | 567 | struct rb_node *next = rb_first(root); |
| 536 | int kernel_range = 0; | 568 | int kernel_range = 0; |
| @@ -588,6 +620,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
| 588 | char dso_name[PATH_MAX]; | 620 | char dso_name[PATH_MAX]; |
| 589 | struct dso *dso; | 621 | struct dso *dso; |
| 590 | 622 | ||
| 623 | if (count == 0) { | ||
| 624 | curr_map = map; | ||
| 625 | goto filter_symbol; | ||
| 626 | } | ||
| 627 | |||
| 591 | if (self->kernel == DSO_TYPE_GUEST_KERNEL) | 628 | if (self->kernel == DSO_TYPE_GUEST_KERNEL) |
| 592 | snprintf(dso_name, sizeof(dso_name), | 629 | snprintf(dso_name, sizeof(dso_name), |
| 593 | "[guest.kernel].%d", | 630 | "[guest.kernel].%d", |
| @@ -613,7 +650,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
| 613 | map_groups__insert(kmaps, curr_map); | 650 | map_groups__insert(kmaps, curr_map); |
| 614 | ++kernel_range; | 651 | ++kernel_range; |
| 615 | } | 652 | } |
| 616 | 653 | filter_symbol: | |
| 617 | if (filter && filter(curr_map, pos)) { | 654 | if (filter && filter(curr_map, pos)) { |
| 618 | discard_symbol: rb_erase(&pos->rb_node, root); | 655 | discard_symbol: rb_erase(&pos->rb_node, root); |
| 619 | symbol__delete(pos); | 656 | symbol__delete(pos); |
| @@ -621,8 +658,9 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
| 621 | if (curr_map != map) { | 658 | if (curr_map != map) { |
| 622 | rb_erase(&pos->rb_node, root); | 659 | rb_erase(&pos->rb_node, root); |
| 623 | symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); | 660 | symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); |
| 624 | } | 661 | ++moved; |
| 625 | count++; | 662 | } else |
| 663 | ++count; | ||
| 626 | } | 664 | } |
| 627 | } | 665 | } |
| 628 | 666 | ||
| @@ -632,7 +670,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
| 632 | dso__set_loaded(curr_map->dso, curr_map->type); | 670 | dso__set_loaded(curr_map->dso, curr_map->type); |
| 633 | } | 671 | } |
| 634 | 672 | ||
| 635 | return count; | 673 | return count + moved; |
| 636 | } | 674 | } |
| 637 | 675 | ||
| 638 | int dso__load_kallsyms(struct dso *self, const char *filename, | 676 | int dso__load_kallsyms(struct dso *self, const char *filename, |
| @@ -641,7 +679,6 @@ int dso__load_kallsyms(struct dso *self, const char *filename, | |||
| 641 | if (dso__load_all_kallsyms(self, filename, map) < 0) | 679 | if (dso__load_all_kallsyms(self, filename, map) < 0) |
| 642 | return -1; | 680 | return -1; |
| 643 | 681 | ||
| 644 | symbols__fixup_end(&self->symbols[map->type]); | ||
| 645 | if (self->kernel == DSO_TYPE_GUEST_KERNEL) | 682 | if (self->kernel == DSO_TYPE_GUEST_KERNEL) |
| 646 | self->origin = DSO__ORIG_GUEST_KERNEL; | 683 | self->origin = DSO__ORIG_GUEST_KERNEL; |
| 647 | else | 684 | else |
| @@ -831,8 +868,11 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map, | |||
| 831 | char sympltname[1024]; | 868 | char sympltname[1024]; |
| 832 | Elf *elf; | 869 | Elf *elf; |
| 833 | int nr = 0, symidx, fd, err = 0; | 870 | int nr = 0, symidx, fd, err = 0; |
| 871 | char name[PATH_MAX]; | ||
| 834 | 872 | ||
| 835 | fd = open(self->long_name, O_RDONLY); | 873 | snprintf(name, sizeof(name), "%s%s", |
| 874 | symbol_conf.symfs, self->long_name); | ||
| 875 | fd = open(name, O_RDONLY); | ||
| 836 | if (fd < 0) | 876 | if (fd < 0) |
| 837 | goto out; | 877 | goto out; |
| 838 | 878 | ||
| @@ -1444,16 +1484,19 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
| 1444 | self->origin++) { | 1484 | self->origin++) { |
| 1445 | switch (self->origin) { | 1485 | switch (self->origin) { |
| 1446 | case DSO__ORIG_BUILD_ID_CACHE: | 1486 | case DSO__ORIG_BUILD_ID_CACHE: |
| 1447 | if (dso__build_id_filename(self, name, size) == NULL) | 1487 | /* skip the locally configured cache if a symfs is given */ |
| 1488 | if (symbol_conf.symfs[0] || | ||
| 1489 | (dso__build_id_filename(self, name, size) == NULL)) { | ||
| 1448 | continue; | 1490 | continue; |
| 1491 | } | ||
| 1449 | break; | 1492 | break; |
| 1450 | case DSO__ORIG_FEDORA: | 1493 | case DSO__ORIG_FEDORA: |
| 1451 | snprintf(name, size, "/usr/lib/debug%s.debug", | 1494 | snprintf(name, size, "%s/usr/lib/debug%s.debug", |
| 1452 | self->long_name); | 1495 | symbol_conf.symfs, self->long_name); |
| 1453 | break; | 1496 | break; |
| 1454 | case DSO__ORIG_UBUNTU: | 1497 | case DSO__ORIG_UBUNTU: |
| 1455 | snprintf(name, size, "/usr/lib/debug%s", | 1498 | snprintf(name, size, "%s/usr/lib/debug%s", |
| 1456 | self->long_name); | 1499 | symbol_conf.symfs, self->long_name); |
| 1457 | break; | 1500 | break; |
| 1458 | case DSO__ORIG_BUILDID: { | 1501 | case DSO__ORIG_BUILDID: { |
| 1459 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 1502 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
| @@ -1465,19 +1508,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
| 1465 | sizeof(self->build_id), | 1508 | sizeof(self->build_id), |
| 1466 | build_id_hex); | 1509 | build_id_hex); |
| 1467 | snprintf(name, size, | 1510 | snprintf(name, size, |
| 1468 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | 1511 | "%s/usr/lib/debug/.build-id/%.2s/%s.debug", |
| 1469 | build_id_hex, build_id_hex + 2); | 1512 | symbol_conf.symfs, build_id_hex, build_id_hex + 2); |
| 1470 | } | 1513 | } |
| 1471 | break; | 1514 | break; |
| 1472 | case DSO__ORIG_DSO: | 1515 | case DSO__ORIG_DSO: |
| 1473 | snprintf(name, size, "%s", self->long_name); | 1516 | snprintf(name, size, "%s%s", |
| 1517 | symbol_conf.symfs, self->long_name); | ||
| 1474 | break; | 1518 | break; |
| 1475 | case DSO__ORIG_GUEST_KMODULE: | 1519 | case DSO__ORIG_GUEST_KMODULE: |
| 1476 | if (map->groups && map->groups->machine) | 1520 | if (map->groups && map->groups->machine) |
| 1477 | root_dir = map->groups->machine->root_dir; | 1521 | root_dir = map->groups->machine->root_dir; |
| 1478 | else | 1522 | else |
| 1479 | root_dir = ""; | 1523 | root_dir = ""; |
| 1480 | snprintf(name, size, "%s%s", root_dir, self->long_name); | 1524 | snprintf(name, size, "%s%s%s", symbol_conf.symfs, |
| 1525 | root_dir, self->long_name); | ||
| 1526 | break; | ||
| 1527 | |||
| 1528 | case DSO__ORIG_KMODULE: | ||
| 1529 | snprintf(name, size, "%s%s", symbol_conf.symfs, | ||
| 1530 | self->long_name); | ||
| 1481 | break; | 1531 | break; |
| 1482 | 1532 | ||
| 1483 | default: | 1533 | default: |
| @@ -1772,21 +1822,24 @@ out_failure: | |||
| 1772 | return -1; | 1822 | return -1; |
| 1773 | } | 1823 | } |
| 1774 | 1824 | ||
| 1775 | static int dso__load_vmlinux(struct dso *self, struct map *map, | 1825 | int dso__load_vmlinux(struct dso *self, struct map *map, |
| 1776 | const char *vmlinux, symbol_filter_t filter) | 1826 | const char *vmlinux, symbol_filter_t filter) |
| 1777 | { | 1827 | { |
| 1778 | int err = -1, fd; | 1828 | int err = -1, fd; |
| 1829 | char symfs_vmlinux[PATH_MAX]; | ||
| 1779 | 1830 | ||
| 1780 | fd = open(vmlinux, O_RDONLY); | 1831 | snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s", |
| 1832 | symbol_conf.symfs, vmlinux); | ||
| 1833 | fd = open(symfs_vmlinux, O_RDONLY); | ||
| 1781 | if (fd < 0) | 1834 | if (fd < 0) |
| 1782 | return -1; | 1835 | return -1; |
| 1783 | 1836 | ||
| 1784 | dso__set_loaded(self, map->type); | 1837 | dso__set_loaded(self, map->type); |
| 1785 | err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0); | 1838 | err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); |
| 1786 | close(fd); | 1839 | close(fd); |
| 1787 | 1840 | ||
| 1788 | if (err > 0) | 1841 | if (err > 0) |
| 1789 | pr_debug("Using %s for symbols\n", vmlinux); | 1842 | pr_debug("Using %s for symbols\n", symfs_vmlinux); |
| 1790 | 1843 | ||
| 1791 | return err; | 1844 | return err; |
| 1792 | } | 1845 | } |
| @@ -1828,8 +1881,8 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
| 1828 | const char *kallsyms_filename = NULL; | 1881 | const char *kallsyms_filename = NULL; |
| 1829 | char *kallsyms_allocated_filename = NULL; | 1882 | char *kallsyms_allocated_filename = NULL; |
| 1830 | /* | 1883 | /* |
| 1831 | * Step 1: if the user specified a vmlinux filename, use it and only | 1884 | * Step 1: if the user specified a kallsyms or vmlinux filename, use |
| 1832 | * it, reporting errors to the user if it cannot be used. | 1885 | * it and only it, reporting errors to the user if it cannot be used. |
| 1833 | * | 1886 | * |
| 1834 | * For instance, try to analyse an ARM perf.data file _without_ a | 1887 | * For instance, try to analyse an ARM perf.data file _without_ a |
| 1835 | * build-id, or if the user specifies the wrong path to the right | 1888 | * build-id, or if the user specifies the wrong path to the right |
| @@ -1842,6 +1895,11 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
| 1842 | * validation in dso__load_vmlinux and will bail out if they don't | 1895 | * validation in dso__load_vmlinux and will bail out if they don't |
| 1843 | * match. | 1896 | * match. |
| 1844 | */ | 1897 | */ |
| 1898 | if (symbol_conf.kallsyms_name != NULL) { | ||
| 1899 | kallsyms_filename = symbol_conf.kallsyms_name; | ||
| 1900 | goto do_kallsyms; | ||
| 1901 | } | ||
| 1902 | |||
| 1845 | if (symbol_conf.vmlinux_name != NULL) { | 1903 | if (symbol_conf.vmlinux_name != NULL) { |
| 1846 | err = dso__load_vmlinux(self, map, | 1904 | err = dso__load_vmlinux(self, map, |
| 1847 | symbol_conf.vmlinux_name, filter); | 1905 | symbol_conf.vmlinux_name, filter); |
| @@ -1859,6 +1917,10 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
| 1859 | goto out_fixup; | 1917 | goto out_fixup; |
| 1860 | } | 1918 | } |
| 1861 | 1919 | ||
| 1920 | /* do not try local files if a symfs was given */ | ||
| 1921 | if (symbol_conf.symfs[0] != 0) | ||
| 1922 | return -1; | ||
| 1923 | |||
| 1862 | /* | 1924 | /* |
| 1863 | * Say the kernel DSO was created when processing the build-id header table, | 1925 | * Say the kernel DSO was created when processing the build-id header table, |
| 1864 | * we have a build-id, so check if it is the same as the running kernel, | 1926 | * we have a build-id, so check if it is the same as the running kernel, |
| @@ -2123,14 +2185,55 @@ static struct dso *machine__create_kernel(struct machine *self) | |||
| 2123 | return kernel; | 2185 | return kernel; |
| 2124 | } | 2186 | } |
| 2125 | 2187 | ||
| 2188 | struct process_args { | ||
| 2189 | u64 start; | ||
| 2190 | }; | ||
| 2191 | |||
| 2192 | static int symbol__in_kernel(void *arg, const char *name, | ||
| 2193 | char type __used, u64 start, u64 end __used) | ||
| 2194 | { | ||
| 2195 | struct process_args *args = arg; | ||
| 2196 | |||
| 2197 | if (strchr(name, '[')) | ||
| 2198 | return 0; | ||
| 2199 | |||
| 2200 | args->start = start; | ||
| 2201 | return 1; | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | /* Figure out the start address of kernel map from /proc/kallsyms */ | ||
| 2205 | static u64 machine__get_kernel_start_addr(struct machine *machine) | ||
| 2206 | { | ||
| 2207 | const char *filename; | ||
| 2208 | char path[PATH_MAX]; | ||
| 2209 | struct process_args args; | ||
| 2210 | |||
| 2211 | if (machine__is_host(machine)) { | ||
| 2212 | filename = "/proc/kallsyms"; | ||
| 2213 | } else { | ||
| 2214 | if (machine__is_default_guest(machine)) | ||
| 2215 | filename = (char *)symbol_conf.default_guest_kallsyms; | ||
| 2216 | else { | ||
| 2217 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); | ||
| 2218 | filename = path; | ||
| 2219 | } | ||
| 2220 | } | ||
| 2221 | |||
| 2222 | if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) | ||
| 2223 | return 0; | ||
| 2224 | |||
| 2225 | return args.start; | ||
| 2226 | } | ||
| 2227 | |||
| 2126 | int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) | 2228 | int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) |
| 2127 | { | 2229 | { |
| 2128 | enum map_type type; | 2230 | enum map_type type; |
| 2231 | u64 start = machine__get_kernel_start_addr(self); | ||
| 2129 | 2232 | ||
| 2130 | for (type = 0; type < MAP__NR_TYPES; ++type) { | 2233 | for (type = 0; type < MAP__NR_TYPES; ++type) { |
| 2131 | struct kmap *kmap; | 2234 | struct kmap *kmap; |
| 2132 | 2235 | ||
| 2133 | self->vmlinux_maps[type] = map__new2(0, kernel, type); | 2236 | self->vmlinux_maps[type] = map__new2(start, kernel, type); |
| 2134 | if (self->vmlinux_maps[type] == NULL) | 2237 | if (self->vmlinux_maps[type] == NULL) |
| 2135 | return -1; | 2238 | return -1; |
| 2136 | 2239 | ||
| @@ -2208,9 +2311,6 @@ static int vmlinux_path__init(void) | |||
| 2208 | struct utsname uts; | 2311 | struct utsname uts; |
| 2209 | char bf[PATH_MAX]; | 2312 | char bf[PATH_MAX]; |
| 2210 | 2313 | ||
| 2211 | if (uname(&uts) < 0) | ||
| 2212 | return -1; | ||
| 2213 | |||
| 2214 | vmlinux_path = malloc(sizeof(char *) * 5); | 2314 | vmlinux_path = malloc(sizeof(char *) * 5); |
| 2215 | if (vmlinux_path == NULL) | 2315 | if (vmlinux_path == NULL) |
| 2216 | return -1; | 2316 | return -1; |
| @@ -2223,6 +2323,14 @@ static int vmlinux_path__init(void) | |||
| 2223 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | 2323 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) |
| 2224 | goto out_fail; | 2324 | goto out_fail; |
| 2225 | ++vmlinux_path__nr_entries; | 2325 | ++vmlinux_path__nr_entries; |
| 2326 | |||
| 2327 | /* only try running kernel version if no symfs was given */ | ||
| 2328 | if (symbol_conf.symfs[0] != 0) | ||
| 2329 | return 0; | ||
| 2330 | |||
| 2331 | if (uname(&uts) < 0) | ||
| 2332 | return -1; | ||
| 2333 | |||
| 2226 | snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); | 2334 | snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); |
| 2227 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | 2335 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); |
| 2228 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | 2336 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) |
| @@ -2282,6 +2390,8 @@ static int setup_list(struct strlist **list, const char *list_str, | |||
| 2282 | 2390 | ||
| 2283 | int symbol__init(void) | 2391 | int symbol__init(void) |
| 2284 | { | 2392 | { |
| 2393 | const char *symfs; | ||
| 2394 | |||
| 2285 | if (symbol_conf.initialized) | 2395 | if (symbol_conf.initialized) |
| 2286 | return 0; | 2396 | return 0; |
| 2287 | 2397 | ||
| @@ -2310,6 +2420,18 @@ int symbol__init(void) | |||
| 2310 | symbol_conf.sym_list_str, "symbol") < 0) | 2420 | symbol_conf.sym_list_str, "symbol") < 0) |
| 2311 | goto out_free_comm_list; | 2421 | goto out_free_comm_list; |
| 2312 | 2422 | ||
| 2423 | /* | ||
| 2424 | * A path to symbols of "/" is identical to "" | ||
| 2425 | * reset here for simplicity. | ||
| 2426 | */ | ||
| 2427 | symfs = realpath(symbol_conf.symfs, NULL); | ||
| 2428 | if (symfs == NULL) | ||
| 2429 | symfs = symbol_conf.symfs; | ||
| 2430 | if (strcmp(symfs, "/") == 0) | ||
| 2431 | symbol_conf.symfs = ""; | ||
| 2432 | if (symfs != symbol_conf.symfs) | ||
| 2433 | free((void *)symfs); | ||
| 2434 | |||
| 2313 | symbol_conf.initialized = true; | 2435 | symbol_conf.initialized = true; |
| 2314 | return 0; | 2436 | return 0; |
| 2315 | 2437 | ||
