Crash Dump Analysis Patterns (Part 5b)

This is a follow up to Optimized Code pattern written previously. Now I discuss the following feature that often bewilders beginners. It is called OMAP code optimization. It is used to make code that needs to be present in memory smaller. So instead of flat address space for compiled function you have pieces of it scattered here and there. This leads to an ambiguity when you try to disassemble OMAP code at its address because WinDbg doesn’t know whether it should treat address range as a function offset (starting from the beginning of the function source code) or just a memory layout offset (starting from the address of that function). Let me illustrate this on IoCreateDevice function code.

Let’s first evaluate a random address starting from the first address of the function (memory layout offset):

kd> ? nt!IoCreateDevice
Evaluate expression: -8796073668256 = fffff800`01275160
kd> ? nt!IoCreateDevice+0×144
Evaluate expression: -8796073667932 = fffff800`012752a4
kd> ? fffff800`012752a4-fffff800`01275160
Evaluate expression: 324 = 00000000`00000144

If we try to disassemble code at the same address the expression will also be evaluated as the memory layout offset:

kd> u nt!IoCreateDevice+0×144
nt!IoCreateDevice+0×1a3:
fffff800`012752a4 83c810          or      eax,10h
fffff800`012752a7 898424b0000000  mov     dword ptr [rsp+0B0h],eax
fffff800`012752ae 85ed            test    ebp,ebp
fffff800`012752b0 8bdd            mov     ebx,ebp
fffff800`012752b2 0f858123feff    jne     nt!IoCreateDevice+0×1b3
fffff800`012752b8 035c2454        add     ebx,dword ptr [rsp+54h]
fffff800`012752bc 488b1585dcf2ff  mov     rdx,qword ptr [nt!IoDeviceObjectType]
fffff800`012752c3 488d8c2488000000 lea     rcx,[rsp+88h]

You see the difference: we give +0×144 offset but the code is shown from +0×1a3! This is because OMAP optimization moved the code from the function offset +0×1a3 to memory locations starting from +0×144. The following picture illustrates this:

If you see this when disassembling a function name+offset address from a thread stack trace you can use raw address instead:

kd> k
Child-SP          RetAddr           Call Site
fffffadf`e3a18d30 fffff800`012b331e component!function+0×72
fffffadf`e3a18d70 fffff800`01044196 nt!PspSystemThreadStartup+0×3e
fffffadf`e3a18dd0 00000000`00000000 nt!KxStartSystemThread+0×16
kd> u fffff800`012b331e
nt!PspSystemThreadStartup+0×3e:
fffff800`012b331e 90              nop
fffff800`012b331f f683fc03000040  test    byte ptr [rbx+3FCh],40h
fffff800`012b3326 0f8515d30600    jne     nt!PspSystemThreadStartup+0×4c
fffff800`012b332c 65488b042588010000 mov   rax,qword ptr gs:[188h]
fffff800`012b3335 483bd8          cmp     rbx,rax
fffff800`012b3338 0f85a6d30600    jne     nt!PspSystemThreadStartup+0×10c
fffff800`012b333e 838bfc03000001  or      dword ptr [rbx+3FCh],1
fffff800`012b3345 33c9            xor     ecx,ecx

You also see OMAP in action also when you try to disassemble the function body using uf command:

kd> uf nt!IoCreateDevice
nt!IoCreateDevice+0×34d:
fffff800`0123907d 834f3008        or      dword ptr [rdi+30h],8
fffff800`01239081 e955c30300      jmp     nt!IoCreateDevice+0×351



nt!IoCreateDevice+0×14c:
fffff800`0126f320 6641be0002      mov     r14w,200h
fffff800`0126f325 e92f5f0000      jmp     nt!IoCreateDevice+0×158
nt!IoCreateDevice+0×3cc:
fffff800`01270bd0 488d4750        lea     rax,[rdi+50h]
fffff800`01270bd4 48894008        mov     qword ptr [rax+8],rax
fffff800`01270bd8 488900          mov     qword ptr [rax],rax
fffff800`01270bdb e95b480000      jmp     nt!IoCreateDevice+0×3d7
nt!IoCreateDevice+0xa4:
fffff800`01273eb9 41b801000000    mov     r8d,1
fffff800`01273ebf 488d154a010700  lea     rdx,[nt!`string’]
fffff800`01273ec6 488d8c24d8000000 lea     rcx,[rsp+0D8h]
fffff800`01273ece 440fc10522f0f2ff xadd    dword ptr [nt!IopUniqueDeviceObjectNumber],r8d
fffff800`01273ed6 41ffc0          inc     r8d
fffff800`01273ed9 e8d236deff      call    nt!swprintf
fffff800`01273ede 4584ed          test    r13b,r13b
fffff800`01273ee1 0f85c1a70800    jne     nt!IoCreateDevice+0xce


- Dmitry Vostokov @ DumpAnalysis.org -

4 Responses to “Crash Dump Analysis Patterns (Part 5b)”

  1. Dmitry Vostokov Says:

    Another example of OMAP when we try to disassemble backwards:

    ChildEBP RetAddr Args to Child
    0006f87c 01034efb application!MultiUserLogonAttempt+0×5ba
    0006fee4 01037120 application!LogonAttempt+0×406

    1: kd> ub application!LogonAttempt+0x406
    ^ Unable to find valid previous instruction for ‘ub application!LogonAttempt+0×406′
    1: kd> u application!LogonAttempt+0×406
    application!LogonAttempt+0×20b:
    010348d5 add dword ptr [edx+10h],ebp

    We have to specify the return address for MultiUserLogonAttempt:

    1: kd> ub 01034efb
    application!LogonAttempt+0×3e4:
    01034ed9 mov dword ptr [ebp-628h],ecx
    01034edf mov ecx,dword ptr [ebp-61Ch]
    01034ee5 mov dword ptr [eax+24h],ecx
    01034ee8 push dword ptr [ebp-61Ch]
    01034eee lea eax,[ebp-638h]
    01034ef4 push eax
    01034ef5 push ebx
    01034ef6 call application!MultiUserLogonAttempt (0102c822)

    1: kd> u 01034efb
    application!LogonAttempt+0×406:
    01034efb mov ecx,dword ptr [ebp-628h]
    01034f01 mov  dword ptr [ebp-608h],eax
    01034f07 mov  eax,dword ptr [ebx+8]
    01034f0a mov  dword ptr [eax+24h],ecx
    01034f0d cmp  dword ptr [application!g_SessionId (010742dc)],0
    01034f14 je application!LogonAttempt+0×47e (01034f73)
    01034f16 lea  eax,[ebx+1078h]
    01034f1c push eax

  2. !analyze -v : Crash Dump Analysis Patterns (Part 5b) Says:

    […] Crash Dump Analysis Patterns (Part 5b) […]

  3. Crash Dump Analysis » Blog Archive » Icons for Memory Dump Analysis Patterns (Part 20) Says:

    […] Today we introduce an icon for OMAP Code Optimization pattern: […]

  4. Dmitry Vostokov Says:

    See also:
    https://msdn.microsoft.com/en-us/library/windows/hardware/ff541382(v=vs.85).aspx

Leave a Reply