Merge tag 'drm-misc-fixes-2019-06-05' of git://anongit.freedesktop.org/drm/drm-misc...
[sfrench/cifs-2.6.git] / arch / mips / vdso / genvdso.h
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 }