Saturday, December 7, 2013

Debugging Map using Windbg

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 [-c "cmd"]

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();
}


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

No comments:

Post a Comment