o fixed darwin/i386 signal handling:

* fixed sigcontextrec definition
    * work around missing Mac OS X support for reporting integer
      division-by-zero as such (reported as generic SIGFPE)
    * return from signal handler to HandleErrorFrame (just like
      on ppc) instead of calling it (and fix up fpu and sse
      status words when doing so)

git-svn-id: trunk@9196 -
This commit is contained in:
Jonas Maebe 2007-11-11 16:27:24 +00:00
parent e385c0f7b1
commit 52a8c3a40c
2 changed files with 57 additions and 16 deletions

View File

@ -603,16 +603,26 @@
*)
tdarwin_stack_t = record
ss_sp : pchar; { signal stack base }
ss_size : clong; { signal stack length }
ss_flags : cint; { SA_DISABLE and/or SA_ONSTACK }
end;
mcontext_t = record
es: i386_exception_state_t;
ss: i386_thread_state_t;
ts: i386_thread_state_t;
fs: i386_float_state_t;
end;
psigcontext = ^sigcontextrec;
psigcontextrec = ^sigcontextrec;
sigcontextrec = record
sc_onstack: cint;
sc_mask: cint;
ts: i386_thread_state;
end;
psigcontext = ^sigcontextrec;
psigcontextrec = ^sigcontextrec;
sigcontextrec = record
uc_onstack : cint;
uc_sigmask : sigset_t; { signal mask used by this context }
uc_stack : tdarwin_stack_t; { stack used by this context }
uc_link : psigcontextrec; { pointer to resuming context }
uc_mcsize : size_t; { size of the machine context passed in }
uc_mcontext: ^mcontext_t; { machine specific context }
end;

View File

@ -16,6 +16,7 @@
procedure SignalToRunerror(Sig: cint; info : psiginfo; SigContext:PSigContext); cdecl;
var
p: pbyte;
res : word;
begin
@ -31,15 +32,35 @@ begin
FPE_FLTRES, { floating point inexact result }
FPE_FLTINV : Res:=207; { invalid floating point operation }
Else
Res:=207; { coprocessor error }
begin
{ Assume that if an integer divide was executed, the }
{ error was a divide-by-zero (FPE_INTDIV is not }
{ implemented as of 10.5.0) }
p:=pbyte(sigcontext^.uc_mcontext^.ts.eip);
if assigned(p) then
begin
{ skip some prefix bytes }
while (p^ in [$66,$67]) do
inc(p);
if (p^ in [$f6,$f7]) and
(((p+1)^ and (%110 shl 3)) = (%110 shl 3)) then
Res:=200
else
Res:=207; { coprocessor error }
end
else
Res:=207;
end;
end;
{ the following is true on ppc, but fortunately not on x86 }
{ FPU exceptions are completely disabled by the kernel if one occurred, it }
{ seems this is necessary to be able to return to user mode. They can be }
{ enabled by executing a sigreturn, however then the exception is triggered }
{ triggered again immediately if we don't turn off the "exception occurred" }
{ flags in fpscr }
{ make sure any fpu operations won't trigger new exceptions in handler }
sysResetFPU;
{ Now clear exception flags in the context }
{ perform an fnclex: clear exception and busy flags }
sigcontext^.uc_mcontext^.fs.fpu_fsw.flag0:=
sigcontext^.uc_mcontext^.fs.fpu_fsw.flag0 and (not(%11111111) and not(1 shl 15));
{ also clear sse exception flags }
sigcontext^.uc_mcontext^.fs.fpu_mxcsr:=
sigcontext^.uc_mcontext^.fs.fpu_mxcsr and not(%111111)
end;
SIGILL,
SIGBUS,
@ -51,6 +72,16 @@ begin
{$endif }
if (res <> 0) then
HandleErrorAddrFrame(res,pointer(sigcontext^.ts.eip),pointer(sigcontext^.ts.ebp));
begin
{ assume regcall calling convention is the default }
sigcontext^.uc_mcontext^.ts.eax:=res;
sigcontext^.uc_mcontext^.ts.edx:=sigcontext^.uc_mcontext^.ts.eip;
sigcontext^.uc_mcontext^.ts.ecx:=sigcontext^.uc_mcontext^.ts.ebp;
{ the ABI expects the stack pointer to be 4 bytes off alignment }
{ due to the return address which has been pushed }
dec(sigcontext^.uc_mcontext^.ts.esp,sizeof(pointer));
{ return to run time error handler }
sigcontext^.uc_mcontext^.ts.eip:=ptruint(@HandleErrorAddrFrame);
end;
end;