mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 01:29:19 +02:00
* system exception handling cleaned up
* fixed setjmp for win64 git-svn-id: trunk@3228 -
This commit is contained in:
parent
c8bd730bd7
commit
dff1eef6e6
@ -20,10 +20,6 @@ interface
|
|||||||
{$define SYSTEMEXCEPTIONDEBUG}
|
{$define SYSTEMEXCEPTIONDEBUG}
|
||||||
{$endif SYSTEMDEBUG}
|
{$endif SYSTEMDEBUG}
|
||||||
|
|
||||||
{$ifdef cpui386}
|
|
||||||
{$define Set_i386_Exception_handler}
|
|
||||||
{$endif cpui386}
|
|
||||||
|
|
||||||
{ include system-independent routine headers }
|
{ include system-independent routine headers }
|
||||||
{$I systemh.inc}
|
{$I systemh.inc}
|
||||||
|
|
||||||
@ -589,8 +585,6 @@ function is_prefetch(p : pointer) : boolean;
|
|||||||
// Hardware exception handling
|
// Hardware exception handling
|
||||||
//
|
//
|
||||||
|
|
||||||
{$ifdef Set_i386_Exception_handler}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Error code definitions for the Win32 API functions
|
Error code definitions for the Win32 API functions
|
||||||
|
|
||||||
@ -690,74 +684,93 @@ type
|
|||||||
Cr0NpxState : Cardinal;
|
Cr0NpxState : Cardinal;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PContext = ^TContext;
|
M128A = record
|
||||||
TContext = packed record
|
Low : QWord;
|
||||||
//
|
High : Int64;
|
||||||
// The flags values within this flag control the contents of
|
|
||||||
// a CONTEXT record.
|
|
||||||
//
|
|
||||||
ContextFlags : Cardinal;
|
|
||||||
|
|
||||||
//
|
|
||||||
// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
|
|
||||||
// set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
|
|
||||||
// included in CONTEXT_FULL.
|
|
||||||
//
|
|
||||||
Dr0, Dr1, Dr2,
|
|
||||||
Dr3, Dr6, Dr7 : Cardinal;
|
|
||||||
|
|
||||||
//
|
|
||||||
// This section is specified/returned if the
|
|
||||||
// ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
|
|
||||||
//
|
|
||||||
FloatSave : TFloatingSaveArea;
|
|
||||||
|
|
||||||
//
|
|
||||||
// This section is specified/returned if the
|
|
||||||
// ContextFlags word contains the flag CONTEXT_SEGMENTS.
|
|
||||||
//
|
|
||||||
SegGs, SegFs,
|
|
||||||
SegEs, SegDs : Cardinal;
|
|
||||||
|
|
||||||
//
|
|
||||||
// This section is specified/returned if the
|
|
||||||
// ContextFlags word contains the flag CONTEXT_INTEGER.
|
|
||||||
//
|
|
||||||
Edi, Esi, Ebx,
|
|
||||||
Edx, Ecx, Eax : Cardinal;
|
|
||||||
|
|
||||||
//
|
|
||||||
// This section is specified/returned if the
|
|
||||||
// ContextFlags word contains the flag CONTEXT_CONTROL.
|
|
||||||
//
|
|
||||||
Ebp : Cardinal;
|
|
||||||
Eip : Cardinal;
|
|
||||||
SegCs : Cardinal;
|
|
||||||
EFlags, Esp, SegSs : Cardinal;
|
|
||||||
|
|
||||||
//
|
|
||||||
// This section is specified/returned if the ContextFlags word
|
|
||||||
// contains the flag CONTEXT_EXTENDED_REGISTERS.
|
|
||||||
// The format and contexts are processor specific
|
|
||||||
//
|
|
||||||
ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
PContext = ^TContext;
|
||||||
|
TContext = record
|
||||||
|
P1Home : QWord;
|
||||||
|
P2Home : QWord;
|
||||||
|
P3Home : QWord;
|
||||||
|
P4Home : QWord;
|
||||||
|
P5Home : QWord;
|
||||||
|
P6Home : QWord;
|
||||||
|
ContextFlags : DWord;
|
||||||
|
MxCsr : DWord;
|
||||||
|
SegCs : word;
|
||||||
|
SegDs : word;
|
||||||
|
SegEs : word;
|
||||||
|
SegFs : word;
|
||||||
|
SegGs : word;
|
||||||
|
SegSs : word;
|
||||||
|
EFlags : DWord;
|
||||||
|
Dr0 : QWord;
|
||||||
|
Dr1 : QWord;
|
||||||
|
Dr2 : QWord;
|
||||||
|
Dr3 : QWord;
|
||||||
|
Dr6 : QWord;
|
||||||
|
Dr7 : QWord;
|
||||||
|
Rax : QWord;
|
||||||
|
Rcx : QWord;
|
||||||
|
Rdx : QWord;
|
||||||
|
Rbx : QWord;
|
||||||
|
Rsp : QWord;
|
||||||
|
Rbp : QWord;
|
||||||
|
Rsi : QWord;
|
||||||
|
Rdi : QWord;
|
||||||
|
R8 : QWord;
|
||||||
|
R9 : QWord;
|
||||||
|
R10 : QWord;
|
||||||
|
R11 : QWord;
|
||||||
|
R12 : QWord;
|
||||||
|
R13 : QWord;
|
||||||
|
R14 : QWord;
|
||||||
|
R15 : QWord;
|
||||||
|
Rip : QWord;
|
||||||
|
Header : array[0..1] of M128A;
|
||||||
|
Legacy : array[0..7] of M128A;
|
||||||
|
Xmm0 : M128A;
|
||||||
|
Xmm1 : M128A;
|
||||||
|
Xmm2 : M128A;
|
||||||
|
Xmm3 : M128A;
|
||||||
|
Xmm4 : M128A;
|
||||||
|
Xmm5 : M128A;
|
||||||
|
Xmm6 : M128A;
|
||||||
|
Xmm7 : M128A;
|
||||||
|
Xmm8 : M128A;
|
||||||
|
Xmm9 : M128A;
|
||||||
|
Xmm10 : M128A;
|
||||||
|
Xmm11 : M128A;
|
||||||
|
Xmm12 : M128A;
|
||||||
|
Xmm13 : M128A;
|
||||||
|
Xmm14 : M128A;
|
||||||
|
Xmm15 : M128A;
|
||||||
|
VectorRegister : array[0..25] of M128A;
|
||||||
|
VectorControl : QWord;
|
||||||
|
DebugControl : QWord;
|
||||||
|
LastBranchToRip : QWord;
|
||||||
|
LastBranchFromRip : QWord;
|
||||||
|
LastExceptionToRip : QWord;
|
||||||
|
LastExceptionFromRip : QWord;
|
||||||
|
end;
|
||||||
|
|
||||||
type
|
type
|
||||||
PExceptionRecord = ^TExceptionRecord;
|
PExceptionRecord = ^TExceptionRecord;
|
||||||
TExceptionRecord = packed record
|
TExceptionRecord = packed record
|
||||||
ExceptionCode : Longint;
|
ExceptionCode : Longint;
|
||||||
ExceptionFlags : Longint;
|
ExceptionFlags : Longint;
|
||||||
ExceptionRecord : PExceptionRecord;
|
ExceptionRecord : PExceptionRecord;
|
||||||
ExceptionAddress : Pointer;
|
ExceptionAddress : Pointer;
|
||||||
NumberParameters : Longint;
|
NumberParameters : Longint;
|
||||||
ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
|
ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PExceptionPointers = ^TExceptionPointers;
|
PExceptionPointers = ^TExceptionPointers;
|
||||||
TExceptionPointers = packed record
|
TExceptionPointers = packed record
|
||||||
ExceptionRecord : PExceptionRecord;
|
ExceptionRecord : PExceptionRecord;
|
||||||
ContextRecord : PContext;
|
ContextRecord : PContext;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ type of functions that should be used for exception handling }
|
{ type of functions that should be used for exception handling }
|
||||||
@ -771,7 +784,7 @@ const
|
|||||||
exceptLevel : Byte = 0;
|
exceptLevel : Byte = 0;
|
||||||
|
|
||||||
var
|
var
|
||||||
exceptEip : array[0..MaxExceptionLevel-1] of Longint;
|
exceptRip : array[0..MaxExceptionLevel-1] of Int64;
|
||||||
exceptError : array[0..MaxExceptionLevel-1] of Byte;
|
exceptError : array[0..MaxExceptionLevel-1] of Byte;
|
||||||
resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
|
resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
|
||||||
|
|
||||||
@ -789,208 +802,177 @@ end;
|
|||||||
{$endif SYSTEMEXCEPTIONDEBUG}
|
{$endif SYSTEMEXCEPTIONDEBUG}
|
||||||
|
|
||||||
procedure JumpToHandleErrorFrame;
|
procedure JumpToHandleErrorFrame;
|
||||||
var
|
var
|
||||||
eip, ebp, error : Longint;
|
rip, rbp, error : int64;
|
||||||
begin
|
begin
|
||||||
// save ebp
|
// save ebp
|
||||||
asm
|
asm
|
||||||
movl (%ebp),%eax
|
movq (%rbp),%rax
|
||||||
movl %eax,ebp
|
movq %rax,rbp
|
||||||
end;
|
|
||||||
if (exceptLevel > 0) then
|
|
||||||
dec(exceptLevel);
|
|
||||||
|
|
||||||
eip:=exceptEip[exceptLevel];
|
|
||||||
error:=exceptError[exceptLevel];
|
|
||||||
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
|
||||||
if IsConsole then
|
|
||||||
writeln(stderr,'In JumpToHandleErrorFrame error=',error);
|
|
||||||
{$endif SYSTEMEXCEPTIONDEBUG}
|
|
||||||
if resetFPU[exceptLevel] then asm
|
|
||||||
fninit
|
|
||||||
fldcw fpucw
|
|
||||||
end;
|
|
||||||
{ build a fake stack }
|
|
||||||
asm
|
|
||||||
{$ifdef REGCALL}
|
|
||||||
movl ebp,%ecx
|
|
||||||
movl eip,%edx
|
|
||||||
movl error,%eax
|
|
||||||
pushl eip
|
|
||||||
movl ebp,%ebp // Change frame pointer
|
|
||||||
{$else}
|
|
||||||
movl ebp,%eax
|
|
||||||
pushl %eax
|
|
||||||
movl eip,%eax
|
|
||||||
pushl %eax
|
|
||||||
movl error,%eax
|
|
||||||
pushl %eax
|
|
||||||
movl eip,%eax
|
|
||||||
pushl %eax
|
|
||||||
movl ebp,%ebp // Change frame pointer
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
|
||||||
jmpl DebugHandleErrorAddrFrame
|
|
||||||
{$else not SYSTEMEXCEPTIONDEBUG}
|
|
||||||
jmpl HandleErrorAddrFrame
|
|
||||||
{$endif SYSTEMEXCEPTIONDEBUG}
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
{ this variable is set to true, if currently an sse check is executed and no sig ill should be generated }
|
|
||||||
sse_check : boolean;
|
|
||||||
|
|
||||||
function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
|
|
||||||
var
|
|
||||||
res: longint;
|
|
||||||
err: byte;
|
|
||||||
must_reset_fpu: boolean;
|
|
||||||
begin
|
|
||||||
res := EXCEPTION_CONTINUE_SEARCH;
|
|
||||||
if excep^.ContextRecord^.SegSs=_SS then begin
|
|
||||||
err := 0;
|
|
||||||
must_reset_fpu := true;
|
|
||||||
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
|
||||||
if IsConsole then Writeln(stderr,'Exception ',
|
|
||||||
hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
|
|
||||||
{$endif SYSTEMEXCEPTIONDEBUG}
|
|
||||||
case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
|
|
||||||
STATUS_INTEGER_DIVIDE_BY_ZERO,
|
|
||||||
STATUS_FLOAT_DIVIDE_BY_ZERO :
|
|
||||||
err := 200;
|
|
||||||
STATUS_ARRAY_BOUNDS_EXCEEDED :
|
|
||||||
begin
|
|
||||||
err := 201;
|
|
||||||
must_reset_fpu := false;
|
|
||||||
end;
|
|
||||||
STATUS_STACK_OVERFLOW :
|
|
||||||
begin
|
|
||||||
err := 202;
|
|
||||||
must_reset_fpu := false;
|
|
||||||
end;
|
|
||||||
STATUS_FLOAT_OVERFLOW :
|
|
||||||
err := 205;
|
|
||||||
STATUS_FLOAT_DENORMAL_OPERAND,
|
|
||||||
STATUS_FLOAT_UNDERFLOW :
|
|
||||||
err := 206;
|
|
||||||
{excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
|
|
||||||
STATUS_FLOAT_INEXACT_RESULT,
|
|
||||||
STATUS_FLOAT_INVALID_OPERATION,
|
|
||||||
STATUS_FLOAT_STACK_CHECK :
|
|
||||||
err := 207;
|
|
||||||
STATUS_INTEGER_OVERFLOW :
|
|
||||||
begin
|
|
||||||
err := 215;
|
|
||||||
must_reset_fpu := false;
|
|
||||||
end;
|
|
||||||
STATUS_ILLEGAL_INSTRUCTION:
|
|
||||||
{ if we're testing sse support, simply set the flag and continue }
|
|
||||||
if sse_check then
|
|
||||||
begin
|
|
||||||
os_supports_sse:=false;
|
|
||||||
{ if yes, then retry }
|
|
||||||
excep^.ExceptionRecord^.ExceptionCode := 0;
|
|
||||||
res:=EXCEPTION_CONTINUE_EXECUTION;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
err := 216;
|
|
||||||
STATUS_ACCESS_VIOLATION:
|
|
||||||
{ Athlon prefetch bug? }
|
|
||||||
if is_prefetch(pointer(excep^.ContextRecord^.Eip)) then
|
|
||||||
begin
|
|
||||||
{ if yes, then retry }
|
|
||||||
excep^.ExceptionRecord^.ExceptionCode := 0;
|
|
||||||
res:=EXCEPTION_CONTINUE_EXECUTION;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
err := 216;
|
|
||||||
|
|
||||||
STATUS_CONTROL_C_EXIT:
|
|
||||||
err := 217;
|
|
||||||
STATUS_PRIVILEGED_INSTRUCTION:
|
|
||||||
begin
|
|
||||||
err := 218;
|
|
||||||
must_reset_fpu := false;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
|
|
||||||
err := 217
|
|
||||||
else
|
|
||||||
err := 255;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
if exceptLevel>0 then
|
||||||
|
dec(exceptLevel);
|
||||||
|
|
||||||
if (err <> 0) and (exceptLevel < MaxExceptionLevel) then begin
|
rip:=exceptRip[exceptLevel];
|
||||||
exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
|
error:=exceptError[exceptLevel];
|
||||||
exceptError[exceptLevel] := err;
|
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
||||||
resetFPU[exceptLevel] := must_reset_fpu;
|
if IsConsole then
|
||||||
inc(exceptLevel);
|
writeln(stderr,'In JumpToHandleErrorFrame error=',error);
|
||||||
|
{$endif SYSTEMEXCEPTIONDEBUG}
|
||||||
excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
|
if resetFPU[exceptLevel] then
|
||||||
excep^.ExceptionRecord^.ExceptionCode := 0;
|
asm
|
||||||
|
fninit
|
||||||
res := EXCEPTION_CONTINUE_EXECUTION;
|
fldcw fpucw
|
||||||
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
|
||||||
if IsConsole then begin
|
|
||||||
writeln(stderr,'Exception Continue Exception set at ',
|
|
||||||
hexstr(exceptEip[exceptLevel],8));
|
|
||||||
writeln(stderr,'Eip changed to ',
|
|
||||||
hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
|
|
||||||
end;
|
end;
|
||||||
{$endif SYSTEMEXCEPTIONDEBUG}
|
{ build a fake stack }
|
||||||
|
asm
|
||||||
|
movq rbp,%r8
|
||||||
|
movq rip,%rdx
|
||||||
|
movq error,%rcx
|
||||||
|
pushq rip
|
||||||
|
movq rbp,%rbp // Change frame pointer
|
||||||
|
|
||||||
|
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
||||||
|
jmpl DebugHandleErrorAddrFrame
|
||||||
|
{$else not SYSTEMEXCEPTIONDEBUG}
|
||||||
|
jmpl HandleErrorAddrFrame
|
||||||
|
{$endif SYSTEMEXCEPTIONDEBUG}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
syswin32_i386_exception_handler := res;
|
|
||||||
end;
|
|
||||||
|
function syswin64_x86_64_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
|
||||||
|
var
|
||||||
|
res: longint;
|
||||||
|
err: byte;
|
||||||
|
must_reset_fpu: boolean;
|
||||||
|
begin
|
||||||
|
res := EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
if excep^.ContextRecord^.SegSs=_SS then
|
||||||
|
begin
|
||||||
|
err := 0;
|
||||||
|
must_reset_fpu := true;
|
||||||
|
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
||||||
|
if IsConsole then Writeln(stderr,'Exception ',
|
||||||
|
hexstr(excep^.ExceptionRecord^.ExceptionCode,8));
|
||||||
|
{$endif SYSTEMEXCEPTIONDEBUG}
|
||||||
|
case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
|
||||||
|
STATUS_INTEGER_DIVIDE_BY_ZERO,
|
||||||
|
STATUS_FLOAT_DIVIDE_BY_ZERO :
|
||||||
|
err := 200;
|
||||||
|
STATUS_ARRAY_BOUNDS_EXCEEDED :
|
||||||
|
begin
|
||||||
|
err := 201;
|
||||||
|
must_reset_fpu := false;
|
||||||
|
end;
|
||||||
|
STATUS_STACK_OVERFLOW :
|
||||||
|
begin
|
||||||
|
err := 202;
|
||||||
|
must_reset_fpu := false;
|
||||||
|
end;
|
||||||
|
STATUS_FLOAT_OVERFLOW :
|
||||||
|
err := 205;
|
||||||
|
STATUS_FLOAT_DENORMAL_OPERAND,
|
||||||
|
STATUS_FLOAT_UNDERFLOW :
|
||||||
|
err := 206;
|
||||||
|
{ excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
|
||||||
|
STATUS_FLOAT_INEXACT_RESULT,
|
||||||
|
STATUS_FLOAT_INVALID_OPERATION,
|
||||||
|
STATUS_FLOAT_STACK_CHECK :
|
||||||
|
err := 207;
|
||||||
|
STATUS_INTEGER_OVERFLOW :
|
||||||
|
begin
|
||||||
|
err := 215;
|
||||||
|
must_reset_fpu := false;
|
||||||
|
end;
|
||||||
|
STATUS_ILLEGAL_INSTRUCTION:
|
||||||
|
err := 216;
|
||||||
|
STATUS_ACCESS_VIOLATION:
|
||||||
|
{ Athlon prefetch bug? }
|
||||||
|
if is_prefetch(pointer(excep^.ContextRecord^.rip)) then
|
||||||
|
begin
|
||||||
|
{ if yes, then retry }
|
||||||
|
excep^.ExceptionRecord^.ExceptionCode := 0;
|
||||||
|
res:=EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
err := 216;
|
||||||
|
|
||||||
|
STATUS_CONTROL_C_EXIT:
|
||||||
|
err := 217;
|
||||||
|
STATUS_PRIVILEGED_INSTRUCTION:
|
||||||
|
begin
|
||||||
|
err := 218;
|
||||||
|
must_reset_fpu := false;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
|
||||||
|
err := 217
|
||||||
|
else
|
||||||
|
err := 255;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (err <> 0) and (exceptLevel < MaxExceptionLevel) then
|
||||||
|
begin
|
||||||
|
exceptRip[exceptLevel] := excep^.ContextRecord^.Rip;
|
||||||
|
exceptError[exceptLevel] := err;
|
||||||
|
resetFPU[exceptLevel] := must_reset_fpu;
|
||||||
|
inc(exceptLevel);
|
||||||
|
|
||||||
|
excep^.ContextRecord^.Rip := Int64(@JumpToHandleErrorFrame);
|
||||||
|
excep^.ExceptionRecord^.ExceptionCode := 0;
|
||||||
|
|
||||||
|
res := EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
||||||
|
if IsConsole then begin
|
||||||
|
writeln(stderr,'Exception Continue Exception set at ',
|
||||||
|
hexstr(exceptEip[exceptLevel],8));
|
||||||
|
writeln(stderr,'Eip changed to ',
|
||||||
|
hexstr(int64(@JumpToHandleErrorFrame),16), ' error=', error);
|
||||||
|
end;
|
||||||
|
{$endif SYSTEMEXCEPTIONDEBUG}
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
syswin64_x86_64_exception_handler := res;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure install_exception_handlers;
|
procedure install_exception_handlers;
|
||||||
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
||||||
var
|
var
|
||||||
oldexceptaddr,
|
oldexceptaddr,
|
||||||
newexceptaddr : Longint;
|
newexceptaddr : Longint;
|
||||||
{$endif SYSTEMEXCEPTIONDEBUG}
|
{$endif SYSTEMEXCEPTIONDEBUG}
|
||||||
|
|
||||||
begin
|
begin
|
||||||
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
||||||
asm
|
asm
|
||||||
movl $0,%eax
|
movl $0,%eax
|
||||||
movl %fs:(%eax),%eax
|
movl %fs:(%eax),%eax
|
||||||
movl %eax,oldexceptaddr
|
movl %eax,oldexceptaddr
|
||||||
end;
|
end;
|
||||||
{$endif SYSTEMEXCEPTIONDEBUG}
|
{$endif SYSTEMEXCEPTIONDEBUG}
|
||||||
SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
|
SetUnhandledExceptionFilter(@syswin64_x86_64_exception_handler);
|
||||||
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
{$ifdef SYSTEMEXCEPTIONDEBUG}
|
||||||
asm
|
asm
|
||||||
movl $0,%eax
|
movl $0,%eax
|
||||||
movl %fs:(%eax),%eax
|
movl %fs:(%eax),%eax
|
||||||
movl %eax,newexceptaddr
|
movl %eax,newexceptaddr
|
||||||
end;
|
end;
|
||||||
if IsConsole then
|
if IsConsole then
|
||||||
writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
|
writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
|
||||||
' new exception ',hexstr(newexceptaddr,8));
|
' new exception ',hexstr(newexceptaddr,8));
|
||||||
{$endif SYSTEMEXCEPTIONDEBUG}
|
{$endif SYSTEMEXCEPTIONDEBUG}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure remove_exception_handlers;
|
procedure remove_exception_handlers;
|
||||||
begin
|
begin
|
||||||
SetUnhandledExceptionFilter(nil);
|
SetUnhandledExceptionFilter(nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$else not cpui386 (Processor specific !!)}
|
|
||||||
procedure install_exception_handlers;
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure remove_exception_handlers;
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
|
|
||||||
{$endif Set_i386_Exception_handler}
|
|
||||||
|
|
||||||
{ because of the brain dead sse detection on x86, this test is post poned }
|
|
||||||
procedure fpc_cpucodeinit;
|
procedure fpc_cpucodeinit;
|
||||||
begin
|
begin
|
||||||
end;
|
end;
|
||||||
|
@ -16,6 +16,22 @@
|
|||||||
|
|
||||||
function setjmp(var S : jmp_buf) : longint;assembler;[Public, alias : 'FPC_SETJMP'];nostackframe;
|
function setjmp(var S : jmp_buf) : longint;assembler;[Public, alias : 'FPC_SETJMP'];nostackframe;
|
||||||
asm
|
asm
|
||||||
|
{$ifdef win64}
|
||||||
|
// Save registers.
|
||||||
|
movq %rbx,(%rcx)
|
||||||
|
movq %rbp,8(%rcx)
|
||||||
|
movq %r12,16(%rcx)
|
||||||
|
movq %r13,24(%rcx)
|
||||||
|
movq %r14,32(%rcx)
|
||||||
|
movq %r15,40(%rcx)
|
||||||
|
movq %rsi,64(%rcx)
|
||||||
|
movq %rdi,72(%rcx)
|
||||||
|
leaq 8(%rsp),%rdx // Save SP as it will be after we return.
|
||||||
|
movq %rdx,48(%rcx)
|
||||||
|
movq 0(%rsp),%r8 // Save PC we are returning to now.
|
||||||
|
movq %r8,56(%rcx)
|
||||||
|
xorq %rax,%rax
|
||||||
|
{$else win64}
|
||||||
// Save registers.
|
// Save registers.
|
||||||
movq %rbx,(%rdi)
|
movq %rbx,(%rdi)
|
||||||
movq %rbp,8(%rdi)
|
movq %rbp,8(%rdi)
|
||||||
@ -28,11 +44,31 @@ function setjmp(var S : jmp_buf) : longint;assembler;[Public, alias : 'FPC_SETJM
|
|||||||
movq 0(%rsp),%rsi // Save PC we are returning to now.
|
movq 0(%rsp),%rsi // Save PC we are returning to now.
|
||||||
movq %rsi,56(%rdi)
|
movq %rsi,56(%rdi)
|
||||||
xorq %rax,%rax
|
xorq %rax,%rax
|
||||||
|
{$endif win64}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure longjmp(var S : jmp_buf;value : longint);assembler;[Public, alias : 'FPC_LONGJMP'];
|
procedure longjmp(var S : jmp_buf;value : longint);assembler;[Public, alias : 'FPC_LONGJMP'];
|
||||||
asm
|
asm
|
||||||
|
{$ifdef win64}
|
||||||
|
// Restore registers.
|
||||||
|
movq (%rcx),%rbx
|
||||||
|
movq 8(%rcx),%rbp
|
||||||
|
movq 16(%rcx),%r12
|
||||||
|
movq 24(%rcx),%r13
|
||||||
|
movq 32(%rcx),%r14
|
||||||
|
movq 40(%rcx),%r15
|
||||||
|
// Set return value for setjmp.
|
||||||
|
test %edx,%edx
|
||||||
|
mov $01,%eax
|
||||||
|
cmove %eax,%edx
|
||||||
|
mov %edx,%eax
|
||||||
|
movq 48(%rcx),%rsp
|
||||||
|
movq 56(%rcx),%rdx
|
||||||
|
movq 64(%rcx),%rsi
|
||||||
|
movq 72(%rcx),%rdi
|
||||||
|
jmpq *%rdx
|
||||||
|
{$else win64}
|
||||||
// Restore registers.
|
// Restore registers.
|
||||||
movq (%rdi),%rbx
|
movq (%rdi),%rbx
|
||||||
movq 8(%rdi),%rbp
|
movq 8(%rdi),%rbp
|
||||||
@ -48,5 +84,6 @@ procedure longjmp(var S : jmp_buf;value : longint);assembler;[Public, alias : 'F
|
|||||||
movq 56(%rdi),%rdx
|
movq 56(%rdi),%rdx
|
||||||
movq 48(%rdi),%rsp
|
movq 48(%rdi),%rsp
|
||||||
jmpq *%rdx
|
jmpq *%rdx
|
||||||
|
{$endif win64}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
type
|
type
|
||||||
jmp_buf = packed record
|
jmp_buf = packed record
|
||||||
rbx,rbp,r12,r13,r14,r15,rsp,rip : qword;
|
rbx,rbp,r12,r13,r14,r15,rsp,rip : qword;
|
||||||
|
{$ifdef win64}
|
||||||
|
rsi,rdi : qword;
|
||||||
|
{$endif win64}
|
||||||
end;
|
end;
|
||||||
pjmp_buf = ^jmp_buf;
|
pjmp_buf = ^jmp_buf;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user