diff options
Diffstat (limited to '')
| -rw-r--r-- | sys/lib/libsa/loadfile.c | 218 |
1 files changed, 30 insertions, 188 deletions
diff --git a/sys/lib/libsa/loadfile.c b/sys/lib/libsa/loadfile.c index a1c1230c9be..4dc70bcf7da 100644 --- a/sys/lib/libsa/loadfile.c +++ b/sys/lib/libsa/loadfile.c @@ -1,5 +1,5 @@ /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */ -/* $OpenBSD: loadfile.c,v 1.12 2007/01/04 07:09:30 miod Exp $ */ +/* $OpenBSD: loadfile.c,v 1.13 2007/05/30 01:25:43 tom Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -94,15 +94,25 @@ #include <sys/exec_ecoff.h> static int coff_exec(int, struct ecoff_exechdr *, u_long *, int); #endif -#ifdef BOOT_ELF -#include <sys/exec_elf.h> -static int elf_exec(int, Elf_Ehdr *, u_long *, int); -#endif #ifdef BOOT_AOUT #include <sys/exec_aout.h> static int aout_exec(int, struct exec *, u_long *, int); #endif +#ifdef BOOT_ELF +#include <sys/exec_elf.h> +#if defined(BOOT_ELF32) && defined(BOOT_ELF64) +/* + * Both defined, so elf32_exec() and elf64_exec() need to be separately + * created (can't do it by including loadfile_elf.c here). + */ +int elf32_exec(int, Elf32_Ehdr *, u_long *, int); +int elf64_exec(int, Elf64_Ehdr *, u_long *, int); +#else +#include "loadfile_elf.c" +#endif +#endif + /* * Open 'filename', read in program and and return 0 if ok 1 on error. * Fill in marks @@ -114,8 +124,11 @@ loadfile(const char *fname, u_long *marks, int flags) #ifdef BOOT_ECOFF struct ecoff_exechdr coff; #endif -#ifdef BOOT_ELF - Elf_Ehdr elf; +#if defined(BOOT_ELF32) || (defined(BOOT_ELF) && ELFSIZE == 32) + Elf32_Ehdr elf32; +#endif +#if defined(BOOT_ELF64) || (defined(BOOT_ELF) && ELFSIZE == 64) + Elf64_Ehdr elf64; #endif #ifdef BOOT_AOUT struct exec aout; @@ -142,10 +155,16 @@ loadfile(const char *fname, u_long *marks, int flags) rval = coff_exec(fd, &hdr.coff, marks, flags); } else #endif -#ifdef BOOT_ELF - if (memcmp(hdr.elf.e_ident, ELFMAG, SELFMAG) == 0 && - hdr.elf.e_ident[EI_CLASS] == ELFCLASS) { - rval = elf_exec(fd, &hdr.elf, marks, flags); +#if defined(BOOT_ELF32) || (defined(BOOT_ELF) && ELFSIZE == 32) + if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 && + hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) { + rval = elf32_exec(fd, &hdr.elf32, marks, flags); + } else +#endif +#if defined(BOOT_ELF64) || (defined(BOOT_ELF) && ELFSIZE == 64) + if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 && + hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) { + rval = elf64_exec(fd, &hdr.elf64, marks, flags); } else #endif #ifdef BOOT_AOUT @@ -254,183 +273,6 @@ coff_exec(int fd, struct ecoff_exechdr *coff, u_long *marks, int flags) } #endif /* BOOT_ECOFF */ -#ifdef BOOT_ELF -static int -elf_exec(int fd, Elf_Ehdr *elf, u_long *marks, int flags) -{ - Elf_Shdr *shp; - Elf_Phdr *phdr; - Elf_Off off; - int i; - size_t sz; - int first; - int havesyms; - paddr_t minp = ~0, maxp = 0, pos = 0; - paddr_t offset = marks[MARK_START], shpp, elfp; - - sz = elf->e_phnum * sizeof(Elf_Phdr); - phdr = ALLOC(sz); - - if (lseek(fd, elf->e_phoff, SEEK_SET) == -1) { - WARN(("lseek phdr")); - FREE(phdr, sz); - return 1; - } - if (read(fd, phdr, sz) != sz) { - WARN(("read program headers")); - FREE(phdr, sz); - return 1; - } - - for (first = 1, i = 0; i < elf->e_phnum; i++) { - - if (phdr[i].p_type != PT_LOAD || - (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0) - continue; - -#define IS_TEXT(p) (p.p_flags & PF_X) -#define IS_DATA(p) ((p.p_flags & PF_X) == 0) -#define IS_BSS(p) (p.p_filesz < p.p_memsz) - /* - * XXX: Assume first address is lowest - */ - if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || - (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { - - /* Read in segment. */ - PROGRESS(("%s%lu", first ? "" : "+", - (u_long)phdr[i].p_filesz)); - - if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) { - WARN(("lseek text")); - FREE(phdr, sz); - return 1; - } - if (READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz) != - phdr[i].p_filesz) { - WARN(("read text")); - FREE(phdr, sz); - return 1; - } - first = 0; - - } - if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) || - (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) { - pos = phdr[i].p_vaddr; - if (minp > pos) - minp = pos; - pos += phdr[i].p_filesz; - if (maxp < pos) - maxp = pos; - } - - /* Zero out bss. */ - if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { - PROGRESS(("+%lu", - (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); - BZERO((phdr[i].p_vaddr + phdr[i].p_filesz), - phdr[i].p_memsz - phdr[i].p_filesz); - } - if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { - pos += phdr[i].p_memsz - phdr[i].p_filesz; - if (maxp < pos) - maxp = pos; - } - } - FREE(phdr, sz); - - /* - * Copy the ELF and section headers. - */ - elfp = maxp = roundup(maxp, sizeof(long)); - if (flags & (LOAD_HDR|COUNT_HDR)) - maxp += sizeof(Elf_Ehdr); - - if (flags & (LOAD_SYM|COUNT_SYM)) { - if (lseek(fd, elf->e_shoff, SEEK_SET) == -1) { - WARN(("lseek section headers")); - return 1; - } - sz = elf->e_shnum * sizeof(Elf_Shdr); - shp = ALLOC(sz); - - if (read(fd, shp, sz) != sz) { - WARN(("read section headers")); - FREE(shp, sz); - return 1; - } - - shpp = maxp; - maxp += roundup(sz, sizeof(long)); - - /* - * Now load the symbol sections themselves. Make sure the - * sections are aligned. Don't bother with string tables if - * there are no symbol sections. - */ - off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(long)); - - for (havesyms = i = 0; i < elf->e_shnum; i++) - if (shp[i].sh_type == SHT_SYMTAB) - havesyms = 1; - - for (first = 1, i = 0; i < elf->e_shnum; i++) { - if (shp[i].sh_type == SHT_SYMTAB || - shp[i].sh_type == SHT_STRTAB) { - if (havesyms && (flags & LOAD_SYM)) { - PROGRESS(("%s%ld", first ? " [" : "+", - (u_long)shp[i].sh_size)); - if (lseek(fd, shp[i].sh_offset, - SEEK_SET) == -1) { - WARN(("lseek symbols")); - FREE(shp, sz); - return 1; - } - if (READ(fd, maxp, shp[i].sh_size) != - shp[i].sh_size) { - WARN(("read symbols")); - FREE(shp, sz); - return 1; - } - } - maxp += roundup(shp[i].sh_size, - sizeof(long)); - shp[i].sh_offset = off; - off += roundup(shp[i].sh_size, sizeof(long)); - first = 0; - } - } - if (flags & LOAD_SYM) { - BCOPY(shp, shpp, sz); - - if (havesyms && first == 0) - PROGRESS(("]")); - } - FREE(shp, sz); - } - - /* - * Frob the copied ELF header to give information relative - * to elfp. - */ - if (flags & LOAD_HDR) { - elf->e_phoff = 0; - elf->e_shoff = sizeof(Elf_Ehdr); - elf->e_phentsize = 0; - elf->e_phnum = 0; - BCOPY(elf, elfp, sizeof(*elf)); - } - - marks[MARK_START] = LOADADDR(minp); - marks[MARK_ENTRY] = LOADADDR(elf->e_entry); - marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ - marks[MARK_SYM] = LOADADDR(elfp); - marks[MARK_END] = LOADADDR(maxp); - return 0; -} -#endif /* BOOT_ELF */ - #ifdef BOOT_AOUT static int aout_exec(int fd, struct exec *x, u_long *marks, int flags) |
