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