General Breakpoints

The first breakpoint concept I want to address concerns the two commands that you use to set breakpoints BP and BU. Both commands take identical parameters and modifiers. You can think of the bp version as a hard breakpoint that WinDBG always associates with an address. If the module containing that breakpoint is unloaded, WinDBG removes the bp breakpoint from the list of breakpoints. bu breakpoints, on the other hand, are associated with a symbol, so WinDBG tracks on the symbol instead of an...

Common Debugging Question Is there anything you can do to fix blown stacks from

Infinite recursion is not, thank goodness, that common, but when it does happen, it's nearly impossible to debug. If you've ever seen an application appear to pause for a second or so and completely disappear without displaying an Application Error dialog box, you're almost certainly looking at infinite recursion. If you can't even get a chance to debug the application, it's very hard to figure out what went wrong with it. Fortunately, the new _resetstkoflw C run-time function attempts to get...

Build All Builds with Debugging Symbols

Some of the debugging system recommendations that I do make aren't that controversial. I've been harping on my first recommendation for years build all builds, including release builds, with full debugging symbols. Debugging symbols are the data that let the debugger show you source and line information, variable names, and data type information for your program. All that information is stored in a .PDB Program Database file associated with your modules. If you're paid by the hour, spending...

Loading and Controlling Extensions

Before we start looking at individual extension commands, I need to talk about how you can see which extensions you've loaded, how to load your own, and how to get help from an extension. To see what extensions you have loaded, use the .chain List Debugger Extensions command. This command also shows you the search order for commands from the top of the display down to the bottom as well as the path that WinDBG searches for the extension DLLs. Under Windows 2000, the display looks like the...

Choosing the Right C RunTime Library for Your Application

Some of the confusion surrounding the use of the CRT libraries in Microsoft Windows development revolves around figuring out which library to use. There are six versions of the library, and they fall into two main categories debug DCRT and release CRT . In each category is a single-threaded static library, a multithreaded static library, and a multithreaded DLL. The static versions of the CRT libraries link the library functions directly into your application and are the default versions used...

The SettingsMaster AddIn

After all the fun I had on SuperSaver, I really wasn't looking forward to the next add-in I had to write for this chapter. In the end, SettingsMaster was not only problem-free but one of the most useful tools I've ever written. I certainly hope you find it useful as well. As the name implies, SettingsMaster's purpose in life is to get all your settings straight. By settings, I mean all your build settings. Many of the bugs I've worked on over the years have come down to build problems, so I...

gl Whole Program Optimization

Microsoft has spent a considerable effort to improve the code generators, and they have done a masterful job of generating very small and very fast code with Visual C .NET. The big change is that instead of doing optimizations in only a single file also known as a compiland at compile time, they can now do cross-file optimization when the program is linked. I'm sure the first time anyone compiles a C project under Visual C .NET, he will see a dramatic reduction in code size. Amazingly, default...

Listing 43 SetBreakpoint from I386CPUHELPC

SetBreakpoint PDEBUGPACKET dp , DWORD dwReadWrite 0 BYTE bTempOp BREAK_OPCODE BOOL bReadMem BOOL bWriteMem BOOL bFlush MEMORY_BASIC_INFORMATION mbi DWORD dwOldProtect ASSERT FALSE IsBadReadPtr dp , sizeof DEBUGPACKET ASSERT FALSE IsBadWritePtr pOpCode , sizeof OPCODE if TRUE IsBadReadPtr dp , sizeof DEBUGPACKET TRUE IsBadWritePtr pOpCode , sizeof OPCODE TRACE0 SetBreakpoint invalid parameters n return FALSE bReadMem DBG_ReadProcessMemory dp- gt hProcess , LPCVOID ulAddr , amp bTempOp , sizeof...

Executing Stepping and Tracing

As you've probably figured out by now, pressing F5 continues execution when you're stopped in WinDBG. You might not have noticed it, but pressing F5 simply causes a g Go command. What's neat about the g command is that you can also specify an address as the parameter. WinDBG uses that address as a one-time breakpoint, so you'll run to that location. Have you ever noticed that pressing Shift Fll, the Step Out command, executes the g command followed by an address sometimes in the form of an...

Useful DCRT Functions

One of the most useful DCRT library functions is _CrtCheckMemory. This function walks through all the memory you've allocated and checks to see whether you have any underwrites or overwrites and whether you've used any previously freed blocks. This one function alone makes the entire DCRT library worth using. A great technique for tracking down memory problems is to scatter assert _CrtCheckMemory calls throughout your code. That way you'll catch those underwrites and overwrites as close to...

For Native Code Know Where Your DLLs Load

If you've ever been hiking in the woods, you know that landmarks can be very important in keeping you from getting lost. When you don't have any landmarks, you can end up going around in circles. When your application crashes, you need a similar kind of landmark to help point you in the right direction so that you're not wandering around in the debugger. The first big landmark for crashes is the base address of your dynamic-link libraries DLLs and ActiveX controls OCXs , which indicates where...

PDB2MAPMap Files After the Fact

One issue that keeps coming up when I discuss finding crash addresses with other developers is the lament that you've already got code out in the field in which you don't have MAP files. Other eagle eye developers have also pointed out that having perfect MAP files means you have to set the base address of all your DLLs as part of the build. If you're working on an existing project that's about to ship, you might not want to destabilize the build by changing a bunch of settings. Additionally,...

The Different Symbol Formats

Before diving into a discussion of accessing symbol tables, I need to go over the various symbol formats available. I've found that people are a little confused about what the different formats are and what they offer, so I want to set the record straight. Common Object File Format COFF was one of the original symbol table formats and was introduced with Windows NT 3.1, the first version of Windows NT. The Windows NT team was experienced with operating system development and wanted to bootstrap...

Implementing MemDumperValidator

Implementing the MemDumperValidator functions was generally straightforward. The first unexpected problem I had to deal with was that the DCRT library doesn't document a way for the hook functions to get the memory block value. The hook functions are passed only a pointer to the user data, not the whole memory block the DCRT library allocates. Fortunately, with the DCRT library source code, I was able to see exactly how the library allocates memory blocks. Memory blocks are all allocated as a...

Creating Dump Files

At any point when you're doing live debugging, you can call the .dump Create Dump File command to create a dump file. Before mentioning anything about what can be in a dump file, I need to point out that it's up to you to specify the extension for any dump file you create. The .dump command will happily write the file exactly as you specify the complete name and path, without adding any missing file extension. The extension you should always use is .DMP. With the extension issue out of the way,...

ExceptionMon

Once I had ProfilerLib up and running, I was able to start ExceptionMon. Looking at the iCorProfilerCallback interface, you'll see that you have all sorts of amazing callbacks to let you know exactly what processing is happening when an exception occurs. It's almost like someone at Microsoft was reading my mind At an initial glance, you might think that ExceptionMon was absolutely trivial to implement. As usual, reality was a little bit different. In my design for ExceptionMon, I wanted to...

Data Breakpoints

Data breakpoints, also called global memory breakpoints, are one of the most powerful tools you have at your disposal. With a data breakpoint, whenever anything changes a particular piece of memory, the debugger stops immediately at the point right after the memory was changed. Data breakpoints are global in scope and are not related to any location except the one doing the memory change. As you can imagine, data breakpoints are just the thing for tracking down all sorts of problems like memory...

Ax

Visual Studio Registers Window

Figure 7-9 General.purpose register layout The flags register, eflags, contains the status flags and the control flags. Various instructions set bits in eflags to indicate the result of those instructions. For example, the zf Zero Flag bit is set to 1 when the result of an instruction is 0. In Chapter 4, I described setting the CPU to single-step mode, which involved setting the tf Trap Flag in the eflags register. Figure 7-10 shows the Registers window from the Visual Studio .NET debugger. The...

Install the Operating System Symbols and Set Up a Symbol Store

As anyone who has spent more than 5 minutes of development time on Windows knows, getting the correct symbols lined up is the secret to debugging faster. In managed code, if you don't have symbols, you might not be able to debug at all. In native code, without symbols, you probably won't get clean call stacks because to walk stacks, you need the frame pointer omission FPO data that's included as part of the PDB file. If you think you have trouble getting everyone on your team and in the company...

Table 173 Memory Block Identifiers

A normal call to new, malloc, or calloc creates a Normal block. Defining crtdbg map alloc causes all heap allocation to default to Normal blocks and associates the source file and line number that allocated the block with the memory block. The memory blocks allocated internally by many runtime library functions are marked as CRT blocks so that they can be handled separately. As a result, you're able to exclude them from leak detection and other memory validation operations. Your application...

Turn On Allow Service To Interact With Desktop

No matter what type of service you're debugging, you'll want to turn on Allow Service To Interact With Desktop on the Log On tab of your service's Properties dialog box. Although you shouldn't have any user interface elements with your service, having assertion notifications that allow you to gain control with the debugger is very helpful. Assertion notifications combined with excellent logging code, such as the code that ATL gives you for writing to the event log, can make it much easier to...

FS Register Access

In Win32 operating systems, the FS register is special because the pointer to the thread information block TIB is stored in it. The TIB is also called the thread environment block TEB . The TIB holds all the thread-specific data so that the operating system can keep your thread access straight. This thread-specific data includes all the structured exception handling SEH chains, thread local storage, the thread stack, and other information needed internally. For more information about SEH, see...

Listing 33 BugslayerStackTrace building a full stack trace with source and line

Builds a readable representation of the stack trace lt summary gt lt returns gt A readable representation of the stack trace lt returns gt New up the StringBuilder to hold all the stuff. StringBuilder StrBld new StringBuilder First thing on is a line feed. StrBld.Append DefaultLineEnd Loop'em and do'em You can't use foreach here as StackTrace is not derived from IEnumerable. for int i 0 i lt FrameCount i StackFrame StkFrame GetFrame i BuildFrameInfo StrBld , StkFrame Takes care of the scut...

Listing 72 EEAddIn example for osversioninfoa

This touches only the first 5 DWORDS in the structs, so you can pass both the ANSI and UNICODE versions in. static int ConvertBaseOSV LPOSVERSIONINFOA pOSVA , char szStr if pOSVA- gt dwMajorVersion 4 amp amp pOSVA- gt dwMinorVersion if pOSVA- gt dwPlatformId VER_PLATFORM_WIN32_NT iCurrPos wsprintf szStr , _T Windows NT 4.0 iCurrPos wsprintf szStr , _T Windows 95 else if pOSVA- gt dwMajorVersion 4 amp amp pOSVA- gt dwMinorVersion 10 iCurrPos wsprintf szStr , _T Windows 98 else if pOSVA- gt...

Figure 74 Autoexpand in a data tip

When entering my new autoexpand rule, I must place it after the section of the AUTOEXP.DAT file delineated by AutoExpand . Your best bet is to place your values right after AutoExpand so that you can find them easily and not mess up the techniques I'll discuss in the next section. The good news is that unlike the managed debugging autoexpands that are read only when you start Visual Studio .NET, the AUTOEXP.DAT file is read in each time you debug, so developing native autoexpand rules is much...

pdbstripped Strip Private Symbols

One of the biggest debugging problems you have at customer sites is getting a clean call stack. The reason you can't get good call stacks is that the stack walking code doesn't have the special frame pointer omission FPO data necessary for it to help decipher the current stack. Since the PDB files for your application are what contain the FPO data, you can just ship them to your customers. While that rightfully makes you and your manager nervous, up until Visual C .NET you were at a loss for...

The Set Next Statement Command

One of the coolest hidden features in the Visual Studio .NET debugger is the Set Next Statement command. It is accessible in both source windows and the Disassembly window on the shortcut menu, but only when you're debugging. What the Set Next Statement command lets you do is change the instruction pointer to a different place in the program. Changing what the program executes is a fantastic debugging technique when you're trying to track down a bug or when you're unit testing and want to test...

Technical Editor Robert Lyon

Did I tell you how proud I am of you yet today In memory of Helen Robbins. You always made the reunions the place to be. We miss you terribly. John Robbins John is a cofounder of Wintellect www.wintellect.com , a consulting, debugging and education company dedicated to helping companies produce better software faster. At Wintellect, John heads up the consulting and debugging services side of the business and helped debug and tune applications for companies such as eBay, Microsoft, and AutoDesk,...

Code Elements

One of the most amazing aspects of Visual Studio .NET is that all the programming constructs for source files can be accessed easily through the object model. The fact we can now simply add, change, or remove items such as methods in all languages supported by Visual Studio .NET without having to do the parsing ourselves opens up huge opportunities for all sorts of unique tools that might never have been created because parsing is so hard. Every time I use the code elements to manipulate the...

Operating System Heaps

Although you thought I might be done with the heap system after so many pages, there's another set of heaps you'll definitely want to know about the operating system heaps. As an application starts under a debugger, Windows turns on the operating system heap checking. This heap isn't the C run-time library debug heap it's the Windows heap code for those heaps created with the HeapCreate API function. The C run-time library heap is a separate entity. Because processes use the operating system...

ProfilerLib

Before we get into the guts of the ExceptionMon profiler, I want to spend a little time talking about ProfilerLib. As you can probably guess from the discussions about the COM Profiling API so far, there's a lot of boilerplate code. Since I'm not really into typing the same thing over and over when I develop software, I quickly realized that I needed a library to do the grunt work, especially given the large number of methods supported by the iCorProfilerCallback interface. The two sample...

Common Debugging Question Why does every developer need Process Explorer

I've already mentioned that Mark Russinovich's wonderful Process Explorer program makes it trivial to find which instance of DLLHOST.EXE has a particular DLL loaded and to determine whether you have relocated DLLs in a process. However, there's so much more to Process Explorer such as being an outstanding debugging tool and I want to take a moment to discuss some of its excellent features. By default, Process Explorer updates periodically, just like Task Manager. Although this updating is great...

Ensuring Correct Symbols Are Loaded

WinDBG excels at symbol handling. Whereas Visual Studio .NET gives you no chance to see exactly what's loaded, WinDBG shows you everything. When I'm doing native debugging, I use WinDBG to ensure I have all my symbols aligned before moving over to the ease of Visual Studio .NET. That way I know exactly where I stand and don't have the surprise of stepping through comments or having an operating system symbol point into never-never land. The most important feature of WinDBG's symbol handling is...

MinDBG A Simple Win32 Debugger

From a distance, a Win32 debugger is a simple program, with only a couple requirements. The first requirement is that the debugger must pass a special flag in the dwCreationFlags parameter to CreateProcess DEBUG_ONLY_THIS_PROCESS. This flag tells the operating system that the calling thread will enter a debug loop to control the process it's starting. If the debugger can handle multiple processes spawned by the initial debuggee, it will pass debug_process as the creation flag. As you can see,...

Info Vss

Just pass on any other exceptions to the debuggee. For any other events, just continue on. Pass on to the operating system. ifdef _DEBUG ContinueDebugEvent stDE.dwProcessId , stDE.dwThreadId , dwContinueStatus Check to see if the detach is supposed to happen. Detaching only works on XP and higher so I'll have do the GetProcAddress to look up the DebugActiveProcessStop. bContinue FALSE GetModuleHandle _T KERNEL32.DLL PFNDEBUGACTIVEPROCESSSTOP BOOL WINAPI CtrlBreakHandler DWORD dwCtrlType I'll...

The Basics

The biggest problem people face when dealing with WinDBG is getting it set up and wading through a ton of spewed output. I want to turn to a few issues that will help you get past some of those hurdles so that you don't have to bear the scars of learning them. Finally, I'll cover some of the odd quirks of WinDBG so that they won't surprise you and leave you scratching you head wondering what went wrong. The big thing to remember about WinDBG is that it's kind of a retro debugger. Heck, the...

Info Udu

TRACE0 GetFirstStackTraceString - invalid pExPtrs n return NULL Get the stack frame filled in. FillInStackFrame pExPtrs- gt ContextRecord Copy over the exception pointers fields so I don't corrupt g_stContext pExPtrs- gt ContextRecord return InternalGetStackTraceString dwOpts LPCTSTR BUGSUTIL_DLLINTERFACE _stdcall All error checking is in InternalGetStackTraceString. Assume that GetFirstStackTraceString has already initialized return InternalGetStackTraceString dwOpts CH_ReadProcessMemory...

Advanced Breakpoint Syntax

Unlike managed debugging, native debugging has additional capabilities to control exactly when and where breakpoints occur. Because of the nature of native symbol generation, many times you need to provide the debugger with additional help so that it properly places the breakpoint where you want it. When it comes to debugging symbols, the rules are much looser than the strict C scoping rules. For example, it's perfectly reasonable to have multiple top-level symbols for LoadLibrary. Each module...

Walking the Stack

Earlier I alluded to the fact that DBGHELP.DLL has the stackWalk64 API function, so we don't have to write our own stack walking code. stackWalk64 is straightforward and takes care of all your stack walking needs. WDBG uses the stackWalk64 API function, just as the WinDBG debugger does. The only snag you might encounter is that the documentation isn't explicit about what needs to be set in the stackframe64 structure. The code here shows you the exact fields that need to be filled out in the...

Using the Debug C RunTime Library

The first step in using the .DCRT library is to include it and turn it on so that you can start benefiting from the memory tracking as early in your project as possible. In your main precompiled header file or whatever header file all the source files in your project will include , add the following line before any include directive in your precompiled header file After the rest of your header files, include CRTDBG.H. Defining _crtdbg_map_alloc will redirect normal calls to memory allocation...

Controlling the TraceListener Object with Configuration Files

If you develop console and Windows Forms applications, for the most part, DefaultTraceListener should serve most of your needs. However, having a message box that pops up every once in a while can wreak havoc on any automated test scripts you might have. Alternatively, you use a third-party component in a Win32 service and the debug build of that component is properly using Debug.Assert. In both of these cases, you want to be able to shut off the message box generated by DefaultTraceListener....

Overview Uno

Your program has crashed. You have the crash address because the operating system is nice enough to give it to you when your application dies. Now what do you do My friend Chris Sells calls this scenario the my program went on vacation and all I got was this lousy address problem. Although having the address is better than nothing, having the source file and the line number of the crash would be much more convenient. I suppose you could always give the source code to your users and have them...

The Important Instructions

Instead of providing a huge table of instructions, I want to show the most important instructions you'll run into and examples of their use. I'll start with the loading instructions and explain all their options. As I get to the other types of instructions, I'll skip parts that are in common with the load instructions and just show their usage. The instructions I don't cover are quite easy to figure out based on their names. This instruction pushes a hard-coded number on the stack. The...

Initialization and Termination in C

After I finished implementing MemDumperValidator and started to test it, I was pleased that the extension worked as planned. However, as I was pondering all the ways that a program can allocate heap memory, I started to break out in a cold sweat. Were static constructors that possibly allocate memory going to give me any problems As I looked at my initial code for MemDumperValidator, I discovered a glaring hole in my logic. Although most developers don't do it much, in some cases, memory is...

Looking at and Evaluating Variables

Peeking at the local variables is the domain of the dv Display Local Variables command. One thing that's a little confusing about using WinDBG is seeing local variables up the stack. It actually takes a couple of commands to do what clicking in the Call Stack window does automatically. The first step is to use the K Display Stack Backtrace command with the N modifier to see the call stack with the frame numbers in the far left column of each stack entry. By the way, my favorite stack display...

Creating and Reading a MAP File

Many people have asked me why I keep recommending that everyone create MAP files with their release builds. Simply put, MAP files are the only textual representation of your program's global symbols and source file and line number information. Although using CrashFinder is far easier than deciphering a MAP file, your MAP files can be read anywhere and anytime, without requiring a supporting program and without requiring all your program's binaries to get the same information. Trust me, at some...

Debugging Injected Code

One of the interesting new features in Visual C .NET is the new attributed programming model. This new model can make COM development much easier because it allows you to combine IDL attributes with your source file so that you must have only a single file to make a COM object. If you'd like to see a real example of attributed COM programming, check out the Tester object from Chapter 16. Additionally, attributed programming offers a consistent way to provide unified message handling for your...

Controlling WinDBG

Now that you've seen the important commands for debugging, I want to turn to a few meta commands that I haven't already covered. You can use these to control or make better use of WinDBG while debugging. Those I discuss are by no means a complete list of all the commands but rather a list of cool meta commands I use on a daily basis when debugging with WinDBG. The simplest but extremely useful command is .cls Clear Screen . This allows you to clear the Command window so that you can start...

Recording Scripts

Now that you're armed with an understanding of the Tester objects and how to call them from your own scripts, I can turn to the TESTREC.EXE program that you'll use to record the interaction with your applications. When you first fire up TESTREC.EXE, you'll notice that it's a text editor that has a little bit of code already written for you. By default, the language is JScript, but I'll show you how to change the default to VBScript in a moment. Starting the recording is as simple as pressing...

Common Debugging Question Why do some function calls start with ILT in the

In the discussion of the code generated by the Gh switch, one of the function calls is call ilt 0 Foo, which has caused confusion for many developers. What you're seeing in action is the magic of incremental linking. ILT stands for Incremental Link Table. When creating a debug build, the linker wants to link the binary as fast as possible. Consequently, each function is given quite a bit of padding so that if the function changes, the linker only has to overwrite that function in place it...