L. Spiro
2005-02-25 03:35:05 UTC
I am writing a debugger with so-far great success, but something seems to be
wrong with my single-stepping routine.
Normally, without single-stepping, I do this:
//============
Breakpoint is hit.
Go to EXCEPTION_BREAKPOINT.
Change the value at the break from 0xCC back to its original value and set
EIP back one step.
Put the thread into single-stepping mode (EFlags |= 0x100).
Then ContinueDebugEvent() is called with DBG_CONTINUE.
Then EXCEPTION_SINGLE_STEP exception is thrown one step later.
I go back to the address of the break that was last hit and add the
breakpoint again.
I remove the single-step flag (EFlags &= ~0x100).
Then ContinueDebugEvent() is called with DBG_CONTINUE and the program
continues until another break is hit.
//============
This works.
Here is my logical pseudo code for single-stepping.
//============
::EXCEPTION_BREAKPOINT IS HANLED THE SAME WAY::
Then EXCEPTION_SINGLE_STEP exception is thrown one step later.
I check to see if this was hit because of a breakpoint from the last
instruction or because of single-stepping from the last instruction.
If it was a breakpoint, I add the 0xCC again.
If I am not in single-stepping mode, I continue as above by removing the
single-step flag and proceeding with DBG_CONTINUE.
If I am in single-step mode, I wait (on that thread) for the command to
either single-step or to continue normally (this waiting period happens
inside the EXCEPTION_SINGLE_STEP catch and before ContinueDebugEvent()).
If the user hits the single-step button, I set the single-step flag again
and call ContinueDebugEvent() with DBG_CONTINUE.
Otherwise I remove the single-step flag and call ContinueDebugEvent() with
DBG_CONTINUE.
//============
Is there something I am missing here?
After I give the command to single-step, the program, well, does something
else besides single-step (as far as I can tell).
To single-step a multi-threaded program, all threads must be set to
single-step, yes?
But if that is so, why does my first solution work when it only single-steps
one thread?
Or is it because that single thread single-steps, but others are still
running?
Usually what happens in my case is that I single step, but then the original
breakpoint is hit again one or two steps later, even though it should not be
anywhere near that breakpoint anymore.
Is it because it is hit on another thread then?
Is the purpose of single-stepping all threads just to make things work
logically or is there actually a Windows® implementation that prevents
single-stepping unless all threads are in single-stepping mode?
L. Spiro
wrong with my single-stepping routine.
Normally, without single-stepping, I do this:
//============
Breakpoint is hit.
Go to EXCEPTION_BREAKPOINT.
Change the value at the break from 0xCC back to its original value and set
EIP back one step.
Put the thread into single-stepping mode (EFlags |= 0x100).
Then ContinueDebugEvent() is called with DBG_CONTINUE.
Then EXCEPTION_SINGLE_STEP exception is thrown one step later.
I go back to the address of the break that was last hit and add the
breakpoint again.
I remove the single-step flag (EFlags &= ~0x100).
Then ContinueDebugEvent() is called with DBG_CONTINUE and the program
continues until another break is hit.
//============
This works.
Here is my logical pseudo code for single-stepping.
//============
::EXCEPTION_BREAKPOINT IS HANLED THE SAME WAY::
Then EXCEPTION_SINGLE_STEP exception is thrown one step later.
I check to see if this was hit because of a breakpoint from the last
instruction or because of single-stepping from the last instruction.
If it was a breakpoint, I add the 0xCC again.
If I am not in single-stepping mode, I continue as above by removing the
single-step flag and proceeding with DBG_CONTINUE.
If I am in single-step mode, I wait (on that thread) for the command to
either single-step or to continue normally (this waiting period happens
inside the EXCEPTION_SINGLE_STEP catch and before ContinueDebugEvent()).
If the user hits the single-step button, I set the single-step flag again
and call ContinueDebugEvent() with DBG_CONTINUE.
Otherwise I remove the single-step flag and call ContinueDebugEvent() with
DBG_CONTINUE.
//============
Is there something I am missing here?
After I give the command to single-step, the program, well, does something
else besides single-step (as far as I can tell).
To single-step a multi-threaded program, all threads must be set to
single-step, yes?
But if that is so, why does my first solution work when it only single-steps
one thread?
Or is it because that single thread single-steps, but others are still
running?
Usually what happens in my case is that I single step, but then the original
breakpoint is hit again one or two steps later, even though it should not be
anywhere near that breakpoint anymore.
Is it because it is hit on another thread then?
Is the purpose of single-stepping all threads just to make things work
logically or is there actually a Windows® implementation that prevents
single-stepping unless all threads are in single-stepping mode?
L. Spiro