Just some background on what I am currently looking on. And why it does not match your case.
In my testcase I have 9 threads, that all go round and round and round on about 12 asm instructions.
So quite often more than one of them is at the same address, and at the same breakpoint.
If 2 threads hit a breakpoint, windows will inform the debugger twice, and each time it informs the debugger is stops all threads (at least it is supposed to, and does for me).
But in order to get the 2nd notification, the debugger must acknowledge the first. And at this time all threads will run again (well the debugger suspends some of them. But given enough threads and the right pattern some will run).
That also means that the following can happen.
(When there are more than 2 threads, then between the 2 breakpoint notifications, there can be other events. And the breakpoint may be removed in those other events. The below is massively simplified)
-- 2 threads hit breakpoint "A"
-> Notification for Thread-1 at "A"
The debugger will handle the notification.
But coincidently at this time, while handling the notification, the breakpoint "A" gets permanently removed.
<- Debugger acknowledges the notification, and app runs again (the other threads will be suspended, but that actually does not matter)
-> Notification for Thread-2 at "A"
The breakpoint no longer exists, but the thread had hit it before.
Here the debugger has a bug. => As it does not see a breakpoint, it does not handle it correctly.
<- Debugger acknowledges the notification, and app runs again
And now the thread with the unhandled breakpoint will crash.
1) Why is it different from your case?-> The breakpoint must get removed (well you did toggle it, so that includes removal)
-> A notification of type "breakpoint hit" must reach the debugger for that removed breakpoint
That I have not seen in your log.
-> Also the thread would fail at the address of the breakpoint (actually + 1 byte).
And your thread fails at this $100002 address. Which was never touched.
That is, if that is indeed correctly reported....
I can only guess it must be in a dll... Because your normal code resides at $4....... addresses. And the Kernel usually is at $7f.......
2) What exactly means "does not handle the breakpoint correctly"Well here is how a breakpoint works (though of course WOW64 for arch/arm will (should) emulate that).
Say the testcase has an instruction like (this is just dummy data)
Address mem-dump asm
0x410010 71 72 73 74 mov rax, eax
The debugger will replace the first byte with $CC (an int3 instruction, that is handled as breakpoint).
The test process will execute the int3, and its instruction pointer will then be at 0x410011. The byte after the breakpoint.
The OS catches the int3 and tells the debugger.
Now the debugger must do 2 things:
- tell the OS, to clear the signal. So the test app does not get a signal for the int3. (that seems still to happen in the buggy case)
- restore the original code, and restore the instruction pointer to 0x410010 => so the original instruction can be run
- (after that, put the breakpoint back in place)
But due to the bug, the debugger does not do the 2nd step.
That means the test app continues at 0x410011. And it takes the "72 ..." as it's next instruction. Only that was never an instruction, and that is why it crashes.