system.pp 27 KB

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