4 * Copyright 1998 Ove Kåven
7 #if defined(linux) && defined(__i386__)
9 /* apparently ELF images are usually loaded high anyway */
11 /* if not, force dosmod at high addresses */
26 #include <sys/types.h>
27 #include <sys/ptrace.h>
31 /* FIXME: hack because libc vm86 may be the old syscall version */
35 static __inline__
int vm86plus( int func
, struct vm86plus_struct
*ptr
)
39 __asm__
__volatile__( "pushl %%ebx\n\t"
48 __asm__
__volatile__("int $0x80"
54 if (res
>= 0) return res
;
59 void set_timer(struct timeval
*tim
)
65 setitimer(ITIMER_REAL
,&cur
,NULL
);
68 volatile int sig_pend
,sig_fatal
=0;
70 struct vm86plus_struct VM86
;
72 void sig_handler(int sig
)
74 if (sig_pend
) fprintf(stderr
,"DOSMOD previous signal %d lost\n",sig_pend
);
76 signal(sig
,sig_handler
);
79 void bad_handler(int sig
)
81 fprintf(stderr
,"DOSMOD caught fatal signal %d\n",sig
);
82 fprintf(stderr
,"(Last known VM86 CS:IP was %04x:%04lx)\n",VM86
.regs
.cs
,VM86
.regs
.eip
);
83 sig_pend
=sig
; sig_fatal
++;
84 signal(sig
,bad_handler
);
87 int main(int argc
,char**argv
)
89 int mfd
=open(argv
[0],O_RDWR
);
95 /* fprintf(stderr,"main is at %08lx, file is %s, fd=%d\n",(unsigned long)&main,argv[0],mfd); */
97 /* Map in our DOS image at the start of the process address space */
99 /* Ulrich Weigand suggested mapping in the DOS image directly from the Wine
102 /* linux currently only allows mapping a process memory if it's being ptraced */
103 /* Linus doesn't like it, so this probably won't work in the future */
104 /* it doesn't even work for me right now */
106 ptrace(PTRACE_ATTACH
,ppid
,0,0);
107 waitpid(ppid
,NULL
,0);
109 img
=mmap(NULL
,0x110000,PROT_EXEC
|PROT_READ
|PROT_WRITE
,MAP_FIXED
|MAP_SHARED
,mfd
,fofs
);
111 ptrace(PTRACE_DETACH
,ppid
,0,0);
114 if (img
==(void*)-1) {
115 fprintf(stderr
,"DOS memory map failed, error=%s\n",strerror(errno
));
116 fprintf(stderr
,"in attempt to map %s, offset %08lX, length 110000, to offset 0\n",argv
[0],fofs
);
119 /* initialize signals and system timer */
120 signal(SIGHUP
,sig_handler
);
121 signal(SIGINT
,sig_handler
);
122 signal(SIGUSR1
,sig_handler
);
123 signal(SIGUSR2
,sig_handler
);
124 signal(SIGALRM
,sig_handler
);
126 signal(SIGQUIT
,bad_handler
);
127 signal(SIGILL
,bad_handler
);
128 signal(SIGBUS
,bad_handler
);
129 signal(SIGFPE
,bad_handler
);
130 signal(SIGSEGV
,bad_handler
);
131 signal(SIGTERM
,bad_handler
);
133 tim
.tv_sec
=0; tim
.tv_usec
=54925;
136 /* report back to the main program that we're ready */
137 ret
=1; /* dosmod protocol revision 1 */
138 write(1,&ret
,sizeof(ret
));
139 /* context exchange loop */
141 if (read(0,&func
,sizeof(func
))!=sizeof(func
)) return 1;
144 case DOSMOD_SET_TIMER
:
145 if (read(0,&tim
,sizeof(tim
))!=sizeof(tim
)) return 1;
151 if (read(0,&VM86
,sizeof(VM86
))!=sizeof(VM86
)) return 1;
152 if (sig_pend
) ret
=DOSMOD_SIGNAL
; else
153 ret
=vm86plus(func
,&VM86
);
154 if (write(1,&ret
,sizeof(ret
))!=sizeof(ret
)) return 1;
155 if (write(1,&VM86
,sizeof(VM86
))!=sizeof(VM86
)) return 1;
158 ret
=sig_pend
; sig_pend
=0;
159 if (write(1,&ret
,sizeof(ret
))!=sizeof(ret
)) return 1;
160 if (sig_fatal
) return 1;
168 #else /* !linux-i386 */
169 int main(void) {return 1;}