Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade from msvcrt.lib to ucrt.lib #122

Open
jonahbeckford opened this issue Sep 28, 2023 · 6 comments
Open

Upgrade from msvcrt.lib to ucrt.lib #122

jonahbeckford opened this issue Sep 28, 2023 · 6 comments

Comments

@jonahbeckford
Copy link
Contributor

With the minimum requirements for OCaml at Windows 10 (I think), we should consider moving off the legacy msvcrt.lib.

Here is the branch I have used for testing: https://github.com/jonahbeckford/flexdll/commits/0.43%2Bucrt

There are two blockers:

  1. Unsupported relocation kind 0003 for __GSHandlerCheck in libcamlrun.lib(intern.obj) #29 is probably related (I'm seeing this error only after upgrading to ucrt.lib.
  2. Some extra libraries are needed (not sure whether this belongs in ocaml/flexdll or ocaml/ocaml itself). I'll place each library in a separate comment below.
@jonahbeckford
Copy link
Contributor Author

+ vcruntime.lib

Fixes:

** Cannot resolve symbols for C:\GitLab-Runner\builds\diskuv\distributions\1.0\dksdk-ffi-ocaml\build\DkSDKFiles\cfg-Release\o\bin\flexdll_msvc64.obj:
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(ints.n.obj):
 _fltused
 memcpy
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(weak.n.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(obj.n.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(readlink.obj):
 __chkstk
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(mmap_ba.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(misc.n.obj):
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(extern.n.obj):
 memcpy
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(_dn\lwt\src\unix\windows_pread_job.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(startup_nat.n.obj):
 _setjmp
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(time.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(_dn\lwt\src\unix\windows_read_job.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(domain.n.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(compact.n.obj):
 _fltused
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(roots_nat.n.obj):
 memset
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(major_gc.n.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(compare.n.obj):
 _fltused
 memcmp
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(io.n.obj):
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(bigarray.n.obj):
 _fltused
 memcpy
 memmove
 memset
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(backtrace.n.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(getaddrinfo.obj):
 memcpy
 memset
 strchr
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(sendrecv.obj):
 __chkstk
 memcpy
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(sys.n.obj):
 __chkstk
 _fltused
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(addrofstr.obj):
 memset
 strchr
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(strofaddr.obj):
 memset
 strchr
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(freelist.n.obj):
 __chkstk
 memcpy
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(minor_gc.n.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(select.obj):
 _fltused
 memset
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(_dn\_opam\.opam-switch\build\cstruct.6.2.0\lib\cstruct_stubs.obj):
 memcmp
 memcpy
 memmove
 memset
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(memory.n.obj):
 _fltused
 memcpy
 memset
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(callback.n.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(win32.n.obj):
 __chkstk
 wcsstr
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(hash.n.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(stat.obj):
 __chkstk
 _fltused
 wcsrchr
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(times.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(_dn\lwt\src\unix\lwt_unix_stubs.obj):
 memcpy
 memmove
 memset
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(utimes.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(gettimeofday.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(array.n.obj):
 _fltused
 memcpy
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(st_stubs.n.obj):
 _setjmp
 longjmp
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(alloc.n.obj):
 _fltused
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(floats.n.obj):
 _fltused
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(getnameinfo.obj):
 __chkstk
 memset
 strchr
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(md5.n.obj):
 __chkstk
 memcpy
 memset
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(parsing.n.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(_dn\lwt\src\unix\windows_write_job.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(printexc.n.obj):
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(write.obj):
 __chkstk
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(intern.n.obj):
 _fltused
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_c.lib(tests\Units\CMakeFiles\test_arithmetic_c.dir\arithmetic\arithmetic.c.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(gmtime.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(sleep.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(sockopt.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(gc_ctrl.n.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(custom.n.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(memprof.n.obj):
 _fltused
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(_dn\lwt\src\unix\windows_pwrite_job.obj):
 memcpy
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(read.obj):
 __chkstk
 memmove
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(str.n.obj):
 memcmp
 memmove
 memset
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(socketaddr.obj):
 memmove

@jonahbeckford
Copy link
Contributor Author

+ kernel32.lib

Fixes

** Cannot resolve symbols for descriptor object:
 AddVectoredExceptionHandler
 CloseHandle
 CreateEventW
 CreateFileMappingW
 CreateFileW
 CreateMutexW
 CreatePipe
 CreateProcessW
 CreateThread
 DeleteCriticalSection
 DeleteFileW
 DeviceIoControl
 DuplicateHandle
 EnterCriticalSection
 ExitThread
 FindClose
 FindFirstFileW
 FindNextFileW
 FlushFileBuffers
 FormatMessageA
 FormatMessageW
 FreeEnvironmentStringsW
 FreeLibrary
 GetConsoleMode
 GetConsoleOutputCP
 GetCurrentProcess
 GetCurrentProcessId
 GetCurrentThreadId
 GetEnvironmentStringsW
 GetEnvironmentVariableW
 GetExitCodeProcess
 GetFileAttributesW
 GetFileInformationByHandle
 GetFileType
 GetFinalPathNameByHandleW
 GetHandleInformation
 GetLastError
 GetModuleFileNameW
 GetModuleHandleW
 GetProcAddress
 GetProcessTimes
 GetSystemDirectoryA
 GetSystemInfo
 GetSystemTime
 GetSystemTimeAsFileTime
 GetTempFileNameW
 GetTempPathW
 GetVersionExW
 InitializeCriticalSection
 LeaveCriticalSection
 LoadLibraryA
 LoadLibraryExW
 LoadLibraryW
 LockFileEx
 MapViewOfFile
 MoveFileExW
 MultiByteToWideChar
 PeekConsoleInputW
 PeekNamedPipe
 QueryPerformanceCounter
 ReadConsoleInputW
 ReadFile
 ReleaseMutex
 RemoveVectoredExceptionHandler
 ResetEvent
 SearchPathW
 SetConsoleCtrlHandler
 SetConsoleOutputCP
 SetEndOfFile
 SetEvent
 SetFilePointer
 SetFilePointerEx
 SetFileTime
 SetHandleInformation
 SetLastError
 SignalObjectAndWait
 Sleep
 SystemTimeToFileTime

jonahbeckford added a commit to jonahbeckford/flexdll that referenced this issue Sep 28, 2023
+vcruntime.lib
+kernel32.lib

Identified in ocaml#122
@nojb
Copy link
Collaborator

nojb commented Sep 29, 2023

Sorry for the naïve question, but to make sure I understand: are we speaking here of linking the executables produced by flexlink/MSVC against ucrt? Somehow I remember that ever since switching to VS 2015, the executables produced by the OCaml comiler (via flexlink/MSVC) already depended on ucrt? I must be missing something...

@jonahbeckford
Copy link
Contributor Author

jonahbeckford commented Sep 29, 2023

The issue is that msvcrt and ucrt don't always play nicely when linked into an executable. From what I understand, we are supposed to be able to mix/match the old C runtime and the Universal C runtime, but we still can get conflicts:

msvcrtd.lib(gs_report.obj) : error LNK2005: __report_gsfailure already defined in vcruntimed.lib(VCRUNTIME140D.dll)

Seems safer just not to link to the old msvcrt runtime when it is not needed. Caveat: I am still testing.


A small summary is at https://www.msys2.org/docs/environments/#msvcrt-vs-ucrt:

Binaries linked with MSVCRT should not be mixed with UCRT ones because the internal structures and data types are different. (More strictly, object files or static libraries built for different targets shouldn't be mixed. DLLs built for different CRTs can be mixed as long as they don't share CRT objects, e.g. FILE*, across DLL boundaries.) Same rule is applied for MSVC compiled binaries because MSVC uses UCRT by default (if not changed).


@nojb "the executables produced by the OCaml comiler (via flexlink/MSVC) already depended on ucrt? I must be missing something...".

I suspect the new thing in VS 2015 was that the binaries started to depend on vcruntime140.dll. If so, that is independent of MSVCRT versus UCRT.

@jonahbeckford
Copy link
Contributor Author

jonahbeckford commented Sep 29, 2023

+ Compiler Routines

I believe these are the last missing symbols to be resolved:

** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(ints.n.obj):
 _fltused
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(readlink.obj):
 __chkstk
** Cannot resolve symbols for tests\Units\test_arithmetic_ml.lib(startup_nat.n.obj):
 _setjmp

From what I can tell these aren't defined in libraries but are instead emitted by the compiler and/or linker. For example, __chkstk should be emitted by MSVC to implement /Gs<n>: https://learn.microsoft.com/en-us/cpp/build/reference/gs-control-stack-checking-calls?view=msvc-170.

I am currently puzzled by why these symbols are not present! My guesses so far:

  • Perhaps link.exe is inserting these routines, and flexlink.exe is not doing the same?
  • Perhaps these symbols are in .obj files, but flexlink.exe is dropping these symbols for some weird reason.

Edit 1:

  • _fltused is answered by https://stackoverflow.com/a/1583220. flexlink.exe will need to define this symbol but only if there is an external link to that symbol. The stackoverflow is incorrect though ... the real code is C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\crt\src\vcruntime\fltused.cpp and is defined to be 0x9875.

Edit 2:

  • __chkstk is defined in C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\crt\src\i386\chkstk.asm, C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\crt\src\i386\chkstk.asm (etc.).
  • Better yet, __chkstk comes pre-compiled at C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133 (etc.):
    ./lib/arm/chkstk.obj
    ./lib/arm64/chkstk.obj
    ./lib/x64/chkstk.obj
    ./lib/x86/chkstk.obj
    

Edit 3:

All the above still needs testing

@jonahbeckford
Copy link
Contributor Author

jonahbeckford commented Sep 30, 2023

+ msvcrt.lib (only for .exe link)

Fixes:

LINK : error LNK2001: unresolved external symbol wmainCRTStartup
src\MainCLI\main-cli.exe : fatal error LNK1120: 1 unresolved externals

Now it is weird that I am putting msvcrt.lib back in. But this is back not when linking DLLs; it is only back when linking .exe (the only place where CRT initialization should occur). And if necessary we could write our own CRT initialization routine just like

flexdll/flexdll_initer.c

Lines 35 to 55 in cc0525e

#ifdef __GNUC__
#ifdef __CYGWIN__
#define entry _cygwin_dll_entry
#endif
#ifdef __MINGW32__
#define entry DllMainCRTStartup
#endif
#else
#define entry _DllMainCRTStartup
#endif
BOOL WINAPI entry(HINSTANCE, DWORD, LPVOID);
BOOL WINAPI FlexDLLiniter(HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID lpReserved) {
if (fdwReason == DLL_PROCESS_ATTACH && !flexdll_init())
return FALSE;
return entry(hinstDLL, fdwReason, lpReserved);
}
is the DLL initialization routine. Confer: https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants