From ae4c8359aabf282d0e1047ab9b5d89cfda3e8928 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 23 Oct 2022 09:46:48 +0200 Subject: [PATCH] Darwin/AArch64: detect when SIGILL indicates an FPU exception Parse the ESR (ESR_ELx, Exception Syndrome Register (ELx)), return run error as in float_raise --- rtl/darwin/aarch64/sig_cpu.inc | 9 +++++-- rtl/darwin/aarch64/sighnd.inc | 45 +++++++++++++++++++++++++++++++--- rtl/darwin/signal.inc | 3 +++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/rtl/darwin/aarch64/sig_cpu.inc b/rtl/darwin/aarch64/sig_cpu.inc index 75d5f16476..600a9e8548 100644 --- a/rtl/darwin/aarch64/sig_cpu.inc +++ b/rtl/darwin/aarch64/sig_cpu.inc @@ -4,6 +4,11 @@ {$ENDIF} + { ESR bits (exception syndrome) values relevant to FPU exceptions } + const + __ESR_EC_Mask = cuint32($3f) shl 26; + __ESR_EC_TrappedAArch64_FloatingPoint = cuint32(%101100) shl 26; + __ESR_ISS_TFV = cuint32(1) shl 23; type __darwin_arm_exception_state64 = record @@ -19,6 +24,7 @@ __sp : cuint64; __pc : cuint64; __cpsr : cuint32; + __pad : cuint32; end; __darwin_arm_neon_state64 = record @@ -28,7 +34,7 @@ __fpcr : cuint32; { array of cuint128 is aligned/padded to multiple of 16 bytes } pad: cuint64; - end; + end {$ifdef VER_3_3}align 16{$endif}; __darwin_arm_debug_state64 = record __bvr : array[0..15] of cuint64; @@ -44,4 +50,3 @@ __ns : __darwin_arm_neon_state64; end; - diff --git a/rtl/darwin/aarch64/sighnd.inc b/rtl/darwin/aarch64/sighnd.inc index e493d5b317..4c93f0c68f 100644 --- a/rtl/darwin/aarch64/sighnd.inc +++ b/rtl/darwin/aarch64/sighnd.inc @@ -16,6 +16,7 @@ procedure SignalToRunerror(Sig: cint; info : PSigInfo; SigContext:PSigContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl; var + fpuexceptionflags: cardinal; res : word; begin res:=0; @@ -31,11 +32,51 @@ begin FPE_FLTINV : Res:=207; { invalid floating point operation } Else Res:=207; {coprocessor error} + SigContext^.uc_mcontext^.__ns.__fpsr:=SigContext^.uc_mcontext^.__ns.__fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift); end; end; SIGBUS: res:=214; - SIGILL, + SIGILL: + begin + { right now, macOS generates SIGILL signals for fpu exceptions on AArch64. + Additionally, fpsr is 0 in the context when this happens. Fortunately, + the esr is valid, so we can decode that one. } + if (Info^.si_code=ILL_ILLTRP) and + { Trapped AArch64 floating point exception } + ((SigContext^.uc_mcontext^.__es.__esr and __ESR_EC_Mask)=__ESR_EC_TrappedAArch64_FloatingPoint) then + begin + { the FPU status bits in the ESR are valid } + if (SigContext^.uc_mcontext^.__es.__esr and __ESR_ISS_TFV)<>0 then + begin + fpuexceptionflags:=(SigContext^.uc_mcontext^.__es.__esr shl fpu_exception_mask_to_status_mask_shift) and fpu_exception_mask; + if (fpuexceptionflags and fpu_dze)<>0 then + res:=208 + else if (fpuexceptionflags and fpu_ofe)<>0 then + res:=205 + else if (fpuexceptionflags and fpu_ufe)<>0 then + res:=206 + else if (fpuexceptionflags and fpu_ioe)<>0 then + res:=207 + else if (fpuexceptionflags and fpu_ixe)<>0 then + res:=207 + else if (fpuexceptionflags and fpu_ide)<>0 then + res:=216 + else + { unknown FPU exception } + res:=207 + end + else + { unknown FPU exception } + res:=207; + end + else + res:=216; + { for safety, always clear in case we had a SIGILL to prevent potential + infinite trap loops, even if it can cause us to miss some FPU + exceptions in case we process an actual illegal instruction } + SigContext^.uc_mcontext^.__ns.__fpsr:=SigContext^.uc_mcontext^.__ns.__fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift); + end; SIGSEGV : res:=216; SIGINT: @@ -43,8 +84,6 @@ begin SIGQUIT: res:=233; end; - { right now, macOS generates SIGILL signals for fpu exceptions, so always clear the fpu exceptions } - SigContext^.uc_mcontext^.__ns.__fpsr:=SigContext^.uc_mcontext^.__ns.__fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift); {$ifdef FPC_USE_SIGPROCMASK} reenable_signal(sig); {$endif } diff --git a/rtl/darwin/signal.inc b/rtl/darwin/signal.inc index 78de160c55..6d61f19ec1 100644 --- a/rtl/darwin/signal.inc +++ b/rtl/darwin/signal.inc @@ -298,3 +298,6 @@ const FPE_FLTSUB = 6; { subscript out of range -NOTIMP on Mac OS X 10.4.7 } FPE_INTDIV = 7; { integer divide by zero -NOTIMP on Mac OS X 10.4.7 } FPE_INTOVF = 8; { integer overflow -NOTIMP on Mac OS X 10.4.7 } + +{ Codes for SIGILL } + ILL_ILLTRP = 2; { /* [XSI] illegal trap */ }