2016-06-09 30 views
0

假設我想調試使用WinDbg的,國開行,或NTSD調試此程序爲Windows:在WinDbg命令中,如何引用與全局變量同名的寄存器?

/* test.c */ 
#include <stdio.h> 

int rip = 42; 

int main(void) 
{ 
    puts("Hello world!"); 
    return (0); 
} 

我編譯AMD64程序和WinDbg的下運行它。我在main()處設置了一個斷點,並且當斷點遇到時,我想檢查RIP寄存器(程序計數器)處的值,以及該值作爲指針處理時的值。

我可以看到寄存器的值直接與r rip,但是當我嘗試看看該地址周圍的內存,WinDbg中顯示我不同的地址!讀過test.pdb中的符號後,WinDbg發現rip是一個在C代碼中聲明的全局變量,它顯示了&rip左右的內存。

0:000> bu test!main 

0:000> g 
Breakpoint 0 hit 
test!main: 
00007ff6`de1868d0 4883ec28  sub  rsp,28h 

0:000> r rip 
rip=00007ff6de1868d0 

0:000> db rip 
00007ff6`de1f2000 2a 00 00 00 ff ff ff ff-01 00 00 00 00 00 00 00 *............... 
00007ff6`de1f2010 01 00 00 00 02 00 00 00-ff ff ff ff ff ff ff ff ................ 
00007ff6`de1f2020 00 00 00 00 00 00 00 00-43 46 92 e5 1b df 00 00 ........CF...... 
00007ff6`de1f2030 bc b9 6d 1a e4 20 ff ff-00 00 00 00 00 00 00 00 ..m.. .......... 
00007ff6`de1f2040 00 01 00 00 00 00 00 00-ca b0 1e de f6 7f 00 00 ................ 
00007ff6`de1f2050 00 00 00 00 00 80 00 00-00 00 00 00 00 80 00 00 ................ 
00007ff6`de1f2060 d0 66 fc c2 f2 01 03 00-ab 90 ec 5e 22 c0 b2 44 .f.........^"..D 
00007ff6`de1f2070 a5 dd fd 71 6a 22 2a 15-00 00 00 00 00 00 00 00 ...qj"*......... 

0:000> ? rip 
Evaluate expression: 140698265264128 = 00007ff6`de1f2000 

0:000> ? dwo(rip) 
Evaluate expression: 42 = 00000000`0000002a 

這真的很煩人,但只要我意識到這一點,當手動讀取這樣的數據時,這不是問題。但是,如果我想使用寄存器的值,例如在腳本調試器,那麼有沒有簡單的解決方法:

0:000> bu test!main ".if (dwo(rip) == 0n42) { .echo Whoops! I don't want to get here! }" 

0:000> g 
Whoops! I don't want to get here! 
test!main: 
00007ff6`de1868d0 4883ec28  sub  rsp,28h 

這個問題,即在程序中隱藏寄存器名稱符號,使事情真的很難我。一個實際的情況:

  1. 我想在CreateFileW()上設置一個斷點,這是一個非常常用的Windows API函數。
  2. 由於我只關心一個特定的文件,我想檢查在RCX寄存器中傳遞的文件名,並繼續經過斷點,除非文件名與我想要的文件匹配。
  3. 但是我不能寫這個條件,因爲程序中的另一個模塊定義了一個符號foobar!rcx,並且我在命令中指定的所有對rcx的引用都指向該全局變量!

那麼我該如何告訴WinDbg:是的,我真的想讀取寄存器?如果我想寫這個寄存器呢?我在這裏必須有一件簡單的事情。

+1

if dwo(@rip)== xx做一些其他的事情如果qwo(@rcx)!= foobar!rcx做一些其他的事情.else gotosleep()@rcx = register rcx whereeas foobar!rcx或簡單的rcx是一個全球性的 – blabb

回答

5

正如在傳遞another question時指出的那樣,您可以在寄存器名稱的前面加上一個符號(@),以強制它被解釋爲寄存器或僞寄存器,繞過嘗試將其解析爲十六進制數字或一個符號。

Registers and Pseudo-Registers in MASM Expressions

您可以使用MASM表達式中的寄存器和僞寄存器。 您可以在所有寄存器和僞寄存器之前添加at符號(@)。 at符號使調試器更快地訪問該值。對於最常見的基於x86的寄存器,這個符號是不必要的。對於其他寄存器和僞寄存器,我們建議您添加at符號,但實際上並不需要。如果省略不常用寄存器的at符號,調試器會嘗試將文本解析爲十六進制數字,然後將其作爲符號,最後作爲寄存器。

+2

我會進一步說,因爲它在MASM語法中速度更快(例如,如果您可以跳過在所有模塊中搜索符號,其中一個是Chrome的900MB PDB),並且在C++語法中是強制性的,這是一個很好的習慣** **總是**將寄存器名稱預先加上'@'。我現在幾乎自動地做到這一點,每當我忘記它並盯着'* BUSY *'消息(即使只是幾秒鐘),我也會爲此而毆打自己。 – conio

+0

@conio絕對。 '@'對我來說也是本能的。 –