First attempt at FreeBSD & Linux ELF support.
Compile and link a new kernel, that will give native ELF support, and provide the hooks for other ELF interpreters as well. To make native ELF binaries use John Polstras elf-kit-1.0.1.. For the time being also use his ld-elf.so.1 and put it in /usr/libexec. The Linux emulator has been enhanced to also run ELF binaries, it is however in its very first incarnation. Just get some Linux ELF libs (Slackware-3.0) and put them in the prober place (/compat/linux/...). I've ben able to run all the Slackware-3.0 binaries I've tried so far. (No it won't run quake yet :)
This commit is contained in:
parent
7c1b69d881
commit
e1743d02cd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=14456
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.5 1996/01/27 23:57:06 rgrimes Exp $
|
||||
# $Id: Makefile,v 1.6 1996/03/02 20:00:35 peter Exp $
|
||||
|
||||
.PATH: ${.CURDIR}/../../sys/i386/linux
|
||||
KMOD= linux_mod
|
||||
@ -11,7 +11,7 @@ NOMAN=
|
||||
|
||||
CFLAGS+= -DLKM -I. -DCOMPAT_43 -DCOMPAT_LINUX #-DDEBUG
|
||||
CPPFLAGS= -I. -I${.CURDIR}/../../sys
|
||||
|
||||
EXPORT_SYMS=_linux_mod
|
||||
CLEANFILES+= vnode_if.h vnode_if.c linux_genassym.o linux_genassym machine \
|
||||
linux_assym.h
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: linux.c,v 1.3 1995/11/13 07:18:38 bde Exp $
|
||||
* $Id: linux.c,v 1.4 1995/11/14 07:34:18 bde Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -34,14 +34,24 @@
|
||||
#include <sys/conf.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/lkm.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include "i386/linux/linux.h"
|
||||
|
||||
extern const struct execsw linux_execsw;
|
||||
|
||||
MOD_EXEC(linux, -1, (struct execsw*)&linux_execsw);
|
||||
|
||||
static Elf32_Interp_info linux_interp = {
|
||||
&elf_linux_sysvec,
|
||||
"/lib/ld-linux.so.1",
|
||||
"/compat/linux"
|
||||
};
|
||||
|
||||
static int
|
||||
linux_load(struct lkm_table *lkmtp, int cmd)
|
||||
{
|
||||
if (elf_insert_interp(&linux_interp))
|
||||
uprintf("Could not install ELF interpreter entry\n");
|
||||
uprintf("Linux emulator installed\n");
|
||||
return 0;
|
||||
}
|
||||
@ -49,6 +59,8 @@ linux_load(struct lkm_table *lkmtp, int cmd)
|
||||
static int
|
||||
linux_unload(struct lkm_table *lkmtp, int cmd)
|
||||
{
|
||||
if (elf_remove_interp(&linux_interp))
|
||||
uprintf("Could not deinstall ELF interpreter entry\n");
|
||||
uprintf("Linux emulator removed\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 1994-1995 Søren Schmidt
|
||||
* Copyright (c) 1994-1996 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,11 +25,12 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: linux.h,v 1.5 1996/03/02 19:37:47 peter Exp $
|
||||
* $Id: linux.h,v 1.6 1996/03/03 19:07:49 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _I386_LINUX_LINUX_H_
|
||||
#define _I386_LINUX_LINUX_H_
|
||||
#include "i386/linux/linux_syscall.h"
|
||||
|
||||
typedef unsigned short linux_uid_t;
|
||||
typedef unsigned short linux_gid_t;
|
||||
@ -97,13 +98,20 @@ struct linux_sigframe {
|
||||
sig_t sf_handler;
|
||||
};
|
||||
|
||||
extern int bsd_to_linux_errno[];
|
||||
extern int bsd_to_linux_signal[];
|
||||
extern int linux_to_bsd_signal[];
|
||||
extern char linux_sigcode[];
|
||||
extern int linux_szsigcode;
|
||||
extern const char linux_emul_path[];
|
||||
|
||||
extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
|
||||
extern struct sysentvec linux_sysvec;
|
||||
extern struct sysentvec elf_linux_sysvec;
|
||||
|
||||
/* dummy struct definitions */
|
||||
struct image_params;
|
||||
int linux_fixup __P((int **stack_base, struct image_params *iparams));
|
||||
struct trapframe;
|
||||
|
||||
/* misc defines */
|
||||
#define LINUX_NAME_MAX 255
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 1994-1995 Søren Schmidt
|
||||
* Copyright (c) 1994-1996 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,7 +25,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: linux_sysent.c,v 1.4 1996/01/14 10:59:57 sos Exp $
|
||||
* $Id: linux_sysvec.c,v 1.1 1996/03/02 19:38:01 peter Exp $
|
||||
*/
|
||||
|
||||
/* XXX we use functions that might not exist. */
|
||||
@ -36,7 +36,9 @@
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
@ -59,62 +61,93 @@
|
||||
|
||||
#include <i386/linux/linux.h>
|
||||
#include <i386/linux/linux_proto.h>
|
||||
#include <i386/linux/linux_syscall.h>
|
||||
|
||||
int linux_fixup __P((int **stack_base, struct image_params *iparams));
|
||||
int elf_linux_fixup __P((int **stack_base, struct image_params *iparams));
|
||||
void linux_prepsyscall __P((struct trapframe *tf, int *args, u_int *code, caddr_t *params));
|
||||
void linux_sendsig __P((sig_t catcher, int sig, int mask, unsigned code));
|
||||
|
||||
/*
|
||||
* Linux syscalls return negative errno's, we do positive and map them
|
||||
*/
|
||||
int bsd_to_linux_errno[ELAST] = {
|
||||
-0, -1, -2, -3, -4, -5, -6, -7, -8, -9,
|
||||
-10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
|
||||
-20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
|
||||
-30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
|
||||
-90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
|
||||
-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
|
||||
-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
|
||||
-116, -66, -6, -6, -6, -6, -6, -37, -38, -9,
|
||||
-6,
|
||||
-0, -1, -2, -3, -4, -5, -6, -7, -8, -9,
|
||||
-10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
|
||||
-20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
|
||||
-30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
|
||||
-90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
|
||||
-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
|
||||
-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
|
||||
-116, -66, -6, -6, -6, -6, -6, -37, -38, -9,
|
||||
-6,
|
||||
};
|
||||
|
||||
int bsd_to_linux_signal[NSIG] = {
|
||||
0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT,
|
||||
LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0,
|
||||
LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV,
|
||||
0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM,
|
||||
LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT,
|
||||
LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO,
|
||||
LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF,
|
||||
LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2
|
||||
0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT,
|
||||
LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0,
|
||||
LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV,
|
||||
0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM,
|
||||
LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT,
|
||||
LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO,
|
||||
LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF,
|
||||
LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2
|
||||
};
|
||||
|
||||
int linux_to_bsd_signal[LINUX_NSIG] = {
|
||||
0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
|
||||
SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
|
||||
SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO,
|
||||
SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0
|
||||
0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
|
||||
SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
|
||||
SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO,
|
||||
SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0
|
||||
};
|
||||
|
||||
int linux_fixup(int **stack_base, struct image_params *imgp)
|
||||
{
|
||||
int *argv, *envp;
|
||||
int *argv, *envp;
|
||||
|
||||
argv = *stack_base;
|
||||
envp = *stack_base + (imgp->argc + 1);
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)envp;
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)argv;
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)imgp->argc;
|
||||
return 0; /* XXX */
|
||||
argv = *stack_base;
|
||||
envp = *stack_base + (imgp->argc + 1);
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)envp;
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)argv;
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)imgp->argc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
|
||||
int elf_linux_fixup(int **stack_base, struct image_params *imgp)
|
||||
{
|
||||
Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
int *pos;
|
||||
|
||||
pos = *stack_base + (imgp->argc + imgp->envc + 2);
|
||||
|
||||
if (args->trace) {
|
||||
AUXARGS_ENTRY(pos, AT_DEBUG, 1);
|
||||
}
|
||||
if (args->execfd != -1) {
|
||||
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
|
||||
}
|
||||
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
|
||||
AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
|
||||
AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
|
||||
AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
|
||||
AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
|
||||
AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
|
||||
AUXARGS_ENTRY(pos, AT_BASE, args->base);
|
||||
AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid);
|
||||
AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid);
|
||||
AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid);
|
||||
AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid);
|
||||
AUXARGS_ENTRY(pos, AT_NULL, 0);
|
||||
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
imgp->auxargs = NULL;
|
||||
|
||||
static void linux_sendsig(sig_t action,
|
||||
int sig,
|
||||
int returnmask,
|
||||
unsigned code);
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)imgp->argc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int _ucodesel, _udatasel;
|
||||
|
||||
@ -129,12 +162,8 @@ extern int _ucodesel, _udatasel;
|
||||
* specified pc, psl.
|
||||
*/
|
||||
|
||||
static void
|
||||
linux_sendsig(catcher, sig, mask, code)
|
||||
sig_t catcher;
|
||||
int sig;
|
||||
int mask;
|
||||
unsigned code;
|
||||
void
|
||||
linux_sendsig(sig_t catcher, int sig, int mask, unsigned code)
|
||||
{
|
||||
register struct proc *p = curproc;
|
||||
register int *regs;
|
||||
@ -327,7 +356,7 @@ linux_sigreturn(p, args, retval)
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
|
||||
{
|
||||
int i;
|
||||
@ -339,20 +368,33 @@ linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
|
||||
*params = NULL; /* no copyin */
|
||||
}
|
||||
|
||||
extern char linux_sigcode[];
|
||||
extern int linux_szsigcode;
|
||||
|
||||
struct sysentvec linux_sysvec = {
|
||||
sizeof (linux_sysent) / sizeof(linux_sysent[0]),
|
||||
linux_sysent,
|
||||
0xff,
|
||||
NSIG,
|
||||
bsd_to_linux_signal,
|
||||
ELAST,
|
||||
bsd_to_linux_errno,
|
||||
linux_fixup,
|
||||
linux_sendsig,
|
||||
linux_sigcode,
|
||||
&linux_szsigcode,
|
||||
linux_prepsyscall,
|
||||
LINUX_SYS_MAXSYSCALL,
|
||||
linux_sysent,
|
||||
0xff,
|
||||
NSIG,
|
||||
bsd_to_linux_signal,
|
||||
ELAST,
|
||||
bsd_to_linux_errno,
|
||||
linux_fixup,
|
||||
linux_sendsig,
|
||||
linux_sigcode,
|
||||
&linux_szsigcode,
|
||||
linux_prepsyscall,
|
||||
};
|
||||
|
||||
struct sysentvec elf_linux_sysvec = {
|
||||
LINUX_SYS_MAXSYSCALL,
|
||||
linux_sysent,
|
||||
0xff,
|
||||
NSIG,
|
||||
bsd_to_linux_signal,
|
||||
ELAST,
|
||||
bsd_to_linux_errno,
|
||||
elf_linux_fixup,
|
||||
linux_sendsig,
|
||||
linux_sigcode,
|
||||
&linux_szsigcode,
|
||||
linux_prepsyscall,
|
||||
};
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
*
|
||||
* from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp
|
||||
* from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp
|
||||
* $Id$
|
||||
* $Id: linux_util.h,v 1.1 1996/03/02 19:38:02 peter Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -78,8 +78,6 @@ stackgap_alloc(sgp, sz)
|
||||
#define DPRINTF(a)
|
||||
#endif
|
||||
|
||||
extern const char linux_emul_path[];
|
||||
|
||||
int linux_emul_find __P((struct proc *, caddr_t *, const char *, char *,
|
||||
char **, int));
|
||||
|
||||
|
@ -42,6 +42,7 @@ kdb/kdb_runpcs.c optional kadb
|
||||
kdb/kdb_sym.c optional kadb
|
||||
kdb/kdb_trap.c optional kadb
|
||||
kern/imgact_aout.c standard
|
||||
kern/imgact_elf.c standard
|
||||
kern/imgact_gzip.c optional gzip
|
||||
kern/imgact_shell.c standard
|
||||
kern/inflate.c optional gzip
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 1994-1995 Søren Schmidt
|
||||
* Copyright (c) 1994-1996 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Based heavily on /sys/kern/imgact_aout.c which is:
|
||||
@ -28,7 +28,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: imgact_linux.c,v 1.8 1996/02/16 18:40:48 peter Exp $
|
||||
* $Id: imgact_linux.c,v 1.9 1996/03/02 19:37:47 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -227,6 +227,6 @@ exec_linux_imgact(imgp)
|
||||
* Since `const' objects end up in the text segment, TEXT_SET is the
|
||||
* correct directive to use.
|
||||
*/
|
||||
const struct execsw linux_execsw = { exec_linux_imgact, "linux" };
|
||||
const struct execsw linux_execsw = { exec_linux_imgact, "linux a.out" };
|
||||
TEXT_SET(execsw_set, linux_execsw);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 1994-1995 Søren Schmidt
|
||||
* Copyright (c) 1994-1996 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,11 +25,12 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: linux.h,v 1.5 1996/03/02 19:37:47 peter Exp $
|
||||
* $Id: linux.h,v 1.6 1996/03/03 19:07:49 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _I386_LINUX_LINUX_H_
|
||||
#define _I386_LINUX_LINUX_H_
|
||||
#include "i386/linux/linux_syscall.h"
|
||||
|
||||
typedef unsigned short linux_uid_t;
|
||||
typedef unsigned short linux_gid_t;
|
||||
@ -97,13 +98,20 @@ struct linux_sigframe {
|
||||
sig_t sf_handler;
|
||||
};
|
||||
|
||||
extern int bsd_to_linux_errno[];
|
||||
extern int bsd_to_linux_signal[];
|
||||
extern int linux_to_bsd_signal[];
|
||||
extern char linux_sigcode[];
|
||||
extern int linux_szsigcode;
|
||||
extern const char linux_emul_path[];
|
||||
|
||||
extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
|
||||
extern struct sysentvec linux_sysvec;
|
||||
extern struct sysentvec elf_linux_sysvec;
|
||||
|
||||
/* dummy struct definitions */
|
||||
struct image_params;
|
||||
int linux_fixup __P((int **stack_base, struct image_params *iparams));
|
||||
struct trapframe;
|
||||
|
||||
/* misc defines */
|
||||
#define LINUX_NAME_MAX 255
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 1994-1995 Søren Schmidt
|
||||
* Copyright (c) 1994-1996 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,7 +25,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: linux_sysent.c,v 1.4 1996/01/14 10:59:57 sos Exp $
|
||||
* $Id: linux_sysvec.c,v 1.1 1996/03/02 19:38:01 peter Exp $
|
||||
*/
|
||||
|
||||
/* XXX we use functions that might not exist. */
|
||||
@ -36,7 +36,9 @@
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_prot.h>
|
||||
@ -59,62 +61,93 @@
|
||||
|
||||
#include <i386/linux/linux.h>
|
||||
#include <i386/linux/linux_proto.h>
|
||||
#include <i386/linux/linux_syscall.h>
|
||||
|
||||
int linux_fixup __P((int **stack_base, struct image_params *iparams));
|
||||
int elf_linux_fixup __P((int **stack_base, struct image_params *iparams));
|
||||
void linux_prepsyscall __P((struct trapframe *tf, int *args, u_int *code, caddr_t *params));
|
||||
void linux_sendsig __P((sig_t catcher, int sig, int mask, unsigned code));
|
||||
|
||||
/*
|
||||
* Linux syscalls return negative errno's, we do positive and map them
|
||||
*/
|
||||
int bsd_to_linux_errno[ELAST] = {
|
||||
-0, -1, -2, -3, -4, -5, -6, -7, -8, -9,
|
||||
-10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
|
||||
-20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
|
||||
-30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
|
||||
-90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
|
||||
-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
|
||||
-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
|
||||
-116, -66, -6, -6, -6, -6, -6, -37, -38, -9,
|
||||
-6,
|
||||
-0, -1, -2, -3, -4, -5, -6, -7, -8, -9,
|
||||
-10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
|
||||
-20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
|
||||
-30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
|
||||
-90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
|
||||
-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
|
||||
-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
|
||||
-116, -66, -6, -6, -6, -6, -6, -37, -38, -9,
|
||||
-6,
|
||||
};
|
||||
|
||||
int bsd_to_linux_signal[NSIG] = {
|
||||
0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT,
|
||||
LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0,
|
||||
LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV,
|
||||
0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM,
|
||||
LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT,
|
||||
LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO,
|
||||
LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF,
|
||||
LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2
|
||||
0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT,
|
||||
LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0,
|
||||
LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV,
|
||||
0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM,
|
||||
LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT,
|
||||
LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO,
|
||||
LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF,
|
||||
LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2
|
||||
};
|
||||
|
||||
int linux_to_bsd_signal[LINUX_NSIG] = {
|
||||
0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
|
||||
SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
|
||||
SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO,
|
||||
SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0
|
||||
0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
|
||||
SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
|
||||
SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO,
|
||||
SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0
|
||||
};
|
||||
|
||||
int linux_fixup(int **stack_base, struct image_params *imgp)
|
||||
{
|
||||
int *argv, *envp;
|
||||
int *argv, *envp;
|
||||
|
||||
argv = *stack_base;
|
||||
envp = *stack_base + (imgp->argc + 1);
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)envp;
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)argv;
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)imgp->argc;
|
||||
return 0; /* XXX */
|
||||
argv = *stack_base;
|
||||
envp = *stack_base + (imgp->argc + 1);
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)envp;
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)argv;
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)imgp->argc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
|
||||
int elf_linux_fixup(int **stack_base, struct image_params *imgp)
|
||||
{
|
||||
Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
int *pos;
|
||||
|
||||
pos = *stack_base + (imgp->argc + imgp->envc + 2);
|
||||
|
||||
if (args->trace) {
|
||||
AUXARGS_ENTRY(pos, AT_DEBUG, 1);
|
||||
}
|
||||
if (args->execfd != -1) {
|
||||
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
|
||||
}
|
||||
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
|
||||
AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
|
||||
AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
|
||||
AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
|
||||
AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
|
||||
AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
|
||||
AUXARGS_ENTRY(pos, AT_BASE, args->base);
|
||||
AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid);
|
||||
AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid);
|
||||
AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid);
|
||||
AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid);
|
||||
AUXARGS_ENTRY(pos, AT_NULL, 0);
|
||||
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
imgp->auxargs = NULL;
|
||||
|
||||
static void linux_sendsig(sig_t action,
|
||||
int sig,
|
||||
int returnmask,
|
||||
unsigned code);
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)imgp->argc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int _ucodesel, _udatasel;
|
||||
|
||||
@ -129,12 +162,8 @@ extern int _ucodesel, _udatasel;
|
||||
* specified pc, psl.
|
||||
*/
|
||||
|
||||
static void
|
||||
linux_sendsig(catcher, sig, mask, code)
|
||||
sig_t catcher;
|
||||
int sig;
|
||||
int mask;
|
||||
unsigned code;
|
||||
void
|
||||
linux_sendsig(sig_t catcher, int sig, int mask, unsigned code)
|
||||
{
|
||||
register struct proc *p = curproc;
|
||||
register int *regs;
|
||||
@ -327,7 +356,7 @@ linux_sigreturn(p, args, retval)
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
|
||||
{
|
||||
int i;
|
||||
@ -339,20 +368,33 @@ linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
|
||||
*params = NULL; /* no copyin */
|
||||
}
|
||||
|
||||
extern char linux_sigcode[];
|
||||
extern int linux_szsigcode;
|
||||
|
||||
struct sysentvec linux_sysvec = {
|
||||
sizeof (linux_sysent) / sizeof(linux_sysent[0]),
|
||||
linux_sysent,
|
||||
0xff,
|
||||
NSIG,
|
||||
bsd_to_linux_signal,
|
||||
ELAST,
|
||||
bsd_to_linux_errno,
|
||||
linux_fixup,
|
||||
linux_sendsig,
|
||||
linux_sigcode,
|
||||
&linux_szsigcode,
|
||||
linux_prepsyscall,
|
||||
LINUX_SYS_MAXSYSCALL,
|
||||
linux_sysent,
|
||||
0xff,
|
||||
NSIG,
|
||||
bsd_to_linux_signal,
|
||||
ELAST,
|
||||
bsd_to_linux_errno,
|
||||
linux_fixup,
|
||||
linux_sendsig,
|
||||
linux_sigcode,
|
||||
&linux_szsigcode,
|
||||
linux_prepsyscall,
|
||||
};
|
||||
|
||||
struct sysentvec elf_linux_sysvec = {
|
||||
LINUX_SYS_MAXSYSCALL,
|
||||
linux_sysent,
|
||||
0xff,
|
||||
NSIG,
|
||||
bsd_to_linux_signal,
|
||||
ELAST,
|
||||
bsd_to_linux_errno,
|
||||
elf_linux_fixup,
|
||||
linux_sendsig,
|
||||
linux_sigcode,
|
||||
&linux_szsigcode,
|
||||
linux_prepsyscall,
|
||||
};
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
*
|
||||
* from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp
|
||||
* from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp
|
||||
* $Id$
|
||||
* $Id: linux_util.h,v 1.1 1996/03/02 19:38:02 peter Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -78,8 +78,6 @@ stackgap_alloc(sgp, sz)
|
||||
#define DPRINTF(a)
|
||||
#endif
|
||||
|
||||
extern const char linux_emul_path[];
|
||||
|
||||
int linux_emul_find __P((struct proc *, caddr_t *, const char *, char *,
|
||||
char **, int));
|
||||
|
||||
|
705
sys/kern/imgact_elf.c
Normal file
705
sys/kern/imgact_elf.c
Normal file
@ -0,0 +1,705 @@
|
||||
/*-
|
||||
* Copyright (c) 1995-1996 Søren Schmidt
|
||||
* Copyright (c) 1996 Peter Wemm
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 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 withough 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/lock.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_prot.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
||||
#include <machine/md_var.h>
|
||||
#include <i386/linux/linux_syscall.h>
|
||||
#include <i386/linux/linux.h>
|
||||
|
||||
#define MAX_PHDR 32 /* XXX enough ? */
|
||||
|
||||
static int read_from_vp __P((struct vnode *vp, vm_offset_t offset, caddr_t buf, vm_size_t size));
|
||||
static int map_pages __P((struct vnode *vp, vm_offset_t offset, vm_offset_t *buf, vm_size_t size));
|
||||
static void unmap_pages __P((struct vnode *vp, vm_offset_t buf, vm_size_t size));
|
||||
static int elf_check_header __P((Elf32_Ehdr *hdr, int type));
|
||||
static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot));
|
||||
static int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry));
|
||||
static int elf_freebsd_fixup __P((int **stack_base, struct image_params *imgp));
|
||||
int exec_elf_imgact __P((struct image_params *imgp));
|
||||
|
||||
int elf_trace = 0;
|
||||
SYSCTL_INT(_debug, 1, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
|
||||
#define UPRINTF if (elf_trace) uprintf
|
||||
|
||||
static struct sysentvec elf_freebsd_sysvec = {
|
||||
SYS_MAXSYSCALL,
|
||||
sysent,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
elf_freebsd_fixup,
|
||||
sendsig,
|
||||
sigcode,
|
||||
&szsigcode,
|
||||
0,
|
||||
};
|
||||
|
||||
static Elf32_Interp_info freebsd_interp = {
|
||||
&elf_freebsd_sysvec,
|
||||
"/usr/libexec/ld-elf.so.1",
|
||||
""
|
||||
};
|
||||
static Elf32_Interp_info *interp_list[MAX_INTERP] = {
|
||||
&freebsd_interp,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
int
|
||||
elf_insert_interp(Elf32_Interp_info *entry)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1; i<MAX_INTERP; i++) {
|
||||
if (interp_list[i] == NULL) {
|
||||
interp_list[i] = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_INTERP)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
elf_remove_interp(Elf32_Interp_info *entry)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1; i<MAX_INTERP; i++) {
|
||||
if (interp_list[i] == entry) {
|
||||
interp_list[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_INTERP)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
map_pages(struct vnode *vp, vm_offset_t offset,
|
||||
vm_offset_t *buf, vm_size_t size)
|
||||
{
|
||||
int error, aresid;
|
||||
vm_offset_t kern_buf;
|
||||
vm_size_t pageoff;
|
||||
|
||||
/*
|
||||
* The request may not be aligned, and may even cross several
|
||||
* page boundaries in the file...
|
||||
*/
|
||||
pageoff = (offset & PAGE_MASK);
|
||||
offset -= pageoff; /* start of first aligned page to map */
|
||||
size += pageoff;
|
||||
size = round_page(size); /* size of aligned pages to map */
|
||||
|
||||
if (error = vm_mmap(kernel_map,
|
||||
&kern_buf,
|
||||
size,
|
||||
VM_PROT_READ,
|
||||
VM_PROT_READ,
|
||||
MAP_FILE,
|
||||
(caddr_t)vp,
|
||||
offset))
|
||||
return error;
|
||||
|
||||
*buf = kern_buf + pageoff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_pages(struct vnode *vp, vm_offset_t buf, vm_size_t size)
|
||||
{
|
||||
int error, aresid;
|
||||
vm_size_t pageoff;
|
||||
|
||||
pageoff = (buf & PAGE_MASK);
|
||||
buf -= pageoff; /* start of first aligned page to map */
|
||||
size += pageoff;
|
||||
size = round_page(size);/* size of aligned pages to map */
|
||||
|
||||
vm_map_remove(kernel_map, buf, size);
|
||||
}
|
||||
|
||||
static int
|
||||
elf_check_permissions(struct proc *p, struct vnode *vp)
|
||||
|
||||
{
|
||||
struct vattr attr;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Check number of open-for-writes on the file and deny execution
|
||||
* if there are any.
|
||||
*/
|
||||
if (vp->v_writecount) {
|
||||
return (ETXTBSY);
|
||||
}
|
||||
|
||||
/* Get file attributes */
|
||||
error = VOP_GETATTR(vp, &attr, p->p_ucred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* 1) Check if file execution is disabled for the filesystem that this
|
||||
* file resides on.
|
||||
* 2) Insure that at least one execute bit is on - otherwise root
|
||||
* will always succeed, and we don't want to happen unless the
|
||||
* file really is executable.
|
||||
* 3) Insure that the file is a regular file.
|
||||
*/
|
||||
if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
|
||||
((attr.va_mode & 0111) == 0) ||
|
||||
(attr.va_type != VREG)) {
|
||||
return (EACCES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero length files can't be exec'd
|
||||
*/
|
||||
if (attr.va_size == 0)
|
||||
return (ENOEXEC);
|
||||
|
||||
/*
|
||||
* Check for execute permission to file based on current credentials.
|
||||
* Then call filesystem specific open routine (which does nothing
|
||||
* in the general case).
|
||||
*/
|
||||
error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = VOP_OPEN(vp, FREAD, p->p_ucred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
elf_check_header(Elf32_Ehdr *hdr, int type)
|
||||
{
|
||||
if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||
hdr->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
hdr->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||
hdr->e_ident[EI_MAG3] == ELFMAG3))
|
||||
return ENOEXEC;
|
||||
|
||||
if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
|
||||
return ENOEXEC;
|
||||
|
||||
if (hdr->e_type != type)
|
||||
return ENOEXEC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
elf_load_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
|
||||
{
|
||||
size_t map_len;
|
||||
vm_offset_t map_addr;
|
||||
int error;
|
||||
unsigned char *data_buf = 0;
|
||||
size_t copy_len;
|
||||
|
||||
map_addr = trunc_page(vmaddr);
|
||||
|
||||
if (memsz > filsz)
|
||||
map_len = trunc_page(offset+filsz) - trunc_page(offset);
|
||||
else
|
||||
map_len = round_page(offset+filsz) - trunc_page(offset);
|
||||
|
||||
if (error = vm_mmap (&vmspace->vm_map,
|
||||
&map_addr,
|
||||
map_len,
|
||||
prot,
|
||||
VM_PROT_ALL,
|
||||
MAP_FILE | MAP_PRIVATE | MAP_FIXED,
|
||||
(caddr_t)vp,
|
||||
trunc_page(offset)))
|
||||
return error;
|
||||
|
||||
if (memsz == filsz)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We have to map the remaining bit of the file into the kernel's
|
||||
* memory map, allocate some anonymous memory, and copy that last
|
||||
* bit into it. The remaining space should be .bss...
|
||||
*/
|
||||
copy_len = (offset + filsz) - trunc_page(offset + filsz);
|
||||
map_addr = trunc_page(vmaddr + filsz);
|
||||
map_len = round_page(memsz) - trunc_page(filsz);
|
||||
|
||||
if (map_len != 0)
|
||||
if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
|
||||
&map_addr, map_len, FALSE,
|
||||
VM_PROT_ALL, VM_PROT_ALL,0))
|
||||
return error;
|
||||
|
||||
if (error = vm_mmap(kernel_map,
|
||||
(vm_offset_t *)&data_buf,
|
||||
PAGE_SIZE,
|
||||
VM_PROT_READ,
|
||||
VM_PROT_READ,
|
||||
MAP_FILE,
|
||||
(caddr_t)vp,
|
||||
trunc_page(offset + filsz)))
|
||||
return error;
|
||||
|
||||
error = copyout(data_buf, (caddr_t)map_addr, copy_len);
|
||||
|
||||
vm_map_remove(kernel_map, (vm_offset_t)data_buf,
|
||||
(vm_offset_t)data_buf + PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Clear the remaining page, we dont need the potential
|
||||
* garbage from the file in there.
|
||||
*/
|
||||
bzero((caddr_t)(map_addr+copy_len), map_len-copy_len);
|
||||
UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
|
||||
{
|
||||
Elf32_Ehdr *hdr = NULL;
|
||||
Elf32_Phdr *phdr = NULL;
|
||||
struct nameidata nd;
|
||||
struct vmspace *vmspace = p->p_vmspace;
|
||||
vm_prot_t prot = 0;
|
||||
unsigned long text_size = 0, data_size = 0;
|
||||
unsigned long text_addr = 0, data_addr = 0;
|
||||
int header_size = 0;
|
||||
int error, i;
|
||||
|
||||
NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
|
||||
|
||||
if (error = namei(&nd))
|
||||
goto fail;
|
||||
|
||||
if (nd.ni_vp == NULL) {
|
||||
error = ENOEXEC;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check permissions, modes, uid, etc on the file, and "open" it.
|
||||
*/
|
||||
error = elf_check_permissions(p, nd.ni_vp);
|
||||
|
||||
/*
|
||||
* No longer need this, and it prevents demand paging.
|
||||
*/
|
||||
VOP_UNLOCK(nd.ni_vp);
|
||||
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Map in the header
|
||||
*/
|
||||
if (error = map_pages(nd.ni_vp, 0, (vm_offset_t *)&hdr, sizeof(hdr)))
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Do we have a valid ELF header ?
|
||||
*/
|
||||
if (error = elf_check_header(hdr, ET_DYN))
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* ouch, need to bounds check in case user gives us a corrupted
|
||||
* file with an insane header size
|
||||
*/
|
||||
if (hdr->e_phnum > MAX_PHDR) { /* XXX: ever more than this? */
|
||||
error = ENOEXEC;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
header_size = hdr->e_phentsize * hdr->e_phnum;
|
||||
|
||||
if (error = map_pages(nd.ni_vp, hdr->e_phoff, (vm_offset_t *)&phdr,
|
||||
header_size))
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < hdr->e_phnum; i++) {
|
||||
switch(phdr[i].p_type) {
|
||||
|
||||
case PT_NULL: /* NULL section */
|
||||
UPRINTF ("ELF(file) PT_NULL section\n");
|
||||
break;
|
||||
case PT_LOAD: /* Loadable segment */
|
||||
{
|
||||
UPRINTF ("ELF(file) PT_LOAD section ");
|
||||
if (phdr[i].p_flags & PF_X)
|
||||
prot |= VM_PROT_EXECUTE;
|
||||
if (phdr[i].p_flags & PF_W)
|
||||
prot |= VM_PROT_WRITE;
|
||||
if (phdr[i].p_flags & PF_R)
|
||||
prot |= VM_PROT_READ;
|
||||
|
||||
if (error = elf_load_section(vmspace, nd.ni_vp,
|
||||
phdr[i].p_offset,
|
||||
(caddr_t)phdr[i].p_vaddr +
|
||||
(*addr),
|
||||
phdr[i].p_memsz,
|
||||
phdr[i].p_filesz, prot))
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Is this .text or .data ??
|
||||
*
|
||||
* We only handle one each of those yet XXX
|
||||
*/
|
||||
if (hdr->e_entry >= phdr[i].p_vaddr &&
|
||||
hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
|
||||
text_size = round_page(phdr[i].p_memsz);
|
||||
text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
|
||||
*entry=(unsigned long)hdr->e_entry+(*addr);
|
||||
UPRINTF(".text <%08x,%08x> entry=%08x\n",
|
||||
text_addr, text_size, *entry);
|
||||
} else {
|
||||
data_size = round_page(phdr[i].p_memsz);
|
||||
data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
|
||||
UPRINTF(".data <%08x,%08x>\n",
|
||||
data_addr, data_size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PT_DYNAMIC:/* Dynamic link information */
|
||||
UPRINTF ("ELF(file) PT_DYNAMIC section\n");
|
||||
break;
|
||||
case PT_INTERP: /* Path to interpreter */
|
||||
UPRINTF ("ELF(file) PT_INTERP section\n");
|
||||
break;
|
||||
case PT_NOTE: /* Note section */
|
||||
UPRINTF ("ELF(file) PT_NOTE section\n");
|
||||
break;
|
||||
case PT_SHLIB: /* Shared lib section */
|
||||
UPRINTF ("ELF(file) PT_SHLIB section\n");
|
||||
break;
|
||||
case PT_PHDR: /* Program header table info */
|
||||
UPRINTF ("ELF(file) PT_PHDR section\n");
|
||||
break;
|
||||
default:
|
||||
UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
if (phdr)
|
||||
unmap_pages(nd.ni_vp, (vm_offset_t)phdr, header_size);
|
||||
if (hdr)
|
||||
unmap_pages(nd.ni_vp, (vm_offset_t)hdr, sizeof(hdr));
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
exec_elf_imgact(struct image_params *imgp)
|
||||
{
|
||||
Elf32_Ehdr *hdr = (Elf32_Ehdr *) imgp->image_header;
|
||||
Elf32_Phdr *phdr, *mapped_phdr = NULL;
|
||||
Elf32_Auxargs *elf_auxargs = NULL;
|
||||
struct vmspace *vmspace = imgp->proc->p_vmspace;
|
||||
vm_prot_t prot = 0;
|
||||
u_long text_size = 0, data_size = 0;
|
||||
u_long text_addr = 0, data_addr = 0;
|
||||
u_long addr, entry = 0, proghdr = 0;
|
||||
int error, i, header_size = 0, interp_len = 0;
|
||||
char *interp = NULL;
|
||||
|
||||
/*
|
||||
* Do we have a valid ELF header ?
|
||||
*/
|
||||
if (elf_check_header(hdr, ET_EXEC))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* From here on down, we return an errno, not -1, as we've
|
||||
* detected an ELF file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ouch, need to bounds check in case user gives us a corrupted
|
||||
* file with an insane header size
|
||||
*/
|
||||
if (hdr->e_phnum > MAX_PHDR) { /* XXX: ever more than this? */
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
header_size = hdr->e_phentsize * hdr->e_phnum;
|
||||
|
||||
if ((hdr->e_phoff > PAGE_SIZE) ||
|
||||
(hdr->e_phoff + header_size) > PAGE_SIZE) {
|
||||
/*
|
||||
* Ouch ! we only get one page full of header...
|
||||
* Try to map it in ourselves, and see how we go.
|
||||
*/
|
||||
if (error = map_pages(imgp->vp, hdr->e_phoff,
|
||||
(vm_offset_t *)&mapped_phdr, header_size))
|
||||
return (error);
|
||||
/*
|
||||
* Save manual mapping for cleanup
|
||||
*/
|
||||
phdr = mapped_phdr;
|
||||
} else {
|
||||
phdr = (Elf32_Phdr*)
|
||||
((char*)(imgp->image_header)+hdr->e_phoff);
|
||||
}
|
||||
|
||||
/*
|
||||
* From this point on, we may have resources that need to be freed.
|
||||
*/
|
||||
if (error = exec_extract_strings(imgp))
|
||||
goto fail;
|
||||
|
||||
exec_new_vmspace(imgp);
|
||||
|
||||
for (i = 0; i < hdr->e_phnum; i++) {
|
||||
switch(phdr[i].p_type) {
|
||||
|
||||
case PT_NULL: /* NULL section */
|
||||
UPRINTF ("ELF PT_NULL section\n");
|
||||
break;
|
||||
case PT_LOAD: /* Loadable segment */
|
||||
{
|
||||
UPRINTF ("ELF PT_LOAD section ");
|
||||
if (phdr[i].p_flags & PF_X)
|
||||
prot |= VM_PROT_EXECUTE;
|
||||
if (phdr[i].p_flags & PF_W)
|
||||
prot |= VM_PROT_WRITE;
|
||||
if (phdr[i].p_flags & PF_R)
|
||||
prot |= VM_PROT_READ;
|
||||
|
||||
if (error = elf_load_section(vmspace, imgp->vp,
|
||||
phdr[i].p_offset,
|
||||
(caddr_t)phdr[i].p_vaddr,
|
||||
phdr[i].p_memsz,
|
||||
phdr[i].p_filesz, prot))
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Is this .text or .data ??
|
||||
*
|
||||
* We only handle one each of those yet XXX
|
||||
*/
|
||||
if (hdr->e_entry >= phdr[i].p_vaddr &&
|
||||
hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
|
||||
text_size = round_page(phdr[i].p_memsz);
|
||||
text_addr = trunc_page(phdr[i].p_vaddr);
|
||||
entry = (u_long)hdr->e_entry;
|
||||
UPRINTF(".text <%08x,%08x> entry=%08x\n",
|
||||
text_addr, text_size, entry);
|
||||
} else {
|
||||
data_size = round_page(phdr[i].p_memsz);
|
||||
data_addr = trunc_page(phdr[i].p_vaddr);
|
||||
UPRINTF(".data <%08x,%08x>\n",
|
||||
data_addr, data_size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PT_DYNAMIC:/* Dynamic link information */
|
||||
UPRINTF ("ELF PT_DYNAMIC section ??\n");
|
||||
break;
|
||||
case PT_INTERP: /* Path to interpreter */
|
||||
UPRINTF ("ELF PT_INTERP section ");
|
||||
if (phdr[i].p_filesz > MAXPATHLEN) {
|
||||
error = ENOEXEC;
|
||||
goto fail;
|
||||
}
|
||||
interp_len = MAXPATHLEN;
|
||||
if (error = map_pages(imgp->vp, phdr[i].p_offset,
|
||||
(vm_offset_t *)&interp, interp_len))
|
||||
goto fail;
|
||||
UPRINTF("<%s>\n", interp);
|
||||
break;
|
||||
case PT_NOTE: /* Note section */
|
||||
UPRINTF ("ELF PT_NOTE section\n");
|
||||
break;
|
||||
case PT_SHLIB: /* Shared lib section */
|
||||
UPRINTF ("ELF PT_SHLIB section\n");
|
||||
break;
|
||||
case PT_PHDR: /* Program header table info */
|
||||
UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
|
||||
proghdr = phdr[i].p_vaddr;
|
||||
break;
|
||||
default:
|
||||
UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
|
||||
}
|
||||
}
|
||||
|
||||
vmspace->vm_tsize = text_size >> PAGE_SHIFT;
|
||||
vmspace->vm_taddr = (caddr_t)text_addr;
|
||||
vmspace->vm_dsize = data_size >> PAGE_SHIFT;
|
||||
vmspace->vm_daddr = (caddr_t)data_addr;
|
||||
|
||||
addr = 2*MAXDSIZ; /* May depend on OS type XXX */
|
||||
|
||||
if (interp) {
|
||||
char path[MAXPATHLEN];
|
||||
/*
|
||||
* So which kind of ELF binary do we have at hand
|
||||
* FreeBSD, SVR4 or Linux ??
|
||||
*/
|
||||
for (i=0; i<MAX_INTERP; i++) {
|
||||
if (interp_list[i] != NULL) {
|
||||
if (!strcmp(interp, interp_list[i]->path)) {
|
||||
imgp->proc->p_sysent =
|
||||
interp_list[i]->sysvec;
|
||||
strcpy(path, interp_list[i]->emul_path);
|
||||
strcat(path, interp_list[i]->path);
|
||||
UPRINTF("interpreter=<%s> %s\n",
|
||||
interp_list[i]->path,
|
||||
interp_list[i]->emul_path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == MAX_INTERP) {
|
||||
uprintf("ELF interpreter %s not known\n", interp);
|
||||
error = ENOEXEC;
|
||||
goto fail;
|
||||
}
|
||||
if (error = elf_load_file(imgp->proc,
|
||||
path,
|
||||
&addr, /* XXX */
|
||||
&imgp->entry_addr)) {
|
||||
uprintf("ELF interpreter %s not found\n", path);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
imgp->entry_addr = entry;
|
||||
|
||||
/*
|
||||
* Construct auxargs table (used by the fixup routine)
|
||||
*/
|
||||
elf_auxargs = malloc(sizeof(Elf32_Auxargs), M_TEMP, M_WAITOK);
|
||||
elf_auxargs->execfd = -1;
|
||||
elf_auxargs->phdr = proghdr;
|
||||
elf_auxargs->phent = hdr->e_phentsize;
|
||||
elf_auxargs->phnum = hdr->e_phnum;
|
||||
elf_auxargs->pagesz = PAGE_SIZE;
|
||||
elf_auxargs->base = addr;
|
||||
elf_auxargs->flags = 0;
|
||||
elf_auxargs->entry = entry;
|
||||
elf_auxargs->trace = elf_trace;
|
||||
|
||||
imgp->auxargs = elf_auxargs;
|
||||
imgp->interpreted = 0;
|
||||
|
||||
/* don't allow modifying the file while we run it */
|
||||
imgp->vp->v_flag |= VTEXT;
|
||||
|
||||
fail:
|
||||
if (mapped_phdr)
|
||||
unmap_pages(imgp->vp, (vm_offset_t)mapped_phdr, header_size);
|
||||
if (interp)
|
||||
unmap_pages(imgp->vp, (vm_offset_t)interp, interp_len);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
elf_freebsd_fixup(int **stack_base, struct image_params *imgp)
|
||||
{
|
||||
Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
int *pos;
|
||||
|
||||
pos = *stack_base + (imgp->argc + imgp->envc + 2);
|
||||
|
||||
if (args->trace) {
|
||||
AUXARGS_ENTRY(pos, AT_DEBUG, 1);
|
||||
}
|
||||
if (args->execfd != -1) {
|
||||
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
|
||||
}
|
||||
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
|
||||
AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
|
||||
AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
|
||||
AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
|
||||
AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
|
||||
AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
|
||||
AUXARGS_ENTRY(pos, AT_BASE, args->base);
|
||||
AUXARGS_ENTRY(pos, AT_NULL, 0);
|
||||
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
imgp->auxargs = NULL;
|
||||
|
||||
(*stack_base)--;
|
||||
**stack_base = (int)imgp->argc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell kern_execve.c about it, with a little help from the linker.
|
||||
* Since `const' objects end up in the text segment, TEXT_SET is the
|
||||
* correct directive to use.
|
||||
*/
|
||||
const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
|
||||
TEXT_SET(execsw_set, elf_execsw);
|
||||
|
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kern_exec.c,v 1.35 1996/02/24 14:32:52 peter Exp $
|
||||
* $Id: kern_exec.c,v 1.36 1996/03/02 19:38:08 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -42,6 +42,7 @@
|
||||
#include <sys/acct.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/sysent.h>
|
||||
@ -118,6 +119,7 @@ execve(p, uap, retval)
|
||||
imgp->vmspace_destroyed = 0;
|
||||
imgp->interpreted = 0;
|
||||
imgp->interpreter_name[0] = '\0';
|
||||
imgp->auxargs = NULL;
|
||||
|
||||
/*
|
||||
* Allocate temporary demand zeroed space for argument and
|
||||
@ -475,11 +477,24 @@ exec_copyout_strings(imgp)
|
||||
((caddr_t)arginfo - szsigcode), szsigcode);
|
||||
|
||||
/*
|
||||
* The '+ 2' is for the null pointers at the end of each of the
|
||||
* arg and env vector sets
|
||||
* If we have a valid auxargs ptr, prepare some room
|
||||
* on the stack.
|
||||
*/
|
||||
vectp = (char **) (destp -
|
||||
(imgp->argc + imgp->envc + 2) * sizeof(char *));
|
||||
if (imgp->auxargs)
|
||||
/*
|
||||
* The '+ 2' is for the null pointers at the end of each of the
|
||||
* arg and env vector sets, and 'AT_COUNT*2' is room for the
|
||||
* ELF Auxargs data.
|
||||
*/
|
||||
vectp = (char **)(destp - (imgp->argc + imgp->envc + 2 +
|
||||
AT_COUNT*2) * sizeof(char*));
|
||||
else
|
||||
/*
|
||||
* The '+ 2' is for the null pointers at the end of each of the
|
||||
* arg and env vector sets
|
||||
*/
|
||||
vectp = (char **)
|
||||
(destp - (imgp->argc + imgp->envc + 2) * sizeof(char*));
|
||||
|
||||
/*
|
||||
* vectp also becomes our initial stack base
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.5 1996/01/27 23:57:06 rgrimes Exp $
|
||||
# $Id: Makefile,v 1.6 1996/03/02 20:00:35 peter Exp $
|
||||
|
||||
.PATH: ${.CURDIR}/../../sys/i386/linux
|
||||
KMOD= linux_mod
|
||||
@ -11,7 +11,7 @@ NOMAN=
|
||||
|
||||
CFLAGS+= -DLKM -I. -DCOMPAT_43 -DCOMPAT_LINUX #-DDEBUG
|
||||
CPPFLAGS= -I. -I${.CURDIR}/../../sys
|
||||
|
||||
EXPORT_SYMS=_linux_mod
|
||||
CLEANFILES+= vnode_if.h vnode_if.c linux_genassym.o linux_genassym machine \
|
||||
linux_assym.h
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: linux.c,v 1.3 1995/11/13 07:18:38 bde Exp $
|
||||
* $Id: linux.c,v 1.4 1995/11/14 07:34:18 bde Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -34,14 +34,24 @@
|
||||
#include <sys/conf.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/lkm.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include "i386/linux/linux.h"
|
||||
|
||||
extern const struct execsw linux_execsw;
|
||||
|
||||
MOD_EXEC(linux, -1, (struct execsw*)&linux_execsw);
|
||||
|
||||
static Elf32_Interp_info linux_interp = {
|
||||
&elf_linux_sysvec,
|
||||
"/lib/ld-linux.so.1",
|
||||
"/compat/linux"
|
||||
};
|
||||
|
||||
static int
|
||||
linux_load(struct lkm_table *lkmtp, int cmd)
|
||||
{
|
||||
if (elf_insert_interp(&linux_interp))
|
||||
uprintf("Could not install ELF interpreter entry\n");
|
||||
uprintf("Linux emulator installed\n");
|
||||
return 0;
|
||||
}
|
||||
@ -49,6 +59,8 @@ linux_load(struct lkm_table *lkmtp, int cmd)
|
||||
static int
|
||||
linux_unload(struct lkm_table *lkmtp, int cmd)
|
||||
{
|
||||
if (elf_remove_interp(&linux_interp))
|
||||
uprintf("Could not deinstall ELF interpreter entry\n");
|
||||
uprintf("Linux emulator removed\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: imgact.h,v 1.9 1995/05/30 08:14:24 rgrimes Exp $
|
||||
* $Id: imgact.h,v 1.10 1995/11/06 12:52:37 davidg Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_IMGACT_H_
|
||||
@ -54,6 +54,7 @@ struct image_params {
|
||||
char vmspace_destroyed; /* flag - we've blown away original vm space */
|
||||
char interpreted; /* flag - this executable is interpreted */
|
||||
char interpreter_name[64]; /* name of the interpreter */
|
||||
void *auxargs; /* ELF Auxinfo structure pointer */
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
|
213
sys/sys/imgact_elf.h
Normal file
213
sys/sys/imgact_elf.h
Normal file
@ -0,0 +1,213 @@
|
||||
/*-
|
||||
* Copyright (c) 1995-1996 Søren Schmidt
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 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 withough 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _IMGACT_ELF_H_
|
||||
#define _IMGACT_ELF_H_
|
||||
|
||||
typedef u_int32_t Elf32_Addr;
|
||||
typedef u_int32_t Elf32_Off;
|
||||
typedef int32_t Elf32_Sword;
|
||||
typedef u_int32_t Elf32_Word;
|
||||
typedef u_int16_t Elf32_Half;
|
||||
|
||||
extern int elf_trace;
|
||||
|
||||
#define EI_NINDENT 16
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NINDENT]; /* file id */
|
||||
Elf32_Half e_type; /* type */
|
||||
Elf32_Half e_machine; /* machine type */
|
||||
Elf32_Word e_version; /* version number */
|
||||
Elf32_Addr e_entry; /* entry point */
|
||||
Elf32_Off e_phoff; /* program hdr offset */
|
||||
Elf32_Off e_shoff; /* section hdr offset */
|
||||
Elf32_Word e_flags; /* flags */
|
||||
Elf32_Half e_ehsize; /* sizeof ehdr */
|
||||
Elf32_Half e_phentsize; /* program header entry size */
|
||||
Elf32_Half e_phnum; /* number of program headers */
|
||||
Elf32_Half e_shentsize; /* section header entry size */
|
||||
Elf32_Half e_shnum; /* number of section headers */
|
||||
Elf32_Half e_shstrndx; /* string table index */
|
||||
} Elf32_Ehdr;
|
||||
|
||||
/*
|
||||
* Values for e_indent entry in struct Elf32_Ehdr.
|
||||
*/
|
||||
#define EI_MAG0 0
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_VERSION 6
|
||||
|
||||
|
||||
#define ELFMAG0 '\177'
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
#define ELFCLASSNONE 0 /* invalid class */
|
||||
#define ELFCLASS32 1 /* 32bit object class */
|
||||
#define ELFCLASS64 2 /* 64bit object class */
|
||||
#define ELFDATANONE 0 /* invalid data encoding */
|
||||
#define ELFDATA2LSB 1 /* little endian */
|
||||
#define ELFDATA2MSB 2 /* big endian */
|
||||
|
||||
/*
|
||||
* Values for e_version entry in struct Elf32_Ehdr.
|
||||
*/
|
||||
#define EV_NONE 0 /* invalid version */
|
||||
#define EV_CURRENT 1 /* current version */
|
||||
|
||||
/*
|
||||
* Values for e_type entry in struct Elf32_Ehdr.
|
||||
*/
|
||||
#define ET_NONE 0
|
||||
#define ET_REL 1
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define ET_CORE 4
|
||||
#define ET_LOPROC 5
|
||||
#define ET_HIPROC 6
|
||||
|
||||
/*
|
||||
* Values for e_machine entry in struct Elf32_Ehdr.
|
||||
*/
|
||||
#define EM_NONE 0
|
||||
#define EM_M32 1
|
||||
#define EM_SPARC 2
|
||||
#define EM_386 3
|
||||
#define EM_68K 4
|
||||
#define EM_88K 5
|
||||
#define EM_486 6
|
||||
#define EM_860 7
|
||||
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word p_type; /* entry type */
|
||||
Elf32_Off p_offset; /* offset */
|
||||
Elf32_Addr p_vaddr; /* virtual address */
|
||||
Elf32_Addr p_paddr; /* physical address */
|
||||
Elf32_Word p_filesz; /* file size */
|
||||
Elf32_Word p_memsz; /* memory size */
|
||||
Elf32_Word p_flags; /* flags */
|
||||
Elf32_Word p_align; /* memory & file alignment */
|
||||
} Elf32_Phdr;
|
||||
|
||||
/*
|
||||
* Values for p_type entry in struct Elf32_Phdr.
|
||||
*/
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
#define PT_SHLIB 5
|
||||
#define PT_PHDR 6
|
||||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7fffffff
|
||||
|
||||
/*
|
||||
* Values for p_flags entry in struct Elf32_Phdr.
|
||||
*/
|
||||
#define PF_X 0x1
|
||||
#define PF_W 0x2
|
||||
#define PF_R 0x4
|
||||
#define PF_MASKPROC 0xf0000000
|
||||
|
||||
/*
|
||||
* Auxiliary vector entry on initial stack.
|
||||
*/
|
||||
typedef struct {
|
||||
Elf32_Sword a_type;
|
||||
Elf32_Word a_val;
|
||||
} Elf32_Auxinfo;
|
||||
|
||||
#define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);}
|
||||
|
||||
/*
|
||||
* Values for a_type in struct Elf32_Auxinfo.
|
||||
*/
|
||||
#define AT_NULL 0 /* Terminates the vector */
|
||||
#define AT_IGNORE 1 /* Ignored */
|
||||
#define AT_EXECFD 2 /* File descriptor of program to load */
|
||||
#define AT_PHDR 3 /* Program header of program already loaded */
|
||||
#define AT_PHENT 4 /* Size of each program header entry */
|
||||
#define AT_PHNUM 5 /* Number of program header entries */
|
||||
#define AT_PAGESZ 6 /* Page size in bytes */
|
||||
#define AT_BASE 7 /* Interpreter's base address */
|
||||
#define AT_FLAGS 8 /* Flags (unused for i386) */
|
||||
#define AT_ENTRY 9 /* Where interpreter should transfer control */
|
||||
|
||||
/*
|
||||
* The following non-standard values are used for passing information
|
||||
* to the (FreeBSD ELF) dynamic linker. Will probably go away soon....
|
||||
*/
|
||||
#define AT_BRK 10 /* Starting point for sbrk and brk */
|
||||
#define AT_DEBUG 11 /* Debugging level */
|
||||
#define AT_COUNT 15
|
||||
|
||||
/*
|
||||
* The following non-standard values are used in Linux ELF binaries.
|
||||
*/
|
||||
#define AT_NOTELF 10 /* Program is not ELF ?? */
|
||||
#define AT_UID 11 /* Real uid */
|
||||
#define AT_EUID 12 /* Effective uid */
|
||||
#define AT_GID 13 /* Real gid */
|
||||
#define AT_EGID 14 /* Effective gid */
|
||||
|
||||
/*
|
||||
* Structure used to pass infomation from the loader to the
|
||||
* stack fixup routine.
|
||||
*/
|
||||
typedef struct {
|
||||
Elf32_Sword execfd;
|
||||
Elf32_Word phdr;
|
||||
Elf32_Word phent;
|
||||
Elf32_Word phnum;
|
||||
Elf32_Word pagesz;
|
||||
Elf32_Word base;
|
||||
Elf32_Word flags;
|
||||
Elf32_Word entry;
|
||||
Elf32_Word trace;
|
||||
} Elf32_Auxargs;
|
||||
|
||||
typedef struct {
|
||||
struct sysentvec *sysvec;
|
||||
char *path;
|
||||
char *emul_path;
|
||||
} Elf32_Interp_info;
|
||||
|
||||
#define MAX_INTERP 8
|
||||
|
||||
int elf_insert_interp __P((Elf32_Interp_info *entry));
|
||||
int elf_remove_interp __P((Elf32_Interp_info *entry));
|
||||
|
||||
#endif /* _IMGACT_ELF_H_ */
|
Loading…
Reference in New Issue
Block a user