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