.. | .. |
---|
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) |
---|
.. | .. |
---|
490 | 548 | size_t sz = min(size, descsz); |
---|
491 | 549 | memcpy(bf, ptr, sz); |
---|
492 | 550 | memset(bf + sz, 0, size - sz); |
---|
493 | | - err = descsz; |
---|
| 551 | + err = sz; |
---|
494 | 552 | break; |
---|
495 | 553 | } |
---|
496 | 554 | } |
---|
.. | .. |
---|
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(runtime_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 | } |
---|