Windbg 从 .foreach 值解析变量

Windbg parse variable from .foreach value

正在 WinDbg 中执行下一个命令

.foreach (function_name {x /1 JittyProject!*}) {.echo function_name}

结果应该是

JittyProject!ApplyAsync
....

是否有可能以某种方式从一个变量 JittyProject 中的 function_name 解析到另一个 ApplyAsync

!for_each_function 过去和现在都是越野车
它需要私有 pdbs
如果您使用未记录的 -f 开关强制它使用 public pdbs
它将无限期挂起,直到您终止 windbg

从 .foreach 输出中解析完整的字符串是 PITA

基本上函数名可以而且确实包含 spaces
.foreach 将每个 space 视为分隔符 所以它会把一个函数名分成多个标记

并且 .foreach 不支持 ctrl+c 或 ctrl+break 或 alt+delete 因此它将继续喷出毒液直到它死去

如果你可以使用最新的 windbg,我建议你切换到 javascript 或 natvis

下面是仅使用 dx natvis 表达式计算器的输出

执行命令并将结果数组获取到用户变量中

dx @$foo = Debugger.Utility.Control.ExecuteCommand("x /1 calc!*")

上面数组的一些示例成员(注意下面的最后一个条目有很多 space 和
.foreach 会将其切成 spaces )

0:000> dx -r0 @$foo[4]
@$foo[4]         : calc!CContainer::ToggleHistoryFunc
0:000> dx -r0 @$foo[101]
@$foo[101]       : calc!`ATL::CAtlRECharTraitsW::GetAbbrevs'::`2'::s_szAbbrevs
0:000> dx -r0 @$foo[861]
@$foo[861]       : calc!ATL::AtlAdd<unsigned int>
0:000> dx -r0 @$foo[1684]
@$foo[1684]      : calc!ATL::CAtlMap<ATL::CStringT<unsigned short,ATL::StrTraitATL<unsigned short,ATL::ChTraitsCRT<unsigned short> > > *,FORMULA_DEFINTION *,MyCStringPtrTrait,ATL::CElementTraits<FORMULA_DEFINTION *> >::GetKeyAt

数组中有 2925 或 0xb6d 个函数

0:000> dx @$foo.Count(),x; dx @$foo.Count(),d
@$foo.Count(),x  : 0xb6d
@$foo.Count(),d  : 2925



0:000> dx -r0 @$foo[2925]
Error: <Unable to get error code text> (0x8000000b) <<< out of bounds
0:000> dx -r0 @$foo[2924]
@$foo[2924]      : calc!Gdiplus::Image::`vector deleting destructor'

现在你有了一个数组,你可以使用 !作为分隔符

0:000> dx -r1 @$foo.Select(p=> new{ Module = p.Substring(0,p.IndexOf("!")), FName = p.Substring(p.IndexOf("!")) })[2924]
@$foo.Select(p=> new{ Module = p.Substring(0,p.IndexOf("!")), FName = p.Substring(p.IndexOf("!")) })[2924]                
    Module           : calc
    FName            : !Gdiplus::Image::`vector deleting destructor'


0:000> dx -r1 @$foo.Select(p=> new{ Module = p.Substring(0,p.IndexOf("!")), FName = p.Substring(p.IndexOf("!")) })[864]
@$foo.Select(p=> new{ Module = p.Substring(0,p.IndexOf("!")), FName = p.Substring(p.IndexOf("!")) })[864]                
    Module           : calc
    FName            : !_real


0:000> dx -r1 @$foo.Select(p=> new{ Module = p.Substring(0,p.IndexOf("!")), FName = p.Substring(p.IndexOf("!")) })[1684]
@$foo.Select(p=> new{ Module = p.Substring(0,p.IndexOf("!")), FName = p.Substring(p.IndexOf("!")) })[1684]                
    Module           : calc
    FName            : !ATL::CAtlMap<ATL::CStringT<unsigned short,ATL::StrTraitATL<unsigned short,ATL::ChTraitsCRT<unsigned short> > > *,FORMULA_DEFINTION *,MyCStringPtrTrait,ATL::CElementTraits<FORMULA_DEFINTION *> >::GetKeyAt

或从所有加载的模块中获取所有函数名称

0:000> dx @$foo = Debugger.Utility.Control.ExecuteCommand("x /1 *!*")
0:000> dx @$foo.Count()
@$foo.Count()    : 0x1d4b9
0:000> dx -r1 @$foo.Select(p=> new{ Module = p.Substring(0,p.IndexOf("!")), FName = p.Substring(p.IndexOf("!")+1) })[15084]
    Module           : COMCTL32
    FName            : CCalendar::_DateSetMax

这个包含 11993 个函数的庞大数组的模块

0:000> dx -r1 @$foo.Select(p=>p.Substring(0,p.IndexOf("!"))).Distinct()
@$foo.Select(p=>p.Substring(0,p.IndexOf("!"))).Distinct()                
    [0x0]            : SharedUserData
    [0x1]            : calc
    [0x2]            : WINMM
    [0x3]            : gdiplus
    [0x4]            : UxTheme
    [0x5]            : COMCTL32
    [0x6]            : VERSION
    [0x7]            : KERNELBASE
    [0x8]            : msvcrt
    [0x9]            : GDI32
    [0xa]            : USER32
    [0xb]            : LPK
    [0xc]            : OLEAUT32
    [0xd]            : ADVAPI32
    [0xe]            : SHLWAPI
    [0xf]            : USP10
    [0x10]           : SHELL32
    [0x11]           : RPCRT4
    [0x12]           : kernel32
    [0x13]           : ole32
    [0x14]           : ntdll
    [0x15]           : sechost