sighnd.inc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt,
  4. member of the Free Pascal development team.
  5. Signal handler is arch dependant due to processor to language
  6. exception conversion.
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. { $define SYSTEM_DEBUG}
  14. { use a trampoline which pushes the return address for proper unwinding }
  15. Procedure SignalToHandleErrorAddrFrame (Errno : longint;addr : CodePointer; frame : Pointer); nostackframe; assembler;
  16. asm
  17. pushq addr
  18. jmp HandleErrorAddrFrame
  19. end;
  20. const
  21. FPU_All = $7f;
  22. function GetFPUState(const SigContext : TSigContext) : word;
  23. begin
  24. if assigned(SigContext.fpstate) then
  25. GetfpuState:=SigContext.fpstate^.swd
  26. else
  27. GetFPUState:=0;
  28. {$ifdef SYSTEM_DEBUG}
  29. if assigned(SigContext.fpstate) then
  30. writeln('Tag: ',sigcontext.fpstate^.twd,' Cw: ',sigcontext.fpstate^.cwd);
  31. Writeln(stderr,'FpuState = ',result);
  32. {$endif SYSTEM_DEBUG}
  33. end;
  34. function GetMMState(const SigContext : TSigContext) : dword;
  35. begin
  36. if assigned(SigContext.fpstate) then
  37. Result:=SigContext.fpstate^.mxcsr
  38. else
  39. Result:=0;
  40. {$ifdef SYSTEM_DEBUG}
  41. Writeln(stderr,'MMState = ',result);
  42. {$endif SYSTEM_DEBUG}
  43. end;
  44. procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl;
  45. var
  46. res,fpustate,MMState : word;
  47. begin
  48. res:=0;
  49. case sig of
  50. SIGFPE :
  51. begin
  52. { this is not allways necessary but I don't know yet
  53. how to tell if it is or not PM }
  54. res:=200;
  55. if SigInfo^.si_code<>FPE_INTDIV then
  56. begin
  57. fpustate:=GetFPUState(SigContext^);
  58. if (FpuState and FPU_All) <> 0 then
  59. begin
  60. { first check the more precise options }
  61. if (FpuState and FPU_DivisionByZero)<>0 then
  62. res:=208
  63. else if (FpuState and FPU_Overflow)<>0 then
  64. res:=205
  65. else if (FpuState and FPU_Underflow)<>0 then
  66. res:=206
  67. else if (FpuState and FPU_Denormal)<>0 then
  68. res:=206
  69. else if (FpuState and (FPU_StackOverflow or FPU_StackUnderflow or FPU_Invalid))<>0 Then
  70. res:=207
  71. else
  72. res:=207; {'Coprocessor Error'}
  73. end
  74. else
  75. begin
  76. MMState:=getMMState(SigContext^);
  77. if (MMState and MM_ExceptionMask)<>0 then
  78. begin
  79. { first check the more precise options }
  80. if (MMState and MM_DivisionByZero)<>0 then
  81. res:=208
  82. else if (MMState and MM_Invalid)<>0 Then
  83. res:=207
  84. else if (MMState and MM_Overflow)<>0 then
  85. res:=205
  86. else if (MMState and MM_Underflow)<>0 then
  87. res:=206
  88. else if (MMState and MM_Denormal)<>0 then
  89. res:=206
  90. else
  91. res:=207; {'Coprocessor Error'}
  92. end;
  93. end;
  94. if assigned(SigContext^.fpstate) then
  95. with SigContext^.fpstate^ do
  96. begin
  97. {$ifdef SYSTEM_DEBUG}
  98. Writeln(stderr,'fpstate^.swd = ',swd);
  99. {$endif SYSTEM_DEBUG}
  100. { actually, I am not sure if we should really touch the controll word }
  101. cwd:=Default8087CW;
  102. { found by trial and error that setting to 0 means empty }
  103. twd:=$0;
  104. { clear top }
  105. swd:=swd and not($3700);
  106. { exceptions are handled, clear all flags
  107. as we return from SignalToRunerrer, we have to clear the exception flags in the context }
  108. mxcsr:=mxcsr and not(MM_ExceptionMask);
  109. swd:=swd and not($37ff);
  110. end;
  111. end;
  112. end;
  113. SIGILL,
  114. SIGBUS,
  115. SIGSEGV:
  116. res:=216;
  117. SIGINT:
  118. res:=217;
  119. SIGQUIT:
  120. res:=233;
  121. end;
  122. reenable_signal(sig);
  123. if res<>0 then
  124. begin
  125. SigContext^.rdi := res;
  126. SigContext^.rsi := SigContext^.rip;
  127. SigContext^.rdx := SigContext^.rbp;
  128. SigContext^.rip := ptruint(@SignalToHandleErrorAddrFrame);
  129. end;
  130. end;