1
0
Fork 0

DBG: implemented repeating variants of step commands

This commit is contained in:
mrexodia 2017-03-12 06:51:46 +01:00
parent 7295f356ee
commit c7c654c24b
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
5 changed files with 87 additions and 71 deletions

View File

@ -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;

View File

@ -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[]);

View File

@ -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);
}

View File

@ -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);

View File

@ -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