208 lines
7.5 KiB
C
208 lines
7.5 KiB
C
/* $NetBSD: exec_elf32.c,v 1.49.2.2 2000/11/03 20:00:38 tv Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 1994 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
* by Christos Zoulas.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the NetBSD
|
|
* Foundation, Inc. and its contributors.
|
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 1996 Christopher G. Demetriou
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
#include "param.h"
|
|
#include "systm.h"
|
|
#include "kernel.h"
|
|
#include "map.h"
|
|
#include "user.h"
|
|
#include "proc.h"
|
|
//#include "malloc.h"
|
|
#include "inode.h"
|
|
#include "namei.h"
|
|
//#include "vnode.h"
|
|
#include "exec.h"
|
|
#include "exec_elf.h"
|
|
#include "fcntl.h"
|
|
//#include "syscall.h"
|
|
#include "signalvar.h"
|
|
#include "mount.h"
|
|
#include "stat.h"
|
|
|
|
|
|
extern char sigcode[], esigcode[];
|
|
|
|
/* round up and down to page boundaries. */
|
|
#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
|
|
#define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
|
|
|
|
/*
|
|
* elf_check(): Prepare an Elf binary's exec package
|
|
*
|
|
* First, set of the various offsets/lengths in the exec package.
|
|
*
|
|
* Then, mark the text image busy (so it can be demand paged) or error
|
|
* out if this is not possible. Finally, set up vmcmds for the
|
|
* text, data, bss, and stack segments.
|
|
*/
|
|
int
|
|
exec_elf_check(struct exec_params *epp)
|
|
{
|
|
struct elf_phdr *ph;
|
|
int error, i, phsize;
|
|
|
|
const char elfident[] = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
|
|
ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV, 0};
|
|
|
|
/*
|
|
* Check that this is an ELF file that we can handle,
|
|
* and do some sanity checks on the header
|
|
*/
|
|
if (epp->hdr_len < sizeof(struct elf_ehdr))
|
|
return ENOEXEC;
|
|
for (i = 0; i < sizeof elfident; i++)
|
|
if (epp->hdr.elf.e_ident[i] != elfident[i])
|
|
return ENOEXEC;
|
|
if (epp->hdr.elf.e_type != ET_EXEC)
|
|
return ENOEXEC;
|
|
if (epp->hdr.elf.e_machine != EM_MIPS || epp->hdr.elf.e_version != EV_CURRENT)
|
|
return ENOEXEC;
|
|
if (epp->hdr.elf.e_phentsize != sizeof(struct elf_phdr) || epp->hdr.elf.e_phoff == 0 || epp->hdr.elf.e_phnum == 0)
|
|
return ENOEXEC;
|
|
if (epp->hdr.elf.e_shnum == 0 || epp->hdr.elf.e_shentsize != sizeof(struct elf_shdr))
|
|
return ENOEXEC;
|
|
|
|
/*
|
|
* Read program headers
|
|
*/
|
|
phsize = epp->hdr.elf.e_phnum * sizeof(struct elf_phdr);
|
|
ph = exec_alloc(phsize, NBPW, epp);
|
|
if (ph == NULL) {
|
|
printf("can't alloc ph[] sz=%d\n", phsize);
|
|
return ENOEXEC;
|
|
}
|
|
if ((error = rdwri(UIO_READ, epp->ip, (caddr_t)ph, phsize, epp->hdr.elf.e_phoff, IO_UNIT, 0)) != 0)
|
|
return ENOEXEC;
|
|
|
|
epp->text.len = epp->data.len = epp->bss.len = epp->stack.len = epp->heap.len = 0;
|
|
epp->text.vaddr = epp->data.vaddr = epp->bss.vaddr = epp->stack.vaddr = epp->heap.vaddr = NO_ADDR;
|
|
|
|
if (epp->hdr.elf.e_phnum == 1 && ph[0].p_type == PT_LOAD && ph[0].p_flags == (PF_R|PF_W|PF_X)) {
|
|
/*
|
|
* In the simple a.out type link, in elf format, there is only
|
|
* one loadable segment that is RWE containing everything
|
|
* Here we fix the memory allocation, and we are done.
|
|
*/
|
|
epp->data.vaddr = (caddr_t)ph[0].p_vaddr;
|
|
epp->data.len = ph[0].p_memsz;
|
|
epp->heap.vaddr = (caddr_t)ph[0].p_vaddr + ph[0].p_memsz;
|
|
epp->heap.len = 0;
|
|
epp->stack.len = SSIZE + epp->argbc + epp->envbc + (epp->argc+epp->envc+4)*NBPW;
|
|
epp->stack.vaddr = (caddr_t)USER_DATA_END - epp->stack.len;
|
|
|
|
/*
|
|
* We assume .bss is the different between the memory data
|
|
* section size and the file size.
|
|
*/
|
|
epp->bss.vaddr = epp->data.vaddr + ph[0].p_filesz;
|
|
epp->bss.len = ph[0].p_memsz - ph[0].p_filesz;
|
|
epp->data.len = epp->bss.vaddr - epp->data.vaddr;
|
|
} else {
|
|
/*
|
|
* At the current moment we don't handle anything else
|
|
* The rest of the code is implemented as need arise.
|
|
*/
|
|
return ENOEXEC;
|
|
}
|
|
|
|
/*
|
|
* Save arglist
|
|
*/
|
|
exec_save_args(epp);
|
|
|
|
/*
|
|
* Establish memory
|
|
*/
|
|
if ((error = exec_estab(epp)) != 0)
|
|
return error;
|
|
|
|
/*
|
|
* Now load the program sections into memory
|
|
*/
|
|
for (i = 0; i < epp->hdr.elf.e_phnum; i++) {
|
|
if (ph[i].p_type != PT_LOAD)
|
|
continue;
|
|
/*
|
|
* Sanity check that the load is to our intended address space.
|
|
*/
|
|
if (!((epp->text.vaddr != NO_ADDR
|
|
&& ((caddr_t)ph[i].p_vaddr >= epp->text.vaddr
|
|
&& (caddr_t)ph[i].p_vaddr + ph[i].p_filesz <= epp->text.vaddr + epp->text.len))
|
|
|| (epp->data.vaddr != NO_ADDR
|
|
&& (caddr_t)ph[i].p_vaddr >= epp->data.vaddr
|
|
&& (caddr_t)ph[i].p_vaddr + ph[i].p_filesz <= epp->data.vaddr + epp->data.len))
|
|
|| ph[i].p_filesz >= ph[i].p_memsz || ph[i].p_filesz <= 0)
|
|
return ENOEXEC;
|
|
|
|
error = rdwri(UIO_READ, epp->ip, (caddr_t)ph[i].p_vaddr, ph[i].p_filesz, ph[i].p_offset, IO_UNIT, 0);
|
|
}
|
|
|
|
exec_clear(epp);
|
|
exec_setupstack(epp->hdr.elf.e_entry, epp);
|
|
|
|
return 0;
|
|
}
|