1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
{
This file is part of the Free Pascal run time library.
(c) 2000-2003 by Marco van de Voort
member of the Free Pascal development team.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
Signalhandler for FreeBSD/i386
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY;without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
procedure SignalToRunerror(Sig: cint; info : psiginfo; SigContext:PSigContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl;
var
p: pbyte;
res : word;
begin
res:=0;
case sig of
SIGFPE :
begin
Case Info^.si_code Of
FPE_INTDIV, { integer divide by zero -NOTIMP on Mac OS X 10.4.7 }
FPE_FLTDIV : Res:=200; { floating point divide by zero }
FPE_FLTOVF : Res:=205; { floating point overflow }
FPE_FLTUND : Res:=206; { floating point underflow }
FPE_FLTRES, { floating point inexact result }
FPE_FLTINV : Res:=207; { invalid floating point operation }
Else
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) }
{$ifdef cpu64}
p:=pbyte(sigcontext^.uc_mcontext^.ts.rip);
{$else cpu64}
p:=pbyte(sigcontext^.uc_mcontext^.ts.eip);
{$endif cpu64}
{ skip some prefix bytes }
while (p^ in [{$ifdef cpu64}$40..$4f,{$endif}$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;
end;
{ 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,
SIGSEGV :
res:=216;
SIGINT:
res:=217;
SIGQUIT:
res:=233;
end;
{$ifdef FPC_USE_SIGPROCMASK}
reenable_signal(sig);
{$endif }
if (res <> 0) then
begin
{$ifdef cpu64}
sigcontext^.uc_mcontext^.ts.rdi:=res;
sigcontext^.uc_mcontext^.ts.rsi:=sigcontext^.uc_mcontext^.ts.rip;
sigcontext^.uc_mcontext^.ts.rdx:=sigcontext^.uc_mcontext^.ts.rbp;
{ 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.rsp,sizeof(pointer));
{ return to run time error handler }
sigcontext^.uc_mcontext^.ts.rip:=ptruint(@HandleErrorAddrFrame);
{$else cpu64}
{ 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 8 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);
{$endif cpu64}
end;
end;
|