dpmiexcp.pp 44 KB

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