Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Condition breakpoint on higher stack frames

In the MSVC++ debugger, is it possible to create a breakpoint in one function, whose condition depends on local variables from other stack frames? I often find myself creating a conditional breakpoint in one function, and when that breakpoint hits, I enable another breakpoint (which I expect to fire before exiting the current function invocation) and continue. It's time-consuming and error-prone.

One approach I've taken in the past is to write the variable in question to a global, and use that global as a condition. But that requires a recompile, and doesn't work with multithreaded code.

like image 646
Sneftel Avatar asked May 07 '14 23:05

Sneftel


People also ask

How do you trigger a breakpoint?

To set a breakpoint in source code: Click in the far left margin next to a line of code. You can also select the line and press F9, select Debug > Toggle Breakpoint, or right-click and select Breakpoint > Insert breakpoint. The breakpoint appears as a red dot in the left margin.

Does breakpoint stop before or after line?

The breakpoint will stop your program just before it executes any of the code on that line. Set a breakpoint at line linenum in source file filename .

What is Call Stack in debugger?

The call stack is a list of all the active functions that have been called to get to the current point of execution. The call stack includes an entry for each function called, as well as which line of code will be returned to when the function returns.

How to check Call Stack in vs?

In Visual Studio Enterprise (only), you can view code maps for the call stack while debugging. In the Call Stack window, open the shortcut menu. Choose Show Call Stack on Code Map (Ctrl + Shift + `).


1 Answers

Yes, that's technically possible. No great joy, mind you, you'll have to tell the debugger to dereference a pointer to obtain the value of the local variable in the other stack frame.

A simple example:

#include "stdafx.h"
#include <iostream>

void foo() {
    for (int ix = 0; ix < 5; ++ix) {
        std::cout << ix << " ";                 // <=== Conditional breakpoint here
    }
}

void bar() {
    for (int jx = 0; jx < 5; ++jx) {
        std::cout << jx << ": ";                // <=== Start with a breakpoint here
        foo();
        std::cout << std::endl;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    bar();
    return 0;
}

You first need to obtain the address of the variable that you want to set the condition on. Set a breakpoint on the indicate line in bar(). When it hits, evaluate &jx and copy the value.

Now set the conditional breakpoint, using that value. I used:

  *(int*)0x0073fbc8 == 2 && ix == 3

Where 0x0073fbc8 was the value I obtained at the first breakpoint. Or you can make it relative from the base pointer register. Set an unconditional breakpoint and when it hits use Debug + Windows + Registers to look at the EBP value. Subtract it from the &jx value. I used:

  *(int*)(ebp+0xd8) == 2 && ix == 3

Both worked well. Note that you'll want to turn ASLR off for the Debug build to have some hope that these addresses are repeatable from one run to another. Project + Properties, Linker, Advanced, Randomized Base Address = No.

like image 74
Hans Passant Avatar answered Sep 21 '22 05:09

Hans Passant