mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 11:09:42 +02:00
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:
parent
e385c0f7b1
commit
52a8c3a40c
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user