| .. | .. |
|---|
| 2 | 2 | #include <fcntl.h> |
|---|
| 3 | 3 | #include <stdio.h> |
|---|
| 4 | 4 | #include <errno.h> |
|---|
| 5 | +#include <stdlib.h> |
|---|
| 5 | 6 | #include <string.h> |
|---|
| 6 | 7 | #include <unistd.h> |
|---|
| 7 | 8 | #include <inttypes.h> |
|---|
| 8 | 9 | |
|---|
| 10 | +#include "dso.h" |
|---|
| 11 | +#include "map.h" |
|---|
| 12 | +#include "maps.h" |
|---|
| 9 | 13 | #include "symbol.h" |
|---|
| 14 | +#include "symsrc.h" |
|---|
| 10 | 15 | #include "demangle-java.h" |
|---|
| 11 | 16 | #include "demangle-rust.h" |
|---|
| 12 | 17 | #include "machine.h" |
|---|
| 13 | 18 | #include "vdso.h" |
|---|
| 14 | 19 | #include "debug.h" |
|---|
| 15 | | -#include "sane_ctype.h" |
|---|
| 20 | +#include "util/copyfile.h" |
|---|
| 21 | +#include <linux/ctype.h> |
|---|
| 22 | +#include <linux/kernel.h> |
|---|
| 23 | +#include <linux/zalloc.h> |
|---|
| 16 | 24 | #include <symbol/kallsyms.h> |
|---|
| 25 | +#include <internal/lib.h> |
|---|
| 17 | 26 | |
|---|
| 18 | 27 | #ifndef EM_AARCH64 |
|---|
| 19 | 28 | #define EM_AARCH64 183 /* ARM 64 bit */ |
|---|
| 20 | 29 | #endif |
|---|
| 21 | 30 | |
|---|
| 31 | +#ifndef ELF32_ST_VISIBILITY |
|---|
| 32 | +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) |
|---|
| 33 | +#endif |
|---|
| 34 | + |
|---|
| 35 | +/* For ELF64 the definitions are the same. */ |
|---|
| 36 | +#ifndef ELF64_ST_VISIBILITY |
|---|
| 37 | +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) |
|---|
| 38 | +#endif |
|---|
| 39 | + |
|---|
| 40 | +/* How to extract information held in the st_other field. */ |
|---|
| 41 | +#ifndef GELF_ST_VISIBILITY |
|---|
| 42 | +#define GELF_ST_VISIBILITY(val) ELF64_ST_VISIBILITY (val) |
|---|
| 43 | +#endif |
|---|
| 44 | + |
|---|
| 22 | 45 | typedef Elf64_Nhdr GElf_Nhdr; |
|---|
| 23 | 46 | |
|---|
| 47 | +#ifndef DMGL_PARAMS |
|---|
| 48 | +#define DMGL_NO_OPTS 0 /* For readability... */ |
|---|
| 49 | +#define DMGL_PARAMS (1 << 0) /* Include function args */ |
|---|
| 50 | +#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ |
|---|
| 51 | +#endif |
|---|
| 52 | + |
|---|
| 53 | +#ifdef HAVE_LIBBFD_SUPPORT |
|---|
| 54 | +#define PACKAGE 'perf' |
|---|
| 55 | +#include <bfd.h> |
|---|
| 56 | +#else |
|---|
| 24 | 57 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT |
|---|
| 25 | 58 | extern char *cplus_demangle(const char *, int); |
|---|
| 26 | 59 | |
|---|
| .. | .. |
|---|
| 36 | 69 | { |
|---|
| 37 | 70 | return NULL; |
|---|
| 38 | 71 | } |
|---|
| 39 | | -#else |
|---|
| 40 | | -#define PACKAGE 'perf' |
|---|
| 41 | | -#include <bfd.h> |
|---|
| 72 | +#endif |
|---|
| 42 | 73 | #endif |
|---|
| 43 | 74 | #endif |
|---|
| 44 | 75 | |
|---|
| .. | .. |
|---|
| 199 | 230 | } |
|---|
| 200 | 231 | |
|---|
| 201 | 232 | return NULL; |
|---|
| 233 | +} |
|---|
| 234 | + |
|---|
| 235 | +static int elf_read_program_header(Elf *elf, u64 vaddr, GElf_Phdr *phdr) |
|---|
| 236 | +{ |
|---|
| 237 | + size_t i, phdrnum; |
|---|
| 238 | + u64 sz; |
|---|
| 239 | + |
|---|
| 240 | + if (elf_getphdrnum(elf, &phdrnum)) |
|---|
| 241 | + return -1; |
|---|
| 242 | + |
|---|
| 243 | + for (i = 0; i < phdrnum; i++) { |
|---|
| 244 | + if (gelf_getphdr(elf, i, phdr) == NULL) |
|---|
| 245 | + return -1; |
|---|
| 246 | + |
|---|
| 247 | + if (phdr->p_type != PT_LOAD) |
|---|
| 248 | + continue; |
|---|
| 249 | + |
|---|
| 250 | + sz = max(phdr->p_memsz, phdr->p_filesz); |
|---|
| 251 | + if (!sz) |
|---|
| 252 | + continue; |
|---|
| 253 | + |
|---|
| 254 | + if (vaddr >= phdr->p_vaddr && (vaddr < phdr->p_vaddr + sz)) |
|---|
| 255 | + return 0; |
|---|
| 256 | + } |
|---|
| 257 | + |
|---|
| 258 | + /* Not found any valid program header */ |
|---|
| 259 | + return -1; |
|---|
| 202 | 260 | } |
|---|
| 203 | 261 | |
|---|
| 204 | 262 | static bool want_demangle(bool is_kernel_sym) |
|---|
| .. | .. |
|---|
| 501 | 559 | return err; |
|---|
| 502 | 560 | } |
|---|
| 503 | 561 | |
|---|
| 504 | | -int filename__read_build_id(const char *filename, void *bf, size_t size) |
|---|
| 562 | +#ifdef HAVE_LIBBFD_BUILDID_SUPPORT |
|---|
| 563 | + |
|---|
| 564 | +int filename__read_build_id(const char *filename, struct build_id *bid) |
|---|
| 505 | 565 | { |
|---|
| 566 | + size_t size = sizeof(bid->data); |
|---|
| 567 | + int err = -1; |
|---|
| 568 | + bfd *abfd; |
|---|
| 569 | + |
|---|
| 570 | + abfd = bfd_openr(filename, NULL); |
|---|
| 571 | + if (!abfd) |
|---|
| 572 | + return -1; |
|---|
| 573 | + |
|---|
| 574 | + if (!bfd_check_format(abfd, bfd_object)) { |
|---|
| 575 | + pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename); |
|---|
| 576 | + goto out_close; |
|---|
| 577 | + } |
|---|
| 578 | + |
|---|
| 579 | + if (!abfd->build_id || abfd->build_id->size > size) |
|---|
| 580 | + goto out_close; |
|---|
| 581 | + |
|---|
| 582 | + memcpy(bid->data, abfd->build_id->data, abfd->build_id->size); |
|---|
| 583 | + memset(bid->data + abfd->build_id->size, 0, size - abfd->build_id->size); |
|---|
| 584 | + err = bid->size = abfd->build_id->size; |
|---|
| 585 | + |
|---|
| 586 | +out_close: |
|---|
| 587 | + bfd_close(abfd); |
|---|
| 588 | + return err; |
|---|
| 589 | +} |
|---|
| 590 | + |
|---|
| 591 | +#else // HAVE_LIBBFD_BUILDID_SUPPORT |
|---|
| 592 | + |
|---|
| 593 | +int filename__read_build_id(const char *filename, struct build_id *bid) |
|---|
| 594 | +{ |
|---|
| 595 | + size_t size = sizeof(bid->data); |
|---|
| 506 | 596 | int fd, err = -1; |
|---|
| 507 | 597 | Elf *elf; |
|---|
| 508 | 598 | |
|---|
| .. | .. |
|---|
| 519 | 609 | goto out_close; |
|---|
| 520 | 610 | } |
|---|
| 521 | 611 | |
|---|
| 522 | | - err = elf_read_build_id(elf, bf, size); |
|---|
| 612 | + err = elf_read_build_id(elf, bid->data, size); |
|---|
| 613 | + if (err > 0) |
|---|
| 614 | + bid->size = err; |
|---|
| 523 | 615 | |
|---|
| 524 | 616 | elf_end(elf); |
|---|
| 525 | 617 | out_close: |
|---|
| .. | .. |
|---|
| 528 | 620 | return err; |
|---|
| 529 | 621 | } |
|---|
| 530 | 622 | |
|---|
| 531 | | -int sysfs__read_build_id(const char *filename, void *build_id, size_t size) |
|---|
| 532 | | -{ |
|---|
| 533 | | - int fd, err = -1; |
|---|
| 623 | +#endif // HAVE_LIBBFD_BUILDID_SUPPORT |
|---|
| 534 | 624 | |
|---|
| 535 | | - if (size < BUILD_ID_SIZE) |
|---|
| 536 | | - goto out; |
|---|
| 625 | +int sysfs__read_build_id(const char *filename, struct build_id *bid) |
|---|
| 626 | +{ |
|---|
| 627 | + size_t size = sizeof(bid->data); |
|---|
| 628 | + int fd, err = -1; |
|---|
| 537 | 629 | |
|---|
| 538 | 630 | fd = open(filename, O_RDONLY); |
|---|
| 539 | 631 | if (fd < 0) |
|---|
| .. | .. |
|---|
| 555 | 647 | break; |
|---|
| 556 | 648 | if (memcmp(bf, "GNU", sizeof("GNU")) == 0) { |
|---|
| 557 | 649 | size_t sz = min(descsz, size); |
|---|
| 558 | | - if (read(fd, build_id, sz) == (ssize_t)sz) { |
|---|
| 559 | | - memset(build_id + sz, 0, size - sz); |
|---|
| 650 | + if (read(fd, bid->data, sz) == (ssize_t)sz) { |
|---|
| 651 | + memset(bid->data + sz, 0, size - sz); |
|---|
| 652 | + bid->size = sz; |
|---|
| 560 | 653 | err = 0; |
|---|
| 561 | 654 | break; |
|---|
| 562 | 655 | } |
|---|
| .. | .. |
|---|
| 578 | 671 | out: |
|---|
| 579 | 672 | return err; |
|---|
| 580 | 673 | } |
|---|
| 674 | + |
|---|
| 675 | +#ifdef HAVE_LIBBFD_SUPPORT |
|---|
| 676 | + |
|---|
| 677 | +int filename__read_debuglink(const char *filename, char *debuglink, |
|---|
| 678 | + size_t size) |
|---|
| 679 | +{ |
|---|
| 680 | + int err = -1; |
|---|
| 681 | + asection *section; |
|---|
| 682 | + bfd *abfd; |
|---|
| 683 | + |
|---|
| 684 | + abfd = bfd_openr(filename, NULL); |
|---|
| 685 | + if (!abfd) |
|---|
| 686 | + return -1; |
|---|
| 687 | + |
|---|
| 688 | + if (!bfd_check_format(abfd, bfd_object)) { |
|---|
| 689 | + pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename); |
|---|
| 690 | + goto out_close; |
|---|
| 691 | + } |
|---|
| 692 | + |
|---|
| 693 | + section = bfd_get_section_by_name(abfd, ".gnu_debuglink"); |
|---|
| 694 | + if (!section) |
|---|
| 695 | + goto out_close; |
|---|
| 696 | + |
|---|
| 697 | + if (section->size > size) |
|---|
| 698 | + goto out_close; |
|---|
| 699 | + |
|---|
| 700 | + if (!bfd_get_section_contents(abfd, section, debuglink, 0, |
|---|
| 701 | + section->size)) |
|---|
| 702 | + goto out_close; |
|---|
| 703 | + |
|---|
| 704 | + err = 0; |
|---|
| 705 | + |
|---|
| 706 | +out_close: |
|---|
| 707 | + bfd_close(abfd); |
|---|
| 708 | + return err; |
|---|
| 709 | +} |
|---|
| 710 | + |
|---|
| 711 | +#else |
|---|
| 581 | 712 | |
|---|
| 582 | 713 | int filename__read_debuglink(const char *filename, char *debuglink, |
|---|
| 583 | 714 | size_t size) |
|---|
| .. | .. |
|---|
| 631 | 762 | return err; |
|---|
| 632 | 763 | } |
|---|
| 633 | 764 | |
|---|
| 765 | +#endif |
|---|
| 766 | + |
|---|
| 634 | 767 | static int dso__swap_init(struct dso *dso, unsigned char eidata) |
|---|
| 635 | 768 | { |
|---|
| 636 | 769 | static unsigned int const endian = 1; |
|---|
| .. | .. |
|---|
| 675 | 808 | close(ss->fd); |
|---|
| 676 | 809 | } |
|---|
| 677 | 810 | |
|---|
| 678 | | -bool __weak elf__needs_adjust_symbols(GElf_Ehdr ehdr) |
|---|
| 811 | +bool elf__needs_adjust_symbols(GElf_Ehdr ehdr) |
|---|
| 679 | 812 | { |
|---|
| 680 | | - return ehdr.e_type == ET_EXEC || ehdr.e_type == ET_REL; |
|---|
| 813 | + /* |
|---|
| 814 | + * Usually vmlinux is an ELF file with type ET_EXEC for most |
|---|
| 815 | + * architectures; except Arm64 kernel is linked with option |
|---|
| 816 | + * '-share', so need to check type ET_DYN. |
|---|
| 817 | + */ |
|---|
| 818 | + return ehdr.e_type == ET_EXEC || ehdr.e_type == ET_REL || |
|---|
| 819 | + ehdr.e_type == ET_DYN; |
|---|
| 681 | 820 | } |
|---|
| 682 | 821 | |
|---|
| 683 | 822 | int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, |
|---|
| 684 | 823 | enum dso_binary_type type) |
|---|
| 685 | 824 | { |
|---|
| 686 | | - int err = -1; |
|---|
| 687 | 825 | GElf_Ehdr ehdr; |
|---|
| 688 | 826 | Elf *elf; |
|---|
| 689 | 827 | int fd; |
|---|
| .. | .. |
|---|
| 723 | 861 | /* Always reject images with a mismatched build-id: */ |
|---|
| 724 | 862 | if (dso->has_build_id && !symbol_conf.ignore_vmlinux_buildid) { |
|---|
| 725 | 863 | u8 build_id[BUILD_ID_SIZE]; |
|---|
| 864 | + struct build_id bid; |
|---|
| 865 | + int size; |
|---|
| 726 | 866 | |
|---|
| 727 | | - if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) { |
|---|
| 867 | + size = elf_read_build_id(elf, build_id, BUILD_ID_SIZE); |
|---|
| 868 | + if (size <= 0) { |
|---|
| 728 | 869 | dso->load_errno = DSO_LOAD_ERRNO__CANNOT_READ_BUILDID; |
|---|
| 729 | 870 | goto out_elf_end; |
|---|
| 730 | 871 | } |
|---|
| 731 | 872 | |
|---|
| 732 | | - if (!dso__build_id_equal(dso, build_id)) { |
|---|
| 873 | + build_id__init(&bid, build_id, size); |
|---|
| 874 | + if (!dso__build_id_equal(dso, &bid)) { |
|---|
| 733 | 875 | pr_debug("%s: build id mismatch for %s.\n", __func__, name); |
|---|
| 734 | 876 | dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID; |
|---|
| 735 | 877 | goto out_elf_end; |
|---|
| .. | .. |
|---|
| 755 | 897 | if (ss->opdshdr.sh_type != SHT_PROGBITS) |
|---|
| 756 | 898 | ss->opdsec = NULL; |
|---|
| 757 | 899 | |
|---|
| 758 | | - if (dso->kernel == DSO_TYPE_USER) |
|---|
| 900 | + if (dso->kernel == DSO_SPACE__USER) |
|---|
| 759 | 901 | ss->adjust_symbols = true; |
|---|
| 760 | 902 | else |
|---|
| 761 | 903 | ss->adjust_symbols = elf__needs_adjust_symbols(ehdr); |
|---|
| .. | .. |
|---|
| 777 | 919 | elf_end(elf); |
|---|
| 778 | 920 | out_close: |
|---|
| 779 | 921 | close(fd); |
|---|
| 780 | | - return err; |
|---|
| 922 | + return -1; |
|---|
| 781 | 923 | } |
|---|
| 782 | 924 | |
|---|
| 783 | 925 | /** |
|---|
| .. | .. |
|---|
| 816 | 958 | |
|---|
| 817 | 959 | static int dso__process_kernel_symbol(struct dso *dso, struct map *map, |
|---|
| 818 | 960 | GElf_Sym *sym, GElf_Shdr *shdr, |
|---|
| 819 | | - struct map_groups *kmaps, struct kmap *kmap, |
|---|
| 961 | + struct maps *kmaps, struct kmap *kmap, |
|---|
| 820 | 962 | struct dso **curr_dsop, struct map **curr_mapp, |
|---|
| 821 | 963 | const char *section_name, |
|---|
| 822 | 964 | bool adjust_kernel_syms, bool kmodule, bool *remap_kernel) |
|---|
| .. | .. |
|---|
| 838 | 980 | * kallsyms and identity maps. Overwrite it to |
|---|
| 839 | 981 | * map to the kernel dso. |
|---|
| 840 | 982 | */ |
|---|
| 841 | | - if (*remap_kernel && dso->kernel) { |
|---|
| 983 | + if (*remap_kernel && dso->kernel && !kmodule) { |
|---|
| 842 | 984 | *remap_kernel = false; |
|---|
| 843 | 985 | map->start = shdr->sh_addr + ref_reloc(kmap); |
|---|
| 844 | 986 | map->end = map->start + shdr->sh_size; |
|---|
| .. | .. |
|---|
| 848 | 990 | /* Ensure maps are correctly ordered */ |
|---|
| 849 | 991 | if (kmaps) { |
|---|
| 850 | 992 | map__get(map); |
|---|
| 851 | | - map_groups__remove(kmaps, map); |
|---|
| 852 | | - map_groups__insert(kmaps, map); |
|---|
| 993 | + maps__remove(kmaps, map); |
|---|
| 994 | + maps__insert(kmaps, map); |
|---|
| 853 | 995 | map__put(map); |
|---|
| 854 | 996 | } |
|---|
| 855 | 997 | } |
|---|
| .. | .. |
|---|
| 874 | 1016 | |
|---|
| 875 | 1017 | snprintf(dso_name, sizeof(dso_name), "%s%s", dso->short_name, section_name); |
|---|
| 876 | 1018 | |
|---|
| 877 | | - curr_map = map_groups__find_by_name(kmaps, dso_name); |
|---|
| 1019 | + curr_map = maps__find_by_name(kmaps, dso_name); |
|---|
| 878 | 1020 | if (curr_map == NULL) { |
|---|
| 879 | 1021 | u64 start = sym->st_value; |
|---|
| 880 | 1022 | |
|---|
| .. | .. |
|---|
| 892 | 1034 | if (curr_map == NULL) |
|---|
| 893 | 1035 | return -1; |
|---|
| 894 | 1036 | |
|---|
| 1037 | + if (curr_dso->kernel) |
|---|
| 1038 | + map__kmap(curr_map)->kmaps = kmaps; |
|---|
| 1039 | + |
|---|
| 895 | 1040 | if (adjust_kernel_syms) { |
|---|
| 896 | 1041 | curr_map->start = shdr->sh_addr + ref_reloc(kmap); |
|---|
| 897 | 1042 | curr_map->end = curr_map->start + shdr->sh_size; |
|---|
| .. | .. |
|---|
| 900 | 1045 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; |
|---|
| 901 | 1046 | } |
|---|
| 902 | 1047 | curr_dso->symtab_type = dso->symtab_type; |
|---|
| 903 | | - map_groups__insert(kmaps, curr_map); |
|---|
| 1048 | + maps__insert(kmaps, curr_map); |
|---|
| 904 | 1049 | /* |
|---|
| 905 | 1050 | * Add it before we drop the referece to curr_map, i.e. while |
|---|
| 906 | 1051 | * we still are sure to have a reference to this DSO via |
|---|
| 907 | 1052 | * *curr_map->dso. |
|---|
| 908 | 1053 | */ |
|---|
| 909 | | - dsos__add(&map->groups->machine->dsos, curr_dso); |
|---|
| 1054 | + dsos__add(&kmaps->machine->dsos, curr_dso); |
|---|
| 910 | 1055 | /* kmaps already got it */ |
|---|
| 911 | 1056 | map__put(curr_map); |
|---|
| 912 | 1057 | dso__set_loaded(curr_dso); |
|---|
| .. | .. |
|---|
| 922 | 1067 | struct symsrc *runtime_ss, int kmodule) |
|---|
| 923 | 1068 | { |
|---|
| 924 | 1069 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; |
|---|
| 925 | | - struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL; |
|---|
| 1070 | + struct maps *kmaps = kmap ? map__kmaps(map) : NULL; |
|---|
| 926 | 1071 | struct map *curr_map = map; |
|---|
| 927 | 1072 | struct dso *curr_dso = dso; |
|---|
| 928 | 1073 | Elf_Data *symstrs, *secstrs; |
|---|
| .. | .. |
|---|
| 1031 | 1176 | * Initial kernel and module mappings do not map to the dso. |
|---|
| 1032 | 1177 | * Flag the fixups. |
|---|
| 1033 | 1178 | */ |
|---|
| 1034 | | - if (dso->kernel || kmodule) { |
|---|
| 1179 | + if (dso->kernel) { |
|---|
| 1035 | 1180 | remap_kernel = true; |
|---|
| 1036 | 1181 | adjust_kernel_syms = dso->adjust_symbols; |
|---|
| 1037 | 1182 | } |
|---|
| .. | .. |
|---|
| 1063 | 1208 | sym.st_value); |
|---|
| 1064 | 1209 | used_opd = true; |
|---|
| 1065 | 1210 | } |
|---|
| 1211 | + |
|---|
| 1066 | 1212 | /* |
|---|
| 1067 | 1213 | * When loading symbols in a data mapping, ABS symbols (which |
|---|
| 1068 | 1214 | * has a value of SHN_ABS in its st_shndx) failed at |
|---|
| .. | .. |
|---|
| 1093 | 1239 | (sym.st_value & 1)) |
|---|
| 1094 | 1240 | --sym.st_value; |
|---|
| 1095 | 1241 | |
|---|
| 1096 | | - if (dso->kernel || kmodule) { |
|---|
| 1242 | + if (dso->kernel) { |
|---|
| 1097 | 1243 | if (dso__process_kernel_symbol(dso, map, &sym, &shdr, kmaps, kmap, &curr_dso, &curr_map, |
|---|
| 1098 | 1244 | section_name, adjust_kernel_syms, kmodule, &remap_kernel)) |
|---|
| 1099 | 1245 | goto out_elf_end; |
|---|
| 1100 | 1246 | } else if ((used_opd && runtime_ss->adjust_symbols) || |
|---|
| 1101 | 1247 | (!used_opd && syms_ss->adjust_symbols)) { |
|---|
| 1102 | | - pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " |
|---|
| 1103 | | - "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__, |
|---|
| 1104 | | - (u64)sym.st_value, (u64)shdr.sh_addr, |
|---|
| 1105 | | - (u64)shdr.sh_offset); |
|---|
| 1106 | | - sym.st_value -= shdr.sh_addr - shdr.sh_offset; |
|---|
| 1248 | + GElf_Phdr phdr; |
|---|
| 1249 | + |
|---|
| 1250 | + if (elf_read_program_header(syms_ss->elf, |
|---|
| 1251 | + (u64)sym.st_value, &phdr)) { |
|---|
| 1252 | + pr_debug4("%s: failed to find program header for " |
|---|
| 1253 | + "symbol: %s st_value: %#" PRIx64 "\n", |
|---|
| 1254 | + __func__, elf_name, (u64)sym.st_value); |
|---|
| 1255 | + pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " |
|---|
| 1256 | + "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", |
|---|
| 1257 | + __func__, (u64)sym.st_value, (u64)shdr.sh_addr, |
|---|
| 1258 | + (u64)shdr.sh_offset); |
|---|
| 1259 | + /* |
|---|
| 1260 | + * Fail to find program header, let's rollback |
|---|
| 1261 | + * to use shdr.sh_addr and shdr.sh_offset to |
|---|
| 1262 | + * calibrate symbol's file address, though this |
|---|
| 1263 | + * is not necessary for normal C ELF file, we |
|---|
| 1264 | + * still need to handle java JIT symbols in this |
|---|
| 1265 | + * case. |
|---|
| 1266 | + */ |
|---|
| 1267 | + sym.st_value -= shdr.sh_addr - shdr.sh_offset; |
|---|
| 1268 | + } else { |
|---|
| 1269 | + pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " |
|---|
| 1270 | + "p_vaddr: %#" PRIx64 " p_offset: %#" PRIx64 "\n", |
|---|
| 1271 | + __func__, (u64)sym.st_value, (u64)phdr.p_vaddr, |
|---|
| 1272 | + (u64)phdr.p_offset); |
|---|
| 1273 | + sym.st_value -= phdr.p_vaddr - phdr.p_offset; |
|---|
| 1274 | + } |
|---|
| 1107 | 1275 | } |
|---|
| 1108 | 1276 | |
|---|
| 1109 | 1277 | demangled = demangle_sym(dso, kmodule, elf_name); |
|---|
| .. | .. |
|---|
| 1127 | 1295 | * For misannotated, zeroed, ASM function sizes. |
|---|
| 1128 | 1296 | */ |
|---|
| 1129 | 1297 | if (nr > 0) { |
|---|
| 1130 | | - symbols__fixup_end(&dso->symbols); |
|---|
| 1298 | + symbols__fixup_end(&dso->symbols, false); |
|---|
| 1131 | 1299 | symbols__fixup_duplicate(&dso->symbols); |
|---|
| 1132 | 1300 | if (kmap) { |
|---|
| 1133 | 1301 | /* |
|---|
| 1134 | 1302 | * We need to fixup this here too because we create new |
|---|
| 1135 | 1303 | * maps here, for things like vsyscall sections. |
|---|
| 1136 | 1304 | */ |
|---|
| 1137 | | - map_groups__fixup_end(kmaps); |
|---|
| 1305 | + maps__fixup_end(kmaps); |
|---|
| 1138 | 1306 | } |
|---|
| 1139 | 1307 | } |
|---|
| 1140 | 1308 | err = nr; |
|---|
| .. | .. |
|---|
| 1461 | 1629 | struct phdr_data *p, *tmp; |
|---|
| 1462 | 1630 | |
|---|
| 1463 | 1631 | list_for_each_entry_safe(p, tmp, &kci->phdrs, node) { |
|---|
| 1464 | | - list_del(&p->node); |
|---|
| 1632 | + list_del_init(&p->node); |
|---|
| 1465 | 1633 | free(p); |
|---|
| 1466 | 1634 | } |
|---|
| 1467 | 1635 | } |
|---|
| .. | .. |
|---|
| 1484 | 1652 | struct sym_data *s, *tmp; |
|---|
| 1485 | 1653 | |
|---|
| 1486 | 1654 | list_for_each_entry_safe(s, tmp, &kci->syms, node) { |
|---|
| 1487 | | - list_del(&s->node); |
|---|
| 1655 | + list_del_init(&s->node); |
|---|
| 1488 | 1656 | free(s); |
|---|
| 1489 | 1657 | } |
|---|
| 1490 | 1658 | } |
|---|
| .. | .. |
|---|
| 1834 | 2002 | * unusual. One significant peculiarity is that the mapping (start -> pgoff) |
|---|
| 1835 | 2003 | * is not the same for the kernel map and the modules map. That happens because |
|---|
| 1836 | 2004 | * the data is copied adjacently whereas the original kcore has gaps. Finally, |
|---|
| 1837 | | - * kallsyms and modules files are compared with their copies to check that |
|---|
| 1838 | | - * modules have not been loaded or unloaded while the copies were taking place. |
|---|
| 2005 | + * kallsyms file is compared with its copy to check that modules have not been |
|---|
| 2006 | + * loaded or unloaded while the copies were taking place. |
|---|
| 1839 | 2007 | * |
|---|
| 1840 | 2008 | * Return: %0 on success, %-1 on failure. |
|---|
| 1841 | 2009 | */ |
|---|
| .. | .. |
|---|
| 1897 | 2065 | if (copy_bytes(kcore.fd, p->offset, extract.fd, offs, p->len)) |
|---|
| 1898 | 2066 | goto out_extract_close; |
|---|
| 1899 | 2067 | } |
|---|
| 1900 | | - |
|---|
| 1901 | | - if (kcore_copy__compare_file(from_dir, to_dir, "modules")) |
|---|
| 1902 | | - goto out_extract_close; |
|---|
| 1903 | 2068 | |
|---|
| 1904 | 2069 | if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms")) |
|---|
| 1905 | 2070 | goto out_extract_close; |
|---|
| .. | .. |
|---|
| 1971 | 2136 | } |
|---|
| 1972 | 2137 | |
|---|
| 1973 | 2138 | #ifdef HAVE_GELF_GETNOTE_SUPPORT |
|---|
| 2139 | + |
|---|
| 2140 | +static void sdt_adjust_loc(struct sdt_note *tmp, GElf_Addr base_off) |
|---|
| 2141 | +{ |
|---|
| 2142 | + if (!base_off) |
|---|
| 2143 | + return; |
|---|
| 2144 | + |
|---|
| 2145 | + if (tmp->bit32) |
|---|
| 2146 | + tmp->addr.a32[SDT_NOTE_IDX_LOC] = |
|---|
| 2147 | + tmp->addr.a32[SDT_NOTE_IDX_LOC] + base_off - |
|---|
| 2148 | + tmp->addr.a32[SDT_NOTE_IDX_BASE]; |
|---|
| 2149 | + else |
|---|
| 2150 | + tmp->addr.a64[SDT_NOTE_IDX_LOC] = |
|---|
| 2151 | + tmp->addr.a64[SDT_NOTE_IDX_LOC] + base_off - |
|---|
| 2152 | + tmp->addr.a64[SDT_NOTE_IDX_BASE]; |
|---|
| 2153 | +} |
|---|
| 2154 | + |
|---|
| 2155 | +static void sdt_adjust_refctr(struct sdt_note *tmp, GElf_Addr base_addr, |
|---|
| 2156 | + GElf_Addr base_off) |
|---|
| 2157 | +{ |
|---|
| 2158 | + if (!base_off) |
|---|
| 2159 | + return; |
|---|
| 2160 | + |
|---|
| 2161 | + if (tmp->bit32 && tmp->addr.a32[SDT_NOTE_IDX_REFCTR]) |
|---|
| 2162 | + tmp->addr.a32[SDT_NOTE_IDX_REFCTR] -= (base_addr - base_off); |
|---|
| 2163 | + else if (tmp->addr.a64[SDT_NOTE_IDX_REFCTR]) |
|---|
| 2164 | + tmp->addr.a64[SDT_NOTE_IDX_REFCTR] -= (base_addr - base_off); |
|---|
| 2165 | +} |
|---|
| 2166 | + |
|---|
| 1974 | 2167 | /** |
|---|
| 1975 | 2168 | * populate_sdt_note : Parse raw data and identify SDT note |
|---|
| 1976 | 2169 | * @elf: elf of the opened file |
|---|
| .. | .. |
|---|
| 1988 | 2181 | const char *provider, *name, *args; |
|---|
| 1989 | 2182 | struct sdt_note *tmp = NULL; |
|---|
| 1990 | 2183 | GElf_Ehdr ehdr; |
|---|
| 1991 | | - GElf_Addr base_off = 0; |
|---|
| 1992 | 2184 | GElf_Shdr shdr; |
|---|
| 1993 | 2185 | int ret = -EINVAL; |
|---|
| 1994 | 2186 | |
|---|
| .. | .. |
|---|
| 2084 | 2276 | * base address in the description of the SDT note. If its different, |
|---|
| 2085 | 2277 | * then accordingly, adjust the note location. |
|---|
| 2086 | 2278 | */ |
|---|
| 2087 | | - if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) { |
|---|
| 2088 | | - base_off = shdr.sh_offset; |
|---|
| 2089 | | - if (base_off) { |
|---|
| 2090 | | - if (tmp->bit32) |
|---|
| 2091 | | - tmp->addr.a32[0] = tmp->addr.a32[0] + base_off - |
|---|
| 2092 | | - tmp->addr.a32[1]; |
|---|
| 2093 | | - else |
|---|
| 2094 | | - tmp->addr.a64[0] = tmp->addr.a64[0] + base_off - |
|---|
| 2095 | | - tmp->addr.a64[1]; |
|---|
| 2096 | | - } |
|---|
| 2097 | | - } |
|---|
| 2279 | + if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) |
|---|
| 2280 | + sdt_adjust_loc(tmp, shdr.sh_offset); |
|---|
| 2281 | + |
|---|
| 2282 | + /* Adjust reference counter offset */ |
|---|
| 2283 | + if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_PROBES_SCN, NULL)) |
|---|
| 2284 | + sdt_adjust_refctr(tmp, shdr.sh_addr, shdr.sh_offset); |
|---|
| 2098 | 2285 | |
|---|
| 2099 | 2286 | list_add_tail(&tmp->note_list, sdt_notes); |
|---|
| 2100 | 2287 | return 0; |
|---|
| 2101 | 2288 | |
|---|
| 2102 | 2289 | out_free_args: |
|---|
| 2103 | | - free(tmp->args); |
|---|
| 2290 | + zfree(&tmp->args); |
|---|
| 2104 | 2291 | out_free_name: |
|---|
| 2105 | | - free(tmp->name); |
|---|
| 2292 | + zfree(&tmp->name); |
|---|
| 2106 | 2293 | out_free_prov: |
|---|
| 2107 | | - free(tmp->provider); |
|---|
| 2294 | + zfree(&tmp->provider); |
|---|
| 2108 | 2295 | out_free_note: |
|---|
| 2109 | 2296 | free(tmp); |
|---|
| 2110 | 2297 | out_err: |
|---|
| .. | .. |
|---|
| 2219 | 2406 | int nr_free = 0; |
|---|
| 2220 | 2407 | |
|---|
| 2221 | 2408 | list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) { |
|---|
| 2222 | | - list_del(&pos->note_list); |
|---|
| 2223 | | - free(pos->name); |
|---|
| 2224 | | - free(pos->provider); |
|---|
| 2409 | + list_del_init(&pos->note_list); |
|---|
| 2410 | + zfree(&pos->args); |
|---|
| 2411 | + zfree(&pos->name); |
|---|
| 2412 | + zfree(&pos->provider); |
|---|
| 2225 | 2413 | free(pos); |
|---|
| 2226 | 2414 | nr_free++; |
|---|
| 2227 | 2415 | } |
|---|