Deleted Added
full compact
link_elf.c (40397) link_elf.c (40435)
1/*-
2 * Copyright (c) 1998 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1998 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: link_elf.c,v 1.5 1998/10/13 09:27:00 peter Exp $
26 * $Id: link_elf.c,v 1.6 1998/10/15 17:16:24 peter Exp $
27 */
28
29#include <sys/param.h>
30#include <sys/kernel.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/proc.h>
34#include <sys/namei.h>
35#include <sys/fcntl.h>
36#include <sys/vnode.h>
37#include <sys/linker.h>
38#include <machine/elf.h>
39
40#include <vm/vm.h>
41#include <vm/vm_prot.h>
42#include <vm/vm_param.h>
43#include <sys/lock.h>
44#include <vm/vm_object.h>
45#include <vm/vm_kern.h>
46#include <vm/vm_extern.h>
47#include <vm/pmap.h>
48#include <vm/vm_map.h>
49
50static int link_elf_load_module(const char*, linker_file_t*);
51static int link_elf_load_file(const char*, linker_file_t*);
52static int link_elf_lookup_symbol(linker_file_t, const char*,
53 linker_sym_t*);
54static int link_elf_symbol_values(linker_file_t, linker_sym_t, linker_symval_t*);
55static int link_elf_search_symbol(linker_file_t, caddr_t value,
56 linker_sym_t* sym, long* diffp);
57
58static void link_elf_unload_file(linker_file_t);
59static void link_elf_unload_module(linker_file_t);
60
61/*
62 * The file representing the currently running kernel. This contains
63 * the global symbol table.
64 */
65
66linker_file_t linker_kernel_file;
67
68static struct linker_class_ops link_elf_class_ops = {
69 link_elf_load_module,
70};
71
72static struct linker_file_ops link_elf_file_ops = {
73 link_elf_lookup_symbol,
74 link_elf_symbol_values,
75 link_elf_search_symbol,
76 link_elf_unload_file,
77};
78
79static struct linker_file_ops link_elf_module_ops = {
80 link_elf_lookup_symbol,
81 link_elf_symbol_values,
82 link_elf_search_symbol,
83 link_elf_unload_module,
84};
85typedef struct elf_file {
86 caddr_t address; /* Relocation address */
87#ifdef SPARSE_MAPPING
88 vm_object_t object; /* VM object to hold file pages */
89#endif
90 const Elf_Dyn* dynamic; /* Symbol table etc. */
91 Elf_Off nbuckets; /* DT_HASH info */
92 Elf_Off nchains;
93 const Elf_Off* buckets;
94 const Elf_Off* chains;
95 caddr_t hash;
96 caddr_t strtab; /* DT_STRTAB */
97 int strsz; /* DT_STRSZ */
98 const Elf_Sym* symtab; /* DT_SYMTAB */
99 Elf_Addr* got; /* DT_PLTGOT */
100 const Elf_Rel* pltrel; /* DT_JMPREL */
101 int pltrelsize; /* DT_PLTRELSZ */
102 const Elf_Rela* pltrela; /* DT_JMPREL */
103 int pltrelasize; /* DT_PLTRELSZ */
104 const Elf_Rel* rel; /* DT_REL */
105 int relsize; /* DT_RELSZ */
106 const Elf_Rela* rela; /* DT_RELA */
107 int relasize; /* DT_RELASZ */
108 caddr_t modptr;
109 const Elf_Sym* ddbsymtab; /* The symbol table we are using */
110 long ddbsymcnt; /* Number of symbols */
111 caddr_t ddbstrtab; /* String table */
112 long ddbstrcnt; /* number of bytes in string table */
113 caddr_t symbase; /* malloc'ed symbold base */
114 caddr_t strbase; /* malloc'ed string base */
115} *elf_file_t;
116
117static int parse_dynamic(linker_file_t lf);
118static int load_dependancies(linker_file_t lf);
119static int relocate_file(linker_file_t lf);
120static int parse_module_symbols(linker_file_t lf);
121
122/*
123 * The kernel symbol table starts here.
124 */
125extern struct _dynamic _DYNAMIC;
126
127static void
128link_elf_init(void* arg)
129{
130#ifdef __ELF__
131 Elf_Dyn *dp;
132 caddr_t modptr, baseptr, sizeptr;
133 elf_file_t ef;
134 char *modname;
135#endif
136
137#if ELF_TARG_CLASS == ELFCLASS32
138 linker_add_class("elf32", NULL, &link_elf_class_ops);
139#else
140 linker_add_class("elf64", NULL, &link_elf_class_ops);
141#endif
142
143#ifdef __ELF__
144 dp = (Elf_Dyn*) &_DYNAMIC;
145 if (dp) {
146 ef = malloc(sizeof(struct elf_file), M_LINKER, M_NOWAIT);
147 if (ef == NULL)
148 panic("link_elf_init: Can't create linker structures for kernel");
149 bzero(ef, sizeof(*ef));
150
151 ef->address = 0;
152#ifdef SPARSE_MAPPING
153 ef->object = 0;
154#endif
155 ef->dynamic = dp;
156 modname = NULL;
157 modptr = preload_search_by_type("elf kernel");
158 if (modptr)
159 modname = (char *)preload_search_info(modptr, MODINFO_NAME);
160 if (modname == NULL)
161 modname = "kernel";
162 linker_kernel_file = linker_make_file(modname, ef, &link_elf_file_ops);
163 if (linker_kernel_file == NULL)
164 panic("link_elf_init: Can't create linker structures for kernel");
165 parse_dynamic(linker_kernel_file);
166 /* Sigh, magic constants. */
167#ifdef __alpha__
168 linker_kernel_file->address = (caddr_t) 0xfffffc0000300000;
169#else
170 linker_kernel_file->address = (caddr_t) 0xf0100000;
171#endif
172 linker_kernel_file->size = -(long)linker_kernel_file->address;
173
174 if (modptr) {
175 ef->modptr = modptr;
176 baseptr = preload_search_info(modptr, MODINFO_ADDR);
177 if (baseptr)
178 linker_kernel_file->address = *(caddr_t *)baseptr;
179 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
180 if (sizeptr)
181 linker_kernel_file->size = *(size_t *)sizeptr;
182 }
183 (void)parse_module_symbols(linker_kernel_file);
184 linker_current_file = linker_kernel_file;
185 }
186#endif
187}
188
189SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
190
191static int
192parse_module_symbols(linker_file_t lf)
193{
194 elf_file_t ef = lf->priv;
195 caddr_t pointer;
196 caddr_t ssym, esym, base;
197 caddr_t strtab;
198 int strcnt;
199 Elf_Sym* symtab;
200 int symcnt;
201
202 if (ef->modptr == NULL)
203 return 0;
204 pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM);
205 if (pointer == NULL)
206 return 0;
207 ssym = *(caddr_t *)pointer;
208 pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM);
209 if (pointer == NULL)
210 return 0;
211 esym = *(caddr_t *)pointer;
212
213 base = ssym;
214
215 symcnt = *(long *)base;
216 base += sizeof(long);
217 symtab = (Elf_Sym *)base;
218 base += roundup(symcnt, sizeof(long));
219
220 if (base > esym || base < ssym) {
221 printf("Symbols are corrupt!\n");
222 return EINVAL;
223 }
224
225 strcnt = *(long *)base;
226 base += sizeof(long);
227 strtab = base;
228 base += roundup(strcnt, sizeof(long));
229
230 if (base > esym || base < ssym) {
231 printf("Symbols are corrupt!\n");
232 return EINVAL;
233 }
234
235 ef->ddbsymtab = symtab;
236 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
237 ef->ddbstrtab = strtab;
238 ef->ddbstrcnt = strcnt;
239
240 return 0;
241}
242
243static int
244parse_dynamic(linker_file_t lf)
245{
246 elf_file_t ef = lf->priv;
247 const Elf_Dyn *dp;
248 int plttype = DT_REL;
249
250 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
251 switch (dp->d_tag) {
252 case DT_HASH:
253 {
254 /* From src/libexec/rtld-elf/rtld.c */
255 const Elf_Off *hashtab = (const Elf_Off *)
256 (ef->address + dp->d_un.d_ptr);
257 ef->nbuckets = hashtab[0];
258 ef->nchains = hashtab[1];
259 ef->buckets = hashtab + 2;
260 ef->chains = ef->buckets + ef->nbuckets;
261 break;
262 }
263 case DT_STRTAB:
264 ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr);
265 break;
266 case DT_STRSZ:
267 ef->strsz = dp->d_un.d_val;
268 break;
269 case DT_SYMTAB:
270 ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr);
271 break;
272 case DT_SYMENT:
273 if (dp->d_un.d_val != sizeof(Elf_Sym))
274 return ENOEXEC;
275 break;
276 case DT_PLTGOT:
277 ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr);
278 break;
279 case DT_REL:
280 ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
281 break;
282 case DT_RELSZ:
283 ef->relsize = dp->d_un.d_val;
284 break;
285 case DT_RELENT:
286 if (dp->d_un.d_val != sizeof(Elf_Rel))
287 return ENOEXEC;
288 break;
289 case DT_JMPREL:
290 ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
291 break;
292 case DT_PLTRELSZ:
293 ef->pltrelsize = dp->d_un.d_val;
294 break;
295 case DT_RELA:
296 ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr);
297 break;
298 case DT_RELASZ:
299 ef->relasize = dp->d_un.d_val;
300 break;
301 case DT_RELAENT:
302 if (dp->d_un.d_val != sizeof(Elf_Rela))
303 return ENOEXEC;
304 break;
305 case DT_PLTREL:
306 plttype = dp->d_un.d_val;
307 if (plttype != DT_REL && plttype != DT_RELA)
308 return ENOEXEC;
309 break;
310 }
311 }
312
313 if (plttype == DT_RELA) {
314 ef->pltrela = (const Elf_Rela *) ef->pltrel;
315 ef->pltrel = NULL;
316 ef->pltrelasize = ef->pltrelsize;
317 ef->pltrelsize = 0;
318 }
319
320 ef->ddbsymtab = ef->symtab;
321 ef->ddbsymcnt = ef->nchains;
322 ef->ddbstrtab = ef->strtab;
323 ef->ddbstrcnt = ef->strsz;
324
325 return 0;
326}
327
328static void
329link_elf_error(const char *s)
330{
331 printf("kldload: %s\n", s);
332}
333
334static int
335link_elf_load_module(const char *filename, linker_file_t *result)
336{
337 caddr_t modptr, baseptr, sizeptr, dynptr;
338 char *type;
339 elf_file_t ef;
340 linker_file_t lf;
341 int error;
342 vm_offset_t dp;
343
344 /* Look to see if we have the module preloaded */
345 modptr = preload_search_by_name(filename);
346 if (modptr == NULL)
347 return (link_elf_load_file(filename, result));
348
349 /* It's preloaded, check we can handle it and collect information */
350 type = (char *)preload_search_info(modptr, MODINFO_TYPE);
351 baseptr = preload_search_info(modptr, MODINFO_ADDR);
352 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
353 dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC);
354 if (type == NULL || strcmp(type, "elf module") != 0)
355 return (EFTYPE);
356 if (baseptr == NULL || sizeptr == NULL || dynptr == NULL)
357 return (EINVAL);
358
359 ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK);
360 if (ef == NULL)
361 return (ENOMEM);
362 bzero(ef, sizeof(*ef));
363 ef->modptr = modptr;
364 ef->address = *(caddr_t *)baseptr;
365#ifdef SPARSE_MAPPING
366 ef->object = 0;
367#endif
368 dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr;
369 ef->dynamic = (Elf_Dyn *)dp;
370 lf = linker_make_file(filename, ef, &link_elf_module_ops);
371 if (lf == NULL) {
372 free(ef, M_LINKER);
373 return ENOMEM;
374 }
375 lf->address = ef->address;
376 lf->size = *(size_t *)sizeptr;
377
378 error = parse_dynamic(lf);
379 if (error) {
380 linker_file_unload(lf);
381 return error;
382 }
383 error = load_dependancies(lf);
384 if (error) {
385 linker_file_unload(lf);
386 return error;
387 }
388 error = relocate_file(lf);
389 if (error) {
390 linker_file_unload(lf);
391 return error;
392 }
393 (void)parse_module_symbols(lf);
394 *result = lf;
395 return (0);
396}
397
398static int
399link_elf_load_file(const char* filename, linker_file_t* result)
400{
401 struct nameidata nd;
402 struct proc* p = curproc; /* XXX */
403 union {
404 Elf_Ehdr hdr;
405 char buf[PAGE_SIZE];
406 } u;
407 int nbytes, i;
408 Elf_Phdr *phdr;
409 Elf_Phdr *phlimit;
410 Elf_Phdr *segs[2];
411 int nsegs;
412 Elf_Phdr *phdyn;
413 Elf_Phdr *phphdr;
414 caddr_t mapbase;
415 size_t mapsize;
416 Elf_Off base_offset;
417 Elf_Addr base_vaddr;
418 Elf_Addr base_vlimit;
419 caddr_t base_addr;
420 Elf_Off data_offset;
421 Elf_Addr data_vaddr;
422 Elf_Addr data_vlimit;
423 caddr_t data_addr;
424 Elf_Addr clear_vaddr;
425 caddr_t clear_addr;
426 size_t nclear;
427 Elf_Addr bss_vaddr;
428 Elf_Addr bss_vlimit;
429 caddr_t bss_addr;
430 int error = 0;
431 int resid;
432 elf_file_t ef;
433 linker_file_t lf;
434 char *pathname;
435 Elf_Shdr *shdr;
436 int symtabindex;
437 int symstrindex;
438 int symcnt;
439 int strcnt;
440
441 shdr = NULL;
442 lf = NULL;
443
444 pathname = linker_search_path(filename);
445 if (pathname == NULL)
446 return ENOENT;
447 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, pathname, p);
448 error = vn_open(&nd, FREAD, 0);
449 free(pathname, M_LINKER);
450 if (error)
451 return error;
452
453 /*
454 * Read the elf header from the file.
455 */
456 error = vn_rdwr(UIO_READ, nd.ni_vp, (void*) &u, sizeof u, 0,
457 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
458 nbytes = sizeof u - resid;
459 if (error)
460 goto out;
461
462 if (!IS_ELF(u.hdr)) {
463 error = ENOEXEC;
464 goto out;
465 }
466
467 if (u.hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS
468 || u.hdr.e_ident[EI_DATA] != ELF_TARG_DATA) {
469 link_elf_error("Unsupported file layout");
470 error = ENOEXEC;
471 goto out;
472 }
473 if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT
474 || u.hdr.e_version != EV_CURRENT) {
475 link_elf_error("Unsupported file version");
476 error = ENOEXEC;
477 goto out;
478 }
479 if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) {
480 link_elf_error("Unsupported file type");
481 error = ENOEXEC;
482 goto out;
483 }
484 if (u.hdr.e_machine != ELF_TARG_MACH) {
485 link_elf_error("Unsupported machine");
486 error = ENOEXEC;
487 goto out;
488 }
489
490 /*
491 * We rely on the program header being in the first page. This is
492 * not strictly required by the ABI specification, but it seems to
493 * always true in practice. And, it simplifies things considerably.
494 */
495 if (!((u.hdr.e_phentsize == sizeof(Elf_Phdr))
496 || (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE)
497 || (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= nbytes)))
498 link_elf_error("Unreadable program headers");
499
500 /*
501 * Scan the program header entries, and save key information.
502 *
503 * We rely on there being exactly two load segments, text and data,
504 * in that order.
505 */
506 phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff);
507 phlimit = phdr + u.hdr.e_phnum;
508 nsegs = 0;
509 phdyn = NULL;
510 phphdr = NULL;
511 while (phdr < phlimit) {
512 switch (phdr->p_type) {
513
514 case PT_LOAD:
515 if (nsegs == 2) {
516 link_elf_error("Too many sections");
517 error = ENOEXEC;
518 goto out;
519 }
520 segs[nsegs] = phdr;
521 ++nsegs;
522 break;
523
524 case PT_PHDR:
525 phphdr = phdr;
526 break;
527
528 case PT_DYNAMIC:
529 phdyn = phdr;
530 break;
531 }
532
533 ++phdr;
534 }
535 if (phdyn == NULL) {
536 link_elf_error("Object is not dynamically-linked");
537 error = ENOEXEC;
538 goto out;
539 }
540
541 /*
542 * Allocate the entire address space of the object, to stake out our
543 * contiguous region, and to establish the base address for relocation.
544 */
545 base_offset = trunc_page(segs[0]->p_offset);
546 base_vaddr = trunc_page(segs[0]->p_vaddr);
547 base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
548 mapsize = base_vlimit - base_vaddr;
549
550 ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK);
551 bzero(ef, sizeof(*ef));
552#ifdef SPARSE_MAPPING
553 ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
554 if (ef->object == NULL) {
555 free(ef, M_LINKER);
556 error = ENOMEM;
557 goto out;
558 }
559 vm_object_reference(ef->object);
560 ef->address = (caddr_t) vm_map_min(kernel_map);
561 error = vm_map_find(kernel_map, ef->object, 0,
562 (vm_offset_t *) &ef->address,
563 mapsize, 1,
564 VM_PROT_ALL, VM_PROT_ALL, 0);
565 if (error) {
566 vm_object_deallocate(ef->object);
567 free(ef, M_LINKER);
568 goto out;
569 }
570#else
571 ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
572#endif
573 mapbase = ef->address;
574
575 /*
576 * Read the text and data sections and zero the bss.
577 */
578 for (i = 0; i < 2; i++) {
579 caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
580 error = vn_rdwr(UIO_READ, nd.ni_vp,
581 segbase, segs[i]->p_filesz, segs[i]->p_offset,
582 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
583 if (error) {
584#ifdef SPARSE_MAPPING
585 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
586 (vm_offset_t) ef->address
587 + (ef->object->size << PAGE_SHIFT));
588 vm_object_deallocate(ef->object);
589#else
590 free(ef->address, M_LINKER);
591#endif
592 free(ef, M_LINKER);
593 goto out;
594 }
595 bzero(segbase + segs[i]->p_filesz,
596 segs[i]->p_memsz - segs[i]->p_filesz);
597
598#ifdef SPARSE_MAPPING
599 /*
600 * Wire down the pages
601 */
602 vm_map_pageable(kernel_map,
603 (vm_offset_t) segbase,
604 (vm_offset_t) segbase + segs[i]->p_memsz,
605 FALSE);
606#endif
607 }
608
609 ef->dynamic = (const Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr);
610
611 lf = linker_make_file(filename, ef, &link_elf_file_ops);
612 if (lf == NULL) {
613#ifdef SPARSE_MAPPING
614 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
615 (vm_offset_t) ef->address
616 + (ef->object->size << PAGE_SHIFT));
617 vm_object_deallocate(ef->object);
618#else
619 free(ef->address, M_LINKER);
620#endif
621 free(ef, M_LINKER);
622 error = ENOMEM;
623 goto out;
624 }
625 lf->address = ef->address;
626 lf->size = mapsize;
627
628 error = parse_dynamic(lf);
629 if (error)
630 goto out;
631 error = load_dependancies(lf);
632 if (error)
633 goto out;
634 error = relocate_file(lf);
635 if (error)
636 goto out;
637
638 /* Try and load the symbol table if it's present. (you can strip it!) */
639 nbytes = u.hdr.e_shnum * u.hdr.e_shentsize;
640 if (nbytes == 0 || u.hdr.e_shoff == 0)
641 goto nosyms;
642 shdr = malloc(nbytes, M_LINKER, M_WAITOK);
643 if (shdr == NULL) {
644 error = ENOMEM;
645 goto out;
646 }
647 bzero(shdr, nbytes);
648 error = vn_rdwr(UIO_READ, nd.ni_vp,
649 (caddr_t)shdr, nbytes, u.hdr.e_shoff,
650 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
651 if (error)
652 goto out;
653 symtabindex = -1;
654 symstrindex = -1;
655 for (i = 0; i < u.hdr.e_shnum; i++) {
656 if (shdr[i].sh_type == SHT_SYMTAB) {
657 symtabindex = i;
658 symstrindex = shdr[i].sh_link;
659 }
660 }
661 if (symtabindex < 0 || symstrindex < 0)
662 goto nosyms;
663
664 symcnt = shdr[symtabindex].sh_size;
665 ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK);
666 strcnt = shdr[symstrindex].sh_size;
667 ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK);
668
669 if (ef->symbase == NULL || ef->strbase == NULL) {
670 error = ENOMEM;
671 goto out;
672 }
673 error = vn_rdwr(UIO_READ, nd.ni_vp,
674 ef->symbase, symcnt, shdr[symtabindex].sh_offset,
675 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
676 if (error)
677 goto out;
678 error = vn_rdwr(UIO_READ, nd.ni_vp,
679 ef->strbase, strcnt, shdr[symstrindex].sh_offset,
680 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
681 if (error)
682 goto out;
683
684 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
685 ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
686 ef->ddbstrcnt = strcnt;
687 ef->ddbstrtab = ef->strbase;
688
689nosyms:
690
691 *result = lf;
692
693out:
694 if (error && lf)
695 linker_file_unload(lf);
696 if (shdr)
697 free(shdr, M_LINKER);
698 VOP_UNLOCK(nd.ni_vp, 0, p);
699 vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
700
701 return error;
702}
703
704static void
705link_elf_unload_file(linker_file_t file)
706{
707 elf_file_t ef = file->priv;
708
709 if (ef) {
710#ifdef SPARSE_MAPPING
711 if (ef->object) {
712 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
713 (vm_offset_t) ef->address
714 + (ef->object->size << PAGE_SHIFT));
715 vm_object_deallocate(ef->object);
716 }
717#else
718 if (ef->address)
719 free(ef->address, M_LINKER);
720#endif
721 if (ef->symbase)
722 free(ef->symbase, M_LINKER);
723 if (ef->strbase)
724 free(ef->strbase, M_LINKER);
725 free(ef, M_LINKER);
726 }
727}
728
729static void
730link_elf_unload_module(linker_file_t file)
731{
732 elf_file_t ef = file->priv;
733
734 if (ef)
735 free(ef, M_LINKER);
736 if (file->filename)
737 preload_delete_name(file->filename);
738}
739
740static int
741load_dependancies(linker_file_t lf)
742{
743 elf_file_t ef = lf->priv;
744 linker_file_t lfdep;
745 char* name;
746 const Elf_Dyn *dp;
747 int error = 0;
748
749 /*
750 * All files are dependant on /kernel.
751 */
752 linker_kernel_file->refs++;
753 linker_file_add_dependancy(lf, linker_kernel_file);
754
755
756 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
757 if (dp->d_tag == DT_NEEDED) {
758 name = ef->strtab + dp->d_un.d_val;
759
760 error = linker_load_file(name, &lfdep);
761 if (error)
762 goto out;
763 error = linker_file_add_dependancy(lf, lfdep);
764 if (error)
765 goto out;
766 }
767 }
768
769out:
770 return error;
771}
772
773static const char *
27 */
28
29#include <sys/param.h>
30#include <sys/kernel.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/proc.h>
34#include <sys/namei.h>
35#include <sys/fcntl.h>
36#include <sys/vnode.h>
37#include <sys/linker.h>
38#include <machine/elf.h>
39
40#include <vm/vm.h>
41#include <vm/vm_prot.h>
42#include <vm/vm_param.h>
43#include <sys/lock.h>
44#include <vm/vm_object.h>
45#include <vm/vm_kern.h>
46#include <vm/vm_extern.h>
47#include <vm/pmap.h>
48#include <vm/vm_map.h>
49
50static int link_elf_load_module(const char*, linker_file_t*);
51static int link_elf_load_file(const char*, linker_file_t*);
52static int link_elf_lookup_symbol(linker_file_t, const char*,
53 linker_sym_t*);
54static int link_elf_symbol_values(linker_file_t, linker_sym_t, linker_symval_t*);
55static int link_elf_search_symbol(linker_file_t, caddr_t value,
56 linker_sym_t* sym, long* diffp);
57
58static void link_elf_unload_file(linker_file_t);
59static void link_elf_unload_module(linker_file_t);
60
61/*
62 * The file representing the currently running kernel. This contains
63 * the global symbol table.
64 */
65
66linker_file_t linker_kernel_file;
67
68static struct linker_class_ops link_elf_class_ops = {
69 link_elf_load_module,
70};
71
72static struct linker_file_ops link_elf_file_ops = {
73 link_elf_lookup_symbol,
74 link_elf_symbol_values,
75 link_elf_search_symbol,
76 link_elf_unload_file,
77};
78
79static struct linker_file_ops link_elf_module_ops = {
80 link_elf_lookup_symbol,
81 link_elf_symbol_values,
82 link_elf_search_symbol,
83 link_elf_unload_module,
84};
85typedef struct elf_file {
86 caddr_t address; /* Relocation address */
87#ifdef SPARSE_MAPPING
88 vm_object_t object; /* VM object to hold file pages */
89#endif
90 const Elf_Dyn* dynamic; /* Symbol table etc. */
91 Elf_Off nbuckets; /* DT_HASH info */
92 Elf_Off nchains;
93 const Elf_Off* buckets;
94 const Elf_Off* chains;
95 caddr_t hash;
96 caddr_t strtab; /* DT_STRTAB */
97 int strsz; /* DT_STRSZ */
98 const Elf_Sym* symtab; /* DT_SYMTAB */
99 Elf_Addr* got; /* DT_PLTGOT */
100 const Elf_Rel* pltrel; /* DT_JMPREL */
101 int pltrelsize; /* DT_PLTRELSZ */
102 const Elf_Rela* pltrela; /* DT_JMPREL */
103 int pltrelasize; /* DT_PLTRELSZ */
104 const Elf_Rel* rel; /* DT_REL */
105 int relsize; /* DT_RELSZ */
106 const Elf_Rela* rela; /* DT_RELA */
107 int relasize; /* DT_RELASZ */
108 caddr_t modptr;
109 const Elf_Sym* ddbsymtab; /* The symbol table we are using */
110 long ddbsymcnt; /* Number of symbols */
111 caddr_t ddbstrtab; /* String table */
112 long ddbstrcnt; /* number of bytes in string table */
113 caddr_t symbase; /* malloc'ed symbold base */
114 caddr_t strbase; /* malloc'ed string base */
115} *elf_file_t;
116
117static int parse_dynamic(linker_file_t lf);
118static int load_dependancies(linker_file_t lf);
119static int relocate_file(linker_file_t lf);
120static int parse_module_symbols(linker_file_t lf);
121
122/*
123 * The kernel symbol table starts here.
124 */
125extern struct _dynamic _DYNAMIC;
126
127static void
128link_elf_init(void* arg)
129{
130#ifdef __ELF__
131 Elf_Dyn *dp;
132 caddr_t modptr, baseptr, sizeptr;
133 elf_file_t ef;
134 char *modname;
135#endif
136
137#if ELF_TARG_CLASS == ELFCLASS32
138 linker_add_class("elf32", NULL, &link_elf_class_ops);
139#else
140 linker_add_class("elf64", NULL, &link_elf_class_ops);
141#endif
142
143#ifdef __ELF__
144 dp = (Elf_Dyn*) &_DYNAMIC;
145 if (dp) {
146 ef = malloc(sizeof(struct elf_file), M_LINKER, M_NOWAIT);
147 if (ef == NULL)
148 panic("link_elf_init: Can't create linker structures for kernel");
149 bzero(ef, sizeof(*ef));
150
151 ef->address = 0;
152#ifdef SPARSE_MAPPING
153 ef->object = 0;
154#endif
155 ef->dynamic = dp;
156 modname = NULL;
157 modptr = preload_search_by_type("elf kernel");
158 if (modptr)
159 modname = (char *)preload_search_info(modptr, MODINFO_NAME);
160 if (modname == NULL)
161 modname = "kernel";
162 linker_kernel_file = linker_make_file(modname, ef, &link_elf_file_ops);
163 if (linker_kernel_file == NULL)
164 panic("link_elf_init: Can't create linker structures for kernel");
165 parse_dynamic(linker_kernel_file);
166 /* Sigh, magic constants. */
167#ifdef __alpha__
168 linker_kernel_file->address = (caddr_t) 0xfffffc0000300000;
169#else
170 linker_kernel_file->address = (caddr_t) 0xf0100000;
171#endif
172 linker_kernel_file->size = -(long)linker_kernel_file->address;
173
174 if (modptr) {
175 ef->modptr = modptr;
176 baseptr = preload_search_info(modptr, MODINFO_ADDR);
177 if (baseptr)
178 linker_kernel_file->address = *(caddr_t *)baseptr;
179 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
180 if (sizeptr)
181 linker_kernel_file->size = *(size_t *)sizeptr;
182 }
183 (void)parse_module_symbols(linker_kernel_file);
184 linker_current_file = linker_kernel_file;
185 }
186#endif
187}
188
189SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
190
191static int
192parse_module_symbols(linker_file_t lf)
193{
194 elf_file_t ef = lf->priv;
195 caddr_t pointer;
196 caddr_t ssym, esym, base;
197 caddr_t strtab;
198 int strcnt;
199 Elf_Sym* symtab;
200 int symcnt;
201
202 if (ef->modptr == NULL)
203 return 0;
204 pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM);
205 if (pointer == NULL)
206 return 0;
207 ssym = *(caddr_t *)pointer;
208 pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM);
209 if (pointer == NULL)
210 return 0;
211 esym = *(caddr_t *)pointer;
212
213 base = ssym;
214
215 symcnt = *(long *)base;
216 base += sizeof(long);
217 symtab = (Elf_Sym *)base;
218 base += roundup(symcnt, sizeof(long));
219
220 if (base > esym || base < ssym) {
221 printf("Symbols are corrupt!\n");
222 return EINVAL;
223 }
224
225 strcnt = *(long *)base;
226 base += sizeof(long);
227 strtab = base;
228 base += roundup(strcnt, sizeof(long));
229
230 if (base > esym || base < ssym) {
231 printf("Symbols are corrupt!\n");
232 return EINVAL;
233 }
234
235 ef->ddbsymtab = symtab;
236 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
237 ef->ddbstrtab = strtab;
238 ef->ddbstrcnt = strcnt;
239
240 return 0;
241}
242
243static int
244parse_dynamic(linker_file_t lf)
245{
246 elf_file_t ef = lf->priv;
247 const Elf_Dyn *dp;
248 int plttype = DT_REL;
249
250 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
251 switch (dp->d_tag) {
252 case DT_HASH:
253 {
254 /* From src/libexec/rtld-elf/rtld.c */
255 const Elf_Off *hashtab = (const Elf_Off *)
256 (ef->address + dp->d_un.d_ptr);
257 ef->nbuckets = hashtab[0];
258 ef->nchains = hashtab[1];
259 ef->buckets = hashtab + 2;
260 ef->chains = ef->buckets + ef->nbuckets;
261 break;
262 }
263 case DT_STRTAB:
264 ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr);
265 break;
266 case DT_STRSZ:
267 ef->strsz = dp->d_un.d_val;
268 break;
269 case DT_SYMTAB:
270 ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr);
271 break;
272 case DT_SYMENT:
273 if (dp->d_un.d_val != sizeof(Elf_Sym))
274 return ENOEXEC;
275 break;
276 case DT_PLTGOT:
277 ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr);
278 break;
279 case DT_REL:
280 ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
281 break;
282 case DT_RELSZ:
283 ef->relsize = dp->d_un.d_val;
284 break;
285 case DT_RELENT:
286 if (dp->d_un.d_val != sizeof(Elf_Rel))
287 return ENOEXEC;
288 break;
289 case DT_JMPREL:
290 ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
291 break;
292 case DT_PLTRELSZ:
293 ef->pltrelsize = dp->d_un.d_val;
294 break;
295 case DT_RELA:
296 ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr);
297 break;
298 case DT_RELASZ:
299 ef->relasize = dp->d_un.d_val;
300 break;
301 case DT_RELAENT:
302 if (dp->d_un.d_val != sizeof(Elf_Rela))
303 return ENOEXEC;
304 break;
305 case DT_PLTREL:
306 plttype = dp->d_un.d_val;
307 if (plttype != DT_REL && plttype != DT_RELA)
308 return ENOEXEC;
309 break;
310 }
311 }
312
313 if (plttype == DT_RELA) {
314 ef->pltrela = (const Elf_Rela *) ef->pltrel;
315 ef->pltrel = NULL;
316 ef->pltrelasize = ef->pltrelsize;
317 ef->pltrelsize = 0;
318 }
319
320 ef->ddbsymtab = ef->symtab;
321 ef->ddbsymcnt = ef->nchains;
322 ef->ddbstrtab = ef->strtab;
323 ef->ddbstrcnt = ef->strsz;
324
325 return 0;
326}
327
328static void
329link_elf_error(const char *s)
330{
331 printf("kldload: %s\n", s);
332}
333
334static int
335link_elf_load_module(const char *filename, linker_file_t *result)
336{
337 caddr_t modptr, baseptr, sizeptr, dynptr;
338 char *type;
339 elf_file_t ef;
340 linker_file_t lf;
341 int error;
342 vm_offset_t dp;
343
344 /* Look to see if we have the module preloaded */
345 modptr = preload_search_by_name(filename);
346 if (modptr == NULL)
347 return (link_elf_load_file(filename, result));
348
349 /* It's preloaded, check we can handle it and collect information */
350 type = (char *)preload_search_info(modptr, MODINFO_TYPE);
351 baseptr = preload_search_info(modptr, MODINFO_ADDR);
352 sizeptr = preload_search_info(modptr, MODINFO_SIZE);
353 dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC);
354 if (type == NULL || strcmp(type, "elf module") != 0)
355 return (EFTYPE);
356 if (baseptr == NULL || sizeptr == NULL || dynptr == NULL)
357 return (EINVAL);
358
359 ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK);
360 if (ef == NULL)
361 return (ENOMEM);
362 bzero(ef, sizeof(*ef));
363 ef->modptr = modptr;
364 ef->address = *(caddr_t *)baseptr;
365#ifdef SPARSE_MAPPING
366 ef->object = 0;
367#endif
368 dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr;
369 ef->dynamic = (Elf_Dyn *)dp;
370 lf = linker_make_file(filename, ef, &link_elf_module_ops);
371 if (lf == NULL) {
372 free(ef, M_LINKER);
373 return ENOMEM;
374 }
375 lf->address = ef->address;
376 lf->size = *(size_t *)sizeptr;
377
378 error = parse_dynamic(lf);
379 if (error) {
380 linker_file_unload(lf);
381 return error;
382 }
383 error = load_dependancies(lf);
384 if (error) {
385 linker_file_unload(lf);
386 return error;
387 }
388 error = relocate_file(lf);
389 if (error) {
390 linker_file_unload(lf);
391 return error;
392 }
393 (void)parse_module_symbols(lf);
394 *result = lf;
395 return (0);
396}
397
398static int
399link_elf_load_file(const char* filename, linker_file_t* result)
400{
401 struct nameidata nd;
402 struct proc* p = curproc; /* XXX */
403 union {
404 Elf_Ehdr hdr;
405 char buf[PAGE_SIZE];
406 } u;
407 int nbytes, i;
408 Elf_Phdr *phdr;
409 Elf_Phdr *phlimit;
410 Elf_Phdr *segs[2];
411 int nsegs;
412 Elf_Phdr *phdyn;
413 Elf_Phdr *phphdr;
414 caddr_t mapbase;
415 size_t mapsize;
416 Elf_Off base_offset;
417 Elf_Addr base_vaddr;
418 Elf_Addr base_vlimit;
419 caddr_t base_addr;
420 Elf_Off data_offset;
421 Elf_Addr data_vaddr;
422 Elf_Addr data_vlimit;
423 caddr_t data_addr;
424 Elf_Addr clear_vaddr;
425 caddr_t clear_addr;
426 size_t nclear;
427 Elf_Addr bss_vaddr;
428 Elf_Addr bss_vlimit;
429 caddr_t bss_addr;
430 int error = 0;
431 int resid;
432 elf_file_t ef;
433 linker_file_t lf;
434 char *pathname;
435 Elf_Shdr *shdr;
436 int symtabindex;
437 int symstrindex;
438 int symcnt;
439 int strcnt;
440
441 shdr = NULL;
442 lf = NULL;
443
444 pathname = linker_search_path(filename);
445 if (pathname == NULL)
446 return ENOENT;
447 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, pathname, p);
448 error = vn_open(&nd, FREAD, 0);
449 free(pathname, M_LINKER);
450 if (error)
451 return error;
452
453 /*
454 * Read the elf header from the file.
455 */
456 error = vn_rdwr(UIO_READ, nd.ni_vp, (void*) &u, sizeof u, 0,
457 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
458 nbytes = sizeof u - resid;
459 if (error)
460 goto out;
461
462 if (!IS_ELF(u.hdr)) {
463 error = ENOEXEC;
464 goto out;
465 }
466
467 if (u.hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS
468 || u.hdr.e_ident[EI_DATA] != ELF_TARG_DATA) {
469 link_elf_error("Unsupported file layout");
470 error = ENOEXEC;
471 goto out;
472 }
473 if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT
474 || u.hdr.e_version != EV_CURRENT) {
475 link_elf_error("Unsupported file version");
476 error = ENOEXEC;
477 goto out;
478 }
479 if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) {
480 link_elf_error("Unsupported file type");
481 error = ENOEXEC;
482 goto out;
483 }
484 if (u.hdr.e_machine != ELF_TARG_MACH) {
485 link_elf_error("Unsupported machine");
486 error = ENOEXEC;
487 goto out;
488 }
489
490 /*
491 * We rely on the program header being in the first page. This is
492 * not strictly required by the ABI specification, but it seems to
493 * always true in practice. And, it simplifies things considerably.
494 */
495 if (!((u.hdr.e_phentsize == sizeof(Elf_Phdr))
496 || (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE)
497 || (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= nbytes)))
498 link_elf_error("Unreadable program headers");
499
500 /*
501 * Scan the program header entries, and save key information.
502 *
503 * We rely on there being exactly two load segments, text and data,
504 * in that order.
505 */
506 phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff);
507 phlimit = phdr + u.hdr.e_phnum;
508 nsegs = 0;
509 phdyn = NULL;
510 phphdr = NULL;
511 while (phdr < phlimit) {
512 switch (phdr->p_type) {
513
514 case PT_LOAD:
515 if (nsegs == 2) {
516 link_elf_error("Too many sections");
517 error = ENOEXEC;
518 goto out;
519 }
520 segs[nsegs] = phdr;
521 ++nsegs;
522 break;
523
524 case PT_PHDR:
525 phphdr = phdr;
526 break;
527
528 case PT_DYNAMIC:
529 phdyn = phdr;
530 break;
531 }
532
533 ++phdr;
534 }
535 if (phdyn == NULL) {
536 link_elf_error("Object is not dynamically-linked");
537 error = ENOEXEC;
538 goto out;
539 }
540
541 /*
542 * Allocate the entire address space of the object, to stake out our
543 * contiguous region, and to establish the base address for relocation.
544 */
545 base_offset = trunc_page(segs[0]->p_offset);
546 base_vaddr = trunc_page(segs[0]->p_vaddr);
547 base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
548 mapsize = base_vlimit - base_vaddr;
549
550 ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK);
551 bzero(ef, sizeof(*ef));
552#ifdef SPARSE_MAPPING
553 ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
554 if (ef->object == NULL) {
555 free(ef, M_LINKER);
556 error = ENOMEM;
557 goto out;
558 }
559 vm_object_reference(ef->object);
560 ef->address = (caddr_t) vm_map_min(kernel_map);
561 error = vm_map_find(kernel_map, ef->object, 0,
562 (vm_offset_t *) &ef->address,
563 mapsize, 1,
564 VM_PROT_ALL, VM_PROT_ALL, 0);
565 if (error) {
566 vm_object_deallocate(ef->object);
567 free(ef, M_LINKER);
568 goto out;
569 }
570#else
571 ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
572#endif
573 mapbase = ef->address;
574
575 /*
576 * Read the text and data sections and zero the bss.
577 */
578 for (i = 0; i < 2; i++) {
579 caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
580 error = vn_rdwr(UIO_READ, nd.ni_vp,
581 segbase, segs[i]->p_filesz, segs[i]->p_offset,
582 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
583 if (error) {
584#ifdef SPARSE_MAPPING
585 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
586 (vm_offset_t) ef->address
587 + (ef->object->size << PAGE_SHIFT));
588 vm_object_deallocate(ef->object);
589#else
590 free(ef->address, M_LINKER);
591#endif
592 free(ef, M_LINKER);
593 goto out;
594 }
595 bzero(segbase + segs[i]->p_filesz,
596 segs[i]->p_memsz - segs[i]->p_filesz);
597
598#ifdef SPARSE_MAPPING
599 /*
600 * Wire down the pages
601 */
602 vm_map_pageable(kernel_map,
603 (vm_offset_t) segbase,
604 (vm_offset_t) segbase + segs[i]->p_memsz,
605 FALSE);
606#endif
607 }
608
609 ef->dynamic = (const Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr);
610
611 lf = linker_make_file(filename, ef, &link_elf_file_ops);
612 if (lf == NULL) {
613#ifdef SPARSE_MAPPING
614 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
615 (vm_offset_t) ef->address
616 + (ef->object->size << PAGE_SHIFT));
617 vm_object_deallocate(ef->object);
618#else
619 free(ef->address, M_LINKER);
620#endif
621 free(ef, M_LINKER);
622 error = ENOMEM;
623 goto out;
624 }
625 lf->address = ef->address;
626 lf->size = mapsize;
627
628 error = parse_dynamic(lf);
629 if (error)
630 goto out;
631 error = load_dependancies(lf);
632 if (error)
633 goto out;
634 error = relocate_file(lf);
635 if (error)
636 goto out;
637
638 /* Try and load the symbol table if it's present. (you can strip it!) */
639 nbytes = u.hdr.e_shnum * u.hdr.e_shentsize;
640 if (nbytes == 0 || u.hdr.e_shoff == 0)
641 goto nosyms;
642 shdr = malloc(nbytes, M_LINKER, M_WAITOK);
643 if (shdr == NULL) {
644 error = ENOMEM;
645 goto out;
646 }
647 bzero(shdr, nbytes);
648 error = vn_rdwr(UIO_READ, nd.ni_vp,
649 (caddr_t)shdr, nbytes, u.hdr.e_shoff,
650 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
651 if (error)
652 goto out;
653 symtabindex = -1;
654 symstrindex = -1;
655 for (i = 0; i < u.hdr.e_shnum; i++) {
656 if (shdr[i].sh_type == SHT_SYMTAB) {
657 symtabindex = i;
658 symstrindex = shdr[i].sh_link;
659 }
660 }
661 if (symtabindex < 0 || symstrindex < 0)
662 goto nosyms;
663
664 symcnt = shdr[symtabindex].sh_size;
665 ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK);
666 strcnt = shdr[symstrindex].sh_size;
667 ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK);
668
669 if (ef->symbase == NULL || ef->strbase == NULL) {
670 error = ENOMEM;
671 goto out;
672 }
673 error = vn_rdwr(UIO_READ, nd.ni_vp,
674 ef->symbase, symcnt, shdr[symtabindex].sh_offset,
675 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
676 if (error)
677 goto out;
678 error = vn_rdwr(UIO_READ, nd.ni_vp,
679 ef->strbase, strcnt, shdr[symstrindex].sh_offset,
680 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
681 if (error)
682 goto out;
683
684 ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
685 ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
686 ef->ddbstrcnt = strcnt;
687 ef->ddbstrtab = ef->strbase;
688
689nosyms:
690
691 *result = lf;
692
693out:
694 if (error && lf)
695 linker_file_unload(lf);
696 if (shdr)
697 free(shdr, M_LINKER);
698 VOP_UNLOCK(nd.ni_vp, 0, p);
699 vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
700
701 return error;
702}
703
704static void
705link_elf_unload_file(linker_file_t file)
706{
707 elf_file_t ef = file->priv;
708
709 if (ef) {
710#ifdef SPARSE_MAPPING
711 if (ef->object) {
712 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
713 (vm_offset_t) ef->address
714 + (ef->object->size << PAGE_SHIFT));
715 vm_object_deallocate(ef->object);
716 }
717#else
718 if (ef->address)
719 free(ef->address, M_LINKER);
720#endif
721 if (ef->symbase)
722 free(ef->symbase, M_LINKER);
723 if (ef->strbase)
724 free(ef->strbase, M_LINKER);
725 free(ef, M_LINKER);
726 }
727}
728
729static void
730link_elf_unload_module(linker_file_t file)
731{
732 elf_file_t ef = file->priv;
733
734 if (ef)
735 free(ef, M_LINKER);
736 if (file->filename)
737 preload_delete_name(file->filename);
738}
739
740static int
741load_dependancies(linker_file_t lf)
742{
743 elf_file_t ef = lf->priv;
744 linker_file_t lfdep;
745 char* name;
746 const Elf_Dyn *dp;
747 int error = 0;
748
749 /*
750 * All files are dependant on /kernel.
751 */
752 linker_kernel_file->refs++;
753 linker_file_add_dependancy(lf, linker_kernel_file);
754
755
756 for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
757 if (dp->d_tag == DT_NEEDED) {
758 name = ef->strtab + dp->d_un.d_val;
759
760 error = linker_load_file(name, &lfdep);
761 if (error)
762 goto out;
763 error = linker_file_add_dependancy(lf, lfdep);
764 if (error)
765 goto out;
766 }
767 }
768
769out:
770 return error;
771}
772
773static const char *
774symbol_name(elf_file_t ef, const Elf_Rela *rela)
774symbol_name(elf_file_t ef, Elf_Word r_info)
775{
776 const Elf_Sym *ref;
777
775{
776 const Elf_Sym *ref;
777
778 if (ELF_R_SYM(rela->r_info)) {
779 ref = ef->symtab + ELF_R_SYM(rela->r_info);
778 if (ELF_R_SYM(r_info)) {
779 ref = ef->symtab + ELF_R_SYM(r_info);
780 return ef->strtab + ref->st_name;
781 } else
782 return NULL;
783}
784
785static int
786relocate_file(linker_file_t lf)
787{
788 elf_file_t ef = lf->priv;
789 const Elf_Rel *rellim;
790 const Elf_Rel *rel;
791 const Elf_Rela *relalim;
792 const Elf_Rela *rela;
780 return ef->strtab + ref->st_name;
781 } else
782 return NULL;
783}
784
785static int
786relocate_file(linker_file_t lf)
787{
788 elf_file_t ef = lf->priv;
789 const Elf_Rel *rellim;
790 const Elf_Rel *rel;
791 const Elf_Rela *relalim;
792 const Elf_Rela *rela;
793 const char *symname;
793
794 /* Perform relocations without addend if there are any: */
794
795 /* Perform relocations without addend if there are any: */
795 rellim = (const Elf_Rel *) ((caddr_t) ef->rel + ef->relsize);
796 for (rel = ef->rel; ef->rel != NULL && rel < rellim; rel++) {
797 Elf_Rela locrela;
798
799 locrela.r_info = rel->r_info;
800 locrela.r_offset = rel->r_offset;
801 locrela.r_addend = 0;
802 if (elf_reloc(lf, &locrela, symbol_name(ef, &locrela)))
803 return ENOENT;
796 rel = ef->rel;
797 if (rel) {
798 rellim = (const Elf_Rel *) ((caddr_t) ef->rel + ef->relsize);
799 while (rel < rellim) {
800 symname = symbol_name(ef, rel->r_info);
801 if (elf_reloc(lf, rel, ELF_RELOC_REL, symname))
802 return ENOENT;
803 rel++;
804 }
804 }
805
806 /* Perform relocations with addend if there are any: */
805 }
806
807 /* Perform relocations with addend if there are any: */
807 relalim = (const Elf_Rela *) ((caddr_t) ef->rela + ef->relasize);
808 for (rela = ef->rela; ef->rela != NULL && rela < relalim; rela++) {
809 if (elf_reloc(lf, rela, symbol_name(ef, rela)))
810 return ENOENT;
808 rela = ef->rela;
809 if (rela) {
810 relalim = (const Elf_Rela *) ((caddr_t) ef->rela + ef->relasize);
811 while (rela < relalim) {
812 symname = symbol_name(ef, rela->r_info);
813 if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname))
814 return ENOENT;
815 rela++;
816 }
811 }
812
813 /* Perform PLT relocations without addend if there are any: */
817 }
818
819 /* Perform PLT relocations without addend if there are any: */
814 rellim = (const Elf_Rel *) ((caddr_t) ef->pltrel + ef->pltrelsize);
815 for (rel = ef->pltrel; ef->pltrel != NULL && rel < rellim; rel++) {
816 Elf_Rela locrela;
817
818 locrela.r_info = rel->r_info;
819 locrela.r_offset = rel->r_offset;
820 locrela.r_addend = 0;
821 if (elf_reloc(lf, &locrela, symbol_name(ef, &locrela)))
822 return ENOENT;
820 rel = ef->pltrel;
821 if (rel) {
822 rellim = (const Elf_Rel *) ((caddr_t) ef->pltrel + ef->pltrelsize);
823 while (rel < rellim) {
824 symname = symbol_name(ef, rel->r_info);
825 if (elf_reloc(lf, rel, ELF_RELOC_REL, symname))
826 return ENOENT;
827 rel++;
828 }
823 }
824
825 /* Perform relocations with addend if there are any: */
829 }
830
831 /* Perform relocations with addend if there are any: */
826 relalim = (const Elf_Rela *) ((caddr_t) ef->pltrela + ef->pltrelasize);
827 for (rela = ef->pltrela; ef->pltrela != NULL && rela < relalim; rela++) {
828 if (elf_reloc(lf, rela, symbol_name(ef, rela)))
829 return ENOENT;
832 rela = ef->pltrela;
833 if (rela) {
834 relalim = (const Elf_Rela *) ((caddr_t) ef->pltrela + ef->pltrelasize);
835 while (rela < relalim) {
836 symname = symbol_name(ef, rela->r_info);
837 if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname))
838 return ENOENT;
839 rela++;
840 }
830 }
831
832 return 0;
833}
834
835/*
836 * Hash function for symbol table lookup. Don't even think about changing
837 * this. It is specified by the System V ABI.
838 */
839static unsigned long
840elf_hash(const char *name)
841{
842 const unsigned char *p = (const unsigned char *) name;
843 unsigned long h = 0;
844 unsigned long g;
845
846 while (*p != '\0') {
847 h = (h << 4) + *p++;
848 if ((g = h & 0xf0000000) != 0)
849 h ^= g >> 24;
850 h &= ~g;
851 }
852 return h;
853}
854
855int
856link_elf_lookup_symbol(linker_file_t lf, const char* name, linker_sym_t* sym)
857{
858 elf_file_t ef = lf->priv;
859 unsigned long symnum;
860 const Elf_Sym* symp;
861 const char *strp;
862 unsigned long hash;
863 int i;
864
865 /* First, search hashed global symbols */
866 hash = elf_hash(name);
867 symnum = ef->buckets[hash % ef->nbuckets];
868
869 while (symnum != STN_UNDEF) {
870 if (symnum >= ef->nchains) {
871 printf("link_elf_lookup_symbol: corrupt symbol table\n");
872 return ENOENT;
873 }
874
875 symp = ef->symtab + symnum;
876 if (symp->st_name == 0) {
877 printf("link_elf_lookup_symbol: corrupt symbol table\n");
878 return ENOENT;
879 }
880
881 strp = ef->strtab + symp->st_name;
882
883 if (strcmp(name, strp) == 0) {
884 if (symp->st_shndx != SHN_UNDEF ||
885 (symp->st_value != 0 &&
886 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
887 *sym = (linker_sym_t) symp;
888 return 0;
889 } else
890 return ENOENT;
891 }
892
893 symnum = ef->chains[symnum];
894 }
895
896 /* If we have not found it, look at the full table (if loaded) */
897 if (ef->symtab == ef->ddbsymtab)
898 return ENOENT;
899
900 /* Exhaustive search */
901 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
902 strp = ef->ddbstrtab + symp->st_name;
903 if (strcmp(name, strp) == 0) {
904 if (symp->st_shndx != SHN_UNDEF ||
905 (symp->st_value != 0 &&
906 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
907 *sym = (linker_sym_t) symp;
908 return 0;
909 } else
910 return ENOENT;
911 }
912 }
913
914 return ENOENT;
915}
916
917static int
918link_elf_symbol_values(linker_file_t lf, linker_sym_t sym, linker_symval_t* symval)
919{
920 elf_file_t ef = lf->priv;
921 Elf_Sym* es = (Elf_Sym*) sym;
922
923 if (es >= ef->symtab && ((es - ef->symtab) < ef->nchains)) {
924 symval->name = ef->strtab + es->st_name;
925 symval->value = (caddr_t) ef->address + es->st_value;
926 symval->size = es->st_size;
927 return 0;
928 }
929 if (ef->symtab == ef->ddbsymtab)
930 return ENOENT;
931 if (es >= ef->ddbsymtab && ((es - ef->ddbsymtab) < ef->ddbsymcnt)) {
932 symval->name = ef->ddbstrtab + es->st_name;
933 symval->value = (caddr_t) ef->address + es->st_value;
934 symval->size = es->st_size;
935 return 0;
936 }
937 return ENOENT;
938}
939
940static int
941link_elf_search_symbol(linker_file_t lf, caddr_t value,
942 linker_sym_t* sym, long* diffp)
943{
944 elf_file_t ef = lf->priv;
945 u_long off = (u_long) value;
946 u_long diff = off;
947 const Elf_Sym* es;
948 const Elf_Sym* best = 0;
949 int i;
950
951 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
952 if (es->st_name == 0)
953 continue;
954 if (off >= es->st_value) {
955 if (off - es->st_value < diff) {
956 diff = off - es->st_value;
957 best = es;
958 if (diff == 0)
959 break;
960 } else if (off - es->st_value == diff) {
961 best = es;
962 }
963 }
964 }
965 if (best == 0)
966 *diffp = off;
967 else
968 *diffp = diff;
969 *sym = (linker_sym_t) best;
970
971 return 0;
972}
841 }
842
843 return 0;
844}
845
846/*
847 * Hash function for symbol table lookup. Don't even think about changing
848 * this. It is specified by the System V ABI.
849 */
850static unsigned long
851elf_hash(const char *name)
852{
853 const unsigned char *p = (const unsigned char *) name;
854 unsigned long h = 0;
855 unsigned long g;
856
857 while (*p != '\0') {
858 h = (h << 4) + *p++;
859 if ((g = h & 0xf0000000) != 0)
860 h ^= g >> 24;
861 h &= ~g;
862 }
863 return h;
864}
865
866int
867link_elf_lookup_symbol(linker_file_t lf, const char* name, linker_sym_t* sym)
868{
869 elf_file_t ef = lf->priv;
870 unsigned long symnum;
871 const Elf_Sym* symp;
872 const char *strp;
873 unsigned long hash;
874 int i;
875
876 /* First, search hashed global symbols */
877 hash = elf_hash(name);
878 symnum = ef->buckets[hash % ef->nbuckets];
879
880 while (symnum != STN_UNDEF) {
881 if (symnum >= ef->nchains) {
882 printf("link_elf_lookup_symbol: corrupt symbol table\n");
883 return ENOENT;
884 }
885
886 symp = ef->symtab + symnum;
887 if (symp->st_name == 0) {
888 printf("link_elf_lookup_symbol: corrupt symbol table\n");
889 return ENOENT;
890 }
891
892 strp = ef->strtab + symp->st_name;
893
894 if (strcmp(name, strp) == 0) {
895 if (symp->st_shndx != SHN_UNDEF ||
896 (symp->st_value != 0 &&
897 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
898 *sym = (linker_sym_t) symp;
899 return 0;
900 } else
901 return ENOENT;
902 }
903
904 symnum = ef->chains[symnum];
905 }
906
907 /* If we have not found it, look at the full table (if loaded) */
908 if (ef->symtab == ef->ddbsymtab)
909 return ENOENT;
910
911 /* Exhaustive search */
912 for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
913 strp = ef->ddbstrtab + symp->st_name;
914 if (strcmp(name, strp) == 0) {
915 if (symp->st_shndx != SHN_UNDEF ||
916 (symp->st_value != 0 &&
917 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
918 *sym = (linker_sym_t) symp;
919 return 0;
920 } else
921 return ENOENT;
922 }
923 }
924
925 return ENOENT;
926}
927
928static int
929link_elf_symbol_values(linker_file_t lf, linker_sym_t sym, linker_symval_t* symval)
930{
931 elf_file_t ef = lf->priv;
932 Elf_Sym* es = (Elf_Sym*) sym;
933
934 if (es >= ef->symtab && ((es - ef->symtab) < ef->nchains)) {
935 symval->name = ef->strtab + es->st_name;
936 symval->value = (caddr_t) ef->address + es->st_value;
937 symval->size = es->st_size;
938 return 0;
939 }
940 if (ef->symtab == ef->ddbsymtab)
941 return ENOENT;
942 if (es >= ef->ddbsymtab && ((es - ef->ddbsymtab) < ef->ddbsymcnt)) {
943 symval->name = ef->ddbstrtab + es->st_name;
944 symval->value = (caddr_t) ef->address + es->st_value;
945 symval->size = es->st_size;
946 return 0;
947 }
948 return ENOENT;
949}
950
951static int
952link_elf_search_symbol(linker_file_t lf, caddr_t value,
953 linker_sym_t* sym, long* diffp)
954{
955 elf_file_t ef = lf->priv;
956 u_long off = (u_long) value;
957 u_long diff = off;
958 const Elf_Sym* es;
959 const Elf_Sym* best = 0;
960 int i;
961
962 for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
963 if (es->st_name == 0)
964 continue;
965 if (off >= es->st_value) {
966 if (off - es->st_value < diff) {
967 diff = off - es->st_value;
968 best = es;
969 if (diff == 0)
970 break;
971 } else if (off - es->st_value == diff) {
972 best = es;
973 }
974 }
975 }
976 if (best == 0)
977 *diffp = off;
978 else
979 *diffp = diff;
980 *sym = (linker_sym_t) best;
981
982 return 0;
983}