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

Advertisement
This entry was posted in Debugging, Visual Studio. Bookmark the permalink.

9 Responses to Breaking on System Functions with the Context Operator

  1. Koby Kahane says:

    Pretty astounding that basic syntax for setting breakpoints in the debugger is poorly documented and broken. Having to use undecorated names by hand is outright embarrassing.
    I’m sure users of the VS debugger will appreciate your research.

    • Ofek Shilon says:

      Hi Koby,
      After writing this up it occurred to me that if I were in MS shoes I probably wouldn’t fix this feature too – there’s just not much value to costumers in it to start with (it’s very easy setting breakpoints anywhere in your code without this weird syntax). The one sub-feature that may be of value (breaking into system functions) *is* working. I guess the right thing to do is annihilate all the broken rest, and maybe simplify the location syntax to Module.exe!FunctionName.
      Regarding decorated names usage: (a) you’re right, (b) I think they’re not needed since VS2008 – will check soon and maybe post again, (c) IIRC, even WinDbg does not decorate the given names himself, but rather allows wildcards – something like
      > bp kernel32.dll!*OutputDebugStrings*
      Am I right?

  2. Koby Kahane says:

    The Windbg address syntax has full support for decorated names. An example taken from the Windbg documentation:

    bu @!”ExecutableName!std::pair<unsigned int,std::basic_string<unsigned short,std::char_traits,std::allocator > >::operator=”

    Additionally, the syntax supports source file and source line specification, e.g. http://msdn.microsoft.com/en-us/library/cc266533.aspx

    It’s true that setting local breakpoints (i.e., by source line) not by point and click is less important, but I really think both ought to just work.

    Be the Visual Studio Debugger team’s priorities regarding this feature as they may, there’s hardly an excuse for the documentation to say one thing and for the product to do another, over the 6.0 (1998), 2002, 2003, 2005, 2008 and 2010 releases.

  3. Pingback: Debugging Memory Leaks, Part 2: CRT support « Ofek’s Visual C++ stuff

  4. Pingback: Debugging Memory Leaks, Part 3: Breaking on Allocations of Given Size « Ofek's Visual C++ stuff

  5. Pingback: Checking Memory Corruption with _CrtCheckMemory – From the Debugger « Ofek's Visual C++ stuff

  6. Pingback: The Case of the ‘X’ That Didn’t Kill the App « Ofek's Visual C++ stuff

  7. Pingback: How to set breakpoints without source code in Visual Studio 2010 « BugSlasher

  8. Pingback: Debugging Tip: How to Set a Breakpoint In a Windows API Function – YekNeb

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 )

Facebook photo

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

Connecting to %s