Skip to content

Commit

Permalink
Opt, 废除__YY_Thunks_Process_Terminating弱符号,提高反初始化性能
Browse files Browse the repository at this point in the history
  • Loading branch information
mingkuang-Chuyu committed Sep 20, 2024
1 parent bb8979b commit 3894356
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 71 deletions.
47 changes: 19 additions & 28 deletions src/Build.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,7 @@ cl /O1 /Os /Oi /GS- /std:c++17 /execution-charset:utf-8 /Zc:sizedDealloc- /Zc:tl
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%

::生成weak符号,一些非必须符号安排为weak可以避免链接失败
LibMaker.exe FixObj "%~dp0..\\objs\\%Platform%\\%1" /WeakExternFix:__security_cookie=%PointType% /WeakExternFix:__YY_Thunks_Process_Terminating=4 /WeakExternFix:__acrt_atexit_table=%PointType% /WeakExternFix:__pfnDllMainCRTStartupForYY_Thunks=%PointType%
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%
if "%3"=="" goto:eof
set DEF_FILES=%3
:AppendWeak
for /f "tokens=1* delims=+" %%a in ("%DEF_FILES%") do (
echo "AppendWeak %~dp0def\\%Platform%\\%%a"
LibMaker.exe AppendWeak /MACHINE:%Platform% /DEF:"%~dp0def\\%Platform%\\%%a" /OUT:"%~dp0..\\objs\\%Platform%\\%1"
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%
set DEF_FILES=%%b
)

if defined DEF_FILES goto :AppendWeak
call:FixObj "%~dp0..\\objs\\%Platform%\\%1" %3

goto:eof

Expand All @@ -57,21 +45,7 @@ cl /O1 /Os /Oi /GS- /std:c++17 /execution-charset:utf-8 /Zc:sizedDealloc- /Zc:tl
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%

::生成weak符号,一些非必须符号安排为weak可以避免链接失败
LibMaker.exe FixObj "%~dp0..\\Lib\\%1\\%Platform%\\YY_Thunks_for_%1.obj" /WeakExternFix:__security_cookie=%PointType% /WeakExternFix:__YY_Thunks_Process_Terminating=4 /WeakExternFix:__acrt_atexit_table=%PointType% /WeakExternFix:__pfnDllMainCRTStartupForYY_Thunks=%PointType%
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%

if "%3"=="" goto:BuildWeak
set DEF_FILES=%3
:AppendWeakByLib
for /f "tokens=1* delims=+" %%a in ("%DEF_FILES%") do (
echo "AppendWeak %~dp0def\\%Platform%\\%%a"
LibMaker.exe /PREFIX:YY_Thunks_ AppendWeak /MACHINE:%Platform% /DEF:"%~dp0def\\%Platform%\\%%a" /OUT:"%~dp0..\\Lib\\%1\\%Platform%\\YY_Thunks_for_%1.obj"
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%
set DEF_FILES=%%b
)

if defined DEF_FILES goto:AppendWeakByLib
:BuildWeak
call:FixObj "%~dp0..\\Lib\\%1\\%Platform%\\YY_Thunks_for_%1.obj" %3

set "SupportApiSet=/SupportApiSet"
set "WinVersion=%1"
Expand Down Expand Up @@ -163,3 +137,20 @@ call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj __WindowsNT10_19041
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%

goto:eof

:: FixObj "XXX\YY_Thunks_for_Vista.obj" 1.def+2.def
:FixObj
LibMaker.exe FixObj %1 /WeakExternFix:__security_cookie=%PointType% /WeakExternFix:__acrt_atexit_table=%PointType% /WeakExternFix:__pfnDllMainCRTStartupForYY_Thunks=%PointType%
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%
if "%2"=="" goto:eof
set DEF_FILES=%2
:AppendWeak
for /f "tokens=1* delims=+" %%a in ("%DEF_FILES%") do (
echo "AppendWeak %~dp0def\\%Platform%\\%%a" %1
LibMaker.exe AppendWeak /MACHINE:%Platform% /DEF:"%~dp0def\\%Platform%\\%%a" /OUT:%1
if %ErrorLevel% NEQ 0 exit /b %ErrorLevel%
set DEF_FILES=%%b
)

if defined DEF_FILES goto :AppendWeak
goto:eof
14 changes: 6 additions & 8 deletions src/Thunks/DllMainCRTStartup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,10 @@ namespace YY::Thunks::internal
break;
#endif
case DLL_PROCESS_DETACH:
#if (YY_Thunks_Target < __WindowsNT5_1)
__YY_Thunks_Process_Terminating = _pReserved != nullptr;
#endif
__if_exists(__YY_Thunks_Process_Terminating)
{
__YY_Thunks_Process_Terminating = _pReserved != nullptr ? -1 : 1;
}

#if YY_Thunks_Target < __WindowsNT6
if (internal::GetSystemVersion() < internal::MakeVersion(6, 0) && _tls_index_old == 0 && g_TlsMode == TlsMode::ByDllMainCRTStartupForYY_Thunks)
Expand All @@ -548,18 +549,15 @@ namespace YY::Thunks::internal
if (_pReserved == nullptr)
{
FreeTlsIndex();
__YY_uninitialize_winapi_thunks();
}
__YY_uninitialize_winapi_thunks();
return _bRet;
}
else
#endif
{
auto _bRet = _pfnDllMainCRTStartup(_hInstance, _uReason, _pReserved);
if (_pReserved == nullptr)
{
__YY_uninitialize_winapi_thunks();
}
__YY_uninitialize_winapi_thunks();
return _bRet;
}
break;
Expand Down
66 changes: 33 additions & 33 deletions src/Thunks/YY_Thunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,34 +104,20 @@ else
*/
EXTERN_C const UINT64 __YY_Thunks_Installed = YY_Thunks_Target;

/*
导出一个外部弱符号,指示当前是否处于强行卸载模式。
EXTERN_C BOOL __YY_Thunks_Process_Terminating;
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
switch(dwReason)
{
case DLL_PROCESS_DETACH:
//我们可以通过 lpReserved != NULL 判断,当前是否处于强行卸载模式。
__YY_Thunks_Process_Terminating = lpReserved != NULL;
……
break;
……
*/
#if (YY_Thunks_Target < __WindowsNT5_1)
//Windows 2000不支持RtlDllShutdownInProgress,因此依然引入__YY_Thunks_Process_Terminating
EXTERN_C extern BOOL __YY_Thunks_Process_Terminating;
#endif
// 从DllMain缓存RtlDllShutdownInProgress状态,规避退出时调用RtlDllShutdownInProgress。
// 0:缓存无效
// 1:模块正常卸载
// -1:开始进程准备终止
static int __YY_Thunks_Process_Terminating;

#if (YY_Thunks_Target < __WindowsNT6)
static HANDLE _GlobalKeyedEventHandle;
#endif

static uintptr_t __security_cookie_yy_thunks;

extern "C" IMAGE_DOS_HEADER __ImageBase;

#define _APPLY(_SYMBOL, _NAME, ...) \
constexpr const wchar_t* _CRT_CONCATENATE(module_name_, _SYMBOL) = _CRT_WIDE(_NAME);
_YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY)
Expand Down Expand Up @@ -561,6 +547,25 @@ static UINT_PTR GetSecurityNewCookie()

static volatile ThunksInitStatus s_eThunksStatus /*= ThunksInitStatus::None*/;

static bool __YY_DllShutdownInProgress()
{
__if_exists(__YY_Thunks_Process_Terminating)
{
if (__YY_Thunks_Process_Terminating != 0)
return __YY_Thunks_Process_Terminating == -1;
}

#if (YY_Thunks_Target < __WindowsNT5_1) || !defined(__USING_NTDLL_LIB)
if (const auto RtlDllShutdownInProgress = (decltype(::RtlDllShutdownInProgress)*)GetProcAddress(try_get_module_ntdll(), "RtlDllShutdownInProgress"))
#endif
{
return RtlDllShutdownInProgress();
}

// 按理说不太可能走到这里,难道是老系统时没有被DllMain接管?
return false;
}

static void __cdecl __YY_uninitialize_winapi_thunks()
{
// 只反初始化一次
Expand All @@ -573,18 +578,8 @@ static void __cdecl __YY_uninitialize_winapi_thunks()
return;

//当DLL被强行卸载时,我们什么都不做,因为依赖的函数指针可能是无效的。
__if_exists(__YY_Thunks_Process_Terminating)
{
if (__YY_Thunks_Process_Terminating)
return;
}
#if (YY_Thunks_Target < __WindowsNT5_1) || !defined(__USING_NTDLL_LIB)
if (const auto RtlDllShutdownInProgress = (decltype(::RtlDllShutdownInProgress)*)GetProcAddress(try_get_module_ntdll(), "RtlDllShutdownInProgress"))
#endif
{
if (RtlDllShutdownInProgress())
return;
}
if(__YY_DllShutdownInProgress())
return;

auto pModule = (HMODULE*)__YY_THUNKS_MODULE_START;
auto pModuleEnd = (HMODULE*)__YY_THUNKS_FUN_START;
Expand Down Expand Up @@ -685,6 +680,11 @@ static int __cdecl __YY_initialize_winapi_thunks()
return 0;
}

// 当前模块是exe不注册反初始化,如果模块就是exe自己,那么反初始化必然代表进程退出
// 当进程退出时,关闭句柄或者卸载DLL这些都不是必须进行的,以提高性能。
if (PVOID(&__ImageBase) == ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ImageBaseAddress)
return 0;

// 如果 == null,那么有2种情况:
// 1. 非UCRT,比如2008,VC6,这时,调用 atexit是安全的,因为atexit在 XIA初始化完成了。
// 2. UCRT 并且处于MD状态。这时 atexit初始化 会提与 XIA,这时也是没有问题的。
Expand Down
2 changes: 0 additions & 2 deletions src/YY-Thunks.UnitTest/weak.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@

const int __YY_Thunks_Process_Terminating;

const void* __acrt_atexit_table;

const void* __pfnDllMainCRTStartupForYY_Thunks;

0 comments on commit 3894356

Please sign in to comment.