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 -
May 22nd, 2007 at 12:07 pm
Another example of OMAP when we try to disassemble backwards:
ChildEBP RetAddr Args to Child0006f87c 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 01034efbapplication!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 01034efbapplication!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
September 18th, 2008 at 9:20 am
[…] Crash Dump Analysis Patterns (Part 5b) […]
April 8th, 2010 at 4:26 pm
[…] Today we introduce an icon for OMAP Code Optimization pattern: […]
October 5th, 2016 at 3:28 pm
See also:
https://msdn.microsoft.com/en-us/library/windows/hardware/ff541382(v=vs.85).aspx