2
0
Fork 0

Added the 990210 version of David Bruce's x286emul.

This commit is contained in:
jaggy 1999-09-27 20:48:10 +00:00
parent 44aac9640f
commit b0149fd074
9 changed files with 147 additions and 69 deletions

View file

@ -1,5 +1,8 @@
Mon Sep 23 20:18:31 BST 1999
* Added the 990210 version of David Bruce's x286emul.
-- Mike
* Changes for 2.3.x compatibility.
-- Mike

View file

@ -6,7 +6,7 @@ BINTYPE=i486-linuxaout
#CPPFLAGS= -I../include -DNEW_SYSCALL -DDEBUG -DDEBUG_LDT -DDEBUG_CALL -DDEBUG_STACK
CPPFLAGS= -I../include -DNEW_SYSCALL -DDEBUG
CPPFLAGS= -I../include -DNEW_SYSCALL -DDEBUG -DDEBUG_LDT
#CFLAGS= -g -O -Wall -Wstrict-prototypes
CFLAGS= -O2 -fomit-frame-pointer -m486 -Wall -Wstrict-prototypes
#LDFLAGS= -Bstatic
@ -19,7 +19,8 @@ OBJS= x286emul.o ldt.o syscall.o \
emu_signal.o emu_odd.o
ifneq ($(BINTYPE),)
CC := /usr/$(BINTYPE)/bin/gcc -pipe -b $(BINTYPE)
#CC := /usr/$(BINTYPE)/bin/gcc -pipe -b $(BINTYPE)
CC := gcc -pipe -b $(BINTYPE)
LD := /usr/$(BINTYPE)/bin/ld -m i386linux
endif
@ -29,13 +30,13 @@ GCCLIB= `$(CC) --print-libgcc-file-name`
all: message x286emul
message:
@echo
@echo " "
@echo "====================================================="
@echo "x286emul is only used for Xenix 286 programs"
@echo "You probably need not worry if this fails to compile."
@echo "Just use the -i option to make if there is a problem."
@echo "====================================================="
@echo
@echo " "
install: all
cp x286emul /usr/lib/x286emul

View file

@ -80,18 +80,24 @@ ___x286syscall:
.align 4
.globl _lcall7
_lcall7:
popl %edx
popl %eax
pushl %edx
movl %eax,%ebx
movl 24(%esp),%eax
pushl %eax /* param 4 */
movl 24(%esp),%eax
pushl %eax /* param 3 */
movl 24(%esp),%eax
pushl %eax /* param 2 */
movl 24(%esp),%eax
pushl %eax /* param 1 */
movl 24(%esp),%eax
pushl %eax /* param op */
.byte 0x9a,0,0,0,0,7,0 /* lcall $7,0 */
jnc L1
movl %eax,_errno
movl $-1,%eax
L1:
popl %ecx
pushl %ebx
pushl %ecx
addl $20,%esp
popl %edx
ret
@ -105,21 +111,23 @@ _x286boot:
#endif
mov %ds,%ax /* ensure %fs == %ds */
mov %ax,%fs
subl %eax,%eax
movl %eax,%ebx
movl %eax,%ecx
movl %eax,%edx
movl %eax,%ebp
movl %eax,%esi
movl %eax,%edi
push %eax
subl %ecx,%ecx
movl %ecx,%ebp
movl %ecx,%esi
movl %ecx,%edi
push %ecx
popfl
movl 4(%esp),%edx
movl 8(%esp),%ebx
lss _init_stk,%esp
lss _init_stk,%esp /* Swap Stack */
movl %esp,%ebp
movl _init_ds,%eax
mov %ax,%ds
mov %ax,%ds /* Set up brk value in ax etc. */
mov %ax,%es
movl %edx,%eax
movl %ebx,%edx
fs/ljmp _init_entry

View file

@ -2,6 +2,7 @@
#include <signal.h>
#include <linux/unistd.h>
#include <unistd.h>
#include <stdlib.h>
#include <ibcs/xout.h>
@ -82,6 +83,7 @@ emu_brk(struct sigcontext_struct *sc)
return 0;
}
/*
* NOTE!
* "limit" is the maximum ofset in a segment
@ -113,11 +115,24 @@ emu_brkctl(struct sigcontext_struct *sc)
}
/*
* Note!
* If we are in DEBUG mode the process of opening the
* Debug file and writing debug info will cause "malloc"
* to be called and memory to me allocated for "malloc"
* just after the last segment of the program.
* We must allow for this posible memory hole
*/
int
int_brkctl(struct sigcontext_struct *sc, int cmd, int incr, int seg)
{
struct modify_ldt_ldt_s ldt_info;
int t_last;
static int orig_last_desc = 0;
if(orig_last_desc == 0)
orig_last_desc = last_desc;
t_last = last_desc;
@ -136,38 +151,21 @@ int_brkctl(struct sigcontext_struct *sc, int cmd, int incr, int seg)
seg = last_desc;
if (incr >= 0) {
if ((cmd == BR_ARGSEG || cmd == BR_IMPSEG) && (unsigned long)(ldt[seg].limit + incr) > ldt[seg].rlimit) {
if(seg == last_desc && (ldt[seg].limit + incr) <= 0xffff && seg != base_desc) {
/*
* Extend the last seg to 64K because it is not a full 64K
* use free mem if available
*/
if(((unsigned long)sbrk(0) - ldt[seg].base) < 0x10000)
sbrk(0x10000 - ((unsigned long)sbrk(0) - ldt[seg].base));
ldt[seg].rlimit = 0xffff;
} else {
if(cmd == BR_ARGSEG)
return -1;
}
if (cmd == BR_ARGSEG && (unsigned long)(ldt[seg].limit + incr) > ldt[seg].rlimit) {
return -1;
}
if (cmd == BR_NEWSEG || (cmd == BR_IMPSEG && (ldt[seg].limit + incr) > ldt[seg].rlimit)) {
if (!LDATA && last_desc == base_desc && cmd == BR_IMPSEG)
return -1;
seg = ++last_desc;
/*
* Use any free memory we have.
* ie memory passed the rlimit of the last
* segment
*/
if(seg-1 == base_desc)
ldt[seg].base = ldt[seg-1].base + 0x10000;
else
ldt[seg].base = ldt[seg-1].base + ldt[seg-1].rlimit + 1;
if (!LDATA && last_desc == base_desc && cmd == BR_IMPSEG) {
return -1;
}
seg = last_desc = last_desc + 1;
if((ldt[seg].base = (unsigned long) malloc(0x10000)) == (unsigned long) NULL) {
last_desc--;
return -1;
}
ldt[seg].limit = -1;
ldt[seg].rlimit = 0xffff;
if(((unsigned long)sbrk(0) - ldt[seg].base) < 0x10000)
sbrk(0x10000 - ((unsigned long)sbrk(0) - ldt[seg].base));
sc->ebx = (seg << 3) | 7;
sc->eax = 0;
@ -223,6 +221,8 @@ int_brkctl(struct sigcontext_struct *sc, int cmd, int incr, int seg)
* Now get rid of any segments > last_desc
*/
while((t_last > last_desc) && (t_last > base_desc)){
if(t_last > orig_last_desc)
free((void *)ldt[t_last].base);
ldt_info.entry_number = t_last;
ldt_info.read_exec_only = 1;
ldt_info.contents = 0;

View file

@ -1,7 +1,7 @@
/*
* emu_odd.c -- Odd syscall's and fixes.
*
* Copyright (C) 1998 Hulcote Electronics (Europe) Ltd.
* Copyright (C) 1998-1999 Hulcote Electronics (Europe) Ltd.
* David Bruce (David@Hulcote.com)
*
* This program is free software; you can redistribute it and/or modify
@ -218,11 +218,6 @@ unsigned short path, path_seg, buf, buf_seg;
buf_seg = sc->ds ;
}
result = verify_area(VERIFY_READ, path_seg, path, 1);
if(result) {
errno = result;
return -1;
}
result = verify_area(VERIFY_WRITE, buf_seg, buf, SIZE_STAT);
if(result) {
errno = result;
@ -246,9 +241,9 @@ int
emu_i_ftime(struct sigcontext_struct *sc)
{
unsigned short *stkladdr;
unsigned short tp, tp_seg;
int result;
struct xnx_timeb td;
unsigned short tp, tp_seg;
if(LDATA){ /* Large Data */
stkladdr = (unsigned short *)(ldt[sc->ss >> 3].base + (sc->ebx & 0xffff));
@ -266,7 +261,9 @@ unsigned short tp, tp_seg;
}
result = lcall7(sc->eax & 0xffff, &td );
memcpy((void *)(tp + ldt[tp_seg >>3].base), (void *)&td, SIZE_TIMEB);
if(result >= 0)
memcpy((void *)(ldt[tp_seg >> 3].base + tp), (void *)&td, SIZE_TIMEB);
return result;
}
@ -371,3 +368,63 @@ int fd1,fd2;
return dup(fd1);
}
}
/*
* ulimit() system call
*
*/
int
emu_i_ulimit(struct sigcontext_struct *sc)
{
unsigned short *stkladdr = 0;
int cmd,arg = 0;
#define MEMLIM (0xdfffff) /* tell them they can have 14 megs of data */
if(LDATA){ /* Large Data */
stkladdr = (unsigned short *)(ldt[sc->ss >> 3].base + (sc->ebx & 0xffff));
cmd = stkladdr[0];
} else {
cmd = sc->ebx & 0xffff;
}
switch(cmd) {
case 2: /* set file limit */
if(LDATA){ /* Large Data */
arg = (long)stkladdr[1] | ((long)stkladdr[2] << 16);
} else {
arg = (sc->ecx & 0xffff) | (sc->esi << 16);
}
case 1: /* get file limit */
case 4: /* max files */
return lcall7(sc->eax & 0xffff, cmd, arg);
case 3:
if(LDATA){ /* Large Data */
arg = lcall7(sc->eax & 0xffff, cmd, arg);
if(arg > MEMLIM)
arg = MEMLIM;
return arg;
} else {
return ldt[last_desc].rlimit;
}
case 64: /* get text offset */
if(LTEXT){
if(LDATA)
return (long)stkladdr[1] + ldt[stkladdr[2] >> 3].base -
ldt[init_cs >> 3].base;
return (sc->ecx & 0xffff) + ldt[(sc->esi &0xffff) >> 3].base -
ldt[init_cs >> 3].base;
} else {
if(LDATA)
return (long)stkladdr[1];
return sc->ecx & 0xffff;
}
default:
errno = EINVAL;
return -1;
}
}

View file

@ -55,7 +55,6 @@
#include "x286emul.h"
#include "emu_signal.h"
#include "ldt.h"
#include "lcall7.h"
#ifdef DEBUG
# include "debug.h"

View file

@ -56,11 +56,11 @@ static syscall_t unix_syscall[] = { /* T == tried */
{ NAME("brk/break") emu_brk ,R_SHORT }, /* 17 */
{ NAME("stat") emu_i_stat ,R_SHORT }, /* 18 T */
{ NAME("seek/lseek") emu_i_sls ,R_LONG }, /* 19 T */
{ NAME("getpid") emu_i_s ,R_SHORT }, /* 20 T */
{ NAME("getpid") emu_i_pipe ,R_LONG }, /* 20 T */
{ NAME("mount") (syscall_func_t)0 ,R_SHORT }, /* 21 */
{ NAME("umount") (syscall_func_t)0 ,R_SHORT }, /* 22 */
{ NAME("setuid") emu_i_s ,R_SHORT }, /* 23 T */
{ NAME("getuid") emu_i_s ,R_SHORT }, /* 24 T */
{ NAME("getuid") emu_i_pipe ,R_LONG }, /* 24 T */
{ NAME("stime") (syscall_func_t)0 ,R_SHORT }, /* 25 */
{ NAME("ptrace") (syscall_func_t)0 ,R_SHORT }, /* 26 */
{ NAME("alarm") emu_i_s ,R_SHORT }, /* 27 T */
@ -83,7 +83,7 @@ static syscall_t unix_syscall[] = { /* T == tried */
{ NAME("prof") (syscall_func_t)0 ,R_VOID }, /* 44 */
{ NAME("lock/plock") (syscall_func_t)0 ,R_SHORT }, /* 45 */
{ NAME("setgid") emu_i_s ,R_SHORT }, /* 46 T */
{ NAME("getgid") emu_i_s ,R_SHORT }, /* 47 T */
{ NAME("getgid") emu_i_pipe ,R_LONG }, /* 47 T */
{ NAME("signal") emu_i_signal ,R_SPECIAL }, /* 48 T */
{ NAME("msgsys") (syscall_func_t)0 ,R_SHORT }, /* 49 */
{ NAME("sysi86/sys3b") (syscall_func_t)0 ,R_SHORT }, /* 50 */
@ -99,7 +99,7 @@ static syscall_t unix_syscall[] = { /* T == tried */
{ NAME("umask") emu_i_s ,R_SHORT }, /* 60 */
{ NAME("chroot") emu_i_a ,R_SHORT }, /* 61 */
{ NAME("fcntl/clocal") emu_i_fcntl ,R_SHORT }, /* 62 T */
{ NAME("ulimit/cxenix") emu_i_sls ,R_LONG }, /* 63 */
{ NAME("ulimit/cxenix") emu_i_ulimit ,R_LONG }, /* 63 */
{ NAME("?") (syscall_func_t)0 ,R_SHORT }, /* 64 */
{ NAME("?") (syscall_func_t)0 ,R_SHORT }, /* 65 */
{ NAME("?") (syscall_func_t)0 ,R_SHORT }, /* 66 */
@ -194,7 +194,7 @@ static syscall_t xenix_syscall[] = {
{ NAME("stkgro") emu_stkgro ,R_SHORT }, /* 8 T */
{ NAME("xptrace") (syscall_func_t)0 ,R_SHORT }, /* 9 */
{ NAME("chsize") emu_i_sls ,R_SHORT }, /* 10 */
{ NAME("ftime") emu_i_ftime ,R_VOID }, /* 11 T */
{ NAME("ftime") emu_i_ftime ,R_SHORT }, /* 11 T */
{ NAME("nap") emu_i_l ,R_LONG }, /* 12 */
{ NAME("sdget") (syscall_func_t)0 ,R_POINTER }, /* 13 */
{ NAME("sdfree") (syscall_func_t)0 ,R_SHORT }, /* 14 */
@ -335,10 +335,12 @@ x286syscall(struct sigcontext_struct *sc)
ret_type = unix_syscall[call_no].ret_type;
}
}
if (ret_type == R_VOID || ret_type == R_SPECIAL){
if(ret_type == R_VOID)
error = 0;
if(ret_type == R_VOID){
sc->eax = 0;
sc->eflags &= (~1);
}
} else {
if (error < 0) {
sc->eax = errno;
@ -357,7 +359,8 @@ x286syscall(struct sigcontext_struct *sc)
}
}
sc->edx = sc->ebx;
#ifdef DEBUG
if (__dbf){
if (error < 0)

View file

@ -29,6 +29,7 @@ extern int emu_i_stat(struct sigcontext_struct *sc);
extern int emu_i_ftime(struct sigcontext_struct *sc);
extern int emu_i_ioctl(struct sigcontext_struct *sc);
extern int emu_i_dup(struct sigcontext_struct *sc);
extern int emu_i_ulimit(struct sigcontext_struct *sc);
/* From emu_signal.c */
#include "emu_signal.h"

View file

@ -129,10 +129,14 @@ sig_segv(int nr, struct sigcontext_struct sc)
{
unsigned char *laddr;
unsigned short *stkladdr;
static int sig_segv_count = 0;
#ifndef NEW_SYSCALL
prog_sc = &sc; /* SHOULD BE FIRST INSTRUCTION!!!!! */
#endif
if(sig_segv_count++ > 4)
exit(1);
#ifdef DEBUG_STACK
if (__dbf) {
@ -181,6 +185,7 @@ sig_segv(int nr, struct sigcontext_struct sc)
* interrupted.
*/
stkladdr[-1] = (unsigned short)(sc.eflags & 0xffff);
sig_segv_count = 0;
return;
}
#endif
@ -198,6 +203,7 @@ sig_segv(int nr, struct sigcontext_struct sc)
#endif
if ((laddr[1] >= 0xf0) && (laddr[1] <= 0xfa)){
fpfixup(laddr);
sig_segv_count = 0;
return;
}
}
@ -375,7 +381,7 @@ set_frame(unsigned long base, unsigned long offset, char *argv[], char *envp[])
int
main(int argc, char *argv[], char *envp[])
{
int x286boot(void);
int x286boot(unsigned long, unsigned long);
unsigned long ds_base;
#ifdef DEBUG
@ -383,8 +389,8 @@ main(int argc, char *argv[], char *envp[])
char *p;
char p1[256];
if ((p = getenv("X286DEBUG"))){ /* Open debug file and get file des out of the way */
snprintf(p1,255,p,getpid()); /* of nasty programs */
if ((p = getenv("X286DEBUG")) && (getuid() == geteuid())){ /* Open debug file and get file des out */
snprintf(p1,255,p,getpid()); /* of the way of nasty programs */
fd = open(p1,O_CREAT | O_APPEND | O_WRONLY, 0644);
if(fd > 0){
fd1 = dup2(fd,0x3f);
@ -449,5 +455,5 @@ main(int argc, char *argv[], char *envp[])
trap_signal(SIGSEGV, (__sighandler_t)sig_segv, SA_NOMASK);
return x286boot();
return x286boot((unsigned long)ldt[last_desc].limit,(unsigned long)(last_desc << 3) | 7);
}