Who's Using the Pool?

Every driver developer must track down bugs related to pool memory allocations. Pool tags can help you find out which allocation is at fault or whether the bug is in another driver.

A pool tag is a four-character literal associated with a memory allocation. By monitoring allocations associated with particular tags, you can tell which components are allocating memory and, more importantly, which components are failing to free the memory they allocate, causing memory leaks.

Assigning pool tags in a driver. Drivers assign pool tags when they allocate paged or nonpaged, cached memory from the kernel-mode pool by using ExAllocatePoolWithTag, ExAllocatePoolWithTagPriority, and ExAllocatePoolWithQuotaTag. (A minidriver uses the class driver's version of these routines, such as NdisAllocateMemoryWithTag for an NDIS miniport driver.)

For example, the following code fragment allocates a buffer from cache-aligned nonpaged pool and associates the pool tag MyBf with the allocation. The pool tag in the ExAllocatePoolWithTag call is specified in reverse order, so the tag appears properly in debugger and tool output.

MyBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
MAX_BUFFER_SIZE, 'fByM');
                    

Pool memory remains allocated until the driver frees it, so the driver must call ExFreePool or ExFreePoolWithTag (or, for a minidriver, the class driver's equivalent routine) to deallocate all memory that it allocated with any of the ExAllocatePoolXxx routines. If you use ExFreePoolWithTag, the supplied tag must match the tag used to allocate the memory; otherwise, the system bugchecks with Bug Check 0xC2: BAD_POOL_CALLER (Windows Debuggers).

When assigning pool tags, use unique tags that distinguish your driver from the other drivers in the system. (The file Pooltag.txt, described later in this tip, lists known tags used by other drivers and Windows components.) Also, be sure to use character literals ('fByM') and not string literals ("fByM"). A character literal evaluates to a constant ULONG, whereas a string literal evaluates to a constant pointer, so using a string literal as a tag causes type mismatch errors when you compile your driver.

The driver writer decides how many tags a driver uses. A small, simple driver might have a single unique tag, whereas a larger, more complex driver might have a different unique tag for each kind of allocation. Having multiple pool tags in a large driver is especially helpful when using the Special Pool option of Driver Verifier because it reduces the likelihood that allocations that use a specific tag will deplete the special pool.

Common errors related to pool tags include using a string literal instead of a character literal, failing to provide a pool tag, or using default pool tags that are obsolete for current versions of Windows. Code Analysis with driver-specific rules, a static source code analysis tool provided with the WDK, can be helpful in finding these and other kinds of errors in driver source code. For more information about Code Analysis for drivers, see the end of this tip.

Examining allocations by pool tag. Pool tags are reported in crash dumps and can be viewed with the kernel debugger or with tools such as Driver Verifier and PoolMon, which show pool tags in memory allocation statistics.

The system tags memory allocations only if pool tagging is enabled, even if you specify a tag with ExAllocatePoolWithTagXxx. Pool tagging is permanently enabled on Windows Server 2003 and later versions of Windows. For Microsoft Windows XP and earlier versions of Windows, you must first enable pool tagging with the Global Flags utility (Gflags) provided with Debugging Tools for Windows.

After pool tagging is enabled, you can use any of the following to examine allocations by pool tag:

  • Kernel debugger extensions. Use the debugger extensions !pool, !poolfind, and !poolused to display memory allocation statistics, search for instances of a specific pool tag in paged or nonpaged pool memory, and display memory use summaries by pool tag for each pool allocation.

    Use the debugger extension !verifier 0x3 to locate outstanding memory allocations after a driver is unloaded or to track allocations while the driver is running. This extension shows the pool tag, the size of the pool, and the address of the function that allocated the memory.

    These debugger extensions are provided in the Debugging Tools for Windows package, which includes debuggers, other debugger tools, and documentation.

  • Driver Verifier. Use the Special Memory Pool option of Driver Verifier to allocate memory marked with a specific pool tag from the special pool, a limited area of nonpaged pool that can be used to monitor allocations for incorrect access. Use GFlags to specify the tag before activating Driver Verifier with this option.

    Driver Verifier is provided with Windows and documented in the Windows DDK.

  • Poolmon. Use PoolMon (the Memory Pool Monitor) to monitor memory allocations by drivers and system components while the system is running. (The Pooltag utility, also provided with the WDK, is a GUI-based subset of this tool.)

    Poolmon and Pooltag are provided with the WDK. The WDK documentation for Windows Server 2003 SP1 contains several detailed examples for using Poolmon, including how to detect memory leaks.

See the resources at the end of this tip for availability of Debugging Tools for Windows and the WDK.

Whose tag is that? The file Pooltag.txt lists the pool tags used for pool allocations by kernel-mode components and drivers supplied with Windows, the associated file or component (if known), and the name of the component. Pooltag.txt is installed with Debugging Tools for Windows (in %windbg%\triage) and with the Windows DDK (in %winddk%\tools\other\platform\poolmon, where platform is amd64, i386, or ia64).

You can search the file for a specific tag to find the tag's owner. The following example shows a few lines from Pooltag.txt:

8042 - i8042prt.sys - PS/2 kb and mouse
ARPC - atmarpc.sys  - ATM ARP Client
ATMU - atmuni.sys   - ATM UNI Call Manager
Atom - <unknown>   - Atom Tables
Abos - <unknown>   - Abiosdsk
                    

If the tag you're looking for doesn't appear in Pooltag.txt, you might be able to find its owner by using one of the following techniques:

  • For 32-bit versions of Windows, use poolmon /c to create a local tag file that lists each tag value assigned by drivers on the local machine (%SystemRoot%\System32\Drivers\*.sys). The default name of this file is Localtag.txt.

  • For Windows 2000 and Windows NT 4.0, use Search to find files that contain a specific pool tag, as described in KB298102, How to Find Pool Tags That Are Used By Third-Party Drivers.

What should you do?

  • When assigning pool tags, use unique tags that distinguish your driver from the other drivers in the system.

  • Be sure to use character literals instead of string literals for your tags.

  • If you're writing a minidriver, use the memory allocation routines provided by the class driver rather than the ExAllocatePoolWithTagXxx routines.

  • Remember to release pool memory and, if you use ExFreePoolWithTag (or equivalent for a minidriver), supply the same tag that was used when allocating the memory.

  • Run Code Analysis (PREfast) with driver-specific rules on your driver source code.

  • For debugging memory allocations on Windows XP and earlier versions of Windows, first use the Gflags utility to enable pool tagging.

  • Use the kernel debugger extensions and tools described in this article to take advantage of pool tags when debugging memory allocations in your driver.

Six Tips for Efficient Memory Use

PREast

Special Pool

PoolMon

Debugging Tools for Windows

 

 

Send comments about this topic to Microsoft