Difference in WinDBG "!analyze -v" stack formatting

Is there anyway to alter the “kb” statement that “!analyze -v” executes
into a “kvn” or to get kb to also show FPO data?

I think most users would consider the second format much more informative.
It should be the default.

All results shown for this version of WinDBG:
Microsoft (R) Windows Debugger Version 10.0.10586.567 X86
and they come from the same minidump.

When I process a minidump with the “!analyze -v” I get a result like this:

STACK_TEXT:
00918d18 768b4740 oleaut32!SysAllocString+0x15
00918d20 77d3c4fc sp3deqpcadhelper!ATL::CComBSTR::CComBSTR+0x2c
00918d34 77d2210d
sp3deqpcadhelper!CCADServices::CheckMemberConditional+0x53d
00918f44 17cdff75 sp3dpullpitasm!PullPitDef::CMConditionalPullBoxSolid+0x86
00918fa8 768ccc68 oleaut32!DispCallFunc+0x165
00918fc8 4ff03c67 msvbvm60+0x63c67
00919924 4ff03975 msvbvm60+0x63975
00919980 186f1fe1 imssymbolentities!PerformMethodViaAutomation+0x3e1
00919a78 186ea61f imssymbolentities!PerformActiveXMethod+0x1bf
00919af4 1865627d imssymbolentities!CSblDefinition::InvokeMethod+0x8bd
00919c74 52353d4e
customassembly!CDMemberDescription::InvokeCMConditional+0x2de

Luckily, years ago I noticed that if I execute “kvn20” after the results of
“!analyze -v” are printed, I get a much more informative stack, with FPO
data:

EXCEPTION_STACK_TEXT:
0:000> kvn20

ChildEBP RetAddr Args to Child

00 00918d18 77d3c4fc cdcdcdcd 00918d38 00918ebc
oleaut32!SysAllocString+0x15 (FPO: [Non-Fpo])
01 00918d2c 77d2210d cdcdcdcd 21747db9 00000000
SP3DEqpCADHelper!ATL::CComBSTR::CComBSTR+0x2c (FPO: [Non-Fpo]) (CONV:
thiscall) [c:\program files (x86)\microsoft visual studio
14.0\vc\atlmfc\include\atlcomcli.h @ 775]
02 00918f3c 17cdff75 1c0e5504 15d65c24 00918f70
SP3DEqpCADHelper!CCADServices::CheckMemberConditional+0x53d (FPO:
[Non-Fpo]) (CONV: stdcall)
[m:\equipment\middle\services\equipcadhelper\sp3deqpcadhelper\cadservices.cpp
@ 1566]
03 00918fa0 768ccc68 1053c118 15d65c24 0091bff4
SP3DPullPitAsm!PullPitDef::CMConditionalPullBoxSolid+0x86
[M:\SharedContent\Src\Equipment\Symbols\SP3DPullPitAsm\PullPitDef.cls @
1082]
04 00918fc0 4ff03c67 1053c118 000000c0 00000004 oleaut32!DispCallFunc+0x165
WARNING: Stack unwind information not available. Following frames may be
wrong.
05 0091991c 4ff03975 1053c118 17cd2808 6003002e msvbvm60+0x63c67
06 00919978 186f1fe1 1053c118 6003002e 1886a110 msvbvm60+0x63975
07 00919a70 186ea61f cccc0003 cccccccc 6003002e
IMSSymbolEntities!PerformMethodViaAutomation+0x3e1 (FPO: [Non-Fpo]) (CONV:
cdecl) [x:\middle\symbol\src\sblentities\sdmethodapi.cpp @ 286]
08 00919aec 1865627d cccc0003 cccccccc 6003002e
IMSSymbolEntities!PerformActiveXMethod+0x1bf (FPO: [Non-Fpo]) (CONV: cdecl)
[x:\middle\symbol\src\sblentities\sdmethodapi.cpp @ 350]
09 00919c6c 52353d4e 2345b9b0 cccc0003 cccccccc
IMSSymbolEntities!CSblDefinition::InvokeMethod+0x8bd (FPO: [Non-Fpo])
(CONV: stdcall) [x:\middle\symbol\src\sblentities\sbldefinition.cpp @ 4078]
0a 00919dcc 520e60b2 15d65c24 0091bff4 b6fb244d
CustomAssembly!CDMemberDescription::InvokeCMConditional+0x2de (FPO:
[Non-Fpo]) (CONV: stdcall)
[m:\commonapp\middle\entities\customassembly\businessobject\dmemberdescription.cpp
@ 1435]

Both of these came from same minidump, by having a script that does
“!analyze -v;.echo EXCEPTION_STACK_TEXT:;kvn20”

Obviously, you will only get source and line number information if you have
the correct PDBs for your DLLs.

Appreciate any input,
Osiris

I just stepped through the !analyze command in the debugger. The call that
!analyze makes to DebugClient::OutputStackTrace uses a hard coded flags
value:

0:001> kc

Call Site

00 dbgeng!DebugClient::OutputStackTrace
01 ext!DbgClient::OutputStackTrace
02 ext!DebugFailureAnalysis::SetContextFollowupDetails
03 ext!DebugFailureAnalysis::AnalyzeStackEx
04 ext!DebugFailureAnalysis::ProcessInformationCore
05 ext!DebugFailureAnalysis::ProcessInformation
06 ext!BcFillAnalysis
07 ext!BcAnalyze
08 ext!AnalyzeBugCheck
09 ext!analyze
0a dbgeng!ExtensionInfo::CallA
0b dbgeng!ExtensionInfo::Call
0c dbgeng!ExtensionInfo::CallAny
0d dbgeng!ParseBangCmd
0e dbgeng!ProcessCommands
0f dbgeng!ProcessCommandsAndCatch
10 dbgeng!Execute
11 dbgeng!DebugClient::ExecuteWide
12 windbg!ProcessCommand
13 windbg!ProcessEngineCommands
14 windbg!EngineLoop
15 KERNEL32!BaseThreadInitThunk
16 ntdll!RtlUserThreadStart

HRESULT OutputStackTrace(
[in] ULONG OutputControl,
[in, optional] PDEBUG_STACK_FRAME Frames,
[in] ULONG FramesSize,
[in] ULONG Flags
);

mov dword ptr [rsp+20h],0Dh <<== Flags == 0xD
mov rax,qword ptr [rcx]
mov rax,qword ptr [rax+108h]
call qword ptr [ext!_guard_dispatch_icall_fptr (00007ffe`7867dd20)]

So, doesn’t look like there’s a way to set this as part of running !analyze
command.

-scott
OSR

you can employ this hack debug the debugger and pass the flags

stack prior to hack

0:002> dx Debugger.Utility.Control.ExecuteCommand(“!analyze
-v”).SkipWhile(a=>(a.Contains(“STACK_TEXT”) == 0)).Take(10)
Debugger.Utility.Control.ExecuteCommand(“!analyze
-v”).SkipWhile(a=>(a.Contains(“STACK_TEXT”) == 0)).Take(10)
[0x0] : STACK_TEXT:
[0x1] : WARNING: Frame IP not in any known module.
Following frames may be wrong.
[0x2] : 00f1dde4 100e9b5c ffffffff 00f1de04 00f1de00 0x0
[0x3] : 00f1e60c 100ec196 10248e54 003fe9d8 0000002e
dbgeng+0xe9b5c
[0x4] : 00f1e620 10147ba5 003fe9d8 00000000 00f1e6b0
dbgeng+0xec196
[0x5] : 00f1e688 10148730 003fe9d8 00000000 bbb100a7
dbgeng+0x147ba5
[0x6] : 00f1e6e8 100bda7c 003fe9d8 00000000 00000000
dbgeng+0x148730
[0x7] : 00f1eb5c 100bdcc4 003fe9d8 00f1ef90 00000002
dbgeng+0xbda7c
[0x8] : 00f1ebb4 0041e08d 003fe9e0 00000001 00f1ef90
dbgeng+0xbdcc4
[0x9] : 00f1ef70 0041e4e7 00000000 00000000 00000040
windbg+0x1e08d

issuing .dbgdbg to spawn a parent debugger that debugs the debugger
debugging your debuggee

0:002> .dbgdbg
Debugger spawned, connect with
“-remote npipe:icfenable,pipe=cdb_pipe,server=XXXX”

now in the ntsd that is spawned

set this conditioanl breakpoint and pass the flag 1fff (look in
dbgeng.h for explanation of values)

bp dbgeng!DebugClient::OutputStackTrace “ed esp+14 1fff ;gc”

0:006> bl
0 e 5b6b1c40 0001 (0001) 0:**** dbgeng!DebugClient::OutputStackTrace “ed e
sp+14 1fff ;gc”

and execute g

now all your further analyze -v will have a verbose stack

0:002> dx Debugger.Utility.Control.ExecuteCommand(“!analyze
-v”).SkipWhile(a=>(a.Contains(“STACK_TEXT”) == 0)).Take(10)
Debugger.Utility.Control.ExecuteCommand(“!analyze
-v”).SkipWhile(a=>(a.Contains(“STACK_TEXT”) == 0)).Take(10)
[0x0] : STACK_TEXT:
[0x1] : # Memory ChildEBP RetAddr Args to Child
[0x2] : WARNING: Frame IP not in any known module.
Following frames may be wrong.
[0x3] : 00 00f1dde4 100e9b5c ffffffff
00f1de04 00f1de00 0x0
[0x4] : 01 828 00f1e60c 100ec196 10248e54
003fe9d8 0000002e dbgeng+0xe9b5c
[0x5] : 02 14 00f1e620 10147ba5 003fe9d8
00000000 00f1e6b0 dbgeng+0xec196
[0x6] : 03 68 00f1e688 10148730 003fe9d8
00000000 bbb100a7 dbgeng+0x147ba5
[0x7] : 04 60 00f1e6e8 100bda7c 003fe9d8
00000000 00000000 dbgeng+0x148730
[0x8] : 05 474 00f1eb5c 100bdcc4 003fe9d8
00f1ef90 00000002 dbgeng+0xbda7c
[0x9] : 06 58 00f1ebb4 0041e08d 003fe9e0
00000001 00f1ef90 dbgeng+0xbdcc4

On 10/3/17, Scott Noone wrote:
> I just stepped through the !analyze command in the debugger. The call that
> !analyze makes to DebugClient::OutputStackTrace uses a hard coded flags
> value:
>
> 0:001> kc
> # Call Site
> 00 dbgeng!DebugClient::OutputStackTrace
> 01 ext!DbgClient::OutputStackTrace
> 02 ext!DebugFailureAnalysis::SetContextFollowupDetails
> 03 ext!DebugFailureAnalysis::AnalyzeStackEx
> 04 ext!DebugFailureAnalysis::ProcessInformationCore
> 05 ext!DebugFailureAnalysis::ProcessInformation
> 06 ext!BcFillAnalysis
> 07 ext!BcAnalyze
> 08 ext!AnalyzeBugCheck
> 09 ext!analyze
> 0a dbgeng!ExtensionInfo::CallA
> 0b dbgeng!ExtensionInfo::Call
> 0c dbgeng!ExtensionInfo::CallAny
> 0d dbgeng!ParseBangCmd
> 0e dbgeng!ProcessCommands
> 0f dbgeng!ProcessCommandsAndCatch
> 10 dbgeng!Execute
> 11 dbgeng!DebugClient::ExecuteWide
> 12 windbg!ProcessCommand
> 13 windbg!ProcessEngineCommands
> 14 windbg!EngineLoop
> 15 KERNEL32!BaseThreadInitThunk
> 16 ntdll!RtlUserThreadStart
>
> HRESULT OutputStackTrace(
> [in] ULONG OutputControl,
> [in, optional] PDEBUG_STACK_FRAME Frames,
> [in] ULONG FramesSize,
> [in] ULONG Flags
> );
>
> mov dword ptr [rsp+20h],0Dh <<== Flags == 0xD
> mov rax,qword ptr [rcx]
> mov rax,qword ptr [rax+108h]
> call qword ptr [ext!_guard_dispatch_icall_fptr (00007ffe`7867dd20)]
>
> So, doesn’t look like there’s a way to set this as part of running !analyze
>
> command.
>
> -scott
> OSR
>
>
> —
> WINDBG is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and software
> drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at
> http:
></http:></http:>

sorry hit enter too soon so following up

if you are issuing a kvn20 after analyze -v wouldn’t that print the
windbg’s stack in the top rather than the dumps exception stack ??

iirc !analyze -v detects that part and skips all the dump analysis
logic stack and only prints the exception stack

On 10/4/17, raj r wrote:
> you can employ this hack debug the debugger and pass the flags
>
> stack prior to hack
>
> 0:002> dx Debugger.Utility.Control.ExecuteCommand(“!analyze
> -v”).SkipWhile(a=>(a.Contains(“STACK_TEXT”) == 0)).Take(10)
> Debugger.Utility.Control.ExecuteCommand(“!analyze
> -v”).SkipWhile(a=>(a.Contains(“STACK_TEXT”) == 0)).Take(10)
> [0x0] : STACK_TEXT:
> [0x1] : WARNING: Frame IP not in any known module.
> Following frames may be wrong.
> [0x2] : 00f1dde4 100e9b5c ffffffff 00f1de04 00f1de00 0x0
> [0x3] : 00f1e60c 100ec196 10248e54 003fe9d8 0000002e
> dbgeng+0xe9b5c
> [0x4] : 00f1e620 10147ba5 003fe9d8 00000000 00f1e6b0
> dbgeng+0xec196
> [0x5] : 00f1e688 10148730 003fe9d8 00000000 bbb100a7
> dbgeng+0x147ba5
> [0x6] : 00f1e6e8 100bda7c 003fe9d8 00000000 00000000
> dbgeng+0x148730
> [0x7] : 00f1eb5c 100bdcc4 003fe9d8 00f1ef90 00000002
> dbgeng+0xbda7c
> [0x8] : 00f1ebb4 0041e08d 003fe9e0 00000001 00f1ef90
> dbgeng+0xbdcc4
> [0x9] : 00f1ef70 0041e4e7 00000000 00000000 00000040
> windbg+0x1e08d
>
>
> issuing .dbgdbg to spawn a parent debugger that debugs the debugger
> debugging your debuggee
>
> 0:002> .dbgdbg
> Debugger spawned, connect with
> “-remote npipe:icfenable,pipe=cdb_pipe,server=XXXX”
>
>
> now in the ntsd that is spawned
>
> set this conditioanl breakpoint and pass the flag 1fff (look in
> dbgeng.h for explanation of values)
>
> bp dbgeng!DebugClient::OutputStackTrace “ed esp+14 1fff ;gc”
>
> 0:006> bl
> 0 e 5b6b1c40 0001 (0001) 0: **** dbgeng!DebugClient::OutputStackTrace
> “ed e
> sp+14 1fff ;gc”
>
> and execute g
>
> now all your further analyze -v will have a verbose stack
>
>
>
> 0:002> dx Debugger.Utility.Control.ExecuteCommand(“!analyze
> -v”).SkipWhile(a=>(a.Contains(“STACK_TEXT”) == 0)).Take(10)
> Debugger.Utility.Control.ExecuteCommand(“!analyze
> -v”).SkipWhile(a=>(a.Contains(“STACK_TEXT”) == 0)).Take(10)
> [0x0] : STACK_TEXT:
> [0x1] : # Memory ChildEBP RetAddr Args to Child
> [0x2] : WARNING: Frame IP not in any known module.
> Following frames may be wrong.
> [0x3] : 00 00f1dde4 100e9b5c ffffffff
> 00f1de04 00f1de00 0x0
> [0x4] : 01 828 00f1e60c 100ec196 10248e54
> 003fe9d8 0000002e dbgeng+0xe9b5c
> [0x5] : 02 14 00f1e620 10147ba5 003fe9d8
> 00000000 00f1e6b0 dbgeng+0xec196
> [0x6] : 03 68 00f1e688 10148730 003fe9d8
> 00000000 bbb100a7 dbgeng+0x147ba5
> [0x7] : 04 60 00f1e6e8 100bda7c 003fe9d8
> 00000000 00000000 dbgeng+0x148730
> [0x8] : 05 474 00f1eb5c 100bdcc4 003fe9d8
> 00f1ef90 00000002 dbgeng+0xbda7c
> [0x9] : 06 58 00f1ebb4 0041e08d 003fe9e0
> 00000001 00f1ef90 dbgeng+0xbdcc4
>
>
>
>
>
>
> On 10/3/17, Scott Noone wrote:
>> I just stepped through the !analyze command in the debugger. The call
>> that
>> !analyze makes to DebugClient::OutputStackTrace uses a hard coded flags
>> value:
>>
>> 0:001> kc
>> # Call Site
>> 00 dbgeng!DebugClient::OutputStackTrace
>> 01 ext!DbgClient::OutputStackTrace
>> 02 ext!DebugFailureAnalysis::SetContextFollowupDetails
>> 03 ext!DebugFailureAnalysis::AnalyzeStackEx
>> 04 ext!DebugFailureAnalysis::ProcessInformationCore
>> 05 ext!DebugFailureAnalysis::ProcessInformation
>> 06 ext!BcFillAnalysis
>> 07 ext!BcAnalyze
>> 08 ext!AnalyzeBugCheck
>> 09 ext!analyze
>> 0a dbgeng!ExtensionInfo::CallA
>> 0b dbgeng!ExtensionInfo::Call
>> 0c dbgeng!ExtensionInfo::CallAny
>> 0d dbgeng!ParseBangCmd
>> 0e dbgeng!ProcessCommands
>> 0f dbgeng!ProcessCommandsAndCatch
>> 10 dbgeng!Execute
>> 11 dbgeng!DebugClient::ExecuteWide
>> 12 windbg!ProcessCommand
>> 13 windbg!ProcessEngineCommands
>> 14 windbg!EngineLoop
>> 15 KERNEL32!BaseThreadInitThunk
>> 16 ntdll!RtlUserThreadStart
>>
>> HRESULT OutputStackTrace(
>> [in] ULONG OutputControl,
>> [in, optional] PDEBUG_STACK_FRAME Frames,
>> [in] ULONG FramesSize,
>> [in] ULONG Flags
>> );
>>
>> mov dword ptr [rsp+20h],0Dh <<== Flags == 0xD
>> mov rax,qword ptr [rcx]
>> mov rax,qword ptr [rax+108h]
>> call qword ptr [ext!_guard_dispatch_icall_fptr
>> (00007ffe`7867dd20)]
>>
>> So, doesn’t look like there’s a way to set this as part of running
>> !analyze
>>
>> command.
>>
>> -scott
>> OSR
>>
>>
>> —
>> WINDBG is sponsored by OSR
>>
>> OSR is hiring!! Info at http://www.osr.com/careers
>>
>>
>> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
>> software
>> drivers!
>> Details at http:
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http:
>>
></http:></http:>