| @@ -1,1145 +1,1086 @@ | | | @@ -1,1145 +1,1086 @@ |
1 | /* $NetBSD: subr_kobj.c,v 1.35 2009/05/23 15:13:57 ad Exp $ */ | | 1 | /* $NetBSD: subr_kobj.c,v 1.36 2009/05/24 15:00:24 ad Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software developed for The NetBSD Foundation | | 7 | * This code is derived from software developed for The NetBSD Foundation |
8 | * by Andrew Doran. | | 8 | * by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /*- | | 32 | /*- |
33 | * Copyright (c) 1998-2000 Doug Rabson | | 33 | * Copyright (c) 1998-2000 Doug Rabson |
34 | * Copyright (c) 2004 Peter Wemm | | 34 | * Copyright (c) 2004 Peter Wemm |
35 | * All rights reserved. | | 35 | * All rights reserved. |
36 | * | | 36 | * |
37 | * Redistribution and use in source and binary forms, with or without | | 37 | * Redistribution and use in source and binary forms, with or without |
38 | * modification, are permitted provided that the following conditions | | 38 | * modification, are permitted provided that the following conditions |
39 | * are met: | | 39 | * are met: |
40 | * 1. Redistributions of source code must retain the above copyright | | 40 | * 1. Redistributions of source code must retain the above copyright |
41 | * notice, this list of conditions and the following disclaimer. | | 41 | * notice, this list of conditions and the following disclaimer. |
42 | * 2. Redistributions in binary form must reproduce the above copyright | | 42 | * 2. Redistributions in binary form must reproduce the above copyright |
43 | * notice, this list of conditions and the following disclaimer in the | | 43 | * notice, this list of conditions and the following disclaimer in the |
44 | * documentation and/or other materials provided with the distribution. | | 44 | * documentation and/or other materials provided with the distribution. |
45 | * | | 45 | * |
46 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | | 46 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
47 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 47 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
48 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 48 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
49 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 49 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
50 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 50 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
51 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 51 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
52 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 52 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
53 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 53 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
54 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 54 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
55 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 55 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
56 | * SUCH DAMAGE. | | 56 | * SUCH DAMAGE. |
57 | */ | | 57 | */ |
58 | | | 58 | |
59 | /* | | 59 | /* |
60 | * Kernel loader for ELF objects. | | 60 | * Kernel loader for ELF objects. |
61 | * | | 61 | * |
62 | * TODO: adjust kmem_alloc() calls to avoid needless fragmentation. | | 62 | * TODO: adjust kmem_alloc() calls to avoid needless fragmentation. |
63 | */ | | 63 | */ |
64 | | | 64 | |
65 | #include <sys/cdefs.h> | | 65 | #include <sys/cdefs.h> |
66 | __KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.35 2009/05/23 15:13:57 ad Exp $"); | | 66 | __KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.36 2009/05/24 15:00:24 ad Exp $"); |
67 | | | 67 | |
68 | #include "opt_modular.h" | | 68 | #include "opt_modular.h" |
69 | | | 69 | |
70 | #define ELFSIZE ARCH_ELFSIZE | | 70 | #include <sys/kobj_impl.h> |
71 | | | | |
72 | #include <sys/systm.h> | | | |
73 | #include <sys/kobj.h> | | | |
74 | #include <sys/errno.h> | | | |
75 | | | 71 | |
76 | #ifdef MODULAR | | 72 | #ifdef MODULAR |
77 | | | 73 | |
78 | #include <sys/param.h> | | 74 | #include <sys/param.h> |
79 | #include <sys/kernel.h> | | 75 | #include <sys/kernel.h> |
80 | #include <sys/kmem.h> | | 76 | #include <sys/kmem.h> |
81 | #include <sys/proc.h> | | 77 | #include <sys/proc.h> |
82 | #include <sys/namei.h> | | 78 | #include <sys/namei.h> |
83 | #include <sys/vnode.h> | | 79 | #include <sys/vnode.h> |
84 | #include <sys/fcntl.h> | | 80 | #include <sys/fcntl.h> |
85 | #include <sys/ksyms.h> | | 81 | #include <sys/ksyms.h> |
86 | #include <sys/module.h> | | 82 | #include <sys/module.h> |
87 | #include <sys/exec.h> | | | |
88 | #include <sys/exec_elf.h> | | | |
89 | | | 83 | |
90 | #include <machine/stdarg.h> | | 84 | #include <machine/stdarg.h> |
91 | | | 85 | |
92 | #include <uvm/uvm_extern.h> | | 86 | #include <uvm/uvm_extern.h> |
93 | | | 87 | |
94 | typedef struct { | | | |
95 | void *addr; | | | |
96 | Elf_Off size; | | | |
97 | int flags; | | | |
98 | int sec; /* Original section */ | | | |
99 | const char *name; | | | |
100 | } progent_t; | | | |
101 | | | | |
102 | typedef struct { | | | |
103 | Elf_Rel *rel; | | | |
104 | int nrel; | | | |
105 | int sec; | | | |
106 | size_t size; | | | |
107 | } relent_t; | | | |
108 | | | | |
109 | typedef struct { | | | |
110 | Elf_Rela *rela; | | | |
111 | int nrela; | | | |
112 | int sec; | | | |
113 | size_t size; | | | |
114 | } relaent_t; | | | |
115 | | | | |
116 | typedef enum kobjtype { | | | |
117 | KT_UNSET, | | | |
118 | KT_VNODE, | | | |
119 | KT_MEMORY | | | |
120 | } kobjtype_t; | | | |
121 | | | | |
122 | struct kobj { | | | |
123 | char ko_name[MAXMODNAME]; | | | |
124 | kobjtype_t ko_type; | | | |
125 | void *ko_source; | | | |
126 | ssize_t ko_memsize; | | | |
127 | vaddr_t ko_address; /* Relocation address */ | | | |
128 | Elf_Shdr *ko_shdr; | | | |
129 | progent_t *ko_progtab; | | | |
130 | relaent_t *ko_relatab; | | | |
131 | relent_t *ko_reltab; | | | |
132 | Elf_Sym *ko_symtab; /* Symbol table */ | | | |
133 | char *ko_strtab; /* String table */ | | | |
134 | char *ko_shstrtab; /* Section name string table */ | | | |
135 | size_t ko_size; /* Size of text/data/bss */ | | | |
136 | size_t ko_symcnt; /* Number of symbols */ | | | |
137 | size_t ko_strtabsz; /* Number of bytes in string table */ | | | |
138 | size_t ko_shstrtabsz; /* Number of bytes in scn str table */ | | | |
139 | size_t ko_shdrsz; | | | |
140 | int ko_nrel; | | | |
141 | int ko_nrela; | | | |
142 | int ko_nprogtab; | | | |
143 | bool ko_ksyms; | | | |
144 | bool ko_loaded; | | | |
145 | }; | | | |
146 | | | | |
147 | static int kobj_relocate(kobj_t, bool); | | 88 | static int kobj_relocate(kobj_t, bool); |
148 | static int kobj_checksyms(kobj_t, bool); | | 89 | static int kobj_checksyms(kobj_t, bool); |
149 | static void kobj_error(const char *, ...); | | 90 | static void kobj_error(const char *, ...); |
150 | static int kobj_read(kobj_t, void **, size_t, off_t); | | 91 | static int kobj_read(kobj_t, void **, size_t, off_t); |
151 | static int kobj_read_bits(kobj_t, void *, size_t, off_t); | | 92 | static int kobj_read_bits(kobj_t, void *, size_t, off_t); |
152 | static void kobj_jettison(kobj_t); | | 93 | static void kobj_jettison(kobj_t); |
153 | static void kobj_free(kobj_t, void *, size_t); | | 94 | static void kobj_free(kobj_t, void *, size_t); |
154 | static void kobj_close(kobj_t); | | 95 | static void kobj_close(kobj_t); |
155 | static int kobj_load(kobj_t); | | 96 | static int kobj_load(kobj_t); |
156 | | | 97 | |
157 | extern struct vm_map *module_map; | | 98 | extern struct vm_map *module_map; |
158 | | | 99 | |
159 | /* | | 100 | /* |
160 | * kobj_load_file: | | 101 | * kobj_load_file: |
161 | * | | 102 | * |
162 | * Load an object located in the file system. | | 103 | * Load an object located in the file system. |
163 | */ | | 104 | */ |
164 | int | | 105 | int |
165 | kobj_load_file(kobj_t *kop, const char *filename, const char *base, | | 106 | kobj_load_file(kobj_t *kop, const char *filename, const char *base, |
166 | bool autoload) | | 107 | bool autoload) |
167 | { | | 108 | { |
168 | struct nameidata nd; | | 109 | struct nameidata nd; |
169 | kauth_cred_t cred; | | 110 | kauth_cred_t cred; |
170 | char *path; | | 111 | char *path; |
171 | int error; | | 112 | int error; |
172 | kobj_t ko; | | 113 | kobj_t ko; |
173 | | | 114 | |
174 | cred = kauth_cred_get(); | | 115 | cred = kauth_cred_get(); |
175 | | | 116 | |
176 | ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); | | 117 | ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); |
177 | if (ko == NULL) { | | 118 | if (ko == NULL) { |
178 | return ENOMEM; | | 119 | return ENOMEM; |
179 | } | | 120 | } |
180 | | | 121 | |
181 | if (autoload) { | | 122 | if (autoload) { |
182 | error = ENOENT; | | 123 | error = ENOENT; |
183 | } else { | | 124 | } else { |
184 | NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename); | | 125 | NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename); |
185 | error = vn_open(&nd, FREAD, 0); | | 126 | error = vn_open(&nd, FREAD, 0); |
186 | } | | 127 | } |
187 | if (error != 0) { | | 128 | if (error != 0) { |
188 | if (error != ENOENT) { | | 129 | if (error != ENOENT) { |
189 | goto out; | | 130 | goto out; |
190 | } | | 131 | } |
191 | path = PNBUF_GET(); | | 132 | path = PNBUF_GET(); |
192 | snprintf(path, MAXPATHLEN - 1, "%s/%s/%s.kmod", base, | | 133 | snprintf(path, MAXPATHLEN - 1, "%s/%s/%s.kmod", base, |
193 | filename, filename); | | 134 | filename, filename); |
194 | NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, UIO_SYSSPACE, path); | | 135 | NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, UIO_SYSSPACE, path); |
195 | error = vn_open(&nd, FREAD, 0); | | 136 | error = vn_open(&nd, FREAD, 0); |
196 | PNBUF_PUT(path); | | 137 | PNBUF_PUT(path); |
197 | } | | 138 | } |
198 | | | 139 | |
199 | out: | | 140 | out: |
200 | if (error != 0) { | | 141 | if (error != 0) { |
201 | kmem_free(ko, sizeof(*ko)); | | 142 | kmem_free(ko, sizeof(*ko)); |
202 | return error; | | 143 | return error; |
203 | } | | 144 | } |
204 | | | 145 | |
205 | ko->ko_type = KT_VNODE; | | 146 | ko->ko_type = KT_VNODE; |
206 | ko->ko_source = nd.ni_vp; | | 147 | ko->ko_source = nd.ni_vp; |
207 | *kop = ko; | | 148 | *kop = ko; |
208 | return kobj_load(ko); | | 149 | return kobj_load(ko); |
209 | } | | 150 | } |
210 | | | 151 | |
211 | /* | | 152 | /* |
212 | * kobj_load_mem: | | 153 | * kobj_load_mem: |
213 | * | | 154 | * |
214 | * Load an object already resident in memory. If size is not -1, | | 155 | * Load an object already resident in memory. If size is not -1, |
215 | * the complete size of the object is known. | | 156 | * the complete size of the object is known. |
216 | */ | | 157 | */ |
217 | int | | 158 | int |
218 | kobj_load_mem(kobj_t *kop, void *base, ssize_t size) | | 159 | kobj_load_mem(kobj_t *kop, void *base, ssize_t size) |
219 | { | | 160 | { |
220 | kobj_t ko; | | 161 | kobj_t ko; |
221 | | | 162 | |
222 | ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); | | 163 | ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); |
223 | if (ko == NULL) { | | 164 | if (ko == NULL) { |
224 | return ENOMEM; | | 165 | return ENOMEM; |
225 | } | | 166 | } |
226 | | | 167 | |
227 | ko->ko_type = KT_MEMORY; | | 168 | ko->ko_type = KT_MEMORY; |
228 | ko->ko_source = base; | | 169 | ko->ko_source = base; |
229 | ko->ko_memsize = size; | | 170 | ko->ko_memsize = size; |
230 | *kop = ko; | | 171 | *kop = ko; |
231 | return kobj_load(ko); | | 172 | return kobj_load(ko); |
232 | } | | 173 | } |
233 | | | 174 | |
234 | /* | | 175 | /* |
235 | * kobj_close: | | 176 | * kobj_close: |
236 | * | | 177 | * |
237 | * Close an open ELF object. | | 178 | * Close an open ELF object. |
238 | */ | | 179 | */ |
239 | static void | | 180 | static void |
240 | kobj_close(kobj_t ko) | | 181 | kobj_close(kobj_t ko) |
241 | { | | 182 | { |
242 | | | 183 | |
243 | if (ko->ko_source == NULL) { | | 184 | if (ko->ko_source == NULL) { |
244 | return; | | 185 | return; |
245 | } | | 186 | } |
246 | | | 187 | |
247 | switch (ko->ko_type) { | | 188 | switch (ko->ko_type) { |
248 | case KT_VNODE: | | 189 | case KT_VNODE: |
249 | VOP_UNLOCK(ko->ko_source, 0); | | 190 | VOP_UNLOCK(ko->ko_source, 0); |
250 | vn_close(ko->ko_source, FREAD, kauth_cred_get()); | | 191 | vn_close(ko->ko_source, FREAD, kauth_cred_get()); |
251 | break; | | 192 | break; |
252 | case KT_MEMORY: | | 193 | case KT_MEMORY: |
253 | /* nothing */ | | 194 | /* nothing */ |
254 | break; | | 195 | break; |
255 | default: | | 196 | default: |
256 | panic("kobj_close: unknown type"); | | 197 | panic("kobj_close: unknown type"); |
257 | break; | | 198 | break; |
258 | } | | 199 | } |
259 | | | 200 | |
260 | ko->ko_source = NULL; | | 201 | ko->ko_source = NULL; |
261 | } | | 202 | } |
262 | | | 203 | |
263 | /* | | 204 | /* |
264 | * kobj_load: | | 205 | * kobj_load: |
265 | * | | 206 | * |
266 | * Load an ELF object and prepare to link into the running kernel | | 207 | * Load an ELF object and prepare to link into the running kernel |
267 | * image. | | 208 | * image. |
268 | */ | | 209 | */ |
269 | static int | | 210 | static int |
270 | kobj_load(kobj_t ko) | | 211 | kobj_load(kobj_t ko) |
271 | { | | 212 | { |
272 | Elf_Ehdr *hdr; | | 213 | Elf_Ehdr *hdr; |
273 | Elf_Shdr *shdr; | | 214 | Elf_Shdr *shdr; |
274 | Elf_Sym *es; | | 215 | Elf_Sym *es; |
275 | vaddr_t mapbase; | | 216 | vaddr_t mapbase; |
276 | size_t mapsize; | | 217 | size_t mapsize; |
277 | int error; | | 218 | int error; |
278 | int symtabindex; | | 219 | int symtabindex; |
279 | int symstrindex; | | 220 | int symstrindex; |
280 | int nsym; | | 221 | int nsym; |
281 | int pb, rl, ra; | | 222 | int pb, rl, ra; |
282 | int alignmask; | | 223 | int alignmask; |
283 | int i, j; | | 224 | int i, j; |
284 | void *addr; | | 225 | void *addr; |
285 | | | 226 | |
286 | KASSERT(ko->ko_type != KT_UNSET); | | 227 | KASSERT(ko->ko_type != KT_UNSET); |
287 | KASSERT(ko->ko_source != NULL); | | 228 | KASSERT(ko->ko_source != NULL); |
288 | | | 229 | |
289 | shdr = NULL; | | 230 | shdr = NULL; |
290 | mapsize = 0; | | 231 | mapsize = 0; |
291 | error = 0; | | 232 | error = 0; |
292 | hdr = NULL; | | 233 | hdr = NULL; |
293 | | | 234 | |
294 | /* | | 235 | /* |
295 | * Read the elf header from the file. | | 236 | * Read the elf header from the file. |
296 | */ | | 237 | */ |
297 | error = kobj_read(ko, (void **)&hdr, sizeof(*hdr), 0); | | 238 | error = kobj_read(ko, (void **)&hdr, sizeof(*hdr), 0); |
298 | if (error != 0) | | 239 | if (error != 0) |
299 | goto out; | | 240 | goto out; |
300 | if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0) { | | 241 | if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0) { |
301 | kobj_error("not an ELF object"); | | 242 | kobj_error("not an ELF object"); |
302 | error = ENOEXEC; | | 243 | error = ENOEXEC; |
303 | goto out; | | 244 | goto out; |
304 | } | | 245 | } |
305 | | | 246 | |
306 | if (hdr->e_ident[EI_VERSION] != EV_CURRENT || | | 247 | if (hdr->e_ident[EI_VERSION] != EV_CURRENT || |
307 | hdr->e_version != EV_CURRENT) { | | 248 | hdr->e_version != EV_CURRENT) { |
308 | kobj_error("unsupported file version"); | | 249 | kobj_error("unsupported file version"); |
309 | error = ENOEXEC; | | 250 | error = ENOEXEC; |
310 | goto out; | | 251 | goto out; |
311 | } | | 252 | } |
312 | if (hdr->e_type != ET_REL) { | | 253 | if (hdr->e_type != ET_REL) { |
313 | kobj_error("unsupported file type"); | | 254 | kobj_error("unsupported file type"); |
314 | error = ENOEXEC; | | 255 | error = ENOEXEC; |
315 | goto out; | | 256 | goto out; |
316 | } | | 257 | } |
317 | switch (hdr->e_machine) { | | 258 | switch (hdr->e_machine) { |
318 | #if ELFSIZE == 32 | | 259 | #if ELFSIZE == 32 |
319 | ELF32_MACHDEP_ID_CASES | | 260 | ELF32_MACHDEP_ID_CASES |
320 | #else | | 261 | #else |
321 | ELF64_MACHDEP_ID_CASES | | 262 | ELF64_MACHDEP_ID_CASES |
322 | #endif | | 263 | #endif |
323 | default: | | 264 | default: |
324 | kobj_error("unsupported machine"); | | 265 | kobj_error("unsupported machine"); |
325 | error = ENOEXEC; | | 266 | error = ENOEXEC; |
326 | goto out; | | 267 | goto out; |
327 | } | | 268 | } |
328 | | | 269 | |
329 | ko->ko_nprogtab = 0; | | 270 | ko->ko_nprogtab = 0; |
330 | ko->ko_shdr = 0; | | 271 | ko->ko_shdr = 0; |
331 | ko->ko_nrel = 0; | | 272 | ko->ko_nrel = 0; |
332 | ko->ko_nrela = 0; | | 273 | ko->ko_nrela = 0; |
333 | | | 274 | |
334 | /* | | 275 | /* |
335 | * Allocate and read in the section header. | | 276 | * Allocate and read in the section header. |
336 | */ | | 277 | */ |
337 | ko->ko_shdrsz = hdr->e_shnum * hdr->e_shentsize; | | 278 | ko->ko_shdrsz = hdr->e_shnum * hdr->e_shentsize; |
338 | if (ko->ko_shdrsz == 0 || hdr->e_shoff == 0 || | | 279 | if (ko->ko_shdrsz == 0 || hdr->e_shoff == 0 || |
339 | hdr->e_shentsize != sizeof(Elf_Shdr)) { | | 280 | hdr->e_shentsize != sizeof(Elf_Shdr)) { |
340 | error = ENOEXEC; | | 281 | error = ENOEXEC; |
341 | goto out; | | 282 | goto out; |
342 | } | | 283 | } |
343 | error = kobj_read(ko, (void **)&shdr, ko->ko_shdrsz, hdr->e_shoff); | | 284 | error = kobj_read(ko, (void **)&shdr, ko->ko_shdrsz, hdr->e_shoff); |
344 | if (error != 0) { | | 285 | if (error != 0) { |
345 | goto out; | | 286 | goto out; |
346 | } | | 287 | } |
347 | ko->ko_shdr = shdr; | | 288 | ko->ko_shdr = shdr; |
348 | | | 289 | |
349 | /* | | 290 | /* |
350 | * Scan the section header for information and table sizing. | | 291 | * Scan the section header for information and table sizing. |
351 | */ | | 292 | */ |
352 | nsym = 0; | | 293 | nsym = 0; |
353 | symtabindex = -1; | | 294 | symtabindex = -1; |
354 | symstrindex = -1; | | 295 | symstrindex = -1; |
355 | for (i = 0; i < hdr->e_shnum; i++) { | | 296 | for (i = 0; i < hdr->e_shnum; i++) { |
356 | switch (shdr[i].sh_type) { | | 297 | switch (shdr[i].sh_type) { |
357 | case SHT_PROGBITS: | | 298 | case SHT_PROGBITS: |
358 | case SHT_NOBITS: | | 299 | case SHT_NOBITS: |
359 | ko->ko_nprogtab++; | | 300 | ko->ko_nprogtab++; |
360 | break; | | 301 | break; |
361 | case SHT_SYMTAB: | | 302 | case SHT_SYMTAB: |
362 | nsym++; | | 303 | nsym++; |
363 | symtabindex = i; | | 304 | symtabindex = i; |
364 | symstrindex = shdr[i].sh_link; | | 305 | symstrindex = shdr[i].sh_link; |
365 | break; | | 306 | break; |
366 | case SHT_REL: | | 307 | case SHT_REL: |
367 | ko->ko_nrel++; | | 308 | ko->ko_nrel++; |
368 | break; | | 309 | break; |
369 | case SHT_RELA: | | 310 | case SHT_RELA: |
370 | ko->ko_nrela++; | | 311 | ko->ko_nrela++; |
371 | break; | | 312 | break; |
372 | case SHT_STRTAB: | | 313 | case SHT_STRTAB: |
373 | break; | | 314 | break; |
374 | } | | 315 | } |
375 | } | | 316 | } |
376 | if (ko->ko_nprogtab == 0) { | | 317 | if (ko->ko_nprogtab == 0) { |
377 | kobj_error("file has no contents"); | | 318 | kobj_error("file has no contents"); |
378 | error = ENOEXEC; | | 319 | error = ENOEXEC; |
379 | goto out; | | 320 | goto out; |
380 | } | | 321 | } |
381 | if (nsym != 1) { | | 322 | if (nsym != 1) { |
382 | /* Only allow one symbol table for now */ | | 323 | /* Only allow one symbol table for now */ |
383 | kobj_error("file has no valid symbol table"); | | 324 | kobj_error("file has no valid symbol table"); |
384 | error = ENOEXEC; | | 325 | error = ENOEXEC; |
385 | goto out; | | 326 | goto out; |
386 | } | | 327 | } |
387 | if (symstrindex < 0 || symstrindex > hdr->e_shnum || | | 328 | if (symstrindex < 0 || symstrindex > hdr->e_shnum || |
388 | shdr[symstrindex].sh_type != SHT_STRTAB) { | | 329 | shdr[symstrindex].sh_type != SHT_STRTAB) { |
389 | kobj_error("file has invalid symbol strings"); | | 330 | kobj_error("file has invalid symbol strings"); |
390 | error = ENOEXEC; | | 331 | error = ENOEXEC; |
391 | goto out; | | 332 | goto out; |
392 | } | | 333 | } |
393 | | | 334 | |
394 | /* | | 335 | /* |
395 | * Allocate space for tracking the load chunks. | | 336 | * Allocate space for tracking the load chunks. |
396 | */ | | 337 | */ |
397 | if (ko->ko_nprogtab != 0) { | | 338 | if (ko->ko_nprogtab != 0) { |
398 | ko->ko_progtab = kmem_zalloc(ko->ko_nprogtab * | | 339 | ko->ko_progtab = kmem_zalloc(ko->ko_nprogtab * |
399 | sizeof(*ko->ko_progtab), KM_SLEEP); | | 340 | sizeof(*ko->ko_progtab), KM_SLEEP); |
400 | if (ko->ko_progtab == NULL) { | | 341 | if (ko->ko_progtab == NULL) { |
401 | error = ENOMEM; | | 342 | error = ENOMEM; |
402 | goto out; | | 343 | goto out; |
403 | } | | 344 | } |
404 | } | | 345 | } |
405 | if (ko->ko_nrel != 0) { | | 346 | if (ko->ko_nrel != 0) { |
406 | ko->ko_reltab = kmem_zalloc(ko->ko_nrel * | | 347 | ko->ko_reltab = kmem_zalloc(ko->ko_nrel * |
407 | sizeof(*ko->ko_reltab), KM_SLEEP); | | 348 | sizeof(*ko->ko_reltab), KM_SLEEP); |
408 | if (ko->ko_reltab == NULL) { | | 349 | if (ko->ko_reltab == NULL) { |
409 | error = ENOMEM; | | 350 | error = ENOMEM; |
410 | goto out; | | 351 | goto out; |
411 | } | | 352 | } |
412 | } | | 353 | } |
413 | if (ko->ko_nrela != 0) { | | 354 | if (ko->ko_nrela != 0) { |
414 | ko->ko_relatab = kmem_zalloc(ko->ko_nrela * | | 355 | ko->ko_relatab = kmem_zalloc(ko->ko_nrela * |
415 | sizeof(*ko->ko_relatab), KM_SLEEP); | | 356 | sizeof(*ko->ko_relatab), KM_SLEEP); |
416 | if (ko->ko_relatab == NULL) { | | 357 | if (ko->ko_relatab == NULL) { |
417 | error = ENOMEM; | | 358 | error = ENOMEM; |
418 | goto out; | | 359 | goto out; |
419 | } | | 360 | } |
420 | } | | 361 | } |
421 | if (symtabindex == -1) { | | 362 | if (symtabindex == -1) { |
422 | kobj_error("lost symbol table index"); | | 363 | kobj_error("lost symbol table index"); |
423 | goto out; | | 364 | goto out; |
424 | } | | 365 | } |
425 | | | 366 | |
426 | /* | | 367 | /* |
427 | * Allocate space for and load the symbol table. | | 368 | * Allocate space for and load the symbol table. |
428 | */ | | 369 | */ |
429 | ko->ko_symcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); | | 370 | ko->ko_symcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); |
430 | if (ko->ko_symcnt == 0) { | | 371 | if (ko->ko_symcnt == 0) { |
431 | kobj_error("no symbol table"); | | 372 | kobj_error("no symbol table"); |
432 | goto out; | | 373 | goto out; |
433 | } | | 374 | } |
434 | error = kobj_read(ko, (void **)&ko->ko_symtab, | | 375 | error = kobj_read(ko, (void **)&ko->ko_symtab, |
435 | ko->ko_symcnt * sizeof(Elf_Sym), | | 376 | ko->ko_symcnt * sizeof(Elf_Sym), |
436 | shdr[symtabindex].sh_offset); | | 377 | shdr[symtabindex].sh_offset); |
437 | if (error != 0) { | | 378 | if (error != 0) { |
438 | goto out; | | 379 | goto out; |
439 | } | | 380 | } |
440 | | | 381 | |
441 | /* | | 382 | /* |
442 | * Allocate space for and load the symbol strings. | | 383 | * Allocate space for and load the symbol strings. |
443 | */ | | 384 | */ |
444 | ko->ko_strtabsz = shdr[symstrindex].sh_size; | | 385 | ko->ko_strtabsz = shdr[symstrindex].sh_size; |
445 | if (ko->ko_strtabsz == 0) { | | 386 | if (ko->ko_strtabsz == 0) { |
446 | kobj_error("no symbol strings"); | | 387 | kobj_error("no symbol strings"); |
447 | goto out; | | 388 | goto out; |
448 | } | | 389 | } |
449 | error = kobj_read(ko, (void *)&ko->ko_strtab, ko->ko_strtabsz, | | 390 | error = kobj_read(ko, (void *)&ko->ko_strtab, ko->ko_strtabsz, |
450 | shdr[symstrindex].sh_offset); | | 391 | shdr[symstrindex].sh_offset); |
451 | if (error != 0) { | | 392 | if (error != 0) { |
452 | goto out; | | 393 | goto out; |
453 | } | | 394 | } |
454 | | | 395 | |
455 | /* | | 396 | /* |
456 | * Do we have a string table for the section names? | | 397 | * Do we have a string table for the section names? |
457 | */ | | 398 | */ |
458 | if (hdr->e_shstrndx != 0 && shdr[hdr->e_shstrndx].sh_size != 0 && | | 399 | if (hdr->e_shstrndx != 0 && shdr[hdr->e_shstrndx].sh_size != 0 && |
459 | shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { | | 400 | shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { |
460 | ko->ko_shstrtabsz = shdr[hdr->e_shstrndx].sh_size; | | 401 | ko->ko_shstrtabsz = shdr[hdr->e_shstrndx].sh_size; |
461 | error = kobj_read(ko, (void **)&ko->ko_shstrtab, | | 402 | error = kobj_read(ko, (void **)&ko->ko_shstrtab, |
462 | shdr[hdr->e_shstrndx].sh_size, | | 403 | shdr[hdr->e_shstrndx].sh_size, |
463 | shdr[hdr->e_shstrndx].sh_offset); | | 404 | shdr[hdr->e_shstrndx].sh_offset); |
464 | if (error != 0) { | | 405 | if (error != 0) { |
465 | goto out; | | 406 | goto out; |
466 | } | | 407 | } |
467 | } | | 408 | } |
468 | | | 409 | |
469 | /* | | 410 | /* |
470 | * Size up code/data(progbits) and bss(nobits). | | 411 | * Size up code/data(progbits) and bss(nobits). |
471 | */ | | 412 | */ |
472 | alignmask = 0; | | 413 | alignmask = 0; |
473 | mapbase = 0; | | 414 | mapbase = 0; |
474 | for (i = 0; i < hdr->e_shnum; i++) { | | 415 | for (i = 0; i < hdr->e_shnum; i++) { |
475 | switch (shdr[i].sh_type) { | | 416 | switch (shdr[i].sh_type) { |
476 | case SHT_PROGBITS: | | 417 | case SHT_PROGBITS: |
477 | case SHT_NOBITS: | | 418 | case SHT_NOBITS: |
478 | if (mapbase == 0) | | 419 | if (mapbase == 0) |
479 | mapbase = shdr[i].sh_offset; | | 420 | mapbase = shdr[i].sh_offset; |
480 | alignmask = shdr[i].sh_addralign - 1; | | 421 | alignmask = shdr[i].sh_addralign - 1; |
481 | mapsize += alignmask; | | 422 | mapsize += alignmask; |
482 | mapsize &= ~alignmask; | | 423 | mapsize &= ~alignmask; |
483 | mapsize += shdr[i].sh_size; | | 424 | mapsize += shdr[i].sh_size; |
484 | break; | | 425 | break; |
485 | } | | 426 | } |
486 | } | | 427 | } |
487 | | | 428 | |
488 | /* | | 429 | /* |
489 | * We know how much space we need for the text/data/bss/etc. | | 430 | * We know how much space we need for the text/data/bss/etc. |
490 | * This stuff needs to be in a single chunk so that profiling etc | | 431 | * This stuff needs to be in a single chunk so that profiling etc |
491 | * can get the bounds and gdb can associate offsets with modules. | | 432 | * can get the bounds and gdb can associate offsets with modules. |
492 | */ | | 433 | */ |
493 | if (mapsize == 0) { | | 434 | if (mapsize == 0) { |
494 | kobj_error("no text/data/bss"); | | 435 | kobj_error("no text/data/bss"); |
495 | goto out; | | 436 | goto out; |
496 | } | | 437 | } |
497 | if (ko->ko_type == KT_MEMORY) { | | 438 | if (ko->ko_type == KT_MEMORY) { |
498 | mapbase += (vaddr_t)ko->ko_source; | | 439 | mapbase += (vaddr_t)ko->ko_source; |
499 | } else { | | 440 | } else { |
500 | mapbase = uvm_km_alloc(module_map, round_page(mapsize), | | 441 | mapbase = uvm_km_alloc(module_map, round_page(mapsize), |
501 | 0, UVM_KMF_WIRED | UVM_KMF_EXEC); | | 442 | 0, UVM_KMF_WIRED | UVM_KMF_EXEC); |
502 | if (mapbase == 0) { | | 443 | if (mapbase == 0) { |
503 | error = ENOMEM; | | 444 | error = ENOMEM; |
504 | goto out; | | 445 | goto out; |
505 | } | | 446 | } |
506 | } | | 447 | } |
507 | ko->ko_address = mapbase; | | 448 | ko->ko_address = mapbase; |
508 | ko->ko_size = mapsize; | | 449 | ko->ko_size = mapsize; |
509 | | | 450 | |
510 | /* | | 451 | /* |
511 | * Now load code/data(progbits), zero bss(nobits), allocate space | | 452 | * Now load code/data(progbits), zero bss(nobits), allocate space |
512 | * for and load relocs | | 453 | * for and load relocs |
513 | */ | | 454 | */ |
514 | pb = 0; | | 455 | pb = 0; |
515 | rl = 0; | | 456 | rl = 0; |
516 | ra = 0; | | 457 | ra = 0; |
517 | alignmask = 0; | | 458 | alignmask = 0; |
518 | for (i = 0; i < hdr->e_shnum; i++) { | | 459 | for (i = 0; i < hdr->e_shnum; i++) { |
519 | switch (shdr[i].sh_type) { | | 460 | switch (shdr[i].sh_type) { |
520 | case SHT_PROGBITS: | | 461 | case SHT_PROGBITS: |
521 | case SHT_NOBITS: | | 462 | case SHT_NOBITS: |
522 | alignmask = shdr[i].sh_addralign - 1; | | 463 | alignmask = shdr[i].sh_addralign - 1; |
523 | if (ko->ko_type == KT_MEMORY) { | | 464 | if (ko->ko_type == KT_MEMORY) { |
524 | addr = (void *)(shdr[i].sh_offset + | | 465 | addr = (void *)(shdr[i].sh_offset + |
525 | (vaddr_t)ko->ko_source); | | 466 | (vaddr_t)ko->ko_source); |
526 | if (((vaddr_t)addr & alignmask) != 0) { | | 467 | if (((vaddr_t)addr & alignmask) != 0) { |
527 | kobj_error("section %d not aligned\n", | | 468 | kobj_error("section %d not aligned\n", |
528 | i); | | 469 | i); |
529 | goto out; | | 470 | goto out; |
530 | } | | 471 | } |
531 | } else { | | 472 | } else { |
532 | mapbase += alignmask; | | 473 | mapbase += alignmask; |
533 | mapbase &= ~alignmask; | | 474 | mapbase &= ~alignmask; |
534 | addr = (void *)mapbase; | | 475 | addr = (void *)mapbase; |
535 | mapbase += shdr[i].sh_size; | | 476 | mapbase += shdr[i].sh_size; |
536 | } | | 477 | } |
537 | ko->ko_progtab[pb].addr = addr; | | 478 | ko->ko_progtab[pb].addr = addr; |
538 | if (shdr[i].sh_type == SHT_PROGBITS) { | | 479 | if (shdr[i].sh_type == SHT_PROGBITS) { |
539 | ko->ko_progtab[pb].name = "<<PROGBITS>>"; | | 480 | ko->ko_progtab[pb].name = "<<PROGBITS>>"; |
540 | error = kobj_read_bits(ko, addr, | | 481 | error = kobj_read_bits(ko, addr, |
541 | shdr[i].sh_size, shdr[i].sh_offset); | | 482 | shdr[i].sh_size, shdr[i].sh_offset); |
542 | if (error != 0) { | | 483 | if (error != 0) { |
543 | goto out; | | 484 | goto out; |
544 | } | | 485 | } |
545 | } else if (ko->ko_type == KT_MEMORY && | | 486 | } else if (ko->ko_type == KT_MEMORY && |
546 | shdr[i].sh_size != 0) { | | 487 | shdr[i].sh_size != 0) { |
547 | kobj_error("non-loadable BSS section in " | | 488 | kobj_error("non-loadable BSS section in " |
548 | "pre-loaded module"); | | 489 | "pre-loaded module"); |
549 | error = EINVAL; | | 490 | error = EINVAL; |
550 | goto out; | | 491 | goto out; |
551 | } else { | | 492 | } else { |
552 | ko->ko_progtab[pb].name = "<<NOBITS>>"; | | 493 | ko->ko_progtab[pb].name = "<<NOBITS>>"; |
553 | memset(addr, 0, shdr[i].sh_size); | | 494 | memset(addr, 0, shdr[i].sh_size); |
554 | } | | 495 | } |
555 | ko->ko_progtab[pb].size = shdr[i].sh_size; | | 496 | ko->ko_progtab[pb].size = shdr[i].sh_size; |
556 | ko->ko_progtab[pb].sec = i; | | 497 | ko->ko_progtab[pb].sec = i; |
557 | if (ko->ko_shstrtab != NULL && shdr[i].sh_name != 0) { | | 498 | if (ko->ko_shstrtab != NULL && shdr[i].sh_name != 0) { |
558 | ko->ko_progtab[pb].name = | | 499 | ko->ko_progtab[pb].name = |
559 | ko->ko_shstrtab + shdr[i].sh_name; | | 500 | ko->ko_shstrtab + shdr[i].sh_name; |
560 | } | | 501 | } |
561 | | | 502 | |
562 | /* Update all symbol values with the offset. */ | | 503 | /* Update all symbol values with the offset. */ |
563 | for (j = 0; j < ko->ko_symcnt; j++) { | | 504 | for (j = 0; j < ko->ko_symcnt; j++) { |
564 | es = &ko->ko_symtab[j]; | | 505 | es = &ko->ko_symtab[j]; |
565 | if (es->st_shndx != i) { | | 506 | if (es->st_shndx != i) { |
566 | continue; | | 507 | continue; |
567 | } | | 508 | } |
568 | es->st_value += (Elf_Addr)addr; | | 509 | es->st_value += (Elf_Addr)addr; |
569 | } | | 510 | } |
570 | pb++; | | 511 | pb++; |
571 | break; | | 512 | break; |
572 | case SHT_REL: | | 513 | case SHT_REL: |
573 | ko->ko_reltab[rl].size = shdr[i].sh_size; | | 514 | ko->ko_reltab[rl].size = shdr[i].sh_size; |
574 | ko->ko_reltab[rl].size -= | | 515 | ko->ko_reltab[rl].size -= |
575 | shdr[i].sh_size % sizeof(Elf_Rel); | | 516 | shdr[i].sh_size % sizeof(Elf_Rel); |
576 | if (ko->ko_reltab[rl].size != 0) { | | 517 | if (ko->ko_reltab[rl].size != 0) { |
577 | ko->ko_reltab[rl].nrel = | | 518 | ko->ko_reltab[rl].nrel = |
578 | shdr[i].sh_size / sizeof(Elf_Rel); | | 519 | shdr[i].sh_size / sizeof(Elf_Rel); |
579 | ko->ko_reltab[rl].sec = shdr[i].sh_info; | | 520 | ko->ko_reltab[rl].sec = shdr[i].sh_info; |
580 | error = kobj_read(ko, | | 521 | error = kobj_read(ko, |
581 | (void **)&ko->ko_reltab[rl].rel, | | 522 | (void **)&ko->ko_reltab[rl].rel, |
582 | ko->ko_reltab[rl].size, | | 523 | ko->ko_reltab[rl].size, |
583 | shdr[i].sh_offset); | | 524 | shdr[i].sh_offset); |
584 | if (error != 0) { | | 525 | if (error != 0) { |
585 | goto out; | | 526 | goto out; |
586 | } | | 527 | } |
587 | } | | 528 | } |
588 | rl++; | | 529 | rl++; |
589 | break; | | 530 | break; |
590 | case SHT_RELA: | | 531 | case SHT_RELA: |
591 | ko->ko_relatab[ra].size = shdr[i].sh_size; | | 532 | ko->ko_relatab[ra].size = shdr[i].sh_size; |
592 | ko->ko_relatab[ra].size -= | | 533 | ko->ko_relatab[ra].size -= |
593 | shdr[i].sh_size % sizeof(Elf_Rela); | | 534 | shdr[i].sh_size % sizeof(Elf_Rela); |
594 | if (ko->ko_relatab[ra].size != 0) { | | 535 | if (ko->ko_relatab[ra].size != 0) { |
595 | ko->ko_relatab[ra].nrela = | | 536 | ko->ko_relatab[ra].nrela = |
596 | shdr[i].sh_size / sizeof(Elf_Rela); | | 537 | shdr[i].sh_size / sizeof(Elf_Rela); |
597 | ko->ko_relatab[ra].sec = shdr[i].sh_info; | | 538 | ko->ko_relatab[ra].sec = shdr[i].sh_info; |
598 | error = kobj_read(ko, | | 539 | error = kobj_read(ko, |
599 | (void **)&ko->ko_relatab[ra].rela, | | 540 | (void **)&ko->ko_relatab[ra].rela, |
600 | shdr[i].sh_size, | | 541 | shdr[i].sh_size, |
601 | shdr[i].sh_offset); | | 542 | shdr[i].sh_offset); |
602 | if (error != 0) { | | 543 | if (error != 0) { |
603 | goto out; | | 544 | goto out; |
604 | } | | 545 | } |
605 | } | | 546 | } |
606 | ra++; | | 547 | ra++; |
607 | break; | | 548 | break; |
608 | default: | | 549 | default: |
609 | break; | | 550 | break; |
610 | } | | 551 | } |
611 | } | | 552 | } |
612 | if (pb != ko->ko_nprogtab) { | | 553 | if (pb != ko->ko_nprogtab) { |
613 | panic("lost progbits"); | | 554 | panic("lost progbits"); |
614 | } | | 555 | } |
615 | if (rl != ko->ko_nrel) { | | 556 | if (rl != ko->ko_nrel) { |
616 | panic("lost rel"); | | 557 | panic("lost rel"); |
617 | } | | 558 | } |
618 | if (ra != ko->ko_nrela) { | | 559 | if (ra != ko->ko_nrela) { |
619 | panic("lost rela"); | | 560 | panic("lost rela"); |
620 | } | | 561 | } |
621 | if (ko->ko_type != KT_MEMORY && mapbase != ko->ko_address + mapsize) { | | 562 | if (ko->ko_type != KT_MEMORY && mapbase != ko->ko_address + mapsize) { |
622 | panic("mapbase 0x%lx != address %lx + mapsize %ld (0x%lx)\n", | | 563 | panic("mapbase 0x%lx != address %lx + mapsize %ld (0x%lx)\n", |
623 | (long)mapbase, (long)ko->ko_address, (long)mapsize, | | 564 | (long)mapbase, (long)ko->ko_address, (long)mapsize, |
624 | (long)ko->ko_address + mapsize); | | 565 | (long)ko->ko_address + mapsize); |
625 | } | | 566 | } |
626 | | | 567 | |
627 | /* | | 568 | /* |
628 | * Perform local relocations only. Relocations relating to global | | 569 | * Perform local relocations only. Relocations relating to global |
629 | * symbols will be done by kobj_affix(). | | 570 | * symbols will be done by kobj_affix(). |
630 | */ | | 571 | */ |
631 | error = kobj_checksyms(ko, false); | | 572 | error = kobj_checksyms(ko, false); |
632 | if (error == 0) { | | 573 | if (error == 0) { |
633 | error = kobj_relocate(ko, true); | | 574 | error = kobj_relocate(ko, true); |
634 | } | | 575 | } |
635 | out: | | 576 | out: |
636 | if (hdr != NULL) { | | 577 | if (hdr != NULL) { |
637 | kobj_free(ko, hdr, sizeof(*hdr)); | | 578 | kobj_free(ko, hdr, sizeof(*hdr)); |
638 | } | | 579 | } |
639 | kobj_close(ko); | | 580 | kobj_close(ko); |
640 | if (error != 0) { | | 581 | if (error != 0) { |
641 | kobj_unload(ko); | | 582 | kobj_unload(ko); |
642 | } | | 583 | } |
643 | | | 584 | |
644 | return error; | | 585 | return error; |
645 | } | | 586 | } |
646 | | | 587 | |
647 | /* | | 588 | /* |
648 | * kobj_unload: | | 589 | * kobj_unload: |
649 | * | | 590 | * |
650 | * Unload an object previously loaded by kobj_load(). | | 591 | * Unload an object previously loaded by kobj_load(). |
651 | */ | | 592 | */ |
652 | void | | 593 | void |
653 | kobj_unload(kobj_t ko) | | 594 | kobj_unload(kobj_t ko) |
654 | { | | 595 | { |
655 | int error; | | 596 | int error; |
656 | | | 597 | |
657 | kobj_close(ko); | | 598 | kobj_close(ko); |
658 | kobj_jettison(ko); | | 599 | kobj_jettison(ko); |
659 | | | 600 | |
660 | /* | | 601 | /* |
661 | * Notify MD code that a module has been unloaded. | | 602 | * Notify MD code that a module has been unloaded. |
662 | */ | | 603 | */ |
663 | if (ko->ko_loaded) { | | 604 | if (ko->ko_loaded) { |
664 | error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, | | 605 | error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, |
665 | false); | | 606 | false); |
666 | if (error != 0) { | | 607 | if (error != 0) { |
667 | kobj_error("machine dependent deinit failed"); | | 608 | kobj_error("machine dependent deinit failed"); |
668 | } | | 609 | } |
669 | } | | 610 | } |
670 | if (ko->ko_address != 0 && ko->ko_type != KT_MEMORY) { | | 611 | if (ko->ko_address != 0 && ko->ko_type != KT_MEMORY) { |
671 | uvm_km_free(module_map, ko->ko_address, round_page(ko->ko_size), | | 612 | uvm_km_free(module_map, ko->ko_address, round_page(ko->ko_size), |
672 | UVM_KMF_WIRED); | | 613 | UVM_KMF_WIRED); |
673 | } | | 614 | } |
674 | if (ko->ko_ksyms == true) { | | 615 | if (ko->ko_ksyms == true) { |
675 | ksyms_modunload(ko->ko_name); | | 616 | ksyms_modunload(ko->ko_name); |
676 | } | | 617 | } |
677 | if (ko->ko_symtab != NULL) { | | 618 | if (ko->ko_symtab != NULL) { |
678 | kobj_free(ko, ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym)); | | 619 | kobj_free(ko, ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym)); |
679 | } | | 620 | } |
680 | if (ko->ko_strtab != NULL) { | | 621 | if (ko->ko_strtab != NULL) { |
681 | kobj_free(ko, ko->ko_strtab, ko->ko_strtabsz); | | 622 | kobj_free(ko, ko->ko_strtab, ko->ko_strtabsz); |
682 | } | | 623 | } |
683 | if (ko->ko_progtab != NULL) { | | 624 | if (ko->ko_progtab != NULL) { |
684 | kobj_free(ko, ko->ko_progtab, ko->ko_nprogtab * | | 625 | kobj_free(ko, ko->ko_progtab, ko->ko_nprogtab * |
685 | sizeof(*ko->ko_progtab)); | | 626 | sizeof(*ko->ko_progtab)); |
686 | ko->ko_progtab = NULL; | | 627 | ko->ko_progtab = NULL; |
687 | } | | 628 | } |
688 | if (ko->ko_shstrtab) { | | 629 | if (ko->ko_shstrtab) { |
689 | kobj_free(ko, ko->ko_shstrtab, ko->ko_shstrtabsz); | | 630 | kobj_free(ko, ko->ko_shstrtab, ko->ko_shstrtabsz); |
690 | ko->ko_shstrtab = NULL; | | 631 | ko->ko_shstrtab = NULL; |
691 | } | | 632 | } |
692 | | | 633 | |
693 | kmem_free(ko, sizeof(*ko)); | | 634 | kmem_free(ko, sizeof(*ko)); |
694 | } | | 635 | } |
695 | | | 636 | |
696 | /* | | 637 | /* |
697 | * kobj_stat: | | 638 | * kobj_stat: |
698 | * | | 639 | * |
699 | * Return size and load address of an object. | | 640 | * Return size and load address of an object. |
700 | */ | | 641 | */ |
701 | void | | 642 | void |
702 | kobj_stat(kobj_t ko, vaddr_t *address, size_t *size) | | 643 | kobj_stat(kobj_t ko, vaddr_t *address, size_t *size) |
703 | { | | 644 | { |
704 | | | 645 | |
705 | if (address != NULL) { | | 646 | if (address != NULL) { |
706 | *address = ko->ko_address; | | 647 | *address = ko->ko_address; |
707 | } | | 648 | } |
708 | if (size != NULL) { | | 649 | if (size != NULL) { |
709 | *size = ko->ko_size; | | 650 | *size = ko->ko_size; |
710 | } | | 651 | } |
711 | } | | 652 | } |
712 | | | 653 | |
713 | /* | | 654 | /* |
714 | * kobj_affix: | | 655 | * kobj_affix: |
715 | * | | 656 | * |
716 | * Set an object's name and perform global relocs. May only be | | 657 | * Set an object's name and perform global relocs. May only be |
717 | * called after the module and any requisite modules are loaded. | | 658 | * called after the module and any requisite modules are loaded. |
718 | */ | | 659 | */ |
719 | int | | 660 | int |
720 | kobj_affix(kobj_t ko, const char *name) | | 661 | kobj_affix(kobj_t ko, const char *name) |
721 | { | | 662 | { |
722 | int error; | | 663 | int error; |
723 | | | 664 | |
724 | KASSERT(ko->ko_ksyms == false); | | 665 | KASSERT(ko->ko_ksyms == false); |
725 | KASSERT(ko->ko_loaded == false); | | 666 | KASSERT(ko->ko_loaded == false); |
726 | | | 667 | |
727 | strlcpy(ko->ko_name, name, sizeof(ko->ko_name)); | | 668 | strlcpy(ko->ko_name, name, sizeof(ko->ko_name)); |
728 | | | 669 | |
729 | /* Cache addresses of undefined symbols. */ | | 670 | /* Cache addresses of undefined symbols. */ |
730 | error = kobj_checksyms(ko, true); | | 671 | error = kobj_checksyms(ko, true); |
731 | | | 672 | |
732 | /* Now do global relocations. */ | | 673 | /* Now do global relocations. */ |
733 | if (error == 0) | | 674 | if (error == 0) |
734 | error = kobj_relocate(ko, false); | | 675 | error = kobj_relocate(ko, false); |
735 | | | 676 | |
736 | /* | | 677 | /* |
737 | * Now that we know the name, register the symbol table. | | 678 | * Now that we know the name, register the symbol table. |
738 | * Do after global relocations because ksyms will pack | | 679 | * Do after global relocations because ksyms will pack |
739 | * the table. | | 680 | * the table. |
740 | */ | | 681 | */ |
741 | if (error == 0) { | | 682 | if (error == 0) { |
742 | ksyms_modload(ko->ko_name, ko->ko_symtab, ko->ko_symcnt * | | 683 | ksyms_modload(ko->ko_name, ko->ko_symtab, ko->ko_symcnt * |
743 | sizeof(Elf_Sym), ko->ko_strtab, ko->ko_strtabsz); | | 684 | sizeof(Elf_Sym), ko->ko_strtab, ko->ko_strtabsz); |
744 | ko->ko_ksyms = true; | | 685 | ko->ko_ksyms = true; |
745 | } | | 686 | } |
746 | | | 687 | |
747 | /* Jettison unneeded memory post-link. */ | | 688 | /* Jettison unneeded memory post-link. */ |
748 | kobj_jettison(ko); | | 689 | kobj_jettison(ko); |
749 | | | 690 | |
750 | /* | | 691 | /* |
751 | * Notify MD code that a module has been loaded. | | 692 | * Notify MD code that a module has been loaded. |
752 | * | | 693 | * |
753 | * Most architectures use this opportunity to flush their caches. | | 694 | * Most architectures use this opportunity to flush their caches. |
754 | */ | | 695 | */ |
755 | if (error == 0) { | | 696 | if (error == 0) { |
756 | error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, | | 697 | error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, |
757 | true); | | 698 | true); |
758 | if (error != 0) { | | 699 | if (error != 0) { |
759 | kobj_error("machine dependent init failed"); | | 700 | kobj_error("machine dependent init failed"); |
760 | } | | 701 | } |
761 | ko->ko_loaded = true; | | 702 | ko->ko_loaded = true; |
762 | } | | 703 | } |
763 | | | 704 | |
764 | /* If there was an error, destroy the whole object. */ | | 705 | /* If there was an error, destroy the whole object. */ |
765 | if (error != 0) { | | 706 | if (error != 0) { |
766 | kobj_unload(ko); | | 707 | kobj_unload(ko); |
767 | } | | 708 | } |
768 | | | 709 | |
769 | return error; | | 710 | return error; |
770 | } | | 711 | } |
771 | | | 712 | |
772 | /* | | 713 | /* |
773 | * kobj_find_section: | | 714 | * kobj_find_section: |
774 | * | | 715 | * |
775 | * Given a section name, search the loaded object and return | | 716 | * Given a section name, search the loaded object and return |
776 | * virtual address if present and loaded. | | 717 | * virtual address if present and loaded. |
777 | */ | | 718 | */ |
778 | int | | 719 | int |
779 | kobj_find_section(kobj_t ko, const char *name, void **addr, size_t *size) | | 720 | kobj_find_section(kobj_t ko, const char *name, void **addr, size_t *size) |
780 | { | | 721 | { |
781 | int i; | | 722 | int i; |
782 | | | 723 | |
783 | KASSERT(ko->ko_progtab != NULL); | | 724 | KASSERT(ko->ko_progtab != NULL); |
784 | | | 725 | |
785 | for (i = 0; i < ko->ko_nprogtab; i++) { | | 726 | for (i = 0; i < ko->ko_nprogtab; i++) { |
786 | if (strcmp(ko->ko_progtab[i].name, name) == 0) { | | 727 | if (strcmp(ko->ko_progtab[i].name, name) == 0) { |
787 | if (addr != NULL) { | | 728 | if (addr != NULL) { |
788 | *addr = ko->ko_progtab[i].addr; | | 729 | *addr = ko->ko_progtab[i].addr; |
789 | } | | 730 | } |
790 | if (size != NULL) { | | 731 | if (size != NULL) { |
791 | *size = ko->ko_progtab[i].size; | | 732 | *size = ko->ko_progtab[i].size; |
792 | } | | 733 | } |
793 | return 0; | | 734 | return 0; |
794 | } | | 735 | } |
795 | } | | 736 | } |
796 | | | 737 | |
797 | return ENOENT; | | 738 | return ENOENT; |
798 | } | | 739 | } |
799 | | | 740 | |
800 | /* | | 741 | /* |
801 | * kobj_jettison: | | 742 | * kobj_jettison: |
802 | * | | 743 | * |
803 | * Release object data not needed after performing relocations. | | 744 | * Release object data not needed after performing relocations. |
804 | */ | | 745 | */ |
805 | static void | | 746 | static void |
806 | kobj_jettison(kobj_t ko) | | 747 | kobj_jettison(kobj_t ko) |
807 | { | | 748 | { |
808 | int i; | | 749 | int i; |
809 | | | 750 | |
810 | if (ko->ko_reltab != NULL) { | | 751 | if (ko->ko_reltab != NULL) { |
811 | for (i = 0; i < ko->ko_nrel; i++) { | | 752 | for (i = 0; i < ko->ko_nrel; i++) { |
812 | if (ko->ko_reltab[i].rel) { | | 753 | if (ko->ko_reltab[i].rel) { |
813 | kobj_free(ko, ko->ko_reltab[i].rel, | | 754 | kobj_free(ko, ko->ko_reltab[i].rel, |
814 | ko->ko_reltab[i].size); | | 755 | ko->ko_reltab[i].size); |
815 | } | | 756 | } |
816 | } | | 757 | } |
817 | kobj_free(ko, ko->ko_reltab, ko->ko_nrel * | | 758 | kobj_free(ko, ko->ko_reltab, ko->ko_nrel * |
818 | sizeof(*ko->ko_reltab)); | | 759 | sizeof(*ko->ko_reltab)); |
819 | ko->ko_reltab = NULL; | | 760 | ko->ko_reltab = NULL; |
820 | ko->ko_nrel = 0; | | 761 | ko->ko_nrel = 0; |
821 | } | | 762 | } |
822 | if (ko->ko_relatab != NULL) { | | 763 | if (ko->ko_relatab != NULL) { |
823 | for (i = 0; i < ko->ko_nrela; i++) { | | 764 | for (i = 0; i < ko->ko_nrela; i++) { |
824 | if (ko->ko_relatab[i].rela) { | | 765 | if (ko->ko_relatab[i].rela) { |
825 | kobj_free(ko, ko->ko_relatab[i].rela, | | 766 | kobj_free(ko, ko->ko_relatab[i].rela, |
826 | ko->ko_relatab[i].size); | | 767 | ko->ko_relatab[i].size); |
827 | } | | 768 | } |
828 | } | | 769 | } |
829 | kobj_free(ko, ko->ko_relatab, ko->ko_nrela * | | 770 | kobj_free(ko, ko->ko_relatab, ko->ko_nrela * |
830 | sizeof(*ko->ko_relatab)); | | 771 | sizeof(*ko->ko_relatab)); |
831 | ko->ko_relatab = NULL; | | 772 | ko->ko_relatab = NULL; |
832 | ko->ko_nrela = 0; | | 773 | ko->ko_nrela = 0; |
833 | } | | 774 | } |
834 | if (ko->ko_shdr != NULL) { | | 775 | if (ko->ko_shdr != NULL) { |
835 | kobj_free(ko, ko->ko_shdr, ko->ko_shdrsz); | | 776 | kobj_free(ko, ko->ko_shdr, ko->ko_shdrsz); |
836 | ko->ko_shdr = NULL; | | 777 | ko->ko_shdr = NULL; |
837 | } | | 778 | } |
838 | } | | 779 | } |
839 | | | 780 | |
840 | /* | | 781 | /* |
841 | * kobj_sym_lookup: | | 782 | * kobj_sym_lookup: |
842 | * | | 783 | * |
843 | * Symbol lookup function to be used when the symbol index | | 784 | * Symbol lookup function to be used when the symbol index |
844 | * is known (ie during relocation). | | 785 | * is known (ie during relocation). |
845 | */ | | 786 | */ |
846 | uintptr_t | | 787 | uintptr_t |
847 | kobj_sym_lookup(kobj_t ko, uintptr_t symidx) | | 788 | kobj_sym_lookup(kobj_t ko, uintptr_t symidx) |
848 | { | | 789 | { |
849 | const Elf_Sym *sym; | | 790 | const Elf_Sym *sym; |
850 | const char *symbol; | | 791 | const char *symbol; |
851 | | | 792 | |
852 | /* Don't even try to lookup the symbol if the index is bogus. */ | | 793 | /* Don't even try to lookup the symbol if the index is bogus. */ |
853 | if (symidx >= ko->ko_symcnt) | | 794 | if (symidx >= ko->ko_symcnt) |
854 | return 0; | | 795 | return 0; |
855 | | | 796 | |
856 | sym = ko->ko_symtab + symidx; | | 797 | sym = ko->ko_symtab + symidx; |
857 | | | 798 | |
858 | /* Quick answer if there is a definition included. */ | | 799 | /* Quick answer if there is a definition included. */ |
859 | if (sym->st_shndx != SHN_UNDEF) { | | 800 | if (sym->st_shndx != SHN_UNDEF) { |
860 | return (uintptr_t)sym->st_value; | | 801 | return (uintptr_t)sym->st_value; |
861 | } | | 802 | } |
862 | | | 803 | |
863 | /* If we get here, then it is undefined and needs a lookup. */ | | 804 | /* If we get here, then it is undefined and needs a lookup. */ |
864 | switch (ELF_ST_BIND(sym->st_info)) { | | 805 | switch (ELF_ST_BIND(sym->st_info)) { |
865 | case STB_LOCAL: | | 806 | case STB_LOCAL: |
866 | /* Local, but undefined? huh? */ | | 807 | /* Local, but undefined? huh? */ |
867 | kobj_error("local symbol undefined"); | | 808 | kobj_error("local symbol undefined"); |
868 | return 0; | | 809 | return 0; |
869 | | | 810 | |
870 | case STB_GLOBAL: | | 811 | case STB_GLOBAL: |
871 | /* Relative to Data or Function name */ | | 812 | /* Relative to Data or Function name */ |
872 | symbol = ko->ko_strtab + sym->st_name; | | 813 | symbol = ko->ko_strtab + sym->st_name; |
873 | | | 814 | |
874 | /* Force a lookup failure if the symbol name is bogus. */ | | 815 | /* Force a lookup failure if the symbol name is bogus. */ |
875 | if (*symbol == 0) { | | 816 | if (*symbol == 0) { |
876 | kobj_error("bad symbol name"); | | 817 | kobj_error("bad symbol name"); |
877 | return 0; | | 818 | return 0; |
878 | } | | 819 | } |
879 | | | 820 | |
880 | return (uintptr_t)sym->st_value; | | 821 | return (uintptr_t)sym->st_value; |
881 | | | 822 | |
882 | case STB_WEAK: | | 823 | case STB_WEAK: |
883 | kobj_error("weak symbols not supported\n"); | | 824 | kobj_error("weak symbols not supported\n"); |
884 | return 0; | | 825 | return 0; |
885 | | | 826 | |
886 | default: | | 827 | default: |
887 | return 0; | | 828 | return 0; |
888 | } | | 829 | } |
889 | } | | 830 | } |
890 | | | 831 | |
891 | /* | | 832 | /* |
892 | * kobj_findbase: | | 833 | * kobj_findbase: |
893 | * | | 834 | * |
894 | * Return base address of the given section. | | 835 | * Return base address of the given section. |
895 | */ | | 836 | */ |
896 | static uintptr_t | | 837 | static uintptr_t |
897 | kobj_findbase(kobj_t ko, int sec) | | 838 | kobj_findbase(kobj_t ko, int sec) |
898 | { | | 839 | { |
899 | int i; | | 840 | int i; |
900 | | | 841 | |
901 | for (i = 0; i < ko->ko_nprogtab; i++) { | | 842 | for (i = 0; i < ko->ko_nprogtab; i++) { |
902 | if (sec == ko->ko_progtab[i].sec) { | | 843 | if (sec == ko->ko_progtab[i].sec) { |
903 | return (uintptr_t)ko->ko_progtab[i].addr; | | 844 | return (uintptr_t)ko->ko_progtab[i].addr; |
904 | } | | 845 | } |
905 | } | | 846 | } |
906 | return 0; | | 847 | return 0; |
907 | } | | 848 | } |
908 | | | 849 | |
909 | /* | | 850 | /* |
910 | * kobj_checksyms: | | 851 | * kobj_checksyms: |
911 | * | | 852 | * |
912 | * Scan symbol table for duplicates or resolve references to | | 853 | * Scan symbol table for duplicates or resolve references to |
913 | * exernal symbols. | | 854 | * exernal symbols. |
914 | */ | | 855 | */ |
915 | static int | | 856 | static int |
916 | kobj_checksyms(kobj_t ko, bool undefined) | | 857 | kobj_checksyms(kobj_t ko, bool undefined) |
917 | { | | 858 | { |
918 | unsigned long rval; | | 859 | unsigned long rval; |
919 | Elf_Sym *sym, *ms; | | 860 | Elf_Sym *sym, *ms; |
920 | const char *name; | | 861 | const char *name; |
921 | int error; | | 862 | int error; |
922 | | | 863 | |
923 | error = 0; | | 864 | error = 0; |
924 | | | 865 | |
925 | for (ms = (sym = ko->ko_symtab) + ko->ko_symcnt; sym < ms; sym++) { | | 866 | for (ms = (sym = ko->ko_symtab) + ko->ko_symcnt; sym < ms; sym++) { |
926 | /* Check validity of the symbol. */ | | 867 | /* Check validity of the symbol. */ |
927 | if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL || | | 868 | if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL || |
928 | sym->st_name == 0) | | 869 | sym->st_name == 0) |
929 | continue; | | 870 | continue; |
930 | if (undefined != (sym->st_shndx == SHN_UNDEF)) { | | 871 | if (undefined != (sym->st_shndx == SHN_UNDEF)) { |
931 | continue; | | 872 | continue; |
932 | } | | 873 | } |
933 | | | 874 | |
934 | /* | | 875 | /* |
935 | * Look it up. Don't need to lock, as it is known that | | 876 | * Look it up. Don't need to lock, as it is known that |
936 | * the symbol tables aren't going to change (we hold | | 877 | * the symbol tables aren't going to change (we hold |
937 | * module_lock). | | 878 | * module_lock). |
938 | */ | | 879 | */ |
939 | name = ko->ko_strtab + sym->st_name; | | 880 | name = ko->ko_strtab + sym->st_name; |
940 | if (ksyms_getval_unlocked(NULL, name, &rval, | | 881 | if (ksyms_getval_unlocked(NULL, name, &rval, |
941 | KSYMS_EXTERN) != 0) { | | 882 | KSYMS_EXTERN) != 0) { |
942 | if (undefined) { | | 883 | if (undefined) { |
943 | kobj_error("symbol `%s' not found", name); | | 884 | kobj_error("symbol `%s' not found", name); |
944 | error = ENOEXEC; | | 885 | error = ENOEXEC; |
945 | } | | 886 | } |
946 | continue; | | 887 | continue; |
947 | } | | 888 | } |
948 | | | 889 | |
949 | /* Save values of undefined globals. */ | | 890 | /* Save values of undefined globals. */ |
950 | if (undefined) { | | 891 | if (undefined) { |
951 | sym->st_value = (Elf_Addr)rval; | | 892 | sym->st_value = (Elf_Addr)rval; |
952 | continue; | | 893 | continue; |
953 | } | | 894 | } |
954 | | | 895 | |
955 | /* Check (and complain) about differing values. */ | | 896 | /* Check (and complain) about differing values. */ |
956 | if (sym->st_value == rval) { | | 897 | if (sym->st_value == rval) { |
957 | continue; | | 898 | continue; |
958 | } | | 899 | } |
959 | if (strcmp(name, "_bss_start") == 0 || | | 900 | if (strcmp(name, "_bss_start") == 0 || |
960 | strcmp(name, "__bss_start") == 0 || | | 901 | strcmp(name, "__bss_start") == 0 || |
961 | strcmp(name, "_bss_end__") == 0 || | | 902 | strcmp(name, "_bss_end__") == 0 || |
962 | strcmp(name, "__bss_end__") == 0 || | | 903 | strcmp(name, "__bss_end__") == 0 || |
963 | strcmp(name, "_edata") == 0 || | | 904 | strcmp(name, "_edata") == 0 || |
964 | strcmp(name, "_end") == 0 || | | 905 | strcmp(name, "_end") == 0 || |
965 | strcmp(name, "__end") == 0 || | | 906 | strcmp(name, "__end") == 0 || |
966 | strcmp(name, "__end__") == 0 || | | 907 | strcmp(name, "__end__") == 0 || |
967 | strncmp(name, "__start_link_set_", 17) == 0 || | | 908 | strncmp(name, "__start_link_set_", 17) == 0 || |
968 | strncmp(name, "__stop_link_set_", 16)) { | | 909 | strncmp(name, "__stop_link_set_", 16)) { |
969 | continue; | | 910 | continue; |
970 | } | | 911 | } |
971 | kobj_error("global symbol `%s' redefined\n", name); | | 912 | kobj_error("global symbol `%s' redefined\n", name); |
972 | error = ENOEXEC; | | 913 | error = ENOEXEC; |
973 | } | | 914 | } |
974 | | | 915 | |
975 | return error; | | 916 | return error; |
976 | } | | 917 | } |
977 | | | 918 | |
978 | /* | | 919 | /* |
979 | * kobj_relocate: | | 920 | * kobj_relocate: |
980 | * | | 921 | * |
981 | * Resolve relocations for the loaded object. | | 922 | * Resolve relocations for the loaded object. |
982 | */ | | 923 | */ |
983 | static int | | 924 | static int |
984 | kobj_relocate(kobj_t ko, bool local) | | 925 | kobj_relocate(kobj_t ko, bool local) |
985 | { | | 926 | { |
986 | const Elf_Rel *rellim; | | 927 | const Elf_Rel *rellim; |
987 | const Elf_Rel *rel; | | 928 | const Elf_Rel *rel; |
988 | const Elf_Rela *relalim; | | 929 | const Elf_Rela *relalim; |
989 | const Elf_Rela *rela; | | 930 | const Elf_Rela *rela; |
990 | const Elf_Sym *sym; | | 931 | const Elf_Sym *sym; |
991 | uintptr_t base; | | 932 | uintptr_t base; |
992 | int i, error; | | 933 | int i, error; |
993 | uintptr_t symidx; | | 934 | uintptr_t symidx; |
994 | | | 935 | |
995 | /* | | 936 | /* |
996 | * Perform relocations without addend if there are any. | | 937 | * Perform relocations without addend if there are any. |
997 | */ | | 938 | */ |
998 | for (i = 0; i < ko->ko_nrel; i++) { | | 939 | for (i = 0; i < ko->ko_nrel; i++) { |
999 | rel = ko->ko_reltab[i].rel; | | 940 | rel = ko->ko_reltab[i].rel; |
1000 | if (rel == NULL) { | | 941 | if (rel == NULL) { |
1001 | continue; | | 942 | continue; |
1002 | } | | 943 | } |
1003 | rellim = rel + ko->ko_reltab[i].nrel; | | 944 | rellim = rel + ko->ko_reltab[i].nrel; |
1004 | base = kobj_findbase(ko, ko->ko_reltab[i].sec); | | 945 | base = kobj_findbase(ko, ko->ko_reltab[i].sec); |
1005 | if (base == 0) { | | 946 | if (base == 0) { |
1006 | panic("lost base for e_reltab"); | | 947 | panic("lost base for e_reltab"); |
1007 | } | | 948 | } |
1008 | for (; rel < rellim; rel++) { | | 949 | for (; rel < rellim; rel++) { |
1009 | symidx = ELF_R_SYM(rel->r_info); | | 950 | symidx = ELF_R_SYM(rel->r_info); |
1010 | if (symidx >= ko->ko_symcnt) { | | 951 | if (symidx >= ko->ko_symcnt) { |
1011 | continue; | | 952 | continue; |
1012 | } | | 953 | } |
1013 | sym = ko->ko_symtab + symidx; | | 954 | sym = ko->ko_symtab + symidx; |
1014 | if (local != (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) { | | 955 | if (local != (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) { |
1015 | continue; | | 956 | continue; |
1016 | } | | 957 | } |
1017 | error = kobj_reloc(ko, base, rel, false, local); | | 958 | error = kobj_reloc(ko, base, rel, false, local); |
1018 | if (error != 0) { | | 959 | if (error != 0) { |
1019 | return ENOENT; | | 960 | return ENOENT; |
1020 | } | | 961 | } |
1021 | } | | 962 | } |
1022 | } | | 963 | } |
1023 | | | 964 | |
1024 | /* | | 965 | /* |
1025 | * Perform relocations with addend if there are any. | | 966 | * Perform relocations with addend if there are any. |
1026 | */ | | 967 | */ |
1027 | for (i = 0; i < ko->ko_nrela; i++) { | | 968 | for (i = 0; i < ko->ko_nrela; i++) { |
1028 | rela = ko->ko_relatab[i].rela; | | 969 | rela = ko->ko_relatab[i].rela; |
1029 | if (rela == NULL) { | | 970 | if (rela == NULL) { |
1030 | continue; | | 971 | continue; |
1031 | } | | 972 | } |
1032 | relalim = rela + ko->ko_relatab[i].nrela; | | 973 | relalim = rela + ko->ko_relatab[i].nrela; |
1033 | base = kobj_findbase(ko, ko->ko_relatab[i].sec); | | 974 | base = kobj_findbase(ko, ko->ko_relatab[i].sec); |
1034 | if (base == 0) { | | 975 | if (base == 0) { |
1035 | panic("lost base for e_relatab"); | | 976 | panic("lost base for e_relatab"); |
1036 | } | | 977 | } |
1037 | for (; rela < relalim; rela++) { | | 978 | for (; rela < relalim; rela++) { |
1038 | symidx = ELF_R_SYM(rela->r_info); | | 979 | symidx = ELF_R_SYM(rela->r_info); |
1039 | if (symidx >= ko->ko_symcnt) { | | 980 | if (symidx >= ko->ko_symcnt) { |
1040 | continue; | | 981 | continue; |
1041 | } | | 982 | } |
1042 | sym = ko->ko_symtab + symidx; | | 983 | sym = ko->ko_symtab + symidx; |
1043 | if (local != (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) { | | 984 | if (local != (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) { |
1044 | continue; | | 985 | continue; |
1045 | } | | 986 | } |
1046 | error = kobj_reloc(ko, base, rela, true, local); | | 987 | error = kobj_reloc(ko, base, rela, true, local); |
1047 | if (error != 0) { | | 988 | if (error != 0) { |
1048 | return ENOENT; | | 989 | return ENOENT; |
1049 | } | | 990 | } |
1050 | } | | 991 | } |
1051 | } | | 992 | } |
1052 | | | 993 | |
1053 | return 0; | | 994 | return 0; |
1054 | } | | 995 | } |
1055 | | | 996 | |
1056 | /* | | 997 | /* |
1057 | * kobj_error: | | 998 | * kobj_error: |
1058 | * | | 999 | * |
1059 | * Utility function: log an error. | | 1000 | * Utility function: log an error. |
1060 | */ | | 1001 | */ |
1061 | static void | | 1002 | static void |
1062 | kobj_error(const char *fmt, ...) | | 1003 | kobj_error(const char *fmt, ...) |
1063 | { | | 1004 | { |
1064 | va_list ap; | | 1005 | va_list ap; |
1065 | | | 1006 | |
1066 | va_start(ap, fmt); | | 1007 | va_start(ap, fmt); |
1067 | printf("WARNING: linker error: "); | | 1008 | printf("WARNING: linker error: "); |
1068 | vprintf(fmt, ap); | | 1009 | vprintf(fmt, ap); |
1069 | printf("\n"); | | 1010 | printf("\n"); |
1070 | va_end(ap); | | 1011 | va_end(ap); |
1071 | } | | 1012 | } |
1072 | | | 1013 | |
1073 | /* | | 1014 | /* |
1074 | * kobj_read: | | 1015 | * kobj_read: |
1075 | * | | 1016 | * |
1076 | * Utility function: read from the object. | | 1017 | * Utility function: read from the object. |
1077 | */ | | 1018 | */ |
1078 | static int | | 1019 | static int |
1079 | kobj_read(kobj_t ko, void **basep, size_t size, off_t off) | | 1020 | kobj_read(kobj_t ko, void **basep, size_t size, off_t off) |
1080 | { | | 1021 | { |
1081 | size_t resid; | | 1022 | size_t resid; |
1082 | void *base; | | 1023 | void *base; |
1083 | int error; | | 1024 | int error; |
1084 | | | 1025 | |
1085 | KASSERT(ko->ko_source != NULL); | | 1026 | KASSERT(ko->ko_source != NULL); |
1086 | | | 1027 | |
1087 | switch (ko->ko_type) { | | 1028 | switch (ko->ko_type) { |
1088 | case KT_VNODE: | | 1029 | case KT_VNODE: |
1089 | base = kmem_alloc(size, KM_SLEEP); | | 1030 | base = kmem_alloc(size, KM_SLEEP); |
1090 | if (base == NULL) { | | 1031 | if (base == NULL) { |
1091 | error = ENOMEM; | | 1032 | error = ENOMEM; |
1092 | break; | | 1033 | break; |
1093 | } | | 1034 | } |
1094 | error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, | | 1035 | error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, |
1095 | UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, | | 1036 | UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, |
1096 | curlwp); | | 1037 | curlwp); |
1097 | if (error == 0 && resid != 0) { | | 1038 | if (error == 0 && resid != 0) { |
1098 | error = EINVAL; | | 1039 | error = EINVAL; |
1099 | } | | 1040 | } |
1100 | if (error != 0) { | | 1041 | if (error != 0) { |
1101 | kmem_free(base, size); | | 1042 | kmem_free(base, size); |
1102 | base = NULL; | | 1043 | base = NULL; |
1103 | } | | 1044 | } |
1104 | break; | | 1045 | break; |
1105 | case KT_MEMORY: | | 1046 | case KT_MEMORY: |
1106 | if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) { | | 1047 | if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) { |
1107 | kobj_error("kobj_read: preloaded object short"); | | 1048 | kobj_error("kobj_read: preloaded object short"); |
1108 | error = EINVAL; | | 1049 | error = EINVAL; |
1109 | base = NULL; | | 1050 | base = NULL; |
1110 | } else { | | 1051 | } else { |
1111 | base = (uint8_t *)ko->ko_source + off; | | 1052 | base = (uint8_t *)ko->ko_source + off; |
1112 | error = 0; | | 1053 | error = 0; |
1113 | } | | 1054 | } |
1114 | break; | | 1055 | break; |
1115 | default: | | 1056 | default: |
1116 | panic("kobj_read: invalid type"); | | 1057 | panic("kobj_read: invalid type"); |
1117 | } | | 1058 | } |
1118 | | | 1059 | |
1119 | *basep = base; | | 1060 | *basep = base; |
1120 | return error; | | 1061 | return error; |
1121 | } | | 1062 | } |
1122 | | | 1063 | |
1123 | /* | | 1064 | /* |
1124 | * kobj_read_bits: | | 1065 | * kobj_read_bits: |
1125 | * | | 1066 | * |
1126 | * Utility function: load a section from the object. | | 1067 | * Utility function: load a section from the object. |
1127 | */ | | 1068 | */ |
1128 | static int | | 1069 | static int |
1129 | kobj_read_bits(kobj_t ko, void *base, size_t size, off_t off) | | 1070 | kobj_read_bits(kobj_t ko, void *base, size_t size, off_t off) |
1130 | { | | 1071 | { |
1131 | size_t resid; | | 1072 | size_t resid; |
1132 | int error; | | 1073 | int error; |
1133 | | | 1074 | |
1134 | KASSERT(ko->ko_source != NULL); | | 1075 | KASSERT(ko->ko_source != NULL); |
1135 | | | 1076 | |
1136 | switch (ko->ko_type) { | | 1077 | switch (ko->ko_type) { |
1137 | case KT_VNODE: | | 1078 | case KT_VNODE: |
1138 | KASSERT((uintptr_t)base >= (uintptr_t)ko->ko_address); | | 1079 | KASSERT((uintptr_t)base >= (uintptr_t)ko->ko_address); |
1139 | KASSERT((uintptr_t)base + size <= | | 1080 | KASSERT((uintptr_t)base + size <= |
1140 | (uintptr_t)ko->ko_address + ko->ko_size); | | 1081 | (uintptr_t)ko->ko_address + ko->ko_size); |
1141 | error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, | | 1082 | error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, |
1142 | UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, | | 1083 | UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, |
1143 | curlwp); | | 1084 | curlwp); |
1144 | if (error == 0 && resid != 0) { | | 1085 | if (error == 0 && resid != 0) { |
1145 | error = EINVAL; | | 1086 | error = EINVAL; |