Windbg 腳本命令簡介 二, Windbg command


 

Windbg  腳本命令簡介 二, Windbg  script command

 

 

$<, $><, $$<, $$><, $$>a< (Run Script File)

 

Sample1.txt文件內容:

.echo The first argument is ${$arg1}.

.echo The fifth argument is ${$arg5}.

.echo The fourth argument is ${$arg4}.

 

 

 

0:000> $$>a<"E:\.net Memory Windbg drill into\scripts\sample1.txt"  abc  "I am ok" "how" "are you" ;rrax

The first argument is abc.

The fifth argument is ${$arg5}.

The fourth argument is are you.

rax=000007fefb309d01

 

腳本路徑中帶空格,需要加引號,參數中帶空格,需要加引號,參數間以空格分開,分號是命令的分割,后面的rrax是第二個命令,而不是第五個參數,rrax或 r rax是顯示rax寄存器的值。

第五個參數沒有傳入,則顯示 “${$arg5}” 這個字面值

 

Token

是否允許文件名中帶分號

是否鏈接以分號分隔的其他命令

是否壓縮到單一行的命令塊

是否允許帶參數

$<

Yes

No

No

No

$><

Yes

No

Yes

No

$$<

No

Yes

No

No

$$><

No

Yes

Yes

No

$$>a<

No

Yes

Yes

Yes

 

1.把所有語句寫在腳本文件的單行中,每個語句和命令之間用分號隔開,然后用$><命令去運行腳本

2.在腳本文件中輸入所有語句,每條語句占一行,然后使用$><命令運行腳本,這些命令會打開腳本文件,用分號替換所有的回車符,然后把結果文件當作單一的命令塊執行.

 

如果文件名中帶分號,則后面就不允許帶上以分號分隔的命令了。但有一種例外,就是

 

Sample1.txt:

.echo the first arg:${$arg1}

.echo I am working

kb

!dumpheap -type HttpRuntime

 

 

0:000> $$>< c:\sample1.txt ;rrax

 

 

 

 

 

 

~s (Set Current Thread)

設置當前線程:

例如 ~2s,則切換到2號線程 提示變為:0:002>

0:002> ~#s:切換到默認線程,提示變為:0:000>

默認線程是dump時正在工作的線程,如果是Crash,則最后發生crash的線程是當前工作線程。

 

 

 

Using Aliases

使用別名:

Alias=Expression

as aS:設置別名,Alias Set

ad:刪除別名 Alias Delete

al:列出所有別名 Aliases List

 

固定名字的內置別名:$u0$u1, ..., $u9

 

內置系統別名:大小寫敏感

0:000> .echo $ntnsym

Ntdll

0:000> .echo $CurrentDumpFile

E:\Ccppt.com\SVR858AppPoolHotel2\AppPoolHotel2.DMP

0:000> $CurrentDumpArchivePath

E:\Ccppt.com\SVR858AppPoolHotel2\AppPoolHotel2.DMP

 

0:000> as my 5+1

0:000> .echo my

5+1

 

 

as, aS (Set Alias)

0:000> aS /x myAlias 5 + 1; .block{.echo myAlias}

//設置myAlias為64bit的 6(5+1結果)

l  如果不用 任何開關,as 會認為該行后面的都是表達式。

         aS myAlias 5 + 1; .block{.echo myAlias}

new line 輸入:.echo myAlias //windbg崩潰

如果不用 .block { },輸出有問題,因為別名的值代入(展開別名的內容)發生在進入一個新的代碼塊時,使用 .block {} 使得產生一個新的代碼block,.echo myAlias在新代碼塊中,則myAlias已經展開。
0:001> aS /x myAlias 5 + 1; .echo myAlias
myAlias

 

0:000> as /c my !eeversion

0:000> .echo my

4.0.30319.296 free

Server mode with 8 gc heaps

SOS Version: 4.0.30319.586 retail build

 

//等價於直接命令 !eeversion

 

 

C:\Sample1.txt

.echo the first arg:${$arg1}

.echo I am working

kb

!dumpheap -type HttpRuntime

 

 

0:000> aS /f my c:\sample1.txt

0:000> .echo my

.echo the first arg:${$arg1}

.echo I am working

kb

!dumpheap -type HttpRuntime

 

//將別名設置為文件內容

 

 

 

 

0:000> ad my

          ^ No information found error in 'ad my'

0:000> ad /q my //刪除my別名,/q表示靜默模式,不提示錯誤

0:000> ad /q * //刪除所有別名

 

 

0:000> al

  Alias            Value 

 -------          -------

 my               0x5

// 列出所有別名

 

 

 

${ } (Alias Interpreter) 別名解釋器

Text ${Alias} Text 
 
Text ${/d:Alias} Text   
//根據別名當前是否已經定義計算出1或者0
 
Text ${/f:Alias} Text   
//如果別名當前已定義則等同於計算別名。如果別名已經定義,${/f:Alias} 被替換為等價的別名;如果別名沒有定義,${/f:Alias}被替換為空字符串
 
Text ${/n:Alias} Text 
//如果別名當前已定義則計算別名的名稱。如果別名已經定義,${/n:Alias}被替換為別名名稱;如果別名沒有定義,${/n:Alias}保留它字面上的值不替換
 
Text ${/v:Alias} Text 

//禁止對任何別名求值。不論別名是否已經定義,${/v:Alias} 總是保持它字面上的值

 

 

0:000> as /x my 5+1

0:000> .echo my

0x6

0:000> .echo i am myself

i am myself

0:000> .echo i am ${my}self //不需要空格

i am 0x6self

0:000> .echo i am my self  //需要有空格

i am 0x6 self

0:000> .echo ${/d:my}  // my被定義了,輸出1,如果my沒定義,則輸出0

1

0:000> .echo ${/f:my}  //解析別名

0x6

0:000> .echo ${/n:my}  //解析別名

my

0:000> .echo ${/v:my}  //永不解析,永輸出字面值

${/v:my}

0:000> ad /q *   //刪除所有別名

0:000> .echo ${/d:my}

0

0:000> .echo ${/f:my}  //沒有定義別名,輸出空字符串

 

0:000> .echo ${/n:my} //沒有定義別名,輸出字面值

${/n:my}

0:000> .echo ${/v:my} //永不解析,永輸出字面值

${/v:my}

 

 

 

 

 

 

Control Flow Tokens

.if

$$ 定義一個變量

as /x my 4

 

.if (${my}>5)

  {

       .printf "${my}";

  }

.elsif (…..)

{

}

.else

  {

       .printf "my value is not greater than 5";

  }

 

.foreach

 

0:000> .foreach /pS 2 /ps 4 /f ( place "d:\myfile.txt") { dds place }
00000000`ffa9fc48  f37c5888
00000000`ffa9fc4c  000007fe
00000000`ffa9fc50  00000000
00000000`ffa9fc54  00000000
…..

 

 

d:\myfile.txt的內容是:

00000000ffa50c98

00000000ffa9f9d8

00000000ffa9fc48

 

 

/pS:循環開始前,初始跳過的個數。

/ps:  循環中,每次迭代跳過的個數。

/f: 來自文件。

 

這里循環中 place的值是每次等於myfile.txt的一行,輸出第一個是myfile.txt 第三行,跳過前面2行,第二次是跳過4行,取第8行,依次13行、18行、23行。

.foreach [Options] ( Variable  { InCommands } ) { OutCommands } 
//從命令中獲取輸入
.foreach [Options] /s ( Variable  "InString" ) { OutCommands } 
//從string中獲取輸入
.foreach [Options] /f ( Variable  "InFile" ) { OutCommands }

//從文件中獲取輸入

 

 

 

.block

Commands ; .block { Commands } ; Commands 

 

 

 

.printf

類似c語言的 printf

0:000> .printf /D "Click <link cmd=\".chain /D\">here</link> to see extensions DLLs."

Click here to see extensions DLLs.0:000> .chain /D

 

/D DML debug xml格式輸出

 

 

 

 

.catch{ }

Commands ; .catch { Commands } ; Commands 

 

類似.block 塊,在catch中的command遇到錯誤時,catch塊中的其他command不會執行,但花括號外面的緊接着catch塊的代碼還會繼續執行。

如果不用.catch { } 整個commands都會停止執行。

 

.break .continue .leave

 

.catch { ... ; .if (Condition) .leave ; ... } 

.leave :離開 catch塊

 

.break //跳出循環

.for (...) { ... ; .if (Condition) .break ; ...} 
 
.while (...) { ... ; .if (Condition) .break ; ...} 
 
.do { ... ; .if (Condition) .break ; ...} (...) 

 

.continue //繼續下一次循環

.for (...) { ... ; .if (Condition) .continue ; ... } 
 
.while (...) { ... ; .if (Condition) .continue ; ... } 
 
.do { ... ; .if (Condition) .continue ; ... } (...) 

 

 

 

 

 

 

 

 

$$ (Comment)

注釋 comments

 

 

r eax; $$ some text; r ebx; * more text; r ecx // * 號后的行內 內容全部是注釋
r eax; $$ some text; r ebx; * more text; r ecx // $$ 后 ; 前的行內 內容是注釋。

// 黃色內容會執行

 

 

 

 

 

 

 

 

 

 

Pseudo-Register Syntax

(偽寄存器)

http://msdn.microsoft.com/en-us/library/ff553485(v=vs.85).aspx

許多寄存器的名字取決於處理器的架構, 因此對於那些偶爾使用調試器的用戶來說很難記住所有平台上的寄存器名字. 為了克服這個問題, 調試器的開發團隊引入了各種偽寄存器(Pseudo-Register), 由調試器將這些偽寄存器對應到不同的硬件架構上.

例如:

  • $ip: 指令指針寄存器;
    • x86上, $ip = eip
    • x64上, $ip = rip
    • Itanium上, $ip = iip

 

所有偽寄存器都以$符號開始,如果使用MASM(微軟宏匯編語言),可以在$符號前加一個@符號。這個@符號告訴調試器,這是一個(偽)寄存器,它不是一個symbol符號。不需要到符號表里去查找這個符號。這樣速度會快很多。

0:000> ? $exp
*** ERROR: Module load completed but symbols could not be loaded for …

Evaluate expression: 143 = 0000008f
0:000> ? @$exp
Evaluate expression: 143 = 0000008f

 

這兩個命令是一樣的,但是第一個要慢很多,它會查找symbol,有時候會看到這樣的提示:

*** ERROR: Module load completed but symbols could not be loaded for

說明它要查找symbol符號文件去找這個符號。

如果有一個符號跟這個偽寄存器的名字一樣,那這里的偽寄存器必須你@符號必須添加。

如果調試器使用了C++的表達式結構,則這里的@符號也是必須的。調試器默認使用C++表達式結構。

0:000> r $t1 = @$t2 //將 $t2偽寄存器拷貝到$t1

 

 

User-Defined Pseudo-Registers

There are 20 user-defined pseudo-registers ($t0$t1, ..., $t19). These pseudo-register are variables that you can read and write through the debugger. You can store any integer value in these pseudo-registers. They can be especially useful as loop variables.

使用r來寫值

例子:

0:000> r $t0=7 //賦值
0:000> r $t1=128
0:000> ? @$t0+@$t1 //計算,MASM表達式結構
Evaluate expression: 135 = 00000000`00000087
0:000> ?? @$t0+@$t1 //計算,C++表達式結構
unsigned int64 0n135 //10進制顯示
0:000> n
base is 10
0:000> n 16 //換進制
base is 16
0:000> ?? @$t0+@$t1
unsigned int64 0x87 //16進制顯示
 

 

0:000> r? $t15 = * (UNICODE_STRING*) 0x12ffbc

 

偽寄存器的值總是Integer.可以使用 r 帶上 ? 開關,並傳入類型,這里的例子是將UNICODE_STRING**類型的0x12ffbc傳入$t15偽寄存器。

 

kd> bp /t @$thread nt!ntopenfile

在當前線程的 ntopenfile函數上設置斷點,每次當前線程調用該函數時都會觸發斷點,但其他線程運行該函數時不會觸發斷點。 $thread 是自動生成的系統偽寄存器。

 

 

 

 

 

.shell (Command Shell)

 

.shell -i InFile [-o OutFile [-e ErrFile]] [Options] ShellCommand

 

 

.shell -i - -ci "!do 0b62e790" FIND /c /i "<table" :說明,-i: 從文件輸入,

                                                                             - : 取消從文件輸入

                                                                             -ci:從后面的命令輸出作為輸入

                                                                        Find: Dos 命令查找 <table 這個字符串

 

“-”代替InFile,表示沒有輸入文件,with no space before the hyphen.

    “-”代替OutFile,表示沒有輸出,如果沒有“-o OutFile”表示默認輸出到Debug窗口, with no space before the hyphen.

       -e ErrFile 類似

 

-ci "Commands"

將 debug的命令作為輸入,多個命令以“;”分號分隔。

 

.shell命令之后的行內元素都被看作是windows shell命令,而不是debug命令,即使這些命令以分號分隔。Windows shell命令不應該以引號括起來。

 

 exit 或 .shell_quit 是退出shell模式, .shell 后面不跟參數則windbg進入shell模式。

 

.shell -i - -ci "~* e!clrstack" FIND  /I "Monitor.Enter"

 

//查找所有線程里的堆棧上是否有包含 Monitor.Enter的函數。一般可以用來看死鎖。

.shell -ci "~* e!clrstack" python.exe "E:\Ccppt.com\.net Memory Windbg drill into\scripts\py.py"

 

 

py.py

import sys

 

for y in (0,1,2,3):

       print (y)

 

for i in sys.argv[1:]:

       print (i)

 

 

.writemem

 

實例中,通過lm命令列出內存中加載的模塊列表,然后通過.writemem命令將其中的模塊存成文件。

 

 

0:000> lm

start    end        module name

010a0000 01124000   fibo     C (private pdb symbols) 

75270000 753a0000   kernel32   (deferred)            

754a0000 75546000   KERNELBASE   (deferred)            

774a0000 775f7000   ntdll      (export symbols)       ntdll.dll

0:000> ? 01124000-010a0000             //計算長度

Evaluate expression: 540672 = 00084000

0:000> .writemem c:\fibo.exe 010a0000 L 00084000

Writing 84000 bytes........................................................................................................................................................................................................................................................................

0:000> .writemem c:\fibo.exe 010a0000 (01124000-0x1)

Writing 84000 bytes........................................................................................................................................................................................................................................................................

 

.writemem可以通過以上兩種方式存儲文件,第一種是指定起始地址和長度,第二種是指定其實和終止地址。

 

 

 

 

 

 

 

 

 

 

 

參考資料:

http://hi.baidu.com/123_mu_tou_ren/item/62e2cf0590bb2b25a0312d16

http://hi.baidu.com/ju_feng/item/c61ab23d788c070bcfb9fe64

http://blogs.msdn.com/b/tess/archive/2007/09/12/debugging-script-dumping-out-current-and-recent-asp-net-requests.aspx

 

 

 

 

 

 


免責聲明!

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



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