1. 程式人生 > >windbg條件斷點總結

windbg條件斷點總結

int 似的 正在 and 控制 清零 並不會 完成後 while

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 ExpressionCommand1‘ ; ‘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中

windbg條件斷點總結