【发布时间】:2015-11-24 03:37:53
【问题描述】:
我有特殊要求,我相信没有别的办法,
即:检测DLL的卸载。我用谷歌搜索并发现
a four-years old SO 关于这个。我选择了相同的
解决方案:钩FreeLibrary。
当代码进入MyFreeLibrary时,我会钩住
以相同的方式指定模块(inline-hook)。而在
MyEntryPoint,我先调用原来的入口点,然后
检查 reason 参数 - 如果值等于
DLL_PROCESS_DETACH,表示这个DLL的清理工作是
刚刚完成,它将从地址空间中卸载。
在这一点上,我有机会做我的工作。它有效。
就这样吗?不幸的是,它还没有完成。一个非常重要的 事情被忽略了:依赖。
例如,a.dll 链接到 b.dll 和 c.dll。当你加载
a.dll、b.dll 和 c.dll 将首先被加载(被初始化)。这
是因为b.dll和c.dll都列在了导入表中
a.dll,它们是 a.dll 的依赖项。同样,当您卸载
a.dll、b.dll 和 c.dll 如果它们的引用也可能被卸载
计数减少到零。我不知道关于如何
loader 找出 DLL 的依赖关系并卸载它们,
MSDN 页面 FreeLibrary 没谈过这个,我很高兴
明白这一点,但我没有找到相关信息。
所以主要的问题是如何检测依赖的卸载 一个DLL模块。我希望有同样的机会做我的工作。
一个可能的解决方案可能是导入表,找出 DLL 的依赖关系从其导入表中,并找出 来自其导入表的依赖项的依赖项等, 找出所有的依赖关系,钩住所有的入口点,我没有 知道,这听起来很疯狂,我需要一些建议。
【问题讨论】:
-
我不确定挂钩入口点是否能可靠地工作 - 据我所知,DLL 不一定要有入口点。
-
@HarryJohnston 我忘了。想了很久怎么解决,一直没有找到答案。也许这是一种错误的方式。 LdrDllNotification 可以工作,它已记录在案,但不幸的是 Windows XP 不支持它,并且 MSDN 表示“此功能可能会在不另行通知的情况下从 Windows 更改或删除”,尽管不太可能。
-
您必须确切知道何时卸载 DLL,还是可以稍微延迟?一种选择是定期枚举模块,然后在您看到一个或多个已卸载时采取行动。
-
@joshpoley 是的,在实际从地址空间卸载之前但在未初始化 (DLL_PROCESS_DETACH) 之后。
标签: c++ windows dll loadlibrary