1
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
16struct 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
24static 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
49static 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
69int 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;
99out_free:
100 free(mi.maps);
101 return ret;
102}
103
104#endif
105