WinDBG Tutorial - Part 1
Items covered
- Attaching to process
- Inspecting local variables (dv, ??)
- Inspecting last error (.lastevent)
- Evaluating parameters (x)
- Setting value (e)
Code used
For this introductory test, we will work with the following test program (Win32 C++ console project):
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
printf("Enter two numbers: ");
int a, b;
scanf("%d%d", &a,&b);
int rez;
rez = a / b;
printf("The division is: %d", rez);
return 0;
}
What the program does is obvious: it reads two integer variables from the command line and calculates the result of their division. The potential error is again obvious: if the latter variable is 0, we’ll get a division by zero exception.
Debugging
Let’s get to work:
Compile and run the program from console:
D:\home\…\Emptyapp\Debug>Emptyapp.exe
Set the symbol path in WinDBG to the Debug folder of the C++ program (where EmptyApp.exe and PDB files are located).
Open WinDBG and attach to the process named “EmptyApp”
For the moment, we will choose Go, as no exception as occurred yet:
0:001> g
(The message in WinDBG will be “Debugee is running”)
Let’s now input two values: a = 6, b = 0
When you press ENTER, winDBG will break because it receives a First-hand exception:
(1e38.1b00): Integer divide-by-zero - code c0000094 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
This exception may be expected and handled (had we inserted a try/catch block in the C++ program), but it is not. Let’s go further and receive the second chance exception:
0:000> g
(1e38.1b00): Integer divide-by-zero - code c0000094 (!!! second chance !!!)
Assuming we didn’t know what happened, let’s find out the call stack:
0:000> k
ChildEBP RetAddr
0022f948 00fa1a28 Emptyapp!wmain+0x79 [d:\home\allinoner\emptyapp\emptyapp\emptyapp.cpp @ 14]
0022f998 00fa186f Emptyapp!__tmainCRTStartup+0x1a8 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 579]
0022f9a0 763d10dc Emptyapp!wmainCRTStartup+0xf [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 399]
0022f9ac 77301e9e kernel32!BaseThreadInitThunk+0xe
0022f9ec 77301e71 ntdll!__RtlUserThreadStart+0x70
0022fa04 00000000 ntdll!_RtlUserThreadStart+0x1b
The error, therefore, originates at line 14 in the source emptyapp.cpp
Since we do have the source for this file, let’s see what line 14 reads:
rez = a / b;
Hmm, we get a division by zero and the line of code contains a division…
Let’s dump the local variables:
0:000> dv
argc = 1
argv = 0x00511310
b = 0
rez = -858993460
a = 6
OK, question was answered, we want to divide a = 6 by b = 0.
Just out of curiosity: what is argv?
0:000> ?? argv
wchar_t ** 0x00511310
Since argc is 1, let’s see the value of the first argument:
0:000> ?? argv[0]
wchar_t * 0x00511318
"Emptyapp.exe"
OK, let’s go further: let’s modify variable b so that no division by zero is thrown:
Firstly, get its address:
0:000> x b
0022f934 b = 0
Secondly, set value of b to 3, for instance:
0:000> e 22f934 3
Inspecting all local variables again:
0:000> dv
argc = 1
argv = 0x00511310
b = 3
rez = -858993460
a = 6
This is it. Let’s let the program finish:
0:000> g
eax=5f24dff0 ebx=00000000 ecx=5f1812bc edx=5f1812bc esi=77377380 edi=77377340
eip=772e8244 esp=0022f8b0 ebp=0022f8cc iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCallRet:
772e8244 c3 ret
The command prompt reads:
Enter two numbers: 6 0
The division is: 2
And finally, to make sure program has exited:
0:000> .lastevent
Last event: 1e38.1b00: Exit process 0:1e38, code 0
debugger time: Sun Jul 12 21:08:08.080 2009 (GMT+3)