用于追踪Windows DLL加载的Python模块
项目描述
dlltracer
《dlltracer》工具是用于诊断Windows上DLL解析失败导致的CPython导入错误的一种辅助工具。
通常,任何DLL加载错误都报告为顶层扩展模块的ImportError
。CPython无法显示更具体的信息,这可能会使得诊断变得困难。
此工具使用未充分记录的性能事件来报告导入扩展模块的中间步骤。这些事件未记录且不受支持,因此格式是通过示例推断出来的,可能会改变,但在它改变之前,它将报告实际发生的加载情况。然而,因为它无法报告从未发生的加载情况,所以您仍然需要进行一些工作来诊断失败的根源。
最有用的静态分析工具是dumpbin,它包含在Visual Studio中。当传递DLL或PYD文件以及/imports
选项时,它将列出所有应加载的依赖项。它通过名称显示它们,即在路径解析之前。
dlltracer
执行动态分析,显示在运行时加载的DLL及其完整路径。结合理解您模块的依赖关系图,更容易诊断整体导入失败的原因。
安装
pip install dlltracer
在您的环境中,pip
命令可能需要替换为更合适的命令,例如python -m pip
或pip3.9
。
使用
注意:无论输出如何收集,此工具都必须以管理员身份运行。否则,启动跟踪将失败,并出现PermissionError
。整个机器上只能有一个线程进行跟踪。因为Windows无法很好地管理跟踪状态,所以此工具将尝试停止任何其他正在运行的跟踪。
基本跟踪,将消息打印到标准输出
import dlltracer
import sys
with dlltracer.Trace(out=sys.stdout):
import module_to_trace
输出可能如下所示(对于import ssl
)
LoadLibrary \Device\HarddiskVolume3\Windows\System32\kernel.appcore.dll
LoadLibrary \Device\HarddiskVolume3\Program Files\Python39\DLLs\_ssl.pyd
LoadLibrary \Device\HarddiskVolume3\Windows\System32\crypt32.dll
LoadLibrary \Device\HarddiskVolume3\Program Files\Python39\DLLs\libcrypto-1_1.dll
LoadLibrary \Device\HarddiskVolume3\Program Files\Python39\DLLs\libssl-1_1.dll
LoadLibrary \Device\HarddiskVolume3\Windows\System32\user32.dll
LoadLibrary \Device\HarddiskVolume3\Windows\System32\win32u.dll
LoadLibrary \Device\HarddiskVolume3\Windows\System32\gdi32.dll
LoadLibrary \Device\HarddiskVolume3\Windows\System32\gdi32full.dll
LoadLibrary \Device\HarddiskVolume3\Windows\System32\msvcp_win.dll
LoadLibrary \Device\HarddiskVolume3\Windows\System32\imm32.dll
LoadLibrary \Device\HarddiskVolume3\Program Files\Python39\DLLs\_socket.pyd
LoadLibrary \Device\HarddiskVolume3\Program Files\Python39\DLLs\select.pyd
失败的导入可能如下所示(对于import ssl
但缺少libcrypto-1_1.dll
)
LoadLibrary \Device\HarddiskVolume3\Windows\System32\kernel.appcore.dll
LoadLibrary \Device\HarddiskVolume3\Program Files\Python39\DLLs\_ssl.pyd
LoadLibrary \Device\HarddiskVolume3\Windows\System32\crypt32.dll
LoadLibrary \Device\HarddiskVolume3\Program Files\Python39\DLLs\libssl-1_1.dll
Failed \Device\HarddiskVolume3\Windows\System32\crypt32.dll
Failed \Device\HarddiskVolume3\Program Files\Python39\DLLs\libssl-1_1.dll
Failed \Device\HarddiskVolume3\Program Files\Python39\DLLs\_ssl.pyd
Traceback (most recent call last):
File "C:\Projects\test-script.py", line 28, in <module>
import ssl
File "C:\Program Files\Python39\lib\ssl.py", line 98, in <module>
import _ssl # if we can't import it, let the error propagate
ImportError: DLL load failed while importing _ssl: The specified module could not be found.
请注意,缺少的DLL从未被提及,因此需要人工分析来诊断根本原因。
写入文件
要将输出写入文件对象(任何可以传递给print
的file=
参数的对象),将其作为Trace
的out=
参数传递。
import dlltracer
with open("log.txt", "w") as log:
with dlltracer.Trace(out=log):
import module_to_trace
收集到列表
要将事件收集到可迭代的对象中,将collect=True
传递给Trace
并绑定上下文管理器。结果将是一个包含事件对象的列表,通常是dlltracer.LoadEvent
和dlltracer.LoadFailedEvent
。
import dlltracer
with dlltracer.Trace(collect=True) as events:
try:
import module_to_trace
except ImportError:
# If we don't handle the error, program will exit before
# we get to inspect the events.
pass
# Inspect the events after ending the trace
all_loaded = {e.path for e in events if isinstance(e, dlltracer.LoadEvent)}
all_failed = {e.path for e in events if isinstance(e, dlltracer.LoadFailedEvent)}
引发审计事件
要为DLL加载引发审计事件,将audit=True
传递给Trace
。引发的事件是dlltracer.load
和dlltracer.failed
,并且两者都只包含路径作为参数。
import dlltracer
import sys
def hook(event, args):
if event == "dlltracer.load":
# args = (path,)
print("Loaded", args[0])
elif event == "dlltracer.failed":
# args = (path,)
print("Failed", args[0])
sys.add_audit_hook(hook)
with dlltracer.Trace(audit=True):
import module_to_trace
其他事件
注意:这主要是为了开发dlltracer
。
因为事件格式可能会改变,并且可能对其他事件感兴趣但尚未处理,所以将debug=True
选项传递给Trace
将启用收集、写入或审计所有事件。常规事件被抑制。
import dlltracer
import sys
def hook(event, args):
if event != "dlltracer.debug":
return
# args schema:
# provider is a UUID representing the event source
# opcode is an int representing the operation
# header is bytes taken directly from the event header
# data is bytes taken directly from the event data
provider, opcode, header, data = args
sys.add_audit_hook(hook)
with dlltracer.Trace(debug=True, audit=True, collect=True, out=sys.stderr) as events:
try:
import module_to_trace
except ImportError:
pass
for e in events:
assert isinstance(e, dlltracer.DebugEvent)
# DebugEvent contains provider, opcode, header and data as for the audit event
贡献
此项目欢迎贡献和建议。大多数贡献都需要您同意贡献者许可协议(CLA),声明您有权并且实际上授予我们使用您贡献的权利。有关详细信息,请访问https://cla.opensource.microsoft.com。
当您提交拉取请求时,CLA机器人将自动确定您是否需要提供CLA,并以适当的方式装饰PR(例如,状态检查,评论)。只需遵循机器人提供的说明即可。您只需要在整个使用我们的CLA的所有存储库中这样做一次。
此项目已采用Microsoft开源代码行为准则。有关更多信息,请参阅代码行为准则常见问题解答或通过opencode@microsoft.com联系以获取任何其他问题或评论。
商标
本项目可能包含项目、产品或服务的商标或标志。未经授权使用Microsoft商标或标志必须遵守并遵循Microsoft的商标和品牌指南。在修改版本的此项目中使用Microsoft商标或标志不得引起混淆或暗示Microsoft赞助。任何第三方商标或标志的使用均需遵守该第三方的政策。
项目详情
下载文件
下载适合您平台文件。如果您不确定选择哪一个,请了解更多关于安装包的信息。
源分发
构建分发
dlltracer-1.0.2.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 7749c30d6372bfb3e5c1d624b0d5d05580b7fc3de92dfaa4f41ef1e5180d219c |
|
MD5 | afee2c66c34596154273172f912a8f73 |
|
BLAKE2b-256 | 20e5e3d0809e0a6c7f1518ebc9a7a917201349287794280d908ab6b5b487dec9 |
dlltracer-1.0.2-cp311-cp311-win_amd64.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | d75f0923f44f115a94e396d4ddde01b46733296cd18a5e14151f937cf96b7139 |
|
MD5 | 94e56f684d4bd6e17c3a5406e593066c |
|
BLAKE2b-256 | c00bcee377cdcb1caea26768e2a8131e285c26ffb091f8ecf66b93688679c1f3 |