diff --git a/Sources/ucrt/inc/corecrt_internal.h b/Sources/ucrt/inc/corecrt_internal.h index 27094ad..c60dc4c 100644 --- a/Sources/ucrt/inc/corecrt_internal.h +++ b/Sources/ucrt/inc/corecrt_internal.h @@ -1488,7 +1488,38 @@ __declspec(dllimport) void __cdecl _amsg_exit( __acrt_ptd* __cdecl __acrt_getptd_head(void); -#ifdef __BuildWithMSVCRT +#if WindowsTargetPlatformMinVersion < WindowsTargetPlatformWindows10_10240 +__declspec(noinline) __inline bool __fastcall IsPointerInMsvcrtDll(const void* p) +{ + if (!p) + return false; + + static uintptr_t s_pBegin; + static uintptr_t s_pEnd; + + if (s_pBegin == (uintptr_t)0 || s_pEnd == (uintptr_t)0) + { + MEMORY_BASIC_INFORMATION _BaseInfo; + if (VirtualQuery(&_amsg_exit, &_BaseInfo, sizeof(_BaseInfo)) == 0) + { + return false; + } + auto _pBegin = (char*)_BaseInfo.AllocationBase; + auto _pEnd = (char*)_BaseInfo.AllocationBase + _BaseInfo.RegionSize; + for (; VirtualQuery(_pEnd + 1, &_BaseInfo, sizeof(_BaseInfo));) + { + if (_pBegin != _BaseInfo.AllocationBase) + break; + + _pEnd = (char*)_BaseInfo.BaseAddress + _BaseInfo.RegionSize; + } + s_pBegin = (uintptr_t)_pBegin; + s_pEnd = (uintptr_t)_pEnd; + } + + return s_pBegin <= (uintptr_t)p && (uintptr_t)p < s_pEnd; +} + __declspec(noinline) __inline __acrt_ptd* __cdecl __acrt_getptd_noexit(void) { // ptd->_thandle 一共有3中情况: @@ -1500,46 +1531,9 @@ __declspec(noinline) __inline __acrt_ptd* __cdecl __acrt_getptd_noexit(void) // 这时必须借助GetThreadId,可是它开销是惊人的,不容易做到快速判断。 // 结合总总情况,我们现在通过判断 _errno() 返回地址是否在msvcrt模块范围来判断 __getptd_noexit 是否发生内存申请失败。 // 具体Bug请参考:https://github.com/Chuyu-Team/VC-LTL5/issues/49 - typedef struct _DllAddressInfo - { - uintptr_t uBaseAddress; - uintptr_t uEndAddress; - } DllAddressInfo; - - static DllAddressInfo s_DllAddressCache; - - if (s_DllAddressCache.uBaseAddress == 0) - { - DllAddressInfo _DllAddressInfo = { (uintptr_t)-1, (uintptr_t)-1}; - MEMORY_BASIC_INFORMATION _BaseInfo; - if (VirtualQuery(&_amsg_exit, &_BaseInfo, sizeof(_BaseInfo))) - { - _DllAddressInfo.uBaseAddress = (uintptr_t)_BaseInfo.AllocationBase; - _DllAddressInfo.uEndAddress = (uintptr_t)_BaseInfo.BaseAddress + _BaseInfo.RegionSize; - - for (; VirtualQuery((void*)(_DllAddressInfo.uEndAddress + 1), &_BaseInfo, sizeof(_BaseInfo));) - { - if (_DllAddressInfo.uBaseAddress != (uintptr_t)_BaseInfo.AllocationBase) - break; - _DllAddressInfo.uEndAddress = (uintptr_t)_BaseInfo.BaseAddress + _BaseInfo.RegionSize; - } - } - -#if defined(_X86_) || defined(_ARM_) - static_assert(sizeof(s_DllAddressCache) == sizeof(LONGLONG), ""); - InterlockedCompareExchange64((volatile LONGLONG*)&s_DllAddressCache, *(LONGLONG*)&_DllAddressInfo, 0); -#elif defined(_IA64_) || defined(_AMD64_) || defined(_ARM64_) - // AMD 早期不支持 InterlockedCompareExchange128,所以不用…… - InterlockedCompareExchange64((volatile LONGLONG*)&s_DllAddressCache.uEndAddress, _DllAddressInfo.uEndAddress, 0); - InterlockedCompareExchange64((volatile LONGLONG*)&s_DllAddressCache.uBaseAddress, _DllAddressInfo.uBaseAddress, 0); -#else -#error unsrpport! -#endif - } - - uintptr_t _p_errno_value = (uintptr_t)_errno(); - if (_p_errno_value == 0 || (s_DllAddressCache.uBaseAddress <= _p_errno_value && _p_errno_value < s_DllAddressCache.uEndAddress)) + auto _p_errno_value = (unsigned char*)_errno(); + if (_p_errno_value == 0 || IsPointerInMsvcrtDll(_p_errno_value)) { return NULL; } @@ -1551,7 +1545,7 @@ __declspec(noinline) __inline __acrt_ptd* __cdecl __acrt_getptd_noexit(void) __acrt_ptd* __cdecl __acrt_getptd_noexit(void); #endif -#ifdef __BuildWithMSVCRT +#if WindowsTargetPlatformMinVersion < WindowsTargetPlatformWindows10_10240 __declspec(noinline) __inline __acrt_ptd* __cdecl __acrt_getptd(void) { __acrt_ptd* ptd = __acrt_getptd_noexit(); @@ -2785,4 +2779,4 @@ windowing_model_policy __cdecl __acrt_get_windowing_model_policy(void); _CRT_END_C_HEADER -//#include \ No newline at end of file +//#include diff --git a/Sources/ucrt/internal/initialization.cpp b/Sources/ucrt/internal/initialization.cpp index 3bc0b9a..fa3bd60 100644 --- a/Sources/ucrt/internal/initialization.cpp +++ b/Sources/ucrt/internal/initialization.cpp @@ -1,4 +1,4 @@ -// +// // initialization.cpp // // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,6 +13,10 @@ #include #include +#if WindowsTargetPlatformMinVersion < __MakeVersion(10, 0, 10240) +bool __cdecl __LTL_ThunksInit(); +#endif + extern "C" { @@ -192,7 +196,7 @@ static bool __cdecl uninitialize_allocated_io_buffers(bool const /* terminating _free_crt(__acrt_stderr_buffer); __acrt_stderr_buffer = nullptr; -#if 0 //msvcrt.dlͷ +#if 0 //msvcrt.dl会释放他们 _free_crt(__argv); __argv = nullptr; @@ -229,6 +233,9 @@ static __acrt_initializer const __acrt_initializers[] = // Global pointers are stored in encoded form; they must be dynamically // initialized to the encoded nullptr value before they are used by the CRT. { initialize_pointers, nullptr }, +#if WindowsTargetPlatformMinVersion < __MakeVersion(10, 0, 10240) + { __LTL_ThunksInit, nullptr }, +#endif // Enclaves only require initializers for supported features. #ifndef _UCRT_ENCLAVE_BUILD { __acrt_initialize_winapi_thunks, __acrt_uninitialize_winapi_thunks }, diff --git a/ucrtbase.msvcrt/fputwc_thunks.cpp b/ucrtbase.msvcrt/fputwc_thunks.cpp index d6cee01..fb84c21 100644 --- a/ucrtbase.msvcrt/fputwc_thunks.cpp +++ b/ucrtbase.msvcrt/fputwc_thunks.cpp @@ -6,12 +6,11 @@ extern "C" __declspec(dllimport) extern _iobuf _iob[20]; +__EXPAND_MSVCRT_FUN(fputc); static int __cdecl fputc_msvcrt(int const c, FILE* const stream) { - __EXPAND_MSVCRT_FUN(fputc); - - if (auto pfputc_msvcrt = __Get_MSVCRT_FUN(fputc)) + if (auto pfputc_msvcrt = try_get_fputc()) { return pfputc_msvcrt(c, stream); } @@ -19,14 +18,13 @@ static int __cdecl fputc_msvcrt(int const c, FILE* const stream) return EOF; } +__EXPAND_MSVCRT_FUN(fputwc); static wint_t __cdecl fputwc_msvcrt( wchar_t _Character, FILE* _Stream) { - __EXPAND_MSVCRT_FUN(fputwc); - - if (auto pfputwc_msvcrt = __Get_MSVCRT_FUN(fputwc)) + if (auto pfputwc_msvcrt = try_get_fputwc()) { return pfputwc_msvcrt(_Character, _Stream); } @@ -34,6 +32,8 @@ static wint_t __cdecl fputwc_msvcrt( return WEOF; } +__EXPAND_MSVCRT_FUN(fwrite); + static size_t __cdecl fwrite_msvcrt( void const* const buffer, size_t const size, @@ -41,9 +41,7 @@ static size_t __cdecl fwrite_msvcrt( FILE* const stream ) { - __EXPAND_MSVCRT_FUN(fwrite); - - if (auto pfwrite_msvcrt = __Get_MSVCRT_FUN(fwrite)) + if (auto pfwrite_msvcrt = try_get_fwrite()) { return pfwrite_msvcrt(buffer, size, count, stream); } diff --git a/ucrtbase.msvcrt/localeconv.cpp b/ucrtbase.msvcrt/localeconv.cpp index bce3d65..9ed8b4f 100644 --- a/ucrtbase.msvcrt/localeconv.cpp +++ b/ucrtbase.msvcrt/localeconv.cpp @@ -67,10 +67,11 @@ static wchar_t* __fastcall MultiByteToWideCharHelper(UINT CodePage, LPCCH lpMult // #if WindowsTargetPlatformMinVersion < WindowsTargetPlatformWindows7 +__EXPAND_MSVCRT_FUN(localeconv); + extern "C" lconv* __cdecl localeconv(void) { - __EXPAND_MSVCRT_FUN(localeconv); - + auto pMSVCRT_localeconv = try_get_localeconv(); if (pMSVCRT_localeconv == nullptr) { //正常不应该为空!! @@ -171,4 +172,4 @@ extern "C" lconv* __cdecl localeconv(void) } _LCRT_DEFINE_IAT_SYMBOL(localeconv); -#endif \ No newline at end of file +#endif diff --git a/ucrtbase.msvcrt/matherr.cpp b/ucrtbase.msvcrt/matherr.cpp index ffaddf4..a0981aa 100644 --- a/ucrtbase.msvcrt/matherr.cpp +++ b/ucrtbase.msvcrt/matherr.cpp @@ -7,15 +7,19 @@ typedef int(__cdecl* _HANDLE_MATH_ERROR)(struct _exception*); static _HANDLE_MATH_ERROR user_matherr; +extern "C" void __cdecl __setusermatherr( + _HANDLE_MATH_ERROR pf + ); + +__EXPAND_MSVCRT_FUN(__setusermatherr); + extern "C" void __cdecl __setusermatherr( _HANDLE_MATH_ERROR pf ) { //继续调用msvcrt版本是为了能接管 msvcrt的user_matherr,但是有一个问题,如果其他人调用了 __setusermatherr,这会覆盖msvcrt的user_matherr //二者会发生不一致……这类问题无法一种健全的解决方案,但是可以暂不处理 - __EXPAND_MSVCRT_FUN(__setusermatherr); - - if (auto p_setusermatherr_msvcrt = __Get_MSVCRT_FUN(__setusermatherr)) + if (auto p_setusermatherr_msvcrt = try_get___setusermatherr()) { p_setusermatherr_msvcrt(pf); } @@ -45,4 +49,4 @@ extern "C" int __cdecl __acrt_invoke_user_matherr(struct _exception* ex) return 0; -} \ No newline at end of file +} diff --git a/ucrtbase.msvcrt/msvcrt_loadhelper.cpp b/ucrtbase.msvcrt/msvcrt_loadhelper.cpp index bc3d49c..8c12aa4 100644 --- a/ucrtbase.msvcrt/msvcrt_loadhelper.cpp +++ b/ucrtbase.msvcrt/msvcrt_loadhelper.cpp @@ -1,7 +1,15 @@ #include +#include -HMODULE __fastcall __LTL_GetMSVCRTModule() +#include "msvcrt_loadhelper.h" + +#pragma comment(linker, "/merge:.YYLT1=.data") +#pragma comment(linker, "/merge:.YYLT2=.rdata") + +typedef void* (__cdecl* InitFunType)(); + +static HMODULE __fastcall __LTL_GetMSVCRTModule() { static HMODULE MSVCRTModuleCache; @@ -21,4 +29,60 @@ HMODULE __fastcall __LTL_GetMSVCRTModule() MSVCRTModuleCache = hMSVCRT ? hMSVCRT : (HMODULE)INVALID_HANDLE_VALUE; return hMSVCRT; -} \ No newline at end of file +} + +__declspec(allocate(".YYLT1$DAA")) static void* s_pfnReserve[] = { nullptr }; +#define __LTL_THUNKS_FUN_START (s_pfnReserve + 1) //指针缓存开始位置 +__declspec(allocate(".YYLT1$DAC")) static void* __LTL_THUNKS_FUN_END[] = { nullptr }; //指针缓存结束位置 + +__declspec(allocate(".YYLT2$IFA")) static void* const s_pfnInitReserve[] = { nullptr }; +#define __LTL_THUNKS_INIT_FUN_START (s_pfnInitReserve + 1) //函数初始化开始位置 +__declspec(allocate(".YYLT2$IFC")) static void* const __LTL_THUNKS_INIT_FUN_END[] = { nullptr }; //函数初始化开始位置 + +bool __cdecl __LTL_ThunksInit() +{ + for (auto p = __LTL_THUNKS_FUN_START; p != __LTL_THUNKS_FUN_END; ++p) + { + *p = __crt_fast_encode_pointer(nullptr); + } + + for (auto p = (InitFunType*)__LTL_THUNKS_INIT_FUN_START; p != (InitFunType*)__LTL_THUNKS_INIT_FUN_END; ++p) + { + if (*p == nullptr) + continue; + + (*p)(); + } + + return true; +} + +namespace YY +{ + namespace VC_LTL + { + void* __fastcall try_get_function( + void** _ppFunAddress, + char const* const _szName) + { + auto _p = __crt_fast_decode_pointer(*_ppFunAddress); + if (_p) + { + return _p == INVALID_HANDLE_VALUE ? nullptr : _p; + } + + do + { + auto _hModule = __LTL_GetMSVCRTModule(); + if (!_hModule) + break; + + _p = GetProcAddress(_hModule, _szName); + + InterlockedExchange((uintptr_t*)_ppFunAddress, (uintptr_t)__crt_fast_encode_pointer(_p ? _p : INVALID_HANDLE_VALUE)); + } while (false); + + return _p; + } + } +} diff --git a/ucrtbase.msvcrt/msvcrt_loadhelper.h b/ucrtbase.msvcrt/msvcrt_loadhelper.h index 3917ec7..ec72fc5 100644 --- a/ucrtbase.msvcrt/msvcrt_loadhelper.h +++ b/ucrtbase.msvcrt/msvcrt_loadhelper.h @@ -1,16 +1,30 @@ #pragma once #include -HMODULE __fastcall __LTL_GetMSVCRTModule(); - -#define __EXPAND_MSVCRT_FUN(name) \ -static decltype(name)* _CRT_CONCATENATE(pMSVCRT_, name); \ -if(_CRT_CONCATENATE(pMSVCRT_, name) == NULL)\ -{ \ - auto fun = GetProcAddress(__LTL_GetMSVCRTModule(), #name);\ - _CRT_CONCATENATE(pMSVCRT_, name) = fun ? (decltype(name)*)fun : (decltype(name)*)INVALID_HANDLE_VALUE;\ -} +#pragma section(".YYLT1$DAA", long, read, write) +#pragma section(".YYLT1$DAB", long, read, write) //LTL函数缓存节点 +#pragma section(".YYLT1$DAC", long, read, write) //保留,暂时用于边界结束 +#pragma section(".YYLT2$IFA", long, read) +#pragma section(".YYLT2$IFB", long, read) //LTL函数缓存初始化函数 +#pragma section(".YYLT2$IFC", long, read) //LTL函数缓存初始化函数结束 -#define __Get_MSVCRT_FUN(name) (_CRT_CONCATENATE(pMSVCRT_, name) != (decltype(name)*)INVALID_HANDLE_VALUE ? _CRT_CONCATENATE(pMSVCRT_, name) : (decltype(name)*)NULL) +namespace YY +{ + namespace VC_LTL + { + void* __fastcall try_get_function( + void** _ppFunAddress, + char const* const _szName); + } +} +#define __EXPAND_MSVCRT_FUN(name) \ +static decltype(name)* _CRT_CONCATENATE(try_get_, name)() \ +{ \ + __declspec(allocate(".YYLT2$IFB")) static void* const s_pfnInitFun = &_CRT_CONCATENATE(try_get_, name); \ + __pragma(warning(suppress:6031)) \ + _bittest((LONG*)(&s_pfnInitFun), 0); \ + __declspec(allocate(".YYLT1$DAB")) static void* _CRT_CONCATENATE(s_pfn_, name); \ + return (decltype(name)*)YY::VC_LTL::try_get_function(&_CRT_CONCATENATE(s_pfn_, name), #name); \ +} diff --git a/ucrtbase.msvcrt/setlocal_thunks.cpp b/ucrtbase.msvcrt/setlocal_thunks.cpp index 5fdd819..6790823 100644 --- a/ucrtbase.msvcrt/setlocal_thunks.cpp +++ b/ucrtbase.msvcrt/setlocal_thunks.cpp @@ -13,6 +13,7 @@ setlocal.cpp 的修正实现,利用现有msvcrt 函数生成新的 #include #include #include "msvcrt_loadhelper.h" + //static __crt_locale_pointers* ___StaticLocale; //const char* __clocalestr;/* (___StaticLocale->locinfo->lc_category[1].locale)*/ @@ -401,31 +402,6 @@ extern "C" extern unsigned char const __newcumap[384] #endif -__declspec(noinline) __inline bool __fastcall IsPointerInMsvcrtDll(const void* p) -{ - if (p == nullptr) - return false; - - static const void* pBegin = nullptr; - static const void* pEnd = nullptr; - - if (pBegin == nullptr || pEnd == nullptr) - { - MEMORY_BASIC_INFORMATION MemoryBasicInfo; - - if (VirtualQuery(__LTL_GetMSVCRTModule(), &MemoryBasicInfo, sizeof(MemoryBasicInfo)) == 0) - { - return false; - } - - pBegin = MemoryBasicInfo.AllocationBase; - pEnd = (char*)MemoryBasicInfo.AllocationBase + MemoryBasicInfo.RegionSize; - } - - return pBegin >= p && p < pEnd; -} - - static void __cdecl __addlocaleref(__crt_locale_data* ptloci) { InterlockedIncrement(&(ptloci->refcount)); @@ -1321,14 +1297,15 @@ static char const* __fastcall TryConverLocalenameToCountry( #if WindowsTargetPlatformMinVersion < WindowsTargetPlatformWindows10_10240 +__EXPAND_MSVCRT_FUN(_create_locale); + EXTERN_C _locale_t __cdecl _create_locale( _In_ int _Category, _In_z_ char const* _Locale ) { //如果存在 _create_locale,那么直接调用系统的 _create_locale - __EXPAND_MSVCRT_FUN(_create_locale); - if (auto p_create_locale_msvcrt = __Get_MSVCRT_FUN(_create_locale)) + if (auto p_create_locale_msvcrt = try_get__create_locale()) { char StaticBuffer[256]; @@ -1472,13 +1449,14 @@ _LCRT_DEFINE_IAT_SYMBOL(_configthreadlocale); #if WindowsTargetPlatformMinVersion < __MakeVersion(6, 2, 9200) +__EXPAND_MSVCRT_FUN(_free_locale); + EXTERN_C void __cdecl _free_locale( _In_opt_ _locale_t plocinfo ) { //如果目标系统存在 _free_locale,那么直接调用它,避免结构体更改导致的不兼容问题 - __EXPAND_MSVCRT_FUN(_free_locale); - if (auto p_free_locale_msvcrt = __Get_MSVCRT_FUN(_free_locale)) + if (auto p_free_locale_msvcrt = try_get__free_locale()) { return p_free_locale_msvcrt(plocinfo); } @@ -1537,6 +1515,8 @@ _LCRT_DEFINE_IAT_SYMBOL(_free_locale); #endif +__EXPAND_MSVCRT_FUN(setlocale); + extern "C" char* __cdecl setlocale( _In_ int _Category, _In_opt_z_ char const* _Locale @@ -1545,8 +1525,7 @@ extern "C" char* __cdecl setlocale( char StaticBuffer[256]; _Locale = TryConverLocalenameToCountry(_Locale, StaticBuffer, _countof(StaticBuffer)); - __EXPAND_MSVCRT_FUN(setlocale); - if (auto p_setlocale_msvcrt = __Get_MSVCRT_FUN(setlocale)) + if (auto p_setlocale_msvcrt = try_get_setlocale()) { return p_setlocale_msvcrt(_Category, _Locale); } @@ -1557,6 +1536,8 @@ extern "C" char* __cdecl setlocale( _LCRT_DEFINE_IAT_SYMBOL(setlocale); +__EXPAND_MSVCRT_FUN(_wsetlocale); + extern "C" wchar_t* __cdecl _wsetlocale( _In_ int _Category, _In_opt_z_ wchar_t const* _Locale @@ -1565,8 +1546,7 @@ extern "C" wchar_t* __cdecl _wsetlocale( wchar_t StaticBuffer[256]; _Locale = TryConverLocalenameToCountry(_Locale, StaticBuffer, _countof(StaticBuffer)); - __EXPAND_MSVCRT_FUN(_wsetlocale); - if (auto p__wsetlocale_msvcrt = __Get_MSVCRT_FUN(_wsetlocale)) + if (auto p__wsetlocale_msvcrt = try_get__wsetlocale()) { return p__wsetlocale_msvcrt(_Category, _Locale); }