The code is highly optimized, frame pointers are omitted.
After running !analyze -v, I executed the proposed STACK_COMMAND:
0:009> ~9s; .ecxr ; kb
eax=00002000 ebx=80070000 ecx=00002000 edx=00000000
esi=00000320 edi=00000000
eip=7c92eb94 esp=00a09600 ebp=00a09664 iopl=0
nv up ei ng nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00000297
ntdll!KiFastSystemCallRet:
7c92eb94 c3 ret
eax=00012730 ebx=00000014 ecx=00000003 edx=00000051
esi=00628cd0 edi=00000014
eip=0102215c esp=00a0f244 ebp=002bf58c iopl=0
nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00010202
App!CSrbIo::MakeSrbIo10+0xc:
0102215c 8b08 mov ecx,dword ptr [eax]
ds:0023:00012730=???
*** Stack trace for last set context - .thread/.cxr resets
it
ChildEBP RetAddr Args to Child
00a0f244 010536a0 00012730 00000043 00000000
App!CSrbIo::MakeSrbIo10+0xc […]
00a0f2a4 010508bd 00a0f2c8 00000000 00a0f300
App!CScsiMmcWocd::EReadFormattedToc+0x160 […]
00a0f2f0 010520a0 00a0f300 002b3b30 00000000
App!CScsiMmcWocd::TMrwMediaInNonMrwDrive+0x5d […]
00a0f318 0103c94e 00000046 00000000 002bcf48
App!CScsiMmcWocd::TMediaIsMrw+0x70 […]
00a0f454 0103d35d 006275e0 002b3b30 0090fe94
App!EDeviceStateToSysinfo+0x25e […]
00a0fe60 0103e542 002b38ec 00000001 00000002
App!CFpIpcServer::Handler+0x27d […]
00a0fe78 01043ab3 002b38ec 002bcf48 00000001
App!CFpIpcServer::Handler_static+0x22 […]
00a0ff20 01043d05 002b38ec 00000000 00000000
App!CIpcppServer::EReqHandler+0x83 […]
00a0ff38 0101d598 002b38e8 0090fea4 0090fe94
App!CIpcppServer::EStaticReqHandler+0x15 […]
00a0ff4c 0101d414 0062621c 00000001 00000000
App!CThreadManager::Vrt_ProcessThreadCall+0x38 […]
00a0ff68 0101d45d 0062621c 0101858c 0062621c
App!CThreadManager::ThreadHoldRoutine+0x34 […]
00a0ff70 0101858c 0062621c 00000000 00626180
App!CThreadManager::U32Stat_ThreadHoldRoutine+0xd […]
00a0ff80 7c349565 00627208 00000000 00000000
App!U32StartThreadHelper+0xc […]
00a0ffb4 7c80b50b 00627218 00000000 00000000
msvcr71!_threadstartex+0x6f […]
00a0ffec 00000000 7c3494f6 00627218 00000000
kernel32!BaseThreadStart+0x37
Now switch to frame 1 (CScsiMmcWocd::EReadFormattedToc) and try
to analyze the local variables:
0:009> .frame 1
01 00a0f2a4 010508bd
App!CScsiMmcWocd::EReadFormattedToc+0x160 […]
First try to display the locals:
0:009> dv
@edx this = 0x00000051
002bf590 ppmmcFormattedTOC =
002bf594 tMinSecFrmFmt =
002bf598 pstatusInfo =
002bf56c fixedBufferForTOC = class CFixedBuffer
002bf568 GetSrbIo = class CGetSrbIo
002bf598 eErr =
002bf560 mmcFormattedTOCHeader =
struct zMmcFormattedTOCHeader
Interesting dv result:
- Usualy this is stored in ecx, but that is another issue…
- I guess, that the first column of dv should display the address
of the variable.
If that is true: Why are the addresses of the locals so far
away from ChildEBP?
The range 002bf560 002bf590 is not contained in the dump. For
my opinion, that is impossible, because locals are allocated on
stack and the stacks are completely dumped.
More interesting: the relative distances between the addresses
displayed by dv are correct. Assuming, that the first parameter
is located at ChildEBP+8, I get 00a0f288 as address for
fixedBufferForTOC.
Using dds to verify the assumption:
0:009> dds 0xa0f288
00a0f288 0100c1bc App!CFixedBuffer::`vftable’
00a0f28c 00000001
00a0f290 00ad0000
00a0f294 00000014
00a0f298 00000000
Well, fixedBufferForTOC is located at 0xa0f288.
Trying dt to display fixedBufferForTOC shows strange results:
0:009> dt -v fixedBufferForTOC 0xa0f288
Local var [AddrFlags 90 AddrOff ffffffe0 Reg/Val ebp (8)] @
0x2bf56c Type CFixedBuffer
class CFixedBuffer, 19 elements, 0x14 bytes
+0x000 __VFN_table : ???
+0x004 m_uiReferenceCount : ??
+0x008 m_pbMem : ???
+0x00c m_uiSize : ??
+0x010 m_pMemBaseAddress : ???
Memory read error 002bf57c
Windbg seems to interpret fixedBufferForTOC at 0xa0f288 as a
pointer pointing to 0x2bf56c. Why?
It seems to me, that something is going badly wrong here.
Additional info:
Displaying the registers suggests, that WinDbg uses ebp as frame
pointer, despite of the fact, that the code model doesn’t use ebp
as frame pointer register:
eax=00012730 ebx=00000014 ecx=00000003 edx=00000051
esi=00628cd0 edi=00000014
eip=0102215c esp=00a0f244 ebp=002bf58c iopl=0
nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00010202
App!CSrbIo::MakeSrbIo10+0xc:
0102215c 8b08 mov ecx,dword ptr [eax]
ds:0023:00012730=???
ebp=002bf58c
0:009> dv
@edx this = 0x00000051
002bf590 ppmmcFormattedTOC =
002bf594 tMinSecFrmFmt =
002bf598 pstatusInfo =
002bf56c fixedBufferForTOC = class CFixedBuffer
002bf568 GetSrbIo = class CGetSrbIo
002bf598 eErr =
002bf560 mmcFormattedTOCHeader =
struct zMmcFormattedTOCHeader
---------------------------
The code is highly optimized, frame pointers are omitted.
After running !analyze -v, I executed the proposed STACK_COMMAND:
0:009> ~9s; .ecxr ; kb
eax=00002000 ebx=80070000 ecx=00002000 edx=00000000
esi=00000320 edi=00000000
eip=7c92eb94 esp=00a09600 ebp=00a09664 iopl=0
nv up ei ng nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00000297
ntdll!KiFastSystemCallRet:
7c92eb94 c3 ret
eax=00012730 ebx=00000014 ecx=00000003 edx=00000051
esi=00628cd0 edi=00000014
eip=0102215c esp=00a0f244 ebp=002bf58c iopl=0
nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00010202
App!CSrbIo::MakeSrbIo10+0xc:
0102215c 8b08 mov ecx,dword ptr [eax]
ds:0023:00012730=???
*** Stack trace for last set context - .thread/.cxr resets
it
ChildEBP RetAddr Args to Child
00a0f244 010536a0 00012730 00000043 00000000
App!CSrbIo::MakeSrbIo10+0xc […]
00a0f2a4 010508bd 00a0f2c8 00000000 00a0f300
App!CScsiMmcWocd::EReadFormattedToc+0x160 […]
00a0f2f0 010520a0 00a0f300 002b3b30 00000000
App!CScsiMmcWocd::TMrwMediaInNonMrwDrive+0x5d […]
00a0f318 0103c94e 00000046 00000000 002bcf48
App!CScsiMmcWocd::TMediaIsMrw+0x70 […]
00a0f454 0103d35d 006275e0 002b3b30 0090fe94
App!EDeviceStateToSysinfo+0x25e […]
00a0fe60 0103e542 002b38ec 00000001 00000002
App!CFpIpcServer::Handler+0x27d […]
00a0fe78 01043ab3 002b38ec 002bcf48 00000001
App!CFpIpcServer::Handler_static+0x22 […]
00a0ff20 01043d05 002b38ec 00000000 00000000
App!CIpcppServer::EReqHandler+0x83 […]
00a0ff38 0101d598 002b38e8 0090fea4 0090fe94
App!CIpcppServer::EStaticReqHandler+0x15 […]
00a0ff4c 0101d414 0062621c 00000001 00000000
App!CThreadManager::Vrt_ProcessThreadCall+0x38 […]
00a0ff68 0101d45d 0062621c 0101858c 0062621c
App!CThreadManager::ThreadHoldRoutine+0x34 […]
00a0ff70 0101858c 0062621c 00000000 00626180
App!CThreadManager::U32Stat_ThreadHoldRoutine+0xd […]
00a0ff80 7c349565 00627208 00000000 00000000
App!U32StartThreadHelper+0xc […]
00a0ffb4 7c80b50b 00627218 00000000 00000000
msvcr71!_threadstartex+0x6f […]
00a0ffec 00000000 7c3494f6 00627218 00000000
kernel32!BaseThreadStart+0x37
Now switch to frame 1 (CScsiMmcWocd::EReadFormattedToc) and try
to analyze the local variables:
0:009> .frame 1
01 00a0f2a4 010508bd
App!CScsiMmcWocd::EReadFormattedToc+0x160 […]
First try to display the locals:
0:009> dv
@edx this = 0x00000051
002bf590 ppmmcFormattedTOC =
002bf594 tMinSecFrmFmt =
002bf598 pstatusInfo =
002bf56c fixedBufferForTOC = class CFixedBuffer
002bf568 GetSrbIo = class CGetSrbIo
002bf598 eErr =
002bf560 mmcFormattedTOCHeader =
struct zMmcFormattedTOCHeader
Interesting dv result:
- Usualy this is stored in ecx, but that is another issue…
- I guess, that the first column of dv should display the address
of the variable.
If that is true: Why are the addresses of the locals so far
away from ChildEBP?
The range 002bf560 002bf590 is not contained in the dump. For
my opinion, that is impossible, because locals are allocated on
stack and the stacks are completely dumped.
More interesting: the relative distances between the addresses
displayed by dv are correct. Assuming, that the first parameter
is located at ChildEBP+8, I get 00a0f288 as address for
fixedBufferForTOC.
Using dds to verify the assumption:
0:009> dds 0xa0f288
00a0f288 0100c1bc App!CFixedBuffer::`vftable’
00a0f28c 00000001
00a0f290 00ad0000
00a0f294 00000014
00a0f298 00000000
Well, fixedBufferForTOC is located at 0xa0f288.
Trying dt to display fixedBufferForTOC shows strange results:
0:009> dt -v fixedBufferForTOC 0xa0f288
Local var [AddrFlags 90 AddrOff ffffffe0 Reg/Val ebp (8)] @
0x2bf56c Type CFixedBuffer
class CFixedBuffer, 19 elements, 0x14 bytes
+0x000 __VFN_table : ???
+0x004 m_uiReferenceCount : ??
+0x008 m_pbMem : ???
+0x00c m_uiSize : ??
+0x010 m_pMemBaseAddress : ???
Memory read error 002bf57c
Windbg seems to interpret fixedBufferForTOC at 0xa0f288 as a
pointer pointing to 0x2bf56c. Why?
It seems to me, that something is going badly wrong here.
—
You are currently subscribed to windbg as: xxxxx@nero.com
To unsubscribe send a blank email to
xxxxx@lists.osr.com
Albrecht Frenzel wrote:
Additional info:
Displaying the registers suggests, that WinDbg uses ebp as frame
pointer, despite of the fact, that the code model doesn’t use ebp as
frame pointer register:
Right. There is no way for WinDBG to know this. It is clever, but it
is not omniscient. Fancy, knowledgable debugger commands become largely
useless when full optimization is turned on, because items that would be
stored in known memory locations without optimization get tucked into
registers that are not findable with optimization.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
windbg uses available symbolic debugging information to determine what
local variables exist and where they are stored. Unfortunately the
compiler rarely emits correct local variable debugging info when
optimizations are on. The compiler team has a plan to fix this at some
point but it’s still a ways off.
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Albrecht Frenzel
Sent: Monday, July 31, 2006 2:27 AM
To: Kernel Debugging Interest List
Subject: [windbg] Analyzing stack frames in crash dumps
Additional info:
Displaying the registers suggests, that WinDbg uses ebp as frame
pointer, despite of the fact, that the code model doesn’t use ebp as
frame pointer register:
eax=00012730 ebx=00000014 ecx=00000003 edx=00000051
esi=00628cd0 edi=00000014
eip=0102215c esp=00a0f244 ebp=002bf58c iopl=0
nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00010202
App!CSrbIo::MakeSrbIo10+0xc:
0102215c 8b08 mov ecx,dword ptr [eax]
ds:0023:00012730=???
ebp=002bf58c
0:009> dv
@edx this = 0x00000051
002bf590 ppmmcFormattedTOC =
002bf594 tMinSecFrmFmt =
002bf598 pstatusInfo =
002bf56c fixedBufferForTOC = class CFixedBuffer
002bf568 GetSrbIo = class CGetSrbIo
002bf598 eErr =
002bf560 mmcFormattedTOCHeader =
struct zMmcFormattedTOCHeader
---------------------------
The code is highly optimized, frame pointers are omitted.
After running !analyze -v, I executed the proposed STACK_COMMAND:
0:009> ~9s; .ecxr ; kb
eax=00002000 ebx=80070000 ecx=00002000 edx=00000000
esi=00000320 edi=00000000
eip=7c92eb94 esp=00a09600 ebp=00a09664 iopl=0
nv up ei ng nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00000297
ntdll!KiFastSystemCallRet:
7c92eb94 c3 ret
eax=00012730 ebx=00000014 ecx=00000003 edx=00000051
esi=00628cd0 edi=00000014
eip=0102215c esp=00a0f244 ebp=002bf58c iopl=0
nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00010202
App!CSrbIo::MakeSrbIo10+0xc:
0102215c 8b08 mov ecx,dword ptr [eax]
ds:0023:00012730=???
*** Stack trace for last set context - .thread/.cxr resets
it
ChildEBP RetAddr Args to Child
00a0f244 010536a0 00012730 00000043 00000000
App!CSrbIo::MakeSrbIo10+0xc […]
00a0f2a4 010508bd 00a0f2c8 00000000 00a0f300
App!CScsiMmcWocd::EReadFormattedToc+0x160 […]
00a0f2f0 010520a0 00a0f300 002b3b30 00000000
App!CScsiMmcWocd::TMrwMediaInNonMrwDrive+0x5d […]
00a0f318 0103c94e 00000046 00000000 002bcf48
App!CScsiMmcWocd::TMediaIsMrw+0x70 […]
00a0f454 0103d35d 006275e0 002b3b30 0090fe94
App!EDeviceStateToSysinfo+0x25e […]
00a0fe60 0103e542 002b38ec 00000001 00000002
App!CFpIpcServer::Handler+0x27d […]
00a0fe78 01043ab3 002b38ec 002bcf48 00000001
App!CFpIpcServer::Handler_static+0x22 […]
00a0ff20 01043d05 002b38ec 00000000 00000000
App!CIpcppServer::EReqHandler+0x83 […]
00a0ff38 0101d598 002b38e8 0090fea4 0090fe94
App!CIpcppServer::EStaticReqHandler+0x15 […]
00a0ff4c 0101d414 0062621c 00000001 00000000
App!CThreadManager::Vrt_ProcessThreadCall+0x38 […]
00a0ff68 0101d45d 0062621c 0101858c 0062621c
App!CThreadManager::ThreadHoldRoutine+0x34 […]
00a0ff70 0101858c 0062621c 00000000 00626180
App!CThreadManager::U32Stat_ThreadHoldRoutine+0xd […]
00a0ff80 7c349565 00627208 00000000 00000000
App!U32StartThreadHelper+0xc […]
00a0ffb4 7c80b50b 00627218 00000000 00000000
msvcr71!_threadstartex+0x6f […]
00a0ffec 00000000 7c3494f6 00627218 00000000
kernel32!BaseThreadStart+0x37
Now switch to frame 1 (CScsiMmcWocd::EReadFormattedToc) and try to
analyze the local variables:
0:009> .frame 1
01 00a0f2a4 010508bd
App!CScsiMmcWocd::EReadFormattedToc+0x160 […]
First try to display the locals:
0:009> dv
@edx this = 0x00000051
002bf590 ppmmcFormattedTOC =
002bf594 tMinSecFrmFmt =
002bf598 pstatusInfo =
002bf56c fixedBufferForTOC = class CFixedBuffer
002bf568 GetSrbIo = class CGetSrbIo
002bf598 eErr =
002bf560 mmcFormattedTOCHeader =
struct zMmcFormattedTOCHeader
Interesting dv result:
- Usualy this is stored in ecx, but that is another issue…
- I guess, that the first column of dv should display the address
of the variable.
If that is true: Why are the addresses of the locals so far
away from ChildEBP?
The range 002bf560 002bf590 is not contained in the dump. For
my opinion, that is impossible, because locals are allocated on
stack and the stacks are completely dumped.
More interesting: the relative distances between the addresses displayed
by dv are correct. Assuming, that the first parameter is located at
ChildEBP+8, I get 00a0f288 as address for fixedBufferForTOC.
Using dds to verify the assumption:
0:009> dds 0xa0f288
00a0f288 0100c1bc App!CFixedBuffer::`vftable’
00a0f28c 00000001
00a0f290 00ad0000
00a0f294 00000014
00a0f298 00000000
Well, fixedBufferForTOC is located at 0xa0f288.
Trying dt to display fixedBufferForTOC shows strange results:
0:009> dt -v fixedBufferForTOC 0xa0f288
Local var [AddrFlags 90 AddrOff ffffffe0 Reg/Val ebp (8)] @
0x2bf56c Type CFixedBuffer
class CFixedBuffer, 19 elements, 0x14 bytes
+0x000 __VFN_table : ???
+0x004 m_uiReferenceCount : ??
+0x008 m_pbMem : ???
+0x00c m_uiSize : ??
+0x010 m_pMemBaseAddress : ???
Memory read error 002bf57c
Windbg seems to interpret fixedBufferForTOC at 0xa0f288 as a pointer
pointing to 0x2bf56c. Why?
It seems to me, that something is going badly wrong here.
—
You are currently subscribed to windbg as: xxxxx@nero.com To
unsubscribe send a blank email to xxxxx@lists.osr.com
—
You are currently subscribed to windbg as: xxxxx@winse.microsoft.com To
unsubscribe send a blank email to xxxxx@lists.osr.com
It is very easy to determine, if a code model uses frame pointers:
-
compare epb against ChildEBP in frame 0. If the values are
unequal: no frame pointers are present.
-
if epb matches ChildEBP: follow the pointer chain. If you
reach the bottom frame, frame pointers are present.
Tim Roberts schrieb:
Albrecht Frenzel wrote:
>Additional info:
>
>Displaying the registers suggests, that WinDbg uses ebp as frame
>pointer, despite of the fact, that the code model doesn’t use ebp as
>frame pointer register:
Right. There is no way for WinDBG to know this. It is clever, but it
is not omniscient. Fancy, knowledgable debugger commands become largely
useless when full optimization is turned on, because items that would be
stored in known memory locations without optimization get tucked into
registers that are not findable with optimization.
It is very easy to determine, if a code model uses frame pointers:
-
compare epb against ChildEBP in frame 0. If the values are
unequal: no frame pointers are present.
-
if epb matches ChildEBP: follow the pointer chain. If you
reach the bottom frame, frame pointers are present.
Tim Roberts schrieb:
Albrecht Frenzel wrote:
>Additional info:
>
>Displaying the registers suggests, that WinDbg uses ebp as frame
>pointer, despite of the fact, that the code model doesn’t use ebp as
>frame pointer register:
Right. There is no way for WinDBG to know this. It is clever, but it
is not omniscient. Fancy, knowledgable debugger commands become largely
useless when full optimization is turned on, because items that would be
stored in known memory locations without optimization get tucked into
registers that are not findable with optimization.
Albrecht Frenzel wrote:
It is very easy to determine, if a code model uses frame pointers:
No, it isn’t.
- compare epb against ChildEBP in frame 0. If the values are
unequal: no frame pointers are present.
How am I going to determine ChildEBP? I have to use the current ebp to
find it. How can I tell whether ebp points into a stack or into random
memory that happens to look like a valid address?
- if epb matches ChildEBP: follow the pointer chain. If you
reach the bottom frame, frame pointers are present.
“The bottom frame”? What does that mean?
The fact is, all the debugger can do is guess. It assumes that ebp
points to a frame, and follows the chain until it comes to an
unreasonable address. That’s the best it can do.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
> How am I going to determine ChildEBP? I have to use the current ebp to
find it. How can I tell whether ebp points into a stack or into random
memory that happens to look like a valid address?
Take a look to kb output - there is a column called ChildEBP,
which is correct, even if the code is optimized and frame
pointers are omitted.
“The bottom frame”? What does that mean?
Simply the last frame displayed by kb. (Completely corrupted
stacks are not so frequent, that false results of kb are large
everyday’s problem.)
The fact is, all the debugger can do is guess. It assumes that ebp
points to a frame, and follows the chain until it comes to an
unreasonable address. That’s the best it can do.
In fact: windbg guesses - why not use the results?
My experience is, that it is useful to try the layout produced by
dv with a correct frame pointer. In many cases the result is ok;
it is the same problem as mapping machine code to a source line:
mostly it works quite well, but there are cases, where windbg fails
In addition, you have no guarantee that some frames use EBP chains while
others do not, so finding the “bottom frame” isn’t always a good frame
of reference. You’d need to find the ‘last frame using ebp’, then
switch your stackwalk mechanics. It’s much better to just trust your
symbols, and get the symbols to include accurate information as to where
variables live when optimizations are on.
Jason
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Wednesday, August 02, 2006 10:04 AM
To: Kernel Debugging Interest List
Subject: Re: [windbg] Analyzing stack frames in crash dumps
Albrecht Frenzel wrote:
It is very easy to determine, if a code model uses frame pointers:
No, it isn’t.
- compare epb against ChildEBP in frame 0. If the values are
unequal: no frame pointers are present.
How am I going to determine ChildEBP? I have to use the current ebp to
find it. How can I tell whether ebp points into a stack or into random
memory that happens to look like a valid address?
- if epb matches ChildEBP: follow the pointer chain. If you
reach the bottom frame, frame pointers are present.
“The bottom frame”? What does that mean?
The fact is, all the debugger can do is guess. It assumes that ebp
points to a frame, and follows the chain until it comes to an
unreasonable address. That’s the best it can do.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
You are currently subscribed to windbg as: xxxxx@winse.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com