Software QA FYI - SQAFYI

Net Debugging? Don't give me none of your VS

By: Edward Elliott

Visual Studio is fine for most debugging purposes. Just occasionally, it isn't practicable, or there are other quicker ways of doing it with a user-mode debugger. Edward argues that debugging in MSIL or assembly language is a strangely liberating experience and can be a lightweight route to discovering the cause of elusive bugs. He starts off with a simple introduction to SOS debugging.

There will come a time that any developer will need to debug an application and will not have access to Visual Studio or, in some cases, even the source code. When debugging a problem on a production web or application server, for example, I really do not want to have to install Visual Studio and copy across all my source code; it just isn’t practical, or sometimes even allowed. It is at times like this that we need another tool, a tool for debugging windows applications, and it just so happens that Microsoft provides a range of such debuggers, which are ideally suited to this type of situation. In this article I am going to explain what debuggers are available, and how you can use them to simplify the process of debugging a .NET application in situations where Visual Studio isn't either practical or available.

In this article I am going to explain what debuggers are available, and how to debug a simple, fairly common example. I hope this will show how it is possible to debug your code in a simple straightforward way.

Why bother?
On the whole, if you are working at your developer machine and are able to reproduce the reported issue, then it is easiest to do your debugging in Visual Studio. However, as I hinted in the introduction, there are many reasons why you cannot always use Visual Studio, and why you should learn and understand the alternatives:
* Visual Studio Crashes – while not a common occurrence, every developer knows that VS sometimes crashes, and often when you need it most. WinDBG / cdb do occasionally crash but rarely and if they do have issues it is pretty simple to download an older or newer version that should be fine..
* Speed – if you are in a hurry and you just want to see something quickly, then starting up cdb takes a fraction of the time it takes to start Visual Studio, and has a significantly smaller footprint.
* Control – the debugging tools provide a wide range of commands and options that allow fine-grained control of the debugging process. For example, you can set a break point on a particular module being loaded, or make changes to the application’s data and code (i.e. you can apply a one- time only patch to your application at run time!).
* Free – the debuggers and SOS are free, you can download them from the Microsoft site and they are updated fairly regularly. As such they make very useful alternatives when Visual Studio is unavailable.
* Crash Dumps – it is simple to create and to view crash dumps, so you can get a dump from a customer or only interrupt service on your live applications briefly while you take a snapshot of it for subsequent debugging. You can debug dumps taken from any of the common tools like DrWatson, ADPlus and Debug Diag .
* SOS includes various helper functions – these allow you to debug .NET deadlocks and list all the objects in memory whilst being able to find what created them to track down memory leaks.
* Remote debugging is significantly simpler – just install on the server and client the remote.exe that comes with the tools and you are ready.
* X64 support – there are no problems debugging X64 applications using the debugging tools, whereas there are issues using Visual Studio to do this.

Meet the debuggers
There are two types of debuggers: kernel and user-mode. Kernel debuggers are used to debug drivers and the Windows kernel. User-Mode debuggers are used for applications and services. We are interested in user-Mode debuggers of which there are two in the Windows debugging toolkit: WinDbg, which is GUI based (with a circa 1990’s interface) and cdb, which is a command line tool.

Both of these debuggers provide a wrapper around dbgEng.dll, which actually does the debugging. The commands and responses are the same from all debuggers so just choose which tool you like and stick to that. I prefer cdb because I like the fact that it only gives you a prompt back when it is ready to accept input. WinDbg, on the other hand, offers such things as stack and variable windows and lets you happily type away before it is ready. The debuggers are assembly debuggers. They let you control the process you are investigating, set break points, and view threads and variables in assembly code. This means that you need to debug and understand machine code, calling conventions, stacks, heaps and memory and so on. The debuggers provide the symbols from your source code in the assembly language, which allow you to get line locations and view different structures and classes but it is still fairly complicated. Even when you have symbols, you have to ensure they are compiled with the executable otherwise they will not match and will give you strange results.

Luckily this nightmare can be averted to an extent because some nice people in Microsoft decided to help the developer community and ship a helper DLL with the .NET framework, sos.dll. It is amazing how appropriate that name really is. This DLL can be loaded by any of the debuggers mentioned above, and understands how the CLR works. All .NET programs provide a wealth of information at run time which we can take advantage of, at least compared with native applications, so .NET debugging really is very simple.

Taking the time now to understand a few simple procedures really will pay dividends and, if you are anything like me, you will think that debugging without VS really is pretty cool and helps you gain a thorough understanding of how the .NET framework actually works.

The Debugging Landscape
Before we delve into how to actually debug code, it is important to understand what happens when you run a .NET application:
1. .NETcode is written in a number of languages: C#, VB.NET or any other CLI-compliant language.
2. This code is compiled into a common MSIL format
3. At runtime, or if NGEN’d, MSIL is compiled to binary instructions for the CPU architecture that it is running on (JITed) , and then executed

By way of an example, let's take a look at some C# code that performs some looping and then outputs some text, and see how the code looks as it is transformed into MSIL then into machine code. I have highlighted the areas which match in each format.

Full article...


Other Resource

... to read more articles, visit http://sqa.fyicenter.com/art/

Net Debugging? Don't give me none of your VS