Advanced Debugging
About AdvDbg Consult Train Services Products Tools Community Contact  
欢迎光临 高端调试 登录 | 注册 | FAQ
 
  ACPI调试
Linux内核调试
Windows内核调试
 
  调试战役
调试原理
新工具观察
 
  Linux
Windows Vista
Windows
 
  Linux驱动
WDF
WDM
 
  PCI Express
PCI/PCI-X
USB
无线通信协议
 
  64位CPU
ARM
IA-32
  CPU Info Center
 
  ACPI标准
系统认证
Desktop
服务器
 
  Embedded Linux
嵌入式开发工具
VxWorks
WinCE
嵌入式Windows
 
  格蠹调试套件(GDK)
  格蠹学院
  小朱书店
  老雷的微博
  《软件调试》
  《格蠹汇编》
  《软件调试(第二版)》
沪ICP备11027180号-1

Windows内核调试

帖子发起人: yushang   发起时间: 2009-08-12 12:12 下午   回复: 11

Print Search
帖子排序:    
   2009-08-12, 12:12 下午
yushang 离线,最后访问时间: 2010/2/23 20:01:13 yushang

发帖数前50位
注册: 2009-08-10
发 贴: 27
IRQL规则
Reply Quote
都说在DPC级别时,不能调用导致缺页中断的函数,我猜想是不是Windows会在某个地方检查当前的IRQL,如果在DPC上就BugCheck一个IRQL_NOT_LESS_OR_EQUAL错误。如果是这样,是在哪个地方检查的呢?我试着检查了一下TRAP0E的代码,发现只要MmAccessFault返回0D0000006的话,就会导致TRAP0E BugCheck这个错误,但是MmAccessFault太长了,有人能提供一点启发吗?
IP 地址: 已记录   报告
   2009-08-12, 15:49 下午
WANGyu 离线,最后访问时间: 2012/9/10 3:34:00 王宇

发帖数前10位
男
注册: 2007-05-08
发 贴: 306
Re: IRQL规则
Reply Quote
这个问题很简单,看看源码 / 跟一下就知道了

http://advdbg.org/forums/2018/ShowPost.aspx

首先 MmAccessFault 内部会判断:

PreviousIrql = KeGetCurrentIrql ();

......

if (
#if (_MI_PAGING_LEVELS >= 4)
(PointerPxe->u.Hard.Valid == 0) ||
#endif
#if (_MI_PAGING_LEVELS >= 3)
(PointerPpe->u.Hard.Valid == 0) ||
#endif
(PointerPde->u.Hard.Valid == 0) ||

((!MI_PDE_MAPS_LARGE_PAGE (PointerPde)) && (PointerPte->u.Hard.Valid == 0))) {

if (KeInvalidAccessAllowed (TrapInformation) == TRUE) {
return STATUS_ACCESS_VIOLATION;
}

KdPrint(("MM:***PAGE FAULT AT IRQL > 1 Va %p, IRQL %lx\n",
VirtualAddress,
PreviousIrql));

if (TrapInformation != NULL) {
MI_DISPLAY_TRAP_INFORMATION (TrapInformation);
}

//
// Signal the fatal error to the trap handler.
//

return STATUS_IN_PAGE_ERROR | 0x10000000;

}

也就是这里的 PTE 等判断失败,返回值 d0000006。这里已经“命中注定”要蓝屏了。

//
// MessageId: STATUS_IN_PAGE_ERROR
//
// MessageText:
//
// The instruction at "0x%08lx" referenced memory at "0x%08lx". The required data was not placed into memory because of an I/O error status of "0x%08lx".
//
#define STATUS_IN_PAGE_ERROR ((NTSTATUS)0xC0000006L) // winnt

----------------------------

此时再回到 _KiTrap0E 的流程做几个判断:

1. Check to determine if the fault occured in the interlocked pop entry slist code.

2. Check to determine if the page fault occured in the user mode interlocked pop entry SLIST code.

3. Did the fault occur in KiSystemService while copying arguments from user stack to kernel stack?

4. Did the fault occur in a VDM?

5. Did the fault occur in a VDM while running in protected mode?

之所以说“命中注定”是因为:

;
; test to see if reserved status code bit is set. If so, then bugchecka
;

cmp eax, STATUS_IN_PAGE_ERROR or 10000000h ; 我们的返回值
je Kt0e12 ; bugchecka

最后蓝屏:

Kt0e12:
CurrentIrql ; (eax) = OldIrql
Kt0e12a:
lock inc ds:_KiHardwareTrigger ; trip hardware analyzer

;
; bugcheck a, addr, irql, load/store, pc
;
mov ecx, [ebp]+TsErrCode ; (ecx)= error code
shr ecx, 1 ; isolate read/write bit
and ecx, _KeErrorMask ;
mov esi, [ebp]+TsEip ; [esi] = faulting instruction

stdCall _KeBugCheck2,

错误码是:IRQL_NOT_LESS_OR_EQUAL

打完收功~
IP 地址: 已记录   报告
   2009-08-13, 17:19 下午
yushang 离线,最后访问时间: 2010/2/23 20:01:13 yushang

发帖数前50位
注册: 2009-08-10
发 贴: 27
Re: IRQL规则
Reply Quote

不过好像PreviousIrql就没有和谁比较过,似乎当前IRQL大于等于DPC的事实隐含在

if (
#if (_MI_PAGING_LEVELS >= 4)
(PointerPxe->u.Hard.Valid == 0) ||
#endif
#if (_MI_PAGING_LEVELS >= 3)
(PointerPpe->u.Hard.Valid == 0) ||
#endif
(PointerPde->u.Hard.Valid == 0) ||

((!MI_PDE_MAPS_LARGE_PAGE (PointerPde)) && (PointerPte->u.Hard.Valid == 0)))

。。。

中,可以这样理解吗?


IP 地址: 已记录   报告
   2009-08-14, 10:04 上午
WANGyu 离线,最后访问时间: 2012/9/10 3:34:00 王宇

发帖数前10位
男
注册: 2007-05-08
发 贴: 306
Re: IRQL规则
Reply Quote
当前 IRQL 大于等于 DPC 本身不是问题
P位 标识出页不在物理内存中才是问题
所以才有那些代码
IP 地址: 已记录   报告
   2009-08-14, 19:53 下午
yushang 离线,最后访问时间: 2010/2/23 20:01:13 yushang

发帖数前50位
注册: 2009-08-10
发 贴: 27
Re: IRQL规则
Reply Quote


IP 地址: 已记录   报告
   2009-08-15, 23:22 下午
yushang 离线,最后访问时间: 2010/2/23 20:01:13 yushang

发帖数前50位
注册: 2009-08-10
发 贴: 27
Re: IRQL规则
Reply Quote
为什么PTE 等判断失败就等效于IRQL >= DPC ,谢谢?
IP 地址: 已记录   报告
   2009-08-17, 09:18 上午
WANGyu 离线,最后访问时间: 2012/9/10 3:34:00 王宇

发帖数前10位
男
注册: 2007-05-08
发 贴: 306
Re: IRQL规则
Reply Quote
IRQL >= DPC 只要你访问的页面有效 (锁定在物理内存中的分页 / 非分页) 就没有问题
但是 IRQL >= DPC 且页面无效,这就违背了 IRQL 的基本准则。


“都说在DPC级别时,不能调用导致缺页中断的函数,我猜想是不是Windows会在某个地方检查当前的IRQL,如果在DPC上就BugCheck一个IRQL_NOT_LESS_OR_EQUAL错误。” <-- 在 DPC 上本身不是错,在 DPC 上缺页才是错
IP 地址: 已记录   报告
   2009-08-17, 20:30 下午
yushang 离线,最后访问时间: 2010/2/23 20:01:13 yushang

发帖数前50位
注册: 2009-08-10
发 贴: 27
Re: IRQL规则
Reply Quote

但是 IRQL >= DPC 且页面无效,这就违背了 IRQL 的基本准则。

是啊,我也是这样认为的,但是系统是在什么地方判断出IRQL >= DPC 的呢?还是引用我前面问过的话:

“。。。好像PreviousIrql就没有和谁比较过。。。”,例如,是不是应该有类似这样的比较:

if ( PreviousIrql >= DISPATCH_LEVEL )

   BugCheck...

谢谢


IP 地址: 已记录   报告
   2009-08-17, 21:56 下午
WANGyu 离线,最后访问时间: 2012/9/10 3:34:00 王宇

发帖数前10位
男
注册: 2007-05-08
发 贴: 306
Re: IRQL规则
Reply Quote
大哥 你介是逼我贴代码啊  WRK 有代码引用协议的........

    PreviousIrql = KeGetCurrentIrql ();

    if (PreviousIrql > APC_LEVEL) {  // 条件一

        if (
#if (_MI_PAGING_LEVELS >= 4)
            (PointerPxe->u.Hard.Valid == 0) ||
#endif
#if (_MI_PAGING_LEVELS >= 3)
            (PointerPpe->u.Hard.Valid == 0) ||
#endif
            (PointerPde->u.Hard.Valid == 0) ||

            ((!MI_PDE_MAPS_LARGE_PAGE (PointerPde)) && (PointerPte->u.Hard.Valid == 0))) {  // 条件二

            if (KeInvalidAccessAllowed (TrapInformation) == TRUE) {
                return STATUS_ACCESS_VIOLATION;
            }

            KdPrint(("MM:***PAGE FAULT AT IRQL > 1  Va %p, IRQL %lx\n",
                     VirtualAddress,
                     PreviousIrql));

            if (TrapInformation != NULL) {
                MI_DISPLAY_TRAP_INFORMATION (TrapInformation);
            }

            //
            // Signal the fatal error to the trap handler.
            //

            return STATUS_IN_PAGE_ERROR | 0x10000000// ~

        }

    ......

    }
IP 地址: 已记录   报告
   2009-08-17, 22:21 下午
yushang 离线,最后访问时间: 2010/2/23 20:01:13 yushang

发帖数前50位
注册: 2009-08-10
发 贴: 27
Re: IRQL规则
Reply Quote

呵呵,终于看到关键的东西了,不贴也可以啊,你只要确认有类似的语句就行了。


IP 地址: 已记录   报告
   2009-08-17, 22:23 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: IRQL规则
Reply Quote
呵呵,刨根问底没有错啊,也可以贴汇编么 :-)
IP 地址: 已记录   报告
   2009-08-17, 22:40 下午
yushang 离线,最后访问时间: 2010/2/23 20:01:13 yushang

发帖数前50位
注册: 2009-08-10
发 贴: 27
Re: IRQL规则
Reply Quote

回过头来看看汇编,似乎下面这一段是和所贴代码对应的

...

call    dword ptr [nt!_imp__KeGetCurrentIrql (804d9108)]     ;PreviousIrql

cmp     al,1                                                                              ;和APC_LEVEL比较

mov     byte ptr [ebp-2],al

jbe     nt!MmAccessFault+0x185

//>APC_LEVEL,进一步判断第二个条件,如果也满足就BSOD了

mov     ecx,ebx

call    nt!MiCheckPdeForPagedPool

...


IP 地址: 已记录   报告
高端调试 » 软件调试 » Windows内核调试 » IRQL规则

 
Legal Notice Privacy Statement Corporate Governance Corporate Governance
(C)2004-2020 ADVDBG.ORG All Rights Reserved.