网页原地址:http://dependencywalker.com/help/html/hidr_module_tree_view.htm
模块依赖关系树视图显示所有模块依赖关系的分层视图。模块可以通过多种方式成为另一个模块的依赖项。
Dependency Walker以您打开的根模块开始,并扫描其导入表以构建所需的依赖模块列表。然后,Dependency Walker扫描每个依赖模块的相关模块。直到所有模块及其相关模块都已处理完毕。
为了防止树无限膨胀和模块之间的无限循环依赖,当Dependency Walker遇到已经处理过的模块时,就会停止相应分支的处理。重复的模块在其伴随图像的中间标有一个小箭头(见下文)。
Dependency Walker还扫描每个相关模块,查找转发到其他模块的函数调用。如果找到转发的函数并且父模块实际调用了该函数,则该函数被转发到的模块也被拉入并添加到依赖关系树中。这些转发的模块在依赖关系树中进行了特殊标记,其附带图像旁边有一个小的状态图像(见下文)。
在处理依赖关系树时,Dependency Walker会在此过程中执行多项有效性检查。它会检查以确保每个模块都是有效的32位或64位Windows模块。它会检查不匹配的二进制文件,例如带有Alpha模块的x86模块。它扫描导入和导出函数表,查找未解析的外部函数。它检查允许的循环依赖性,以及不允许的循环转发依赖性。处理时遇到的任何错误都将使用特殊图像(见下文)显示错误的特定模块和/或消息框。
“ 自动展开”选项控制加载模块后最初看到的树的分支数量。启用此选项后,将显示整个树。关闭该选项后,将仅显示根模块,其直接依赖项和有错误的模块。
可以使用完整文件路径或仅使用文件名显示模块以节省屏幕空间。您可以使用“ 完整路径”选项控制显示的内容。您还可以通过选择“ 复制命令”将所选模块的文件名或路径复制到剪贴板。复制的实际文本将根据“ 完整路径”选项的设置方式而有所不同。模块依赖关系树视图的内容也可以使用“ 保存命令”或“ 另存为命令”保存到文本文件中。
以下是依赖关系树中可能显示的图片列表。此列表只是所有可能图像的子集。实际图像可以是以下一个或多个图像的组合:
普通图像
普通模块,没有错误。
重复模块。该模块已在树中的其他位置处理。您可以使用“ 突出显示原始实例”命令在树中查找模块的原始实例。
转发模块。此模块是依赖项,因为父模块已将其中一个函数转发到此模块。
延迟加载模块。如果在运行时调用它导出的函数,则将动态加载此模块。
动态模块。在分析期间检测到此模块,并由其父模块动态加载或使用。如果模块没有父模块,则Dependency Walker无法确定谁加载了模块。有关详细信息,请参阅使用应用程序分析检测动态依赖关系。
该模块是通过调用LoadLibraryEx(配合标志位DONT_RESOLVE_DLL_REFERENCES 和LOAD_LIBRARY_AS_DATAFILE)来动态加载的。这些标志使模块无需加载其依赖模块或调用模块的DllMain函数即可映射到内存中。
64位模块。此模块旨在在64位版本的Windows上运行。如果此图像不存在,则假定模块为32位。
警告和错误图像
缺少模块。在搜索路径中找不到此模块。有关更多信息,请参阅配置搜索顺序命令。
模块无效。有关描述模块错误的错误消息,请参阅 模块列表视图。
模块警告。此模块要么缺少其父模块所需的一个或多个导出函数,要么是CPU类型错误,要么在加载时无法初始化。对于缺少导出函数的情况,导入函数列表视图将列出导致问题的无法解析的函数。对于隐式依赖项,这个错误会导致父模块无法加载。如果模块无法加载或初始化,请检查 日志视图以获取有关故障的详细信息。
延迟加载模块警告。此模块要么缺少其父模块所需的一个或多个导出函数,要么是错误的CPU类型。对于缺少导出函数的情况, 导入函数列表视图将列出缺少的无法解析的函数。对于延迟加载,这很可能不是错误,因为开发人员使用延迟加载模块的一个原因是他们不确定依赖模块中是否存在特定函数。延迟加载模块的父节点能从该问题中恢复。
动态模块警告。父模块尝试使用GetProcAddress获取函数地址时,此模块缺少一个或多个导出函数,或者CPU类型错误或加载时无法初始化。对于缺少导出到处函数的情况, 导入函数列表视图将列出父模块无法找到的函数。对于动态依赖关系,这通常只是一个警告,因为模块动态检查另一个模块中是否存在函数是完全正常的,即使该函数不存在也是如此。如果模块无法加载或初始化,请检查 日志视图以获取有关故障的详细信息。
有关模块错误的更多详细信息,请参阅“ 如何解释依赖性沃克中的警告和错误”部分。
模块可能不止一次显示为单个父模块的依赖项。Dependency Walker执行此操作以通知您此模块是一个依赖项,原因不止一个。模块可以显示为隐式链接依赖项,转发依赖项和动态依赖项,所有这些都在单个父模块下。
例如,如果模块A隐式链接到模块B,您将在模块A下看到模块B作为隐式依赖项。父模块B实例的父导入功能列表视图中列出的功能是模块A能够成功加载所需的功能。在运行时分析期间,如果模块A动态加载模块B,模块B的第二个实例将出现在模块A下,但这次使用不同的图像(见上文)表示它是动态加载的。在模块B的第二个实例的父导入函数列表视图中列出的函数是模块A在运行时使用GetProcAddress函数调用在模块B中查找的内容。