xref: /freebsd/sys/kern/link_elf.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /*-
2  * Copyright (c) 1998-2000 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  * $FreeBSD$
27  */
28 
29 #include "opt_ddb.h"
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/lock.h>
35 #include <sys/malloc.h>
36 #include <sys/mutex.h>
37 #include <sys/proc.h>
38 #include <sys/namei.h>
39 #include <sys/fcntl.h>
40 #include <sys/vnode.h>
41 #include <sys/linker.h>
42 
43 #include <machine/elf.h>
44 
45 #include <vm/vm.h>
46 #include <vm/vm_param.h>
47 #ifdef SPARSE_MAPPING
48 #include <vm/vm_object.h>
49 #include <vm/vm_kern.h>
50 #include <vm/vm_extern.h>
51 #endif
52 #include <vm/pmap.h>
53 #include <vm/vm_map.h>
54 
55 #ifdef __AOUT__
56 #include <nlist.h>
57 #endif
58 #include <link.h>
59 
60 #include "linker_if.h"
61 
62 typedef struct elf_file {
63     struct linker_file	lf;		/* Common fields */
64     int			preloaded;	/* Was file pre-loaded */
65     caddr_t		address;	/* Relocation address */
66 #ifdef SPARSE_MAPPING
67     vm_object_t		object;		/* VM object to hold file pages */
68 #endif
69     Elf_Dyn*		dynamic;	/* Symbol table etc. */
70     Elf_Off		nbuckets;	/* DT_HASH info */
71     Elf_Off		nchains;
72     const Elf_Off*	buckets;
73     const Elf_Off*	chains;
74     caddr_t		hash;
75     caddr_t		strtab;		/* DT_STRTAB */
76     int			strsz;		/* DT_STRSZ */
77     const Elf_Sym*	symtab;		/* DT_SYMTAB */
78     Elf_Addr*		got;		/* DT_PLTGOT */
79     const Elf_Rel*	pltrel;		/* DT_JMPREL */
80     int			pltrelsize;	/* DT_PLTRELSZ */
81     const Elf_Rela*	pltrela;	/* DT_JMPREL */
82     int			pltrelasize;	/* DT_PLTRELSZ */
83     const Elf_Rel*	rel;		/* DT_REL */
84     int			relsize;	/* DT_RELSZ */
85     const Elf_Rela*	rela;		/* DT_RELA */
86     int			relasize;	/* DT_RELASZ */
87     caddr_t		modptr;
88     const Elf_Sym*	ddbsymtab;	/* The symbol table we are using */
89     long		ddbsymcnt;	/* Number of symbols */
90     caddr_t		ddbstrtab;	/* String table */
91     long		ddbstrcnt;	/* number of bytes in string table */
92     caddr_t		symbase;	/* malloc'ed symbold base */
93     caddr_t		strbase;	/* malloc'ed string base */
94 #ifdef DDB
95     struct link_map	gdb;		/* hooks for gdb */
96 #endif
97 } *elf_file_t;
98 
99 static int	link_elf_link_preload(linker_class_t cls,
100 				      const char*, linker_file_t*);
101 static int	link_elf_link_preload_finish(linker_file_t);
102 static int	link_elf_load_file(linker_class_t, const char*, linker_file_t*);
103 static int	link_elf_lookup_symbol(linker_file_t, const char*,
104 				       c_linker_sym_t*);
105 static int	link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*);
106 static int	link_elf_search_symbol(linker_file_t, caddr_t value,
107 				       c_linker_sym_t* sym, long* diffp);
108 
109 static void	link_elf_unload_file(linker_file_t);
110 static void	link_elf_unload_preload(linker_file_t);
111 static int	link_elf_lookup_set(linker_file_t, const char *,
112 				    void ***, void ***, int *);
113 
114 static kobj_method_t link_elf_methods[] = {
115     KOBJMETHOD(linker_lookup_symbol,	link_elf_lookup_symbol),
116     KOBJMETHOD(linker_symbol_values,	link_elf_symbol_values),
117     KOBJMETHOD(linker_search_symbol,	link_elf_search_symbol),
118     KOBJMETHOD(linker_unload,		link_elf_unload_file),
119     KOBJMETHOD(linker_load_file,	link_elf_load_file),
120     KOBJMETHOD(linker_link_preload,	link_elf_link_preload),
121     KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
122     KOBJMETHOD(linker_lookup_set,	link_elf_lookup_set),
123     { 0, 0 }
124 };
125 
126 static struct linker_class link_elf_class = {
127 #if ELF_TARG_CLASS == ELFCLASS32
128     "elf32",
129 #else
130     "elf64",
131 #endif
132     link_elf_methods, sizeof(struct elf_file)
133 };
134 
135 static int		parse_dynamic(elf_file_t ef);
136 static int		relocate_file(elf_file_t ef);
137 static int		link_elf_preload_parse_symbols(elf_file_t ef);
138 
139 #ifdef DDB
140 static void		r_debug_state(struct r_debug *dummy_one,
141 				      struct link_map *dummy_two);
142 
143 /*
144  * A list of loaded modules for GDB to use for loading symbols.
145  */
146 struct r_debug r_debug;
147 
148 #define GDB_STATE(s)	r_debug.r_state = s; r_debug_state(NULL, NULL);
149 
150 /*
151  * Function for the debugger to set a breakpoint on to gain control.
152  */
153 void
154 r_debug_state(struct r_debug *dummy_one __unused,
155 	      struct link_map *dummy_two __unused)
156 {
157 }
158 
159 #endif
160 
161 /*
162  * The kernel symbol table starts here.
163  */
164 #ifndef __ia64__
165 extern struct _dynamic _DYNAMIC;
166 #endif
167 
168 static void
169 link_elf_init(void* arg)
170 {
171 #ifdef __ELF__
172     Elf_Dyn	*dp;
173     caddr_t	modptr, baseptr, sizeptr;
174     elf_file_t	ef;
175     char	*modname;
176 #endif
177 
178     linker_add_class(&link_elf_class);
179 
180 #ifdef __ELF__
181 #ifndef __ia64__
182     dp = (Elf_Dyn*) &_DYNAMIC;
183 #else
184     dp = 0;
185 #endif
186     if (dp) {
187 	modname = NULL;
188 	modptr = preload_search_by_type("elf kernel");
189 	if (modptr)
190 	    modname = (char *)preload_search_info(modptr, MODINFO_NAME);
191 	if (modname == NULL)
192 	    modname = "kernel";
193 	linker_kernel_file = linker_make_file(modname, &link_elf_class);
194 	if (linker_kernel_file == NULL)
195 	    panic("link_elf_init: Can't create linker structures for kernel");
196 
197 	ef = (elf_file_t) linker_kernel_file;
198 	ef->preloaded = 1;
199 	ef->address = 0;
200 #ifdef SPARSE_MAPPING
201 	ef->object = 0;
202 #endif
203 	ef->dynamic = dp;
204 
205 	parse_dynamic(ef);
206 	linker_kernel_file->address = (caddr_t) KERNBASE;
207 	linker_kernel_file->size = -(intptr_t)linker_kernel_file->address;
208 
209 	if (modptr) {
210 	    ef->modptr = modptr;
211 	    baseptr = preload_search_info(modptr, MODINFO_ADDR);
212 	    if (baseptr)
213 		linker_kernel_file->address = *(caddr_t *)baseptr;
214 	    sizeptr = preload_search_info(modptr, MODINFO_SIZE);
215 	    if (sizeptr)
216 		linker_kernel_file->size = *(size_t *)sizeptr;
217 	}
218 	(void)link_elf_preload_parse_symbols(ef);
219 
220 #ifdef DDB
221 	ef->gdb.l_addr = linker_kernel_file->address;
222 	ef->gdb.l_name = modname;
223 	ef->gdb.l_ld = dp;
224 	ef->gdb.l_prev = 0;
225 	ef->gdb.l_next = 0;
226 
227 	r_debug.r_map = &ef->gdb;
228 	r_debug.r_brk = r_debug_state;
229 	r_debug.r_state = RT_CONSISTENT;
230 
231 	r_debug_state(NULL, NULL);	/* say hello to gdb! */
232 #endif
233 
234     }
235 #endif
236 }
237 
238 SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
239 
240 static int
241 link_elf_preload_parse_symbols(elf_file_t ef)
242 {
243     caddr_t	pointer;
244     caddr_t	ssym, esym, base;
245     caddr_t	strtab;
246     int		strcnt;
247     Elf_Sym*	symtab;
248     int		symcnt;
249 
250     if (ef->modptr == NULL)
251 	return 0;
252     pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM);
253     if (pointer == NULL)
254 	return 0;
255     ssym = *(caddr_t *)pointer;
256     pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM);
257     if (pointer == NULL)
258 	return 0;
259     esym = *(caddr_t *)pointer;
260 
261     base = ssym;
262 
263     symcnt = *(long *)base;
264     base += sizeof(long);
265     symtab = (Elf_Sym *)base;
266     base += roundup(symcnt, sizeof(long));
267 
268     if (base > esym || base < ssym) {
269 	printf("Symbols are corrupt!\n");
270 	return EINVAL;
271     }
272 
273     strcnt = *(long *)base;
274     base += sizeof(long);
275     strtab = base;
276     base += roundup(strcnt, sizeof(long));
277 
278     if (base > esym || base < ssym) {
279 	printf("Symbols are corrupt!\n");
280 	return EINVAL;
281     }
282 
283     ef->ddbsymtab = symtab;
284     ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
285     ef->ddbstrtab = strtab;
286     ef->ddbstrcnt = strcnt;
287 
288     return 0;
289 }
290 
291 static int
292 parse_dynamic(elf_file_t ef)
293 {
294     Elf_Dyn *dp;
295     int plttype = DT_REL;
296 
297     for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
298 	switch (dp->d_tag) {
299 	case DT_HASH:
300 	{
301 	    /* From src/libexec/rtld-elf/rtld.c */
302 	    const Elf_Off *hashtab = (const Elf_Off *)
303 		(ef->address + dp->d_un.d_ptr);
304 	    ef->nbuckets = hashtab[0];
305 	    ef->nchains = hashtab[1];
306 	    ef->buckets = hashtab + 2;
307 	    ef->chains = ef->buckets + ef->nbuckets;
308 	    break;
309 	}
310 	case DT_STRTAB:
311 	    ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr);
312 	    break;
313 	case DT_STRSZ:
314 	    ef->strsz = dp->d_un.d_val;
315 	    break;
316 	case DT_SYMTAB:
317 	    ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr);
318 	    break;
319 	case DT_SYMENT:
320 	    if (dp->d_un.d_val != sizeof(Elf_Sym))
321 		return ENOEXEC;
322 	    break;
323 	case DT_PLTGOT:
324 	    ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr);
325 	    break;
326 	case DT_REL:
327 	    ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
328 	    break;
329 	case DT_RELSZ:
330 	    ef->relsize = dp->d_un.d_val;
331 	    break;
332 	case DT_RELENT:
333 	    if (dp->d_un.d_val != sizeof(Elf_Rel))
334 		return ENOEXEC;
335 	    break;
336 	case DT_JMPREL:
337 	    ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
338 	    break;
339 	case DT_PLTRELSZ:
340 	    ef->pltrelsize = dp->d_un.d_val;
341 	    break;
342 	case DT_RELA:
343 	    ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr);
344 	    break;
345 	case DT_RELASZ:
346 	    ef->relasize = dp->d_un.d_val;
347 	    break;
348 	case DT_RELAENT:
349 	    if (dp->d_un.d_val != sizeof(Elf_Rela))
350 		return ENOEXEC;
351 	    break;
352 	case DT_PLTREL:
353 	    plttype = dp->d_un.d_val;
354 	    if (plttype != DT_REL && plttype != DT_RELA)
355 		return ENOEXEC;
356 	    break;
357 #ifdef DDB
358 	case DT_DEBUG:
359 	    dp->d_un.d_ptr = (Elf_Addr) &r_debug;
360 	    break;
361 #endif
362 	}
363     }
364 
365     if (plttype == DT_RELA) {
366 	ef->pltrela = (const Elf_Rela *) ef->pltrel;
367 	ef->pltrel = NULL;
368 	ef->pltrelasize = ef->pltrelsize;
369 	ef->pltrelsize = 0;
370     }
371 
372     ef->ddbsymtab = ef->symtab;
373     ef->ddbsymcnt = ef->nchains;
374     ef->ddbstrtab = ef->strtab;
375     ef->ddbstrcnt = ef->strsz;
376 
377     return 0;
378 }
379 
380 static void
381 link_elf_error(const char *s)
382 {
383     printf("kldload: %s\n", s);
384 }
385 
386 #ifdef DDB
387 
388 static void
389 link_elf_add_gdb(struct link_map *l)
390 {
391     struct link_map *prev;
392 
393     /*
394      * Scan to the end of the list.
395      */
396     for (prev = r_debug.r_map; prev->l_next != NULL; prev = prev->l_next)
397 	;
398 
399     /* Link in the new entry. */
400     l->l_prev = prev;
401     l->l_next = prev->l_next;
402     prev->l_next = l;
403 }
404 
405 static void
406 link_elf_delete_gdb(struct link_map *l)
407 {
408     if (l->l_prev == NULL) {
409 	if ((r_debug.r_map = l->l_next) != NULL)
410 	    l->l_next->l_prev = NULL;
411 	return;
412     }
413 
414     if ((l->l_prev->l_next = l->l_next) != NULL)
415 	l->l_next->l_prev = l->l_prev;
416 }
417 
418 #endif /* DDB */
419 
420 static int
421 link_elf_link_preload(linker_class_t cls,
422 		      const char* filename, linker_file_t *result)
423 {
424     caddr_t		modptr, baseptr, sizeptr, dynptr;
425     char		*type;
426     elf_file_t		ef;
427     linker_file_t	lf;
428     int			error;
429     vm_offset_t		dp;
430 
431     /* Look to see if we have the file preloaded */
432     modptr = preload_search_by_name(filename);
433     if (modptr == NULL)
434 	return ENOENT;
435 
436     type = (char *)preload_search_info(modptr, MODINFO_TYPE);
437     baseptr = preload_search_info(modptr, MODINFO_ADDR);
438     sizeptr = preload_search_info(modptr, MODINFO_SIZE);
439     dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC);
440     if (type == NULL || strcmp(type, "elf module") != 0)
441 	return (EFTYPE);
442     if (baseptr == NULL || sizeptr == NULL || dynptr == NULL)
443 	return (EINVAL);
444 
445     lf = linker_make_file(filename, &link_elf_class);
446     if (lf == NULL) {
447 	return ENOMEM;
448     }
449 
450     ef = (elf_file_t) lf;
451     ef->preloaded = 1;
452     ef->modptr = modptr;
453     ef->address = *(caddr_t *)baseptr;
454 #ifdef SPARSE_MAPPING
455     ef->object = 0;
456 #endif
457     dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr;
458     ef->dynamic = (Elf_Dyn *)dp;
459     lf->address = ef->address;
460     lf->size = *(size_t *)sizeptr;
461 
462     error = parse_dynamic(ef);
463     if (error) {
464 	linker_file_unload(lf);
465 	return error;
466     }
467     *result = lf;
468     return (0);
469 }
470 
471 static int
472 link_elf_link_preload_finish(linker_file_t lf)
473 {
474     elf_file_t		ef;
475     int error;
476 
477     ef = (elf_file_t) lf;
478 #if 0	/* this will be more trouble than it's worth for now */
479     for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
480 	if (dp->d_tag != DT_NEEDED)
481 	    continue;
482 	modname = ef->strtab + dp->d_un.d_val;
483 	error = linker_load_module(modname, lf);
484 	if (error)
485 	    goto out;
486     }
487 #endif
488     error = relocate_file(ef);
489     if (error)
490 	return error;
491     (void)link_elf_preload_parse_symbols(ef);
492 
493 #ifdef DDB
494     GDB_STATE(RT_ADD);
495     ef->gdb.l_addr = lf->address;
496     ef->gdb.l_name = lf->filename;
497     ef->gdb.l_ld = ef->dynamic;
498     link_elf_add_gdb(&ef->gdb);
499     GDB_STATE(RT_CONSISTENT);
500 #endif
501 
502     return (0);
503 }
504 
505 static int
506 link_elf_load_file(linker_class_t cls, const char* filename, linker_file_t* result)
507 {
508     struct nameidata nd;
509     struct proc* p = curproc;	/* XXX */
510     Elf_Ehdr *hdr;
511     caddr_t firstpage;
512     int nbytes, i;
513     Elf_Phdr *phdr;
514     Elf_Phdr *phlimit;
515     Elf_Phdr *segs[2];
516     int nsegs;
517     Elf_Phdr *phdyn;
518     Elf_Phdr *phphdr;
519     caddr_t mapbase;
520     size_t mapsize;
521     Elf_Off base_offset;
522     Elf_Addr base_vaddr;
523     Elf_Addr base_vlimit;
524     int error = 0;
525     int resid, flags;
526     elf_file_t ef;
527     linker_file_t lf;
528     Elf_Shdr *shdr;
529     int symtabindex;
530     int symstrindex;
531     int symcnt;
532     int strcnt;
533 
534     shdr = NULL;
535     lf = NULL;
536 
537     NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, p);
538     flags = FREAD;
539     error = vn_open(&nd, &flags, 0);
540     if (error)
541 	return error;
542     NDFREE(&nd, NDF_ONLY_PNBUF);
543 
544     /*
545      * Read the elf header from the file.
546      */
547     firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK);
548     if (firstpage == NULL) {
549 	error = ENOMEM;
550 	goto out;
551     }
552     hdr = (Elf_Ehdr *)firstpage;
553     error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0,
554 		    UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
555     nbytes = PAGE_SIZE - resid;
556     if (error)
557 	goto out;
558 
559     if (!IS_ELF(*hdr)) {
560 	error = ENOEXEC;
561 	goto out;
562     }
563 
564     if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
565       || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
566 	link_elf_error("Unsupported file layout");
567 	error = ENOEXEC;
568 	goto out;
569     }
570     if (hdr->e_ident[EI_VERSION] != EV_CURRENT
571       || hdr->e_version != EV_CURRENT) {
572 	link_elf_error("Unsupported file version");
573 	error = ENOEXEC;
574 	goto out;
575     }
576     if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
577 	link_elf_error("Unsupported file type");
578 	error = ENOEXEC;
579 	goto out;
580     }
581     if (hdr->e_machine != ELF_TARG_MACH) {
582 	link_elf_error("Unsupported machine");
583 	error = ENOEXEC;
584 	goto out;
585     }
586 
587     /*
588      * We rely on the program header being in the first page.  This is
589      * not strictly required by the ABI specification, but it seems to
590      * always true in practice.  And, it simplifies things considerably.
591      */
592     if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) &&
593 	  (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) &&
594 	  (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes)))
595 	link_elf_error("Unreadable program headers");
596 
597     /*
598      * Scan the program header entries, and save key information.
599      *
600      * We rely on there being exactly two load segments, text and data,
601      * in that order.
602      */
603     phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff);
604     phlimit = phdr + hdr->e_phnum;
605     nsegs = 0;
606     phdyn = NULL;
607     phphdr = NULL;
608     while (phdr < phlimit) {
609 	switch (phdr->p_type) {
610 
611 	case PT_LOAD:
612 	    if (nsegs == 2) {
613 		link_elf_error("Too many sections");
614 		error = ENOEXEC;
615 		goto out;
616 	    }
617 	    segs[nsegs] = phdr;
618 	    ++nsegs;
619 	    break;
620 
621 	case PT_PHDR:
622 	    phphdr = phdr;
623 	    break;
624 
625 	case PT_DYNAMIC:
626 	    phdyn = phdr;
627 	    break;
628 
629 	case PT_INTERP:
630 	    link_elf_error("Unsupported file type");
631 	    error = ENOEXEC;
632 	    goto out;
633 	}
634 
635 	++phdr;
636     }
637     if (phdyn == NULL) {
638 	link_elf_error("Object is not dynamically-linked");
639 	error = ENOEXEC;
640 	goto out;
641     }
642 
643     /*
644      * Allocate the entire address space of the object, to stake out our
645      * contiguous region, and to establish the base address for relocation.
646      */
647     base_offset = trunc_page(segs[0]->p_offset);
648     base_vaddr = trunc_page(segs[0]->p_vaddr);
649     base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
650     mapsize = base_vlimit - base_vaddr;
651 
652     lf = linker_make_file(filename, &link_elf_class);
653     if (!lf) {
654 	error = ENOMEM;
655 	goto out;
656     }
657 
658     ef = (elf_file_t) lf;
659 #ifdef SPARSE_MAPPING
660     mtx_lock(&vm_mtx);
661     ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
662     if (ef->object == NULL) {
663     	mtx_unlock(&vm_mtx);
664 	free(ef, M_LINKER);
665 	error = ENOMEM;
666 	goto out;
667     }
668     vm_object_reference(ef->object);
669     ef->address = (caddr_t) vm_map_min(kernel_map);
670     error = vm_map_find(kernel_map, ef->object, 0,
671 			(vm_offset_t *) &ef->address,
672 			mapsize, 1,
673 			VM_PROT_ALL, VM_PROT_ALL, 0);
674     if (error) {
675 	vm_object_deallocate(ef->object);
676     	mtx_unlock(&vm_mtx);
677 	ef->object = 0;
678 	goto out;
679     }
680     mtx_unlock(&vm_mtx);
681 #else
682     ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
683     if (!ef->address) {
684 	error = ENOMEM;
685 	goto out;
686     }
687 #endif
688     mapbase = ef->address;
689 
690     /*
691      * Read the text and data sections and zero the bss.
692      */
693     for (i = 0; i < 2; i++) {
694 	caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
695 	error = vn_rdwr(UIO_READ, nd.ni_vp,
696 			segbase, segs[i]->p_filesz, segs[i]->p_offset,
697 			UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
698 	if (error) {
699 	    goto out;
700 	}
701 	bzero(segbase + segs[i]->p_filesz,
702 	      segs[i]->p_memsz - segs[i]->p_filesz);
703 
704 #ifdef SPARSE_MAPPING
705 	/*
706 	 * Wire down the pages
707 	 */
708 	mtx_lock(&vm_mtx);
709 	vm_map_pageable(kernel_map,
710 			(vm_offset_t) segbase,
711 			(vm_offset_t) segbase + segs[i]->p_memsz,
712 			FALSE);
713 	mtx_unlock(&vm_mtx);
714 #endif
715     }
716 
717     ef->dynamic = (Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr);
718 
719     lf->address = ef->address;
720     lf->size = mapsize;
721 
722     error = parse_dynamic(ef);
723     if (error)
724 	goto out;
725     error = linker_load_dependancies(lf);
726     if (error)
727 	goto out;
728 #if 0	/* this will be more trouble than it's worth for now */
729     for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
730 	if (dp->d_tag != DT_NEEDED)
731 	    continue;
732 	modname = ef->strtab + dp->d_un.d_val;
733 	error = linker_load_module(modname, lf);
734 	if (error)
735 	    goto out;
736     }
737 #endif
738     error = relocate_file(ef);
739     if (error)
740 	goto out;
741 
742     /* Try and load the symbol table if it's present.  (you can strip it!) */
743     nbytes = hdr->e_shnum * hdr->e_shentsize;
744     if (nbytes == 0 || hdr->e_shoff == 0)
745 	goto nosyms;
746     shdr = malloc(nbytes, M_LINKER, M_WAITOK | M_ZERO);
747     if (shdr == NULL) {
748 	error = ENOMEM;
749 	goto out;
750     }
751     error = vn_rdwr(UIO_READ, nd.ni_vp,
752 		    (caddr_t)shdr, nbytes, hdr->e_shoff,
753 		    UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
754     if (error)
755 	goto out;
756     symtabindex = -1;
757     symstrindex = -1;
758     for (i = 0; i < hdr->e_shnum; i++) {
759 	if (shdr[i].sh_type == SHT_SYMTAB) {
760 	    symtabindex = i;
761 	    symstrindex = shdr[i].sh_link;
762 	}
763     }
764     if (symtabindex < 0 || symstrindex < 0)
765 	goto nosyms;
766 
767     symcnt = shdr[symtabindex].sh_size;
768     ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK);
769     strcnt = shdr[symstrindex].sh_size;
770     ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK);
771 
772     if (ef->symbase == NULL || ef->strbase == NULL) {
773 	error = ENOMEM;
774 	goto out;
775     }
776     error = vn_rdwr(UIO_READ, nd.ni_vp,
777 		    ef->symbase, symcnt, shdr[symtabindex].sh_offset,
778 		    UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
779     if (error)
780 	goto out;
781     error = vn_rdwr(UIO_READ, nd.ni_vp,
782 		    ef->strbase, strcnt, shdr[symstrindex].sh_offset,
783 		    UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
784     if (error)
785 	goto out;
786 
787     ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
788     ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
789     ef->ddbstrcnt = strcnt;
790     ef->ddbstrtab = ef->strbase;
791 
792 #ifdef DDB
793     GDB_STATE(RT_ADD);
794     ef->gdb.l_addr = lf->address;
795     ef->gdb.l_name = filename;
796     ef->gdb.l_ld = ef->dynamic;
797     link_elf_add_gdb(&ef->gdb);
798     GDB_STATE(RT_CONSISTENT);
799 #endif
800 
801 nosyms:
802 
803     *result = lf;
804 
805 out:
806     if (error && lf)
807 	linker_file_unload(lf);
808     if (shdr)
809 	free(shdr, M_LINKER);
810     if (firstpage)
811 	free(firstpage, M_LINKER);
812     VOP_UNLOCK(nd.ni_vp, 0, p);
813     vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
814 
815     return error;
816 }
817 
818 static void
819 link_elf_unload_file(linker_file_t file)
820 {
821     elf_file_t ef = (elf_file_t) file;
822 
823 #ifdef DDB
824     if (ef->gdb.l_ld) {
825 	GDB_STATE(RT_DELETE);
826 	link_elf_delete_gdb(&ef->gdb);
827 	GDB_STATE(RT_CONSISTENT);
828     }
829 #endif
830 
831     if (ef->preloaded) {
832 	link_elf_unload_preload(file);
833 	return;
834     }
835 #ifdef SPARSE_MAPPING
836     if (ef->object) {
837 	mtx_lock(&vm_mtx);
838 	vm_map_remove(kernel_map, (vm_offset_t) ef->address,
839 		      (vm_offset_t) ef->address
840 		      + (ef->object->size << PAGE_SHIFT));
841 	vm_object_deallocate(ef->object);
842 	mtx_unlock(&vm_mtx);
843     }
844 #else
845     if (ef->address)
846 	free(ef->address, M_LINKER);
847 #endif
848     if (ef->symbase)
849 	free(ef->symbase, M_LINKER);
850     if (ef->strbase)
851 	free(ef->strbase, M_LINKER);
852 }
853 
854 static void
855 link_elf_unload_preload(linker_file_t file)
856 {
857     if (file->filename)
858 	preload_delete_name(file->filename);
859 }
860 
861 static const char *
862 symbol_name(elf_file_t ef, Elf_Word r_info)
863 {
864     const Elf_Sym *ref;
865 
866     if (ELF_R_SYM(r_info)) {
867 	ref = ef->symtab + ELF_R_SYM(r_info);
868 	return ef->strtab + ref->st_name;
869     } else
870 	return NULL;
871 }
872 
873 static int
874 relocate_file(elf_file_t ef)
875 {
876     const Elf_Rel *rellim;
877     const Elf_Rel *rel;
878     const Elf_Rela *relalim;
879     const Elf_Rela *rela;
880     const char *symname;
881 
882     /* Perform relocations without addend if there are any: */
883     rel = ef->rel;
884     if (rel) {
885 	rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
886 	while (rel < rellim) {
887 	    symname = symbol_name(ef, rel->r_info);
888 	    if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, symname)) {
889 		printf("link_elf: symbol %s undefined\n", symname);
890 		return ENOENT;
891 	    }
892 	    rel++;
893 	}
894     }
895 
896     /* Perform relocations with addend if there are any: */
897     rela = ef->rela;
898     if (rela) {
899 	relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
900 	while (rela < relalim) {
901 	    symname = symbol_name(ef, rela->r_info);
902 	    if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, symname)) {
903 		printf("link_elf: symbol %s undefined\n", symname);
904 		return ENOENT;
905 	    }
906 	    rela++;
907 	}
908     }
909 
910     /* Perform PLT relocations without addend if there are any: */
911     rel = ef->pltrel;
912     if (rel) {
913 	rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
914 	while (rel < rellim) {
915 	    symname = symbol_name(ef, rel->r_info);
916 	    if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL, symname)) {
917 		printf("link_elf: symbol %s undefined\n", symname);
918 		return ENOENT;
919 	    }
920 	    rel++;
921 	}
922     }
923 
924     /* Perform relocations with addend if there are any: */
925     rela = ef->pltrela;
926     if (rela) {
927 	relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
928 	while (rela < relalim) {
929 	    symname = symbol_name(ef, rela->r_info);
930 	    if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA, symname)) {
931 		printf("link_elf: symbol %s undefined\n", symname);
932 		return ENOENT;
933 	    }
934 	    rela++;
935 	}
936     }
937 
938     return 0;
939 }
940 
941 /*
942  * Hash function for symbol table lookup.  Don't even think about changing
943  * this.  It is specified by the System V ABI.
944  */
945 static unsigned long
946 elf_hash(const char *name)
947 {
948     const unsigned char *p = (const unsigned char *) name;
949     unsigned long h = 0;
950     unsigned long g;
951 
952     while (*p != '\0') {
953 	h = (h << 4) + *p++;
954 	if ((g = h & 0xf0000000) != 0)
955 	    h ^= g >> 24;
956 	h &= ~g;
957     }
958     return h;
959 }
960 
961 int
962 link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym)
963 {
964     elf_file_t ef = (elf_file_t) lf;
965     unsigned long symnum;
966     const Elf_Sym* symp;
967     const char *strp;
968     unsigned long hash;
969     int i;
970 
971     /* First, search hashed global symbols */
972     hash = elf_hash(name);
973     symnum = ef->buckets[hash % ef->nbuckets];
974 
975     while (symnum != STN_UNDEF) {
976 	if (symnum >= ef->nchains) {
977 	    printf("link_elf_lookup_symbol: corrupt symbol table\n");
978 	    return ENOENT;
979 	}
980 
981 	symp = ef->symtab + symnum;
982 	if (symp->st_name == 0) {
983 	    printf("link_elf_lookup_symbol: corrupt symbol table\n");
984 	    return ENOENT;
985 	}
986 
987 	strp = ef->strtab + symp->st_name;
988 
989 	if (strcmp(name, strp) == 0) {
990 	    if (symp->st_shndx != SHN_UNDEF ||
991 		(symp->st_value != 0 &&
992 		 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
993 		*sym = (c_linker_sym_t) symp;
994 		return 0;
995 	    } else
996 		return ENOENT;
997 	}
998 
999 	symnum = ef->chains[symnum];
1000     }
1001 
1002     /* If we have not found it, look at the full table (if loaded) */
1003     if (ef->symtab == ef->ddbsymtab)
1004 	return ENOENT;
1005 
1006     /* Exhaustive search */
1007     for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1008 	strp = ef->ddbstrtab + symp->st_name;
1009 	if (strcmp(name, strp) == 0) {
1010 	    if (symp->st_shndx != SHN_UNDEF ||
1011 		(symp->st_value != 0 &&
1012 		 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
1013 		*sym = (c_linker_sym_t) symp;
1014 		return 0;
1015 	    } else
1016 		return ENOENT;
1017 	}
1018     }
1019 
1020     return ENOENT;
1021 }
1022 
1023 static int
1024 link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval_t* symval)
1025 {
1026 	elf_file_t ef = (elf_file_t) lf;
1027 	const Elf_Sym* es = (const Elf_Sym*) sym;
1028 
1029 	if (es >= ef->symtab && ((es - ef->symtab) < ef->nchains)) {
1030 	    symval->name = ef->strtab + es->st_name;
1031 	    symval->value = (caddr_t) ef->address + es->st_value;
1032 	    symval->size = es->st_size;
1033 	    return 0;
1034 	}
1035 	if (ef->symtab == ef->ddbsymtab)
1036 	    return ENOENT;
1037 	if (es >= ef->ddbsymtab && ((es - ef->ddbsymtab) < ef->ddbsymcnt)) {
1038 	    symval->name = ef->ddbstrtab + es->st_name;
1039 	    symval->value = (caddr_t) ef->address + es->st_value;
1040 	    symval->size = es->st_size;
1041 	    return 0;
1042 	}
1043 	return ENOENT;
1044 }
1045 
1046 static int
1047 link_elf_search_symbol(linker_file_t lf, caddr_t value,
1048 		       c_linker_sym_t* sym, long* diffp)
1049 {
1050 	elf_file_t ef = (elf_file_t) lf;
1051 	u_long off = (uintptr_t) (void *) value;
1052 	u_long diff = off;
1053 	u_long st_value;
1054 	const Elf_Sym* es;
1055 	const Elf_Sym* best = 0;
1056 	int i;
1057 
1058 	for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
1059 		if (es->st_name == 0)
1060 			continue;
1061 		st_value = es->st_value + (uintptr_t) (void *) ef->address;
1062 		if (off >= st_value) {
1063 			if (off - st_value < diff) {
1064 				diff = off - st_value;
1065 				best = es;
1066 				if (diff == 0)
1067 					break;
1068 			} else if (off - st_value == diff) {
1069 				best = es;
1070 			}
1071 		}
1072 	}
1073 	if (best == 0)
1074 		*diffp = off;
1075 	else
1076 		*diffp = diff;
1077 	*sym = (c_linker_sym_t) best;
1078 
1079 	return 0;
1080 }
1081 
1082 /*
1083  * Look up a linker set on an ELF system.
1084  */
1085 static int
1086 link_elf_lookup_set(linker_file_t lf, const char *name,
1087 		    void ***startp, void ***stopp, int *countp)
1088 {
1089 	c_linker_sym_t sym;
1090 	linker_symval_t symval;
1091 	char *setsym;
1092 	void **start, **stop;
1093 	int len, error = 0, count;
1094 
1095 	len = strlen(name) + sizeof("__start_set_"); /* sizeof includes \0 */
1096 	setsym = malloc(len, M_LINKER, M_WAITOK);
1097 	if (setsym == NULL)
1098 		return ENOMEM;
1099 
1100 	/* get address of first entry */
1101 	snprintf(setsym, len, "%s%s", "__start_set_", name);
1102 	error = link_elf_lookup_symbol(lf, setsym, &sym);
1103 	if (error)
1104 		goto out;
1105 	link_elf_symbol_values(lf, sym, &symval);
1106 	if (symval.value == 0) {
1107 		error = ESRCH;
1108 		goto out;
1109 	}
1110 	start = (void **)symval.value;
1111 
1112 	/* get address of last entry */
1113 	snprintf(setsym, len, "%s%s", "__stop_set_", name);
1114 	error = link_elf_lookup_symbol(lf, setsym, &sym);
1115 	if (error)
1116 		goto out;
1117 	link_elf_symbol_values(lf, sym, &symval);
1118 	if (symval.value == 0) {
1119 		error = ESRCH;
1120 		goto out;
1121 	}
1122 	stop = (void **)symval.value;
1123 
1124 	/* and the number of entries */
1125 	count = stop - start;
1126 
1127 	/* and copy out */
1128 	if (startp)
1129 		*startp = start;
1130 	if (stopp)
1131 		*stopp = stop;
1132 	if (countp)
1133 		*countp = count;
1134 
1135 out:
1136 	free(setsym, M_LINKER);
1137 	return error;
1138 }
1139