当前位置: 首页 > news >正文

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)

相关文章:

  • ArcPy错误处理与调试技巧(3)
  • SRE 基础知识:在站点可靠性工程中可以期待什么
  • Mac电脑上本地安装 MySQL并配置开启自启完整流程
  • 数字创新智慧园区建设及运维方案
  • go环境配置
  • MATLAB中properties函数用法
  • 【Linux命令】scp远程拷贝
  • 考研系列—操作系统:第五章、输入输出(I/O)管理
  • 【笔记】在 MSYS2(MINGW64)中安装 python-maturin 的记录
  • 【python深度学习】Day 42 Grad-CAM与Hook函数
  • 关于langchain使用API加载model的方式
  • C++基础算法————广度优先搜索(BFS)
  • Spring AI调用Ollama+DeepSeek
  • 微调大模型:什么时候该做,什么时候不该做?
  • NodeJS全栈开发面试题讲解——P2Express / Nest 后端开发
  • 【2025最新】Java图书借阅管理系统:从课程作业到实战应用的完整解决方案
  • java CountDownLatch‌
  • Sa-Token 同端登录冲突检测实战
  • 【harbor】--配置https
  • C++ 之 多态 【虚函数表、多态的原理、动态绑定与静态绑定】
  • 深圳网站制作公司报价/网站点击量软件
  • 企石网站建设/公众号怎么做文章推广
  • 网站建设合同模板/如何建立网站的步骤
  • 最权威最有效的投诉平台/网站seo优化方法
  • 鄂尔多斯 网站制作/西安今天刚刚发生的新闻
  • 寿光网站建设m0536/seo外链优化培训