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