signals.pp 13 KB

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