Archive for the ‘Crash Dump Analysis’ Category

Inconsistent dump, stack trace collection, LPC, thread, process, executive resource wait chains, missing threads and waiting thread time: pattern cooperation

Saturday, February 27th, 2010

Here is a synthetic case study to show various wait chain patterns. The complete memory dump from a frozen system is inconsistent, saved by LiveKd. Stack trace collection shows many threads waiting for LPC replies:

THREAD 87432520  Cid 0b10.0dd8  Teb: 7ff83000 Win32Thread: 00000000 WAIT: (Unknown) UserMode Non-Alertable
    8743270c  Semaphore Limit 0x1
Waiting for reply to LPC MessageId 007ade85:
Current LPC port d676e560
Not impersonating
DeviceMap                 d6f05be8
Owning Process            87581c78       Image:         ProcessA.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      4093415        Ticks: 659565 (0:02:51:45.703)
Context Switch Count      111255            
UserTime                  00:00:27.781
KernelTime                00:00:02.015
Win32 Start Address MSVCR71!_threadstartex (0×7c3494f6)
Start Address kernel32!BaseThreadStartThunk (0×77e617ec)
Stack Init b6439000 Current b6438c08 Base b6439000 Limit b6436000 Call 0
Priority 8 BasePriority 8 PriorityDecrement 0
Kernel stack not resident.
ChildEBP RetAddr 
b6438c10 00000000 0×0

Checking MessageId by using !lpc command gives us the following LPC server thread that is waiting for a mutant owned by thread 866d63e8 (this is equivalent that thread 85b209d0 is waiting for thread 866d63e8):

THREAD 85b209d0  Cid 1524.2770  Teb: 7ff78000 Win32Thread: 00000000 WAIT: (Unknown) UserMode Non-Alertable
    85e9ba00  Mutant - owning thread 866d63e8
Not impersonating
DeviceMap                 d64008d8
Owning Process            87200880       Image:         ProcessB.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      4093415        Ticks: 659565 (0:02:51:45.703)
Context Switch Count      28            
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address 0×007ade85
LPC Server thread working on message Id 7ade85
Start Address kernel32!BaseThreadStartThunk (0×77e617ec)
Stack Init b42e5000 Current b42e4c60 Base b42e5000 Limit b42e2000 Call 0
Priority 10 BasePriority 10 PriorityDecrement 0
Kernel stack not resident.
ChildEBP RetAddr 
b42e4c68 00000000 0xa000a02

Thread 866d63e8 is waiting for a process 86b33b30:

THREAD 866d63e8  Cid 1524.3984  Teb: 7ff6e000 Win32Thread: 00000000 WAIT: (Unknown) UserMode Non-Alertable
    86b33b30  ProcessObject
    866d6460  NotificationTimer
Not impersonating
DeviceMap                 d64008d8
Owning Process            87200880       Image:         ProcessB.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      4755080     
Context Switch Count      4767            
UserTime                  00:00:00.015
KernelTime                00:00:00.000
Win32 Start Address 0×007a5051
LPC Server thread working on message Id 7a5051
Start Address kernel32!BaseThreadStartThunk (0×77e617ec)
Stack Init ab459000 Current ab458c60 Base ab459000 Limit ab456000 Call 0
Priority 10 BasePriority 10 PriorityDecrement 0
ChildEBP RetAddr 
ab458c78 8083d5b1 nt!KiSwapContext+0×26
ab458ca4 8083df9e nt!KiSwapThread+0×2e5
ab458cec 8092ae67 nt!KeWaitForSingleObject+0×346
ab458d50 80833bef nt!NtWaitForSingleObject+0×9a
ab458d50 7c82860c nt!KiFastCallEntry+0xfc (TrapFrame @ ab458d64)
0499fbec 7c827d29 ntdll!KiFastSystemCallRet
0499fbf0 76548721 ntdll!ZwWaitForSingleObject+0xc
0499fc0c 7654aa54 ProcessB!WaitForProcess+0×4a
[…]
0499ffec 00000000 kernel32!BaseThreadStart+0×34

We find the following thread in the process 86b33b30 (there is only one thread left where we expect many of them in ProcessC):

THREAD 85a6fdb0  Cid 5c0c.26f4  Teb: 7ffdf000 Win32Thread: b9b778a0 WAIT: (Unknown) KernelMode Non-Alertable
    86686030  SynchronizationEvent
    85a6fe28  NotificationTimer
Not impersonating
DeviceMap                 d6767248
Owning Process            86b33b30       Image:         ProcessC.EXE
Attached Process          N/A            Image:         N/A
Wait Start TickCount      4755681     
Context Switch Count      77668                 LargeStack
UserTime                  00:00:00.437
KernelTime                00:00:04.421
*** ERROR: Module load completed but symbols could not be loaded for ProcessC.EXE
Win32 Start Address 0×300010cc
Start Address kernel32!BaseProcessStartThunk (0×77e617f8)
Stack Init 9ad92000 Current 9ad91a40 Base 9ad92000 Limit 9ad8d000 Call 0
Priority 10 BasePriority 10 PriorityDecrement 0
ChildEBP RetAddr 
9ad91a58 8083d5b1 nt!KiSwapContext+0×26
9ad91a84 8083df9e nt!KiSwapThread+0×2e5
9ad91acc 8081e05b nt!KeWaitForSingleObject+0×346
9ad91b08 8082e012 nt!ExpWaitForResource+0xd5
9ad91b28 b6a9c1ee nt!ExAcquireResourceExclusiveLite+0×8d
WARNING: Stack unwind information not available. Following frames may be wrong.
9ad91b38 b6ab09d3 DriverA+0×21ee
[…]
9ad91c3c 80840153 DriverA+0×1ed6

9ad91c50 8092b51f nt!IofCallDriver+0×45
9ad91c64 8092b454 nt!IopSynchronousServiceTail+0×10b
9ad91d00 8092b574 nt!IopXxxControlFile+0×60f
9ad91d34 80833bef nt!NtDeviceIoControlFile+0×2a
9ad91d34 7c82860c nt!KiFastCallEntry+0xfc (TrapFrame @ 9ad91d64)
0012d4e0 00000000 ntdll!KiFastSystemCallRet

It is blocked by DriverA waiting for an executive resource. Fortunately !locks command works for this inconsistent dump and we finally reach thread 86ba5638:

0: kd> !locks

Resource @ 0x85610d30    Exclusively owned
    Contention Count = 4
    NumberOfExclusiveWaiters = 1
     Threads: 86ba5638-01<*>
     Threads Waiting On Exclusive Access:
              85a6fdb0

This thread belongs to another instance of ProcessC.exe (different process 8690dd88):

0: kd> !thread 86ba5638 1f
THREAD 86ba5638  Cid 186c.1574  Teb: 7ffdf000 Win32Thread: b9a28a70 WAIT: (Unknown) KernelMode Non-Alertable
    8944e3d4  SynchronizationEvent
Not impersonating
DeviceMap                 d6767248
Owning Process            8690dd88       Image:         ProcessC.EXE
Attached Process          N/A            Image:         N/A
Wait Start TickCount      4074148        Ticks: 678832 (0:02:56:46.750)
Context Switch Count      95896                 LargeStack
UserTime                  00:00:00.593
KernelTime                00:00:05.343
*** ERROR: Module load completed but symbols could not be loaded for ProcessC.EXE
Win32 Start Address 0×300010cc
Start Address kernel32!BaseProcessStartThunk (0×77e617f8)
Stack Init 99ef2000 Current 99ef19c0 Base 99ef2000 Limit 99eec000 Call 0
Priority 10 BasePriority 10 PriorityDecrement 0
ChildEBP RetAddr 
99ef19d8 8083d5b1 nt!KiSwapContext+0×26
99ef1a04 8083df9e nt!KiSwapThread+0×2e5
99ef1a4c 80853f3f nt!KeWaitForSingleObject+0×346
99ef1a64 8081d45f nt!KiAcquireFastMutex+0×13
99ef1a70 b6a9c70d nt!ExAcquireFastMutex+0×20
WARNING: Stack unwind information not available. Following frames may be wrong.
99ef1a7c b6aaf22a DriverA+0×270d
[…]
99ef1c3c 80840153 DriverA+0×1ed6

99ef1c50 8092b51f nt!IofCallDriver+0×45
99ef1c64 8092b454 nt!IopSynchronousServiceTail+0×10b
99ef1d00 8092b574 nt!IopXxxControlFile+0×60f
99ef1d34 80833bef nt!NtDeviceIoControlFile+0×2a
99ef1d34 7c82860c nt!KiFastCallEntry+0xfc (TrapFrame @ 99ef1d64)
0012db08 00000000 ntdll!KiFastSystemCallRet

We see this thread is also blocked by DriverA. We also check thread waiting times. All threads involved in wait chains have their Ticks value less than 86ba5638. This means that thread 86ba5638 was blocked earlier. We contact DriverA vendor for any possible updates.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Crash Dump Analysis Patterns (Part 96)

Sunday, February 21st, 2010

For certain stack traces we should always be aware of Coincidental Frames similar to Coincidental Symbolic Information pattern for raw stack data. Such frames can lead to a wrong analysis conclusion. Consider this stack trace fragment from a kernel memory dump:

0: kd> kL 100
ChildEBP RetAddr
9c5b6550 8082d9a4 nt!KeBugCheckEx+0×1b
9c5b6914 8088befa nt!KiDispatchException+0×3a2
9c5b697c 8088beae nt!CommonDispatchException+0×4a
9c5b699c 80a6056d nt!KiExceptionExit+0×186
9c5b69a0 80893ae2 hal!KeReleaseQueuedSpinLock+0×2d
9c5b6a08 b20c3de5 nt!MiFreePoolPages+0×7dc
WARNING: Stack unwind information not available. Following frames may be wrong.
9c5b6a48 b20c4107 DeriverA+0×17de5
[…]

The frame with MiFreePoolPages symbol might suggest some sort of a pool corruption. We can even double check return addresses and see the valid common sense assembly language code:

0: kd> ub 8088beae
nt!KiExceptionExit+0×167:
8088be8f 33c9            xor     ecx,ecx
8088be91 e81a000000      call    nt!CommonDispatchException (8088beb0)
8088be96 33d2            xor     edx,edx
8088be98 b901000000      mov     ecx,1
8088be9d e80e000000      call    nt!CommonDispatchException (8088beb0)
8088bea2 33d2            xor     edx,edx
8088bea4 b902000000      mov     ecx,2
8088bea9 e802000000      call    nt!CommonDispatchException (8088beb0)

0: kd> ub 80a6056d
hal!KeReleaseQueuedSpinLock+0×1b:
80a6055b 7511            jne     hal!KeReleaseQueuedSpinLock+0×2e (80a6056e)
80a6055d 50              push    eax
80a6055e f00fb119        lock cmpxchg dword ptr [ecx],ebx
80a60562 58              pop     eax
80a60563 7512            jne     hal!KeReleaseQueuedSpinLock+0×37 (80a60577)
80a60565 5b              pop     ebx
80a60566 8aca            mov     cl,dl
80a60568 e8871e0000      call    hal!KfLowerIrql (80a623f4)

0: kd> ub 80893ae2
nt!MiFreePoolPages+0×7c3:
80893ac9 761c            jbe     nt!MiFreePoolPages+0×7e1 (80893ae7)
80893acb ff75f8          push    dword ptr [ebp-8]
80893ace ff7508          push    dword ptr [ebp+8]
80893ad1 e87ea1fcff      call    nt!MiFreeNonPagedPool (8085dc54)
80893ad6 8a55ff          mov     dl,byte ptr [ebp-1]
80893ad9 6a0f            push    0Fh
80893adb 59              pop     ecx
80893adc ff1524118080    call    dword ptr [nt!_imp_KeReleaseQueuedSpinLock (80801124)]

0: kd> ub b20c3de5
DriverA+0×17dcf:
b20c3dcf 51              push    ecx
b20c3dd0 ff5010          call    dword ptr [eax+10h]
b20c3dd3 eb10            jmp     DriverA+0×17de5 (b20c3de5)
b20c3dd5 8b5508          mov     edx,dword ptr [ebp+8]
b20c3dd8 52              push    edx
b20c3dd9 8d86a0000000    lea     eax,[esi+0A0h]
b20c3ddf 50              push    eax
b20c3de0 e8ebf1ffff      call    DriverA+0×16fd0 (b20c2fd0)

However, if we try to reconstruct the stack trace manually we would naturally skip these 3 frames (shown in magenta):

9c5b6550 8082d9a4 nt!KeBugCheckEx+0x1b
9c5b6914 8088befa nt!KiDispatchException+0x3a2
9c5b697c 8088beae nt!CommonDispatchException+0x4a
9c5b699c 80a6056d nt!KiExceptionExit+0×186
9c5b69a0 80893ae2 hal!KeReleaseQueuedSpinLock+0×2d
9c5b6a08 b20c3de5 nt!MiFreePoolPages+0×7dc

9c5b6a48 b20c4107 DeriverA+0×17de5
[…]

0: kd> !thread
THREAD 8f277020  Cid 081c.7298  Teb: 7ff11000 Win32Thread: 00000000 RUNNING on processor 0
IRP List:
8e234b60: (0006,0094) Flags: 00000000  Mdl: 00000000
Not impersonating
DeviceMap                 e1002880
Owning Process            8fc78b80       Image:         ProcessA.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      49046879       Ticks: 0
Context Switch Count      10
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address DllA!ThreadA (0x7654dc90)
Start Address kernel32!BaseThreadStartThunk (0x77e617dc)
Stack Init 9c5b7000 Current 9c5b6c50 Base 9c5b7000 Limit 9c5b4000 Call 0
Priority 10 BasePriority 10 PriorityDecrement 0
ChildEBP RetAddr  Args to Child
[…]

0: kd> dds 9c5b4000 9c5b7000
9c5b4000  00000000
9c5b4004  00000000
9c5b4008  00000000
[...]
9c5b6290  ffdff13c
9c5b6294  9c5b6550
9c5b6298  80827e01 nt!KeBugCheckEx+0×1b
9c5b629c  00000008
9c5b62a0  00000286
[…]
9c5b654c  00000000
9c5b6550  9c5b6914
9c5b6554  8082d9a4 nt!KiDispatchException+0×3a2
9c5b6558  0000008e
9c5b655c  c0000005
[…]
9c5b6910  ffffffff
9c5b6914  9c5b6984
9c5b6918  8088befa nt!CommonDispatchException+0×4a
9c5b691c  9c5b6930
9c5b6920  00000000
[…]
9c5b6980  8088beae nt!KiExceptionExit+0×186
9c5b6984  9c5b6a08
9c5b6988  b20c3032 DriverA+0×17032
9c5b698c  badb0d00
9c5b6990  00000006
9c5b6994  8dc11cec
9c5b6998  808b6900 nt!KiTimerTableLock+0×3c0
9c5b699c  9c5b69d4
9c5b69a0  80a6056d hal!KeReleaseQueuedSpinLock+0×2d
9c5b69a4  80893ae2 nt!MiFreePoolPages+0×7dc

9c5b69a8  808b0b40 nt!NonPagedPoolDescriptor
9c5b69ac  03151fd0
9c5b69b0  00000000
9c5b69b4  00000000
[…]
9c5b6a04  8f47123b
9c5b6a08  9c5b6a48
9c5b6a0c  b20c3de5 DriverA+0×17de5
9c5b6a10  8e3640a0
9c5b6a14  8f4710d0
[…]
9c5b6a44  00000000
9c5b6a48  9c5b6a80
9c5b6a4c  b20c4107 DriverA+0×18107
9c5b6a50  8f4710d0
9c5b6a54  9c5b6a6c
[…]

If we try to find a pointer to the exception record we get this crash address:

0: kd> .exr 9c5b6930
ExceptionAddress: b20c3032 (DriverA+0×00017032)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: 00000157
Attempt to read from address 00000157

If we disassemble it we see an inlined string or memory copy, perhaps wcscpy function:

0: kd> u b20c3032
DriverA+0×17032:
b20c3032 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
b20c3034 8bcb            mov     ecx,ebx
b20c3036 83e103          and     ecx,3
b20c3039 f3a4            rep movs byte ptr es:[edi],byte ptr [esi]
b20c303b 8b750c          mov     esi,dword ptr [ebp+0Ch]
b20c303e 0fb7ca          movzx   ecx,dx
b20c3041 894e14          mov     dword ptr [esi+14h],ecx
b20c3044 8b700c          mov     esi,dword ptr [eax+0Ch]

So the problem happened in DriverA code, not in MiFreePoolPages or KeReleaseQueuedSpinLock.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Bus Debugging

Friday, February 19th, 2010

This post is not about debugging a computer bus. It is about debugging on a bus. More correctly, it is about debugging software running on a bus, not on a computer bus but on a real bus. A few days ago I was on a bus leaving Dublin bus station to Dublin airport. Looking around inside the bus I noticed one monitor had a characteristic Windows XP-style message box of an access violation. It was just before disembarking the bus so I made a mental effort to memorize the referenced memory address: 0×4000 and the instruction address: x73f18a09. The application name was bb.exe. Google search for 73f10000 module load address points to this one:

ModLoad: 73f10000 73f6c000   C:\WINDOWS\system32\DSOUND.dll

Not really a debugging (there’s no fix from me) so it can be named as a bus analysis exercise.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Crash Dump Analysis Patterns (Part 42f)

Tuesday, February 16th, 2010

Here we show an example of a wait chain involving process objects. This Wait Chain pattern variation is similar to threads waiting for thread objects. When looking at stack trace collection from a complete memory dump file we see several threads in a set of processes are blocked in ALPC wait chain:

THREAD fffffa80110b8700  Cid 12f8.1328  Teb: 000000007ef9a000 Win32Thread: 0000000000000000 WAIT: (WrLpcReply) UserMode Non-Alertable
    fffffa80110b8a90  Semaphore Limit 0x1
Waiting for reply to ALPC Message fffff8801c7096e0 : queued at port fffffa8010c9d9a0 : owned by process fffffa80109c8c10
Not impersonating
DeviceMap                 fffff880097ce5e0
Owning Process            fffffa80110ad510       Image:         ProcessA.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      14004580       Ticks: 62149 (0:00:16:09.530)
Context Switch Count      25100            
UserTime                  00:00:00.421
KernelTime                00:00:00.218
Win32 Start Address 0×0000000074ca29e1
Stack Init fffffa6003bc4db0 Current fffffa6003bc4670
Base fffffa6003bc5000 Limit fffffa6003bbf000 Call 0
Priority 8 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`03bc46b0 fffff800`01cba0fa nt!KiSwapContext+0×7f
fffffa60`03bc47f0 fffff800`01caedab nt!KiSwapThread+0×13a
fffffa60`03bc4860 fffff800`01ce4e72 nt!KeWaitForSingleObject+0×2cb
fffffa60`03bc48f0 fffff800`01f32f34 nt!AlpcpSignalAndWait+0×92
fffffa60`03bc4980 fffff800`01f2f9c6 nt!AlpcpReceiveSynchronousReply+0×44
fffffa60`03bc49e0 fffff800`01f1f52f nt!AlpcpProcessSynchronousRequest+0×24f
fffffa60`03bc4b00 fffff800`01cb7973 nt!NtAlpcSendWaitReceivePort+0×19f
fffffa60`03bc4bb0 00000000`7713756a nt!KiSystemServiceCopyEnd+0×13 (TrapFrame @ fffffa60`03bc4c20)
00000000`016ee5b8 00000000`74f9993f ntdll!ZwAlpcSendWaitReceivePort+0xa
00000000`016ee5c0 00000000`74f8a996 wow64!whNtAlpcSendWaitReceivePort+0×5f
00000000`016ee610 00000000`75183688 wow64!Wow64SystemServiceEx+0xca
00000000`016eeec0 00000000`74f8ab46 wow64cpu!ServiceNoTurbo+0×28
00000000`016eef50 00000000`74f8a14c wow64!RunCpuSimulation+0xa
00000000`016eef80 00000000`771605a8 wow64!Wow64LdrpInitialize+0×4b4
00000000`016ef4e0 00000000`771168de ntdll! ?? ::FNODOBFM::`string’+0×20aa1
00000000`016ef590 00000000`00000000 ntdll!LdrInitializeThunk+0xe

1: kd> !alpc /m fffff8801c7096e0

Message @ fffff8801c7096e0
  MessageID             : 0x263C (9788)
  CallbackID            : 0x29F2A02 (43985410)
  SequenceNumber        : 0x000009FE (2558)
  Type                  : LPC_REQUEST
  DataLength            : 0x0058 (88)
  TotalLength           : 0x0080 (128)
  Canceled              : No
  Release               : No
  ReplyWaitReply        : No
  Continuation          : Yes
  OwnerPort             : fffffa8015128040 [ALPC_CLIENT_COMMUNICATION_PORT]
  WaitingThread         : fffffa80110b8700
  QueueType             : ALPC_MSGQUEUE_PENDING
  QueuePort             : fffffa8010c9d9a0 [ALPC_CONNECTION_PORT]
  QueuePortOwnerProcess : fffffa80109c8c10 (ProcessB.exe)
  ServerThread          : fffffa8013b87bb0
  QuotaCharged          : No
  CancelQueuePort       : 0000000000000000
  CancelSequencePort    : 0000000000000000
  CancelSequenceNumber  : 0×00000000 (0)
  ClientContext         : 0000000009b49208
  ServerContext         : 0000000000000000
  PortContext           : 000000000280f0d0
  CancelPortContext     : 0000000000000000
  SecurityData          : 0000000000000000
  View                  : 0000000000000000

If we look at process fffffa80109c8c10 and its thread fffffa8013b87bb0 we would see that it is blocked as well on some kind of a lock:

THREAD fffffa8013b87bb0  Cid 0358.2c60  Teb: 000007fffff7e000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
    fffffa8010bca370  Semaphore Limit 0x7fffffff
    fffffa8013b87c68  NotificationTimer
Impersonation token:  fffff8801e614060 (Level Impersonation)
DeviceMap                 fffff880097ce5e0
Owning Process            fffffa80109c8c10       Image:         ProcessB.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      14004580       Ticks: 62149 (0:00:16:09.530)
Context Switch Count      134            
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address RPCRT4!ThreadStartRoutine (0x000007feff267780)
Stack Init fffffa6035a1fdb0 Current fffffa6035a1f940
Base fffffa6035a20000 Limit fffffa6035a1a000 Call 0
Priority 11 BasePriority 10 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`35a1f980 fffff800`01cba0fa nt!KiSwapContext+0x7f
fffffa60`35a1fac0 fffff800`01caedab nt!KiSwapThread+0x13a
fffffa60`35a1fb30 fffff800`01f1d608 nt!KeWaitForSingleObject+0x2cb
fffffa60`35a1fbc0 fffff800`01cb7973 nt!NtWaitForSingleObject+0x98
fffffa60`35a1fc20 00000000`77136d5a nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffffa60`35a1fc20)
00000000`0486ec28 00000000`770f559f ntdll!ZwWaitForSingleObject+0xa
00000000`0486ec30 00000000`ff77d4e9 ntdll!RtlAcquireResourceShared+0xd1
00000000`0486ec70 00000000`ff77fb4d ProcessB!CLock::CLock+0×61
[…]
00000000`0486eee0 000007fe`ff261f46 RPCRT4!Invoke+0×65
00000000`0486ef40 000007fe`ff26254d RPCRT4!NdrStubCall2+0×348
00000000`0486f520 000007fe`ff2868d4 RPCRT4!NdrServerCall2+0×1d
00000000`0486f550 000007fe`ff2869f0 RPCRT4!DispatchToStubInCNoAvrf+0×14
00000000`0486f580 000007fe`ff287402 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0×100
00000000`0486f670 000007fe`ff287080 RPCRT4!LRPC_SCALL::DispatchRequest+0×1c2
00000000`0486f6e0 000007fe`ff2862bb RPCRT4!LRPC_SCALL::HandleRequest+0×200
00000000`0486f800 000007fe`ff285e1a RPCRT4!LRPC_ADDRESS::ProcessIO+0×44a
00000000`0486f920 000007fe`ff267769 RPCRT4!LOADABLE_TRANSPORT::ProcessIOEvents+0×24a
00000000`0486f9d0 000007fe`ff267714 RPCRT4!ProcessIOEventsWrapper+0×9
00000000`0486fa00 000007fe`ff2677a4 RPCRT4!BaseCachedThreadRoutine+0×94
00000000`0486fa40 00000000`76fdbe3d RPCRT4!ThreadStartRoutine+0×24
00000000`0486fa70 00000000`77116a51 kernel32!BaseThreadInitThunk+0xd
00000000`0486faa0 00000000`00000000 ntdll!RtlUserThreadStart+0×1d

There are many such threads and inspection of all threads in the process fffffa80109c8c10 reveals another thread waiting for an ALPC reply:

THREAD fffffa8010c9b060  Cid 0358.02ac  Teb: 000007fffffd3000 Win32Thread: 0000000000000000 WAIT: (WrLpcReply) UserMode Non-Alertable
    fffffa8010c9b3f0  Semaphore Limit 0x1
    Waiting for reply to ALPC Message fffff88011994cf0 : queued at port fffffa8010840360 : owned by process fffffa801083e120
Not impersonating
DeviceMap                 fffff880000073d0
Owning Process            fffffa80109c8c10       Image:         ProcessB.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      13986969       Ticks: 79760 (0:00:20:44.263)
Context Switch Count      712            
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address ntdll!TppWorkerThread (0×0000000077107cb0)
Stack Init fffffa6004bfbdb0 Current fffffa6004bfb670
Base fffffa6004bfc000 Limit fffffa6004bf6000 Call 0
Priority 10 BasePriority 10 PriorityDecrement 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
Child-SP          RetAddr           Call Site
fffffa60`04bfb6b0 fffff800`01cba0fa nt!KiSwapContext+0×7f
fffffa60`04bfb7f0 fffff800`01caedab nt!KiSwapThread+0×13a
fffffa60`04bfb860 fffff800`01ce4e72 nt!KeWaitForSingleObject+0×2cb
fffffa60`04bfb8f0 fffff800`01f32f34 nt!AlpcpSignalAndWait+0×92
fffffa60`04bfb980 fffff800`01f2f9c6 nt!AlpcpReceiveSynchronousReply+0×44
fffffa60`04bfb9e0 fffff800`01f1f52f nt!AlpcpProcessSynchronousRequest+0×24f
fffffa60`04bfbb00 fffff800`01cb7973 nt!NtAlpcSendWaitReceivePort+0×19f
fffffa60`04bfbbb0 00000000`7713756a nt!KiSystemServiceCopyEnd+0×13 (TrapFrame @ fffffa60`04bfbc20)
00000000`00c3f2f8 00000000`771872c9 ntdll!ZwAlpcSendWaitReceivePort+0xa
[…]
00000000`00c3f810 00000000`77107fd0 ntdll!RtlpTpWorkCallback+0xf2
00000000`00c3f8c0 00000000`76fdbe3d ntdll!TppWorkerThread+0×3d6
00000000`00c3fb40 00000000`77116a51 kernel32!BaseThreadInitThunk+0xd
00000000`00c3fb70 00000000`00000000 ntdll!RtlUserThreadStart+0×1d

1: kd> !alpc /m fffff88011994cf0

Message @ fffff88011994cf0
  MessageID             : 0x033C (828)
  CallbackID            : 0x29CEF57 (43839319)
  SequenceNumber        : 0x000000D8 (216)
  Type                  : LPC_REQUEST
  DataLength            : 0x000C (12)
  TotalLength           : 0x0034 (52)
  Canceled              : No
  Release               : No
  ReplyWaitReply        : No
  Continuation          : Yes
  OwnerPort             : fffffa8010c99040 [ALPC_CLIENT_COMMUNICATION_PORT]
  WaitingThread         : fffffa8010c9b060
  QueueType             : ALPC_MSGQUEUE_PENDING
  QueuePort             : fffffa8010840360 [ALPC_CONNECTION_PORT]
  QueuePortOwnerProcess : fffffa801083e120 (ProcessC.exe)
  ServerThread          : fffffa80109837d0
  QuotaCharged          : No
  CancelQueuePort       : 0000000000000000
  CancelSequencePort    : 0000000000000000
  CancelSequenceNumber  : 0×00000000 (0)
  ClientContext         : 0000000000000000
  ServerContext         : 0000000000000000
  PortContext           : 00000000005f3400
  CancelPortContext     : 0000000000000000
  SecurityData          : 0000000000000000
  View                  : 0000000000000000

We see that ProcessC thread fffffa80109837d0 is waiting for a process object fffffa801434cb40:

THREAD fffffa80109837d0  Cid 027c.02b0  Teb: 000007fffffdb000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
    fffffa801434cb40  ProcessObject
Not impersonating
DeviceMap                 fffff880000073d0
Owning Process            fffffa801083e120       Image:         ProcessC.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      13986969       Ticks: 79760 (0:00:20:44.263)
Context Switch Count      520            
UserTime                  00:00:00.000
KernelTime                00:00:00.062
Win32 Start Address 0×000000004826dcf4
Stack Init fffffa6002547db0 Current fffffa6002547940
Base fffffa6002548000 Limit fffffa6002542000 Call 0
Priority 13 BasePriority 11 PriorityDecrement 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
Child-SP          RetAddr           Call Site
fffffa60`02547980 fffff800`01cba0fa nt!KiSwapContext+0×7f
fffffa60`02547ac0 fffff800`01caedab nt!KiSwapThread+0×13a
fffffa60`02547b30 fffff800`01f1d608 nt!KeWaitForSingleObject+0×2cb
fffffa60`02547bc0 fffff800`01cb7973 nt!NtWaitForSingleObject+0×98
fffffa60`02547c20 00000000`77136d5a nt!KiSystemServiceCopyEnd+0×13 (TrapFrame @ fffffa60`02547c20)
00000000`0024f7c8 00000000`4826ea97 ntdll!ZwWaitForSingleObject+0xa
00000000`0024f7d0 00000000`4826ef44 ProcessC!TerminatePID+0xa3
[…]
00000000`0024fc90 00000000`00000000 ntdll!RtlUserThreadStart+0×29

When we inspect process fffffa801434cb40 we see that it has only one thread with many usual threads missing. The blocked thread stack trace has DriverA module code waiting for an event:

1: kd> !process fffffa801434cb40 ff
PROCESS fffffa801434cb40
    SessionId: 1  Cid: a0c8    Peb: 7fffffdc000  ParentCid: 1c08
    DirBase: 19c6cc000  ObjectTable: fffff8801767ee00  HandleCount: 287.
    Image: ProcessD.exe
    VadRoot fffffa8021be17d0 Vads 71 Clone 0 Private 955. Modified 1245. Locked 0.
    DeviceMap fffff880000073d0
    Token                             fffff880187cb3c0
    ElapsedTime                       00:49:23.432
    UserTime                          00:00:00.686
    KernelTime                        00:00:00.904
    QuotaPoolUsage[PagedPool]         208080
    QuotaPoolUsage[NonPagedPool]      6720
    Working Set Sizes (now,min,max)  (2620, 50, 345) (10480KB, 200KB, 1380KB)
    PeakWorkingSetSize                3136
    VirtualSize                       101 Mb
    PeakVirtualSize                   222 Mb
    PageFaultCount                    13495
    MemoryPriority                    BACKGROUND
    BasePriority                      13
    CommitCharge                      1154

[...]

THREAD fffffa8012249b30  Cid a0c8.31b4  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
   fffffa801180a6a0  SynchronizationEvent
   Not impersonating
DeviceMap                 fffff880000073d0
Owning Process            fffffa801434cb40       Image:         ProcessD.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      13986969       Ticks: 79760 (0:00:20:44.263)
Context Switch Count      97            
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address DllA (0xfffff96000eeada0)
Stack Init fffffa601b841db0 Current fffffa601b841960
Base fffffa601b842000 Limit fffffa601b83c000 Call 0
Priority 13 BasePriority 13 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`1b8419a0 fffff800`01cba0fa nt!KiSwapContext+0x7f
fffffa60`1b841ae0 fffff800`01caedab nt!KiSwapThread+0x13a
fffffa60`1b841b50 fffff960`00eeb281 nt!KeWaitForSingleObject+0x2cb
fffffa60`1b841c20 fffff800`01ec7bc7 DriverA+0×4b281
fffffa60`1b841d50 fffff800`01cf65a6 nt!PspSystemThreadStartup+0×57
fffffa60`1b841d80 00000000`00000000 nt!KiStartSystemThread+0×16

We therefore recommend to contact the vendor of DriverA component.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Project CARE Update (14.02.10)

Sunday, February 14th, 2010

Thanks to everyone who submitted their debugger logs. Now VBScript and WinDbg script files are available for download from the CARE page:

http://www.dumpanalysis.org/care

VBScript file scans all hard drives for .DMP files and launches WinDbg to run a mode-independent WinDbg script. Each instance of WinDbg appends the output to dbgeng.log file that you can submit to CARE (please zip it if exceeds 2Mb).

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Memory Systems Language (Part 1)

Friday, February 12th, 2010

Computer memory analysis is based on interconnected structures of symbols and we state that there exists a memory language that extends a hierarchy of modeling and implementation languages (both domain-specific and general-purpose):

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Forthcoming Memory Dump Analysis Anthology, Volume 4

Thursday, February 11th, 2010

This is a revised, edited, cross-referenced and thematically organized volume of selected DumpAnalysis.org blog posts about crash dump analysis and debugging written in July 2009 - January 2010 for software engineers developing and maintaining products on Windows platforms, quality assurance engineers testing software on Windows platforms and technical support and escalation engineers dealing with complex software issues. The fourth volume features:

- 13 new crash dump analysis patterns
- 13 new pattern interaction case studies
- 10 new trace analysis patterns
- 6 new Debugware patterns and case study
- Workaround patterns
- Updated checklist
- Fully cross-referenced with Volume 1, Volume 2 and Volume 3
- New appendixes

Product information:

  • Title: Memory Dump Analysis Anthology, Volume 4
  • Author: Dmitry Vostokov
  • Language: English
  • Product Dimensions: 22.86 x 15.24
  • Paperback: 410 pages
  • Publisher: Opentask (30 March 2010)
  • ISBN-13: 978-1-906717-86-5
  • Hardcover: 410 pages
  • Publisher: Opentask (30 April 2010)
  • ISBN-13: 978-1-906717-87-2

Back cover features memory space art image: Internal Process Combustion.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Complete Stack Traces from x64 System

Tuesday, February 9th, 2010

Previously I wrote on how to get a 32-bit stack trace from a 32-bit process thread on an x64 system. There are situations when we are interested in all such stack traces, for example, from a complete memory dump. I wrote a script that extracts both 64-bit and WOW64 32-bit stack traces:

.load wow64exts
!for_each_thread "!thread @#Thread 1f;.thread /w @#Thread; .reload; kb 256; .effmach AMD64"

Example output fragment for a thread fffffa801f3a3bb0 from a very long debugger log file:

[...]

Setting context for owner process...
.process /p /r fffffa8013177c10

                                    

THREAD fffffa801f3a3bb0  Cid 4b4c.5fec  Teb: 000000007efaa000 Win32Thread: fffff900c1efad50 WAIT: (UserRequest) UserMode Non-Alertable
    fffffa8021ce4590  NotificationEvent
    fffffa801f3a3c68  NotificationTimer
Not impersonating
DeviceMap                 fffff8801b551720
Owning Process            fffffa8013177c10       Image:         application.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      14066428       Ticks: 301 (0:00:00:04.695)
Context Switch Count      248                 LargeStack
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address mscorwks!Thread::intermediateThreadProc (0x00000000733853b3)
Stack Init fffffa60190e5db0 Current fffffa60190e5940
Base fffffa60190e6000 Limit fffffa60190df000 Call 0
Priority 11 BasePriority 10 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`190e5980 fffff800`01cba0fa nt!KiSwapContext+0x7f
fffffa60`190e5ac0 fffff800`01caedab nt!KiSwapThread+0x13a
fffffa60`190e5b30 fffff800`01f1d608 nt!KeWaitForSingleObject+0x2cb
fffffa60`190e5bc0 fffff800`01cb7973 nt!NtWaitForSingleObject+0x98
fffffa60`190e5c20 00000000`75183d09 nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffffa60`190e5c20)
00000000`069ef118 00000000`75183b06 wow64cpu!CpupSyscallStub+0x9
00000000`069ef120 00000000`74f8ab46 wow64cpu!Thunk0ArgReloadState+0x1a
00000000`069ef190 00000000`74f8a14c wow64!RunCpuSimulation+0xa
00000000`069ef1c0 00000000`771605a8 wow64!Wow64LdrpInitialize+0x4b4
00000000`069ef720 00000000`771168de ntdll! ?? ::FNODOBFM::`string'+0x20aa1
00000000`069ef7d0 00000000`00000000 ntdll!LdrInitializeThunk+0xe

.process /p /r 0
Implicit thread is now fffffa80`1f3a3bb0
WARNING: WOW context retrieval requires
switching to the thread's process context.
Use .process /p fffffa80`1f6b2990 to switch back.
Implicit process is now fffffa80`13177c10
x86 context set
Loading Kernel Symbols
Loading User Symbols
Loading unloaded module list
Loading Wow64 Symbols
ChildEBP RetAddr
06aefc68 76921270 ntdll_772b0000!ZwWaitForSingleObject+0x15
06aefcd8 7328c639 kernel32!WaitForSingleObjectEx+0xbe
06aefd1c 7328c56f mscorwks!PEImage::LoadImage+0x1af
06aefd6c 7328c58e mscorwks!CLREvent::WaitEx+0x117
06aefd80 733770fb mscorwks!CLREvent::Wait+0x17
06aefe00 73377589 mscorwks!ThreadpoolMgr::SafeWait+0x73
06aefe64 733853f9 mscorwks!ThreadpoolMgr::WorkerThreadStart+0x11c
06aeff88 7699eccb mscorwks!Thread::intermediateThreadProc+0x49
06aeff94 7732d24d kernel32!BaseThreadInitThunk+0xe
06aeffd4 7732d45f ntdll_772b0000!__RtlUserThreadStart+0x23
06aeffec 00000000 ntdll_772b0000!_RtlUserThreadStart+0x1b
Effective machine: x64 (AMD64)

[...]

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

10 Common Mistakes in Memory Analysis (Part 7)

Monday, February 8th, 2010

Another common mistake I observe is relying on what debuggers report without double-checking. Present day debuggers, like WinDbg or GDB, are symbol-driven, they do not possess much of that semantic knowledge that a human debugger has. Also, it is better to report more than less: what is irrelevant can be skipped over by a skilled memory analyst but what looks suspicious to the problem at hand shall be double-checked to see if it is not coincidental. One example we consider here is Coincidental Symbolic Information

An application is frequently crashing. The process memory dump file shows only one thread left inside without any exception handling frames. In order to hypothesize about the probable cause the thread raw stack data is analyzed. It shows a few C++ STL calls with a custom smart pointer class and memory allocator like this:

app!std::vector<SmartPtr<ClassA>, std::allocator<SmartPtr<ClassA> > >::operator[]+

WinDbg !analyze-v command output points to this code:

FOLLOWUP_IP:
app!std::bad_alloc::~bad_alloc <PERF> (app+0x0)+0
00400000 4d  dec     ebp

Raw stack data contains a few symbolic references to bad_alloc destructor too:

[...]
0012f9c0  00000100
0012f9c4  00400100 app!std::bad_alloc::~bad_alloc <PERF> (app+0x100)
0012f9c8  00000000
0012f9cc  0012f9b4
0012f9d0  00484488 app!_NULL_IMPORT_DESCRIPTOR+0x1984
0012f9d4  0012fa8c
0012f9d8  7c828290 ntdll!_except_handler3
0012f9dc  0012fa3c
0012f9e0  7c82b04a ntdll!RtlImageNtHeaderEx+0xee
0012f9e4  00482f08 app!_NULL_IMPORT_DESCRIPTOR+0x404
0012f9e8  00151ed0
0012f9ec  00484c1e app!_NULL_IMPORT_DESCRIPTOR+0x211a
0012f9f0  00000100
0012f9f4  00400100 app!std::bad_alloc::~bad_alloc <PERF> (app+0x100)
[...]

By linking all these three pieces together an engineer hypothesized that the cause of failure is memory allocation. However, careful analysis reveals all of them as a coincidental symbolic information and renders hypothesis much less plausible:

1.  The address of app!std::bad_alloc::~bad_alloc is 00400000 which coincides with the start of the main application module:

0:000> lm a 00400000
start    end        module name
00400000 004c4000   app    (no symbols)

As a consequence, its assembly language code makes no sense:

0:000> u 00400000
app:
00400000 4d              dec     ebp
00400001 5a              pop     edx
00400002 90              nop
00400003 0003            add     byte ptr [ebx],al
00400005 0000            add     byte ptr [eax],al
00400007 000400          add     byte ptr [eax+eax],al
0040000a 0000            add     byte ptr [eax],al
0040000c ff              ???

2. All std::vector references are in fact fragments of a UNICODE string that can be dumped using du command:

[...]
0012ef14  00430056 app!std::vector<SmartPtr<ClassA>, std::allocator<SmartPtr<ClassA> > >::operator[]+0x16
0012ef18  00300038
0012ef1c  0043002e app!std::vector<SmartPtr<ClassA>, std::allocator<SmartPtr<ClassA> > >::size+0x1
[...]

0:000> du 0012ef14 l6
0012ef14  "VC80.C"

3. Raw stack data references to bad_alloc destructor are still module addresses in disguise, 00400100 or app+0×100, with nonsense assembly code:

0:000> u 00400100
app+0x100:
00400100 50              push    eax
00400101 45              inc     ebp
00400102 0000            add     byte ptr [eax],al
00400104 4c              dec     esp
00400105 010500571aac    add     dword ptr ds:[0AC1A5700h],eax
0040010b 4a              dec     edx
0040010c 0000            add     byte ptr [eax],al
0040010e 0000            add     byte ptr [eax],al

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Demystifying first-chance exceptions (Part 2)

Thursday, February 4th, 2010

Sometimes we are not interested in first-chance exceptions as in the previous part but are interested in only second-chance exceptions to be sure that they were not handled as a part of an implementation design. Some tools like ADPlus can save dump files for both debugger events but I was asked to explain the difference between the first- and second-chance exceptions on W2K3 system where NTSD debugger was used to attach to a service process and save a dump. Initially the following command was used:

C:\> ntsd -psn ServiceA -noio -g -c ".dump /ma /u C:\UserDumps\ServiceA; q"

The dump was saved and analyzed. An engineer then decided that a second-chance exception dump file was needed for confirmation of an unhandled exception (because it was perceived that a postmortem debugger wasn’t saving any crash dumps) and requested to use the same command but with an -x switch that disables first-chance exception break in a debugger:

C:\> ntsd -psn ServiceA -noio -g -x -c “.dump /ma /u C:\UserDumps\ServiceA; q”

Note that q command terminates the debuggee so it was also advised to use qd to detach NTSD and let the service die naturally.  

Two different possible exception memory dumps and the third possibility of a postmortem memory dump already complicates the picture not counting possible process-dumper-in-the-middle memory dumps that can be saved by userdump.exe if there is any exception dialog between the first- and second-chance exception processing. So I created two “Time Arrow” diagrams aiming to depict two exception scenarios using TestDefaultDebugger tool and the following simplified commands on x64 W2K3 system:

C:\> ntsd -pn TestDefaultDebugger64.exe -g -c ".dump /ma /u C:\UserDumps\TDD; qd"

and 

C:\> ntsd -pn TestDefaultDebugger64.exe -g -x -c “.dump /ma /u C:\UserDumps\TDD; qd”

Also drwtsn32.exe was set as a default postmortem debugger (but we could also use CDB, WinDbg or any other process dumper as shown in Vista example). 

The first diagram shows that an attached debugger (a screenshot of WinDbg is used in place of NTSD for both diagrams) receives a first-chance debugger event and saves a process memory dump, then detaches and the previous debuggee process continues looking for exception handlers and not finding anyone launches a postmortem debugger and, as a result, another dump is saved too:

We can double check the first-chance exception dump file to see if it is the right one. Indeed, there are no signs of exception processing on thread raw stack:

This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(e50.e54): Access violation - code c0000005 (first/second chance not available)
*** ERROR: Module load completed but symbols could not be loaded for TestDefaultDebugger64.exe
TestDefaultDebugger64+0×1570:
00000000`00401570 c704250000000000000000 mov dword ptr [0],0 ds:00000000`00000000=????????

0:000> !teb
TEB at 000007fffffde000
    ExceptionList:        0000000000000000
    StackBase:            0000000000130000
    StackLimit:           000000000012c000
    SubSystemTib:         0000000000000000
    FiberData:            0000000000001e00
    ArbitraryUserPointer: 0000000000000000
    Self:                 000007fffffde000
    EnvironmentPointer:   0000000000000000
    ClientId:             0000000000000e50 . 0000000000000e54
    RpcHandle:            0000000000000000
    Tls Storage:          0000000000000000
    PEB Address:          000007fffffda000
    LastErrorValue:       0
    LastStatusValue:      c0000023
    Count Owned Locks:    0
    HardErrorMode:        0

0:000> dqs 000000000012c000 0000000000130000
00000000`0012c000  00000000`00000000
00000000`0012c008  00000000`00000000
00000000`0012c010  00000000`00000000
00000000`0012c018  00000000`00000000

[... no c0000005 ...]

00000000`0012ff60  00000000`00000000
00000000`0012ff68  00000000`00000000
00000000`0012ff70  00000000`00000000
00000000`0012ff78  00000000`77d596ac kernel32!BaseProcessStart+0x29
00000000`0012ff80  00000000`00000000
00000000`0012ff88  00000000`00000000
00000000`0012ff90  00000000`00000000
00000000`0012ff98  00000000`00000000
00000000`0012ffa0  00000000`00000000
00000000`0012ffa8  00000000`00000000
00000000`0012ffb0  00000000`004148d0 TestDefaultDebugger64+0x148d0
00000000`0012ffb8  00000000`00000000
00000000`0012ffc0  00000000`00000000
00000000`0012ffc8  00000000`00000000
00000000`0012ffd0  00000000`00000000
00000000`0012ffd8  00000000`00000000
00000000`0012ffe0  00000000`00000000
00000000`0012ffe8  00000000`00000000
00000000`0012fff0  00000000`00000000
00000000`0012fff8  00000000`00000000
00000000`00130000  00000020`78746341

The second diagram shows that an attached debugger ignores a first-chance debugger event but saves  a process memory dump upon a second-chance exception event after the debugee can’t find any handlers, then detaches and the previous debuggee process launches a postmortem debugger to save another postmortem memory dump:

In both second-chance and postmortem process memory dump files we can find c0000005 exception code on thread raw stack.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Native Script Debugging

Monday, February 1st, 2010

While testing a WinDbg script for the CARE system (the script enumerates files on a Windows PC and processes memory dumps to generate a log file with the output of debugger commands) I found that after successful processing of many files the next launched WinDbg instance suddenly showed this message box:

To find out, I attached another WinDbg instance to its process in order to examine the real command line. In this small case study instead of using kb WinDbg command to show a stack trace and its arguments I employ kn, .frame and kb <lines> commands for visual clarity and to illustrate strack trace frame navigation. In the failed WinDbg instance that had just started we see only one thread showing Message Box pattern:

0:000> ~*kn

.  0  Id: dc8.fb4 Suspend: 1 Teb: 000007ff`fffdc000 Unfrozen
 # Child-SP          RetAddr           Call Site
00 00000000`0025d4b8 00000000`76fc5118 USER32!NtUserWaitMessage+0xa
01 00000000`0025d4c0 00000000`76fc5770 USER32!DialogBox2+0x261
02 00000000`0025d540 00000000`7701000d USER32!InternalDialogBox+0x134
03 00000000`0025d5a0 00000000`7700f2b8 USER32!SoftModalMessageBox+0x9fb
04 00000000`0025d6d0 00000000`7700eb17 USER32!MessageBoxWorker+0x314
05 00000000`0025d890 00000000`7700ea10 USER32!MessageBoxTimeoutW+0xb3
06 00000000`0025d950 00000001`3f9016a6 USER32!MessageBoxW+0x4c
07 00000000`0025d990 00000001`3f90175c WinDbg!TextMsgBox+0x96
08 00000000`0025d9d0 00000001`3f9017d7 WinDbg!FormatMsgBoxV+0x9c
09 00000000`0025dbe0 00000001`3f9075c7 WinDbg!InfoBox+0x37
0a 00000000`0025dc20 00000001`3f9084f7 WinDbg!ParseCommandLine+0x1a57
0b 00000000`0025dcc0 00000001`3f913739 WinDbg!wmain+0×287
0c 00000000`0025fd80 00000000`7708be3d WinDbg!_CxxFrameHandler3+0×291
0d 00000000`0025fdc0 00000000`771c6a51 kernel32!BaseThreadInitThunk+0xd
0e 00000000`0025fdf0 00000000`00000000 ntdll!RtlUserThreadStart+0×1d

We see the frame # 0b contains the return address of wmain function (starting point of execution of UNICODE C/C++ programs) that has this prototype:

int wmain(int argc, wchar_t *argv[], wchar_t *envp[]);

We switch to that frame to examine its first 3 parameters and use kb command that shows stack traces starting from the current frame (we are interested in the top stack trace line only):

0:000> .frame b
0b 00000000`0025dcc0 00000001`3f913739 WinDbg!wmain+0×287

0:000> kb 1
RetAddr           : Args to Child                                                           : Call Site
00000001`3f913739 : 00000000`0000000c 00000000`00278b60 00000000`00279e10 000007de`a4ecc920 : WinDbg!wmain+0×287

Because the function prototype shows the second function parameter as an array of wide character null-terminated strings we use dpu command to dump them. We also note that we have only 0xc array members and use this as the length argument for dpu:

0:000> dpu 00000000`00278b60 Lc
00000000`00278b60  00000000`00278bc8 “C:\Program Files\Debugging Tools for Windows (x64)\WinD”
00000000`00278b68  00000000`00278c44 “-y”
00000000`00278b70  00000000`00278c4a “srv*c:\ms*http://msdl.microsoft.com/download/symbols;sr”
00000000`00278b78  00000000`00278d0c “-z”
00000000`00278b80  00000000`00278d12 “C:\MemoryDumps\CST\ColorimetricTracing”
00000000`00278b88  00000000`00278d60 “(4).DMP”

00000000`00278b90  00000000`00278d70 “-c”
00000000`00278b98  00000000`00278d76 “$$>a<DebuggerLogs.txt;q”
00000000`00278ba0  00000000`00278da6 “-Q”
00000000`00278ba8  00000000`00278dac “-QS”
00000000`00278bb0  00000000`00278db4 “-QY”
00000000`00278bb8  00000000`00278dbc “-QSY”

We see in the output above that “C:\MemoryDumps\CST\ColorimetricTracing” and “(4).DMP” strings were probably split from one file name “C:\MemoryDumps\CST\ColorimetricTracing (4).DMP” and this means that we forgot to enclose the file name parameter in double quotation marks when passing it from VB script to WinDbg.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Bugtation No.110

Sunday, January 31st, 2010

Debugging at large. Remember those bugs from The Day Earth Stood Still movie that were nicely deactivated at once? Remember Nobel Laureate Professor Barnhardt was threading with Klaatu over the correct version of General Relativity on a blackboard and then at once realized that he was talking to an alien? His next phrase was the one that I repeat every day (and I also listen to Bach every day):

“I have so many questions to ask” this memory dump.

The Day the Earth Stood Still (2008 film)

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Mode-independent WinDbg scripts

Friday, January 29th, 2010

These are scripts that can be run without modification in both user and kernel modes to collect information from user and kernel spaces. For example, we want to collect thread stack traces for CARE system and we have different kinds of memory dumps stored on our computer. There is no a single command that can show stack traces for all threads in a process and kernel / complete memory dumps. However, we can combine separate mode-sensitive commands in one script:

.kframes 1000
!for_each_thread !thread @#Thread 1f
~*kv

The first command eliminates the common mistake of truncated traces. The second command fails for process user memory dumps but shows full 3-parameter stack trace for every thread in a system including user space thread stack counterpart for complete memory dumps after switching to the appropriate process context if any. The third command fails for kernel and complete memory dumps but lists stack traces for each thread in a process user memory dump. Therefore, we have just one script that we can run against all memory dumps.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -  

Debugger’s Screen Resolution

Wednesday, January 27th, 2010

What screen resolutions do debuggers use? Google analytics provides statistics for 2009. 1,071 different screen resolutions were used (I guess this diversity comes from multi-monitor configurations and PDA) with top 10:

Clearly old 800×600 is in minority today. There were lucky debuggers with 5120×1024 (128-bit ready for wider stack traces?) and 3840×2100 (I need more book sales for that) and even someone with screen resolution 0×0 viewed the content 12 times.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Bug-sistential and Bug-sistentialism (Debugging Slang, Part 6)

Tuesday, January 26th, 2010

Bug-sistential - pertaining to existing bugs
Bug-sistentialism - a pessimistic outlook about the existence of bugs

Examples: What a bug-sistential problem we have to solve here! Pure bug-sistentialism!

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Plans for The Year of Dump Analysis

Monday, January 18th, 2010

After exciting results of  the previous year of debugging it is time to announce modest plans for this year, 0×7DA:

Release the first beta version of EasyDbg

Release the first beta version of CARE (Crash Analysis Report Environment) for a pattern-driven debugger log analyzer with standards for structured audience-driven reports

Release the first beta version of STARE (Software Trace Analysis Report Environment) for a pattern-driven software trace analyzer with corresponding standards for structured audience-driven reports

Publish the following books on dump analysis that address different audiences (general users, system administrators, support and escalation engineers, testers, software engineers, security and software defect researchers):

Windows Debugging Notebook
Crash Dump Analysis for System Administrators and Support Engineers
- Memory Dump Analysis Anthology, Volume 4
- Memory Dump Analysis Anthology, Volume 5
- Memory Dump Analysis Anthology Color Supplement
- Principles of Memory Dump Analysis
- My Computer Crashes and Freezes: A Non-technical Guide to Software and Hardware Errors
- Linux, FreeBSD and Mac OS X Debugging: Practical Foundations
- Encyclopedia of Crash Dump Analysis Patterns
- WinDbg In Use: Debugging Exercises

Publish articles related to memory dump analysis in Debugged! magazine

Update WinDbg Poster and Cards

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

MDAAV1 and WDPF are the Most Gifted today

Friday, January 15th, 2010

Just noticed on Amazon tabs:

What is so special today? I come back to check again on 14th of February :-)

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

The Year of Debugging in Retrospection

Thursday, January 14th, 2010

The Year of Debugging, 0×7D9, was a remarkable year for DumpAnalysis.org. Here is the list of achievements to report:

- Software Trace Analysis as a new discipline with its own set of patterns

- Unification of Memory Dump Analysis with Software Trace Analysis (DA+TA)

- New computer memory dump-based art movements: Opcodism and Physicalist Art

- Discovery of 3D computer memory visualization techniques

- Establishing Software Maintenance Institute

- Broadening software fault injection as Software Defect Construction discipline

- Establishing a new profession of a Software Defect Researcher

- Starting ambitious Dictionary of Debugging

- Publishing Windows Debugging: Practical Foundations book

- Publishing the first x86-free Windows debugging book: x64 Windows Debugging: Practical Foundations

- Establishing the new debugging magazine: Debugged! MZ/PE

- Publishing Memory Dump Analysis Anthology, Volume 3

- Cooperation with OpenTask to promote First Fault Software Problem Solving book

- Establishing Debugging Expert(s) Magazine Online

- Creating the first development process for debugging and software troubleshooting tools: RADII

- Publishing the first pattern-driven memory dump analysis troubleshooting methodology as a foundation for software debugging

- Proposal for an International Memory Analysts and Debuggers Day

- Almost completed Windows Debugging Notebook to be published soon

Now DumpAnalysis.org focuses on The Year of Dump Analysis, 0×7DA, as a foundation for the forthcoming debugging decade and reveals future plans this weekend.

I’m sure that many other organizations and individuals have no less remarkable accomplishments to report for 2009. I promise to track down and write about some of them in the forthcoming book:

The Science of Dr. Watson: An Illustrated History of Debugging (ISBN: 978-1906717070)

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -

Crash, Core and Memory Dumps in Science Fiction and Fantasy (Part 1)

Sunday, January 10th, 2010

Being an aspiring SF delayed-writer I was curious about the usage of memory dump concept in science fiction. Here’s a selection of sentence fragments that give some picture (a few are from fiction not SF) and I plan to analyze it further in another part. Some phrases are funny for me but you decide which of them for yourself (I even ordered one fiction and two SF books from the list below):

A Fire Upon The Deep (Zones of Thought) by Vernor Vinge

“the environment programs will likely have a bizarre crash-atmosphere dump, thermal runaway, anything.”

A Nepenthean Solution by Rod Rogers

“Their computers started misbehaving very badly. Random data dumps, crashes, disk wipes, that type of thing.”

Sex, Drugs, & Rock & Roll! by Charles A Brobst

“it’s possible to dump bios and crash the systems.”

Down and Out in the Magic Kingdom by Cory Doctorow

“Just switch on guest access and I’ll core-dump it to you. It’s wild.”

Interface by Neal Stephenson and J. Frederick George

“We’re going to do a core dump on this whole night. Zeldo said ‘Analyze it’”

Champions of the Force (Star Wars: The Jedi Academy Trilogy, Volume 3) by Kevin J. Anderson

“Complete core dump of all the Maw’s backup computer files.”

The Mandalorian Armor (Star Wars: The Bounty Hunter Wars, Book 1) by K.W. Jeter

“he could do a core dump and take everything back to his own ship”

More Than Honor (Honor Harrington) by David Weber

“Rerouting, cross-connections, garbled text, crossed order-response loops, spontaneous memory core dumps … Nothing working the way it should.”

Futures from Nature by Henry Gee

“My toaster had a core dump and wouldn’t boot up”

Endgame: A Novel (Doom #4) by Dafydd ab Hugh and Brad Linaweaver

“The Data Pastiche did not give us sufficient information. We must study the core-dump.”

Newton’s Wake: A Space Opera by Ken MacLeod

“a big clue, but not definitive. So we took a core dump.”

Mindstar Rising by Peter F. Hamilton

“O’Donal fed the Trojan an activation code keyed to the core’s dump order.”

Worlds in Collision: Star Trek (Star Trek: the Original Series) and Memory Prime (Star Trek, No 42) by Judith Reeves-Stevens and Garfield Reeves-Stevens

“the interface team will commence an unscheduled emergency core dump as an essential test of the system’s backup integrity.”

Spinward Fringe Resurrection And Awakening by Randolph Lalonde

“I’m going to find one of the computer cores and dump you inside.”

Nothing Sacred: A Novel by Tom Flynn

“‘Ship’s thought engines are in core dump,’ Hinsin cried. ‘The Onesie’s probing them aggressively. They’re spewing information’”

X-Universe Volume One by Darren Astles and Steve Miller

“a core-dump and re-write of the Al algorithms”

Nshalain Troubles: The Return (Volume 3) by Bob Horton

“If necessary we could even do a core dump through a transposer link”

Second Chances by Susan Shwartz

“He could do a core dump in his sleep, but never had.”

Soul of the Algorithm by Norbert Weissinger

“By the way, we had a core dump on PIDs Two thirty- eight and Two thirty-nine.”

God Behind the Firewall by Anirban Ray

“The operating system kernel had crashed - it was a core dump. I wondered what kind of an operating system it was”

A Real Boy by Heather Breo

“unit was connected to a large processor so that a core dump could be performed. This would include all accrued memory.”

A Chip Called Wanda by J. L. Kerry

“the system computer until lie could crash it, initiating a core dump, in which the horrified system processor would frantically write important data to several files during its death throes.”

The Enemy Papers by Barry B Longyear

“began setting up the sequence to dump the memory cores.”

Chaos and Rage by Frank Tinsman

“I’m doing a core dump and it won’t even give me a status bar”

Alien Parable by Khezla Durr

“When the information came through it was like the core dump on a computer. It came through so fast”

ANIMA: a novel about Second Life by Dalian Hansen

“You have to go in for another complete core dump.”

Hammerjack by Marc D. Giller

“memory dump was in progress. The core was wiping itself clean”

HeadSpace by Paul Barrows

“eyes staring into the virtual gateway of the RAM dump core, head lolling involuntarily as his fingers worked the mechanism.”

Blood and Fire by David Gerrold

“We’ll dump a copy of the core into one of our transmitters and let them decode it”

Dragon Drive: A Comedia Mundana: Volume 1: The Finger of God by Wayne Richards

“by telephone lines, not yet, but we can send him core dumps via radio, over the comsat links, can’t we?”

The Armies of Memory (Thousand Cultures) by John Barnes

“Shan was dumping my short-term memory into his”

The Ghost Brigades by John Scalzi

“his sudden memory dump”

The Ultimate Hitchhiker’s Guide to the Galaxy by Douglas Adams

“He pulled out a small memory dump module”

Pandora’s Star by Peter F. Hamilton

“You left with him four days after your last memory dump in the Kirova Clinic’s secure store.”

Marque and Reprisal (Vatta’s War) by Elizabeth Moon

“It was bad they had to do a memory dump off my implant”

Star Strike (The Inheritance Trilogy, Book 1) by Ian Douglas

“They wouldn’t need to ask her questions or elicit her cooperation; all they’d need to do was pull a full memory dump.”

“‘Sarha, how’s the memory dump coming on?’ ‘No problems, Joshua. The bitek array is accepting’”

Spin State by Chris Moriarty

“a mere memory dump an interactive tutorial triggered by her entry into the memory palace”

Foundation and Chaos: The Second Foundation Trilogy (Foundation Trilogy Series) by Greg Bear

“With Daneel’s frequent memory dumps and adjustments,”

Sphere by Michael Crichton

“It’s got to be a memory dump from somewhere inside our own computer system.”

A Time to Be Born (Star Trek The Next Generation) by John Vornholt

“His memory dump was almost at the present day”

Undertow by Elizabeth Bear

“memory to dump yet and Security will download whatever’s in there”

Kiln People (The Kiln Books) by David Brin

“Irene here has been duplicating so heavily, taking full memory dumps from every ditto she makes, that she’s reached a limit”

Quarantine by Greg Egan

“it isn’t present in any of my stolen memory dumps.”

The Ship Who Searched (The Ship Series) by Anne McCaffrey and Mercedes Lackey

“She triggered memory-dump, and everything came over in compressed mode”

The Callahan Chronicals by Spider Robinson

“file memory dump, sending information in a block rather than bit by bit”

The Wellstone by Wil McCarthy

“And with the Palace Guard’s memory dump you’re the most famous of all”

Whole Wide World by Paul McAuley

“I can reboot and rebuild him from the last memory dump, but it’ll take a little while.”

Pashazade by Jon Courtenay Grimwood

“digiLux so old it had a separate flash unit and came minus a removable memory dump which was where Dr Dee came in”

The Great Book of Amber: The Complete Amber Chronicles, 1-10 (Chronicles of Amber) by Roger Zelazny

“You can’t dump its memory or kill its power from a remote terminal.”

The Best of All Possible Wars by Larry Niven

“they’ll follow it come core-collapse or memory dump;”

The Worthing Saga by Orson Scott Card

“We dump the memories back into your head as soon as you come out”

Playgrounds of the Mind by Larry Niven

“Signal for a memory dump, see what can be retrieved.”

Alien Taste (Ukiah Oregon, Book 1) by Wen Spencer

“To grow that much, the mouse would have to dump its memory storage.”

Firedance by Steven Barnes

“My last memory dump was before the raid”

Worldmakers: SF Adventures in Terraforming by Gardner Dozois

“I’d search memory dumps to find where souls might be kept”

Glasshouse by Charles Stross

“I emigrated to Zemlya right after my previous memory dump.”

Two to the Fifth (Xanth) by Piers Anthony

“It’s a real memory dump.”

Dreaming Down-Under by Jack Dann and Janeen Webb

“That’s what’s inhibiting the near-memory dump.”

Before the Storm (Star Wars: The Black Fleet Crisis, Book 1) by Michael P. Kube-Mcdowell

“Droids will dump their memory data under sensor-torture.”

WebMage (Ravirn, Book 1) by Kelly McCullough

“That’s probably the upload cycle, when it dumps its memory back to the server.”

Midnight at the Well of Souls by Jack L. Chalker

“You forgot to dump the computer memory when you closed up.”

Redrobe by Jon Courtenay Grimwood

“the one who purchased some kid to use as a memory dump”

X-Men - The Last Stand by Chris Claremont

“No sign whatsoever that been wounded If only he could dump the sense memories of those hurts as”

Metaplanetary: A Novel of Interplanetary Civil War by Tony Daniel

“Every day, to dump her memories in the form of a sentence or two”

The Purple Spacebunny (Volume 02) by Clarence E. Shellito II

“In computer terms, he was doing a memory dump and compressing the math in his mind to lock it”

This Place Only by Walter G. Klimczak

“The first stage included a memory splice. The second a partial data purge. A memory dump.”

The Worldwrights by Max Grant

“I was able to pick up some of their history while the memory dump went through me on its way to the manekine.”

Alien Revelation by Tony Ruggiero

“He thought of it as a memory dump and as a form of therapy.”

Genetic Suicide by James Cooper

“Yes, think of it as a selective memory dump.”

A Great Circle: The Mayfield Trilogy by Reynolds Price

“again as if to gouge one more memorial in this memory dump.”

Cross Purposes by Gary C. Gibson

“facsimile clones built in hurry up growth tanks. Electron-scripted memory dumps gave them something to think, A list personality and entertainment”

Shanghai Dream by Sahr Johnny

“The memory dump cuts to the front of the school.”

Elysian Fields by Drew Dale Daniel Bryenton

“which led to a biolab full of clone tanks and memory-dump modules.”

Cubicle Farm Fantasy: An Indian IT worker’s dream about escaping the rat race by Ranjit Sankar

“reading memory dumps and providing technical leadership to a bunch of bozos”

Infinity Plus by Keith Brooke and Nick Gevers

“A simula plus full memory dump will tie up most of my processing power.”

Sin’s Doorway and Other Ominous Entrances: The Selected Stories of Manly Wade Wellman (Volume 4) by Manly Wade Wellman

“consciously used me as a dump for his memories.”

ReBody by Clive Warner

“No other solution. EMP damages my network too. I can dump memory into magnetic stores, isolate all processors”

The Light by J Powers

“On the monitor screen flashed dumps of memory, neural net models, machine code, the innermost workings of the supercomputer operating system”

Fools’ Experiments by Edward M. Lerner

“I’m ready to stop reading these damn memory dumps. Let the little imps go back to it.”

Echoes of Earth by Sean Williams and Shane Dix

“to accept her final memory dump if she did.”

Fallen Host by Lyda Morehouse

“I had all my memories ready to dump, and I still couldn’t do it. Then the idea hit me”

LifeQuest: Dozens of Stories about Cryonics, Uploading, and other Transhuman Adventures by Fred Chamberlain, Linda Chamberlain, Thomas Donaldson, and Lee Corbin

“Map their memory centers, dump the data in a neuro-simulator and use artificial intelligence to to index topics”

Redemption Ark (Revelation Space) by Alastair Reynolds

“would make it so much easier if he could just dump his memories directly-but the other Conjoiner ’s neural blockades were secure.”

An Isaac Asimov Robot Mystery: Mirage (Isaac Asimov’s Robot Mystery) by Mark W. Tiedemann

“I want a memory dump set up, too-we need to download the RI for study.”

How Precious Was That While by Piers Anthony

“you don’t want to clutter your memory with them. For example, if that person was your sibling, you can dump that memory right there.”

Tangent by Robert G. Ferrell

“figure out some way of getting at least one full memory dump from her.”

THE FLIGHT of the SOLAR ARCHANGEL by Rod Rogers

“Yeah, yeah, yeah. All right, dump memory and we’ll scan it line by line.”

Death Match by Lincoln Child

“It appears to be a successful memory dump”

Presentations Plus by David A. Peoples

“first two minutes. Then we stand up we go to memory location ‘x,’ open our mouth and do a ‘memory dump’.”

Full Circle by Danielle Steel

“Dump the memory. And move on.”

MindFlossing: 100% Pure From Concentrate by Jakob Wahlberg

“Did you ever do a memory dump and debug?”

Love’s Illusions by Ceria Mackonvitz and Alina Ardeleanu Igna

“I need a brain dump. A memory dump. To clear my head up. Clear my head away.”

Harmonescape by Rick Leinheuser

“my jittery smile masking the memory dump going on behind my probing eyes. The jig was up.”

The Micah Files by Robert Pirie

“It sounds like you’re doing a memory dump. Robert continued assuring her of its relevancy.”

Journey Out From The Mundane Shell by Anthony Doyle

“we recognize a place in time, it has become a memory dump,”

Humour the Computer by Andrew J. Davison

“A memory dump follows.”

No Outward Sign by Bill Neugent

“A memory dump, in case you hit any self-destruct routines.”

Hazard 666: A New Meaning for Terror by Paul Landry

“see if he could preoccupy the robot so it would dump memory and not remember what it did.”

Biotechnology Is Murder: A Ben Candidi Mystery (Ben Candidi Mysteries) by Dirk Wyle

“Careful, you don’t want to dump the memory.”

Omaha by Caoimhghin Ó Catháin

“Let me dump its memory then you can tell me which numbers are drug related.”

Satan’s Touch by Forrest Carlyle

“Just a dump of system memory so I can debug.”

You Have to Be Careful in the Land of the Free by James Kelman

“I had a bus and a plane to catch, and memories to dump; memories to dump.”

The Bug by Ellen Ullman

“unconditional program death, producing no core file, no dump of the program’s memory state.”

Evening Song: Òran Feasgair by Randolph Waugh

“a law that would make a memory dump mandatory, you would have access to history in its entirety”

Storm Killer by Benjamin Blue

“the technician had commanded the computer to freeze its memory and not reuse any memory that had recently been used and released back to the system. The tech had done a copy dump of the entire memory and he’s now manually reviewing the contents of each piece of frozen storage”

remember to BLINK by Jason Heim

“I print out the memory dump, which uses up four reams of paper.”

Bystander by Maksim Gorky and Bernard G. Guerney

“Come, now, Tanya, search a bit in the dump of your memory.”

- Dmitry Vostokov @ DumpAnalysis.org -

Top 10 “Most Gifted” and “Most Wished For” Debugging and Assembly Language Books

Sunday, January 10th, 2010

Just noticed that Amazon introduced additional daily updated tabs for book categories. MDAA volumes are in top 10 ”Most Gifted” and “Most Wished For” Debugging and Assembly Language titles (today). Volume 3 is featured as a Hot New Release:

I assume ”Most Gifted” is about “gift wrapping” when you order a book :-)

- Dmitry Vostokov @ DumpAnalysis.org -