Search code examples
windbgconditional-breakpoint

How to set conditional breakpoin based on parameter value using windbg


I want to set a conditional breakpoint based on a member of one parameter, Now I can use command dt to check this parameter, My code looks like this:

void test(const MyClassB &inst, int value)
{
}

Now I can use the dt command to view the first parameter, the result:

0:000:x86> dt MyClassB @esp+4
dbgee!MyClassB
   +0x000 id               : (null) 
   +0x004 m                : 0n2130567168
   +0x008 myClassA         : MyClassA

Now I want to set a conditional breakpoint on this method based on the value of inst.m, anybody can show me how to do that? Thanks a bunch!

And It's appreciated if anybody can give some information about how to use the offset(such as +0x004 for m), thanks!


Solution

  • Snippet Compiled with cl /Zi /nologo /W4 /analyze %1% /link /RELEASE in msvc++2010exp

     #include <stdio.h>
        class MyClass {
            int width,length;
        public:
            void set_val(int,int);
            int  area(); 
        };
        void MyClass::set_val(int x , int y) {
            width  = x;
            length = y;
        }
        int MyClass::area() {
            return width*length;
        }
        void main(void) {  
            MyClass foo;
            for (int i = 0; i < 10; i++) {
                foo.set_val(i,5);
                printf("%d\n",foo.area());
            }
        }
    

    In windbg to set a conditional breakpoint on set_val() to break when width == 7

    Conditional Breakpoint syntax Explanation

    classtest!MyClass::set_val <module!class::method>
    @@c++() using c++ expression evaluator
    @ecx holds the this pointer suitably type casted to MyClass *
    width is a member of MyClass
    we use 6 for comparison purpose in this demo
    as we are setting break point prior to execution of set_val() method
    (notice the uninitialized garbage when printing the first time
    gc go from condition after displaying MyClass if width != 7
    .else is implied to break when width == 7

    command should be in one line

    bp classtest!MyClass::set_val    
    ".if( @@c++((((MyClass *) @ecx )->width)) != 6 ) {dt MyClass @ecx ; gc }"
    

    results

    0:000> bp classtest!MyClass::set_val ".if( @@c++((((MyClass *) @ecx )->width)) != 6 ) {dt MyClass @ecx ; gc }"
    0:000> bl
     0 e 00401000     0001 (0001)  0:**** classtest!MyClass::set_val ".if( @@c++((((MyClass *) @ecx )->width)) != 6 ) {dt MyClass @ecx ; gc }"
    0:000> g
    ModLoad: 5cb70000 5cb96000   C:\WINDOWS\system32\ShimEng.dll
    classtest!MyClass
       +0x000 width            : 0n4205541
       +0x004 length           : 0n4208683
    classtest!MyClass
       +0x000 width            : 0n0
       +0x004 length           : 0n5
    classtest!MyClass
       +0x000 width            : 0n1
       +0x004 length           : 0n5
    classtest!MyClass
       +0x000 width            : 0n2
       +0x004 length           : 0n5
    classtest!MyClass
       +0x000 width            : 0n3
       +0x004 length           : 0n5
    classtest!MyClass
       +0x000 width            : 0n4
       +0x004 length           : 0n5
    classtest!MyClass
       +0x000 width            : 0n5
       +0x004 length           : 0n5
    eax=00000007 ebx=7ffdf000 ecx=0013ff70 edx=00416680 esi=00000000 edi=0098f6ee
    eip=00401000 esp=0013ff60 ebp=0013ff78 iopl=0         nv up ei ng nz ac po cy
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000293
    classtest!MyClass::set_val:
    00401000 55              push    ebp
    0:000> dd esp l3
    0013ff60  0040106c 00000007 00000005
    0:000> x @eip
    0:000> ?? @eip
    unsigned int 0x401000
    0:000> lsa . 0,1
    >    8: void MyClass::set_val(int x , int y) {
    0:000> dv
               this = 0xfffffffe
                  x = 0n7
                  y = 0n5