How to use WinDbg to debug native programs

WinDbg is a powerful debug tool which can help programmer to locate the issues in a short time, especially in case there is no development environment. If the software product has been deployed to the customers' workstation and an issue occurred, can you ask your customer to install a visual studio for you to diagnostic it? Ofcourse not. Thus, WinDbg can help you in this situation. This article is to introduce how to start your trip on WinDbg. Hope it is helpful for you, enjoy it!

 

1.Download andinstall Debugging Tools for Windows

http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx

 

2.Setup environmentvariables to point to Microsoft Symbol server

_NT_SYMBOL_PATH = http://msdl.microsoft.com/download/symbols

OR

Specify it from[File]->[Symbol File Path...] in the menu of WinDbg UI

 

3.Start to debug theprogram you want to debug

a. start the programfrom windbg :[File]->[Open Executable...]

b. attach windbg toan existing process:[File]->[Attach to a process...]

c. automaticallyattach a debugger to an application when it starts to run:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Image File Execution Options

Create a newregistry key with the name of the process you want to debug, add an stringvalue "Debugger", set the data to the full path of ntsd.exe. It willuse ntsd.exe to debug the process you specified here.

 

 

 

4.Use command todebug the program

Category

Command

Description

Example

RUN

F10/p

Step over

 

 

F11/t

Step into

 

 

Shift+F11/gu

Step out

 

 

F5/g

Go

 

 

F9

Insert/Remove breakpoint

 

Display

dv

Display local variable

 

 

R

Display register

R ecx

 

U

Show usassemble

U WindbgEx1!Example2

 

kb

Display stack trace

 

 

.lastevent

Last exception record

 

 

bl

List all of the breakpoints

 

 

lm

List all of the loaded modules

 

 

~

Display all threads

 

 

.hh

help

.hh dbgerr005

QUIT

Q

 

 

 

5.Example

First of all, startthe process you want to debug:[File]->[Open Executable...].

Click [Call stack]icon in UI or Alt+6 to sett the call stack, Alt+2 to show the Watch window...

Add breakpoint insource code, and F5 to run into the breakpoint, see the illustration below:

 

 

 

Now, it is the sameas the Visual Studio platform. F10 to step over, and F11 to step into.

Press F5 to run intothe breakpoint, the variable is displayed in Locals window.

 

 

Press F5 to continuethe process,  an exception raised anddisplayed in Command window:

0:000> g

(1668.1920): Integerdivide-by-zero - code c0000094 (first chance)

First chance exceptions arereported before any exception handling.

This exception may be expectedand handled.

WindbgEx1!Example2+0x2d:

00000001`3f27117d f7f9            idiv    eax,ecx

 

We can display theregister using the "r" command:

0:000> r ecx

ecx=0

0:000> r eax

eax=47

From the assemblyand register value, we can find the reason of the exception.

 

Note: First chanceexceptions are thrown from the application, which gets a change to handle theexception, if the application does not handle the exception, the debugger willcatch it and has another change, we can it second change exception,  to handle it.

 

 

The example isdownloaded from here:

http://www.codeproject.com/KB/debug/windbg_part1/windbg_part1_src.zip

Example c++ code
1 // WindbgEx1.cpp : Defines the entry point for the console application.
2  //
3  
4 #include "stdafx.h"
5 #include <stdio.h>
6 #include <stdlib.h>
7  //#include "wdbgexts.h"
8
9 CRITICAL_SECTION cs;
10
11 /*
12 The first thread enters a CS and runs away. The following shows how you can debug such a problem.
13
14 0:001> ~*kb
15
16 0 Id: 894.848 Suspend: 1 Teb: 7ffde000 Unfrozen
17 ChildEBP RetAddr Args to Child
18 0012fde4 77f5c534 77f69f68 000007f4 00000000 SharedUserData!SystemCallStub+0x4
19 0012fde8 77f69f68 000007f4 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
20 0012fe70 77f5b2e6 00446dc8 0041531f 00446dc8 ntdll!RtlpWaitForCriticalSection+0x125
21 0012fe78 0041531f 00446dc8 00000000 00000002 ntdll!RtlEnterCriticalSection+0x46
22 0012ff74 0041579f 00000001 003235c0 00323608 WindbgEx1!main+0x8f
23 0012ffc0 77e814c7 00000000 00000002 7ffdf000 WindbgEx1!mainCRTStartup+0x1cf
24 0012fff0 00000000 0041458c 00000000 78746341 kernel32!BaseProcessStart+0x23
25
26 # 1 Id: 894.e9c Suspend: 1 Teb: 7ffdd000 Unfrozen
27 ChildEBP RetAddr Args to Child
28 0034ffc8 77f5f31f 00000005 00000004 00000001 ntdll!DbgBreakPoint
29 0034fff4 00000000 00000000 00000000 00000000 ntdll!DbgUiRemoteBreakin+0x2d
30 0:001> dt 00446dc8
31 cs
32 +0x000 DebugInfo : 0x77fc4240
33 +0x004 LockCount : 1
34 +0x008 RecursionCount : 1
35 +0x00c OwningThread : 0x000005dc
36 +0x010 LockSemaphore : 0x000007f4
37 +0x014 SpinCount : 0
38 0:001> ~
39 0 Id: 894.848 Suspend: 1 Teb: 7ffde000 Unfrozen
40 . 1 Id: 894.e9c Suspend: 1 Teb: 7ffdd000 Unfrozen
41
42 The owning thread (0x5dc) does not show up in the threads list => a thread has locked the critical section and exitted.
43 */
44
45 // Acquire a critSec and run away.
46 DWORD WINAPI newThreadProc(LPVOID lpParameter)
47 {
48 InitializeCriticalSection(&cs);
49 EnterCriticalSection(&cs);
50 return 0;
51 }
52
53 /*
54 Example1: application hang
55
56 This program hangs because a thread acquires a critical section and exits without releasing it and
57 another thread waits forever on that CS.
58 */
59 void Example1()
60 {
61 DWORD tid = 0;
62 HANDLE hThread = CreateThread(NULL, 0, newThreadProc, NULL, 0, &tid); // let the thread execute immediately
63
64 WaitForSingleObject(hThread, INFINITE);
65 EnterCriticalSection(&cs);
66 }
67
68 /*
69 Example2: Exception: Divide by zero
70
71 Commands you want to execute:
72 - .lastevent [o/p: Integer divide-by-zero],
73 OR:
74 - u [output: idiv ecx]
75 - r ecx [o/p: 0]
76 => divide by zero
77 */
78
79 void Example2()
80 {
81 int y = 71;
82 y = y / (71 - y);
83 }
84
85 /*
86 Example3: Execute a command every time a breakpoint is hit.
87
88 bp WindbgEx1!Example3+0x3d "dd [ebp-0x14] L1; .echo hello world;g" will print value of i in every iteration
89 */
90 void Example3()
91 {
92 int k = 0;
93 for (int i = 0; i < 100; ++i)
94 {
95 // bp WindbgEx1!Example3+0x3d "dd k L1; g" will print value of k in every iteration
96 k = rand();
97 }
98 }
99
100 /*
101 Example4: Exception: null pointer access
102
103 Run under windbg; the debugger will report a first chance exception and this asm instruction in x86:
104 - mov dword ptr [eax],0x50 ds:0023:00000000=????????
105 - 0:000> r eax
106 eax=00000000
107
108 If you turn on source debugging, the line *i = 80 will be highlighted.
109 */
110 void Example4()
111 {
112 int* i = NULL;
113 *i = 80;
114 }
115
116 /*
117 Example5: Exception: double deletion
118 */
119 void Example5()
120 {
121 char* str = new char[20];
122 delete [] str;
123 delete [] str; // error!
124 strcpy(str, "hi");
125 }
126
127 /*
128 Example6: Exception: stack overflow due to infinite recursion
129 If you run under the debugger, the debugger will get first and second chance stack overflow exceptions.
130 */
131 void Example6_1();
132 void Example6()
133 {
134 Example6_1();
135 }
136
137 void Example6_1()
138 {
139 Example6();
140 }
141
142 void Example7()
143 {
144 int i = 5, j = 7;
145 j = 5 + 7;
146 }
147
148 int _tmain(int argc, _TCHAR* argv[])
149 {
150 if (argc > 1 && argv)
151 {
152 int which = atoi(argv[1]);
153 switch (which)
154 {
155 case 1:
156 Example1();
157 break;
158
159 case 2:
160 Example2();
161 break;
162
163 case 3:
164 Example3();
165 break;
166
167 case 4:
168 Example4();
169 break;
170
171 case 5:
172 Example5();
173 break;
174
175 case 6:
176 Example6();
177 break;
178
179 case 7:
180 Example7();
181 break;
182 case 8:
183 {
184 char *TheLastParameter[100];
185
186 sprintf(*TheLastParameter, "The last parameter is %s", argv[argc]);
187 printf(*TheLastParameter);
188
189 return 0;
190 }
191 }
192 }
193 return 0;
194
195 }

 


1 // WindbgEx1.cpp : Defines the entry point for the console application.
2 //
3
4 #include "stdafx.h"
5 #include <stdio.h>
6 #include <stdlib.h>
7 //#include "wdbgexts.h"
8
9 CRITICAL_SECTION cs;
10
11 /*
12 The first thread enters a CS and runs away. The following shows how you can debug such a problem.
13
14 0:001> ~*kb
15
16 0 Id: 894.848 Suspend: 1 Teb: 7ffde000 Unfrozen
17 ChildEBP RetAddr Args to Child
18 0012fde4 77f5c534 77f69f68 000007f4 00000000 SharedUserData!SystemCallStub+0x4
19 0012fde8 77f69f68 000007f4 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
20 0012fe70 77f5b2e6 00446dc8 0041531f 00446dc8 ntdll!RtlpWaitForCriticalSection+0x125
21 0012fe78 0041531f 00446dc8 00000000 00000002 ntdll!RtlEnterCriticalSection+0x46
22 0012ff74 0041579f 00000001 003235c0 00323608 WindbgEx1!main+0x8f
23 0012ffc0 77e814c7 00000000 00000002 7ffdf000 WindbgEx1!mainCRTStartup+0x1cf
24 0012fff0 00000000 0041458c 00000000 78746341 kernel32!BaseProcessStart+0x23
25
26 # 1 Id: 894.e9c Suspend: 1 Teb: 7ffdd000 Unfrozen
27 ChildEBP RetAddr Args to Child
28 0034ffc8 77f5f31f 00000005 00000004 00000001 ntdll!DbgBreakPoint
29 0034fff4 00000000 00000000 00000000 00000000 ntdll!DbgUiRemoteBreakin+0x2d
30 0:001> dt 00446dc8
31 cs
32 +0x000 DebugInfo : 0x77fc4240
33 +0x004 LockCount : 1
34 +0x008 RecursionCount : 1
35 +0x00c OwningThread : 0x000005dc
36 +0x010 LockSemaphore : 0x000007f4
37 +0x014 SpinCount : 0
38 0:001> ~
39 0 Id: 894.848 Suspend: 1 Teb: 7ffde000 Unfrozen
40 . 1 Id: 894.e9c Suspend: 1 Teb: 7ffdd000 Unfrozen
41
42 The owning thread (0x5dc) does not show up in the threads list => a thread has locked the critical section and exitted.
43 */
44
45 // Acquire a critSec and run away.
46 DWORD WINAPI newThreadProc(LPVOID lpParameter)
47 {
48 InitializeCriticalSection(&cs);
49 EnterCriticalSection(&cs);
50 return 0;
51 }
52
53 /*
54 Example1: application hang
55
56 This program hangs because a thread acquires a critical section and exits without releasing it and
57 another thread waits forever on that CS.
58 */
59 void Example1()
60 {
61 DWORD tid = 0;
62 HANDLE hThread = CreateThread(NULL, 0, newThreadProc, NULL, 0, &tid); // let the thread execute immediately
63
64 WaitForSingleObject(hThread, INFINITE);
65 EnterCriticalSection(&cs);
66 }
67
68 /*
69 Example2: Exception: Divide by zero
70
71 Commands you want to execute:
72 - .lastevent [o/p: Integer divide-by-zero],
73 OR:
74 - u [output: idiv ecx]
75 - r ecx [o/p: 0]
76 => divide by zero
77 */
78
79 void Example2()
80 {
81 int y = 71;
82 y = y / (71 - y);
83 }
84
85 /*
86 Example3: Execute a command every time a breakpoint is hit.
87
88 bp WindbgEx1!Example3+0x3d "dd [ebp-0x14] L1; .echo hello world;g" will print value of i in every iteration
89 */
90 void Example3()
91 {
92 int k = 0;
93 for (int i = 0; i < 100; ++i)
94 {
95 // bp WindbgEx1!Example3+0x3d "dd k L1; g" will print value of k in every iteration
96 k = rand();
97 }
98 }
99
100 /*
101 Example4: Exception: null pointer access
102
103 Run under windbg; the debugger will report a first chance exception and this asm instruction in x86:
104 - mov dword ptr [eax],0x50 ds:0023:00000000=????????
105 - 0:000> r eax
106 eax=00000000
107
108 If you turn on source debugging, the line *i = 80 will be highlighted.
109 */
110 void Example4()
111 {
112 int* i = NULL;
113 *i = 80;
114 }
115
116 /*
117 Example5: Exception: double deletion
118 */
119 void Example5()
120 {
121 char* str = new char[20];
122 delete [] str;
123 delete [] str; // error!
124 strcpy(str, "hi");
125 }
126
127 /*
128 Example6: Exception: stack overflow due to infinite recursion
129 If you run under the debugger, the debugger will get first and second chance stack overflow exceptions.
130 */
131 void Example6_1();
132 void Example6()
133 {
134 Example6_1();
135 }
136
137 void Example6_1()
138 {
139 Example6();
140 }
141
142 void Example7()
143 {
144 int i = 5, j = 7;
145 j = 5 + 7;
146 }
147
148 int _tmain(int argc, _TCHAR* argv[])
149 {
150 if (argc > 1 && argv)
151 {
152 int which = atoi(argv[1]);
153 switch (which)
154 {
155 case 1:
156 Example1();
157 break;
158
159 case 2:
160 Example2();
161 break;
162
163 case 3:
164 Example3();
165 break;
166
167 case 4:
168 Example4();
169 break;
170
171 case 5:
172 Example5();
173 break;
174
175 case 6:
176 Example6();
177 break;
178
179 case 7:
180 Example7();
181 break;
182 case 8:
183 {
184 char *TheLastParameter[100];
185
186 sprintf(*TheLastParameter, "The last parameter is %s", argv[argc]);
187 printf(*TheLastParameter);
188
189 return 0;
190 }
191 }
192 }
193 return 0;
194
195 }

 

posted @ 2010-07-21 19:43  皮业勇  阅读(1038)  评论(0编辑  收藏  举报