signals.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. unit signals;
  2. interface
  3. { Signals }
  4. const
  5. SIGABRT = 288;
  6. SIGFPE = 289;
  7. SIGILL = 290;
  8. SIGSEGV = 291;
  9. SIGTERM = 292;
  10. SIGALRM = 293;
  11. SIGHUP = 294;
  12. SIGINT = 295;
  13. SIGKILL = 296;
  14. SIGPIPE = 297;
  15. SIGQUIT = 298;
  16. SIGUSR1 = 299;
  17. SIGUSR2 = 300;
  18. SIGNOFP = 301;
  19. SIGTRAP = 302;
  20. SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
  21. SIGPROF = 304;
  22. SIGMAX = 320;
  23. SIG_BLOCK = 1;
  24. SIG_SETMASK = 2;
  25. SIG_UNBLOCK = 3;
  26. function SIG_DFL( x: longint) : longint;
  27. function SIG_ERR( x: longint) : longint;
  28. function SIG_IGN( x: longint) : longint;
  29. type
  30. SignalHandler = function (v : longint) : longint;
  31. PSignalHandler = ^SignalHandler; { to be compatible with linux.pp }
  32. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  33. const
  34. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  35. type
  36. FLOATING_SAVE_AREA = record
  37. ControlWord : DWORD;
  38. StatusWord : DWORD;
  39. TagWord : DWORD;
  40. ErrorOffset : DWORD;
  41. ErrorSelector : DWORD;
  42. DataOffset : DWORD;
  43. DataSelector : DWORD;
  44. RegisterArea : array[0..79] of BYTE;
  45. Cr0NpxState : DWORD;
  46. end;
  47. _FLOATING_SAVE_AREA = FLOATING_SAVE_AREA;
  48. TFLOATINGSAVEAREA = FLOATING_SAVE_AREA;
  49. PFLOATINGSAVEAREA = ^FLOATING_SAVE_AREA;
  50. CONTEXT = record
  51. ContextFlags : DWORD;
  52. Dr0 : DWORD;
  53. Dr1 : DWORD;
  54. Dr2 : DWORD;
  55. Dr3 : DWORD;
  56. Dr6 : DWORD;
  57. Dr7 : DWORD;
  58. FloatSave : FLOATING_SAVE_AREA;
  59. SegGs : DWORD;
  60. SegFs : DWORD;
  61. SegEs : DWORD;
  62. SegDs : DWORD;
  63. Edi : DWORD;
  64. Esi : DWORD;
  65. Ebx : DWORD;
  66. Edx : DWORD;
  67. Ecx : DWORD;
  68. Eax : DWORD;
  69. Ebp : DWORD;
  70. Eip : DWORD;
  71. SegCs : DWORD;
  72. EFlags : DWORD;
  73. Esp : DWORD;
  74. SegSs : DWORD;
  75. end;
  76. LPCONTEXT = ^CONTEXT;
  77. _CONTEXT = CONTEXT;
  78. TCONTEXT = CONTEXT;
  79. PCONTEXT = ^CONTEXT;
  80. type
  81. pexception_record = ^exception_record;
  82. EXCEPTION_RECORD = record
  83. ExceptionCode : longint;
  84. ExceptionFlags : longint;
  85. ExceptionRecord : pexception_record;
  86. ExceptionAddress : pointer;
  87. NumberParameters : longint;
  88. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of pointer;
  89. end;
  90. PEXCEPTION_POINTERS = ^EXCEPTION_POINTERS;
  91. EXCEPTION_POINTERS = record
  92. ExceptionRecord : PEXCEPTION_RECORD ;
  93. ContextRecord : PCONTEXT ;
  94. end;
  95. implementation
  96. const
  97. EXCEPTION_ACCESS_VIOLATION = $c0000005;
  98. EXCEPTION_BREAKPOINT = $80000003;
  99. EXCEPTION_DATATYPE_MISALIGNMENT = $80000002;
  100. EXCEPTION_SINGLE_STEP = $80000004;
  101. EXCEPTION_ARRAY_BOUNDS_EXCEEDED = $c000008c;
  102. EXCEPTION_FLT_DENORMAL_OPERAND = $c000008d;
  103. EXCEPTION_FLT_DIVIDE_BY_ZERO = $c000008e;
  104. EXCEPTION_FLT_INEXACT_RESULT = $c000008f;
  105. EXCEPTION_FLT_INVALID_OPERATION = $c0000090;
  106. EXCEPTION_FLT_OVERFLOW = $c0000091;
  107. EXCEPTION_FLT_STACK_CHECK = $c0000092;
  108. EXCEPTION_FLT_UNDERFLOW = $c0000093;
  109. EXCEPTION_INT_DIVIDE_BY_ZERO = $c0000094;
  110. EXCEPTION_INT_OVERFLOW = $c0000095;
  111. EXCEPTION_INVALID_HANDLE = $c0000008;
  112. EXCEPTION_PRIV_INSTRUCTION = $c0000096;
  113. EXCEPTION_NONCONTINUABLE_EXCEPTION = $c0000025;
  114. EXCEPTION_NONCONTINUABLE = $1;
  115. EXCEPTION_STACK_OVERFLOW = $c00000fd;
  116. EXCEPTION_INVALID_DISPOSITION = $c0000026;
  117. EXCEPTION_ILLEGAL_INSTRUCTION = $C000001D;
  118. EXCEPTION_IN_PAGE_ERROR = $C0000006;
  119. EXCEPTION_EXECUTE_HANDLER = 1;
  120. EXCEPTION_CONTINUE_EXECUTION = -(1);
  121. EXCEPTION_CONTINUE_SEARCH = 0;
  122. type
  123. { type of functions that should be used for exception handling }
  124. LPTOP_LEVEL_EXCEPTION_FILTER = function(excep :PEXCEPTION_POINTERS) : longint;stdcall;
  125. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : LPTOP_LEVEL_EXCEPTION_FILTER)
  126. : LPTOP_LEVEL_EXCEPTION_FILTER;
  127. external 'kernel32' name 'SetUnhandledExceptionFilter';
  128. var
  129. signal_list : Array[SIGABRT..SIGMAX] of SignalHandler;
  130. var
  131. { value of the stack segment
  132. to check if the call stack can be written on exceptions }
  133. _SS : longint;
  134. const
  135. fpucw : word = $1332;
  136. Exception_handler_installed : boolean = false;
  137. MAX_Level = 16;
  138. except_level : byte = 0;
  139. var
  140. except_eip : array[0..Max_level-1] of longint;
  141. except_signal : array[0..Max_level-1] of longint;
  142. reset_fpu : array[0..max_level-1] of boolean;
  143. procedure JumpToHandleSignal;
  144. var
  145. res, eip, ebp, sigtype : longint;
  146. begin
  147. asm
  148. pushal
  149. movl (%ebp),%eax
  150. movl %eax,ebp
  151. end;
  152. if except_level>0 then
  153. dec(except_level)
  154. else
  155. exit;
  156. eip:=except_eip[except_level];
  157. sigtype:=except_signal[except_level];
  158. if reset_fpu[except_level] then
  159. asm
  160. fninit
  161. fldcw fpucw
  162. end;
  163. if (sigtype>=SIGABRT) and (sigtype<=SIGMAX) and
  164. (signal_list[sigtype]<>@SIG_DFL) then
  165. begin
  166. res:=signal_list[sigtype](sigtype);
  167. end
  168. else
  169. res:=0;
  170. if res=0 then
  171. RunError(sigtype)
  172. else
  173. { jump back to old code }
  174. asm
  175. popal
  176. movl eip,%eax
  177. movl %eax,4(%ebp)
  178. ret
  179. end;
  180. end;
  181. function Signals_exception_handler(excep :PEXCEPTION_POINTERS) : longint;stdcall;
  182. var frame,res : longint;
  183. function CallSignal(sigtype,frame : longint;must_reset_fpu : boolean) : longint;
  184. begin
  185. if frame=0 then
  186. CallSignal:=Exception_Continue_Search
  187. else
  188. begin
  189. if except_level >= Max_level then
  190. exit;
  191. except_eip[except_level]:=excep^.ContextRecord^.Eip;
  192. except_signal[except_level]:=sigtype;
  193. reset_fpu[except_level]:=must_reset_fpu;
  194. inc(except_level);
  195. dec(excep^.ContextRecord^.Esp,4);
  196. plongint (excep^.ContextRecord^.Esp)^ := excep^.ContextRecord^.Eip;
  197. excep^.ContextRecord^.Eip:=longint(@JumpToHandleSignal);
  198. CallSignal:=Exception_Continue_Execution;
  199. end;
  200. end;
  201. begin
  202. {$ifdef i386}
  203. if excep^.ContextRecord^.SegSs=_SS then
  204. frame:=excep^.ContextRecord^.Ebp
  205. else
  206. {$endif i386}
  207. frame:=0;
  208. { default : unhandled !}
  209. res:=Exception_Continue_Search;
  210. {$ifdef SYSTEMEXCEPTIONDEBUG}
  211. if IsConsole then
  212. writeln(stderr,'Exception ',
  213. hexstr(excep^.ExceptionRecord^.ExceptionCode,8));
  214. {$endif SYSTEMEXCEPTIONDEBUG}
  215. case excep^.ExceptionRecord^.ExceptionCode of
  216. EXCEPTION_ACCESS_VIOLATION :
  217. res:=CallSignal(SIGSEGV,frame,false);
  218. { EXCEPTION_BREAKPOINT = $80000003;
  219. EXCEPTION_DATATYPE_MISALIGNMENT = $80000002;
  220. EXCEPTION_SINGLE_STEP = $80000004; }
  221. EXCEPTION_ARRAY_BOUNDS_EXCEEDED :
  222. res:=CallSignal(SIGSEGV,frame,false);
  223. EXCEPTION_FLT_DENORMAL_OPERAND :
  224. begin
  225. res:=CallSignal(SIGFPE,frame,true);
  226. end;
  227. EXCEPTION_FLT_DIVIDE_BY_ZERO :
  228. begin
  229. res:=CallSignal(SIGFPE,frame,true);
  230. {excep^.ContextRecord^.FloatSave.StatusWord:=excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  231. end;
  232. {EXCEPTION_FLT_INEXACT_RESULT = $c000008f; }
  233. EXCEPTION_FLT_INVALID_OPERATION :
  234. begin
  235. res:=CallSignal(SIGFPE,frame,true);
  236. end;
  237. EXCEPTION_FLT_OVERFLOW :
  238. begin
  239. res:=CallSignal(SIGFPE,frame,true);
  240. end;
  241. EXCEPTION_FLT_STACK_CHECK :
  242. begin
  243. res:=CallSignal(SIGFPE,frame,true);
  244. end;
  245. EXCEPTION_FLT_UNDERFLOW :
  246. begin
  247. res:=CallSignal(SIGFPE,frame,true); { should be accepted as zero !! }
  248. end;
  249. EXCEPTION_INT_DIVIDE_BY_ZERO :
  250. res:=CallSignal(SIGFPE,frame,false);
  251. EXCEPTION_INT_OVERFLOW :
  252. res:=CallSignal(SIGFPE,frame,false);
  253. {EXCEPTION_INVALID_HANDLE = $c0000008;
  254. EXCEPTION_PRIV_INSTRUCTION = $c0000096;
  255. EXCEPTION_NONCONTINUABLE_EXCEPTION = $c0000025;
  256. EXCEPTION_NONCONTINUABLE = $1;}
  257. EXCEPTION_STACK_OVERFLOW :
  258. res:=CallSignal(SIGSEGV,frame,false);
  259. {EXCEPTION_INVALID_DISPOSITION = $c0000026;}
  260. EXCEPTION_ILLEGAL_INSTRUCTION,
  261. EXCEPTION_PRIV_INSTRUCTION,
  262. EXCEPTION_IN_PAGE_ERROR,
  263. EXCEPTION_SINGLE_STEP : res:=CallSignal(SIGSEGV,frame,false);
  264. end;
  265. Signals_exception_handler:=res;
  266. end;
  267. procedure install_exception_handler;
  268. {$ifdef SYSTEMEXCEPTIONDEBUG}
  269. var
  270. oldexceptaddr,newexceptaddr : longint;
  271. {$endif SYSTEMEXCEPTIONDEBUG}
  272. begin
  273. if Exception_handler_installed then
  274. exit;
  275. {$ifdef SYSTEMEXCEPTIONDEBUG}
  276. asm
  277. movl $0,%eax
  278. movl %fs:(%eax),%eax
  279. movl %eax,oldexceptaddr
  280. end;
  281. {$endif SYSTEMEXCEPTIONDEBUG}
  282. SetUnhandledExceptionFilter(@Signals_exception_handler);
  283. {$ifdef SYSTEMEXCEPTIONDEBUG}
  284. asm
  285. movl $0,%eax
  286. movl %fs:(%eax),%eax
  287. movl %eax,newexceptaddr
  288. end;
  289. if IsConsole then
  290. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  291. ' new exception ',hexstr(newexceptaddr,8));
  292. {$endif SYSTEMEXCEPTIONDEBUG}
  293. Exception_handler_installed := true;
  294. end;
  295. procedure remove_exception_handler;
  296. begin
  297. if not Exception_handler_installed then
  298. exit;
  299. SetUnhandledExceptionFilter(nil);
  300. end;
  301. function SIG_ERR(x:longint):longint;
  302. begin
  303. SIG_ERR:=-1;
  304. end;
  305. function SIG_IGN(x:longint):longint;
  306. begin
  307. SIG_IGN:=-1;
  308. end;
  309. function SIG_DFL(x:longint):longint;
  310. begin
  311. SIG_DFL:=0;
  312. end;
  313. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  314. var
  315. temp : SignalHandler;
  316. begin
  317. if ((sig < SIGABRT) or (sig > SIGMAX) or (sig = SIGKILL)) then
  318. begin
  319. signal:=@SIG_ERR;
  320. runerror(201);
  321. end;
  322. if not Exception_handler_installed then
  323. install_exception_handler;
  324. temp := signal_list[sig];
  325. signal_list[sig] := func;
  326. signal:=temp;
  327. end;
  328. var
  329. i : longint;
  330. initialization
  331. {$ifdef i386}
  332. asm
  333. xorl %eax,%eax
  334. movw %ss,%ax
  335. movl %eax,_SS
  336. end;
  337. {$endif i386}
  338. for i:=SIGABRT to SIGMAX do
  339. signal_list[i]:=@SIG_DFL;
  340. { install_exception_handler;
  341. delay this to first use
  342. as other units also might install their handlers PM }
  343. finalization
  344. remove_exception_handler;
  345. end.