dpmiexcp.pp 26 KB

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