2008-09-24 12 views
45

Tôi đã nhận ra rằng Windbg là một trình gỡ lỗi rất mạnh mẽ cho nền tảng Windows & Tôi học được điều gì đó mới mẻ về nó một lần trong một thời gian. Người dùng Windbg có thể chia sẻ một số kỹ năng điên rồ của họ không?Mẹo/thủ thuật Windbg yêu thích của bạn là gì?

ps: Tôi không tìm kiếm một lệnh tiện lợi, chúng có thể được tìm thấy trong tài liệu. Làm thế nào về chia sẻ lời khuyên về làm một cái gì đó mà người ta không thể tưởng tượng khác có thể được thực hiện với windbg? ví dụ. Một số cách để tạo ra số liệu thống kê về phân bổ bộ nhớ khi một tiến trình được chạy dưới windbg.

Trả lời

27

Yêu thích của tôi là lệnh .cmdtree <file> (không có giấy tờ, nhưng được tham chiếu trong ghi chú phát hành trước đó). Điều này có thể hỗ trợ trong việc đưa lên một cửa sổ khác (có thể được cập nhật) để hiển thị các lệnh hữu ích hoặc thường được sử dụng. Điều này có thể giúp người dùng sử dụng công cụ hiệu quả hơn nhiều.

Ban đầu nói về đây, với một ví dụ cho <file> tham số: http://blogs.msdn.com/debuggingtoolbox/archive/2008/09/17/special-command-execute-commands-from-a-customized-user-interface-with-cmdtree.aspx

Ví dụ: alt text http://blogs.msdn.com/photos/debuggingtoolbox/images/8954736/original.aspx

+4

donnot biết tại sao, nhưng có vẻ như không có sẵn trong WinDbg: 6.12.0002.633, khi bước vào .cmdtree tệp trợ giúp bật lên. –

+4

Thông số tệp có được bao gồm không? Tôi đã sử dụng cùng một phiên bản WinDbg với lệnh đó thành công. –

+0

bạn đã đúng, tôi đã bỏ lỡ thông số tệp. –

18

Lệnh sau đi rất tiện dụng khi tìm kiếm trên stack cho C++ đối tượng với vtables, đặc biệt là khi làm việc với bản phát hành khi một vài thứ được tối ưu hóa.

DPP đặc biệt Phạm vi


Có thể tải một file PE tùy ý như bãi là gọn gàng:

windbg -z mylib.dll


Query GetLastError() với:

gle


Điều này giúp giải mã các mã lỗi thường gặp:

lỗi ERROR_NUMBER
+1

dpp - tốt nhất, cảm ơn. – user15071

+0

dpp - trình tiết kiệm cuộc sống! , cảm ơn nhiều!!! – Tal

+0

cảm ơn rất nhiều vì những lời khuyên –

15

Hầu như 60% các lệnh tôi sử dụng hàng ngày ..

dv /i /t 
?? this 
kM (kinda undocumented) generates links to frames 
.frame x 
!analyze -v 
!lmi 
~ 
+2

Wow. kM khá tuyệt vời! – Aaron

1

Làm không sử dụng lệnh .heap -stat của WinDbg. Nó đôi khi sẽ cung cấp cho bạn đầu ra không chính xác. Thay vào đó, hãy sử dụng báo cáo bộ nhớ DebugDiags.

Có số chính xác, sau đó bạn có thể sử dụng lệnh .heap -flt ... của WinDbg.

2

Tôi thích sử dụng lệnh breakpoint nâng cao, chẳng hạn như sử dụng điểm ngắt để tạo điểm ngắt một lần mới.

10

Các "tip" Tôi sử dụng thường xuyên nhất là một trong đó sẽ giúp bạn tiết kiệm từ việc phải chạm mà pesky chuột thường xuyên: Alt +

Alt + sẽ đặt trọng tâm vào cửa sổ lệnh để bạn có thể thực sự gõ lệnh và do đó mũi tên lên thực sự cuộn qua lịch sử lệnh. Tuy nhiên, nó không hoạt động nếu tiêu điểm của bạn đã có trong lịch sử lệnh có thể cuộn.

Peeve: tại sao heck là các lần nhấn phím bị bỏ qua trong khi tiêu điểm nằm trong cửa sổ nguồn? Nó không giống như bạn có thể chỉnh sửa mã nguồn từ bên trong WinDbg. Alt + để giải cứu.

+1

'alt + 2, alt + 1, alt + 2, ctrl + F4' Lame hack ... Sẽ hoạt động ngay cả khi con trỏ nằm trong cửa sổ lệnh. : P – anishsane

25

Để điều tra rò rỉ bộ nhớ trong bãi chứa sự cố (vì tôi thích UMDH cho các quy trình trực tiếp). Chiến lược là các đối tượng cùng loại đều được phân bổ với cùng kích thước.

  • Feed the lệnh !heap -h 0 lên phiên bản dòng lệnh cdb.exe WinDbg (đối với tốc độ lớn hơn) để có được tất cả các phân bổ đống:
"C:\Program Files\Debugging Tools for Windows\cdb.exe" -c "!heap -h 0;q" -z [DumpPath] > DumpHeapEntries.log 
  • Sử dụng Cygwin để grep danh sách phân bổ, phân nhóm theo kích thước:
grep "busy ([[:alnum:]]\+)" DumpHeapEntries.log \ 
| gawk '{ str = $8; gsub(/\(|\)/, "", str); print "0x" str " 0x" $4 }' \ 
| sort \ 
| uniq -c \ 
| gawk '{ printf "%10.2f %10d %10d (%s = %d)\n", $1*strtonum($3)/1024, $1, strtonum($3), $2, strtonum($2) }' \ 
| sort > DumpHeapEntriesStats.log 
  • Bạn nhận được một bảng trông như thế này, ví dụ, nói với chúng ta rằng 25.529.270 phân bổ 0x24 byte mất gần 1,2   GB bộ nhớ.
8489.52  707  12296 (0x3000 = 12288) 
    11894.28  5924  2056 (0x800 = 2048) 
    13222.66  846250   16 (0x2 = 2) 
    14120.41  602471   24 (0x2 = 2) 
    31539.30 2018515   16 (0x1 = 1) 
    38902.01 1659819   24 (0x1 = 1) 
    40856.38  817  51208 (0xc800 = 51200) 
1196684.53 25529270   48 (0x24 = 36) 
  • Sau đó, nếu đối tượng của bạn có vtables, chỉ cần sử dụng lệnh dps để tìm kiếm một số phân bổ đống 0x24 byte trong DumpHeapEntries.log phải biết loại của các đối tượng được tham gia tất cả bộ nhớ.
0:075> dps 3be7f7e8 
3be7f7e8 00020006 
3be7f7ec 090c01e7 
3be7f7f0 0b40fe94 SomeDll!SomeType::`vftable' 
3be7f7f4 00000000 
3be7f7f8 00000000 

Đó là cheesy nhưng nó hoạt động :)

+0

Đây là người sử thi, cảm ơn một tấn cho đăng nó. – pj4533

+0

Tôi đã cố gắng thực hiện điều này bản thân mình, nhưng tôi bối rối. Làm thế nào để bạn nhận được địa chỉ '3be7f7e8' để cung cấp cho dds? Đó có phải là cột đầu tiên trong đầu ra heap không? Có nghĩa là bạn tìm kiếm nhật ký ban đầu của bạn để phân bổ kích thước đó, lấy địa chỉ, sau đó thực hiện một dds trên đó? – pj4533

+0

Chính xác, trong nhật ký bạn nhận được một dòng giống như thế này cho mọi cấp phát bộ nhớ: "3be7f7e8: 00038. 00040 [107] - busy (24)". 24 là giá trị chúng tôi tìm kiếm ở đây, nhận được từ bảng trên cho chúng tôi biết rằng hầu hết bộ nhớ được sử dụng bởi phân bổ 0x24 byte. Tôi sau đó sử dụng ít Cygwin để tìm kiếm DumpHeapEntriesStats.log cho những dòng này bằng cách sử dụng lệnh "/ (24)", chọn một số địa chỉ phù hợp và dds chúng trong cdb/WinDBG. – jturcotte

7

Một từ (tốt, OK, ba): DML, ví dụ: Debugger Markup Language.

Đây là một bổ sung khá gần đây cho WinDbg và nó không được ghi trong tệp trợ giúp. Tuy nhiên có một số tài liệu trong "dml.doc" trong thư mục cài đặt cho Công cụ gỡ lỗi cho Windows.

Về cơ bản, đây là cú pháp giống HTML bạn có thể thêm vào tập lệnh trình gỡ lỗi để định dạng và quan trọng hơn là liên kết. Bạn có thể sử dụng liên kết để gọi các tập lệnh khác hoặc thậm chí là cùng một tập lệnh.

Công việc hàng ngày của tôi liên quan đến việc duy trì mô hình meta cung cấp các đối tượng chung và mối quan hệ giữa các đối tượng cho một phần lớn phần mềm C++. Đầu tiên, để dễ dàng gỡ lỗi, tôi đã viết một kịch bản kết xuất đơn giản để trích xuất thông tin có liên quan từ các đối tượng này.

Bây giờ, với DML, tôi đã có thể thêm liên kết vào đầu ra, cho phép cùng một tập lệnh được gọi lại trên các đối tượng liên quan. Điều này cho phép khám phá nhanh hơn một mô hình.

Dưới đây là một ví dụ đơn giản. Giả sử đối tượng trong nội quan có một mối quan hệ được gọi là "tham chiếu" đối tượng khác. r @ $ t0 = $ arg1 $$ arg1 là địa chỉ của một đối tượng để kiểm tra

Rõ ràng, đây là một ví dụ khá đóng hộp, nhưng công cụ này thực sự là vô giá đối với tôi. Thay vì săn bắn xung quanh trong các đối tượng rất phức tạp cho các thành viên dữ liệu phù hợp (thường mất đến một phút và nhiều thủ thuật đúc và dereferencing khác), mọi thứ đều tự động chỉ với một cú nhấp chuột!

4

Một câu trả lời khác đã đề cập đến cửa sổ lệnh và Alt + để tập trung vào cửa sổ nhập lệnh. Có ai cảm thấy khó khăn để di chuyển cửa sổ đầu ra lệnh mà không cần sử dụng chuột?

Vâng, gần đây tôi đã sử dụng AutoHotkey để cuộn cửa sổ đầu ra lệnh bằng bàn phím và không rời khỏi cửa sổ nhập lệnh.

; WM_VSCROLL = 0x115 (277) 
ScrollUp(control="") 
{ 
    SendMessage, 277, 0, 0, %control%, A 
} 

ScrollDown(control="") 
{ 
    SendMessage, 277, 1, 0, %control%, A 
} 

ScrollPageUp(control="") 
{ 
    SendMessage, 277, 2, 0, %control%, A 
} 

ScrollPageDown(control="") 
{ 
    SendMessage, 277, 3, 0, %control%, A 
} 

ScrollToTop(control="") 
{ 
    SendMessage, 277, 6, 0, %control%, A 
} 

ScrollToBottom(control="") 
{ 
    SendMessage, 277, 7, 0, %control%, A 
} 

#IfWinActive, ahk_class WinDbgFrameClass 
    ; For WinDbg, when the child window is attached to the main window 
    !UP::ScrollUp("RichEdit50W1") 
    ^k::ScrollUp("RichEdit50W1") 
    !DOWN::ScrollDown("RichEdit50W1") 
    ^j::ScrollDown("RichEdit50W1") 
    !PGDN::ScrollPageDown("RichEdit50W1") 
    !PGUP::ScrollPageUp("RichEdit50W1") 
    !HOME::ScrollToTop("RichEdit50W1") 
    !END::ScrollToBottom("RichEdit50W1") 
#IfWinActive, ahk_class WinBaseClass 
    ; Also for WinDbg, when the child window is a separate window 
    !UP::ScrollUp("RichEdit50W1") 
    !DOWN::ScrollDown("RichEdit50W1") 
    !PGDN::ScrollPageDown("RichEdit50W1") 
    !PGUP::ScrollPageUp("RichEdit50W1") 
    !HOME::ScrollToTop("RichEdit50W1") 
    !END::ScrollToBottom("RichEdit50W1") 

Sau khi kịch bản này được điều hành, bạn có thể sử dụng Alt + lên/xuống để di chuyển một dòng của cửa sổ đầu ra lệnh, Alt + PgDn/PgUp để di chuyển một màn hình. Lưu ý: có vẻ như các phiên bản WinDbg khác nhau sẽ có tên lớp khác nhau cho cửa sổ và điều khiển, vì vậy bạn có thể muốn sử dụng công cụ gián điệp cửa sổ do AutoHotkey cung cấp để tìm tên lớp thực tế trước tiên.

6
  • .prefer_dml 1

    này sửa đổi nhiều được xây dựng trong các lệnh (ví dụ, lm) để hiển thị đầu ra DML cho phép bạn nhấp vào liên kết thay vì lệnh chạy. Khá tiện dụng ...

  • .reload /f /o file.dll (các /o sẽ ghi đè lên bản hiện tại của biểu tượng bạn có)

  • .enable_unicode 1 // Chuyển chế độ gỡ lỗi để mặc định Unicode cho chuỗi vì tất cả các thành phần của Windows sử dụng Unicode trong nội bộ , điều này khá tiện dụng.

  • .ignore_missing_pages 1 // Nếu bạn thực hiện nhiều phân tích kết xuất hạt nhân, bạn sẽ thấy rất nhiều lỗi liên quan đến bộ nhớ được phân trang. Lệnh này sẽ thông báo cho trình gỡ rối ngừng việc chặn cảnh báo này.

bí danh alias bí danh ...

Lưu cho mình một số thời gian trong việc gỡ lỗi. Dưới đây là một số của tôi:

aS !p !process; 
aS !t !thread; 
aS .f .frame; 
aS .p .process /p /r 
aS .t .thread /p /r 
aS dv dv /V /i /t //make dv do your favorite options by default 
aS f !process 0 0 //f for find, e.g. f explorer.exe 
1

Đối với lệnh & đơn giản (tĩnh hoặc automatable) thói quen nơi debugger được sử dụng, nó rất mát mẻ để có thể đặt tất cả các trình gỡ lỗi lệnh để chạy qua trong một file lệnh văn bản và chạy điều đó dưới dạng đầu vào thông qua kd.exe hoặc cdb.exe, có thể gọi qua tập lệnh batch, v.v.

Chạy bất cứ khi nào bạn cần thực hiện cùng một quy trình cũ, không cần phải khởi động WinDbg và thực hiện mọi việc theo cách thủ công. Quá xấu này không hoạt động khi bạn không chắc chắn những gì bạn đang tìm kiếm, hoặc một số thông số lệnh cần phân tích thủ công để tìm/nhận.

4

Script để tải SOS dựa trên phiên bản .NET framework (v2.0/v4.0):

!for_each_module .if(($sicmp("@#ModuleName" , "mscorwks") = 0)) 
{.loadby sos mscorwks} .elsif ($sicmp("@#ModuleName" , "clr") = 0) 
{.loadby sos clr} 
1

Nền tảng độc lập chuỗi bãi cho mã số quản lý mà sẽ làm việc cho x86/x64:

j $ptrsize = 8 'aS !ds .printf "%mu \n", c+';'aS !ds .printf "%mu \n", 10+' 

đây là một cách sử dụng mẫu:

0:000> !ds 00000000023620b8 

MaxConcurrentInstances