Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stepping through code on one thread leads to debugger breaking on all breakpoints unconditionally #20

Open
ynwarcs opened this issue Oct 15, 2024 · 1 comment · May be fixed by #21
Open

Comments

@ynwarcs
Copy link

ynwarcs commented Oct 15, 2024

Basically, if a conditional breakpoint triggers while you're stepping through some unrelated code on another thread, the debugger will break at the breakpoint regardless of the condition being true or false. This also deletes the implicit breakpoint at the step-over/step-into address, so if you want to continue stepping you have to go back to the address and set an explicit breakpoint.

I checked the behaviour in other debuggers and WinDBG also has this same bug, but Visual Studio and IDA's debugger handle it properly: the condition is evaluated and the debugger only breaks if the condition is true. Additionally, the implicit breakpoint is not destroyed, so continuing will lead to the program properly breaking at the step-over/step-into address.

Repro steps:

  • Compile the following program:
#include <thread>
#include <Windows.h>

int main()
{
	auto lambda = []()
		{
			while (true)
			{
				OutputDebugStringA("Hello from the other thread\n");
				Sleep(1200u);
			}
		};

	std::thread workerThread(lambda);

	while (true)
	{
		OutputDebugStringA("Hello from the main thread\n");
		Sleep(3000u);
	}

	workerThread.join();
	return 0;
}
  • Run the executable, attach x64dbg.
  • Set a normal breakpoint at the Sleep call on the main thread.
  • Set a breakpoint with condition "0" at the Sleep call from the worker thread.
  • Wait until program breaks at the first breakpoint.
  • Step over the Sleep call.
  • Observe that the debugger breaks on the second breakpoint, despite the condition being false.
@ynwarcs
Copy link
Author

ynwarcs commented Oct 15, 2024

I guess this could be thought of as three separate problems:

a) breakpoints hijack stepping behaviour (regardless of whether they are on the same thread), in VS this also happens but only for breakpoints on the same thread. I guess there's no way to tell whether the debug event received from the OS is a step completion event or a breakpoint event so this could be acceptable to an extent.
b) breakpoints triggered during a step operation will make the debugger break regardless of the break condition being false or true
c) other threads can hijack stepping of the thread on which the step is being performed.

To mimic VS's behaviour in a) & c), we would just need to isolate the stepping state we're storing to a specific thread, as is done in the PR above. To fix the behaviour in b), we'd need to be able to evaluate the breakpoint condition from TitanEngine and do nothing if it's false.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant