Here is the script which we can use for displaying the MAP:
.if ($sicmp("${$arg1}", "-n") == 0) {
.if (@@(@$t0->_Isnil) == 0) {
.if (@$t2 == 1) {
.printf /D "%p \n", @$t0, @$t0
.printf "key = "
?? @$t0->_Myval.first
.printf "value = "
?? @$t0->_Myval.second
} .else {
r? $t9 = @$t0->_Myval
command
}
}
$$ Recurse into _Left, _Right unless they point to the root of the tree
.if (@@(@$t0->_Left) != @@(@$t1)) {
.push /r /q
r? $t0 = @$t0->_Left
$$>a< ${$arg0} -n
.pop /r /q
}
.if (@@(@$t0->_Right) != @@(@$t1)) {
.push /r /q
r? $t0 = @$t0->_Right
$$>a< ${$arg0} -n
.pop /r /q
}
} .else {
r? $t0 = ${$arg1}
.if (${/d:$arg2}) {
.if ($sicmp("${$arg2}", "-c") == 0) {
r $t2 = 0
aS ${/v:command} "${$arg3}"
}
} .else {
r $t2 = 1
aS ${/v:command} " "
}
.printf "size = %d\n", @@(@$t0._Mysize)
r? $t0 = @$t0._Myhead->_Parent
r? $t1 = @$t0->_Parent
$$>a< ${$arg0} -n
ad command
}
traverse_map.script
A WinDbg script that traverses std::map objects.
Usage:
$$>a< traverse_map.script
where cmd can reference @$t9, e.g. "?? @$t9.second" (this is the pair held by the map) and can also reference @$t0, which is the actual tree node pointer.
Examples:
$$>a< traverse_map.script my_map -c ".block { .echo ----; ?? @$t9.first; ?? @$t9.second; }"
$$>a< traverse_map.script m -c ".block { .if (@@(@$t9.first) == 8) { .echo ----; ?? @$t9.second } }"
$$>a< traverse_map.script my_map
Sample Program:-
class MapTest
{
public:
void PopulateMap();
private:
map m_Map1;
map m_Map2;
};
void MapTest::PopulateMap()
{
m_Map1[0] = 99;
m_Map1[1] = 100;
m_Map2[0] = wstring(L"Hello");
m_Map2[1] = wstring(L"World");
//stop the debugger here
__asm int 3
}
int _tmain(int argc, _TCHAR* argv[])
{
map mm;
mm[1] = 1;
mm[2] = 2;
//stop the debugger
__asm int 3
MapTest mt;
mt.PopulateMap();
.if ($sicmp("${$arg1}", "-n") == 0) {
.if (@@(@$t0->_Isnil) == 0) {
.if (@$t2 == 1) {
.printf /D "
.printf "key = "
?? @$t0->_Myval.first
.printf "value = "
?? @$t0->_Myval.second
} .else {
r? $t9 = @$t0->_Myval
command
}
}
$$ Recurse into _Left, _Right unless they point to the root of the tree
.if (@@(@$t0->_Left) != @@(@$t1)) {
.push /r /q
r? $t0 = @$t0->_Left
$$>a< ${$arg0} -n
.pop /r /q
}
.if (@@(@$t0->_Right) != @@(@$t1)) {
.push /r /q
r? $t0 = @$t0->_Right
$$>a< ${$arg0} -n
.pop /r /q
}
} .else {
r? $t0 = ${$arg1}
.if (${/d:$arg2}) {
.if ($sicmp("${$arg2}", "-c") == 0) {
r $t2 = 0
aS ${/v:command} "${$arg3}"
}
} .else {
r $t2 = 1
aS ${/v:command} " "
}
.printf "size = %d\n", @@(@$t0._Mysize)
r? $t0 = @$t0._Myhead->_Parent
r? $t1 = @$t0->_Parent
$$>a< ${$arg0} -n
ad command
}
traverse_map.script
A WinDbg script that traverses std::map objects.
Usage:
$$>a< traverse_map.script
where cmd can reference @$t9, e.g. "?? @$t9.second" (this is the pair held by the map) and can also reference @$t0, which is the actual tree node pointer.
Examples:
$$>a< traverse_map.script my_map -c ".block { .echo ----; ?? @$t9.first; ?? @$t9.second; }"
$$>a< traverse_map.script m -c ".block { .if (@@(@$t9.first) == 8) { .echo ----; ?? @$t9.second } }"
$$>a< traverse_map.script my_map
Sample Program:-
class MapTest
{
public:
void PopulateMap();
private:
map
map
};
void MapTest::PopulateMap()
{
m_Map1[0] = 99;
m_Map1[1] = 100;
m_Map2[0] = wstring(L"Hello");
m_Map2[1] = wstring(L"World");
//stop the debugger here
__asm int 3
}
int _tmain(int argc, _TCHAR* argv[])
{
map
mm[1] = 1;
mm[2] = 2;
//stop the debugger
__asm int 3
MapTest mt;
mt.PopulateMap();
}
TestApp!wmain+0x8a:
0125203a 8d4d94 lea ecx,[ebp-6Ch]
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script mm
size = 2
002e8a48
key = int 0n1
value = int 0n1
002e8aa0
key = int 0n2
value = int 0n2
0:000> g
(2f68.2260): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=7efde000 ecx=8c2cadb9 edx=65a7d238 esi=001af620 edi=001af784
eip=01251f26 esp=001af620 ebp=001af790 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
TestApp!MapTest::PopulateMap+0x186:
01251f26 cc int 3
0:000> dv
this = 0x001af8ec
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script this->m_Map1
size = 2
002e8bc0
key = int 0n0
value = int 0n99
002e8c18
key = int 0n1
value = int 0n100
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script this->m_Map2
size = 2
002e8c70
key = int 0n0
value = class std::basic_string,std::allocator >
+0x000 _Myfirstiter : (null)
+0x004 _Alval : std::allocator
=01240000 npos : 0x905a4d
+0x008 _Bx : std::basic_string,std::allocator >::_Bxty
+0x018 _Mysize : 5
+0x01c _Myres : 7
002e8ce0
key = int 0n1
value = class std::basic_string,std::allocator >
+0x000 _Myfirstiter : (null)
+0x004 _Alval : std::allocator
=01240000 npos : 0x905a4d
+0x008 _Bx : std::basic_string,std::allocator >::_Bxty
+0x018 _Mysize : 5
+0x01c _Myres : 7
References:-
http://blogs.microsoft.co.il/sasha/2013/07/25/displaying-and-searching-stdmap-contents-in-windbg/
https://github.com/goldshtn/windbg-extensions