Merged kernel support for ELF executable format from karolina.lindqvist.
Now kernel can directly run executables generated by gcc.
This commit is contained in:
207
sys/kernel/exec_elf.c
Normal file
207
sys/kernel/exec_elf.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/* $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;
|
||||
}
|
||||
Reference in New Issue
Block a user