9 #include <linux/sched.h>
10 #include <asm/system.h>
12 extern void ___sig_restore();
13 extern void ___masksig_restore();
15 /* Similar to the sigaction function in libc, except it leaves alone the
19 wine_sigaction(int sig
,struct sigaction
* new, struct sigaction
* old
)
21 __asm__("int $0x80":"=a" (sig
)
22 :"0" (SYS_sigaction
),"b" (sig
),"c" (new),"d" (old
));
30 struct sigaction segv_act
;
32 struct sigcontext_struct
{
33 unsigned short gs
, __gsh
;
34 unsigned short fs
, __fsh
;
35 unsigned short es
, __esh
;
36 unsigned short ds
, __dsh
;
48 unsigned short cs
, __csh
;
50 unsigned long esp_at_signal
;
51 unsigned short ss
, __ssh
;
53 unsigned long oldmask
;
58 GetTimeDate(int time_flag
, struct sigcontext_struct
* context
)
64 now
= localtime(<ime
);
67 context
->ecx
= (now
->tm_hour
<< 8) | now
->tm_min
;
68 context
->edx
= now
->tm_sec
<< 8;
72 context
->ecx
= now
->tm_year
+ 1900;
73 context
->edx
= ((now
->tm_mon
+ 1) << 8) | now
->tm_mday
;
74 context
->eax
&= 0xff00;
75 context
->eax
|= now
->tm_wday
;
79 /* We handle all int21 calls here. There is some duplicate code from
80 misc/dos.c that I am unsure how to deal with, since the locations
81 that we store the registers are all different */
84 do_int21(struct sigcontext_struct
* context
){
85 fprintf(stderr
,"Doing int21 %x ", (context
->eax
>> 8) & 0xff);
86 switch((context
->eax
>> 8) & 0xff){
88 context
->eax
= 0x0303; /* Hey folks, this is DOS V3.3! */
93 /* Ignore any attempt to set a segment vector */
97 case 0x35: /* Return a NULL segment selector - this will bomb
98 if anyone ever tries to use it */
104 GetTimeDate(0, context
);
105 /* Function does not return */
108 GetTimeDate(1, context
);
109 /* Function does not return */
112 exit(context
->eax
& 0xff);
116 fprintf(stderr
,"Unable to handle int 0x21 %x\n", context
->eax
);
123 do_int1A(struct sigcontext_struct
* context
){
127 switch((context
->eax
>> 8) & 0xff){
130 ticks
= (int) (ltime
* HZ
);
131 context
->ecx
= ticks
>> 16;
132 context
->edx
= ticks
& 0x0000FFFF;
133 context
->eax
= 0; /* No midnight rollover */
137 fprintf(stderr
,"Unable to handle int 0x1A %x\n", context
->eax
);
143 static void win_segfault(int signal
, struct sigcontext_struct context
){
144 unsigned char * instr
;
149 /* First take care of a few preliminaries */
150 if(signal
!= SIGSEGV
) exit(1);
151 if((context
.cs
& 7) != 7){
153 "Segmentation fault in Wine program (%x:%x)."
155 context
.cs
, context
.eip
);
159 /* Now take a look at the actual instruction where the program
161 instr
= (char *) ((context
.cs
<< 16) | (context
.eip
& 0xffff));
165 "Unexpected Windows program segfault"
166 " - opcode = %x\n", *instr
);
178 if(!do_int21(&context
)) goto oops
;
181 if(!do_int1A(&context
)) goto oops
;
184 fprintf(stderr
,"Unexpected Windows interrupt %x\n", intno
);
188 /* OK, done handling the interrupt */
190 context
.eip
+= 2; /* Bypass the int instruction */
194 fprintf(stderr
,"In win_segfault %x:%x\n", context
.cs
, context
.eip
);
195 fprintf(stderr
,"Stack: %x:%x\n", context
.ss
, context
.esp_at_signal
);
196 dump
= (int*) &context
;
199 fprintf(stderr
," %8.8x", *dump
++);
201 fprintf(stderr
,"\n");
203 fprintf(stderr
,"\n");
209 segv_act
.sa_handler
= (__sighandler_t
) win_segfault
;
210 /* Point to the top of the stack, minus 4 just in case, and make
212 segv_act
.sa_restorer
=
213 (void (*)()) (((unsigned int)(cstack
+ sizeof(cstack
) - 4)) & ~3);
214 wine_sigaction(SIGSEGV
, &segv_act
, NULL
);