^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "dso.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "maps.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "symsrc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "demangle-java.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "demangle-rust.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "machine.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "vdso.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "util/copyfile.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <symbol/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <internal/lib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #ifndef EM_AARCH64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define EM_AARCH64 183 /* ARM 64 bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #ifndef ELF32_ST_VISIBILITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* For ELF64 the definitions are the same. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #ifndef ELF64_ST_VISIBILITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* How to extract information held in the st_other field. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #ifndef GELF_ST_VISIBILITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define GELF_ST_VISIBILITY(val) ELF64_ST_VISIBILITY (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) typedef Elf64_Nhdr GElf_Nhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #ifndef DMGL_PARAMS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define DMGL_NO_OPTS 0 /* For readability... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define DMGL_PARAMS (1 << 0) /* Include function args */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #ifdef HAVE_LIBBFD_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define PACKAGE 'perf'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <bfd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) extern char *cplus_demangle(const char *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return cplus_demangle(c, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #ifdef NO_DEMANGLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static inline char *bfd_demangle(void __maybe_unused *v,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) const char __maybe_unused *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int __maybe_unused i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int elf_getphdrnum(Elf *elf, size_t *dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) GElf_Ehdr gehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) GElf_Ehdr *ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ehdr = gelf_getehdr(elf, &gehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!ehdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *dst = ehdr->e_phnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #ifndef HAVE_ELF_GETSHDRSTRNDX_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int elf_getshdrstrndx(Elf *elf __maybe_unused, size_t *dst __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) pr_err("%s: update your libelf to > 0.140, this one lacks elf_getshdrstrndx().\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #ifndef NT_GNU_BUILD_ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define NT_GNU_BUILD_ID 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * elf_symtab__for_each_symbol - iterate thru all the symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @syms: struct elf_symtab instance to iterate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @idx: uint32_t idx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @sym: GElf_Sym iterator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) for (idx = 0, gelf_getsym(syms, idx, &sym);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) idx < nr_syms; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) idx++, gelf_getsym(syms, idx, &sym))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static inline uint8_t elf_sym__type(const GElf_Sym *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return GELF_ST_TYPE(sym->st_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static inline uint8_t elf_sym__visibility(const GElf_Sym *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return GELF_ST_VISIBILITY(sym->st_other);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #ifndef STT_GNU_IFUNC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define STT_GNU_IFUNC 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static inline int elf_sym__is_function(const GElf_Sym *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return (elf_sym__type(sym) == STT_FUNC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) elf_sym__type(sym) == STT_GNU_IFUNC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) sym->st_name != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) sym->st_shndx != SHN_UNDEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static inline bool elf_sym__is_object(const GElf_Sym *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return elf_sym__type(sym) == STT_OBJECT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) sym->st_name != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) sym->st_shndx != SHN_UNDEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static inline int elf_sym__is_label(const GElf_Sym *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return elf_sym__type(sym) == STT_NOTYPE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) sym->st_name != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) sym->st_shndx != SHN_UNDEF &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) sym->st_shndx != SHN_ABS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) elf_sym__visibility(sym) != STV_HIDDEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) elf_sym__visibility(sym) != STV_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static bool elf_sym__filter(GElf_Sym *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return elf_sym__is_function(sym) || elf_sym__is_object(sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static inline const char *elf_sym__name(const GElf_Sym *sym,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) const Elf_Data *symstrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return symstrs->d_buf + sym->st_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static inline const char *elf_sec__name(const GElf_Shdr *shdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) const Elf_Data *secstrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return secstrs->d_buf + shdr->sh_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static inline int elf_sec__is_text(const GElf_Shdr *shdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) const Elf_Data *secstrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) const Elf_Data *secstrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static bool elf_sec__filter(GElf_Shdr *shdr, Elf_Data *secstrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return elf_sec__is_text(shdr, secstrs) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) elf_sec__is_data(shdr, secstrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) Elf_Scn *sec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) GElf_Shdr shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) size_t cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) while ((sec = elf_nextscn(elf, sec)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) gelf_getshdr(sec, &shdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if ((addr >= shdr.sh_addr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) (addr < (shdr.sh_addr + shdr.sh_size)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ++cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) GElf_Shdr *shp, const char *name, size_t *idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) Elf_Scn *sec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) size_t cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* Elf is corrupted/truncated, avoid calling elf_strptr. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) while ((sec = elf_nextscn(elf, sec)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) gelf_getshdr(sec, shp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (str && !strcmp(name, str)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *idx = cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ++cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static bool want_demangle(bool is_kernel_sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int demangle_flags = verbose > 0 ? (DMGL_PARAMS | DMGL_ANSI) : DMGL_NO_OPTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) char *demangled = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * We need to figure out if the object was created from C++ sources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * DWARF DW_compile_unit has this, but we don't always have access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * to it...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (!want_demangle(dso->kernel || kmodule))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return demangled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) demangled = bfd_demangle(NULL, elf_name, demangle_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (demangled == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) else if (rust_is_mangled(demangled))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * Input to Rust demangling is the BFD-demangled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * name which it Rust-demangles in place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) rust_demangle_sym(demangled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return demangled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) idx < nr_entries; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) idx < nr_entries; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * We need to check if we have a .dynsym, so that we can handle the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * .plt, synthesizing its symbols, that aren't on the symtabs (be it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * .dynsym or .symtab).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * And always look at the original dso, not at debuginfo packages, that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) uint32_t nr_rel_entries, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) GElf_Sym sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) u64 plt_offset, plt_header_size, plt_entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) GElf_Shdr shdr_plt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct symbol *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) GElf_Shdr shdr_rel_plt, shdr_dynsym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) Elf_Data *reldata, *syms, *symstrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) size_t dynsym_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) char sympltname[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int nr = 0, symidx, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!ss->dynsym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) elf = ss->elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ehdr = ss->ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) scn_dynsym = ss->dynsym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) shdr_dynsym = ss->dynshdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dynsym_idx = ss->dynsym_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (scn_dynsym == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ".rela.plt", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (scn_plt_rel == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ".rel.plt", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (scn_plt_rel == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (shdr_rel_plt.sh_link != dynsym_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * Fetch the relocation section to find the idxes to the GOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * and the symbols in the .dynsym they refer to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) reldata = elf_getdata(scn_plt_rel, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (reldata == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) syms = elf_getdata(scn_dynsym, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (syms == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (scn_symstrs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) symstrs = elf_getdata(scn_symstrs, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (symstrs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (symstrs->d_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) plt_offset = shdr_plt.sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) switch (ehdr.e_machine) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case EM_ARM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) plt_header_size = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) plt_entry_size = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case EM_AARCH64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) plt_header_size = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) plt_entry_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case EM_SPARC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) plt_header_size = 48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) plt_entry_size = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) case EM_SPARCV9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) plt_header_size = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) plt_entry_size = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/xtensa need to be checked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) plt_header_size = shdr_plt.sh_entsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) plt_entry_size = shdr_plt.sh_entsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) plt_offset += plt_header_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (shdr_rel_plt.sh_type == SHT_RELA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) GElf_Rela pos_mem, *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) elf_section__for_each_rela(reldata, pos, pos_mem, idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) nr_rel_entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) const char *elf_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) char *demangled = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) symidx = GELF_R_SYM(pos->r_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) gelf_getsym(syms, symidx, &sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) elf_name = elf_sym__name(&sym, symstrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) demangled = demangle_sym(dso, 0, elf_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (demangled != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) elf_name = demangled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) snprintf(sympltname, sizeof(sympltname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) "%s@plt", elf_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) free(demangled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) f = symbol__new(plt_offset, plt_entry_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) STB_GLOBAL, STT_FUNC, sympltname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (!f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) plt_offset += plt_entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) symbols__insert(&dso->symbols, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ++nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) } else if (shdr_rel_plt.sh_type == SHT_REL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) GElf_Rel pos_mem, *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) elf_section__for_each_rel(reldata, pos, pos_mem, idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) nr_rel_entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) const char *elf_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) char *demangled = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) symidx = GELF_R_SYM(pos->r_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) gelf_getsym(syms, symidx, &sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) elf_name = elf_sym__name(&sym, symstrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) demangled = demangle_sym(dso, 0, elf_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (demangled != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) elf_name = demangled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) snprintf(sympltname, sizeof(sympltname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) "%s@plt", elf_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) free(demangled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) f = symbol__new(plt_offset, plt_entry_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) STB_GLOBAL, STT_FUNC, sympltname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (!f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) plt_offset += plt_entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) symbols__insert(&dso->symbols, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) ++nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) out_elf_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (err == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) pr_debug("%s: problems reading %s PLT info.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) __func__, dso->long_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return demangle_sym(dso, kmodule, elf_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * Align offset to 4 bytes as needed for note name and descriptor data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) #define NOTE_ALIGN(n) (((n) + 3) & -4U)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static int elf_read_build_id(Elf *elf, void *bf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) GElf_Shdr shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) Elf_Data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) Elf_Scn *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) Elf_Kind ek;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) void *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (size < BUILD_ID_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ek = elf_kind(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (ek != ELF_K_ELF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (gelf_getehdr(elf, &ehdr) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) pr_err("%s: cannot get elf header.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * Check following sections for notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * '.note.gnu.build-id'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * '.notes'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * '.note' (VDSO specific)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) sec = elf_section_by_name(elf, &ehdr, &shdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ".note.gnu.build-id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) sec = elf_section_by_name(elf, &ehdr, &shdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ".notes", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) sec = elf_section_by_name(elf, &ehdr, &shdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ".note", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) } while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) data = elf_getdata(sec, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (data == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ptr = data->d_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) while (ptr < (data->d_buf + data->d_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) GElf_Nhdr *nhdr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) descsz = NOTE_ALIGN(nhdr->n_descsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ptr += sizeof(*nhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) name = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) ptr += namesz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (nhdr->n_type == NT_GNU_BUILD_ID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) nhdr->n_namesz == sizeof("GNU")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) size_t sz = min(size, descsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) memcpy(bf, ptr, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) memset(bf + sz, 0, size - sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) err = descsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ptr += descsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) #ifdef HAVE_LIBBFD_BUILDID_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) int filename__read_build_id(const char *filename, struct build_id *bid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) size_t size = sizeof(bid->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) bfd *abfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) abfd = bfd_openr(filename, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (!abfd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (!bfd_check_format(abfd, bfd_object)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (!abfd->build_id || abfd->build_id->size > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) memcpy(bid->data, abfd->build_id->data, abfd->build_id->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) memset(bid->data + abfd->build_id->size, 0, size - abfd->build_id->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) err = bid->size = abfd->build_id->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) bfd_close(abfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) #else // HAVE_LIBBFD_BUILDID_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) int filename__read_build_id(const char *filename, struct build_id *bid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) size_t size = sizeof(bid->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int fd, err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (size < BUILD_ID_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) fd = open(filename, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (elf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) err = elf_read_build_id(elf, bid->data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (err > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) bid->size = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) elf_end(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) #endif // HAVE_LIBBFD_BUILDID_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) int sysfs__read_build_id(const char *filename, struct build_id *bid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) size_t size = sizeof(bid->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) int fd, err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) fd = open(filename, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) char bf[BUFSIZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) GElf_Nhdr nhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) size_t namesz, descsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) namesz = NOTE_ALIGN(nhdr.n_namesz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) descsz = NOTE_ALIGN(nhdr.n_descsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (nhdr.n_type == NT_GNU_BUILD_ID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) nhdr.n_namesz == sizeof("GNU")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (read(fd, bf, namesz) != (ssize_t)namesz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) size_t sz = min(descsz, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (read(fd, bid->data, sz) == (ssize_t)sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) memset(bid->data + sz, 0, size - sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) bid->size = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) } else if (read(fd, bf, descsz) != (ssize_t)descsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int n = namesz + descsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (n > (int)sizeof(bf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) n = sizeof(bf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) __func__, filename, nhdr.n_namesz, nhdr.n_descsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (read(fd, bf, n) != n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) #ifdef HAVE_LIBBFD_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) int filename__read_debuglink(const char *filename, char *debuglink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) asection *section;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) bfd *abfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) abfd = bfd_openr(filename, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (!abfd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (!bfd_check_format(abfd, bfd_object)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) section = bfd_get_section_by_name(abfd, ".gnu_debuglink");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (!section)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (section->size > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (!bfd_get_section_contents(abfd, section, debuglink, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) section->size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) bfd_close(abfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) int filename__read_debuglink(const char *filename, char *debuglink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) int fd, err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) GElf_Shdr shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) Elf_Data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) Elf_Scn *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) Elf_Kind ek;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) fd = open(filename, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (elf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) ek = elf_kind(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (ek != ELF_K_ELF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (gelf_getehdr(elf, &ehdr) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) pr_err("%s: cannot get elf header.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) sec = elf_section_by_name(elf, &ehdr, &shdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ".gnu_debuglink", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (sec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) data = elf_getdata(sec, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (data == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* the start of this section is a zero-terminated string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) strncpy(debuglink, data->d_buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) out_elf_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) elf_end(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static int dso__swap_init(struct dso *dso, unsigned char eidata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static unsigned int const endian = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dso->needs_swap = DSO_SWAP__NO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) switch (eidata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) case ELFDATA2LSB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* We are big endian, DSO is little endian. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (*(unsigned char const *)&endian != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dso->needs_swap = DSO_SWAP__YES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) case ELFDATA2MSB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* We are little endian, DSO is big endian. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (*(unsigned char const *)&endian != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) dso->needs_swap = DSO_SWAP__YES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) pr_err("unrecognized DSO data encoding %d\n", eidata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) bool symsrc__possibly_runtime(struct symsrc *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return ss->dynsym || ss->opdsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) bool symsrc__has_symtab(struct symsrc *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return ss->symtab != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) void symsrc__destroy(struct symsrc *ss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) zfree(&ss->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) elf_end(ss->elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) close(ss->fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * Usually vmlinux is an ELF file with type ET_EXEC for most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * architectures; except Arm64 kernel is linked with option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * '-share', so need to check type ET_DYN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return ehdr.e_type == ET_EXEC || ehdr.e_type == ET_REL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) ehdr.e_type == ET_DYN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) enum dso_binary_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (dso__needs_decompress(dso)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) fd = dso__decompress_kmodule_fd(dso, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) type = dso->symtab_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) fd = open(name, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dso->load_errno = errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (elf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (gelf_getehdr(elf, &ehdr) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) pr_debug("%s: cannot get elf header.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) dso->load_errno = DSO_LOAD_ERRNO__INTERNAL_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /* Always reject images with a mismatched build-id: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (dso->has_build_id && !symbol_conf.ignore_vmlinux_buildid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) u8 build_id[BUILD_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct build_id bid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) size = elf_read_build_id(elf, build_id, BUILD_ID_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (size <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) dso->load_errno = DSO_LOAD_ERRNO__CANNOT_READ_BUILDID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) build_id__init(&bid, build_id, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (!dso__build_id_equal(dso, &bid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) pr_debug("%s: build id mismatch for %s.\n", __func__, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (ss->symshdr.sh_type != SHT_SYMTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) ss->symtab = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) ss->dynsym_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) ss->dynsym = elf_section_by_name(elf, &ehdr, &ss->dynshdr, ".dynsym",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) &ss->dynsym_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (ss->dynshdr.sh_type != SHT_DYNSYM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ss->dynsym = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) ss->opdidx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) ss->opdsec = elf_section_by_name(elf, &ehdr, &ss->opdshdr, ".opd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) &ss->opdidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (ss->opdshdr.sh_type != SHT_PROGBITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ss->opdsec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (dso->kernel == DSO_SPACE__USER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ss->adjust_symbols = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) ss->adjust_symbols = elf__needs_adjust_symbols(ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) ss->name = strdup(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (!ss->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) dso->load_errno = errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) ss->elf = elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) ss->fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) ss->ehdr = ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ss->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) out_elf_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) elf_end(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * ref_reloc_sym_not_found - has kernel relocation symbol been found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * @kmap: kernel maps and relocation reference symbol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * This function returns %true if we are dealing with the kernel maps and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * relocation reference symbol has not yet been found. Otherwise %false is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static bool ref_reloc_sym_not_found(struct kmap *kmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) !kmap->ref_reloc_sym->unrelocated_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * ref_reloc - kernel relocation offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * @kmap: kernel maps and relocation reference symbol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * This function returns the offset of kernel addresses as determined by using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * the relocation reference symbol i.e. if the kernel has not been relocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * then the return value is zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static u64 ref_reloc(struct kmap *kmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (kmap && kmap->ref_reloc_sym &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) kmap->ref_reloc_sym->unrelocated_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return kmap->ref_reloc_sym->addr -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) kmap->ref_reloc_sym->unrelocated_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) void __weak arch__sym_update(struct symbol *s __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) GElf_Sym *sym __maybe_unused) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) GElf_Sym *sym, GElf_Shdr *shdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) struct maps *kmaps, struct kmap *kmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) struct dso **curr_dsop, struct map **curr_mapp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) const char *section_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) bool adjust_kernel_syms, bool kmodule, bool *remap_kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct dso *curr_dso = *curr_dsop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct map *curr_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) char dso_name[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* Adjust symbol to map to file offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (adjust_kernel_syms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) sym->st_value -= shdr->sh_addr - shdr->sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (strcmp(section_name, (curr_dso->short_name + dso->short_name_len)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (strcmp(section_name, ".text") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * The initial kernel mapping is based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) * kallsyms and identity maps. Overwrite it to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * map to the kernel dso.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (*remap_kernel && dso->kernel && !kmodule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) *remap_kernel = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) map->start = shdr->sh_addr + ref_reloc(kmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) map->end = map->start + shdr->sh_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) map->pgoff = shdr->sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) map->map_ip = map__map_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) map->unmap_ip = map__unmap_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /* Ensure maps are correctly ordered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (kmaps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) map__get(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) maps__remove(kmaps, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) maps__insert(kmaps, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) map__put(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * The initial module mapping is based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * /proc/modules mapped to offset zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) * Overwrite it to map to the module dso.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (*remap_kernel && kmodule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) *remap_kernel = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) map->pgoff = shdr->sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) *curr_mapp = map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) *curr_dsop = dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (!kmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) snprintf(dso_name, sizeof(dso_name), "%s%s", dso->short_name, section_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) curr_map = maps__find_by_name(kmaps, dso_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (curr_map == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) u64 start = sym->st_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (kmodule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) start += map->start + shdr->sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) curr_dso = dso__new(dso_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (curr_dso == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) curr_dso->kernel = dso->kernel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) curr_dso->long_name = dso->long_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) curr_dso->long_name_len = dso->long_name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) curr_map = map__new2(start, curr_dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) dso__put(curr_dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (curr_map == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (curr_dso->kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) map__kmap(curr_map)->kmaps = kmaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (adjust_kernel_syms) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) curr_map->start = shdr->sh_addr + ref_reloc(kmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) curr_map->end = curr_map->start + shdr->sh_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) curr_map->pgoff = shdr->sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) curr_dso->symtab_type = dso->symtab_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) maps__insert(kmaps, curr_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * Add it before we drop the referece to curr_map, i.e. while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * we still are sure to have a reference to this DSO via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * *curr_map->dso.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) dsos__add(&kmaps->machine->dsos, curr_dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /* kmaps already got it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) map__put(curr_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) dso__set_loaded(curr_dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) *curr_mapp = curr_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) *curr_dsop = curr_dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) *curr_dsop = curr_map->dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) struct symsrc *runtime_ss, int kmodule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct maps *kmaps = kmap ? map__kmaps(map) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) struct map *curr_map = map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) struct dso *curr_dso = dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) Elf_Data *symstrs, *secstrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) uint32_t nr_syms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) uint32_t idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) GElf_Shdr shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) GElf_Shdr tshdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) Elf_Data *syms, *opddata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) GElf_Sym sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) Elf_Scn *sec, *sec_strndx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) int nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) bool remap_kernel = false, adjust_kernel_syms = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (kmap && !kmaps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) dso->symtab_type = syms_ss->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) dso->is_64_bit = syms_ss->is_64_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) dso->rel = syms_ss->ehdr.e_type == ET_REL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * Modules may already have symbols from kallsyms, but those symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * have the wrong values for the dso maps, so remove them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (kmodule && syms_ss->symtab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) symbols__delete(&dso->symbols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (!syms_ss->symtab) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * If the vmlinux is stripped, fail so we will fall back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * to using kallsyms. The vmlinux runtime symbols aren't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * of much use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (dso->kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) syms_ss->symtab = syms_ss->dynsym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) syms_ss->symshdr = syms_ss->dynshdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) elf = syms_ss->elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) ehdr = syms_ss->ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) sec = syms_ss->symtab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) shdr = syms_ss->symshdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (elf_section_by_name(runtime_ss->elf, &runtime_ss->ehdr, &tshdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) ".text", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) dso->text_offset = tshdr.sh_addr - tshdr.sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (runtime_ss->opdsec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) opddata = elf_rawdata(runtime_ss->opdsec, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) syms = elf_getdata(sec, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (syms == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) sec = elf_getscn(elf, shdr.sh_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (sec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) symstrs = elf_getdata(sec, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (symstrs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (sec_strndx == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) secstrs = elf_getdata(sec_strndx, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (secstrs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) nr_syms = shdr.sh_size / shdr.sh_entsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) memset(&sym, 0, sizeof(sym));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * The kernel relocation symbol is needed in advance in order to adjust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * kernel maps correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (ref_reloc_sym_not_found(kmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) const char *elf_name = elf_sym__name(&sym, symstrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (strcmp(elf_name, kmap->ref_reloc_sym->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) map->reloc = kmap->ref_reloc_sym->addr -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) kmap->ref_reloc_sym->unrelocated_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) * Handle any relocation of vdso necessary because older kernels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) * attempted to prelink vdso to its virtual address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (dso__is_vdso(dso))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) map->reloc = map->start - dso->text_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) dso->adjust_symbols = runtime_ss->adjust_symbols || ref_reloc(kmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * Initial kernel and module mappings do not map to the dso.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * Flag the fixups.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (dso->kernel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) remap_kernel = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) adjust_kernel_syms = dso->adjust_symbols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) struct symbol *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) const char *elf_name = elf_sym__name(&sym, symstrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) char *demangled = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) int is_label = elf_sym__is_label(&sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) const char *section_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) bool used_opd = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (!is_label && !elf_sym__filter(&sym))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) /* Reject ARM ELF "mapping symbols": these aren't unique and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * don't identify functions, so will confuse the profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * output: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (ehdr.e_machine == EM_ARM || ehdr.e_machine == EM_AARCH64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (elf_name[0] == '$' && strchr("adtx", elf_name[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) && (elf_name[2] == '\0' || elf_name[2] == '.'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (runtime_ss->opdsec && sym.st_shndx == runtime_ss->opdidx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) u32 offset = sym.st_value - syms_ss->opdshdr.sh_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) u64 *opd = opddata->d_buf + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) sym.st_value = DSO__SWAP(dso, u64, *opd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) sym.st_shndx = elf_addr_to_index(runtime_ss->elf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) sym.st_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) used_opd = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) * When loading symbols in a data mapping, ABS symbols (which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) * has a value of SHN_ABS in its st_shndx) failed at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * elf_getscn(). And it marks the loading as a failure so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * already loaded symbols cannot be fixed up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) * I'm not sure what should be done. Just ignore them for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) * - Namhyung Kim
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (sym.st_shndx == SHN_ABS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) sec = elf_getscn(runtime_ss->elf, sym.st_shndx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) gelf_getshdr(sec, &shdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (is_label && !elf_sec__filter(&shdr, secstrs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) section_name = elf_sec__name(&shdr, secstrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) /* On ARM, symbols for thumb functions have 1 added to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) * the symbol address as a flag - remove it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if ((ehdr.e_machine == EM_ARM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) (GELF_ST_TYPE(sym.st_info) == STT_FUNC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) (sym.st_value & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) --sym.st_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (dso->kernel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (dso__process_kernel_symbol(dso, map, &sym, &shdr, kmaps, kmap, &curr_dso, &curr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) section_name, adjust_kernel_syms, kmodule, &remap_kernel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) } else if ((used_opd && runtime_ss->adjust_symbols) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) (!used_opd && syms_ss->adjust_symbols)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) (u64)sym.st_value, (u64)shdr.sh_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) (u64)shdr.sh_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) sym.st_value -= shdr.sh_addr - shdr.sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) demangled = demangle_sym(dso, kmodule, elf_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (demangled != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) elf_name = demangled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) f = symbol__new(sym.st_value, sym.st_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) GELF_ST_BIND(sym.st_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) GELF_ST_TYPE(sym.st_info), elf_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) free(demangled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (!f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) goto out_elf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) arch__sym_update(f, &sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) __symbols__insert(&curr_dso->symbols, f, dso->kernel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) nr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * For misannotated, zeroed, ASM function sizes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (nr > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) symbols__fixup_end(&dso->symbols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) symbols__fixup_duplicate(&dso->symbols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (kmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) * We need to fixup this here too because we create new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) * maps here, for things like vsyscall sections.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) maps__fixup_end(kmaps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) err = nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) out_elf_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) static int elf_read_maps(Elf *elf, bool exe, mapfn_t mapfn, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) GElf_Phdr phdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) size_t i, phdrnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) u64 sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (elf_getphdrnum(elf, &phdrnum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) for (i = 0; i < phdrnum; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (gelf_getphdr(elf, i, &phdr) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (phdr.p_type != PT_LOAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (exe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (!(phdr.p_flags & PF_X))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (!(phdr.p_flags & PF_R))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) sz = min(phdr.p_memsz, phdr.p_filesz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (!sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) err = mapfn(phdr.p_vaddr, sz, phdr.p_offset, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) bool *is_64_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (elf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (is_64_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) *is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) err = elf_read_maps(elf, exe, mapfn, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) elf_end(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) enum dso_type dso__type_fd(int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) enum dso_type dso_type = DSO__TYPE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) Elf_Kind ek;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (elf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) ek = elf_kind(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (ek != ELF_K_ELF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) goto out_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (gelf_getclass(elf) == ELFCLASS64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) dso_type = DSO__TYPE_64BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) goto out_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (gelf_getehdr(elf, &ehdr) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) goto out_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (ehdr.e_machine == EM_X86_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) dso_type = DSO__TYPE_X32BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) dso_type = DSO__TYPE_32BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) out_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) elf_end(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) return dso_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) ssize_t r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) size_t n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) char *buf = malloc(page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (lseek(to, to_offs, SEEK_SET) != to_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (lseek(from, from_offs, SEEK_SET) != from_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) while (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) n = page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (len < n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) n = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) /* Use read because mmap won't work on proc files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) r = read(from, buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) n = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) r = write(to, buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if ((size_t)r != n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) len -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) free(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) struct kcore {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) int elfclass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) static int kcore__open(struct kcore *kcore, const char *filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) GElf_Ehdr *ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) kcore->fd = open(filename, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) if (kcore->fd == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) kcore->elf = elf_begin(kcore->fd, ELF_C_READ, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) if (!kcore->elf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) kcore->elfclass = gelf_getclass(kcore->elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (kcore->elfclass == ELFCLASSNONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) goto out_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (!ehdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) goto out_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) out_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) elf_end(kcore->elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) close(kcore->fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) bool temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) kcore->elfclass = elfclass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) if (temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) kcore->fd = mkstemp(filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (kcore->fd == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) kcore->elf = elf_begin(kcore->fd, ELF_C_WRITE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) if (!kcore->elf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (!gelf_newehdr(kcore->elf, elfclass))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) goto out_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) memset(&kcore->ehdr, 0, sizeof(GElf_Ehdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) out_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) elf_end(kcore->elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) close(kcore->fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) unlink(filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) static void kcore__close(struct kcore *kcore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) elf_end(kcore->elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) close(kcore->fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) GElf_Ehdr *ehdr = &to->ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) GElf_Ehdr *kehdr = &from->ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) memcpy(ehdr->e_ident, kehdr->e_ident, EI_NIDENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) ehdr->e_type = kehdr->e_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) ehdr->e_machine = kehdr->e_machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) ehdr->e_version = kehdr->e_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) ehdr->e_entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) ehdr->e_shoff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) ehdr->e_flags = kehdr->e_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) ehdr->e_phnum = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) ehdr->e_shentsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) ehdr->e_shnum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) ehdr->e_shstrndx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if (from->elfclass == ELFCLASS32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) ehdr->e_phoff = sizeof(Elf32_Ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) ehdr->e_ehsize = sizeof(Elf32_Ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) ehdr->e_phentsize = sizeof(Elf32_Phdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) ehdr->e_phoff = sizeof(Elf64_Ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) ehdr->e_ehsize = sizeof(Elf64_Ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) ehdr->e_phentsize = sizeof(Elf64_Phdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (!gelf_update_ehdr(to->elf, ehdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (!gelf_newphdr(to->elf, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) u64 addr, u64 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) GElf_Phdr phdr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) .p_type = PT_LOAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) .p_flags = PF_R | PF_W | PF_X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) .p_offset = offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) .p_vaddr = addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) .p_paddr = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) .p_filesz = len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) .p_memsz = len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) .p_align = page_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (!gelf_update_phdr(kcore->elf, idx, &phdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) static off_t kcore__write(struct kcore *kcore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return elf_update(kcore->elf, ELF_C_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) struct phdr_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) off_t offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) off_t rel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) u64 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) u64 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) struct phdr_data *remaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) struct sym_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) u64 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) struct kcore_copy_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) u64 stext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) u64 etext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) u64 first_symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) u64 last_symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) u64 first_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) u64 first_module_symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) u64 last_module_symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) size_t phnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) struct list_head phdrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) struct list_head syms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) #define kcore_copy__for_each_phdr(k, p) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) list_for_each_entry((p), &(k)->phdrs, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) static struct phdr_data *phdr_data__new(u64 addr, u64 len, off_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) struct phdr_data *p = zalloc(sizeof(*p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) p->addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) p->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) p->offset = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) static struct phdr_data *kcore_copy_info__addnew(struct kcore_copy_info *kci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) u64 addr, u64 len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) off_t offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) struct phdr_data *p = phdr_data__new(addr, len, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) list_add_tail(&p->node, &kci->phdrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) static void kcore_copy__free_phdrs(struct kcore_copy_info *kci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) struct phdr_data *p, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) list_for_each_entry_safe(p, tmp, &kci->phdrs, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) list_del_init(&p->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) free(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) static struct sym_data *kcore_copy__new_sym(struct kcore_copy_info *kci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) u64 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) struct sym_data *s = zalloc(sizeof(*s));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) if (s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) s->addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) list_add_tail(&s->node, &kci->syms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) static void kcore_copy__free_syms(struct kcore_copy_info *kci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) struct sym_data *s, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) list_for_each_entry_safe(s, tmp, &kci->syms, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) list_del_init(&s->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) free(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) static int kcore_copy__process_kallsyms(void *arg, const char *name, char type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) u64 start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) struct kcore_copy_info *kci = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) if (!kallsyms__is_function(type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (strchr(name, '[')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) if (!kci->first_module_symbol || start < kci->first_module_symbol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) kci->first_module_symbol = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) if (start > kci->last_module_symbol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) kci->last_module_symbol = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (!kci->first_symbol || start < kci->first_symbol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) kci->first_symbol = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) if (!kci->last_symbol || start > kci->last_symbol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) kci->last_symbol = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) if (!strcmp(name, "_stext")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) kci->stext = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (!strcmp(name, "_etext")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) kci->etext = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) if (is_entry_trampoline(name) && !kcore_copy__new_sym(kci, start))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) const char *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) char kallsyms_filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) scnprintf(kallsyms_filename, PATH_MAX, "%s/kallsyms", dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (symbol__restricted_filename(kallsyms_filename, "/proc/kallsyms"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) if (kallsyms__parse(kallsyms_filename, kci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) kcore_copy__process_kallsyms) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) static int kcore_copy__process_modules(void *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) const char *name __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) u64 start, u64 size __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) struct kcore_copy_info *kci = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) if (!kci->first_module || start < kci->first_module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) kci->first_module = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) static int kcore_copy__parse_modules(struct kcore_copy_info *kci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) const char *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) char modules_filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) scnprintf(modules_filename, PATH_MAX, "%s/modules", dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (symbol__restricted_filename(modules_filename, "/proc/modules"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) if (modules__parse(modules_filename, kci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) kcore_copy__process_modules) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) static int kcore_copy__map(struct kcore_copy_info *kci, u64 start, u64 end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) u64 pgoff, u64 s, u64 e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) u64 len, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) if (s < start || s >= end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) offset = (s - start) + pgoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) len = e < end ? e - s : end - s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) return kcore_copy_info__addnew(kci, s, len, offset) ? 0 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) struct kcore_copy_info *kci = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) u64 end = start + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) struct sym_data *sdat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) if (kcore_copy__map(kci, start, end, pgoff, kci->stext, kci->etext))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (kcore_copy__map(kci, start, end, pgoff, kci->first_module,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) kci->last_module_symbol))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) list_for_each_entry(sdat, &kci->syms, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) u64 s = round_down(sdat->addr, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) if (kcore_copy__map(kci, start, end, pgoff, s, s + len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) static int kcore_copy__read_maps(struct kcore_copy_info *kci, Elf *elf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) if (elf_read_maps(elf, true, kcore_copy__read_map, kci) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) static void kcore_copy__find_remaps(struct kcore_copy_info *kci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) struct phdr_data *p, *k = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) u64 kend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) if (!kci->stext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) /* Find phdr that corresponds to the kernel map (contains stext) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) kcore_copy__for_each_phdr(kci, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) u64 pend = p->addr + p->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) if (p->addr <= kci->stext && pend >= kci->stext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) k = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (!k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) kend = k->offset + k->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) /* Find phdrs that remap the kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) kcore_copy__for_each_phdr(kci, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) u64 pend = p->offset + p->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) if (p == k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if (p->offset >= k->offset && pend <= kend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) p->remaps = k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) static void kcore_copy__layout(struct kcore_copy_info *kci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) struct phdr_data *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) off_t rel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) kcore_copy__find_remaps(kci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) kcore_copy__for_each_phdr(kci, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) if (!p->remaps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) p->rel = rel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) rel += p->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) kci->phnum += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) kcore_copy__for_each_phdr(kci, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) struct phdr_data *k = p->remaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) p->rel = p->offset - k->offset + k->rel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) Elf *elf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) if (kcore_copy__parse_kallsyms(kci, dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) if (kcore_copy__parse_modules(kci, dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) if (kci->stext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) kci->stext = round_down(kci->stext, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) kci->stext = round_down(kci->first_symbol, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) if (kci->etext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) kci->etext = round_up(kci->etext, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) } else if (kci->last_symbol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) kci->etext = round_up(kci->last_symbol, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) kci->etext += page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) if (kci->first_module_symbol &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) (!kci->first_module || kci->first_module_symbol < kci->first_module))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) kci->first_module = kci->first_module_symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) kci->first_module = round_down(kci->first_module, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) if (kci->last_module_symbol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) kci->last_module_symbol = round_up(kci->last_module_symbol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) kci->last_module_symbol += page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) if (!kci->stext || !kci->etext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) if (kci->first_module && !kci->last_module_symbol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (kcore_copy__read_maps(kci, elf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) kcore_copy__layout(kci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) static int kcore_copy__copy_file(const char *from_dir, const char *to_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) char from_filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) char to_filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) return copyfile_mode(from_filename, to_filename, 0400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) static int kcore_copy__unlink(const char *dir, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) char filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) scnprintf(filename, PATH_MAX, "%s/%s", dir, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) return unlink(filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) static int kcore_copy__compare_fds(int from, int to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) char *buf_from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) char *buf_to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) int err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) buf_from = malloc(page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) buf_to = malloc(page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) if (!buf_from || !buf_to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) /* Use read because mmap won't work on proc files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) ret = read(from, buf_from, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) len = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) if (readn(to, buf_to, len) != (int)len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) if (memcmp(buf_from, buf_to, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) free(buf_to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) free(buf_from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) static int kcore_copy__compare_files(const char *from_filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) const char *to_filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) int from, to, err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) from = open(from_filename, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) if (from < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) to = open(to_filename, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) if (to < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) goto out_close_from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) err = kcore_copy__compare_fds(from, to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) close(to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) out_close_from:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) close(from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) static int kcore_copy__compare_file(const char *from_dir, const char *to_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) char from_filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) char to_filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) return kcore_copy__compare_files(from_filename, to_filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) * kcore_copy - copy kallsyms, modules and kcore from one directory to another.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) * @from_dir: from directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) * @to_dir: to directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) * This function copies kallsyms, modules and kcore files from one directory to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) * another. kallsyms and modules are copied entirely. Only code segments are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) * copied from kcore. It is assumed that two segments suffice: one for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) * kernel proper and one for all the modules. The code segments are determined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) * from kallsyms and modules files. The kernel map starts at _stext or the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) * lowest function symbol, and ends at _etext or the highest function symbol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) * The module map starts at the lowest module address and ends at the highest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) * module symbol. Start addresses are rounded down to the nearest page. End
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) * addresses are rounded up to the nearest page. An extra page is added to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) * highest kernel symbol and highest module symbol to, hopefully, encompass that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) * symbol too. Because it contains only code sections, the resulting kcore is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) * unusual. One significant peculiarity is that the mapping (start -> pgoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) * is not the same for the kernel map and the modules map. That happens because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) * the data is copied adjacently whereas the original kcore has gaps. Finally,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) * kallsyms and modules files are compared with their copies to check that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) * modules have not been loaded or unloaded while the copies were taking place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) * Return: %0 on success, %-1 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) int kcore_copy(const char *from_dir, const char *to_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) struct kcore kcore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) struct kcore extract;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) int idx = 0, err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) off_t offset, sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) struct kcore_copy_info kci = { .stext = 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) char kcore_filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) char extract_filename[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) struct phdr_data *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) INIT_LIST_HEAD(&kci.phdrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) INIT_LIST_HEAD(&kci.syms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) if (kcore_copy__copy_file(from_dir, to_dir, "modules"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) goto out_unlink_kallsyms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) scnprintf(kcore_filename, PATH_MAX, "%s/kcore", from_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) scnprintf(extract_filename, PATH_MAX, "%s/kcore", to_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) if (kcore__open(&kcore, kcore_filename))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) goto out_unlink_modules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) if (kcore_copy__calc_maps(&kci, from_dir, kcore.elf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) goto out_kcore_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) if (kcore__init(&extract, extract_filename, kcore.elfclass, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) goto out_kcore_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) if (kcore__copy_hdr(&kcore, &extract, kci.phnum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) offset = gelf_fsize(extract.elf, ELF_T_EHDR, 1, EV_CURRENT) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) gelf_fsize(extract.elf, ELF_T_PHDR, kci.phnum, EV_CURRENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) offset = round_up(offset, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) kcore_copy__for_each_phdr(&kci, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) off_t offs = p->rel + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) if (kcore__add_phdr(&extract, idx++, offs, p->addr, p->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) sz = kcore__write(&extract);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) if (sz < 0 || sz > offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) kcore_copy__for_each_phdr(&kci, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) off_t offs = p->rel + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) if (p->remaps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) if (copy_bytes(kcore.fd, p->offset, extract.fd, offs, p->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) out_extract_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) kcore__close(&extract);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) unlink(extract_filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) out_kcore_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) kcore__close(&kcore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) out_unlink_modules:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) kcore_copy__unlink(to_dir, "modules");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) out_unlink_kallsyms:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) kcore_copy__unlink(to_dir, "kallsyms");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) kcore_copy__free_phdrs(&kci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) kcore_copy__free_syms(&kci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) int kcore_extract__create(struct kcore_extract *kce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) struct kcore kcore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) struct kcore extract;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) size_t count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) int idx = 0, err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) off_t offset = page_size, sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) if (kcore__open(&kcore, kce->kcore_filename))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) strcpy(kce->extract_filename, PERF_KCORE_EXTRACT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) if (kcore__init(&extract, kce->extract_filename, kcore.elfclass, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) goto out_kcore_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) if (kcore__copy_hdr(&kcore, &extract, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) if (kcore__add_phdr(&extract, idx, offset, kce->addr, kce->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) sz = kcore__write(&extract);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) if (sz < 0 || sz > offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) if (copy_bytes(kcore.fd, kce->offs, extract.fd, offset, kce->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) goto out_extract_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) out_extract_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) kcore__close(&extract);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) unlink(kce->extract_filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) out_kcore_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) kcore__close(&kcore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) void kcore_extract__delete(struct kcore_extract *kce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) unlink(kce->extract_filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) #ifdef HAVE_GELF_GETNOTE_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) static void sdt_adjust_loc(struct sdt_note *tmp, GElf_Addr base_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) if (!base_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) if (tmp->bit32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) tmp->addr.a32[SDT_NOTE_IDX_LOC] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) tmp->addr.a32[SDT_NOTE_IDX_LOC] + base_off -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) tmp->addr.a32[SDT_NOTE_IDX_BASE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) tmp->addr.a64[SDT_NOTE_IDX_LOC] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) tmp->addr.a64[SDT_NOTE_IDX_LOC] + base_off -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) tmp->addr.a64[SDT_NOTE_IDX_BASE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) static void sdt_adjust_refctr(struct sdt_note *tmp, GElf_Addr base_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) GElf_Addr base_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) if (!base_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) if (tmp->bit32 && tmp->addr.a32[SDT_NOTE_IDX_REFCTR])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) tmp->addr.a32[SDT_NOTE_IDX_REFCTR] -= (base_addr - base_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) else if (tmp->addr.a64[SDT_NOTE_IDX_REFCTR])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) tmp->addr.a64[SDT_NOTE_IDX_REFCTR] -= (base_addr - base_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) * populate_sdt_note : Parse raw data and identify SDT note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) * @elf: elf of the opened file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) * @data: raw data of a section with description offset applied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) * @len: note description size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) * @type: type of the note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) * @sdt_notes: List to add the SDT note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) * Responsible for parsing the @data in section .note.stapsdt in @elf and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) * if its an SDT note, it appends to @sdt_notes list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) static int populate_sdt_note(Elf **elf, const char *data, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) struct list_head *sdt_notes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) const char *provider, *name, *args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) struct sdt_note *tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) GElf_Shdr shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) Elf64_Addr a64[NR_ADDR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) Elf32_Addr a32[NR_ADDR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) } buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) Elf_Data dst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) .d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) .d_size = gelf_fsize((*elf), ELF_T_ADDR, NR_ADDR, EV_CURRENT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) .d_off = 0, .d_align = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) Elf_Data src = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) .d_buf = (void *) data, .d_type = ELF_T_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) .d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) .d_align = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) tmp = (struct sdt_note *)calloc(1, sizeof(struct sdt_note));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) if (!tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) INIT_LIST_HEAD(&tmp->note_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) if (len < dst.d_size + 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) goto out_free_note;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) /* Translation from file representation to memory representation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) if (gelf_xlatetom(*elf, &dst, &src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) elf_getident(*elf, NULL)[EI_DATA]) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) pr_err("gelf_xlatetom : %s\n", elf_errmsg(-1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) goto out_free_note;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) /* Populate the fields of sdt_note */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) provider = data + dst.d_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) name = (const char *)memchr(provider, '\0', data + len - provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) if (name++ == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) goto out_free_note;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) tmp->provider = strdup(provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) if (!tmp->provider) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) goto out_free_note;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) tmp->name = strdup(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) if (!tmp->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) goto out_free_prov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) args = memchr(name, '\0', data + len - name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) * There is no argument if:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) * - We reached the end of the note;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) * - There is not enough room to hold a potential string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) * - The argument string is empty or just contains ':'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) if (args == NULL || data + len - args < 2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) args[1] == ':' || args[1] == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) tmp->args = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) tmp->args = strdup(++args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) if (!tmp->args) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) goto out_free_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) if (gelf_getclass(*elf) == ELFCLASS32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) tmp->bit32 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) memcpy(&tmp->addr, &buf, 3 * sizeof(Elf64_Addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) tmp->bit32 = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) if (!gelf_getehdr(*elf, &ehdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) pr_debug("%s : cannot get elf header.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) goto out_free_args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) /* Adjust the prelink effect :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) * Find out the .stapsdt.base section.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) * This scn will help us to handle prelinking (if present).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) * Compare the retrieved file offset of the base section with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) * base address in the description of the SDT note. If its different,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) * then accordingly, adjust the note location.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) sdt_adjust_loc(tmp, shdr.sh_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) /* Adjust reference counter offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_PROBES_SCN, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) sdt_adjust_refctr(tmp, shdr.sh_addr, shdr.sh_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) list_add_tail(&tmp->note_list, sdt_notes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) out_free_args:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) zfree(&tmp->args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) out_free_name:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) zfree(&tmp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) out_free_prov:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) zfree(&tmp->provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) out_free_note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) * construct_sdt_notes_list : constructs a list of SDT notes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) * @elf : elf to look into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) * @sdt_notes : empty list_head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) * Scans the sections in 'elf' for the section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) * .note.stapsdt. It, then calls populate_sdt_note to find
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) * out the SDT events and populates the 'sdt_notes'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) static int construct_sdt_notes_list(Elf *elf, struct list_head *sdt_notes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) GElf_Ehdr ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) Elf_Scn *scn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) Elf_Data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) GElf_Shdr shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) size_t shstrndx, next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) GElf_Nhdr nhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) size_t name_off, desc_off, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) if (gelf_getehdr(elf, &ehdr) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) goto out_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) goto out_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) /* Look for the required section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) scn = elf_section_by_name(elf, &ehdr, &shdr, SDT_NOTE_SCN, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) if (!scn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) goto out_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) if ((shdr.sh_type != SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) goto out_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) data = elf_getdata(scn, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) /* Get the SDT notes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) for (offset = 0; (next = gelf_getnote(data, offset, &nhdr, &name_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) &desc_off)) > 0; offset = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) if (nhdr.n_namesz == sizeof(SDT_NOTE_NAME) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) !memcmp(data->d_buf + name_off, SDT_NOTE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) sizeof(SDT_NOTE_NAME))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) /* Check the type of the note */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) if (nhdr.n_type != SDT_NOTE_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) goto out_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) ret = populate_sdt_note(&elf, ((data->d_buf) + desc_off),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) nhdr.n_descsz, sdt_notes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) goto out_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) if (list_empty(sdt_notes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) out_ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) * get_sdt_note_list : Wrapper to construct a list of sdt notes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) * @head : empty list_head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) * @target : file to find SDT notes from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) * This opens the file, initializes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) * the ELF and then calls construct_sdt_notes_list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) int get_sdt_note_list(struct list_head *head, const char *target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) Elf *elf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) int fd, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) fd = open(target, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) return -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) if (!elf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) ret = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) ret = construct_sdt_notes_list(elf, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) elf_end(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) * cleanup_sdt_note_list : free the sdt notes' list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) * @sdt_notes: sdt notes' list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) * Free up the SDT notes in @sdt_notes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) * Returns the number of SDT notes free'd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) int cleanup_sdt_note_list(struct list_head *sdt_notes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) struct sdt_note *tmp, *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) int nr_free = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) list_del_init(&pos->note_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) zfree(&pos->args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) zfree(&pos->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) zfree(&pos->provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) free(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) nr_free++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) return nr_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) * sdt_notes__get_count: Counts the number of sdt events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) * @start: list_head to sdt_notes list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) * Returns the number of SDT notes in a list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) int sdt_notes__get_count(struct list_head *start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) struct sdt_note *sdt_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) list_for_each_entry(sdt_ptr, start, note_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) void symbol__elf_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) elf_version(EV_CURRENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) }