g_dwLastErrorToBreakOn: Watching Errors on VS Revisited

Raymond Chen posted about SetLastError recently, and an interesting discussion ensued. One comment in particular caught my eye:

The easiest way to catch a specific last error value in debugger is to set ntdll!g_dwLastErrorToBreakOn to that value.

A good while back I needed to break when such a LastError is set, and dug up all sorts of hacks to do so – breaking at SetLastError, setting data breakpoint on the thread-env-block-error, and the like. Beyond being cumbersome and plain ugly such breakpoint tricks can be very slow, and give a lot of false positives.

Seems the Win32 folks had similar needs and I was glad to discover they formed a better (undocumented, but still) solution. The authoritative source seems to be a 2007 post from Microsoft’s Daniel Pearson:

..Hiding inside of kernel32’s address space is a global variable called g_dwLastErrorToBreakOn. It turns out that SetLastError checks the value of this variable and if it’s non-zero, calls DbgBreakPoint if the two [values] match.

It’s a zero-overhead trick, and is very easy to do in Visual Studio: make sure kernel32.dll symbols are loaded, then type in a watch window –

(int*){,,kernel32.dll}_g_dwLastErrorToBreakOn

– and edit the referenced int:

image

Pearson notes two changes introduced in Vista:

(1) Up until XP, only Win32 API implemented in KERNEL32.DLL actually used SetLastError (and so tested g_dwLastErrorToBreakOn) – other dll’s used to set the error value via RtlSetLastWin32Error. Since Vista all Win32 API which set an error do so with SetLastError, so the g_dwLastErrorToBreakOn is much more reliable.

(2) Since Vista, g_dwLastErrorToBreakOn moved to NTDLL.DLL, so the VS usage should be changed to –

(int*){,,ntdll.dll}_g_dwLastErrorToBreakOn

It’s interesting to note that ntdll.dll does contain a separate instance of g_dwLastErrortToBreakOn also on XP machines:

image

But I verified that this value is never read, on calls into both kernel32 and ntdll.

Advertisements
This entry was posted in Debugging, Win32. Bookmark the permalink.

2 Responses to g_dwLastErrorToBreakOn: Watching Errors on VS Revisited

  1. Niv Fisher says:

    Great post – will come in handy!

    BTW, what is the default value? does it ignore (ie. not break) when zero?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s