Breaking on System Functions with the Context Operator

[Edit, Aug 2010:] About a year after this trial-and-error-ish investigation, I accidently found this hidden bit of documentation which pretty much sums it up.

The context operator is technically documented, although barely so. Seemed to me the reason is that it’s mostly broken – but turns out you can in fact get some value out of it.

The documented syntax template is:

{[function],[source],[module] } location

(it is one of 3 different templates, but that’s the one that’s useful to me). Apparently these names have different meaning in different contexts.

Broken, Official Syntax

Here ‘function’ seems to mean function name, ‘source’ means source file, ‘location’ means line number in source file. Some of the documented examples prefix it with ‘@’, others with ‘.’. (edit: this is explicitly acknowledged elsewhere, but never explained).  From brief experimenting, however, none of these are working and this feature seems all but completely broken.

{,MySource.cpp,}@20


can get you to break at random locations in the file, or refuse to parse altogether.

{MyFunc, MyApp.cpp,}@3

May actually work. May also set the break location at a different line in the function. If the specified line is out of the function range, it may either set a break at a seemingly random source location or fail to parse.

etc. etc.  Documentation hasn’t changed between VS2003 and VS2010, and it seems these issues aren’t going anywhere anytime soon.

Working, Not-Really-Official Syntax

Turns out if you interpret ‘location’ as a function name, you may actually get some work done.  This is mentioned as a single-line example in the VC6 documentation, and also sporadically on the web.  For example:

{,,}MyFunc

Actually works.

With slight modifications (that Gregg does not mention), this can be used to break into functions with no source code: (a) include the module (i.e., exe/dll name) and (b) use decorated function names (this is said to be redundant since VS2008).  Needless to say, if you intend to break in MS functions (Win32, CRT or other), you’d need to obtain public MS symbols – maybe more on that in a future post.

For example,

{,,}OutputDebugStringW


would fail to parse,

{,,}_OutputDebugStringW@4


would parse successfully but will not set a break, and finally –

{,,kernel32.dll}_OutputDebugStringW@4

would get the job done.

Getting decorated names can be much easier than stated before, since most interesting MS functions are C functions: the decorated name (and module) can be viewed in the call-stack window, by stepping into the function (in disassembly):

decorcallstack

Obtaining Decorated Names

There is a neat command line tool called UNDNAME.EXE to un-decorate a name, but what if you need the opposite? I.e., given a function header, how do you get its decorated name?

Well, you could reconstruct it manually. The decoration scheme is intentionally undocumented, but at least 2 efforts were made to reverse engineer it.

If the name you’re after is of a function from your source, you can momentarily plant a FUNCDNAME inside it to get access to the decorated name from your code, and then, say, OutputDebugString it.

In the general case, there are two documented ways to obtain the decoration:

(1) Using DUMPBIN,

(2) Using a Listing File.

Using a listing file is superior in at least two ways: (a) it is one stage shorter – you don’t need to perform extra-analysis on compilation outputs, and (b) the step you save requires a command shell, which I personally avoid like the plague. Seriously, it is 2009. You shouldn’t work like they did in 1980 unless you have absolutely no choice.

In a recent StackOverflow discussion, two other options came up: using map files, and using dependency walker. These seemed like valid, even creative, solutions – and I wondered why MS didn’t document them as valid ways to observe decorations.

Well, MS chose so for a reason. Both suggestions have a fundamental flaw: map files, as well as dependency-walker display, contain only decorated names. This can be a serious problem if you need to isolate the decorated name to one of several function overloads. Your map file can, for example, include the following two names:

?ExtractElement@@YAHV?$_com_ptr_t@V?$_com_IIID@UIDCXOBJ@@$1?_GUID_5a54cea3_94aa_11d6_bdc8_00c04f03ca8b@@3U__s_GUID@@B@@@@KAAV?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@@Z
?ExtractElement@@YAHV?$_com_ptr_t@V?$_com_IIID@UIDCXOBJ@@$1?_GUID_5a54cea3_94aa_11d6_bdc8_00c04f03ca8b@@3U__s_GUID@@B@@@@K@Z

Have fun deciding which of the two matches -


BOOL ExtractElement( IDCXOBJPtr pObj, CONST DWORD Tag , CString& strOut)

Searching Through Memory in Visual Studio

MS maintains two separate debugger product lines – one (supposedly owned by the smaller team) being WinDbg and the other shipped with Visual Studio. There’s an ever-going online flame for superiority between fans of both debuggers (sample 1, sample 2).

By and far WinDbg is considered the ‘serious’ brother, and partially for a good reason.  There are important domains where WinDbg is the only option – notably kernel mode debugging. It is also said to be easier on remote debugging (which I’ve tried only with VS, and admittedly had some trouble).  However, I’ve too often seen claims for WinDbg superiority that are just based on poor VS skills – I’ll try and dedicate some posts to show VS parallels of common WinDbg capabilities.  I currently believe if you do user mode debugging with source code (even in production builds), there’s no real reason for you to step back to the command-line UI of WinDbg. I’d be happy to hear if anyone has different experience.

So, starting off with memory search. This is a relatively known capability of WinDbg, but it’s apparently much less known it is in fact available in VS.

You can search through a memory range for a particular pattern (e.g., a string) or one of several patterns. You do this by typing at the Immediate window (Ctrl+Alt+I while debugging), and the complete syntax is here.

A notable shortcoming of VS is that it does not implement the ‘L?’ address-range WinDbg syntax, so a single search is limited to a memory range of 256M.  On the few occasions where I needed this functionality, this wasn’t a major issue.

Digg This