system.pp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2006 by Florian Klaempfl and Pavel Ozerski
  4. member of the Free Pascal development team.
  5. FPC Pascal system unit for the Win64 API.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit System;
  13. interface
  14. {$ifdef SYSTEMDEBUG}
  15. {$define SYSTEMEXCEPTIONDEBUG}
  16. {$endif SYSTEMDEBUG}
  17. { include system-independent routine headers }
  18. {$I systemh.inc}
  19. const
  20. LineEnding = #13#10;
  21. LFNSupport = true;
  22. DirectorySeparator = '\';
  23. DriveSeparator = ':';
  24. PathSeparator = ';';
  25. { FileNameCaseSensitive is defined separately below!!! }
  26. maxExitCode = 65535;
  27. MaxPathLen = 260;
  28. type
  29. PEXCEPTION_FRAME = ^TEXCEPTION_FRAME;
  30. TEXCEPTION_FRAME = record
  31. next : PEXCEPTION_FRAME;
  32. handler : pointer;
  33. end;
  34. const
  35. { Default filehandles }
  36. UnusedHandle : THandle = THandle(-1);
  37. StdInputHandle : THandle = 0;
  38. StdOutputHandle : THandle = 0;
  39. StdErrorHandle : THandle = 0;
  40. FileNameCaseSensitive : boolean = true;
  41. CtrlZMarksEOF: boolean = true; (* #26 not considered as end of file *)
  42. sLineBreak = LineEnding;
  43. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  44. { Thread count for DLL }
  45. Thread_count : longint = 0;
  46. type
  47. TStartupInfo = record
  48. cb : longint;
  49. lpReserved : Pointer;
  50. lpDesktop : Pointer;
  51. lpTitle : Pointer;
  52. dwX : longint;
  53. dwY : longint;
  54. dwXSize : longint;
  55. dwYSize : longint;
  56. dwXCountChars : longint;
  57. dwYCountChars : longint;
  58. dwFillAttribute : longint;
  59. dwFlags : longint;
  60. wShowWindow : Word;
  61. cbReserved2 : Word;
  62. lpReserved2 : Pointer;
  63. hStdInput : THandle;
  64. hStdOutput : THandle;
  65. hStdError : THandle;
  66. end;
  67. var
  68. { C compatible arguments }
  69. argc : longint;
  70. argv : ppchar;
  71. { Win32 Info }
  72. startupinfo : tstartupinfo;
  73. hprevinst,
  74. MainInstance,
  75. cmdshow : longint;
  76. DLLreason,DLLparam:longint;
  77. type
  78. TDLL_Process_Entry_Hook = function (dllparam : longint) : longbool;
  79. TDLL_Entry_Hook = procedure (dllparam : longint);
  80. const
  81. Dll_Process_Attach_Hook : TDLL_Process_Entry_Hook = nil;
  82. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  83. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  84. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  85. implementation
  86. var
  87. SysInstance : Longint;public;
  88. {$ifdef i386}
  89. {$define HAS_RESOURCES}
  90. {$i win32res.inc}
  91. {$endif}
  92. { used by wstrings.inc because wstrings.inc is included before sysos.inc
  93. this is put here (FK) }
  94. function SysAllocStringLen(psz:pointer;len:dword):pointer;stdcall;
  95. external 'oleaut32.dll' name 'SysAllocStringLen';
  96. procedure SysFreeString(bstr:pointer);stdcall;
  97. external 'oleaut32.dll' name 'SysFreeString';
  98. function SysReAllocStringLen(var bstr:pointer;psz: pointer;
  99. len:dword): Integer; stdcall;external 'oleaut32.dll' name 'SysReAllocStringLen';
  100. { include system independent routines }
  101. {$I system.inc}
  102. {*****************************************************************************
  103. Parameter Handling
  104. *****************************************************************************}
  105. var
  106. ModuleName : array[0..255] of char;
  107. function GetCommandFile:pchar;
  108. begin
  109. GetModuleFileName(0,@ModuleName,255);
  110. GetCommandFile:=@ModuleName;
  111. end;
  112. procedure setup_arguments;
  113. var
  114. arglen,
  115. count : longint;
  116. argstart,
  117. pc,arg : pchar;
  118. quote : char;
  119. argvlen : longint;
  120. procedure allocarg(idx,len:longint);
  121. var
  122. oldargvlen : longint;
  123. begin
  124. if idx>=argvlen then
  125. begin
  126. oldargvlen:=argvlen;
  127. argvlen:=(idx+8) and (not 7);
  128. sysreallocmem(argv,argvlen*sizeof(pointer));
  129. fillchar(argv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
  130. end;
  131. { use realloc to reuse already existing memory }
  132. { always allocate, even if length is zero, since }
  133. { the arg. is still present! }
  134. sysreallocmem(argv[idx],len+1);
  135. end;
  136. begin
  137. SetupProcVars;
  138. { create commandline, it starts with the executed filename which is argv[0] }
  139. { Win32 passes the command NOT via the args, but via getmodulefilename}
  140. count:=0;
  141. argv:=nil;
  142. argvlen:=0;
  143. pc:=getcommandfile;
  144. Arglen:=0;
  145. repeat
  146. Inc(Arglen);
  147. until (pc[Arglen]=#0);
  148. allocarg(count,arglen);
  149. move(pc^,argv[count]^,arglen+1);
  150. { Setup cmdline variable }
  151. cmdline:=GetCommandLine;
  152. { process arguments }
  153. pc:=cmdline;
  154. {$IfDef SYSTEM_DEBUG_STARTUP}
  155. Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
  156. {$EndIf }
  157. while pc^<>#0 do
  158. begin
  159. { skip leading spaces }
  160. while pc^ in [#1..#32] do
  161. inc(pc);
  162. if pc^=#0 then
  163. break;
  164. { calc argument length }
  165. quote:=' ';
  166. argstart:=pc;
  167. arglen:=0;
  168. while (pc^<>#0) do
  169. begin
  170. case pc^ of
  171. #1..#32 :
  172. begin
  173. if quote<>' ' then
  174. inc(arglen)
  175. else
  176. break;
  177. end;
  178. '"' :
  179. begin
  180. if quote<>'''' then
  181. begin
  182. if pchar(pc+1)^<>'"' then
  183. begin
  184. if quote='"' then
  185. quote:=' '
  186. else
  187. quote:='"';
  188. end
  189. else
  190. inc(pc);
  191. end
  192. else
  193. inc(arglen);
  194. end;
  195. '''' :
  196. begin
  197. if quote<>'"' then
  198. begin
  199. if pchar(pc+1)^<>'''' then
  200. begin
  201. if quote='''' then
  202. quote:=' '
  203. else
  204. quote:='''';
  205. end
  206. else
  207. inc(pc);
  208. end
  209. else
  210. inc(arglen);
  211. end;
  212. else
  213. inc(arglen);
  214. end;
  215. inc(pc);
  216. end;
  217. { copy argument }
  218. { Don't copy the first one, it is already there.}
  219. If Count<>0 then
  220. begin
  221. allocarg(count,arglen);
  222. quote:=' ';
  223. pc:=argstart;
  224. arg:=argv[count];
  225. while (pc^<>#0) do
  226. begin
  227. case pc^ of
  228. #1..#32 :
  229. begin
  230. if quote<>' ' then
  231. begin
  232. arg^:=pc^;
  233. inc(arg);
  234. end
  235. else
  236. break;
  237. end;
  238. '"' :
  239. begin
  240. if quote<>'''' then
  241. begin
  242. if pchar(pc+1)^<>'"' then
  243. begin
  244. if quote='"' then
  245. quote:=' '
  246. else
  247. quote:='"';
  248. end
  249. else
  250. inc(pc);
  251. end
  252. else
  253. begin
  254. arg^:=pc^;
  255. inc(arg);
  256. end;
  257. end;
  258. '''' :
  259. begin
  260. if quote<>'"' then
  261. begin
  262. if pchar(pc+1)^<>'''' then
  263. begin
  264. if quote='''' then
  265. quote:=' '
  266. else
  267. quote:='''';
  268. end
  269. else
  270. inc(pc);
  271. end
  272. else
  273. begin
  274. arg^:=pc^;
  275. inc(arg);
  276. end;
  277. end;
  278. else
  279. begin
  280. arg^:=pc^;
  281. inc(arg);
  282. end;
  283. end;
  284. inc(pc);
  285. end;
  286. arg^:=#0;
  287. end;
  288. {$IfDef SYSTEM_DEBUG_STARTUP}
  289. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  290. {$EndIf SYSTEM_DEBUG_STARTUP}
  291. inc(count);
  292. end;
  293. { get argc and create an nil entry }
  294. argc:=count;
  295. allocarg(argc,0);
  296. { free unused memory }
  297. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  298. end;
  299. function paramcount : longint;
  300. begin
  301. paramcount := argc - 1;
  302. end;
  303. function paramstr(l : longint) : string;
  304. begin
  305. if (l>=0) and (l<argc) then
  306. paramstr:=strpas(argv[l])
  307. else
  308. paramstr:='';
  309. end;
  310. procedure randomize;
  311. begin
  312. randseed:=GetTickCount;
  313. end;
  314. {*****************************************************************************
  315. System Dependent Exit code
  316. *****************************************************************************}
  317. procedure install_exception_handlers;forward;
  318. procedure remove_exception_handlers;forward;
  319. procedure PascalMain;stdcall;external name 'PASCALMAIN';
  320. procedure fpc_do_exit;stdcall;external name 'FPC_DO_EXIT';
  321. Procedure ExitDLL(Exitcode : longint); forward;
  322. Procedure system_exit;
  323. begin
  324. { don't call ExitProcess inside
  325. the DLL exit code !!
  326. This crashes Win95 at least PM }
  327. if IsLibrary then
  328. ExitDLL(ExitCode);
  329. if not IsConsole then
  330. begin
  331. Close(stderr);
  332. Close(stdout);
  333. { what about Input and Output ?? PM }
  334. end;
  335. remove_exception_handlers;
  336. { call exitprocess, with cleanup as required }
  337. ExitProcess(exitcode);
  338. end;
  339. var
  340. { old compilers emitted a reference to _fltused if a module contains
  341. floating type code so the linker could leave away floating point
  342. libraries or not. VC does this as well so we need to define this
  343. symbol as well (FK)
  344. }
  345. _fltused : int64;cvar;public;
  346. { value of the stack segment
  347. to check if the call stack can be written on exceptions }
  348. _SS : Cardinal;
  349. procedure Exe_entry;[public,alias:'_FPC_EXE_Entry'];
  350. var
  351. ST : pointer;
  352. begin
  353. IsLibrary:=false;
  354. { install the handlers for exe only ?
  355. or should we install them for DLL also ? (PM) }
  356. install_exception_handlers;
  357. ExitCode:=0;
  358. asm
  359. { keep stack aligned }
  360. pushq $0
  361. pushq %rbp
  362. movq %rsp,%rax
  363. movq %rax,st
  364. end;
  365. StackTop:=st;
  366. asm
  367. xorl %rax,%rax
  368. movw %ss,%ax
  369. movl %eax,_SS
  370. call SysResetFPU
  371. xorl %rbp,%rbp
  372. call PASCALMAIN
  373. popq %rbp
  374. popq %rax
  375. end;
  376. { if we pass here there was no error ! }
  377. system_exit;
  378. end;
  379. Const
  380. { DllEntryPoint }
  381. DLL_PROCESS_ATTACH = 1;
  382. DLL_THREAD_ATTACH = 2;
  383. DLL_PROCESS_DETACH = 0;
  384. DLL_THREAD_DETACH = 3;
  385. Var
  386. DLLBuf : Jmp_buf;
  387. Const
  388. DLLExitOK : boolean = true;
  389. function Dll_entry : longbool;
  390. var
  391. res : longbool;
  392. begin
  393. IsLibrary:=true;
  394. Dll_entry:=false;
  395. case DLLreason of
  396. DLL_PROCESS_ATTACH :
  397. begin
  398. If SetJmp(DLLBuf) = 0 then
  399. begin
  400. if assigned(Dll_Process_Attach_Hook) then
  401. begin
  402. res:=Dll_Process_Attach_Hook(DllParam);
  403. if not res then
  404. exit(false);
  405. end;
  406. PASCALMAIN;
  407. Dll_entry:=true;
  408. end
  409. else
  410. Dll_entry:=DLLExitOK;
  411. end;
  412. DLL_THREAD_ATTACH :
  413. begin
  414. inc(Thread_count);
  415. {$warning Allocate Threadvars !}
  416. if assigned(Dll_Thread_Attach_Hook) then
  417. Dll_Thread_Attach_Hook(DllParam);
  418. Dll_entry:=true; { return value is ignored }
  419. end;
  420. DLL_THREAD_DETACH :
  421. begin
  422. dec(Thread_count);
  423. if assigned(Dll_Thread_Detach_Hook) then
  424. Dll_Thread_Detach_Hook(DllParam);
  425. {$warning Release Threadvars !}
  426. Dll_entry:=true; { return value is ignored }
  427. end;
  428. DLL_PROCESS_DETACH :
  429. begin
  430. Dll_entry:=true; { return value is ignored }
  431. If SetJmp(DLLBuf) = 0 then
  432. begin
  433. FPC_DO_EXIT;
  434. end;
  435. if assigned(Dll_Process_Detach_Hook) then
  436. Dll_Process_Detach_Hook(DllParam);
  437. end;
  438. end;
  439. end;
  440. Procedure ExitDLL(Exitcode : longint);
  441. begin
  442. DLLExitOK:=ExitCode=0;
  443. LongJmp(DLLBuf,1);
  444. end;
  445. {$ifndef VER2_0}
  446. procedure _FPC_mainCRTStartup;stdcall;public name '_mainCRTStartup';
  447. begin
  448. IsConsole:=true;
  449. Exe_entry;
  450. end;
  451. procedure _FPC_WinMainCRTStartup;stdcall;public name '_WinMainCRTStartup';
  452. begin
  453. IsConsole:=false;
  454. Exe_entry;
  455. end;
  456. procedure _FPC_DLLMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);stdcall;public name '_DLLMainCRTStartup';
  457. begin
  458. IsConsole:=true;
  459. sysinstance:=_hinstance;
  460. dllreason:=_dllreason;
  461. dllparam:=_dllparam;
  462. DLL_Entry;
  463. end;
  464. procedure _FPC_DLLWinMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);stdcall;public name '_DLLWinMainCRTStartup';
  465. begin
  466. IsConsole:=false;
  467. sysinstance:=_hinstance;
  468. dllreason:=_dllreason;
  469. dllparam:=_dllparam;
  470. DLL_Entry;
  471. end;
  472. {$endif VER2_0}
  473. function GetCurrentProcess : dword;
  474. stdcall;external 'kernel32' name 'GetCurrentProcess';
  475. function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
  476. stdcall;external 'kernel32' name 'ReadProcessMemory';
  477. function is_prefetch(p : pointer) : boolean;
  478. var
  479. a : array[0..15] of byte;
  480. doagain : boolean;
  481. instrlo,instrhi,opcode : byte;
  482. i : longint;
  483. begin
  484. result:=false;
  485. { read memory savely without causing another exeception }
  486. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  487. exit;
  488. i:=0;
  489. doagain:=true;
  490. while doagain and (i<15) do
  491. begin
  492. opcode:=a[i];
  493. instrlo:=opcode and $f;
  494. instrhi:=opcode and $f0;
  495. case instrhi of
  496. { prefix? }
  497. $20,$30:
  498. doagain:=(instrlo and 7)=6;
  499. $60:
  500. doagain:=(instrlo and $c)=4;
  501. $f0:
  502. doagain:=instrlo in [0,2,3];
  503. $0:
  504. begin
  505. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  506. exit;
  507. end;
  508. else
  509. doagain:=false;
  510. end;
  511. inc(i);
  512. end;
  513. end;
  514. //
  515. // Hardware exception handling
  516. //
  517. {
  518. Error code definitions for the Win32 API functions
  519. Values are 32 bit values layed out as follows:
  520. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  521. 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  522. +---+-+-+-----------------------+-------------------------------+
  523. |Sev|C|R| Facility | Code |
  524. +---+-+-+-----------------------+-------------------------------+
  525. where
  526. Sev - is the severity code
  527. 00 - Success
  528. 01 - Informational
  529. 10 - Warning
  530. 11 - Error
  531. C - is the Customer code flag
  532. R - is a reserved bit
  533. Facility - is the facility code
  534. Code - is the facility's status code
  535. }
  536. const
  537. SEVERITY_SUCCESS = $00000000;
  538. SEVERITY_INFORMATIONAL = $40000000;
  539. SEVERITY_WARNING = $80000000;
  540. SEVERITY_ERROR = $C0000000;
  541. const
  542. STATUS_SEGMENT_NOTIFICATION = $40000005;
  543. DBG_TERMINATE_THREAD = $40010003;
  544. DBG_TERMINATE_PROCESS = $40010004;
  545. DBG_CONTROL_C = $40010005;
  546. DBG_CONTROL_BREAK = $40010008;
  547. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  548. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  549. STATUS_BREAKPOINT = $80000003;
  550. STATUS_SINGLE_STEP = $80000004;
  551. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  552. STATUS_ACCESS_VIOLATION = $C0000005;
  553. STATUS_IN_PAGE_ERROR = $C0000006;
  554. STATUS_INVALID_HANDLE = $C0000008;
  555. STATUS_NO_MEMORY = $C0000017;
  556. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  557. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  558. STATUS_INVALID_DISPOSITION = $C0000026;
  559. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  560. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  561. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  562. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  563. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  564. STATUS_FLOAT_OVERFLOW = $C0000091;
  565. STATUS_FLOAT_STACK_CHECK = $C0000092;
  566. STATUS_FLOAT_UNDERFLOW = $C0000093;
  567. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  568. STATUS_INTEGER_OVERFLOW = $C0000095;
  569. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  570. STATUS_STACK_OVERFLOW = $C00000FD;
  571. STATUS_CONTROL_C_EXIT = $C000013A;
  572. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  573. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  574. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  575. EXCEPTION_EXECUTE_HANDLER = 1;
  576. EXCEPTION_CONTINUE_EXECUTION = $fffffffff;
  577. EXCEPTION_CONTINUE_SEARCH = 0;
  578. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  579. CONTEXT_X86 = $00010000;
  580. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  581. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  582. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  583. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  584. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  585. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  586. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  587. MAXIMUM_SUPPORTED_EXTENSION = 512;
  588. type
  589. M128A = record
  590. Low : QWord;
  591. High : Int64;
  592. end;
  593. PContext = ^TContext;
  594. TContext = record
  595. P1Home : QWord;
  596. P2Home : QWord;
  597. P3Home : QWord;
  598. P4Home : QWord;
  599. P5Home : QWord;
  600. P6Home : QWord;
  601. ContextFlags : DWord;
  602. MxCsr : DWord;
  603. SegCs : word;
  604. SegDs : word;
  605. SegEs : word;
  606. SegFs : word;
  607. SegGs : word;
  608. SegSs : word;
  609. EFlags : DWord;
  610. Dr0 : QWord;
  611. Dr1 : QWord;
  612. Dr2 : QWord;
  613. Dr3 : QWord;
  614. Dr6 : QWord;
  615. Dr7 : QWord;
  616. Rax : QWord;
  617. Rcx : QWord;
  618. Rdx : QWord;
  619. Rbx : QWord;
  620. Rsp : QWord;
  621. Rbp : QWord;
  622. Rsi : QWord;
  623. Rdi : QWord;
  624. R8 : QWord;
  625. R9 : QWord;
  626. R10 : QWord;
  627. R11 : QWord;
  628. R12 : QWord;
  629. R13 : QWord;
  630. R14 : QWord;
  631. R15 : QWord;
  632. Rip : QWord;
  633. Header : array[0..1] of M128A;
  634. Legacy : array[0..7] of M128A;
  635. Xmm0 : M128A;
  636. Xmm1 : M128A;
  637. Xmm2 : M128A;
  638. Xmm3 : M128A;
  639. Xmm4 : M128A;
  640. Xmm5 : M128A;
  641. Xmm6 : M128A;
  642. Xmm7 : M128A;
  643. Xmm8 : M128A;
  644. Xmm9 : M128A;
  645. Xmm10 : M128A;
  646. Xmm11 : M128A;
  647. Xmm12 : M128A;
  648. Xmm13 : M128A;
  649. Xmm14 : M128A;
  650. Xmm15 : M128A;
  651. VectorRegister : array[0..25] of M128A;
  652. VectorControl : QWord;
  653. DebugControl : QWord;
  654. LastBranchToRip : QWord;
  655. LastBranchFromRip : QWord;
  656. LastExceptionToRip : QWord;
  657. LastExceptionFromRip : QWord;
  658. end;
  659. type
  660. PExceptionRecord = ^TExceptionRecord;
  661. TExceptionRecord = record
  662. ExceptionCode : DWord;
  663. ExceptionFlags : DWord;
  664. ExceptionRecord : PExceptionRecord;
  665. ExceptionAddress : Pointer;
  666. NumberParameters : DWord;
  667. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  668. end;
  669. PExceptionPointers = ^TExceptionPointers;
  670. TExceptionPointers = packed record
  671. ExceptionRecord : PExceptionRecord;
  672. ContextRecord : PContext;
  673. end;
  674. TVectoredExceptionHandler = function (excep : PExceptionPointers) : Longint;
  675. function AddVectoredExceptionHandler(FirstHandler : DWORD;VectoredHandler : TVectoredExceptionHandler) : longint;
  676. external 'kernel32' name 'AddVectoredExceptionHandler';
  677. const
  678. MaxExceptionLevel = 16;
  679. exceptLevel : Byte = 0;
  680. var
  681. exceptRip : array[0..MaxExceptionLevel-1] of Int64;
  682. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  683. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  684. {$ifdef SYSTEMEXCEPTIONDEBUG}
  685. procedure DebugHandleErrorAddrFrame(error : longint; addr, frame : pointer);
  686. begin
  687. if IsConsole then
  688. begin
  689. write(stderr,'HandleErrorAddrFrame(error=',error);
  690. write(stderr,',addr=',hexstr(int64(addr),16));
  691. writeln(stderr,',frame=',hexstr(int64(frame),16),')');
  692. end;
  693. HandleErrorAddrFrame(error,addr,frame);
  694. end;
  695. {$endif SYSTEMEXCEPTIONDEBUG}
  696. procedure JumpToHandleErrorFrame;
  697. var
  698. rip, rbp : int64;
  699. error : longint;
  700. begin
  701. // save ebp
  702. asm
  703. movq (%rbp),%rax
  704. movq %rax,rbp
  705. end;
  706. if exceptLevel>0 then
  707. dec(exceptLevel);
  708. rip:=exceptRip[exceptLevel];
  709. error:=exceptError[exceptLevel];
  710. {$ifdef SYSTEMEXCEPTIONDEBUG}
  711. if IsConsole then
  712. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  713. {$endif SYSTEMEXCEPTIONDEBUG}
  714. if resetFPU[exceptLevel] then
  715. SysResetFPU;
  716. { build a fake stack }
  717. asm
  718. movq rbp,%r8
  719. movq rip,%rdx
  720. movl error,%ecx
  721. pushq rip
  722. movq rbp,%rbp // Change frame pointer
  723. {$ifdef SYSTEMEXCEPTIONDEBUG}
  724. jmpl DebugHandleErrorAddrFrame
  725. {$else not SYSTEMEXCEPTIONDEBUG}
  726. jmpl HandleErrorAddrFrame
  727. {$endif SYSTEMEXCEPTIONDEBUG}
  728. end;
  729. end;
  730. function syswin64_x86_64_exception_handler(excep : PExceptionPointers) : Longint;public;
  731. var
  732. res: longint;
  733. err: byte;
  734. must_reset_fpu: boolean;
  735. begin
  736. res:=EXCEPTION_CONTINUE_SEARCH;
  737. {$ifdef SYSTEMEXCEPTIONDEBUG}
  738. if IsConsole then
  739. Writeln(stderr,'syswin64_x86_64_exception_handler called');
  740. {$endif SYSTEMEXCEPTIONDEBUG}
  741. if excep^.ContextRecord^.SegSs=_SS then
  742. begin
  743. err := 0;
  744. must_reset_fpu := true;
  745. {$ifdef SYSTEMEXCEPTIONDEBUG}
  746. if IsConsole then Writeln(stderr,'Exception ',
  747. hexstr(excep^.ExceptionRecord^.ExceptionCode,8));
  748. {$endif SYSTEMEXCEPTIONDEBUG}
  749. case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
  750. STATUS_INTEGER_DIVIDE_BY_ZERO,
  751. STATUS_FLOAT_DIVIDE_BY_ZERO :
  752. err := 200;
  753. STATUS_ARRAY_BOUNDS_EXCEEDED :
  754. begin
  755. err := 201;
  756. must_reset_fpu := false;
  757. end;
  758. STATUS_STACK_OVERFLOW :
  759. begin
  760. err := 202;
  761. must_reset_fpu := false;
  762. end;
  763. STATUS_FLOAT_OVERFLOW :
  764. err := 205;
  765. STATUS_FLOAT_DENORMAL_OPERAND,
  766. STATUS_FLOAT_UNDERFLOW :
  767. err := 206;
  768. { excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  769. STATUS_FLOAT_INEXACT_RESULT,
  770. STATUS_FLOAT_INVALID_OPERATION,
  771. STATUS_FLOAT_STACK_CHECK :
  772. err := 207;
  773. STATUS_INTEGER_OVERFLOW :
  774. begin
  775. err := 215;
  776. must_reset_fpu := false;
  777. end;
  778. STATUS_ILLEGAL_INSTRUCTION:
  779. err := 216;
  780. STATUS_ACCESS_VIOLATION:
  781. { Athlon prefetch bug? }
  782. if is_prefetch(pointer(excep^.ContextRecord^.rip)) then
  783. begin
  784. { if yes, then retry }
  785. excep^.ExceptionRecord^.ExceptionCode := 0;
  786. res:=EXCEPTION_CONTINUE_EXECUTION;
  787. end
  788. else
  789. err := 216;
  790. STATUS_CONTROL_C_EXIT:
  791. err := 217;
  792. STATUS_PRIVILEGED_INSTRUCTION:
  793. begin
  794. err := 218;
  795. must_reset_fpu := false;
  796. end;
  797. else
  798. begin
  799. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  800. err := 217
  801. else
  802. err := 255;
  803. end;
  804. end;
  805. if (err <> 0) and (exceptLevel < MaxExceptionLevel) then
  806. begin
  807. exceptRip[exceptLevel] := excep^.ContextRecord^.Rip;
  808. exceptError[exceptLevel] := err;
  809. resetFPU[exceptLevel] := must_reset_fpu;
  810. inc(exceptLevel);
  811. excep^.ContextRecord^.Rip := Int64(@JumpToHandleErrorFrame);
  812. excep^.ExceptionRecord^.ExceptionCode := 0;
  813. res := EXCEPTION_CONTINUE_EXECUTION;
  814. {$ifdef SYSTEMEXCEPTIONDEBUG}
  815. if IsConsole then begin
  816. writeln(stderr,'Exception Continue Exception set at ',
  817. hexstr(exceptRip[exceptLevel-1],16));
  818. writeln(stderr,'Rip changed to ',
  819. hexstr(int64(@JumpToHandleErrorFrame),16), ' error=', err);
  820. end;
  821. {$endif SYSTEMEXCEPTIONDEBUG}
  822. end;
  823. end;
  824. syswin64_x86_64_exception_handler := res;
  825. end;
  826. procedure install_exception_handlers;
  827. begin
  828. AddVectoredExceptionHandler(1,@syswin64_x86_64_exception_handler);
  829. end;
  830. procedure remove_exception_handlers;
  831. begin
  832. end;
  833. procedure fpc_cpucodeinit;
  834. begin
  835. end;
  836. {****************************************************************************
  837. OS dependend widestrings
  838. ****************************************************************************}
  839. const
  840. { MultiByteToWideChar }
  841. MB_PRECOMPOSED = 1;
  842. CP_ACP = 0;
  843. function MultiByteToWideChar(CodePage:UINT; dwFlags:DWORD; lpMultiByteStr:PChar; cchMultiByte:longint; lpWideCharStr:PWideChar;cchWideChar:longint):longint;
  844. stdcall; external 'kernel32' name 'MultiByteToWideChar';
  845. function WideCharToMultiByte(CodePage:UINT; dwFlags:DWORD; lpWideCharStr:PWideChar; cchWideChar:longint; lpMultiByteStr:PChar;cchMultiByte:longint; lpDefaultChar:PChar; lpUsedDefaultChar:pointer):longint;
  846. stdcall; external 'kernel32' name 'WideCharToMultiByte';
  847. function CharUpperBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD;
  848. stdcall; external 'user32' name 'CharUpperBuffW';
  849. function CharLowerBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD;
  850. stdcall; external 'user32' name 'CharLowerBuffW';
  851. procedure Win32Wide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
  852. var
  853. destlen: SizeInt;
  854. begin
  855. // retrieve length including trailing #0
  856. destlen:=WideCharToMultiByte(CP_ACP, 0, source, len+1, nil, 0, nil, nil);
  857. setlength(dest, destlen-1);
  858. WideCharToMultiByte(CP_ACP, 0, source, len+1, @dest[1], destlen, nil, nil);
  859. end;
  860. procedure Win32Ansi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
  861. var
  862. destlen: SizeInt;
  863. begin
  864. // retrieve length including trailing #0
  865. destlen:=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, source, len+1, nil, 0);
  866. setlength(dest, destlen-1);
  867. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, source, len+1, @dest[1], destlen);
  868. end;
  869. function Win32WideUpper(const s : WideString) : WideString;
  870. begin
  871. result:=s;
  872. UniqueString(result);
  873. if length(result)>0 then
  874. CharUpperBuff(LPWSTR(result),length(result));
  875. end;
  876. function Win32WideLower(const s : WideString) : WideString;
  877. begin
  878. result:=s;
  879. UniqueString(result);
  880. if length(result)>0 then
  881. CharLowerBuff(LPWSTR(result),length(result));
  882. end;
  883. { there is a similiar procedure in sysutils which inits the fields which
  884. are only relevant for the sysutils units }
  885. procedure InitWin32Widestrings;
  886. begin
  887. widestringmanager.Wide2AnsiMoveProc:=@Win32Wide2AnsiMove;
  888. widestringmanager.Ansi2WideMoveProc:=@Win32Ansi2WideMove;
  889. widestringmanager.UpperWideStringProc:=@Win32WideUpper;
  890. widestringmanager.LowerWideStringProc:=@Win32WideLower;
  891. end;
  892. {****************************************************************************
  893. Error Message writing using messageboxes
  894. ****************************************************************************}
  895. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  896. stdcall;external 'user32' name 'MessageBoxA';
  897. const
  898. ErrorBufferLength = 1024;
  899. var
  900. ErrorBuf : array[0..ErrorBufferLength] of char;
  901. ErrorLen : longint;
  902. Function ErrorWrite(Var F: TextRec): Integer;
  903. {
  904. An error message should always end with #13#10#13#10
  905. }
  906. var
  907. p : pchar;
  908. i : longint;
  909. Begin
  910. if F.BufPos>0 then
  911. begin
  912. if F.BufPos+ErrorLen>ErrorBufferLength then
  913. i:=ErrorBufferLength-ErrorLen
  914. else
  915. i:=F.BufPos;
  916. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  917. inc(ErrorLen,i);
  918. ErrorBuf[ErrorLen]:=#0;
  919. end;
  920. if ErrorLen>3 then
  921. begin
  922. p:=@ErrorBuf[ErrorLen];
  923. for i:=1 to 4 do
  924. begin
  925. dec(p);
  926. if not(p^ in [#10,#13]) then
  927. break;
  928. end;
  929. end;
  930. if ErrorLen=ErrorBufferLength then
  931. i:=4;
  932. if (i=4) then
  933. begin
  934. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  935. ErrorLen:=0;
  936. end;
  937. F.BufPos:=0;
  938. ErrorWrite:=0;
  939. End;
  940. Function ErrorClose(Var F: TextRec): Integer;
  941. begin
  942. if ErrorLen>0 then
  943. begin
  944. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  945. ErrorLen:=0;
  946. end;
  947. ErrorLen:=0;
  948. ErrorClose:=0;
  949. end;
  950. Function ErrorOpen(Var F: TextRec): Integer;
  951. Begin
  952. TextRec(F).InOutFunc:=@ErrorWrite;
  953. TextRec(F).FlushFunc:=@ErrorWrite;
  954. TextRec(F).CloseFunc:=@ErrorClose;
  955. ErrorOpen:=0;
  956. End;
  957. procedure AssignError(Var T: Text);
  958. begin
  959. Assign(T,'');
  960. TextRec(T).OpenFunc:=@ErrorOpen;
  961. Rewrite(T);
  962. end;
  963. procedure SysInitStdIO;
  964. begin
  965. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  966. displayed in a messagebox }
  967. StdInputHandle:=THandle(GetStdHandle(STD_INPUT_HANDLE));
  968. StdOutputHandle:=THandle(GetStdHandle(STD_OUTPUT_HANDLE));
  969. StdErrorHandle:=THandle(GetStdHandle(STD_ERROR_HANDLE));
  970. if not IsConsole then
  971. begin
  972. AssignError(stderr);
  973. AssignError(stdout);
  974. Assign(Output,'');
  975. Assign(Input,'');
  976. Assign(ErrOutput,'');
  977. end
  978. else
  979. begin
  980. OpenStdIO(Input,fmInput,StdInputHandle);
  981. OpenStdIO(Output,fmOutput,StdOutputHandle);
  982. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  983. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  984. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  985. end;
  986. end;
  987. (* ProcessID cached to avoid repeated calls to GetCurrentProcess. *)
  988. var
  989. ProcessID: SizeUInt;
  990. function GetProcessID: SizeUInt;
  991. begin
  992. GetProcessID := ProcessID;
  993. end;
  994. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  995. begin
  996. result := stklen;
  997. end;
  998. begin
  999. SysResetFPU;
  1000. StackLength := CheckInitialStkLen(InitialStkLen);
  1001. StackBottom := StackTop - StackLength;
  1002. { get some helpful informations }
  1003. GetStartupInfo(@startupinfo);
  1004. { some misc Win32 stuff }
  1005. hprevinst:=0;
  1006. if not IsLibrary then
  1007. SysInstance:=getmodulehandle(GetCommandFile);
  1008. MainInstance:=HInstance;
  1009. cmdshow:=startupinfo.wshowwindow;
  1010. { Setup heap }
  1011. InitHeap;
  1012. SysInitExceptions;
  1013. { setup fastmove stuff }
  1014. fpc_cpucodeinit;
  1015. SysInitStdIO;
  1016. { Arguments }
  1017. setup_arguments;
  1018. { Reset IO Error }
  1019. InOutRes:=0;
  1020. ProcessID := GetCurrentProcessID;
  1021. { threading }
  1022. InitSystemThreads;
  1023. { Reset internal error variable }
  1024. errno:=0;
  1025. initvariantmanager;
  1026. initwidestringmanager;
  1027. InitWin32Widestrings;
  1028. end.