Channels ▼
RSS

.NET

Debugging with NTSD and Application Verifier

Source Code Accompanies This Article. Download It Now.


Application Verifier Limitations

I designed the program in Example 5(a) to specifically use a 16-byte buffer to be sure that the buffer overrun was detected. That is, an apparent limitation of AppVerif revealed through experimentation is that when it intercepts an allocation, it returns a buffer with a start address that is 16-byte aligned. This means that if the code were to request only a 10-byte buffer, then AppVerif would not return a pointer to the last 10 bytes of the valid block. Instead, it would return a pointer to the last 16 bytes of the valid block. The remaining 6 bytes in the block are still valid memory and, unfortunately, the application can happily overrun the 10-byte buffer by up to 6 bytes despite being verified by AppVerif.

So, to automatically detect 1-byte overruns using AppVerif, I need to write wrappers around the malloc and free functions. Example 8 shows examples of suitable wrapper functions called AvrfAlloc and AvrfFree. AvrfAlloc ensures that it always asks malloc for a buffer with a size that is a multiple of 16 bytes. However, it then moves the pointer so that it is exactly the requested number of bytes before the end of the buffer. It also uses a single byte just before the start of the returned buffer to store the offset in bytes from the previous 16-byte alignment so that AvrfFree can later move the buffer pointer back before freeing it. AvrfAlloc effectively pushes the end of the returned buffer to be right before the next 16-byte boundary. Now when the application is being verified by AppVerif, the 1-byte overrun will always be into an inaccessible page of memory.

void *AvrfAlloc(size_t cb)
{
   char *pch = NULL;
   char delta = 0;

   cb++;
   delta = cb & 16;
   if (0 != delta)
   {
      delta = 16 - delta;
      cb += delta;
   }
   pch = malloc(cb);
   if (NULL != pch)
   {
      pch += delta;
      *pch++ = delta + 1;
   }
   return(pch);
}
void AvrfFree(void *pv)
{
   char offset = *((char*)pv - 1);
   free((char*)pv - offset);
}

Example 8: Wrapper functions for malloc and free that compensate for the 16-byte alignment imposed by AppVerif.

Another coding method that helps spot buffer overruns regardless of the presence of AppVerif is to write code that simulates what AppVerif is doing here, but without its 16-byte buffer alignment restriction. Listing One (available electronically; see "Resource Center," page 5) contains the source code for two functions called MyAlloc and MyFree that do just this, and can replace malloc and free. The MyAlloc function calls the Windows Memory Management function VirtualAlloc to allocate enough pages to hold the requested buffer, plus an additional page called the guard page (one page is typically 4096 bytes). This means that each call to MyAlloc allocates at least two pages. It then calls VirtualProtect to mark the guard page as inaccessible. Finally, it returns a pointer to an address located exactly at the originally requested number of bytes before the beginning of the guard page. The corresponding MyFree function simply rounds the pointer value down to the nearest page boundary before passing it to VirtualFree. As with AppVerif, this uses a lot of extra memory, and can noticeably slow down the application.

Debugging Customer Crashes

Debugging crashes is fairly straightforward when you have physical access to the machine. However, if the crash occurs at customer sites, then you often cannot get access to the customer's machine. In these cases, I ask the customer to configure the built-in Dr. Watson for Windows tool to automatically generate a crash dump file when the access violation occurs. The customer then sends me the crash dump file so that I can load it into ntsd using the command ntsd -z user.dmp.

The Dr. Watson tool works okay, but in some cases, a customer's machine may not generate the required Dr. Watson crash dumps. As a work around, it is worthwhile to prepare a short note for the customer describing how to obtain a crash dump using ntsd.exe (or perhaps just point them to this article!). In the case where an application is crashing and the customer knows how to reproduce the crash (in Microsoft parlance, "the customer has a repro"), they can obtain a crash dump by running ntsd.exe from the command line, passing the application command-line as an argument (ntsd -g MyApp.exe, for instance). The customer then performs their repro and, when the crash occurs, the debugger breaks in. A crash dump can be generated using a Create Dump File command similar to .dump /m C:\Files\user.dmp. Similarly, to get a crash dump for a hung application, the customer can attach the ntsd debugger to the running application by specifying the process identifier for the application (for example, ntsd.exe -p <pid>). The debugger breaks into the application, and the customer can obtain a crash dump as previously described.

Conclusion

I've given here an overview of the Microsoft NT Symbolic Debugger (ntsd) and Microsoft Application Verifier, along with some useful code samples. For further information about the truly enormous array of ntsd debugger commands, I recommend reading the debugger.chm help file that ships with the Microsoft Debugging Tools for Windows package.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video