[zz]Adventures In A 32-bit Minidump, Part 0
2010-05-03 21:44
363 查看
http://www.sevenforums.com/287662-post1.html
Yes, I realise it has "stacked", but how?!?
One of the items of information stored in a minidump is the "stack" of the crashing thread.
All threads have a stack, at all times, and the word "stack" is not used here in the slang sense (to crumple and fall). Since a thread's stack is fundamental to our understanding of its activity, including those times when that thread has caused a crash, let's examine a simple stack in more detail:
kd> k
ChildEBP RetAddr
f8b69dac 805c4cce nt!ExpWorkerThread+0x100
f8b69ddc 805411c2 nt!PspSystemThreadStartup+0x34
00000000 00000000 nt!KiThreadStartup+0x16
The 'k' (stack unwind) command was used to display the current thread's stack. In the display above, there are 3 columns of information:
ChildEBP: a pointer to a memory location which stores the address of the previous function on the stack ("stack frame").
RetAddr: The "return address" where processing will resume once this function returns (finishes what it had to do).
(not labeled) Function name: the module name and function names, according to the module symbols.
Focus first on the top frame of the current stack:
ChildEBP RetAddr
f8b69dac 805c4cce nt!ExpWorkerThread+0x100
The ChildEBP pointer is supposed to contain the address of the previous function's frame. Let's examine what is at that location using a variation of the debugger's 'd' (dump memory) command:
kd> dd f8b69dac L1
f8b69dac f8b69ddc
Notice that the address found there corresponds exactly to the previous (middle of the current stack) function's ChildEBP:
ChildEBP RetAddr
f8b69ddc 805411c2 nt!PspSystemThreadStartup+0x34
And now let's repeat the same procedure with the next ChildEBP value:
kd> dd f8b69ddc L1
f8b69ddc 00000000
The number found at memory address f8b69ddc is zero (0). That confirms what the last line from the full stack listing is telling us:
ChildEBP RetAddr
00000000 00000000 nt!KiThreadStartup+0x16
Since the function name is "KiThreadStartup" (Kernel Internal Thread Startup), it's understandable that the stack does not extend any further back, and KiThreadStartup was in fact the first function on the stack. Hence, the ChildEBP in that case was zero (0) - it wasn't called from another function.
What about RetAddr, the "return address"? Let's check the top frame's RetAddr:
ChildEBP RetAddr
f8b69dac 805c4cce nt!ExpWorkerThread+0x100
f8b69ddc 805411c2 nt!PspSystemThreadStartup+0x34
00000000 00000000 nt!KiThreadStartup+0x16
The stack suggests that the ExpWorkerThread function was called by PspSystemThreadStartup, and it is logical to assume that control would be returned back to PspSystemThreadStartup once ExpWorkerThread has completed whatever task it was asked to perform. If we examine those memory addresses using the debugger's 'ln' ("list nearest" [function]) command:
kd> ln 805c4cce
(805c4c9a) nt!PspSystemThreadStartup+0x34
Yes, execution will resume precisely where we left off in PspSystemThreadStartup - at 0x34 (52 decimal) bytes from the start of that function. Likewise, we can expect that once PspSystemThreadStartup is completely finished, the OS will give control back to KiThreadStartup:
kd> ln 805411c2
(805411ac) nt!KiThreadStartup+0x16
=========================================
One potential question at this point is how does the debugger display the stack based on the contents of a memory dump - how does the 'k' command produce its output?
For each thread, the OS maintains an information block which keeps track of many thread attributes, including the locations in memory where the thread's stack starts and finishes. During a crash, the "information block" for the thread which directly caused the crash is recorded in the memory dump, and portions of it can be viewed with the '!thread' debugger command:
kd> !thread
THREAD 82265470 Cid 0004.0108 Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 0
Not impersonating
DeviceMap e1005570
Owning Process 0 Image: <Unknown>
Attached Process 82154500 Image: winlogon.exe
Wait Start TickCount 38493 Ticks: 0
Context Switch Count 768
UserTime 00:00:00.000
KernelTime 00:00:00.020
Start Address nt!ExpWorkerThread (0x80533ee6)
Stack Init f8b6a000 Current f8b69d1c Base f8b6a000 Limit f8b67000 Call 0
Priority 12 BasePriority 12 PriorityDecrement 0 DecrementCount 0
Note the stored stack values, including the "current" stack pointer at the time. Based on a series of steps very similar to what we did above by following ChildEBP from a function back to its caller, the debugger "unwinds" and hence displays the crashing thread's stack in text format.
The function names at or near the top of the stack form an excellent starting point for web searches regarding the question of whether others have experienced identical or very similar crashes.
Yes, I realise it has "stacked", but how?!?
One of the items of information stored in a minidump is the "stack" of the crashing thread.
All threads have a stack, at all times, and the word "stack" is not used here in the slang sense (to crumple and fall). Since a thread's stack is fundamental to our understanding of its activity, including those times when that thread has caused a crash, let's examine a simple stack in more detail:
kd> k
ChildEBP RetAddr
f8b69dac 805c4cce nt!ExpWorkerThread+0x100
f8b69ddc 805411c2 nt!PspSystemThreadStartup+0x34
00000000 00000000 nt!KiThreadStartup+0x16
The 'k' (stack unwind) command was used to display the current thread's stack. In the display above, there are 3 columns of information:
ChildEBP: a pointer to a memory location which stores the address of the previous function on the stack ("stack frame").
RetAddr: The "return address" where processing will resume once this function returns (finishes what it had to do).
(not labeled) Function name: the module name and function names, according to the module symbols.
Focus first on the top frame of the current stack:
ChildEBP RetAddr
f8b69dac 805c4cce nt!ExpWorkerThread+0x100
The ChildEBP pointer is supposed to contain the address of the previous function's frame. Let's examine what is at that location using a variation of the debugger's 'd' (dump memory) command:
kd> dd f8b69dac L1
f8b69dac f8b69ddc
Notice that the address found there corresponds exactly to the previous (middle of the current stack) function's ChildEBP:
ChildEBP RetAddr
f8b69ddc 805411c2 nt!PspSystemThreadStartup+0x34
And now let's repeat the same procedure with the next ChildEBP value:
kd> dd f8b69ddc L1
f8b69ddc 00000000
The number found at memory address f8b69ddc is zero (0). That confirms what the last line from the full stack listing is telling us:
ChildEBP RetAddr
00000000 00000000 nt!KiThreadStartup+0x16
Since the function name is "KiThreadStartup" (Kernel Internal Thread Startup), it's understandable that the stack does not extend any further back, and KiThreadStartup was in fact the first function on the stack. Hence, the ChildEBP in that case was zero (0) - it wasn't called from another function.
What about RetAddr, the "return address"? Let's check the top frame's RetAddr:
ChildEBP RetAddr
f8b69dac 805c4cce nt!ExpWorkerThread+0x100
f8b69ddc 805411c2 nt!PspSystemThreadStartup+0x34
00000000 00000000 nt!KiThreadStartup+0x16
The stack suggests that the ExpWorkerThread function was called by PspSystemThreadStartup, and it is logical to assume that control would be returned back to PspSystemThreadStartup once ExpWorkerThread has completed whatever task it was asked to perform. If we examine those memory addresses using the debugger's 'ln' ("list nearest" [function]) command:
kd> ln 805c4cce
(805c4c9a) nt!PspSystemThreadStartup+0x34
Yes, execution will resume precisely where we left off in PspSystemThreadStartup - at 0x34 (52 decimal) bytes from the start of that function. Likewise, we can expect that once PspSystemThreadStartup is completely finished, the OS will give control back to KiThreadStartup:
kd> ln 805411c2
(805411ac) nt!KiThreadStartup+0x16
=========================================
One potential question at this point is how does the debugger display the stack based on the contents of a memory dump - how does the 'k' command produce its output?
For each thread, the OS maintains an information block which keeps track of many thread attributes, including the locations in memory where the thread's stack starts and finishes. During a crash, the "information block" for the thread which directly caused the crash is recorded in the memory dump, and portions of it can be viewed with the '!thread' debugger command:
kd> !thread
THREAD 82265470 Cid 0004.0108 Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 0
Not impersonating
DeviceMap e1005570
Owning Process 0 Image: <Unknown>
Attached Process 82154500 Image: winlogon.exe
Wait Start TickCount 38493 Ticks: 0
Context Switch Count 768
UserTime 00:00:00.000
KernelTime 00:00:00.020
Start Address nt!ExpWorkerThread (0x80533ee6)
Stack Init f8b6a000 Current f8b69d1c Base f8b6a000 Limit f8b67000 Call 0
Priority 12 BasePriority 12 PriorityDecrement 0 DecrementCount 0
Note the stored stack values, including the "current" stack pointer at the time. Based on a series of steps very similar to what we did above by following ChildEBP from a function back to its caller, the debugger "unwinds" and hence displays the crashing thread's stack in text format.
The function names at or near the top of the stack form an excellent starting point for web searches regarding the question of whether others have experienced identical or very similar crashes.
相关文章推荐
- [zz]Adventures In A 32-bit Minidump, Part 1
- [zz]Adventures In A 32-bit Minidump, Part 2
- You receive a C4226 or a C4236 error message when you compile code to contain the keyword in 32-bit Visual C++(ZZ)
- Double prefix overrides to provide 16-bit operand size in a 32/64 operating mode
- This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed.
- Qt 5.2.1 applications (32 bit) in CentOS (64 bit with gcc 4.8.2)
- Coursera-An Introduction to Interactive Programming in Python (Part 1)-Mini-project — “Guess the number” game
- What the hell is cmp byte ptr[rax],0 in a managed mini dump?
- Coursera-An Introduction to Interactive Programming in Python (Part 1)-Mini-project #4 —"Pong"
- Problems with System.OutOfMemoryException At System.String.GetStringForStringBuilder in 32-Bit Managed Solutions
- Running in 64 bit mode with the 32 bit Oracle client installed问题
- The best method for counting bits in a 32-bit integer(2)
- Attempt to load Oracle client libraries threw BadImageFormatException. This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed.
- 转:Heap spraying high addresses in 32-bit Chrome/Firefox on 64-bit Windows
- Internet Information Services is running in 32-bit emulation mode. Correct the issue listed above and re-run setup.
- Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\VsProjects\T\Debug\T.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
- How to Increase the Memory Limit for 32-bit Applications in Windows 64-bit OS
- Coursera-An Introduction to Interactive Programming in Python (Part 1)-Mini-project #3 —"Stopwatch: The Game"
- Save a 32-bit Bitmap as 1-bit .bmp file in C#
- Exception in thread "main" java.lang.UnsatisfiedLinkError: Cannot load 32-bit SWT libraries on 64-bi