load_elf.c revision 247413
133965Sjdp/*-
260484Sobrien * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
333965Sjdp * Copyright (c) 1998 Peter Wemm <peter@freebsd.org>
433965Sjdp * All rights reserved.
533965Sjdp *
633965Sjdp * Redistribution and use in source and binary forms, with or without
733965Sjdp * modification, are permitted provided that the following conditions
833965Sjdp * are met:
933965Sjdp * 1. Redistributions of source code must retain the above copyright
1033965Sjdp *    notice, this list of conditions and the following disclaimer.
1133965Sjdp * 2. Redistributions in binary form must reproduce the above copyright
1233965Sjdp *    notice, this list of conditions and the following disclaimer in the
1333965Sjdp *    documentation and/or other materials provided with the distribution.
1433965Sjdp *
1533965Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1633965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1733965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1833965Sjdp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1933965Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2033965Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2133965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2233965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2333965Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2433965Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2533965Sjdp * SUCH DAMAGE.
2633965Sjdp */
2733965Sjdp
2833965Sjdp#include <sys/cdefs.h>
2933965Sjdp__FBSDID("$FreeBSD: head/sys/boot/common/load_elf.c 247413 2013-02-27 19:59:41Z ian $");
3033965Sjdp
3160484Sobrien#include <sys/param.h>
3233965Sjdp#include <sys/exec.h>
3333965Sjdp#include <sys/linker.h>
3433965Sjdp#include <sys/module.h>
3533965Sjdp#include <sys/stdint.h>
3633965Sjdp#include <string.h>
3733965Sjdp#include <machine/elf.h>
3833965Sjdp#include <stand.h>
3933965Sjdp#define FREEBSD_ELF
4033965Sjdp#include <link.h>
4133965Sjdp
4233965Sjdp#include "bootstrap.h"
4333965Sjdp
4433965Sjdp#define COPYOUT(s,d,l)	archsw.arch_copyout((vm_offset_t)(s), d, l)
4533965Sjdp
4638889Sjdp#if defined(__i386__) && __ELF_WORD_SIZE == 64
4738889Sjdp#undef ELF_TARG_CLASS
4833965Sjdp#undef ELF_TARG_MACH
4933965Sjdp#define ELF_TARG_CLASS  ELFCLASS64
5033965Sjdp#define ELF_TARG_MACH   EM_X86_64
5133965Sjdp#endif
5233965Sjdp
5333965Sjdptypedef struct elf_file {
5433965Sjdp    Elf_Phdr 	*ph;
5533965Sjdp    Elf_Ehdr	*ehdr;
5633965Sjdp    Elf_Sym	*symtab;
5733965Sjdp    Elf_Hashelt	*hashtab;
5833965Sjdp    Elf_Hashelt	nbuckets;
5933965Sjdp    Elf_Hashelt	nchains;
6033965Sjdp    Elf_Hashelt	*buckets;
6133965Sjdp    Elf_Hashelt	*chains;
6233965Sjdp    Elf_Rel	*rel;
6333965Sjdp    size_t	relsz;
6433965Sjdp    Elf_Rela	*rela;
6533965Sjdp    size_t	relasz;
6633965Sjdp    char	*strtab;
6733965Sjdp    size_t	strsz;
6833965Sjdp    int		fd;
6933965Sjdp    caddr_t	firstpage;
7033965Sjdp    size_t	firstlen;
7133965Sjdp    int		kernel;
7233965Sjdp    u_int64_t	off;
7333965Sjdp} *elf_file_t;
7433965Sjdp
7533965Sjdpstatic int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, u_int64_t loadaddr);
7633965Sjdpstatic int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym);
7733965Sjdpstatic int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
7833965Sjdp    Elf_Addr p, void *val, size_t len);
7933965Sjdpstatic int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef);
8033965Sjdpstatic symaddr_fn __elfN(symaddr);
8133965Sjdpstatic char	*fake_modname(const char *name);
8233965Sjdp
8333965Sjdpconst char	*__elfN(kerneltype) = "elf kernel";
8433965Sjdpconst char	*__elfN(moduletype) = "elf module";
8533965Sjdp
8633965Sjdpu_int64_t	__elfN(relocation_offset) = 0;
8733965Sjdp
8833965Sjdp/*
8933965Sjdp * Attempt to load the file (file) as an ELF module.  It will be stored at
9033965Sjdp * (dest), and a pointer to a module structure describing the loaded object
9133965Sjdp * will be saved in (result).
9233965Sjdp */
9333965Sjdpint
9433965Sjdp__elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
9533965Sjdp{
9633965Sjdp    struct preloaded_file	*fp, *kfp;
9733965Sjdp    struct elf_file		ef;
9833965Sjdp    Elf_Ehdr 			*ehdr;
9933965Sjdp    int				err;
10033965Sjdp    ssize_t			bytes_read;
10133965Sjdp
10233965Sjdp    fp = NULL;
10333965Sjdp    bzero(&ef, sizeof(struct elf_file));
10433965Sjdp
10533965Sjdp    /*
10633965Sjdp     * Open the image, read and validate the ELF header
10733965Sjdp     */
10833965Sjdp    if (filename == NULL)	/* can't handle nameless */
10933965Sjdp	return(EFTYPE);
11033965Sjdp    if ((ef.fd = open(filename, O_RDONLY)) == -1)
11133965Sjdp	return(errno);
11233965Sjdp    ef.firstpage = malloc(PAGE_SIZE);
11333965Sjdp    if (ef.firstpage == NULL) {
11433965Sjdp	close(ef.fd);
11533965Sjdp	return(ENOMEM);
11633965Sjdp    }
11733965Sjdp    bytes_read = read(ef.fd, ef.firstpage, PAGE_SIZE);
11833965Sjdp    ef.firstlen = (size_t)bytes_read;
11933965Sjdp    if (bytes_read < 0 || ef.firstlen <= sizeof(Elf_Ehdr)) {
12033965Sjdp	err = EFTYPE;		/* could be EIO, but may be small file */
12133965Sjdp	goto oerr;
12233965Sjdp    }
12333965Sjdp    ehdr = ef.ehdr = (Elf_Ehdr *)ef.firstpage;
12433965Sjdp
12533965Sjdp    /* Is it ELF? */
12633965Sjdp    if (!IS_ELF(*ehdr)) {
12733965Sjdp	err = EFTYPE;
12833965Sjdp	goto oerr;
12933965Sjdp    }
13033965Sjdp    if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||	/* Layout ? */
13133965Sjdp	ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
13260484Sobrien	ehdr->e_ident[EI_VERSION] != EV_CURRENT ||	/* Version ? */
13360484Sobrien	ehdr->e_version != EV_CURRENT ||
13460484Sobrien	ehdr->e_machine != ELF_TARG_MACH) {		/* Machine ? */
13533965Sjdp	err = EFTYPE;
13633965Sjdp	goto oerr;
13733965Sjdp    }
13833965Sjdp
13933965Sjdp
14033965Sjdp    /*
14133965Sjdp     * Check to see what sort of module we are.
14233965Sjdp     */
14333965Sjdp    kfp = file_findfile(NULL, NULL);
14433965Sjdp    if (ehdr->e_type == ET_DYN) {
14533965Sjdp	/* Looks like a kld module */
14633965Sjdp	if (kfp == NULL) {
14733965Sjdp	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n");
14833965Sjdp	    err = EPERM;
14933965Sjdp	    goto oerr;
15033965Sjdp	}
15133965Sjdp	if (strcmp(__elfN(kerneltype), kfp->f_type)) {
15233965Sjdp	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module with kernel type '%s'\n", kfp->f_type);
15333965Sjdp	    err = EPERM;
15433965Sjdp	    goto oerr;
15533965Sjdp	}
15633965Sjdp	/* Looks OK, got ahead */
15733965Sjdp	ef.kernel = 0;
15833965Sjdp
15933965Sjdp    } else if (ehdr->e_type == ET_EXEC) {
16033965Sjdp	/* Looks like a kernel */
16133965Sjdp	if (kfp != NULL) {
16233965Sjdp	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n");
16333965Sjdp	    err = EPERM;
16433965Sjdp	    goto oerr;
16533965Sjdp	}
16633965Sjdp	/*
16733965Sjdp	 * Calculate destination address based on kernel entrypoint
16833965Sjdp	 */
16933965Sjdp	dest = (ehdr->e_entry & ~PAGE_MASK);
17033965Sjdp	if (dest == 0) {
17133965Sjdp	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n");
17233965Sjdp	    err = EPERM;
17333965Sjdp	    goto oerr;
17433965Sjdp	}
17533965Sjdp	ef.kernel = 1;
17633965Sjdp
17733965Sjdp    } else {
17833965Sjdp	err = EFTYPE;
17933965Sjdp	goto oerr;
18033965Sjdp    }
18133965Sjdp
18233965Sjdp    if (archsw.arch_loadaddr != NULL)
18333965Sjdp	dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest);
18433965Sjdp    else
18533965Sjdp	dest = roundup(dest, PAGE_SIZE);
18633965Sjdp
18733965Sjdp    /*
18833965Sjdp     * Ok, we think we should handle this.
18933965Sjdp     */
19033965Sjdp    fp = file_alloc();
19133965Sjdp    if (fp == NULL) {
19233965Sjdp	    printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: cannot allocate module info\n");
19333965Sjdp	    err = EPERM;
19433965Sjdp	    goto out;
19533965Sjdp    }
19633965Sjdp    if (ef.kernel)
19733965Sjdp	setenv("kernelname", filename, 1);
19833965Sjdp    fp->f_name = strdup(filename);
19933965Sjdp    fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype));
20033965Sjdp
20133965Sjdp#ifdef ELF_VERBOSE
20233965Sjdp    if (ef.kernel)
20333965Sjdp	printf("%s entry at 0x%jx\n", filename, (uintmax_t)ehdr->e_entry);
20433965Sjdp#else
20533965Sjdp    printf("%s ", filename);
20633965Sjdp#endif
20733965Sjdp
20833965Sjdp    fp->f_size = __elfN(loadimage)(fp, &ef, dest);
20933965Sjdp    if (fp->f_size == 0 || fp->f_addr == 0)
21033965Sjdp	goto ioerr;
21160484Sobrien
21233965Sjdp    /* save exec header as metadata */
21333965Sjdp    file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr);
21433965Sjdp
21533965Sjdp    /* Load OK, return module pointer */
21633965Sjdp    *result = (struct preloaded_file *)fp;
21733965Sjdp    err = 0;
21833965Sjdp    goto out;
21933965Sjdp
22033965Sjdp ioerr:
22133965Sjdp    err = EIO;
22233965Sjdp oerr:
22333965Sjdp    file_discard(fp);
22433965Sjdp out:
22533965Sjdp    if (ef.firstpage)
22633965Sjdp	free(ef.firstpage);
22733965Sjdp    close(ef.fd);
22833965Sjdp    return(err);
22933965Sjdp}
23033965Sjdp
23133965Sjdp/*
23233965Sjdp * With the file (fd) open on the image, and (ehdr) containing
23333965Sjdp * the Elf header, load the image at (off)
23433965Sjdp */
23533965Sjdpstatic int
23633965Sjdp__elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
23733965Sjdp{
23833965Sjdp    int 	i;
23933965Sjdp    u_int	j;
24033965Sjdp    Elf_Ehdr	*ehdr;
24133965Sjdp    Elf_Phdr	*phdr, *php;
24233965Sjdp    Elf_Shdr	*shdr;
24333965Sjdp    int		ret;
24433965Sjdp    vm_offset_t firstaddr;
24533965Sjdp    vm_offset_t lastaddr;
24633965Sjdp    size_t	chunk;
24733965Sjdp    ssize_t	result;
24833965Sjdp    Elf_Addr	ssym, esym;
24933965Sjdp    Elf_Dyn	*dp;
25033965Sjdp    Elf_Addr	adp;
25160484Sobrien    int		ndp;
25260484Sobrien    int		symstrindex;
25360484Sobrien    int		symtabindex;
25460484Sobrien    Elf_Size	size;
25560484Sobrien    u_int	fpcopy;
25660484Sobrien
25760484Sobrien    dp = NULL;
25860484Sobrien    shdr = NULL;
25933965Sjdp    ret = 0;
26033965Sjdp    firstaddr = lastaddr = 0;
26133965Sjdp    ehdr = ef->ehdr;
26233965Sjdp    if (ef->kernel) {
26333965Sjdp#if defined(__i386__) || defined(__amd64__)
26433965Sjdp#if __ELF_WORD_SIZE == 64
26533965Sjdp	off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */
26633965Sjdp#else
26733965Sjdp	off = - (off & 0xff000000u);	/* i386 relocates after locore */
26833965Sjdp#endif
26933965Sjdp#elif defined(__powerpc__)
27033965Sjdp	/*
27133965Sjdp	 * On the purely virtual memory machines like e500, the kernel is
27233965Sjdp	 * linked against its final VA range, which is most often not
27333965Sjdp	 * available at the loader stage, but only after kernel initializes
27433965Sjdp	 * and completes its VM settings. In such cases we cannot use p_vaddr
27533965Sjdp	 * field directly to load ELF segments, but put them at some
27633965Sjdp	 * 'load-time' locations.
27733965Sjdp	 */
27833965Sjdp	if (off & 0xf0000000u) {
27933965Sjdp	    off = -(off & 0xf0000000u);
28060484Sobrien	    /*
28160484Sobrien	     * XXX the physical load address should not be hardcoded. Note
28233965Sjdp	     * that the Book-E kernel assumes that it's loaded at a 16MB
28333965Sjdp	     * boundary for now...
28433965Sjdp	     */
28533965Sjdp	    off += 0x01000000;
28633965Sjdp	    ehdr->e_entry += off;
28733965Sjdp#ifdef ELF_VERBOSE
28833965Sjdp	    printf("Converted entry 0x%08x\n", ehdr->e_entry);
28933965Sjdp#endif
29033965Sjdp	} else
29133965Sjdp	    off = 0;
29233965Sjdp#elif defined(__arm__)
29333965Sjdp	/*
29433965Sjdp	 * The elf headers in some kernels specify virtual addresses in all
29533965Sjdp	 * header fields.  More recently, the e_entry and p_paddr fields are the
29633965Sjdp	 * proper physical addresses.  Even when the p_paddr fields are correct,
29733965Sjdp	 * the MI code below uses the p_vaddr fields with an offset added for
29833965Sjdp	 * loading (doing so is arguably wrong).  To make loading work, we need
29933965Sjdp	 * an offset that represents the difference between physical and virtual
30033965Sjdp	 * addressing.  ARM kernels are always linked at 0xC0000000.  Depending
30133965Sjdp	 * on the headers, the offset value passed in may be physical or virtual
30233965Sjdp	 * (because it typically comes from e_entry), but we always replace
30333965Sjdp	 * whatever is passed in with the va<->pa offset.  On the other hand, we
30433965Sjdp	 * only adjust the entry point if it's a virtual address to begin with.
30533965Sjdp	 */
30633965Sjdp	off = -0xc0000000u;
30733965Sjdp	if ((ehdr->e_entry & 0xc0000000u) == 0xc0000000u)
30833965Sjdp		ehdr->e_entry += off;
30933965Sjdp#ifdef ELF_VERBOSE
31033965Sjdp	printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off);
31133965Sjdp#endif
31233965Sjdp#else
313	off = 0;		/* other archs use direct mapped kernels */
314#endif
315	__elfN(relocation_offset) = off;
316    }
317    ef->off = off;
318
319    if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) {
320	printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n");
321	goto out;
322    }
323    phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff);
324
325    for (i = 0; i < ehdr->e_phnum; i++) {
326	/* We want to load PT_LOAD segments only.. */
327	if (phdr[i].p_type != PT_LOAD)
328	    continue;
329
330#ifdef ELF_VERBOSE
331	printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx",
332	    (long)phdr[i].p_filesz, (long)phdr[i].p_offset,
333	    (long)(phdr[i].p_vaddr + off),
334	    (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
335#else
336	if ((phdr[i].p_flags & PF_W) == 0) {
337	    printf("text=0x%lx ", (long)phdr[i].p_filesz);
338	} else {
339	    printf("data=0x%lx", (long)phdr[i].p_filesz);
340	    if (phdr[i].p_filesz < phdr[i].p_memsz)
341		printf("+0x%lx", (long)(phdr[i].p_memsz -phdr[i].p_filesz));
342	    printf(" ");
343	}
344#endif
345	fpcopy = 0;
346	if (ef->firstlen > phdr[i].p_offset) {
347	    fpcopy = ef->firstlen - phdr[i].p_offset;
348	    archsw.arch_copyin(ef->firstpage + phdr[i].p_offset,
349			       phdr[i].p_vaddr + off, fpcopy);
350	}
351	if (phdr[i].p_filesz > fpcopy) {
352	    if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy,
353		phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) {
354		printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
355		    "_loadimage: read failed\n");
356		goto out;
357	    }
358	}
359	/* clear space from oversized segments; eg: bss */
360	if (phdr[i].p_filesz < phdr[i].p_memsz) {
361#ifdef ELF_VERBOSE
362	    printf(" (bss: 0x%lx-0x%lx)",
363		(long)(phdr[i].p_vaddr + off + phdr[i].p_filesz),
364		(long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
365#endif
366
367	    kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz,
368		phdr[i].p_memsz - phdr[i].p_filesz);
369	}
370#ifdef ELF_VERBOSE
371	printf("\n");
372#endif
373
374	if (archsw.arch_loadseg != NULL)
375	    archsw.arch_loadseg(ehdr, phdr + i, off);
376
377	if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off))
378	    firstaddr = phdr[i].p_vaddr + off;
379	if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz))
380	    lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz;
381    }
382    lastaddr = roundup(lastaddr, sizeof(long));
383
384    /*
385     * Now grab the symbol tables.  This isn't easy if we're reading a
386     * .gz file.  I think the rule is going to have to be that you must
387     * strip a file to remove symbols before gzipping it so that we do not
388     * try to lseek() on it.
389     */
390    chunk = ehdr->e_shnum * ehdr->e_shentsize;
391    if (chunk == 0 || ehdr->e_shoff == 0)
392	goto nosyms;
393    shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk);
394    if (shdr == NULL) {
395	printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
396	    "_loadimage: failed to read section headers");
397	goto nosyms;
398    }
399    symtabindex = -1;
400    symstrindex = -1;
401    for (i = 0; i < ehdr->e_shnum; i++) {
402	if (shdr[i].sh_type != SHT_SYMTAB)
403	    continue;
404	for (j = 0; j < ehdr->e_phnum; j++) {
405	    if (phdr[j].p_type != PT_LOAD)
406		continue;
407	    if (shdr[i].sh_offset >= phdr[j].p_offset &&
408		(shdr[i].sh_offset + shdr[i].sh_size <=
409		 phdr[j].p_offset + phdr[j].p_filesz)) {
410		shdr[i].sh_offset = 0;
411		shdr[i].sh_size = 0;
412		break;
413	    }
414	}
415	if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0)
416	    continue;		/* alread loaded in a PT_LOAD above */
417	/* Save it for loading below */
418	symtabindex = i;
419	symstrindex = shdr[i].sh_link;
420    }
421    if (symtabindex < 0 || symstrindex < 0)
422	goto nosyms;
423
424    /* Ok, committed to a load. */
425#ifndef ELF_VERBOSE
426    printf("syms=[");
427#endif
428    ssym = lastaddr;
429    for (i = symtabindex; i >= 0; i = symstrindex) {
430#ifdef ELF_VERBOSE
431	char	*secname;
432
433	switch(shdr[i].sh_type) {
434	    case SHT_SYMTAB:		/* Symbol table */
435		secname = "symtab";
436		break;
437	    case SHT_STRTAB:		/* String table */
438		secname = "strtab";
439		break;
440	    default:
441		secname = "WHOA!!";
442		break;
443	}
444#endif
445
446	size = shdr[i].sh_size;
447	archsw.arch_copyin(&size, lastaddr, sizeof(size));
448	lastaddr += sizeof(size);
449
450#ifdef ELF_VERBOSE
451	printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname,
452	    (uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset,
453	    (uintmax_t)lastaddr, (uintmax_t)(lastaddr + shdr[i].sh_size));
454#else
455	if (i == symstrindex)
456	    printf("+");
457	printf("0x%lx+0x%lx", (long)sizeof(size), (long)size);
458#endif
459
460	if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) {
461	    printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!");
462	    lastaddr = ssym;
463	    ssym = 0;
464	    goto nosyms;
465	}
466	result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size);
467	if (result < 0 || (size_t)result != shdr[i].sh_size) {
468	    printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped! (%ju != %ju)", (uintmax_t)result,
469		(uintmax_t)shdr[i].sh_size);
470	    lastaddr = ssym;
471	    ssym = 0;
472	    goto nosyms;
473	}
474	/* Reset offsets relative to ssym */
475	lastaddr += shdr[i].sh_size;
476	lastaddr = roundup(lastaddr, sizeof(size));
477	if (i == symtabindex)
478	    symtabindex = -1;
479	else if (i == symstrindex)
480	    symstrindex = -1;
481    }
482    esym = lastaddr;
483#ifndef ELF_VERBOSE
484    printf("]");
485#endif
486
487    file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
488    file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym);
489
490nosyms:
491    printf("\n");
492
493    ret = lastaddr - firstaddr;
494    fp->f_addr = firstaddr;
495
496    php = NULL;
497    for (i = 0; i < ehdr->e_phnum; i++) {
498	if (phdr[i].p_type == PT_DYNAMIC) {
499	    php = phdr + i;
500	    adp = php->p_vaddr;
501	    file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), &adp);
502	    break;
503	}
504    }
505
506    if (php == NULL)	/* this is bad, we cannot get to symbols or _DYNAMIC */
507	goto out;
508
509    ndp = php->p_filesz / sizeof(Elf_Dyn);
510    if (ndp == 0)
511	goto out;
512    dp = malloc(php->p_filesz);
513    if (dp == NULL)
514	goto out;
515    archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz);
516
517    ef->strsz = 0;
518    for (i = 0; i < ndp; i++) {
519	if (dp[i].d_tag == 0)
520	    break;
521	switch (dp[i].d_tag) {
522	case DT_HASH:
523	    ef->hashtab = (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off);
524	    break;
525	case DT_STRTAB:
526	    ef->strtab = (char *)(uintptr_t)(dp[i].d_un.d_ptr + off);
527	    break;
528	case DT_STRSZ:
529	    ef->strsz = dp[i].d_un.d_val;
530	    break;
531	case DT_SYMTAB:
532	    ef->symtab = (Elf_Sym*)(uintptr_t)(dp[i].d_un.d_ptr + off);
533	    break;
534	case DT_REL:
535	    ef->rel = (Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off);
536	    break;
537	case DT_RELSZ:
538	    ef->relsz = dp[i].d_un.d_val;
539	    break;
540	case DT_RELA:
541	    ef->rela = (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off);
542	    break;
543	case DT_RELASZ:
544	    ef->relasz = dp[i].d_un.d_val;
545	    break;
546	default:
547	    break;
548	}
549    }
550    if (ef->hashtab == NULL || ef->symtab == NULL ||
551	ef->strtab == NULL || ef->strsz == 0)
552	goto out;
553    COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets));
554    COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains));
555    ef->buckets = ef->hashtab + 2;
556    ef->chains = ef->buckets + ef->nbuckets;
557    if (__elfN(parse_modmetadata)(fp, ef) == 0)
558	goto out;
559
560    if (ef->kernel)			/* kernel must not depend on anything */
561	goto out;
562
563out:
564    if (dp)
565	free(dp);
566    if (shdr)
567	free(shdr);
568    return ret;
569}
570
571static char invalid_name[] = "bad";
572
573char *
574fake_modname(const char *name)
575{
576    const char *sp, *ep;
577    char *fp;
578    size_t len;
579
580    sp = strrchr(name, '/');
581    if (sp)
582	sp++;
583    else
584	sp = name;
585    ep = strrchr(name, '.');
586    if (ep) {
587	    if (ep == name) {
588		sp = invalid_name;
589		ep = invalid_name + sizeof(invalid_name) - 1;
590	    }
591    } else
592	ep = name + strlen(name);
593    len = ep - sp;
594    fp = malloc(len + 1);
595    if (fp == NULL)
596	return NULL;
597    memcpy(fp, sp, len);
598    fp[len] = '\0';
599    return fp;
600}
601
602#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
603struct mod_metadata64 {
604	int		md_version;	/* structure version MDTV_* */
605	int		md_type;	/* type of entry MDT_* */
606	u_int64_t	md_data;	/* specific data */
607	u_int64_t	md_cval;	/* common string label */
608};
609#endif
610
611int
612__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
613{
614    struct mod_metadata md;
615#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
616    struct mod_metadata64 md64;
617#endif
618    struct mod_depend *mdepend;
619    struct mod_version mver;
620    Elf_Sym sym;
621    char *s;
622    int error, modcnt, minfolen;
623    Elf_Addr v, p, p_stop;
624
625    if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
626	return 0;
627    p = sym.st_value + ef->off;
628    if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
629	return ENOENT;
630    p_stop = sym.st_value + ef->off;
631
632    modcnt = 0;
633    while (p < p_stop) {
634	COPYOUT(p, &v, sizeof(v));
635	error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v));
636	if (error == EOPNOTSUPP)
637	    v += ef->off;
638	else if (error != 0)
639	    return (error);
640#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
641	COPYOUT(v, &md64, sizeof(md64));
642	error = __elfN(reloc_ptr)(fp, ef, v, &md64, sizeof(md64));
643	if (error == EOPNOTSUPP) {
644	    md64.md_cval += ef->off;
645	    md64.md_data += ef->off;
646	} else if (error != 0)
647	    return (error);
648	md.md_version = md64.md_version;
649	md.md_type = md64.md_type;
650	md.md_cval = (const char *)(uintptr_t)md64.md_cval;
651	md.md_data = (void *)(uintptr_t)md64.md_data;
652#else
653	COPYOUT(v, &md, sizeof(md));
654	error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md));
655	if (error == EOPNOTSUPP) {
656	    md.md_cval += ef->off;
657	    md.md_data += ef->off;
658	} else if (error != 0)
659	    return (error);
660#endif
661	p += sizeof(Elf_Addr);
662	switch(md.md_type) {
663	  case MDT_DEPEND:
664	    if (ef->kernel)		/* kernel must not depend on anything */
665	      break;
666	    s = strdupout((vm_offset_t)md.md_cval);
667	    minfolen = sizeof(*mdepend) + strlen(s) + 1;
668	    mdepend = malloc(minfolen);
669	    if (mdepend == NULL)
670		return ENOMEM;
671	    COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend));
672	    strcpy((char*)(mdepend + 1), s);
673	    free(s);
674	    file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend);
675	    free(mdepend);
676	    break;
677	  case MDT_VERSION:
678	    s = strdupout((vm_offset_t)md.md_cval);
679	    COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver));
680	    file_addmodule(fp, s, mver.mv_version, NULL);
681	    free(s);
682	    modcnt++;
683	    break;
684	}
685    }
686    if (modcnt == 0) {
687	s = fake_modname(fp->f_name);
688	file_addmodule(fp, s, 1, NULL);
689	free(s);
690    }
691    return 0;
692}
693
694static unsigned long
695elf_hash(const char *name)
696{
697    const unsigned char *p = (const unsigned char *) name;
698    unsigned long h = 0;
699    unsigned long g;
700
701    while (*p != '\0') {
702	h = (h << 4) + *p++;
703	if ((g = h & 0xf0000000) != 0)
704	    h ^= g >> 24;
705	h &= ~g;
706    }
707    return h;
708}
709
710static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE) "_lookup_symbol: corrupt symbol table\n";
711int
712__elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, const char* name,
713		  Elf_Sym *symp)
714{
715    Elf_Hashelt symnum;
716    Elf_Sym sym;
717    char *strp;
718    unsigned long hash;
719
720    hash = elf_hash(name);
721    COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum));
722
723    while (symnum != STN_UNDEF) {
724	if (symnum >= ef->nchains) {
725	    printf(__elfN(bad_symtable));
726	    return ENOENT;
727	}
728
729	COPYOUT(ef->symtab + symnum, &sym, sizeof(sym));
730	if (sym.st_name == 0) {
731	    printf(__elfN(bad_symtable));
732	    return ENOENT;
733	}
734
735	strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name));
736	if (strcmp(name, strp) == 0) {
737	    free(strp);
738	    if (sym.st_shndx != SHN_UNDEF ||
739		(sym.st_value != 0 &&
740		 ELF_ST_TYPE(sym.st_info) == STT_FUNC)) {
741		*symp = sym;
742		return 0;
743	    }
744	    return ENOENT;
745	}
746	free(strp);
747	COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum));
748    }
749    return ENOENT;
750}
751
752/*
753 * Apply any intra-module relocations to the value. p is the load address
754 * of the value and val/len is the value to be modified. This does NOT modify
755 * the image in-place, because this is done by kern_linker later on.
756 *
757 * Returns EOPNOTSUPP if no relocation method is supplied.
758 */
759static int
760__elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
761    Elf_Addr p, void *val, size_t len)
762{
763	size_t n;
764	Elf_Rela a;
765	Elf_Rel r;
766	int error;
767
768	/*
769	 * The kernel is already relocated, but we still want to apply
770	 * offset adjustments.
771	 */
772	if (ef->kernel)
773		return (EOPNOTSUPP);
774
775	for (n = 0; n < ef->relsz / sizeof(r); n++) {
776		COPYOUT(ef->rel + n, &r, sizeof(r));
777
778		error = __elfN(reloc)(ef, __elfN(symaddr), &r, ELF_RELOC_REL,
779		    ef->off, p, val, len);
780		if (error != 0)
781			return (error);
782	}
783	for (n = 0; n < ef->relasz / sizeof(a); n++) {
784		COPYOUT(ef->rela + n, &a, sizeof(a));
785
786		error = __elfN(reloc)(ef, __elfN(symaddr), &a, ELF_RELOC_RELA,
787		    ef->off, p, val, len);
788		if (error != 0)
789			return (error);
790	}
791
792	return (0);
793}
794
795static Elf_Addr
796__elfN(symaddr)(struct elf_file *ef, Elf_Size symidx)
797{
798
799	/* Symbol lookup by index not required here. */
800	return (0);
801}
802