Its been a while since I wrote anything. I got very busy at work and couldn’t get anything going for the blog and also I spent too much time playing Ninja Gaiden and Halo 2 on Xbox Live :). Today I am going to do a walkthrough on how to look at a dump file in windbg and some of the basic commands. Windbg is the coolest weapon in a Debugging Ninja’s hands ? I guess you can make out where I came up with this analogy. For this exercise I have used VC++.net 2003 and written an unmanaged console application which looks some thing like this
int _tmain(int argc, _TCHAR* argv)
Test *temp = (Test *)malloc(sizeof(Test));
temp->y = 10;
temp = NULL;
temp->y = 30;
Sorry for choosing such a simple example. But this serves the purpose. I assume that you have the debugging tools for windows installed. The link is in the previous blog entry. When I run this application, it will crash with an access violation. Since this application crashes at start up, what you can do is go to the Debugging Folder that you had installed and you can start the application as follows
adplus –crash –sc c:\myfolder\Myapp.exe
This will launch the app under the debugger and will capture the crash when the error occurs. Run the debug build and make sure you have the pdb file also. Now when the crash occurs, we will get a folder something like “Crash_Mode….Date … Time…”. In this folder you will find the three dump files. The first one is the First Change AV.dmp, then the Process ShutDown.dmp and then the second Chance AV.dmp. The second change AV.dmp is the one we are interested in. Now launch windbg. This should be in the debugger folder or it should show up in start->Programs->Debugging tools for windows.
The first thing that we need to do is to set the symbol file path. Microsoft provides a symbol server that contains the public symbols for the system dlls. The way you would set it up is Go to File->Symbol File Path and then type the following
Make sure you create a folder called websysmbols. This is the folder where the Microsoft Symbols will get downloaded. Once you set this up, click ok to this dialog and then Save the workspace so that every time you launch windbg it is already set. The go to File->Open Crash dump and then select the Second Chance Av.dmp. Once you open it, you will see a command window come up and see something like this
(7f8.f7c): Access violation - code c0000005 (!!! second chance !!!)
eax=00000000 ebx=7ffde000 ecx=00000000 edx=00000000 esi=7c91d369 edi=0012fedc
eip=00411ca4 esp=0012fdec ebp=0012fedc iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
*** WARNING: Unable to verify checksum for Win32Con.exe
00411ca4 c7001e000000 mov dword ptr [eax],0x1e ds:0023:00000000=????????
In the command prompt you will see 0.000> and this is the thread ID. So basically this is the thread where the crash occurred. The first thing that you want to look at is the call stack. The command is “kb” Enter kb in the command window and you will see the following
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0012fedc 00414d00 00000001 003218b8 00321918 Win32Con+0x11ca4
0012ffc0 7c816d4f 0012f7b4 7c91d369 7ffde000 Win32Con+0x14d00
0012fff0 00000000 00411384 00000000 78746341 kernel32!BaseProcessStart+0x23
My program name was Win32Con. If you see we see Win32Con!(some address). At this point it only displays addresses instead of function names and this is because we have only setup symbol path for the system dlls and not the application itself. So go back to the file->symbol File Path and then browse to the folder where you the symbol file for your app and then click the reload check box and click ok. Now when you type kb, you will see the following
ChildEBP RetAddr Args to Child
0012fedc 00414d00 00000001 003218b8 00321918 Win32Con!main+0xb4 [c:\stubs\win32con\win32con.cpp @ 48]
0012ffc0 7c816d4f 0012f7b4 7c91d369 7ffde000 Win32Con!mainCRTStartup+0x170 [f:\vs70builds\3077\vc\crtbld\crt\src\crt0.c @ 259]
0012fff0 00000000 00411384 00000000 78746341 kernel32!BaseProcessStart
Now you can see the function where the crash occurred. So we now know that we crash in main. If you have the source file, you go to file->Source file path and point to it. Then Go to View->CallStack and in this window click source and it should take you right to the source line were the crash occurred. In this case it will take you to
Temp->y = 30.
You can look at local variables of a function by using the following command “dv” .When you do dv you get the following output
argc = 1
argv = 0x003218b8
var2 = class Test
var1 = class Test
temp = 0x00000000
You can clearly see that temp is NULL when we are trying to access the object which results in the AV. You can get a list of threads by doing the following “~*” . You can get the call stacks for all threads by using “~* kb”. To switch to a particular thread you can do
“~2s” and that will take to thread 2. If you want to examine the local variables for a different function than the one at the top, you need to figure out the frame number.
# ChildEBP RetAddr
00 0012fedc 00414d00 Win32Con!main+0xb4
01 0012ffc0 7c816d4f Win32Con!mainCRTStartup+0x170
02 0012fff0 00000000 kernel32!BaseProcessStart+0x23
0:000> .frame 1
01 0012ffc0 7c816d4f Win32Con!mainCRTStartup+
Now the context changes to frame 1 and you can look at its local variables. You can get the parameters by using the view->callstack window and choosing the different options.
I shall leave the discussion about stack frames and how variables are pushed to the stack and how return addresses are stored and base pointers to another day. I have given you steps on how to setup windbg and setup symbol paths and look at crash dumps. The commands that I have listed are some of the basic ones that can get you started and the help that comes with windbg has a list of all the commands and explains them in detail. Reading a dump is like an Art and I am still trying to learn things. The familiarity with the product where the problem happens and knowledge of the technology would enable you to get more information from it. There is no cookie cutter methods to learn reading dumps. The more you look at it, the more easier it will become. At this point I shall stop here and hope there is not too much of a break between this post and my next post.