Windbg脚本和扩展工具之一STL容器扩展命令
--by solidmango
想写一篇关于windbg的STL容器扩展命令的文章已经有一段时间了,但是最近项目比较忙,再加上有几本书特别想读,所以就耽误下来了,以至于整个三月都没来得及写,今天终于有时间可以把这篇文章写完。至于windbg和STL都是什么在这里我就不细说了,能打开我这篇文章的想必都是行家,那么我为什么想写着么一个主题的文章呢?
STL容器在调试的时候内部实现相对来说还是比较复杂的,而在某些生产情况下和一些极端的问题分析的时候visual studio 是登不了大雅之堂的,当然我不是说vs不好,在很多时候他是神器,但是它不是万能的。
举个例子:
如下类型的map
std::map<int,string>
实际的内部节点类型可能是这样的:
std::_Tree_nod<std::_Tmap_traits<int,std::basic_string<char,std::char_traits<char>,
std::allocator<char>>,
std::less<int>,
std::allocator<
std::pair<
int const , std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >,0> >::_Node
STL内部traits的应用遍地都是,但是甚至好多谢了好久代码的人可能都还是理解不了其巧妙之处。可能是由于其实现相对比较复杂,windbg内部的和现有的扩展对这块的调试支持都相对较差,当然如果你是高手,在某些简单的情况下,这块是有方法绕过去的,但是问题如果想对复杂就恐怕不行了。
那么我都做了什呢?我实现了如下的几个扩展命令,只要给出地址和类型就可以将整个容器打出来。
0:000> !help
PRTSTLMap <Address> Type
PRTSTLMap2 <Address> Type
PRTSTLList <Address> Type
PRTSTLVector <Address> Type
详细的每个命令的使用情况请参照如下的demo:
如下为!PRTSTLMap使用方法:
0:000>!PRTSTLMap (0x0012fd14+0x194) std::pair,std::allocator > >Size of map is: 5TestSTLMap!std::pair ,std::allocator > > +0x000 first : 11 +0x004 second : std::basic_string ,std::allocator > +0x000 _Alval : std::allocator =00400000 npos : 0x905a4d +0x004 _Bx : std::basic_string ,std::allocator >::_Bxty +0x000 _Buf : [16] "aaa" +0x000 _Ptr : 0x00616161 "" +0x014 _Mysize : 3 +0x018 _Myres : 0xfTestSTLMap!std::pair ,std::allocator > > +0x000 first : 12 +0x004 second : std::basic_string ,std::allocator > +0x000 _Alval : std::allocator =00400000 npos : 0x905a4d +0x004 _Bx : std::basic_string ,std::allocator >::_Bxty +0x000 _Buf : [16] "bbb" +0x000 _Ptr : 0x00626262 "" +0x014 _Mysize : 3 +0x018 _Myres : 0xfTestSTLMap!std::pair ,std::allocator > > +0x000 first : 13 +0x004 second : std::basic_string ,std::allocator > +0x000 _Alval : std::allocator =00400000 npos : 0x905a4d +0x004 _Bx : std::basic_string ,std::allocator >::_Bxty +0x000 _Buf : [16] "ccc" +0x000 _Ptr : 0x00636363 "w" +0x014 _Mysize : 3 +0x018 _Myres : 0xfTestSTLMap!std::pair ,std::allocator > > +0x000 first : 14 +0x004 second : std::basic_string ,std::allocator > +0x000 _Alval : std::allocator =00400000 npos : 0x905a4d +0x004 _Bx : std::basic_string ,std::allocator >::_Bxty +0x000 _Buf : [16] "dddd" +0x000 _Ptr : 0x64646464 "--- memory read error at address 0x64646464 ---" +0x014 _Mysize : 4 +0x018 _Myres : 0xfTestSTLMap!std::pair ,std::allocator > > +0x000 first : 15 +0x004 second : std::basic_string ,std::allocator > +0x000 _Alval : std::allocator =00400000 npos : 0x905a4d +0x004 _Bx : std::basic_string ,std::allocator >::_Bxty +0x000 _Buf : [16] "eeeee" +0x000 _Ptr : 0x65656565 "--- memory read error at address 0x65656565 ---" +0x014 _Mysize : 5 +0x018 _Myres : 0xf
如下为扩展名伶!PRTSTLList的使用方法:
0:000> !PRTSTLList (0x0012fd14+0x178) CPoint Size of list is: 3TestSTLMap!CPoint +0x000 x : 7 +0x004 y : 8TestSTLMap!CPoint +0x000 x : 4 +0x004 y : 6TestSTLMap!CPoint +0x000 x : 6 +0x004 y : 9
如下为扩展名伶! PRTSTLVector的使用方法:
0:000> !PRTSTLVector (0x0012fd14+0x1d4) CPointSize of Vector is: 6TestSTLMap!CPoint +0x000 x : 17 +0x004 y : 88TestSTLMap!CPoint +0x000 x : 16 +0x004 y : 87TestSTLMap!CPoint +0x000 x : 15 +0x004 y : 86TestSTLMap!CPoint +0x000 x : 14 +0x004 y : 85TestSTLMap!CPoint +0x000 x : 13 +0x004 y : 84TestSTLMap!CPoint +0x000 x : 12 +0x004 y : 83
总结
本文实现了几种扩展WINDBG STL调试支持的扩展命令,旨在方便STL调试,算是抛砖引玉,希望打开大家的视野,其实好多时候在某些领域我们是可以做一些事情的,不要总跟在老外的后面走,由于需要使用这些扩展命令的人不多,本文不会附上相关的扩展文件,如果有人需要,请私信。