使用静态驱动程序验证程序查找 Windows 驱动程序中的缺陷

静态驱动程序验证程序 (SDV) 使用一组接口规则和操作系统模型来确定驱动程序是否与 Windows 操作系统正确交互。 SDV 发现驱动程序代码中的缺陷,这些缺陷可能指向驱动程序中的潜在 bug。

SDV 可以分析符合以下驱动程序模型之一的内核模式驱动程序:WDM、KMDF、NDIS 或 Storport。 有关详细信息,请参阅 支持的驱动程序确定静态驱动程序验证程序是否支持驱动程序或库。 此外,SDV (严重受限的规则集提供有限的支持,这些规则集侧重于常规错误,例如不遵循上述驱动程序模型的驱动程序的 null 取消引用) 。

准备源代码

使用以下步骤准备代码以进行分析。

  1. 使用函数角色类型声明驱动程序提供的函数

    SDV 要求使用函数角色类型声明来声明函数。 例如,必须使用 DRIVER_INITIALIZE 函数角色类型声明 DriverEntry 例程:

    DRIVER_INITIALIZE DriverEntry;
    

    声明后,实现 (或定义) 回调例程,如下所示:

    /
    // Driver initialization routine
    //
    NTSTATUS
      DriverEntry(
        _In_ struct _DRIVER_OBJECT  *DriverObject,
        _In_ PUNICODE_STRING  RegistryPath
        )
      {
          // Function body
      }
    

    每个支持的驱动程序模型都有一组用于驱动程序回调函数和调度例程的函数角色类型。 这些函数角色类型在 WDK 头文件中声明。 例如,下面是 Wdm.h 中显示的DRIVER_INITIALIZE角色类型的函数原型。

    /
    // Define driver initialization routine type.
    //
    _Function_class_(DRIVER_INITIALIZE)
    _IRQL_requires_same_
    typedef
    NTSTATUS
    DRIVER_INITIALIZE (
        _In_ struct _DRIVER_OBJECT *DriverObject,
        _In_ PUNICODE_STRING RegistryPath
        );
    
    typedef DRIVER_INITIALIZE *PDRIVER_INITIALIZE;
    

    由于函数角色类型已在 WDK 头文件中定义,因此只需将回调函数声明为该类型。 在本例中,将 DriverEntry 声明为 DRIVER_INITIALIZE 类型。 有关驱动程序模型的函数角色类型的完整列表,请参阅 使用函数角色类型声明

  2. 运行适用于 C/C++ 的代码分析

    为了帮助你确定是否准备好源代码,请在 Visual Studio 中运行 代码分析工具 。 代码分析工具检查 SDV 所需的函数角色类型声明。 当函数定义的参数与函数角色类型中的参数不匹配时,代码分析工具可以帮助识别可能已遗漏的任何函数声明或发出警告。

    • 在 Visual Studio 中打开驱动程序项目。
    • 在“ 生成 ”菜单中,单击“ 对解决方案运行代码分析”。

    结果显示在 “代码分析 ”窗口中。 修复可能错过的任何函数声明。 还可以配置代码分析工具,使其在生成解决方案时运行。

    下表显示了代码分析工具可能会在驱动程序代码中找到的一些警告。 若要运行静态驱动程序验证程序,驱动程序需要没有这些缺陷。

    C/C++ 警告的代码分析 说明
    C28101 驱动程序模块已推断出当前函数是 <function-type> 函数
    C28022 此函数上的函数类与用于定义它的 typedef 的函数类不匹配。
    C28023 要分配或传递的函数应具有针对至少一个类的 _Function_class_ 批注
    C28024 要分配到的函数指针是用函数类批注的,它未包含在函数类列表中。
    C28169 调度函数<>没有任何_Dispatch_type_注释
    C28208 函数签名与函数声明不匹配

运行静态驱动程序验证程序

  1. 在 Visual Studio 中打开驱动程序项目 (.vcxProj) 文件。 在“ 驱动程序 ”菜单中,单击“ 启动静态驱动程序验证程序...”

    这会打开静态驱动程序验证程序应用程序,可在其中控制、配置和计划静态驱动程序验证程序何时执行分析。

  2. 如果驱动程序包含库,请单击“ ”选项卡,然后单击“ 添加库 ”以添加库。

    浏览到库源代码的目录,然后选择项目文件 (.vcxProj) 。 添加驱动程序包含的所有库。 在 SDV 分析驱动程序之前,必须添加这些库。 开始分析驱动程序时,SDV 还会分析尚未处理的库。 处理库后,它将存储在全局 SDV 缓存中。 有关详细信息,请参阅 静态驱动程序验证程序中的库处理

  3. 检查静态驱动程序验证程序的配置设置。 单击“配置”选项卡。

    项目配置 项目配置显示你在 Visual Studio 中选择的配置和平台设置。

    资源 在大多数情况下,可以使用默认设置。 如果 SDV 报告 Timeout、GiveUp 或 Spaceout,则可以尝试调整这些设置。 有关详细信息,请参阅 对静态驱动程序验证程序进行故障排除的建议

    附表 选择开始验证的开始时间。 默认设置是在单击“”选项卡上的“启动”后立即开始分析。根据驱动程序的大小及其复杂性,静态分析可能需要很长时间才能运行。 你可能希望将分析安排在最方便的时候开始;例如,在一天结束时。

    注意

    ]请务必检查计算机的电源管理计划,以确保计算机在分析期间不会进入睡眠状态。

  4. 单击“ 规则 ”选项卡,选择要在开始分析时验证的驱动程序 API 使用规则。

    静态驱动程序验证程序检测正在 (WDF、WDM、NDIS 或 Storport) 分析的驱动程序类型,并为驱动程序类型选择默认规则集。 如果这是你第一次在驱动程序上运行 SDV,则应运行默认规则集。

    有关规则的信息,请参阅 DDI 符合性规则

  5. 启动静态分析。 单击“ ”选项卡,然后单击“ 开始”。 单击“ 开始”时,将显示一条消息,告知你已计划静态分析,并且分析可能需要很长时间才能运行。 单击 “确定” 继续。 分析从计划的时间开始。

查看和分析结果

随着静态分析的进行,SDV 将报告分析的状态。 分析完成后,SDV 将报告结果和统计信息。 如果驱动程序无法满足 API 使用规则,结果将报告为缺陷。

如果遇到任何问题,SDV 会在 “警告 ”和“ 错误” 页上显示这些问题。 “ 驱动程序属性” 页显示某些驱动程序属性的测试结果。 驱动程序属性测试用于识别驱动程序功能,以进一步限定分析。 可以使用 驱动程序属性 结果来确认驱动程序的预期属性和支持的功能。

若要查看 静态驱动程序验证程序报告中的特定缺陷,请单击“ 结果 ”窗格中的“缺陷”。 这将打开 跟踪查看器,其中显示规则冲突的代码路径的跟踪。 有关详细信息,请参阅 解释静态驱动程序验证程序结果

注意

静态驱动程序验证程序保留分析的结果和设置。 若要清除结果,请单击“ 清理”。

对静态驱动程序验证程序结果进行故障排除

如果 SDV 报告未发现任何缺陷,检查“主”选项卡以确保检测到入口点。 如果驱动程序未使用函数角色类型声明函数,SDV 将无法分析和查找驱动程序代码中的缺陷。 有关详细信息,请参阅 使用函数角色类型声明

如果 SDV 报告超时或无法返回有用的结果,则可能需要更改一些 SDV 配置选项。 有关如何排查 SDV 问题的详细信息,请参阅 针对静态驱动程序验证程序故障排除的建议

确定静态驱动程序验证程序是否支持你的驱动程序或库

使用函数角色类型声明

静态驱动程序验证程序规则

代码分析工具