dpmiexcp.pp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562
  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. {$ifndef IN_SYSTEM}
  13. {$GOTO ON}
  14. {$define IN_DPMIEXCP_UNIT}
  15. {$ifndef NO_EXCEPTIONS_IN_SYSTEM}
  16. {$define EXCEPTIONS_IN_SYSTEM}
  17. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  18. Unit DpmiExcp;
  19. { If linking to C code we must avoid loading of the dpmiexcp.o
  20. in libc.a from the equivalent C code
  21. => all global functions from dpmiexcp.c must be aliased PM
  22. Problem this is only valid for DJGPP v2.01 }
  23. interface
  24. {$ifdef NO_EXCEPTIONS_IN_SYSTEM}
  25. uses
  26. go32;
  27. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  28. {$endif ndef IN_SYSTEM}
  29. { No stack checking ! }
  30. {$S-}
  31. { Decide if we want to create the C functions or not }
  32. {$ifdef EXCEPTIONS_IN_SYSTEM}
  33. { If exceptions are in system the C functions must be
  34. inserted in the system unit }
  35. {$ifdef IN_DPMIEXCP_UNIT}
  36. {$undef CREATE_C_FUNCTIONS}
  37. {$else not IN_DPMIEXCP_UNIT}
  38. {$define CREATE_C_FUNCTIONS}
  39. {$endif ndef IN_DPMIEXCP_UNIT}
  40. {$else not EXCEPTIONS_IN_SYSTEM}
  41. {$define CREATE_C_FUNCTIONS}
  42. {$endif not EXCEPTIONS_IN_SYSTEM}
  43. { Error Messages }
  44. function do_faulting_finish_message(fake : boolean) : integer;cdecl;
  45. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  46. { SetJmp/LongJmp }
  47. type
  48. { must also contain exception_state !! }
  49. pdpmi_jmp_buf = ^dpmi_jmp_buf;
  50. dpmi_jmp_buf = packed record
  51. eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
  52. cs,ds,es,fs,gs,ss : word;
  53. sigmask : longint; { for POSIX signals only }
  54. signum : longint; { for expansion ie 386 exception number }
  55. exception_ptr : pdpmi_jmp_buf; { pointer to previous exception if exists }
  56. end;
  57. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  58. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  59. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  60. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  61. { Signals }
  62. const
  63. SIGABRT = 288;
  64. SIGFPE = 289;
  65. SIGILL = 290;
  66. SIGSEGV = 291;
  67. SIGTERM = 292;
  68. SIGALRM = 293;
  69. SIGHUP = 294;
  70. SIGINT = 295;
  71. SIGKILL = 296;
  72. SIGPIPE = 297;
  73. SIGQUIT = 298;
  74. SIGUSR1 = 299;
  75. SIGUSR2 = 300;
  76. SIGNOFP = 301;
  77. SIGTRAP = 302;
  78. SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
  79. SIGPROF = 304;
  80. SIGMAX = 320;
  81. SIG_BLOCK = 1;
  82. SIG_SETMASK = 2;
  83. SIG_UNBLOCK = 3;
  84. function SIG_DFL( x: longint) : longint;
  85. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  86. function SIG_ERR( x: longint) : longint;
  87. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  88. function SIG_IGN( x: longint) : longint;
  89. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  90. type
  91. SignalHandler = function (v : longint) : longint;
  92. PSignalHandler = ^SignalHandler; { to be compatible with linux.pp }
  93. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  94. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  95. function _raise(sig : longint) : longint;
  96. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  97. { Exceptions }
  98. type
  99. pexception_state = ^texception_state;
  100. texception_state = record
  101. __eax, __ebx, __ecx, __edx, __esi : longint;
  102. __edi, __ebp, __esp, __eip, __eflags : longint;
  103. __cs, __ds, __es, __fs, __gs, __ss : word;
  104. __sigmask : longint; { for POSIX signals only }
  105. __signum : longint; { for expansion }
  106. __exception_ptr : pexception_state; { pointer to previous exception }
  107. __fpu_state : array [0..108-1] of byte; { for future use }
  108. end;
  109. procedure djgpp_exception_toggle;
  110. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  111. procedure djgpp_exception_setup;
  112. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  113. function djgpp_exception_state : pexception_state;
  114. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  115. function djgpp_set_ctrl_c(enable : boolean) : boolean;
  116. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  117. { Other }
  118. function dpmi_set_coprocessor_emulation(flag : longint) : longint;
  119. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  120. function __djgpp_set_sigint_key(new_key : longint) : longint;cdecl;
  121. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  122. function __djgpp_set_sigquit_key(new_key : longint) : longint;cdecl;
  123. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  124. function __djgpp__traceback_exit(sig : longint) : longint;cdecl;
  125. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  126. {$ifndef IN_SYSTEM}
  127. implementation
  128. {$endif IN_SYSTEM}
  129. {$asmmode ATT}
  130. {$ifdef CREATE_C_FUNCTIONS}
  131. {$L exceptn.o}
  132. {$endif CREATE_C_FUNCTIONS}
  133. {$ifndef CREATE_C_FUNCTIONS}
  134. procedure djgpp_exception_toggle;
  135. external name '___djgpp_exception_toggle';
  136. procedure djgpp_exception_setup;
  137. external name '___djgpp_exception_setup';
  138. function __djgpp_set_sigint_key(new_key : longint) : longint;cdecl;
  139. external name '___djgpp_set_sigint_key';
  140. function __djgpp_set_sigquit_key(new_key : longint) : longint;cdecl;
  141. external name '___djgpp_set_sigquit_key';
  142. function __djgpp__traceback_exit(sig : longint) : longint;cdecl;
  143. external name '__djgpp__traceback_exit';
  144. {$else CREATE_C_FUNCTIONS}
  145. var
  146. v2prt0_ds_alias : word;external name '___v2prt0_ds_alias';
  147. djgpp_ds_alias : word;external name '___djgpp_ds_alias';
  148. djgpp_old_kbd : tseginfo;external name '___djgpp_old_kbd';
  149. djgpp_hw_lock_start : longint;external name '___djgpp_hw_lock_start';
  150. djgpp_hw_lock_end : longint;external name '___djgpp_hw_lock_end';
  151. djgpp_dos_sel : word;external name '___djgpp_dos_sel';
  152. djgpp_exception_table : array[0..0] of pointer;external name '___djgpp_exception_table';
  153. dosmemselector : word;external name '_core_selector';
  154. procedure djgpp_i24;external name '___djgpp_i24';
  155. procedure djgpp_iret;external name '___djgpp_iret';
  156. procedure djgpp_npx_hdlr;external name '___djgpp_npx_hdlr';
  157. procedure djgpp_kbd_hdlr;external name '___djgpp_kbd_hdlr';
  158. procedure djgpp_kbd_hdlr_pc98;external name '___djgpp_kbd_hdlr_pc98';
  159. procedure djgpp_cbrk_hdlr;external name '___djgpp_cbrk_hdlr';
  160. {$endif CREATE_C_FUNCTIONS}
  161. var
  162. endtext : longint;external name '_etext';
  163. starttext : longint;external name 'start';
  164. djgpp_exception_state_ptr : pexception_state;external name '___djgpp_exception_state_ptr';
  165. djgpp_hwint_flags : longint;external name '___djgpp_hwint_flags';
  166. {$ifdef CREATE_C_FUNCTIONS}
  167. var
  168. exceptions_on : boolean;
  169. { old_int00 : tseginfo;cvar;external;
  170. old_int75 : tseginfo;cvar;external; }
  171. const
  172. cbrk_vect : byte = $1b;
  173. exception_level : longint = 0;
  174. {$endif CREATE_C_FUNCTIONS}
  175. {$ifndef IN_DPMIEXCP_UNIT}
  176. {****************************************************************************
  177. DPMI functions copied from go32 unit
  178. ****************************************************************************}
  179. const
  180. int31error : word = 0;
  181. procedure test_int31(flag : longint);
  182. begin
  183. asm
  184. pushl %ebx
  185. movw $0,INT31ERROR
  186. movl flag,%ebx
  187. testb $1,%bl
  188. jz .Lti31_1
  189. movw %ax,INT31ERROR
  190. xorl %eax,%eax
  191. jmp .Lti31_2
  192. .Lti31_1:
  193. movl $1,%eax
  194. .Lti31_2:
  195. popl %ebx
  196. end;
  197. end;
  198. function set_pm_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  199. begin
  200. asm
  201. movl intaddr,%eax
  202. movl (%eax),%edx
  203. movw 4(%eax),%cx
  204. movl $0x212,%eax
  205. movb e,%bl
  206. int $0x31
  207. pushf
  208. call test_int31
  209. movb %al,__RESULT
  210. end;
  211. end;
  212. function set_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  213. begin
  214. asm
  215. movl intaddr,%eax
  216. movl (%eax),%edx
  217. movw 4(%eax),%cx
  218. movl $0x203,%eax
  219. movb e,%bl
  220. int $0x31
  221. pushf
  222. call test_int31
  223. movb %al,__RESULT
  224. end;
  225. end;
  226. function get_pm_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  227. begin
  228. asm
  229. movl $0x210,%eax
  230. movb e,%bl
  231. int $0x31
  232. pushf
  233. call test_int31
  234. movb %al,__RESULT
  235. movl intaddr,%eax
  236. movl %edx,(%eax)
  237. movw %cx,4(%eax)
  238. end;
  239. end;
  240. function get_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  241. begin
  242. asm
  243. movl $0x202,%eax
  244. movb e,%bl
  245. int $0x31
  246. pushf
  247. call test_int31
  248. movb %al,__RESULT
  249. movl intaddr,%eax
  250. movl %edx,(%eax)
  251. movw %cx,4(%eax)
  252. end;
  253. end;
  254. function get_segment_base_address(d : word) : longint;
  255. begin
  256. asm
  257. movw d,%bx
  258. movl $6,%eax
  259. int $0x31
  260. xorl %eax,%eax
  261. movw %dx,%ax
  262. shll $16,%ecx
  263. orl %ecx,%eax
  264. movl %eax,__RESULT
  265. end;
  266. end;
  267. function get_segment_limit(d : word) : longint;
  268. begin
  269. asm
  270. movzwl d,%eax
  271. lsl %eax,%eax
  272. jz .L_ok2
  273. xorl %eax,%eax
  274. .L_ok2:
  275. movl %eax,__RESULT
  276. end;
  277. end;
  278. function set_rm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  279. begin
  280. asm
  281. movl intaddr,%eax
  282. movw (%eax),%dx
  283. movw 4(%eax),%cx
  284. movl $0x201,%eax
  285. movb vector,%bl
  286. int $0x31
  287. pushf
  288. call test_int31
  289. movb %al,__RESULT
  290. end;
  291. end;
  292. function get_rm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  293. begin
  294. asm
  295. movb vector,%bl
  296. movl $0x200,%eax
  297. int $0x31
  298. pushf
  299. call test_int31
  300. movb %al,__RESULT
  301. movl intaddr,%eax
  302. movzwl %dx,%edx
  303. movl %edx,(%eax)
  304. movw %cx,4(%eax)
  305. end;
  306. end;
  307. function free_rm_callback(var intaddr : tseginfo) : boolean;
  308. begin
  309. asm
  310. movl intaddr,%eax
  311. movw (%eax),%dx
  312. movw 4(%eax),%cx
  313. movl $0x304,%eax
  314. int $0x31
  315. pushf
  316. call test_int31
  317. movb %al,__RESULT
  318. end;
  319. end;
  320. function get_rm_callback(pm_func : pointer;const reg : trealregs;var rmcb : tseginfo) : boolean;
  321. begin
  322. asm
  323. movl pm_func,%esi
  324. movl reg,%edi
  325. pushw %es
  326. movw v2prt0_ds_alias,%ax
  327. movw %ax,%es
  328. pushw %ds
  329. movw %cs,%ax
  330. movw %ax,%ds
  331. movl $0x303,%eax
  332. int $0x31
  333. popw %ds
  334. popw %es
  335. pushf
  336. call test_int31
  337. movb %al,__RESULT
  338. movl rmcb,%eax
  339. movzwl %dx,%edx
  340. movl %edx,(%eax)
  341. movw %cx,4(%eax)
  342. end;
  343. end;
  344. function lock_linear_region(linearaddr, size : longint) : boolean;
  345. begin
  346. asm
  347. movl $0x600,%eax
  348. movl linearaddr,%ecx
  349. movl %ecx,%ebx
  350. shrl $16,%ebx
  351. movl size,%esi
  352. movl %esi,%edi
  353. shrl $16,%esi
  354. int $0x31
  355. pushf
  356. call test_int31
  357. movb %al,__RESULT
  358. end;
  359. end;
  360. function lock_code(functionaddr : pointer;size : longint) : boolean;
  361. var
  362. linearaddr : longint;
  363. begin
  364. linearaddr:=longint(functionaddr)+get_segment_base_address(get_cs);
  365. lock_code:=lock_linear_region(linearaddr,size);
  366. end;
  367. {$endif ndef IN_DPMIEXCP_UNIT}
  368. {****************************************************************************
  369. Helpers
  370. ****************************************************************************}
  371. procedure err(const x : string);
  372. begin
  373. write(stderr, x);
  374. end;
  375. procedure errln(const x : string);
  376. begin
  377. writeln(stderr, x);
  378. end;
  379. procedure itox(v,len : longint);
  380. var
  381. st : string;
  382. begin
  383. st:=hexstr(v,len);
  384. err(st);
  385. end;
  386. {****************************************************************************
  387. SetJmp/LongJmp
  388. ****************************************************************************}
  389. {$ifdef CREATE_C_FUNCTIONS}
  390. function c_setjmp(var rec : dpmi_jmp_buf) : longint;[public, alias : '_setjmp'];
  391. begin
  392. { here we need to be subtle :
  393. - we need to return with the arg still on the stack
  394. - but we also need to jmp to FPC_setjmp and not to call it
  395. because otherwise the return address is wrong !!
  396. For this we shift the return address down and
  397. duplicate the rec on stack }
  398. asm
  399. movl %ebp,%esp
  400. popl %ebp
  401. subl $8,%esp
  402. movl %eax,(%esp)
  403. movl 8(%esp),%eax
  404. movl %eax,4(%esp)
  405. movl 12(%esp),%eax
  406. movl %eax,8(%esp)
  407. popl %eax
  408. jmp dpmi_setjmp
  409. end;
  410. end;
  411. {$endif CREATE_C_FUNCTIONS}
  412. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  413. {$ifndef CREATE_C_FUNCTIONS}
  414. external name 'FPC_setjmp';
  415. {$else CREATE_C_FUNCTIONS}
  416. [alias : 'FPC_setjmp'];
  417. begin
  418. asm
  419. pushl %edi
  420. movl rec,%edi
  421. movl %eax,(%edi)
  422. movl %ebx,4(%edi)
  423. movl %ecx,8(%edi)
  424. movl %edx,12(%edi)
  425. movl %esi,16(%edi)
  426. { load edi }
  427. movl -4(%ebp),%eax
  428. { ... and store it }
  429. movl %eax,20(%edi)
  430. { ebp ... }
  431. movl (%ebp),%eax
  432. movl %eax,24(%edi)
  433. { esp ... }
  434. movl %esp,%eax
  435. addl $12,%eax
  436. movl %eax,28(%edi)
  437. { the return address }
  438. movl 4(%ebp),%eax
  439. movl %eax,32(%edi)
  440. { flags ... }
  441. pushfl
  442. popl 36(%edi)
  443. { !!!!! the segment registers, not yet needed }
  444. { you need them if the exception comes from
  445. an interrupt or a seg_move }
  446. movw %cs,40(%edi)
  447. movw %ds,42(%edi)
  448. movw %es,44(%edi)
  449. movw %fs,46(%edi)
  450. movw %gs,48(%edi)
  451. movw %ss,50(%edi)
  452. movl djgpp_exception_state_ptr, %eax
  453. movl %eax, 60(%edi)
  454. { restore EDI }
  455. pop %edi
  456. { we come from the initial call }
  457. xorl %eax,%eax
  458. movl %eax,__RESULT
  459. { leave USING RET inside CDECL functions is risky as
  460. some registers are pushed at entry
  461. ret $4 not anymore since cdecl !! }
  462. end;
  463. end;
  464. {$endif CREATE_C_FUNCTIONS}
  465. {$ifdef CREATE_C_FUNCTIONS}
  466. procedure c_longjmp(var rec : dpmi_jmp_buf;return_value : longint);[public, alias : '_longjmp'];
  467. begin
  468. dpmi_longjmp(rec,return_value);
  469. { never gets here !! so pascal stack convention is no problem }
  470. end;
  471. {$endif CREATE_C_FUNCTIONS}
  472. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  473. {$ifndef CREATE_C_FUNCTIONS}
  474. external name 'FPC_longjmp';
  475. {$else CREATE_C_FUNCTIONS}
  476. [public, alias : 'FPC_longjmp'];
  477. begin
  478. if (exception_level>0) then
  479. dec(exception_level);
  480. asm
  481. { restore compiler shit }
  482. popl %ebp
  483. { copy from longjmp.S }
  484. movl 4(%esp),%edi { get dpmi_jmp_buf }
  485. movl 8(%esp),%eax { store retval in j->eax }
  486. movl %eax,0(%edi)
  487. movw 46(%edi),%fs
  488. movw 48(%edi),%gs
  489. movl 4(%edi),%ebx
  490. movl 8(%edi),%ecx
  491. movl 12(%edi),%edx
  492. movl 24(%edi),%ebp
  493. { Now for some uglyness. The dpmi_jmp_buf structure may be ABOVE the
  494. point on the new SS:ESP we are moving to. We don't allow overlap,
  495. but do force that it always be valid. We will use ES:ESI for
  496. our new stack before swapping to it. }
  497. movw 50(%edi),%es
  498. movl 28(%edi),%esi
  499. subl $28,%esi { We need 7 working longwords on stack }
  500. movl 60(%edi),%eax
  501. movl %eax,%es:(%esi) { Exception pointer }
  502. movzwl 42(%edi),%eax
  503. movl %eax,%es:4(%esi) { DS }
  504. movl 20(%edi),%eax
  505. movl %eax,%es:8(%esi) { EDI }
  506. movl 16(%edi),%eax
  507. movl %eax,%es:12(%esi) { ESI }
  508. movl 32(%edi),%eax
  509. movl %eax,%es:16(%esi) { EIP - start of IRET frame }
  510. movl 40(%edi),%eax
  511. movl %eax,%es:20(%esi) { CS }
  512. movl 36(%edi),%eax
  513. movl %eax,%es:24(%esi) { EFLAGS }
  514. movl 0(%edi),%eax
  515. movw 44(%edi),%es
  516. movw 50(%edi),%ss
  517. movl %esi,%esp
  518. popl djgpp_exception_state_ptr
  519. popl %ds
  520. popl %edi
  521. popl %esi
  522. iret { actually jump to new cs:eip loading flags }
  523. end;
  524. end;
  525. {$endif CREATE_C_FUNCTIONS}
  526. {****************************************************************************
  527. Signals
  528. ****************************************************************************}
  529. var
  530. signal_list : Array[0..SIGMAX] of SignalHandler;cvar;
  531. {$ifndef CREATE_C_FUNCTIONS}external;{$endif}
  532. {$ifdef CREATE_C_FUNCTIONS}
  533. function SIG_ERR(x:longint):longint;[public,alias : '___djgpp_SIG_ERR'];
  534. begin
  535. SIG_ERR:=-1;
  536. end;
  537. function SIG_IGN(x:longint):longint;[public,alias : '___djgpp_SIG_IGN'];
  538. begin
  539. SIG_IGN:=-1;
  540. end;
  541. function SIG_DFL(x:longint):longint;[public,alias : '___djgpp_SIG_DFL'];
  542. begin
  543. SIG_DFL:=0;
  544. end;
  545. {$else CREATE_C_FUNCTIONS}
  546. function SIG_ERR(x:longint):longint;external name '___djgpp_SIG_ERR';
  547. function SIG_IGN(x:longint):longint;external name '___djgpp_SIG_IGN';
  548. function SIG_DFL(x:longint):longint;external name '___djgpp_SIG_DFL';
  549. {$endif CREATE_C_FUNCTIONS}
  550. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  551. var
  552. temp : SignalHandler;
  553. begin
  554. if ((sig < 0) or (sig > SIGMAX) or (sig = SIGKILL)) then
  555. begin
  556. signal:=@SIG_ERR;
  557. runerror(201);
  558. end;
  559. temp := signal_list[sig];
  560. signal_list[sig] := func;
  561. signal:=temp;
  562. end;
  563. {$ifdef CREATE_C_FUNCTIONS}
  564. { C counter part }
  565. function c_signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;[public,alias : '_signal'];
  566. var
  567. temp : SignalHandler;
  568. begin
  569. temp:=signal(sig,func);
  570. c_signal:=temp;
  571. end;
  572. {$endif CREATE_C_FUNCTIONS}
  573. const
  574. signames : array [0..14] of string[4] = (
  575. 'ABRT','FPE ','ILL ','SEGV','TERM','ALRM','HUP ',
  576. 'INT ','KILL','PIPE','QUIT','USR1','USR2','NOFP','TRAP');
  577. procedure print_signal_name(sig : longint);
  578. begin
  579. if ((sig >= SIGABRT) and (sig <= SIGTRAP)) then
  580. begin
  581. err('Exiting due to signal SIG');
  582. err(signames[sig-sigabrt]);
  583. end
  584. else
  585. begin
  586. err('Exiting due to signal $');
  587. itox(sig, 4);
  588. end;
  589. errln('');
  590. end;
  591. function _raise(sig : longint) : longint;
  592. var
  593. temp : SignalHandler;
  594. begin
  595. if(sig < 0) or (sig > SIGMAX) then
  596. exit(-1);
  597. temp:=signal_list[sig];
  598. if (temp = SignalHandler(@SIG_IGN)) then
  599. exit(0);
  600. if (temp = SignalHandler(@SIG_DFL)) then
  601. begin
  602. print_signal_name(sig);
  603. do_faulting_finish_message(djgpp_exception_state<>nil); { Exits, does not return }
  604. exit(-1);
  605. end;
  606. { this is incompatible with dxegen-dxeload stuff PM }
  607. if ((cardinal(temp) < cardinal(@starttext)) or
  608. (cardinal(temp) > cardinal(@endtext))) then
  609. begin
  610. errln('Bad signal handler, ');
  611. print_signal_name(sig);
  612. do_faulting_finish_message(djgpp_exception_state<>nil); { Exits, does not return }
  613. exit(-1);
  614. end;
  615. { WARNING !!! temp can be a pascal or a C
  616. function... thus %esp can be modified here !!!
  617. This might be dangerous for some optimizations ?? PM }
  618. temp(sig);
  619. exit(0);
  620. end;
  621. {$ifdef CREATE_C_FUNCTIONS}
  622. function c_raise(sig : longint) : longint;cdecl;[public,alias : '_raise'];
  623. begin
  624. c_raise:=_raise(sig);
  625. end;
  626. {$endif CREATE_C_FUNCTIONS}
  627. {****************************************************************************
  628. Exceptions
  629. ****************************************************************************}
  630. {$ifdef CREATE_C_FUNCTIONS}
  631. function except_to_sig(excep : longint) : longint;
  632. begin
  633. case excep of
  634. 5,8,9,11,12,13,14 : exit(SIGSEGV);
  635. 0,4,16 : exit(SIGFPE);
  636. 1,3 : exit(SIGTRAP);
  637. 7 : exit(SIGNOFP);
  638. else
  639. begin
  640. case excep of
  641. $75 : exit(SIGFPE);
  642. $78 : exit(SIGTIMR);
  643. $1b,
  644. $79 : exit(SIGINT);
  645. $7a : exit(SIGQUIT);
  646. else
  647. exit(SIGILL);
  648. end;
  649. end;
  650. end;
  651. end;
  652. procedure show_call_frame(djgpp_exception_state : pexception_state);
  653. begin
  654. errln('Call frame traceback EIPs:');
  655. errln(' 0x'+hexstr(djgpp_exception_state^.__eip, 8));
  656. dump_stack(stderr,djgpp_exception_state^.__ebp);
  657. end;
  658. const
  659. EXCEPTIONCOUNT = 18;
  660. exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (
  661. 'Division by Zero',
  662. 'Debug',
  663. 'NMI',
  664. 'Breakpoint',
  665. 'Overflow',
  666. 'Bounds Check',
  667. 'Invalid Opcode',
  668. 'Coprocessor not available',
  669. 'Double Fault',
  670. 'Coprocessor overrun',
  671. 'Invalid TSS',
  672. 'Segment Not Present',
  673. 'Stack Fault',
  674. 'General Protection Fault',
  675. 'Page fault',
  676. ' ',
  677. 'Coprocessor Error',
  678. 'Alignment Check');
  679. has_error : array [0..EXCEPTIONCOUNT-1] of byte =
  680. (0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1);
  681. cbrk_hooked : boolean = false;
  682. old_video_mode : byte = 3;
  683. procedure dump_selector(const name : string; sel : word);
  684. var
  685. base,limit : longint;
  686. begin
  687. err(name);
  688. err(': sel=');
  689. itox(sel, 4);
  690. if (sel<>0) then
  691. begin
  692. base:=get_segment_base_address(sel);
  693. err(' base='); itox(base, 8);
  694. limit:=get_segment_limit(sel);
  695. err(' limit='); itox(limit, 8);
  696. end;
  697. errln('');
  698. end;
  699. function farpeekb(sel : word;offset : longint) : byte;
  700. var
  701. b : byte;
  702. begin
  703. {$ifdef IN_DPMIEXCP_UNIT}
  704. seg_move(sel,offset,get_ds,longint(@b),1);
  705. {$else not IN_DPMIEXCP_UNIT}
  706. sysseg_move(sel,offset,get_ds,longint(@b),1);
  707. {$endif IN_DPMIEXCP_UNIT}
  708. farpeekb:=b;
  709. end;
  710. const message_level : byte = 0;
  711. procedure ___exit(c:longint);cdecl;external name '___exit';
  712. {$endif CREATE_C_FUNCTIONS}
  713. function do_faulting_finish_message(fake : boolean) : integer;cdecl;
  714. {$ifndef CREATE_C_FUNCTIONS}
  715. external;
  716. {$else CREATE_C_FUNCTIONS}
  717. public;
  718. var
  719. en : pchar;
  720. signum,i : longint;
  721. old_vid : byte;
  722. label
  723. simple_exit;
  724. begin
  725. inc(message_level);
  726. if message_level>2 then
  727. goto simple_exit;
  728. do_faulting_finish_message:=0;
  729. signum:=djgpp_exception_state_ptr^.__signum;
  730. { check video mode for original here and reset (not if PC98) */ }
  731. if ((go32_info_block.linear_address_of_primary_screen <> $a0000) and
  732. (farpeekb(dosmemselector, $449) <> old_video_mode)) then
  733. begin
  734. old_vid:=old_video_mode;
  735. asm
  736. pusha
  737. movzbl old_vid,%eax
  738. int $0x10
  739. popa
  740. nop
  741. end;
  742. end;
  743. if (signum >= EXCEPTIONCOUNT) then
  744. begin
  745. case signum of
  746. $75 : en:='Floating Point exception';
  747. $1b : en:='Control-Break Pressed';
  748. $79 : en:='Control-C Pressed';
  749. else
  750. en:=nil;
  751. end;
  752. end
  753. else
  754. en:=exception_names[signum];
  755. if (en = nil) then
  756. begin
  757. if fake then
  758. err('Raised ')
  759. else
  760. err('Exception ');
  761. itox(signum, 2);
  762. err(' at eip=');
  763. itox(djgpp_exception_state_ptr^.__eip, 8);
  764. end
  765. else
  766. begin
  767. write(stderr, 'FPC ',en);
  768. err(' at eip=');
  769. itox(djgpp_exception_state_ptr^.__eip, 8);
  770. end;
  771. { Control-C should stop the program also !}
  772. {if (signum = $79) then
  773. begin
  774. errln('');
  775. exit(-1);
  776. end;}
  777. if ((signum < EXCEPTIONCOUNT) and (has_error[signum]=1)) then
  778. begin
  779. errorcode := djgpp_exception_state_ptr^.__sigmask and $ffff;
  780. if(errorcode<>0) then
  781. begin
  782. err(', error=');
  783. itox(errorcode, 4);
  784. end;
  785. end;
  786. errln('');
  787. err('eax=');
  788. itox(djgpp_exception_state_ptr^.__eax, 8);
  789. err(' ebx='); itox(djgpp_exception_state_ptr^.__ebx, 8);
  790. err(' ecx='); itox(djgpp_exception_state_ptr^.__ecx, 8);
  791. err(' edx='); itox(djgpp_exception_state_ptr^.__edx, 8);
  792. err(' esi='); itox(djgpp_exception_state_ptr^.__esi, 8);
  793. err(' edi='); itox(djgpp_exception_state_ptr^.__edi, 8);
  794. errln('');
  795. err('ebp='); itox(djgpp_exception_state_ptr^.__ebp, 8);
  796. err(' esp='); itox(djgpp_exception_state_ptr^.__esp, 8);
  797. err(' program=');
  798. errln(paramstr(0));
  799. dump_selector('cs', djgpp_exception_state_ptr^.__cs);
  800. dump_selector('ds', djgpp_exception_state_ptr^.__ds);
  801. dump_selector('es', djgpp_exception_state_ptr^.__es);
  802. dump_selector('fs', djgpp_exception_state_ptr^.__fs);
  803. dump_selector('gs', djgpp_exception_state_ptr^.__gs);
  804. dump_selector('ss', djgpp_exception_state_ptr^.__ss);
  805. errln('');
  806. if (djgpp_exception_state_ptr^.__cs = get_cs) then
  807. show_call_frame(djgpp_exception_state_ptr)
  808. {$ifdef DPMIEXCP_DEBUG}
  809. else
  810. errln('Exception occured in another context');
  811. {$endif def DPMIEXCP_DEBUG}
  812. ;
  813. if assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  814. if (djgpp_exception_state_ptr^.__exception_ptr^.__cs = get_cs) then
  815. begin
  816. Errln('First exception level stack');
  817. show_call_frame(djgpp_exception_state_ptr^.__exception_ptr);
  818. end
  819. {$ifdef DPMIEXCP_DEBUG}
  820. else
  821. begin
  822. errln('First exception occured in another context');
  823. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  824. do_faulting_finish_message(false);
  825. end;
  826. {$endif def DPMIEXCP_DEBUG}
  827. ;
  828. { must not return !! }
  829. simple_exit:
  830. if exceptions_on then
  831. djgpp_exception_toggle;
  832. ___exit(-1);
  833. end;
  834. {$endif CREATE_C_FUNCTIONS}
  835. function djgpp_exception_state:pexception_state;assembler;
  836. asm
  837. movl djgpp_exception_state_ptr,%eax
  838. end;
  839. {$ifdef CREATE_C_FUNCTIONS}
  840. procedure djgpp_exception_processor;[public,alias : '___djgpp_exception_processor'];
  841. var
  842. sig : longint;
  843. begin
  844. if not assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  845. exception_level:=1
  846. else
  847. inc(exception_level);
  848. sig:=djgpp_exception_state_ptr^.__signum;
  849. if (exception_level=1) or (sig=$78) then
  850. begin
  851. sig := except_to_sig(sig);
  852. if signal_list[djgpp_exception_state_ptr^.__signum]
  853. <>SignalHandler(@SIG_DFL) then
  854. _raise(djgpp_exception_state_ptr^.__signum)
  855. else
  856. _raise(sig);
  857. if (djgpp_exception_state_ptr^.__signum >= EXCEPTIONCOUNT) then
  858. { Not exception so continue OK }
  859. dpmi_longjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^, djgpp_exception_state_ptr^.__eax);
  860. { User handler did not exit or longjmp, we must exit }
  861. err('FPC cannot continue from exception, exiting due to signal ');
  862. itox(sig, 4);
  863. errln('');
  864. end
  865. else
  866. begin
  867. if exception_level>2 then
  868. begin
  869. if exception_level=3 then
  870. errln('FPC triple exception, exiting !!! ');
  871. if (exceptions_on) then
  872. djgpp_exception_toggle;
  873. ___exit(1);
  874. end;
  875. err('FPC double exception, exiting due to signal ');
  876. itox(sig, 4);
  877. errln('');
  878. end;
  879. do_faulting_finish_message(djgpp_exception_state<>nil);
  880. end;
  881. type
  882. trealseginfo = tseginfo;
  883. pseginfo = ^tseginfo;
  884. var
  885. except_ori : array [0..EXCEPTIONCOUNT-1] of tseginfo;
  886. {$ifdef DPMIEXCP_DEBUG}
  887. export name '_ori_exceptions';
  888. {$endif def DPMIEXCP_DEBUG}
  889. kbd_ori : tseginfo;
  890. npx_ori : tseginfo;
  891. cbrk_ori,
  892. cbrk_rmcb : trealseginfo;
  893. cbrk_regs : trealregs;
  894. v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  895. procedure djgpp_exception_toggle;
  896. [public,alias : '___djgpp_exception_toggle'];
  897. var
  898. _except : tseginfo;
  899. i : longint;
  900. begin
  901. {$ifdef DPMIEXCP_DEBUG}
  902. if exceptions_on then
  903. errln('Disabling FPC exceptions')
  904. else
  905. errln('Enabling FPC exceptions');
  906. {$endif DPMIEXCP_DEBUG}
  907. { toggle here to avoid infinite recursion }
  908. { if a subfunction calls runerror !! }
  909. exceptions_on:=not exceptions_on;
  910. v2prt0_exceptions_on:=exceptions_on;
  911. for i:=0 to EXCEPTIONCOUNT-1 do
  912. begin
  913. if get_pm_exception_handler(i,_except) then
  914. begin
  915. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  916. begin
  917. if not set_pm_exception_handler(i,except_ori[i]) then
  918. errln('error setting exception nø'+hexstr(i,2));
  919. end;
  920. except_ori[i]:=_except;
  921. end
  922. else
  923. begin
  924. if get_exception_handler(i,_except) then
  925. begin
  926. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  927. begin
  928. if not set_exception_handler(i,except_ori[i]) then
  929. errln('error setting exception nø'+hexstr(i,2));
  930. end;
  931. except_ori[i]:=_except;
  932. end;
  933. end;
  934. end;
  935. get_pm_interrupt($75,_except);
  936. set_pm_interrupt($75,npx_ori);
  937. npx_ori:=_except;
  938. get_pm_interrupt(9,_except);
  939. set_pm_interrupt(9,kbd_ori);
  940. kbd_ori:=_except;
  941. if (cbrk_hooked) then
  942. begin
  943. set_rm_interrupt(cbrk_vect,cbrk_ori);
  944. free_rm_callback(cbrk_rmcb);
  945. cbrk_hooked := false;
  946. {$ifdef DPMIEXCP_DEBUG}
  947. errln('back to ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  948. {$endif DPMIEXCP_DEBUG}
  949. end
  950. else
  951. begin
  952. get_rm_interrupt(cbrk_vect, cbrk_ori);
  953. {$ifdef DPMIEXCP_DEBUG}
  954. errln('ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  955. {$endif DPMIEXCP_DEBUG}
  956. get_rm_callback(@djgpp_cbrk_hdlr, cbrk_regs, cbrk_rmcb);
  957. set_rm_interrupt(cbrk_vect, cbrk_rmcb);
  958. {$ifdef DPMIEXCP_DEBUG}
  959. errln('now rm cbrk '+hexstr(cbrk_rmcb.segment,4)+':'+hexstr(longint(cbrk_rmcb.offset),4));
  960. {$endif DPMIEXCP_DEBUG}
  961. cbrk_hooked := true;
  962. end;
  963. end;
  964. {$endif CREATE_C_FUNCTIONS}
  965. function dpmi_set_coprocessor_emulation(flag : longint) : longint;
  966. var
  967. res : longint;
  968. begin
  969. asm
  970. movl flag,%ebx
  971. movl $0xe01,%eax
  972. int $0x31
  973. jc .L_coproc_error
  974. xorl %eax,%eax
  975. .L_coproc_error:
  976. movl %eax,res
  977. end;
  978. dpmi_set_coprocessor_emulation:=res;
  979. end;
  980. {$ifdef CREATE_C_FUNCTIONS}
  981. var
  982. _swap_in : pointer;external name '_swap_in';
  983. _swap_out : pointer;external name '_swap_out';
  984. _exception_exit : pointer;external name '_exception_exit';
  985. procedure dpmiexcp_exit{(status : longint)};[public,alias : 'excep_exit'];
  986. { We need to restore hardware interrupt handlers even if somebody calls
  987. `_exit' directly, or else we crash the machine in nested programs.
  988. We only toggle the handlers if the original keyboard handler is intact
  989. (otherwise, they might have already toggled them). }
  990. begin
  991. if (exceptions_on) then
  992. djgpp_exception_toggle;
  993. _exception_exit:=nil;
  994. _swap_in:=nil;
  995. _swap_out:=nil;
  996. { restore the FPU state }
  997. dpmi_set_coprocessor_emulation(1);
  998. end;
  999. { _exit in dpmiexcp.c
  1000. is already present in v2prt0.as PM}
  1001. { used by dos.pp for swap vectors }
  1002. procedure dpmi_swap_in;[public,alias : 'swap_in'];
  1003. begin
  1004. if not (exceptions_on) then
  1005. djgpp_exception_toggle;
  1006. end;
  1007. procedure dpmi_swap_out;[public,alias : 'swap_out'];
  1008. begin
  1009. if (exceptions_on) then
  1010. djgpp_exception_toggle;
  1011. end;
  1012. var
  1013. ___djgpp_app_DS : word;external name '___djgpp_app_DS';
  1014. ___djgpp_our_DS : word;external name '___djgpp_our_DS';
  1015. __djgpp_sigint_mask : word;external name '___djgpp_sigint_mask';
  1016. __djgpp_sigint_key : word;external name '___djgpp_sigint_key';
  1017. __djgpp_sigquit_mask : word;external name '___djgpp_sigquit_mask';
  1018. __djgpp_sigquit_key : word;external name '___djgpp_sigquit_key';
  1019. { to avoid loading of C lib version of dpmiexcp
  1020. I need to have all exported assembler labels
  1021. of dpmiexcp.c in this unit.
  1022. DJGPP v2.03 add to new functions:
  1023. __djgpp_set_sigint_key
  1024. __djgpp_set_sigquit_key
  1025. that I implement here simply translating C code PM }
  1026. Const
  1027. LSHIFT = 1;
  1028. RSHIFT = 2;
  1029. CTRL = 4;
  1030. ALT = 8;
  1031. DEFAULT_SIGINT = $042e; { Ctrl-C: scan code 2Eh, kb status 04h }
  1032. DEFAULT_SIGQUIT = $042b; { Ctrl-\: scan code 2Bh, kb status 04h }
  1033. DEFAULT_SIGINT_98 = $042b; { Ctrl-C: scan code 2Bh, kb status 04h }
  1034. DEFAULT_SIGQUIT_98 = $040d; { Ctrl-\: scan code 0Dh, kb status 04h }
  1035. { Make it so the key NEW_KEY will generate the signal SIG.
  1036. NEW_KEY must include the keyboard status byte in bits 8-15 and the
  1037. scan code in bits 0-7. }
  1038. function set_signal_key(sig,new_key : longint) : longint;
  1039. type
  1040. pword = ^word;
  1041. var
  1042. old_key : longint;
  1043. mask,key : pword;
  1044. kb_status : word;
  1045. begin
  1046. if (sig = SIGINT) then
  1047. begin
  1048. mask := @__djgpp_sigint_mask;
  1049. key := @__djgpp_sigint_key;
  1050. end
  1051. else if (sig = SIGQUIT) then
  1052. begin
  1053. mask := @__djgpp_sigquit_mask;
  1054. key := @__djgpp_sigquit_key;
  1055. end
  1056. else
  1057. exit(-1);
  1058. old_key := key^;
  1059. key^ := new_key and $ffff;
  1060. kb_status := key^ shr 8;
  1061. mask^ := $f; { Alt, Ctrl and Shift bits only }
  1062. { Mask off the RShift bit unless they explicitly asked for it.
  1063. Our keyboard handler pretends that LShift is pressed when they
  1064. press RShift. }
  1065. if ((kb_status and RSHIFT) = 0) then
  1066. mask^ :=mask^ and not RSHIFT;
  1067. { Mask off the LShift bit if any of the Ctrl or Alt are set
  1068. since Shift doesn't matter when Ctrl and/or Alt are pressed. }
  1069. if (kb_status and (CTRL or ALT))<>0 then
  1070. mask^:= mask^ and not LSHIFT;
  1071. exit(old_key);
  1072. end;
  1073. function __djgpp_set_sigint_key(new_key : longint) : longint;cdecl;
  1074. begin
  1075. __djgpp_set_sigint_key:=set_signal_key(SIGINT, new_key);
  1076. end;
  1077. function __djgpp_set_sigquit_key(new_key : longint) : longint;cdecl;
  1078. begin
  1079. __djgpp_set_sigquit_key:=set_signal_key(SIGQUIT, new_key);
  1080. end;
  1081. function __djgpp__traceback_exit(sig : longint) : longint;cdecl;
  1082. var
  1083. fake_exception : texception_state;
  1084. begin
  1085. if (sig >= SIGABRT) and (sig <= SIGTRAP) then
  1086. begin
  1087. if djgpp_exception_state_ptr=nil then
  1088. begin
  1089. { This is a software signal, like SIGABRT or SIGKILL.
  1090. Fill the exception structure, so we get the traceback. }
  1091. djgpp_exception_state_ptr:=@fake_exception;
  1092. if (dpmi_setjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^)<>0) then
  1093. begin
  1094. errln('Bad longjmp to __djgpp_exception_state--aborting');
  1095. do_faulting_finish_message(true); { does not return }
  1096. end
  1097. else
  1098. { Fake the exception number. 7Ah is the last one hardwired
  1099. inside exceptn.S, for SIGQUIT. }
  1100. djgpp_exception_state_ptr^.__signum:=$7a + 1 + sig - SIGABRT;
  1101. end;
  1102. end;
  1103. print_signal_name(sig);
  1104. if assigned(djgpp_exception_state_ptr) then
  1105. { This exits, does not return. }
  1106. do_faulting_finish_message(djgpp_exception_state_ptr=@fake_exception);
  1107. ___exit(-1);
  1108. __djgpp__traceback_exit:=0;
  1109. end;
  1110. procedure djgpp_exception_setup;
  1111. [alias : '___djgpp_exception_setup'];
  1112. var
  1113. temp_kbd,
  1114. temp_npx : pointer;
  1115. _except,
  1116. old_kbd : tseginfo;
  1117. locksize : longint;
  1118. i : longint;
  1119. begin
  1120. if assigned(_exception_exit) then
  1121. exit;
  1122. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  1123. begin
  1124. __djgpp_set_sigint_key(DEFAULT_SIGINT);
  1125. __djgpp_set_sigquit_key(DEFAULT_SIGQUIT);
  1126. end
  1127. else
  1128. begin { for PC98 }
  1129. __djgpp_set_sigint_key(DEFAULT_SIGINT_98);
  1130. __djgpp_set_sigquit_key(DEFAULT_SIGQUIT_98);
  1131. end;
  1132. _exception_exit:=@dpmiexcp_exit;
  1133. _swap_in:=@dpmi_swap_in;
  1134. _swap_out:=@dpmi_swap_out;
  1135. { reset signals }
  1136. for i := 0 to SIGMAX do
  1137. signal_list[i] := SignalHandler(@SIG_DFL);
  1138. { app_DS only used when converting HW interrupts to exceptions }
  1139. asm
  1140. movw %ds,___djgpp_app_DS
  1141. movw %ds,___djgpp_our_DS
  1142. end;
  1143. djgpp_dos_sel:=dosmemselector;
  1144. { lock addresses which may see HW interrupts }
  1145. lock_code(@djgpp_hw_lock_start,@djgpp_hw_lock_end-@djgpp_hw_lock_start);
  1146. _except.segment:=get_cs;
  1147. _except.offset:=@djgpp_exception_table;
  1148. for i:=0 to ExceptionCount-1 do
  1149. begin
  1150. except_ori[i] := _except; { New value to set }
  1151. inc(_except.offset,4); { This is the size of push n, jmp }
  1152. end;
  1153. kbd_ori.segment:=_except.segment;
  1154. npx_ori.segment:=_except.segment;
  1155. npx_ori.offset:=@djgpp_npx_hdlr;
  1156. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  1157. kbd_ori.offset:=@djgpp_kbd_hdlr
  1158. else
  1159. begin
  1160. kbd_ori.offset:=@djgpp_kbd_hdlr_pc98;
  1161. cbrk_vect := $06;
  1162. _except.offset:=@djgpp_iret;
  1163. set_pm_interrupt($23,_except);
  1164. end;
  1165. _except.offset:=@djgpp_i24;
  1166. set_pm_interrupt($24, _except);
  1167. get_pm_interrupt(9,djgpp_old_kbd);
  1168. djgpp_exception_toggle; { Set new values & save old values }
  1169. { get original video mode and save }
  1170. old_video_mode := farpeekb(dosmemselector, $449);
  1171. end;
  1172. {$endif CREATE_C_FUNCTIONS}
  1173. function djgpp_set_ctrl_c(enable : boolean) : boolean;
  1174. begin
  1175. djgpp_set_ctrl_c:=(djgpp_hwint_flags and 1)=0;
  1176. if enable then
  1177. djgpp_hwint_flags:=djgpp_hwint_flags and (not 1)
  1178. else
  1179. djgpp_hwint_flags:=djgpp_hwint_flags or 1;
  1180. end;
  1181. {$ifdef CREATE_C_FUNCTIONS}
  1182. function c_djgpp_set_ctrl_c(enable : longint) : boolean;cdecl;[public,alias : '___djgpp_set_ctrl_c'];
  1183. begin
  1184. c_djgpp_set_ctrl_c:=djgpp_set_ctrl_c(boolean(enable));
  1185. end;
  1186. {$endif def CREATE_C_FUNCTIONS}
  1187. {$ifdef IN_DPMIEXCP_UNIT}
  1188. procedure ResetDefaultHandlers;
  1189. begin
  1190. Signal(SIGSEGV,@SIG_DFL);
  1191. Signal(SIGFPE,@SIG_DFL);
  1192. Signal(SIGNOFP,@SIG_DFL);
  1193. Signal(SIGTRAP,@SIG_DFL);
  1194. Signal(SIGTIMR,@SIG_DFL);
  1195. Signal(SIGINT,@SIG_DFL);
  1196. Signal(SIGQUIT,@SIG_DFL);
  1197. Signal(SIGILL,@SIG_DFL);
  1198. end;
  1199. {$endif IN_DPMIEXCP_UNIT}
  1200. procedure InitDPMIExcp;
  1201. begin
  1202. {$ifdef CREATE_C_FUNCTIONS}
  1203. djgpp_ds_alias:=v2prt0_ds_alias;
  1204. djgpp_exception_setup;
  1205. {$endif CREATE_C_FUNCTIONS}
  1206. end;
  1207. {$ifndef IN_SYSTEM}
  1208. begin
  1209. {$ifdef CREATE_C_FUNCTIONS}
  1210. InitDPMIExcp;
  1211. {$else not CREATE_C_FUNCTIONS}
  1212. ResetDefaultHandlers;
  1213. {$endif CREATE_C_FUNCTIONS}
  1214. end.
  1215. {$else IN_SYSTEM}
  1216. const
  1217. FPU_Invalid = 1;
  1218. FPU_Denormal = 2;
  1219. FPU_DivisionByZero = 4;
  1220. FPU_Overflow = 8;
  1221. FPU_Underflow = $10;
  1222. FPU_StackUnderflow = $20;
  1223. FPU_StackOverflow = $40;
  1224. FPU_ExceptionMask = $ff;
  1225. FPU_ControlWord : word = $1332;
  1226. function HandleException(sig : longint) : longint;
  1227. var
  1228. truesig : longint;
  1229. ErrorOfSig : longint;
  1230. FpuStatus,FPUControl : word;
  1231. eip,ebp : longint;
  1232. begin
  1233. if assigned(djgpp_exception_state_ptr) then
  1234. truesig:=djgpp_exception_state_ptr^.__signum
  1235. else
  1236. truesig:=sig;
  1237. ErrorOfSig:=0;
  1238. case truesig of
  1239. {exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (}
  1240. 0 : ErrorOfSig:=200; {'Division by Zero'}
  1241. 5 : ErrorOfSig:=201; {'Bounds Check'}
  1242. 12 : ErrorOfSig:=202; {'Stack Fault'}
  1243. 7, {'Coprocessor not available'}
  1244. 9, {'Coprocessor overrun'}
  1245. SIGNOFP : ErrorOfSig:=207;
  1246. 16,SIGFPE,$75 : begin
  1247. { This needs special handling }
  1248. { to discriminate between 205,206 and 207 }
  1249. if truesig=$75 then
  1250. fpustatus:=djgpp_exception_state_ptr^.__sigmask and $ffff
  1251. else
  1252. asm
  1253. fnstsw %ax
  1254. fnclex
  1255. movw %ax,fpustatus
  1256. end;
  1257. if (FpuStatus and FPU_Invalid)<>0 then
  1258. ErrorOfSig:=216
  1259. else if (FpuStatus and FPU_Denormal)<>0 then
  1260. ErrorOfSig:=216
  1261. else if (FpuStatus and FPU_DivisionByZero)<>0 then
  1262. ErrorOfSig:=200
  1263. else if (FpuStatus and FPU_Overflow)<>0 then
  1264. ErrorOfSig:=205
  1265. else if (FpuStatus and FPU_Underflow)<>0 then
  1266. ErrorOfSig:=206
  1267. else
  1268. ErrorOfSig:=207; {'Coprocessor Error'}
  1269. { if exceptions then Reset FPU and reload control word }
  1270. if (FPUStatus and FPU_ExceptionMask)<>0 then
  1271. asm
  1272. fninit
  1273. fldcw FPU_ControlWord
  1274. end;
  1275. end;
  1276. 4 : ErrorOfSig:=215; {'Overflow'}
  1277. 1, {'Debug'}
  1278. 2, {'NMI'}
  1279. 3, {'Breakpoint'}
  1280. 6, {'Invalid Opcode'}
  1281. 8, {'Double Fault'}
  1282. 10, {'Invalid TSS'}
  1283. 11, {'Segment Not Present'}
  1284. 13, {'General Protection Fault'}
  1285. 14, {'Page fault'}
  1286. 15, {' ',}
  1287. 17, {'Alignment Check');}
  1288. SIGSEGV,SIGTRAP,SIGTIMR,SIGINT,SIGQUIT
  1289. : ErrorOfSig:=216;
  1290. end;
  1291. if assigned(djgpp_exception_state_ptr) then
  1292. Begin
  1293. if exception_level>0 then
  1294. dec(exception_level);
  1295. eip:=djgpp_exception_state_ptr^.__eip;
  1296. ebp:=djgpp_exception_state_ptr^.__ebp;
  1297. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  1298. HandleErrorAddrFrame(ErrorOfSig,eip,ebp);
  1299. End
  1300. else
  1301. { probably higher level is required }
  1302. HandleErrorFrame(ErrorOfSig,get_caller_frame(get_frame));
  1303. HandleException:=0;
  1304. end;
  1305. procedure InstallDefaultHandlers;
  1306. begin
  1307. Signal(SIGSEGV,@HandleException);
  1308. Signal(SIGFPE,@HandleException);
  1309. Signal(SIGNOFP,@HandleException);
  1310. Signal(SIGTRAP,@HandleException);
  1311. Signal(SIGTIMR,@HandleException);
  1312. Signal(SIGINT,@HandleException);
  1313. Signal(SIGQUIT,@HandleException);
  1314. Signal(SIGILL,@HandleException);
  1315. end;
  1316. {$endif IN_SYSTEM}
  1317. {
  1318. $Log$
  1319. Revision 1.16 2000-03-31 23:19:12 pierre
  1320. * changed handling of interrupt 0x75 :
  1321. the status word is saved into ___djgpp_fpu_state
  1322. and inserted in __sigmaks field of djgpp exception record
  1323. BUT fnclex is called after to avoid a second interrupt
  1324. generation on fn??? calls
  1325. Revision 1.15 2000/03/30 13:40:57 pierre
  1326. * fix FPU and multiple exception problems
  1327. Revision 1.14 2000/03/13 19:45:21 pierre
  1328. + exceptions in system is default now
  1329. Revision 1.13 2000/03/10 09:53:17 pierre
  1330. * some clean up for exceptions in system
  1331. Revision 1.12 2000/03/09 09:15:10 pierre
  1332. + support for djgpp v2.03 (added some new functions that are in v2.03 ofdpmiexcp.c)
  1333. + code to integrate exception support inside the system unit
  1334. Revision 1.10 2000/01/10 12:14:57 pierre
  1335. * add $goto on to avoid problems
  1336. Revision 1.9 2000/01/07 16:41:31 daniel
  1337. * copyright 2000
  1338. Revision 1.8 2000/01/07 16:32:23 daniel
  1339. * copyright 2000 added
  1340. Revision 1.7 1999/03/01 15:40:49 peter
  1341. * use external names
  1342. * removed all direct assembler modes
  1343. Revision 1.6 1999/02/05 12:49:25 pierre
  1344. <> debug conditionnal renamed DPMIEXCP_DEBUG
  1345. Revision 1.5 1999/01/22 15:46:33 pierre
  1346. * PsignalHandler is now a pointer as changed in linux.pp
  1347. Revision 1.4 1999/01/22 12:39:19 pierre
  1348. + added text arg for dump_stack
  1349. Revision 1.3 1999/01/18 09:14:20 pierre
  1350. * exception_level counting was wrong if dpmi_jmp_buf was copied
  1351. Revision 1.2 1998/12/21 14:23:12 pierre
  1352. dpmiexcp.pp
  1353. Revision 1.1 1998/12/21 13:07:02 peter
  1354. * use -FE
  1355. Revision 1.11 1998/11/17 09:42:50 pierre
  1356. * position check of signal handler was wrong
  1357. Revision 1.10 1998/10/13 21:42:42 peter
  1358. * cleanup and use of external var
  1359. * fixed ctrl-break crashes
  1360. Revision 1.9 1998/08/20 08:08:36 pierre
  1361. * dpmiexcp did not compile with older versions
  1362. due to the proc to procvar bug
  1363. * makefile separator problem fixed
  1364. Revision 1.8 1998/08/19 10:56:33 pierre
  1365. + added some special code for C interface
  1366. to avoid loading of crt1.o or dpmiexcp.o from the libc.a
  1367. Revision 1.7 1998/08/15 17:01:13 peter
  1368. * smartlinking the units works now
  1369. * setjmp/longjmp -> dmpi_setjmp/dpmi_longjmp to solve systemunit
  1370. conflict
  1371. Revision 1.6 1998/08/04 13:31:32 pierre
  1372. * changed all FPK into FPC
  1373. Revision 1.5 1998/07/08 12:02:19 carl
  1374. * make it compiler under fpc v0995
  1375. Revision 1.4 1998/06/26 08:19:08 pierre
  1376. + all debug in ifdef SYSTEMDEBUG
  1377. + added local arrays :
  1378. opennames names of opened files
  1379. fileopen boolean array to know if still open
  1380. usefull with gdb if you get problems about too
  1381. many open files !!
  1382. Revision 1.3 1998/05/31 14:18:23 peter
  1383. * force att or direct assembling
  1384. * cleanup of some files
  1385. Revision 1.2 1998/04/21 14:46:33 pierre
  1386. + debug info better output
  1387. no normal code changed
  1388. }