dpmiexcp.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Pierre Muller
  5. DPMI Exception routines for Go32V2
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$GOTO ON}
  13. Unit DPMIExcp;
  14. { If linking to C code we must avoid loading of the dpmiexcp.o
  15. in libc.a from the equivalent C code
  16. => all global functions from dpmiexcp.c must be aliased PM
  17. Problem this is only valid for DJGPP v2.01 }
  18. interface
  19. uses
  20. go32;
  21. { No stack checking ! }
  22. {$S-}
  23. { Error Messages }
  24. function do_faulting_finish_message : integer;
  25. { SetJmp/LongJmp }
  26. type
  27. { must also contain exception_state !! }
  28. pdpmi_jmp_buf = ^dpmi_jmp_buf;
  29. dpmi_jmp_buf = packed record
  30. eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
  31. cs,ds,es,fs,gs,ss : word;
  32. sigmask : longint; { for POSIX signals only }
  33. signum : longint; { for expansion ie 386 exception number }
  34. exception_ptr : pdpmi_jmp_buf; { pointer to previous exception if exists }
  35. end;
  36. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  37. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  38. { Signals }
  39. const
  40. SIGABRT = 288;
  41. SIGFPE = 289;
  42. SIGILL = 290;
  43. SIGSEGV = 291;
  44. SIGTERM = 292;
  45. SIGALRM = 293;
  46. SIGHUP = 294;
  47. SIGINT = 295;
  48. SIGKILL = 296;
  49. SIGPIPE = 297;
  50. SIGQUIT = 298;
  51. SIGUSR1 = 299;
  52. SIGUSR2 = 300;
  53. SIGNOFP = 301;
  54. SIGTRAP = 302;
  55. SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
  56. SIGPROF = 304;
  57. SIGMAX = 320;
  58. SIG_BLOCK = 1;
  59. SIG_SETMASK = 2;
  60. SIG_UNBLOCK = 3;
  61. function SIG_DFL( x: longint) : longint;
  62. function SIG_ERR( x: longint) : longint;
  63. function SIG_IGN( x: longint) : longint;
  64. type
  65. SignalHandler = function (v : longint) : longint;
  66. PSignalHandler = ^SignalHandler; { to be compatible with linux.pp }
  67. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  68. function _raise(sig : longint) : longint;
  69. { Exceptions }
  70. type
  71. pexception_state = ^texception_state;
  72. texception_state = record
  73. __eax, __ebx, __ecx, __edx, __esi : longint;
  74. __edi, __ebp, __esp, __eip, __eflags : longint;
  75. __cs, __ds, __es, __fs, __gs, __ss : word;
  76. __sigmask : longint; { for POSIX signals only }
  77. __signum : longint; { for expansion }
  78. __exception_ptr : pexception_state; { pointer to previous exception }
  79. __fpu_state : array [0..108-1] of byte; { for future use }
  80. end;
  81. procedure djgpp_exception_toggle;
  82. procedure djgpp_exception_setup;
  83. function djgpp_exception_state : pexception_state;
  84. function djgpp_set_ctrl_c(enable : boolean) : boolean;
  85. { Other }
  86. function dpmi_set_coprocessor_emulation(flag : longint) : longint;
  87. implementation
  88. {$asmmode ATT}
  89. {$L exceptn.o}
  90. var
  91. v2prt0_ds_alias : pointer;external name '___v2prt0_ds_alias';
  92. djgpp_ds_alias : pointer;external name '___djgpp_ds_alias';
  93. djgpp_exception_state_ptr : pexception_state;external name '___djgpp_exception_state_ptr';
  94. endtext : longint;external name '_etext';
  95. starttext : longint;external name 'start';
  96. djgpp_old_kbd : tseginfo;external name '___djgpp_old_kbd';
  97. djgpp_hw_lock_start : longint;external name '___djgpp_hw_lock_start';
  98. djgpp_hw_lock_end : longint;external name '___djgpp_hw_lock_end';
  99. djgpp_hwint_flags : longint;external name '___djgpp_hwint_flags';
  100. djgpp_dos_sel : word;external name '___djgpp_dos_sel';
  101. djgpp_exception_table : array[0..0] of pointer;external name '___djgpp_exception_table';
  102. procedure djgpp_i24;external name '___djgpp_i24';
  103. procedure djgpp_iret;external name '___djgpp_iret';
  104. procedure djgpp_npx_hdlr;external name '___djgpp_npx_hdlr';
  105. procedure djgpp_kbd_hdlr;external name '___djgpp_kbd_hdlr';
  106. procedure djgpp_kbd_hdlr_pc98;external name '___djgpp_kbd_hdlr_pc98';
  107. procedure djgpp_cbrk_hdlr;external name '___djgpp_cbrk_hdlr';
  108. var
  109. exceptions_on : boolean;
  110. { old_int00 : tseginfo;cvar;external;
  111. old_int75 : tseginfo;cvar;external; }
  112. const
  113. cbrk_vect : byte = $1b;
  114. exception_level : longint = 0;
  115. {****************************************************************************
  116. Helpers
  117. ****************************************************************************}
  118. procedure err(const x : string);
  119. begin
  120. write(stderr, x);
  121. end;
  122. procedure errln(const x : string);
  123. begin
  124. writeln(stderr, x);
  125. end;
  126. procedure itox(v,len : longint);
  127. var
  128. st : string;
  129. begin
  130. st:=hexstr(v,len);
  131. err(st);
  132. end;
  133. {****************************************************************************
  134. SetJmp/LongJmp
  135. ****************************************************************************}
  136. function c_setjmp(var rec : dpmi_jmp_buf) : longint;[public, alias : '_setjmp'];
  137. begin
  138. { here we need to be subtle :
  139. - we need to return with the arg still on the stack
  140. - but we also need to jmp to FPC_setjmp and not to call it
  141. because otherwise the return address is wrong !!
  142. For this we shift the return address down and
  143. duplicate the rec on stack }
  144. asm
  145. movl %ebp,%esp
  146. popl %ebp
  147. subl $8,%esp
  148. movl %eax,(%esp)
  149. movl 8(%esp),%eax
  150. movl %eax,4(%esp)
  151. movl 12(%esp),%eax
  152. movl %eax,8(%esp)
  153. popl %eax
  154. jmp dpmi_setjmp
  155. end;
  156. end;
  157. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  158. begin
  159. asm
  160. pushl %edi
  161. movl rec,%edi
  162. movl %eax,(%edi)
  163. movl %ebx,4(%edi)
  164. movl %ecx,8(%edi)
  165. movl %edx,12(%edi)
  166. movl %esi,16(%edi)
  167. { load edi }
  168. movl -4(%ebp),%eax
  169. { ... and store it }
  170. movl %eax,20(%edi)
  171. { ebp ... }
  172. movl (%ebp),%eax
  173. movl %eax,24(%edi)
  174. { esp ... }
  175. movl %esp,%eax
  176. addl $12,%eax
  177. movl %eax,28(%edi)
  178. { the return address }
  179. movl 4(%ebp),%eax
  180. movl %eax,32(%edi)
  181. { flags ... }
  182. pushfl
  183. popl 36(%edi)
  184. { !!!!! the segment registers, not yet needed }
  185. { you need them if the exception comes from
  186. an interrupt or a seg_move }
  187. movw %cs,40(%edi)
  188. movw %ds,42(%edi)
  189. movw %es,44(%edi)
  190. movw %fs,46(%edi)
  191. movw %gs,48(%edi)
  192. movw %ss,50(%edi)
  193. movl djgpp_exception_state_ptr, %eax
  194. movl %eax, 60(%edi)
  195. { restore EDI }
  196. pop %edi
  197. { we come from the initial call }
  198. xorl %eax,%eax
  199. movl %eax,__RESULT
  200. { leave USING RET inside CDECL functions is risky as
  201. some registers are pushed at entry
  202. ret $4 not anymore since cdecl !! }
  203. end;
  204. end;
  205. procedure c_longjmp(var rec : dpmi_jmp_buf;return_value : longint);[public, alias : '_longjmp'];
  206. begin
  207. dpmi_longjmp(rec,return_value);
  208. { never gets here !! so pascal stack convention is no problem }
  209. end;
  210. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);[alias : 'FPC_longjmp'];
  211. begin
  212. if (exception_level>0) then
  213. dec(exception_level);
  214. asm
  215. { restore compiler shit }
  216. popl %ebp
  217. { copy from longjmp.S }
  218. movl 4(%esp),%edi { get dpmi_jmp_buf }
  219. movl 8(%esp),%eax { store retval in j->eax }
  220. movl %eax,0(%edi)
  221. movw 46(%edi),%fs
  222. movw 48(%edi),%gs
  223. movl 4(%edi),%ebx
  224. movl 8(%edi),%ecx
  225. movl 12(%edi),%edx
  226. movl 24(%edi),%ebp
  227. { Now for some uglyness. The dpmi_jmp_buf structure may be ABOVE the
  228. point on the new SS:ESP we are moving to. We don't allow overlap,
  229. but do force that it always be valid. We will use ES:ESI for
  230. our new stack before swapping to it. }
  231. movw 50(%edi),%es
  232. movl 28(%edi),%esi
  233. subl $28,%esi { We need 7 working longwords on stack }
  234. movl 60(%edi),%eax
  235. movl %eax,%es:(%esi) { Exception pointer }
  236. movzwl 42(%edi),%eax
  237. movl %eax,%es:4(%esi) { DS }
  238. movl 20(%edi),%eax
  239. movl %eax,%es:8(%esi) { EDI }
  240. movl 16(%edi),%eax
  241. movl %eax,%es:12(%esi) { ESI }
  242. movl 32(%edi),%eax
  243. movl %eax,%es:16(%esi) { EIP - start of IRET frame }
  244. movl 40(%edi),%eax
  245. movl %eax,%es:20(%esi) { CS }
  246. movl 36(%edi),%eax
  247. movl %eax,%es:24(%esi) { EFLAGS }
  248. movl 0(%edi),%eax
  249. movw 44(%edi),%es
  250. movw 50(%edi),%ss
  251. movl %esi,%esp
  252. popl djgpp_exception_state_ptr
  253. popl %ds
  254. popl %edi
  255. popl %esi
  256. iret { actually jump to new cs:eip loading flags }
  257. end;
  258. end;
  259. {****************************************************************************
  260. Signals
  261. ****************************************************************************}
  262. var
  263. signal_list : Array[0..SIGMAX] of SignalHandler;
  264. function SIG_ERR(x:longint):longint;
  265. begin
  266. SIG_ERR:=-1;
  267. end;
  268. function SIG_IGN(x:longint):longint;
  269. begin
  270. SIG_IGN:=-1;
  271. end;
  272. function SIG_DFL(x:longint):longint;
  273. begin
  274. SIG_DFL:=0;
  275. end;
  276. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  277. var
  278. temp : SignalHandler;
  279. begin
  280. if ((sig <= 0) or (sig > SIGMAX) or (sig = SIGKILL)) then
  281. begin
  282. signal:=@SIG_ERR;
  283. runerror(201);
  284. end;
  285. temp := signal_list[sig - 1];
  286. signal_list[sig - 1] := func;
  287. signal:=temp;
  288. end;
  289. { C counter part }
  290. function c_signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;[public,alias : '_signal'];
  291. var
  292. temp : SignalHandler;
  293. begin
  294. temp:=signal(sig,func);
  295. c_signal:=temp;
  296. end;
  297. const
  298. signames : array [0..14] of string[4] = (
  299. 'ABRT','FPE ','ILL ','SEGV','TERM','ALRM','HUP ',
  300. 'INT ','KILL','PIPE','QUIT','USR1','USR2','NOFP','TRAP');
  301. function _raise(sig : longint) : longint;
  302. var
  303. temp : SignalHandler;
  304. label
  305. traceback_exit;
  306. begin
  307. if(sig <= 0) or (sig > SIGMAX) then
  308. exit(-1);
  309. temp:=signal_list[sig - 1];
  310. if (temp = SignalHandler(@SIG_IGN)) then
  311. exit(0);
  312. if (temp = SignalHandler(@SIG_DFL)) then
  313. begin
  314. traceback_exit:
  315. if ((sig >= SIGABRT) and (sig <= SIGTRAP)) then
  316. begin
  317. err('Exiting due to signal SIG');
  318. err(signames[sig-sigabrt]);
  319. end
  320. else
  321. begin
  322. err('Exiting due to signal $');
  323. itox(sig, 4);
  324. end;
  325. errln('');
  326. do_faulting_finish_message(); { Exits, does not return }
  327. exit(-1);
  328. end;
  329. { this is incompatible with dxegen-dxeload stuff PM }
  330. if ((cardinal(temp) < cardinal(@starttext)) or
  331. (cardinal(temp) > cardinal(@endtext))) then
  332. begin
  333. errln('Bad signal handler, ');
  334. goto traceback_exit;
  335. end;
  336. temp(sig);
  337. exit(0);
  338. end;
  339. function c_raise(sig : longint) : longint;cdecl;[public,alias : '_raise'];
  340. begin
  341. c_raise:=_raise(sig);
  342. end;
  343. {****************************************************************************
  344. Exceptions
  345. ****************************************************************************}
  346. function except_to_sig(excep : longint) : longint;
  347. begin
  348. case excep of
  349. 5,8,9,11,12,13,14 : exit(SIGSEGV);
  350. 0,4,16 : exit(SIGFPE);
  351. 1,3 : exit(SIGTRAP);
  352. 7 : exit(SIGNOFP);
  353. else
  354. begin
  355. case excep of
  356. $75 : exit(SIGFPE);
  357. $78 : exit(SIGTIMR);
  358. $1b,
  359. $79 : exit(SIGINT);
  360. else
  361. exit(SIGILL);
  362. end;
  363. end;
  364. end;
  365. end;
  366. procedure show_call_frame(djgpp_exception_state : pexception_state);
  367. begin
  368. errln('Call frame traceback EIPs:');
  369. errln(' 0x'+hexstr(djgpp_exception_state^.__eip, 8));
  370. dump_stack(stderr,djgpp_exception_state^.__ebp);
  371. end;
  372. const
  373. EXCEPTIONCOUNT = 18;
  374. exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (
  375. 'Division by Zero',
  376. 'Debug',
  377. 'NMI',
  378. 'Breakpoint',
  379. 'Overflow',
  380. 'Bounds Check',
  381. 'Invalid Opcode',
  382. 'Coprocessor not available',
  383. 'Double Fault',
  384. 'Coprocessor overrun',
  385. 'Invalid TSS',
  386. 'Segment Not Present',
  387. 'Stack Fault',
  388. 'General Protection Fault',
  389. 'Page fault',
  390. ' ',
  391. 'Coprocessor Error',
  392. 'Alignment Check');
  393. has_error : array [0..EXCEPTIONCOUNT-1] of byte =
  394. (0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1);
  395. cbrk_hooked : boolean = false;
  396. old_video_mode : byte = 3;
  397. procedure dump_selector(const name : string; sel : word);
  398. var
  399. base,limit : longint;
  400. begin
  401. err(name);
  402. err(': sel=');
  403. itox(sel, 4);
  404. if (sel<>0) then
  405. begin
  406. base:=get_segment_base_address(sel);
  407. err(' base='); itox(base, 8);
  408. limit:=get_segment_limit(sel);
  409. err(' limit='); itox(limit, 8);
  410. end;
  411. errln('');
  412. end;
  413. function farpeekb(sel : word;offset : longint) : byte;
  414. var
  415. b : byte;
  416. begin
  417. seg_move(sel,offset,get_ds,longint(@b),1);
  418. farpeekb:=b;
  419. end;
  420. const message_level : byte = 0;
  421. procedure ___exit(c:byte);cdecl;external name '___exit';
  422. function do_faulting_finish_message : integer;
  423. var
  424. en : pchar;
  425. signum,i : longint;
  426. old_vid : byte;
  427. label
  428. simple_exit;
  429. begin
  430. inc(message_level);
  431. if message_level>2 then
  432. goto simple_exit;
  433. do_faulting_finish_message:=0;
  434. signum:=djgpp_exception_state_ptr^.__signum;
  435. { check video mode for original here and reset (not if PC98) */ }
  436. if ((go32_info_block.linear_address_of_primary_screen <> $a0000) and
  437. (farpeekb(dosmemselector, $449) <> old_video_mode)) then
  438. begin
  439. old_vid:=old_video_mode;
  440. asm
  441. pusha
  442. movzbl old_vid,%eax
  443. int $0x10
  444. popa
  445. nop
  446. end;
  447. end;
  448. if (signum >= EXCEPTIONCOUNT) then
  449. begin
  450. case signum of
  451. $75 : en:='Floating Point exception';
  452. $1b : en:='Control-Break Pressed';
  453. $79 : en:='Control-C Pressed';
  454. else
  455. en:=nil;
  456. end;
  457. end
  458. else
  459. en:=exception_names[signum];
  460. if (en = nil) then
  461. begin
  462. err('Exception ');
  463. itox(signum, 2);
  464. err(' at eip=');
  465. itox(djgpp_exception_state_ptr^.__eip, 8);
  466. end
  467. else
  468. begin
  469. write(stderr, 'FPC ',en);
  470. err(' at eip=');
  471. itox(djgpp_exception_state_ptr^.__eip, 8);
  472. end;
  473. { Control-C should stop the program also !}
  474. {if (signum = $79) then
  475. begin
  476. errln('');
  477. exit(-1);
  478. end;}
  479. if ((signum < EXCEPTIONCOUNT) and (has_error[signum]=1)) then
  480. begin
  481. errorcode := djgpp_exception_state_ptr^.__sigmask and $ffff;
  482. if(errorcode<>0) then
  483. begin
  484. err(', error=');
  485. itox(errorcode, 4);
  486. end;
  487. end;
  488. errln('');
  489. err('eax=');
  490. itox(djgpp_exception_state_ptr^.__eax, 8);
  491. err(' ebx='); itox(djgpp_exception_state_ptr^.__ebx, 8);
  492. err(' ecx='); itox(djgpp_exception_state_ptr^.__ecx, 8);
  493. err(' edx='); itox(djgpp_exception_state_ptr^.__edx, 8);
  494. err(' esi='); itox(djgpp_exception_state_ptr^.__esi, 8);
  495. err(' edi='); itox(djgpp_exception_state_ptr^.__edi, 8);
  496. errln('');
  497. err('ebp='); itox(djgpp_exception_state_ptr^.__ebp, 8);
  498. err(' esp='); itox(djgpp_exception_state_ptr^.__esp, 8);
  499. err(' program=');
  500. errln(paramstr(0));
  501. dump_selector('cs', djgpp_exception_state_ptr^.__cs);
  502. dump_selector('ds', djgpp_exception_state_ptr^.__ds);
  503. dump_selector('es', djgpp_exception_state_ptr^.__es);
  504. dump_selector('fs', djgpp_exception_state_ptr^.__fs);
  505. dump_selector('gs', djgpp_exception_state_ptr^.__gs);
  506. dump_selector('ss', djgpp_exception_state_ptr^.__ss);
  507. errln('');
  508. if (djgpp_exception_state_ptr^.__cs = get_cs) then
  509. show_call_frame(djgpp_exception_state_ptr)
  510. {$ifdef DPMIEXCP_DEBUG}
  511. else
  512. errln('Exception occured in another context');
  513. {$endif def DPMIEXCP_DEBUG}
  514. ;
  515. if assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  516. if (djgpp_exception_state_ptr^.__exception_ptr^.__cs = get_cs) then
  517. begin
  518. Errln('First exception level stack');
  519. show_call_frame(djgpp_exception_state_ptr^.__exception_ptr);
  520. end
  521. {$ifdef DPMIEXCP_DEBUG}
  522. else
  523. begin
  524. errln('First exception occured in another context');
  525. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  526. do_faulting_finish_message();
  527. end;
  528. {$endif def DPMIEXCP_DEBUG}
  529. ;
  530. { must not return !! }
  531. simple_exit:
  532. if exceptions_on then
  533. djgpp_exception_toggle;
  534. ___exit(1);
  535. end;
  536. function djgpp_exception_state:pexception_state;assembler;
  537. asm
  538. movl djgpp_exception_state_ptr,%eax
  539. end;
  540. procedure djgpp_exception_processor;[public,alias : '___djgpp_exception_processor'];
  541. var
  542. sig : longint;
  543. begin
  544. if not assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  545. exception_level:=1
  546. else
  547. inc(exception_level);
  548. sig:=djgpp_exception_state_ptr^.__signum;
  549. if (exception_level=1) or (sig=$78) then
  550. begin
  551. sig := except_to_sig(sig);
  552. _raise(sig);
  553. if (djgpp_exception_state_ptr^.__signum >= EXCEPTIONCOUNT) then
  554. { Not exception so continue OK }
  555. dpmi_longjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^, djgpp_exception_state_ptr^.__eax);
  556. { User handler did not exit or longjmp, we must exit }
  557. err('FPC cannot continue from exception, exiting due to signal ');
  558. itox(sig, 4);
  559. errln('');
  560. end
  561. else
  562. begin
  563. if exception_level>2 then
  564. begin
  565. errln('FPC triple exception, exiting !!! ');
  566. if (exceptions_on) then
  567. djgpp_exception_toggle;
  568. asm
  569. pushw $1
  570. call ___exit
  571. end;
  572. end;
  573. err('FPC double exception, exiting due to signal ');
  574. itox(sig, 4);
  575. errln('');
  576. end;
  577. do_faulting_finish_message;
  578. end;
  579. type
  580. trealseginfo = tseginfo;
  581. pseginfo = ^tseginfo;
  582. var
  583. except_ori : array [0..EXCEPTIONCOUNT-1] of tseginfo;
  584. {$ifdef DPMIEXCP_DEBUG}
  585. export name '_ori_exceptions';
  586. {$endif def DPMIEXCP_DEBUG}
  587. kbd_ori : tseginfo;
  588. npx_ori : tseginfo;
  589. cbrk_ori,
  590. cbrk_rmcb : trealseginfo;
  591. cbrk_regs : registers;
  592. v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  593. procedure djgpp_exception_toggle;[alias : '___djgpp_exception_toggle'];
  594. var
  595. _except : tseginfo;
  596. i : longint;
  597. begin
  598. {$ifdef DPMIEXCP_DEBUG}
  599. if exceptions_on then
  600. errln('Disabling FPC exceptions')
  601. else
  602. errln('Enabling FPC exceptions');
  603. {$endif DPMIEXCP_DEBUG}
  604. { toggle here to avoid infinite recursion }
  605. { if a subfunction calls runerror !! }
  606. exceptions_on:=not exceptions_on;
  607. v2prt0_exceptions_on:=exceptions_on;
  608. for i:=0 to EXCEPTIONCOUNT-1 do
  609. begin
  610. if get_pm_exception_handler(i,_except) then
  611. begin
  612. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  613. begin
  614. if not set_pm_exception_handler(i,except_ori[i]) then
  615. errln('error setting exception nø'+hexstr(i,2));
  616. end;
  617. except_ori[i]:=_except;
  618. end
  619. else
  620. begin
  621. if get_exception_handler(i,_except) then
  622. begin
  623. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  624. begin
  625. if not set_exception_handler(i,except_ori[i]) then
  626. errln('error setting exception nø'+hexstr(i,2));
  627. end;
  628. except_ori[i]:=_except;
  629. end;
  630. end;
  631. end;
  632. get_pm_interrupt($75,_except);
  633. set_pm_interrupt($75,npx_ori);
  634. npx_ori:=_except;
  635. get_pm_interrupt(9,_except);
  636. set_pm_interrupt(9,kbd_ori);
  637. kbd_ori:=_except;
  638. if (cbrk_hooked) then
  639. begin
  640. set_rm_interrupt(cbrk_vect,cbrk_ori);
  641. free_rm_callback(cbrk_rmcb);
  642. cbrk_hooked := false;
  643. {$ifdef DPMIEXCP_DEBUG}
  644. errln('back to ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  645. {$endif DPMIEXCP_DEBUG}
  646. end
  647. else
  648. begin
  649. get_rm_interrupt(cbrk_vect, cbrk_ori);
  650. {$ifdef DPMIEXCP_DEBUG}
  651. errln('ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  652. {$endif DPMIEXCP_DEBUG}
  653. get_rm_callback(@djgpp_cbrk_hdlr, cbrk_regs, cbrk_rmcb);
  654. set_rm_interrupt(cbrk_vect, cbrk_rmcb);
  655. {$ifdef DPMIEXCP_DEBUG}
  656. errln('now rm cbrk '+hexstr(cbrk_rmcb.segment,4)+':'+hexstr(longint(cbrk_rmcb.offset),4));
  657. {$endif DPMIEXCP_DEBUG}
  658. cbrk_hooked := true;
  659. end;
  660. end;
  661. function dpmi_set_coprocessor_emulation(flag : longint) : longint;
  662. var
  663. res : longint;
  664. begin
  665. asm
  666. movl flag,%ebx
  667. movl $0xe01,%eax
  668. int $0x31
  669. jc .L_coproc_error
  670. xorl %eax,%eax
  671. .L_coproc_error:
  672. movl %eax,res
  673. end;
  674. dpmi_set_coprocessor_emulation:=res;
  675. end;
  676. var
  677. _swap_in : pointer;external name '_swap_in';
  678. _swap_out : pointer;external name '_swap_out';
  679. _exception_exit : pointer;external name '_exception_exit';
  680. procedure dpmiexcp_exit{(status : longint)};[public,alias : 'excep_exit'];
  681. { We need to restore hardware interrupt handlers even if somebody calls
  682. `_exit' directly, or else we crash the machine in nested programs.
  683. We only toggle the handlers if the original keyboard handler is intact
  684. (otherwise, they might have already toggled them). }
  685. begin
  686. if (exceptions_on) then
  687. djgpp_exception_toggle;
  688. _exception_exit:=nil;
  689. _swap_in:=nil;
  690. _swap_out:=nil;
  691. { restore the FPU state }
  692. dpmi_set_coprocessor_emulation(1);
  693. end;
  694. { _exit in dpmiexcp.c
  695. is already present in v2prt0.as PM}
  696. { used by dos.pp for swap vectors }
  697. procedure dpmi_swap_in;[public,alias : 'swap_in'];
  698. begin
  699. if not (exceptions_on) then
  700. djgpp_exception_toggle;
  701. end;
  702. procedure dpmi_swap_out;[public,alias : 'swap_out'];
  703. begin
  704. if (exceptions_on) then
  705. djgpp_exception_toggle;
  706. end;
  707. var
  708. ___djgpp_app_DS : word;external name '___djgpp_app_DS';
  709. ___djgpp_our_DS : word;external name '___djgpp_our_DS';
  710. procedure djgpp_exception_setup;[alias : '___djgpp_exception_setup'];
  711. var
  712. temp_kbd,
  713. temp_npx : pointer;
  714. _except,
  715. old_kbd : tseginfo;
  716. locksize : longint;
  717. i : longint;
  718. begin
  719. if assigned(_exception_exit) then
  720. exit;
  721. _exception_exit:=@dpmiexcp_exit;
  722. _swap_in:=@dpmi_swap_in;
  723. _swap_out:=@dpmi_swap_out;
  724. { reset signals }
  725. for i := 0 to SIGMAX-1 do
  726. signal_list[i] := SignalHandler(@SIG_DFL);
  727. { app_DS only used when converting HW interrupts to exceptions }
  728. asm
  729. movw %ds,___djgpp_app_DS
  730. movw %ds,___djgpp_our_DS
  731. end;
  732. djgpp_dos_sel:=dosmemselector;
  733. { lock addresses which may see HW interrupts }
  734. lock_code(@djgpp_hw_lock_start,@djgpp_hw_lock_end-@djgpp_hw_lock_start);
  735. _except.segment:=get_cs;
  736. _except.offset:=@djgpp_exception_table;
  737. for i:=0 to ExceptionCount-1 do
  738. begin
  739. except_ori[i] := _except; { New value to set }
  740. inc(_except.offset,4); { This is the size of push n, jmp }
  741. end;
  742. kbd_ori.segment:=_except.segment;
  743. npx_ori.segment:=_except.segment;
  744. npx_ori.offset:=@djgpp_npx_hdlr;
  745. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  746. kbd_ori.offset:=@djgpp_kbd_hdlr
  747. else
  748. begin
  749. kbd_ori.offset:=@djgpp_kbd_hdlr_pc98;
  750. cbrk_vect := $06;
  751. _except.offset:=@djgpp_iret;
  752. set_pm_interrupt($23,_except);
  753. end;
  754. _except.offset:=@djgpp_i24;
  755. set_pm_interrupt($24, _except);
  756. get_pm_interrupt(9,djgpp_old_kbd);
  757. djgpp_exception_toggle; { Set new values & save old values }
  758. { get original video mode and save }
  759. old_video_mode := farpeekb(dosmemselector, $449);
  760. end;
  761. function djgpp_set_ctrl_c(enable : boolean) : boolean;
  762. begin
  763. djgpp_set_ctrl_c:=(djgpp_hwint_flags and 1)=0;
  764. if enable then
  765. djgpp_hwint_flags:=djgpp_hwint_flags and (not 1)
  766. else
  767. djgpp_hwint_flags:=djgpp_hwint_flags or 1;
  768. end;
  769. function c_djgpp_set_ctrl_c(enable : longint) : boolean;cdecl;[public,alias : '___djgpp_set_ctrl_c'];
  770. begin
  771. c_djgpp_set_ctrl_c:=djgpp_set_ctrl_c(boolean(enable));
  772. end;
  773. procedure InitDPMIExcp;
  774. begin
  775. djgpp_ds_alias:=v2prt0_ds_alias;
  776. djgpp_exception_setup;
  777. end;
  778. begin
  779. InitDPMIExcp;
  780. end.
  781. {
  782. $Log$
  783. Revision 1.11 2000-02-09 16:59:28 peter
  784. * truncated log
  785. Revision 1.10 2000/01/10 12:14:57 pierre
  786. * add $goto on to avoid problems
  787. Revision 1.9 2000/01/07 16:41:31 daniel
  788. * copyright 2000
  789. Revision 1.8 2000/01/07 16:32:23 daniel
  790. * copyright 2000 added
  791. }