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