link_elf.c revision 54655
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 * $FreeBSD: head/sys/kern/link_elf.c 54655 1999-12-15 23:02:35Z eivind $
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_param.h>
42#include <vm/vm_zone.h>
43#include <sys/lock.h>
44#ifdef SPARSE_MAPPING
45#include <vm/vm_object.h>
46#include <vm/vm_kern.h>
47#include <vm/vm_extern.h>
48#endif
49#include <vm/pmap.h>
50#include <vm/vm_map.h>
51
52static int	link_elf_load_module(const char*, linker_file_t*);
53static int	link_elf_load_file(const char*, linker_file_t*);
54static int	link_elf_lookup_symbol(linker_file_t, const char*,
55				       c_linker_sym_t*);
56static int	link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*);
57static int	link_elf_search_symbol(linker_file_t, caddr_t value,
58				       c_linker_sym_t* sym, long* diffp);
59
60static void	link_elf_unload_file(linker_file_t);
61static void	link_elf_unload_module(linker_file_t);
62
63static struct linker_class_ops link_elf_class_ops = {
64    link_elf_load_module,
65};
66
67static struct linker_file_ops link_elf_file_ops = {
68    link_elf_lookup_symbol,
69    link_elf_symbol_values,
70    link_elf_search_symbol,
71    link_elf_unload_file,
72};
73
74static struct linker_file_ops link_elf_module_ops = {
75    link_elf_lookup_symbol,
76    link_elf_symbol_values,
77    link_elf_search_symbol,
78    link_elf_unload_module,
79};
80typedef struct elf_file {
81    caddr_t		address;	/* Relocation address */
82#ifdef SPARSE_MAPPING
83    vm_object_t		object;		/* VM object to hold file pages */
84#endif
85    const Elf_Dyn*	dynamic;	/* Symbol table etc. */
86    Elf_Off		nbuckets;	/* DT_HASH info */
87    Elf_Off		nchains;
88    const Elf_Off*	buckets;
89    const Elf_Off*	chains;
90    caddr_t		hash;
91    caddr_t		strtab;		/* DT_STRTAB */
92    int			strsz;		/* DT_STRSZ */
93    const Elf_Sym*	symtab;		/* DT_SYMTAB */
94    Elf_Addr*		got;		/* DT_PLTGOT */
95    const Elf_Rel*	pltrel;		/* DT_JMPREL */
96    int			pltrelsize;	/* DT_PLTRELSZ */
97    const Elf_Rela*	pltrela;	/* DT_JMPREL */
98    int			pltrelasize;	/* DT_PLTRELSZ */
99    const Elf_Rel*	rel;		/* DT_REL */
100    int			relsize;	/* DT_RELSZ */
101    const Elf_Rela*	rela;		/* DT_RELA */
102    int			relasize;	/* DT_RELASZ */
103    caddr_t		modptr;
104    const Elf_Sym*	ddbsymtab;	/* The symbol table we are using */
105    long		ddbsymcnt;	/* Number of symbols */
106    caddr_t		ddbstrtab;	/* String table */
107    long		ddbstrcnt;	/* number of bytes in string table */
108    caddr_t		symbase;	/* malloc'ed symbold base */
109    caddr_t		strbase;	/* malloc'ed string base */
110} *elf_file_t;
111
112static int		parse_dynamic(linker_file_t lf);
113static int		load_dependancies(linker_file_t lf);
114static int		relocate_file(linker_file_t lf);
115static int		parse_module_symbols(linker_file_t lf);
116
117/*
118 * The kernel symbol table starts here.
119 */
120extern struct _dynamic _DYNAMIC;
121
122static void
123link_elf_init(void* arg)
124{
125#ifdef __ELF__
126    Elf_Dyn	*dp;
127    caddr_t	modptr, baseptr, sizeptr;
128    elf_file_t	ef;
129    char	*modname;
130#endif
131
132#if ELF_TARG_CLASS == ELFCLASS32
133    linker_add_class("elf32", NULL, &link_elf_class_ops);
134#else
135    linker_add_class("elf64", NULL, &link_elf_class_ops);
136#endif
137
138#ifdef __ELF__
139    dp = (Elf_Dyn*) &_DYNAMIC;
140    if (dp) {
141	ef = malloc(sizeof(struct elf_file), M_LINKER, M_NOWAIT);
142	if (ef == NULL)
143	    panic("link_elf_init: Can't create linker structures for kernel");
144	bzero(ef, sizeof(*ef));
145
146	ef->address = 0;
147#ifdef SPARSE_MAPPING
148	ef->object = 0;
149#endif
150	ef->dynamic = dp;
151	modname = NULL;
152	modptr = preload_search_by_type("elf kernel");
153	if (modptr)
154	    modname = (char *)preload_search_info(modptr, MODINFO_NAME);
155	if (modname == NULL)
156	    modname = "kernel";
157	linker_kernel_file = linker_make_file(modname, ef, &link_elf_file_ops);
158	if (linker_kernel_file == NULL)
159	    panic("link_elf_init: Can't create linker structures for kernel");
160	parse_dynamic(linker_kernel_file);
161	linker_kernel_file->address = (caddr_t) KERNBASE;
162	linker_kernel_file->size = -(intptr_t)linker_kernel_file->address;
163
164	if (modptr) {
165	    ef->modptr = modptr;
166	    baseptr = preload_search_info(modptr, MODINFO_ADDR);
167	    if (baseptr)
168		linker_kernel_file->address = *(caddr_t *)baseptr;
169	    sizeptr = preload_search_info(modptr, MODINFO_SIZE);
170	    if (sizeptr)
171		linker_kernel_file->size = *(size_t *)sizeptr;
172	}
173	(void)parse_module_symbols(linker_kernel_file);
174	linker_current_file = linker_kernel_file;
175	linker_kernel_file->flags |= LINKER_FILE_LINKED;
176    }
177#endif
178}
179
180SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
181
182static int
183parse_module_symbols(linker_file_t lf)
184{
185    elf_file_t ef = lf->priv;
186    caddr_t	pointer;
187    caddr_t	ssym, esym, base;
188    caddr_t	strtab;
189    int		strcnt;
190    Elf_Sym*	symtab;
191    int		symcnt;
192
193    if (ef->modptr == NULL)
194	return 0;
195    pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM);
196    if (pointer == NULL)
197	return 0;
198    ssym = *(caddr_t *)pointer;
199    pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM);
200    if (pointer == NULL)
201	return 0;
202    esym = *(caddr_t *)pointer;
203
204    base = ssym;
205
206    symcnt = *(long *)base;
207    base += sizeof(long);
208    symtab = (Elf_Sym *)base;
209    base += roundup(symcnt, sizeof(long));
210
211    if (base > esym || base < ssym) {
212	printf("Symbols are corrupt!\n");
213	return EINVAL;
214    }
215
216    strcnt = *(long *)base;
217    base += sizeof(long);
218    strtab = base;
219    base += roundup(strcnt, sizeof(long));
220
221    if (base > esym || base < ssym) {
222	printf("Symbols are corrupt!\n");
223	return EINVAL;
224    }
225
226    ef->ddbsymtab = symtab;
227    ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
228    ef->ddbstrtab = strtab;
229    ef->ddbstrcnt = strcnt;
230
231    return 0;
232}
233
234static int
235parse_dynamic(linker_file_t lf)
236{
237    elf_file_t ef = lf->priv;
238    const Elf_Dyn *dp;
239    int plttype = DT_REL;
240
241    for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
242	switch (dp->d_tag) {
243	case DT_HASH:
244	{
245	    /* From src/libexec/rtld-elf/rtld.c */
246	    const Elf_Off *hashtab = (const Elf_Off *)
247		(ef->address + dp->d_un.d_ptr);
248	    ef->nbuckets = hashtab[0];
249	    ef->nchains = hashtab[1];
250	    ef->buckets = hashtab + 2;
251	    ef->chains = ef->buckets + ef->nbuckets;
252	    break;
253	}
254	case DT_STRTAB:
255	    ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr);
256	    break;
257	case DT_STRSZ:
258	    ef->strsz = dp->d_un.d_val;
259	    break;
260	case DT_SYMTAB:
261	    ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr);
262	    break;
263	case DT_SYMENT:
264	    if (dp->d_un.d_val != sizeof(Elf_Sym))
265		return ENOEXEC;
266	    break;
267	case DT_PLTGOT:
268	    ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr);
269	    break;
270	case DT_REL:
271	    ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
272	    break;
273	case DT_RELSZ:
274	    ef->relsize = dp->d_un.d_val;
275	    break;
276	case DT_RELENT:
277	    if (dp->d_un.d_val != sizeof(Elf_Rel))
278		return ENOEXEC;
279	    break;
280	case DT_JMPREL:
281	    ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
282	    break;
283	case DT_PLTRELSZ:
284	    ef->pltrelsize = dp->d_un.d_val;
285	    break;
286	case DT_RELA:
287	    ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr);
288	    break;
289	case DT_RELASZ:
290	    ef->relasize = dp->d_un.d_val;
291	    break;
292	case DT_RELAENT:
293	    if (dp->d_un.d_val != sizeof(Elf_Rela))
294		return ENOEXEC;
295	    break;
296	case DT_PLTREL:
297	    plttype = dp->d_un.d_val;
298	    if (plttype != DT_REL && plttype != DT_RELA)
299		return ENOEXEC;
300	    break;
301	}
302    }
303
304    if (plttype == DT_RELA) {
305	ef->pltrela = (const Elf_Rela *) ef->pltrel;
306	ef->pltrel = NULL;
307	ef->pltrelasize = ef->pltrelsize;
308	ef->pltrelsize = 0;
309    }
310
311    ef->ddbsymtab = ef->symtab;
312    ef->ddbsymcnt = ef->nchains;
313    ef->ddbstrtab = ef->strtab;
314    ef->ddbstrcnt = ef->strsz;
315
316    return 0;
317}
318
319static void
320link_elf_error(const char *s)
321{
322    printf("kldload: %s\n", s);
323}
324
325static int
326link_elf_load_module(const char *filename, linker_file_t *result)
327{
328    caddr_t		modptr, baseptr, sizeptr, dynptr;
329    char		*type;
330    elf_file_t		ef;
331    linker_file_t	lf;
332    int			error;
333    vm_offset_t		dp;
334
335    /* Look to see if we have the module preloaded */
336    modptr = preload_search_by_name(filename);
337    if (modptr == NULL)
338	return (link_elf_load_file(filename, result));
339
340    /* It's preloaded, check we can handle it and collect information */
341    type = (char *)preload_search_info(modptr, MODINFO_TYPE);
342    baseptr = preload_search_info(modptr, MODINFO_ADDR);
343    sizeptr = preload_search_info(modptr, MODINFO_SIZE);
344    dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC);
345    if (type == NULL || strcmp(type, "elf module") != 0)
346	return (EFTYPE);
347    if (baseptr == NULL || sizeptr == NULL || dynptr == NULL)
348	return (EINVAL);
349
350    ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK);
351    if (ef == NULL)
352	return (ENOMEM);
353    bzero(ef, sizeof(*ef));
354    ef->modptr = modptr;
355    ef->address = *(caddr_t *)baseptr;
356#ifdef SPARSE_MAPPING
357    ef->object = 0;
358#endif
359    dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr;
360    ef->dynamic = (Elf_Dyn *)dp;
361    lf = linker_make_file(filename, ef, &link_elf_module_ops);
362    if (lf == NULL) {
363	free(ef, M_LINKER);
364	return ENOMEM;
365    }
366    lf->address = ef->address;
367    lf->size = *(size_t *)sizeptr;
368
369    error = parse_dynamic(lf);
370    if (error) {
371	linker_file_unload(lf);
372	return error;
373    }
374    error = load_dependancies(lf);
375    if (error) {
376	linker_file_unload(lf);
377	return error;
378    }
379    error = relocate_file(lf);
380    if (error) {
381	linker_file_unload(lf);
382	return error;
383    }
384    (void)parse_module_symbols(lf);
385    lf->flags |= LINKER_FILE_LINKED;
386    *result = lf;
387    return (0);
388}
389
390static int
391link_elf_load_file(const char* filename, linker_file_t* result)
392{
393    struct nameidata nd;
394    struct proc* p = curproc;	/* XXX */
395    Elf_Ehdr *hdr;
396    caddr_t firstpage;
397    int nbytes, i;
398    Elf_Phdr *phdr;
399    Elf_Phdr *phlimit;
400    Elf_Phdr *segs[2];
401    int nsegs;
402    Elf_Phdr *phdyn;
403    Elf_Phdr *phphdr;
404    caddr_t mapbase;
405    size_t mapsize;
406    Elf_Off base_offset;
407    Elf_Addr base_vaddr;
408    Elf_Addr base_vlimit;
409    int error = 0;
410    int resid;
411    elf_file_t ef;
412    linker_file_t lf;
413    char *pathname;
414    Elf_Shdr *shdr;
415    int symtabindex;
416    int symstrindex;
417    int symcnt;
418    int strcnt;
419
420    shdr = NULL;
421    lf = NULL;
422
423    pathname = linker_search_path(filename);
424    if (pathname == NULL)
425	return ENOENT;
426
427    NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, pathname, p);
428    error = vn_open(&nd, FREAD, 0);
429    free(pathname, M_LINKER);
430    if (error)
431	return error;
432    NDFREE(&nd, NDF_ONLY_PNBUF);
433
434    /*
435     * Read the elf header from the file.
436     */
437    firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK);
438    if (firstpage == NULL) {
439	error = ENOMEM;
440	goto out;
441    }
442    hdr = (Elf_Ehdr *)firstpage;
443    error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0,
444		    UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
445    nbytes = PAGE_SIZE - resid;
446    if (error)
447	goto out;
448
449    if (!IS_ELF(*hdr)) {
450	error = ENOEXEC;
451	goto out;
452    }
453
454    if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
455      || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
456	link_elf_error("Unsupported file layout");
457	error = ENOEXEC;
458	goto out;
459    }
460    if (hdr->e_ident[EI_VERSION] != EV_CURRENT
461      || hdr->e_version != EV_CURRENT) {
462	link_elf_error("Unsupported file version");
463	error = ENOEXEC;
464	goto out;
465    }
466    if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
467	link_elf_error("Unsupported file type");
468	error = ENOEXEC;
469	goto out;
470    }
471    if (hdr->e_machine != ELF_TARG_MACH) {
472	link_elf_error("Unsupported machine");
473	error = ENOEXEC;
474	goto out;
475    }
476
477    /*
478     * We rely on the program header being in the first page.  This is
479     * not strictly required by the ABI specification, but it seems to
480     * always true in practice.  And, it simplifies things considerably.
481     */
482    if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) &&
483	  (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) &&
484	  (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes)))
485	link_elf_error("Unreadable program headers");
486
487    /*
488     * Scan the program header entries, and save key information.
489     *
490     * We rely on there being exactly two load segments, text and data,
491     * in that order.
492     */
493    phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff);
494    phlimit = phdr + hdr->e_phnum;
495    nsegs = 0;
496    phdyn = NULL;
497    phphdr = NULL;
498    while (phdr < phlimit) {
499	switch (phdr->p_type) {
500
501	case PT_LOAD:
502	    if (nsegs == 2) {
503		link_elf_error("Too many sections");
504		error = ENOEXEC;
505		goto out;
506	    }
507	    segs[nsegs] = phdr;
508	    ++nsegs;
509	    break;
510
511	case PT_PHDR:
512	    phphdr = phdr;
513	    break;
514
515	case PT_DYNAMIC:
516	    phdyn = phdr;
517	    break;
518	}
519
520	++phdr;
521    }
522    if (phdyn == NULL) {
523	link_elf_error("Object is not dynamically-linked");
524	error = ENOEXEC;
525	goto out;
526    }
527
528    /*
529     * Allocate the entire address space of the object, to stake out our
530     * contiguous region, and to establish the base address for relocation.
531     */
532    base_offset = trunc_page(segs[0]->p_offset);
533    base_vaddr = trunc_page(segs[0]->p_vaddr);
534    base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
535    mapsize = base_vlimit - base_vaddr;
536
537    ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK);
538    bzero(ef, sizeof(*ef));
539#ifdef SPARSE_MAPPING
540    ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
541    if (ef->object == NULL) {
542	free(ef, M_LINKER);
543	error = ENOMEM;
544	goto out;
545    }
546    vm_object_reference(ef->object);
547    ef->address = (caddr_t) vm_map_min(kernel_map);
548    error = vm_map_find(kernel_map, ef->object, 0,
549			(vm_offset_t *) &ef->address,
550			mapsize, 1,
551			VM_PROT_ALL, VM_PROT_ALL, 0);
552    if (error) {
553	vm_object_deallocate(ef->object);
554	free(ef, M_LINKER);
555	goto out;
556    }
557#else
558    ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
559#endif
560    mapbase = ef->address;
561
562    /*
563     * Read the text and data sections and zero the bss.
564     */
565    for (i = 0; i < 2; i++) {
566	caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
567	error = vn_rdwr(UIO_READ, nd.ni_vp,
568			segbase, segs[i]->p_filesz, segs[i]->p_offset,
569			UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
570	if (error) {
571#ifdef SPARSE_MAPPING
572	    vm_map_remove(kernel_map, (vm_offset_t) ef->address,
573			  (vm_offset_t) ef->address
574			  + (ef->object->size << PAGE_SHIFT));
575	    vm_object_deallocate(ef->object);
576#else
577	    free(ef->address, M_LINKER);
578#endif
579	    free(ef, M_LINKER);
580	    goto out;
581	}
582	bzero(segbase + segs[i]->p_filesz,
583	      segs[i]->p_memsz - segs[i]->p_filesz);
584
585#ifdef SPARSE_MAPPING
586	/*
587	 * Wire down the pages
588	 */
589	vm_map_pageable(kernel_map,
590			(vm_offset_t) segbase,
591			(vm_offset_t) segbase + segs[i]->p_memsz,
592			FALSE);
593#endif
594    }
595
596    ef->dynamic = (const Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr);
597
598    lf = linker_make_file(filename, ef, &link_elf_file_ops);
599    if (lf == NULL) {
600#ifdef SPARSE_MAPPING
601	vm_map_remove(kernel_map, (vm_offset_t) ef->address,
602		      (vm_offset_t) ef->address
603		      + (ef->object->size << PAGE_SHIFT));
604	vm_object_deallocate(ef->object);
605#else
606	free(ef->address, M_LINKER);
607#endif
608	free(ef, M_LINKER);
609	error = ENOMEM;
610	goto out;
611    }
612    lf->address = ef->address;
613    lf->size = mapsize;
614
615    error = parse_dynamic(lf);
616    if (error)
617	goto out;
618    error = load_dependancies(lf);
619    if (error)
620	goto out;
621    error = relocate_file(lf);
622    if (error)
623	goto out;
624
625    /* Try and load the symbol table if it's present.  (you can strip it!) */
626    nbytes = hdr->e_shnum * hdr->e_shentsize;
627    if (nbytes == 0 || hdr->e_shoff == 0)
628	goto nosyms;
629    shdr = malloc(nbytes, M_LINKER, M_WAITOK);
630    if (shdr == NULL) {
631	error = ENOMEM;
632	goto out;
633    }
634    bzero(shdr, nbytes);
635    error = vn_rdwr(UIO_READ, nd.ni_vp,
636		    (caddr_t)shdr, nbytes, hdr->e_shoff,
637		    UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
638    if (error)
639	goto out;
640    symtabindex = -1;
641    symstrindex = -1;
642    for (i = 0; i < hdr->e_shnum; i++) {
643	if (shdr[i].sh_type == SHT_SYMTAB) {
644	    symtabindex = i;
645	    symstrindex = shdr[i].sh_link;
646	}
647    }
648    if (symtabindex < 0 || symstrindex < 0)
649	goto nosyms;
650
651    symcnt = shdr[symtabindex].sh_size;
652    ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK);
653    strcnt = shdr[symstrindex].sh_size;
654    ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK);
655
656    if (ef->symbase == NULL || ef->strbase == NULL) {
657	error = ENOMEM;
658	goto out;
659    }
660    error = vn_rdwr(UIO_READ, nd.ni_vp,
661		    ef->symbase, symcnt, shdr[symtabindex].sh_offset,
662		    UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
663    if (error)
664	goto out;
665    error = vn_rdwr(UIO_READ, nd.ni_vp,
666		    ef->strbase, strcnt, shdr[symstrindex].sh_offset,
667		    UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
668    if (error)
669	goto out;
670
671    ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
672    ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
673    ef->ddbstrcnt = strcnt;
674    ef->ddbstrtab = ef->strbase;
675
676    lf->flags |= LINKER_FILE_LINKED;
677
678nosyms:
679
680    *result = lf;
681
682out:
683    if (error && lf)
684	linker_file_unload(lf);
685    if (shdr)
686	free(shdr, M_LINKER);
687    if (firstpage)
688	free(firstpage, M_LINKER);
689    VOP_UNLOCK(nd.ni_vp, 0, p);
690    vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
691
692    return error;
693}
694
695static void
696link_elf_unload_file(linker_file_t file)
697{
698    elf_file_t ef = file->priv;
699
700    if (ef) {
701#ifdef SPARSE_MAPPING
702	if (ef->object) {
703	    vm_map_remove(kernel_map, (vm_offset_t) ef->address,
704			  (vm_offset_t) ef->address
705			  + (ef->object->size << PAGE_SHIFT));
706	    vm_object_deallocate(ef->object);
707	}
708#else
709	if (ef->address)
710	    free(ef->address, M_LINKER);
711#endif
712	if (ef->symbase)
713	    free(ef->symbase, M_LINKER);
714	if (ef->strbase)
715	    free(ef->strbase, M_LINKER);
716	free(ef, M_LINKER);
717    }
718}
719
720static void
721link_elf_unload_module(linker_file_t file)
722{
723    elf_file_t ef = file->priv;
724
725    if (ef)
726	free(ef, M_LINKER);
727    if (file->filename)
728	preload_delete_name(file->filename);
729}
730
731static int
732load_dependancies(linker_file_t lf)
733{
734    elf_file_t ef = lf->priv;
735    linker_file_t lfdep;
736    char* name;
737    const Elf_Dyn *dp;
738    int error = 0;
739
740    /*
741     * All files are dependant on /kernel.
742     */
743    if (linker_kernel_file) {
744	linker_kernel_file->refs++;
745	linker_file_add_dependancy(lf, linker_kernel_file);
746    }
747
748    for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
749	if (dp->d_tag == DT_NEEDED) {
750	    name = ef->strtab + dp->d_un.d_val;
751
752	    error = linker_load_file(name, &lfdep);
753	    if (error)
754		goto out;
755	    error = linker_file_add_dependancy(lf, lfdep);
756	    if (error)
757		goto out;
758	}
759    }
760
761out:
762    return error;
763}
764
765static const char *
766symbol_name(elf_file_t ef, Elf_Word r_info)
767{
768    const Elf_Sym *ref;
769
770    if (ELF_R_SYM(r_info)) {
771	ref = ef->symtab + ELF_R_SYM(r_info);
772	return ef->strtab + ref->st_name;
773    } else
774	return NULL;
775}
776
777static int
778relocate_file(linker_file_t lf)
779{
780    elf_file_t ef = lf->priv;
781    const Elf_Rel *rellim;
782    const Elf_Rel *rel;
783    const Elf_Rela *relalim;
784    const Elf_Rela *rela;
785    const char *symname;
786
787    /* Perform relocations without addend if there are any: */
788    rel = ef->rel;
789    if (rel) {
790	rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
791	while (rel < rellim) {
792	    symname = symbol_name(ef, rel->r_info);
793	    if (elf_reloc(lf, rel, ELF_RELOC_REL, symname)) {
794		printf("link_elf: symbol %s undefined\n", symname);
795		return ENOENT;
796	    }
797	    rel++;
798	}
799    }
800
801    /* Perform relocations with addend if there are any: */
802    rela = ef->rela;
803    if (rela) {
804	relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
805	while (rela < relalim) {
806	    symname = symbol_name(ef, rela->r_info);
807	    if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname)) {
808		printf("link_elf: symbol %s undefined\n", symname);
809		return ENOENT;
810	    }
811	    rela++;
812	}
813    }
814
815    /* Perform PLT relocations without addend if there are any: */
816    rel = ef->pltrel;
817    if (rel) {
818	rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
819	while (rel < rellim) {
820	    symname = symbol_name(ef, rel->r_info);
821	    if (elf_reloc(lf, rel, ELF_RELOC_REL, symname)) {
822		printf("link_elf: symbol %s undefined\n", symname);
823		return ENOENT;
824	    }
825	    rel++;
826	}
827    }
828
829    /* Perform relocations with addend if there are any: */
830    rela = ef->pltrela;
831    if (rela) {
832	relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
833	while (rela < relalim) {
834	    symname = symbol_name(ef, rela->r_info);
835	    if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname)) {
836		printf("link_elf: symbol %s undefined\n", symname);
837		return ENOENT;
838	    }
839	    rela++;
840	}
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, c_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 = (c_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 = (c_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, c_linker_sym_t sym, linker_symval_t* symval)
930{
931	elf_file_t ef = lf->priv;
932	const Elf_Sym* es = (const 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		       c_linker_sym_t* sym, long* diffp)
954{
955	elf_file_t ef = lf->priv;
956	u_long off = (uintptr_t) value;
957	u_long diff = off;
958	const Elf_Sym* es;
959	const Elf_Sym* best = 0;
960	int i;
961	u_long st_value;
962
963	for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
964		if (es->st_name == 0)
965			continue;
966		st_value = es->st_value + (u_long)ef->address;
967		if (off >= st_value) {
968			if (off - st_value < diff) {
969				diff = off - st_value;
970				best = es;
971				if (diff == 0)
972					break;
973			} else if (off - st_value == diff) {
974				best = es;
975			}
976		}
977	}
978	if (best == 0)
979		*diffp = off;
980	else
981		*diffp = diff;
982	*sym = (c_linker_sym_t) best;
983
984	return 0;
985}
986