Added the 990210 version of David Bruce's x286emul.
This commit is contained in:
parent
44aac9640f
commit
b0149fd074
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
#include "x286emul.h"
|
||||
#include "emu_signal.h"
|
||||
#include "ldt.h"
|
||||
#include "lcall7.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
# include "debug.h"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 = ≻ /* 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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue