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开发_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