用windbg寻找设备树根节点

Posted Yuri800

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用windbg寻找设备树根节点相关的知识,希望对你有一定的参考价值。

    用ReactOS上明确说过,Pnp管理器对每种设备都会创建一个虚拟root device用于构建设备树;同时这个新创建的root device又作为一个设备栈的栈底,往上形成完整的设备栈。用windbg调试时,可以看到这个虚拟设备属于/driver/pnpmanager驱动。

    昨天出于好奇想看下设备树,结果发现只有虚拟设备attach在/driver/pnpmanger创建的设备上,而类似pci/usb设备的设备栈栈底根本不是/driver/pnpmanager设备,这让我很是怀疑,M$到底怎样形成以root为根节点的设备树。

如mssmbios.sys位于设备管理器system设备类下,注册表路径为:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\SYSTEM\0002

用windbg查看设备堆栈,可以看到这个设备attach在/driver/pnpmanger根节点上:

kd> !drvobj mssmbios
Driver object (81f81da0) is for:
 \Driver\mssmbios
Driver Extension List: (id , addr)

Device Object list:
81c8e408  
kd> !devstack 81c8e408  
  !DevObj   !DrvObj            !DevExt   ObjectName
> 81c8e408  \Driver\mssmbios   81c8e4c0  
  821e73d0  \Driver\PnpManager 821e7488  00000034 
!DevNode 821e7288 :
  DeviceInst is "Root\SYSTEM\0002"
  ServiceName is "mssmbios"
又如DDK样例toaster的虚拟总线设备busenum同样位于system设备类下,注册表路径为:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\SYSTEM\0003

其设备栈为:,亦可看到栈底pnpmanager设备

kd> !drvobj busenum
Driver object (81f81030) is for:
 \Driver\busenum
Driver Extension List: (id , addr)

Device Object list:
81ff3030  
kd> !devstack 81ff3030  
  !DevObj   !DrvObj            !DevExt   ObjectName
> 81ff3030  \Driver\busenum    81ff30e8  
  821e7190  \Driver\PnpManager 821e7248  00000035
!DevNode 821a0008 :
  DeviceInst is "Root\SYSTEM\0003"
  ServiceName is "busenum"
    然而,对于一些总线设备根本找不到pnpmanager,如PCI总线和USB总线:

kd> !drvobj pci
Driver object (82189218) is for:
 \Driver\PCI
Driver Extension List: (id , addr)

Device Object list:
82127c70  82127e50  82127030  821e03a0
...
8219cb98  821e5370  821ba160  
kd> !devstack 82127c70  
  !DevObj   !DrvObj            !DevExt   ObjectName
  81d34028  \Driver\usbehci    81d340e0  USBFDO-1
  82127790  \Driver\ACPI       82187810  00000064
> 82127c70  \Driver\PCI        82127d28  NTPNP_PCI0043
!DevNode 821272e8 :
  DeviceInst is "PCI\VEN_15AD&DEV_0770&SUBSYS_077015AD&REV_00\4&47b7341&0&1888"
  ServiceName is "usbehci"

kd> !drvobj usbhub
Driver object (820de2c0) is for:
 \Driver\usbhub
Driver Extension List: (id , addr)

Device Object list:
81c74c98  81d542f0  820f1b70  81fcac98
81c7ac98  
kd> !devstack  81c74c98  
  !DevObj   !DrvObj            !DevExt   ObjectName
> 81c74c98  \Driver\usbhub     81c74d50  00000079
  81d542f0  \Driver\usbhub     81d543a8  USBPDO-3
!DevNode 81c82c48 :
  DeviceInst is "USB\Vid_0e0f&Pid_0002\6&2edefd9b&0&2"
  ServiceName is "usbhub"
    对此,我百思不得解,pnpmanager去哪了?经过周AM指点,搞明白一件事:用!drvobj PCI列出pci设备中,除了最后一个是Fdo,其他都是Pdo(这里Fdo设备的意思是由PCI总线驱动AddDevice函数创建的设备,附加在底层的ACPI总线上,而Pdo设备是PCI总线探测到总线上接入了新设备,从而为这个新设备创建了一个Pdo以形成设备栈)。这些Fdo本身是由PCI总线创建,因此并不会attach在pnpmanager上,而通过查找Fdo设备的设备栈,才能找出栈底Pnpmanager。

    顺着周AM的思路,我重新调试了一遍,的确找到了PCI总线所在的Pnpmanager,以上面的环境为例,

kd> !drvobj pci
Driver object (82189218) is for:
 \Driver\PCI
Driver Extension List: (id , addr)

Device Object list:
82127c70  82127e50  82127030  821e03a0
...
8219cb98  821e5370  821ba160 
Pci总线驱动创建的设备0x821ba160就是Fdo(为什么Fdo位于最后?因为这是PCI!AddDevice创建的第一个设备对象,之后创建的设备对象都通过InsertListTail插入到设备队列头部,因此遍历设备队列时,Fdo是最后被遍历到的),查看它的设备栈:

kd> !devstack 821ba160
  !DevObj   !DrvObj            !DevExt   ObjectName
> 821ba160  \Driver\PCI        821ba218  
  821731a8  \Driver\ACPI       821e2940  00000038
!DevNode 821de178 :
  DeviceInst is "ACPI\PNP0A03\2&daba3ff&0"
  ServiceName is "pci"
    PCI设备堆叠在ACPI的Pdo上,怪不得找不到在PCI的设备栈中找不到Pnpmanager。继续寻祖,查找ACPI驱动创建的Fdo:

kd> !drvobj ACPI
Driver object (8219ca10) is for:
 \Driver\ACPI
Driver Extension List: (id , addr)

Device Object list:
8212c628  8212c740  8212c858  82126538
...
821731a8  8219c8f8  
kd> !devstack 8219c8f8  
  !DevObj   !DrvObj            !DevExt   ObjectName
> 8219c8f8  \Driver\ACPI       821e2ea0  
  821a0aa8  \Driver\ACPI_HAL   821a0b60  00000037
!DevNode 8219cd50 :
  DeviceInst is "ACPI_HAL\PNP0C08\0"
  ServiceName is "ACPI"
    同样ACPI的Fdo堆叠在ACPI_HAL驱动的Pdo上,继续寻祖,这次找ACPI_HAL的堆叠情况:

kd> !drvobj ACPI_HAL
Driver object (821a0f38) is for:
 \Driver\ACPI_HAL
Driver Extension List: (id , addr)

Device Object list:
821a0aa8  821a0bc8  
kd> !devstack 821a0bc8  
  !DevObj   !DrvObj            !DevExt   ObjectName
> 821a0bc8  \Driver\ACPI_HAL   821a0c80  
  821a4c68  \Driver\PnpManager 821a4d20  00000001
!DevNode 821a4b20 :
  DeviceInst is "Root\ACPI_HAL\0000"
    终于在ACPI_HAL驱动的Fdo设备栈中找到了Pnpmanager。这和Windows内核原理与实现书中提供的设备树的结构完全相似

    如果此时再深究一下PnpManager驱动创建的设备对象,会发现系统中果真只有一个根设备节点,而其他的PnpManager设备对象都是为了扩展设备树一点一点生长出来的:

kd> !drvobj PnpManager
Driver object (821eb2e8) is for:
 \Driver\PnpManager
Driver Extension List: (id , addr)

Device Object list:
821e7190  821e73d0  821e7610  821e7850
...
821a4c68  821a4020  
kd> !devstack  821a4020  
  !DevObj   !DrvObj            !DevExt   ObjectName
> 821a4020  \Driver\PnpManager 821a40d8  
!DevNode 821a4ee8 :
  DeviceInst is "HTREE\ROOT\0" <----从名字能感觉出这是根设备节点
kd> !devstack 821a4c68  
  !DevObj   !DrvObj            !DevExt   ObjectName
  821a0bc8  \Driver\ACPI_HAL   821a0c80  
> 821a4c68  \Driver\PnpManager 821a4d20  00000001  <----<span style="font-family: Arial, Helvetica, sans-serif;">名字看着这么没个性,肯定不是根设备节点了</span>
!DevNode 821a4b20 :
  DeviceInst is "Root\ACPI_HAL\0000" 





以上是关于用windbg寻找设备树根节点的主要内容,如果未能解决你的问题,请参考以下文章

[javascript]二叉树根节点到叶子节点和为指定值的路径

二叉树根节点到叶子节点的所有路径和(NC5/考察次数Top53/难度中等)

数据结构——二叉树根节点到特定节点路径(C语言版)

并查集题目模板及java代码

C语言 求二叉树根节点到叶子节点的路径

二叉树根节点到叶子节点和为指定值的路径(NC8/考察次数Top54/难度中等)