link_elf.c revision 194784
1219019Sgabor/*-
2219019Sgabor * Copyright (c) 1998-2000 Doug Rabson
3219019Sgabor * All rights reserved.
4219019Sgabor *
5219019Sgabor * Redistribution and use in source and binary forms, with or without
6219019Sgabor * modification, are permitted provided that the following conditions
7219019Sgabor * 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
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/kern/link_elf.c 194784 2009-06-23 22:42:39Z jeff $");
29
30#include "opt_ddb.h"
31#include "opt_gdb.h"
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#ifdef GPROF
36#include <sys/gmon.h>
37#endif
38#include <sys/kernel.h>
39#include <sys/lock.h>
40#include <sys/malloc.h>
41#include <sys/mutex.h>
42#include <sys/mount.h>
43#include <sys/pcpu.h>
44#include <sys/proc.h>
45#include <sys/namei.h>
46#include <sys/fcntl.h>
47#include <sys/vnode.h>
48#include <sys/linker.h>
49
50#include <machine/elf.h>
51
52#include <security/mac/mac_framework.h>
53
54#include <vm/vm.h>
55#include <vm/vm_param.h>
56#ifdef SPARSE_MAPPING
57#include <vm/vm_object.h>
58#include <vm/vm_kern.h>
59#include <vm/vm_extern.h>
60#endif
61#include <vm/pmap.h>
62#include <vm/vm_map.h>
63
64#include <sys/link_elf.h>
65
66#ifdef DDB_CTF
67#include <net/zlib.h>
68#endif
69
70#include "linker_if.h"
71
72#define MAXSEGS 4
73
74typedef struct elf_file {
75    struct linker_file	lf;		/* Common fields */
76    int			preloaded;	/* Was file pre-loaded */
77    caddr_t		address;	/* Relocation address */
78#ifdef SPARSE_MAPPING
79    vm_object_t		object;		/* VM object to hold file pages */
80#endif
81    Elf_Dyn*		dynamic;	/* Symbol table etc. */
82    Elf_Hashelt		nbuckets;	/* DT_HASH info */
83    Elf_Hashelt		nchains;
84    const Elf_Hashelt*	buckets;
85    const Elf_Hashelt*	chains;
86    caddr_t		hash;
87    caddr_t		strtab;		/* DT_STRTAB */
88    int			strsz;		/* DT_STRSZ */
89    const Elf_Sym*	symtab;		/* DT_SYMTAB */
90    Elf_Addr*		got;		/* DT_PLTGOT */
91    const Elf_Rel*	pltrel;		/* DT_JMPREL */
92    int			pltrelsize;	/* DT_PLTRELSZ */
93    const Elf_Rela*	pltrela;	/* DT_JMPREL */
94    int			pltrelasize;	/* DT_PLTRELSZ */
95    const Elf_Rel*	rel;		/* DT_REL */
96    int			relsize;	/* DT_RELSZ */
97    const Elf_Rela*	rela;		/* DT_RELA */
98    int			relasize;	/* DT_RELASZ */
99    caddr_t		modptr;
100    const Elf_Sym*	ddbsymtab;	/* The symbol table we are using */
101    long		ddbsymcnt;	/* Number of symbols */
102    caddr_t		ddbstrtab;	/* String table */
103    long		ddbstrcnt;	/* number of bytes in string table */
104    caddr_t		symbase;	/* malloc'ed symbold base */
105    caddr_t		strbase;	/* malloc'ed string base */
106    caddr_t		ctftab;		/* CTF table */
107    long		ctfcnt;		/* number of bytes in CTF table */
108    caddr_t		ctfoff;		/* CTF offset table */
109    caddr_t		typoff;		/* Type offset table */
110    long		typlen;		/* Number of type entries. */
111    Elf_Addr		pcpu_start;	/* Pre-relocation pcpu set start. */
112    Elf_Addr		pcpu_stop;	/* Pre-relocation pcpu set stop. */
113    Elf_Addr		pcpu_base;	/* Relocated pcpu set address. */
114#ifdef GDB
115    struct link_map	gdb;		/* hooks for gdb */
116#endif
117} *elf_file_t;
118
119#include <kern/kern_ctf.c>
120
121static int	link_elf_link_common_finish(linker_file_t);
122static int	link_elf_link_preload(linker_class_t cls,
123				      const char*, linker_file_t*);
124static int	link_elf_link_preload_finish(linker_file_t);
125static int	link_elf_load_file(linker_class_t, const char*, linker_file_t*);
126static int	link_elf_lookup_symbol(linker_file_t, const char*,
127				       c_linker_sym_t*);
128static int	link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*);
129static int	link_elf_search_symbol(linker_file_t, caddr_t value,
130				       c_linker_sym_t* sym, long* diffp);
131
132static void	link_elf_unload_file(linker_file_t);
133static void	link_elf_unload_preload(linker_file_t);
134static int	link_elf_lookup_set(linker_file_t, const char *,
135				    void ***, void ***, int *);
136static int	link_elf_each_function_name(linker_file_t,
137				int (*)(const char *, void *),
138				void *);
139static int	link_elf_each_function_nameval(linker_file_t,
140				linker_function_nameval_callback_t,
141				void *);
142static void	link_elf_reloc_local(linker_file_t);
143static long	link_elf_symtab_get(linker_file_t, const Elf_Sym **);
144static long	link_elf_strtab_get(linker_file_t, caddr_t *);
145static Elf_Addr	elf_lookup(linker_file_t lf, Elf_Size symidx, int deps);
146
147static kobj_method_t link_elf_methods[] = {
148    KOBJMETHOD(linker_lookup_symbol,	link_elf_lookup_symbol),
149    KOBJMETHOD(linker_symbol_values,	link_elf_symbol_values),
150    KOBJMETHOD(linker_search_symbol,	link_elf_search_symbol),
151    KOBJMETHOD(linker_unload,		link_elf_unload_file),
152    KOBJMETHOD(linker_load_file,	link_elf_load_file),
153    KOBJMETHOD(linker_link_preload,	link_elf_link_preload),
154    KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish),
155    KOBJMETHOD(linker_lookup_set,	link_elf_lookup_set),
156    KOBJMETHOD(linker_each_function_name, link_elf_each_function_name),
157    KOBJMETHOD(linker_each_function_nameval, link_elf_each_function_nameval),
158    KOBJMETHOD(linker_ctf_get,          link_elf_ctf_get),
159    KOBJMETHOD(linker_symtab_get, 	link_elf_symtab_get),
160    KOBJMETHOD(linker_strtab_get, 	link_elf_strtab_get),
161    { 0, 0 }
162};
163
164static struct linker_class link_elf_class = {
165#if ELF_TARG_CLASS == ELFCLASS32
166    "elf32",
167#else
168    "elf64",
169#endif
170    link_elf_methods, sizeof(struct elf_file)
171};
172
173static int		parse_dynamic(elf_file_t ef);
174static int		relocate_file(elf_file_t ef);
175static int		link_elf_preload_parse_symbols(elf_file_t ef);
176
177#ifdef GDB
178static void		r_debug_state(struct r_debug *dummy_one,
179				      struct link_map *dummy_two);
180
181/*
182 * A list of loaded modules for GDB to use for loading symbols.
183 */
184struct r_debug r_debug;
185
186#define GDB_STATE(s)	r_debug.r_state = s; r_debug_state(NULL, NULL);
187
188/*
189 * Function for the debugger to set a breakpoint on to gain control.
190 */
191static void
192r_debug_state(struct r_debug *dummy_one __unused,
193	      struct link_map *dummy_two __unused)
194{
195}
196
197static void
198link_elf_add_gdb(struct link_map *l)
199{
200    struct link_map *prev;
201
202    l->l_next = NULL;
203
204    if (r_debug.r_map == NULL) {
205	/* Add first. */
206	l->l_prev = NULL;
207	r_debug.r_map = l;
208    } else {
209	/* Append to list. */
210	for (prev = r_debug.r_map; prev->l_next != NULL; prev = prev->l_next)
211	    ;
212	l->l_prev = prev;
213	prev->l_next = l;
214    }
215}
216
217static void
218link_elf_delete_gdb(struct link_map *l)
219{
220    if (l->l_prev == NULL) {
221	/* Remove first. */
222	if ((r_debug.r_map = l->l_next) != NULL)
223	    l->l_next->l_prev = NULL;
224    } else {
225	/* Remove any but first. */
226	if ((l->l_prev->l_next = l->l_next) != NULL)
227	    l->l_next->l_prev = l->l_prev;
228    }
229}
230#endif /* GDB */
231
232#ifdef __ia64__
233Elf_Addr link_elf_get_gp(linker_file_t);
234#endif
235
236/*
237 * The kernel symbol table starts here.
238 */
239extern struct _dynamic _DYNAMIC;
240
241static void
242link_elf_error(const char *filename, const char *s)
243{
244	if (filename == NULL)
245		printf("kldload: %s\n", s);
246	else
247		printf("kldload: %s: %s\n", filename, s);
248}
249
250/*
251 * Actions performed after linking/loading both the preloaded kernel and any
252 * modules; whether preloaded or dynamicly loaded.
253 */
254static int
255link_elf_link_common_finish(linker_file_t lf)
256{
257#ifdef GDB
258    elf_file_t ef = (elf_file_t)lf;
259    char *newfilename;
260#endif
261    int error;
262
263    /* Notify MD code that a module is being loaded. */
264    error = elf_cpu_load_file(lf);
265    if (error)
266	return (error);
267
268#ifdef GDB
269    GDB_STATE(RT_ADD);
270    ef->gdb.l_addr = lf->address;
271    newfilename = malloc(strlen(lf->filename) + 1, M_LINKER, M_WAITOK);
272    strcpy(newfilename, lf->filename);
273    ef->gdb.l_name = newfilename;
274    ef->gdb.l_ld = ef->dynamic;
275    link_elf_add_gdb(&ef->gdb);
276    GDB_STATE(RT_CONSISTENT);
277#endif
278
279    return (0);
280}
281
282static void
283link_elf_init(void* arg)
284{
285    Elf_Dyn	*dp;
286    caddr_t	modptr, baseptr, sizeptr;
287    elf_file_t	ef;
288    char	*modname;
289
290    linker_add_class(&link_elf_class);
291
292    dp = (Elf_Dyn*) &_DYNAMIC;
293    modname = NULL;
294    modptr = preload_search_by_type("elf" __XSTRING(__ELF_WORD_SIZE) " kernel");
295    if (modptr == NULL)
296	modptr = preload_search_by_type("elf kernel");
297    if (modptr)
298	modname = (char *)preload_search_info(modptr, MODINFO_NAME);
299    if (modname == NULL)
300	modname = "kernel";
301    linker_kernel_file = linker_make_file(modname, &link_elf_class);
302    if (linker_kernel_file == NULL)
303	panic("link_elf_init: Can't create linker structures for kernel");
304
305    ef = (elf_file_t) linker_kernel_file;
306    ef->preloaded = 1;
307    ef->address = 0;
308#ifdef SPARSE_MAPPING
309    ef->object = 0;
310#endif
311    ef->dynamic = dp;
312
313    if (dp)
314	parse_dynamic(ef);
315    linker_kernel_file->address = (caddr_t) KERNBASE;
316    linker_kernel_file->size = -(intptr_t)linker_kernel_file->address;
317
318    if (modptr) {
319	ef->modptr = modptr;
320	baseptr = preload_search_info(modptr, MODINFO_ADDR);
321	if (baseptr)
322	    linker_kernel_file->address = *(caddr_t *)baseptr;
323	sizeptr = preload_search_info(modptr, MODINFO_SIZE);
324	if (sizeptr)
325	    linker_kernel_file->size = *(size_t *)sizeptr;
326    }
327    (void)link_elf_preload_parse_symbols(ef);
328
329#ifdef GDB
330    r_debug.r_map = NULL;
331    r_debug.r_brk = r_debug_state;
332    r_debug.r_state = RT_CONSISTENT;
333#endif
334
335    (void)link_elf_link_common_finish(linker_kernel_file);
336    linker_kernel_file->flags |= LINKER_FILE_LINKED;
337}
338
339SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_THIRD, link_elf_init, 0);
340
341static int
342link_elf_preload_parse_symbols(elf_file_t ef)
343{
344    caddr_t	pointer;
345    caddr_t	ssym, esym, base;
346    caddr_t	strtab;
347    int		strcnt;
348    Elf_Sym*	symtab;
349    int		symcnt;
350
351    if (ef->modptr == NULL)
352	return 0;
353    pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM);
354    if (pointer == NULL)
355	return 0;
356    ssym = *(caddr_t *)pointer;
357    pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_ESYM);
358    if (pointer == NULL)
359	return 0;
360    esym = *(caddr_t *)pointer;
361
362    base = ssym;
363
364    symcnt = *(long *)base;
365    base += sizeof(long);
366    symtab = (Elf_Sym *)base;
367    base += roundup(symcnt, sizeof(long));
368
369    if (base > esym || base < ssym) {
370	printf("Symbols are corrupt!\n");
371	return EINVAL;
372    }
373
374    strcnt = *(long *)base;
375    base += sizeof(long);
376    strtab = base;
377    base += roundup(strcnt, sizeof(long));
378
379    if (base > esym || base < ssym) {
380	printf("Symbols are corrupt!\n");
381	return EINVAL;
382    }
383
384    ef->ddbsymtab = symtab;
385    ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
386    ef->ddbstrtab = strtab;
387    ef->ddbstrcnt = strcnt;
388
389    return 0;
390}
391
392static int
393parse_dynamic(elf_file_t ef)
394{
395    Elf_Dyn *dp;
396    int plttype = DT_REL;
397
398    for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
399	switch (dp->d_tag) {
400	case DT_HASH:
401	{
402	    /* From src/libexec/rtld-elf/rtld.c */
403	    const Elf_Hashelt *hashtab = (const Elf_Hashelt *)
404		(ef->address + dp->d_un.d_ptr);
405	    ef->nbuckets = hashtab[0];
406	    ef->nchains = hashtab[1];
407	    ef->buckets = hashtab + 2;
408	    ef->chains = ef->buckets + ef->nbuckets;
409	    break;
410	}
411	case DT_STRTAB:
412	    ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr);
413	    break;
414	case DT_STRSZ:
415	    ef->strsz = dp->d_un.d_val;
416	    break;
417	case DT_SYMTAB:
418	    ef->symtab = (Elf_Sym*) (ef->address + dp->d_un.d_ptr);
419	    break;
420	case DT_SYMENT:
421	    if (dp->d_un.d_val != sizeof(Elf_Sym))
422		return ENOEXEC;
423	    break;
424	case DT_PLTGOT:
425	    ef->got = (Elf_Addr *) (ef->address + dp->d_un.d_ptr);
426	    break;
427	case DT_REL:
428	    ef->rel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
429	    break;
430	case DT_RELSZ:
431	    ef->relsize = dp->d_un.d_val;
432	    break;
433	case DT_RELENT:
434	    if (dp->d_un.d_val != sizeof(Elf_Rel))
435		return ENOEXEC;
436	    break;
437	case DT_JMPREL:
438	    ef->pltrel = (const Elf_Rel *) (ef->address + dp->d_un.d_ptr);
439	    break;
440	case DT_PLTRELSZ:
441	    ef->pltrelsize = dp->d_un.d_val;
442	    break;
443	case DT_RELA:
444	    ef->rela = (const Elf_Rela *) (ef->address + dp->d_un.d_ptr);
445	    break;
446	case DT_RELASZ:
447	    ef->relasize = dp->d_un.d_val;
448	    break;
449	case DT_RELAENT:
450	    if (dp->d_un.d_val != sizeof(Elf_Rela))
451		return ENOEXEC;
452	    break;
453	case DT_PLTREL:
454	    plttype = dp->d_un.d_val;
455	    if (plttype != DT_REL && plttype != DT_RELA)
456		return ENOEXEC;
457	    break;
458#ifdef GDB
459	case DT_DEBUG:
460	    dp->d_un.d_ptr = (Elf_Addr) &r_debug;
461	    break;
462#endif
463	}
464    }
465
466    if (plttype == DT_RELA) {
467	ef->pltrela = (const Elf_Rela *) ef->pltrel;
468	ef->pltrel = NULL;
469	ef->pltrelasize = ef->pltrelsize;
470	ef->pltrelsize = 0;
471    }
472
473    ef->ddbsymtab = ef->symtab;
474    ef->ddbsymcnt = ef->nchains;
475    ef->ddbstrtab = ef->strtab;
476    ef->ddbstrcnt = ef->strsz;
477
478    return 0;
479}
480
481static int
482parse_dpcpu(elf_file_t ef)
483{
484    int count;
485    int error;
486
487    ef->pcpu_start = 0;
488    ef->pcpu_stop = 0;
489    error = link_elf_lookup_set(&ef->lf, "pcpu", (void ***)&ef->pcpu_start,
490                               (void ***)&ef->pcpu_stop, &count);
491    /* Error just means there is no pcpu set to relocate. */
492    if (error)
493        return (0);
494    count *= sizeof(void *);
495    /*
496     * Allocate space in the primary pcpu area.  Copy in our initialization
497     * from the data section and then initialize all per-cpu storage from
498     * that.
499     */
500    ef->pcpu_base = (Elf_Addr)(uintptr_t)dpcpu_alloc(count);
501    if (ef->pcpu_base == (Elf_Addr)NULL)
502        return (ENOSPC);
503    memcpy((void *)ef->pcpu_base, (void *)ef->pcpu_start, count);
504    dpcpu_copy((void *)ef->pcpu_base, count);
505
506    return (0);
507}
508
509static int
510link_elf_link_preload(linker_class_t cls,
511		      const char* filename, linker_file_t *result)
512{
513    caddr_t		modptr, baseptr, sizeptr, dynptr;
514    char		*type;
515    elf_file_t		ef;
516    linker_file_t	lf;
517    int			error;
518    vm_offset_t		dp;
519
520    /* Look to see if we have the file preloaded */
521    modptr = preload_search_by_name(filename);
522    if (modptr == NULL)
523	return ENOENT;
524
525    type = (char *)preload_search_info(modptr, MODINFO_TYPE);
526    baseptr = preload_search_info(modptr, MODINFO_ADDR);
527    sizeptr = preload_search_info(modptr, MODINFO_SIZE);
528    dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC);
529    if (type == NULL ||
530	(strcmp(type, "elf" __XSTRING(__ELF_WORD_SIZE) " module") != 0 &&
531	 strcmp(type, "elf module") != 0))
532	return (EFTYPE);
533    if (baseptr == NULL || sizeptr == NULL || dynptr == NULL)
534	return (EINVAL);
535
536    lf = linker_make_file(filename, &link_elf_class);
537    if (lf == NULL) {
538	return ENOMEM;
539    }
540
541    ef = (elf_file_t) lf;
542    ef->preloaded = 1;
543    ef->modptr = modptr;
544    ef->address = *(caddr_t *)baseptr;
545#ifdef SPARSE_MAPPING
546    ef->object = 0;
547#endif
548    dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr;
549    ef->dynamic = (Elf_Dyn *)dp;
550    lf->address = ef->address;
551    lf->size = *(size_t *)sizeptr;
552
553    error = parse_dynamic(ef);
554    if (error == 0)
555        error = parse_dpcpu(ef);
556    if (error) {
557	linker_file_unload(lf, LINKER_UNLOAD_FORCE);
558	return error;
559    }
560    link_elf_reloc_local(lf);
561    *result = lf;
562    return (0);
563}
564
565static int
566link_elf_link_preload_finish(linker_file_t lf)
567{
568    elf_file_t		ef;
569    int error;
570
571    ef = (elf_file_t) lf;
572#if 0	/* this will be more trouble than it's worth for now */
573    for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
574	if (dp->d_tag != DT_NEEDED)
575	    continue;
576	modname = ef->strtab + dp->d_un.d_val;
577	error = linker_load_module(modname, lf);
578	if (error)
579	    goto out;
580    }
581#endif
582    error = relocate_file(ef);
583    if (error)
584	return error;
585    (void)link_elf_preload_parse_symbols(ef);
586
587    return (link_elf_link_common_finish(lf));
588}
589
590static int
591link_elf_load_file(linker_class_t cls, const char* filename,
592	linker_file_t* result)
593{
594    struct nameidata nd;
595    struct thread* td = curthread;	/* XXX */
596    Elf_Ehdr *hdr;
597    caddr_t firstpage;
598    int nbytes, i;
599    Elf_Phdr *phdr;
600    Elf_Phdr *phlimit;
601    Elf_Phdr *segs[MAXSEGS];
602    int nsegs;
603    Elf_Phdr *phdyn;
604    Elf_Phdr *phphdr;
605    caddr_t mapbase;
606    size_t mapsize;
607    Elf_Off base_offset;
608    Elf_Addr base_vaddr;
609    Elf_Addr base_vlimit;
610    int error = 0;
611    int resid, flags;
612    elf_file_t ef;
613    linker_file_t lf;
614    Elf_Shdr *shdr;
615    int symtabindex;
616    int symstrindex;
617    int symcnt;
618    int strcnt;
619    int vfslocked;
620
621    shdr = NULL;
622    lf = NULL;
623
624    NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, filename, td);
625    flags = FREAD;
626    error = vn_open(&nd, &flags, 0, NULL);
627    if (error)
628	return error;
629    vfslocked = NDHASGIANT(&nd);
630    NDFREE(&nd, NDF_ONLY_PNBUF);
631    if (nd.ni_vp->v_type != VREG) {
632	error = ENOEXEC;
633	firstpage = NULL;
634	goto out;
635    }
636#ifdef MAC
637    error = mac_kld_check_load(curthread->td_ucred, nd.ni_vp);
638    if (error) {
639	firstpage = NULL;
640	goto out;
641    }
642#endif
643
644    /*
645     * Read the elf header from the file.
646     */
647    firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK);
648    if (firstpage == NULL) {
649	error = ENOMEM;
650	goto out;
651    }
652    hdr = (Elf_Ehdr *)firstpage;
653    error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0,
654		    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
655		    &resid, td);
656    nbytes = PAGE_SIZE - resid;
657    if (error)
658	goto out;
659
660    if (!IS_ELF(*hdr)) {
661	error = ENOEXEC;
662	goto out;
663    }
664
665    if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
666      || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
667	link_elf_error(filename, "Unsupported file layout");
668	error = ENOEXEC;
669	goto out;
670    }
671    if (hdr->e_ident[EI_VERSION] != EV_CURRENT
672      || hdr->e_version != EV_CURRENT) {
673	link_elf_error(filename, "Unsupported file version");
674	error = ENOEXEC;
675	goto out;
676    }
677    if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
678	error = ENOSYS;
679	goto out;
680    }
681    if (hdr->e_machine != ELF_TARG_MACH) {
682	link_elf_error(filename, "Unsupported machine");
683	error = ENOEXEC;
684	goto out;
685    }
686
687    /*
688     * We rely on the program header being in the first page.  This is
689     * not strictly required by the ABI specification, but it seems to
690     * always true in practice.  And, it simplifies things considerably.
691     */
692    if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) &&
693	  (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) &&
694	  (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes)))
695	link_elf_error(filename, "Unreadable program headers");
696
697    /*
698     * Scan the program header entries, and save key information.
699     *
700     * We rely on there being exactly two load segments, text and data,
701     * in that order.
702     */
703    phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff);
704    phlimit = phdr + hdr->e_phnum;
705    nsegs = 0;
706    phdyn = NULL;
707    phphdr = NULL;
708    while (phdr < phlimit) {
709	switch (phdr->p_type) {
710
711	case PT_LOAD:
712	    if (nsegs == MAXSEGS) {
713		link_elf_error(filename, "Too many sections");
714		error = ENOEXEC;
715		goto out;
716	    }
717	    /*
718	     * XXX: We just trust they come in right order ??
719	     */
720	    segs[nsegs] = phdr;
721	    ++nsegs;
722	    break;
723
724	case PT_PHDR:
725	    phphdr = phdr;
726	    break;
727
728	case PT_DYNAMIC:
729	    phdyn = phdr;
730	    break;
731
732	case PT_INTERP:
733	    error = ENOSYS;
734	    goto out;
735	}
736
737	++phdr;
738    }
739    if (phdyn == NULL) {
740	link_elf_error(filename, "Object is not dynamically-linked");
741	error = ENOEXEC;
742	goto out;
743    }
744    if (nsegs == 0) {
745	link_elf_error(filename, "No sections");
746	error = ENOEXEC;
747	goto out;
748    }
749
750    /*
751     * Allocate the entire address space of the object, to stake out our
752     * contiguous region, and to establish the base address for relocation.
753     */
754    base_offset = trunc_page(segs[0]->p_offset);
755    base_vaddr = trunc_page(segs[0]->p_vaddr);
756    base_vlimit = round_page(segs[nsegs - 1]->p_vaddr +
757	segs[nsegs - 1]->p_memsz);
758    mapsize = base_vlimit - base_vaddr;
759
760    lf = linker_make_file(filename, &link_elf_class);
761    if (!lf) {
762	error = ENOMEM;
763	goto out;
764    }
765
766    ef = (elf_file_t) lf;
767#ifdef SPARSE_MAPPING
768    ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
769    if (ef->object == NULL) {
770	error = ENOMEM;
771	goto out;
772    }
773    ef->address = (caddr_t) vm_map_min(kernel_map);
774    error = vm_map_find(kernel_map, ef->object, 0,
775			(vm_offset_t *) &ef->address,
776			mapsize, 1,
777			VM_PROT_ALL, VM_PROT_ALL, 0);
778    if (error) {
779	vm_object_deallocate(ef->object);
780	ef->object = 0;
781	goto out;
782    }
783#else
784    ef->address = malloc(mapsize, M_LINKER, M_WAITOK);
785    if (!ef->address) {
786	error = ENOMEM;
787	goto out;
788    }
789#endif
790    mapbase = ef->address;
791
792    /*
793     * Read the text and data sections and zero the bss.
794     */
795    for (i = 0; i < nsegs; i++) {
796	caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
797	error = vn_rdwr(UIO_READ, nd.ni_vp,
798			segbase, segs[i]->p_filesz, segs[i]->p_offset,
799			UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
800			&resid, td);
801	if (error) {
802	    goto out;
803	}
804	bzero(segbase + segs[i]->p_filesz,
805	      segs[i]->p_memsz - segs[i]->p_filesz);
806
807#ifdef SPARSE_MAPPING
808	/*
809	 * Wire down the pages
810	 */
811	error = vm_map_wire(kernel_map,
812		    (vm_offset_t) segbase,
813		    (vm_offset_t) segbase + segs[i]->p_memsz,
814		    VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
815	if (error != KERN_SUCCESS) {
816	    error = ENOMEM;
817	    goto out;
818	}
819#endif
820    }
821
822#ifdef GPROF
823    /* Update profiling information with the new text segment. */
824    mtx_lock(&Giant);
825    kmupetext((uintfptr_t)(mapbase + segs[0]->p_vaddr - base_vaddr +
826	segs[0]->p_memsz));
827    mtx_unlock(&Giant);
828#endif
829
830    ef->dynamic = (Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr);
831
832    lf->address = ef->address;
833    lf->size = mapsize;
834
835    error = parse_dynamic(ef);
836    if (error)
837	goto out;
838    error = parse_dpcpu(ef);
839    if (error)
840        goto out;
841    link_elf_reloc_local(lf);
842
843    VOP_UNLOCK(nd.ni_vp, 0);
844    error = linker_load_dependencies(lf);
845    vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY);
846    if (error)
847	goto out;
848#if 0	/* this will be more trouble than it's worth for now */
849    for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
850	if (dp->d_tag != DT_NEEDED)
851	    continue;
852	modname = ef->strtab + dp->d_un.d_val;
853	error = linker_load_module(modname, lf);
854	if (error)
855	    goto out;
856    }
857#endif
858    error = relocate_file(ef);
859    if (error)
860	goto out;
861
862    /* Try and load the symbol table if it's present.  (you can strip it!) */
863    nbytes = hdr->e_shnum * hdr->e_shentsize;
864    if (nbytes == 0 || hdr->e_shoff == 0)
865	goto nosyms;
866    shdr = malloc(nbytes, M_LINKER, M_WAITOK | M_ZERO);
867    if (shdr == NULL) {
868	error = ENOMEM;
869	goto out;
870    }
871    error = vn_rdwr(UIO_READ, nd.ni_vp,
872		    (caddr_t)shdr, nbytes, hdr->e_shoff,
873		    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
874		    &resid, td);
875    if (error)
876	goto out;
877    symtabindex = -1;
878    symstrindex = -1;
879    for (i = 0; i < hdr->e_shnum; i++) {
880	if (shdr[i].sh_type == SHT_SYMTAB) {
881	    symtabindex = i;
882	    symstrindex = shdr[i].sh_link;
883	}
884    }
885    if (symtabindex < 0 || symstrindex < 0)
886	goto nosyms;
887
888    symcnt = shdr[symtabindex].sh_size;
889    ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK);
890    strcnt = shdr[symstrindex].sh_size;
891    ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK);
892
893    if (ef->symbase == NULL || ef->strbase == NULL) {
894	error = ENOMEM;
895	goto out;
896    }
897    error = vn_rdwr(UIO_READ, nd.ni_vp,
898		    ef->symbase, symcnt, shdr[symtabindex].sh_offset,
899		    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
900		    &resid, td);
901    if (error)
902	goto out;
903    error = vn_rdwr(UIO_READ, nd.ni_vp,
904		    ef->strbase, strcnt, shdr[symstrindex].sh_offset,
905		    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
906		    &resid, td);
907    if (error)
908	goto out;
909
910    ef->ddbsymcnt = symcnt / sizeof(Elf_Sym);
911    ef->ddbsymtab = (const Elf_Sym *)ef->symbase;
912    ef->ddbstrcnt = strcnt;
913    ef->ddbstrtab = ef->strbase;
914
915    error = link_elf_link_common_finish(lf);
916    if (error)
917	goto out;
918
919nosyms:
920
921    *result = lf;
922
923out:
924    if (error && lf)
925	linker_file_unload(lf, LINKER_UNLOAD_FORCE);
926    if (shdr)
927	free(shdr, M_LINKER);
928    if (firstpage)
929	free(firstpage, M_LINKER);
930    VOP_UNLOCK(nd.ni_vp, 0);
931    vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
932    VFS_UNLOCK_GIANT(vfslocked);
933
934    return error;
935}
936
937Elf_Addr
938elf_relocaddr(linker_file_t lf, Elf_Addr x)
939{
940    elf_file_t ef;
941
942    ef = (elf_file_t)lf;
943    if (x >= ef->pcpu_start && x < ef->pcpu_stop)
944	return ((x - ef->pcpu_start) + ef->pcpu_base);
945    return (x);
946}
947
948
949static void
950link_elf_unload_file(linker_file_t file)
951{
952    elf_file_t ef = (elf_file_t) file;
953
954    if (ef->pcpu_base) {
955        dpcpu_free((void *)ef->pcpu_base, ef->pcpu_stop - ef->pcpu_start);
956    }
957#ifdef GDB
958    if (ef->gdb.l_ld) {
959	GDB_STATE(RT_DELETE);
960	free((void *)(uintptr_t)ef->gdb.l_name, M_LINKER);
961	link_elf_delete_gdb(&ef->gdb);
962	GDB_STATE(RT_CONSISTENT);
963    }
964#endif
965
966    /* Notify MD code that a module is being unloaded. */
967    elf_cpu_unload_file(file);
968
969    if (ef->preloaded) {
970	link_elf_unload_preload(file);
971	return;
972    }
973
974#ifdef SPARSE_MAPPING
975    if (ef->object) {
976	vm_map_remove(kernel_map, (vm_offset_t) ef->address,
977		      (vm_offset_t) ef->address
978		      + (ef->object->size << PAGE_SHIFT));
979    }
980#else
981    if (ef->address)
982	free(ef->address, M_LINKER);
983#endif
984    if (ef->symbase)
985	free(ef->symbase, M_LINKER);
986    if (ef->strbase)
987	free(ef->strbase, M_LINKER);
988    if (ef->ctftab)
989	free(ef->ctftab, M_LINKER);
990    if (ef->ctfoff)
991	free(ef->ctfoff, M_LINKER);
992    if (ef->typoff)
993	free(ef->typoff, M_LINKER);
994}
995
996static void
997link_elf_unload_preload(linker_file_t file)
998{
999    if (file->filename)
1000	preload_delete_name(file->filename);
1001}
1002
1003static const char *
1004symbol_name(elf_file_t ef, Elf_Size r_info)
1005{
1006    const Elf_Sym *ref;
1007
1008    if (ELF_R_SYM(r_info)) {
1009	ref = ef->symtab + ELF_R_SYM(r_info);
1010	return ef->strtab + ref->st_name;
1011    } else
1012	return NULL;
1013}
1014
1015static int
1016relocate_file(elf_file_t ef)
1017{
1018    const Elf_Rel *rellim;
1019    const Elf_Rel *rel;
1020    const Elf_Rela *relalim;
1021    const Elf_Rela *rela;
1022    const char *symname;
1023
1024    /* Perform relocations without addend if there are any: */
1025    rel = ef->rel;
1026    if (rel) {
1027	rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
1028	while (rel < rellim) {
1029	    if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL,
1030			  elf_lookup)) {
1031		symname = symbol_name(ef, rel->r_info);
1032		printf("link_elf: symbol %s undefined\n", symname);
1033		return ENOENT;
1034	    }
1035	    rel++;
1036	}
1037    }
1038
1039    /* Perform relocations with addend if there are any: */
1040    rela = ef->rela;
1041    if (rela) {
1042	relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
1043	while (rela < relalim) {
1044	    if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA,
1045			  elf_lookup)) {
1046		symname = symbol_name(ef, rela->r_info);
1047		printf("link_elf: symbol %s undefined\n", symname);
1048		return ENOENT;
1049	    }
1050	    rela++;
1051	}
1052    }
1053
1054    /* Perform PLT relocations without addend if there are any: */
1055    rel = ef->pltrel;
1056    if (rel) {
1057	rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize);
1058	while (rel < rellim) {
1059	    if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL,
1060			  elf_lookup)) {
1061		symname = symbol_name(ef, rel->r_info);
1062		printf("link_elf: symbol %s undefined\n", symname);
1063		return ENOENT;
1064	    }
1065	    rel++;
1066	}
1067    }
1068
1069    /* Perform relocations with addend if there are any: */
1070    rela = ef->pltrela;
1071    if (rela) {
1072	relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize);
1073	while (rela < relalim) {
1074	    if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA,
1075			  elf_lookup)) {
1076		symname = symbol_name(ef, rela->r_info);
1077		printf("link_elf: symbol %s undefined\n", symname);
1078		return ENOENT;
1079	    }
1080	    rela++;
1081	}
1082    }
1083
1084    return 0;
1085}
1086
1087/*
1088 * Hash function for symbol table lookup.  Don't even think about changing
1089 * this.  It is specified by the System V ABI.
1090 */
1091static unsigned long
1092elf_hash(const char *name)
1093{
1094    const unsigned char *p = (const unsigned char *) name;
1095    unsigned long h = 0;
1096    unsigned long g;
1097
1098    while (*p != '\0') {
1099	h = (h << 4) + *p++;
1100	if ((g = h & 0xf0000000) != 0)
1101	    h ^= g >> 24;
1102	h &= ~g;
1103    }
1104    return h;
1105}
1106
1107static int
1108link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym)
1109{
1110    elf_file_t ef = (elf_file_t) lf;
1111    unsigned long symnum;
1112    const Elf_Sym* symp;
1113    const char *strp;
1114    unsigned long hash;
1115    int i;
1116
1117    /* If we don't have a hash, bail. */
1118    if (ef->buckets == NULL || ef->nbuckets == 0) {
1119	printf("link_elf_lookup_symbol: missing symbol hash table\n");
1120	return ENOENT;
1121    }
1122
1123    /* First, search hashed global symbols */
1124    hash = elf_hash(name);
1125    symnum = ef->buckets[hash % ef->nbuckets];
1126
1127    while (symnum != STN_UNDEF) {
1128	if (symnum >= ef->nchains) {
1129	    printf("link_elf_lookup_symbol: corrupt symbol table\n");
1130	    return ENOENT;
1131	}
1132
1133	symp = ef->symtab + symnum;
1134	if (symp->st_name == 0) {
1135	    printf("link_elf_lookup_symbol: corrupt symbol table\n");
1136	    return ENOENT;
1137	}
1138
1139	strp = ef->strtab + symp->st_name;
1140
1141	if (strcmp(name, strp) == 0) {
1142	    if (symp->st_shndx != SHN_UNDEF ||
1143		(symp->st_value != 0 &&
1144		 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
1145		*sym = (c_linker_sym_t) symp;
1146		return 0;
1147	    } else
1148		return ENOENT;
1149	}
1150
1151	symnum = ef->chains[symnum];
1152    }
1153
1154    /* If we have not found it, look at the full table (if loaded) */
1155    if (ef->symtab == ef->ddbsymtab)
1156	return ENOENT;
1157
1158    /* Exhaustive search */
1159    for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1160	strp = ef->ddbstrtab + symp->st_name;
1161	if (strcmp(name, strp) == 0) {
1162	    if (symp->st_shndx != SHN_UNDEF ||
1163		(symp->st_value != 0 &&
1164		 ELF_ST_TYPE(symp->st_info) == STT_FUNC)) {
1165		*sym = (c_linker_sym_t) symp;
1166		return 0;
1167	    } else
1168		return ENOENT;
1169	}
1170    }
1171
1172    return ENOENT;
1173}
1174
1175static int
1176link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval_t* symval)
1177{
1178	elf_file_t ef = (elf_file_t) lf;
1179	const Elf_Sym* es = (const Elf_Sym*) sym;
1180
1181	if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) {
1182	    symval->name = ef->strtab + es->st_name;
1183	    symval->value = (caddr_t) ef->address + es->st_value;
1184	    symval->size = es->st_size;
1185	    return 0;
1186	}
1187	if (ef->symtab == ef->ddbsymtab)
1188	    return ENOENT;
1189	if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
1190	    symval->name = ef->ddbstrtab + es->st_name;
1191	    symval->value = (caddr_t) ef->address + es->st_value;
1192	    symval->size = es->st_size;
1193	    return 0;
1194	}
1195	return ENOENT;
1196}
1197
1198static int
1199link_elf_search_symbol(linker_file_t lf, caddr_t value,
1200		       c_linker_sym_t* sym, long* diffp)
1201{
1202	elf_file_t ef = (elf_file_t) lf;
1203	u_long off = (uintptr_t) (void *) value;
1204	u_long diff = off;
1205	u_long st_value;
1206	const Elf_Sym* es;
1207	const Elf_Sym* best = 0;
1208	int i;
1209
1210	for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
1211		if (es->st_name == 0)
1212			continue;
1213		st_value = es->st_value + (uintptr_t) (void *) ef->address;
1214		if (off >= st_value) {
1215			if (off - st_value < diff) {
1216				diff = off - st_value;
1217				best = es;
1218				if (diff == 0)
1219					break;
1220			} else if (off - st_value == diff) {
1221				best = es;
1222			}
1223		}
1224	}
1225	if (best == 0)
1226		*diffp = off;
1227	else
1228		*diffp = diff;
1229	*sym = (c_linker_sym_t) best;
1230
1231	return 0;
1232}
1233
1234/*
1235 * Look up a linker set on an ELF system.
1236 */
1237static int
1238link_elf_lookup_set(linker_file_t lf, const char *name,
1239		    void ***startp, void ***stopp, int *countp)
1240{
1241	c_linker_sym_t sym;
1242	linker_symval_t symval;
1243	char *setsym;
1244	void **start, **stop;
1245	int len, error = 0, count;
1246
1247	len = strlen(name) + sizeof("__start_set_"); /* sizeof includes \0 */
1248	setsym = malloc(len, M_LINKER, M_WAITOK);
1249	if (setsym == NULL)
1250		return ENOMEM;
1251
1252	/* get address of first entry */
1253	snprintf(setsym, len, "%s%s", "__start_set_", name);
1254	error = link_elf_lookup_symbol(lf, setsym, &sym);
1255	if (error)
1256		goto out;
1257	link_elf_symbol_values(lf, sym, &symval);
1258	if (symval.value == 0) {
1259		error = ESRCH;
1260		goto out;
1261	}
1262	start = (void **)symval.value;
1263
1264	/* get address of last entry */
1265	snprintf(setsym, len, "%s%s", "__stop_set_", name);
1266	error = link_elf_lookup_symbol(lf, setsym, &sym);
1267	if (error)
1268		goto out;
1269	link_elf_symbol_values(lf, sym, &symval);
1270	if (symval.value == 0) {
1271		error = ESRCH;
1272		goto out;
1273	}
1274	stop = (void **)symval.value;
1275
1276	/* and the number of entries */
1277	count = stop - start;
1278
1279	/* and copy out */
1280	if (startp)
1281		*startp = start;
1282	if (stopp)
1283		*stopp = stop;
1284	if (countp)
1285		*countp = count;
1286
1287out:
1288	free(setsym, M_LINKER);
1289	return error;
1290}
1291
1292static int
1293link_elf_each_function_name(linker_file_t file,
1294  int (*callback)(const char *, void *), void *opaque) {
1295    elf_file_t ef = (elf_file_t)file;
1296    const Elf_Sym* symp;
1297    int i, error;
1298
1299    /* Exhaustive search */
1300    for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1301	if (symp->st_value != 0 &&
1302	    ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
1303		error = callback(ef->ddbstrtab + symp->st_name, opaque);
1304		if (error)
1305		    return (error);
1306	}
1307    }
1308    return (0);
1309}
1310
1311static int
1312link_elf_each_function_nameval(linker_file_t file,
1313    linker_function_nameval_callback_t callback, void *opaque)
1314{
1315	linker_symval_t symval;
1316	elf_file_t ef = (elf_file_t)file;
1317	const Elf_Sym* symp;
1318	int i, error;
1319
1320	/* Exhaustive search */
1321	for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1322		if (symp->st_value != 0 &&
1323		    ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
1324			error = link_elf_symbol_values(file, (c_linker_sym_t) symp, &symval);
1325			if (error)
1326				return (error);
1327			error = callback(file, i, &symval, opaque);
1328			if (error)
1329				return (error);
1330		}
1331	}
1332	return (0);
1333}
1334
1335#ifdef __ia64__
1336/*
1337 * Each KLD has its own GP. The GP value for each load module is given by
1338 * DT_PLTGOT on ia64. We need GP to construct function descriptors, but
1339 * don't have direct access to the ELF file structure. The link_elf_get_gp()
1340 * function returns the GP given a pointer to a generic linker file struct.
1341 */
1342Elf_Addr
1343link_elf_get_gp(linker_file_t lf)
1344{
1345	elf_file_t ef = (elf_file_t)lf;
1346	return (Elf_Addr)ef->got;
1347}
1348#endif
1349
1350const Elf_Sym *
1351elf_get_sym(linker_file_t lf, Elf_Size symidx)
1352{
1353	elf_file_t ef = (elf_file_t)lf;
1354
1355	if (symidx >= ef->nchains)
1356		return (NULL);
1357	return (ef->symtab + symidx);
1358}
1359
1360const char *
1361elf_get_symname(linker_file_t lf, Elf_Size symidx)
1362{
1363	elf_file_t ef = (elf_file_t)lf;
1364	const Elf_Sym *sym;
1365
1366	if (symidx >= ef->nchains)
1367		return (NULL);
1368	sym = ef->symtab + symidx;
1369	return (ef->strtab + sym->st_name);
1370}
1371
1372/*
1373 * Symbol lookup function that can be used when the symbol index is known (ie
1374 * in relocations). It uses the symbol index instead of doing a fully fledged
1375 * hash table based lookup when such is valid. For example for local symbols.
1376 * This is not only more efficient, it's also more correct. It's not always
1377 * the case that the symbol can be found through the hash table.
1378 */
1379static Elf_Addr
1380elf_lookup(linker_file_t lf, Elf_Size symidx, int deps)
1381{
1382	elf_file_t ef = (elf_file_t)lf;
1383	const Elf_Sym *sym;
1384	const char *symbol;
1385
1386	/* Don't even try to lookup the symbol if the index is bogus. */
1387	if (symidx >= ef->nchains)
1388		return (0);
1389
1390	sym = ef->symtab + symidx;
1391
1392	/*
1393	 * Don't do a full lookup when the symbol is local. It may even
1394	 * fail because it may not be found through the hash table.
1395	 */
1396	if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
1397		/* Force lookup failure when we have an insanity. */
1398		if (sym->st_shndx == SHN_UNDEF || sym->st_value == 0)
1399			return (0);
1400		return ((Elf_Addr)ef->address + sym->st_value);
1401	}
1402
1403	/*
1404	 * XXX we can avoid doing a hash table based lookup for global
1405	 * symbols as well. This however is not always valid, so we'll
1406	 * just do it the hard way for now. Performance tweaks can
1407	 * always be added.
1408	 */
1409
1410	symbol = ef->strtab + sym->st_name;
1411
1412	/* Force a lookup failure if the symbol name is bogus. */
1413	if (*symbol == 0)
1414		return (0);
1415
1416	return ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps));
1417}
1418
1419static void
1420link_elf_reloc_local(linker_file_t lf)
1421{
1422    const Elf_Rel *rellim;
1423    const Elf_Rel *rel;
1424    const Elf_Rela *relalim;
1425    const Elf_Rela *rela;
1426    elf_file_t ef = (elf_file_t)lf;
1427
1428    /* Perform relocations without addend if there are any: */
1429    if ((rel = ef->rel) != NULL) {
1430	rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize);
1431	while (rel < rellim) {
1432	    elf_reloc_local(lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL,
1433			    elf_lookup);
1434	    rel++;
1435	}
1436    }
1437
1438    /* Perform relocations with addend if there are any: */
1439    if ((rela = ef->rela) != NULL) {
1440	relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize);
1441	while (rela < relalim) {
1442	    elf_reloc_local(lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA,
1443			    elf_lookup);
1444	    rela++;
1445	}
1446    }
1447}
1448
1449static long
1450link_elf_symtab_get(linker_file_t lf, const Elf_Sym **symtab)
1451{
1452    elf_file_t ef = (elf_file_t)lf;
1453
1454    *symtab = ef->ddbsymtab;
1455
1456    if (*symtab == NULL)
1457        return (0);
1458
1459    return (ef->ddbsymcnt);
1460}
1461
1462static long
1463link_elf_strtab_get(linker_file_t lf, caddr_t *strtab)
1464{
1465    elf_file_t ef = (elf_file_t)lf;
1466
1467    *strtab = ef->ddbstrtab;
1468
1469    if (*strtab == NULL)
1470        return (0);
1471
1472    return (ef->ddbstrcnt);
1473}
1474