diff options
Diffstat (limited to 'arch/mips/vdso/genvdso.h')
-rw-r--r-- | arch/mips/vdso/genvdso.h | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/arch/mips/vdso/genvdso.h b/arch/mips/vdso/genvdso.h new file mode 100644 index 000000000..9bfb87403 --- /dev/null +++ b/arch/mips/vdso/genvdso.h | |||
@@ -0,0 +1,132 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
2 | /* | ||
3 | * Copyright (C) 2015 Imagination Technologies | ||
4 | * Author: Alex Smith <alex.smith@imgtec.com> | ||
5 | */ | ||
6 | |||
7 | static inline bool FUNC(patch_vdso)(const char *path, void *vdso) | ||
8 | { | ||
9 | const ELF(Ehdr) *ehdr = vdso; | ||
10 | void *shdrs; | ||
11 | ELF(Shdr) *shdr; | ||
12 | char *shstrtab, *name; | ||
13 | uint16_t sh_count, sh_entsize, i; | ||
14 | |||
15 | shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff); | ||
16 | sh_count = swap_uint16(ehdr->e_shnum); | ||
17 | sh_entsize = swap_uint16(ehdr->e_shentsize); | ||
18 | |||
19 | shdr = shdrs + (sh_entsize * swap_uint16(ehdr->e_shstrndx)); | ||
20 | shstrtab = vdso + FUNC(swap_uint)(shdr->sh_offset); | ||
21 | |||
22 | for (i = 0; i < sh_count; i++) { | ||
23 | shdr = shdrs + (i * sh_entsize); | ||
24 | name = shstrtab + swap_uint32(shdr->sh_name); | ||
25 | |||
26 | /* | ||
27 | * Ensure there are no relocation sections - ld.so does not | ||
28 | * relocate the VDSO so if there are relocations things will | ||
29 | * break. | ||
30 | */ | ||
31 | switch (swap_uint32(shdr->sh_type)) { | ||
32 | case SHT_REL: | ||
33 | case SHT_RELA: | ||
34 | fprintf(stderr, | ||
35 | "%s: '%s' contains relocation sections\n", | ||
36 | program_name, path); | ||
37 | return false; | ||
38 | } | ||
39 | |||
40 | /* Check for existing sections. */ | ||
41 | if (strcmp(name, ".MIPS.abiflags") == 0) { | ||
42 | fprintf(stderr, | ||
43 | "%s: '%s' already contains a '.MIPS.abiflags' section\n", | ||
44 | program_name, path); | ||
45 | return false; | ||
46 | } | ||
47 | |||
48 | if (strcmp(name, ".mips_abiflags") == 0) { | ||
49 | strcpy(name, ".MIPS.abiflags"); | ||
50 | shdr->sh_type = swap_uint32(SHT_MIPS_ABIFLAGS); | ||
51 | shdr->sh_entsize = shdr->sh_size; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return true; | ||
56 | } | ||
57 | |||
58 | static inline bool FUNC(get_symbols)(const char *path, void *vdso) | ||
59 | { | ||
60 | const ELF(Ehdr) *ehdr = vdso; | ||
61 | void *shdrs, *symtab; | ||
62 | ELF(Shdr) *shdr; | ||
63 | const ELF(Sym) *sym; | ||
64 | char *strtab, *name; | ||
65 | uint16_t sh_count, sh_entsize, st_count, st_entsize, i, j; | ||
66 | uint64_t offset; | ||
67 | uint32_t flags; | ||
68 | |||
69 | shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff); | ||
70 | sh_count = swap_uint16(ehdr->e_shnum); | ||
71 | sh_entsize = swap_uint16(ehdr->e_shentsize); | ||
72 | |||
73 | for (i = 0; i < sh_count; i++) { | ||
74 | shdr = shdrs + (i * sh_entsize); | ||
75 | |||
76 | if (swap_uint32(shdr->sh_type) == SHT_SYMTAB) | ||
77 | break; | ||
78 | } | ||
79 | |||
80 | if (i == sh_count) { | ||
81 | fprintf(stderr, "%s: '%s' has no symbol table\n", program_name, | ||
82 | path); | ||
83 | return false; | ||
84 | } | ||
85 | |||
86 | /* Get flags */ | ||
87 | flags = swap_uint32(ehdr->e_flags); | ||
88 | if (elf_class == ELFCLASS64) | ||
89 | elf_abi = ABI_N64; | ||
90 | else if (flags & EF_MIPS_ABI2) | ||
91 | elf_abi = ABI_N32; | ||
92 | else | ||
93 | elf_abi = ABI_O32; | ||
94 | |||
95 | /* Get symbol table. */ | ||
96 | symtab = vdso + FUNC(swap_uint)(shdr->sh_offset); | ||
97 | st_entsize = FUNC(swap_uint)(shdr->sh_entsize); | ||
98 | st_count = FUNC(swap_uint)(shdr->sh_size) / st_entsize; | ||
99 | |||
100 | /* Get string table. */ | ||
101 | shdr = shdrs + (swap_uint32(shdr->sh_link) * sh_entsize); | ||
102 | strtab = vdso + FUNC(swap_uint)(shdr->sh_offset); | ||
103 | |||
104 | /* Write offsets for symbols needed by the kernel. */ | ||
105 | for (i = 0; vdso_symbols[i].name; i++) { | ||
106 | if (!(vdso_symbols[i].abis & elf_abi)) | ||
107 | continue; | ||
108 | |||
109 | for (j = 0; j < st_count; j++) { | ||
110 | sym = symtab + (j * st_entsize); | ||
111 | name = strtab + swap_uint32(sym->st_name); | ||
112 | |||
113 | if (!strcmp(name, vdso_symbols[i].name)) { | ||
114 | offset = FUNC(swap_uint)(sym->st_value); | ||
115 | |||
116 | fprintf(out_file, | ||
117 | "\t.%s = 0x%" PRIx64 ",\n", | ||
118 | vdso_symbols[i].offset_name, offset); | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | if (j == st_count) { | ||
124 | fprintf(stderr, | ||
125 | "%s: '%s' is missing required symbol '%s'\n", | ||
126 | program_name, path, vdso_symbols[i].name); | ||
127 | return false; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return true; | ||
132 | } | ||