system.pp 28 KB

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