77.windbg-!drvobj、.devstack(驱动对象,设备栈,AttachedDevice)

驱动程序设备栈解析
本文介绍了驱动程序中设备栈的概念及工作原理,包括物理设备对象(PDO)、功能驱动对象(FDO)等,并通过实例展示了如何使用Windbg命令查看设备栈。

引言

      

驱动的设备栈可以参看:http://blog.youkuaiyun.com/hgy413/article/details/17737517,如下:

驱动设备的创建顺序是,先创建底层PDO,再创建高层的FDO,PDO和FDO之间可能夹杂着各种过滤驱动,每次的设备对象由不同驱动程序所创建,有的驱动程序是系统自带的,有的需要程序员来编写,底层设备对象寻找上层的设备对象,是依靠底层设备对象的AttachedDevice寻找的,如果某一设备的AttachedDevice为空,说明已经到了设备堆栈的顶部,而高层设备找低一层的设备对象,只能能过设备扩展来记录,如下图:


   

PDO:物理设备对象,由总线(BUS)创建

FDO:功能驱动对象,实现PDO的某些功能

FIDO:可插入由PDO-FDO组在的设备栈中,参与IRP处理

CDO:控制设备对象,不对应真实/逻辑的物理设备,我们大部分是写这种,一般来讲,一个驱动程序只会创建唯一的功能设备对象, 功能设备对象一般不用来处理具体的物理设备功能,仅仅作为 驱动程序的编程接口,与其他模块交互

   

设备栈 

1.系统中的I/O请求虽然发送给指定的设备对象,但请求却是通过 设备栈来传递的

2.最上层的设备对象首先获得机会处理请求,然后传递给下层设 备对象。如果上层设备对象处理完请求,则可以拒绝将命令继 续下传,下层设备对象就失去了处理的机会
 
3.功能设备对象会完成大多数的工作,只把部分I/O请求传递给物 理设备对象。  I/O请求在设备栈中传递完毕后,还会有一次从栈底开始的逆向 回调过程,进行完成后操作

4.过滤设备对象可以把自己插入到设备栈中任意位置,过滤顺向 的IO请求包,或者逆序的回调过程。多个过滤设备对象可以叠 加

       

!drvobj 

!drvobj 扩展命令显示DRIVER_OBJECT 的详细信息。
Flags
(Windows 2000和之后) 可以是下面这些位的任意组合。(默认为0x01)
Bit 0 (0x1)
显示驱动拥有的设备对象。
Bit 1 (0x2)
显示驱动的dispatch例程的入口点。
Bit 2 (0x4)
显示驱动的设备对象的详细信息(需要设置bit 0)
以打印机驱动为例:

0: kd> !drvobj parport
Driver object (89a48ce8) is for:
 \Driver\Parport
Driver Extension List: (id , addr)

Device Object list:
895e3040  8969d030  
等同于
0: kd> !drvobj \Driver\Parport
Driver object (89a48ce8) is for:
 \Driver\Parport
Driver Extension List: (id , addr)

Device Object list:
895e3040  8969d030  
等同于
0: kd> !drvobj 89a48ce8
Driver object (89a48ce8) is for:
 \Driver\Parport
Driver Extension List: (id , addr)

Device Object list:
895e3040  8969d030  
   

!devstack

!devstack 扩展显示设备对象关联的设备栈的格式化后的信息。
DeviceObject
指定设备对象。可以是DEVICE_OBJECT 结构的16进制地址或者设备名。
以上面为例:
0: kd> !devstack 895e3040
  !DevObj   !DrvObj            !DevExt   ObjectName
> 895e3040  \Driver\Parport    895e30f8  Parallel0
!DevNode 899ce970 :
  DeviceInst is "LPTENUM\MicrosoftRawPort\6&16ccfde1&0&LPT1"
0: kd> !devstack 8969d030  
  !DevObj   !DrvObj            !DevExt   ObjectName
> 8969d030  \Driver\Parport    8969d0e8  ParallelPort0
  89a56bb8  \Driver\ACPI       89bfeb30  00000071
!DevNode 89a56728 :
  DeviceInst is "ACPI\PNP0400\5&324d5432&0"
  ServiceName is "Parport"
从上面可以看到设备栈,它的底层设备栈是89a56bb8,对应的驱动是ACPI,
我们来看看ACPI一共创建了多少个设备:
0: kd> !drvobj \Driver\ACPI
Driver object (89c5c8b0) is for:
 \Driver\ACPI
Driver Extension List: (id , addr)


Device Object list:
89ba9870  89ba9988  89ba9aa0  89ba9bb8
89ad59a0  89ad5ab8  89ad5bd0  89ad5ce8
89ad5e00  89ad5f18  89ad5030  8971c2b0
8971c3c8  8971c4e0  8971cce8  8971ce00
8971cf18  89a87208  89ae4770  89ae4888
89ae49a0  89ae4ab8  89ae4bd0  89ae4ce8
89ae4e00  89ae4f18  89a63540  89a63658
89a63770  89a63888  89a639a0  89a63ab8
89a63bd0  89a63ce8  89a63e00  89a63f18
89c14658  89c14770  89c14888  89c149a0
89c14ab8  89c14bd0  89c14ce8  89c14e00
89c14f18  89bab4c8  89c46db0  89c10f18
89baa6b8  89bf91f8  89c471f8  89aa74e8
89b94378  897068a8  8972d218  89bcb1a8
89be01a8  89bf51a8  89c11e70  89c11920
89c5c520  
有点多啊,它们分布在不同的设备栈中,随便取个看看,比如第三个:
0: kd> !devstack  89ba9aa0
  !DevObj   !DrvObj            !DevExt   ObjectName
  8970f030  \Driver\serenum    8970f0e8  
  89b84638  \Driver\Serial     89b846f0  Serial0
> 89ba9aa0  \Driver\ACPI       89c474a0  00000074
!DevNode 89ba9608 :
  DeviceInst is "ACPI\PNP0501\1"
  ServiceName is "Serial"
来看看AttachedDevice,当一个FDO附加在一个PDO上时,PDO的AttachedDevice会记录FDO的位置,PDO会被称为底层驱动或下层驱动,而FDO会被称为高层驱动或上层驱动,越上层越接近发出IO请求的地方,如上面,
0: kd> dt 89ba9aa0 _DEVICE_OBJECT -y AttachedDevice
nt!_DEVICE_OBJECT
   +0x010 AttachedDevice : 0x89b84638 _DEVICE_OBJECT
0: kd> dt 89b84638 _DEVICE_OBJECT -y AttachedDevice
nt!_DEVICE_OBJECT
   +0x010 AttachedDevice : 0x8970f030 _DEVICE_OBJECT
0: kd> dt 8970f030 _DEVICE_OBJECT -y AttachedDevice
nt!_DEVICE_OBJECT
   +0x010 AttachedDevice : (null) 
可以看到_DEVICE_OBJECT的AttachedDevice可以从下向上遍历设备栈,而设备栈中每一层设备都分属于不同驱动,而_DEVICE_OBJECT的NextDevice可以遍历当前驱动创建的所有设备,这是两个不同的概念

































<think>我们正在讨论WinDbg中禁用符号加载优化选项(SYMOPT_100)的问题。SYMOPT_100是WinDbg的一个符号选项,它控制符号加载的行为。在WinDbg中,符号选项可以通过`.symopt`命令来查看和修改。SYMOPT_100的具体含义是:忽略符号服务器上的索引,而直接使用符号文件。禁用这个选项(即关闭SYMOPT_100)意味着在从符号服务器加载符号时,会使用索引来加快符号的查找速度。 用户可能遇到的问题是:在调试过程中,符号加载速度慢,或者加载了不正确的符号。通过禁用SYMOPT_100(即关闭该选项),可以尝试使用符号服务器上的索引来加速符号加载,并确保加载正确的符号。 在WinDbg中,我们可以通过以下步骤来禁用SYMOPT_100(注意:禁用SYMOPT_100实际上是关闭这个选项,即从当前符号选项设置中移除SYMOPT_100): 1. 首先,查看当前的符号选项设置:`.symopt` 2. 然后,计算新的符号选项值:当前值 与上 SYMOPT_100的反码(即从当前选项中移除SYMOPT_100) - SYMOPT_100的值为0x100(即256),所以反码为0xFFFFFEFF(在32位下)或0xFFFFFFFFFFFFFEFF(在64位下)。但在WinDbg中,我们通常使用按位操作来移除某个标志。 3. 使用命令:`.symopt- 0x100` 来移除SYMOPT_100标志。 另一种方法是直接设置符号选项值: `.symopt <new_value>` 其中`<new_value>`是新的符号选项的整数值。我们可以先获取当前值,然后减去0x100(如果当前包含SYMOPT_100的话)。 但是,更直接的方法是使用`.symopt-`命令来移除某个选项。 具体步骤: 1. 打开WinDbg。 2. 在命令窗口中,输入以下命令来查看当前符号选项: ``` .symopt ``` 记下当前的值,并注意是否包含0x100(即SYMOPT_IGNORE_NT_SYMPATH)。 注意:实际上,SYMOPT_100在文档中称为SYMOPT_IGNORE_NT_SYMPATH,但根据Windows调试工具文档,符号选项的常量名称可能有所不同。在最新的文档中,0x100对应的选项是忽略_NT_SYMBOL_PATH环境变量。然而,在较早的文档中,0x100可能对应其他含义。因此,我们需要确认用户使用的WinDbg版本。 根据最新的Windows调试工具文档(WinDbg 10),符号选项常量如下: - 0x100: SYMOPT_IGNORE_NT_SYMPATH - 忽略_NT_SYMBOL_PATH环境变量。 - 0x200: SYMOPT_DEBUG_TYPE_PTR - 用于调试类型指针。 - 等等。 但是,在用户的问题中,SYMOPT_100通常指的是0x100这个选项。不过,在WinDbg中,符号选项的默认设置通常不包括0x100。用户可能希望禁用这个选项,即关闭忽略_NT_SYMBOL_PATH环境变量的功能,从而让调试器使用环境变量中设置的符号路径。 因此,如果用户想要禁用SYMOPT_100(即不再忽略_NT_SYMBOL_PATH),那么应该移除0x100这个标志。 操作命令: ``` .symopt- 0x100 ``` 然后,再次运行`.symopt`来确认0x100已经被移除。 另外,如果用户想要完全重置符号选项,可以使用: ``` .symopt+ 0x80000000 // 恢复默认值(默认值包含一些基本选项) ``` 但注意,默认值中并不包含0x100,所以如果用户只是希望移除0x100,那么直接移除即可。 如果用户遇到符号加载问题,除了调整符号选项,还应该检查符号路径(`.sympath`)设置是否正确,以及符号服务器是否可用。 总结: - 禁用SYMOPT_100(即关闭0x100选项)的命令是:`.symopt- 0x100` - 启用SYMOPT_100(即打开0x100选项)的命令是:`.symopt+ 0x100` 用户的需求是禁用(disable)SYMOPT_100,所以我们使用移除选项的命令。 注意:在WinDbg中,符号选项的修改只影响当前调试会话。 如果用户需要持久化设置,可以考虑在启动WinDbg时通过命令行参数设置,或者使用脚本初始化。 参考文档:[Symbol Options](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/symbol-options) 由于我们无法直接链接外部文档,这里仅提供参考。 相关问题: 1. 如何查看WinDbg中的当前符号选项? 2. 如何设置符号路径(_NT_SYMBOL_PATH)? 3. WinDbg中常见的符号加载问题有哪些? 4. 如何重置WinDbg的符号选项到默认值? 以上问题可以帮助用户进一步了解符号配置和故障排除。</think>### WinDbg 禁用 SYMOPT_100 的步骤 在 WinDbg 中,`SYMOPT_100`(十六进制值 `0x100`)是符号选项(Symbol Options)的一部分,它控制符号加载的行为。禁用此选项通常用于解决符号加载问题或优化调试过程。以下是具体操作步骤: #### 1. **查看当前符号选项** 在 WinDbg 命令窗口中输入: ```windbg .symopt ``` 输出示例: ``` Symbol options: 0x30237 SYMOPT_CASE_INSENSITIVE - on SYMOPT_UNDNAME - on SYMOPT_DEFERRED_LOADS - on SYMOPT_LOAD_LINES - on SYMOPT_OMAP_FIND_NEAREST - on SYMOPT_DEBUG - on ``` 记录十六进制值(如 `0x30237`)[^1]。 #### 2. **禁用 SYMOPT_100** - **方法 1:直接移除标志位** 使用命令: ```windbg .symopt- 0x100 ``` 这会从当前符号选项中减去 `0x100`。 - **方法 2:手动计算新值** 若当前值为 `0x30237`,禁用 `0x100` 后的新值为: $$ \text{新值} = \text{原值} \ \& \ \sim\text{0x100} = \text{0x30237} \ \& \ \text{0xFFFFFEFF} = \text{0x30137} $$ 然后显式设置: ```windbg .symopt 0x30137 ``` #### 3. **验证是否禁用** 再次运行: ```windbg .symopt ``` 检查输出中是否包含 `SYMOPT_IGNORE_NT_SYMPATH`(即 `0x100` 的别名),确保该选项已消失[^2]。 --- ### 关键说明 - **作用**:`SYMOPT_100`(`SYMOPT_IGNORE_NT_SYMPATH`)会忽略 `_NT_SYMBOL_PATH` 环境变量。禁用后,WinDbg 将重新遵守该变量指定的符号路径。 - **应用场景**: - 解决符号加载失败问题(如 `PDB not found`)。 - 强制使用本地符号缓存而非远程服务器。 - 调试时需动态切换符号路径。 - **持久性**:此修改仅对当前调试会话有效。重启 WinDbg 后需重新配置。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值