Bugchecks: SYSTEM_THREAD_EXCEPTION_NOT_HANDLED
Another bugcheck that is similar to KMODE_EXCEPTION_NOT_HANDLED and KERNEL_MODE_EXCEPTION_NOT_HANDLED is SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (0×7E).
This bugcheck happens when you have an exception in a system thread and there is no exception handler to catch it, i.e. no __try/__except. System threads are created by calling PsCreateSystemThread function. Here is its description from DDK:
The PsCreateSystemThread routine creates a system thread that executes in kernel mode and returns a handle for the thread.
By default PspUnhandledExceptionInSystemThread function is set as a default exception handler and its purpose is to call KeBugCheckEx.
The typical call stack in dumps with 7E bugcheck is:
1: kd> k
ChildEBP RetAddr
f70703cc 809a1eb2 nt!KeBugCheckEx+0x1b (FPO: [Non-Fpo])
f70703e8 80964a94 nt!PspUnhandledExceptionInSystemThread+0x1a
f7070ddc 80841a96 nt!PspSystemThreadStartup+0x56
00000000 00000000 nt!KiThreadStartup+0x16
To see how this bugcheck is generated from processor trap we need to look at raw stack. Let’s look at some example. !analyze -v command gives us the following output:
SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e)
This is a very common bugcheck. Usually the exception address pinpoints the driver/function that caused the problem. Always note this address as well as the link date of the driver/image that contains this address.
Arguments:
Arg1: 80000003, The exception code that was not handled
Arg2: f69d9dd7, The address that the exception occurred at
Arg3: f70708c0, Exception Record Address
Arg4: f70705bc, Context Record Address
EXCEPTION_RECORD: f70708c0 -- (.exr fffffffff70708c0)
ExceptionAddress: f69d9dd7 (driver+0x00014dd7)
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 3
Parameter[0]: 00000000
Parameter[1]: 8a784020
Parameter[2]: 00000044
CONTEXT: f70705bc -- (.cxr fffffffff70705bc)
eax=00000001 ebx=00000032 ecx=8a37c000 edx=00000044 esi=8a37c000 edi=000000c7
eip=f69d9dd7 esp=f7070988 ebp=00004000 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
driver+0x14dd7:
f69d9dd7 cc int 3
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
f7070998 f69dfbd1 80800000 00000000 8a37c000 driver+0x14dd7
00000000 00000000 00000000 00000000 00000000 driver+0x1abd1
We see that the thread encountered the breakpoint instruction and we also see that the call stack that led to breakpoint exception is incomplete. Here we must dump the raw stack data and try to reconstruct the stack manually. System threads are started with the execution of KiThreadStartup function. So let’s dump the stack starting from ESP register and up to some value, find startup function there and try to walk EBP chain:
1: kd> dds esp esp+1000
...
...
...
f7070a04 f7070a40
f7070a08 f71172ec NDIS!ndisMCommonHaltMiniport+0×375
f7070a0c 8a37c000
f7070a10 8a60f5c0
f7070a14 8a610748
f7070a18 8a610748
f7070a1c 00000058
f7070a20 00000005
f7070a24 00000004
f7070a28 f7527000
f7070a2c 00000685
f7070a30 f710943a NDIS!ndisMDummyIndicatePacket
f7070a34 00000000
f7070a38 8a610778
f7070a3c 00010748
f7070a40 f7070b74
f7070a44 f7117640 NDIS!ndisMHaltMiniport+0×21
f7070a48 8a610990
…
… (intermediate frames are omitted to save space)
…
f7070d7c e104a338
f7070d80 f7070dac
f7070d84 8083f72e nt!ExpWorkerThread+0xeb
f7070d88 894d0ed8
f7070d8c 00000000
f7070d90 8a784020
f7070d94 00000000
f7070d98 00000000
f7070d9c 00000000
f7070da0 00000001
f7070da4 00000000
f7070da8 808f0cb7 nt!PiWalkDeviceList
f7070dac f7070ddc
f7070db0 8092ccff nt!PspSystemThreadStartup+0×2e
f7070db4 894d0ed8
f7070db8 00000000
f7070dbc 00000000
f7070dc0 00000000
f7070dc4 f7070db8
f7070dc8 f7070410
f7070dcc ffffffff
f7070dd0 8083b9bc nt!_except_handler3
f7070dd4 808408f8 nt!ObWatchHandles+0×5f4
f7070dd8 00000000
f7070ddc 00000000
f7070de0 80841a96 nt!KiThreadStartup+0×16
f7070de4 8083f671 nt!ExpWorkerThread
The last EBP value we are able to get is f7070a04 and we can specify it to the extended version of k command together with ESP and EIP value of crash point:
1: kd> k L=f7070a04 f7070988 f69d9dd7
ChildEBP RetAddr
f7070998 f69dfbd1 driver+0x14dd7
f7070a40 f7117640 NDIS!ndisMCommonHaltMiniport+0x375
f7070a48 f711891a NDIS!ndisMHaltMiniport+0x21
f7070b74 f71196e5 NDIS!ndisPnPRemoveDevice+0x189
f7070ba4 8083f9d0 NDIS!ndisPnPDispatch+0x15d
f7070bb8 808f6a25 nt!IofCallDriver+0x45
f7070be4 808e20b5 nt!IopSynchronousCall+0xbe
f7070c38 8080beae nt!IopRemoveDevice+0x97
f7070c60 808e149b nt!IopRemoveLockedDeviceNode+0x160
f7070c78 808e18cc nt!IopDeleteLockedDeviceNode+0x50
f7070cac 808e1732 nt!IopDeleteLockedDeviceNodes+0x3f
f7070d40 808e19b6 nt!PiProcessQueryRemoveAndEject+0x7ad
f7070d5c 808e7879 nt!PiProcessTargetDeviceEvent+0x2a
f7070d80 8083f72e nt!PiWalkDeviceList+0x1d2
f7070dac 8092ccff nt!ExpWorkerThread+0xeb
f7070ddc 80841a96 nt!PspSystemThreadStartup+0x2e
00000000 00000000 nt!KiThreadStartup+0x16
This was the execution path before the exception. However when int 3 instruction was hit then processor generated a trap with interrupt vector 3 (4th entry in interrupt descriptor table, zero-based) and the corresponding function in IDT, KiTrap03, was called. Therefore we need to find this function on the same raw stack and try to build stack trace for our exception handling code path:
1: kd> dds esp esp+1000
f70703b4 0000007e
f70703b8 80000003
f70703bc f69d9dd7 driver+0x14dd7
f70703c0 f70708c0
f70703c4 f70705bc
f70703c8 00000000
f70703cc f70703e8
f70703d0 809a1eb2 nt!PspUnhandledExceptionInSystemThread+0x1a
f70703d4 0000007e
...
...
...
f7070418 f707043c
f707041c 8083b578 nt!ExecuteHandler2+0×26
f7070420 f70708c0
f7070424 f7070dcc
f7070428 f70705bc
f707042c f70704d8
f7070430 f7070894
f7070434 8083b58c nt!ExecuteHandler2+0×3a
f7070438 f7070dcc
f707043c f70704ec
f7070440 8083b54a nt!ExecuteHandler+0×24
f7070444 f70708c0
…
… (intermediate frames are omitted to save space)
…
f7070890 f7070410
f7070894 f7070dcc
f7070898 8083b9bc nt!_except_handler3
f707089c 80850c10 nt!`string’+0×10c
f70708a0 ffffffff
f70708a4 f7070914
f70708a8 808357a4 nt!CommonDispatchException+0×4a
f70708ac f70708c0
f70708b0 00000000
f70708b4 f7070914
f70708b8 00000000
f70708bc 00000001
f70708c0 80000003
f70708c4 00000000
f70708c8 00000000
f70708cc f69d9dd7 driver+0×14dd7
f70708d0 00000003
f70708d4 00000000
f70708d8 8a784020
f70708dc 00000044
f70708e0 ffffffff
f70708e4 00000001
f70708e8 f7737a7c
f70708ec f7070934
f70708f0 8083f164 nt!KeWaitForSingleObject+0×346
f70708f4 000000c7
f70708f8 00000000
f70708fc 00000031
f7070900 00000000
f7070904 f707091c
f7070908 80840569 nt!KeSetTimerEx+0×179
f707090c 000000c7
f7070910 80835f39 nt!KiTrap03+0xb0
f7070914 00004000
The last EBP value we are able to get is f7070418 so the following stack trace emerges albeit not accurate as it doesn’t show that KeBugCheckEx was called from PspUnhandledExceptionInSystemThread as can be seen from disassembly. However it does show that the main function that orchestrates stack unwinding is KiDispatchException:
1: kd> k L=f7070418
ChildEBP RetAddr
f7070418 8083b578 nt!KeBugCheckEx+0x1b
f707043c 8083b54a nt!ExecuteHandler2+0x26
f70704ec 80810664 nt!ExecuteHandler+0x24
f70708a4 808357a4 nt!KiDispatchException+0x131
f707090c 80835f39 nt!CommonDispatchException+0x4a
f707090c f69d9dd8 nt!KiTrap03+0xb0
1: kd> uf nt!PspUnhandledExceptionInSystemThread
nt!PspUnhandledExceptionInSystemThread:
809a1e98 8bff mov edi,edi
809a1e9a 55 push ebp
809a1e9b 8bec mov ebp,esp
809a1e9d 8b4d08 mov ecx,dword ptr [ebp+8]
809a1ea0 ff7104 push dword ptr [ecx+4]
809a1ea3 8b01 mov eax,dword ptr [ecx]
809a1ea5 50 push eax
809a1ea6 ff700c push dword ptr [eax+0Ch]
809a1ea9 ff30 push dword ptr [eax]
809a1eab 6a7e push 7Eh
809a1ead e8f197edff call nt!KeBugCheckEx (8087b6a3)
At the end to illustrate this bugcheck I created the following UML sequence diagram (trap processing that leads to KiDispatchException will be depicted in another post):

- Dmitry Vostokov -