Wdf框架之WdfObject状态机(2)

    前一篇博文<Wdf框架之WdfObject状态机(1)>提到调用WdfObjectCreate使框架对象被纳入对象状态机的管理之下。本篇我们看下框架对象的销毁过程,即如何结束它的生命周期,进而退出状态机。由于对象的销毁往往会引发着子对象的销毁,整个过程跟迷宫一样复杂,所以我们先在迷宫外了解一下穿越迷宫的捷径,暂时不深入探索----即假设程序中只创建一个Wdf驱动对象(空驱动,没有子对象),不提供其他任何功能,然后停用驱动。

#include <ntddk.h>
#include <wdf.h>

void Unload(WDFDRIVER drvObj)
{
	UNREFERENCED_PARAMETER(drvObj);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT drvObj, PUNICODE_STRING regPath)
{
	WDF_DRIVER_CONFIG config;
	WDFDRIVER drvHnd;
	UNREFERENCED_PARAMETER(regPath);

	WDF_DRIVER_CONFIG_INIT(&config, NULL);
	config.DriverInitFlags = WdfDriverInitNonPnpDriver;

	config.EvtDriverUnload = Unload;
	return WdfDriverCreate(drvObj,regPath,NULL,&config,&drvHnd);
}
如前所述,这是个简单的空的驱动程序,不创建任何设备对象,可以说这是一个非PNP驱动。对于非PNP驱动需要为WDF_DRIVER_CONFIG!DriverInitFlags域指定WdfDriverInitNonPnpDriver;同时,为 WDF_DRIVER_CONFIG!EvtDriverUnload域指定Unload函数。该驱动通过sc create/sc delete创建/删除服务,通过sc start/sc stop加载/停用驱动。

    大家已经知道,调用WdfDriverCreate后会创建FxDriver对象,并返回代表FxDriver的句柄 。我们的目标是观察FxDriver!m_ObjectState在驱动卸载过程中的状态变化。虽然,我们有WDF的源码,却无法单步跟踪源码和确切的状态值。不过,这是无法阻止我观察对象的状态变化的,变通之策就是从WdfDriverCreate返回的句柄获得FxDriver对象,然后通过设置访问断点来追踪状态变迁。下列输出是Wdf01000!FxDriver::m_ObjectState域在结构中的偏移:

kd> dt Wdf01000!FxDriver -y m_ObjectState 
   +0x012 m_ObjectState : Uint2B
    现在,我们开始着手于从WDF句柄获得WDF对象。虽然WDF源码中给出了两者之间的计算方法
VOID 
FxObjectHandleGetPtr(
    __in PFX_DRIVER_GLOBALS FxDriverGlobals,
    __in WDFOBJECT Handle,
    __in WDFTYPE Type,
    __out PVOID* PPObject
    ); //从WDF句柄获得WDF对象的内联函数
但是谁能保证它会一成不变的保持下去,所以还是得依靠windbg的扩展命令----!wdfhandle,在实例代码的return语句之后下断点,当命中断点后,运行下列命令:
kd> .load wdfkd ;加载调试wdf驱动的DLL,以支持windbg扩展命令
kd> ?? drvHnd ;查看WdfDriverCreate返回的句柄值
struct WDFDRIVER__ *  0x73bf71e8;<-----句柄值
   +0x000 unused           : ??
kd> !wdfhandle 0x73bf71e8 ;!wdfhandle用以根据句柄值获得对象信息
Treating handle as a KMDF handle!
Dumping WDFHANDLE 0x73bf71e8
=============================
Handle type is WDFDRIVER
Refcount: 1
...
!wdfobject 0x8c408e10 ;提示运行!wdfobject, 0x8c408e10应该就是FxObject对象的地址  
kd> !wdfobject 0x8c408e10 ;
The type for object  is FxDriver
State: FxObjectStateCreated (0x1) ;<-----!wdfobject已经分析出当前FxObject对象的状态值
!wdfhandle 0x73bf71e8
上面的一系列命令,我们成功获得FxDriver对象的地址(记得记下这个地址,后面调试过程中会反复使用上诉命令),接着,准备下访问断点:

kd> dt FxDriver 0x8c408e10 -y m_Refcnt -y m_ObjectState
Wdf01000!FxDriver
   +0x008 m_Refcnt      : 0n1
   +0x012 m_ObjectState : 1
kd> ba w 4 0x8c408e10+0x08 ;FxDriver!m_Refcnt的访问断点
kd> ba w 4 0x8c408e10+0x10 ;FxDriver!m_ObjectState的访问断点,考虑到内存对齐,所以偏移设置为0x10


    另外,为了验证在调用wdf01000!FxDriver::Unload前,FxDriver!m_ObjectState的状态未发生改变,还需要在wdf01000!FxDriver::Unload处下断点:

kd> x wdf01000!FxDriver::Unload
86a16672          Wdf01000!FxDriver::Unload (struct _DRIVER_OBJECT *)
kd> bp Wdf01000!FxDriver::Unload

    现在万事俱备,准备观察状态的变化。驱动停止过程中,在Wdf01000!FxDriver::Unload处遇到断点,正如所料,此时FxObject状态没有改变,为FxObjectStateCreated:

kd> g
Breakpoint 4 hit
Wdf01000!FxDriver::Unload:
86a16672 8bff            mov     edi,edi
kd> bl
 0 e a4d510d8     0001 (0001) KMDFdrv!FxDriverEntry
 1 e a4d51036     0001 (0001) KMDFdrv!DriverEntry+0x36
 2 e 8c408e18 w 4 0001 (0001) 
 3 e 8c408e20 w 4 0001 (0001) 
 4 e 86a16672     0001 (0001) Wdf01000!FxDriver::Unload

kd> kb
 # ChildEBP RetAddr  Args to Child              
00 b2c03bb8 a4d511de afc5b890 b2c03be0 81bc5013 Wdf01000!FxDriver::Unload ;断点发生在FxDriver::Unload[fxdriver.cpp @ 143]
01 b2c03bc4 81bc5013 afc5b890 8c234910 afc257c0 KMDFdrv!FxStubDriverUnload+0x1a [stub.cpp @ 159]
02 b2c03be0 8191b8c5 8c234910 00000000 afc257c0 nt!IopLoadUnloadDriver+0x77
kd> !wdfobject 0x8c408e10 ;查看FxDriver::m_ObjectState状态

The type for object 0x8c408e10 is FxDriver
State: FxObjectStateCreated (0x1) ;从驱动启动到停用,m_ObjectState状态一直没有改变
!wdfhandle 0x73bf71e8

kd> !wdfhandle 0x73bf71e8 
Treating handle as a KMDF handle!

Dumping WDFHANDLE 0x73bf71e8
=============================
Handle type is WDFDRIVER
Refcount: 1 <-引用计数也没有发生改变

!wdfobject 0x8c408e10

继续放调试器运行,由于FxDriver会频繁修改m_Refcnt和m_ObjectState的值,因此调试器会陆陆续续的中断若干次(附注,根据我观察,每次发生访问断点时esi寄存器存放FxDriver对象的地址):

kd> g
Breakpoint 3 hit
Wdf01000!FxObject::IsForceDisposeThreadLocked+0xd [inlined in Wdf01000!FxObject::DeleteObject+0xbe]:
86a0589e 0f859db90200    jne     Wdf01000!FxObject::DeleteObject+0x2ba61 (86a31241)
kd> ub . L2
Wdf01000!FxObject::SetObjectStateLocked+0xf [fxobjectstatemachine.cpp @ 124] [inlined in Wdf01000!FxObject::DeleteObject+0xb5 [fxobjectstatemachine.cpp @ 124]]:
86a05895 b809000000      mov     eax,9
86a0589a 66894612        mov     word ptr [esi+12h],ax ;汇编代码显示,框架正在修改m_ObjectState的值
kd> kb
 # ChildEBP RetAddr  Args to Child              
00 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::IsForceDisposeThreadLocked+0xd [fxobject.hpp @ 1379]
01 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::DisposeChildrenWorker+0xd [fxobjectstatemachine.cpp @ 1094]
02 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::DeleteWorkerAndUnlock+0x30 [d:\th\minkernel\wdf\framework\shared\object\fxobjectstatemachine.cpp @ 937]
03 b2c03ba4 86a166b2 8c234910 81a8f220 afc257c0 Wdf01000!FxObject::DeleteObject+0xbe [fxobjectstatemachine.cpp @ 124]
04 b2c03bb8 a4d511de afc5b890 b2c03be0 81bc5013 Wdf01000!FxDriver::Unload+0x40 [fxdriver.cpp @ 176]
05 b2c03bc4 81bc5013 afc5b890 8c234910 afc257c0 KMDFdrv!FxStubDriverUnload+0x1a [stub.cpp @ 159]

这次中断是因为框架企图修改FxDriver::m_ObjectState的状态值:

kd> !wdfobject 0x8c408e10
The type for object 0x8c408e10 is FxDriver
State: FxObjectStateDeletedDisposing (0x9) <--m_ObjectState由1变为9
!wdfhandle 0x73bf71e8
dt FxDriver 0x8c408e10

kd> !wdfhandle 0x73bf71e8
Treating handle as a KMDF handle!
Dumping WDFHANDLE 0x73bf71e8
=============================
Handle type is WDFDRIVER
Refcount: 1 <--引用计数暂无改变

!wdfobject 0x8c408e10

继续让windbg运行,之后马上会触发访问断点,这次还是因为修改m_ObjectState的状态:

kd> g
Breakpoint 3 hit
Wdf01000!FxObject::DeleteObject+0x11e:
86a058fe 8bff            mov     edi,edi
kd> ub . L3
Wdf01000!FxObject::SetObjectStateLocked+0x9 [fxobjectstatemachine.cpp @ 124] [inlined in Wdf01000!FxObject::DeleteObject+0x10f [fxobjectstatemachine.cpp @ 124]]:
86a058ef 0f85b1b90200    jne     Wdf01000!FxObject::DeleteObject+0x2bac6 (86a312a6)
86a058f5 b80a000000      mov     eax,0Ah
86a058fa 66894612        mov     word ptr [esi+12h],ax
kd> !wdfhandle 0x73bf71e8
Treating handle as a KMDF handle!

Dumping WDFHANDLE 0x73bf71e8
=============================
Handle type is WDFDRIVER
Refcount: 1 ;引用计数没有发生改变
!wdfobject 0x8c408e10
kd> !wdfobject 0x8c408e10

The type for object 0x8c408e10 is FxDriver
State: FxObjectStateDeletedAndDisposed (0xa) ;m_ObjectState状态值由9变为0xa
!wdfhandle 0x73bf71e8

dt FxDriver 0x8c408e10
kd> kb
 # ChildEBP RetAddr  Args to Child              
00 b2c03ba4 86a166b2 8c234910 81a8f220 afc257c0 Wdf01000!FxObject::DeleteObject+0x11e [fxobjectstatemachine.cpp @ 124]
01 b2c03bb8 a4d511de afc5b890 b2c03be0 81bc5013 Wdf01000!FxDriver::Unload+0x40 [fxdriver.cpp @ 176]
02 b2c03bc4 81bc5013 afc5b890 8c234910 afc257c0 KMDFdrv!FxStubDriverUnload+0x1a [stub.cpp @ 159]
03 b2c03be0 8191b8c5 8c234910 00000000 afc257c0 nt!IopLoadUnloadDriver+0x77

再次F5,下一次触发访问中断是因为Unload中调用Release减少FxDriver的引用计数

kd> g
Breakpoint 2 hit
Wdf01000!FxObject::Release+0x12 [inlined in Wdf01000!FxObject::DeleteObject+0x14a]:
86a0592a 48              dec     eax
kd> kb
 # ChildEBP RetAddr  Args to Child              
00 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::Release+0x12 [fxobject.hpp @ 867] ;<-Unload引起Release减少引用
01 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::DeletedAndDisposedWorkerLocked+0x44 [fxobjectstatemachine.cpp @ 1215]
02 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::DeleteWorkerAndUnlock+0xbc [fxobjectstatemachine.cpp @ 941]
03 b2c03ba4 86a166b2 8c234910 81a8f220 afc257c0 Wdf01000!FxObject::DeleteObject+0x14a [fxobjectstatemachine.cpp @ 124]
04 b2c03bb8 a4d511de afc5b890 b2c03be0 81bc5013 Wdf01000!FxDriver::Unload+0x40 [fxdriver.cpp @ 176]
05 b2c03bc4 81bc5013 afc5b890 8c234910 afc257c0 KMDFdrv!FxStubDriverUnload+0x1a [stub.cpp @ 159]
kd> ub . L4
Wdf01000!FxObject::IsDebug [fxobjectstatemachine.cpp @ 124] [inlined in Wdf01000!FxObject::DeleteObject+0x138 [fxobjectstatemachine.cpp @ 124]]:
86a05918 f6461080        test    byte ptr [esi+10h],80h ;<-修改引用计数的指令
86a0591c 0f85deb90200    jne     Wdf01000!FxObject::DeleteObject+0x2bb20 (86a31300)
86a05922 83c8ff          or      eax,0FFFFFFFFh
86a05925 f00fc14608      lock xadd dword ptr [esi+8],eax
kd> !wdfobject 0x8c408e10

The type for object 0x8c408e10 is FxDriver
State: FxObjectStateDeletedAndDisposed (0xa) ;m_ObjectState状态从上次触发中断以来,没有发生改变
!wdfhandle 0x73bf71e8

dt FxDriver 0x8c408e10

kd> !wdfhandle 0x73bf71e8
Treating handle as a KMDF handle!

Dumping WDFHANDLE 0x73bf71e8
=============================
Handle type is WDFDRIVER
Refcount: 0 ;<-引用计数减少为零

!wdfobject 0x8c408e10
由于引用计数m_Refcnt归零,会引起Wdf框架调用对象的析构函数FxDriver::~FxDriver。期间又会引起FxDriver状态变化:
kd> g
Breakpoint 3 hit
Wdf01000!FxObject::~FxObject+0x51: ;<--框架目前进入了FxObject析构函数
86a0c1b1 5e              pop     esi
kd> kb
 # ChildEBP RetAddr  Args to Child              
00 b2c03b78 86a210b5 8c408e10 b2c03ba4 86a05acb Wdf01000!FxObject::~FxObject+0x51 [fxobject.cpp @ 155]
01 b2c03b84 86a05acb 00000001 afdb0118 8c408e10 Wdf01000!FxDriver::`scalar deleting destructor'+0xd
02 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::SelfDestruct+0xe7 [fxobject.hpp @ 441]
03 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::ProcessDestroy+0x17c [fxobjectstatemachine.cpp @ 371]
04 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::FinalRelease+0x19a [fxobject.cpp @ 249]
05 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::Release+0x1b3 [fxobject.hpp @ 870]
06 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::DeletedAndDisposedWorkerLocked+0x1e5 [fxobjectstatemachine.cpp @ 1215]
07 (Inline) -------- -------- -------- -------- Wdf01000!FxObject::DeleteWorkerAndUnlock+0x25d [fxobjectstatemachine.cpp @ 941]
08 b2c03ba4 86a166b2 8c234910 81a8f220 afc257c0 Wdf01000!FxObject::DeleteObject+0x2eb [fxobjectstatemachine.cpp @ 124]
09 b2c03bb8 a4d511de afc5b890 b2c03be0 81bc5013 Wdf01000!FxDriver::Unload+0x40 [fxdriver.cpp @ 176]
0a b2c03bc4 81bc5013 afc5b890 8c234910 afc257c0 KMDFdrv!FxStubDriverUnload+0x1a [stub.cpp @ 159]
0b b2c03be0 8191b8c5 8c234910 00000000 afc257c0 nt!IopLoadUnloadDriver+0x77
kd> ub . L4
Wdf01000!FxObject::SetObjectStateLocked+0x9 [fxobject.cpp @ 155] [inlined in Wdf01000!FxObject::~FxObject+0x3e [fxobject.cpp @ 155]]:
86a0c19e 0f853e5d0200    jne     Wdf01000!FxObject::~FxObject+0x25d82 (86a31ee2)
86a0c1a4 b80c000000      mov     eax,0Ch
86a0c1a9 c6461c00        mov     byte ptr [esi+1Ch],0
86a0c1ad 66894612        mov     word ptr [esi+12h],ax ;<-Wdf框架修改m_ObjectState状态值
kd> !wdfhandle 0x73bf71e8
Treating handle as a KMDF handle!
Dumping WDFHANDLE 0x73bf71e8
=============================
Handle type is WDFDRIVER
Refcount: 0
!wdfobject 0x8c408e10
kd> !wdfobject 0x8c408e10
The type for object 0x8c408e10 is FxDriver
State: FxObjectStateDestroyed (0xc) ;状态值由前面的0x0a变为0x0c
!wdfhandle 0x73bf71e8
之后,再次F5再也没有触发中断(当然,这片内存会被系统其它组件使用,这另当别论),可见FxObjectStateDestroyed是Wdf对象生命周期中的最后一步,经过这一步,先前申请的内存将被释放回收。这篇文章先写到这,后面会借助前面调试的线索的帮助,在源码中走一走~


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值