nt!MiDispatchFault函数里面的nt!IoPageRead函数分析和nt!MiWaitForInPageComplete函数分析
第一部分:背景nt!IoPageRead函数最终结果
f78d685c 80a923d9 899abb00 8962de48 8962de28 nt!IoPageRead+0x19 (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\ntos\io\iomgr\iosubs.c @ 9095]
1f f78d68ec 80abdc3e 00000001 c1080000 c0304200 nt!MiDispatchFault+0x1dbd (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\ntos\mm\pagfault.c @ 1121]
status = IoPageRead (ReadBlock->FilePointer,
&ReadBlock->Mdl,
&ReadBlock->ReadOffset,
&ReadBlock->Event,
&ReadBlock->IoStatus);
if (!NT_SUCCESS(status)) {
//
// Set the event as the I/O system doesn't set it on errors.
//
ReadBlock->IoStatus.Status = status;
ReadBlock->IoStatus.Information = 0;
KeSetEvent (&ReadBlock->Event, 0, FALSE);
}
//
// Initializing PageFrameIndex is not needed for correctness, but
// without it the compiler cannot compile this code W4 to check
// for use of uninitialized variables.
//
PageFrameIndex = (PFN_NUMBER)-1;
//
// Wait for the I/O operation.
//
status = MiWaitForInPageComplete (ReadBlock->Pfn,
ReadPte,
VirtualAddress,
&SavedPte,
CapturedEvent,
Process);
1: kd> g
Breakpoint 3 hit
eax=00000000 ebx=8962de10 ecx=f7145777 edx=01880001 esi=00000000 edi=8962de20
eip=80a923d9 esp=f78d6878 ebp=f78d68ec iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000286
nt!MiDispatchFault+0x1dbd:
80a923d9 85c0 test eax,eax
1: kd> !pte c1080000
VA c1080000
PDE at C0300C10 PTE at C0304200
contains 0A03F963 contains 00027400
pfn a03f -G-DA--KWEV not valid
Proto: E1009C00
1: kd> db c1080000
c1080000 eb 52 90 4e 54 46 53 20-20 20 20 00 02 08 00 00 .R.NTFS .....
c1080010 00 00 00 00 00 f8 00 00-3f 00 ff 00 3f 00 00 00 ........?...?...
c1080020 00 00 00 00 80 00 80 00-24 97 ff 04 00 00 00 00 ........$.......
c1080030 00 00 0c 00 00 00 00 00-72 f9 4f 00 00 00 00 00 ........r.O.....
c1080040 f6 00 00 00 01 00 00 00-7b dc 85 d8 fa 85 d8 12 ........{.......
c1080050 00 00 00 00 fa 33 c0 8e-d0 bc 00 7c fb b8 c0 07 .....3.....|....
c1080060 8e d8 e8 16 00 b8 00 0d-8e c0 33 db c6 06 0e 00 ..........3.....
c1080070 10 e8 53 00 68 00 0d 68-6a 02 cb 8a 16 24 00 b4 ..S.h..hj....$..
第二部分:nt!MiWaitForInPageComplete函数分析
1: kd> p
nt!MiDispatchFault+0x1de7:
80a92403 e89e79ffff call nt!MiWaitForInPageComplete (80a89da6)
1: kd> t
nt!MiWaitForInPageComplete:
80a89da6 55 push ebp
1: kd> dv
Pfn2 = 0x810f1650
PointerPte = 0xe1009c00
FaultingAddress = 0xc1080000
PointerPteContents = 0xf78d68b4
InPageSupport = 0x8962de10
CurrentProcess = 0x00000000
1: kd> kv
# ChildEBP RetAddr Args to Child
00 f78d68ec 80abdc3e 00000001 c1080000 c0304200 nt!MiWaitForInPageComplete+0x762 (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\ntos\mm\pagfault.c @ 4398]
01 f78d6950 80afef3c 00000000 c1080000 00000000 nt!MmAccessFault+0xc64 (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\ntos\mm\mmfault.c @ 860]
02 f78d6950 80bf989f 00000000 c1080000 00000000 nt!_KiTrap0E+0xe8 (FPO: [0,0] TrapFrame @ f78d6968) (CONV: cdecl) [d:\srv03rtm\base\ntos\ke\i386\trap.asm @ 5516]
03 f78d6a28 f7171729 899abb00 f78d6a64 00000200 nt!CcMapData+0x137 (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\ntos\cache\pinsup.c @ 260]
04 f78d6a54 f7196c08 89528450 8962deb0 00000000 Ntfs!NtfsMapStream+0xaf (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\fs\ntfs\cachesup.c @ 625]
05 f78d6ac0 f7191e0a 89528450 89469100 f78d6c80 Ntfs!NtfsReadBootSector+0x15a (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\fs\ntfs\fsctrl.c @ 5143]
06 f78d6cec f717c5aa 89528450 8963fd18 89528450 Ntfs!NtfsMountVolume+0x226 (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\fs\ntfs\fsctrl.c @ 1307]
07 f78d6d04 f71484b0 89528450 8963fd18 8999d020 Ntfs!NtfsCommonFileSystemControl+0x8c (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\fs\ntfs\fsctrl.c @ 837]
08 f78d6d80 80af2bb9 89528450 00000000 8999d020 Ntfs!NtfsFspDispatch+0x1fe (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\fs\ntfs\fspdisp.c @ 336]
09 f78d6dac 80d391f0 89528450 00000000 00000000 nt!ExpWorkerThread+0x10f (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\ntos\ex\worker.c @ 1153]
0a f78d6ddc 80b00d52 80af2aaa 00000000 00000000 nt!PspSystemThreadStartup+0x2e (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\ntos\ps\create.c @ 2213]
0b 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16 [d:\srv03rtm\base\ntos\ke\i386\threadbg.asm @ 81]
第三部分:nt!KeWaitForSingleObject函数直接返回了
//
// Wait for the I/O to complete. Note that we can't wait for all
// the objects simultaneously as other threads/processes could be
// waiting for the same event. The first thread which completes
// the wait and gets the PFN lock may reuse the event for another
// fault before this thread completes its wait.
//
KeWaitForSingleObject( &InPageSupport->Event,
WrPageIn,
KernelMode,
FALSE,
NULL);
//
// If the signal state is greater than zero, then satisfy the wait.
//
} else if (Objectx->Header.SignalState > 0) {
KiWaitSatisfyOther(Objectx);
WaitStatus = (NTSTATUS)(0);
goto NoWait;
}
1: kd> dv
ReadBlock = 0x8962de10
1: kd> dx -r1 ((ntkrnlmp!_MMINPAGE_SUPPORT *)0x8962de10)
((ntkrnlmp!_MMINPAGE_SUPPORT *)0x8962de10) : 0x8962de10 [Type: _MMINPAGE_SUPPORT *]
[+0x000] Event [Type: _KEVENT]
[+0x010] IoStatus [Type: _IO_STATUS_BLOCK]
[+0x018] ReadOffset : {0} [Type: _LARGE_INTEGER]
[+0x020] WaitCount : 1 [Type: long]
[+0x024] Thread : 0x8999d020 [Type: _ETHREAD *]
[+0x028] FilePointer : 0x899abb00 [Type: _FILE_OBJECT *]
[+0x02c] BasePte : 0xe1009c00 [Type: _MMPTE *]
[+0x030] Pfn : 0x810f1650 [Type: _MMPFN *]
[+0x034] u1 [Type: __unnamed]
[+0x038] Mdl [Type: _MDL]
[+0x054] Page [Type: unsigned long [16]]
[+0x094] ListEntry [Type: _SINGLE_LIST_ENTRY]
1: kd> dx -r1 (*((ntkrnlmp!_KEVENT *)0x8962de10))
(*((ntkrnlmp!_KEVENT *)0x8962de10)) [Type: _KEVENT]
[+0x000] Header [Type: _DISPATCHER_HEADER]
1: kd> dx -r1 (*((ntkrnlmp!_DISPATCHER_HEADER *)0x8962de10))
(*((ntkrnlmp!_DISPATCHER_HEADER *)0x8962de10)) [Type: _DISPATCHER_HEADER]
[+0x000] Type : 0x0 [Type: unsigned char]
[+0x001] Absolute : 0x0 [Type: unsigned char]
[+0x002] Size : 0x4 [Type: unsigned char]
[+0x003] Inserted : 0x0 [Type: unsigned char]
[+0x003] DebugActive : 0x0 [Type: unsigned char]
[+0x000] Lock : 262144 [Type: long]
[+0x004] SignalState : 1 [Type: long]
[+0x008] WaitListHead [Type: _LIST_ENTRY]
第四部分:
//
// Check to see if this is the first thread to complete the in-page
// operation.
//
Pfn = InPageSupport->Pfn;
if (Pfn2 != Pfn) {
ASSERT (Pfn2->u4.PteFrame != MI_MAGIC_AWE_PTEFRAME);
Pfn2->u3.e1.ReadInProgress = 0;
}
1: kd> dv
Pfn2 = 0x810f1650 Pfn2 = 0x810f1650
PointerPte = 0xe1009c00
FaultingAddress = 0xc1080000
PointerPteContents = 0xf78d68b4
InPageSupport = 0x8962de10
CurrentProcess = 0x00000000
Process = 0x810f1650
Protection = 0xc1080000
status2 = 0n0
ProtoVad = 0x00000000
LastPage = 0x8962de10
1: kd> dx -r1 ((ntkrnlmp!_MMINPAGE_SUPPORT *)0x8962de10)
((ntkrnlmp!_MMINPAGE_SUPPORT *)0x8962de10) : 0x8962de10 [Type: _MMINPAGE_SUPPORT *]
[+0x000] Event [Type: _KEVENT]
[+0x010] IoStatus [Type: _IO_STATUS_BLOCK]
[+0x018] ReadOffset : {0} [Type: _LARGE_INTEGER]
[+0x020] WaitCount : 1 [Type: long]
[+0x024] Thread : 0x8999d020 [Type: _ETHREAD *]
[+0x028] FilePointer : 0x899abb00 [Type: _FILE_OBJECT *]
[+0x02c] BasePte : 0xe1009c00 [Type: _MMPTE *]
[+0x030] Pfn : 0x810f1650 [Type: _MMPFN *] Pfn : 0x810f1650
[+0x034] u1 [Type: __unnamed]
[+0x038] Mdl [Type: _MDL]
[+0x054] Page [Type: unsigned long [16]]
[+0x094] ListEntry [Type: _SINGLE_LIST_ENTRY]
1: kd> dd 0x810f1650
810f1650 8962de10 e1009c00 00000000 0001100a
810f1660 fcf194c6 2000a1cd
if (Pfn2->u4.InPageError == 1) {
+0x014 u4 : __unnamed
+0x000 EntireFrame : Uint4B
+0x000 PteFrame : Pos 0, 26 Bits
+0x000 InPageError : Pos 26, 1 Bit 0
0010 0000
第五部分:
1: kd> dx -r1 ((ntkrnlmp!_MMINPAGE_SUPPORT *)0x8962de10)
((ntkrnlmp!_MMINPAGE_SUPPORT *)0x8962de10) : 0x8962de10 [Type: _MMINPAGE_SUPPORT *]
[+0x000] Event [Type: _KEVENT]
[+0x010] IoStatus [Type: _IO_STATUS_BLOCK]
[+0x018] ReadOffset : {0} [Type: _LARGE_INTEGER]
[+0x020] WaitCount : 1 [Type: long]
[+0x024] Thread : 0x8999d020 [Type: _ETHREAD *]
[+0x028] FilePointer : 0x899abb00 [Type: _FILE_OBJECT *]
[+0x02c] BasePte : 0xe1009c00 [Type: _MMPTE *]
[+0x030] Pfn : 0x810f1650 [Type: _MMPFN *]
[+0x034] u1 [Type: __unnamed]
[+0x038] Mdl [Type: _MDL]
[+0x054] Page [Type: unsigned long [16]]
[+0x094] ListEntry [Type: _SINGLE_LIST_ENTRY]
1: kd> dx -r1 (*((ntkrnlmp!__unnamed *)0x8962de44))
(*((ntkrnlmp!__unnamed *)0x8962de44)) [Type: __unnamed]
[+0x000] e1 [Type: _MMINPAGE_FLAGS]
[+0x000] LongFlags : 0x0 [Type: unsigned long]
[+0x000] PrefetchMdl : 0x0 [Type: _MDL *]
1: kd> dx -r1 (*((ntkrnlmp!_MMINPAGE_FLAGS *)0x8962de44))
(*((ntkrnlmp!_MMINPAGE_FLAGS *)0x8962de44)) [Type: _MMINPAGE_FLAGS]
[+0x000 ( 0: 0)] Completed : 0x0 [Type: unsigned long]
[+0x000 ( 1: 1)] Available1 : 0x0 [Type: unsigned long]
[+0x000 ( 2: 2)] Available2 : 0x0 [Type: unsigned long]
[+0x000 (31: 3)] PrefetchMdlHighBits : 0x0 [Type: unsigned long]
if (InPageSupport->u1.e1.Completed == 0) {
//
// The ReadInProgress bit for the dummy page is constantly cleared
// below as there are generally multiple inpage blocks pointing to
// the same dummy page.
//
ASSERT ((Pfn->u3.e1.ReadInProgress == 1) ||
(Pfn->PteAddress == MI_PF_DUMMY_PAGE_PTE));
InPageSupport->u1.e1.Completed = 1;
1: kd> dx -r1 (*((ntkrnlmp!__unnamed *)0x8962de44))
(*((ntkrnlmp!__unnamed *)0x8962de44)) [Type: __unnamed]
[+0x000] e1 [Type: _MMINPAGE_FLAGS]
[+0x000] LongFlags : 0x1 [Type: unsigned long]
[+0x000] PrefetchMdl : 0x1 [Type: _MDL *]
1: kd> dx -r1 (*((ntkrnlmp!_MMINPAGE_FLAGS *)0x8962de44))
(*((ntkrnlmp!_MMINPAGE_FLAGS *)0x8962de44)) [Type: _MMINPAGE_FLAGS]
[+0x000 ( 0: 0)] Completed : 0x1 [Type: unsigned long]
[+0x000 ( 1: 1)] Available1 : 0x0 [Type: unsigned long]
[+0x000 ( 2: 2)] Available2 : 0x0 [Type: unsigned long]
[+0x000 (31: 3)] PrefetchMdlHighBits : 0x0 [Type: unsigned long]
第六部分:
Mdl = &InPageSupport->Mdl;
if (InPageSupport->u1.e1.PrefetchMdlHighBits != 0) {
//
// This is a prefetcher-issued read.
//
Mdl = MI_EXTRACT_PREFETCH_MDL (InPageSupport);
}
if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) {
MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
}
1: kd> dx -r1 (*((ntkrnlmp!_MDL *)0x8962de48))
(*((ntkrnlmp!_MDL *)0x8962de48)) [Type: _MDL]
[+0x000] Next : 0x0 [Type: _MDL *]
[+0x004] Size : 32 [Type: short]
[+0x006] MdlFlags : 66 [Type: short]
[+0x008] Process : 0x20202020 [Type: _EPROCESS *]
[+0x00c] MappedSystemVa : 0x80402020 [Type: void *]
[+0x010] StartVa : 0x2700000 [Type: void *]
[+0x014] ByteCount : 0x1000 [Type: unsigned long]
[+0x018] ByteOffset : 0x0 [Type: unsigned long]
#define MDL_MAPPED_TO_SYSTEM_VA 0x0001
#define MDL_PAGES_LOCKED 0x0002 1
#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004 1
#define MDL_ALLOCATED_FIXED_SIZE 0x0008
#define MDL_PARTIAL 0x0010
#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020 1
#define MDL_IO_PAGE_READ 0x0040 1
第七部分:设置Pfn的状态Pfn->u3.e1.ReadInProgress和Pfn->u1.Event
1: kd> dd 0x810f1650
810f1650 8962de10 e1009c00 00000000 0001100a
810f1660 fcf194c6 2000a1cd
Pfn->u3.e1.ReadInProgress = 0; 关键地方1:
Pfn->u1.Event = NULL; 关键地方2:
1: kd> dt kevent 8962de10
hal!KEVENT
+0x000 Header : _DISPATCHER_HEADER
1: kd> dx -id 0,0,899a2278 -r1 (*((halmacpi!_DISPATCHER_HEADER *)0x8962de10))
(*((halmacpi!_DISPATCHER_HEADER *)0x8962de10)) [Type: _DISPATCHER_HEADER]
[+0x000] Type : 0x0 [Type: unsigned char]
[+0x001] Absolute : 0x0 [Type: unsigned char]
[+0x002] Size : 0x4 [Type: unsigned char]
[+0x003] Inserted : 0x0 [Type: unsigned char]
[+0x003] DebugActive : 0x0 [Type: unsigned char]
[+0x000] Lock : 262144 [Type: long]
[+0x004] SignalState : 1 [Type: long]
[+0x008] WaitListHead [Type: _LIST_ENTRY]
1: kd> dx -id 0,0,899a2278 -r1 (*((halmacpi!_LIST_ENTRY *)0x8962de18))
(*((halmacpi!_LIST_ENTRY *)0x8962de18)) [Type: _LIST_ENTRY]
[+0x000] Flink : 0x8962de18 [Type: _LIST_ENTRY *]
[+0x004] Blink : 0x8962de18 [Type: _LIST_ENTRY *]
0000 1010
+0x00c u3 : __unnamed
+0x000 e1 : _MMPFNENTRY
+0x000 Modified : Pos 0, 1 Bit
+0x000 ReadInProgress : Pos 1, 1 Bit 1
+0x000 WriteInProgress : Pos 2, 1 Bit
1: kd> dd 0x810f1650
810f1650 00000000 e1009c00 00000000 00011008
810f1660 fcf194c6 2000a1cd
第八部分:
if (!NT_SUCCESS(InPageSupport->IoStatus.Status)) {
1: kd> dx -r1 (*((ntkrnlmp!_IO_STATUS_BLOCK *)0x8962de20))
(*((ntkrnlmp!_IO_STATUS_BLOCK *)0x8962de20)) [Type: _IO_STATUS_BLOCK]
[+0x000] Status : 0 [Type: long]
[+0x000] Pointer : 0x0 [Type: void *]
[+0x004] Information : 0x1000 [Type: unsigned long] [+0x004] Information : 0x1000
else {
MiFaultRetries = 0;
MiUserFaultRetries = 0;
if (InPageSupport->IoStatus.Information != Mdl->ByteCount) {
1: kd> dx -r1 (*((ntkrnlmp!_MDL *)0x8962de48))
(*((ntkrnlmp!_MDL *)0x8962de48)) [Type: _MDL]
[+0x000] Next : 0x0 [Type: _MDL *]
[+0x004] Size : 32 [Type: short]
[+0x006] MdlFlags : 66 [Type: short]
[+0x008] Process : 0x20202020 [Type: _EPROCESS *]
[+0x00c] MappedSystemVa : 0x80402020 [Type: void *]
[+0x010] StartVa : 0x2700000 [Type: void *]
[+0x014] ByteCount : 0x1000 [Type: unsigned long] [+0x014] ByteCount : 0x1000
[+0x018] ByteOffset : 0x0 [Type: unsigned long]
第九部分:Check to see if the faulting PTE has changed.关键部分:
1: kd> dv
Pfn2 = 0x00000000
PointerPte = 0xe1009c00
FaultingAddress = 0xc1080000
if (CurrentProcess == PREFETCH_PROCESS) {
return STATUS_SUCCESS;
}
//
// Check to see if the faulting PTE has changed.
//
NewPointerPte = MiFindActualFaultingPte (FaultingAddress);
//
// If this PTE is in prototype PTE format, make the pointer to the
// PTE point to the prototype PTE.
//
if (NewPointerPte == NULL) {
return STATUS_PTE_CHANGED;
}
if (NewPointerPte != PointerPte) {
第十部分:第一次调用nt!MiFindActualFaultingPte函数,参数:FaultingAddress = 0xc1080000
1: kd> p
nt!MiWaitForInPageComplete+0x6fa:
80a8a4a0 e8f3f3ffff call nt!MiFindActualFaultingPte (80a89898)
1: kd> t
nt!MiFindActualFaultingPte:
80a89898 55 push ebp
1: kd> kc
#
00 nt!MiFindActualFaultingPte
01 nt!MiWaitForInPageComplete
02 nt!MiDispatchFault
03 nt!MmAccessFault
04 nt!_KiTrap0E
05 nt!CcMapData
06 Ntfs!NtfsMapStream
07 Ntfs!NtfsReadBootSector
08 Ntfs!NtfsMountVolume
09 Ntfs!NtfsCommonFileSystemControl
0a Ntfs!NtfsFspDispatch
0b nt!ExpWorkerThread
0c nt!PspSystemThreadStartup
0d nt!KiThreadStartup
1: kd> dv
FaultingAddress = 0xc1080000
Protection = 8
ProtoVad = 0xc1080000
PointerPte = MiGetPdeAddress (FaultingAddress);
if (PointerPte->u.Hard.Valid == 0) {
1: kd> !pte c1080000
VA c1080000
PDE at C0300C10 PTE at C0304200
contains 0A03F963 contains 00027400
pfn a03f -G-DA--KWEV not valid
Proto: E1009C00
#define MiGetPdeAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))
1100 0001 0000 1000 0000 0000 0000 0000
1100 0001 0000
c10
c0300c10
1: kd> p
nt!MiFindActualFaultingPte+0x24:
80a898bc f60001 test byte ptr [eax],1
1: kd> !pte c1080000
VA c1080000
PDE at C0300C10 PTE at C0304200
contains 0A03F963 contains 00027400
pfn a03f -G-DA--KWEV not valid
Proto: E1009C00
1: kd> p
nt!MiFindActualFaultingPte+0x27:
80a898bf 746b je nt!MiFindActualFaultingPte+0x94 (80a8992c)
1: kd> r
eax=c0300c10
1: kd> dd c0300c10
c0300c10 0a03f963
if (PointerPte->u.Hard.Valid == 0) {
//
// Page table page is not valid.
//
return PointerPte;
}
第十一部分:检查页表项
PointerPte = MiGetPteAddress (FaultingAddress);
#define MiGetPteAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))
1: kd> dd C0304200
c0304200 00027400 00027402 00027404 00027406
c0304210 00027408 0002740a 0002740c 0002740e
+0x000 Soft : _MMPTE_SOFTWARE
+0x000 Valid : Pos 0, 1 Bit
+0x000 PageFileLow : Pos 1, 4 Bits
+0x000 Protection : Pos 5, 5 Bits
+0x000 Prototype : Pos 10, 1 Bit 1
+0x000 Transition : Pos 11, 1 Bit
+0x000 PageFileHigh : Pos 12, 20 Bits
if (PointerPte->u.Soft.Prototype == 0) {
0111 0100 0000 0000
#define MI_PTE_LOOKUP_NEEDED (0xfffff)
//
// Check to see if the PTE which maps the prototype PTE is valid.
//
if (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED) {
//
// Protection is here, PTE must be located in VAD.
第十二部分:
}
else {
//
// Protection is in ProtoPte.
//
ProtoPteAddress = MiPteToProto (PointerPte); 关键地方2: =E1009C00
}
1: kd> !pte c1080000
VA c1080000
PDE at C0300C10 PTE at C0304200
contains 0A03F963 contains 00027400
pfn a03f -G-DA--KWEV not valid
Proto: E1009C00
C0304200
#define MiPteToProto(lpte) (PMMPTE)((PMMPTE)(((((lpte)->u.Long) >> 11) << 9) + \
(((((lpte)->u.Long)) << 24) >> 23) + \
MmProtopte_Base))
#define MmProtopte_Base ((ULONG)MmPagedPoolStart)
1: kd> x nt!MmPagedPoolStart
80b15028 nt!MmPagedPoolStart = 0xe1000000
0010 0111 0100 0000 0000
0010 0111 00 0000 0000
00 10 01 11 00 0000 0000
09c00
PointerFaultingPte = MiFindActualFaultingPte (ProtoPteAddress);
第十三部分:第二次调用nt!MiFindActualFaultingPte函数,参数:FaultingAddress = 0xe1009c00
1: kd> p
nt!MiFindActualFaultingPte+0x88:
80a89920 e873ffffff call nt!MiFindActualFaultingPte (80a89898)
1: kd> t
nt!MiFindActualFaultingPte:
80a89898 55 push ebp
1: kd> kc
#
00 nt!MiFindActualFaultingPte
01 nt!MiFindActualFaultingPte
02 nt!MiWaitForInPageComplete
03 nt!MiDispatchFault
04 nt!MmAccessFault
05 nt!_KiTrap0E
06 nt!CcMapData
07 Ntfs!NtfsMapStream
08 Ntfs!NtfsReadBootSector
09 Ntfs!NtfsMountVolume
0a Ntfs!NtfsCommonFileSystemControl
0b Ntfs!NtfsFspDispatch
0c nt!ExpWorkerThread
0d nt!PspSystemThreadStartup
0e nt!KiThreadStartup
1: kd> dv
FaultingAddress = 0xe1009c00 //FaultingAddress = 0xc1080000
Protection = 8
ProtoVad = 0xe1009c00
1: kd> !pte 0xe1009c00
VA e1009c00
PDE at C0300E10 PTE at C0384024
contains 0A1C0963 contains 0A1CD963
pfn a1c0 -G-DA--KWEV pfn a1cd -G-DA--KWEV
PointerPte = MiGetPdeAddress (FaultingAddress); =C0300E10
1: kd> dd C0300E10
c0300e10 0a1c0963 00000000 00000000 00000000
c0300e20 00000000 00000000 00000000 00000000
c0300e30 00000000 00000000 00000000 00000000
PointerPte = MiGetPteAddress (FaultingAddress);
if (PointerPte->u.Hard.Valid == 1) {
1: kd> dd C0384024
c0384024 0a1cd963 0a272963 0a273963 0a274963
c0384034 0a275963 0a276963 0a277963 0a278963
1: kd> !dc 0a1cdc00
# a1cdc00 0a0ee8c0 fcf194c6 fcf194c6 fcf194c6 ................
# a1cdc10 fcf194c6 fcf194c6 fcf194c6 fcf194c6 ................
# a1cdc20 fcf194c6 fcf194c6 fcf194c6 fcf194c6 ................
# a1cdc30 fcf194c6 fcf194c6 fcf194c6 fcf194c6 ................
# a1cdc40 fcf194c6 fcf194c6 fcf194c6 fcf194c6 ................
# a1cdc50 fcf194c6 fcf194c6 fcf194c6 fcf194c6 ................
PointerPte = MiGetPteAddress (FaultingAddress);
if (PointerPte->u.Hard.Valid == 1) {
//
// Page is already valid, no need to fault it in.
//
return NULL; //返回NULL
}
第十四部分:return PointerPte;
1: kd> p
nt!MiFindActualFaultingPte+0x3e:
80a898d6 a801 test al,1
1: kd> p
nt!MiFindActualFaultingPte+0x40:
80a898d8 7404 je nt!MiFindActualFaultingPte+0x46 (80a898de)
1: kd> r
eax=0a1cd963
1: kd> p
nt!MiFindActualFaultingPte+0x95:
80a8992d c20400 ret 4
1: kd> r
eax=c0304200
if (PointerFaultingPte == NULL) {
return PointerPte;
}
参考:
PointerPte = MiGetPteAddress (FaultingAddress);
if (PointerPte->u.Hard.Valid == 1) {
参考:
第十五部分:
//
// Check to see if the faulting PTE has changed.
//
NewPointerPte = MiFindActualFaultingPte (FaultingAddress); eax=c0304200
1: kd> !pte c1080000
VA c1080000
PDE at C0300C10 PTE at C0304200
contains 0A03F963 contains 00027400
pfn a03f -G-DA--KWEV not valid
Proto: E1009C00
1: kd> dd c0304200
c0304200 00027400 00027402 00027404 00027406
c0304210 00027408 0002740a 0002740c 0002740e
0111 0100 0000 0000
if (NewPointerPte != PointerPte) {
//
// Check to make sure the NewPointerPte is not a prototype PTE
// which refers to the page being made valid.
//
if (NewPointerPte->u.Soft.Prototype == 1) {
if (NewPointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED) {
ProtoPte = MiCheckVirtualAddress (FaultingAddress,
&Protection,
&ProtoVad);
}
else {
ProtoPte = MiPteToProto (NewPointerPte);
}
1: kd> p
nt!MiWaitForInPageComplete+0x701:
80a8a4a7 7452 je nt!MiWaitForInPageComplete+0x755 (80a8a4fb)
1: kd> p
nt!MiWaitForInPageComplete+0x703:
80a8a4a9 3b450c cmp eax,dword ptr [ebp+0Ch]
1: kd> r
eax=c0304200 ebx=8962de10 ecx=0a1c0001 edx=00027000 esi=8962de48 edi=810f1650
eip=80a8a4a9 esp=f78d6848 ebp=f78d6858 iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000286
nt!MiWaitForInPageComplete+0x703:
80a8a4a9 3b450c cmp eax,dword ptr [ebp+0Ch] ss:0010:f78d6864=e1009c00
1: kd> dd f78d6858+c
f78d6864 e1009c00
else {
ProtoPte = MiPteToProto (NewPointerPte);
}
//
// Make sure the prototype PTE refers to the PTE made valid.
//
if (ProtoPte != PointerPte) {
return STATUS_PTE_CHANGED;
}
else {
ProtoPte = MiPteToProto (NewPointerPte);
}
1: kd> p
nt!MiWaitForInPageComplete+0x744:
80a8a4ea 8d0441 lea eax,[ecx+eax*2]
1: kd> p
nt!MiWaitForInPageComplete+0x747:
80a8a4ed 3b450c cmp eax,dword ptr [ebp+0Ch]
1: kd> r
eax=e1009c00
1: kd> p
nt!MiWaitForInPageComplete+0x762:
80a8a508 c21800 ret 18h
1: kd> r
eax=00000000
第十六部分:参数结果
1: kd> dd C0304200
c0304200 00027400 00027402 00027404 00027406
c0304210 00027408 0002740a 0002740c 0002740e
c0304220 00027410 00027412 00027414 00027416
c0304230 00027418 0002741a 0002741c 0002741e
c0304240 00027420 00027422 00027424 00027426
c0304250 00027428 0002742a 0002742c 0002742e
c0304260 00027430 00027432 00027434 00027436
c0304270 00027438 0002743a 0002743c 0002743e
1: kd> dd 0xe1009c00
e1009c00 0a0ee8c0 fcf194c6 fcf194c6 fcf194c6
e1009c10 fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c20 fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c30 fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c40 fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c50 fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c60 fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c70 fcf194c6 fcf194c6 fcf194c6 fcf194c6
f78d6a54 f7196c08 89528450 8962deb0 00000000 Ntfs!NtfsMapStream+0xaf (FPO: [Non-Fpo]) (CONV: stdcall) [d:\srv03rtm\base\fs\ntfs\cachesup.c @ 625]
1: kd> dt _scb 8962deb0
Ntfs!_SCB
+0x000 Header : _NTFS_ADVANCED_FCB_HEADER
+0x040 FcbLinks : _LIST_ENTRY [ 0xe13622e0 - 0xe13622e0 ]
+0x048 Fcb : 0xe13622b0 _FCB
+0x04c Vcb : 0x89469100 _VCB
+0x050 ScbState : 0x460
+0x054 NonCachedCleanupCount : 0
+0x058 CleanupCount : 0
+0x05c CloseCount : 1
+0x060 ShareAccess : _SHARE_ACCESS
+0x07c AttributeTypeCode : 0x80
+0x080 AttributeName : _UNICODE_STRING ""
+0x088 FileObject : 0x899abb00 _FILE_OBJECT
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_FILE_OBJECT *)0x899abb00)
((Ntfs!_FILE_OBJECT *)0x899abb00) : 0x899abb00 [Type: _FILE_OBJECT *]
[+0x000] Type : 5 [Type: short]
[+0x002] Size : 112 [Type: short]
[+0x004] DeviceObject : 0x8962dc08 : Device for "\Driver\Ftdisk" [Type: _DEVICE_OBJECT *]
[+0x008] Vpb : 0x8990b178 [Type: _VPB *]
[+0x00c] FsContext : 0x8962deb0 [Type: void *]
[+0x010] FsContext2 : 0x0 [Type: void *]
[+0x014] SectionObjectPointer : 0x8997b584 [Type: _SECTION_OBJECT_POINTERS *]
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_SECTION_OBJECT_POINTERS *)0x8997b584)
((Ntfs!_SECTION_OBJECT_POINTERS *)0x8997b584) : 0x8997b584 [Type: _SECTION_OBJECT_POINTERS *]
[+0x000] DataSectionObject : 0x898f28e8 [Type: void *]
[+0x004] SharedCacheMap : 0x898f19d0 [Type: void *]
[+0x008] ImageSectionObject : 0x0 [Type: void *]
1: kd> dt subsection 0x898f28e8+30
nt!SUBSECTION
+0x000 ControlArea : 0x898f28e8 _CONTROL_AREA
+0x004 u : __unnamed
+0x008 StartingSector : 0
+0x00c NumberOfFullSectors : 0x100
+0x010 SubsectionBase : 0xe1009c00 _MMPTE
+0x014 UnusedPtes : 0
+0x018 PtesInSubsection : 0x100
+0x01c NextSubsection : (null)