Windows Driver开发_TraceEvents调试以及加载驱动的方法

Posted 17岁boy想当攻城狮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Windows Driver开发_TraceEvents调试以及加载驱动的方法相关的知识,希望对你有一定的参考价值。

在最新版的WDK框架里,我们新建了Windows Driver KMDF模型之后默认使用的TraceEvents来打印输出的,这套输出机制叫WPP,我们可以在DriverEntry函数里看到它的初始化代码:

WPP_INIT_TRACING(DriverObject, RegistryPath);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

如果想要使用TraceEvents需要在WPP_INIT_TRACING之后才能使用,它们依赖于Trace.h文件,一般默认生成KMDF时Visual Studio会自动生成这个头文件,里面包含了WPP的相关定义。

如果没有可以新建一个Trace.h头文件,并输入如下内容:

这段代码取自微软官方封装的WPP代码。

/*++

Module Name:

    Trace.h

Abstract:

    Header file for the debug tracing related function defintions and macros.

Environment:

    Kernel mode

--*/

//
// Define the tracing flags.
//
// Tracing GUID - 16803b14-05e0-4215-9336-06418469d132
//

#define WPP_CONTROL_GUIDS                                              \\
    WPP_DEFINE_CONTROL_GUID(                                           \\
        KMDFDriver1TraceGuid, (16803b14,05e0,4215,9336,06418469d132), \\
                                                                            \\
        WPP_DEFINE_BIT(MYDRIVER_ALL_INFO)                              \\
        WPP_DEFINE_BIT(TRACE_DRIVER)                                   \\
        WPP_DEFINE_BIT(TRACE_DEVICE)                                   \\
        WPP_DEFINE_BIT(TRACE_QUEUE)                                    \\
        )                             

#define WPP_FLAG_LEVEL_LOGGER(flag, level)                                  \\
    WPP_LEVEL_LOGGER(flag)

#define WPP_FLAG_LEVEL_ENABLED(flag, level)                                 \\
    (WPP_LEVEL_ENABLED(flag) &&                                             \\
     WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)

#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \\
           WPP_LEVEL_LOGGER(flags)
               
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \\
           (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)

//           
// WPP orders static parameters before dynamic parameters. To support the Trace function
// defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to
// reorder the arguments to what the .tpl configuration file expects.
//
#define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags)
#define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags)

//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC TraceFLAGS=MYDRIVER_ALL_INFO(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//

 最下面这段是伪指令,给编译器看的,目的就是生成Trace宏函数

//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC TraceFLAGS=MYDRIVER_ALL_INFO(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//

然后在你的源文件中包含"Trace.h"头文件,包含好了我们在修改一下配置,让Visual Stuio知道Trace对应的描述文件是哪个,我们打开项目配置开始配置:

一、在Wpp Tracing中将Run Wpp Tracing设置为Yes,开启Trace日志功能

二、将Function And Macro Options中的Enable Infight Trace Recorder设置为yes,开启追踪功能,让日志输出到内核记录日志里去,这样就能用一些软件去读这个记录日志里读到我们的通过Trace打印的日志了。

 三、在File Options中的Scan Configuration Data里输入我们刚刚创建的文件名,告诉编译器描述Trace文件是哪个。 

包含了之后在你的文件中包含"driver.tmh"就可以了,这里的名称以你包含Trace.h的文件名称为例,在编译时编译器会自动编译Trace.h中的伪指令并生成对应的.tmh文件。

tmh文件里就包含了TraceEvents宏函数声明和实现

在使用TraceEvents函数之前需要先初始化,在你的DriverEvent里将它初始化:

WPP_INIT_TRACING(DriverObject, RegistryPath);

这里介绍一下TraceEvents的宏函数的使用方法:

TraceEvents(LEVEL, FLAGS, STR,...);

LEVEL表示信息模式级别,可以取以下值:

#define TRACE_LEVEL_NONE        0   // Tracing is not on
#define TRACE_LEVEL_CRITICAL    1   // Abnormal exit or termination
#define TRACE_LEVEL_FATAL       1   // Deprecated name for Abnormal exit or termination
#define TRACE_LEVEL_ERROR       2   // Severe errors that need logging
#define TRACE_LEVEL_WARNING     3   // Warnings such as allocation failure
#define TRACE_LEVEL_INFORMATION 4   // Includes non-error cases(e.g.,Entry-Exit)
#define TRACE_LEVEL_VERBOSE     5   // Detailed traces from intermediate steps
#define TRACE_LEVEL_RESERVED6   6
#define TRACE_LEVEL_RESERVED7   7
#define TRACE_LEVEL_RESERVED8   8
#define TRACE_LEVEL_RESERVED9   9

FLAGS表示标志,即当前打印的发生在哪个标志上,当我们创建一个KMDF框架时一般分为三个文件:

Device.c 设备文件,在加载驱动时会调用,用于创建设备,比如Linux驱动加载以后会在Dev下创建一个设备文件

Driver.c   驱动文件,驱动代码

Queue.c   驱动退出相关代码

这三个分别对应不同事件时产生的,Device.c会在创建设备时被调用,而Driver.c则是驱动代码,用于驱动设备时会被调用,Queue.c则是在收尾时会被调用。

在打印时应针对不同的情况设置不同的FLAGS,所以FLAGS支持如下几个选项:

MYDRIVER_ALL_INFO:所有,通用设备信息

TRACE_DRIVER:驱动标志,表示当前处于驱动事件阶段

TRACE_DEVICE:设备标志,表示当前处于设备事件阶段

TRACE_QUEUE:收尾标志,表示当前设备驱动将进行uninstall

有时使用这些标志可能会出现未定义的情况,可以忽略,你build之后不会报错,这个原因可能是编译器生成tmh文件时缓存没有更新过来。

最后演示一下用法:

TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Hello Word!");

可变参数,可以像Printf一样使用

TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Hello Word!%d",1);

当我们编译好并生成sys之后我们想要调试怎么办?

WDK提供了一个工具:traceview.exe,注意TraceEvents打印的只能用这款软件DbgView查看不到的。

你到WDK的安装目录下进入Tools-x64(x86)下能找到这款软件。

然后选中File-Create New Log Session,然后选择PDB调试的方式,我们生成的sys一般都附带了PDB文件,里面包含了调试信息,sys驱动文件路径等等。

选择你的PDB之后点击OK

然后点击Next

 最后点击Finish,如果想保存Log可以选中Log Trace Event Data To File 

最后我们设置事件等级,双击Level 

因为我们里面使用的是TRACE_LEVEL_INFORMATION,所以选中Information

最后FLags全都选中,然后点击OK就可以了 

到这一步日志系统就准备好了,那么就剩最后一步,就是加载驱动。

WDK自带了一个devcon.exe的工具,但是用起来不是那么方便,这里我使用的是另外一个加载的工具,Windows也提供了SC加载服务的API函数,大家可以利用这些函数实现自己的加载工具。

我使用的是:DriverMonitor,同时也有:KmdManager,这两款加载工具目前还是不错的。

以下是这两款软件的截图,同时附上下载地址:SysLoader驱动加载程序,用于调试驱动-WindowsServer文档类资源-CSDN下载

DriverMonitor:

KmdManager:

这里我使用的是DriverMonitor,以管理员权限打开它,然后选择:File-Open Driver...

选择你的Driver 

然后点击GO图标会开始调用驱动代码,DriverCreate函数是在加载驱动时调用的,当点击GO图标时调用的驱动代码是DriverEntry函数。

当我们执行的时候它报了一个错误:

翻译过来就是Windows无法验证数字签名,这个是在Win7以后的系统都需要数字签名,如何申请签名这个后面说,先教大家在调试时解决这个问题,大家可以在Win10的Setting界面进入高级选项,关闭数字签名,具体可以Web搜索一下Win10关闭数字签名

然后就可以了

 同时在TraceView中可以看到对应的输出:

当我们想删除驱动时可以点击X图标就可以了

以上是关于Windows Driver开发_TraceEvents调试以及加载驱动的方法的主要内容,如果未能解决你的问题,请参考以下文章

Windows Driver开发_安装与配置环境

Windows Driver开发_TraceEvents调试以及加载驱动的方法

Windows Driver开发_TraceEvents调试以及加载驱动的方法

Windows Driver开发_NT Driver框架:The driver is not in a state to accept this command

Windows Driver开发_NT Driver框架:The driver is not in a state to accept this command

在Windows下编译mongo-c-driver 1.3.x