Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What expressions are allowed in tracepoints?

When creating a tracepoint in Visual Studio (right-click the breakpoint and choose "When Hit..."), the dialog has this text, emphasis mine:

You can include the value of a variable or other expression in the message by placing it in curly braces...

What expressions are allowed?

like image 375
Kurt Hutchinson Avatar asked Feb 04 '13 21:02

Kurt Hutchinson


People also ask

What are Tracepoints?

Tracepoints are a new debugger feature in Visual Studio. A tracepoint is a breakpoint with a custom action associated with it. When a tracepoint is hit, the debugger performs the specified tracepoint action instead of, or in addition to, breaking program execution.

How do you use Tracepoint?

Set tracepoints in source codeTo initialize a tracepoint, first click on the gutter to the left of the line number where you want to set the tracepoint. Hover over the red circle and then click the gear icon. This action opens the Breakpoint Settings window. Select the Action checkbox.

What is Visual Studio Tracepoint?

Tracepoint is an awesome feature of Visual Studio and it is available since Visual Studio 2005. It allows you to write the values in output window without even stopping at any point or you can stop it after the loop and see how the loop progressed based on your needs.

How do I enable debugging in Visual Studio?

In the Visual Studio toolbar, make sure the configuration is set to Debug. To start debugging, select the profile name in the toolbar, such as <project profile name>, IIS Express, or <IIS profile name> in the toolbar, select Start Debugging from the Debug menu, or press F5.


2 Answers

Microsoft's documentation is rather sparse on the exact details of what is and is not allowed. Most of the below was found by trial and error in the Immediate window. Note that this list is for C++, as that's what I code in. I believe in C#, some of the prohibited items below are actually allowed.

Most basic expressions can be evaluated, including casting, setting variables, and calling functions.

General Restrictions
  • Only C-style casts supported; no static_cast, dynamic_cast, reinterpret_cast, const_cast
  • Can't declare new variables or create objects
  • Can't use overloaded operators
  • Ternary operator doesn't work
  • Can't use the comma operator because Visual Studio uses it to format the result of the expression; use multiple sets of braces for multiple expressions
Function Calls
  • Prohibited calls:
    • Lambdas (can't define or call them)
    • Functions in an anonymous namespace
    • Functions that take objects by value (because you can't create objects)
  • Permitted calls:
    • Member functions, both regular and virtual
    • Functions taking references or pointers, to either fundamental or class types
    • Passing in-scope variables
    • Using "&" to pass pointers to in-scope variables
    • Passing the literals "true", "false", numbers
    • Passing string literals, as long you don't run afoul of the "can't create objects" rule
    • Calling multiple functions with one tracepoint by using multiple sets of braces
Variable Assignment
  • Prohibited:
    • Objects
    • String literals
  • Permitted:
    • Variables with fundamental types, value either from literals or other variables
    • Memory addresses, after casting: { *(bool*)(0x1234) = true }
    • Registers: { @eip = 0x1234 }

Use Cases

Calling functions from tracepoints can be quite powerful. You can get around most of the restrictions listed above with a carefully set up function and the right call. Here are some more specific ideas.

Force an if

Pretty straightforward: set up a tracepoint to set a variable and force an if-condition to true or false, depending on what you need to test. All without adding code or leaving the debug session.

Breakpoint "toggling"

I've seen the question a few times, "I need to break in a spot that gets hit a lot. I'd like to simply enable that breakpoint from another breakpoint, so the one I care about only gets breaks from a certain code path. How can I do that?" With our knowledge above, it's easy, although you do need a helper variable.

  1. Create a global boolean, set to false.
  2. Create a breakpoint at your final destination, with a condition to break only when the global flag is true.
  3. Set tracepoints in the critical spots that assign the global flag to true.

The nice thing is that you can move the tracepoints around without leaving the debugging session. Use the Immediate window or the Watch window to reset your global flag, if you need to make another run at it. When you're done, all you need to clean up is that global boolean. No other code to remove.

Automatically skip code

The EIP register (at least on x86) is the instruction pointer. If you assign to it, you can change your program flow.

  1. Find the address of the line you want to skip to by breaking on it once and looking at the value of EIP, either in the Registers window or the Watch window with "@eip,x". (Note that the value in the Registers window is hex, but without the leading "0x".)
  2. Add a tracepoint on the line you want to skip from, with an expression like {@eip = address}, using the address from step 1.
  3. EIP assignment will happen before anything on the line is executed.

Although this can be handy, be careful because skipping code like this can cause weird behavior.

like image 123
Kurt Hutchinson Avatar answered Oct 10 '22 05:10

Kurt Hutchinson


As Kurt Hutchinson says, string assignment is not allowed in a tracepoint. You can get around this by creating a method that assigns the string variable, and call that.

public static class Helper
{
    public static void AssignTo(this string value, out string variable)
    {
        variable = value;
    }
}

Then in your tracepoint message:

{"new string value".AssignTo(out stringVariable)}
like image 29
Protector one Avatar answered Oct 10 '22 05:10

Protector one