DBG: implemented repeating variants of step commands
This commit is contained in:
parent
7295f356ee
commit
c7c654c24b
|
@ -19,8 +19,10 @@ static bool skipInt3Stepping(int argc, char* argv[])
|
|||
MemRead(cip, &ch, sizeof(ch));
|
||||
if(ch == 0xCC && getLastExceptionInfo().ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||
{
|
||||
//Don't allow skipping of multiple consecutive INT3 instructions
|
||||
getLastExceptionInfo().ExceptionRecord.ExceptionCode = 0;
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Skipped INT3!"));
|
||||
cbDebugSkip(argc, argv);
|
||||
cbDebugSkip(1, argv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -206,7 +208,7 @@ bool cbDebugDetach(int argc, char* argv[])
|
|||
bool cbDebugRun(int argc, char* argv[])
|
||||
{
|
||||
HistoryClear();
|
||||
skipInt3Stepping(argc, argv);
|
||||
skipInt3Stepping(1, argv);
|
||||
return cbDebugRunInternal(argc, argv);
|
||||
}
|
||||
|
||||
|
@ -288,12 +290,17 @@ bool cbDebugContinue(int argc, char* argv[])
|
|||
|
||||
bool cbDebugStepInto(int argc, char* argv[])
|
||||
{
|
||||
if(skipInt3Stepping(argc, argv))
|
||||
duint steprepeat = 1;
|
||||
if(argc > 1 && !valfromstring(argv[1], &steprepeat, false))
|
||||
return false;
|
||||
if(!steprepeat) //nothing to be done
|
||||
return true;
|
||||
if(skipInt3Stepping(1, argv) && !--steprepeat)
|
||||
return true;
|
||||
StepIntoWow64((void*)cbStep);
|
||||
// History
|
||||
HistoryAdd();
|
||||
dbgsetstepping(true);
|
||||
dbgsetsteprepeat(true, steprepeat);
|
||||
return cbDebugRunInternal(1, argv);
|
||||
}
|
||||
|
||||
|
@ -311,12 +318,17 @@ bool cbDebugseStepInto(int argc, char* argv[])
|
|||
|
||||
bool cbDebugStepOver(int argc, char* argv[])
|
||||
{
|
||||
if(skipInt3Stepping(argc, argv))
|
||||
duint steprepeat = 1;
|
||||
if(argc > 1 && !valfromstring(argv[1], &steprepeat, false))
|
||||
return false;
|
||||
if(!steprepeat) //nothing to be done
|
||||
return true;
|
||||
if(skipInt3Stepping(1, argv) && !--steprepeat)
|
||||
return true;
|
||||
StepOver((void*)cbStep);
|
||||
// History
|
||||
HistoryClear();
|
||||
dbgsetstepping(true);
|
||||
dbgsetsteprepeat(false, steprepeat);
|
||||
return cbDebugRunInternal(1, argv);
|
||||
}
|
||||
|
||||
|
@ -332,28 +344,16 @@ bool cbDebugseStepOver(int argc, char* argv[])
|
|||
return cbDebugStepOver(argc, argv);
|
||||
}
|
||||
|
||||
bool cbDebugSingleStep(int argc, char* argv[])
|
||||
{
|
||||
duint stepcount = 1;
|
||||
if(argc > 1)
|
||||
if(!valfromstring(argv[1], &stepcount))
|
||||
stepcount = 1;
|
||||
SingleStep((DWORD)stepcount, (void*)cbStep);
|
||||
HistoryClear();
|
||||
dbgsetstepping(true);
|
||||
return cbDebugRunInternal(1, argv);
|
||||
}
|
||||
|
||||
bool cbDebugeSingleStep(int argc, char* argv[])
|
||||
{
|
||||
dbgsetskipexceptions(true);
|
||||
return cbDebugSingleStep(argc, argv);
|
||||
}
|
||||
|
||||
bool cbDebugStepOut(int argc, char* argv[])
|
||||
{
|
||||
duint steprepeat = 1;
|
||||
if(argc > 1 && !valfromstring(argv[1], &steprepeat, false))
|
||||
return false;
|
||||
if(!steprepeat) //nothing to be done
|
||||
return true;
|
||||
HistoryClear();
|
||||
StepOver((void*)cbRtrStep);
|
||||
dbgsetsteprepeat(false, steprepeat);
|
||||
return cbDebugRunInternal(1, argv);
|
||||
}
|
||||
|
||||
|
@ -365,13 +365,18 @@ bool cbDebugeStepOut(int argc, char* argv[])
|
|||
|
||||
bool cbDebugSkip(int argc, char* argv[])
|
||||
{
|
||||
duint skiprepeat = 1;
|
||||
if(argc > 1 && !valfromstring(argv[1], &skiprepeat, false))
|
||||
return false;
|
||||
SetNextDbgContinueStatus(DBG_CONTINUE); //swallow the exception
|
||||
duint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
BASIC_INSTRUCTION_INFO basicinfo;
|
||||
memset(&basicinfo, 0, sizeof(basicinfo));
|
||||
disasmfast(cip, &basicinfo);
|
||||
cip += basicinfo.size;
|
||||
_dbg_dbgtraceexecute(cip);
|
||||
while(skiprepeat--)
|
||||
{
|
||||
disasmfast(cip, &basicinfo);
|
||||
cip += basicinfo.size;
|
||||
_dbg_dbgtraceexecute(cip);
|
||||
}
|
||||
SetContextDataEx(hActiveThread, UE_CIP, cip);
|
||||
DebugUpdateGuiAsync(cip, false); //update GUI
|
||||
return true;
|
||||
|
|
|
@ -18,8 +18,6 @@ bool cbDebugseStepInto(int argc, char* argv[]);
|
|||
bool cbDebugStepOver(int argc, char* argv[]);
|
||||
bool cbDebugeStepOver(int argc, char* argv[]);
|
||||
bool cbDebugseStepOver(int argc, char* argv[]);
|
||||
bool cbDebugSingleStep(int argc, char* argv[]);
|
||||
bool cbDebugeSingleStep(int argc, char* argv[]);
|
||||
bool cbDebugStepOut(int argc, char* argv[]);
|
||||
bool cbDebugeStepOut(int argc, char* argv[]);
|
||||
bool cbDebugSkip(int argc, char* argv[]);
|
||||
|
|
|
@ -177,7 +177,8 @@ static bool bFileIsDll = false;
|
|||
static duint pDebuggedBase = 0;
|
||||
static duint pCreateProcessBase = 0;
|
||||
static duint pDebuggedEntry = 0;
|
||||
static bool isStepping = false;
|
||||
static bool bRepeatIn = false;
|
||||
static duint stepRepeat = 0;
|
||||
static bool isPausedByUser = false;
|
||||
static bool isDetachedByUser = false;
|
||||
static bool bIsAttached = false;
|
||||
|
@ -407,9 +408,10 @@ void dbgsetskipexceptions(bool skip)
|
|||
skipExceptionCount = 0;
|
||||
}
|
||||
|
||||
void dbgsetstepping(bool stepping)
|
||||
void dbgsetsteprepeat(bool steppingIn, duint repeat)
|
||||
{
|
||||
isStepping = stepping;
|
||||
bRepeatIn = steppingIn;
|
||||
stepRepeat = repeat;
|
||||
}
|
||||
|
||||
void dbgsetispausedbyuser(bool b)
|
||||
|
@ -1183,41 +1185,54 @@ void DebugSetBreakpoints()
|
|||
void cbStep()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
isStepping = false;
|
||||
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
DebugUpdateGuiSetStateAsync(CIP, true);
|
||||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
// Plugin interaction
|
||||
PLUG_CB_STEPPED stepInfo;
|
||||
stepInfo.reserved = 0;
|
||||
//lock
|
||||
lock(WAITID_RUN);
|
||||
// Plugin callback
|
||||
PLUG_CB_PAUSEDEBUG pauseInfo = { nullptr };
|
||||
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
|
||||
dbgsetforeground();
|
||||
dbgsetskipexceptions(false);
|
||||
plugincbcall(CB_STEPPED, &stepInfo);
|
||||
wait(WAITID_RUN);
|
||||
if(!stepRepeat || !--stepRepeat)
|
||||
{
|
||||
DebugUpdateGuiSetStateAsync(CIP, true);
|
||||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
// Plugin interaction
|
||||
PLUG_CB_STEPPED stepInfo;
|
||||
stepInfo.reserved = 0;
|
||||
//lock
|
||||
lock(WAITID_RUN);
|
||||
// Plugin callback
|
||||
PLUG_CB_PAUSEDEBUG pauseInfo = { nullptr };
|
||||
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
|
||||
dbgsetforeground();
|
||||
dbgsetskipexceptions(false);
|
||||
plugincbcall(CB_STEPPED, &stepInfo);
|
||||
wait(WAITID_RUN);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(bTraceRecordEnabledDuringTrace)
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
(bRepeatIn ? StepIntoWow64 : StepOver)(cbStep);
|
||||
}
|
||||
}
|
||||
|
||||
static void cbRtrFinalStep()
|
||||
static void cbRtrFinalStep(bool checkRepeat = false)
|
||||
{
|
||||
dbgcleartracestate();
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
DebugUpdateGuiSetStateAsync(CIP, true);
|
||||
//lock
|
||||
lock(WAITID_RUN);
|
||||
// Plugin callback
|
||||
PLUG_CB_PAUSEDEBUG pauseInfo = { nullptr };
|
||||
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
|
||||
dbgsetforeground();
|
||||
dbgsetskipexceptions(false);
|
||||
wait(WAITID_RUN);
|
||||
if(!checkRepeat || !stepRepeat || !--stepRepeat)
|
||||
{
|
||||
dbgcleartracestate();
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
DebugUpdateGuiSetStateAsync(CIP, true);
|
||||
//lock
|
||||
lock(WAITID_RUN);
|
||||
// Plugin callback
|
||||
PLUG_CB_PAUSEDEBUG pauseInfo = { nullptr };
|
||||
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
|
||||
dbgsetforeground();
|
||||
dbgsetskipexceptions(false);
|
||||
wait(WAITID_RUN);
|
||||
}
|
||||
else
|
||||
StepOver((void*)cbRtrStep);
|
||||
}
|
||||
|
||||
void cbRtrStep()
|
||||
|
@ -1229,7 +1244,7 @@ void cbRtrStep()
|
|||
if(bTraceRecordEnabledDuringTrace)
|
||||
_dbg_dbgtraceexecute(cip);
|
||||
if(ch == 0xC3 || ch == 0xC2)
|
||||
cbRtrFinalStep();
|
||||
cbRtrFinalStep(true);
|
||||
else if(ch == 0x26 || ch == 0x36 || ch == 0x2e || ch == 0x3e || (ch >= 0x64 && ch <= 0x67) || ch == 0xf2 || ch == 0xf3 //instruction prefixes
|
||||
#ifdef _WIN64
|
||||
|| (ch >= 0x40 && ch <= 0x4f)
|
||||
|
@ -1241,7 +1256,7 @@ void cbRtrStep()
|
|||
memset(data, 0, sizeof(data));
|
||||
MemRead(cip, data, MAX_DISASM_BUFFER);
|
||||
if(cp.Disassemble(cip, data) && cp.GetId() == X86_INS_RET)
|
||||
cbRtrFinalStep();
|
||||
cbRtrFinalStep(true);
|
||||
else
|
||||
StepOver((void*)cbRtrStep);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ void DebugRemoveBreakpoints();
|
|||
void DebugSetBreakpoints();
|
||||
void GuiSetDebugStateAsync(DBGSTATE state);
|
||||
void dbgsetskipexceptions(bool skip);
|
||||
void dbgsetstepping(bool stepping);
|
||||
void dbgsetsteprepeat(bool steppingIn, duint repeat);
|
||||
void dbgsetispausedbyuser(bool b);
|
||||
void dbgsetisdetachedbyuser(bool b);
|
||||
void dbgsetfreezestack(bool freeze);
|
||||
|
|
|
@ -110,14 +110,12 @@ static void registercommands()
|
|||
dbgcmdnew("serun\1sego", cbDebugSerun, true); //run + swallow exception
|
||||
dbgcmdnew("pause", cbDebugPause, false); //pause debugger
|
||||
dbgcmdnew("DebugContinue\1con", cbDebugContinue, true); //set continue status
|
||||
dbgcmdnew("StepInto\1sti", cbDebugStepInto, true); //StepInto
|
||||
dbgcmdnew("StepInto\1sti\1SingleStep\1sstep\1sst", cbDebugStepInto, true); //StepInto
|
||||
dbgcmdnew("eStepInto\1esti", cbDebugeStepInto, true); //StepInto + skip first chance exceptions
|
||||
dbgcmdnew("seStepInto\1sesti", cbDebugseStepInto, true); //StepInto + swallow exception
|
||||
dbgcmdnew("seStepInto\1sesti\1eSingleStep\1esstep\1esst", cbDebugseStepInto, true); //StepInto + swallow exception
|
||||
dbgcmdnew("StepOver\1step\1sto\1st", cbDebugStepOver, true); //StepOver
|
||||
dbgcmdnew("eStepOver\1estep\1esto\1est", cbDebugeStepOver, true); //StepOver + skip first chance exceptions
|
||||
dbgcmdnew("seStepOver\1sestep\1sesto\1sest", cbDebugseStepOver, true); //StepOver + swallow exception
|
||||
dbgcmdnew("SingleStep\1sstep\1sst", cbDebugSingleStep, true); //SingleStep arg1:count
|
||||
dbgcmdnew("eSingleStep\1esstep\1esst", cbDebugeSingleStep, true); //SingleStep arg1:count + skip first chance exceptions
|
||||
dbgcmdnew("StepOut\1rtr", cbDebugStepOut, true); //StepOut
|
||||
dbgcmdnew("eStepOut\1ertr", cbDebugeStepOut, true); //rtr + skip first chance exceptions
|
||||
dbgcmdnew("skip", cbDebugSkip, true); //skip one instruction
|
||||
|
|
Loading…
Reference in New Issue