windbg條件斷點總結


1 .  條件斷點是斷點命令 ( bp 或者 bu ) 與j命令或者.if命令一起使用的,后面跟着一個gc命令

     0:000> bp Address "j (Condition) 'OptionalCommands'; 'gc' "

     0:000> bp Address ".if (Condition) {OptionalCommands} .else {gc}"

 

2.      這里說下j命令,j命令的語法如下, 這里的Expression是表達式,通過計算表達式的值,TRUE就指向Command1,  FALSE指向Command2

          j Expression Command1 ; Command2 
     j Expression 'Command1' ; 'Command2

   這里也可以使用多個命令,多個命令用單引號' ' 包含,並且用分號 ; 分隔開, 如果命令字符串有一個,那么單引號也可以省略

     Command2后面不能添加額外的命令或者增加多余的分號,就算你添加了,Command2分號后面的值也會被忽略

 

     0:000> j (MySymbol=0) 'r eax'; 'r ebx; r ecx'    如果MySymbol為0,執行r eax, 否則執行r ebx   r ecx

         你可以省略在r eax附加的單引號,如果你想忽略命令,就直接使用空格來作為標記

      0:000> j (MySymbol=0) ''; 'r ebx; r ecx' 
    0:000> j (MySymbol=0)  ; 'r ebx; r ecx' 

          你也可以在其他命令中使用j命令,比如,你可以使用j命令來創建一個條件斷點

      0:000> bp `mysource.cpp:143` "j (poi(MyVar)>0n20) ''; 'gc' "

 

3.      這里倆說說z命令  z (Execute While), 當條件成立時,z命令會執行一個命令

    User-Mode

        Command ; z( Expression ) 

         Kernel-Mode

         Command ; [Processor] z( Expression ) 

   Command: 當表達式條件為真的時候,命令最少執行一次

   在許多調試器命令中,分號都是用於分割不相關的命令,在z命令中,分號從命令參數中分割Z命令

   Command命令總是至少執行一次,當表達式檢測到非零時,命令再次被執行,然后表達式再次被檢測,這個行為類似於C語言的do-while循環,並不是簡單的while循環

       如果"z"左側有很多分號分開的命令,那么當表達式為真的時候,z左側所有的命令都將被執行

       如果z之后添加其他分號和額外的命令,這些額外的命令將會在lopp完成后執行,但是通常不建議這樣做, 因為他會產生無意義的輸出

       除非因為其他行為表達式變成FALSE

       注意,你可以嵌套Z命令

       下面的代碼展示一中eax寄存器清零的方法

  0:000> reax = eax - 1 ; z(eax)

       下面的代碼展示了eax和ebx寄存器遞增,直到他們中的一個至少是8,然后ecx寄存器+1

       0:000> reax=eax+1; rebx=ebx+1; z((eax<8)|(ebx<8)); recx=ecx+1   (來這里理解成do-while  更容易理解)

      下面例子使用C++表達式語法,然后使用$t0為寄存器作為循環變量

      0:000> .expr /s c++
      Current expression evaluator: C++ - C++ source expressions

      db pindexcreate[@$t0].szKey; r$t0=@t0+1; z( @$t0 < cIndexCreate )

 

4.   這里說說.if 標記(token)

  .if (Condition) { Commands } 

  .if (Condition) { Commands } .else { Commands } 

  .if (Condition) { Commands } .elsif (Condition) { Commands } 

  .if (Condition) { Commands } .elsif (Condition) { Commands } .else { Commands }

  Condition: 如果條件計算后值為0的話,就作為false,否則作為true, 括號中的條件是可選的,條件必須是表達式,不能是調試器命令,它將被MASM或者C++語法計算

       Commands:按條件執行一個或多個命令,命令塊需要包括在大括號中,即使里面只有一個命令,多個命令應該由分號分隔開,但是最后一個命令則不需要用分號

 

5.   這里說說gc命令( Go from Conditional Breakpoint )

      gc命令從條件斷點中恢復執行,與命中斷點的方法相同

      當一個條件斷點的末尾包含一個執行命令的時候,這應該是gc命令

      0:000> bp Address "j (Condition) 'OptionalCommands'; 'gc' " 

      當表達式為FALSE,並且遇到斷點的話,將使用與上次相同的類型繼續執行,比如你用g命令遇到了這個斷點,將恢復執行,但是當你單步到這里的時候,gc將以單步的方式恢復執行

     另外,下面是個不正確的斷點公式,將總是恢復執行,即使你在遇到斷點前正在單步

    0:000> bp Address "j (Condition) 'OptionalCommands'; 'g' " 

 

6.   使用J命令的條件斷點的基本語法如下:

        0:000> bp Address "j (Condition) 'OptionalCommands'; 'gc' "

     使用.if標記的條件斷點的語法如下:

        0:000> bp Address ".if (Condition) {OptionalCommands} .else {gc}"

     下面的命令設置了一個斷點在Mysourc.dpp文件的143行,當觸發這個斷點后,會檢測MyVar這個變量,如果這個變量小於等於20,就繼續執行,如果大於20,就停止執行  

       0:000> bp `mysource.cpp:143` "j (poi(MyVar)>0n20) '  '; 'gc' " 
  0:000> bp `mysource.cpp:143` ".if (poi(MyVar)>0n20) {} .else {gc}"

      這里解釋一波

     bp命令是設置斷點,即使上面這兩個例子使用的是bp,你仍然可以用bu命令

     源文件和行數是用~指定的

     當斷點觸發后,雙引號" "中的命令將被執行,上面的例子中,命令是j命令或者.if標記,在括號中測試表達式

     在源程序中,MyVar是一個整數,如果你使用C++語法,MyVar將作為一個整數,在這個例子中( 已經默認的調試器配置中 )使用MASM表達式語法,

     在MASM表達式中,MyVar被作為一個地址,因此你需要poi操作符來解引用它

     如果你的變量是一個C指針,那么你需要解引用兩次,像這樣poi(poi(MyPtr)), 0n前綴,代表這是個10進制

     括號中的表達式后面跟着兩個命令,j命令后面的是單引號' '保護,.if標記后面是尖括號{ }包含,如果表達式為真的話,第一個命令被執行,

     在上面的 例子中,第一個命令為空,因為不會執行命令,並且將控制交給調試器,如果括號中的表達式為FALSE,則第二個命令將被執行

    第二個命令應該盡量使用gc,因為這個命令會恢復執行,與上次觸發斷點前的方式一樣( 單步,步進,自由執行 )   

  

  如果要在每次傳遞斷點或最終命中時看到消息, 可以在單引號或大括號中使用其他命令。例如:

  0:000> bp `:143` "j (poi(MyVar)>5) '.echo MyVar Too Big'; '.echo MyVar Acceptable; gc' " 
  0:000> bp `:143` ".if (poi(MyVar)>5) {.echo MyVar Too Big} .else {.echo MyVar Acceptable; gc} " 

       這些注釋是很重要的,如果你有幾個斷點,同時觸發,調試器並不會顯示哪個斷點命中

 

7.    條件斷點和寄存器符號擴展

  你可以設置條件斷點在寄存器值上面,下面的命令將斷在myFunction函數的開始處,如果EAX寄存器等於0xA3

    0:000> bp mydriver!myFunction "j @eax = 0xa3  '';'gc'" 
    0:000> bp mydriver!myFunction ".if @eax = 0xa3  {} .else {gc}"

  注意,下面類似的命令並不一定會中斷,當eax等於0xC0004321的時候

    0:000> bp mydriver!myFunction "j @eax = 0xc0004321  '';'gc'" 
    0:000> bp mydriver!myFunction ".if @eax = 0xc0004321  {} .else {gc}"

        上面的命令會失敗,因為MASM表達式計算的符號擴展寄存器的高位為1,當eax的值為0xC0004321的時候,它將被作為0xFFFFFFFF~C0004321,

   但是並不是在用戶模式,因此前面的命令在用戶模式下,將無法正常工作,如果你屏蔽了eax的高位,命令將在內核模式下正常工作,但是現在,他在用戶模式將會失敗

      為了讓你的命令在用戶和內核模式下正常工作,在上面的命令中,你應該屏蔽高32位,通過AND操作符與運算0x00000000~FFFFFFFF

    0:000> bp mydriver!myFunction "j (@eax & 0x0`ffffffff) = 0x0`c0004321  '';'gc'" 
    0:000> bp mydriver!myFunction ".if (@eax & 0x0`ffffffff) = 0x0`c0004321  {} .else {gc}"

8.   條件斷點的局限

  如果你從內核調試器控制用戶態調試器,則不能使用條件斷點或其他任何斷點命令,比如gc命令 ,g命令,如果使用這些命令, 則串行接口可能無法保持斷點的數量, 並且您將無法中斷回CDB中


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM