load_elf.c revision 40327
139830Speter/*-
239830Speter * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
339830Speter * Copyright (c) 1998 Peter Wemm <peter@freebsd.org>
439830Speter * All rights reserved.
539830Speter *
639830Speter * Redistribution and use in source and binary forms, with or without
739830Speter * modification, are permitted provided that the following conditions
839830Speter * are met:
939830Speter * 1. Redistributions of source code must retain the above copyright
1039830Speter *    notice, this list of conditions and the following disclaimer.
1139830Speter * 2. Redistributions in binary form must reproduce the above copyright
1239830Speter *    notice, this list of conditions and the following disclaimer in the
1339830Speter *    documentation and/or other materials provided with the distribution.
1439830Speter *
1539830Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1639830Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1739830Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1839830Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1939830Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2039830Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2139830Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2239830Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2339830Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2439830Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2539830Speter * SUCH DAMAGE.
2639830Speter *
2740327Speter *	$Id: load_elf.c,v 1.5 1998/10/13 09:25:27 peter Exp $
2839830Speter */
2939830Speter
3039830Speter#include <sys/param.h>
3139830Speter#include <sys/exec.h>
3239830Speter#include <sys/reboot.h>
3340143Speter#include <sys/linker.h>
3439830Speter#include <string.h>
3539830Speter#include <machine/bootinfo.h>
3639830Speter#include <machine/elf.h>
3739830Speter#include <stand.h>
3839830Speter#define FREEBSD_ELF
3939830Speter#include <link.h>
4039830Speter
4139830Speter#include "bootstrap.h"
4239830Speter
4340143Speterstatic int	elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, int kernel);
4439830Speter
4539830Speterchar	*elf_kerneltype = "elf kernel";
4639830Speterchar	*elf_moduletype = "elf module";
4739830Speter
4839830Speter/*
4939830Speter * Attempt to load the file (file) as an ELF module.  It will be stored at
5039830Speter * (dest), and a pointer to a module structure describing the loaded object
5139830Speter * will be saved in (result).
5239830Speter */
5339830Speterint
5439830Speterelf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
5539830Speter{
5639830Speter    struct loaded_module	*mp, *kmp;
5739830Speter    Elf_Ehdr			ehdr;
5839830Speter    int				fd;
5939830Speter    int				err, kernel;
6039830Speter    u_int			pad;
6140143Speter    char			*s;
6239830Speter
6339830Speter    mp = NULL;
6439830Speter
6539830Speter    /*
6639830Speter     * Open the image, read and validate the ELF header
6739830Speter     */
6839830Speter    if (filename == NULL)	/* can't handle nameless */
6939830Speter	return(EFTYPE);
7039830Speter    if ((fd = open(filename, O_RDONLY)) == -1)
7139830Speter	return(errno);
7239830Speter    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
7339830Speter	err = EFTYPE;		/* could be EIO, but may be small file */
7439830Speter	goto oerr;
7539830Speter    }
7639830Speter
7739830Speter    /* Is it ELF? */
7839830Speter    if (!IS_ELF(ehdr)) {
7939830Speter	err = EFTYPE;
8039830Speter	goto oerr;
8139830Speter    }
8239830Speter    if (ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||	/* Layout ? */
8339830Speter	ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
8439830Speter	ehdr.e_ident[EI_VERSION] != EV_CURRENT ||	/* Version ? */
8539830Speter	ehdr.e_version != EV_CURRENT ||
8639830Speter	ehdr.e_machine != ELF_TARG_MACH) {		/* Machine ? */
8739830Speter	err = EFTYPE;
8839830Speter	goto oerr;
8939830Speter    }
9039830Speter
9139830Speter
9239830Speter    /*
9339830Speter     * Check to see what sort of module we are.
9439830Speter     */
9539830Speter    kmp = mod_findmodule(NULL, NULL);
9639830Speter    if (ehdr.e_type == ET_DYN) {
9739830Speter	/* Looks like a kld module */
9839830Speter	if (kmp == NULL) {
9939830Speter	    printf("elf_loadmodule: can't load module before kernel\n");
10039830Speter	    err = EPERM;
10139830Speter	    goto oerr;
10239830Speter	}
10339830Speter	if (strcmp(elf_kerneltype, kmp->m_type)) {
10439830Speter	    printf("elf_loadmodule: can't load module with kernel type '%s'\n", kmp->m_type);
10539830Speter	    err = EPERM;
10639830Speter	    goto oerr;
10739830Speter	}
10839830Speter	/* Looks OK, got ahead */
10939830Speter	kernel = 0;
11039830Speter
11139830Speter	/* Page-align the load address */
11240143Speter	pad = (u_int)dest & PAGE_MASK;
11339830Speter	if (pad != 0) {
11439830Speter	    pad = PAGE_SIZE - pad;
11540143Speter	    dest += pad;
11639830Speter	}
11739830Speter    } else if (ehdr.e_type == ET_EXEC) {
11839830Speter	/* Looks like a kernel */
11939830Speter	if (kmp != NULL) {
12039830Speter	    printf("elf_loadmodule: kernel already loaded\n");
12139830Speter	    err = EPERM;
12239830Speter	    goto oerr;
12339830Speter	}
12439830Speter	/*
12539830Speter	 * Calculate destination address based on kernel entrypoint
12639830Speter	 */
12739830Speter	dest = (vm_offset_t) ehdr.e_entry;
12839830Speter	if (dest == 0) {
12939830Speter	    printf("elf_loadmodule: not a kernel (maybe static binary?)\n");
13039830Speter	    err = EPERM;
13139830Speter	    goto oerr;
13239830Speter	}
13339830Speter	kernel = 1;
13439830Speter
13539830Speter    } else {
13639830Speter	err = EFTYPE;
13739830Speter	goto oerr;
13839830Speter    }
13939830Speter
14039830Speter    /*
14139830Speter     * Ok, we think we should handle this.
14239830Speter     */
14339830Speter    mp = mod_allocmodule();
14440143Speter    if (mp == NULL) {
14540143Speter	    printf("elf_loadmodule: cannot allocate module info\n");
14640143Speter	    err = EPERM;
14740143Speter	    goto out;
14840143Speter    }
14939830Speter    if (kernel)
15040143Speter	setenv("kernelname", filename, 1);
15140143Speter    s = strrchr(filename, '/');
15240143Speter    if (s)
15340143Speter	mp->m_name = strdup(s + 1);
15440143Speter    else
15540143Speter	mp->m_name = strdup(filename);
15639830Speter    mp->m_type = strdup(kernel ? elf_kerneltype : elf_moduletype);
15739830Speter
15840291Speter#ifdef ELF_VERBOSE
15940254Speter    if (kernel)
16040254Speter	printf("%s entry at %p\n", filename, (void *) dest);
16140327Speter#else
16240327Speter    printf("%s ", filename);
16340291Speter#endif
16439830Speter
16540143Speter    mp->m_size = elf_loadimage(mp, fd, dest, &ehdr, kernel);
16640143Speter    if (mp->m_size == 0 || mp->m_addr == 0)
16739830Speter	goto ioerr;
16839830Speter
16939830Speter    /* save exec header as metadata */
17039830Speter    mod_addmetadata(mp, MODINFOMD_ELFHDR, sizeof(ehdr), &ehdr);
17139830Speter
17239830Speter    /* Load OK, return module pointer */
17339830Speter    *result = (struct loaded_module *)mp;
17439830Speter    err = 0;
17539830Speter    goto out;
17639830Speter
17739830Speter ioerr:
17839830Speter    err = EIO;
17939830Speter oerr:
18039830Speter    mod_discard(mp);
18139830Speter out:
18239830Speter    close(fd);
18339830Speter    return(err);
18439830Speter}
18539830Speter
18639830Speter/*
18739830Speter * With the file (fd) open on the image, and (ehdr) containing
18840143Speter * the Elf header, load the image at (off)
18939830Speter */
19039830Speterstatic int
19140143Speterelf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
19239887Speter	      Elf_Ehdr *ehdr, int kernel)
19339830Speter{
19439887Speter    int 	i, j;
19539830Speter    Elf_Phdr	*phdr;
19639887Speter    Elf_Shdr	*shdr;
19739830Speter    int		ret;
19839830Speter    vm_offset_t firstaddr;
19939830Speter    vm_offset_t lastaddr;
20039830Speter    void	*buf;
20139887Speter    size_t	resid, chunk;
20239887Speter    vm_offset_t	dest;
20339887Speter    vm_offset_t	ssym, esym;
20440143Speter    Elf_Dyn	*dp;
20540143Speter    int		ndp;
20640143Speter    int		deplen;
20740143Speter    char	*depdata;
20840143Speter    char	*s;
20940143Speter    int		len;
21040143Speter    char	*strtab;
21140143Speter    size_t	strsz;
21240254Speter    int		symstrindex;
21340254Speter    int		symtabindex;
21440254Speter    long	size;
21539830Speter
21640143Speter    dp = NULL;
21740143Speter    shdr = NULL;
21839830Speter    ret = 0;
21939830Speter    firstaddr = lastaddr = 0;
22040143Speter    if (kernel) {
22139830Speter#ifdef __i386__
22239830Speter	off = 0x10000000;	/* -0xf0000000  - i386 relocates after locore */
22339830Speter#else
22439830Speter	off = 0;		/* alpha is direct mapped for kernels */
22539830Speter#endif
22640143Speter    }
22739830Speter
22839830Speter    phdr = malloc(ehdr->e_phnum * sizeof(*phdr));
22939830Speter    if (phdr == NULL)
23039830Speter	goto out;
23139830Speter
23239830Speter    if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1) {
23339830Speter	printf("elf_loadexec: lseek for phdr failed\n");
23439830Speter	goto out;
23539830Speter    }
23639830Speter    if (read(fd, phdr, ehdr->e_phnum * sizeof(*phdr)) !=
23739830Speter	ehdr->e_phnum * sizeof(*phdr)) {
23839830Speter	printf("elf_loadexec: cannot read program header\n");
23939830Speter	goto out;
24039830Speter    }
24139830Speter
24239830Speter    for (i = 0; i < ehdr->e_phnum; i++) {
24339830Speter	/* We want to load PT_LOAD segments only.. */
24439830Speter	if (phdr[i].p_type != PT_LOAD)
24539830Speter	    continue;
24639830Speter
24740254Speter#ifdef ELF_VERBOSE
24839887Speter	printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx",
24939830Speter	    (long)phdr[i].p_filesz, (long)phdr[i].p_offset,
25039830Speter	    (long)(phdr[i].p_vaddr + off),
25139887Speter	    (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
25240254Speter#else
25340291Speter	if ((phdr[i].p_flags & PF_W) == 0) {
25440291Speter	    printf("text=0x%lx ", (long)phdr[i].p_filesz);
25540291Speter	} else {
25640291Speter	    printf("data=0x%lx", (long)phdr[i].p_filesz);
25740291Speter	    if (phdr[i].p_filesz < phdr[i].p_memsz)
25840291Speter		printf("+0x%lx", (long)(phdr[i].p_memsz -phdr[i].p_filesz));
25940291Speter	    printf(" ");
26040291Speter	}
26140254Speter#endif
26239830Speter
26339830Speter	if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) {
26439887Speter	    printf("\nelf_loadexec: cannot seek\n");
26539830Speter	    goto out;
26639830Speter	}
26739830Speter	if (archsw.arch_readin(fd, phdr[i].p_vaddr + off, phdr[i].p_filesz) !=
26839830Speter	    phdr[i].p_filesz) {
26939887Speter	    printf("\nelf_loadexec: archsw.readin failed\n");
27039830Speter	    goto out;
27139830Speter	}
27239830Speter	/* clear space from oversized segments; eg: bss */
27339830Speter	if (phdr[i].p_filesz < phdr[i].p_memsz) {
27440254Speter#ifdef ELF_VERBOSE
27539887Speter	    printf(" (bss: 0x%lx-0x%lx)",
27639830Speter		(long)(phdr[i].p_vaddr + off + phdr[i].p_filesz),
27739830Speter		(long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
27840254Speter#endif
27939830Speter
28039887Speter	    /* no archsw.arch_bzero */
28139830Speter	    buf = malloc(PAGE_SIZE);
28239830Speter	    bzero(buf, PAGE_SIZE);
28339830Speter	    resid = phdr[i].p_memsz - phdr[i].p_filesz;
28439830Speter	    dest = phdr[i].p_vaddr + off + phdr[i].p_filesz;
28539830Speter	    while (resid > 0) {
28639830Speter		chunk = min(PAGE_SIZE, resid);
28739830Speter		archsw.arch_copyin(buf, dest, chunk);
28839830Speter		resid -= chunk;
28939830Speter		dest += chunk;
29039830Speter	    }
29139830Speter	    free(buf);
29239830Speter	}
29340254Speter#ifdef ELF_VERBOSE
29439887Speter	printf("\n");
29540254Speter#endif
29639830Speter
29740143Speter	if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off))
29839830Speter	    firstaddr = phdr[i].p_vaddr + off;
29940143Speter	if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz))
30039830Speter	    lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz;
30139830Speter    }
30240254Speter    lastaddr = roundup(lastaddr, sizeof(long));
30339830Speter
30439887Speter    /*
30539887Speter     * Now grab the symbol tables.  This isn't easy if we're reading a
30639887Speter     * .gz file.  I think the rule is going to have to be that you must
30739887Speter     * strip a file to remove symbols before gzipping it so that we do not
30840254Speter     * try to lseek() on it.
30939887Speter     */
31039887Speter    chunk = ehdr->e_shnum * ehdr->e_shentsize;
31140291Speter    if (chunk == 0 || ehdr->e_shoff == 0)
31240291Speter	goto nosyms;
31339887Speter    shdr = malloc(chunk);
31439887Speter    if (shdr == NULL)
31539887Speter	goto nosyms;
31639887Speter    if (lseek(fd, ehdr->e_shoff, SEEK_SET) == -1) {
31740254Speter	printf("\nelf_loadimage: cannot lseek() to section headers\n");
31839887Speter	goto nosyms;
31939887Speter    }
32039887Speter    if (read(fd, shdr, chunk) != chunk) {
32140254Speter	printf("\nelf_loadimage: read section headers failed\n");
32239887Speter	goto nosyms;
32339887Speter    }
32440254Speter    symtabindex = -1;
32540254Speter    symstrindex = -1;
32639887Speter    for (i = 0; i < ehdr->e_shnum; i++) {
32740254Speter	if (shdr[i].sh_type != SHT_SYMTAB)
32840143Speter	    continue;
32939887Speter	for (j = 0; j < ehdr->e_phnum; j++) {
33039887Speter	    if (phdr[j].p_type != PT_LOAD)
33139887Speter		continue;
33239887Speter	    if (shdr[i].sh_offset >= phdr[j].p_offset &&
33339887Speter		(shdr[i].sh_offset + shdr[i].sh_size <=
33439887Speter		 phdr[j].p_offset + phdr[j].p_filesz)) {
33539887Speter		shdr[i].sh_offset = 0;
33639887Speter		shdr[i].sh_size = 0;
33739887Speter		break;
33839887Speter	    }
33939887Speter	}
34039887Speter	if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0)
34139887Speter	    continue;		/* alread loaded in a PT_LOAD above */
34240254Speter	/* Save it for loading below */
34340254Speter	symtabindex = i;
34440254Speter	symstrindex = shdr[i].sh_link;
34540254Speter    }
34640254Speter    if (symtabindex < 0 || symstrindex < 0)
34740254Speter	goto nosyms;
34839887Speter
34940254Speter    /* Ok, committed to a load. */
35040254Speter#ifndef ELF_VERBOSE
35140291Speter    printf("syms=[");
35240254Speter#endif
35340254Speter    ssym = lastaddr;
35440254Speter    for (i = symtabindex; i >= 0; i = symstrindex) {
35540254Speter#ifdef ELF_VERBOSE
35640254Speter	char	*secname;
35740254Speter
35840254Speter	switch(shdr[i].sh_type) {
35940254Speter	    case SHT_SYMTAB:		/* Symbol table */
36040254Speter		secname = "symtab";
36140254Speter		break;
36240254Speter	    case SHT_STRTAB:		/* String table */
36340254Speter		secname = "strtab";
36440254Speter		break;
36540254Speter	    default:
36640254Speter		secname = "WHOA!!";
36740254Speter		break;
36840254Speter	}
36940254Speter#endif
37040254Speter
37140254Speter	size = shdr[i].sh_size;
37240254Speter	archsw.arch_copyin(&size, lastaddr, sizeof(size));
37340254Speter	lastaddr += sizeof(long);
37440254Speter
37540254Speter#ifdef ELF_VERBOSE
37639887Speter	printf("%s: 0x%x@0x%x -> 0x%x-0x%x\n", secname,
37739887Speter	    shdr[i].sh_size, shdr[i].sh_offset,
37839887Speter	    lastaddr, lastaddr + shdr[i].sh_size);
37940254Speter#else
38040291Speter	if (i == symstrindex)
38140291Speter	    printf("+");
38240254Speter	printf("0x%x+0x%lx", sizeof(size), size);
38340254Speter#endif
38440254Speter
38539887Speter	if (lseek(fd, shdr[i].sh_offset, SEEK_SET) == -1) {
38639887Speter	    printf("\nelf_loadimage: could not seek for symbols - skipped!\n");
38740254Speter	    lastaddr = ssym;
38840254Speter	    ssym = 0;
38940254Speter	    goto nosyms;
39039887Speter	}
39139887Speter	if (archsw.arch_readin(fd, lastaddr, shdr[i].sh_size) !=
39239887Speter	    shdr[i].sh_size) {
39339887Speter	    printf("\nelf_loadimage: could not read symbols - skipped!\n");
39440254Speter	    lastaddr = ssym;
39540254Speter	    ssym = 0;
39640254Speter	    goto nosyms;
39739887Speter	}
39839887Speter	/* Reset offsets relative to ssym */
39939887Speter	lastaddr += shdr[i].sh_size;
40039887Speter	lastaddr = roundup(lastaddr, sizeof(long));
40140254Speter	if (i == symtabindex)
40240254Speter	    symtabindex = -1;
40340254Speter	else if (i == symstrindex)
40440254Speter	    symstrindex = -1;
40539887Speter    }
40639887Speter    esym = lastaddr;
40740254Speter#ifndef ELF_VERBOSE
40840254Speter    printf("]\n");
40940254Speter#endif
41039887Speter
41140143Speter    mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
41240143Speter    mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym);
41339887Speter
41439887Speternosyms:
41539887Speter
41639830Speter    ret = lastaddr - firstaddr;
41740143Speter    mp->m_addr = firstaddr;
41840143Speter
41940143Speter    for (i = 0; i < ehdr->e_phnum; i++) {
42040143Speter	if (phdr[i].p_type == PT_DYNAMIC) {
42140143Speter	    dp = (Elf_Dyn *)(phdr[i].p_vaddr);
42240143Speter	    mod_addmetadata(mp, MODINFOMD_DYNAMIC, sizeof(dp), &dp);
42340143Speter	    dp = NULL;
42440143Speter	    break;
42540143Speter	}
42640143Speter    }
42740143Speter
42840143Speter    if (kernel)		/* kernel must not depend on anything */
42940143Speter	goto out;
43040143Speter
43140143Speter    ndp = 0;
43240143Speter    for (i = 0; i < ehdr->e_phnum; i++) {
43340143Speter	if (phdr[i].p_type == PT_DYNAMIC) {
43440143Speter	    ndp = phdr[i].p_filesz / sizeof(Elf_Dyn);
43540143Speter	    dp = malloc(phdr[i].p_filesz);
43640143Speter	    archsw.arch_copyout(phdr[i].p_vaddr + off, dp, phdr[i].p_filesz);
43740143Speter	}
43840143Speter    }
43940143Speter    if (dp == NULL || ndp == 0)
44040143Speter	goto out;
44140143Speter    strtab = NULL;
44240143Speter    strsz = 0;
44340143Speter    deplen = 0;
44440143Speter    for (i = 0; i < ndp; i++) {
44540143Speter	if (dp[i].d_tag == NULL)
44640143Speter	    break;
44740143Speter	switch (dp[i].d_tag) {
44840143Speter	case DT_STRTAB:
44940143Speter	    strtab = (char *)(dp[i].d_un.d_ptr + off);
45040143Speter	    break;
45140143Speter	case DT_STRSZ:
45240143Speter	    strsz = dp[i].d_un.d_val;
45340143Speter	    break;
45440143Speter	default:
45540143Speter	    break;
45640143Speter	}
45740143Speter    }
45840143Speter    if (strtab == NULL || strsz == 0)
45940143Speter	goto out;
46040143Speter
46140143Speter    deplen = 0;
46240143Speter    for (i = 0; i < ndp; i++) {
46340143Speter	if (dp[i].d_tag == NULL)
46440143Speter	    break;
46540143Speter	switch (dp[i].d_tag) {
46640143Speter	case DT_NEEDED:		/* count size for dependency list */
46740143Speter	    j = dp[i].d_un.d_ptr;
46840143Speter	    if (j < 1 || j > (strsz - 2))
46940143Speter		continue;	/* bad symbol name index */
47040143Speter	    deplen += strlenout((vm_offset_t)&strtab[j]) + 1;
47140143Speter	    break;
47240143Speter	default:
47340143Speter	    break;
47440143Speter	}
47540143Speter    }
47640143Speter
47740143Speter    if (deplen > 0) {
47840143Speter	depdata = malloc(deplen);
47940143Speter	if (depdata == NULL)
48040143Speter	    goto out;
48140143Speter	s = depdata;
48240143Speter	for (i = 0; i < ndp; i++) {
48340143Speter	    if (dp[i].d_tag == NULL)
48440143Speter		break;
48540143Speter	    switch (dp[i].d_tag) {
48640143Speter	    case DT_NEEDED:	/* dependency list */
48740143Speter		j = dp[i].d_un.d_ptr;
48840143Speter	    	len = strlenout((vm_offset_t)&strtab[j]) + 1;
48940143Speter		archsw.arch_copyout((vm_offset_t)&strtab[j], s, len);
49040143Speter		s += len;
49140143Speter		break;
49240143Speter	    default:
49340143Speter		break;
49440143Speter	    }
49540143Speter	}
49640143Speter	if ((s - depdata) > 0)
49740143Speter	    mod_addmetadata(mp, MODINFOMD_DEPLIST, s - depdata, depdata);
49840143Speter	free(depdata);
49940143Speter    }
50040143Speter
50139830Speterout:
50240143Speter    if (dp)
50340143Speter	free(dp);
50440143Speter    if (shdr)
50540143Speter	free(shdr);
50639830Speter    if (phdr)
50739830Speter	free(phdr);
50839830Speter    return ret;
50939830Speter}
510