用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 821ba160Pci总线驱动创建的设备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]二叉树根节点到叶子节点和为指定值的路径