1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/types.h> 3 #include <linux/string.h> 4 #include <stdlib.h> 5 6 #include "../../util/util.h" 7 #include "../../util/machine.h" 8 #include "../../util/map.h" 9 #include "../../util/symbol.h" 10 #include <linux/ctype.h> 11 12 #include <symbol/kallsyms.h> 13 14 #if defined(__x86_64__) 15 16 struct extra_kernel_map_info { 17 int cnt; 18 int max_cnt; 19 struct extra_kernel_map *maps; 20 bool get_entry_trampolines; 21 u64 entry_trampoline; 22 }; 23 24 static int add_extra_kernel_map(struct extra_kernel_map_info *mi, u64 start, 25 u64 end, u64 pgoff, const char *name) 26 { 27 if (mi->cnt >= mi->max_cnt) { 28 void *buf; 29 size_t sz; 30 31 mi->max_cnt = mi->max_cnt ? mi->max_cnt * 2 : 32; 32 sz = sizeof(struct extra_kernel_map) * mi->max_cnt; 33 buf = realloc(mi->maps, sz); 34 if (!buf) 35 return -1; 36 mi->maps = buf; 37 } 38 39 mi->maps[mi->cnt].start = start; 40 mi->maps[mi->cnt].end = end; 41 mi->maps[mi->cnt].pgoff = pgoff; 42 strlcpy(mi->maps[mi->cnt].name, name, KMAP_NAME_LEN); 43 44 mi->cnt += 1; 45 46 return 0; 47 } 48 49 static int find_extra_kernel_maps(void *arg, const char *name, char type, 50 u64 start) 51 { 52 struct extra_kernel_map_info *mi = arg; 53 54 if (!mi->entry_trampoline && kallsyms2elf_binding(type) == STB_GLOBAL && 55 !strcmp(name, "_entry_trampoline")) { 56 mi->entry_trampoline = start; 57 return 0; 58 } 59 60 if (is_entry_trampoline(name)) { 61 u64 end = start + page_size; 62 63 return add_extra_kernel_map(mi, start, end, 0, name); 64 } 65 66 return 0; 67 } 68 69 int machine__create_extra_kernel_maps(struct machine *machine, 70 struct dso *kernel) 71 { 72 struct extra_kernel_map_info mi = { .cnt = 0, }; 73 char filename[PATH_MAX]; 74 int ret; 75 int i; 76 77 machine__get_kallsyms_filename(machine, filename, PATH_MAX); 78 79 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 80 return 0; 81 82 ret = kallsyms__parse(filename, &mi, find_extra_kernel_maps); 83 if (ret) 84 goto out_free; 85 86 if (!mi.entry_trampoline) 87 goto out_free; 88 89 for (i = 0; i < mi.cnt; i++) { 90 struct extra_kernel_map *xm = &mi.maps[i]; 91 92 xm->pgoff = mi.entry_trampoline; 93 ret = machine__create_extra_kernel_map(machine, kernel, xm); 94 if (ret) 95 goto out_free; 96 } 97 98 machine->trampolines_mapped = mi.cnt; 99 out_free: 100 free(mi.maps); 101 return ret; 102 } 103 104 #endif 105