fpmingw.pas 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. unit fpmingw;
  2. {
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 2009 by Marco van de Voort
  5. Mingw helpers. Currently mostly atexit.
  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. {$I globdir.inc}
  13. interface
  14. // mingw put atexit in binaries, so that it can have one atexit, and call it from
  15. // dll and .exe startup code.
  16. // This unit provides a similar service for when mingw code (read: libgdb and friends) are statically
  17. // linked to FPC.
  18. Type
  19. TCFunction = function:longint cdecl; // prototype of an handler to be registered with atexit
  20. function atexit(p:TCFunction):longint; cdecl; // export our own atexit handler
  21. implementation
  22. uses
  23. windows,
  24. gdbint; // force dependancies that hopefully make it execute at the right moment.
  25. // prototype of atexit:
  26. Type
  27. TAtexitFunction = function(p:TCFUnction):longint cdecl;
  28. {$ifdef win64}
  29. var __imp_atexit : TAtExitFunction; Cvar; external; // "true" atexit in mingw libs.
  30. {$else not win64}
  31. var _imp__atexit : TAtExitFunction; Cvar; external; // "true" atexit in mingw libs.
  32. {$endif not win64}
  33. var
  34. hMsvcrt : HModule = 0;
  35. free_Msvcrt : boolean;
  36. {$ifdef win32}
  37. fctMsvcrtLongJmp : pointer;cvar;external;
  38. {$else not win32}
  39. fctMsvcrtLongJmp : pointer;cvar;
  40. {$endif not win32}
  41. function atexit(p:TCFunction):longint;cdecl; [public, alias : '_atexit'];
  42. begin
  43. {$ifdef win64}
  44. atexit:=__imp_atexit(p); // simply route to "true" atexit
  45. {$else not win64}
  46. atexit:=_imp__atexit(p); // simply route to "true" atexit
  47. {$endif not win64}
  48. end;
  49. {$ifdef win32}
  50. procedure __cpu_features_init; cdecl; external;
  51. {$endif win32}
  52. procedure _pei386_runtime_relocator; cdecl; external;
  53. procedure __main; cdecl;external;
  54. procedure doinit;
  55. // other mingw initialization. Sequence from crt1.c
  56. begin
  57. // not (yet) done: set mingw exception handlers:
  58. // SetUnhandledExceptionFilter (_gnu_exception_handler);
  59. {$ifndef DISABLE_CPU_FEATURES_INIT}
  60. {$ifdef win32}
  61. __cpu_features_init; // load CPU features. Might be useful for debugger :-)
  62. {$endif win32}
  63. {$endif ndef DISABLE_CPU_FEATURES_INIT}
  64. // fpreset; // don't do this, we init our own fp mask
  65. // _mingw32_init_mainargs (); // mingw doesn't handle arguments not necessary.
  66. // _mingw32_init_fmode (); // Set default filemode. Is not done for libraries, so we don't.
  67. // Adust references to dllimported data that have non-zero offsets.
  68. _pei386_runtime_relocator; //
  69. // aligns stack here to 16 bytes
  70. {From libgcc.a, __main calls global class constructors via
  71. __do_global_ctors, This in turn registers __do_global_dtors
  72. as the first entry of the app's atexit table. We do this
  73. explicitly at app startup rather than rely on gcc to generate
  74. the call in main's prologue, since main may be imported from a dll
  75. which has its own __do_global_ctors. }
  76. {$ifdef win64}
  77. if (hMsvcrt=0) then
  78. hMsvcrt := GetModuleHandleA ('msvcrt.dll');
  79. if (hMsvcrt=0) then
  80. begin
  81. hMsvcrt := LoadLibraryA ('msvcrt.dll');
  82. free_Msvcrt := true;
  83. end;
  84. fctMsvcrtLongJmp := GetProcAddress(hMsvcrt, 'longjmp');
  85. // __main; // should be libgcc initialization but this causes infinite loop.
  86. {$endif win64}
  87. end;
  88. procedure _cexit; cdecl; external;
  89. procedure doatexit;
  90. begin
  91. {
  92. * Perform exit processing for the C library. This means
  93. * flushing output and calling 'atexit' registered functions.
  94. }
  95. if free_Msvcrt and (hMsvcrt<>0) then
  96. begin
  97. free_Msvcrt := false;
  98. FreeLibrary (hMsvcrt);
  99. hMsvcrt := 0;
  100. end;
  101. _cexit ();
  102. end;
  103. initialization
  104. doinit;
  105. finalization
  106. doatexit;
  107. end.