summaryrefslogtreecommitdiff
path: root/sys/boot/common/load_elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/common/load_elf.c')
-rw-r--r--sys/boot/common/load_elf.c113
1 files changed, 58 insertions, 55 deletions
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index ff1f50638ac8a..b2b38c7800b65 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: load_elf.c,v 1.9 1998/10/17 03:06:38 peter Exp $
+ * $Id: load_elf.c,v 1.7 1998/10/15 21:56:47 dfr Exp $
*/
#include <sys/param.h>
@@ -40,7 +40,7 @@
#include "bootstrap.h"
-static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, int kernel, caddr_t firstpage, int firstlen);
+static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, Elf_Phdr *phdr, int kernel);
char *elf_kerneltype = "elf kernel";
char *elf_moduletype = "elf module";
@@ -54,15 +54,15 @@ int
elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
{
struct loaded_module *mp, *kmp;
- Elf_Ehdr *ehdr;
+ Elf_Ehdr ehdr;
+ Elf_Phdr *phdr;
int fd;
int err, kernel;
u_int pad;
char *s;
- caddr_t firstpage;
- int firstlen;
mp = NULL;
+ phdr = NULL;
/*
* Open the image, read and validate the ELF header
@@ -71,26 +71,21 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
return(EFTYPE);
if ((fd = open(filename, O_RDONLY)) == -1)
return(errno);
- firstpage = malloc(PAGE_SIZE);
- if (firstpage == NULL)
- return(ENOMEM);
- firstlen = read(fd, firstpage, PAGE_SIZE);
- if (firstlen <= sizeof(ehdr)) {
+ if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
err = EFTYPE; /* could be EIO, but may be small file */
goto oerr;
}
- ehdr = (Elf_Ehdr *)firstpage;
/* Is it ELF? */
- if (!IS_ELF(*ehdr)) {
+ if (!IS_ELF(ehdr)) {
err = EFTYPE;
goto oerr;
}
- if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
- ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
- ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
- ehdr->e_version != EV_CURRENT ||
- ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */
+ if (ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
+ ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
+ ehdr.e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
+ ehdr.e_version != EV_CURRENT ||
+ ehdr.e_machine != ELF_TARG_MACH) { /* Machine ? */
err = EFTYPE;
goto oerr;
}
@@ -100,7 +95,7 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
* Check to see what sort of module we are.
*/
kmp = mod_findmodule(NULL, NULL);
- if (ehdr->e_type == ET_DYN) {
+ if (ehdr.e_type == ET_DYN) {
/* Looks like a kld module */
if (kmp == NULL) {
printf("elf_loadmodule: can't load module before kernel\n");
@@ -121,7 +116,7 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
pad = PAGE_SIZE - pad;
dest += pad;
}
- } else if (ehdr->e_type == ET_EXEC) {
+ } else if (ehdr.e_type == ET_EXEC) {
/* Looks like a kernel */
if (kmp != NULL) {
printf("elf_loadmodule: kernel already loaded\n");
@@ -131,7 +126,7 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
/*
* Calculate destination address based on kernel entrypoint
*/
- dest = (vm_offset_t) ehdr->e_entry;
+ dest = (vm_offset_t) ehdr.e_entry;
if (dest == 0) {
printf("elf_loadmodule: not a kernel (maybe static binary?)\n");
err = EPERM;
@@ -169,12 +164,36 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
printf("%s ", filename);
#endif
- mp->m_size = elf_loadimage(mp, fd, dest, ehdr, kernel, firstpage, firstlen);
+ phdr = malloc(ehdr.e_phnum * sizeof(*phdr));
+ if (phdr == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ if (lseek(fd, ehdr.e_phoff, SEEK_SET) == -1) {
+ printf("elf_loadexec: lseek for phdr failed\n");
+ goto ioerr;
+ }
+ if (read(fd, phdr, ehdr.e_phnum * sizeof(*phdr)) !=
+ ehdr.e_phnum * sizeof(*phdr)) {
+ printf("elf_loadmodule: cannot read program header\n");
+ goto ioerr;
+ }
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ close(fd);
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ printf("elf_loadmodule: cannot reset file position\n");
+ mod_discard(mp);
+ return errno;
+ }
+ }
+
+ mp->m_size = elf_loadimage(mp, fd, dest, &ehdr, phdr, kernel);
if (mp->m_size == 0 || mp->m_addr == 0)
goto ioerr;
/* save exec header as metadata */
- mod_addmetadata(mp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr);
+ mod_addmetadata(mp, MODINFOMD_ELFHDR, sizeof(ehdr), &ehdr);
/* Load OK, return module pointer */
*result = (struct loaded_module *)mp;
@@ -186,8 +205,8 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
oerr:
mod_discard(mp);
out:
- if (firstpage)
- free(firstpage);
+ if (phdr)
+ free(phdr);
close(fd);
return(err);
}
@@ -198,10 +217,9 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
*/
static int
elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
- Elf_Ehdr *ehdr, int kernel, caddr_t firstpage, int firstlen)
+ Elf_Ehdr *ehdr, Elf_Phdr *phdr, int kernel)
{
int i, j;
- Elf_Phdr *phdr;
Elf_Shdr *shdr;
int ret;
vm_offset_t firstaddr;
@@ -221,7 +239,6 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
int symstrindex;
int symtabindex;
long size;
- int fpcopy;
dp = NULL;
shdr = NULL;
@@ -235,12 +252,6 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
#endif
}
- if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > firstlen) {
- printf("elf_loadimage: program header not within first page\n");
- goto out;
- }
- phdr = (Elf_Phdr *)(firstpage + ehdr->e_phoff);
-
for (i = 0; i < ehdr->e_phnum; i++) {
/* We want to load PT_LOAD segments only.. */
if (phdr[i].p_type != PT_LOAD)
@@ -261,22 +272,15 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
printf(" ");
}
#endif
- fpcopy = 0;
- if (firstlen > phdr[i].p_offset) {
- fpcopy = firstlen - phdr[i].p_offset;
- archsw.arch_copyin(firstpage + phdr[i].p_offset,
- phdr[i].p_vaddr + off, fpcopy);
+
+ if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) {
+ printf("\nelf_loadexec: cannot seek\n");
+ goto out;
}
- if (phdr[i].p_filesz > fpcopy) {
- if (lseek(fd, phdr[i].p_offset + fpcopy, SEEK_SET) == -1) {
- printf("\nelf_loadexec: cannot seek\n");
- goto out;
- }
- if (archsw.arch_readin(fd, phdr[i].p_vaddr + off + fpcopy,
- phdr[i].p_filesz - fpcopy) != phdr[i].p_filesz - fpcopy) {
- printf("\nelf_loadexec: archsw.readin failed\n");
- goto out;
- }
+ if (archsw.arch_readin(fd, phdr[i].p_vaddr + off, phdr[i].p_filesz) !=
+ phdr[i].p_filesz) {
+ printf("\nelf_loadexec: archsw.readin failed\n");
+ goto out;
}
/* clear space from oversized segments; eg: bss */
if (phdr[i].p_filesz < phdr[i].p_memsz) {
@@ -323,11 +327,11 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
if (shdr == NULL)
goto nosyms;
if (lseek(fd, ehdr->e_shoff, SEEK_SET) == -1) {
- printf("\nelf_loadimage: cannot lseek() to section headers");
+ printf("\nelf_loadimage: cannot lseek() to section headers\n");
goto nosyms;
}
if (read(fd, shdr, chunk) != chunk) {
- printf("\nelf_loadimage: read section headers failed");
+ printf("\nelf_loadimage: read section headers failed\n");
goto nosyms;
}
symtabindex = -1;
@@ -382,7 +386,7 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
lastaddr += sizeof(long);
#ifdef ELF_VERBOSE
- printf("\n%s: 0x%lx@0x%lx -> 0x%lx-0x%lx", secname,
+ printf("%s: 0x%lx@0x%lx -> 0x%lx-0x%lx\n", secname,
shdr[i].sh_size, shdr[i].sh_offset,
lastaddr, lastaddr + shdr[i].sh_size);
#else
@@ -392,14 +396,14 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
#endif
if (lseek(fd, shdr[i].sh_offset, SEEK_SET) == -1) {
- printf("\nelf_loadimage: could not seek for symbols - skipped!");
+ printf("\nelf_loadimage: could not seek for symbols - skipped!\n");
lastaddr = ssym;
ssym = 0;
goto nosyms;
}
if (archsw.arch_readin(fd, lastaddr, shdr[i].sh_size) !=
shdr[i].sh_size) {
- printf("\nelf_loadimage: could not read symbols - skipped!");
+ printf("\nelf_loadimage: could not read symbols - skipped!\n");
lastaddr = ssym;
ssym = 0;
goto nosyms;
@@ -414,14 +418,13 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off,
}
esym = lastaddr;
#ifndef ELF_VERBOSE
- printf("]");
+ printf("]\n");
#endif
mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym);
nosyms:
- printf("\n");
ret = lastaddr - firstaddr;
mp->m_addr = firstaddr;